s3:lib: Fix code spelling
[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
342         DLIST_ADD(local_interfaces, iface);
343
344         DEBUG(2,("added interface %s ip=%s ",
345                 iface->name,
346                 print_sockaddr(addr, sizeof(addr), &iface->ip) ));
347         DEBUG(2,("bcast=%s ",
348                 print_sockaddr(addr, sizeof(addr),
349                         &iface->bcast) ));
350         DEBUG(2,("netmask=%s\n",
351                 print_sockaddr(addr, sizeof(addr),
352                         &iface->netmask) ));
353 }
354
355
356 static void parse_extra_info(char *key, uint64_t *speed, uint32_t *cap,
357                              uint32_t *if_index)
358 {
359         while (key != NULL && *key != '\0') {
360                 char *next_key;
361                 char *val;
362                 int error = 0;
363
364                 next_key = strchr_m(key, ',');
365                 if (next_key != NULL) {
366                         *next_key++ = 0;
367                 }
368
369                 val = strchr_m(key, '=');
370                 if (val != NULL) {
371                         *val++ = 0;
372
373                         if (strequal_m(key, "speed")) {
374                                 *speed = (uint64_t)smb_strtoull(val,
375                                                                 NULL,
376                                                                 0,
377                                                                 &error,
378                                                                 SMB_STR_STANDARD);
379                                 if (error != 0) {
380                                         DBG_DEBUG("Invalid speed value (%s)\n", val);
381                                 }
382                         } else if (strequal_m(key, "capability")) {
383                                 if (strequal_m(val, "RSS")) {
384                                         *cap |= FSCTL_NET_IFACE_RSS_CAPABLE;
385                                 } else if (strequal(val, "RDMA")) {
386                                         *cap |= FSCTL_NET_IFACE_RDMA_CAPABLE;
387                                 } else {
388                                         DBG_WARNING("Capability unknown: "
389                                                     "'%s'\n", val);
390                                 }
391                         } else if (strequal_m(key, "if_index")) {
392                                 *if_index = (uint32_t)smb_strtoul(val,
393                                                                   NULL,
394                                                                   0,
395                                                                   &error,
396                                                                   SMB_STR_STANDARD);
397                                 if (error != 0) {
398                                         DBG_DEBUG("Invalid key value (%s)\n", val);
399                                 }
400                         } else {
401                                 DBG_DEBUG("Key unknown: '%s'\n", key);
402                         }
403                 }
404
405                 key = next_key;
406         }
407 }
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 static void interpret_interface(char *token)
442 {
443         struct sockaddr_storage ss;
444         struct sockaddr_storage ss_mask;
445         struct sockaddr_storage ss_net;
446         struct sockaddr_storage ss_bcast;
447         struct iface_struct ifs;
448         char *p;
449         int i;
450         bool added=false;
451         bool goodaddr = false;
452         uint64_t speed = 0;
453         uint32_t cap = FSCTL_NET_IFACE_NONE_CAPABLE;
454         uint32_t if_index = 0;
455         bool speed_set = false;
456         bool cap_set = false;
457         bool if_index_set = false;
458
459         /*
460          * extract speed / capability information if present
461          */
462         p = strchr_m(token, ';');
463         if (p != NULL) {
464                 *p++ = 0;
465                 parse_extra_info(p, &speed, &cap, &if_index);
466                 if (speed != 0) {
467                         speed_set = true;
468                 }
469                 if (cap != FSCTL_NET_IFACE_NONE_CAPABLE) {
470                         cap_set = true;
471                 }
472                 if (if_index != 0) {
473                         if_index_set = true;
474                 }
475         }
476
477         /* first check if it is an interface name */
478         for (i=0;i<total_probed;i++) {
479                 if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
480                         if (speed_set) {
481                                 probed_ifaces[i].linkspeed = speed;
482                         }
483                         if (cap_set) {
484                                 probed_ifaces[i].capability = cap;
485                         }
486                         if (if_index_set) {
487                                 probed_ifaces[i].if_index = if_index;
488                         }
489                         add_interface(&probed_ifaces[i]);
490                         added = true;
491                 }
492         }
493         if (added) {
494                 return;
495         }
496
497         p = strchr_m(token,'/');
498         if (p == NULL) {
499                 if (!interpret_string_addr(&ss, token, 0)) {
500                         DEBUG(2, ("interpret_interface: Can't find address "
501                                   "for %s\n", token));
502                         return;
503                 }
504
505                 for (i=0;i<total_probed;i++) {
506                         if (sockaddr_equal((struct sockaddr *)&ss,
507                                 (struct sockaddr *)&probed_ifaces[i].ip))
508                         {
509                                 if (speed_set) {
510                                         probed_ifaces[i].linkspeed = speed;
511                                 }
512                                 if (cap_set) {
513                                         probed_ifaces[i].capability = cap;
514                                 }
515                                 if (if_index_set) {
516                                         probed_ifaces[i].if_index = if_index;
517                                 }
518                                 add_interface(&probed_ifaces[i]);
519                                 return;
520                         }
521                 }
522                 DEBUG(2,("interpret_interface: "
523                         "can't determine interface for %s\n",
524                         token));
525                 return;
526         }
527
528         /* parse it into an IP address/netmasklength pair */
529         *p = 0;
530         goodaddr = interpret_string_addr(&ss, token, 0);
531         *p++ = '/';
532
533         if (!goodaddr) {
534                 DEBUG(2,("interpret_interface: "
535                         "can't determine interface for %s\n",
536                         token));
537                 return;
538         }
539
540         if (strlen(p) > 2) {
541                 goodaddr = interpret_string_addr(&ss_mask, p, 0);
542                 if (!goodaddr) {
543                         DEBUG(2,("interpret_interface: "
544                                 "can't determine netmask from %s\n",
545                                 p));
546                         return;
547                 }
548         } else {
549                 int error = 0;
550                 unsigned long val;
551
552                 val = smb_strtoul(p, NULL, 0, &error, SMB_STR_FULL_STR_CONV);
553                 if (error != 0) {
554                         DEBUG(2,("interpret_interface: "
555                                 "can't determine netmask value from %s\n",
556                                 p));
557                         return;
558                 }
559                 if (!make_netmask(&ss_mask, &ss, val)) {
560                         DEBUG(2,("interpret_interface: "
561                                 "can't apply netmask value %lu from %s\n",
562                                 val,
563                                 p));
564                         return;
565                 }
566         }
567
568         make_bcast(&ss_bcast, &ss, &ss_mask);
569         make_net(&ss_net, &ss, &ss_mask);
570
571         /* Maybe the first component was a broadcast address. */
572         if (sockaddr_equal((struct sockaddr *)&ss_bcast, (struct sockaddr *)&ss) ||
573                 sockaddr_equal((struct sockaddr *)&ss_net, (struct sockaddr *)&ss)) {
574                 for (i=0;i<total_probed;i++) {
575                         if (same_net((struct sockaddr *)&ss, 
576                                                  (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                                 struct sockaddr_storage saved_mask =
582                                         probed_ifaces[i].netmask;
583                                 probed_ifaces[i].netmask = ss_mask;
584                                 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                                 if (speed_set) {
590                                         probed_ifaces[i].linkspeed = speed;
591                                 }
592                                 if (cap_set) {
593                                         probed_ifaces[i].capability = cap;
594                                 }
595                                 if (if_index_set) {
596                                         probed_ifaces[i].if_index = if_index;
597                                 }
598                                 add_interface(&probed_ifaces[i]);
599                                 probed_ifaces[i].netmask = saved_mask;
600                                 return;
601                         }
602                 }
603                 DEBUG(2,("interpret_interface: Can't determine ip for "
604                         "broadcast address %s\n",
605                         token));
606                 return;
607         }
608
609         /* Just fake up the interface definition. User knows best. */
610
611         DEBUG(2,("interpret_interface: Adding interface %s\n",
612                 token));
613
614         ZERO_STRUCT(ifs);
615         (void)strlcpy(ifs.name, token, sizeof(ifs.name));
616         ifs.flags = IFF_BROADCAST;
617         ifs.ip = ss;
618         ifs.netmask = ss_mask;
619         ifs.bcast = ss_bcast;
620         if (if_index_set) {
621                 ifs.if_index = if_index;
622         }
623         if (speed_set) {
624                 ifs.linkspeed = speed;
625         } else {
626                 ifs.linkspeed = 1000 * 1000 * 1000;
627         }
628         ifs.capability = cap;
629         add_interface(&ifs);
630 }
631
632 /****************************************************************************
633  Load the list of network interfaces.
634 ****************************************************************************/
635
636 void load_interfaces(void)
637 {
638         struct iface_struct *ifaces = NULL;
639         const char **ptr = lp_interfaces();
640         int i;
641
642         gfree_interfaces();
643
644         /* Probe the kernel for interfaces */
645         total_probed = get_interfaces(talloc_tos(), &ifaces);
646
647         if (total_probed > 0) {
648                 probed_ifaces = (struct iface_struct *)smb_memdup(ifaces,
649                                 sizeof(ifaces[0])*total_probed);
650                 if (!probed_ifaces) {
651                         DEBUG(0,("ERROR: smb_memdup failed\n"));
652                         exit(1);
653                 }
654         }
655         TALLOC_FREE(ifaces);
656
657         /* if we don't have a interfaces line then use all broadcast capable
658            interfaces except loopback */
659         if (!ptr || !*ptr || !**ptr) {
660                 if (total_probed <= 0) {
661                         DEBUG(0,("ERROR: Could not determine network "
662                         "interfaces, you must use a interfaces config line\n"));
663                         exit(1);
664                 }
665                 for (i=0;i<total_probed;i++) {
666                         if (probed_ifaces[i].flags & IFF_BROADCAST) {
667                                 add_interface(&probed_ifaces[i]);
668                         }
669                 }
670                 return;
671         }
672
673         if (ptr) {
674                 while (*ptr) {
675                         char *ptr_cpy = SMB_STRDUP(*ptr);
676                         if (ptr_cpy) {
677                                 interpret_interface(ptr_cpy);
678                                 free(ptr_cpy);
679                         }
680                         ptr++;
681                 }
682         }
683
684         if (!local_interfaces) {
685                 DEBUG(0,("WARNING: no network interfaces found\n"));
686         }
687 }
688
689
690 void gfree_interfaces(void)
691 {
692         while (local_interfaces) {
693                 struct interface *iface = local_interfaces;
694                 DLIST_REMOVE(local_interfaces, local_interfaces);
695                 SAFE_FREE(iface->name);
696                 SAFE_FREE(iface);
697         }
698
699         SAFE_FREE(probed_ifaces);
700 }
701
702 /****************************************************************************
703  Return True if the list of probed interfaces has changed.
704 ****************************************************************************/
705
706 bool interfaces_changed(void)
707 {
708         bool ret = false;
709         int n;
710         struct iface_struct *ifaces = NULL;
711
712         n = get_interfaces(talloc_tos(), &ifaces);
713
714         if ((n > 0 )&& (n != total_probed ||
715                         memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
716                 ret = true;
717         }
718
719         TALLOC_FREE(ifaces);
720         return ret;
721 }