Annotation of src/usr.bin/sudo/interfaces.c, Revision 1.2
1.1 millert 1: /*
1.2 ! millert 2: * Copyright (c) 1996, 1998-2001 Todd C. Miller <Todd.Miller@courtesan.com>
1.1 millert 3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: *
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: *
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * 3. The name of the author may not be used to endorse or promote products
17: * derived from this software without specific prior written permission.
18: *
19: * 4. Products derived from this software may not be called "Sudo" nor
20: * may "Sudo" appear in their names without specific prior written
21: * permission from the author.
22: *
23: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
25: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
26: * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33: */
34:
35: /*
36: * Supress a warning w/ gcc on Digital UN*X.
37: * The system headers should really do this....
38: */
39: #if defined(__osf__) && !defined(__cplusplus)
40: struct mbuf;
41: struct rtentry;
42: #endif
43:
44: #include "config.h"
45:
1.2 ! millert 46: #include <sys/types.h>
! 47: #include <sys/socket.h>
! 48: #include <sys/param.h>
! 49: #include <sys/time.h>
! 50: #include <sys/ioctl.h>
! 51: #if defined(HAVE_SYS_SOCKIO_H) && !defined(SIOCGIFCONF)
! 52: # include <sys/sockio.h>
! 53: #endif
1.1 millert 54: #include <stdio.h>
55: #ifdef STDC_HEADERS
1.2 ! millert 56: # include <stdlib.h>
! 57: # include <stddef.h>
! 58: #else
! 59: # ifdef HAVE_STDLIB_H
! 60: # include <stdlib.h>
! 61: # endif
1.1 millert 62: #endif /* STDC_HEADERS */
1.2 ! millert 63: #ifdef HAVE_STRING_H
! 64: # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
! 65: # include <memory.h>
! 66: # endif
! 67: # include <string.h>
! 68: #else
! 69: # ifdef HAVE_STRINGS_H
! 70: # include <strings.h>
! 71: # endif
! 72: #endif /* HAVE_STRING_H */
1.1 millert 73: #ifdef HAVE_UNISTD_H
1.2 ! millert 74: # include <unistd.h>
1.1 millert 75: #endif /* HAVE_UNISTD_H */
76: #include <netdb.h>
77: #include <errno.h>
78: #ifdef _ISC
1.2 ! millert 79: # include <sys/stream.h>
! 80: # include <sys/sioctl.h>
! 81: # include <sys/stropts.h>
! 82: # include <net/errno.h>
! 83: # define STRSET(cmd, param, len) {strioctl.ic_cmd=(cmd);\
1.1 millert 84: strioctl.ic_dp=(param);\
85: strioctl.ic_timout=0;\
86: strioctl.ic_len=(len);}
87: #endif /* _ISC */
88: #ifdef _MIPS
1.2 ! millert 89: # include <net/soioctl.h>
1.1 millert 90: #endif /* _MIPS */
91: #include <netinet/in.h>
92: #include <arpa/inet.h>
93: #include <net/if.h>
1.2 ! millert 94: #ifdef HAVE_GETIFADDRS
! 95: # include <ifaddrs.h>
! 96: #endif
1.1 millert 97:
98: #include "sudo.h"
99: #include "interfaces.h"
100:
101: #ifndef lint
1.2 ! millert 102: static const char rcsid[] = "$Sudo: interfaces.c,v 1.62 2001/12/14 22:12:39 millert Exp $";
1.1 millert 103: #endif /* lint */
104:
105:
1.2 ! millert 106: #ifdef HAVE_GETIFADDRS
! 107:
! 108: /*
! 109: * Allocate and fill in the interfaces global variable with the
! 110: * machine's ip addresses and netmasks.
! 111: */
! 112: void
! 113: load_interfaces()
! 114: {
! 115: struct ifaddrs *ifa, *ifaddrs;
! 116: /* XXX - sockaddr_in6 sin6; */
! 117: struct sockaddr_in *sin;
! 118: int i;
! 119:
! 120: if (getifaddrs(&ifaddrs))
! 121: return;
! 122:
! 123: /* Allocate space for the interfaces list. */
! 124: for (ifa = ifaddrs; ifa -> ifa_next; ifa = ifa -> ifa_next) {
! 125: /* Skip interfaces marked "down" and "loopback". */
! 126: if (ifa->ifa_addr == NULL || !(ifa->ifa_flags & IFF_UP) ||
! 127: (ifa->ifa_flags & IFF_LOOPBACK))
! 128: continue;
! 129:
! 130: switch(ifa->ifa_addr->sa_family) {
! 131: /* XXX - AF_INET6 */
! 132: case AF_INET:
! 133: num_interfaces++;
! 134: break;
! 135: }
! 136: }
! 137: interfaces =
! 138: (struct interface *) emalloc(sizeof(struct interface) * num_interfaces);
! 139:
! 140: /* Store the ip addr / netmask pairs. */
! 141: for (ifa = ifaddrs, i = 0; ifa -> ifa_next; ifa = ifa -> ifa_next) {
! 142: /* Skip interfaces marked "down" and "loopback". */
! 143: if (ifa->ifa_addr == NULL || !(ifa->ifa_flags & IFF_UP) ||
! 144: (ifa->ifa_flags & IFF_LOOPBACK))
! 145: continue;
! 146:
! 147: switch(ifa->ifa_addr->sa_family) {
! 148: /* XXX - AF_INET6 */
! 149: case AF_INET:
! 150: sin = (struct sockaddr_in *)ifa->ifa_addr;
! 151: memcpy(&interfaces[i].addr, &sin->sin_addr,
! 152: sizeof(struct in_addr));
! 153: sin = (struct sockaddr_in *)ifa->ifa_netmask;
! 154: memcpy(&interfaces[i].netmask, &sin->sin_addr,
! 155: sizeof(struct in_addr));
! 156: i++;
! 157: break;
! 158: }
! 159: }
! 160: freeifaddrs(ifaddrs);
! 161: }
! 162:
! 163: #elif defined(SIOCGIFCONF) && !defined(STUB_LOAD_INTERFACES)
! 164:
1.1 millert 165: /*
166: * Allocate and fill in the interfaces global variable with the
167: * machine's ip addresses and netmasks.
168: */
169: void
170: load_interfaces()
171: {
172: struct ifconf *ifconf;
173: struct ifreq *ifr, ifr_tmp;
174: struct sockaddr_in *sin;
175: int sock, n, i;
176: size_t len = sizeof(struct ifconf) + BUFSIZ;
177: char *previfname = "", *ifconf_buf = NULL;
178: #ifdef _ISC
179: struct strioctl strioctl;
180: #endif /* _ISC */
181:
182: sock = socket(AF_INET, SOCK_DGRAM, 0);
183: if (sock < 0) {
184: (void) fprintf(stderr, "%s: cannot open socket: %s\n",
185: Argv[0], strerror(errno));
186: exit(1);
187: }
188:
189: /*
190: * Get interface configuration or return (leaving num_interfaces 0)
191: */
192: for (;;) {
193: ifconf_buf = erealloc(ifconf_buf, len);
194: ifconf = (struct ifconf *) ifconf_buf;
195: ifconf->ifc_len = len - sizeof(struct ifconf);
196: ifconf->ifc_buf = (caddr_t) (ifconf_buf + sizeof(struct ifconf));
197:
198: /* Networking may not be installed in kernel... */
199: #ifdef _ISC
200: STRSET(SIOCGIFCONF, (caddr_t) ifconf, len);
201: if (ioctl(sock, I_STR, (caddr_t) &strioctl) < 0) {
202: #else
203: if (ioctl(sock, SIOCGIFCONF, (caddr_t) ifconf) < 0) {
204: #endif /* _ISC */
205: free(ifconf_buf);
206: (void) close(sock);
207: return;
208: }
209:
210: /* Break out of loop if we have a big enough buffer. */
211: if (ifconf->ifc_len + sizeof(struct ifreq) < len)
212: break;
213: len += BUFSIZ;
214: }
215:
216: /* Allocate space for the maximum number of interfaces that could exist. */
217: n = ifconf->ifc_len / sizeof(struct ifreq);
218: interfaces = (struct interface *) emalloc(sizeof(struct interface) * n);
219:
220: /* For each interface, store the ip address and netmask. */
221: for (i = 0; i < ifconf->ifc_len; ) {
222: /* Get a pointer to the current interface. */
223: ifr = (struct ifreq *) &ifconf->ifc_buf[i];
224:
225: /* Set i to the subscript of the next interface. */
226: i += sizeof(struct ifreq);
227: #ifdef HAVE_SA_LEN
228: if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_addr))
229: i += ifr->ifr_addr.sa_len - sizeof(struct sockaddr);
230: #endif /* HAVE_SA_LEN */
231:
232: /* Skip duplicates and interfaces with NULL addresses. */
233: sin = (struct sockaddr_in *) &ifr->ifr_addr;
234: if (sin->sin_addr.s_addr == 0 ||
235: strncmp(previfname, ifr->ifr_name, sizeof(ifr->ifr_name) - 1) == 0)
236: continue;
237:
238: if (ifr->ifr_addr.sa_family != AF_INET)
239: continue;
240:
241: #ifdef SIOCGIFFLAGS
242: memset(&ifr_tmp, 0, sizeof(ifr_tmp));
243: strncpy(ifr_tmp.ifr_name, ifr->ifr_name, sizeof(ifr_tmp.ifr_name) - 1);
244: if (ioctl(sock, SIOCGIFFLAGS, (caddr_t) &ifr_tmp) < 0)
245: #endif
246: ifr_tmp = *ifr;
247:
248: /* Skip interfaces marked "down" and "loopback". */
249: if (!(ifr_tmp.ifr_flags & IFF_UP) || (ifr_tmp.ifr_flags & IFF_LOOPBACK))
250: continue;
251:
252: sin = (struct sockaddr_in *) &ifr->ifr_addr;
253: interfaces[num_interfaces].addr.s_addr = sin->sin_addr.s_addr;
254:
255: /* Stash the name of the interface we saved. */
256: previfname = ifr->ifr_name;
257:
258: /* Get the netmask. */
259: (void) memset(&ifr_tmp, 0, sizeof(ifr_tmp));
260: strncpy(ifr_tmp.ifr_name, ifr->ifr_name, sizeof(ifr_tmp.ifr_name) - 1);
261: #ifdef SIOCGIFNETMASK
262: #ifdef _ISC
263: STRSET(SIOCGIFNETMASK, (caddr_t) &ifr_tmp, sizeof(ifr_tmp));
264: if (ioctl(sock, I_STR, (caddr_t) &strioctl) == 0) {
265: #else
266: if (ioctl(sock, SIOCGIFNETMASK, (caddr_t) &ifr_tmp) == 0) {
267: #endif /* _ISC */
268: sin = (struct sockaddr_in *) &ifr_tmp.ifr_addr;
269:
270: interfaces[num_interfaces].netmask.s_addr = sin->sin_addr.s_addr;
271: } else {
272: #else
273: {
274: #endif /* SIOCGIFNETMASK */
275: if (IN_CLASSC(interfaces[num_interfaces].addr.s_addr))
276: interfaces[num_interfaces].netmask.s_addr = htonl(IN_CLASSC_NET);
277: else if (IN_CLASSB(interfaces[num_interfaces].addr.s_addr))
278: interfaces[num_interfaces].netmask.s_addr = htonl(IN_CLASSB_NET);
279: else
280: interfaces[num_interfaces].netmask.s_addr = htonl(IN_CLASSA_NET);
281: }
282:
283: /* Only now can we be sure it was a good/interesting interface. */
284: num_interfaces++;
285: }
286:
287: /* If the expected size < real size, realloc the array. */
288: if (n != num_interfaces) {
289: if (num_interfaces != 0)
290: interfaces = (struct interface *) erealloc(interfaces,
291: sizeof(struct interface) * num_interfaces);
292: else
293: free(interfaces);
294: }
295: free(ifconf_buf);
296: (void) close(sock);
297: }
298:
299: #else /* !SIOCGIFCONF || STUB_LOAD_INTERFACES */
300:
301: /*
302: * Stub function for those without SIOCGIFCONF
303: */
304: void
305: load_interfaces()
306: {
307: return;
308: }
309:
310: #endif /* SIOCGIFCONF && !STUB_LOAD_INTERFACES */
1.2 ! millert 311:
! 312: void
! 313: dump_interfaces()
! 314: {
! 315: int i;
! 316:
! 317: puts("Local IP address and netmask pairs:");
! 318: for (i = 0; i < num_interfaces; i++)
! 319: printf("\t%s / 0x%x\n", inet_ntoa(interfaces[i].addr),
! 320: ntohl(interfaces[i].netmask.s_addr));
! 321: }