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