added code from Philip A Prindeville <philipp@enteka.com> which expands
[samba.git] / source3 / lib / interface.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    multiple interface handling
5    Copyright (C) Andrew Tridgell 1992-1997
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 2 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, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 #include <assert.h>             /* added by philipp */
25
26 extern int DEBUGLEVEL;
27
28 struct in_addr ipzero;
29 struct in_addr wins_ip;
30
31 struct interface *local_interfaces  = NULL;
32 struct interface *present_interfaces = NULL;
33
34 struct interface *last_iface;
35
36 static void get_interfaces()
37 {  
38   int sock = -1;               /* AF_INET raw socket desc */
39   char buff[1024];
40   struct ifreq *ifr=NULL, ifr2;
41   int i;
42   struct interface *iface, *last_iface = NULL;
43
44 #ifndef ifr_mtu
45 #define ifr_mtu ifr_metric
46 #endif
47
48 #if defined(EVEREST)
49   int n_interfaces;
50   struct ifconf ifc;
51   struct ifreq  *ifreqs;
52 #elif defined(USE_IFREQ)
53   struct ifreq ifreq;
54   struct strioctl strioctl;
55   struct ifconf *ifc;
56 #else
57   struct ifconf ifc;
58 #endif
59
60   if (present_interfaces) return;       /* already initialized */
61
62   /* Create a socket to the INET kernel. */
63 #if USE_SOCKRAW
64   if ((sock = socket(AF_INET, SOCK_RAW, PF_INET )) < 0)
65 #else
66     if ((sock = socket(AF_INET, SOCK_DGRAM, 0 )) < 0)
67 #endif
68       {
69         DEBUG(0,( "Unable to open socket to get broadcast address\n"));
70         return;
71       }
72   
73   /* Get a list of the configured interfaces */
74 #ifdef EVEREST
75   /* This is part of SCO Openserver 5: The ioctls are no longer part
76      if the lower level STREAMS interface glue. They are now real
77      ioctl calls */
78
79   if (ioctl(sock, SIOCGIFANUM, &n_interfaces) < 0) {
80     DEBUG(0,( "SIOCGIFANUM: %s\n", strerror(errno)));
81   } else {
82     DEBUG(0,( "number of interfaces returned is: %d\n", n_interfaces));
83
84     ifc.ifc_len = sizeof(struct ifreq) * n_interfaces;
85     ifc.ifc_buf = (caddr_t) alloca(ifc.ifc_len);
86
87     if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
88       DEBUG(0, ( "SIOCGIFCONF: %s\n", strerror(errno)));
89     else {
90       ifr = ifc.ifc_req;
91
92       for (i = 0; i < n_interfaces; ++i) {
93         ifr2 = ifr[i];
94         if (ioctl(sock, SIOCGIFFLAGS, &ifr2) < 0)
95           DEBUG(0,("SIOCGIFFLAGS failed\n"));
96
97         if ((ifr2.ifr_flags & (IFF_RUNNING | IFF_LOOPBACK)) != IFF_RUNNING)
98           continue;
99
100         iface = (struct interface *)malloc(sizeof(*iface));
101         assert(iface != NULL);
102         iface->next = NULL;
103         iface->ip = ((struct sockaddr_in *) &ifr[i].ifr_addr)->sin_addr;
104         iface->name = strdup(ifr[i].ifr_name);
105         iface->flags = ifr2.ifr_flags;
106
107         /* complete with netmask and b'cast address */
108         ifr2 = *ifr;
109         if (ioctl(sock, SIOCGIFNETMASK, &ifr2) < 0)
110           DEBUG(0,("SIOCGIFNETMASK failed\n"));
111         else
112           iface->nmask = ((struct sockaddr_in *)&ifr2.ifr_addr)->sin_addr;
113         if (ioctl(sock, SIOCGIFBRDADDR, &ifr2) < 0)
114           DEBUG(0,("SIOCGIFBRDADDR failed\n"));
115         else
116           iface->bcast = ((struct sockaddr_in *)&ifr2.ifr_addr)->sin_addr;
117         if (ioctl(sock, SIOCGIFMTU, &ifr2) < 0)
118           DEBUG(0,("SIOCGIFMTU failed\n"));
119         else
120           iface->mtu = ifr2.ifr_mtu;
121
122         DEBUG(4,("Netmask for %s = %s\n", iface->name, inet_ntoa(iface->nmask)));
123
124         if (!present_interfaces)
125           present_interfaces = iface;
126         else
127           last_iface->next = iface;
128         last_iface = iface;
129       }
130     }
131   }
132 #elif defined(USE_IFREQ)
133   ifc = (struct ifconf *)buff;
134   ifc->ifc_len = BUFSIZ - sizeof(struct ifconf);
135   strioctl.ic_cmd = SIOCGIFCONF;
136   strioctl.ic_dp  = (char *)ifc;
137   strioctl.ic_len = sizeof(buff);
138   if (ioctl(sock, I_STR, &strioctl) < 0) {
139     DEBUG(0,( "I_STR/SIOCGIFCONF: %s\n", strerror(errno)));
140   } else {
141     ifr = (struct ifreq *)ifc->ifc_req;  
142
143     /* Loop through interfaces, looking for given IP address */
144     for (i = ifc->ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
145       ifr2 = *ifr;
146       if (ioctl(sock, SIOCGIFFLAGS, &ifr2) < 0)
147         DEBUG(0,("SIOCGIFFLAGS failed\n"));
148
149       if ((ifr2.ifr_flags & (IFF_RUNNING | IFF_LOOPBACK)) == IFF_RUNNING) {
150
151         iface = (struct interface *)malloc(sizeof(*iface));
152         assert(iface != NULL);
153         iface->next = NULL;
154         iface->ip = (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr;
155         iface->name = strdup(ifr->ifr_name);
156         iface->flags = ifr2.ifr_flags;
157
158         /* complete with netmask and b'cast address */
159         ifr2 = *ifr;
160         strioctl.ic_cmd = SIOCGIFNETMASK;
161         strioctl.ic_dp  = (char *)&ifr2;
162         strioctl.ic_len = sizeof(struct ifr2);
163         if (ioctl(sock, I_STR, &strioctl) < 0)
164           DEBUG(0,("Failed I_STR/SIOCGIFNETMASK: %s\n", strerror(errno)));
165         else
166           iface->nmask = ((struct sockaddr_in *)&ifr2.ifr_addr)->sin_addr;
167         strioctl.ic_cmd = SIOCGIFBRDADDR;
168         if (ioctl(sock, I_STR, &strioctl) < 0)
169           DEBUG(0,("SIOCGIFBRDADDR failed\n"));
170         else
171           iface->bcast = ((struct sockaddr_in *)&ifr2.ifr_addr)->sin_addr;
172         strioctl.ic_cmd = SIOCGIFMTU;
173         if (ioctl(sock, I_STR, &strioctl) < 0)
174           DEBUG(0,("SIOCGIFMTU failed\n"));
175         else
176           iface->mtu = ifr2.ifr_mtu;
177
178         DEBUG(4,("Netmask for %s = %s\n", iface->name, inet_ntoa(iface->nmask)));
179
180         if (!present_interfaces)
181           present_interfaces = iface;
182         else
183           last_iface->next = iface;
184         last_iface = iface;
185       }
186     }
187   }
188 #elif defined(__FreeBSD__) || defined(NETBSD) || defined(AMIGA) || defined(_AIX41)
189   ifc.ifc_len = sizeof(buff);
190   ifc.ifc_buf = buff;
191   if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
192     DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
193   } else {
194     ifr = ifc.ifc_req;
195     /* Loop through interfaces, looking for given IP address */
196     i = ifc.ifc_len;
197     while (i > 0) {
198       ifr2 = *ifr;
199       if (ioctl(sock, SIOCGIFFLAGS, &ifr2) < 0)
200         DEBUG(0,("SIOCGIFFLAGS failed\n"));
201
202       if ((ifr2.ifr_flags & (IFF_RUNNING | IFF_LOOPBACK)) == IFF_RUNNING) {
203         iface = (struct interface *)malloc(sizeof(*iface));
204         assert(iface != NULL);
205         iface->next = NULL;
206         iface->ip = (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr;
207         iface->name = strdup(ifr->ifr_name);
208         iface->flags = ifr2.ifr_flags;
209
210         /* complete with netmask and b'cast address */
211         ifr2 = *ifr;
212         if (ioctl(sock, SIOCGIFNETMASK, &ifr2) < 0)
213           DEBUG(0,("SIOCGIFNETMASK failed\n"));
214         else
215           iface->nmask = (*(struct sockaddr_in *)&ifr2.ifr_addr).sin_addr;
216         if (ioctl(sock, SIOCGIFBRDADDR, &ifr2) < 0)
217           DEBUG(0,("SIOCGIFBRDADDR failed\n"));
218         else
219           iface->bcast = (*(struct sockaddr_in *)&ifr2.ifr_addr).sin_addr;
220         if (ioctl(sock, SIOCGIFMTU, &ifr2) < 0)
221           DEBUG(0,("SIOCGIFMTU failed\n"));
222         else
223           iface->mtu = ifr2.ifr_mtu;
224
225         DEBUG(4,("Netmask for %s = %s\n", iface->name, inet_ntoa(iface->nmask)));
226
227         if (!present_interfaces)
228           present_interfaces = iface;
229         else
230           last_iface->next = iface;
231         last_iface = iface;
232       }
233
234       i -= ifr->ifr_addr.sa_len + IFNAMSIZ;
235       ifr = (struct ifreq*) ((char*) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
236     }
237   }
238 #else
239   ifc.ifc_len = sizeof(buff);
240   ifc.ifc_buf = buff;
241   if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
242     DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
243   } else {
244     ifr = ifc.ifc_req;
245   
246     /* Loop through interfaces, looking for given IP address */
247     for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
248       ifr2 = *ifr;
249       if (ioctl(sock, SIOCGIFFLAGS, &ifr2) < 0)
250         DEBUG(0,("SIOCGIFFLAGS failed\n"));
251
252       if ((ifr2.ifr_flags & (IFF_RUNNING | IFF_LOOPBACK)) == IFF_RUNNING) {
253 #ifdef BSDI
254         if (ioctl(sock, SIOCGIFADDR, ifr) < 0) break;
255 #endif
256
257         iface = (struct interface *)malloc(sizeof(*iface));
258         assert(iface != NULL);
259         iface->next = NULL;
260         iface->ip = (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr;
261         iface->name = strdup(ifr->ifr_name);
262         iface->flags = ifr2.ifr_flags;
263
264         /* complete with netmask and b'cast address */
265         ifr2 = *ifr;
266         if (ioctl(sock, SIOCGIFNETMASK, &ifr2) < 0)
267           DEBUG(0,("SIOCGIFNETMASK failed\n"));
268         else
269           iface->nmask = (*(struct sockaddr_in *)&ifr2.ifr_addr).sin_addr;
270         if (ioctl(sock, SIOCGIFBRDADDR, &ifr2) < 0)
271           DEBUG(0,("SIOCGIFBRDADDR failed\n"));
272         else
273           iface->bcast = (*(struct sockaddr_in *)&ifr2.ifr_addr).sin_addr;
274         if (ioctl(sock, SIOCGIFMTU, &ifr2) < 0)
275           DEBUG(0,("SIOCGIFMTU failed\n"));
276         else
277           iface->mtu = ifr2.ifr_mtu;
278
279         DEBUG(4,("Netmask for %s = %s\n", iface->name, inet_ntoa(iface->nmask)));
280
281         if (!present_interfaces)
282           present_interfaces = iface;
283         else
284           last_iface->next = iface;
285         last_iface = iface;
286       }
287     }
288   }
289 #endif
290
291   /* Close up shop */
292   (void) close(sock);
293
294 }  /* get_interfaces */
295
296
297 /****************************************************************************
298 load a list of network interfaces
299 ****************************************************************************/
300 static void interpret_interfaces(char *s, struct interface **interfaces,
301                 char *description)
302 {
303   char *ptr = s;
304   fstring token;
305   struct interface *iface, *i;
306   BOOL seenALL = False;
307
308   ipzero = *interpret_addr2("0.0.0.0");
309   wins_ip = *interpret_addr2("255.255.255.255");
310
311   get_interfaces();
312
313   while (next_token(&ptr,token,NULL)) {
314
315     if (strcasecmp(token, "ALL")) {
316       if (*interfaces) {
317         DEBUG(0, ("Error: interface name \"ALL\" must occur alone\n"));
318         /* should do something here ... */
319       }
320
321       /* should we copy the list, or just point at it? */
322       for (i = present_interfaces; i; i = i->next) {
323         iface = (struct interface *)malloc(sizeof(*iface));
324         if (!iface) return;
325
326         *iface = *i;
327         iface->next = NULL;
328
329         if (!(*interfaces))
330           (*interfaces) = iface;
331         else
332           last_iface->next = iface;
333         last_iface = iface;
334       }
335
336       seenALL = True;
337       continue;
338     } else if (seenALL) {
339       DEBUG(0, ("Error: can't mix interface \"ALL\" with other interface namess\n"));
340       continue;
341     }
342
343     /* maybe we already have it listed */
344     for (i=(*interfaces);i;i=i->next)
345       if (strcasecmp(token,i->name)) break;
346     if (i) continue;
347
348     iface = (struct interface *)malloc(sizeof(*iface));
349     if (!iface) return;
350
351     /* make sure name is known */
352     for (i=present_interfaces;i;i=i->next)
353       if (strcasecmp(token,i->name)) break;
354
355     if (!i) {
356       DEBUG(0, ("Warning: unknown interface \"%s\" specified\n", token));
357       continue;
358     }
359
360     *iface = *i;
361     iface->next = NULL;
362     if (iface->bcast.s_addr != (iface->ip.s_addr | ~iface->nmask.s_addr)) {
363       DEBUG(0, ("Warning: overriding b'cast address %s on interface %s\n",
364             inet_ntoa(iface->bcast), iface->name));
365       iface->bcast.s_addr = iface->ip.s_addr | ~iface->nmask.s_addr;
366     }
367
368     if (!(*interfaces)) {
369       (*interfaces) = iface;
370     } else {
371       last_iface->next = iface;
372     }
373     last_iface = iface;
374     DEBUG(1,("Added %s ip=%s ",description,inet_ntoa(iface->ip)));
375     DEBUG(1,("bcast=%s ",inet_ntoa(iface->bcast)));
376     DEBUG(1,("nmask=%s\n",inet_ntoa(iface->nmask)));         
377   }
378
379   if (! *interfaces)
380     DEBUG(0,("Error: no interfaces specified.\n"));
381 }
382
383
384 /****************************************************************************
385 load the remote and local interfaces
386 ****************************************************************************/
387 void load_interfaces(void)
388 {
389   /* add the machine's interfaces to local interface structure*/
390   interpret_interfaces(lp_interfaces(), &local_interfaces,"interface");
391 }
392
393
394 /****************************************************************************
395   override the defaults
396   **************************************************************************/
397 void iface_set_default(char *ip,char *bcast,char *nmask)
398 {
399   DEBUG(0, ("iface_set_default: function deprecated.\n"));
400   exit(1);
401 }
402
403
404 /****************************************************************************
405   check if an IP is one of mine
406   **************************************************************************/
407 BOOL ismyip(struct in_addr ip)
408 {
409   struct interface *i;
410   for (i=local_interfaces;i;i=i->next)
411     if (ip_equal(i->ip,ip)) return True;
412   return False;
413 }
414
415 /****************************************************************************
416   check if a bcast is one of mine
417   **************************************************************************/
418 BOOL ismybcast(struct in_addr bcast)
419 {
420   struct interface *i;
421   for (i=local_interfaces;i;i=i->next)
422     if (ip_equal(i->bcast,bcast)) return True;
423   return False;
424 }
425
426 /****************************************************************************
427   how many interfaces do we have
428   **************************************************************************/
429 int iface_count(void)
430 {
431   int ret = 0;
432   struct interface *i;
433
434   for (i=local_interfaces;i;i=i->next)
435     ret++;
436   return ret;
437 }
438
439 /****************************************************************************
440   return IP of the Nth interface
441   **************************************************************************/
442 struct in_addr *iface_n_ip(int n)
443 {
444   struct interface *i;
445   
446   for (i=local_interfaces;i && n;i=i->next)
447     n--;
448
449   if (i) return &i->ip;
450   return NULL;
451 }
452
453 static struct interface *iface_find(struct in_addr ip)
454 {
455   struct interface *i;
456   if (zero_ip(ip)) return local_interfaces;
457
458   for (i=local_interfaces;i;i=i->next)
459     if (same_net(i->ip,ip,i->nmask)) return i;
460
461   return local_interfaces;
462 }
463
464 /* these 3 functions return the ip/bcast/nmask for the interface
465    most appropriate for the given ip address */
466
467 struct in_addr *iface_bcast(struct in_addr ip)
468 {
469   return(&iface_find(ip)->bcast);
470 }
471
472 struct in_addr *iface_nmask(struct in_addr ip)
473 {
474   return(&iface_find(ip)->nmask);
475 }
476
477 struct in_addr *iface_ip(struct in_addr ip)
478 {
479   return(&iface_find(ip)->ip);
480 }
481