Janitorial duties to make autogen.sh portable.
[Samba/gebeck_regimport.git] / source3 / lib / interface.c
blob4d8010e31bc4e61e4019a624ddb129ea6e86f962
1 /*
2 Unix SMB/CIFS implementation.
3 multiple interface handling
4 Copyright (C) Andrew Tridgell 1992-1998
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.
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.
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.
21 #include "includes.h"
23 static struct iface_struct *probed_ifaces;
24 static int total_probed;
26 struct in_addr allones_ip;
27 struct in_addr loopback_ip;
29 static struct interface *local_interfaces;
31 #define ALLONES ((uint32)0xFFFFFFFF)
32 #define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
33 #define MKNETADDR(_IP, _NM) (_IP & _NM)
35 /****************************************************************************
36 Try and find an interface that matches an ip. If we cannot, return NULL
37 **************************************************************************/
38 static struct interface *iface_find(struct in_addr ip, BOOL CheckMask)
40 struct interface *i;
41 if (is_zero_ip(ip)) return local_interfaces;
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;
48 return NULL;
52 /****************************************************************************
53 add an interface to the linked list of interfaces
54 ****************************************************************************/
55 static void add_interface(struct in_addr ip, struct in_addr nmask)
57 struct interface *iface;
58 if (iface_find(ip, False)) {
59 DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip)));
60 return;
63 if (ip_equal(nmask, allones_ip)) {
64 DEBUG(3,("not adding non-broadcast interface %s\n",inet_ntoa(ip)));
65 return;
68 iface = (struct interface *)malloc(sizeof(*iface));
69 if (!iface) return;
71 ZERO_STRUCTPN(iface);
73 iface->ip = ip;
74 iface->nmask = nmask;
75 iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
77 DLIST_ADD(local_interfaces, iface);
79 DEBUG(2,("added interface ip=%s ",inet_ntoa(iface->ip)));
80 DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
81 DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));
86 /****************************************************************************
87 interpret a single element from a interfaces= config line
89 This handles the following different forms:
91 1) wildcard interface name
92 2) DNS name
93 3) IP/masklen
94 4) ip/mask
95 5) bcast/mask
96 ****************************************************************************/
97 static void interpret_interface(const char *token)
99 struct in_addr ip, nmask;
100 char *p;
101 int i, added=0;
103 zero_ip(&ip);
104 zero_ip(&nmask);
106 /* first check if it is an interface name */
107 for (i=0;i<total_probed;i++) {
108 if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
109 add_interface(probed_ifaces[i].ip,
110 probed_ifaces[i].netmask);
111 added = 1;
114 if (added) return;
116 /* maybe it is a DNS name */
117 p = strchr_m(token,'/');
118 if (!p) {
119 ip = *interpret_addr2(token);
120 for (i=0;i<total_probed;i++) {
121 if (ip.s_addr == probed_ifaces[i].ip.s_addr &&
122 !ip_equal(allones_ip, probed_ifaces[i].netmask)) {
123 add_interface(probed_ifaces[i].ip,
124 probed_ifaces[i].netmask);
125 return;
128 DEBUG(2,("can't determine netmask for %s\n", token));
129 return;
132 /* parse it into an IP address/netmasklength pair */
133 *p++ = 0;
135 ip = *interpret_addr2(token);
137 if (strlen(p) > 2) {
138 nmask = *interpret_addr2(p);
139 } else {
140 nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES));
143 /* maybe the first component was a broadcast address */
144 if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) ||
145 ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) {
146 for (i=0;i<total_probed;i++) {
147 if (same_net(ip, probed_ifaces[i].ip, nmask)) {
148 add_interface(probed_ifaces[i].ip, nmask);
149 return;
152 DEBUG(2,("Can't determine ip for broadcast address %s\n", token));
153 return;
156 add_interface(ip, nmask);
160 /****************************************************************************
161 load the list of network interfaces
162 ****************************************************************************/
163 void load_interfaces(void)
165 const char **ptr;
166 int i;
167 struct iface_struct ifaces[MAX_INTERFACES];
169 ptr = lp_interfaces();
171 allones_ip = *interpret_addr2("255.255.255.255");
172 loopback_ip = *interpret_addr2("127.0.0.1");
174 SAFE_FREE(probed_ifaces);
176 /* dump the current interfaces if any */
177 while (local_interfaces) {
178 struct interface *iface = local_interfaces;
179 DLIST_REMOVE(local_interfaces, local_interfaces);
180 ZERO_STRUCTPN(iface);
181 SAFE_FREE(iface);
184 /* probe the kernel for interfaces */
185 total_probed = get_interfaces(ifaces, MAX_INTERFACES);
187 if (total_probed > 0) {
188 probed_ifaces = memdup(ifaces, sizeof(ifaces[0])*total_probed);
191 /* if we don't have a interfaces line then use all broadcast capable
192 interfaces except loopback */
193 if (!ptr || !*ptr || !**ptr) {
194 if (total_probed <= 0) {
195 DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n"));
196 exit(1);
198 for (i=0;i<total_probed;i++) {
199 if (probed_ifaces[i].netmask.s_addr != allones_ip.s_addr &&
200 probed_ifaces[i].ip.s_addr != loopback_ip.s_addr) {
201 add_interface(probed_ifaces[i].ip,
202 probed_ifaces[i].netmask);
205 return;
208 if (ptr) {
209 while (*ptr) {
210 interpret_interface(*ptr);
211 ptr++;
215 if (!local_interfaces) {
216 DEBUG(0,("WARNING: no network interfaces found\n"));
221 /****************************************************************************
222 return True if the list of probed interfaces has changed
223 ****************************************************************************/
224 BOOL interfaces_changed(void)
226 int n;
227 struct iface_struct ifaces[MAX_INTERFACES];
229 n = get_interfaces(ifaces, MAX_INTERFACES);
231 if ((n > 0 )&& (n != total_probed ||
232 memcmp(ifaces, probed_ifaces, sizeof(ifaces[0])*n))) {
233 return True;
236 return False;
240 /****************************************************************************
241 check if an IP is one of mine
242 **************************************************************************/
243 BOOL ismyip(struct in_addr ip)
245 struct interface *i;
246 for (i=local_interfaces;i;i=i->next)
247 if (ip_equal(i->ip,ip)) return True;
248 return False;
251 /****************************************************************************
252 check if a packet is from a local (known) net
253 **************************************************************************/
254 BOOL is_local_net(struct in_addr from)
256 struct interface *i;
257 for (i=local_interfaces;i;i=i->next) {
258 if((from.s_addr & i->nmask.s_addr) ==
259 (i->ip.s_addr & i->nmask.s_addr))
260 return True;
262 return False;
265 /****************************************************************************
266 how many interfaces do we have
267 **************************************************************************/
268 int iface_count(void)
270 int ret = 0;
271 struct interface *i;
273 for (i=local_interfaces;i;i=i->next)
274 ret++;
275 return ret;
278 /****************************************************************************
279 return the Nth interface
280 **************************************************************************/
281 struct interface *get_interface(int n)
283 struct interface *i;
285 for (i=local_interfaces;i && n;i=i->next)
286 n--;
288 if (i) return i;
289 return NULL;
292 /****************************************************************************
293 return IP of the Nth interface
294 **************************************************************************/
295 struct in_addr *iface_n_ip(int n)
297 struct interface *i;
299 for (i=local_interfaces;i && n;i=i->next)
300 n--;
302 if (i) return &i->ip;
303 return NULL;
306 /****************************************************************************
307 return bcast of the Nth interface
308 **************************************************************************/
309 struct in_addr *iface_n_bcast(int n)
311 struct interface *i;
313 for (i=local_interfaces;i && n;i=i->next)
314 n--;
316 if (i) return &i->bcast;
317 return NULL;
321 /* these 3 functions return the ip/bcast/nmask for the interface
322 most appropriate for the given ip address. If they can't find
323 an appropriate interface they return the requested field of the
324 first known interface. */
326 struct in_addr *iface_ip(struct in_addr ip)
328 struct interface *i = iface_find(ip, True);
329 return(i ? &i->ip : &local_interfaces->ip);
333 return True if a IP is directly reachable on one of our interfaces
335 BOOL iface_local(struct in_addr ip)
337 return iface_find(ip, True) ? True : False;