Line data Source code
1 : #define _GNU_SOURCE 2 : #include "fd_net_util.h" 3 : 4 : #include <fcntl.h> 5 : #include <errno.h> 6 : #include <sched.h> 7 : #include <unistd.h> 8 : #include <net/if.h> 9 : #include <sys/ioctl.h> 10 : #include <sys/socket.h> 11 : #include <linux/netlink.h> 12 : #include <linux/rtnetlink.h> 13 : #include <netinet/in.h> 14 : 15 : int 16 3 : fd_net_util_internet_ifindex( uint * ifindex ) { 17 3 : int sock = socket( AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE ); 18 3 : if( FD_UNLIKELY( -1==sock ) ) return -1; 19 : 20 3 : struct { 21 3 : struct nlmsghdr nlh; 22 3 : struct rtmsg rt; 23 3 : char buf[ 8192UL ]; 24 3 : } request; 25 : 26 3 : memset(&request, 0, sizeof(request)); 27 3 : request.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 28 3 : request.nlh.nlmsg_flags = NLM_F_REQUEST; 29 3 : request.nlh.nlmsg_type = RTM_GETROUTE; 30 3 : request.rt.rtm_family = AF_INET; 31 3 : request.rt.rtm_dst_len = 32; 32 : 33 3 : struct rtattr *rta = (struct rtattr *)( ( (char *)&request ) + NLMSG_ALIGN( request.nlh.nlmsg_len ) ); 34 3 : rta->rta_len = RTA_LENGTH(4); 35 3 : rta->rta_type = RTA_DST; 36 3 : request.nlh.nlmsg_len = NLMSG_ALIGN( request.nlh.nlmsg_len ) + (uint)RTA_LENGTH( 4 ); 37 : 38 3 : uint ip = (8 << 24) | (8 << 16) | (8 << 8) | 8; 39 3 : fd_memcpy( RTA_DATA( rta ), &ip, 4 ); 40 : 41 3 : long sent = send( sock, &request, request.nlh.nlmsg_len, 0 ); 42 3 : if( FD_UNLIKELY( -1==sent ) ) { 43 0 : close( sock ); 44 0 : return -1; 45 0 : } 46 3 : FD_TEST( sent==request.nlh.nlmsg_len ); 47 : 48 3 : char response[ 8192UL ]; 49 3 : long len = recv( sock, response, sizeof(response), 0 ); 50 3 : if( FD_UNLIKELY( -1==len ) ) { 51 0 : close( sock ); 52 0 : return -1; 53 3 : } else if( FD_UNLIKELY( len==sizeof(response) ) ) { 54 0 : errno = ENOBUFS; 55 0 : close( sock ); 56 0 : return -1; 57 0 : } 58 : 59 3 : struct nlmsghdr *nlh; 60 3 : int result = -1; 61 3 : for( nlh = (struct nlmsghdr *)response; NLMSG_OK( nlh, len ); nlh = NLMSG_NEXT( nlh, len ) ) { 62 3 : struct rtmsg *rt = NLMSG_DATA( nlh ); 63 : 64 3 : struct rtattr *rta = RTM_RTA( rt ); 65 3 : uint rtl = (uint)RTM_PAYLOAD( nlh ); 66 : 67 21 : for (; RTA_OK( rta, rtl ); rta = RTA_NEXT( rta, rtl ) ) { 68 21 : if (rta->rta_type == RTA_OIF) { 69 3 : result = *(int *)RTA_DATA(rta); 70 3 : } 71 21 : } 72 3 : } 73 : 74 3 : if( FD_UNLIKELY( -1==close( sock ) ) ) return -1; 75 : 76 3 : if( FD_LIKELY( result>=0 ) ) { 77 3 : *ifindex = (uint)result; 78 3 : return 0; 79 3 : } else { 80 0 : errno = ENODEV; 81 0 : return -1; 82 0 : } 83 3 : } 84 : 85 : int 86 : fd_net_util_if_addr( const char * interface, 87 3 : uint * addr ) { 88 3 : int fd = socket( AF_INET, SOCK_DGRAM, 0 ); 89 3 : if( FD_UNLIKELY( -1==fd ) ) return -1; 90 : 91 3 : struct ifreq ifr = {0}; 92 3 : ifr.ifr_addr.sa_family = AF_INET; 93 3 : strncpy( ifr.ifr_name, interface, IFNAMSIZ ); 94 3 : ifr.ifr_name[ IFNAMSIZ-1 ] = '\0'; 95 : 96 3 : if( FD_UNLIKELY( -1==ioctl( fd, SIOCGIFADDR, &ifr ) ) ) return -1; 97 3 : if( FD_UNLIKELY( -1==close( fd ) ) ) return -1; 98 : 99 3 : *addr = ((struct sockaddr_in *)fd_type_pun( &ifr.ifr_addr ))->sin_addr.s_addr; 100 3 : return 0; 101 3 : }