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