home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / samba-1.9.18p7.tar.gz / samba-1.9.18p7.tar / samba-1.9.18p7 / source / interface.c < prev    next >
C/C++ Source or Header  |  1998-05-04  |  15KB  |  533 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    multiple interface handling
  5.    Copyright (C) Andrew Tridgell 1992-1998
  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 allones_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. static struct interface *local_interfaces  = NULL;
  37.  
  38. struct interface *last_iface;
  39.  
  40. #define ALLONES  ((uint32)0xFFFFFFFF)
  41. #define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
  42. /****************************************************************************
  43. calculate the default netmask for an address
  44. ****************************************************************************/
  45. static void default_netmask(struct in_addr *inm, struct in_addr *iad)
  46. {
  47.     /*
  48.     ** Guess a netmask based on the class of the IP address given.
  49.     */
  50.     switch((ntohl(iad->s_addr) & 0xE0000000)) {
  51.         case 0x00000000:     /* Class A addr */
  52.         case 0x20000000:
  53.         case 0x40000000:
  54.         case 0x60000000:
  55.         inm->s_addr = htonl(0xFF000000);
  56.         break;
  57.         
  58.     case 0x80000000:    /* Class B addr */
  59.         case 0xA0000000:
  60.         inm->s_addr = htonl(0xFFFF0000);
  61.         break;
  62.         
  63.     case 0xC0000000:    /* Class C addr */
  64.         inm->s_addr = htonl(0xFFFFFF00);
  65.         break;
  66.         
  67.     default:        /* ??? */
  68.         inm->s_addr = htonl(0xFFFFFFF0);
  69.         }
  70. }
  71.  
  72.  
  73. /****************************************************************************
  74.   get the broadcast address for our address 
  75. (troyer@saifr00.ateng.az.honeywell.com)
  76. ****************************************************************************/
  77. static void get_broadcast(struct in_addr *if_ipaddr,
  78.               struct in_addr *if_bcast,
  79.               struct in_addr *if_nmask)
  80. {  
  81.   BOOL found = False;
  82. #ifndef NO_GET_BROADCAST
  83.   int sock = -1;               /* AF_INET raw socket desc */
  84.   char buff[1024];
  85.   struct ifreq *ifr=NULL;
  86.   int i;
  87.  
  88. #if defined(EVEREST)
  89.   int n_interfaces;
  90.   struct ifconf ifc;
  91.   struct ifreq  *ifreqs;
  92. #elif defined(USE_IFREQ)
  93.   struct ifreq ifreq;
  94.   struct strioctl strioctl;
  95.   struct ifconf *ifc;
  96. #else
  97.   struct ifconf ifc;
  98. #endif
  99. #endif
  100.  
  101.   /* get a default netmask and broadcast */
  102.   default_netmask(if_nmask, if_ipaddr);
  103.  
  104. #ifndef NO_GET_BROADCAST  
  105.   /* Create a socket to the INET kernel. */
  106. #if USE_SOCKRAW
  107.   if ((sock = socket(AF_INET, SOCK_RAW, PF_INET )) < 0)
  108. #else
  109.     if ((sock = socket(AF_INET, SOCK_DGRAM, 0 )) < 0)
  110. #endif
  111.       {
  112.         DEBUG(0,( "Unable to open socket to get broadcast address\n"));
  113.         return;
  114.       }
  115.   
  116.   /* Get a list of the configured interfaces */
  117. #ifdef EVEREST
  118.   /* This is part of SCO Openserver 5: The ioctls are no longer part
  119.      if the lower level STREAMS interface glue. They are now real
  120.      ioctl calls */
  121.  
  122.   if (ioctl(sock, SIOCGIFANUM, &n_interfaces) < 0) {
  123.     DEBUG(0,( "SIOCGIFANUM: %s\n", strerror(errno)));
  124.   } else {
  125.     DEBUG(0,( "number of interfaces returned is: %d\n", n_interfaces));
  126.  
  127.     ifc.ifc_len = sizeof(struct ifreq) * n_interfaces;
  128.     ifc.ifc_buf = (caddr_t) alloca(ifc.ifc_len);
  129.  
  130.     if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
  131.       DEBUG(0, ( "SIOCGIFCONF: %s\n", strerror(errno)));
  132.     else {
  133.       ifr = ifc.ifc_req;
  134.  
  135.       for (i = 0; i < n_interfaces; ++i) {
  136.     if (if_ipaddr->s_addr ==
  137.         ((struct sockaddr_in *) &ifr[i].ifr_addr)->sin_addr.s_addr) {
  138.       found = True;
  139.       break;
  140.     }
  141.       }
  142.     }
  143.   }
  144. #elif defined(USE_IFREQ)
  145.   ifc = (struct ifconf *)buff;
  146.   ifc->ifc_len = BUFSIZ - sizeof(struct ifconf);
  147.   strioctl.ic_cmd = SIOCGIFCONF;
  148.   strioctl.ic_dp  = (char *)ifc;
  149.   strioctl.ic_len = sizeof(buff);
  150.   if (ioctl(sock, I_STR, &strioctl) < 0) {
  151.     DEBUG(0,( "I_STR/SIOCGIFCONF: %s\n", strerror(errno)));
  152.   } else {
  153.     ifr = (struct ifreq *)ifc->ifc_req;  
  154.  
  155.     /* Loop through interfaces, looking for given IP address */
  156.     for (i = ifc->ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
  157.       if (if_ipaddr->s_addr ==
  158.       (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
  159.     found = True;
  160.     break;
  161.       }
  162.     }
  163.   }
  164. #elif defined(__FreeBSD__) || defined(NETBSD) || defined(AMIGA) || defined(_AIX41) || defined(__OpenBSD__)
  165.   ifc.ifc_len = sizeof(buff);
  166.   ifc.ifc_buf = buff;
  167.   if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
  168.     DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
  169.   } else {
  170.     ifr = ifc.ifc_req;
  171.     /* Loop through interfaces, looking for given IP address */
  172.     i = ifc.ifc_len;
  173.     while (i > 0) {
  174.       if (if_ipaddr->s_addr ==
  175.       (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
  176.     found = True;
  177.     break;
  178.       }
  179.       i -= ifr->ifr_addr.sa_len + IFNAMSIZ;
  180.       ifr = (struct ifreq*) ((char*) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
  181.     }
  182.   }
  183. #else
  184.   ifc.ifc_len = sizeof(buff);
  185.   ifc.ifc_buf = buff;
  186.   if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
  187.     DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
  188.   } else {
  189.     ifr = ifc.ifc_req;
  190.   
  191.     /* Loop through interfaces, looking for given IP address */
  192.     for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
  193. #ifdef BSDI
  194.       if (ioctl(sock, SIOCGIFADDR, ifr) < 0) break;
  195. #endif
  196.       if (if_ipaddr->s_addr ==
  197.       (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
  198.     found = True;
  199.     break;
  200.       }
  201.     }
  202.   }
  203. #endif
  204.   
  205.   if (!found) {
  206.     DEBUG(0,("No interface found for address %s\n", inet_ntoa(*if_ipaddr)));
  207.   } else {
  208.     /* Get the netmask address from the kernel */
  209. #ifdef USE_IFREQ
  210.     ifreq = *ifr;
  211.   
  212.     strioctl.ic_cmd = SIOCGIFNETMASK;
  213.     strioctl.ic_dp  = (char *)&ifreq;
  214.     strioctl.ic_len = sizeof(struct ifreq);
  215.     if (ioctl(sock, I_STR, &strioctl) < 0)
  216.       DEBUG(0,("Failed I_STR/SIOCGIFNETMASK: %s\n", strerror(errno)));
  217.     else
  218.       *if_nmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
  219. #else
  220.     if (ioctl(sock, SIOCGIFNETMASK, ifr) < 0)
  221.       DEBUG(0,("SIOCGIFNETMASK failed\n"));
  222.     else
  223.       *if_nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
  224. #endif
  225.  
  226.     DEBUG(4,("Netmask for %s = %s\n", ifr->ifr_name,
  227.          inet_ntoa(*if_nmask)));
  228.   }
  229.  
  230.   /* Close up shop */
  231.   (void) close(sock);
  232.   
  233. #endif
  234.  
  235.   /* sanity check on the netmask */
  236.   {
  237.     uint32 nm;
  238.     short onbc;
  239.     short offbc;
  240.  
  241.     nm = ntohl(if_nmask->s_addr);
  242.     onbc = 0;
  243.     offbc = 0;
  244.     while( (onbc + offbc) < 32 )
  245.          {
  246.            if( nm & 0x80000000 )
  247.              {
  248.                onbc++;
  249.                if( offbc ) /* already found an off bit, so mask is wrong */
  250.                  {
  251.                    onbc = 34;
  252.                  }
  253.              }
  254.            else
  255.              {
  256.                offbc++;
  257.              }
  258.            nm <<= 1;
  259.          }
  260.     if ((onbc < 8)||(onbc == 34)) {
  261.       DEBUG(0,("Impossible netmask %s - using defaults\n",inet_ntoa(*if_nmask)));
  262.       default_netmask(if_nmask, if_ipaddr);      
  263.     }
  264.   }
  265.  
  266.   /* derive the broadcast assuming a 1's broadcast, as this is what
  267.      all MS operating systems do, we have to comply even if the unix
  268.      box is setup differently */
  269.   {
  270.     if_bcast->s_addr = MKBCADDR(if_ipaddr->s_addr, if_nmask->s_addr);
  271.   }
  272.   
  273.   DEBUG(4,("Derived broadcast address %s\n", inet_ntoa(*if_bcast)));
  274. }  /* get_broadcast */
  275.  
  276.  
  277.  
  278. /****************************************************************************
  279. load a list of network interfaces
  280. ****************************************************************************/
  281. static void interpret_interfaces(char *s, struct interface **interfaces,
  282.         char *description)
  283. {
  284.   char *ptr;
  285.   fstring token;
  286.   struct interface *iface;
  287.   struct in_addr ip;
  288.  
  289.   ptr = s;
  290.   ipzero = *interpret_addr2("0.0.0.0");
  291.   allones_ip = *interpret_addr2("255.255.255.255");
  292.   loopback_ip = *interpret_addr2("127.0.0.1");
  293.  
  294.   while (next_token(&ptr,token,NULL)) {
  295.     /* parse it into an IP address/netmasklength pair */
  296.     char *p = strchr(token,'/');
  297.     if (p) *p++ = 0;
  298.  
  299.     ip = *interpret_addr2(token);
  300.  
  301.     /* maybe we already have it listed */
  302.     {
  303.       struct interface *i;
  304.       for (i=(*interfaces);i;i=i->next)
  305.     if (ip_equal(ip,i->ip)) break;
  306.       if (i) continue;
  307.     }
  308.  
  309.     iface = (struct interface *)malloc(sizeof(*iface));
  310.     if (!iface) return;
  311.  
  312.     iface->ip = ip;
  313.  
  314.     if (p) {
  315.       if (strlen(p) > 2)
  316.        iface->nmask = *interpret_addr2(p);
  317.       else
  318.        iface->nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES));
  319.     } else {
  320.       default_netmask(&iface->nmask,&iface->ip);
  321.     }
  322.     iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
  323.     iface->next = NULL;
  324.  
  325.     if (!(*interfaces)) {
  326.       (*interfaces) = iface;
  327.     } else {
  328.       last_iface->next = iface;
  329.     }
  330.     last_iface = iface;
  331.     DEBUG(2,("Added %s ip=%s ",description,inet_ntoa(iface->ip)));
  332.     DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
  333.     DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));         
  334.   }
  335.  
  336.   if (*interfaces) return;
  337.  
  338.   /* setup a default interface */
  339.   iface = (struct interface *)malloc(sizeof(*iface));
  340.   if (!iface) return;
  341.  
  342.   iface->next = NULL;
  343.  
  344.   if (got_ip) {
  345.     iface->ip = default_ip;
  346.   } else {
  347.     get_myname(NULL,&iface->ip);
  348.   }
  349.  
  350.   if (got_bcast) {
  351.     iface->bcast = default_bcast;
  352.   } else {
  353.     get_broadcast(&iface->ip,&iface->bcast,&iface->nmask);
  354.   }
  355.  
  356.   if (got_nmask) {
  357.     iface->nmask = default_nmask;
  358.     iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
  359.   }
  360.  
  361.   if (iface->bcast.s_addr != MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr)) {
  362.     DEBUG(2,("Warning: inconsistant interface %s\n",inet_ntoa(iface->ip)));
  363.   }
  364.  
  365.   iface->next = NULL;
  366.   (*interfaces) = last_iface = iface;
  367.  
  368.   DEBUG(2,("Added interface ip=%s ",inet_ntoa(iface->ip)));
  369.   DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
  370.   DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));         
  371. }
  372.  
  373.  
  374. /****************************************************************************
  375. load the remote and local interfaces
  376. ****************************************************************************/
  377. void load_interfaces(void)
  378. {
  379.   /* add the machine's interfaces to local interface structure*/
  380.   interpret_interfaces(lp_interfaces(), &local_interfaces,"interface");
  381. }
  382.  
  383.  
  384. /****************************************************************************
  385.   override the defaults
  386.   **************************************************************************/
  387. void iface_set_default(char *ip,char *bcast,char *nmask)
  388. {
  389.   if (ip) {
  390.     got_ip = True;
  391.     default_ip = *interpret_addr2(ip);
  392.   }
  393.  
  394.   if (bcast) {
  395.     got_bcast = True;
  396.     default_bcast = *interpret_addr2(bcast);
  397.   }
  398.  
  399.   if (nmask) {
  400.     got_nmask = True;
  401.     default_nmask = *interpret_addr2(nmask);
  402.   }
  403. }
  404.  
  405.  
  406. /****************************************************************************
  407.   check if an IP is one of mine
  408.   **************************************************************************/
  409. BOOL ismyip(struct in_addr ip)
  410. {
  411.   struct interface *i;
  412.   for (i=local_interfaces;i;i=i->next)
  413.     if (ip_equal(i->ip,ip)) return True;
  414.   return False;
  415. }
  416.  
  417. /****************************************************************************
  418.   check if a bcast is one of mine
  419.   **************************************************************************/
  420. BOOL ismybcast(struct in_addr bcast)
  421. {
  422.   struct interface *i;
  423.   for (i=local_interfaces;i;i=i->next)
  424.     if (ip_equal(i->bcast,bcast)) return True;
  425.   return False;
  426. }
  427.  
  428. /****************************************************************************
  429.   check if a packet is from a local (known) net
  430.   **************************************************************************/
  431. BOOL is_local_net(struct in_addr from)
  432. {
  433.   struct interface *i;
  434.   for (i=local_interfaces;i;i=i->next)
  435.     if((from.s_addr & i->nmask.s_addr) == (i->ip.s_addr & i->nmask.s_addr))
  436.       return True;
  437.   return False;
  438. }
  439.  
  440. /****************************************************************************
  441.   how many interfaces do we have
  442.   **************************************************************************/
  443. int iface_count(void)
  444. {
  445.   int ret = 0;
  446.   struct interface *i;
  447.  
  448.   for (i=local_interfaces;i;i=i->next)
  449.     ret++;
  450.   return ret;
  451. }
  452.  
  453. /****************************************************************************
  454.  True if we have two or more interfaces.
  455.   **************************************************************************/
  456. BOOL we_are_multihomed(void)
  457. {
  458.   static int multi = -1;
  459.  
  460.   if(multi == -1)
  461.     multi = (iface_count() > 1 ? True : False);
  462.  
  463.   return multi;
  464. }
  465.  
  466. /****************************************************************************
  467.   return the Nth interface
  468.   **************************************************************************/
  469. struct interface *get_interface(int n)
  470.   struct interface *i;
  471.   
  472.   for (i=local_interfaces;i && n;i=i->next)
  473.     n--;
  474.  
  475.   if (i) return i;
  476.   return NULL;
  477. }
  478.  
  479. /****************************************************************************
  480.   return IP of the Nth interface
  481.   **************************************************************************/
  482. struct in_addr *iface_n_ip(int n)
  483. {
  484.   struct interface *i;
  485.   
  486.   for (i=local_interfaces;i && n;i=i->next)
  487.     n--;
  488.  
  489.   if (i) return &i->ip;
  490.   return NULL;
  491. }
  492.  
  493. /****************************************************************************
  494. Try and find an interface that matches an ip. If we cannot, return NULL
  495.   **************************************************************************/
  496. static struct interface *iface_find(struct in_addr ip)
  497. {
  498.   struct interface *i;
  499.   if (zero_ip(ip)) return local_interfaces;
  500.  
  501.   for (i=local_interfaces;i;i=i->next)
  502.     if (same_net(i->ip,ip,i->nmask)) return i;
  503.  
  504.   return NULL;
  505. }
  506.  
  507. /* these 3 functions return the ip/bcast/nmask for the interface
  508.    most appropriate for the given ip address. If they can't find
  509.    an appropriate interface they return the requested field of the
  510.    first known interface. */
  511.  
  512. struct in_addr *iface_bcast(struct in_addr ip)
  513. {
  514.   struct interface *i = iface_find(ip);
  515.   return(i ? &i->bcast : &local_interfaces->bcast);
  516. }
  517.  
  518. struct in_addr *iface_nmask(struct in_addr ip)
  519. {
  520.   struct interface *i = iface_find(ip);
  521.   return(i ? &i->nmask : &local_interfaces->nmask);
  522. }
  523.  
  524. struct in_addr *iface_ip(struct in_addr ip)
  525. {
  526.   struct interface *i = iface_find(ip);
  527.   return(i ? &i->ip : &local_interfaces->ip);
  528. }
  529.  
  530.  
  531.  
  532.