1/* $Id: getifaddr.c,v 1.10 2009/10/28 07:44:43 jmaggard Exp $ */ 2/* MiniUPnP project 3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ 4 * (c) 2006 Thomas Bernard 5 * This software is subject to the conditions detailed 6 * in the LICENCE file provided within the distribution */ 7 8#include <stdio.h> 9#include <stdlib.h> 10#include <string.h> 11#include <unistd.h> 12#include <sys/ioctl.h> 13#include <sys/types.h> 14#include <sys/socket.h> 15#include <net/if.h> 16#include <arpa/inet.h> 17#include <netinet/in.h> 18#include <netdb.h> 19#include <errno.h> 20#if defined(sun) 21#include <sys/sockio.h> 22#endif 23 24#include "getifaddr.h" 25#include "log.h" 26 27int 28getifaddr(const char * ifname, char * buf, int len) 29{ 30 /* SIOCGIFADDR struct ifreq * */ 31 int s; 32 struct ifreq ifr; 33 int ifrlen; 34 struct sockaddr_in * addr; 35 ifrlen = sizeof(ifr); 36 s = socket(PF_INET, SOCK_DGRAM, 0); 37 if(s < 0) 38 { 39 DPRINTF(E_ERROR, L_GENERAL, "socket(PF_INET, SOCK_DGRAM): %s\n", strerror(errno)); 40 return -1; 41 } 42 strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 43 if(ioctl(s, SIOCGIFADDR, &ifr, &ifrlen) < 0) 44 { 45 DPRINTF(E_ERROR, L_GENERAL, "ioctl(s, SIOCGIFADDR, ...): %s\n", strerror(errno)); 46 close(s); 47 return -1; 48 } 49 addr = (struct sockaddr_in *)&ifr.ifr_addr; 50 if(!inet_ntop(AF_INET, &addr->sin_addr, buf, len)) 51 { 52 DPRINTF(E_ERROR, L_GENERAL, "inet_ntop(): %s\n", strerror(errno)); 53 close(s); 54 return -1; 55 } 56 close(s); 57 return 0; 58} 59 60int 61getsysaddr(char * buf, int len) 62{ 63 int i; 64 int s = socket(PF_INET, SOCK_STREAM, 0); 65 struct sockaddr_in addr; 66 struct ifreq ifr; 67 int ret = -1; 68 69 for (i=1; i > 0; i++) 70 { 71 ifr.ifr_ifindex = i; 72 if( ioctl(s, SIOCGIFNAME, &ifr) < 0 ) 73 break; 74 if(ioctl(s, SIOCGIFADDR, &ifr, sizeof(struct ifreq)) < 0) 75 continue; 76 memcpy(&addr, &ifr.ifr_addr, sizeof(addr)); 77 if(strncmp(inet_ntoa(addr.sin_addr), "127.", 4) == 0) 78 continue; 79 if(!inet_ntop(AF_INET, &addr.sin_addr, buf, len)) 80 { 81 DPRINTF(E_ERROR, L_GENERAL, "inet_ntop(): %s\n", strerror(errno)); 82 close(s); 83 break; 84 } 85 ret = 0; 86 break; 87 } 88 close(s); 89 90 return(ret); 91} 92 93int 94getsyshwaddr(char * buf, int len) 95{ 96 struct if_nameindex *ifaces, *if_idx; 97 unsigned char mac[6]; 98 struct ifreq ifr; 99 int fd; 100 int ret = -1; 101 102 memset(&mac, '\0', sizeof(mac)); 103 /* Get the spatially unique node identifier */ 104 fd = socket(AF_INET, SOCK_DGRAM, 0); 105 if( fd < 0 ) 106 return(ret); 107 108 ifaces = if_nameindex(); 109 if(!ifaces) 110 return(ret); 111 112 for(if_idx = ifaces; if_idx->if_index; if_idx++) 113 { 114 strncpy(ifr.ifr_name, if_idx->if_name, IFNAMSIZ); 115 if(ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) 116 continue; 117 if(ifr.ifr_ifru.ifru_flags & IFF_LOOPBACK) 118 continue; 119 if( ioctl(fd, SIOCGIFHWADDR, &ifr) < 0 ) 120 continue; 121 if( MACADDR_IS_ZERO(&ifr.ifr_hwaddr.sa_data) ) 122 continue; 123 ret = 0; 124 break; 125 } 126 if_freenameindex(ifaces); 127 close(fd); 128 129 if(ret == 0) 130 { 131 if(len > 12) 132 { 133 memmove(mac, ifr.ifr_hwaddr.sa_data, 6); 134 sprintf(buf, "%02x%02x%02x%02x%02x%02x", 135 mac[0]&0xFF, mac[1]&0xFF, mac[2]&0xFF, 136 mac[3]&0xFF, mac[4]&0xFF, mac[5]&0xFF); 137 } 138 else if(len == 6) 139 { 140 memmove(buf, ifr.ifr_hwaddr.sa_data, 6); 141 } 142 } 143 return ret; 144} 145 146int 147get_remote_mac(struct in_addr ip_addr, unsigned char * mac) 148{ 149 struct in_addr arp_ent; 150 FILE * arp; 151 char remote_ip[16]; 152 int matches, hwtype, flags; 153 memset(mac, 0xFF, 6); 154 155 arp = fopen("/proc/net/arp", "r"); 156 if( !arp ) 157 return 1; 158 while( !feof(arp) ) 159 { 160 matches = fscanf(arp, "%s 0x%X 0x%X %hhx:%hhx:%hhx:%hhx:%hhx:%hhx", 161 remote_ip, &hwtype, &flags, 162 &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); 163 if( matches != 9 ) 164 continue; 165 inet_pton(AF_INET, remote_ip, &arp_ent); 166 if( ip_addr.s_addr == arp_ent.s_addr ) 167 break; 168 mac[0] = 0xFF; 169 } 170 fclose(arp); 171 172 if( mac[0] == 0xFF ) 173 { 174 memset(mac, 0xFF, 6); 175 return 1; 176 } 177 178 return 0; 179} 180