LCOV - code coverage report
Current view: top level - source3/lib - interface.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 166 322 51.6 %
Date: 2024-01-11 09:59:51 Functions: 16 22 72.7 %

          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       11164 : bool ismyaddr(const struct sockaddr *ip)
      36             : {
      37           0 :         struct interface *i;
      38       29902 :         for (i=local_interfaces;i;i=i->next) {
      39       22889 :                 if (sockaddr_equal((struct sockaddr *)&i->ip,ip)) {
      40        4151 :                         return true;
      41             :                 }
      42             :         }
      43        7013 :         return false;
      44             : }
      45             : 
      46        8176 : bool ismyip_v4(struct in_addr ip)
      47             : {
      48           0 :         struct sockaddr_storage ss;
      49        8176 :         in_addr_to_sockaddr_storage(&ss, ip);
      50        8176 :         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      130042 : static struct interface *iface_find(const struct sockaddr *ip,
      58             :                                 bool check_mask)
      59             : {
      60         434 :         struct interface *i;
      61             : 
      62      130042 :         if (is_address_any(ip)) {
      63           0 :                 return local_interfaces;
      64             :         }
      65             : 
      66      470395 :         for (i=local_interfaces;i;i=i->next) {
      67      340747 :                 if (check_mask) {
      68         788 :                         if (same_net(ip, (struct sockaddr *)&i->ip, (struct sockaddr *)&i->netmask)) {
      69         394 :                                 return i;
      70             :                         }
      71      339959 :                 } else if (sockaddr_equal((struct sockaddr *)&i->ip, ip)) {
      72           0 :                         return i;
      73             :                 }
      74             :         }
      75             : 
      76      129214 :         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         802 : int iface_count(void)
     126             : {
     127         802 :         int ret = 0;
     128           0 :         struct interface *i;
     129             : 
     130        2916 :         for (i=local_interfaces;i;i=i->next) {
     131        2114 :                 ret++;
     132             :         }
     133         802 :         return ret;
     134             : }
     135             : 
     136             : /****************************************************************************
     137             :  How many non-loopback IPv4 interfaces do we have ?
     138             : **************************************************************************/
     139             : 
     140          78 : int iface_count_v4_nl(void)
     141             : {
     142          78 :         int ret = 0;
     143           0 :         struct interface *i;
     144             : 
     145         234 :         for (i=local_interfaces;i;i=i->next) {
     146         156 :                 if (is_loopback_addr((struct sockaddr *)&i->ip)) {
     147           0 :                         continue;
     148             :                 }
     149         156 :                 if (i->ip.ss_family == AF_INET) {
     150          78 :                         ret++;
     151             :                 }
     152             :         }
     153          78 :         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         222 : struct interface *get_interface(int n)
     184             : {
     185           0 :         struct interface *i;
     186             : 
     187         333 :         for (i=local_interfaces;i && n;i=i->next) {
     188         111 :                 n--;
     189             :         }
     190             : 
     191         222 :         if (i) {
     192         222 :                 return i;
     193             :         }
     194           0 :         return NULL;
     195             : }
     196             : 
     197             : /****************************************************************************
     198             :  Return IP sockaddr_storage of the Nth interface.
     199             : **************************************************************************/
     200             : 
     201         346 : const struct sockaddr_storage *iface_n_sockaddr_storage(int n)
     202             : {
     203           0 :         struct interface *i;
     204             : 
     205         974 :         for (i=local_interfaces;i && n;i=i->next) {
     206         628 :                 n--;
     207             :         }
     208             : 
     209         346 :         if (i) {
     210         346 :                 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         192 : const struct in_addr *iface_n_ip_v4(int n)
     220             : {
     221           0 :         struct interface *i;
     222             : 
     223         288 :         for (i=local_interfaces;i && n;i=i->next) {
     224          96 :                 n--;
     225             :         }
     226             : 
     227         192 :         if (i && i->ip.ss_family == AF_INET) {
     228          96 :                 return &((const struct sockaddr_in *)&i->ip)->sin_addr;
     229             :         }
     230          96 :         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        1006 : const struct sockaddr_storage *iface_n_bcast(int n)
     256             : {
     257           0 :         struct interface *i;
     258             : 
     259        2839 :         for (i=local_interfaces;i && n;i=i->next) {
     260        1833 :                 n--;
     261             :         }
     262             : 
     263        1006 :         if (i) {
     264        1006 :                 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         312 : const struct sockaddr_storage *iface_ip(const struct sockaddr *ip)
     275             : {
     276         312 :         struct interface *i = iface_find(ip, true);
     277         312 :         if (i) {
     278         312 :                 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          82 : bool iface_local(const struct sockaddr *ip)
     297             : {
     298          82 :         return iface_find(ip, true) ? true : false;
     299             : }
     300             : 
     301             : /****************************************************************************
     302             :  Add an interface to the linked list of interfaces.
     303             : ****************************************************************************/
     304             : 
     305      129648 : static void add_interface(const struct iface_struct *ifs)
     306             : {
     307         434 :         char addr[INET6_ADDRSTRLEN];
     308         434 :         struct interface *iface;
     309             : 
     310      129648 :         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      129648 :         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      129648 :         iface = SMB_MALLOC_P(struct interface);
     323      129648 :         if (!iface) {
     324           0 :                 return;
     325             :         }
     326             : 
     327      129648 :         ZERO_STRUCTPN(iface);
     328             : 
     329      129648 :         iface->name = SMB_STRDUP(ifs->name);
     330      129648 :         if (!iface->name) {
     331           0 :                 SAFE_FREE(iface);
     332           0 :                 return;
     333             :         }
     334      129648 :         iface->flags = ifs->flags;
     335      129648 :         iface->ip = ifs->ip;
     336      129648 :         iface->netmask = ifs->netmask;
     337      129648 :         iface->bcast = ifs->bcast;
     338      129648 :         iface->linkspeed = ifs->linkspeed;
     339      129648 :         iface->capability = ifs->capability;
     340      129648 :         iface->if_index = ifs->if_index;
     341             : 
     342      129648 :         DLIST_ADD(local_interfaces, iface);
     343             : 
     344      129648 :         DEBUG(2,("added interface %s ip=%s ",
     345             :                 iface->name,
     346             :                 print_sockaddr(addr, sizeof(addr), &iface->ip) ));
     347      129648 :         DEBUG(2,("bcast=%s ",
     348             :                 print_sockaddr(addr, sizeof(addr),
     349             :                         &iface->bcast) ));
     350      129648 :         DEBUG(2,("netmask=%s\n",
     351             :                 print_sockaddr(addr, sizeof(addr),
     352             :                         &iface->netmask) ));
     353             : }
     354             : 
     355             : 
     356           0 : static void parse_extra_info(char *key, uint64_t *speed, uint32_t *cap,
     357             :                              uint32_t *if_index)
     358             : {
     359           0 :         while (key != NULL && *key != '\0') {
     360           0 :                 char *next_key;
     361           0 :                 char *val;
     362           0 :                 int error = 0;
     363             : 
     364           0 :                 next_key = strchr_m(key, ',');
     365           0 :                 if (next_key != NULL) {
     366           0 :                         *next_key++ = 0;
     367             :                 }
     368             : 
     369           0 :                 val = strchr_m(key, '=');
     370           0 :                 if (val != NULL) {
     371           0 :                         *val++ = 0;
     372             : 
     373           0 :                         if (strequal_m(key, "speed")) {
     374           0 :                                 *speed = (uint64_t)smb_strtoull(val,
     375             :                                                                 NULL,
     376             :                                                                 0,
     377             :                                                                 &error,
     378             :                                                                 SMB_STR_STANDARD);
     379           0 :                                 if (error != 0) {
     380           0 :                                         DBG_DEBUG("Invalid speed value (%s)\n", val);
     381             :                                 }
     382           0 :                         } else if (strequal_m(key, "capability")) {
     383           0 :                                 if (strequal_m(val, "RSS")) {
     384           0 :                                         *cap |= FSCTL_NET_IFACE_RSS_CAPABLE;
     385           0 :                                 } else if (strequal(val, "RDMA")) {
     386           0 :                                         *cap |= FSCTL_NET_IFACE_RDMA_CAPABLE;
     387             :                                 } else {
     388           0 :                                         DBG_WARNING("Capability unknown: "
     389             :                                                     "'%s'\n", val);
     390             :                                 }
     391           0 :                         } else if (strequal_m(key, "if_index")) {
     392           0 :                                 *if_index = (uint32_t)smb_strtoul(val,
     393             :                                                                   NULL,
     394             :                                                                   0,
     395             :                                                                   &error,
     396             :                                                                   SMB_STR_STANDARD);
     397           0 :                                 if (error != 0) {
     398           0 :                                         DBG_DEBUG("Invalid key value (%s)\n", val);
     399             :                                 }
     400             :                         } else {
     401           0 :                                 DBG_DEBUG("Key unknown: '%s'\n", key);
     402             :                         }
     403             :                 }
     404             : 
     405           0 :                 key = next_key;
     406             :         }
     407           0 : }
     408             : 
     409             : /****************************************************************************
     410             :  Interpret a single element from a interfaces= config line.
     411             : 
     412             :  This handles the following different forms:
     413             : 
     414             :  1) wildcard interface name
     415             :  2) DNS name
     416             :  3) IP/masklen
     417             :  4) ip/mask
     418             :  5) bcast/mask
     419             : 
     420             :  Additional information for an interface can be specified with
     421             :  this extended syntax:
     422             : 
     423             :     "interface[;key1=value1[,key2=value2[...]]]"
     424             : 
     425             :  Note: The double quoting is important for the
     426             :        smb.conf parser! Otherwise the ';' and ',' separates
     427             :        two interfaces.
     428             : 
     429             :  where
     430             :  - keys known: 'speed', 'capability', 'if_index'
     431             :  - speed is in bits per second
     432             :  - capabilities known: 'RSS', 'RDMA'
     433             :  - if_index should be used with care, because
     434             :    these indexes should not conicide with indexes
     435             :    the kernel sets...
     436             : 
     437             :  Note: The specified values overwrite the autodetected values!
     438             : 
     439             : ****************************************************************************/
     440             : 
     441      129540 : static void interpret_interface(char *token)
     442             : {
     443         406 :         struct sockaddr_storage ss;
     444         406 :         struct sockaddr_storage ss_mask;
     445         406 :         struct sockaddr_storage ss_net;
     446         406 :         struct sockaddr_storage ss_bcast;
     447         406 :         struct iface_struct ifs;
     448         406 :         char *p;
     449         406 :         int i;
     450      129540 :         bool added=false;
     451      129540 :         bool goodaddr = false;
     452      129540 :         uint64_t speed = 0;
     453      129540 :         uint32_t cap = FSCTL_NET_IFACE_NONE_CAPABLE;
     454      129540 :         uint32_t if_index = 0;
     455      129540 :         bool speed_set = false;
     456      129540 :         bool cap_set = false;
     457      129540 :         bool if_index_set = false;
     458             : 
     459             :         /*
     460             :          * extract speed / capability information if present
     461             :          */
     462      129540 :         p = strchr_m(token, ';');
     463      129540 :         if (p != NULL) {
     464           0 :                 *p++ = 0;
     465           0 :                 parse_extra_info(p, &speed, &cap, &if_index);
     466           0 :                 if (speed != 0) {
     467           0 :                         speed_set = true;
     468             :                 }
     469           0 :                 if (cap != FSCTL_NET_IFACE_NONE_CAPABLE) {
     470           0 :                         cap_set = true;
     471             :                 }
     472           0 :                 if (if_index != 0) {
     473           0 :                         if_index_set = true;
     474             :                 }
     475             :         }
     476             : 
     477             :         /* first check if it is an interface name */
     478      647700 :         for (i=0;i<total_probed;i++) {
     479      518160 :                 if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
     480           0 :                         if (speed_set) {
     481           0 :                                 probed_ifaces[i].linkspeed = speed;
     482             :                         }
     483           0 :                         if (cap_set) {
     484           0 :                                 probed_ifaces[i].capability = cap;
     485             :                         }
     486           0 :                         if (if_index_set) {
     487           0 :                                 probed_ifaces[i].if_index = if_index;
     488             :                         }
     489           0 :                         add_interface(&probed_ifaces[i]);
     490           0 :                         added = true;
     491             :                 }
     492             :         }
     493      129540 :         if (added) {
     494           0 :                 return;
     495             :         }
     496             : 
     497      129540 :         p = strchr_m(token,'/');
     498      129540 :         if (p == NULL) {
     499           0 :                 if (!interpret_string_addr(&ss, token, 0)) {
     500           0 :                         DEBUG(2, ("interpret_interface: Can't find address "
     501             :                                   "for %s\n", token));
     502           0 :                         return;
     503             :                 }
     504             : 
     505           0 :                 for (i=0;i<total_probed;i++) {
     506           0 :                         if (sockaddr_equal((struct sockaddr *)&ss,
     507           0 :                                 (struct sockaddr *)&probed_ifaces[i].ip))
     508             :                         {
     509           0 :                                 if (speed_set) {
     510           0 :                                         probed_ifaces[i].linkspeed = speed;
     511             :                                 }
     512           0 :                                 if (cap_set) {
     513           0 :                                         probed_ifaces[i].capability = cap;
     514             :                                 }
     515           0 :                                 if (if_index_set) {
     516           0 :                                         probed_ifaces[i].if_index = if_index;
     517             :                                 }
     518           0 :                                 add_interface(&probed_ifaces[i]);
     519           0 :                                 return;
     520             :                         }
     521             :                 }
     522           0 :                 DEBUG(2,("interpret_interface: "
     523             :                         "can't determine interface for %s\n",
     524             :                         token));
     525           0 :                 return;
     526             :         }
     527             : 
     528             :         /* parse it into an IP address/netmasklength pair */
     529      129540 :         *p = 0;
     530      129540 :         goodaddr = interpret_string_addr(&ss, token, 0);
     531      129540 :         *p++ = '/';
     532             : 
     533      129540 :         if (!goodaddr) {
     534           0 :                 DEBUG(2,("interpret_interface: "
     535             :                         "can't determine interface for %s\n",
     536             :                         token));
     537           0 :                 return;
     538             :         }
     539             : 
     540      129540 :         if (strlen(p) > 2) {
     541           0 :                 goodaddr = interpret_string_addr(&ss_mask, p, 0);
     542           0 :                 if (!goodaddr) {
     543           0 :                         DEBUG(2,("interpret_interface: "
     544             :                                 "can't determine netmask from %s\n",
     545             :                                 p));
     546           0 :                         return;
     547             :                 }
     548             :         } else {
     549      129540 :                 int error = 0;
     550         406 :                 unsigned long val;
     551             : 
     552      129540 :                 val = smb_strtoul(p, NULL, 0, &error, SMB_STR_FULL_STR_CONV);
     553      129540 :                 if (error != 0) {
     554           0 :                         DEBUG(2,("interpret_interface: "
     555             :                                 "can't determine netmask value from %s\n",
     556             :                                 p));
     557           0 :                         return;
     558             :                 }
     559      129540 :                 if (!make_netmask(&ss_mask, &ss, val)) {
     560           0 :                         DEBUG(2,("interpret_interface: "
     561             :                                 "can't apply netmask value %lu from %s\n",
     562             :                                 val,
     563             :                                 p));
     564           0 :                         return;
     565             :                 }
     566             :         }
     567             : 
     568      129540 :         make_bcast(&ss_bcast, &ss, &ss_mask);
     569      129540 :         make_net(&ss_net, &ss, &ss_mask);
     570             : 
     571             :         /* Maybe the first component was a broadcast address. */
     572      259080 :         if (sockaddr_equal((struct sockaddr *)&ss_bcast, (struct sockaddr *)&ss) ||
     573      129540 :                 sockaddr_equal((struct sockaddr *)&ss_net, (struct sockaddr *)&ss)) {
     574           0 :                 for (i=0;i<total_probed;i++) {
     575           0 :                         if (same_net((struct sockaddr *)&ss, 
     576           0 :                                                  (struct sockaddr *)&probed_ifaces[i].ip, 
     577             :                                                  (struct sockaddr *)&ss_mask)) {
     578             :                                 /* Temporarily replace netmask on
     579             :                                  * the detected interface - user knows
     580             :                                  * best.... */
     581           0 :                                 struct sockaddr_storage saved_mask =
     582           0 :                                         probed_ifaces[i].netmask;
     583           0 :                                 probed_ifaces[i].netmask = ss_mask;
     584           0 :                                 DEBUG(2,("interpret_interface: "
     585             :                                         "using netmask value %s from "
     586             :                                         "config file on interface %s\n",
     587             :                                         p,
     588             :                                         probed_ifaces[i].name));
     589           0 :                                 if (speed_set) {
     590           0 :                                         probed_ifaces[i].linkspeed = speed;
     591             :                                 }
     592           0 :                                 if (cap_set) {
     593           0 :                                         probed_ifaces[i].capability = cap;
     594             :                                 }
     595           0 :                                 if (if_index_set) {
     596           0 :                                         probed_ifaces[i].if_index = if_index;
     597             :                                 }
     598           0 :                                 add_interface(&probed_ifaces[i]);
     599           0 :                                 probed_ifaces[i].netmask = saved_mask;
     600           0 :                                 return;
     601             :                         }
     602             :                 }
     603           0 :                 DEBUG(2,("interpret_interface: Can't determine ip for "
     604             :                         "broadcast address %s\n",
     605             :                         token));
     606           0 :                 return;
     607             :         }
     608             : 
     609             :         /* Just fake up the interface definition. User knows best. */
     610             : 
     611      129540 :         DEBUG(2,("interpret_interface: Adding interface %s\n",
     612             :                 token));
     613             : 
     614      129540 :         ZERO_STRUCT(ifs);
     615      129540 :         (void)strlcpy(ifs.name, token, sizeof(ifs.name));
     616      129540 :         ifs.flags = IFF_BROADCAST;
     617      129540 :         ifs.ip = ss;
     618      129540 :         ifs.netmask = ss_mask;
     619      129540 :         ifs.bcast = ss_bcast;
     620      129540 :         if (if_index_set) {
     621           0 :                 ifs.if_index = if_index;
     622             :         }
     623      129540 :         if (speed_set) {
     624           0 :                 ifs.linkspeed = speed;
     625             :         } else {
     626      129540 :                 ifs.linkspeed = 1000 * 1000 * 1000;
     627             :         }
     628      129540 :         ifs.capability = cap;
     629      129540 :         add_interface(&ifs);
     630             : }
     631             : 
     632             : /****************************************************************************
     633             :  Load the list of network interfaces.
     634             : ****************************************************************************/
     635             : 
     636       25519 : void load_interfaces(void)
     637             : {
     638       25519 :         struct iface_struct *ifaces = NULL;
     639       25519 :         const char **ptr = lp_interfaces();
     640          72 :         int i;
     641             : 
     642       25519 :         gfree_interfaces();
     643             : 
     644             :         /* Probe the kernel for interfaces */
     645       25519 :         total_probed = get_interfaces(talloc_tos(), &ifaces);
     646             : 
     647       25519 :         if (total_probed > 0) {
     648       25519 :                 probed_ifaces = (struct iface_struct *)smb_memdup(ifaces,
     649             :                                 sizeof(ifaces[0])*total_probed);
     650       25519 :                 if (!probed_ifaces) {
     651           0 :                         DEBUG(0,("ERROR: smb_memdup failed\n"));
     652           0 :                         exit(1);
     653             :                 }
     654             :         }
     655       25519 :         TALLOC_FREE(ifaces);
     656             : 
     657             :         /* if we don't have a interfaces line then use all broadcast capable
     658             :            interfaces except loopback */
     659       25519 :         if (!ptr || !*ptr || !**ptr) {
     660          54 :                 if (total_probed <= 0) {
     661           0 :                         DEBUG(0,("ERROR: Could not determine network "
     662             :                         "interfaces, you must use a interfaces config line\n"));
     663           0 :                         exit(1);
     664             :                 }
     665         270 :                 for (i=0;i<total_probed;i++) {
     666         216 :                         if (probed_ifaces[i].flags & IFF_BROADCAST) {
     667         108 :                                 add_interface(&probed_ifaces[i]);
     668             :                         }
     669             :                 }
     670          54 :                 return;
     671             :         }
     672             : 
     673       25407 :         if (ptr) {
     674      155005 :                 while (*ptr) {
     675      129540 :                         char *ptr_cpy = SMB_STRDUP(*ptr);
     676      129540 :                         if (ptr_cpy) {
     677      129540 :                                 interpret_interface(ptr_cpy);
     678      129540 :                                 free(ptr_cpy);
     679             :                         }
     680      129540 :                         ptr++;
     681             :                 }
     682             :         }
     683             : 
     684       25465 :         if (!local_interfaces) {
     685           0 :                 DEBUG(0,("WARNING: no network interfaces found\n"));
     686             :         }
     687             : }
     688             : 
     689             : 
     690       40577 : void gfree_interfaces(void)
     691             : {
     692      143590 :         while (local_interfaces) {
     693       98599 :                 struct interface *iface = local_interfaces;
     694       98599 :                 DLIST_REMOVE(local_interfaces, local_interfaces);
     695       98599 :                 SAFE_FREE(iface->name);
     696       98676 :                 SAFE_FREE(iface);
     697             :         }
     698             : 
     699       40577 :         SAFE_FREE(probed_ifaces);
     700       40577 : }
     701             : 
     702             : /****************************************************************************
     703             :  Return True if the list of probed interfaces has changed.
     704             : ****************************************************************************/
     705             : 
     706         424 : bool interfaces_changed(void)
     707             : {
     708         424 :         bool ret = false;
     709           0 :         int n;
     710         424 :         struct iface_struct *ifaces = NULL;
     711             : 
     712         424 :         n = get_interfaces(talloc_tos(), &ifaces);
     713             : 
     714         424 :         if ((n > 0 )&& (n != total_probed ||
     715         424 :                         memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
     716           0 :                 ret = true;
     717             :         }
     718             : 
     719         424 :         TALLOC_FREE(ifaces);
     720         424 :         return ret;
     721             : }

Generated by: LCOV version 1.14