8af2696a446cac2ec6e6a737a44b69e25c8222a2
[kai/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 extern int DEBUGLEVEL;
25
26 struct in_addr ipzero;
27 struct in_addr wins_ip;
28 struct in_addr loopback_ip;
29 static struct in_addr default_ip;
30 static struct in_addr default_bcast;
31 static struct in_addr default_nmask;
32 static BOOL got_ip=False;
33 static BOOL got_bcast=False;
34 static BOOL got_nmask=False;
35
36 struct interface *local_interfaces  = NULL;
37
38 struct interface *last_iface;
39
40 /****************************************************************************
41 calculate the default netmask for an address
42 ****************************************************************************/
43 static void default_netmask(struct in_addr *inm, struct in_addr *iad)
44 {
45   uint32 ad = ntohl(iad->s_addr);
46   uint32 nm;
47   /*
48   ** Guess a netmask based on the class of the IP address given.
49   */
50   if ( (ad & 0x80000000) == 0 ) {
51     /* class A address */
52     nm = 0xFF000000;
53   } else if ( (ad & 0xC0000000) == 0x80000000 ) {
54     /* class B address */
55     nm = 0xFFFF0000;
56   } else if ( (ad & 0xE0000000) == 0xC0000000 ) {
57     /* class C address */
58     nm = 0xFFFFFF00;
59   }  else {
60     /* class D or E; netmask doesn't make much sense - guess 4 bits */
61     nm =  0xFFFFFFF0;
62   }
63   inm->s_addr = htonl(nm);
64 }
65
66
67 /****************************************************************************
68   get the broadcast address for our address 
69 (troyer@saifr00.ateng.az.honeywell.com)
70 ****************************************************************************/
71 static void get_broadcast(struct in_addr *if_ipaddr,
72                           struct in_addr *if_bcast,
73                           struct in_addr *if_nmask)
74 {  
75   BOOL found = False;
76 #ifndef NO_GET_BROADCAST
77   int sock = -1;               /* AF_INET raw socket desc */
78   char buff[1024];
79   struct ifreq *ifr=NULL;
80   int i;
81
82 #if defined(EVEREST)
83   int n_interfaces;
84   struct ifconf ifc;
85   struct ifreq  *ifreqs;
86 #elif defined(USE_IFREQ)
87   struct ifreq ifreq;
88   struct strioctl strioctl;
89   struct ifconf *ifc;
90 #else
91   struct ifconf ifc;
92 #endif
93 #endif
94
95   /* get a default netmask and broadcast */
96   default_netmask(if_nmask, if_ipaddr);
97
98 #ifndef NO_GET_BROADCAST  
99   /* Create a socket to the INET kernel. */
100 #if USE_SOCKRAW
101   if ((sock = socket(AF_INET, SOCK_RAW, PF_INET )) < 0)
102 #else
103     if ((sock = socket(AF_INET, SOCK_DGRAM, 0 )) < 0)
104 #endif
105       {
106         DEBUG(0,( "Unable to open socket to get broadcast address\n"));
107         return;
108       }
109   
110   /* Get a list of the configured interfaces */
111 #ifdef EVEREST
112   /* This is part of SCO Openserver 5: The ioctls are no longer part
113      if the lower level STREAMS interface glue. They are now real
114      ioctl calls */
115
116   if (ioctl(sock, SIOCGIFANUM, &n_interfaces) < 0) {
117     DEBUG(0,( "SIOCGIFANUM: %s\n", strerror(errno)));
118   } else {
119     DEBUG(0,( "number of interfaces returned is: %d\n", n_interfaces));
120
121     ifc.ifc_len = sizeof(struct ifreq) * n_interfaces;
122     ifc.ifc_buf = (caddr_t) alloca(ifc.ifc_len);
123
124     if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
125       DEBUG(0, ( "SIOCGIFCONF: %s\n", strerror(errno)));
126     else {
127       ifr = ifc.ifc_req;
128
129       for (i = 0; i < n_interfaces; ++i) {
130         if (if_ipaddr->s_addr ==
131             ((struct sockaddr_in *) &ifr[i].ifr_addr)->sin_addr.s_addr) {
132           found = True;
133           break;
134         }
135       }
136     }
137   }
138 #elif defined(USE_IFREQ)
139   ifc = (struct ifconf *)buff;
140   ifc->ifc_len = BUFSIZ - sizeof(struct ifconf);
141   strioctl.ic_cmd = SIOCGIFCONF;
142   strioctl.ic_dp  = (char *)ifc;
143   strioctl.ic_len = sizeof(buff);
144   if (ioctl(sock, I_STR, &strioctl) < 0) {
145     DEBUG(0,( "I_STR/SIOCGIFCONF: %s\n", strerror(errno)));
146   } else {
147     ifr = (struct ifreq *)ifc->ifc_req;  
148
149     /* Loop through interfaces, looking for given IP address */
150     for (i = ifc->ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
151       if (if_ipaddr->s_addr ==
152           (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
153         found = True;
154         break;
155       }
156     }
157   }
158 #elif defined(__FreeBSD__) || defined(NETBSD) || defined(AMIGA) || defined(_AIX41)
159   ifc.ifc_len = sizeof(buff);
160   ifc.ifc_buf = buff;
161   if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
162     DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
163   } else {
164     ifr = ifc.ifc_req;
165     /* Loop through interfaces, looking for given IP address */
166     i = ifc.ifc_len;
167     while (i > 0) {
168       if (if_ipaddr->s_addr ==
169           (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
170         found = True;
171         break;
172       }
173       i -= ifr->ifr_addr.sa_len + IFNAMSIZ;
174       ifr = (struct ifreq*) ((char*) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
175     }
176   }
177 #else
178   ifc.ifc_len = sizeof(buff);
179   ifc.ifc_buf = buff;
180   if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
181     DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
182   } else {
183     ifr = ifc.ifc_req;
184   
185     /* Loop through interfaces, looking for given IP address */
186     for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
187 #ifdef BSDI
188       if (ioctl(sock, SIOCGIFADDR, ifr) < 0) break;
189 #endif
190       if (if_ipaddr->s_addr ==
191           (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
192         found = True;
193         break;
194       }
195     }
196   }
197 #endif
198   
199   if (!found) {
200     DEBUG(0,("No interface found for address %s\n", inet_ntoa(*if_ipaddr)));
201   } else {
202     /* Get the netmask address from the kernel */
203 #ifdef USE_IFREQ
204     ifreq = *ifr;
205   
206     strioctl.ic_cmd = SIOCGIFNETMASK;
207     strioctl.ic_dp  = (char *)&ifreq;
208     strioctl.ic_len = sizeof(struct ifreq);
209     if (ioctl(sock, I_STR, &strioctl) < 0)
210       DEBUG(0,("Failed I_STR/SIOCGIFNETMASK: %s\n", strerror(errno)));
211     else
212       *if_nmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
213 #else
214     if (ioctl(sock, SIOCGIFNETMASK, ifr) < 0)
215       DEBUG(0,("SIOCGIFNETMASK failed\n"));
216     else
217       *if_nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
218 #endif
219
220     DEBUG(4,("Netmask for %s = %s\n", ifr->ifr_name,
221              inet_ntoa(*if_nmask)));
222   }
223
224   /* Close up shop */
225   (void) close(sock);
226   
227 #endif
228
229   /* sanity check on the netmask */
230   {
231     uint32 nm = ntohl(if_nmask->s_addr);
232     if ((nm >> 24) != 0xFF) {
233       DEBUG(0,("Impossible netmask %s - using defaults\n",inet_ntoa(*if_nmask)));
234       default_netmask(if_nmask, if_ipaddr);      
235     }
236   }
237
238   /* derive the broadcast assuming a 1's broadcast, as this is what
239      all MS operating systems do, we have to comply even if the unix
240      box is setup differently */
241   {
242     uint32 ad = ntohl(if_ipaddr->s_addr);
243     uint32 nm = ntohl(if_nmask->s_addr);
244     uint32 bc = (ad & nm) | (0xffffffff & ~nm);
245     if_bcast->s_addr = htonl(bc);
246   }
247   
248   DEBUG(4,("Derived broadcast address %s\n", inet_ntoa(*if_bcast)));
249 }  /* get_broadcast */
250
251
252
253 /****************************************************************************
254 load a list of network interfaces
255 ****************************************************************************/
256 static void interpret_interfaces(char *s, struct interface **interfaces,
257                 char *description)
258 {
259   char *ptr = s;
260   fstring token;
261   struct interface *iface;
262   struct in_addr ip;
263
264   ipzero = *interpret_addr2("0.0.0.0");
265   wins_ip = *interpret_addr2("255.255.255.255");
266   loopback_ip = *interpret_addr2("127.0.0.1");
267
268   while (next_token(&ptr,token,NULL)) {
269     /* parse it into an IP address/netmasklength pair */
270     char *p = strchr(token,'/');
271     if (p) *p = 0;
272
273     ip = *interpret_addr2(token);
274
275     /* maybe we already have it listed */
276     {
277       struct interface *i;
278       for (i=(*interfaces);i;i=i->next)
279         if (ip_equal(ip,i->ip)) break;
280       if (i) continue;
281     }
282
283     iface = (struct interface *)malloc(sizeof(*iface));
284     if (!iface) return;
285
286     iface->ip = ip;
287
288     if (p) {
289       if (strlen(p+1)>2)
290         iface->nmask = *interpret_addr2(p+1);
291       else
292         iface->nmask.s_addr = htonl(~((1<<(32-atoi(p+1)))-1));
293     } else {
294       default_netmask(&iface->nmask,&iface->ip);
295     }
296     iface->bcast.s_addr = iface->ip.s_addr | ~iface->nmask.s_addr;
297     iface->next = NULL;
298
299     if (!(*interfaces)) {
300       (*interfaces) = iface;
301     } else {
302       last_iface->next = iface;
303     }
304     last_iface = iface;
305     DEBUG(2,("Added %s ip=%s ",description,inet_ntoa(iface->ip)));
306     DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
307     DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));         
308   }
309
310   if (*interfaces) return;
311
312   /* setup a default interface */
313   iface = (struct interface *)malloc(sizeof(*iface));
314   if (!iface) return;
315
316   iface->next = NULL;
317
318   if (got_ip) {
319     iface->ip = default_ip;
320   } else {
321     get_myname(NULL,&iface->ip);
322   }
323
324   if (got_bcast) {
325     iface->bcast = default_bcast;
326   } else {
327     get_broadcast(&iface->ip,&iface->bcast,&iface->nmask);
328   }
329
330   if (got_nmask) {
331     iface->nmask = default_nmask;
332     iface->bcast.s_addr = iface->ip.s_addr | ~iface->nmask.s_addr;
333   }
334
335   if (iface->bcast.s_addr != (iface->ip.s_addr | ~iface->nmask.s_addr)) {
336     DEBUG(2,("Warning: inconsistant interface %s\n",inet_ntoa(iface->ip)));
337   }
338
339   iface->next = NULL;
340   (*interfaces) = last_iface = iface;
341
342   DEBUG(2,("Added interface ip=%s ",inet_ntoa(iface->ip)));
343   DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
344   DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));           
345 }
346
347
348 /****************************************************************************
349 load the remote and local interfaces
350 ****************************************************************************/
351 void load_interfaces(void)
352 {
353   /* add the machine's interfaces to local interface structure*/
354   interpret_interfaces(lp_interfaces(), &local_interfaces,"interface");
355 }
356
357
358 /****************************************************************************
359   override the defaults
360   **************************************************************************/
361 void iface_set_default(char *ip,char *bcast,char *nmask)
362 {
363   if (ip) {
364     got_ip = True;
365     default_ip = *interpret_addr2(ip);
366   }
367
368   if (bcast) {
369     got_bcast = True;
370     default_bcast = *interpret_addr2(bcast);
371   }
372
373   if (nmask) {
374     got_nmask = True;
375     default_nmask = *interpret_addr2(nmask);
376   }
377 }
378
379
380 /****************************************************************************
381   check if an IP is one of mine
382   **************************************************************************/
383 BOOL ismyip(struct in_addr ip)
384 {
385   struct interface *i;
386   for (i=local_interfaces;i;i=i->next)
387     if (ip_equal(i->ip,ip)) return True;
388   return False;
389 }
390
391 /****************************************************************************
392   check if a bcast is one of mine
393   **************************************************************************/
394 BOOL ismybcast(struct in_addr bcast)
395 {
396   struct interface *i;
397   for (i=local_interfaces;i;i=i->next)
398     if (ip_equal(i->bcast,bcast)) return True;
399   return False;
400 }
401
402 /****************************************************************************
403   check if a packet is from a local (known) net
404   **************************************************************************/
405 BOOL is_local_net(struct in_addr from)
406 {
407   struct interface *i;
408   for (i=local_interfaces;i;i=i->next)
409     if((from.s_addr & i->nmask.s_addr) == (i->ip.s_addr & i->nmask.s_addr))
410       return True;
411   return False;
412 }
413
414 /****************************************************************************
415   how many interfaces do we have
416   **************************************************************************/
417 int iface_count(void)
418 {
419   int ret = 0;
420   struct interface *i;
421
422   for (i=local_interfaces;i;i=i->next)
423     ret++;
424   return ret;
425 }
426
427 /****************************************************************************
428   return IP of the Nth interface
429   **************************************************************************/
430 struct in_addr *iface_n_ip(int n)
431 {
432   struct interface *i;
433   
434   for (i=local_interfaces;i && n;i=i->next)
435     n--;
436
437   if (i) return &i->ip;
438   return NULL;
439 }
440
441 /****************************************************************************
442 Try and find an interface that matches an ip. If we cannot, return NULL
443   **************************************************************************/
444 static struct interface *iface_find(struct in_addr ip)
445 {
446   struct interface *i;
447   if (zero_ip(ip)) return local_interfaces;
448
449   for (i=local_interfaces;i;i=i->next)
450     if (same_net(i->ip,ip,i->nmask)) return i;
451
452   return NULL;
453 }
454
455 /* these 3 functions return the ip/bcast/nmask for the interface
456    most appropriate for the given ip address */
457
458 struct in_addr *iface_bcast(struct in_addr ip)
459 {
460   struct interface *i = iface_find(ip);
461   return(i ? &i->bcast : &local_interfaces->bcast);
462 }
463
464 struct in_addr *iface_nmask(struct in_addr ip)
465 {
466   struct interface *i = iface_find(ip);
467   return(i ? &i->nmask : &local_interfaces->nmask);
468 }
469
470 struct in_addr *iface_ip(struct in_addr ip)
471 {
472   struct interface *i = iface_find(ip);
473   return(i ? &i->ip : &local_interfaces->ip);
474 }
475
476
477