144099b7bSPaul Traina /* 244099b7bSPaul Traina * getif.c : get an interface structure 344099b7bSPaul Traina */ 444099b7bSPaul Traina 544099b7bSPaul Traina #include <sys/types.h> 644099b7bSPaul Traina #include <sys/socket.h> 744099b7bSPaul Traina #include <sys/ioctl.h> 844099b7bSPaul Traina 944099b7bSPaul Traina #if defined(SUNOS) || defined(SVR4) 1044099b7bSPaul Traina #include <sys/sockio.h> 1144099b7bSPaul Traina #endif 1244099b7bSPaul Traina #ifdef SVR4 1344099b7bSPaul Traina #include <sys/stropts.h> 1444099b7bSPaul Traina #endif 1544099b7bSPaul Traina 16e08ac58bSPaul Traina #ifdef _AIX32 17e08ac58bSPaul Traina #include <sys/time.h> /* for struct timeval in net/if.h */ 18e08ac58bSPaul Traina #endif 1944099b7bSPaul Traina #include <net/if.h> /* for struct ifreq */ 2044099b7bSPaul Traina #include <netinet/in.h> 2144099b7bSPaul Traina 2244099b7bSPaul Traina #ifndef NO_UNISTD 2344099b7bSPaul Traina #include <unistd.h> 2444099b7bSPaul Traina #endif 2544099b7bSPaul Traina #include <syslog.h> 2644099b7bSPaul Traina #include <errno.h> 2744099b7bSPaul Traina #include <assert.h> 2844099b7bSPaul Traina 2944099b7bSPaul Traina #include "getif.h" 3044099b7bSPaul Traina #include "report.h" 3144099b7bSPaul Traina 3244099b7bSPaul Traina #ifdef __bsdi__ 3344099b7bSPaul Traina #define BSD 43 3444099b7bSPaul Traina #endif 3544099b7bSPaul Traina 3644099b7bSPaul Traina static struct ifreq ifreq[10]; /* Holds interface configuration */ 3744099b7bSPaul Traina static struct ifconf ifconf; /* points to ifreq */ 3844099b7bSPaul Traina 3944099b7bSPaul Traina static int nmatch(); 4044099b7bSPaul Traina 4144099b7bSPaul Traina /* Return a pointer to the interface struct for the passed address. */ 4244099b7bSPaul Traina struct ifreq * 4344099b7bSPaul Traina getif(s, addrp) 4444099b7bSPaul Traina int s; /* socket file descriptor */ 4544099b7bSPaul Traina struct in_addr *addrp; /* destination address on interface */ 4644099b7bSPaul Traina { 4744099b7bSPaul Traina int maxmatch; 4844099b7bSPaul Traina int len, m, incr; 4944099b7bSPaul Traina struct ifreq *ifrq, *ifrmax; 5044099b7bSPaul Traina struct sockaddr_in *sip; 5144099b7bSPaul Traina char *p; 5244099b7bSPaul Traina 5344099b7bSPaul Traina /* If no address was supplied, just return NULL. */ 5444099b7bSPaul Traina if (!addrp) 5544099b7bSPaul Traina return (struct ifreq *) 0; 5644099b7bSPaul Traina 5744099b7bSPaul Traina /* Get the interface config if not done already. */ 5844099b7bSPaul Traina if (ifconf.ifc_len == 0) { 5944099b7bSPaul Traina #ifdef SVR4 6044099b7bSPaul Traina /* 6144099b7bSPaul Traina * SysVr4 returns garbage if you do this the obvious way! 6244099b7bSPaul Traina * This one took a while to figure out... -gwr 6344099b7bSPaul Traina */ 6444099b7bSPaul Traina struct strioctl ioc; 6544099b7bSPaul Traina ioc.ic_cmd = SIOCGIFCONF; 6644099b7bSPaul Traina ioc.ic_timout = 0; 6744099b7bSPaul Traina ioc.ic_len = sizeof(ifreq); 6844099b7bSPaul Traina ioc.ic_dp = (char *) ifreq; 6944099b7bSPaul Traina m = ioctl(s, I_STR, (char *) &ioc); 7044099b7bSPaul Traina ifconf.ifc_len = ioc.ic_len; 7144099b7bSPaul Traina ifconf.ifc_req = ifreq; 7244099b7bSPaul Traina #else /* SVR4 */ 7344099b7bSPaul Traina ifconf.ifc_len = sizeof(ifreq); 7444099b7bSPaul Traina ifconf.ifc_req = ifreq; 7544099b7bSPaul Traina m = ioctl(s, SIOCGIFCONF, (caddr_t) & ifconf); 7644099b7bSPaul Traina #endif /* SVR4 */ 7744099b7bSPaul Traina if ((m < 0) || (ifconf.ifc_len <= 0)) { 7844099b7bSPaul Traina report(LOG_ERR, "ioctl SIOCGIFCONF"); 7944099b7bSPaul Traina return (struct ifreq *) 0; 8044099b7bSPaul Traina } 8144099b7bSPaul Traina } 8244099b7bSPaul Traina maxmatch = 7; /* this many bits or less... */ 8344099b7bSPaul Traina ifrmax = (struct ifreq *) 0;/* ... is not a valid match */ 8444099b7bSPaul Traina p = (char *) ifreq; 8544099b7bSPaul Traina len = ifconf.ifc_len; 8644099b7bSPaul Traina while (len > 0) { 8744099b7bSPaul Traina ifrq = (struct ifreq *) p; 8844099b7bSPaul Traina sip = (struct sockaddr_in *) &ifrq->ifr_addr; 8944099b7bSPaul Traina m = nmatch(addrp, &(sip->sin_addr)); 9044099b7bSPaul Traina if (m > maxmatch) { 9144099b7bSPaul Traina maxmatch = m; 9244099b7bSPaul Traina ifrmax = ifrq; 9344099b7bSPaul Traina } 944f5241c6SPaul Traina #ifndef IFNAMSIZ 9544099b7bSPaul Traina /* BSD not defined or earlier than 4.3 */ 9644099b7bSPaul Traina incr = sizeof(*ifrq); 974f5241c6SPaul Traina #else 9844099b7bSPaul Traina incr = ifrq->ifr_addr.sa_len + IFNAMSIZ; 994f5241c6SPaul Traina #endif 10044099b7bSPaul Traina 10144099b7bSPaul Traina p += incr; 10244099b7bSPaul Traina len -= incr; 10344099b7bSPaul Traina } 10444099b7bSPaul Traina 10544099b7bSPaul Traina return ifrmax; 10644099b7bSPaul Traina } 10744099b7bSPaul Traina 10844099b7bSPaul Traina /* 10944099b7bSPaul Traina * Return the number of leading bits matching in the 11044099b7bSPaul Traina * internet addresses supplied. 11144099b7bSPaul Traina */ 11244099b7bSPaul Traina static int 11344099b7bSPaul Traina nmatch(ca, cb) 11444099b7bSPaul Traina u_char *ca, *cb; /* ptrs to IP address, network order */ 11544099b7bSPaul Traina { 11644099b7bSPaul Traina u_int m = 0; /* count of matching bits */ 11744099b7bSPaul Traina u_int n = 4; /* bytes left, then bitmask */ 11844099b7bSPaul Traina 11944099b7bSPaul Traina /* Count matching bytes. */ 12044099b7bSPaul Traina while (n && (*ca == *cb)) { 12144099b7bSPaul Traina ca++; 12244099b7bSPaul Traina cb++; 12344099b7bSPaul Traina m += 8; 12444099b7bSPaul Traina n--; 12544099b7bSPaul Traina } 12644099b7bSPaul Traina /* Now count matching bits. */ 12744099b7bSPaul Traina if (n) { 12844099b7bSPaul Traina n = 0x80; 12944099b7bSPaul Traina while (n && ((*ca & n) == (*cb & n))) { 13044099b7bSPaul Traina m++; 13144099b7bSPaul Traina n >>= 1; 13244099b7bSPaul Traina } 13344099b7bSPaul Traina } 13444099b7bSPaul Traina return (m); 13544099b7bSPaul Traina } 13644099b7bSPaul Traina 13744099b7bSPaul Traina /* 13844099b7bSPaul Traina * Local Variables: 13944099b7bSPaul Traina * tab-width: 4 14044099b7bSPaul Traina * c-indent-level: 4 14144099b7bSPaul Traina * c-argdecl-indent: 4 14244099b7bSPaul Traina * c-continued-statement-offset: 4 14344099b7bSPaul Traina * c-continued-brace-offset: -4 14444099b7bSPaul Traina * c-label-offset: -4 14544099b7bSPaul Traina * c-brace-offset: 0 14644099b7bSPaul Traina * End: 14744099b7bSPaul Traina */ 148