merge from the autoconf2 branch to the main branch
[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)) {
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 bcast is one of mine
264   **************************************************************************/
265 BOOL ismybcast(struct in_addr bcast)
266 {
267   struct interface *i;
268   for (i=local_interfaces;i;i=i->next)
269     if (ip_equal(i->bcast,bcast)) return True;
270   return False;
271 }
272
273 /****************************************************************************
274   check if a packet is from a local (known) net
275   **************************************************************************/
276 BOOL is_local_net(struct in_addr from)
277 {
278   struct interface *i;
279   for (i=local_interfaces;i;i=i->next)
280     if((from.s_addr & i->nmask.s_addr) == (i->ip.s_addr & i->nmask.s_addr))
281       return True;
282   return False;
283 }
284
285 /****************************************************************************
286   how many interfaces do we have
287   **************************************************************************/
288 int iface_count(void)
289 {
290   int ret = 0;
291   struct interface *i;
292
293   for (i=local_interfaces;i;i=i->next)
294     ret++;
295   return ret;
296 }
297
298 /****************************************************************************
299  True if we have two or more interfaces.
300   **************************************************************************/
301 BOOL we_are_multihomed(void)
302 {
303   static int multi = -1;
304
305   if(multi == -1)
306     multi = (iface_count() > 1 ? True : False);
307
308   return multi;
309 }
310
311 /****************************************************************************
312   return the Nth interface
313   **************************************************************************/
314 struct interface *get_interface(int n)
315
316   struct interface *i;
317   
318   for (i=local_interfaces;i && n;i=i->next)
319     n--;
320
321   if (i) return i;
322   return NULL;
323 }
324
325 /****************************************************************************
326   return IP of the Nth interface
327   **************************************************************************/
328 struct in_addr *iface_n_ip(int n)
329 {
330   struct interface *i;
331   
332   for (i=local_interfaces;i && n;i=i->next)
333     n--;
334
335   if (i) return &i->ip;
336   return NULL;
337 }
338
339 /****************************************************************************
340 Try and find an interface that matches an ip. If we cannot, return NULL
341   **************************************************************************/
342 static struct interface *iface_find(struct in_addr ip)
343 {
344   struct interface *i;
345   if (zero_ip(ip)) return local_interfaces;
346
347   for (i=local_interfaces;i;i=i->next)
348     if (same_net(i->ip,ip,i->nmask)) return i;
349
350   return NULL;
351 }
352
353 /* these 3 functions return the ip/bcast/nmask for the interface
354    most appropriate for the given ip address. If they can't find
355    an appropriate interface they return the requested field of the
356    first known interface. */
357
358 struct in_addr *iface_bcast(struct in_addr ip)
359 {
360   struct interface *i = iface_find(ip);
361   return(i ? &i->bcast : &local_interfaces->bcast);
362 }
363
364 struct in_addr *iface_nmask(struct in_addr ip)
365 {
366   struct interface *i = iface_find(ip);
367   return(i ? &i->nmask : &local_interfaces->nmask);
368 }
369
370 struct in_addr *iface_ip(struct in_addr ip)
371 {
372   struct interface *i = iface_find(ip);
373   return(i ? &i->ip : &local_interfaces->ip);
374 }
375
376
377