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