13229Spst/* 23229Spst * getif.c : get an interface structure 318471Swosch * 450476Speter * $FreeBSD$ 53229Spst */ 63229Spst 73229Spst#include <sys/types.h> 83229Spst#include <sys/socket.h> 93229Spst#include <sys/ioctl.h> 103229Spst 113229Spst#if defined(SUNOS) || defined(SVR4) 123229Spst#include <sys/sockio.h> 133229Spst#endif 143229Spst#ifdef SVR4 153229Spst#include <sys/stropts.h> 163229Spst#endif 173229Spst 1813572Spst#include <sys/time.h> /* for struct timeval in net/if.h */ 193229Spst#include <net/if.h> /* for struct ifreq */ 203229Spst#include <netinet/in.h> 213229Spst 223229Spst#ifndef NO_UNISTD 233229Spst#include <unistd.h> 243229Spst#endif 253229Spst#include <syslog.h> 263229Spst#include <errno.h> 273229Spst#include <assert.h> 283229Spst 293229Spst#include "getif.h" 303229Spst#include "report.h" 313229Spst 323229Spst#ifdef __bsdi__ 333229Spst#define BSD 43 343229Spst#endif 353229Spst 363229Spststatic struct ifreq ifreq[10]; /* Holds interface configuration */ 373229Spststatic struct ifconf ifconf; /* points to ifreq */ 383229Spst 393229Spststatic int nmatch(); 403229Spst 413229Spst/* Return a pointer to the interface struct for the passed address. */ 423229Spststruct ifreq * 433229Spstgetif(s, addrp) 443229Spst int s; /* socket file descriptor */ 453229Spst struct in_addr *addrp; /* destination address on interface */ 463229Spst{ 473229Spst int maxmatch; 483229Spst int len, m, incr; 493229Spst struct ifreq *ifrq, *ifrmax; 503229Spst struct sockaddr_in *sip; 513229Spst char *p; 523229Spst 533229Spst /* If no address was supplied, just return NULL. */ 543229Spst if (!addrp) 553229Spst return (struct ifreq *) 0; 563229Spst 573229Spst /* Get the interface config if not done already. */ 583229Spst if (ifconf.ifc_len == 0) { 593229Spst#ifdef SVR4 603229Spst /* 613229Spst * SysVr4 returns garbage if you do this the obvious way! 623229Spst * This one took a while to figure out... -gwr 633229Spst */ 643229Spst struct strioctl ioc; 653229Spst ioc.ic_cmd = SIOCGIFCONF; 663229Spst ioc.ic_timout = 0; 673229Spst ioc.ic_len = sizeof(ifreq); 683229Spst ioc.ic_dp = (char *) ifreq; 693229Spst m = ioctl(s, I_STR, (char *) &ioc); 703229Spst ifconf.ifc_len = ioc.ic_len; 713229Spst ifconf.ifc_req = ifreq; 723229Spst#else /* SVR4 */ 733229Spst ifconf.ifc_len = sizeof(ifreq); 743229Spst ifconf.ifc_req = ifreq; 753229Spst m = ioctl(s, SIOCGIFCONF, (caddr_t) & ifconf); 763229Spst#endif /* SVR4 */ 773229Spst if ((m < 0) || (ifconf.ifc_len <= 0)) { 783229Spst report(LOG_ERR, "ioctl SIOCGIFCONF"); 793229Spst return (struct ifreq *) 0; 803229Spst } 813229Spst } 823229Spst maxmatch = 7; /* this many bits or less... */ 833229Spst ifrmax = (struct ifreq *) 0;/* ... is not a valid match */ 843229Spst p = (char *) ifreq; 853229Spst len = ifconf.ifc_len; 863229Spst while (len > 0) { 873229Spst ifrq = (struct ifreq *) p; 883229Spst sip = (struct sockaddr_in *) &ifrq->ifr_addr; 89132848Skan m = nmatch((u_char *)addrp, (u_char *)&(sip->sin_addr)); 903229Spst if (m > maxmatch) { 913229Spst maxmatch = m; 923229Spst ifrmax = ifrq; 933229Spst } 9413582Spst#ifndef IFNAMSIZ 953229Spst /* BSD not defined or earlier than 4.3 */ 963229Spst incr = sizeof(*ifrq); 9713582Spst#else 983229Spst incr = ifrq->ifr_addr.sa_len + IFNAMSIZ; 9913582Spst#endif 1003229Spst 1013229Spst p += incr; 1023229Spst len -= incr; 1033229Spst } 1043229Spst 1053229Spst return ifrmax; 1063229Spst} 1073229Spst 1083229Spst/* 1093229Spst * Return the number of leading bits matching in the 1103229Spst * internet addresses supplied. 1113229Spst */ 1123229Spststatic int 1133229Spstnmatch(ca, cb) 1143229Spst u_char *ca, *cb; /* ptrs to IP address, network order */ 1153229Spst{ 1163229Spst u_int m = 0; /* count of matching bits */ 1173229Spst u_int n = 4; /* bytes left, then bitmask */ 1183229Spst 1193229Spst /* Count matching bytes. */ 1203229Spst while (n && (*ca == *cb)) { 1213229Spst ca++; 1223229Spst cb++; 1233229Spst m += 8; 1243229Spst n--; 1253229Spst } 1263229Spst /* Now count matching bits. */ 1273229Spst if (n) { 1283229Spst n = 0x80; 1293229Spst while (n && ((*ca & n) == (*cb & n))) { 1303229Spst m++; 1313229Spst n >>= 1; 1323229Spst } 1333229Spst } 1343229Spst return (m); 1353229Spst} 1363229Spst 1373229Spst/* 1383229Spst * Local Variables: 1393229Spst * tab-width: 4 1403229Spst * c-indent-level: 4 1413229Spst * c-argdecl-indent: 4 1423229Spst * c-continued-statement-offset: 4 1433229Spst * c-continued-brace-offset: -4 1443229Spst * c-label-offset: -4 1453229Spst * c-brace-offset: 0 1463229Spst * End: 1473229Spst */ 148