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