2 Unix SMB/Netbios implementation.
4 multiple interface handling
5 Copyright (C) Andrew Tridgell 1992-1997
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.
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.
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.
24 #include <assert.h> /* added by philipp */
26 extern int DEBUGLEVEL;
28 struct in_addr ipzero;
29 struct in_addr wins_ip;
31 struct interface *local_interfaces = NULL;
32 struct interface *present_interfaces = NULL;
34 struct interface *last_iface;
36 static void get_interfaces()
38 int sock = -1; /* AF_INET raw socket desc */
40 struct ifreq *ifr=NULL, ifr2;
42 struct interface *iface, *last_iface = NULL;
45 #define ifr_mtu ifr_metric
52 #elif defined(USE_IFREQ)
54 struct strioctl strioctl;
60 if (present_interfaces) return; /* already initialized */
62 /* Create a socket to the INET kernel. */
64 if ((sock = socket(AF_INET, SOCK_RAW, PF_INET )) < 0)
66 if ((sock = socket(AF_INET, SOCK_DGRAM, 0 )) < 0)
69 DEBUG(0,( "Unable to open socket to get broadcast address\n"));
73 /* Get a list of the configured interfaces */
75 /* This is part of SCO Openserver 5: The ioctls are no longer part
76 if the lower level STREAMS interface glue. They are now real
79 if (ioctl(sock, SIOCGIFANUM, &n_interfaces) < 0) {
80 DEBUG(0,( "SIOCGIFANUM: %s\n", strerror(errno)));
82 DEBUG(0,( "number of interfaces returned is: %d\n", n_interfaces));
84 ifc.ifc_len = sizeof(struct ifreq) * n_interfaces;
85 ifc.ifc_buf = (caddr_t) alloca(ifc.ifc_len);
87 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
88 DEBUG(0, ( "SIOCGIFCONF: %s\n", strerror(errno)));
92 for (i = 0; i < n_interfaces; ++i) {
94 if (ioctl(sock, SIOCGIFFLAGS, &ifr2) < 0)
95 DEBUG(0,("SIOCGIFFLAGS failed\n"));
97 if ((ifr2.ifr_flags & (IFF_RUNNING | IFF_LOOPBACK)) != IFF_RUNNING)
100 iface = (struct interface *)malloc(sizeof(*iface));
101 assert(iface != NULL);
103 iface->ip = ((struct sockaddr_in *) &ifr[i].ifr_addr)->sin_addr;
104 iface->name = strdup(ifr[i].ifr_name);
105 iface->flags = ifr2.ifr_flags;
107 /* complete with netmask and b'cast address */
109 if (ioctl(sock, SIOCGIFNETMASK, &ifr2) < 0)
110 DEBUG(0,("SIOCGIFNETMASK failed\n"));
112 iface->nmask = ((struct sockaddr_in *)&ifr2.ifr_addr)->sin_addr;
113 if (ioctl(sock, SIOCGIFBRDADDR, &ifr2) < 0)
114 DEBUG(0,("SIOCGIFBRDADDR failed\n"));
116 iface->bcast = ((struct sockaddr_in *)&ifr2.ifr_addr)->sin_addr;
117 if (ioctl(sock, SIOCGIFMTU, &ifr2) < 0)
118 DEBUG(0,("SIOCGIFMTU failed\n"));
120 iface->mtu = ifr2.ifr_mtu;
122 DEBUG(4,("Netmask for %s = %s\n", iface->name, inet_ntoa(iface->nmask)));
124 if (!present_interfaces)
125 present_interfaces = iface;
127 last_iface->next = iface;
132 #elif defined(USE_IFREQ)
133 ifc = (struct ifconf *)buff;
134 ifc->ifc_len = BUFSIZ - sizeof(struct ifconf);
135 strioctl.ic_cmd = SIOCGIFCONF;
136 strioctl.ic_dp = (char *)ifc;
137 strioctl.ic_len = sizeof(buff);
138 if (ioctl(sock, I_STR, &strioctl) < 0) {
139 DEBUG(0,( "I_STR/SIOCGIFCONF: %s\n", strerror(errno)));
141 ifr = (struct ifreq *)ifc->ifc_req;
143 /* Loop through interfaces, looking for given IP address */
144 for (i = ifc->ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
146 if (ioctl(sock, SIOCGIFFLAGS, &ifr2) < 0)
147 DEBUG(0,("SIOCGIFFLAGS failed\n"));
149 if ((ifr2.ifr_flags & (IFF_RUNNING | IFF_LOOPBACK)) == IFF_RUNNING) {
151 iface = (struct interface *)malloc(sizeof(*iface));
152 assert(iface != NULL);
154 iface->ip = (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr;
155 iface->name = strdup(ifr->ifr_name);
156 iface->flags = ifr2.ifr_flags;
158 /* complete with netmask and b'cast address */
160 strioctl.ic_cmd = SIOCGIFNETMASK;
161 strioctl.ic_dp = (char *)&ifr2;
162 strioctl.ic_len = sizeof(struct ifr2);
163 if (ioctl(sock, I_STR, &strioctl) < 0)
164 DEBUG(0,("Failed I_STR/SIOCGIFNETMASK: %s\n", strerror(errno)));
166 iface->nmask = ((struct sockaddr_in *)&ifr2.ifr_addr)->sin_addr;
167 strioctl.ic_cmd = SIOCGIFBRDADDR;
168 if (ioctl(sock, I_STR, &strioctl) < 0)
169 DEBUG(0,("SIOCGIFBRDADDR failed\n"));
171 iface->bcast = ((struct sockaddr_in *)&ifr2.ifr_addr)->sin_addr;
172 strioctl.ic_cmd = SIOCGIFMTU;
173 if (ioctl(sock, I_STR, &strioctl) < 0)
174 DEBUG(0,("SIOCGIFMTU failed\n"));
176 iface->mtu = ifr2.ifr_mtu;
178 DEBUG(4,("Netmask for %s = %s\n", iface->name, inet_ntoa(iface->nmask)));
180 if (!present_interfaces)
181 present_interfaces = iface;
183 last_iface->next = iface;
188 #elif defined(__FreeBSD__) || defined(NETBSD) || defined(AMIGA) || defined(_AIX41)
189 ifc.ifc_len = sizeof(buff);
191 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
192 DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
195 /* Loop through interfaces, looking for given IP address */
199 if (ioctl(sock, SIOCGIFFLAGS, &ifr2) < 0)
200 DEBUG(0,("SIOCGIFFLAGS failed\n"));
202 if ((ifr2.ifr_flags & (IFF_RUNNING | IFF_LOOPBACK)) == IFF_RUNNING) {
203 iface = (struct interface *)malloc(sizeof(*iface));
204 assert(iface != NULL);
206 iface->ip = (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr;
207 iface->name = strdup(ifr->ifr_name);
208 iface->flags = ifr2.ifr_flags;
210 /* complete with netmask and b'cast address */
212 if (ioctl(sock, SIOCGIFNETMASK, &ifr2) < 0)
213 DEBUG(0,("SIOCGIFNETMASK failed\n"));
215 iface->nmask = (*(struct sockaddr_in *)&ifr2.ifr_addr).sin_addr;
216 if (ioctl(sock, SIOCGIFBRDADDR, &ifr2) < 0)
217 DEBUG(0,("SIOCGIFBRDADDR failed\n"));
219 iface->bcast = (*(struct sockaddr_in *)&ifr2.ifr_addr).sin_addr;
220 if (ioctl(sock, SIOCGIFMTU, &ifr2) < 0)
221 DEBUG(0,("SIOCGIFMTU failed\n"));
223 iface->mtu = ifr2.ifr_mtu;
225 DEBUG(4,("Netmask for %s = %s\n", iface->name, inet_ntoa(iface->nmask)));
227 if (!present_interfaces)
228 present_interfaces = iface;
230 last_iface->next = iface;
234 i -= ifr->ifr_addr.sa_len + IFNAMSIZ;
235 ifr = (struct ifreq*) ((char*) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
239 ifc.ifc_len = sizeof(buff);
241 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
242 DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
246 /* Loop through interfaces, looking for given IP address */
247 for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
249 if (ioctl(sock, SIOCGIFFLAGS, &ifr2) < 0)
250 DEBUG(0,("SIOCGIFFLAGS failed\n"));
252 if ((ifr2.ifr_flags & (IFF_RUNNING | IFF_LOOPBACK)) == IFF_RUNNING) {
254 if (ioctl(sock, SIOCGIFADDR, ifr) < 0) break;
257 iface = (struct interface *)malloc(sizeof(*iface));
258 assert(iface != NULL);
260 iface->ip = (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr;
261 iface->name = strdup(ifr->ifr_name);
262 iface->flags = ifr2.ifr_flags;
264 /* complete with netmask and b'cast address */
266 if (ioctl(sock, SIOCGIFNETMASK, &ifr2) < 0)
267 DEBUG(0,("SIOCGIFNETMASK failed\n"));
269 iface->nmask = (*(struct sockaddr_in *)&ifr2.ifr_addr).sin_addr;
270 if (ioctl(sock, SIOCGIFBRDADDR, &ifr2) < 0)
271 DEBUG(0,("SIOCGIFBRDADDR failed\n"));
273 iface->bcast = (*(struct sockaddr_in *)&ifr2.ifr_addr).sin_addr;
274 if (ioctl(sock, SIOCGIFMTU, &ifr2) < 0)
275 DEBUG(0,("SIOCGIFMTU failed\n"));
277 iface->mtu = ifr2.ifr_mtu;
279 DEBUG(4,("Netmask for %s = %s\n", iface->name, inet_ntoa(iface->nmask)));
281 if (!present_interfaces)
282 present_interfaces = iface;
284 last_iface->next = iface;
294 } /* get_interfaces */
297 /****************************************************************************
298 load a list of network interfaces
299 ****************************************************************************/
300 static void interpret_interfaces(char *s, struct interface **interfaces,
305 struct interface *iface, *i;
306 BOOL seenALL = False;
308 ipzero = *interpret_addr2("0.0.0.0");
309 wins_ip = *interpret_addr2("255.255.255.255");
313 while (next_token(&ptr,token,NULL)) {
315 if (strcasecmp(token, "ALL")) {
317 DEBUG(0, ("Error: interface name \"ALL\" must occur alone\n"));
318 /* should do something here ... */
321 /* should we copy the list, or just point at it? */
322 for (i = present_interfaces; i; i = i->next) {
323 iface = (struct interface *)malloc(sizeof(*iface));
330 (*interfaces) = iface;
332 last_iface->next = iface;
338 } else if (seenALL) {
339 DEBUG(0, ("Error: can't mix interface \"ALL\" with other interface namess\n"));
343 /* maybe we already have it listed */
344 for (i=(*interfaces);i;i=i->next)
345 if (strcasecmp(token,i->name)) break;
348 iface = (struct interface *)malloc(sizeof(*iface));
351 /* make sure name is known */
352 for (i=present_interfaces;i;i=i->next)
353 if (strcasecmp(token,i->name)) break;
356 DEBUG(0, ("Warning: unknown interface \"%s\" specified\n", token));
362 if (iface->bcast.s_addr != (iface->ip.s_addr | ~iface->nmask.s_addr)) {
363 DEBUG(0, ("Warning: overriding b'cast address %s on interface %s\n",
364 inet_ntoa(iface->bcast), iface->name));
365 iface->bcast.s_addr = iface->ip.s_addr | ~iface->nmask.s_addr;
368 if (!(*interfaces)) {
369 (*interfaces) = iface;
371 last_iface->next = iface;
374 DEBUG(1,("Added %s ip=%s ",description,inet_ntoa(iface->ip)));
375 DEBUG(1,("bcast=%s ",inet_ntoa(iface->bcast)));
376 DEBUG(1,("nmask=%s\n",inet_ntoa(iface->nmask)));
380 DEBUG(0,("Error: no interfaces specified.\n"));
384 /****************************************************************************
385 load the remote and local interfaces
386 ****************************************************************************/
387 void load_interfaces(void)
389 /* add the machine's interfaces to local interface structure*/
390 interpret_interfaces(lp_interfaces(), &local_interfaces,"interface");
394 /****************************************************************************
395 override the defaults
396 **************************************************************************/
397 void iface_set_default(char *ip,char *bcast,char *nmask)
399 DEBUG(0, ("iface_set_default: function deprecated.\n"));
404 /****************************************************************************
405 check if an IP is one of mine
406 **************************************************************************/
407 BOOL ismyip(struct in_addr ip)
410 for (i=local_interfaces;i;i=i->next)
411 if (ip_equal(i->ip,ip)) return True;
415 /****************************************************************************
416 check if a bcast is one of mine
417 **************************************************************************/
418 BOOL ismybcast(struct in_addr bcast)
421 for (i=local_interfaces;i;i=i->next)
422 if (ip_equal(i->bcast,bcast)) return True;
426 /****************************************************************************
427 how many interfaces do we have
428 **************************************************************************/
429 int iface_count(void)
434 for (i=local_interfaces;i;i=i->next)
439 /****************************************************************************
440 return IP of the Nth interface
441 **************************************************************************/
442 struct in_addr *iface_n_ip(int n)
446 for (i=local_interfaces;i && n;i=i->next)
449 if (i) return &i->ip;
453 static struct interface *iface_find(struct in_addr ip)
456 if (zero_ip(ip)) return local_interfaces;
458 for (i=local_interfaces;i;i=i->next)
459 if (same_net(i->ip,ip,i->nmask)) return i;
461 return local_interfaces;
464 /* these 3 functions return the ip/bcast/nmask for the interface
465 most appropriate for the given ip address */
467 struct in_addr *iface_bcast(struct in_addr ip)
469 return(&iface_find(ip)->bcast);
472 struct in_addr *iface_nmask(struct in_addr ip)
474 return(&iface_find(ip)->nmask);
477 struct in_addr *iface_ip(struct in_addr ip)
479 return(&iface_find(ip)->ip);