source: trunk/samba-3.0.25pre1/source/lib/interface.c@ 5

Last change on this file since 5 was 1, checked in by Paul Smedley, 18 years ago

Initial code import

File size: 9.1 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
189 if (total_probed > 0) {
190 probed_ifaces = (struct iface_struct *)memdup(ifaces, sizeof(ifaces[0])*total_probed);
191 if (!probed_ifaces) {
192 DEBUG(0,("ERROR: memdup failed\n"));
193 exit(1);
194 }
195 }
196
197 /* if we don't have a interfaces line then use all broadcast capable
198 interfaces except loopback */
199 if (!ptr || !*ptr || !**ptr) {
200 if (total_probed <= 0) {
201 DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n"));
202 exit(1);
203 }
204 for (i=0;i<total_probed;i++) {
205 if (
206#if !defined(__s390__)
207 probed_ifaces[i].netmask.s_addr != allones_ip.s_addr &&
208#endif
209 probed_ifaces[i].ip.s_addr != loopback_ip.s_addr) {
210 add_interface(probed_ifaces[i].ip,
211 probed_ifaces[i].netmask);
212 }
213 }
214 return;
215 }
216
217 if (ptr) {
218 while (*ptr) {
219 char *ptr_cpy = SMB_STRDUP(*ptr);
220 if (ptr_cpy) {
221 interpret_interface(ptr_cpy);
222 free(ptr_cpy);
223 }
224 ptr++;
225 }
226 }
227
228 if (!local_interfaces) {
229 DEBUG(0,("WARNING: no network interfaces found\n"));
230 }
231}
232
233
234/****************************************************************************
235return True if the list of probed interfaces has changed
236****************************************************************************/
237BOOL interfaces_changed(void)
238{
239 int n;
240 struct iface_struct ifaces[MAX_INTERFACES];
241
242 n = get_interfaces(ifaces, MAX_INTERFACES);
243
244 if ((n > 0 )&& (n != total_probed ||
245 memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
246 return True;
247 }
248
249 return False;
250}
251
252
253/****************************************************************************
254 check if an IP is one of mine
255 **************************************************************************/
256BOOL ismyip(struct in_addr ip)
257{
258 struct interface *i;
259 for (i=local_interfaces;i;i=i->next)
260 if (ip_equal(i->ip,ip)) return True;
261 return False;
262}
263
264/****************************************************************************
265 check if a packet is from a local (known) net
266 **************************************************************************/
267BOOL is_local_net(struct in_addr from)
268{
269 struct interface *i;
270 for (i=local_interfaces;i;i=i->next) {
271 if((from.s_addr & i->nmask.s_addr) ==
272 (i->ip.s_addr & i->nmask.s_addr))
273 return True;
274 }
275 return False;
276}
277
278/****************************************************************************
279 how many interfaces do we have
280 **************************************************************************/
281int iface_count(void)
282{
283 int ret = 0;
284 struct interface *i;
285
286 for (i=local_interfaces;i;i=i->next)
287 ret++;
288 return ret;
289}
290
291/****************************************************************************
292 return the Nth interface
293 **************************************************************************/
294struct interface *get_interface(int n)
295{
296 struct interface *i;
297
298 for (i=local_interfaces;i && n;i=i->next)
299 n--;
300
301 if (i) return i;
302 return NULL;
303}
304
305/****************************************************************************
306 return IP of the Nth interface
307 **************************************************************************/
308struct in_addr *iface_n_ip(int n)
309{
310 struct interface *i;
311
312 for (i=local_interfaces;i && n;i=i->next)
313 n--;
314
315 if (i) return &i->ip;
316 return NULL;
317}
318
319/****************************************************************************
320 return bcast of the Nth interface
321 **************************************************************************/
322struct in_addr *iface_n_bcast(int n)
323{
324 struct interface *i;
325
326 for (i=local_interfaces;i && n;i=i->next)
327 n--;
328
329 if (i) return &i->bcast;
330 return NULL;
331}
332
333
334/* these 3 functions return the ip/bcast/nmask for the interface
335 most appropriate for the given ip address. If they can't find
336 an appropriate interface they return the requested field of the
337 first known interface. */
338
339struct in_addr *iface_ip(struct in_addr ip)
340{
341 struct interface *i = iface_find(ip, True);
342 return(i ? &i->ip : &local_interfaces->ip);
343}
344
345/*
346 return True if a IP is directly reachable on one of our interfaces
347*/
348BOOL iface_local(struct in_addr ip)
349{
350 return iface_find(ip, True) ? True : False;
351}
Note: See TracBrowser for help on using the repository browser.