1 /* 2 * getif.c : get an interface structure 3 * 4 * $FreeBSD$ 5 */ 6 7 #include <sys/types.h> 8 #include <sys/socket.h> 9 #include <sys/ioctl.h> 10 11 #if defined(SUNOS) || defined(SVR4) 12 #include <sys/sockio.h> 13 #endif 14 #ifdef SVR4 15 #include <sys/stropts.h> 16 #endif 17 18 #include <sys/time.h> /* for struct timeval in net/if.h */ 19 #include <net/if.h> /* for struct ifreq */ 20 #include <netinet/in.h> 21 22 #ifndef NO_UNISTD 23 #include <unistd.h> 24 #endif 25 #include <syslog.h> 26 #include <errno.h> 27 #include <assert.h> 28 29 #include "getif.h" 30 #include "report.h" 31 32 #ifdef __bsdi__ 33 #define BSD 43 34 #endif 35 36 static struct ifreq ifreq[10]; /* Holds interface configuration */ 37 static struct ifconf ifconf; /* points to ifreq */ 38 39 static int nmatch(); 40 41 /* Return a pointer to the interface struct for the passed address. */ 42 struct ifreq * 43 getif(s, addrp) 44 int s; /* socket file descriptor */ 45 struct in_addr *addrp; /* destination address on interface */ 46 { 47 int maxmatch; 48 int len, m, incr; 49 struct ifreq *ifrq, *ifrmax; 50 struct sockaddr_in *sip; 51 char *p; 52 53 /* If no address was supplied, just return NULL. */ 54 if (!addrp) 55 return (struct ifreq *) 0; 56 57 /* Get the interface config if not done already. */ 58 if (ifconf.ifc_len == 0) { 59 #ifdef SVR4 60 /* 61 * SysVr4 returns garbage if you do this the obvious way! 62 * This one took a while to figure out... -gwr 63 */ 64 struct strioctl ioc; 65 ioc.ic_cmd = SIOCGIFCONF; 66 ioc.ic_timout = 0; 67 ioc.ic_len = sizeof(ifreq); 68 ioc.ic_dp = (char *) ifreq; 69 m = ioctl(s, I_STR, (char *) &ioc); 70 ifconf.ifc_len = ioc.ic_len; 71 ifconf.ifc_req = ifreq; 72 #else /* SVR4 */ 73 ifconf.ifc_len = sizeof(ifreq); 74 ifconf.ifc_req = ifreq; 75 m = ioctl(s, SIOCGIFCONF, (caddr_t) & ifconf); 76 #endif /* SVR4 */ 77 if ((m < 0) || (ifconf.ifc_len <= 0)) { 78 report(LOG_ERR, "ioctl SIOCGIFCONF"); 79 return (struct ifreq *) 0; 80 } 81 } 82 maxmatch = 7; /* this many bits or less... */ 83 ifrmax = (struct ifreq *) 0;/* ... is not a valid match */ 84 p = (char *) ifreq; 85 len = ifconf.ifc_len; 86 while (len > 0) { 87 ifrq = (struct ifreq *) p; 88 sip = (struct sockaddr_in *) &ifrq->ifr_addr; 89 m = nmatch((u_char *)addrp, (u_char *)&(sip->sin_addr)); 90 if (m > maxmatch) { 91 maxmatch = m; 92 ifrmax = ifrq; 93 } 94 #ifndef IFNAMSIZ 95 /* BSD not defined or earlier than 4.3 */ 96 incr = sizeof(*ifrq); 97 #else 98 incr = ifrq->ifr_addr.sa_len + IFNAMSIZ; 99 #endif 100 101 p += incr; 102 len -= incr; 103 } 104 105 return ifrmax; 106 } 107 108 /* 109 * Return the number of leading bits matching in the 110 * internet addresses supplied. 111 */ 112 static int 113 nmatch(ca, cb) 114 u_char *ca, *cb; /* ptrs to IP address, network order */ 115 { 116 u_int m = 0; /* count of matching bits */ 117 u_int n = 4; /* bytes left, then bitmask */ 118 119 /* Count matching bytes. */ 120 while (n && (*ca == *cb)) { 121 ca++; 122 cb++; 123 m += 8; 124 n--; 125 } 126 /* Now count matching bits. */ 127 if (n) { 128 n = 0x80; 129 while (n && ((*ca & n) == (*cb & n))) { 130 m++; 131 n >>= 1; 132 } 133 } 134 return (m); 135 } 136 137 /* 138 * Local Variables: 139 * tab-width: 4 140 * c-indent-level: 4 141 * c-argdecl-indent: 4 142 * c-continued-statement-offset: 4 143 * c-continued-brace-offset: -4 144 * c-label-offset: -4 145 * c-brace-offset: 0 146 * End: 147 */ 148