s3: Change sockaddr util function names for consistency
[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
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.
155 **************************************************************************/
156
157 const struct in_addr *first_ipv4_iface(void)
158 {
159         struct interface *i;
160
161         for (i=local_interfaces;i ;i=i->next) {
162                 if (i->ip.ss_family == AF_INET) {
163                         break;
164                 }
165         }
166
167         if (!i) {
168                 return NULL;
169         }
170         return &((const struct sockaddr_in *)&i->ip)->sin_addr;
171 }
172
173 /****************************************************************************
174  Return the Nth interface.
175 **************************************************************************/
176
177 struct interface *get_interface(int n)
178 {
179         struct interface *i;
180
181         for (i=local_interfaces;i && n;i=i->next) {
182                 n--;
183         }
184
185         if (i) {
186                 return i;
187         }
188         return NULL;
189 }
190
191 /****************************************************************************
192  Return IP sockaddr_storage of the Nth interface.
193 **************************************************************************/
194
195 const struct sockaddr_storage *iface_n_sockaddr_storage(int n)
196 {
197         struct interface *i;
198
199         for (i=local_interfaces;i && n;i=i->next) {
200                 n--;
201         }
202
203         if (i) {
204                 return &i->ip;
205         }
206         return NULL;
207 }
208
209 /****************************************************************************
210  Return IPv4 of the Nth interface (if a v4 address). NULL otherwise.
211 **************************************************************************/
212
213 const struct in_addr *iface_n_ip_v4(int n)
214 {
215         struct interface *i;
216
217         for (i=local_interfaces;i && n;i=i->next) {
218                 n--;
219         }
220
221         if (i && i->ip.ss_family == AF_INET) {
222                 return &((const struct sockaddr_in *)&i->ip)->sin_addr;
223         }
224         return NULL;
225 }
226
227 /****************************************************************************
228  Return IPv4 bcast of the Nth interface (if a v4 address). NULL otherwise.
229 **************************************************************************/
230
231 const struct in_addr *iface_n_bcast_v4(int n)
232 {
233         struct interface *i;
234
235         for (i=local_interfaces;i && n;i=i->next) {
236                 n--;
237         }
238
239         if (i && i->ip.ss_family == AF_INET) {
240                 return &((const struct sockaddr_in *)&i->bcast)->sin_addr;
241         }
242         return NULL;
243 }
244
245 /****************************************************************************
246  Return bcast of the Nth interface.
247 **************************************************************************/
248
249 const struct sockaddr_storage *iface_n_bcast(int n)
250 {
251         struct interface *i;
252
253         for (i=local_interfaces;i && n;i=i->next) {
254                 n--;
255         }
256
257         if (i) {
258                 return &i->bcast;
259         }
260         return NULL;
261 }
262
263 /* these 3 functions return the ip/bcast/nmask for the interface
264    most appropriate for the given ip address. If they can't find
265    an appropriate interface they return the requested field of the
266    first known interface. */
267
268 const struct sockaddr_storage *iface_ip(const struct sockaddr *ip)
269 {
270         struct interface *i = iface_find(ip, true);
271         if (i) {
272                 return &i->ip;
273         }
274
275         /* Search for the first interface with
276          * matching address family. */
277
278         for (i=local_interfaces;i;i=i->next) {
279                 if (i->ip.ss_family == ip->sa_family) {
280                         return &i->ip;
281                 }
282         }
283         return NULL;
284 }
285
286 /*
287   return True if a IP is directly reachable on one of our interfaces
288 */
289
290 bool iface_local(const struct sockaddr *ip)
291 {
292         return iface_find(ip, true) ? true : false;
293 }
294
295 /****************************************************************************
296  Add an interface to the linked list of interfaces.
297 ****************************************************************************/
298
299 static void add_interface(const struct iface_struct *ifs)
300 {
301         char addr[INET6_ADDRSTRLEN];
302         struct interface *iface;
303
304         if (iface_find((struct sockaddr *)&ifs->ip, False)) {
305                 DEBUG(3,("add_interface: not adding duplicate interface %s\n",
306                         print_sockaddr(addr, sizeof(addr), &ifs->ip) ));
307                 return;
308         }
309
310         if (!(ifs->flags & (IFF_BROADCAST|IFF_LOOPBACK))) {
311                 DEBUG(3,("not adding non-broadcast interface %s\n",
312                                         ifs->name ));
313                 return;
314         }
315
316         iface = SMB_MALLOC_P(struct interface);
317         if (!iface) {
318                 return;
319         }
320
321         ZERO_STRUCTPN(iface);
322
323         iface->name = SMB_STRDUP(ifs->name);
324         if (!iface->name) {
325                 SAFE_FREE(iface);
326                 return;
327         }
328         iface->flags = ifs->flags;
329         iface->ip = ifs->ip;
330         iface->netmask = ifs->netmask;
331         iface->bcast = ifs->bcast;
332
333         DLIST_ADD(local_interfaces, iface);
334
335         DEBUG(2,("added interface %s ip=%s ",
336                 iface->name,
337                 print_sockaddr(addr, sizeof(addr), &iface->ip) ));
338         DEBUG(2,("bcast=%s ",
339                 print_sockaddr(addr, sizeof(addr),
340                         &iface->bcast) ));
341         DEBUG(2,("netmask=%s\n",
342                 print_sockaddr(addr, sizeof(addr),
343                         &iface->netmask) ));
344 }
345
346 /****************************************************************************
347  Interpret a single element from a interfaces= config line.
348
349  This handles the following different forms:
350
351  1) wildcard interface name
352  2) DNS name
353  3) IP/masklen
354  4) ip/mask
355  5) bcast/mask
356 ****************************************************************************/
357
358 static void interpret_interface(char *token)
359 {
360         struct sockaddr_storage ss;
361         struct sockaddr_storage ss_mask;
362         struct sockaddr_storage ss_net;
363         struct sockaddr_storage ss_bcast;
364         struct iface_struct ifs;
365         char *p;
366         int i;
367         bool added=false;
368         bool goodaddr = false;
369
370         /* first check if it is an interface name */
371         for (i=0;i<total_probed;i++) {
372                 if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
373                         add_interface(&probed_ifaces[i]);
374                         added = true;
375                 }
376         }
377         if (added) {
378                 return;
379         }
380
381         /* maybe it is a DNS name */
382         p = strchr_m(token,'/');
383         if (p == NULL) {
384                 if (!interpret_string_addr(&ss, token, 0)) {
385                         DEBUG(2, ("interpret_interface: Can't find address "
386                                   "for %s\n", token));
387                         return;
388                 }
389
390                 for (i=0;i<total_probed;i++) {
391                         if (sockaddr_equal((struct sockaddr *)&ss, (struct sockaddr *)&probed_ifaces[i].ip)) {
392                                 add_interface(&probed_ifaces[i]);
393                                 return;
394                         }
395                 }
396                 DEBUG(2,("interpret_interface: "
397                         "can't determine interface for %s\n",
398                         token));
399                 return;
400         }
401
402         /* parse it into an IP address/netmasklength pair */
403         *p = 0;
404         goodaddr = interpret_string_addr(&ss, token, 0);
405         *p++ = '/';
406
407         if (!goodaddr) {
408                 DEBUG(2,("interpret_interface: "
409                         "can't determine interface for %s\n",
410                         token));
411                 return;
412         }
413
414         if (strlen(p) > 2) {
415                 goodaddr = interpret_string_addr(&ss_mask, p, 0);
416                 if (!goodaddr) {
417                         DEBUG(2,("interpret_interface: "
418                                 "can't determine netmask from %s\n",
419                                 p));
420                         return;
421                 }
422         } else {
423                 char *endp = NULL;
424                 unsigned long val = strtoul(p, &endp, 0);
425                 if (p == endp || (endp && *endp != '\0')) {
426                         DEBUG(2,("interpret_interface: "
427                                 "can't determine netmask value from %s\n",
428                                 p));
429                         return;
430                 }
431                 if (!make_netmask(&ss_mask, &ss, val)) {
432                         DEBUG(2,("interpret_interface: "
433                                 "can't apply netmask value %lu from %s\n",
434                                 val,
435                                 p));
436                         return;
437                 }
438         }
439
440         make_bcast(&ss_bcast, &ss, &ss_mask);
441         make_net(&ss_net, &ss, &ss_mask);
442
443         /* Maybe the first component was a broadcast address. */
444         if (sockaddr_equal((struct sockaddr *)&ss_bcast, (struct sockaddr *)&ss) ||
445                 sockaddr_equal((struct sockaddr *)&ss_net, (struct sockaddr *)&ss)) {
446                 for (i=0;i<total_probed;i++) {
447                         if (same_net((struct sockaddr *)&ss, 
448                                                  (struct sockaddr *)&probed_ifaces[i].ip, 
449                                                  (struct sockaddr *)&ss_mask)) {
450                                 /* Temporarily replace netmask on
451                                  * the detected interface - user knows
452                                  * best.... */
453                                 struct sockaddr_storage saved_mask =
454                                         probed_ifaces[i].netmask;
455                                 probed_ifaces[i].netmask = ss_mask;
456                                 DEBUG(2,("interpret_interface: "
457                                         "using netmask value %s from "
458                                         "config file on interface %s\n",
459                                         p,
460                                         probed_ifaces[i].name));
461                                 add_interface(&probed_ifaces[i]);
462                                 probed_ifaces[i].netmask = saved_mask;
463                                 return;
464                         }
465                 }
466                 DEBUG(2,("interpret_interface: Can't determine ip for "
467                         "broadcast address %s\n",
468                         token));
469                 return;
470         }
471
472         /* Just fake up the interface definition. User knows best. */
473
474         DEBUG(2,("interpret_interface: Adding interface %s\n",
475                 token));
476
477         ZERO_STRUCT(ifs);
478         (void)strlcpy(ifs.name, token, sizeof(ifs.name));
479         ifs.flags = IFF_BROADCAST;
480         ifs.ip = ss;
481         ifs.netmask = ss_mask;
482         ifs.bcast = ss_bcast;
483         add_interface(&ifs);
484 }
485
486 /****************************************************************************
487  Load the list of network interfaces.
488 ****************************************************************************/
489
490 void load_interfaces(void)
491 {
492         struct iface_struct ifaces[MAX_INTERFACES];
493         const char **ptr = lp_interfaces();
494         int i;
495
496         SAFE_FREE(probed_ifaces);
497
498         /* dump the current interfaces if any */
499         while (local_interfaces) {
500                 struct interface *iface = local_interfaces;
501                 DLIST_REMOVE(local_interfaces, local_interfaces);
502                 SAFE_FREE(iface->name);
503                 SAFE_FREE(iface);
504         }
505
506         /* Probe the kernel for interfaces */
507         total_probed = get_interfaces(ifaces, MAX_INTERFACES);
508
509         if (total_probed > 0) {
510                 probed_ifaces = (struct iface_struct *)memdup(ifaces,
511                                 sizeof(ifaces[0])*total_probed);
512                 if (!probed_ifaces) {
513                         DEBUG(0,("ERROR: memdup failed\n"));
514                         exit(1);
515                 }
516         }
517
518         /* if we don't have a interfaces line then use all broadcast capable
519            interfaces except loopback */
520         if (!ptr || !*ptr || !**ptr) {
521                 if (total_probed <= 0) {
522                         DEBUG(0,("ERROR: Could not determine network "
523                         "interfaces, you must use a interfaces config line\n"));
524                         exit(1);
525                 }
526                 for (i=0;i<total_probed;i++) {
527                         if (probed_ifaces[i].flags & IFF_BROADCAST) {
528                                 add_interface(&probed_ifaces[i]);
529                         }
530                 }
531                 return;
532         }
533
534         if (ptr) {
535                 while (*ptr) {
536                         char *ptr_cpy = SMB_STRDUP(*ptr);
537                         if (ptr_cpy) {
538                                 interpret_interface(ptr_cpy);
539                                 free(ptr_cpy);
540                         }
541                         ptr++;
542                 }
543         }
544
545         if (!local_interfaces) {
546                 DEBUG(0,("WARNING: no network interfaces found\n"));
547         }
548 }
549
550
551 void gfree_interfaces(void)
552 {
553         while (local_interfaces) {
554                 struct interface *iface = local_interfaces;
555                 DLIST_REMOVE(local_interfaces, local_interfaces);
556                 SAFE_FREE(iface->name);
557                 SAFE_FREE(iface);
558         }
559
560         SAFE_FREE(probed_ifaces);
561 }
562
563 /****************************************************************************
564  Return True if the list of probed interfaces has changed.
565 ****************************************************************************/
566
567 bool interfaces_changed(void)
568 {
569         int n;
570         struct iface_struct ifaces[MAX_INTERFACES];
571
572         n = get_interfaces(ifaces, MAX_INTERFACES);
573
574         if ((n > 0 )&& (n != total_probed ||
575                         memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
576                 return true;
577         }
578
579         return false;
580 }