source: branches/samba-3.0/source/lib/interface.c@ 457

Last change on this file since 457 was 366, checked in by Herwig Bauernfeind, 16 years ago

Better fix for hardcoded \lib directory in 3.0.x

File size: 10.2 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 multiple interface handling
4 Copyright (C) Andrew Tridgell 1992-1998
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include "includes.h"
22
23static struct iface_struct *probed_ifaces;
24static int total_probed;
25
26struct in_addr allones_ip;
27struct in_addr loopback_ip;
28
29static struct interface *local_interfaces;
30
31#define ALLONES ((uint32)0xFFFFFFFF)
32#define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
33#define MKNETADDR(_IP, _NM) (_IP & _NM)
34
35/****************************************************************************
36Try and find an interface that matches an ip. If we cannot, return NULL
37 **************************************************************************/
38static struct interface *iface_find(struct in_addr ip, BOOL CheckMask)
39{
40 struct interface *i;
41 if (is_zero_ip(ip)) return local_interfaces;
42
43 for (i=local_interfaces;i;i=i->next)
44 if (CheckMask) {
45 if (same_net(i->ip,ip,i->nmask)) return i;
46 } else if ((i->ip).s_addr == ip.s_addr) return i;
47
48 return NULL;
49}
50
51
52/****************************************************************************
53add an interface to the linked list of interfaces
54****************************************************************************/
55static void add_interface(struct in_addr ip, struct in_addr nmask)
56{
57 struct interface *iface;
58 if (iface_find(ip, False)) {
59 DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip)));
60 return;
61 }
62
63#if !defined(__s390__)
64 if (ip_equal(nmask, allones_ip)) {
65 DEBUG(3,("not adding non-broadcast interface %s\n",inet_ntoa(ip)));
66 return;
67 }
68#endif
69
70 iface = SMB_MALLOC_P(struct interface);
71 if (!iface) return;
72
73 ZERO_STRUCTPN(iface);
74
75 iface->ip = ip;
76 iface->nmask = nmask;
77 iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
78
79 DLIST_ADD(local_interfaces, iface);
80
81 DEBUG(2,("added interface ip=%s ",inet_ntoa(iface->ip)));
82 DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
83 DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));
84}
85
86
87
88/****************************************************************************
89interpret a single element from a interfaces= config line
90
91This handles the following different forms:
92
931) wildcard interface name
942) DNS name
953) IP/masklen
964) ip/mask
975) bcast/mask
98****************************************************************************/
99static void interpret_interface(char *token)
100{
101 struct in_addr ip, nmask;
102 char *p;
103 int i, added=0;
104
105 zero_ip(&ip);
106 zero_ip(&nmask);
107
108 /* first check if it is an interface name */
109 for (i=0;i<total_probed;i++) {
110 if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
111 add_interface(probed_ifaces[i].ip,
112 probed_ifaces[i].netmask);
113 added = 1;
114 }
115 }
116 if (added) return;
117
118 /* maybe it is a DNS name */
119 p = strchr_m(token,'/');
120 if (!p) {
121 ip = *interpret_addr2(token);
122 for (i=0;i<total_probed;i++) {
123 if (ip.s_addr == probed_ifaces[i].ip.s_addr &&
124 !ip_equal(allones_ip, probed_ifaces[i].netmask)) {
125 add_interface(probed_ifaces[i].ip,
126 probed_ifaces[i].netmask);
127 return;
128 }
129 }
130 DEBUG(2,("can't determine netmask for %s\n", token));
131 return;
132 }
133
134 /* parse it into an IP address/netmasklength pair */
135 *p = 0;
136 ip = *interpret_addr2(token);
137 *p++ = '/';
138
139 if (strlen(p) > 2) {
140 nmask = *interpret_addr2(p);
141 } else {
142 nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES));
143 }
144
145 /* maybe the first component was a broadcast address */
146 if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) ||
147 ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) {
148 for (i=0;i<total_probed;i++) {
149 if (same_net(ip, probed_ifaces[i].ip, nmask)) {
150 add_interface(probed_ifaces[i].ip, nmask);
151 return;
152 }
153 }
154 DEBUG(2,("Can't determine ip for broadcast address %s\n", token));
155 return;
156 }
157
158 add_interface(ip, nmask);
159}
160
161
162/****************************************************************************
163load the list of network interfaces
164****************************************************************************/
165void load_interfaces(void)
166{
167 const char **ptr;
168 int i;
169 struct iface_struct ifaces[MAX_INTERFACES];
170
171 ptr = lp_interfaces();
172
173 allones_ip = *interpret_addr2("255.255.255.255");
174 loopback_ip = *interpret_addr2("127.0.0.1");
175
176 SAFE_FREE(probed_ifaces);
177
178 /* dump the current interfaces if any */
179 while (local_interfaces) {
180 struct interface *iface = local_interfaces;
181 DLIST_REMOVE(local_interfaces, local_interfaces);
182 ZERO_STRUCTPN(iface);
183 SAFE_FREE(iface);
184 }
185
186 /* probe the kernel for interfaces */
187 total_probed = get_interfaces(ifaces, MAX_INTERFACES);
188 DEBUG(2, ("interfaces added %i\n", total_probed));
189
190 if (total_probed > 0) {
191 probed_ifaces = (struct iface_struct *)memdup(ifaces, sizeof(ifaces[0])*total_probed);
192 if (!probed_ifaces) {
193 DEBUG(0,("ERROR: memdup failed\n"));
194 exit(1);
195 }
196 }
197
198 /* if we don't have a interfaces line then use all broadcast capable
199 interfaces except loopback */
200 if (!ptr || !*ptr || !**ptr) {
201 if (total_probed <= 0) {
202 DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n"));
203 exit(1);
204 }
205 for (i=0;i<total_probed;i++) {
206 if (
207#if !defined(__s390__)
208 probed_ifaces[i].netmask.s_addr != allones_ip.s_addr &&
209#endif
210 probed_ifaces[i].ip.s_addr != loopback_ip.s_addr) {
211 add_interface(probed_ifaces[i].ip,
212 probed_ifaces[i].netmask);
213 }
214 }
215 return;
216 }
217
218 if (ptr) {
219 while (*ptr) {
220 char *ptr_cpy = SMB_STRDUP(*ptr);
221 if (ptr_cpy) {
222 interpret_interface(ptr_cpy);
223 free(ptr_cpy);
224 }
225 ptr++;
226 }
227 }
228
229 if (!local_interfaces) {
230 DEBUG(0,("WARNING: no network interfaces found\n"));
231 }
232}
233
234
235void gfree_interfaces(void)
236{
237 while (local_interfaces) {
238 struct interface *iface = local_interfaces;
239 DLIST_REMOVE(local_interfaces, local_interfaces);
240 ZERO_STRUCTPN(iface);
241 SAFE_FREE(iface);
242 }
243
244 SAFE_FREE(probed_ifaces);
245}
246
247/****************************************************************************
248return True if the list of probed interfaces has changed
249****************************************************************************/
250BOOL interfaces_changed(void)
251{
252 int n;
253 struct iface_struct ifaces[MAX_INTERFACES];
254
255 n = get_interfaces(ifaces, MAX_INTERFACES);
256
257 if ((n > 0 )&& (n != total_probed ||
258 memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
259 return True;
260 }
261
262 return False;
263}
264
265
266/****************************************************************************
267 check if an IP is one of mine
268 **************************************************************************/
269BOOL ismyip(struct in_addr ip)
270{
271 struct interface *i;
272 for (i=local_interfaces;i;i=i->next)
273 if (ip_equal(i->ip,ip)) return True;
274 return False;
275}
276
277/****************************************************************************
278 check if a packet is from a local (known) net
279 **************************************************************************/
280BOOL is_local_net(struct in_addr from)
281{
282 struct interface *i;
283 for (i=local_interfaces;i;i=i->next) {
284 if((from.s_addr & i->nmask.s_addr) ==
285 (i->ip.s_addr & i->nmask.s_addr))
286 return True;
287 }
288 return False;
289}
290
291/****************************************************************************
292 how many interfaces do we have
293 **************************************************************************/
294int iface_count(void)
295{
296 int ret = 0;
297 struct interface *i;
298
299 for (i=local_interfaces;i;i=i->next)
300 ret++;
301 return ret;
302}
303
304/****************************************************************************
305 how many non-loopback interfaces do we have
306 **************************************************************************/
307int iface_count_nl(void)
308{
309 int ret = 0;
310 struct interface *i;
311
312 for (i=local_interfaces;i;i=i->next) {
313 if (ip_equal(i->ip, loopback_ip)) {
314 continue;
315 }
316 ret++;
317 }
318 return ret;
319}
320
321/****************************************************************************
322 return the Nth interface
323 **************************************************************************/
324struct interface *get_interface(int n)
325{
326 struct interface *i;
327
328 for (i=local_interfaces;i && n;i=i->next)
329 n--;
330
331 if (i) return i;
332 return NULL;
333}
334
335/****************************************************************************
336 return IP of the Nth interface
337 **************************************************************************/
338struct in_addr *iface_n_ip(int n)
339{
340 struct interface *i;
341
342 for (i=local_interfaces;i && n;i=i->next)
343 n--;
344
345 if (i) return &i->ip;
346 return NULL;
347}
348
349/****************************************************************************
350 return bcast of the Nth interface
351 **************************************************************************/
352struct in_addr *iface_n_bcast(int n)
353{
354 struct interface *i;
355
356 for (i=local_interfaces;i && n;i=i->next)
357 n--;
358
359 if (i) return &i->bcast;
360 return NULL;
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
369struct in_addr *iface_ip(struct in_addr ip)
370{
371 struct interface *i = iface_find(ip, True);
372 return(i ? &i->ip : &local_interfaces->ip);
373}
374
375/*
376 return True if a IP is directly reachable on one of our interfaces
377*/
378BOOL iface_local(struct in_addr ip)
379{
380 return iface_find(ip, True) ? True : False;
381}
Note: See TracBrowser for help on using the repository browser.