python:tests: Store keys as bytes rather than as lists of ints
[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 #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 bool ismyaddr(const struct sockaddr *ip)
36 {
37         struct interface *i;
38         for (i=local_interfaces;i;i=i->next) {
39                 if (sockaddr_equal((struct sockaddr *)&i->ip,ip)) {
40                         return true;
41                 }
42         }
43         return false;
44 }
45
46 bool ismyip_v4(struct in_addr ip)
47 {
48         struct sockaddr_storage ss;
49         in_addr_to_sockaddr_storage(&ss, ip);
50         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 static struct interface *iface_find(const struct sockaddr *ip,
58                                 bool check_mask)
59 {
60         struct interface *i;
61
62         if (is_address_any(ip)) {
63                 return local_interfaces;
64         }
65
66         for (i=local_interfaces;i;i=i->next) {
67                 if (check_mask) {
68                         if (same_net(ip, (struct sockaddr *)&i->ip, (struct sockaddr *)&i->netmask)) {
69                                 return i;
70                         }
71                 } else if (sockaddr_equal((struct sockaddr *)&i->ip, ip)) {
72                         return i;
73                 }
74         }
75
76         return NULL;
77 }
78
79 /****************************************************************************
80  Check if a packet is from a local (known) net.
81 **************************************************************************/
82
83 bool is_local_net(const struct sockaddr *from)
84 {
85         struct interface *i;
86         for (i=local_interfaces;i;i=i->next) {
87                 if (same_net(from, (struct sockaddr *)&i->ip, (struct sockaddr *)&i->netmask)) {
88                         return true;
89                 }
90         }
91         return false;
92 }
93
94 #if defined(HAVE_IPV6)
95 void setup_linklocal_scope_id(struct sockaddr *pss)
96 {
97         struct interface *i;
98         for (i=local_interfaces;i;i=i->next) {
99                 if (sockaddr_equal((struct sockaddr *)&i->ip,pss)) {
100                         struct sockaddr_in6 *psa6 =
101                                 (struct sockaddr_in6 *)pss;
102                         psa6->sin6_scope_id = if_nametoindex(i->name);
103                         return;
104                 }
105         }
106 }
107 #endif
108
109 /****************************************************************************
110  Check if a packet is from a local (known) net.
111 **************************************************************************/
112
113 bool is_local_net_v4(struct in_addr from)
114 {
115         struct sockaddr_storage ss;
116
117         in_addr_to_sockaddr_storage(&ss, from);
118         return is_local_net((struct sockaddr *)&ss);
119 }
120
121 /****************************************************************************
122  How many interfaces do we have ?
123 **************************************************************************/
124
125 int iface_count(void)
126 {
127         int ret = 0;
128         struct interface *i;
129
130         for (i=local_interfaces;i;i=i->next) {
131                 ret++;
132         }
133         return ret;
134 }
135
136 /****************************************************************************
137  How many non-loopback IPv4 interfaces do we have ?
138 **************************************************************************/
139
140 int iface_count_v4_nl(void)
141 {
142         int ret = 0;
143         struct interface *i;
144
145         for (i=local_interfaces;i;i=i->next) {
146                 if (is_loopback_addr((struct sockaddr *)&i->ip)) {
147                         continue;
148                 }
149                 if (i->ip.ss_family == AF_INET) {
150                         ret++;
151                 }
152         }
153         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 const struct in_addr *first_ipv4_iface(void)
162 {
163         struct interface *i;
164
165         for (i=local_interfaces;i ;i=i->next) {
166                 if ((i->ip.ss_family == AF_INET) &&
167                     (!is_zero_ip_v4(((struct sockaddr_in *)&i->ip)->sin_addr)))
168                 {
169                         break;
170                 }
171         }
172
173         if (!i) {
174                 return NULL;
175         }
176         return &((const struct sockaddr_in *)&i->ip)->sin_addr;
177 }
178
179 /****************************************************************************
180  Return the Nth interface.
181 **************************************************************************/
182
183 struct interface *get_interface(int n)
184 {
185         struct interface *i;
186
187         for (i=local_interfaces;i && n;i=i->next) {
188                 n--;
189         }
190
191         if (i) {
192                 return i;
193         }
194         return NULL;
195 }
196
197 /****************************************************************************
198  Return IP sockaddr_storage of the Nth interface.
199 **************************************************************************/
200
201 const struct sockaddr_storage *iface_n_sockaddr_storage(int n)
202 {
203         struct interface *i;
204
205         for (i=local_interfaces;i && n;i=i->next) {
206                 n--;
207         }
208
209         if (i) {
210                 return &i->ip;
211         }
212         return NULL;
213 }
214
215 /****************************************************************************
216  Return IPv4 of the Nth interface (if a v4 address). NULL otherwise.
217 **************************************************************************/
218
219 const struct in_addr *iface_n_ip_v4(int n)
220 {
221         struct interface *i;
222
223         for (i=local_interfaces;i && n;i=i->next) {
224                 n--;
225         }
226
227         if (i && i->ip.ss_family == AF_INET) {
228                 return &((const struct sockaddr_in *)&i->ip)->sin_addr;
229         }
230         return NULL;
231 }
232
233 /****************************************************************************
234  Return IPv4 bcast of the Nth interface (if a v4 address). NULL otherwise.
235 **************************************************************************/
236
237 const struct in_addr *iface_n_bcast_v4(int n)
238 {
239         struct interface *i;
240
241         for (i=local_interfaces;i && n;i=i->next) {
242                 n--;
243         }
244
245         if (i && i->ip.ss_family == AF_INET) {
246                 return &((const struct sockaddr_in *)&i->bcast)->sin_addr;
247         }
248         return NULL;
249 }
250
251 /****************************************************************************
252  Return bcast of the Nth interface.
253 **************************************************************************/
254
255 const struct sockaddr_storage *iface_n_bcast(int n)
256 {
257         struct interface *i;
258
259         for (i=local_interfaces;i && n;i=i->next) {
260                 n--;
261         }
262
263         if (i) {
264                 return &i->bcast;
265         }
266         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 const struct sockaddr_storage *iface_ip(const struct sockaddr *ip)
275 {
276         struct interface *i = iface_find(ip, true);
277         if (i) {
278                 return &i->ip;
279         }
280
281         /* Search for the first interface with
282          * matching address family. */
283
284         for (i=local_interfaces;i;i=i->next) {
285                 if (i->ip.ss_family == ip->sa_family) {
286                         return &i->ip;
287                 }
288         }
289         return NULL;
290 }
291
292 /*
293   return True if a IP is directly reachable on one of our interfaces
294 */
295
296 bool iface_local(const struct sockaddr *ip)
297 {
298         return iface_find(ip, true) ? true : false;
299 }
300
301 /****************************************************************************
302  Add an interface to the linked list of interfaces.
303 ****************************************************************************/
304
305 static void add_interface(const struct iface_struct *ifs)
306 {
307         char addr[INET6_ADDRSTRLEN];
308         struct interface *iface;
309
310         if (iface_find((const struct sockaddr *)&ifs->ip, False)) {
311                 DEBUG(3,("add_interface: not adding duplicate interface %s\n",
312                         print_sockaddr(addr, sizeof(addr), &ifs->ip) ));
313                 return;
314         }
315
316         if (!(ifs->flags & (IFF_BROADCAST|IFF_LOOPBACK))) {
317                 DEBUG(3,("not adding non-broadcast interface %s\n",
318                                         ifs->name ));
319                 return;
320         }
321
322         iface = SMB_MALLOC_P(struct interface);
323         if (!iface) {
324                 return;
325         }
326
327         ZERO_STRUCTPN(iface);
328
329         iface->name = SMB_STRDUP(ifs->name);
330         if (!iface->name) {
331                 SAFE_FREE(iface);
332                 return;
333         }
334         iface->flags = ifs->flags;
335         iface->ip = ifs->ip;
336         iface->netmask = ifs->netmask;
337         iface->bcast = ifs->bcast;
338         iface->linkspeed = ifs->linkspeed;
339         iface->capability = ifs->capability;
340         iface->if_index = ifs->if_index;
341         iface->options = ifs->options;
342
343         DLIST_ADD(local_interfaces, iface);
344
345         DEBUG(2,("added interface %s ip=%s ",
346                 iface->name,
347                 print_sockaddr(addr, sizeof(addr), &iface->ip) ));
348         DEBUG(2,("bcast=%s ",
349                 print_sockaddr(addr, sizeof(addr),
350                         &iface->bcast) ));
351         DEBUG(2,("netmask=%s\n",
352                 print_sockaddr(addr, sizeof(addr),
353                         &iface->netmask) ));
354 }
355
356
357 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         while (key != NULL && *key != '\0') {
364                 char *next_key;
365                 char *val;
366                 int error = 0;
367
368                 next_key = strchr_m(key, ',');
369                 if (next_key != NULL) {
370                         *next_key++ = 0;
371                 }
372
373                 val = strchr_m(key, '=');
374                 if (val != NULL) {
375                         *val++ = 0;
376
377                         if (strequal_m(key, "speed")) {
378                                 *speed = (uint64_t)smb_strtoull(val,
379                                                                 NULL,
380                                                                 0,
381                                                                 &error,
382                                                                 SMB_STR_STANDARD);
383                                 if (error != 0) {
384                                         DBG_DEBUG("Invalid speed value (%s)\n", val);
385                                 }
386                         } else if (strequal_m(key, "capability")) {
387                                 if (strequal_m(val, "RSS")) {
388                                         *cap |= FSCTL_NET_IFACE_RSS_CAPABLE;
389                                 } else if (strequal(val, "RDMA")) {
390                                         *cap |= FSCTL_NET_IFACE_RDMA_CAPABLE;
391                                 } else {
392                                         DBG_WARNING("Capability unknown: "
393                                                     "'%s'\n", val);
394                                 }
395                         } else if (strequal_m(key, "if_index")) {
396                                 *if_index = (uint32_t)smb_strtoul(val,
397                                                                   NULL,
398                                                                   0,
399                                                                   &error,
400                                                                   SMB_STR_STANDARD);
401                                 if (error != 0) {
402                                         DBG_DEBUG("Invalid key value (%s)\n", val);
403                                 }
404                         } else if (strequal_m(key, "options")) {
405                                 if (strequal_m(val, "dynamic")) {
406                                         *options |= IFACE_DYNAMIC_OPTION;
407                                 } else if (strequal_m(val, "nodynamic")) {
408                                         *options &= ~IFACE_DYNAMIC_OPTION;
409                                 } else {
410                                         DBG_WARNING("Options unknown: "
411                                                     "'%s'\n", val);
412                                 }
413                         } else {
414                                 DBG_DEBUG("Key unknown: '%s'\n", key);
415                         }
416                 }
417
418                 key = next_key;
419         }
420 }
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 static void interpret_interface(char *token)
455 {
456         struct sockaddr_storage ss;
457         struct sockaddr_storage ss_mask;
458         struct sockaddr_storage ss_net;
459         struct sockaddr_storage ss_bcast;
460         struct iface_struct ifs;
461         char *p;
462         int i;
463         bool added=false;
464         bool goodaddr = false;
465         uint64_t speed = 0;
466         uint32_t cap = FSCTL_NET_IFACE_NONE_CAPABLE;
467         uint32_t if_index = 0;
468         bool speed_set = false;
469         bool cap_set = false;
470         bool if_index_set = false;
471         uint32_t options = IFACE_NONE_OPTION;
472         bool options_set = false;
473
474         /*
475          * extract speed / capability information if present
476          */
477         p = strchr_m(token, ';');
478         if (p != NULL) {
479                 *p++ = 0;
480                 parse_extra_info(p, &speed, &cap, &if_index, &options);
481                 if (speed != 0) {
482                         speed_set = true;
483                 }
484                 if (cap != FSCTL_NET_IFACE_NONE_CAPABLE) {
485                         cap_set = true;
486                 }
487                 if (if_index != 0) {
488                         if_index_set = true;
489                 }
490                 if (options != IFACE_NONE_OPTION) {
491                         options_set = true;
492                 }
493         }
494
495         /* first check if it is an interface name */
496         for (i=0;i<total_probed;i++) {
497                 if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
498                         if (speed_set) {
499                                 probed_ifaces[i].linkspeed = speed;
500                         }
501                         if (cap_set) {
502                                 probed_ifaces[i].capability = cap;
503                         }
504                         if (if_index_set) {
505                                 probed_ifaces[i].if_index = if_index;
506                         }
507                         if (options_set) {
508                                  probed_ifaces[i].options = options;
509                         }
510                         add_interface(&probed_ifaces[i]);
511                         added = true;
512                 }
513         }
514         if (added) {
515                 return;
516         }
517
518         p = strchr_m(token,'/');
519         if (p == NULL) {
520                 if (!interpret_string_addr(&ss, token, 0)) {
521                         DEBUG(2, ("interpret_interface: Can't find address "
522                                   "for %s\n", token));
523                         return;
524                 }
525
526                 for (i=0;i<total_probed;i++) {
527                         if (sockaddr_equal((struct sockaddr *)&ss,
528                                 (struct sockaddr *)&probed_ifaces[i].ip))
529                         {
530                                 if (speed_set) {
531                                         probed_ifaces[i].linkspeed = speed;
532                                 }
533                                 if (cap_set) {
534                                         probed_ifaces[i].capability = cap;
535                                 }
536                                 if (if_index_set) {
537                                         probed_ifaces[i].if_index = if_index;
538                                 }
539                                 if (options_set) {
540                                         probed_ifaces[i].options = options;
541                                 }
542                                 add_interface(&probed_ifaces[i]);
543                                 return;
544                         }
545                 }
546                 DEBUG(2,("interpret_interface: "
547                         "can't determine interface for %s\n",
548                         token));
549                 return;
550         }
551
552         /* parse it into an IP address/netmasklength pair */
553         *p = 0;
554         goodaddr = interpret_string_addr(&ss, token, 0);
555         *p++ = '/';
556
557         if (!goodaddr) {
558                 DEBUG(2,("interpret_interface: "
559                         "can't determine interface for %s\n",
560                         token));
561                 return;
562         }
563
564         if (strlen(p) > 2) {
565                 goodaddr = interpret_string_addr(&ss_mask, p, 0);
566                 if (!goodaddr) {
567                         DEBUG(2,("interpret_interface: "
568                                 "can't determine netmask from %s\n",
569                                 p));
570                         return;
571                 }
572         } else {
573                 int error = 0;
574                 unsigned long val;
575
576                 val = smb_strtoul(p, NULL, 0, &error, SMB_STR_FULL_STR_CONV);
577                 if (error != 0) {
578                         DEBUG(2,("interpret_interface: "
579                                 "can't determine netmask value from %s\n",
580                                 p));
581                         return;
582                 }
583                 if (!make_netmask(&ss_mask, &ss, val)) {
584                         DEBUG(2,("interpret_interface: "
585                                 "can't apply netmask value %lu from %s\n",
586                                 val,
587                                 p));
588                         return;
589                 }
590         }
591
592         make_bcast(&ss_bcast, &ss, &ss_mask);
593         make_net(&ss_net, &ss, &ss_mask);
594
595         /* Maybe the first component was a broadcast address. */
596         if (sockaddr_equal((struct sockaddr *)&ss_bcast, (struct sockaddr *)&ss) ||
597                 sockaddr_equal((struct sockaddr *)&ss_net, (struct sockaddr *)&ss)) {
598                 for (i=0;i<total_probed;i++) {
599                         if (same_net((struct sockaddr *)&ss, 
600                                                  (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                                 struct sockaddr_storage saved_mask =
606                                         probed_ifaces[i].netmask;
607                                 probed_ifaces[i].netmask = ss_mask;
608                                 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                                 if (speed_set) {
614                                         probed_ifaces[i].linkspeed = speed;
615                                 }
616                                 if (cap_set) {
617                                         probed_ifaces[i].capability = cap;
618                                 }
619                                 if (if_index_set) {
620                                         probed_ifaces[i].if_index = if_index;
621                                 }
622                                 if (options_set) {
623                                         probed_ifaces[i].options = options;
624                                 }
625                                 add_interface(&probed_ifaces[i]);
626                                 probed_ifaces[i].netmask = saved_mask;
627                                 return;
628                         }
629                 }
630                 DEBUG(2,("interpret_interface: Can't determine ip for "
631                         "broadcast address %s\n",
632                         token));
633                 return;
634         }
635
636         /* Just fake up the interface definition. User knows best. */
637
638         DEBUG(2,("interpret_interface: Adding interface %s\n",
639                 token));
640
641         ZERO_STRUCT(ifs);
642         (void)strlcpy(ifs.name, token, sizeof(ifs.name));
643         ifs.flags = IFF_BROADCAST;
644         ifs.ip = ss;
645         ifs.netmask = ss_mask;
646         ifs.bcast = ss_bcast;
647         if (if_index_set) {
648                 ifs.if_index = if_index;
649         }
650         if (speed_set) {
651                 ifs.linkspeed = speed;
652         } else {
653                 ifs.linkspeed = 1000 * 1000 * 1000;
654         }
655         ifs.capability = cap;
656         ifs.options = options;
657         add_interface(&ifs);
658 }
659
660 /****************************************************************************
661  Load the list of network interfaces.
662 ****************************************************************************/
663
664 void load_interfaces(void)
665 {
666         struct iface_struct *ifaces = NULL;
667         const char **ptr = lp_interfaces();
668         int i;
669
670         gfree_interfaces();
671
672         /* Probe the kernel for interfaces */
673         total_probed = get_interfaces(talloc_tos(), &ifaces);
674
675         if (total_probed > 0) {
676                 probed_ifaces = (struct iface_struct *)smb_memdup(ifaces,
677                                 sizeof(ifaces[0])*total_probed);
678                 if (!probed_ifaces) {
679                         DEBUG(0,("ERROR: smb_memdup failed\n"));
680                         exit(1);
681                 }
682         }
683         TALLOC_FREE(ifaces);
684
685         /* if we don't have a interfaces line then use all broadcast capable
686            interfaces except loopback */
687         if (!ptr || !*ptr || !**ptr) {
688                 if (total_probed <= 0) {
689                         DEBUG(0,("ERROR: Could not determine network "
690                         "interfaces, you must use a interfaces config line\n"));
691                         exit(1);
692                 }
693                 for (i=0;i<total_probed;i++) {
694                         if (probed_ifaces[i].flags & IFF_BROADCAST) {
695                                 add_interface(&probed_ifaces[i]);
696                         }
697                 }
698                 return;
699         }
700
701         if (ptr) {
702                 while (*ptr) {
703                         char *ptr_cpy = SMB_STRDUP(*ptr);
704                         if (ptr_cpy) {
705                                 interpret_interface(ptr_cpy);
706                                 free(ptr_cpy);
707                         }
708                         ptr++;
709                 }
710         }
711
712         if (!local_interfaces) {
713                 DEBUG(0,("WARNING: no network interfaces found\n"));
714         }
715 }
716
717
718 void gfree_interfaces(void)
719 {
720         while (local_interfaces) {
721                 struct interface *iface = local_interfaces;
722                 DLIST_REMOVE(local_interfaces, local_interfaces);
723                 SAFE_FREE(iface->name);
724                 SAFE_FREE(iface);
725         }
726
727         SAFE_FREE(probed_ifaces);
728 }
729
730 /****************************************************************************
731  Return True if the list of probed interfaces has changed.
732 ****************************************************************************/
733
734 bool interfaces_changed(void)
735 {
736         bool ret = false;
737         int n;
738         struct iface_struct *ifaces = NULL;
739
740         n = get_interfaces(talloc_tos(), &ifaces);
741
742         if ((n > 0 )&& (n != total_probed ||
743                         memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
744                 ret = true;
745         }
746
747         TALLOC_FREE(ifaces);
748         return ret;
749 }
750
751 /****************************************************************************
752  Return True if interface exists for given interface index and options
753 **************************************************************************/
754
755 bool interface_ifindex_exists_with_options(int if_index, uint32_t options)
756 {
757         struct interface *i = NULL;
758
759         for (i = local_interfaces; i != NULL; i = i->next) {
760                 if ((i->if_index == if_index) && (i->options & options)) {
761                         return true;
762                 }
763         }
764
765         return false;
766 }