diff options
author | Luke Leighton <lkcl@samba.org> | 1997-09-23 16:09:12 +0000 |
---|---|---|
committer | Luke Leighton <lkcl@samba.org> | 1997-09-23 16:09:12 +0000 |
commit | b3c610541b7284cbd59827b13af86a457268ae96 (patch) | |
tree | 32b59dfa389da16b4163294d708cb8b170e1483e | |
parent | 7885239b62672d23b060044ffd857ad811132906 (diff) | |
download | samba-b3c610541b7284cbd59827b13af86a457268ae96.tar.gz samba-b3c610541b7284cbd59827b13af86a457268ae96.tar.bz2 samba-b3c610541b7284cbd59827b13af86a457268ae96.zip |
added code from Philip A Prindeville <philipp@enteka.com> which expands
the interfaces option to this:
"interfaces = le0 le1" or "interfaces = all".
it uses SIOCGIFxxxx ioctl calls.
(This used to be commit 39071415ba6f8a00e2909e443261d0059fe27e82)
-rw-r--r-- | source3/include/smb.h | 3 | ||||
-rw-r--r-- | source3/lib/interface.c | 396 |
2 files changed, 213 insertions, 186 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h index 6ef0e6f9d0..05f73f7f45 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -433,6 +433,9 @@ struct interface struct in_addr ip; struct in_addr bcast; struct in_addr nmask; + char *name; + size_t mtu; /* may be useful in future... */ + short flags; }; /* share mode record pointed to in shared memory hash bucket */ diff --git a/source3/lib/interface.c b/source3/lib/interface.c index 940af1eccf..e03333280a 100644 --- a/source3/lib/interface.c +++ b/source3/lib/interface.c @@ -21,62 +21,29 @@ #include "includes.h" +#include <assert.h> /* added by philipp */ + extern int DEBUGLEVEL; struct in_addr ipzero; struct in_addr wins_ip; -static struct in_addr default_ip; -static struct in_addr default_bcast; -static struct in_addr default_nmask; -static BOOL got_ip=False; -static BOOL got_bcast=False; -static BOOL got_nmask=False; struct interface *local_interfaces = NULL; +struct interface *present_interfaces = NULL; struct interface *last_iface; -/**************************************************************************** -calculate the default netmask for an address -****************************************************************************/ -static void default_netmask(struct in_addr *inm, struct in_addr *iad) -{ - uint32 ad = ntohl(iad->s_addr); - uint32 nm; - /* - ** Guess a netmask based on the class of the IP address given. - */ - if ( (ad & 0x80000000) == 0 ) { - /* class A address */ - nm = 0xFF000000; - } else if ( (ad & 0xC0000000) == 0x80000000 ) { - /* class B address */ - nm = 0xFFFF0000; - } else if ( (ad & 0xE0000000) == 0xC0000000 ) { - /* class C address */ - nm = 0xFFFFFF00; - } else { - /* class D or E; netmask doesn't make much sense - guess 4 bits */ - nm = 0xFFFFFFF0; - } - inm->s_addr = htonl(nm); -} - - -/**************************************************************************** - get the broadcast address for our address -(troyer@saifr00.ateng.az.honeywell.com) -****************************************************************************/ -static void get_broadcast(struct in_addr *if_ipaddr, - struct in_addr *if_bcast, - struct in_addr *if_nmask) +static void get_interfaces() { - BOOL found = False; -#ifndef NO_GET_BROADCAST int sock = -1; /* AF_INET raw socket desc */ char buff[1024]; - struct ifreq *ifr=NULL; + struct ifreq *ifr=NULL, ifr2; int i; + struct interface *iface, *last_iface = NULL; + +#ifndef ifr_mtu +#define ifr_mtu ifr_metric +#endif #if defined(EVEREST) int n_interfaces; @@ -89,12 +56,9 @@ static void get_broadcast(struct in_addr *if_ipaddr, #else struct ifconf ifc; #endif -#endif - /* get a default netmask and broadcast */ - default_netmask(if_nmask, if_ipaddr); + if (present_interfaces) return; /* already initialized */ -#ifndef NO_GET_BROADCAST /* Create a socket to the INET kernel. */ #if USE_SOCKRAW if ((sock = socket(AF_INET, SOCK_RAW, PF_INET )) < 0) @@ -126,11 +90,42 @@ static void get_broadcast(struct in_addr *if_ipaddr, ifr = ifc.ifc_req; for (i = 0; i < n_interfaces; ++i) { - if (if_ipaddr->s_addr == - ((struct sockaddr_in *) &ifr[i].ifr_addr)->sin_addr.s_addr) { - found = True; - break; - } + ifr2 = ifr[i]; + if (ioctl(sock, SIOCGIFFLAGS, &ifr2) < 0) + DEBUG(0,("SIOCGIFFLAGS failed\n")); + + if ((ifr2.ifr_flags & (IFF_RUNNING | IFF_LOOPBACK)) != IFF_RUNNING) + continue; + + iface = (struct interface *)malloc(sizeof(*iface)); + assert(iface != NULL); + iface->next = NULL; + iface->ip = ((struct sockaddr_in *) &ifr[i].ifr_addr)->sin_addr; + iface->name = strdup(ifr[i].ifr_name); + iface->flags = ifr2.ifr_flags; + + /* complete with netmask and b'cast address */ + ifr2 = *ifr; + if (ioctl(sock, SIOCGIFNETMASK, &ifr2) < 0) + DEBUG(0,("SIOCGIFNETMASK failed\n")); + else + iface->nmask = ((struct sockaddr_in *)&ifr2.ifr_addr)->sin_addr; + if (ioctl(sock, SIOCGIFBRDADDR, &ifr2) < 0) + DEBUG(0,("SIOCGIFBRDADDR failed\n")); + else + iface->bcast = ((struct sockaddr_in *)&ifr2.ifr_addr)->sin_addr; + if (ioctl(sock, SIOCGIFMTU, &ifr2) < 0) + DEBUG(0,("SIOCGIFMTU failed\n")); + else + iface->mtu = ifr2.ifr_mtu; + + DEBUG(4,("Netmask for %s = %s\n", iface->name, inet_ntoa(iface->nmask))); + + if (!present_interfaces) + present_interfaces = iface; + else + last_iface->next = iface; + last_iface = iface; } } } @@ -147,10 +142,46 @@ static void get_broadcast(struct in_addr *if_ipaddr, /* Loop through interfaces, looking for given IP address */ for (i = ifc->ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) { - if (if_ipaddr->s_addr == - (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) { - found = True; - break; + ifr2 = *ifr; + if (ioctl(sock, SIOCGIFFLAGS, &ifr2) < 0) + DEBUG(0,("SIOCGIFFLAGS failed\n")); + + if ((ifr2.ifr_flags & (IFF_RUNNING | IFF_LOOPBACK)) == IFF_RUNNING) { + + iface = (struct interface *)malloc(sizeof(*iface)); + assert(iface != NULL); + iface->next = NULL; + iface->ip = (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr; + iface->name = strdup(ifr->ifr_name); + iface->flags = ifr2.ifr_flags; + + /* complete with netmask and b'cast address */ + ifr2 = *ifr; + strioctl.ic_cmd = SIOCGIFNETMASK; + strioctl.ic_dp = (char *)&ifr2; + strioctl.ic_len = sizeof(struct ifr2); + if (ioctl(sock, I_STR, &strioctl) < 0) + DEBUG(0,("Failed I_STR/SIOCGIFNETMASK: %s\n", strerror(errno))); + else + iface->nmask = ((struct sockaddr_in *)&ifr2.ifr_addr)->sin_addr; + strioctl.ic_cmd = SIOCGIFBRDADDR; + if (ioctl(sock, I_STR, &strioctl) < 0) + DEBUG(0,("SIOCGIFBRDADDR failed\n")); + else + iface->bcast = ((struct sockaddr_in *)&ifr2.ifr_addr)->sin_addr; + strioctl.ic_cmd = SIOCGIFMTU; + if (ioctl(sock, I_STR, &strioctl) < 0) + DEBUG(0,("SIOCGIFMTU failed\n")); + else + iface->mtu = ifr2.ifr_mtu; + + DEBUG(4,("Netmask for %s = %s\n", iface->name, inet_ntoa(iface->nmask))); + + if (!present_interfaces) + present_interfaces = iface; + else + last_iface->next = iface; + last_iface = iface; } } } @@ -164,11 +195,42 @@ static void get_broadcast(struct in_addr *if_ipaddr, /* Loop through interfaces, looking for given IP address */ i = ifc.ifc_len; while (i > 0) { - if (if_ipaddr->s_addr == - (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) { - found = True; - break; + ifr2 = *ifr; + if (ioctl(sock, SIOCGIFFLAGS, &ifr2) < 0) + DEBUG(0,("SIOCGIFFLAGS failed\n")); + + if ((ifr2.ifr_flags & (IFF_RUNNING | IFF_LOOPBACK)) == IFF_RUNNING) { + iface = (struct interface *)malloc(sizeof(*iface)); + assert(iface != NULL); + iface->next = NULL; + iface->ip = (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr; + iface->name = strdup(ifr->ifr_name); + iface->flags = ifr2.ifr_flags; + + /* complete with netmask and b'cast address */ + ifr2 = *ifr; + if (ioctl(sock, SIOCGIFNETMASK, &ifr2) < 0) + DEBUG(0,("SIOCGIFNETMASK failed\n")); + else + iface->nmask = (*(struct sockaddr_in *)&ifr2.ifr_addr).sin_addr; + if (ioctl(sock, SIOCGIFBRDADDR, &ifr2) < 0) + DEBUG(0,("SIOCGIFBRDADDR failed\n")); + else + iface->bcast = (*(struct sockaddr_in *)&ifr2.ifr_addr).sin_addr; + if (ioctl(sock, SIOCGIFMTU, &ifr2) < 0) + DEBUG(0,("SIOCGIFMTU failed\n")); + else + iface->mtu = ifr2.ifr_mtu; + + DEBUG(4,("Netmask for %s = %s\n", iface->name, inet_ntoa(iface->nmask))); + + if (!present_interfaces) + present_interfaces = iface; + else + last_iface->next = iface; + last_iface = iface; } + i -= ifr->ifr_addr.sa_len + IFNAMSIZ; ifr = (struct ifreq*) ((char*) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ); } @@ -183,70 +245,53 @@ static void get_broadcast(struct in_addr *if_ipaddr, /* Loop through interfaces, looking for given IP address */ for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) { + ifr2 = *ifr; + if (ioctl(sock, SIOCGIFFLAGS, &ifr2) < 0) + DEBUG(0,("SIOCGIFFLAGS failed\n")); + + if ((ifr2.ifr_flags & (IFF_RUNNING | IFF_LOOPBACK)) == IFF_RUNNING) { #ifdef BSDI - if (ioctl(sock, SIOCGIFADDR, ifr) < 0) break; + if (ioctl(sock, SIOCGIFADDR, ifr) < 0) break; #endif - if (if_ipaddr->s_addr == - (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) { - found = True; - break; + + iface = (struct interface *)malloc(sizeof(*iface)); + assert(iface != NULL); + iface->next = NULL; + iface->ip = (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr; + iface->name = strdup(ifr->ifr_name); + iface->flags = ifr2.ifr_flags; + + /* complete with netmask and b'cast address */ + ifr2 = *ifr; + if (ioctl(sock, SIOCGIFNETMASK, &ifr2) < 0) + DEBUG(0,("SIOCGIFNETMASK failed\n")); + else + iface->nmask = (*(struct sockaddr_in *)&ifr2.ifr_addr).sin_addr; + if (ioctl(sock, SIOCGIFBRDADDR, &ifr2) < 0) + DEBUG(0,("SIOCGIFBRDADDR failed\n")); + else + iface->bcast = (*(struct sockaddr_in *)&ifr2.ifr_addr).sin_addr; + if (ioctl(sock, SIOCGIFMTU, &ifr2) < 0) + DEBUG(0,("SIOCGIFMTU failed\n")); + else + iface->mtu = ifr2.ifr_mtu; + + DEBUG(4,("Netmask for %s = %s\n", iface->name, inet_ntoa(iface->nmask))); + + if (!present_interfaces) + present_interfaces = iface; + else + last_iface->next = iface; + last_iface = iface; } } } #endif - - if (!found) { - DEBUG(0,("No interface found for address %s\n", inet_ntoa(*if_ipaddr))); - } else { - /* Get the netmask address from the kernel */ -#ifdef USE_IFREQ - ifreq = *ifr; - - strioctl.ic_cmd = SIOCGIFNETMASK; - strioctl.ic_dp = (char *)&ifreq; - strioctl.ic_len = sizeof(struct ifreq); - if (ioctl(sock, I_STR, &strioctl) < 0) - DEBUG(0,("Failed I_STR/SIOCGIFNETMASK: %s\n", strerror(errno))); - else - *if_nmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr; -#else - if (ioctl(sock, SIOCGIFNETMASK, ifr) < 0) - DEBUG(0,("SIOCGIFNETMASK failed\n")); - else - *if_nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr; -#endif - - DEBUG(4,("Netmask for %s = %s\n", ifr->ifr_name, - inet_ntoa(*if_nmask))); - } /* Close up shop */ (void) close(sock); - -#endif - - /* sanity check on the netmask */ - { - uint32 nm = ntohl(if_nmask->s_addr); - if ((nm >> 24) != 0xFF) { - DEBUG(0,("Impossible netmask %s - using defaults\n",inet_ntoa(*if_nmask))); - default_netmask(if_nmask, if_ipaddr); - } - } - - /* derive the broadcast assuming a 1's broadcast, as this is what - all MS operating systems do, we have to comply even if the unix - box is setup differently */ - { - uint32 ad = ntohl(if_ipaddr->s_addr); - uint32 nm = ntohl(if_nmask->s_addr); - uint32 bc = (ad & nm) | (0xffffffff & ~nm); - if_bcast->s_addr = htonl(bc); - } - - DEBUG(4,("Derived broadcast address %s\n", inet_ntoa(*if_bcast))); -} /* get_broadcast */ +} /* get_interfaces */ /**************************************************************************** @@ -257,42 +302,68 @@ static void interpret_interfaces(char *s, struct interface **interfaces, { char *ptr = s; fstring token; - struct interface *iface; - struct in_addr ip; + struct interface *iface, *i; + BOOL seenALL = False; ipzero = *interpret_addr2("0.0.0.0"); wins_ip = *interpret_addr2("255.255.255.255"); + get_interfaces(); + while (next_token(&ptr,token,NULL)) { - /* parse it into an IP address/netmasklength pair */ - char *p = strchr(token,'/'); - if (p) *p = 0; - ip = *interpret_addr2(token); + if (strcasecmp(token, "ALL")) { + if (*interfaces) { + DEBUG(0, ("Error: interface name \"ALL\" must occur alone\n")); + /* should do something here ... */ + } - /* maybe we already have it listed */ - { - struct interface *i; - for (i=(*interfaces);i;i=i->next) - if (ip_equal(ip,i->ip)) break; - if (i) continue; + /* should we copy the list, or just point at it? */ + for (i = present_interfaces; i; i = i->next) { + iface = (struct interface *)malloc(sizeof(*iface)); + if (!iface) return; + + *iface = *i; + iface->next = NULL; + + if (!(*interfaces)) + (*interfaces) = iface; + else + last_iface->next = iface; + last_iface = iface; + } + + seenALL = True; + continue; + } else if (seenALL) { + DEBUG(0, ("Error: can't mix interface \"ALL\" with other interface namess\n")); + continue; } + /* maybe we already have it listed */ + for (i=(*interfaces);i;i=i->next) + if (strcasecmp(token,i->name)) break; + if (i) continue; + iface = (struct interface *)malloc(sizeof(*iface)); if (!iface) return; - iface->ip = ip; + /* make sure name is known */ + for (i=present_interfaces;i;i=i->next) + if (strcasecmp(token,i->name)) break; - if (p) { - if (strlen(p+1)>2) - iface->nmask = *interpret_addr2(p+1); - else - iface->nmask.s_addr = htonl(~((1<<(32-atoi(p+1)))-1)); - } else { - default_netmask(&iface->nmask,&iface->ip); + if (!i) { + DEBUG(0, ("Warning: unknown interface \"%s\" specified\n", token)); + continue; } - iface->bcast.s_addr = iface->ip.s_addr | ~iface->nmask.s_addr; + + *iface = *i; iface->next = NULL; + if (iface->bcast.s_addr != (iface->ip.s_addr | ~iface->nmask.s_addr)) { + DEBUG(0, ("Warning: overriding b'cast address %s on interface %s\n", + inet_ntoa(iface->bcast), iface->name)); + iface->bcast.s_addr = iface->ip.s_addr | ~iface->nmask.s_addr; + } if (!(*interfaces)) { (*interfaces) = iface; @@ -305,41 +376,8 @@ static void interpret_interfaces(char *s, struct interface **interfaces, DEBUG(1,("nmask=%s\n",inet_ntoa(iface->nmask))); } - if (*interfaces) return; - - /* setup a default interface */ - iface = (struct interface *)malloc(sizeof(*iface)); - if (!iface) return; - - iface->next = NULL; - - if (got_ip) { - iface->ip = default_ip; - } else { - get_myname(NULL,&iface->ip); - } - - if (got_bcast) { - iface->bcast = default_bcast; - } else { - get_broadcast(&iface->ip,&iface->bcast,&iface->nmask); - } - - if (got_nmask) { - iface->nmask = default_nmask; - iface->bcast.s_addr = iface->ip.s_addr | ~iface->nmask.s_addr; - } - - if (iface->bcast.s_addr != (iface->ip.s_addr | ~iface->nmask.s_addr)) { - DEBUG(2,("Warning: inconsistant interface %s\n",inet_ntoa(iface->ip))); - } - - iface->next = NULL; - (*interfaces) = last_iface = iface; - - DEBUG(1,("Added interface ip=%s ",inet_ntoa(iface->ip))); - DEBUG(1,("bcast=%s ",inet_ntoa(iface->bcast))); - DEBUG(1,("nmask=%s\n",inet_ntoa(iface->nmask))); + if (! *interfaces) + DEBUG(0,("Error: no interfaces specified.\n")); } @@ -358,20 +396,8 @@ void load_interfaces(void) **************************************************************************/ void iface_set_default(char *ip,char *bcast,char *nmask) { - if (ip) { - got_ip = True; - default_ip = *interpret_addr2(ip); - } - - if (bcast) { - got_bcast = True; - default_bcast = *interpret_addr2(bcast); - } - - if (nmask) { - got_nmask = True; - default_nmask = *interpret_addr2(nmask); - } + DEBUG(0, ("iface_set_default: function deprecated.\n")); + exit(1); } @@ -453,5 +479,3 @@ struct in_addr *iface_ip(struct in_addr ip) return(&iface_find(ip)->ip); } - - |