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