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
ismyaddr(const struct sockaddr * ip)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
ismyip_v4(struct in_addr ip)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
iface_find(const struct sockaddr * ip,bool check_mask)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
is_local_net(const struct sockaddr * from)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)
setup_linklocal_scope_id(struct sockaddr * pss)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
is_local_net_v4(struct in_addr from)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
iface_count(void)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
iface_count_v4_nl(void)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
first_ipv4_iface(void)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
get_interface(int n)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
iface_n_sockaddr_storage(int n)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
iface_n_ip_v4(int n)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
iface_n_bcast_v4(int n)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
iface_n_bcast(int n)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
iface_ip(const struct sockaddr * ip)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
iface_local(const struct sockaddr * ip)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
add_interface(const struct iface_struct * ifs)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
parse_extra_info(char * key,uint64_t * speed,uint32_t * cap,uint32_t * if_index)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)smb_strtoull(val,
374 NULL,
375 0,
376 &error,
377 SMB_STR_STANDARD);
378 if (error != 0) {
379 DBG_DEBUG("Invalid speed value (%s)\n", val);
380 }
381 } else if (strequal_m(key, "capability")) {
382 if (strequal_m(val, "RSS")) {
383 *cap |= FSCTL_NET_IFACE_RSS_CAPABLE;
384 } else if (strequal(val, "RDMA")) {
385 *cap |= FSCTL_NET_IFACE_RDMA_CAPABLE;
386 } else {
387 DBG_WARNING("Capability unknown: "
388 "'%s'\n", val);
389 }
390 } else if (strequal_m(key, "if_index")) {
391 *if_index = (uint32_t)smb_strtoul(val,
392 NULL,
393 0,
394 &error,
395 SMB_STR_STANDARD);
396 if (error != 0) {
397 DBG_DEBUG("Invalid key value (%s)\n", val);
398 }
399 } else {
400 DBG_DEBUG("Key unknown: '%s'\n", key);
401 }
402 }
403
404 key = next_key;
405 }
406 }
407
408 /****************************************************************************
409 Interpret a single element from a interfaces= config line.
410
411 This handles the following different forms:
412
413 1) wildcard interface name
414 2) DNS name
415 3) IP/masklen
416 4) ip/mask
417 5) bcast/mask
418
419 Additional information for an interface can be specified with
420 this extended syntax:
421
422 interface[;key1=value1[,key2=value2[...]]]
423
424 where
425 - keys known: 'speed', 'capability', 'if_index'
426 - speed is in bits per second
427 - capabilites known: 'RSS', 'RDMA'
428 - if_index should be used with care, because
429 these indexes should not conicide with indexes
430 the kernel sets...
431
432 ****************************************************************************/
433
interpret_interface(char * token)434 static void interpret_interface(char *token)
435 {
436 struct sockaddr_storage ss;
437 struct sockaddr_storage ss_mask;
438 struct sockaddr_storage ss_net;
439 struct sockaddr_storage ss_bcast;
440 struct iface_struct ifs;
441 char *p;
442 int i;
443 bool added=false;
444 bool goodaddr = false;
445 uint64_t speed = 0;
446 uint32_t cap = FSCTL_NET_IFACE_NONE_CAPABLE;
447 uint32_t if_index = 0;
448 bool speed_set = false;
449 bool cap_set = false;
450 bool if_index_set = false;
451
452 /* first check if it is an interface name */
453 for (i=0;i<total_probed;i++) {
454 if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
455 add_interface(&probed_ifaces[i]);
456 added = true;
457 }
458 }
459 if (added) {
460 return;
461 }
462
463 /*
464 * extract speed / capability information if present
465 */
466 p = strchr_m(token, ';');
467 if (p != NULL) {
468 *p++ = 0;
469 parse_extra_info(p, &speed, &cap, &if_index);
470 if (speed != 0) {
471 speed_set = true;
472 }
473 if (cap != FSCTL_NET_IFACE_NONE_CAPABLE) {
474 cap_set = true;
475 }
476 if (if_index != 0) {
477 if_index_set = true;
478 }
479 }
480
481 p = strchr_m(token,'/');
482 if (p == NULL) {
483 if (!interpret_string_addr(&ss, token, 0)) {
484 DEBUG(2, ("interpret_interface: Can't find address "
485 "for %s\n", token));
486 return;
487 }
488
489 for (i=0;i<total_probed;i++) {
490 if (sockaddr_equal((struct sockaddr *)&ss,
491 (struct sockaddr *)&probed_ifaces[i].ip))
492 {
493 if (speed_set) {
494 probed_ifaces[i].linkspeed = speed;
495 }
496 if (cap_set) {
497 probed_ifaces[i].capability = cap;
498 }
499 if (if_index_set) {
500 probed_ifaces[i].if_index = if_index;
501 }
502 add_interface(&probed_ifaces[i]);
503 return;
504 }
505 }
506 DEBUG(2,("interpret_interface: "
507 "can't determine interface for %s\n",
508 token));
509 return;
510 }
511
512 /* parse it into an IP address/netmasklength pair */
513 *p = 0;
514 goodaddr = interpret_string_addr(&ss, token, 0);
515 *p++ = '/';
516
517 if (!goodaddr) {
518 DEBUG(2,("interpret_interface: "
519 "can't determine interface for %s\n",
520 token));
521 return;
522 }
523
524 if (strlen(p) > 2) {
525 goodaddr = interpret_string_addr(&ss_mask, p, 0);
526 if (!goodaddr) {
527 DEBUG(2,("interpret_interface: "
528 "can't determine netmask from %s\n",
529 p));
530 return;
531 }
532 } else {
533 int error = 0;
534 unsigned long val;
535
536 val = smb_strtoul(p, NULL, 0, &error, SMB_STR_FULL_STR_CONV);
537 if (error != 0) {
538 DEBUG(2,("interpret_interface: "
539 "can't determine netmask value from %s\n",
540 p));
541 return;
542 }
543 if (!make_netmask(&ss_mask, &ss, val)) {
544 DEBUG(2,("interpret_interface: "
545 "can't apply netmask value %lu from %s\n",
546 val,
547 p));
548 return;
549 }
550 }
551
552 make_bcast(&ss_bcast, &ss, &ss_mask);
553 make_net(&ss_net, &ss, &ss_mask);
554
555 /* Maybe the first component was a broadcast address. */
556 if (sockaddr_equal((struct sockaddr *)&ss_bcast, (struct sockaddr *)&ss) ||
557 sockaddr_equal((struct sockaddr *)&ss_net, (struct sockaddr *)&ss)) {
558 for (i=0;i<total_probed;i++) {
559 if (same_net((struct sockaddr *)&ss,
560 (struct sockaddr *)&probed_ifaces[i].ip,
561 (struct sockaddr *)&ss_mask)) {
562 /* Temporarily replace netmask on
563 * the detected interface - user knows
564 * best.... */
565 struct sockaddr_storage saved_mask =
566 probed_ifaces[i].netmask;
567 probed_ifaces[i].netmask = ss_mask;
568 DEBUG(2,("interpret_interface: "
569 "using netmask value %s from "
570 "config file on interface %s\n",
571 p,
572 probed_ifaces[i].name));
573 if (speed_set) {
574 probed_ifaces[i].linkspeed = speed;
575 }
576 if (cap_set) {
577 probed_ifaces[i].capability = cap;
578 }
579 if (if_index_set) {
580 probed_ifaces[i].if_index = if_index;
581 }
582 add_interface(&probed_ifaces[i]);
583 probed_ifaces[i].netmask = saved_mask;
584 return;
585 }
586 }
587 DEBUG(2,("interpret_interface: Can't determine ip for "
588 "broadcast address %s\n",
589 token));
590 return;
591 }
592
593 /* Just fake up the interface definition. User knows best. */
594
595 DEBUG(2,("interpret_interface: Adding interface %s\n",
596 token));
597
598 ZERO_STRUCT(ifs);
599 (void)strlcpy(ifs.name, token, sizeof(ifs.name));
600 ifs.flags = IFF_BROADCAST;
601 ifs.ip = ss;
602 ifs.netmask = ss_mask;
603 ifs.bcast = ss_bcast;
604 if (if_index_set) {
605 ifs.if_index = if_index;
606 }
607 if (speed_set) {
608 ifs.linkspeed = speed;
609 } else {
610 ifs.linkspeed = 1000 * 1000 * 1000;
611 }
612 ifs.capability = cap;
613 add_interface(&ifs);
614 }
615
616 /****************************************************************************
617 Load the list of network interfaces.
618 ****************************************************************************/
619
load_interfaces(void)620 void load_interfaces(void)
621 {
622 struct iface_struct *ifaces = NULL;
623 const char **ptr = lp_interfaces();
624 int i;
625
626 gfree_interfaces();
627
628 /* Probe the kernel for interfaces */
629 total_probed = get_interfaces(talloc_tos(), &ifaces);
630
631 if (total_probed > 0) {
632 probed_ifaces = (struct iface_struct *)smb_memdup(ifaces,
633 sizeof(ifaces[0])*total_probed);
634 if (!probed_ifaces) {
635 DEBUG(0,("ERROR: smb_memdup failed\n"));
636 exit(1);
637 }
638 }
639 TALLOC_FREE(ifaces);
640
641 /* if we don't have a interfaces line then use all broadcast capable
642 interfaces except loopback */
643 if (!ptr || !*ptr || !**ptr) {
644 if (total_probed <= 0) {
645 DEBUG(0,("ERROR: Could not determine network "
646 "interfaces, you must use a interfaces config line\n"));
647 exit(1);
648 }
649 for (i=0;i<total_probed;i++) {
650 if (probed_ifaces[i].flags & IFF_BROADCAST) {
651 add_interface(&probed_ifaces[i]);
652 }
653 }
654 return;
655 }
656
657 if (ptr) {
658 while (*ptr) {
659 char *ptr_cpy = SMB_STRDUP(*ptr);
660 if (ptr_cpy) {
661 interpret_interface(ptr_cpy);
662 free(ptr_cpy);
663 }
664 ptr++;
665 }
666 }
667
668 if (!local_interfaces) {
669 DEBUG(0,("WARNING: no network interfaces found\n"));
670 }
671 }
672
673
gfree_interfaces(void)674 void gfree_interfaces(void)
675 {
676 while (local_interfaces) {
677 struct interface *iface = local_interfaces;
678 DLIST_REMOVE(local_interfaces, local_interfaces);
679 SAFE_FREE(iface->name);
680 SAFE_FREE(iface);
681 }
682
683 SAFE_FREE(probed_ifaces);
684 }
685
686 /****************************************************************************
687 Return True if the list of probed interfaces has changed.
688 ****************************************************************************/
689
interfaces_changed(void)690 bool interfaces_changed(void)
691 {
692 bool ret = false;
693 int n;
694 struct iface_struct *ifaces = NULL;
695
696 n = get_interfaces(talloc_tos(), &ifaces);
697
698 if ((n > 0 )&& (n != total_probed ||
699 memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
700 ret = true;
701 }
702
703 TALLOC_FREE(ifaces);
704 return ret;
705 }
706