home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / Networking / SambaManager / samba-1.9.17p4 / source / interface.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-30  |  12.4 KB  |  460 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    multiple interface handling
  5.    Copyright (C) Andrew Tridgell 1992-1997
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. #include "includes.h"
  23.  
  24. extern int DEBUGLEVEL;
  25.  
  26. struct in_addr ipzero;
  27. struct in_addr wins_ip;
  28. struct in_addr loopback_ip;
  29. static struct in_addr default_ip;
  30. static struct in_addr default_bcast;
  31. static struct in_addr default_nmask;
  32. static BOOL got_ip=False;
  33. static BOOL got_bcast=False;
  34. static BOOL got_nmask=False;
  35.  
  36. struct interface *local_interfaces  = NULL;
  37.  
  38. struct interface *last_iface;
  39.  
  40. /****************************************************************************
  41. calculate the default netmask for an address
  42. ****************************************************************************/
  43. static void default_netmask(struct in_addr *inm, struct in_addr *iad)
  44. {
  45.   uint32 ad = ntohl(iad->s_addr);
  46.   uint32 nm;
  47.   /*
  48.   ** Guess a netmask based on the class of the IP address given.
  49.   */
  50.   if ( (ad & 0x80000000) == 0 ) {
  51.     /* class A address */
  52.     nm = 0xFF000000;
  53.   } else if ( (ad & 0xC0000000) == 0x80000000 ) {
  54.     /* class B address */
  55.     nm = 0xFFFF0000;
  56.   } else if ( (ad & 0xE0000000) == 0xC0000000 ) {
  57.     /* class C address */
  58.     nm = 0xFFFFFF00;
  59.   }  else {
  60.     /* class D or E; netmask doesn't make much sense - guess 4 bits */
  61.     nm =  0xFFFFFFF0;
  62.   }
  63.   inm->s_addr = htonl(nm);
  64. }
  65.  
  66.  
  67. /****************************************************************************
  68.   get the broadcast address for our address 
  69. (troyer@saifr00.ateng.az.honeywell.com)
  70. ****************************************************************************/
  71. static void get_broadcast(struct in_addr *if_ipaddr,
  72.               struct in_addr *if_bcast,
  73.               struct in_addr *if_nmask)
  74. {  
  75.   BOOL found = False;
  76. #ifndef NO_GET_BROADCAST
  77.   int sock = -1;               /* AF_INET raw socket desc */
  78.   char buff[1024];
  79.   struct ifreq *ifr=NULL;
  80.   int i;
  81.  
  82. #if defined(EVEREST)
  83.   int n_interfaces;
  84.   struct ifconf ifc;
  85.   struct ifreq  *ifreqs;
  86. #elif defined(USE_IFREQ)
  87.   struct ifreq ifreq;
  88.   struct strioctl strioctl;
  89.   struct ifconf *ifc;
  90. #else
  91.   struct ifconf ifc;
  92. #endif
  93. #endif
  94.  
  95.   /* get a default netmask and broadcast */
  96.   default_netmask(if_nmask, if_ipaddr);
  97.  
  98. #ifndef NO_GET_BROADCAST  
  99.   /* Create a socket to the INET kernel. */
  100. #if USE_SOCKRAW
  101.   if ((sock = socket(AF_INET, SOCK_RAW, PF_INET )) < 0)
  102. #else
  103.     if ((sock = socket(AF_INET, SOCK_DGRAM, 0 )) < 0)
  104. #endif
  105.       {
  106.         DEBUG(0,( "Unable to open socket to get broadcast address\n"));
  107.         return;
  108.       }
  109.   
  110.   /* Get a list of the configured interfaces */
  111. #ifdef EVEREST
  112.   /* This is part of SCO Openserver 5: The ioctls are no longer part
  113.      if the lower level STREAMS interface glue. They are now real
  114.      ioctl calls */
  115.  
  116.   if (ioctl(sock, SIOCGIFANUM, &n_interfaces) < 0) {
  117.     DEBUG(0,( "SIOCGIFANUM: %s\n", strerror(errno)));
  118.   } else {
  119.     DEBUG(0,( "number of interfaces returned is: %d\n", n_interfaces));
  120.  
  121.     ifc.ifc_len = sizeof(struct ifreq) * n_interfaces;
  122.     ifc.ifc_buf = (caddr_t) alloca(ifc.ifc_len);
  123.  
  124.     if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
  125.       DEBUG(0, ( "SIOCGIFCONF: %s\n", strerror(errno)));
  126.     else {
  127.       ifr = ifc.ifc_req;
  128.  
  129.       for (i = 0; i < n_interfaces; ++i) {
  130.     if (if_ipaddr->s_addr ==
  131.         ((struct sockaddr_in *) &ifr[i].ifr_addr)->sin_addr.s_addr) {
  132.       found = True;
  133.       break;
  134.     }
  135.       }
  136.     }
  137.   }
  138. #elif defined(USE_IFREQ)
  139.   ifc = (struct ifconf *)buff;
  140.   ifc->ifc_len = BUFSIZ - sizeof(struct ifconf);
  141.   strioctl.ic_cmd = SIOCGIFCONF;
  142.   strioctl.ic_dp  = (char *)ifc;
  143.   strioctl.ic_len = sizeof(buff);
  144.   if (ioctl(sock, I_STR, &strioctl) < 0) {
  145.     DEBUG(0,( "I_STR/SIOCGIFCONF: %s\n", strerror(errno)));
  146.   } else {
  147.     ifr = (struct ifreq *)ifc->ifc_req;  
  148.  
  149.     /* Loop through interfaces, looking for given IP address */
  150.     for (i = ifc->ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
  151.       if (if_ipaddr->s_addr ==
  152.       (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
  153.     found = True;
  154.     break;
  155.       }
  156.     }
  157.   }
  158. #elif defined(__FreeBSD__) || defined(NETBSD) || defined(AMIGA) || defined(_AIX41)
  159.   ifc.ifc_len = sizeof(buff);
  160.   ifc.ifc_buf = buff;
  161.   if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
  162.     DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
  163.   } else {
  164.     ifr = ifc.ifc_req;
  165.     /* Loop through interfaces, looking for given IP address */
  166.     i = ifc.ifc_len;
  167.     while (i > 0) {
  168.       if (if_ipaddr->s_addr ==
  169.       (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
  170.     found = True;
  171.     break;
  172.       }
  173.       i -= ifr->ifr_addr.sa_len + IFNAMSIZ;
  174.       ifr = (struct ifreq*) ((char*) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
  175.     }
  176.   }
  177. #else
  178.   ifc.ifc_len = sizeof(buff);
  179.   ifc.ifc_buf = buff;
  180.   if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
  181.     DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
  182.   } else {
  183.     ifr = ifc.ifc_req;
  184.   
  185.     /* Loop through interfaces, looking for given IP address */
  186.     for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
  187. #ifdef BSDI
  188.       if (ioctl(sock, SIOCGIFADDR, ifr) < 0) break;
  189. #endif
  190.       if (if_ipaddr->s_addr ==
  191.       (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
  192.     found = True;
  193.     break;
  194.       }
  195.     }
  196.   }
  197. #endif
  198.   
  199.   if (!found) {
  200.     DEBUG(0,("No interface found for address %s\n", inet_ntoa(*if_ipaddr)));
  201.   } else {
  202.     /* Get the netmask address from the kernel */
  203. #ifdef USE_IFREQ
  204.     ifreq = *ifr;
  205.   
  206.     strioctl.ic_cmd = SIOCGIFNETMASK;
  207.     strioctl.ic_dp  = (char *)&ifreq;
  208.     strioctl.ic_len = sizeof(struct ifreq);
  209.     if (ioctl(sock, I_STR, &strioctl) < 0)
  210.       DEBUG(0,("Failed I_STR/SIOCGIFNETMASK: %s\n", strerror(errno)));
  211.     else
  212.       *if_nmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
  213. #else
  214.     if (ioctl(sock, SIOCGIFNETMASK, ifr) < 0)
  215.       DEBUG(0,("SIOCGIFNETMASK failed\n"));
  216.     else
  217.       *if_nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
  218. #endif
  219.  
  220.     DEBUG(4,("Netmask for %s = %s\n", ifr->ifr_name,
  221.          inet_ntoa(*if_nmask)));
  222.   }
  223.  
  224.   /* Close up shop */
  225.   (void) close(sock);
  226.   
  227. #endif
  228.  
  229.   /* sanity check on the netmask */
  230.   {
  231.     uint32 nm = ntohl(if_nmask->s_addr);
  232.     if ((nm >> 24) != 0xFF) {
  233.       DEBUG(0,("Impossible netmask %s - using defaults\n",inet_ntoa(*if_nmask)));
  234.       default_netmask(if_nmask, if_ipaddr);      
  235.     }
  236.   }
  237.  
  238.   /* derive the broadcast assuming a 1's broadcast, as this is what
  239.      all MS operating systems do, we have to comply even if the unix
  240.      box is setup differently */
  241.   {
  242.     uint32 ad = ntohl(if_ipaddr->s_addr);
  243.     uint32 nm = ntohl(if_nmask->s_addr);
  244.     uint32 bc = (ad & nm) | (0xffffffff & ~nm);
  245.     if_bcast->s_addr = htonl(bc);
  246.   }
  247.   
  248.   DEBUG(4,("Derived broadcast address %s\n", inet_ntoa(*if_bcast)));
  249. }  /* get_broadcast */
  250.  
  251.  
  252.  
  253. /****************************************************************************
  254. load a list of network interfaces
  255. ****************************************************************************/
  256. static void interpret_interfaces(char *s, struct interface **interfaces,
  257.         char *description)
  258. {
  259.   char *ptr = s;
  260.   fstring token;
  261.   struct interface *iface;
  262.   struct in_addr ip;
  263.  
  264.   ipzero = *interpret_addr2("0.0.0.0");
  265.   wins_ip = *interpret_addr2("255.255.255.255");
  266.   loopback_ip = *interpret_addr2("127.0.0.1");
  267.  
  268.   while (next_token(&ptr,token,NULL)) {
  269.     /* parse it into an IP address/netmasklength pair */
  270.     char *p = strchr(token,'/');
  271.     if (p) *p = 0;
  272.  
  273.     ip = *interpret_addr2(token);
  274.  
  275.     /* maybe we already have it listed */
  276.     {
  277.       struct interface *i;
  278.       for (i=(*interfaces);i;i=i->next)
  279.     if (ip_equal(ip,i->ip)) break;
  280.       if (i) continue;
  281.     }
  282.  
  283.     iface = (struct interface *)malloc(sizeof(*iface));
  284.     if (!iface) return;
  285.  
  286.     iface->ip = ip;
  287.  
  288.     if (p) {
  289.       if (strlen(p+1)>2)
  290.     iface->nmask = *interpret_addr2(p+1);
  291.       else
  292.     iface->nmask.s_addr = htonl(~((1<<(32-atoi(p+1)))-1));
  293.     } else {
  294.       default_netmask(&iface->nmask,&iface->ip);
  295.     }
  296.     iface->bcast.s_addr = iface->ip.s_addr | ~iface->nmask.s_addr;
  297.     iface->next = NULL;
  298.  
  299.     if (!(*interfaces)) {
  300.       (*interfaces) = iface;
  301.     } else {
  302.       last_iface->next = iface;
  303.     }
  304.     last_iface = iface;
  305.     DEBUG(1,("Added %s ip=%s ",description,inet_ntoa(iface->ip)));
  306.     DEBUG(1,("bcast=%s ",inet_ntoa(iface->bcast)));
  307.     DEBUG(1,("nmask=%s\n",inet_ntoa(iface->nmask)));         
  308.   }
  309.  
  310.   if (*interfaces) return;
  311.  
  312.   /* setup a default interface */
  313.   iface = (struct interface *)malloc(sizeof(*iface));
  314.   if (!iface) return;
  315.  
  316.   iface->next = NULL;
  317.  
  318.   if (got_ip) {
  319.     iface->ip = default_ip;
  320.   } else {
  321.     get_myname(NULL,&iface->ip);
  322.   }
  323.  
  324.   if (got_bcast) {
  325.     iface->bcast = default_bcast;
  326.   } else {
  327.     get_broadcast(&iface->ip,&iface->bcast,&iface->nmask);
  328.   }
  329.  
  330.   if (got_nmask) {
  331.     iface->nmask = default_nmask;
  332.     iface->bcast.s_addr = iface->ip.s_addr | ~iface->nmask.s_addr;
  333.   }
  334.  
  335.   if (iface->bcast.s_addr != (iface->ip.s_addr | ~iface->nmask.s_addr)) {
  336.     DEBUG(2,("Warning: inconsistant interface %s\n",inet_ntoa(iface->ip)));
  337.   }
  338.  
  339.   iface->next = NULL;
  340.   (*interfaces) = last_iface = iface;
  341.  
  342.   DEBUG(2,("Added interface ip=%s ",inet_ntoa(iface->ip)));
  343.   DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
  344.   DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));         
  345. }
  346.  
  347.  
  348. /****************************************************************************
  349. load the remote and local interfaces
  350. ****************************************************************************/
  351. void load_interfaces(void)
  352. {
  353.   /* add the machine's interfaces to local interface structure*/
  354.   interpret_interfaces(lp_interfaces(), &local_interfaces,"interface");
  355. }
  356.  
  357.  
  358. /****************************************************************************
  359.   override the defaults
  360.   **************************************************************************/
  361. void iface_set_default(char *ip,char *bcast,char *nmask)
  362. {
  363.   if (ip) {
  364.     got_ip = True;
  365.     default_ip = *interpret_addr2(ip);
  366.   }
  367.  
  368.   if (bcast) {
  369.     got_bcast = True;
  370.     default_bcast = *interpret_addr2(bcast);
  371.   }
  372.  
  373.   if (nmask) {
  374.     got_nmask = True;
  375.     default_nmask = *interpret_addr2(nmask);
  376.   }
  377. }
  378.  
  379.  
  380. /****************************************************************************
  381.   check if an IP is one of mine
  382.   **************************************************************************/
  383. BOOL ismyip(struct in_addr ip)
  384. {
  385.   struct interface *i;
  386.   for (i=local_interfaces;i;i=i->next)
  387.     if (ip_equal(i->ip,ip)) return True;
  388.   return False;
  389. }
  390.  
  391. /****************************************************************************
  392.   check if a bcast is one of mine
  393.   **************************************************************************/
  394. BOOL ismybcast(struct in_addr bcast)
  395. {
  396.   struct interface *i;
  397.   for (i=local_interfaces;i;i=i->next)
  398.     if (ip_equal(i->bcast,bcast)) return True;
  399.   return False;
  400. }
  401.  
  402. /****************************************************************************
  403.   how many interfaces do we have
  404.   **************************************************************************/
  405. int iface_count(void)
  406. {
  407.   int ret = 0;
  408.   struct interface *i;
  409.  
  410.   for (i=local_interfaces;i;i=i->next)
  411.     ret++;
  412.   return ret;
  413. }
  414.  
  415. /****************************************************************************
  416.   return IP of the Nth interface
  417.   **************************************************************************/
  418. struct in_addr *iface_n_ip(int n)
  419. {
  420.   struct interface *i;
  421.   
  422.   for (i=local_interfaces;i && n;i=i->next)
  423.     n--;
  424.  
  425.   if (i) return &i->ip;
  426.   return NULL;
  427. }
  428.  
  429. static struct interface *iface_find(struct in_addr ip)
  430. {
  431.   struct interface *i;
  432.   if (zero_ip(ip)) return local_interfaces;
  433.  
  434.   for (i=local_interfaces;i;i=i->next)
  435.     if (same_net(i->ip,ip,i->nmask)) return i;
  436.  
  437.   return local_interfaces;
  438. }
  439.  
  440. /* these 3 functions return the ip/bcast/nmask for the interface
  441.    most appropriate for the given ip address */
  442.  
  443. struct in_addr *iface_bcast(struct in_addr ip)
  444. {
  445.   return(&iface_find(ip)->bcast);
  446. }
  447.  
  448. struct in_addr *iface_nmask(struct in_addr ip)
  449. {
  450.   return(&iface_find(ip)->nmask);
  451. }
  452.  
  453. struct in_addr *iface_ip(struct in_addr ip)
  454. {
  455.   return(&iface_find(ip)->ip);
  456. }
  457.  
  458.  
  459.  
  460.