Annotation of embedaddon/sudo/src/net_ifs.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (c) 1996, 1998-2005, 2007-2010
! 3: * Todd C. Miller <Todd.Miller@courtesan.com>
! 4: *
! 5: * Permission to use, copy, modify, and distribute this software for any
! 6: * purpose with or without fee is hereby granted, provided that the above
! 7: * copyright notice and this permission notice appear in all copies.
! 8: *
! 9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 16: *
! 17: * Sponsored in part by the Defense Advanced Research Projects
! 18: * Agency (DARPA) and Air Force Research Laboratory, Air Force
! 19: * Materiel Command, USAF, under agreement number F39502-99-1-0512.
! 20: */
! 21:
! 22: /*
! 23: * Suppress a warning w/ gcc on Digital UN*X.
! 24: * The system headers should really do this....
! 25: */
! 26: #if defined(__osf__) && !defined(__cplusplus)
! 27: struct mbuf;
! 28: struct rtentry;
! 29: #endif
! 30:
! 31: #include <config.h>
! 32:
! 33: #include <sys/types.h>
! 34: #include <sys/socket.h>
! 35: #include <sys/param.h>
! 36: #include <sys/time.h>
! 37: #include <sys/ioctl.h>
! 38: #if defined(HAVE_SYS_SOCKIO_H) && !defined(SIOCGIFCONF)
! 39: # include <sys/sockio.h>
! 40: #endif
! 41: #include <stdio.h>
! 42: #ifdef STDC_HEADERS
! 43: # include <stdlib.h>
! 44: # include <stddef.h>
! 45: #else
! 46: # ifdef HAVE_STDLIB_H
! 47: # include <stdlib.h>
! 48: # endif
! 49: #endif /* STDC_HEADERS */
! 50: #ifdef HAVE_STRING_H
! 51: # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
! 52: # include <memory.h>
! 53: # endif
! 54: # include <string.h>
! 55: #endif /* HAVE_STRING_H */
! 56: #ifdef HAVE_STRINGS_H
! 57: # include <strings.h>
! 58: #endif /* HAVE_STRINGS_H */
! 59: #ifdef HAVE_UNISTD_H
! 60: # include <unistd.h>
! 61: #endif /* HAVE_UNISTD_H */
! 62: #include <netdb.h>
! 63: #include <errno.h>
! 64: #ifdef _ISC
! 65: # include <sys/stream.h>
! 66: # include <sys/sioctl.h>
! 67: # include <sys/stropts.h>
! 68: # define STRSET(cmd, param, len) {strioctl.ic_cmd=(cmd);\
! 69: strioctl.ic_dp=(param);\
! 70: strioctl.ic_timout=0;\
! 71: strioctl.ic_len=(len);}
! 72: #endif /* _ISC */
! 73: #ifdef _MIPS
! 74: # include <net/soioctl.h>
! 75: #endif /* _MIPS */
! 76: #include <netinet/in.h>
! 77: #include <arpa/inet.h>
! 78: #include <net/if.h>
! 79: #ifdef HAVE_GETIFADDRS
! 80: # include <ifaddrs.h>
! 81: #endif
! 82:
! 83: #include "missing.h"
! 84: #include "alloc.h"
! 85: #include "error.h"
! 86:
! 87: #define DEFAULT_TEXT_DOMAIN "sudo"
! 88: #include "gettext.h"
! 89:
! 90: /* Minix apparently lacks IFF_LOOPBACK */
! 91: #ifndef IFF_LOOPBACK
! 92: # define IFF_LOOPBACK 0
! 93: #endif
! 94:
! 95: #ifndef INET6_ADDRSTRLEN
! 96: # define INET6_ADDRSTRLEN 46
! 97: #endif
! 98:
! 99: #ifdef HAVE_GETIFADDRS
! 100:
! 101: /*
! 102: * Fill in the interfaces string with the machine's ip addresses and netmasks
! 103: * and return the number of interfaces found.
! 104: */
! 105: int
! 106: get_net_ifs(char **addrinfo)
! 107: {
! 108: struct ifaddrs *ifa, *ifaddrs;
! 109: struct sockaddr_in *sin;
! 110: #ifdef HAVE_IN6_ADDR
! 111: struct sockaddr_in6 *sin6;
! 112: char addrbuf[INET6_ADDRSTRLEN];
! 113: #endif
! 114: int ailen, i, len, num_interfaces = 0;
! 115: char *cp;
! 116:
! 117: if (getifaddrs(&ifaddrs))
! 118: return 0;
! 119:
! 120: /* Allocate space for the interfaces info string. */
! 121: for (ifa = ifaddrs; ifa != NULL; ifa = ifa -> ifa_next) {
! 122: /* Skip interfaces marked "down" and "loopback". */
! 123: if (ifa->ifa_addr == NULL || ifa->ifa_netmask == NULL ||
! 124: !ISSET(ifa->ifa_flags, IFF_UP) || ISSET(ifa->ifa_flags, IFF_LOOPBACK))
! 125: continue;
! 126:
! 127: switch (ifa->ifa_addr->sa_family) {
! 128: case AF_INET:
! 129: #ifdef HAVE_IN6_ADDR
! 130: case AF_INET6:
! 131: #endif
! 132: num_interfaces++;
! 133: break;
! 134: }
! 135: }
! 136: if (num_interfaces == 0)
! 137: return 0;
! 138: ailen = num_interfaces * 2 * INET6_ADDRSTRLEN;
! 139: *addrinfo = cp = emalloc(ailen);
! 140:
! 141: /* Store the IP addr/netmask pairs. */
! 142: for (ifa = ifaddrs, i = 0; ifa != NULL; ifa = ifa -> ifa_next) {
! 143: /* Skip interfaces marked "down" and "loopback". */
! 144: if (ifa->ifa_addr == NULL || ifa->ifa_netmask == NULL ||
! 145: !ISSET(ifa->ifa_flags, IFF_UP) || ISSET(ifa->ifa_flags, IFF_LOOPBACK))
! 146: continue;
! 147:
! 148: switch (ifa->ifa_addr->sa_family) {
! 149: case AF_INET:
! 150: sin = (struct sockaddr_in *)ifa->ifa_addr;
! 151: len = snprintf(cp, ailen - (*addrinfo - cp),
! 152: "%s%s/", cp == *addrinfo ? "" : " ",
! 153: inet_ntoa(sin->sin_addr));
! 154: if (len <= 0 || len >= ailen - (*addrinfo - cp)) {
! 155: warningx(_("load_interfaces: overflow detected"));
! 156: goto done;
! 157: }
! 158: cp += len;
! 159:
! 160: sin = (struct sockaddr_in *)ifa->ifa_netmask;
! 161: len = snprintf(cp, ailen - (*addrinfo - cp),
! 162: "%s", inet_ntoa(sin->sin_addr));
! 163: if (len <= 0 || len >= ailen - (*addrinfo - cp)) {
! 164: warningx(_("load_interfaces: overflow detected"));
! 165: goto done;
! 166: }
! 167: cp += len;
! 168: break;
! 169: #ifdef HAVE_IN6_ADDR
! 170: case AF_INET6:
! 171: sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
! 172: inet_ntop(AF_INET6, &sin6->sin6_addr, addrbuf, sizeof(addrbuf));
! 173: len = snprintf(cp, ailen - (*addrinfo - cp),
! 174: "%s%s/", cp == *addrinfo ? "" : " ", addrbuf);
! 175: if (len <= 0 || len >= ailen - (*addrinfo - cp)) {
! 176: warningx(_("load_interfaces: overflow detected"));
! 177: goto done;
! 178: }
! 179: cp += len;
! 180:
! 181: sin6 = (struct sockaddr_in6 *)ifa->ifa_netmask;
! 182: inet_ntop(AF_INET6, &sin6->sin6_addr, addrbuf, sizeof(addrbuf));
! 183: len = snprintf(cp, ailen - (*addrinfo - cp), "%s", addrbuf);
! 184: if (len <= 0 || len >= ailen - (*addrinfo - cp)) {
! 185: warningx(_("load_interfaces: overflow detected"));
! 186: goto done;
! 187: }
! 188: cp += len;
! 189: break;
! 190: #endif /* HAVE_IN6_ADDR */
! 191: }
! 192: }
! 193:
! 194: done:
! 195: #ifdef HAVE_FREEIFADDRS
! 196: freeifaddrs(ifaddrs);
! 197: #else
! 198: efree(ifaddrs);
! 199: #endif
! 200: return num_interfaces;
! 201: }
! 202:
! 203: #elif defined(SIOCGIFCONF) && !defined(STUB_LOAD_INTERFACES)
! 204:
! 205: /*
! 206: * Allocate and fill in the interfaces global variable with the
! 207: * machine's ip addresses and netmasks.
! 208: */
! 209: int
! 210: get_net_ifs(char **addrinfo)
! 211: {
! 212: struct ifconf *ifconf;
! 213: struct ifreq *ifr, ifr_tmp;
! 214: struct sockaddr_in *sin;
! 215: int ailen, i, len, n, sock, num_interfaces = 0;
! 216: size_t buflen = sizeof(struct ifconf) + BUFSIZ;
! 217: char *cp, *previfname = "", *ifconf_buf = NULL;
! 218: #ifdef _ISC
! 219: struct strioctl strioctl;
! 220: #endif /* _ISC */
! 221:
! 222: sock = socket(AF_INET, SOCK_DGRAM, 0);
! 223: if (sock < 0)
! 224: error(1, _("unable to open socket"));
! 225:
! 226: /*
! 227: * Get interface configuration or return.
! 228: */
! 229: for (;;) {
! 230: ifconf_buf = emalloc(buflen);
! 231: ifconf = (struct ifconf *) ifconf_buf;
! 232: ifconf->ifc_len = buflen - sizeof(struct ifconf);
! 233: ifconf->ifc_buf = (caddr_t) (ifconf_buf + sizeof(struct ifconf));
! 234:
! 235: #ifdef _ISC
! 236: STRSET(SIOCGIFCONF, (caddr_t) ifconf, buflen);
! 237: if (ioctl(sock, I_STR, (caddr_t) &strioctl) < 0)
! 238: #else
! 239: /* Note that some kernels return EINVAL if the buffer is too small */
! 240: if (ioctl(sock, SIOCGIFCONF, (caddr_t) ifconf) < 0 && errno != EINVAL)
! 241: #endif /* _ISC */
! 242: goto done;
! 243:
! 244: /* Break out of loop if we have a big enough buffer. */
! 245: if (ifconf->ifc_len + sizeof(struct ifreq) < buflen)
! 246: break;
! 247: buflen += BUFSIZ;
! 248: efree(ifconf_buf);
! 249: }
! 250:
! 251: /* Allocate space for the maximum number of interfaces that could exist. */
! 252: if ((n = ifconf->ifc_len / sizeof(struct ifreq)) == 0)
! 253: return 0;
! 254: ailen = n * 2 * INET6_ADDRSTRLEN;
! 255: *addrinfo = cp = emalloc(ailen);
! 256:
! 257: /* For each interface, store the ip address and netmask. */
! 258: for (i = 0; i < ifconf->ifc_len; ) {
! 259: /* Get a pointer to the current interface. */
! 260: ifr = (struct ifreq *) &ifconf->ifc_buf[i];
! 261:
! 262: /* Set i to the subscript of the next interface. */
! 263: i += sizeof(struct ifreq);
! 264: #ifdef HAVE_SA_LEN
! 265: if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_addr))
! 266: i += ifr->ifr_addr.sa_len - sizeof(struct sockaddr);
! 267: #endif /* HAVE_SA_LEN */
! 268:
! 269: /* Skip duplicates and interfaces with NULL addresses. */
! 270: sin = (struct sockaddr_in *) &ifr->ifr_addr;
! 271: if (sin->sin_addr.s_addr == 0 ||
! 272: strncmp(previfname, ifr->ifr_name, sizeof(ifr->ifr_name) - 1) == 0)
! 273: continue;
! 274:
! 275: if (ifr->ifr_addr.sa_family != AF_INET)
! 276: continue;
! 277:
! 278: #ifdef SIOCGIFFLAGS
! 279: memset(&ifr_tmp, 0, sizeof(ifr_tmp));
! 280: strncpy(ifr_tmp.ifr_name, ifr->ifr_name, sizeof(ifr_tmp.ifr_name) - 1);
! 281: if (ioctl(sock, SIOCGIFFLAGS, (caddr_t) &ifr_tmp) < 0)
! 282: #endif
! 283: ifr_tmp = *ifr;
! 284:
! 285: /* Skip interfaces marked "down" and "loopback". */
! 286: if (!ISSET(ifr_tmp.ifr_flags, IFF_UP) ||
! 287: ISSET(ifr_tmp.ifr_flags, IFF_LOOPBACK))
! 288: continue;
! 289:
! 290: sin = (struct sockaddr_in *) &ifr->ifr_addr;
! 291: len = snprintf(cp, ailen - (*addrinfo - cp),
! 292: "%s%s/", cp == *addrinfo ? "" : " ",
! 293: inet_ntoa(sin->sin_addr));
! 294: if (len <= 0 || len >= ailen - (*addrinfo - cp)) {
! 295: warningx(_("load_interfaces: overflow detected"));
! 296: goto done;
! 297: }
! 298: cp += len;
! 299:
! 300: /* Stash the name of the interface we saved. */
! 301: previfname = ifr->ifr_name;
! 302:
! 303: /* Get the netmask. */
! 304: memset(&ifr_tmp, 0, sizeof(ifr_tmp));
! 305: strncpy(ifr_tmp.ifr_name, ifr->ifr_name, sizeof(ifr_tmp.ifr_name) - 1);
! 306: #ifdef _ISC
! 307: STRSET(SIOCGIFNETMASK, (caddr_t) &ifr_tmp, sizeof(ifr_tmp));
! 308: if (ioctl(sock, I_STR, (caddr_t) &strioctl) < 0) {
! 309: #else
! 310: if (ioctl(sock, SIOCGIFNETMASK, (caddr_t) &ifr_tmp) < 0) {
! 311: #endif /* _ISC */
! 312: sin = (struct sockaddr_in *) &ifr_tmp.ifr_addr;
! 313: sin->sin_addr.s_addr = htonl(IN_CLASSC_NET);
! 314: }
! 315: sin = (struct sockaddr_in *) &ifr_tmp.ifr_addr;
! 316: len = snprintf(cp, ailen - (*addrinfo - cp),
! 317: "%s", inet_ntoa(sin->sin_addr));
! 318: if (len <= 0 || len >= ailen - (*addrinfo - cp)) {
! 319: warningx(_("load_interfaces: overflow detected"));
! 320: goto done;
! 321: }
! 322: cp += len;
! 323: num_interfaces++;
! 324: }
! 325:
! 326: done:
! 327: efree(ifconf_buf);
! 328: (void) close(sock);
! 329:
! 330: return num_interfaces;
! 331: }
! 332:
! 333: #else /* !SIOCGIFCONF || STUB_LOAD_INTERFACES */
! 334:
! 335: /*
! 336: * Stub function for those without SIOCGIFCONF or getifaddrs()
! 337: */
! 338: int
! 339: get_net_ifs(char **addrinfo)
! 340: {
! 341: return 0;
! 342: }
! 343:
! 344: #endif /* SIOCGIFCONF && !STUB_LOAD_INTERFACES */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>