diff --git a/sbin/ifconfig/af_atalk.c b/sbin/ifconfig/af_atalk.c index 0ceb8b92b318..9accc75fdc19 100644 --- a/sbin/ifconfig/af_atalk.c +++ b/sbin/ifconfig/af_atalk.c @@ -1,184 +1,182 @@ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include -#include /* for RTX_IFA */ #include #include #include #include #include #include +#include #include #include "ifconfig.h" static struct netrange at_nr; /* AppleTalk net range */ static struct ifaliasreq at_addreq; /* XXX FIXME -- should use strtoul for better parsing. */ static void setatrange(const char *range, int dummy __unused, int s, const struct afswtch *afp) { u_int first = 123, last = 123; if (sscanf(range, "%u-%u", &first, &last) != 2 || first == 0 || first > 0xffff || last == 0 || last > 0xffff || first > last) errx(1, "%s: illegal net range: %u-%u", range, first, last); at_nr.nr_firstnet = htons(first); at_nr.nr_lastnet = htons(last); } static void setatphase(const char *phase, int dummy __unused, int s, const struct afswtch *afp) { if (!strcmp(phase, "1")) at_nr.nr_phase = 1; else if (!strcmp(phase, "2")) at_nr.nr_phase = 2; else errx(1, "%s: illegal phase", phase); } static void -at_status(int s __unused, const struct rt_addrinfo * info) +at_status(int s __unused, const struct ifaddrs *ifa) { struct sockaddr_at *sat, null_sat; struct netrange *nr; memset(&null_sat, 0, sizeof(null_sat)); - sat = (struct sockaddr_at *)info->rti_info[RTAX_IFA]; + sat = (struct sockaddr_at *)ifa->ifa_addr; if (sat == NULL) return; nr = &sat->sat_range.r_netrange; printf("\tatalk %d.%d range %d-%d phase %d", ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase); - if (flags & IFF_POINTOPOINT) { - /* note RTAX_BRD overlap with IFF_BROADCAST */ - sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD]; - if (!sat) + if (ifa->ifa_flags & IFF_POINTOPOINT) { + sat = (struct sockaddr_at *)ifa->ifa_dstaddr; + if (sat == NULL) sat = &null_sat; printf("--> %d.%d", ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node); } - if (flags & IFF_BROADCAST) { - /* note RTAX_BRD overlap with IFF_POINTOPOINT */ - sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD]; - if (sat) + if (ifa->ifa_flags & IFF_BROADCAST) { + sat = (struct sockaddr_at *)ifa->ifa_broadaddr; + if (sat != NULL) printf(" broadcast %d.%d", ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node); } putchar('\n'); } static void at_getaddr(const char *addr, int which) { struct sockaddr_at *sat = (struct sockaddr_at *) &at_addreq.ifra_addr; u_int net, node; sat->sat_family = AF_APPLETALK; sat->sat_len = sizeof(*sat); if (which == MASK) errx(1, "AppleTalk does not use netmasks"); if (sscanf(addr, "%u.%u", &net, &node) != 2 || net > 0xffff || node > 0xfe) errx(1, "%s: illegal address", addr); sat->sat_addr.s_net = htons(net); sat->sat_addr.s_node = node; } static void at_postproc(int s, const struct afswtch *afp) { struct sockaddr_at *sat = (struct sockaddr_at *) &at_addreq.ifra_addr; if (at_nr.nr_phase == 0) at_nr.nr_phase = 2; /* Default phase 2 */ if (at_nr.nr_firstnet == 0) at_nr.nr_firstnet = /* Default range of one */ at_nr.nr_lastnet = sat->sat_addr.s_net; printf("\tatalk %d.%d range %d-%d phase %d\n", ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet), at_nr.nr_phase); if ((u_short) ntohs(at_nr.nr_firstnet) > (u_short) ntohs(sat->sat_addr.s_net) || (u_short) ntohs(at_nr.nr_lastnet) < (u_short) ntohs(sat->sat_addr.s_net)) errx(1, "AppleTalk address is not in range"); sat->sat_range.r_netrange = at_nr; } static struct cmd atalk_cmds[] = { DEF_CMD_ARG("range", setatrange), DEF_CMD_ARG("phase", setatphase), }; static struct afswtch af_atalk = { .af_name = "atalk", .af_af = AF_APPLETALK, .af_status = at_status, .af_getaddr = at_getaddr, .af_postproc = at_postproc, .af_difaddr = SIOCDIFADDR, .af_aifaddr = SIOCAIFADDR, .af_ridreq = &at_addreq, .af_addreq = &at_addreq, }; static __constructor void atalk_ctor(void) { #define N(a) (sizeof(a) / sizeof(a[0])) int i; for (i = 0; i < N(atalk_cmds); i++) cmd_register(&atalk_cmds[i]); af_register(&af_atalk); #undef N } diff --git a/sbin/ifconfig/af_inet.c b/sbin/ifconfig/af_inet.c index 7678daa1aa97..1720b1981d87 100644 --- a/sbin/ifconfig/af_inet.c +++ b/sbin/ifconfig/af_inet.c @@ -1,202 +1,200 @@ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include -#include /* for RTX_IFA */ #include #include #include #include #include +#include #include #include /* for struct ifaddr */ #include #include #include #include "ifconfig.h" static struct ifaliasreq in_addreq; static struct ifreq in_ridreq; static void -in_status(int s __unused, const struct rt_addrinfo * info) +in_status(int s __unused, const struct ifaddrs *ifa) { struct sockaddr_in *sin, null_sin; memset(&null_sin, 0, sizeof(null_sin)); - sin = (struct sockaddr_in *)info->rti_info[RTAX_IFA]; + sin = (struct sockaddr_in *)ifa->ifa_addr; if (sin == NULL) return; printf("\tinet %s ", inet_ntoa(sin->sin_addr)); - if (flags & IFF_POINTOPOINT) { - /* note RTAX_BRD overlap with IFF_BROADCAST */ - sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD]; - if (!sin) + if (ifa->ifa_flags & IFF_POINTOPOINT) { + sin = (struct sockaddr_in *)ifa->ifa_dstaddr; + if (sin == NULL) sin = &null_sin; printf("--> %s ", inet_ntoa(sin->sin_addr)); } - sin = (struct sockaddr_in *)info->rti_info[RTAX_NETMASK]; - if (!sin) + sin = (struct sockaddr_in *)ifa->ifa_netmask; + if (sin == NULL) sin = &null_sin; printf("netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr)); - if (flags & IFF_BROADCAST) { - /* note RTAX_BRD overlap with IFF_POINTOPOINT */ - sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD]; - if (sin && sin->sin_addr.s_addr != 0) + if (ifa->ifa_flags & IFF_BROADCAST) { + sin = (struct sockaddr_in *)ifa->ifa_broadaddr; + if (sin != NULL && sin->sin_addr.s_addr != 0) printf("broadcast %s", inet_ntoa(sin->sin_addr)); } putchar('\n'); } #define SIN(x) ((struct sockaddr_in *) &(x)) static struct sockaddr_in *sintab[] = { SIN(in_ridreq.ifr_addr), SIN(in_addreq.ifra_addr), SIN(in_addreq.ifra_mask), SIN(in_addreq.ifra_broadaddr) }; static void in_getaddr(const char *s, int which) { #define MIN(a,b) ((a)<(b)?(a):(b)) struct sockaddr_in *sin = sintab[which]; struct hostent *hp; struct netent *np; sin->sin_len = sizeof(*sin); if (which != MASK) sin->sin_family = AF_INET; if (which == ADDR) { char *p = NULL; if((p = strrchr(s, '/')) != NULL) { /* address is `name/masklen' */ int masklen; int ret; struct sockaddr_in *min = sintab[MASK]; *p = '\0'; ret = sscanf(p+1, "%u", &masklen); if(ret != 1 || (masklen < 0 || masklen > 32)) { *p = '/'; errx(1, "%s: bad value", s); } min->sin_len = sizeof(*min); min->sin_addr.s_addr = htonl(~((1LL << (32 - masklen)) - 1) & 0xffffffff); } } if (inet_aton(s, &sin->sin_addr)) return; if ((hp = gethostbyname(s)) != 0) bcopy(hp->h_addr, (char *)&sin->sin_addr, MIN(hp->h_length, sizeof(sin->sin_addr))); else if ((np = getnetbyname(s)) != 0) sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); else errx(1, "%s: bad value", s); #undef MIN } static void in_status_tunnel(int s) { char src[NI_MAXHOST]; char dst[NI_MAXHOST]; struct ifreq ifr; const struct sockaddr *sa = (const struct sockaddr *) &ifr.ifr_addr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, name, IFNAMSIZ); if (ioctl(s, SIOCGIFPSRCADDR, (caddr_t)&ifr) < 0) return; if (sa->sa_family != AF_INET) return; if (getnameinfo(sa, sa->sa_len, src, sizeof(src), 0, 0, NI_NUMERICHOST) != 0) src[0] = '\0'; if (ioctl(s, SIOCGIFPDSTADDR, (caddr_t)&ifr) < 0) return; if (sa->sa_family != AF_INET) return; if (getnameinfo(sa, sa->sa_len, dst, sizeof(dst), 0, 0, NI_NUMERICHOST) != 0) dst[0] = '\0'; printf("\ttunnel inet %s --> %s\n", src, dst); } static void in_set_tunnel(int s, struct addrinfo *srcres, struct addrinfo *dstres) { struct ifaliasreq addreq; memset(&addreq, 0, sizeof(addreq)); strncpy(addreq.ifra_name, name, IFNAMSIZ); memcpy(&addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len); memcpy(&addreq.ifra_dstaddr, dstres->ai_addr, dstres->ai_addr->sa_len); if (ioctl(s, SIOCSIFPHYADDR, &addreq) < 0) warn("SIOCSIFPHYADDR"); } static struct afswtch af_inet = { .af_name = "inet", .af_af = AF_INET, .af_status = in_status, .af_getaddr = in_getaddr, .af_status_tunnel = in_status_tunnel, .af_settunnel = in_set_tunnel, .af_difaddr = SIOCDIFADDR, .af_aifaddr = SIOCAIFADDR, .af_ridreq = &in_ridreq, .af_addreq = &in_addreq, }; static __constructor void inet_ctor(void) { af_register(&af_inet); } diff --git a/sbin/ifconfig/af_inet6.c b/sbin/ifconfig/af_inet6.c index 2aae38225235..f1871fb4996c 100644 --- a/sbin/ifconfig/af_inet6.c +++ b/sbin/ifconfig/af_inet6.c @@ -1,540 +1,538 @@ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include -#include /* for RTX_IFA */ #include #include #include #include #include #include #include #include #include /* for struct ifaddr */ #include #include #include #include /* Define ND6_INFINITE_LIFETIME */ #include "ifconfig.h" static struct in6_ifreq in6_ridreq; static struct in6_aliasreq in6_addreq = { { 0 }, { 0 }, { 0 }, { 0 }, 0, { 0, 0, ND6_INFINITE_LIFETIME, ND6_INFINITE_LIFETIME } }; static int ip6lifetime; static void in6_fillscopeid(struct sockaddr_in6 *sin6); static int prefix(void *, int); static char *sec2str(time_t); static int explicit_prefix = 0; static char addr_buf[MAXHOSTNAMELEN *2 + 1]; /*for getnameinfo()*/ static void setifprefixlen(const char *addr, int dummy __unused, int s, const struct afswtch *afp) { if (afp->af_getprefix != NULL) afp->af_getprefix(addr, MASK); explicit_prefix = 1; } static void setip6flags(const char *dummyaddr __unused, int flag, int dummysoc __unused, const struct afswtch *afp) { if (afp->af_af != AF_INET6) err(1, "address flags can be set only for inet6 addresses"); if (flag < 0) in6_addreq.ifra_flags &= ~(-flag); else in6_addreq.ifra_flags |= flag; } static void setip6lifetime(const char *cmd, const char *val, int s, const struct afswtch *afp) { time_t newval, t; char *ep; t = time(NULL); newval = (time_t)strtoul(val, &ep, 0); if (val == ep) errx(1, "invalid %s", cmd); if (afp->af_af != AF_INET6) errx(1, "%s not allowed for the AF", cmd); if (strcmp(cmd, "vltime") == 0) { in6_addreq.ifra_lifetime.ia6t_expire = t + newval; in6_addreq.ifra_lifetime.ia6t_vltime = newval; } else if (strcmp(cmd, "pltime") == 0) { in6_addreq.ifra_lifetime.ia6t_preferred = t + newval; in6_addreq.ifra_lifetime.ia6t_pltime = newval; } } static void setip6pltime(const char *seconds, int dummy __unused, int s, const struct afswtch *afp) { setip6lifetime("pltime", seconds, s, afp); } static void setip6vltime(const char *seconds, int dummy __unused, int s, const struct afswtch *afp) { setip6lifetime("vltime", seconds, s, afp); } static void setip6eui64(const char *cmd, int dummy __unused, int s, const struct afswtch *afp) { struct ifaddrs *ifap, *ifa; const struct sockaddr_in6 *sin6 = NULL; const struct in6_addr *lladdr = NULL; struct in6_addr *in6; if (afp->af_af != AF_INET6) errx(EXIT_FAILURE, "%s not allowed for the AF", cmd); in6 = (struct in6_addr *)&in6_addreq.ifra_addr.sin6_addr; if (memcmp(&in6addr_any.s6_addr[8], &in6->s6_addr[8], 8) != 0) errx(EXIT_FAILURE, "interface index is already filled"); if (getifaddrs(&ifap) != 0) err(EXIT_FAILURE, "getifaddrs"); for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family == AF_INET6 && strcmp(ifa->ifa_name, name) == 0) { sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr; if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { lladdr = &sin6->sin6_addr; break; } } } if (!lladdr) errx(EXIT_FAILURE, "could not determine link local address"); memcpy(&in6->s6_addr[8], &lladdr->s6_addr[8], 8); freeifaddrs(ifap); } static void in6_fillscopeid(struct sockaddr_in6 *sin6) { #if defined(__KAME__) && defined(KAME_SCOPEID) if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { sin6->sin6_scope_id = ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0; } #endif } static void -in6_status(int s __unused, const struct rt_addrinfo * info) +in6_status(int s __unused, const struct ifaddrs *ifa) { struct sockaddr_in6 *sin, null_sin; struct in6_ifreq ifr6; int s6; u_int32_t flags6; struct in6_addrlifetime lifetime; time_t t = time(NULL); int error; u_int32_t scopeid; memset(&null_sin, 0, sizeof(null_sin)); - sin = (struct sockaddr_in6 *)info->rti_info[RTAX_IFA]; + sin = (struct sockaddr_in6 *)ifa->ifa_addr; if (sin == NULL) return; strncpy(ifr6.ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name)); if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { warn("socket(AF_INET6,SOCK_DGRAM)"); return; } ifr6.ifr_addr = *sin; if (ioctl(s6, SIOCGIFAFLAG_IN6, &ifr6) < 0) { warn("ioctl(SIOCGIFAFLAG_IN6)"); close(s6); return; } flags6 = ifr6.ifr_ifru.ifru_flags6; memset(&lifetime, 0, sizeof(lifetime)); ifr6.ifr_addr = *sin; if (ioctl(s6, SIOCGIFALIFETIME_IN6, &ifr6) < 0) { warn("ioctl(SIOCGIFALIFETIME_IN6)"); close(s6); return; } lifetime = ifr6.ifr_ifru.ifru_lifetime; close(s6); /* XXX: embedded link local addr check */ if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) { u_short index; index = *(u_short *)&sin->sin6_addr.s6_addr[2]; *(u_short *)&sin->sin6_addr.s6_addr[2] = 0; if (sin->sin6_scope_id == 0) sin->sin6_scope_id = ntohs(index); } scopeid = sin->sin6_scope_id; error = getnameinfo((struct sockaddr *)sin, sin->sin6_len, addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST); if (error != 0) inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, sizeof(addr_buf)); printf("\tinet6 %s ", addr_buf); - if (flags & IFF_POINTOPOINT) { - /* note RTAX_BRD overlap with IFF_BROADCAST */ - sin = (struct sockaddr_in6 *)info->rti_info[RTAX_BRD]; + if (ifa->ifa_flags & IFF_POINTOPOINT) { + sin = (struct sockaddr_in6 *)ifa->ifa_dstaddr; /* * some of the interfaces do not have valid destination * address. */ - if (sin && sin->sin6_family == AF_INET6) { + if (sin != NULL && sin->sin6_family == AF_INET6) { int error; /* XXX: embedded link local addr check */ if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) { u_short index; index = *(u_short *)&sin->sin6_addr.s6_addr[2]; *(u_short *)&sin->sin6_addr.s6_addr[2] = 0; if (sin->sin6_scope_id == 0) sin->sin6_scope_id = ntohs(index); } error = getnameinfo((struct sockaddr *)sin, sin->sin6_len, addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST); if (error != 0) inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, sizeof(addr_buf)); printf("--> %s ", addr_buf); } } - sin = (struct sockaddr_in6 *)info->rti_info[RTAX_NETMASK]; - if (!sin) + sin = (struct sockaddr_in6 *)ifa->ifa_netmask; + if (sin == NULL) sin = &null_sin; printf("prefixlen %d ", prefix(&sin->sin6_addr, sizeof(struct in6_addr))); if ((flags6 & IN6_IFF_ANYCAST) != 0) printf("anycast "); if ((flags6 & IN6_IFF_TENTATIVE) != 0) printf("tentative "); if ((flags6 & IN6_IFF_DUPLICATED) != 0) printf("duplicated "); if ((flags6 & IN6_IFF_DETACHED) != 0) printf("detached "); if ((flags6 & IN6_IFF_DEPRECATED) != 0) printf("deprecated "); if ((flags6 & IN6_IFF_AUTOCONF) != 0) printf("autoconf "); if ((flags6 & IN6_IFF_TEMPORARY) != 0) printf("temporary "); if (scopeid) printf("scopeid 0x%x ", scopeid); if (ip6lifetime && (lifetime.ia6t_preferred || lifetime.ia6t_expire)) { printf("pltime "); if (lifetime.ia6t_preferred) { printf("%s ", lifetime.ia6t_preferred < t ? "0" : sec2str(lifetime.ia6t_preferred - t)); } else printf("infty "); printf("vltime "); if (lifetime.ia6t_expire) { printf("%s ", lifetime.ia6t_expire < t ? "0" : sec2str(lifetime.ia6t_expire - t)); } else printf("infty "); } putchar('\n'); } #define SIN6(x) ((struct sockaddr_in6 *) &(x)) static struct sockaddr_in6 *sin6tab[] = { SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr), SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr) }; static void in6_getprefix(const char *plen, int which) { struct sockaddr_in6 *sin = sin6tab[which]; u_char *cp; int len = atoi(plen); if ((len < 0) || (len > 128)) errx(1, "%s: bad value", plen); sin->sin6_len = sizeof(*sin); if (which != MASK) sin->sin6_family = AF_INET6; if ((len == 0) || (len == 128)) { memset(&sin->sin6_addr, 0xff, sizeof(struct in6_addr)); return; } memset((void *)&sin->sin6_addr, 0x00, sizeof(sin->sin6_addr)); for (cp = (u_char *)&sin->sin6_addr; len > 7; len -= 8) *cp++ = 0xff; *cp = 0xff << (8 - len); } static void in6_getaddr(const char *s, int which) { struct sockaddr_in6 *sin = sin6tab[which]; struct addrinfo hints, *res; int error = -1; newaddr &= 1; sin->sin6_len = sizeof(*sin); if (which != MASK) sin->sin6_family = AF_INET6; if (which == ADDR) { char *p = NULL; if((p = strrchr(s, '/')) != NULL) { *p = '\0'; in6_getprefix(p + 1, MASK); explicit_prefix = 1; } } if (sin->sin6_family == AF_INET6) { bzero(&hints, sizeof(struct addrinfo)); hints.ai_family = AF_INET6; error = getaddrinfo(s, NULL, &hints, &res); } if (error != 0) { if (inet_pton(AF_INET6, s, &sin->sin6_addr) != 1) errx(1, "%s: bad value", s); } else bcopy(res->ai_addr, sin, res->ai_addrlen); } static int prefix(void *val, int size) { u_char *name = (u_char *)val; int byte, bit, plen = 0; for (byte = 0; byte < size; byte++, plen += 8) if (name[byte] != 0xff) break; if (byte == size) return (plen); for (bit = 7; bit != 0; bit--, plen++) if (!(name[byte] & (1 << bit))) break; for (; bit != 0; bit--) if (name[byte] & (1 << bit)) return(0); byte++; for (; byte < size; byte++) if (name[byte]) return(0); return (plen); } static char * sec2str(time_t total) { static char result[256]; int days, hours, mins, secs; int first = 1; char *p = result; if (0) { days = total / 3600 / 24; hours = (total / 3600) % 24; mins = (total / 60) % 60; secs = total % 60; if (days) { first = 0; p += sprintf(p, "%dd", days); } if (!first || hours) { first = 0; p += sprintf(p, "%dh", hours); } if (!first || mins) { first = 0; p += sprintf(p, "%dm", mins); } sprintf(p, "%ds", secs); } else sprintf(result, "%lu", (unsigned long)total); return(result); } static void in6_postproc(int s, const struct afswtch *afp) { if (explicit_prefix == 0) { /* Aggregatable address architecture defines all prefixes are 64. So, it is convenient to set prefixlen to 64 if it is not specified. */ setifprefixlen("64", 0, s, afp); /* in6_getprefix("64", MASK) if MASK is available here... */ } } static void in6_status_tunnel(int s) { char src[NI_MAXHOST]; char dst[NI_MAXHOST]; struct in6_ifreq in6_ifr; const struct sockaddr *sa = (const struct sockaddr *) &in6_ifr.ifr_addr; memset(&in6_ifr, 0, sizeof(in6_ifr)); strncpy(in6_ifr.ifr_name, name, IFNAMSIZ); if (ioctl(s, SIOCGIFPSRCADDR_IN6, (caddr_t)&in6_ifr) < 0) return; if (sa->sa_family != AF_INET6) return; in6_fillscopeid(&in6_ifr.ifr_addr); if (getnameinfo(sa, sa->sa_len, src, sizeof(src), 0, 0, NI_NUMERICHOST) != 0) src[0] = '\0'; if (ioctl(s, SIOCGIFPDSTADDR_IN6, (caddr_t)&in6_ifr) < 0) return; if (sa->sa_family != AF_INET6) return; in6_fillscopeid(&in6_ifr.ifr_addr); if (getnameinfo(sa, sa->sa_len, dst, sizeof(dst), 0, 0, NI_NUMERICHOST) != 0) dst[0] = '\0'; printf("\ttunnel inet6 %s --> %s\n", src, dst); } static void in6_set_tunnel(int s, struct addrinfo *srcres, struct addrinfo *dstres) { struct in6_aliasreq in6_addreq; memset(&in6_addreq, 0, sizeof(in6_addreq)); strncpy(in6_addreq.ifra_name, name, IFNAMSIZ); memcpy(&in6_addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len); memcpy(&in6_addreq.ifra_dstaddr, dstres->ai_addr, dstres->ai_addr->sa_len); if (ioctl(s, SIOCSIFPHYADDR_IN6, &in6_addreq) < 0) warn("SIOCSIFPHYADDR_IN6"); } static struct cmd inet6_cmds[] = { DEF_CMD_ARG("prefixlen", setifprefixlen), DEF_CMD("anycast", IN6_IFF_ANYCAST, setip6flags), DEF_CMD("tentative", IN6_IFF_TENTATIVE, setip6flags), DEF_CMD("-tentative", -IN6_IFF_TENTATIVE, setip6flags), DEF_CMD("deprecated", IN6_IFF_DEPRECATED, setip6flags), DEF_CMD("-deprecated", -IN6_IFF_DEPRECATED, setip6flags), DEF_CMD("autoconf", IN6_IFF_AUTOCONF, setip6flags), DEF_CMD("-autoconf", -IN6_IFF_AUTOCONF, setip6flags), DEF_CMD_ARG("pltime", setip6pltime), DEF_CMD_ARG("vltime", setip6vltime), DEF_CMD("eui64", 0, setip6eui64), }; static struct afswtch af_inet6 = { .af_name = "inet6", .af_af = AF_INET6, .af_status = in6_status, .af_getaddr = in6_getaddr, .af_getprefix = in6_getprefix, .af_postproc = in6_postproc, .af_status_tunnel = in6_status_tunnel, .af_settunnel = in6_set_tunnel, .af_difaddr = SIOCDIFADDR_IN6, .af_aifaddr = SIOCAIFADDR_IN6, .af_ridreq = &in6_addreq, .af_addreq = &in6_addreq, }; static void in6_Lopt_cb(const char *optarg __unused) { ip6lifetime++; /* print IPv6 address lifetime */ } static struct option in6_Lopt = { "L", "[-L]", in6_Lopt_cb }; static __constructor void inet6_ctor(void) { #define N(a) (sizeof(a) / sizeof(a[0])) int i; for (i = 0; i < N(inet6_cmds); i++) cmd_register(&inet6_cmds[i]); af_register(&af_inet6); opt_register(&in6_Lopt); #undef N } diff --git a/sbin/ifconfig/af_ipx.c b/sbin/ifconfig/af_ipx.c index d16e2eb86d97..3ed0a9bc5ac0 100644 --- a/sbin/ifconfig/af_ipx.c +++ b/sbin/ifconfig/af_ipx.c @@ -1,128 +1,128 @@ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include -#include #include #include #include #include +#include #include #define IPXIP #define IPTUNNEL #include #include #include "ifconfig.h" static struct ifaliasreq ipx_addreq; static struct ifreq ipx_ridreq; static void -ipx_status(int s __unused, const struct rt_addrinfo * info) +ipx_status(int s __unused, const struct ifaddrs *ifa) { struct sockaddr_ipx *sipx, null_sipx; - sipx = (struct sockaddr_ipx *)info->rti_info[RTAX_IFA]; + sipx = (struct sockaddr_ipx *)ifa->ifa_addr; if (sipx == NULL) return; printf("\tipx %s ", ipx_ntoa(sipx->sipx_addr)); - if (flags & IFF_POINTOPOINT) { - sipx = (struct sockaddr_ipx *)info->rti_info[RTAX_BRD]; - if (!sipx) { + if (ifa->ifa_flags & IFF_POINTOPOINT) { + sipx = (struct sockaddr_ipx *)ifa->ifa_broadaddr; + if (sipx == NULL) { memset(&null_sipx, 0, sizeof(null_sipx)); sipx = &null_sipx; } printf("--> %s ", ipx_ntoa(sipx->sipx_addr)); } putchar('\n'); } #define SIPX(x) ((struct sockaddr_ipx *) &(x)) struct sockaddr_ipx *sipxtab[] = { SIPX(ipx_ridreq.ifr_addr), SIPX(ipx_addreq.ifra_addr), SIPX(ipx_addreq.ifra_mask), SIPX(ipx_addreq.ifra_broadaddr) }; static void ipx_getaddr(const char *addr, int which) { struct sockaddr_ipx *sipx = sipxtab[which]; sipx->sipx_family = AF_IPX; sipx->sipx_len = sizeof(*sipx); sipx->sipx_addr = ipx_addr(addr); if (which == MASK) printf("Attempt to set IPX netmask will be ineffectual\n"); } static void ipx_postproc(int s, const struct afswtch *afp) { if (setipdst) { struct ipxip_req rq; int size = sizeof(rq); rq.rq_ipx = ipx_addreq.ifra_addr; rq.rq_ip = ipx_addreq.ifra_dstaddr; if (setsockopt(s, 0, SO_IPXIP_ROUTE, &rq, size) < 0) Perror("Encapsulation Routing"); } } static struct afswtch af_ipx = { .af_name = "ipx", .af_af = AF_IPX, .af_status = ipx_status, .af_getaddr = ipx_getaddr, .af_postproc = ipx_postproc, .af_difaddr = SIOCDIFADDR, .af_aifaddr = SIOCAIFADDR, .af_ridreq = &ipx_ridreq, .af_addreq = &ipx_addreq, }; static __constructor void ipx_ctor(void) { af_register(&af_ipx); } diff --git a/sbin/ifconfig/af_link.c b/sbin/ifconfig/af_link.c index d61075065f5b..f77515e5115e 100644 --- a/sbin/ifconfig/af_link.c +++ b/sbin/ifconfig/af_link.c @@ -1,127 +1,127 @@ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include -#include /* for RTX_IFA */ #include #include #include #include +#include #include #include #include #include "ifconfig.h" static struct ifreq link_ridreq; static void -link_status(int s __unused, const struct rt_addrinfo *info) +link_status(int s __unused, const struct ifaddrs *ifa) { - const struct sockaddr_dl *sdl = - (const struct sockaddr_dl *) info->rti_info[RTAX_IFA]; + /* XXX no const 'cuz LLADDR is defined wrong */ + struct sockaddr_dl *sdl = (struct sockaddr_dl *) ifa->ifa_addr; if (sdl != NULL && sdl->sdl_alen > 0) { if (sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == ETHER_ADDR_LEN) printf("\tether %s\n", - ether_ntoa((const struct ether_addr *)LLADDR(sdl))); + ether_ntoa((struct ether_addr *)LLADDR(sdl))); else { int n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0; printf("\tlladdr %s\n", link_ntoa(sdl) + n); } } } static void link_getaddr(const char *addr, int which) { char *temp; struct sockaddr_dl sdl; struct sockaddr *sa = &link_ridreq.ifr_addr; if (which != ADDR) errx(1, "can't set link-level netmask or broadcast"); if ((temp = malloc(strlen(addr) + 2)) == NULL) errx(1, "malloc failed"); temp[0] = ':'; strcpy(temp + 1, addr); sdl.sdl_len = sizeof(sdl); link_addr(temp, &sdl); free(temp); if (sdl.sdl_alen > sizeof(sa->sa_data)) errx(1, "malformed link-level address"); sa->sa_family = AF_LINK; sa->sa_len = sdl.sdl_alen; bcopy(LLADDR(&sdl), sa->sa_data, sdl.sdl_alen); } static struct afswtch af_link = { .af_name = "link", .af_af = AF_LINK, .af_status = link_status, .af_getaddr = link_getaddr, .af_aifaddr = SIOCSIFLLADDR, .af_addreq = &link_ridreq, }; static struct afswtch af_ether = { .af_name = "ether", .af_af = AF_LINK, .af_status = link_status, .af_getaddr = link_getaddr, .af_aifaddr = SIOCSIFLLADDR, .af_addreq = &link_ridreq, }; static struct afswtch af_lladdr = { .af_name = "lladdr", .af_af = AF_LINK, .af_status = link_status, .af_getaddr = link_getaddr, .af_aifaddr = SIOCSIFLLADDR, .af_addreq = &link_ridreq, }; static __constructor void link_ctor(void) { af_register(&af_link); af_register(&af_ether); af_register(&af_lladdr); } diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c index 684bf9006828..3860bd5411e9 100644 --- a/sbin/ifconfig/ifconfig.c +++ b/sbin/ifconfig/ifconfig.c @@ -1,1057 +1,985 @@ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* IP */ #include #include #include #include +#include #include #include #include #include #include #include #include #include #include "ifconfig.h" /* * Since "struct ifreq" is composed of various union members, callers * should pay special attention to interprete the value. * (.e.g. little/big endian difference in the structure.) */ struct ifreq ifr; char name[IFNAMSIZ]; -int flags; int setaddr; int setipdst; int setmask; int doalias; int clearaddr; int newaddr = 1; int verbose; int supmedia = 0; int printkeys = 0; /* Print keying material for interfaces. */ static int ifconfig(int argc, char *const *argv, const struct afswtch *afp); -static void status(const struct afswtch *afp, int addrcount, - struct sockaddr_dl *sdl, struct if_msghdr *ifm, - struct ifa_msghdr *ifam); +static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl, + struct ifaddrs *ifa); static void tunnel_status(int s); static void usage(void); static struct afswtch *af_getbyname(const char *name); static struct afswtch *af_getbyfamily(int af); static void af_other_status(int); static struct option *opts = NULL; void opt_register(struct option *p) { p->next = opts; opts = p; } static void usage(void) { char options[1024]; struct option *p; /* XXX not right but close enough for now */ options[0] = '\0'; for (p = opts; p != NULL; p = p->next) { strlcat(options, p->opt_usage, sizeof(options)); strlcat(options, " ", sizeof(options)); } fprintf(stderr, "usage: ifconfig %sinterface address_family [address [dest_address]]\n" " [parameters]\n" " ifconfig interface create\n" " ifconfig -a %s[-d] [-m] [-u] [-v] [address_family]\n" " ifconfig -l [-d] [-u] [address_family]\n" " ifconfig %s[-d] [-m] [-u] [-v]\n", options, options, options); exit(1); } int main(int argc, char *argv[]) { int c, all, namesonly, downonly, uponly; - int need_nl = 0, count = 0; const struct afswtch *afp = NULL; - int addrcount, ifindex; - struct if_msghdr *ifm, *nextifm; - struct ifa_msghdr *ifam; - struct sockaddr_dl *sdl; - char *buf, *lim, *next; - size_t needed; - int mib[6]; - char options[1024]; + int ifindex; + struct ifaddrs *ifap, *ifa; + struct ifreq paifr; + const struct sockaddr_dl *sdl; + char options[1024], *cp; + const char *ifname; struct option *p; all = downonly = uponly = namesonly = verbose = 0; /* Parse leading line options */ strlcpy(options, "adklmuv", sizeof(options)); for (p = opts; p != NULL; p = p->next) strlcat(options, p->opt, sizeof(options)); while ((c = getopt(argc, argv, options)) != -1) { switch (c) { case 'a': /* scan all interfaces */ all++; break; case 'd': /* restrict scan to "down" interfaces */ downonly++; break; case 'k': printkeys++; break; case 'l': /* scan interface names only */ namesonly++; break; case 'm': /* show media choices in status */ supmedia = 1; break; case 'u': /* restrict scan to "up" interfaces */ uponly++; break; case 'v': verbose++; break; default: for (p = opts; p != NULL; p = p->next) if (p->opt[0] == c) { p->cb(optarg); break; } if (p == NULL) usage(); break; } } argc -= optind; argv += optind; /* -l cannot be used with -a or -m */ if (namesonly && (all || supmedia)) usage(); /* nonsense.. */ if (uponly && downonly) usage(); /* no arguments is equivalent to '-a' */ if (!namesonly && argc < 1) all = 1; /* -a and -l allow an address family arg to limit the output */ if (all || namesonly) { if (argc > 1) usage(); + ifname = NULL; ifindex = 0; if (argc == 1) { afp = af_getbyname(*argv); if (afp == NULL) usage(); if (afp->af_name != NULL) argc--, argv++; /* leave with afp non-zero */ } } else { /* not listing, need an argument */ if (argc < 1) usage(); - strncpy(name, *argv, sizeof(name)); + ifname = *argv; argc--, argv++; /* check and maybe load support for this interface */ - ifmaybeload(name); + ifmaybeload(ifname); - ifindex = if_nametoindex(name); + ifindex = if_nametoindex(ifname); if (ifindex == 0) { /* * NOTE: We must special-case the `create' command * right here as we would otherwise fail when trying * to find the interface. */ if (argc > 0 && (strcmp(argv[0], "create") == 0 || strcmp(argv[0], "plumb") == 0)) { ifconfig(argc, argv, NULL); exit(0); } - errx(1, "interface %s does not exist", name); + errx(1, "interface %s does not exist", ifname); } } /* Check for address family */ if (argc > 0) { afp = af_getbyname(*argv); if (afp != NULL) argc--, argv++; } -retry: - mib[0] = CTL_NET; - mib[1] = PF_ROUTE; - mib[2] = 0; - mib[3] = 0; /* address family */ - mib[4] = NET_RT_IFLIST; - mib[5] = ifindex; /* interface index */ - - /* if particular family specified, only ask about it */ - if (afp != NULL) - mib[3] = afp->af_af; - - if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) - errx(1, "iflist-sysctl-estimate"); - if ((buf = malloc(needed)) == NULL) - errx(1, "malloc"); - if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { - if (errno == ENOMEM && count++ < 10) { - warnx("Routing table grew, retrying"); - free(buf); - sleep(1); - goto retry; - } - errx(1, "actual retrieval of interface table"); - } - lim = buf + needed; - - next = buf; - while (next < lim) { - - ifm = (struct if_msghdr *)next; - - if (ifm->ifm_type == RTM_IFINFO) { - if (ifm->ifm_data.ifi_datalen == 0) - ifm->ifm_data.ifi_datalen = sizeof(struct if_data); - sdl = (struct sockaddr_dl *)((char *)ifm + sizeof(struct if_msghdr) - - sizeof(struct if_data) + ifm->ifm_data.ifi_datalen); - flags = ifm->ifm_flags; - } else { - fprintf(stderr, "out of sync parsing NET_RT_IFLIST\n"); - fprintf(stderr, "expected %d, got %d\n", RTM_IFINFO, - ifm->ifm_type); - fprintf(stderr, "msglen = %d\n", ifm->ifm_msglen); - fprintf(stderr, "buf:%p, next:%p, lim:%p\n", buf, next, - lim); - exit (1); + if (getifaddrs(&ifap) != 0) + err(EXIT_FAILURE, "getifaddrs"); + cp = NULL; + ifindex = 0; + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + memset(&paifr, 0, sizeof(paifr)); + strncpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name)); + if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) { + memcpy(&paifr.ifr_addr, ifa->ifa_addr, + ifa->ifa_addr->sa_len); } - next += ifm->ifm_msglen; - ifam = NULL; - addrcount = 0; - while (next < lim) { - - nextifm = (struct if_msghdr *)next; - - if (nextifm->ifm_type != RTM_NEWADDR) - break; - - if (ifam == NULL) - ifam = (struct ifa_msghdr *)nextifm; + if (ifname != NULL && strcmp(ifname, ifa->ifa_name) != 0) + continue; + if (ifa->ifa_addr->sa_family == AF_LINK) + sdl = (const struct sockaddr_dl *) ifa->ifa_addr; + else + sdl = NULL; + if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0) + continue; + if (strlcpy(name, ifa->ifa_name, sizeof(name)) >= sizeof(name)) + continue; + cp = ifa->ifa_name; - addrcount++; - next += nextifm->ifm_msglen; - } - memcpy(name, sdl->sdl_data, - sizeof(name) <= sdl->sdl_nlen ? - sizeof(name)-1 : sdl->sdl_nlen); - name[sizeof(name) <= sdl->sdl_nlen ? - sizeof(name)-1 : sdl->sdl_nlen] = '\0'; - - if (all || namesonly) { - if (uponly) - if ((flags & IFF_UP) == 0) - continue; /* not up */ - if (downonly) - if (flags & IFF_UP) - continue; /* not down */ - if (namesonly) { - if (afp == NULL || afp->af_af != AF_LINK || - sdl->sdl_type == IFT_ETHER) { - if (need_nl) - putchar(' '); - fputs(name, stdout); - need_nl++; - } - continue; - } + if (downonly && (ifa->ifa_flags & IFF_UP) != 0) + continue; + if (uponly && (ifa->ifa_flags & IFF_UP) == 0) + continue; + ifindex++; + /* + * Are we just listing the interfaces? + */ + if (namesonly) { + if (ifindex > 1) + printf(" "); + fputs(name, stdout); + continue; } if (argc > 0) ifconfig(argc, argv, afp); else - status(afp, addrcount, sdl, ifm, ifam); + status(afp, sdl, ifa); } - free(buf); - - if (namesonly && need_nl > 0) - putchar('\n'); + if (namesonly) + printf("\n"); + freeifaddrs(ifap); - exit (0); + exit(0); } static struct afswtch *afs = NULL; void af_register(struct afswtch *p) { p->af_next = afs; afs = p; } static struct afswtch * af_getbyname(const char *name) { struct afswtch *afp; for (afp = afs; afp != NULL; afp = afp->af_next) if (strcmp(afp->af_name, name) == 0) return afp; return NULL; } static struct afswtch * af_getbyfamily(int af) { struct afswtch *afp; for (afp = afs; afp != NULL; afp = afp->af_next) if (afp->af_af == af) return afp; return NULL; } static void af_other_status(int s) { struct afswtch *afp; uint8_t afmask[howmany(AF_MAX, NBBY)]; memset(afmask, 0, sizeof(afmask)); for (afp = afs; afp != NULL; afp = afp->af_next) { if (afp->af_other_status == NULL) continue; if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af)) continue; afp->af_other_status(s); setbit(afmask, afp->af_af); } } static void af_all_tunnel_status(int s) { struct afswtch *afp; uint8_t afmask[howmany(AF_MAX, NBBY)]; memset(afmask, 0, sizeof(afmask)); for (afp = afs; afp != NULL; afp = afp->af_next) { if (afp->af_status_tunnel == NULL) continue; if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af)) continue; afp->af_status_tunnel(s); setbit(afmask, afp->af_af); } } static struct cmd *cmds = NULL; void cmd_register(struct cmd *p) { p->c_next = cmds; cmds = p; } static const struct cmd * cmd_lookup(const char *name) { #define N(a) (sizeof(a)/sizeof(a[0])) const struct cmd *p; for (p = cmds; p != NULL; p = p->c_next) if (strcmp(name, p->c_name) == 0) return p; return NULL; #undef N } struct callback { callback_func *cb_func; void *cb_arg; struct callback *cb_next; }; static struct callback *callbacks = NULL; void callback_register(callback_func *func, void *arg) { struct callback *cb; cb = malloc(sizeof(struct callback)); if (cb == NULL) errx(1, "unable to allocate memory for callback"); cb->cb_func = func; cb->cb_arg = arg; cb->cb_next = callbacks; callbacks = cb; } /* specially-handled commands */ static void setifaddr(const char *, int, int, const struct afswtch *); static const struct cmd setifaddr_cmd = DEF_CMD("ifaddr", 0, setifaddr); static void setifdstaddr(const char *, int, int, const struct afswtch *); static const struct cmd setifdstaddr_cmd = DEF_CMD("ifdstaddr", 0, setifdstaddr); static int ifconfig(int argc, char *const *argv, const struct afswtch *afp) { struct callback *cb; int s; if (afp == NULL) afp = af_getbyname("inet"); ifr.ifr_addr.sa_family = afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ? AF_INET : afp->af_af; strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) err(1, "socket(family %u,SOCK_DGRAM", ifr.ifr_addr.sa_family); while (argc > 0) { const struct cmd *p; p = cmd_lookup(*argv); if (p == NULL) { /* * Not a recognized command, choose between setting * the interface address and the dst address. */ p = (setaddr ? &setifdstaddr_cmd : &setifaddr_cmd); } if (p->c_u.c_func || p->c_u.c_func2) { if (p->c_parameter == NEXTARG) { if (argv[1] == NULL) errx(1, "'%s' requires argument", p->c_name); p->c_u.c_func(argv[1], 0, s, afp); argc--, argv++; } else if (p->c_parameter == OPTARG) { p->c_u.c_func(argv[1], 0, s, afp); if (argv[1] != NULL) argc--, argv++; } else if (p->c_parameter == NEXTARG2) { if (argc < 3) errx(1, "'%s' requires 2 arguments", p->c_name); p->c_u.c_func2(argv[1], argv[2], s, afp); argc -= 2, argv += 2; } else p->c_u.c_func(*argv, p->c_parameter, s, afp); } argc--, argv++; } /* * Do any post argument processing required by the address family. */ if (afp->af_postproc != NULL) afp->af_postproc(s, afp); /* * Do deferred callbacks registered while processing * command-line arguments. */ for (cb = callbacks; cb != NULL; cb = cb->cb_next) cb->cb_func(s, cb->cb_arg); /* * Do deferred operations. */ if (clearaddr) { if (afp->af_ridreq == NULL || afp->af_difaddr == 0) { warnx("interface %s cannot change %s addresses!", name, afp->af_name); clearaddr = 0; } } if (clearaddr) { int ret; strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name); ret = ioctl(s, afp->af_difaddr, afp->af_ridreq); if (ret < 0) { if (errno == EADDRNOTAVAIL && (doalias >= 0)) { /* means no previous address for interface */ } else Perror("ioctl (SIOCDIFADDR)"); } } if (newaddr) { if (afp->af_addreq == NULL || afp->af_aifaddr == 0) { warnx("interface %s cannot change %s addresses!", name, afp->af_name); newaddr = 0; } } if (newaddr && (setaddr || setmask)) { strncpy(afp->af_addreq, name, sizeof ifr.ifr_name); if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0) Perror("ioctl (SIOCAIFADDR)"); } close(s); return(0); } /*ARGSUSED*/ static void setifaddr(const char *addr, int param, int s, const struct afswtch *afp) { if (afp->af_getaddr == NULL) return; /* * Delay the ioctl to set the interface addr until flags are all set. * The address interpretation may depend on the flags, * and the flags may change when the address is set. */ setaddr++; if (doalias == 0 && afp->af_af != AF_LINK) clearaddr = 1; afp->af_getaddr(addr, (doalias >= 0 ? ADDR : RIDADDR)); } static void settunnel(const char *src, const char *dst, int s, const struct afswtch *afp) { struct addrinfo *srcres, *dstres; int ecode; if (afp->af_settunnel == NULL) { warn("address family %s does not support tunnel setup", afp->af_name); return; } if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0) errx(1, "error in parsing address string: %s", gai_strerror(ecode)); if ((ecode = getaddrinfo(dst, NULL, NULL, &dstres)) != 0) errx(1, "error in parsing address string: %s", gai_strerror(ecode)); if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family) errx(1, "source and destination address families do not match"); afp->af_settunnel(s, srcres, dstres); freeaddrinfo(srcres); freeaddrinfo(dstres); } /* ARGSUSED */ static void deletetunnel(const char *vname, int param, int s, const struct afswtch *afp) { if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0) err(1, "SIOCDIFPHYADDR"); } static void setifnetmask(const char *addr, int dummy __unused, int s, const struct afswtch *afp) { if (afp->af_getaddr != NULL) { setmask++; afp->af_getaddr(addr, MASK); } } static void setifbroadaddr(const char *addr, int dummy __unused, int s, const struct afswtch *afp) { if (afp->af_getaddr != NULL) afp->af_getaddr(addr, DSTADDR); } static void setifipdst(const char *addr, int dummy __unused, int s, const struct afswtch *afp) { const struct afswtch *inet; inet = af_getbyname("inet"); if (inet == NULL) return; inet->af_getaddr(addr, DSTADDR); setipdst++; clearaddr = 0; newaddr = 0; } static void notealias(const char *addr, int param, int s, const struct afswtch *afp) { #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) if (setaddr && doalias == 0 && param < 0) if (afp->af_addreq != NULL && afp->af_ridreq != NULL) bcopy((caddr_t)rqtosa(af_addreq), (caddr_t)rqtosa(af_ridreq), rqtosa(af_addreq)->sa_len); doalias = param; if (param < 0) { clearaddr = 1; newaddr = 0; } else clearaddr = 0; #undef rqtosa } /*ARGSUSED*/ static void setifdstaddr(const char *addr, int param __unused, int s, const struct afswtch *afp) { if (afp->af_getaddr != NULL) afp->af_getaddr(addr, DSTADDR); } /* * Note: doing an SIOCIGIFFLAGS scribbles on the union portion * of the ifreq structure, which may confuse other parts of ifconfig. * Make a private copy so we can avoid that. */ static void setifflags(const char *vname, int value, int s, const struct afswtch *afp) { struct ifreq my_ifr; + int flags; bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq)); if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) { Perror("ioctl (SIOCGIFFLAGS)"); exit(1); } strncpy(my_ifr.ifr_name, name, sizeof (my_ifr.ifr_name)); flags = (my_ifr.ifr_flags & 0xffff) | (my_ifr.ifr_flagshigh << 16); if (value < 0) { value = -value; flags &= ~value; } else flags |= value; my_ifr.ifr_flags = flags & 0xffff; my_ifr.ifr_flagshigh = flags >> 16; if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0) Perror(vname); } void setifcap(const char *vname, int value, int s, const struct afswtch *afp) { + int flags; if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) { Perror("ioctl (SIOCGIFCAP)"); exit(1); } flags = ifr.ifr_curcap; if (value < 0) { value = -value; flags &= ~value; } else flags |= value; flags &= ifr.ifr_reqcap; ifr.ifr_reqcap = flags; if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0) Perror(vname); } static void setifmetric(const char *val, int dummy __unused, int s, const struct afswtch *afp) { strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); ifr.ifr_metric = atoi(val); if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) warn("ioctl (set metric)"); } static void setifmtu(const char *val, int dummy __unused, int s, const struct afswtch *afp) { strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); ifr.ifr_mtu = atoi(val); if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) warn("ioctl (set mtu)"); } static void setifname(const char *val, int dummy __unused, int s, const struct afswtch *afp) { char *newname; newname = strdup(val); if (newname == NULL) { warn("no memory to set ifname"); return; } ifr.ifr_data = newname; if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) { warn("ioctl (set name)"); free(newname); return; } strlcpy(name, newname, sizeof(name)); free(newname); } -/* - * Expand the compacted form of addresses as returned via the - * configuration read via sysctl(). - */ -static void -rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo) -{ - struct sockaddr *sa; - int i; - - memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); - for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { - if ((rtinfo->rti_addrs & (1 << i)) == 0) - continue; - rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; - cp += SA_SIZE(sa); - } -} - #define IFFBITS \ "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \ "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \ "\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP\25NEEDSGIANT" #define IFCAPBITS \ "\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \ "\10VLAN_HWCSUM\11TSO4\12TSO6" /* * Print the status of the interface. If an address family was * specified, show only it; otherwise, show them all. */ static void -status(const struct afswtch *afp, int addrcount, struct sockaddr_dl *sdl, - struct if_msghdr *ifm, struct ifa_msghdr *ifam) +status(const struct afswtch *afp, const struct sockaddr_dl *sdl, + struct ifaddrs *ifa) { - struct rt_addrinfo info; + struct ifaddrs *ift; int allfamilies, s; struct ifstat ifs; if (afp == NULL) { allfamilies = 1; afp = af_getbyname("inet"); } else allfamilies = 0; ifr.ifr_addr.sa_family = afp->af_af == AF_LINK ? AF_INET : afp->af_af; strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0); if (s < 0) err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family); printf("%s: ", name); - printb("flags", flags, IFFBITS); - if (ifm->ifm_data.ifi_metric) - printf(" metric %ld", ifm->ifm_data.ifi_metric); - if (ifm->ifm_data.ifi_mtu) - printf(" mtu %ld", ifm->ifm_data.ifi_mtu); + printb("flags", ifa->ifa_flags, IFFBITS); + if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1) + printf(" metric %d", ifr.ifr_metric); + if (ioctl(s, SIOCGIFMTU, &ifr) != -1) + printf(" mtu %d", ifr.ifr_mtu); putchar('\n'); if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) { if (ifr.ifr_curcap != 0) { printb("\toptions", ifr.ifr_curcap, IFCAPBITS); putchar('\n'); } if (supmedia && ifr.ifr_reqcap != 0) { printb("\tcapabilities", ifr.ifr_reqcap, IFCAPBITS); putchar('\n'); } } tunnel_status(s); - while (addrcount > 0) { - info.rti_addrs = ifam->ifam_addrs; - /* Expand the compacted addresses */ - rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, - &info); - + for (ift = ifa; ift != NULL; ift = ift->ifa_next) { + if (ift->ifa_addr == NULL) + continue; + if (strcmp(ifa->ifa_name, ift->ifa_name) != 0) + continue; if (allfamilies) { const struct afswtch *p; - p = af_getbyfamily(info.rti_info[RTAX_IFA]->sa_family); + p = af_getbyfamily(ift->ifa_addr->sa_family); if (p != NULL && p->af_status != NULL) - p->af_status(s, &info); - } else if (afp->af_af == info.rti_info[RTAX_IFA]->sa_family) - afp->af_status(s, &info); - addrcount--; - ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen); + p->af_status(s, ift); + } else if (afp->af_af == ift->ifa_addr->sa_family) + afp->af_status(s, ift); } +#if 0 if (allfamilies || afp->af_af == AF_LINK) { const struct afswtch *lafp; /* * Hack; the link level address is received separately * from the routing information so any address is not * handled above. Cobble together an entry and invoke * the status method specially. */ lafp = af_getbyname("lladdr"); if (lafp != NULL) { info.rti_info[RTAX_IFA] = (struct sockaddr *)sdl; lafp->af_status(s, &info); } } +#endif if (allfamilies) af_other_status(s); else if (afp->af_other_status != NULL) afp->af_other_status(s); strncpy(ifs.ifs_name, name, sizeof ifs.ifs_name); if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) printf("%s", ifs.ascii); close(s); return; } static void tunnel_status(int s) { af_all_tunnel_status(s); } void Perror(const char *cmd) { switch (errno) { case ENXIO: errx(1, "%s: no such interface", cmd); break; case EPERM: errx(1, "%s: permission denied", cmd); break; default: err(1, "%s", cmd); } } /* * Print a value a la the %b format of the kernel's printf */ void printb(const char *s, unsigned v, const char *bits) { int i, any = 0; char c; if (bits && *bits == 8) printf("%s=%o", s, v); else printf("%s=%x", s, v); bits++; if (bits) { putchar('<'); while ((i = *bits++) != '\0') { if (v & (1 << (i-1))) { if (any) putchar(','); any = 1; for (; (c = *bits) > 32; bits++) putchar(c); } else for (; *bits > 32; bits++) ; } putchar('>'); } } void -ifmaybeload(char *name) +ifmaybeload(const char *name) { struct module_stat mstat; int fileid, modid; char ifkind[35], *cp, *dp; /* turn interface and unit into module name */ strcpy(ifkind, "if_"); for (cp = name, dp = ifkind + 3; (*cp != 0) && !isdigit(*cp); cp++, dp++) *dp = *cp; *dp = 0; /* scan files in kernel */ mstat.version = sizeof(struct module_stat); for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { /* scan modules in file */ for (modid = kldfirstmod(fileid); modid > 0; modid = modfnext(modid)) { if (modstat(modid, &mstat) < 0) continue; /* strip bus name if present */ if ((cp = strchr(mstat.name, '/')) != NULL) { cp++; } else { cp = mstat.name; } /* already loaded? */ if (strncmp(name, cp, strlen(cp)) == 0 || strncmp(ifkind, cp, strlen(cp)) == 0) return; } } /* not present, we should try to load it */ kldload(ifkind); } static struct cmd basic_cmds[] = { DEF_CMD("up", IFF_UP, setifflags), DEF_CMD("down", -IFF_UP, setifflags), DEF_CMD("arp", -IFF_NOARP, setifflags), DEF_CMD("-arp", IFF_NOARP, setifflags), DEF_CMD("debug", IFF_DEBUG, setifflags), DEF_CMD("-debug", -IFF_DEBUG, setifflags), DEF_CMD("promisc", IFF_PPROMISC, setifflags), DEF_CMD("-promisc", -IFF_PPROMISC, setifflags), DEF_CMD("add", IFF_UP, notealias), DEF_CMD("alias", IFF_UP, notealias), DEF_CMD("-alias", -IFF_UP, notealias), DEF_CMD("delete", -IFF_UP, notealias), DEF_CMD("remove", -IFF_UP, notealias), #ifdef notdef #define EN_SWABIPS 0x1000 DEF_CMD("swabips", EN_SWABIPS, setifflags), DEF_CMD("-swabips", -EN_SWABIPS, setifflags), #endif DEF_CMD_ARG("netmask", setifnetmask), DEF_CMD_ARG("metric", setifmetric), DEF_CMD_ARG("broadcast", setifbroadaddr), DEF_CMD_ARG("ipdst", setifipdst), DEF_CMD_ARG2("tunnel", settunnel), DEF_CMD("-tunnel", 0, deletetunnel), DEF_CMD("deletetunnel", 0, deletetunnel), DEF_CMD("link0", IFF_LINK0, setifflags), DEF_CMD("-link0", -IFF_LINK0, setifflags), DEF_CMD("link1", IFF_LINK1, setifflags), DEF_CMD("-link1", -IFF_LINK1, setifflags), DEF_CMD("link2", IFF_LINK2, setifflags), DEF_CMD("-link2", -IFF_LINK2, setifflags), DEF_CMD("monitor", IFF_MONITOR, setifflags), DEF_CMD("-monitor", -IFF_MONITOR, setifflags), DEF_CMD("staticarp", IFF_STATICARP, setifflags), DEF_CMD("-staticarp", -IFF_STATICARP, setifflags), DEF_CMD("rxcsum", IFCAP_RXCSUM, setifcap), DEF_CMD("-rxcsum", -IFCAP_RXCSUM, setifcap), DEF_CMD("txcsum", IFCAP_TXCSUM, setifcap), DEF_CMD("-txcsum", -IFCAP_TXCSUM, setifcap), DEF_CMD("netcons", IFCAP_NETCONS, setifcap), DEF_CMD("-netcons", -IFCAP_NETCONS, setifcap), DEF_CMD("polling", IFCAP_POLLING, setifcap), DEF_CMD("-polling", -IFCAP_POLLING, setifcap), DEF_CMD("tso", IFCAP_TSO, setifcap), DEF_CMD("-tso", -IFCAP_TSO, setifcap), DEF_CMD("normal", -IFF_LINK0, setifflags), DEF_CMD("compress", IFF_LINK0, setifflags), DEF_CMD("noicmp", IFF_LINK1, setifflags), DEF_CMD_ARG("mtu", setifmtu), DEF_CMD_ARG("name", setifname), }; static __constructor void ifconfig_ctor(void) { #define N(a) (sizeof(a) / sizeof(a[0])) int i; for (i = 0; i < N(basic_cmds); i++) cmd_register(&basic_cmds[i]); #undef N } diff --git a/sbin/ifconfig/ifconfig.h b/sbin/ifconfig/ifconfig.h index 79f1fcb4198f..ef7cec5a28af 100644 --- a/sbin/ifconfig/ifconfig.h +++ b/sbin/ifconfig/ifconfig.h @@ -1,143 +1,142 @@ /* * Copyright (c) 1997 Peter Wemm. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed for the FreeBSD Project * by Peter Wemm. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * so there! * * $FreeBSD$ */ #define __constructor __attribute__((constructor)) struct afswtch; struct cmd; typedef void c_func(const char *cmd, int arg, int s, const struct afswtch *afp); typedef void c_func2(const char *arg1, const char *arg2, int s, const struct afswtch *afp); struct cmd { const char *c_name; int c_parameter; #define NEXTARG 0xffffff /* has following arg */ #define NEXTARG2 0xfffffe /* has 2 following args */ #define OPTARG 0xfffffd /* has optional following arg */ union { c_func *c_func; c_func2 *c_func2; } c_u; struct cmd *c_next; }; void cmd_register(struct cmd *); typedef void callback_func(int s, void *); void callback_register(callback_func *, void *); /* * Macros for declaring command functions and initializing entries. */ #define DECL_CMD_FUNC(name, cmd, arg) \ void name(const char *cmd, int arg, int s, const struct afswtch *afp) #define DECL_CMD_FUNC2(name, arg1, arg2) \ void name(const char *arg1, const char *arg2, int s, const struct afswtch *afp) #define DEF_CMD(name, param, func) { name, param, { .c_func = func } } #define DEF_CMD_ARG(name, func) { name, NEXTARG, { .c_func = func } } #define DEF_CMD_OPTARG(name, func) { name, OPTARG, { .c_func = func } } #define DEF_CMD_ARG2(name, func) { name, NEXTARG2, { .c_func2 = func } } -struct rt_addrinfo; +struct ifaddrs; struct addrinfo; enum { RIDADDR, ADDR, MASK, DSTADDR, }; struct afswtch { const char *af_name; /* as given on cmd line, e.g. "inet" */ short af_af; /* AF_* */ /* * Status is handled one of two ways; if there is an * address associated with the interface then the * associated address family af_status method is invoked * with the appropriate addressin info. Otherwise, if * all possible info is to be displayed and af_other_status * is defined then it is invoked after all address status * is presented. */ - void (*af_status)(int, const struct rt_addrinfo *); + void (*af_status)(int, const struct ifaddrs *); void (*af_other_status)(int); /* parse address method */ void (*af_getaddr)(const char *, int); /* parse prefix method (IPv6) */ void (*af_getprefix)(const char *, int); void (*af_postproc)(int s, const struct afswtch *); u_long af_difaddr; /* set dst if address ioctl */ u_long af_aifaddr; /* set if address ioctl */ void *af_ridreq; /* */ void *af_addreq; /* */ struct afswtch *af_next; /* XXX doesn't fit model */ void (*af_status_tunnel)(int); void (*af_settunnel)(int s, struct addrinfo *srcres, struct addrinfo *dstres); }; void af_register(struct afswtch *); struct option { const char *opt; const char *opt_usage; void (*cb)(const char *arg); struct option *next; }; void opt_register(struct option *); extern struct ifreq ifr; extern char name[IFNAMSIZ]; /* name of interface */ extern int allmedia; extern int supmedia; extern int printkeys; -extern int flags; extern int newaddr; extern int verbose; extern int setipdst; void setifcap(const char *, int value, int s, const struct afswtch *); void Perror(const char *cmd); void printb(const char *s, unsigned value, const char *bits); -void ifmaybeload(char *name); +void ifmaybeload(const char *name); typedef void clone_callback_func(int, struct ifreq *); void clone_setcallback(clone_callback_func *);