diff options
Diffstat (limited to 'source3/lib')
-rw-r--r-- | source3/lib/interface.c | 421 | ||||
-rw-r--r-- | source3/lib/time.c | 8 | ||||
-rw-r--r-- | source3/lib/util.c | 219 |
3 files changed, 427 insertions, 221 deletions
diff --git a/source3/lib/interface.c b/source3/lib/interface.c new file mode 100644 index 0000000000..a47ef6e47e --- /dev/null +++ b/source3/lib/interface.c @@ -0,0 +1,421 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + multiple interface handling + Copyright (C) Andrew Tridgell 1992-1995 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "loadparm.h" + +extern int DEBUGLEVEL; + +struct in_addr ipzero; +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; + +static struct interface { + struct interface *next; + struct in_addr ip; + struct in_addr bcast; + struct in_addr nmask; +} *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) +{ + unsigned long ad = ntohl(iad->s_addr); + unsigned long 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) +{ + BOOL found = False; +#ifndef NO_GET_BROADCAST + int sock = -1; /* AF_INET raw socket desc */ + char buff[1024]; + struct ifreq *ifr=NULL; + int i; + +#if defined(EVEREST) + int n_interfaces; + struct ifconf ifc; + struct ifreq *ifreqs; +#elif defined(USE_IFREQ) + struct ifreq ifreq; + struct strioctl strioctl; + struct ifconf *ifc; +#else + struct ifconf ifc; +#endif +#endif + + /* get a default netmask and broadcast */ + default_netmask(if_nmask, if_ipaddr); + +#ifndef NO_GET_BROADCAST + /* Create a socket to the INET kernel. */ +#if USE_SOCKRAW + if ((sock = socket(AF_INET, SOCK_RAW, PF_INET )) < 0) +#else + if ((sock = socket(AF_INET, SOCK_DGRAM, 0 )) < 0) +#endif + { + DEBUG(0,( "Unable to open socket to get broadcast address\n")); + return; + } + + /* Get a list of the configured interfaces */ +#ifdef EVEREST + /* This is part of SCO Openserver 5: The ioctls are no longer part + if the lower level STREAMS interface glue. They are now real + ioctl calls */ + + if (ioctl(sock, SIOCGIFANUM, &n_interfaces) < 0) { + DEBUG(0,( "SIOCGIFANUM: %s\n", strerror(errno))); + } else { + DEBUG(0,( "number of interfaces returned is: %d\n", n_interfaces)); + + ifc.ifc_len = sizeof(struct ifreq) * n_interfaces; + ifc.ifc_buf = (caddr_t) alloca(ifc.ifc_len); + + if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) + DEBUG(0, ( "SIOCGIFCONF: %s\n", strerror(errno))); + else { + 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; + } + } + } + } +#elif defined(USE_IFREQ) + ifc = (struct ifconf *)buff; + ifc->ifc_len = BUFSIZ - sizeof(struct ifconf); + strioctl.ic_cmd = SIOCGIFCONF; + strioctl.ic_dp = (char *)ifc; + strioctl.ic_len = sizeof(buff); + if (ioctl(sock, I_STR, &strioctl) < 0) { + DEBUG(0,( "I_STR/SIOCGIFCONF: %s\n", strerror(errno))); + } else { + ifr = (struct ifreq *)ifc->ifc_req; + + /* 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; + } + } + } +#elif defined(__FreeBSD__) || defined(NETBSD) + ifc.ifc_len = sizeof(buff); + ifc.ifc_buf = buff; + if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) { + DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno))); + } else { + ifr = ifc.ifc_req; + /* 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; + } + i -= ifr->ifr_addr.sa_len + IFNAMSIZ; + ifr = (struct ifreq*) ((char*) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ); + } + } +#else + ifc.ifc_len = sizeof(buff); + ifc.ifc_buf = buff; + if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) { + DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno))); + } else { + ifr = ifc.ifc_req; + + /* Loop through interfaces, looking for given IP address */ + for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) { +#ifdef BSDI + 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; + } + } + } +#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 */ + { + unsigned long 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 */ + { + unsigned long ad = ntohl(if_ipaddr->s_addr); + unsigned long nm = ntohl(if_nmask->s_addr); + unsigned long bc = (ad & nm) | (0xffffffff & ~nm); + if_bcast->s_addr = htonl(bc); + } + + DEBUG(4,("Derived broadcast address %s\n", inet_ntoa(*if_bcast))); +} /* get_broadcast */ + + + + +/**************************************************************************** +load a list of network interfaces +****************************************************************************/ +void load_interfaces(void) +{ + char *s = lp_interfaces(); + char *ptr = s; + fstring token; + struct interface *iface; + struct in_addr ip; + + ipzero = *interpret_addr2("0.0.0.0"); + + 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); + + /* 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; + } + + iface = (struct interface *)malloc(sizeof(*iface)); + if (!iface) return; + + iface->ip = ip; + + 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); + } + iface->bcast.s_addr = iface->ip.s_addr | ~iface->nmask.s_addr; + iface->next = NULL; + + if (!interfaces) { + interfaces = iface; + } else { + last_iface->next = iface; + } + 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) return; + + /* setup a default interface */ + iface = (struct interface *)malloc(sizeof(*iface)); + if (!iface) return; + + 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))); + } + + 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))); +} + + +/**************************************************************************** + override the defaults + **************************************************************************/ +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); + } +} + + +/**************************************************************************** + check if an IP is one of mine + **************************************************************************/ +BOOL ismyip(struct in_addr ip) +{ + struct interface *i; + for (i=interfaces;i;i=i->next) + if (ip_equal(i->ip,ip)) return True; + return False; +} + +/**************************************************************************** + check if a bcast is one of mine + **************************************************************************/ +BOOL ismybcast(struct in_addr bcast) +{ + struct interface *i; + for (i=interfaces;i;i=i->next) + if (ip_equal(i->bcast,bcast)) return True; + return False; +} + +static struct interface *iface_find(struct in_addr ip) +{ + struct interface *i; + if (zero_ip(ip)) return interfaces; + + for (i=interfaces;i;i=i->next) + if (same_net(i->ip,ip,i->nmask)) return i; + + return interfaces; +} + + +/* these 3 functions return the ip/bcast/nmask for the interface + most appropriate for the given ip address */ + +struct in_addr *iface_bcast(struct in_addr ip) +{ + return(&iface_find(ip)->bcast); +} + +struct in_addr *iface_nmask(struct in_addr ip) +{ + return(&iface_find(ip)->nmask); +} + +struct in_addr *iface_ip(struct in_addr ip) +{ + return(&iface_find(ip)->ip); +} + + diff --git a/source3/lib/time.c b/source3/lib/time.c index 0b6e6df9b0..efcda804c4 100644 --- a/source3/lib/time.c +++ b/source3/lib/time.c @@ -142,6 +142,10 @@ static int TimeZoneFaster(time_t t) if (t < low) low = TIME_T_MIN; + high = t + MAX_DST_WIDTH/2; + if (high < t) + high = TIME_T_MAX; + /* widen the new entry using two bisection searches */ while (low+60*60 < dst_table[i].start) { if (dst_table[i].start - low > MAX_DST_SKIP*2) @@ -154,10 +158,6 @@ static int TimeZoneFaster(time_t t) low = t; } - high = low + MAX_DST_WIDTH/2; - if (high < t) - high = TIME_T_MAX; - while (high-60*60 > dst_table[i].end) { if (high - dst_table[i].end > MAX_DST_SKIP*2) t = dst_table[i].end + MAX_DST_SKIP; diff --git a/source3/lib/util.c b/source3/lib/util.c index 8c088f306e..6cc9a7e172 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -49,11 +49,6 @@ struct in_addr lastip; /* the last port received from */ int lastport=0; -/* my IP, the broadcast IP and the Netmask */ -struct in_addr myip; -struct in_addr bcast_ip; -struct in_addr Netmask; - int trans_num = 0; /* @@ -2801,216 +2796,6 @@ void become_daemon(void) #endif } -/**************************************************************************** -calculate the default netmask for an address -****************************************************************************/ -static void default_netmask(struct in_addr *inm, struct in_addr *iad) -{ - unsigned long ad = ntohl(iad->s_addr); - unsigned long 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) -****************************************************************************/ -void get_broadcast(struct in_addr *if_ipaddr, - struct in_addr *if_bcast, - struct in_addr *if_nmask) -{ - BOOL found = False; -#ifndef NO_GET_BROADCAST - int sock = -1; /* AF_INET raw socket desc */ - char buff[1024]; - struct ifreq *ifr=NULL; - int i; - -#if defined(EVEREST) - int n_interfaces; - struct ifconf ifc; - struct ifreq *ifreqs; -#elif defined(USE_IFREQ) - struct ifreq ifreq; - struct strioctl strioctl; - struct ifconf *ifc; -#else - struct ifconf ifc; -#endif -#endif - - /* get a default netmask and broadcast */ - default_netmask(if_nmask, if_ipaddr); - -#ifndef NO_GET_BROADCAST - /* Create a socket to the INET kernel. */ -#if USE_SOCKRAW - if ((sock = socket(AF_INET, SOCK_RAW, PF_INET )) < 0) -#else - if ((sock = socket(AF_INET, SOCK_DGRAM, 0 )) < 0) -#endif - { - DEBUG(0,( "Unable to open socket to get broadcast address\n")); - return; - } - - /* Get a list of the configured interfaces */ -#ifdef EVEREST - /* This is part of SCO Openserver 5: The ioctls are no longer part - if the lower level STREAMS interface glue. They are now real - ioctl calls */ - - if (ioctl(sock, SIOCGIFANUM, &n_interfaces) < 0) { - DEBUG(0,( "SIOCGIFANUM: %s\n", strerror(errno))); - } else { - DEBUG(0,( "number of interfaces returned is: %d\n", n_interfaces)); - - ifc.ifc_len = sizeof(struct ifreq) * n_interfaces; - ifc.ifc_buf = (caddr_t) alloca(ifc.ifc_len); - - if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) - DEBUG(0, ( "SIOCGIFCONF: %s\n", strerror(errno))); - else { - 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; - } - } - } - } -#elif defined(USE_IFREQ) - ifc = (struct ifconf *)buff; - ifc->ifc_len = BUFSIZ - sizeof(struct ifconf); - strioctl.ic_cmd = SIOCGIFCONF; - strioctl.ic_dp = (char *)ifc; - strioctl.ic_len = sizeof(buff); - if (ioctl(sock, I_STR, &strioctl) < 0) { - DEBUG(0,( "I_STR/SIOCGIFCONF: %s\n", strerror(errno))); - } else { - ifr = (struct ifreq *)ifc->ifc_req; - - /* 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; - } - } - } -#elif defined(__FreeBSD__) || defined(NETBSD) - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; - if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) { - DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno))); - } else { - ifr = ifc.ifc_req; - /* 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; - } - i -= ifr->ifr_addr.sa_len + IFNAMSIZ; - ifr = (struct ifreq*) ((char*) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ); - } - } -#else - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; - if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) { - DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno))); - } else { - ifr = ifc.ifc_req; - - /* Loop through interfaces, looking for given IP address */ - for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) { -#ifdef BSDI - 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; - } - } - } -#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(2,("Netmask for %s = %s\n", ifr->ifr_name, - inet_ntoa(*if_nmask))); - } - - /* Close up shop */ - (void) close(sock); - -#endif - - /* sanity check on the netmask */ - { - unsigned long 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 */ - { - unsigned long ad = ntohl(if_ipaddr->s_addr); - unsigned long nm = ntohl(if_nmask->s_addr); - unsigned long bc = (ad & nm) | (0xffffffff & ~nm); - if_bcast->s_addr = htonl(bc); - } - - DEBUG(2,("Derived broadcast address %s\n", inet_ntoa(*if_bcast))); -} /* get_broadcast */ - /**************************************************************************** put up a yes/no prompt @@ -3511,7 +3296,7 @@ struct in_addr *interpret_addr2(char *str) { static struct in_addr ret; unsigned long a = interpret_addr(str); - putip((char *)&ret,(char *)&a); + ret.s_addr = a; return(&ret); } @@ -3731,7 +3516,7 @@ my own panic function - not suitable for general use ********************************************************************/ void ajt_panic(void) { - system("/usr/bin/X11/xedit -display :0 /tmp/ERROR_FAULT &"); + system("/usr/bin/X11/xedit -display :0 /tmp/ERROR_FAULT"); } #endif |