1176868Srink/* 2176869Srink * getif.c : get an interface structure 3176869Srink * 4176869Srink * $FreeBSD$ 5176869Srink */ 6176869Srink 7176869Srink#include <sys/types.h> 8176869Srink#include <sys/socket.h> 9176869Srink#include <sys/ioctl.h> 10176869Srink 11176869Srink#if defined(SUNOS) || defined(SVR4) 12176869Srink#include <sys/sockio.h> 13176869Srink#endif 14176869Srink#ifdef SVR4 15176869Srink#include <sys/stropts.h> 16176869Srink#endif 17176869Srink 18176869Srink#include <sys/time.h> /* for struct timeval in net/if.h */ 19176869Srink#include <net/if.h> /* for struct ifreq */ 20176869Srink#include <netinet/in.h> 21176869Srink 22176869Srink#ifndef NO_UNISTD 23176869Srink#include <unistd.h> 24176869Srink#endif 25176869Srink#include <syslog.h> 26176869Srink#include <errno.h> 27176868Srink#include <assert.h> 28176868Srink 29176868Srink#include "getif.h" 30176868Srink#include "report.h" 31176868Srink 32176868Srink#ifdef __bsdi__ 33176868Srink#define BSD 43 34176868Srink#endif 35176868Srink 36176868Srinkstatic struct ifreq ifreq[10]; /* Holds interface configuration */ 37176868Srinkstatic struct ifconf ifconf; /* points to ifreq */ 38176868Srink 39176868Srinkstatic int nmatch(); 40176868Srink 41176868Srink/* Return a pointer to the interface struct for the passed address. */ 42176868Srinkstruct ifreq * 43176868Srinkgetif(s, addrp) 44176868Srink int s; /* socket file descriptor */ 45176868Srink struct in_addr *addrp; /* destination address on interface */ 46210933Sjoel{ 47176868Srink int maxmatch; 48176868Srink int len, m, incr; 49210933Sjoel struct ifreq *ifrq, *ifrmax; 50176868Srink struct sockaddr_in *sip; 51176868Srink char *p; 52176868Srink 53176868Srink /* If no address was supplied, just return NULL. */ 54176868Srink if (!addrp) 55176868Srink return (struct ifreq *) 0; 56176868Srink 57176868Srink /* Get the interface config if not done already. */ 58176868Srink if (ifconf.ifc_len == 0) { 59176868Srink#ifdef SVR4 60176868Srink /* 61176868Srink * SysVr4 returns garbage if you do this the obvious way! 62176868Srink * This one took a while to figure out... -gwr 63176868Srink */ 64176868Srink struct strioctl ioc; 65176868Srink ioc.ic_cmd = SIOCGIFCONF; 66176868Srink ioc.ic_timout = 0; 67176868Srink ioc.ic_len = sizeof(ifreq); 68176868Srink ioc.ic_dp = (char *) ifreq; 69176868Srink m = ioctl(s, I_STR, (char *) &ioc); 70176868Srink ifconf.ifc_len = ioc.ic_len; 71176868Srink ifconf.ifc_req = ifreq; 72176868Srink#else /* SVR4 */ 73176868Srink ifconf.ifc_len = sizeof(ifreq); 74176868Srink ifconf.ifc_req = ifreq; 75176868Srink m = ioctl(s, SIOCGIFCONF, (caddr_t) & ifconf); 76176868Srink#endif /* SVR4 */ 77176868Srink if ((m < 0) || (ifconf.ifc_len <= 0)) { 78176868Srink report(LOG_ERR, "ioctl SIOCGIFCONF"); 79176868Srink return (struct ifreq *) 0; 80176868Srink } 81176868Srink } 82176868Srink maxmatch = 7; /* this many bits or less... */ 83176868Srink ifrmax = (struct ifreq *) 0;/* ... is not a valid match */ 84176868Srink p = (char *) ifreq; 85176868Srink len = ifconf.ifc_len; 86176868Srink while (len > 0) { 87176868Srink ifrq = (struct ifreq *) p; 88176868Srink sip = (struct sockaddr_in *) &ifrq->ifr_addr; 89208028Suqs m = nmatch((u_char *)addrp, (u_char *)&(sip->sin_addr)); 90208028Suqs if (m > maxmatch) { 91208028Suqs maxmatch = m; 92208028Suqs ifrmax = ifrq; 93208028Suqs } 94176868Srink#ifndef IFNAMSIZ 95176868Srink /* BSD not defined or earlier than 4.3 */ 96176868Srink incr = sizeof(*ifrq); 97176868Srink#else 98176868Srink incr = ifrq->ifr_addr.sa_len + IFNAMSIZ; 99176868Srink#endif 100176868Srink 101176868Srink p += incr; 102176868Srink len -= incr; 103176868Srink } 104176868Srink 105176868Srink return ifrmax; 106176868Srink} 107176868Srink 108176868Srink/* 109176868Srink * Return the number of leading bits matching in the 110176868Srink * internet addresses supplied. 111176868Srink */ 112176868Srinkstatic int 113176868Srinknmatch(ca, cb) 114176868Srink u_char *ca, *cb; /* ptrs to IP address, network order */ 115176868Srink{ 116176868Srink u_int m = 0; /* count of matching bits */ 117176868Srink u_int n = 4; /* bytes left, then bitmask */ 118176868Srink 119176868Srink /* Count matching bytes. */ 120176868Srink 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