65d276021ce2be2c709cd04b80fe394a90d33c8a
[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-1998
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 allones_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 static struct interface *local_interfaces  = NULL;
37
38 struct interface *last_iface;
39
40 #define ALLONES  ((uint32)0xFFFFFFFF)
41 #define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
42 /****************************************************************************
43 calculate the default netmask for an address
44 ****************************************************************************/
45 static void default_netmask(struct in_addr *inm, struct in_addr *iad)
46 {
47         /*
48         ** Guess a netmask based on the class of the IP address given.
49         */
50         switch((ntohl(iad->s_addr) & 0xE0000000)) {
51         case 0x00000000:     /* Class A addr */
52         case 0x20000000:
53         case 0x40000000:
54         case 0x60000000:
55                 inm->s_addr = htonl(0xFF000000);
56                 break;
57                 
58         case 0x80000000:        /* Class B addr */
59         case 0xA0000000:
60                 inm->s_addr = htonl(0xFFFF0000);
61                 break;
62                 
63         case 0xC0000000:        /* Class C addr */
64                 inm->s_addr = htonl(0xFFFFFF00);
65                 break;
66                 
67         default:                /* ??? */
68                 inm->s_addr = htonl(0xFFFFFFF0);
69         }
70 }
71
72
73 /****************************************************************************
74   get the broadcast address for our address 
75 (troyer@saifr00.ateng.az.honeywell.com)
76 ****************************************************************************/
77 static void get_broadcast(struct in_addr *if_ipaddr,
78                           struct in_addr *if_bcast,
79                           struct in_addr *if_nmask)
80 {  
81         uint32 nm;
82         short onbc;
83         short offbc;
84
85         /* get a default netmask and broadcast */
86         default_netmask(if_nmask, if_ipaddr);
87
88         get_netmask(if_ipaddr, if_nmask);
89
90         /* sanity check on the netmask */
91         nm = ntohl(if_nmask->s_addr);
92         onbc = 0;
93         offbc = 0;
94         while((onbc + offbc) < 32) {
95                 if(nm & 0x80000000) {
96                         onbc++;
97                         if(offbc) {
98                                 /* already found an off bit, so mask
99                                    is wrong */
100                                 onbc = 34;
101                         }
102                 } else {
103                         offbc++;
104                 }
105                 nm <<= 1;
106         }
107         if ((onbc < 8)||(onbc == 34)) {
108                 DEBUG(0,("Impossible netmask %s - using defaults\n",
109                          inet_ntoa(*if_nmask)));
110                 default_netmask(if_nmask, if_ipaddr);      
111         }
112
113         /* derive the broadcast assuming a 1's broadcast, as this is what
114            all MS operating systems do, we have to comply even if the unix
115            box is setup differently */
116         if_bcast->s_addr = MKBCADDR(if_ipaddr->s_addr, if_nmask->s_addr);
117   
118         DEBUG(4,("Derived broadcast address %s\n", inet_ntoa(*if_bcast)));
119 }
120
121
122
123 /****************************************************************************
124 load a list of network interfaces
125 ****************************************************************************/
126 static void interpret_interfaces(char *s, struct interface **interfaces,
127                 char *description)
128 {
129   char *ptr;
130   fstring token;
131   struct interface *iface;
132   struct in_addr ip;
133
134   ptr = s;
135   ipzero = *interpret_addr2("0.0.0.0");
136   allones_ip = *interpret_addr2("255.255.255.255");
137   loopback_ip = *interpret_addr2("127.0.0.1");
138
139   while (next_token(&ptr,token,NULL,sizeof(token))) {
140     /* parse it into an IP address/netmasklength pair */
141     char *p = strchr(token,'/');
142     if (p) *p++ = 0;
143
144     ip = *interpret_addr2(token);
145
146     /* maybe we already have it listed */
147     {
148       struct interface *i;
149       for (i=(*interfaces);i;i=i->next)
150         if (ip_equal(ip,i->ip)) break;
151       if (i) continue;
152     }
153
154     iface = (struct interface *)malloc(sizeof(*iface));
155     if (!iface) return;
156
157     iface->ip = ip;
158
159     if (p) {
160       if (strlen(p) > 2)
161        iface->nmask = *interpret_addr2(p);
162       else
163        iface->nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES));
164     } else {
165       default_netmask(&iface->nmask,&iface->ip);
166     }
167     iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
168     iface->next = NULL;
169
170     if (!(*interfaces)) {
171       (*interfaces) = iface;
172     } else {
173       last_iface->next = iface;
174     }
175     last_iface = iface;
176     DEBUG(2,("Added %s ip=%s ",description,inet_ntoa(iface->ip)));
177     DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
178     DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));         
179   }
180
181   if (*interfaces) return;
182
183   /* setup a default interface */
184   iface = (struct interface *)malloc(sizeof(*iface));
185   if (!iface) return;
186
187   iface->next = NULL;
188
189   if (got_ip) {
190     iface->ip = default_ip;
191   } else {
192     get_myname(NULL,&iface->ip);
193   }
194
195   if (got_bcast) {
196     iface->bcast = default_bcast;
197   } else {
198     get_broadcast(&iface->ip,&iface->bcast,&iface->nmask);
199   }
200
201   if (got_nmask) {
202     iface->nmask = default_nmask;
203     iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
204   }
205
206   if (iface->bcast.s_addr != MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr)) {
207     DEBUG(2,("Warning: inconsistant interface %s\n",inet_ntoa(iface->ip)));
208   }
209
210   iface->next = NULL;
211   (*interfaces) = last_iface = iface;
212
213   DEBUG(2,("Added interface ip=%s ",inet_ntoa(iface->ip)));
214   DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
215   DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));           
216 }
217
218
219 /****************************************************************************
220 load the remote and local interfaces
221 ****************************************************************************/
222 void load_interfaces(void)
223 {
224   /* add the machine's interfaces to local interface structure*/
225   interpret_interfaces(lp_interfaces(), &local_interfaces,"interface");
226 }
227
228
229 /****************************************************************************
230   override the defaults
231   **************************************************************************/
232 void iface_set_default(char *ip,char *bcast,char *nmask)
233 {
234   if (ip) {
235     got_ip = True;
236     default_ip = *interpret_addr2(ip);
237   }
238
239   if (bcast) {
240     got_bcast = True;
241     default_bcast = *interpret_addr2(bcast);
242   }
243
244   if (nmask) {
245     got_nmask = True;
246     default_nmask = *interpret_addr2(nmask);
247   }
248 }
249
250
251 /****************************************************************************
252   check if an IP is one of mine
253   **************************************************************************/
254 BOOL ismyip(struct in_addr ip)
255 {
256   struct interface *i;
257   for (i=local_interfaces;i;i=i->next)
258     if (ip_equal(i->ip,ip)) return True;
259   return False;
260 }
261
262 /****************************************************************************
263   check if a packet is from a local (known) net
264   **************************************************************************/
265 BOOL is_local_net(struct in_addr from)
266 {
267   struct interface *i;
268   for (i=local_interfaces;i;i=i->next)
269     if((from.s_addr & i->nmask.s_addr) == (i->ip.s_addr & i->nmask.s_addr))
270       return True;
271   return False;
272 }
273
274 /****************************************************************************
275   how many interfaces do we have
276   **************************************************************************/
277 int iface_count(void)
278 {
279   int ret = 0;
280   struct interface *i;
281
282   for (i=local_interfaces;i;i=i->next)
283     ret++;
284   return ret;
285 }
286
287 /****************************************************************************
288  True if we have two or more interfaces.
289   **************************************************************************/
290 BOOL we_are_multihomed(void)
291 {
292   static int multi = -1;
293
294   if(multi == -1)
295     multi = (iface_count() > 1 ? True : False);
296
297   return multi;
298 }
299
300 /****************************************************************************
301   return the Nth interface
302   **************************************************************************/
303 struct interface *get_interface(int n)
304
305   struct interface *i;
306   
307   for (i=local_interfaces;i && n;i=i->next)
308     n--;
309
310   if (i) return i;
311   return NULL;
312 }
313
314 /****************************************************************************
315   return IP of the Nth interface
316   **************************************************************************/
317 struct in_addr *iface_n_ip(int n)
318 {
319   struct interface *i;
320   
321   for (i=local_interfaces;i && n;i=i->next)
322     n--;
323
324   if (i) return &i->ip;
325   return NULL;
326 }
327
328 /****************************************************************************
329 Try and find an interface that matches an ip. If we cannot, return NULL
330   **************************************************************************/
331 static struct interface *iface_find(struct in_addr ip)
332 {
333   struct interface *i;
334   if (zero_ip(ip)) return local_interfaces;
335
336   for (i=local_interfaces;i;i=i->next)
337     if (same_net(i->ip,ip,i->nmask)) return i;
338
339   return NULL;
340 }
341
342
343 /****************************************************************************
344 this function provides a simple hash of the configured interfaces. It is
345 used to detect a change in interfaces to tell us whether to discard
346 the current wins.dat file.
347 Note that the result is independent of the order of the interfaces
348   **************************************************************************/
349 unsigned iface_hash(void)
350 {
351         unsigned ret = 0;
352         struct interface *i;
353
354         for (i=local_interfaces;i;i=i->next) {
355                 unsigned x1 = (unsigned)str_checksum(inet_ntoa(i->ip));
356                 unsigned x2 = (unsigned)str_checksum(inet_ntoa(i->nmask));
357                 ret ^= (x1 ^ x2);
358         }
359
360         return ret;
361 }
362
363
364 /* these 3 functions return the ip/bcast/nmask for the interface
365    most appropriate for the given ip address. If they can't find
366    an appropriate interface they return the requested field of the
367    first known interface. */
368
369 struct in_addr *iface_bcast(struct in_addr ip)
370 {
371   struct interface *i = iface_find(ip);
372   return(i ? &i->bcast : &local_interfaces->bcast);
373 }
374
375 struct in_addr *iface_ip(struct in_addr ip)
376 {
377   struct interface *i = iface_find(ip);
378   return(i ? &i->ip : &local_interfaces->ip);
379 }
380
381
382