LCOV - code coverage report
Current view: top level - source3/lib - interface.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 172 346 49.7 %
Date: 2024-05-31 13:13:24 Functions: 16 23 69.6 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    multiple interface handling
       4             :    Copyright (C) Andrew Tridgell 1992-1998
       5             :    Copyright (C) Jeremy Allison 2007
       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 3 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, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "lib/socket/interfaces.h"
      23             : #include "librpc/gen_ndr/ioctl.h"
      24             : #include "lib/util/smb_strtox.h"
      25             : 
      26             : static struct iface_struct *probed_ifaces;
      27             : static int total_probed;
      28             : 
      29             : static struct interface *local_interfaces;
      30             : 
      31             : /****************************************************************************
      32             :  Check if an IP is one of mine.
      33             : **************************************************************************/
      34             : 
      35       11636 : bool ismyaddr(const struct sockaddr *ip)
      36             : {
      37           0 :         struct interface *i;
      38       31384 :         for (i=local_interfaces;i;i=i->next) {
      39       23990 :                 if (sockaddr_equal((struct sockaddr *)&i->ip,ip)) {
      40        4242 :                         return true;
      41             :                 }
      42             :         }
      43        7394 :         return false;
      44             : }
      45             : 
      46        8581 : bool ismyip_v4(struct in_addr ip)
      47             : {
      48           0 :         struct sockaddr_storage ss;
      49        8581 :         in_addr_to_sockaddr_storage(&ss, ip);
      50        8581 :         return ismyaddr((struct sockaddr *)&ss);
      51             : }
      52             : 
      53             : /****************************************************************************
      54             :  Try and find an interface that matches an ip. If we cannot, return NULL.
      55             : **************************************************************************/
      56             : 
      57      135280 : static struct interface *iface_find(const struct sockaddr *ip,
      58             :                                 bool check_mask)
      59             : {
      60         450 :         struct interface *i;
      61             : 
      62      135280 :         if (is_address_any(ip)) {
      63           0 :                 return local_interfaces;
      64             :         }
      65             : 
      66      489774 :         for (i=local_interfaces;i;i=i->next) {
      67      354902 :                 if (check_mask) {
      68         816 :                         if (same_net(ip, (struct sockaddr *)&i->ip, (struct sockaddr *)&i->netmask)) {
      69         408 :                                 return i;
      70             :                         }
      71      354086 :                 } else if (sockaddr_equal((struct sockaddr *)&i->ip, ip)) {
      72           0 :                         return i;
      73             :                 }
      74             :         }
      75             : 
      76      134422 :         return NULL;
      77             : }
      78             : 
      79             : /****************************************************************************
      80             :  Check if a packet is from a local (known) net.
      81             : **************************************************************************/
      82             : 
      83           0 : bool is_local_net(const struct sockaddr *from)
      84             : {
      85           0 :         struct interface *i;
      86           0 :         for (i=local_interfaces;i;i=i->next) {
      87           0 :                 if (same_net(from, (struct sockaddr *)&i->ip, (struct sockaddr *)&i->netmask)) {
      88           0 :                         return true;
      89             :                 }
      90             :         }
      91           0 :         return false;
      92             : }
      93             : 
      94             : #if defined(HAVE_IPV6)
      95           0 : void setup_linklocal_scope_id(struct sockaddr *pss)
      96             : {
      97           0 :         struct interface *i;
      98           0 :         for (i=local_interfaces;i;i=i->next) {
      99           0 :                 if (sockaddr_equal((struct sockaddr *)&i->ip,pss)) {
     100           0 :                         struct sockaddr_in6 *psa6 =
     101             :                                 (struct sockaddr_in6 *)pss;
     102           0 :                         psa6->sin6_scope_id = if_nametoindex(i->name);
     103           0 :                         return;
     104             :                 }
     105             :         }
     106             : }
     107             : #endif
     108             : 
     109             : /****************************************************************************
     110             :  Check if a packet is from a local (known) net.
     111             : **************************************************************************/
     112             : 
     113           0 : bool is_local_net_v4(struct in_addr from)
     114             : {
     115           0 :         struct sockaddr_storage ss;
     116             : 
     117           0 :         in_addr_to_sockaddr_storage(&ss, from);
     118           0 :         return is_local_net((struct sockaddr *)&ss);
     119             : }
     120             : 
     121             : /****************************************************************************
     122             :  How many interfaces do we have ?
     123             : **************************************************************************/
     124             : 
     125         872 : int iface_count(void)
     126             : {
     127         872 :         int ret = 0;
     128           8 :         struct interface *i;
     129             : 
     130        3181 :         for (i=local_interfaces;i;i=i->next) {
     131        2309 :                 ret++;
     132             :         }
     133         872 :         return ret;
     134             : }
     135             : 
     136             : /****************************************************************************
     137             :  How many non-loopback IPv4 interfaces do we have ?
     138             : **************************************************************************/
     139             : 
     140          86 : int iface_count_v4_nl(void)
     141             : {
     142          86 :         int ret = 0;
     143           0 :         struct interface *i;
     144             : 
     145         258 :         for (i=local_interfaces;i;i=i->next) {
     146         172 :                 if (is_loopback_addr((struct sockaddr *)&i->ip)) {
     147           0 :                         continue;
     148             :                 }
     149         172 :                 if (i->ip.ss_family == AF_INET) {
     150          86 :                         ret++;
     151             :                 }
     152             :         }
     153          86 :         return ret;
     154             : }
     155             : 
     156             : /****************************************************************************
     157             :  Return a pointer to the in_addr of the first IPv4 interface that's
     158             :  not 0.0.0.0.
     159             : **************************************************************************/
     160             : 
     161           0 : const struct in_addr *first_ipv4_iface(void)
     162             : {
     163           0 :         struct interface *i;
     164             : 
     165           0 :         for (i=local_interfaces;i ;i=i->next) {
     166           0 :                 if ((i->ip.ss_family == AF_INET) &&
     167           0 :                     (!is_zero_ip_v4(((struct sockaddr_in *)&i->ip)->sin_addr)))
     168             :                 {
     169           0 :                         break;
     170             :                 }
     171             :         }
     172             : 
     173           0 :         if (!i) {
     174           0 :                 return NULL;
     175             :         }
     176           0 :         return &((const struct sockaddr_in *)&i->ip)->sin_addr;
     177             : }
     178             : 
     179             : /****************************************************************************
     180             :  Return the Nth interface.
     181             : **************************************************************************/
     182             : 
     183         326 : struct interface *get_interface(int n)
     184             : {
     185          16 :         struct interface *i;
     186             : 
     187         489 :         for (i=local_interfaces;i && n;i=i->next) {
     188         163 :                 n--;
     189             :         }
     190             : 
     191         326 :         if (i) {
     192         326 :                 return i;
     193             :         }
     194           0 :         return NULL;
     195             : }
     196             : 
     197             : /****************************************************************************
     198             :  Return IP sockaddr_storage of the Nth interface.
     199             : **************************************************************************/
     200             : 
     201         386 : const struct sockaddr_storage *iface_n_sockaddr_storage(int n)
     202             : {
     203           0 :         struct interface *i;
     204             : 
     205        1034 :         for (i=local_interfaces;i && n;i=i->next) {
     206         648 :                 n--;
     207             :         }
     208             : 
     209         386 :         if (i) {
     210         386 :                 return &i->ip;
     211             :         }
     212           0 :         return NULL;
     213             : }
     214             : 
     215             : /****************************************************************************
     216             :  Return IPv4 of the Nth interface (if a v4 address). NULL otherwise.
     217             : **************************************************************************/
     218             : 
     219         170 : const struct in_addr *iface_n_ip_v4(int n)
     220             : {
     221           0 :         struct interface *i;
     222             : 
     223         255 :         for (i=local_interfaces;i && n;i=i->next) {
     224          85 :                 n--;
     225             :         }
     226             : 
     227         170 :         if (i && i->ip.ss_family == AF_INET) {
     228          85 :                 return &((const struct sockaddr_in *)&i->ip)->sin_addr;
     229             :         }
     230          85 :         return NULL;
     231             : }
     232             : 
     233             : /****************************************************************************
     234             :  Return IPv4 bcast of the Nth interface (if a v4 address). NULL otherwise.
     235             : **************************************************************************/
     236             : 
     237           0 : const struct in_addr *iface_n_bcast_v4(int n)
     238             : {
     239           0 :         struct interface *i;
     240             : 
     241           0 :         for (i=local_interfaces;i && n;i=i->next) {
     242           0 :                 n--;
     243             :         }
     244             : 
     245           0 :         if (i && i->ip.ss_family == AF_INET) {
     246           0 :                 return &((const struct sockaddr_in *)&i->bcast)->sin_addr;
     247             :         }
     248           0 :         return NULL;
     249             : }
     250             : 
     251             : /****************************************************************************
     252             :  Return bcast of the Nth interface.
     253             : **************************************************************************/
     254             : 
     255        1085 : const struct sockaddr_storage *iface_n_bcast(int n)
     256             : {
     257           0 :         struct interface *i;
     258             : 
     259        3150 :         for (i=local_interfaces;i && n;i=i->next) {
     260        2065 :                 n--;
     261             :         }
     262             : 
     263        1085 :         if (i) {
     264        1085 :                 return &i->bcast;
     265             :         }
     266           0 :         return NULL;
     267             : }
     268             : 
     269             : /* these 3 functions return the ip/bcast/nmask for the interface
     270             :    most appropriate for the given ip address. If they can't find
     271             :    an appropriate interface they return the requested field of the
     272             :    first known interface. */
     273             : 
     274         356 : const struct sockaddr_storage *iface_ip(const struct sockaddr *ip)
     275             : {
     276         356 :         struct interface *i = iface_find(ip, true);
     277         356 :         if (i) {
     278         356 :                 return &i->ip;
     279             :         }
     280             : 
     281             :         /* Search for the first interface with
     282             :          * matching address family. */
     283             : 
     284           0 :         for (i=local_interfaces;i;i=i->next) {
     285           0 :                 if (i->ip.ss_family == ip->sa_family) {
     286           0 :                         return &i->ip;
     287             :                 }
     288             :         }
     289           0 :         return NULL;
     290             : }
     291             : 
     292             : /*
     293             :   return True if a IP is directly reachable on one of our interfaces
     294             : */
     295             : 
     296          52 : bool iface_local(const struct sockaddr *ip)
     297             : {
     298          52 :         return iface_find(ip, true) ? true : false;
     299             : }
     300             : 
     301             : /****************************************************************************
     302             :  Add an interface to the linked list of interfaces.
     303             : ****************************************************************************/
     304             : 
     305      134872 : static void add_interface(const struct iface_struct *ifs)
     306             : {
     307         450 :         char addr[INET6_ADDRSTRLEN];
     308         450 :         struct interface *iface;
     309             : 
     310      134872 :         if (iface_find((const struct sockaddr *)&ifs->ip, False)) {
     311           0 :                 DEBUG(3,("add_interface: not adding duplicate interface %s\n",
     312             :                         print_sockaddr(addr, sizeof(addr), &ifs->ip) ));
     313           0 :                 return;
     314             :         }
     315             : 
     316      134872 :         if (!(ifs->flags & (IFF_BROADCAST|IFF_LOOPBACK))) {
     317           0 :                 DEBUG(3,("not adding non-broadcast interface %s\n",
     318             :                                         ifs->name ));
     319           0 :                 return;
     320             :         }
     321             : 
     322      134872 :         iface = SMB_MALLOC_P(struct interface);
     323      134872 :         if (!iface) {
     324           0 :                 return;
     325             :         }
     326             : 
     327      134872 :         ZERO_STRUCTPN(iface);
     328             : 
     329      134872 :         iface->name = SMB_STRDUP(ifs->name);
     330      134872 :         if (!iface->name) {
     331           0 :                 SAFE_FREE(iface);
     332           0 :                 return;
     333             :         }
     334      134872 :         iface->flags = ifs->flags;
     335      134872 :         iface->ip = ifs->ip;
     336      134872 :         iface->netmask = ifs->netmask;
     337      134872 :         iface->bcast = ifs->bcast;
     338      134872 :         iface->linkspeed = ifs->linkspeed;
     339      134872 :         iface->capability = ifs->capability;
     340      134872 :         iface->if_index = ifs->if_index;
     341      134872 :         iface->options = ifs->options;
     342             : 
     343      134872 :         DLIST_ADD(local_interfaces, iface);
     344             : 
     345      134872 :         DEBUG(2,("added interface %s ip=%s ",
     346             :                 iface->name,
     347             :                 print_sockaddr(addr, sizeof(addr), &iface->ip) ));
     348      134872 :         DEBUG(2,("bcast=%s ",
     349             :                 print_sockaddr(addr, sizeof(addr),
     350             :                         &iface->bcast) ));
     351      134872 :         DEBUG(2,("netmask=%s\n",
     352             :                 print_sockaddr(addr, sizeof(addr),
     353             :                         &iface->netmask) ));
     354             : }
     355             : 
     356             : 
     357           0 : static void parse_extra_info(char *key,
     358             :                              uint64_t *speed,
     359             :                              uint32_t *cap,
     360             :                              uint32_t *if_index,
     361             :                              uint32_t *options)
     362             : {
     363           0 :         while (key != NULL && *key != '\0') {
     364           0 :                 char *next_key;
     365           0 :                 char *val;
     366           0 :                 int error = 0;
     367             : 
     368           0 :                 next_key = strchr_m(key, ',');
     369           0 :                 if (next_key != NULL) {
     370           0 :                         *next_key++ = 0;
     371             :                 }
     372             : 
     373           0 :                 val = strchr_m(key, '=');
     374           0 :                 if (val != NULL) {
     375           0 :                         *val++ = 0;
     376             : 
     377           0 :                         if (strequal_m(key, "speed")) {
     378           0 :                                 *speed = (uint64_t)smb_strtoull(val,
     379             :                                                                 NULL,
     380             :                                                                 0,
     381             :                                                                 &error,
     382             :                                                                 SMB_STR_STANDARD);
     383           0 :                                 if (error != 0) {
     384           0 :                                         DBG_DEBUG("Invalid speed value (%s)\n", val);
     385             :                                 }
     386           0 :                         } else if (strequal_m(key, "capability")) {
     387           0 :                                 if (strequal_m(val, "RSS")) {
     388           0 :                                         *cap |= FSCTL_NET_IFACE_RSS_CAPABLE;
     389           0 :                                 } else if (strequal(val, "RDMA")) {
     390           0 :                                         *cap |= FSCTL_NET_IFACE_RDMA_CAPABLE;
     391             :                                 } else {
     392           0 :                                         DBG_WARNING("Capability unknown: "
     393             :                                                     "'%s'\n", val);
     394             :                                 }
     395           0 :                         } else if (strequal_m(key, "if_index")) {
     396           0 :                                 *if_index = (uint32_t)smb_strtoul(val,
     397             :                                                                   NULL,
     398             :                                                                   0,
     399             :                                                                   &error,
     400             :                                                                   SMB_STR_STANDARD);
     401           0 :                                 if (error != 0) {
     402           0 :                                         DBG_DEBUG("Invalid key value (%s)\n", val);
     403             :                                 }
     404           0 :                         } else if (strequal_m(key, "options")) {
     405           0 :                                 if (strequal_m(val, "dynamic")) {
     406           0 :                                         *options |= IFACE_DYNAMIC_OPTION;
     407           0 :                                 } else if (strequal_m(val, "nodynamic")) {
     408           0 :                                         *options &= ~IFACE_DYNAMIC_OPTION;
     409             :                                 } else {
     410           0 :                                         DBG_WARNING("Options unknown: "
     411             :                                                     "'%s'\n", val);
     412             :                                 }
     413             :                         } else {
     414           0 :                                 DBG_DEBUG("Key unknown: '%s'\n", key);
     415             :                         }
     416             :                 }
     417             : 
     418           0 :                 key = next_key;
     419             :         }
     420           0 : }
     421             : 
     422             : /****************************************************************************
     423             :  Interpret a single element from a interfaces= config line.
     424             : 
     425             :  This handles the following different forms:
     426             : 
     427             :  1) wildcard interface name
     428             :  2) DNS name
     429             :  3) IP/masklen
     430             :  4) ip/mask
     431             :  5) bcast/mask
     432             : 
     433             :  Additional information for an interface can be specified with
     434             :  this extended syntax:
     435             : 
     436             :     "interface[;key1=value1[,key2=value2[...]]]"
     437             : 
     438             :  Note: The double quoting is important for the
     439             :        smb.conf parser! Otherwise the ';' and ',' separates
     440             :        two interfaces.
     441             : 
     442             :  where
     443             :  - keys known: 'speed', 'capability', 'if_index'
     444             :  - speed is in bits per second
     445             :  - capabilities known: 'RSS', 'RDMA'
     446             :  - if_index should be used with care, because
     447             :    these indexes should not conicide with indexes
     448             :    the kernel sets...
     449             : 
     450             :  Note: The specified values overwrite the autodetected values!
     451             : 
     452             : ****************************************************************************/
     453             : 
     454      134764 : static void interpret_interface(char *token)
     455             : {
     456         422 :         struct sockaddr_storage ss;
     457         422 :         struct sockaddr_storage ss_mask;
     458         422 :         struct sockaddr_storage ss_net;
     459         422 :         struct sockaddr_storage ss_bcast;
     460         422 :         struct iface_struct ifs;
     461         422 :         char *p;
     462         422 :         int i;
     463      134764 :         bool added=false;
     464      134764 :         bool goodaddr = false;
     465      134764 :         uint64_t speed = 0;
     466      134764 :         uint32_t cap = FSCTL_NET_IFACE_NONE_CAPABLE;
     467      134764 :         uint32_t if_index = 0;
     468      134764 :         bool speed_set = false;
     469      134764 :         bool cap_set = false;
     470      134764 :         bool if_index_set = false;
     471      134764 :         uint32_t options = IFACE_NONE_OPTION;
     472      134764 :         bool options_set = false;
     473             : 
     474             :         /*
     475             :          * extract speed / capability information if present
     476             :          */
     477      134764 :         p = strchr_m(token, ';');
     478      134764 :         if (p != NULL) {
     479           0 :                 *p++ = 0;
     480           0 :                 parse_extra_info(p, &speed, &cap, &if_index, &options);
     481           0 :                 if (speed != 0) {
     482           0 :                         speed_set = true;
     483             :                 }
     484           0 :                 if (cap != FSCTL_NET_IFACE_NONE_CAPABLE) {
     485           0 :                         cap_set = true;
     486             :                 }
     487           0 :                 if (if_index != 0) {
     488           0 :                         if_index_set = true;
     489             :                 }
     490           0 :                 if (options != IFACE_NONE_OPTION) {
     491           0 :                         options_set = true;
     492             :                 }
     493             :         }
     494             : 
     495             :         /* first check if it is an interface name */
     496      673820 :         for (i=0;i<total_probed;i++) {
     497      539056 :                 if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
     498           0 :                         if (speed_set) {
     499           0 :                                 probed_ifaces[i].linkspeed = speed;
     500             :                         }
     501           0 :                         if (cap_set) {
     502           0 :                                 probed_ifaces[i].capability = cap;
     503             :                         }
     504           0 :                         if (if_index_set) {
     505           0 :                                 probed_ifaces[i].if_index = if_index;
     506             :                         }
     507           0 :                         if (options_set) {
     508           0 :                                  probed_ifaces[i].options = options;
     509             :                         }
     510           0 :                         add_interface(&probed_ifaces[i]);
     511           0 :                         added = true;
     512             :                 }
     513             :         }
     514      134764 :         if (added) {
     515           0 :                 return;
     516             :         }
     517             : 
     518      134764 :         p = strchr_m(token,'/');
     519      134764 :         if (p == NULL) {
     520           0 :                 if (!interpret_string_addr(&ss, token, 0)) {
     521           0 :                         DEBUG(2, ("interpret_interface: Can't find address "
     522             :                                   "for %s\n", token));
     523           0 :                         return;
     524             :                 }
     525             : 
     526           0 :                 for (i=0;i<total_probed;i++) {
     527           0 :                         if (sockaddr_equal((struct sockaddr *)&ss,
     528           0 :                                 (struct sockaddr *)&probed_ifaces[i].ip))
     529             :                         {
     530           0 :                                 if (speed_set) {
     531           0 :                                         probed_ifaces[i].linkspeed = speed;
     532             :                                 }
     533           0 :                                 if (cap_set) {
     534           0 :                                         probed_ifaces[i].capability = cap;
     535             :                                 }
     536           0 :                                 if (if_index_set) {
     537           0 :                                         probed_ifaces[i].if_index = if_index;
     538             :                                 }
     539           0 :                                 if (options_set) {
     540           0 :                                         probed_ifaces[i].options = options;
     541             :                                 }
     542           0 :                                 add_interface(&probed_ifaces[i]);
     543           0 :                                 return;
     544             :                         }
     545             :                 }
     546           0 :                 DEBUG(2,("interpret_interface: "
     547             :                         "can't determine interface for %s\n",
     548             :                         token));
     549           0 :                 return;
     550             :         }
     551             : 
     552             :         /* parse it into an IP address/netmasklength pair */
     553      134764 :         *p = 0;
     554      134764 :         goodaddr = interpret_string_addr(&ss, token, 0);
     555      134764 :         *p++ = '/';
     556             : 
     557      134764 :         if (!goodaddr) {
     558           0 :                 DEBUG(2,("interpret_interface: "
     559             :                         "can't determine interface for %s\n",
     560             :                         token));
     561           0 :                 return;
     562             :         }
     563             : 
     564      134764 :         if (strlen(p) > 2) {
     565           0 :                 goodaddr = interpret_string_addr(&ss_mask, p, 0);
     566           0 :                 if (!goodaddr) {
     567           0 :                         DEBUG(2,("interpret_interface: "
     568             :                                 "can't determine netmask from %s\n",
     569             :                                 p));
     570           0 :                         return;
     571             :                 }
     572             :         } else {
     573      134764 :                 int error = 0;
     574         422 :                 unsigned long val;
     575             : 
     576      134764 :                 val = smb_strtoul(p, NULL, 0, &error, SMB_STR_FULL_STR_CONV);
     577      134764 :                 if (error != 0) {
     578           0 :                         DEBUG(2,("interpret_interface: "
     579             :                                 "can't determine netmask value from %s\n",
     580             :                                 p));
     581           0 :                         return;
     582             :                 }
     583      134764 :                 if (!make_netmask(&ss_mask, &ss, val)) {
     584           0 :                         DEBUG(2,("interpret_interface: "
     585             :                                 "can't apply netmask value %lu from %s\n",
     586             :                                 val,
     587             :                                 p));
     588           0 :                         return;
     589             :                 }
     590             :         }
     591             : 
     592      134764 :         make_bcast(&ss_bcast, &ss, &ss_mask);
     593      134764 :         make_net(&ss_net, &ss, &ss_mask);
     594             : 
     595             :         /* Maybe the first component was a broadcast address. */
     596      269528 :         if (sockaddr_equal((struct sockaddr *)&ss_bcast, (struct sockaddr *)&ss) ||
     597      134764 :                 sockaddr_equal((struct sockaddr *)&ss_net, (struct sockaddr *)&ss)) {
     598           0 :                 for (i=0;i<total_probed;i++) {
     599           0 :                         if (same_net((struct sockaddr *)&ss, 
     600           0 :                                                  (struct sockaddr *)&probed_ifaces[i].ip, 
     601             :                                                  (struct sockaddr *)&ss_mask)) {
     602             :                                 /* Temporarily replace netmask on
     603             :                                  * the detected interface - user knows
     604             :                                  * best.... */
     605           0 :                                 struct sockaddr_storage saved_mask =
     606           0 :                                         probed_ifaces[i].netmask;
     607           0 :                                 probed_ifaces[i].netmask = ss_mask;
     608           0 :                                 DEBUG(2,("interpret_interface: "
     609             :                                         "using netmask value %s from "
     610             :                                         "config file on interface %s\n",
     611             :                                         p,
     612             :                                         probed_ifaces[i].name));
     613           0 :                                 if (speed_set) {
     614           0 :                                         probed_ifaces[i].linkspeed = speed;
     615             :                                 }
     616           0 :                                 if (cap_set) {
     617           0 :                                         probed_ifaces[i].capability = cap;
     618             :                                 }
     619           0 :                                 if (if_index_set) {
     620           0 :                                         probed_ifaces[i].if_index = if_index;
     621             :                                 }
     622           0 :                                 if (options_set) {
     623           0 :                                         probed_ifaces[i].options = options;
     624             :                                 }
     625           0 :                                 add_interface(&probed_ifaces[i]);
     626           0 :                                 probed_ifaces[i].netmask = saved_mask;
     627           0 :                                 return;
     628             :                         }
     629             :                 }
     630           0 :                 DEBUG(2,("interpret_interface: Can't determine ip for "
     631             :                         "broadcast address %s\n",
     632             :                         token));
     633           0 :                 return;
     634             :         }
     635             : 
     636             :         /* Just fake up the interface definition. User knows best. */
     637             : 
     638      134764 :         DEBUG(2,("interpret_interface: Adding interface %s\n",
     639             :                 token));
     640             : 
     641      134764 :         ZERO_STRUCT(ifs);
     642      134764 :         (void)strlcpy(ifs.name, token, sizeof(ifs.name));
     643      134764 :         ifs.flags = IFF_BROADCAST;
     644      134764 :         ifs.ip = ss;
     645      134764 :         ifs.netmask = ss_mask;
     646      134764 :         ifs.bcast = ss_bcast;
     647      134764 :         if (if_index_set) {
     648           0 :                 ifs.if_index = if_index;
     649             :         }
     650      134764 :         if (speed_set) {
     651           0 :                 ifs.linkspeed = speed;
     652             :         } else {
     653      134764 :                 ifs.linkspeed = 1000 * 1000 * 1000;
     654             :         }
     655      134764 :         ifs.capability = cap;
     656      134764 :         ifs.options = options;
     657      134764 :         add_interface(&ifs);
     658             : }
     659             : 
     660             : /****************************************************************************
     661             :  Load the list of network interfaces.
     662             : ****************************************************************************/
     663             : 
     664       26486 : void load_interfaces(void)
     665             : {
     666       26486 :         struct iface_struct *ifaces = NULL;
     667       26486 :         const char **ptr = lp_interfaces();
     668          80 :         int i;
     669             : 
     670       26486 :         gfree_interfaces();
     671             : 
     672             :         /* Probe the kernel for interfaces */
     673       26486 :         total_probed = get_interfaces(talloc_tos(), &ifaces);
     674             : 
     675       26486 :         if (total_probed > 0) {
     676       26486 :                 probed_ifaces = (struct iface_struct *)smb_memdup(ifaces,
     677             :                                 sizeof(ifaces[0])*total_probed);
     678       26486 :                 if (!probed_ifaces) {
     679           0 :                         DEBUG(0,("ERROR: smb_memdup failed\n"));
     680           0 :                         exit(1);
     681             :                 }
     682             :         }
     683       26486 :         TALLOC_FREE(ifaces);
     684             : 
     685             :         /* if we don't have a interfaces line then use all broadcast capable
     686             :            interfaces except loopback */
     687       26486 :         if (!ptr || !*ptr || !**ptr) {
     688          54 :                 if (total_probed <= 0) {
     689           0 :                         DEBUG(0,("ERROR: Could not determine network "
     690             :                         "interfaces, you must use a interfaces config line\n"));
     691           0 :                         exit(1);
     692             :                 }
     693         270 :                 for (i=0;i<total_probed;i++) {
     694         216 :                         if (probed_ifaces[i].flags & IFF_BROADCAST) {
     695         108 :                                 add_interface(&probed_ifaces[i]);
     696             :                         }
     697             :                 }
     698          54 :                 return;
     699             :         }
     700             : 
     701       26366 :         if (ptr) {
     702      161196 :                 while (*ptr) {
     703      134764 :                         char *ptr_cpy = SMB_STRDUP(*ptr);
     704      134764 :                         if (ptr_cpy) {
     705      134764 :                                 interpret_interface(ptr_cpy);
     706      134764 :                                 free(ptr_cpy);
     707             :                         }
     708      134764 :                         ptr++;
     709             :                 }
     710             :         }
     711             : 
     712       26432 :         if (!local_interfaces) {
     713           0 :                 DEBUG(0,("WARNING: no network interfaces found\n"));
     714             :         }
     715             : }
     716             : 
     717             : 
     718       42295 : void gfree_interfaces(void)
     719             : {
     720      150374 :         while (local_interfaces) {
     721      103445 :                 struct interface *iface = local_interfaces;
     722      103445 :                 DLIST_REMOVE(local_interfaces, local_interfaces);
     723      103445 :                 SAFE_FREE(iface->name);
     724      103530 :                 SAFE_FREE(iface);
     725             :         }
     726             : 
     727       42295 :         SAFE_FREE(probed_ifaces);
     728       42295 : }
     729             : 
     730             : /****************************************************************************
     731             :  Return True if the list of probed interfaces has changed.
     732             : ****************************************************************************/
     733             : 
     734         499 : bool interfaces_changed(void)
     735             : {
     736         499 :         bool ret = false;
     737           0 :         int n;
     738         499 :         struct iface_struct *ifaces = NULL;
     739             : 
     740         499 :         n = get_interfaces(talloc_tos(), &ifaces);
     741             : 
     742         499 :         if ((n > 0 )&& (n != total_probed ||
     743         499 :                         memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
     744           0 :                 ret = true;
     745             :         }
     746             : 
     747         499 :         TALLOC_FREE(ifaces);
     748         499 :         return ret;
     749             : }
     750             : 
     751             : /****************************************************************************
     752             :  Return True if interface exists for given interface index and options
     753             : **************************************************************************/
     754             : 
     755           0 : bool interface_ifindex_exists_with_options(int if_index, uint32_t options)
     756             : {
     757           0 :         struct interface *i = NULL;
     758             : 
     759           0 :         for (i = local_interfaces; i != NULL; i = i->next) {
     760           0 :                 if ((i->if_index == if_index) && (i->options & options)) {
     761           0 :                         return true;
     762             :                 }
     763             :         }
     764             : 
     765           0 :         return false;
     766             : }

Generated by: LCOV version 1.14