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