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