diff options
Diffstat (limited to 'sbin/ifconfig')
32 files changed, 4745 insertions, 2245 deletions
diff --git a/sbin/ifconfig/Makefile b/sbin/ifconfig/Makefile index c48375b8c6d9..2553e61b5e9e 100644 --- a/sbin/ifconfig/Makefile +++ b/sbin/ifconfig/Makefile @@ -1,6 +1,3 @@ -# From: @(#)Makefile 8.1 (Berkeley) 6/5/93 -# $FreeBSD$ - .include <src.opts.mk> PACKAGE=runtime @@ -71,10 +68,15 @@ LIBADD+= jail .endif LIBADD+= nv +.if ${MK_NETLINK_SUPPORT} != "no" +SRCS+= ifconfig_netlink.c +.else +CFLAGS+=-DWITHOUT_NETLINK +.endif + MAN= ifconfig.8 CFLAGS+= -Wall -Wmissing-prototypes -Wcast-qual -Wwrite-strings -Wnested-externs -WARNS?= 2 HAS_TESTS= SUBDIR.${MK_TESTS}+= tests diff --git a/sbin/ifconfig/Makefile.depend b/sbin/ifconfig/Makefile.depend index 896ebc6ade5f..da0504014f9d 100644 --- a/sbin/ifconfig/Makefile.depend +++ b/sbin/ifconfig/Makefile.depend @@ -1,4 +1,3 @@ -# $FreeBSD$ # Autogenerated - do NOT edit! DIRDEPS = \ @@ -8,8 +7,9 @@ DIRDEPS = \ lib/${CSU_DIR} \ lib/libc \ lib/libcompiler_rt \ - lib/libexpat \ - lib/libsbuf \ + lib/libifconfig \ + lib/libnv \ + lib/libutil \ lib/msun \ diff --git a/sbin/ifconfig/Makefile.depend.options b/sbin/ifconfig/Makefile.depend.options index 91c60b1a0b29..8dc0fcbc30de 100644 --- a/sbin/ifconfig/Makefile.depend.options +++ b/sbin/ifconfig/Makefile.depend.options @@ -1,4 +1,3 @@ -# $FreeBSD$ # This file is not autogenerated - take care! DIRDEPS_OPTIONS= JAIL WIRELESS_SUPPORT diff --git a/sbin/ifconfig/af_inet.c b/sbin/ifconfig/af_inet.c index c5c40de155d6..4fd74d481b3a 100644 --- a/sbin/ifconfig/af_inet.c +++ b/sbin/ifconfig/af_inet.c @@ -29,11 +29,6 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <sys/param.h> #include <sys/ioctl.h> #include <sys/socket.h> @@ -53,23 +48,35 @@ static const char rcsid[] = #include <netdb.h> #include "ifconfig.h" +#include "ifconfig_netlink.h" +#ifdef WITHOUT_NETLINK static struct in_aliasreq in_addreq; static struct ifreq in_ridreq; +#else +struct in_px { + struct in_addr addr; + int plen; + bool addrset; + bool maskset; +}; +struct in_pdata { + struct in_px addr; + struct in_px dst_addr; + struct in_px brd_addr; + uint32_t flags; + uint32_t vhid; +}; +static struct in_pdata in_add, in_del; +#endif + static char addr_buf[NI_MAXHOST]; /*for getnameinfo()*/ extern char *f_inet, *f_addr; static void -in_status(int s __unused, const struct ifaddrs *ifa) +print_addr(struct sockaddr_in *sin) { - struct sockaddr_in *sin, null_sin; int error, n_flags; - - memset(&null_sin, 0, sizeof(null_sin)); - - sin = (struct sockaddr_in *)ifa->ifa_addr; - if (sin == NULL) - return; if (f_addr != NULL && strcmp(f_addr, "fqdn") == 0) n_flags = 0; @@ -85,15 +92,28 @@ in_status(int s __unused, const struct ifaddrs *ifa) inet_ntop(AF_INET, &sin->sin_addr, addr_buf, sizeof(addr_buf)); printf("\tinet %s", addr_buf); +} + +#ifdef WITHOUT_NETLINK +static void +in_status(if_ctx *ctx __unused, const struct ifaddrs *ifa) +{ + struct sockaddr_in *sin, null_sin = {}; + + sin = satosin(ifa->ifa_addr); + if (sin == NULL) + return; + + print_addr(sin); if (ifa->ifa_flags & IFF_POINTOPOINT) { - sin = (struct sockaddr_in *)ifa->ifa_dstaddr; + sin = satosin(ifa->ifa_dstaddr); if (sin == NULL) sin = &null_sin; printf(" --> %s", inet_ntoa(sin->sin_addr)); } - sin = (struct sockaddr_in *)ifa->ifa_netmask; + sin = satosin(ifa->ifa_netmask); if (sin == NULL) sin = &null_sin; if (f_inet != NULL && strcmp(f_inet, "cidr") == 0) { @@ -114,16 +134,62 @@ in_status(int s __unused, const struct ifaddrs *ifa) printf(" netmask 0x%lx", (unsigned long)ntohl(sin->sin_addr.s_addr)); if (ifa->ifa_flags & IFF_BROADCAST) { - sin = (struct sockaddr_in *)ifa->ifa_broadaddr; + sin = satosin(ifa->ifa_broadaddr); if (sin != NULL && sin->sin_addr.s_addr != 0) printf(" broadcast %s", inet_ntoa(sin->sin_addr)); } - print_vhid(ifa, " "); + print_vhid(ifa); putchar('\n'); } +#else +static struct in_addr +get_mask(int plen) +{ + struct in_addr a; + + a.s_addr = htonl(plen ? ~((1 << (32 - plen)) - 1) : 0); + + return (a); +} + +static void +in_status_nl(if_ctx *ctx __unused, if_link_t *link, if_addr_t *ifa) +{ + struct sockaddr_in *sin = satosin(ifa->ifa_local); + int plen = ifa->ifa_prefixlen; + + print_addr(sin); + + if (link->ifi_flags & IFF_POINTOPOINT) { + struct sockaddr_in *dst = satosin(ifa->ifa_address); + + printf(" --> %s", inet_ntoa(dst->sin_addr)); + } + if (f_inet != NULL && strcmp(f_inet, "cidr") == 0) { + printf("/%d", plen); + } else if (f_inet != NULL && strcmp(f_inet, "dotted") == 0) + printf(" netmask %s", inet_ntoa(get_mask(plen))); + else + printf(" netmask 0x%lx", (unsigned long)ntohl(get_mask(plen).s_addr)); + + if ((link->ifi_flags & IFF_BROADCAST) && plen != 0) { + struct sockaddr_in *brd = satosin(ifa->ifa_broadcast); + if (brd != NULL) + printf(" broadcast %s", inet_ntoa(brd->sin_addr)); + } + + if (ifa->ifaf_vhid != 0) + printf(" vhid %d", ifa->ifaf_vhid); + + putchar('\n'); +} +#endif + + +#ifdef WITHOUT_NETLINK #define SIN(x) ((struct sockaddr_in *) &(x)) static struct sockaddr_in *sintab[] = { SIN(in_ridreq.ifr_addr), SIN(in_addreq.ifra_addr), @@ -131,6 +197,12 @@ static struct sockaddr_in *sintab[] = { }; static void +in_copyaddr(if_ctx *ctx __unused, int to, int from) +{ + memcpy(sintab[to], sintab[from], sizeof(struct sockaddr_in)); +} + +static void in_getaddr(const char *s, int which) { struct sockaddr_in *sin = sintab[which]; @@ -146,7 +218,7 @@ in_getaddr(const char *s, int which) if((p = strrchr(s, '/')) != NULL) { const char *errstr; /* address is `name/masklen' */ - int masklen; + int masklen = 0; struct sockaddr_in *min = sintab[MASK]; *p = '\0'; if (!isdigit(*(p + 1))) @@ -175,18 +247,221 @@ in_getaddr(const char *s, int which) errx(1, "%s: bad value", s); } +#else + +static struct in_px *sintab_nl[] = { + &in_del.addr, /* RIDADDR */ + &in_add.addr, /* ADDR */ + NULL, /* MASK */ + &in_add.dst_addr, /* DSTADDR*/ + &in_add.brd_addr, /* BRDADDR*/ +}; + +static void +in_copyaddr(if_ctx *ctx __unused, int to, int from) +{ + sintab_nl[to]->addr = sintab_nl[from]->addr; + sintab_nl[to]->addrset = sintab_nl[from]->addrset; +} + +static void +in_getip(const char *addr_str, struct in_addr *ip) +{ + struct hostent *hp; + struct netent *np; + + if (inet_aton(addr_str, ip)) + return; + if ((hp = gethostbyname(addr_str)) != NULL) + bcopy(hp->h_addr, (char *)ip, + MIN((size_t)hp->h_length, sizeof(ip))); + else if ((np = getnetbyname(addr_str)) != NULL) + *ip = inet_makeaddr(np->n_net, INADDR_ANY); + else + errx(1, "%s: bad value", addr_str); +} + +static void +in_getaddr(const char *s, int which) +{ + struct in_px *px = sintab_nl[which]; + + if (which == MASK) { + struct in_px *px_addr = sintab_nl[ADDR]; + struct in_addr mask = {}; + + in_getip(s, &mask); + px_addr->plen = __bitcount32(mask.s_addr); + px_addr->maskset = true; + return; + } + + if (which == ADDR) { + char *p = NULL; + + if((p = strrchr(s, '/')) != NULL) { + const char *errstr; + /* address is `name/masklen' */ + int masklen; + *p = '\0'; + if (!isdigit(*(p + 1))) + errstr = "invalid"; + else + masklen = (int)strtonum(p + 1, 0, 32, &errstr); + if (errstr != NULL) { + *p = '/'; + errx(1, "%s: bad value (width %s)", s, errstr); + } + px->plen = masklen; + px->maskset = true; + } + } + + in_getip(s, &px->addr); + px->addrset = true; +} + +/* + * Deletes the first found IPv4 interface address for the interface. + * + * This function provides SIOCDIFADDR semantics missing in Netlink. + * When no valid IPv4 address is specified (sin_family or sin_len is wrong) to + * the SIOCDIFADDR call, it deletes the first found IPv4 address on the interface. + * 'ifconfig IFNAME inet addr/prefix' relies on that behavior, as it + * executes empty SIOCDIFADDR before adding a new address. + */ +static int +in_delete_first_nl(if_ctx *ctx) +{ + struct nlmsghdr *hdr; + struct ifaddrmsg *ifahdr; + uint32_t nlmsg_seq; + struct in_addr addr; + struct snl_writer nw = {}; + struct snl_errmsg_data e = {}; + struct snl_state *ss = ctx->io_ss; + bool found = false; + + uint32_t ifindex = if_nametoindex_nl(ss, ctx->ifname); + if (ifindex == 0) { + /* No interface with the desired name, nothing to delete */ + return (EADDRNOTAVAIL); + } + + snl_init_writer(ss, &nw); + hdr = snl_create_msg_request(&nw, NL_RTM_GETADDR); + hdr->nlmsg_flags |= NLM_F_DUMP; + ifahdr = snl_reserve_msg_object(&nw, struct ifaddrmsg); + ifahdr->ifa_family = AF_INET; + ifahdr->ifa_index = ifindex; + + if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr)) + return (EINVAL); + + nlmsg_seq = hdr->nlmsg_seq; + while ((hdr = snl_read_reply_multi(ss, nlmsg_seq, &e)) != NULL) { + struct snl_parsed_addr attrs = {}; + if (snl_parse_nlmsg(ss, hdr, &snl_rtm_addr_parser, &attrs)) { + addr = satosin(attrs.ifa_local)->sin_addr; + ifindex = attrs.ifa_index; + found = true; + break; + } else + return (EINVAL); + } + if (e.error != 0) { + if (e.error_str != NULL) + warnx("%s(): %s", __func__, e.error_str); + return (e.error); + } + + if (!found) + return (0); + + /* Try to delete the found address */ + snl_init_writer(ss, &nw); + hdr = snl_create_msg_request(&nw, NL_RTM_DELADDR); + ifahdr = snl_reserve_msg_object(&nw, struct ifaddrmsg); + ifahdr->ifa_family = AF_INET; + ifahdr->ifa_index = ifindex; + snl_add_msg_attr_ip4(&nw, IFA_LOCAL, &addr); + + if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr)) + return (EINVAL); + memset(&e, 0, sizeof(e)); + snl_read_reply_code(ss, hdr->nlmsg_seq, &e); + if (e.error_str != NULL) + warnx("%s(): %s", __func__, e.error_str); + + return (e.error); +} + + +static int +in_exec_nl(if_ctx *ctx, unsigned long action, void *data) +{ + struct in_pdata *pdata = (struct in_pdata *)data; + struct snl_writer nw = {}; + + if (action == NL_RTM_DELADDR && !pdata->addr.addrset) + return (in_delete_first_nl(ctx)); + + snl_init_writer(ctx->io_ss, &nw); + struct nlmsghdr *hdr = snl_create_msg_request(&nw, action); + struct ifaddrmsg *ifahdr = snl_reserve_msg_object(&nw, struct ifaddrmsg); + + ifahdr->ifa_family = AF_INET; + ifahdr->ifa_prefixlen = pdata->addr.plen; + ifahdr->ifa_index = if_nametoindex_nl(ctx->io_ss, ctx->ifname); + + snl_add_msg_attr_ip4(&nw, IFA_LOCAL, &pdata->addr.addr); + if (action == NL_RTM_NEWADDR && pdata->dst_addr.addrset) + snl_add_msg_attr_ip4(&nw, IFA_ADDRESS, &pdata->dst_addr.addr); + if (action == NL_RTM_NEWADDR && pdata->brd_addr.addrset) + snl_add_msg_attr_ip4(&nw, IFA_BROADCAST, &pdata->brd_addr.addr); + + int off = snl_add_msg_attr_nested(&nw, IFA_FREEBSD); + snl_add_msg_attr_u32(&nw, IFAF_FLAGS, pdata->flags); + if (pdata->vhid != 0) + snl_add_msg_attr_u32(&nw, IFAF_VHID, pdata->vhid); + snl_end_attr_nested(&nw, off); + + if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ctx->io_ss, hdr)) + return (0); + + struct snl_errmsg_data e = {}; + snl_read_reply_code(ctx->io_ss, hdr->nlmsg_seq, &e); + if (e.error_str != NULL) + warnx("%s(): %s", __func__, e.error_str); + + return (e.error); +} +#endif + +static void +err_nomask(int ifflags) +{ + if ((ifflags & (IFF_POINTOPOINT | IFF_LOOPBACK)) == 0) { + errx(1, "ERROR: setting interface address without mask is no longer supported."); + } +} + static void -in_postproc(int s, const struct afswtch *afp, int newaddr, int ifflags) +in_postproc(if_ctx *ctx __unused, int newaddr, int ifflags) { - if (sintab[ADDR]->sin_len != 0 && sintab[MASK]->sin_len == 0 && - newaddr && (ifflags & (IFF_POINTOPOINT | IFF_LOOPBACK)) == 0) { - warnx("WARNING: setting interface address without mask " - "is deprecated,\ndefault mask may not be correct."); +#ifdef WITHOUT_NETLINK + if (sintab[ADDR]->sin_len != 0 && sintab[MASK]->sin_len == 0 && newaddr) { + err_nomask(ifflags); } +#else + if (sintab_nl[ADDR]->addrset && !sintab_nl[ADDR]->maskset && newaddr) { + err_nomask(ifflags); + } +#endif } static void -in_status_tunnel(int s) +in_status_tunnel(if_ctx *ctx) { char src[NI_MAXHOST]; char dst[NI_MAXHOST]; @@ -194,16 +469,16 @@ in_status_tunnel(int s) const struct sockaddr *sa = (const struct sockaddr *) &ifr.ifr_addr; memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, name, IFNAMSIZ); + strlcpy(ifr.ifr_name, ctx->ifname, IFNAMSIZ); - if (ioctl(s, SIOCGIFPSRCADDR, (caddr_t)&ifr) < 0) + if (ioctl_ctx(ctx, 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) + if (ioctl_ctx(ctx, SIOCGIFPDSTADDR, (caddr_t)&ifr) < 0) return; if (sa->sa_family != AF_INET) return; @@ -214,31 +489,56 @@ in_status_tunnel(int s) } static void -in_set_tunnel(int s, struct addrinfo *srcres, struct addrinfo *dstres) +in_set_tunnel(if_ctx *ctx, struct addrinfo *srcres, struct addrinfo *dstres) { struct in_aliasreq addreq; memset(&addreq, 0, sizeof(addreq)); - strlcpy(addreq.ifra_name, name, IFNAMSIZ); + strlcpy(addreq.ifra_name, ctx->ifname, 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) + if (ioctl_ctx(ctx, SIOCSIFPHYADDR, &addreq) < 0) warn("SIOCSIFPHYADDR"); } +static void +in_set_vhid(int vhid) +{ +#ifdef WITHOUT_NETLINK + in_addreq.ifra_vhid = vhid; +#else + in_add.vhid = (uint32_t)vhid; +#endif +} + static struct afswtch af_inet = { .af_name = "inet", .af_af = AF_INET, +#ifdef WITHOUT_NETLINK .af_status = in_status, +#else + .af_status = in_status_nl, +#endif .af_getaddr = in_getaddr, + .af_copyaddr = in_copyaddr, .af_postproc = in_postproc, .af_status_tunnel = in_status_tunnel, .af_settunnel = in_set_tunnel, + .af_setvhid = in_set_vhid, +#ifdef WITHOUT_NETLINK .af_difaddr = SIOCDIFADDR, .af_aifaddr = SIOCAIFADDR, .af_ridreq = &in_ridreq, .af_addreq = &in_addreq, + .af_exec = af_exec_ioctl, +#else + .af_difaddr = NL_RTM_DELADDR, + .af_aifaddr = NL_RTM_NEWADDR, + .af_ridreq = &in_del, + .af_addreq = &in_add, + .af_exec = in_exec_nl, +#endif }; static __constructor void diff --git a/sbin/ifconfig/af_inet6.c b/sbin/ifconfig/af_inet6.c index 08902b934ad8..17dc068ee875 100644 --- a/sbin/ifconfig/af_inet6.c +++ b/sbin/ifconfig/af_inet6.c @@ -29,11 +29,6 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <sys/param.h> #include <sys/ioctl.h> #include <sys/socket.h> @@ -57,53 +52,98 @@ static const char rcsid[] = #include <netinet6/nd6.h> /* Define ND6_INFINITE_LIFETIME */ #include "ifconfig.h" +#include "ifconfig_netlink.h" + +#ifndef WITHOUT_NETLINK +struct in6_px { + struct in6_addr addr; + int plen; + bool set; +}; +struct in6_pdata { + struct in6_px addr; + struct in6_px dst_addr; + struct in6_addrlifetime lifetime; + uint32_t flags; + uint32_t vhid; +}; +static struct in6_pdata in6_del; +static struct in6_pdata in6_add = { + .lifetime = { 0, 0, ND6_INFINITE_LIFETIME, ND6_INFINITE_LIFETIME }, +}; +#else static struct in6_ifreq in6_ridreq; static struct in6_aliasreq in6_addreq = { .ifra_flags = 0, .ifra_lifetime = { 0, 0, ND6_INFINITE_LIFETIME, ND6_INFINITE_LIFETIME } }; +#endif static int ip6lifetime; +#ifdef WITHOUT_NETLINK static int prefix(void *, int); +#endif static char *sec2str(time_t); static int explicit_prefix = 0; extern char *f_inet6, *f_addr; -extern void setnd6flags(const char *, int, int, const struct afswtch *); -extern void setnd6defif(const char *, int, int, const struct afswtch *); -extern void nd6_status(int); +extern void setnd6flags(if_ctx *, const char *, int); +extern void setnd6defif(if_ctx *,const char *, int); +extern void nd6_status(if_ctx *); static char addr_buf[NI_MAXHOST]; /*for getnameinfo()*/ static void -setifprefixlen(const char *addr, int dummy __unused, int s, - const struct afswtch *afp) +setifprefixlen(if_ctx *ctx __netlink_unused, const char *addr, int dummy __unused) { +#ifdef WITHOUT_NETLINK + const struct afswtch *afp = ctx->afp; + if (afp->af_getprefix != NULL) afp->af_getprefix(addr, MASK); +#else + int plen = strtol(addr, NULL, 10); + + if ((plen < 0) || (plen > 128)) + errx(1, "%s: bad value", addr); + in6_add.addr.plen = plen; +#endif explicit_prefix = 1; } static void -setip6flags(const char *dummyaddr __unused, int flag, int dummysoc __unused, - const struct afswtch *afp) +setip6flags(if_ctx *ctx, const char *dummyaddr __unused, int flag) { + const struct afswtch *afp = ctx->afp; + if (afp->af_af != AF_INET6) err(1, "address flags can be set only for inet6 addresses"); +#ifdef WITHOUT_NETLINK if (flag < 0) in6_addreq.ifra_flags &= ~(-flag); else in6_addreq.ifra_flags |= flag; +#else + if (flag < 0) + in6_add.flags &= ~(-flag); + else + in6_add.flags |= flag; +#endif } static void -setip6lifetime(const char *cmd, const char *val, int s, - const struct afswtch *afp) +setip6lifetime(if_ctx *ctx, const char *cmd, const char *val) { + const struct afswtch *afp = ctx->afp; struct timespec now; time_t newval; char *ep; +#ifdef WITHOUT_NETLINK + struct in6_addrlifetime *lifetime = &in6_addreq.ifra_lifetime; +#else + struct in6_addrlifetime *lifetime = &in6_add.lifetime; +#endif clock_gettime(CLOCK_MONOTONIC_FAST, &now); newval = (time_t)strtoul(val, &ep, 0); @@ -112,32 +152,30 @@ setip6lifetime(const char *cmd, const char *val, int s, 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 = now.tv_sec + newval; - in6_addreq.ifra_lifetime.ia6t_vltime = newval; + lifetime->ia6t_expire = now.tv_sec + newval; + lifetime->ia6t_vltime = newval; } else if (strcmp(cmd, "pltime") == 0) { - in6_addreq.ifra_lifetime.ia6t_preferred = now.tv_sec + newval; - in6_addreq.ifra_lifetime.ia6t_pltime = newval; + lifetime->ia6t_preferred = now.tv_sec + newval; + lifetime->ia6t_pltime = newval; } } static void -setip6pltime(const char *seconds, int dummy __unused, int s, - const struct afswtch *afp) +setip6pltime(if_ctx *ctx, const char *seconds, int dummy __unused) { - setip6lifetime("pltime", seconds, s, afp); + setip6lifetime(ctx, "pltime", seconds); } static void -setip6vltime(const char *seconds, int dummy __unused, int s, - const struct afswtch *afp) +setip6vltime(if_ctx *ctx, const char *seconds, int dummy __unused) { - setip6lifetime("vltime", seconds, s, afp); + setip6lifetime(ctx, "vltime", seconds); } static void -setip6eui64(const char *cmd, int dummy __unused, int s, - const struct afswtch *afp) +setip6eui64(if_ctx *ctx, const char *cmd, int dummy __unused) { + const struct afswtch *afp = ctx->afp; struct ifaddrs *ifap, *ifa; const struct sockaddr_in6 *sin6 = NULL; const struct in6_addr *lladdr = NULL; @@ -145,15 +183,19 @@ setip6eui64(const char *cmd, int dummy __unused, int s, if (afp->af_af != AF_INET6) errx(EXIT_FAILURE, "%s not allowed for the AF", cmd); +#ifdef WITHOUT_NETLINK in6 = (struct in6_addr *)&in6_addreq.ifra_addr.sin6_addr; +#else + in6 = &in6_add.addr.addr; +#endif 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; + strcmp(ifa->ifa_name, ctx->ifname) == 0) { + sin6 = (const struct sockaddr_in6 *)satosin6(ifa->ifa_addr); if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { lladdr = &sin6->sin6_addr; break; @@ -169,25 +211,94 @@ setip6eui64(const char *cmd, int dummy __unused, int s, } static void -in6_status(int s __unused, const struct ifaddrs *ifa) +print_addr(struct sockaddr_in6 *sin) +{ + int error, n_flags; + + if (f_addr != NULL && strcmp(f_addr, "fqdn") == 0) + n_flags = 0; + else if (f_addr != NULL && strcmp(f_addr, "host") == 0) + n_flags = NI_NOFQDN; + else + n_flags = NI_NUMERICHOST; + error = getnameinfo((struct sockaddr *)sin, sin->sin6_len, + addr_buf, sizeof(addr_buf), NULL, 0, + n_flags); + if (error != 0) + inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, + sizeof(addr_buf)); + printf("\tinet6 %s", addr_buf); +} + +static void +print_p2p(struct sockaddr_in6 *sin) +{ + int error; + + 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); +} + +static void +print_mask(int plen) +{ + if (f_inet6 != NULL && strcmp(f_inet6, "cidr") == 0) + printf("/%d", plen); + else + printf(" prefixlen %d", plen); +} + +static void +print_flags(int flags6) { - struct sockaddr_in6 *sin, null_sin; + 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 ((flags6 & IN6_IFF_PREFER_SOURCE) != 0) + printf(" prefer_source"); + +} + +static void +print_lifetime(const char *prepend, time_t px_time, struct timespec *now) +{ + printf(" %s", prepend); + if (px_time == 0) + printf(" infty"); + + printf(" %s", px_time < now->tv_sec ? "0" : sec2str(px_time - now->tv_sec)); +} + +#ifdef WITHOUT_NETLINK +static void +in6_status(if_ctx *ctx, const struct ifaddrs *ifa) +{ + struct sockaddr_in6 *sin, null_sin = {}; struct in6_ifreq ifr6; int s6; u_int32_t flags6; struct in6_addrlifetime lifetime; - struct timespec now; - int error, n_flags; - clock_gettime(CLOCK_MONOTONIC_FAST, &now); - - memset(&null_sin, 0, sizeof(null_sin)); - - sin = (struct sockaddr_in6 *)ifa->ifa_addr; + sin = satosin6(ifa->ifa_addr); if (sin == NULL) return; - strlcpy(ifr6.ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name)); + strlcpy(ifr6.ifr_name, ctx->ifname, sizeof(ifr6.ifr_name)); if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { warn("socket(AF_INET6,SOCK_DGRAM)"); return; @@ -209,101 +320,202 @@ in6_status(int s __unused, const struct ifaddrs *ifa) lifetime = ifr6.ifr_ifru.ifru_lifetime; close(s6); - if (f_addr != NULL && strcmp(f_addr, "fqdn") == 0) - n_flags = 0; - else if (f_addr != NULL && strcmp(f_addr, "host") == 0) - n_flags = NI_NOFQDN; - else - n_flags = NI_NUMERICHOST; - error = getnameinfo((struct sockaddr *)sin, sin->sin6_len, - addr_buf, sizeof(addr_buf), NULL, 0, - n_flags); - if (error != 0) - inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, - sizeof(addr_buf)); - printf("\tinet6 %s", addr_buf); + print_addr(sin); if (ifa->ifa_flags & IFF_POINTOPOINT) { - sin = (struct sockaddr_in6 *)ifa->ifa_dstaddr; + sin = satosin6(ifa->ifa_dstaddr); /* * some of the interfaces do not have valid destination * address. */ - if (sin != NULL && sin->sin6_family == AF_INET6) { - int error; - - 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); - } + if (sin != NULL && sin->sin6_family == AF_INET6) + print_p2p(sin); } - sin = (struct sockaddr_in6 *)ifa->ifa_netmask; + sin = satosin6(ifa->ifa_netmask); if (sin == NULL) sin = &null_sin; - if (f_inet6 != NULL && strcmp(f_inet6, "cidr") == 0) - printf("/%d", prefix(&sin->sin6_addr, - sizeof(struct in6_addr))); - else - printf(" prefixlen %d", prefix(&sin->sin6_addr, - sizeof(struct in6_addr))); + print_mask(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 ((flags6 & IN6_IFF_PREFER_SOURCE) != 0) - printf(" prefer_source"); + print_flags(flags6); - if (((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_scope_id) + if ((satosin6(ifa->ifa_addr))->sin6_scope_id) printf(" scopeid 0x%x", - ((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_scope_id); + (satosin6(ifa->ifa_addr))->sin6_scope_id); if (ip6lifetime && (lifetime.ia6t_preferred || lifetime.ia6t_expire)) { - printf(" pltime"); - if (lifetime.ia6t_preferred) { - printf(" %s", lifetime.ia6t_preferred < now.tv_sec - ? "0" : - sec2str(lifetime.ia6t_preferred - now.tv_sec)); - } else - printf(" infty"); - - printf(" vltime"); - if (lifetime.ia6t_expire) { - printf(" %s", lifetime.ia6t_expire < now.tv_sec - ? "0" : - sec2str(lifetime.ia6t_expire - now.tv_sec)); - } else - printf(" infty"); + struct timespec now; + + clock_gettime(CLOCK_MONOTONIC_FAST, &now); + print_lifetime("pltime", lifetime.ia6t_preferred, &now); + print_lifetime("vltime", lifetime.ia6t_expire, &now); + } + + print_vhid(ifa); + + putchar('\n'); +} + +#else +static void +show_lifetime(struct ifa_cacheinfo *ci) +{ + struct timespec now; + uint32_t pl, vl; + + if (ci == NULL) + return; + + int count = ci->ifa_prefered != ND6_INFINITE_LIFETIME; + count += ci->ifa_valid != ND6_INFINITE_LIFETIME; + if (count == 0) + return; + + pl = (ci->ifa_prefered == ND6_INFINITE_LIFETIME) ? 0 : ci->ifa_prefered; + vl = (ci->ifa_valid == ND6_INFINITE_LIFETIME) ? 0 : ci->ifa_valid; + + clock_gettime(CLOCK_MONOTONIC_FAST, &now); + print_lifetime("pltime", pl + now.tv_sec, &now); + print_lifetime("vltime", vl + now.tv_sec, &now); +} + +static void +in6_status_nl(if_ctx *ctx __unused, if_link_t *link __unused, if_addr_t *ifa) +{ + int plen = ifa->ifa_prefixlen; + uint32_t scopeid; + + if (ifa->ifa_local == NULL) { + /* Non-P2P address */ + scopeid = satosin6(ifa->ifa_address)->sin6_scope_id; + print_addr(satosin6(ifa->ifa_address)); + } else { + scopeid = satosin6(ifa->ifa_local)->sin6_scope_id; + print_addr(satosin6(ifa->ifa_local)); + print_p2p(satosin6(ifa->ifa_address)); } - print_vhid(ifa, " "); + print_mask(plen); + print_flags(ifa->ifaf_flags); + + if (scopeid != 0) + printf(" scopeid 0x%x", scopeid); + + show_lifetime(ifa->ifa_cacheinfo); + + if (ifa->ifaf_vhid != 0) + printf(" vhid %d", ifa->ifaf_vhid); putchar('\n'); } -#define SIN6(x) ((struct sockaddr_in6 *) &(x)) +static struct in6_px *sin6tab_nl[] = { + &in6_del.addr, /* RIDADDR */ + &in6_add.addr, /* ADDR */ + NULL, /* MASK */ + &in6_add.dst_addr, /* DSTADDR*/ +}; + +static void +in6_copyaddr(if_ctx *ctx __unused, int to, int from) +{ + sin6tab_nl[to]->addr = sin6tab_nl[from]->addr; + sin6tab_nl[to]->set = sin6tab_nl[from]->set; +} + +static void +in6_getaddr(const char *addr_str, int which) +{ + struct in6_px *px = sin6tab_nl[which]; + + if (which == MASK) + errx(1, "netmask: invalid option for inet6"); + if (which == BRDADDR) + errx(1, "broadcast: invalid option for inet6"); + + px->set = true; + px->plen = 128; + if (which == ADDR) { + char *p = NULL; + if((p = strrchr(addr_str, '/')) != NULL) { + *p = '\0'; + int plen = strtol(p + 1, NULL, 10); + if (plen < 0 || plen > 128) + errx(1, "%s: bad value", p + 1); + px->plen = plen; + explicit_prefix = 1; + } + } + + struct addrinfo hints = { .ai_family = AF_INET6 }; + struct addrinfo *res; + + int error = getaddrinfo(addr_str, NULL, &hints, &res); + if (error != 0) { + if (inet_pton(AF_INET6, addr_str, &px->addr) != 1) + errx(1, "%s: bad value", addr_str); + } else { + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *)(void *)res->ai_addr; + px->addr = sin6->sin6_addr; + freeaddrinfo(res); + } +} + +static int +in6_exec_nl(if_ctx *ctx, unsigned long action, void *data) +{ + struct in6_pdata *pdata = (struct in6_pdata *)data; + struct snl_writer nw = {}; + + snl_init_writer(ctx->io_ss, &nw); + struct nlmsghdr *hdr = snl_create_msg_request(&nw, action); + struct ifaddrmsg *ifahdr = snl_reserve_msg_object(&nw, struct ifaddrmsg); + + ifahdr->ifa_family = AF_INET6; + ifahdr->ifa_prefixlen = pdata->addr.plen; + ifahdr->ifa_index = if_nametoindex_nl(ctx->io_ss, ctx->ifname); + + snl_add_msg_attr_ip6(&nw, IFA_LOCAL, &pdata->addr.addr); + if (action == NL_RTM_NEWADDR && pdata->dst_addr.set) + snl_add_msg_attr_ip6(&nw, IFA_ADDRESS, &pdata->dst_addr.addr); + + struct ifa_cacheinfo ci = { + .ifa_prefered = pdata->lifetime.ia6t_pltime, + .ifa_valid = pdata->lifetime.ia6t_vltime, + }; + snl_add_msg_attr(&nw, IFA_CACHEINFO, sizeof(ci), &ci); + + int off = snl_add_msg_attr_nested(&nw, IFA_FREEBSD); + snl_add_msg_attr_u32(&nw, IFAF_FLAGS, pdata->flags); + if (pdata->vhid != 0) + snl_add_msg_attr_u32(&nw, IFAF_VHID, pdata->vhid); + snl_end_attr_nested(&nw, off); + + if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ctx->io_ss, hdr)) + return (0); + + struct snl_errmsg_data e = {}; + snl_read_reply_code(ctx->io_ss, hdr->nlmsg_seq, &e); + + return (e.error); +} +#endif + +#ifdef WITHOUT_NETLINK 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) + &in6_ridreq.ifr_addr, &in6_addreq.ifra_addr, + &in6_addreq.ifra_prefixmask, &in6_addreq.ifra_dstaddr }; static void +in6_copyaddr(if_ctx *ctx __unused, int to, int from) +{ + memcpy(sin6tab[to], sin6tab[from], sizeof(struct sockaddr_in6)); +} + +static void in6_getprefix(const char *plen, int which) { struct sockaddr_in6 *sin = sin6tab[which]; @@ -332,8 +544,6 @@ in6_getaddr(const char *s, int which) struct addrinfo hints, *res; int error = -1; - newaddr &= 1; - sin->sin6_len = sizeof(*sin); if (which != MASK) sin->sin6_family = AF_INET6; @@ -384,6 +594,7 @@ prefix(void *val, int size) return(0); return (plen); } +#endif static char * sec2str(time_t total) @@ -419,20 +630,20 @@ sec2str(time_t total) } static void -in6_postproc(int s, const struct afswtch *afp, int newaddr __unused, +in6_postproc(if_ctx *ctx, int newaddr __unused, int ifflags __unused) { 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); + setifprefixlen(ctx, "64", 0); /* in6_getprefix("64", MASK) if MASK is available here... */ } } static void -in6_status_tunnel(int s) +in6_status_tunnel(if_ctx *ctx) { char src[NI_MAXHOST]; char dst[NI_MAXHOST]; @@ -440,9 +651,9 @@ in6_status_tunnel(int s) const struct sockaddr *sa = (const struct sockaddr *) &in6_ifr.ifr_addr; memset(&in6_ifr, 0, sizeof(in6_ifr)); - strlcpy(in6_ifr.ifr_name, name, sizeof(in6_ifr.ifr_name)); + strlcpy(in6_ifr.ifr_name, ctx->ifname, sizeof(in6_ifr.ifr_name)); - if (ioctl(s, SIOCGIFPSRCADDR_IN6, (caddr_t)&in6_ifr) < 0) + if (ioctl_ctx(ctx, SIOCGIFPSRCADDR_IN6, (caddr_t)&in6_ifr) < 0) return; if (sa->sa_family != AF_INET6) return; @@ -450,7 +661,7 @@ in6_status_tunnel(int s) NI_NUMERICHOST) != 0) src[0] = '\0'; - if (ioctl(s, SIOCGIFPDSTADDR_IN6, (caddr_t)&in6_ifr) < 0) + if (ioctl_ctx(ctx, SIOCGIFPDSTADDR_IN6, (caddr_t)&in6_ifr) < 0) return; if (sa->sa_family != AF_INET6) return; @@ -462,20 +673,29 @@ in6_status_tunnel(int s) } static void -in6_set_tunnel(int s, struct addrinfo *srcres, struct addrinfo *dstres) +in6_set_tunnel(if_ctx *ctx, struct addrinfo *srcres, struct addrinfo *dstres) { - struct in6_aliasreq in6_addreq; + struct in6_aliasreq in6_req = {}; - memset(&in6_addreq, 0, sizeof(in6_addreq)); - strlcpy(in6_addreq.ifra_name, name, sizeof(in6_addreq.ifra_name)); - memcpy(&in6_addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len); - memcpy(&in6_addreq.ifra_dstaddr, dstres->ai_addr, + strlcpy(in6_req.ifra_name, ctx->ifname, sizeof(in6_req.ifra_name)); + memcpy(&in6_req.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len); + memcpy(&in6_req.ifra_dstaddr, dstres->ai_addr, dstres->ai_addr->sa_len); - if (ioctl(s, SIOCSIFPHYADDR_IN6, &in6_addreq) < 0) + if (ioctl_ctx(ctx, SIOCSIFPHYADDR_IN6, &in6_req) < 0) warn("SIOCSIFPHYADDR_IN6"); } +static void +in6_set_vhid(int vhid) +{ +#ifdef WITHOUT_NETLINK + in6_addreq.ifra_vhid = vhid; +#else + in6_add.vhid = (uint32_t)vhid; +#endif +} + static struct cmd inet6_cmds[] = { DEF_CMD_ARG("prefixlen", setifprefixlen), DEF_CMD("anycast", IN6_IFF_ANYCAST, setip6flags), @@ -515,21 +735,38 @@ static struct cmd inet6_cmds[] = { static struct afswtch af_inet6 = { .af_name = "inet6", .af_af = AF_INET6, +#ifdef WITHOUT_NETLINK .af_status = in6_status, +#else + .af_status = in6_status_nl, +#endif .af_getaddr = in6_getaddr, + .af_copyaddr = in6_copyaddr, +#ifdef WITHOUT_NETLINK .af_getprefix = in6_getprefix, +#endif .af_other_status = nd6_status, .af_postproc = in6_postproc, .af_status_tunnel = in6_status_tunnel, .af_settunnel = in6_set_tunnel, + .af_setvhid = in6_set_vhid, +#ifdef WITHOUT_NETLINK .af_difaddr = SIOCDIFADDR_IN6, .af_aifaddr = SIOCAIFADDR_IN6, .af_ridreq = &in6_addreq, .af_addreq = &in6_addreq, + .af_exec = af_exec_ioctl, +#else + .af_difaddr = NL_RTM_DELADDR, + .af_aifaddr = NL_RTM_NEWADDR, + .af_ridreq = &in6_add, + .af_addreq = &in6_add, + .af_exec = in6_exec_nl, +#endif }; static void -in6_Lopt_cb(const char *optarg __unused) +in6_Lopt_cb(const char *arg __unused) { ip6lifetime++; /* print IPv6 address lifetime */ } diff --git a/sbin/ifconfig/af_link.c b/sbin/ifconfig/af_link.c index fb7a235b2f49..55b75d847c16 100644 --- a/sbin/ifconfig/af_link.c +++ b/sbin/ifconfig/af_link.c @@ -29,11 +29,6 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <sys/types.h> #include <sys/ioctl.h> #include <sys/socket.h> @@ -51,39 +46,80 @@ static const char rcsid[] = #include <net/ethernet.h> #include "ifconfig.h" +#include "ifconfig_netlink.h" static struct ifreq link_ridreq; extern char *f_ether; static void -link_status(int s __unused, const struct ifaddrs *ifa) +print_ether(const struct ether_addr *addr, const char *prefix) { - /* XXX no const 'cuz LLADDR is defined wrong */ - struct sockaddr_dl *sdl; - char *ether_format, *format_char; - struct ifreq ifr; - int n, rc, sock_hw; - static const u_char laggaddr[6] = {0}; + char *ether_format = ether_ntoa(addr); - sdl = (struct sockaddr_dl *) ifa->ifa_addr; - if (sdl == NULL || sdl->sdl_alen == 0) - return; + if (f_ether != NULL) { + if (strcmp(f_ether, "dash") == 0) { + char *format_char; - if ((sdl->sdl_type == IFT_ETHER || sdl->sdl_type == IFT_L2VLAN || - sdl->sdl_type == IFT_BRIDGE) && sdl->sdl_alen == ETHER_ADDR_LEN) { - ether_format = ether_ntoa((struct ether_addr *)LLADDR(sdl)); - if (f_ether != NULL && strcmp(f_ether, "dash") == 0) { - while ((format_char = strchr(ether_format, ':')) != - NULL) { + while ((format_char = strchr(ether_format, ':')) != NULL) { *format_char = '-'; } + } else if (strcmp(f_ether, "dotted") == 0) { + /* Indices 0 and 1 is kept as is. */ + ether_format[ 2] = ether_format[ 3]; + ether_format[ 3] = ether_format[ 4]; + ether_format[ 4] = '.'; + ether_format[ 5] = ether_format[ 6]; + ether_format[ 6] = ether_format[ 7]; + ether_format[ 7] = ether_format[ 9]; + ether_format[ 8] = ether_format[10]; + ether_format[ 9] = '.'; + ether_format[10] = ether_format[12]; + ether_format[11] = ether_format[13]; + ether_format[12] = ether_format[15]; + ether_format[13] = ether_format[16]; + ether_format[14] = '\0'; } - printf("\tether %s\n", ether_format); + } + printf("\t%s %s\n", prefix, ether_format); +} + +static void +print_lladdr(struct sockaddr_dl *sdl) +{ + if (match_ether(sdl)) { + print_ether((struct ether_addr *)LLADDR(sdl), "ether"); } else { - n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0; + int n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0; printf("\tlladdr %s\n", link_ntoa(sdl) + n); } +} + +static void +print_pcp(if_ctx *ctx) +{ + struct ifreq ifr = {}; + + if (ioctl_ctx_ifr(ctx, SIOCGLANPCP, &ifr) == 0 && + ifr.ifr_lan_pcp != IFNET_PCP_NONE) + printf("\tpcp %d\n", ifr.ifr_lan_pcp); +} + +#ifdef WITHOUT_NETLINK +static void +link_status(if_ctx *ctx, const struct ifaddrs *ifa) +{ + /* XXX no const 'cuz LLADDR is defined wrong */ + struct sockaddr_dl *sdl; + struct ifreq ifr; + int rc, sock_hw; + static const u_char laggaddr[6] = {0}; + + sdl = satosdl(ifa->ifa_addr); + if (sdl == NULL || sdl->sdl_alen == 0) + return; + + print_lladdr(sdl); /* * Best-effort (i.e. failures are silent) to get original @@ -118,21 +154,37 @@ link_status(int s __unused, const struct ifaddrs *ifa) memcmp(ifr.ifr_addr.sa_data, LLADDR(sdl), sdl->sdl_alen) == 0) goto pcp; - ether_format = ether_ntoa((const struct ether_addr *) - &ifr.ifr_addr.sa_data); - if (f_ether != NULL && strcmp(f_ether, "dash") == 0) { - for (format_char = strchr(ether_format, ':'); - format_char != NULL; - format_char = strchr(ether_format, ':')) - *format_char = '-'; - } - printf("\thwaddr %s\n", ether_format); - + print_ether((const struct ether_addr *)&ifr.ifr_addr.sa_data, "hwaddr"); pcp: - if (ioctl(s, SIOCGLANPCP, (caddr_t)&ifr) == 0 && - ifr.ifr_lan_pcp != IFNET_PCP_NONE) - printf("\tpcp %d\n", ifr.ifr_lan_pcp); + print_pcp(ctx); +} + +#else + +static void +link_status_nl(if_ctx *ctx, if_link_t *link, if_addr_t *ifa __unused) +{ + if (link->ifla_address != NULL) { + struct sockaddr_dl sdl = { + .sdl_len = sizeof(struct sockaddr_dl), + .sdl_family = AF_LINK, + .sdl_type = convert_iftype(link->ifi_type), + .sdl_alen = NLA_DATA_LEN(link->ifla_address), + }; + memcpy(LLADDR(&sdl), NLA_DATA(link->ifla_address), sdl.sdl_alen); + print_lladdr(&sdl); + + if (link->iflaf_orig_hwaddr != NULL) { + struct nlattr *hwaddr = link->iflaf_orig_hwaddr; + + if (memcmp(NLA_DATA(hwaddr), NLA_DATA(link->ifla_address), sdl.sdl_alen)) + print_ether((struct ether_addr *)NLA_DATA(hwaddr), "hwaddr"); + } + } + if (convert_iftype(link->ifi_type) == IFT_ETHER) + print_pcp(ctx); } +#endif static void link_getaddr(const char *addr, int which) @@ -158,7 +210,8 @@ link_getaddr(const char *addr, int which) temp[0] = ':'; strcpy(temp + 1, addr); sdl.sdl_len = sizeof(sdl); - link_addr(temp, &sdl); + if (link_addr(temp, &sdl) == -1) + errx(1, "malformed link-level address"); free(temp); } if (sdl.sdl_alen > sizeof(sa->sa_data)) @@ -171,26 +224,41 @@ link_getaddr(const char *addr, int which) static struct afswtch af_link = { .af_name = "link", .af_af = AF_LINK, +#ifdef WITHOUT_NETLINK .af_status = link_status, +#else + .af_status = link_status_nl, +#endif .af_getaddr = link_getaddr, .af_aifaddr = SIOCSIFLLADDR, .af_addreq = &link_ridreq, + .af_exec = af_exec_ioctl, }; static struct afswtch af_ether = { .af_name = "ether", .af_af = AF_LINK, +#ifdef WITHOUT_NETLINK .af_status = link_status, +#else + .af_status = link_status_nl, +#endif .af_getaddr = link_getaddr, .af_aifaddr = SIOCSIFLLADDR, .af_addreq = &link_ridreq, + .af_exec = af_exec_ioctl, }; static struct afswtch af_lladdr = { .af_name = "lladdr", .af_af = AF_LINK, +#ifdef WITHOUT_NETLINK .af_status = link_status, +#else + .af_status = link_status_nl, +#endif .af_getaddr = link_getaddr, .af_aifaddr = SIOCSIFLLADDR, .af_addreq = &link_ridreq, + .af_exec = af_exec_ioctl, }; static __constructor void diff --git a/sbin/ifconfig/af_nd6.c b/sbin/ifconfig/af_nd6.c index b6cda30dc06d..2899ad6a0778 100644 --- a/sbin/ifconfig/af_nd6.c +++ b/sbin/ifconfig/af_nd6.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2009 Hiroki Sato. All rights reserved. * @@ -25,11 +25,6 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <sys/param.h> #include <sys/ioctl.h> #include <sys/socket.h> @@ -57,34 +52,36 @@ static const char rcsid[] = #include "ifconfig.h" #define MAX_SYSCTL_TRY 5 +static const char *ND6BITS[] = { + [0] = "PERFORMNUD", + [1] = "ACCEPT_RTADV", + [2] = "PREFER_SOURCE", + [3] = "IFDISABLED", + [4] = "DONT_SET_IFROUTE", + [5] = "AUTO_LINKLOCAL", + [6] = "NO_RADR", + [7] = "NO_PREFER_IFACE", + [8] = "NO_DAD", #ifdef DRAFT_IETF_6MAN_IPV6ONLY_FLAG -#define ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \ - "\004IFDISABLED\005DONT_SET_IFROUTE\006AUTO_LINKLOCAL" \ - "\007NO_RADR\010NO_PREFER_IFACE\011NO_DAD" \ - "\012IPV6_ONLY\013IPV6_ONLY_MANUAL" \ - "\020DEFAULTIF" -#else -#define ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \ - "\004IFDISABLED\005DONT_SET_IFROUTE\006AUTO_LINKLOCAL" \ - "\007NO_RADR\010NO_PREFER_IFACE\011NO_DAD\020DEFAULTIF" + [9] = "IPV6_ONLY", + [10] = "IPV6_ONLY_MANUAL", #endif + [15] = "DEFAULTIF", +}; -static int isnd6defif(int); -void setnd6flags(const char *, int, int, const struct afswtch *); -void setnd6defif(const char *, int, int, const struct afswtch *); -void nd6_status(int); +static int isnd6defif(if_ctx *ctx, int s); +void setnd6flags(if_ctx *, const char *, int); +void setnd6defif(if_ctx *,const char *, int); +void nd6_status(if_ctx *); void -setnd6flags(const char *dummyaddr __unused, - int d, int s, - const struct afswtch *afp) +setnd6flags(if_ctx *ctx, const char *dummyaddr __unused, int d) { - struct in6_ndireq nd; + struct in6_ndireq nd = {}; int error; - memset(&nd, 0, sizeof(nd)); - strlcpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname)); - error = ioctl(s, SIOCGIFINFO_IN6, &nd); + strlcpy(nd.ifname, ctx->ifname, sizeof(nd.ifname)); + error = ioctl_ctx(ctx, SIOCGIFINFO_IN6, &nd); if (error) { warn("ioctl(SIOCGIFINFO_IN6)"); return; @@ -93,25 +90,22 @@ setnd6flags(const char *dummyaddr __unused, nd.ndi.flags &= ~(-d); else nd.ndi.flags |= d; - error = ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd); + error = ioctl_ctx(ctx, SIOCSIFINFO_IN6, (caddr_t)&nd); if (error) warn("ioctl(SIOCSIFINFO_IN6)"); } void -setnd6defif(const char *dummyaddr __unused, - int d, int s, - const struct afswtch *afp) +setnd6defif(if_ctx *ctx, const char *dummyaddr __unused, int d) { - struct in6_ndifreq ndifreq; + struct in6_ndifreq ndifreq = {}; int ifindex; int error; - memset(&ndifreq, 0, sizeof(ndifreq)); - strlcpy(ndifreq.ifname, ifr.ifr_name, sizeof(ndifreq.ifname)); + strlcpy(ndifreq.ifname, ctx->ifname, sizeof(ndifreq.ifname)); if (d < 0) { - if (isnd6defif(s)) { + if (isnd6defif(ctx, ctx->io_s)) { /* ifindex = 0 means to remove default if */ ifindex = 0; } else @@ -122,20 +116,19 @@ setnd6defif(const char *dummyaddr __unused, } ndifreq.ifindex = ifindex; - error = ioctl(s, SIOCSDEFIFACE_IN6, (caddr_t)&ndifreq); + error = ioctl_ctx(ctx, SIOCSDEFIFACE_IN6, (caddr_t)&ndifreq); if (error) warn("ioctl(SIOCSDEFIFACE_IN6)"); } static int -isnd6defif(int s) +isnd6defif(if_ctx *ctx, int s) { - struct in6_ndifreq ndifreq; + struct in6_ndifreq ndifreq = {}; unsigned int ifindex; int error; - memset(&ndifreq, 0, sizeof(ndifreq)); - strlcpy(ndifreq.ifname, ifr.ifr_name, sizeof(ndifreq.ifname)); + strlcpy(ndifreq.ifname, ctx->ifname, sizeof(ndifreq.ifname)); ifindex = if_nametoindex(ndifreq.ifname); error = ioctl(s, SIOCGDEFIFACE_IN6, (caddr_t)&ndifreq); @@ -147,15 +140,15 @@ isnd6defif(int s) } void -nd6_status(int s) +nd6_status(if_ctx *ctx) { - struct in6_ndireq nd; + struct in6_ndireq nd = {}; int s6; int error; int isdefif; + uint32_t bits; - memset(&nd, 0, sizeof(nd)); - strlcpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname)); + strlcpy(nd.ifname, ctx->ifname, sizeof(nd.ifname)); if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { if (errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT) warn("socket(AF_INET6, SOCK_DGRAM)"); @@ -168,11 +161,12 @@ nd6_status(int s) close(s6); return; } - isdefif = isnd6defif(s6); + isdefif = isnd6defif(ctx, s6); close(s6); if (nd.ndi.flags == 0 && !isdefif) return; - printb("\tnd6 options", - (unsigned int)(nd.ndi.flags | (isdefif << 15)), ND6BITS); + bits = (nd.ndi.flags | (isdefif << 15)); + printf("\tnd6 options=%x", bits); + print_bits("options", &bits, 1, ND6BITS, nitems(ND6BITS)); putchar('\n'); } diff --git a/sbin/ifconfig/carp.c b/sbin/ifconfig/carp.c index 23a119e3b9d7..7c7398f92d48 100644 --- a/sbin/ifconfig/carp.c +++ b/sbin/ifconfig/carp.c @@ -1,8 +1,7 @@ -/* $FreeBSD$ */ /* from $OpenBSD: ifconfig.c,v 1.82 2003/10/19 05:43:35 mcbride Exp $ */ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2002 Michael Shalayeff. All rights reserved. * Copyright (c) 2003 Ryan McBride. All rights reserved. @@ -42,13 +41,17 @@ #include <netinet/in_var.h> #include <netinet/ip_carp.h> +#include <arpa/inet.h> + #include <ctype.h> +#include <stdbool.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <err.h> #include <errno.h> +#include <netdb.h> #include <libifconfig.h> @@ -56,41 +59,58 @@ static const char *carp_states[] = { CARP_STATES }; -static void carp_status(int s); -static void setcarp_vhid(const char *, int, int, const struct afswtch *rafp); -static void setcarp_callback(int, void *); -static void setcarp_advbase(const char *,int, int, const struct afswtch *rafp); -static void setcarp_advskew(const char *, int, int, const struct afswtch *rafp); -static void setcarp_passwd(const char *, int, int, const struct afswtch *rafp); +static void setcarp_callback(if_ctx *, void *); static int carpr_vhid = -1; static int carpr_advskew = -1; static int carpr_advbase = -1; static int carpr_state = -1; +static struct in_addr carp_addr; +static struct in6_addr carp_addr6; static unsigned char const *carpr_key; +static carp_version_t carpr_version; +static uint8_t carpr_vrrp_prio; +static uint16_t carpr_vrrp_adv_inter; static void -carp_status(int s) +carp_status(if_ctx *ctx) { - struct carpreq carpr[CARP_MAXVHID]; + struct ifconfig_carp carpr[CARP_MAXVHID]; + char addr_buf[NI_MAXHOST]; - if (ifconfig_carp_get_info(lifh, name, carpr, CARP_MAXVHID) == -1) + if (ifconfig_carp_get_info(lifh, ctx->ifname, carpr, CARP_MAXVHID) == -1) return; for (size_t i = 0; i < carpr[0].carpr_count; i++) { - printf("\tcarp: %s vhid %d advbase %d advskew %d", - carp_states[carpr[i].carpr_state], carpr[i].carpr_vhid, - carpr[i].carpr_advbase, carpr[i].carpr_advskew); - if (printkeys && carpr[i].carpr_key[0] != '\0') - printf(" key \"%s\"\n", carpr[i].carpr_key); - else - printf("\n"); + switch (carpr[i].carpr_version) { + case CARP_VERSION_CARP: + printf("\tcarp: %s vhid %d advbase %d advskew %d", + carp_states[carpr[i].carpr_state], carpr[i].carpr_vhid, + carpr[i].carpr_advbase, carpr[i].carpr_advskew); + if (ctx->args->printkeys && carpr[i].carpr_key[0] != '\0') + printf(" key \"%s\"\n", carpr[i].carpr_key); + else + printf("\n"); + + inet_ntop(AF_INET6, &carpr[i].carpr_addr6, addr_buf, + sizeof(addr_buf)); + + printf("\t peer %s peer6 %s\n", + inet_ntoa(carpr[i].carpr_addr), addr_buf); + break; + case CARP_VERSION_VRRPv3: + printf("\tvrrp: %s vrid %d prio %d interval %d\n", + carp_states[carpr[i].carpr_state], carpr[i].carpr_vhid, + carpr[i].carpr_vrrp_prio, carpr[i].carpr_vrrp_adv_inter); + break; + } } } static void -setcarp_vhid(const char *val, int d, int s, const struct afswtch *afp) +setcarp_vhid(if_ctx *ctx, const char *val, int dummy __unused) { + const struct afswtch *afp = ctx->afp; carpr_vhid = atoi(val); @@ -98,47 +118,23 @@ setcarp_vhid(const char *val, int d, int s, const struct afswtch *afp) errx(1, "vhid must be greater than 0 and less than %u", CARP_MAXVHID); - switch (afp->af_af) { -#ifdef INET - case AF_INET: - { - struct in_aliasreq *ifra; - - ifra = (struct in_aliasreq *)afp->af_addreq; - ifra->ifra_vhid = carpr_vhid; - break; - } -#endif -#ifdef INET6 - case AF_INET6: - { - struct in6_aliasreq *ifra; - - ifra = (struct in6_aliasreq *)afp->af_addreq; - ifra->ifra_vhid = carpr_vhid; - break; - } -#endif - default: + if (afp->af_setvhid == NULL) errx(1, "%s doesn't support carp(4)", afp->af_name); - } - + afp->af_setvhid(carpr_vhid); callback_register(setcarp_callback, NULL); } static void -setcarp_callback(int s, void *arg __unused) +setcarp_callback(if_ctx *ctx, void *arg __unused) { - struct carpreq carpr; - - bzero(&carpr, sizeof(struct carpreq)); - carpr.carpr_vhid = carpr_vhid; - carpr.carpr_count = 1; - ifr.ifr_data = (caddr_t)&carpr; + struct ifconfig_carp carpr = { }; - if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1 && errno != ENOENT) - err(1, "SIOCGVH"); + if (ifconfig_carp_get_vhid(lifh, ctx->ifname, &carpr, carpr_vhid) == -1) { + if (ifconfig_err_errno(lifh) != ENOENT) + return; + } + carpr.carpr_vhid = carpr_vhid; if (carpr_key != NULL) /* XXX Should hash the password into the key here? */ strlcpy(carpr.carpr_key, carpr_key, CARP_KEY_LEN); @@ -148,13 +144,24 @@ setcarp_callback(int s, void *arg __unused) carpr.carpr_advbase = carpr_advbase; if (carpr_state > -1) carpr.carpr_state = carpr_state; - - if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) + if (carp_addr.s_addr != INADDR_ANY) + carpr.carpr_addr = carp_addr; + if (! IN6_IS_ADDR_UNSPECIFIED(&carp_addr6)) + memcpy(&carpr.carpr_addr6, &carp_addr6, + sizeof(carp_addr6)); + if (carpr_version != 0) + carpr.carpr_version = carpr_version; + if (carpr_vrrp_prio != 0) + carpr.carpr_vrrp_prio = carpr_vrrp_prio; + if (carpr_vrrp_adv_inter != 0) + carpr.carpr_vrrp_adv_inter = carpr_vrrp_adv_inter; + + if (ifconfig_carp_set_info(lifh, ctx->ifname, &carpr)) err(1, "SIOCSVH"); } static void -setcarp_passwd(const char *val, int d, int s, const struct afswtch *afp) +setcarp_passwd(if_ctx *ctx __unused, const char *val, int dummy __unused) { if (carpr_vhid == -1) @@ -164,7 +171,7 @@ setcarp_passwd(const char *val, int d, int s, const struct afswtch *afp) } static void -setcarp_advskew(const char *val, int d, int s, const struct afswtch *afp) +setcarp_advskew(if_ctx *ctx __unused, const char *val, int dummy __unused) { if (carpr_vhid == -1) @@ -174,7 +181,7 @@ setcarp_advskew(const char *val, int d, int s, const struct afswtch *afp) } static void -setcarp_advbase(const char *val, int d, int s, const struct afswtch *afp) +setcarp_advbase(if_ctx *ctx __unused, const char *val, int dummy __unused) { if (carpr_vhid == -1) @@ -184,7 +191,7 @@ setcarp_advbase(const char *val, int d, int s, const struct afswtch *afp) } static void -setcarp_state(const char *val, int d, int s, const struct afswtch *afp) +setcarp_state(if_ctx *ctx __unused, const char *val, int dummy __unused) { int i; @@ -200,12 +207,81 @@ setcarp_state(const char *val, int d, int s, const struct afswtch *afp) errx(1, "unknown state"); } +static void +setcarp_peer(if_ctx *ctx __unused, const char *val, int dummy __unused) +{ + carp_addr.s_addr = inet_addr(val); +} + +static void +setcarp_mcast(if_ctx *ctx __unused, const char *val __unused, int dummy __unused) +{ + carp_addr.s_addr = htonl(INADDR_CARP_GROUP); +} + +static void +setcarp_peer6(if_ctx *ctx __unused, const char *val, int dummy __unused) +{ + struct addrinfo hints, *res; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_flags = AI_NUMERICHOST; + + if (getaddrinfo(val, NULL, &hints, &res) != 0) + errx(1, "Invalid IPv6 address %s", val); + + memcpy(&carp_addr6, &(satosin6(res->ai_addr))->sin6_addr, sizeof(carp_addr6)); + freeaddrinfo(res); +} + +static void +setcarp_mcast6(if_ctx *ctx __unused, const char *val __unused, int dummy __unused) +{ + bzero(&carp_addr6, sizeof(carp_addr6)); + carp_addr6.s6_addr[0] = 0xff; + carp_addr6.s6_addr[1] = 0x02; + carp_addr6.s6_addr[15] = 0x12; +} + +static void +setcarp_version(if_ctx *ctx __unused, const char *val, int dummy __unused) +{ + carpr_version = atoi(val); + + if (carpr_version != CARP_VERSION_CARP && carpr_version != CARP_VERSION_VRRPv3) + errx(1, "version must be %d or %d", CARP_VERSION_CARP, + CARP_VERSION_VRRPv3); +} + +static void +setvrrp_prio(if_ctx *ctx __unused, const char *val, int dummy __unused) +{ + carpr_vrrp_prio = atoi(val); +} + +static void +setvrrp_interval(if_ctx *ctx __unused, const char *val, int dummy __unused) +{ + carpr_vrrp_adv_inter = atoi(val); + + if (carpr_vrrp_adv_inter == 0 || carpr_vrrp_adv_inter > VRRP_MAX_INTERVAL) + errx(1, "vrrpinterval must be greater than 0 and less than %d", VRRP_MAX_INTERVAL); +} + static struct cmd carp_cmds[] = { DEF_CMD_ARG("advbase", setcarp_advbase), DEF_CMD_ARG("advskew", setcarp_advskew), DEF_CMD_ARG("pass", setcarp_passwd), DEF_CMD_ARG("vhid", setcarp_vhid), DEF_CMD_ARG("state", setcarp_state), + DEF_CMD_ARG("peer", setcarp_peer), + DEF_CMD("mcast", 0, setcarp_mcast), + DEF_CMD_ARG("peer6", setcarp_peer6), + DEF_CMD("mcast6", 0, setcarp_mcast6), + DEF_CMD_ARG("carpver", setcarp_version), + DEF_CMD_ARG("vrrpprio", setvrrp_prio), + DEF_CMD_ARG("vrrpinterval", setvrrp_interval), }; static struct afswtch af_carp = { .af_name = "af_carp", @@ -216,9 +292,7 @@ static struct afswtch af_carp = { static __constructor void carp_ctor(void) { - int i; - - for (i = 0; i < nitems(carp_cmds); i++) + for (size_t i = 0; i < nitems(carp_cmds); i++) cmd_register(&carp_cmds[i]); af_register(&af_carp); } diff --git a/sbin/ifconfig/ifbridge.c b/sbin/ifconfig/ifbridge.c index 2bd9c96f2489..ce5d2f4894fa 100644 --- a/sbin/ifconfig/ifbridge.c +++ b/sbin/ifconfig/ifbridge.c @@ -35,11 +35,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <sys/param.h> #include <sys/ioctl.h> #include <sys/socket.h> @@ -85,28 +80,26 @@ get_val(const char *cp, u_long *valp) } static int -do_cmd(int sock, u_long op, void *arg, size_t argsize, int set) +do_cmd(if_ctx *ctx, u_long op, void *arg, size_t argsize, int set) { - struct ifdrv ifd; - - memset(&ifd, 0, sizeof(ifd)); + struct ifdrv ifd = {}; - strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name)); + strlcpy(ifd.ifd_name, ctx->ifname, sizeof(ifd.ifd_name)); ifd.ifd_cmd = op; ifd.ifd_len = argsize; ifd.ifd_data = arg; - return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd)); + return (ioctl_ctx(ctx, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd)); } static void -do_bridgeflag(int sock, const char *ifs, int flag, int set) +do_bridgeflag(if_ctx *ctx, const char *ifs, int flag, int set) { struct ifbreq req; strlcpy(req.ifbr_ifsname, ifs, sizeof(req.ifbr_ifsname)); - if (do_cmd(sock, BRDGGIFFLGS, &req, sizeof(req), 0) < 0) + if (do_cmd(ctx, BRDGGIFFLGS, &req, sizeof(req), 0) < 0) err(1, "unable to get bridge flags"); if (set) @@ -114,17 +107,17 @@ do_bridgeflag(int sock, const char *ifs, int flag, int set) else req.ifbr_ifsflags &= ~flag; - if (do_cmd(sock, BRDGSIFFLGS, &req, sizeof(req), 1) < 0) + if (do_cmd(ctx, BRDGSIFFLGS, &req, sizeof(req), 1) < 0) err(1, "unable to set bridge flags"); } static void -bridge_addresses(int s, const char *prefix) +bridge_addresses(if_ctx *ctx, const char *prefix) { struct ifbaconf ifbac; struct ifbareq *ifba; char *inbuf = NULL, *ninbuf; - int i, len = 8192; + size_t len = 8192; struct ether_addr ea; for (;;) { @@ -133,14 +126,14 @@ bridge_addresses(int s, const char *prefix) err(1, "unable to allocate address buffer"); ifbac.ifbac_len = len; ifbac.ifbac_buf = inbuf = ninbuf; - if (do_cmd(s, BRDGRTS, &ifbac, sizeof(ifbac), 0) < 0) + if (do_cmd(ctx, BRDGRTS, &ifbac, sizeof(ifbac), 0) < 0) err(1, "unable to get address cache"); if ((ifbac.ifbac_len + sizeof(*ifba)) < len) break; len *= 2; } - for (i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) { + for (unsigned long i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) { ifba = ifbac.ifbac_req + i; memcpy(ea.octet, ifba->ifba_dst, sizeof(ea.octet)); @@ -154,7 +147,37 @@ bridge_addresses(int s, const char *prefix) } static void -bridge_status(int s) +print_vlans(ifbvlan_set_t *vlans) +{ + unsigned printed = 0; + + for (unsigned vlan = DOT1Q_VID_MIN; vlan <= DOT1Q_VID_MAX;) { + unsigned last; + + if (!BRVLAN_TEST(vlans, vlan)) { + ++vlan; + continue; + } + + last = vlan; + while (last < DOT1Q_VID_MAX && BRVLAN_TEST(vlans, last + 1)) + ++last; + + if (printed == 0) + printf(" tagged "); + else + printf(","); + + printf("%u", vlan); + if (last != vlan) + printf("-%u", last); + ++printed; + vlan = last + 1; + } +} + +static void +bridge_status(if_ctx *ctx) { struct ifconfig_bridge_status *bridge; struct ifbropreq *params; @@ -162,7 +185,7 @@ bridge_status(int s) uint8_t lladdr[ETHER_ADDR_LEN]; uint16_t bprio; - if (ifconfig_bridge_get_bridge_status(lifh, name, &bridge) == -1) + if (ifconfig_bridge_get_bridge_status(lifh, ctx->ifname, &bridge) == -1) return; params = bridge->params; @@ -218,6 +241,9 @@ bridge_status(int s) else printf(" <unknown state %d>", state); } + if (member->ifbr_untagged != 0) + printf(" untagged %u", (unsigned)member->ifbr_untagged); + print_vlans(&bridge->member_vlans[i]); printf("\n"); } @@ -225,178 +251,177 @@ bridge_status(int s) } static void -setbridge_add(const char *val, int d, int s, const struct afswtch *afp) +setbridge_add(if_ctx *ctx, const char *val, int dummy __unused) { struct ifbreq req; memset(&req, 0, sizeof(req)); strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); - if (do_cmd(s, BRDGADD, &req, sizeof(req), 1) < 0) + if (do_cmd(ctx, BRDGADD, &req, sizeof(req), 1) < 0) err(1, "BRDGADD %s", val); } static void -setbridge_delete(const char *val, int d, int s, const struct afswtch *afp) +setbridge_delete(if_ctx *ctx, const char *val, int dummy __unused) { struct ifbreq req; memset(&req, 0, sizeof(req)); strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); - if (do_cmd(s, BRDGDEL, &req, sizeof(req), 1) < 0) + if (do_cmd(ctx, BRDGDEL, &req, sizeof(req), 1) < 0) err(1, "BRDGDEL %s", val); } static void -setbridge_discover(const char *val, int d, int s, const struct afswtch *afp) +setbridge_discover(if_ctx *ctx, const char *val, int dummy __unused) { - do_bridgeflag(s, val, IFBIF_DISCOVER, 1); + do_bridgeflag(ctx, val, IFBIF_DISCOVER, 1); } static void -unsetbridge_discover(const char *val, int d, int s, const struct afswtch *afp) +unsetbridge_discover(if_ctx *ctx, const char *val, int dummy __unused) { - do_bridgeflag(s, val, IFBIF_DISCOVER, 0); + do_bridgeflag(ctx, val, IFBIF_DISCOVER, 0); } static void -setbridge_learn(const char *val, int d, int s, const struct afswtch *afp) +setbridge_learn(if_ctx *ctx, const char *val, int dummy __unused) { - do_bridgeflag(s, val, IFBIF_LEARNING, 1); + do_bridgeflag(ctx, val, IFBIF_LEARNING, 1); } static void -unsetbridge_learn(const char *val, int d, int s, const struct afswtch *afp) +unsetbridge_learn(if_ctx *ctx, const char *val, int dummy __unused) { - do_bridgeflag(s, val, IFBIF_LEARNING, 0); + do_bridgeflag(ctx, val, IFBIF_LEARNING, 0); } static void -setbridge_sticky(const char *val, int d, int s, const struct afswtch *afp) +setbridge_sticky(if_ctx *ctx, const char *val, int dummy __unused) { - do_bridgeflag(s, val, IFBIF_STICKY, 1); + do_bridgeflag(ctx, val, IFBIF_STICKY, 1); } static void -unsetbridge_sticky(const char *val, int d, int s, const struct afswtch *afp) +unsetbridge_sticky(if_ctx *ctx, const char *val, int dummy __unused) { - do_bridgeflag(s, val, IFBIF_STICKY, 0); + do_bridgeflag(ctx, val, IFBIF_STICKY, 0); } static void -setbridge_span(const char *val, int d, int s, const struct afswtch *afp) +setbridge_span(if_ctx *ctx, const char *val, int dummy __unused) { struct ifbreq req; memset(&req, 0, sizeof(req)); strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); - if (do_cmd(s, BRDGADDS, &req, sizeof(req), 1) < 0) + if (do_cmd(ctx, BRDGADDS, &req, sizeof(req), 1) < 0) err(1, "BRDGADDS %s", val); } static void -unsetbridge_span(const char *val, int d, int s, const struct afswtch *afp) +unsetbridge_span(if_ctx *ctx, const char *val, int dummy __unused) { struct ifbreq req; memset(&req, 0, sizeof(req)); strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); - if (do_cmd(s, BRDGDELS, &req, sizeof(req), 1) < 0) + if (do_cmd(ctx, BRDGDELS, &req, sizeof(req), 1) < 0) err(1, "BRDGDELS %s", val); } static void -setbridge_stp(const char *val, int d, int s, const struct afswtch *afp) +setbridge_stp(if_ctx *ctx, const char *val, int dummy __unused) { - do_bridgeflag(s, val, IFBIF_STP, 1); + do_bridgeflag(ctx, val, IFBIF_STP, 1); } static void -unsetbridge_stp(const char *val, int d, int s, const struct afswtch *afp) +unsetbridge_stp(if_ctx *ctx, const char *val, int dummy __unused) { - do_bridgeflag(s, val, IFBIF_STP, 0); + do_bridgeflag(ctx, val, IFBIF_STP, 0); } static void -setbridge_edge(const char *val, int d, int s, const struct afswtch *afp) +setbridge_edge(if_ctx *ctx, const char *val, int dummy __unused) { - do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 1); + do_bridgeflag(ctx, val, IFBIF_BSTP_EDGE, 1); } static void -unsetbridge_edge(const char *val, int d, int s, const struct afswtch *afp) +unsetbridge_edge(if_ctx *ctx, const char *val, int dummy __unused) { - do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 0); + do_bridgeflag(ctx, val, IFBIF_BSTP_EDGE, 0); } static void -setbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp) +setbridge_autoedge(if_ctx *ctx, const char *val, int dummy __unused) { - do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 1); + do_bridgeflag(ctx, val, IFBIF_BSTP_AUTOEDGE, 1); } static void -unsetbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp) +unsetbridge_autoedge(if_ctx *ctx, const char *val, int dummy __unused) { - do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 0); + do_bridgeflag(ctx, val, IFBIF_BSTP_AUTOEDGE, 0); } static void -setbridge_ptp(const char *val, int d, int s, const struct afswtch *afp) +setbridge_ptp(if_ctx *ctx, const char *val, int dummy __unused) { - do_bridgeflag(s, val, IFBIF_BSTP_PTP, 1); + do_bridgeflag(ctx, val, IFBIF_BSTP_PTP, 1); } static void -unsetbridge_ptp(const char *val, int d, int s, const struct afswtch *afp) +unsetbridge_ptp(if_ctx *ctx, const char *val, int dummy __unused) { - do_bridgeflag(s, val, IFBIF_BSTP_PTP, 0); + do_bridgeflag(ctx, val, IFBIF_BSTP_PTP, 0); } static void -setbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp) +setbridge_autoptp(if_ctx *ctx, const char *val, int dummy __unused) { - do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 1); + do_bridgeflag(ctx, val, IFBIF_BSTP_AUTOPTP, 1); } static void -unsetbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp) +unsetbridge_autoptp(if_ctx *ctx, const char *val, int dummy __unused) { - do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 0); + do_bridgeflag(ctx, val, IFBIF_BSTP_AUTOPTP, 0); } static void -setbridge_flush(const char *val, int d, int s, const struct afswtch *afp) +setbridge_flush(if_ctx *ctx, const char *val __unused, int dummy __unused) { struct ifbreq req; memset(&req, 0, sizeof(req)); req.ifbr_ifsflags = IFBF_FLUSHDYN; - if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0) + if (do_cmd(ctx, BRDGFLUSH, &req, sizeof(req), 1) < 0) err(1, "BRDGFLUSH"); } static void -setbridge_flushall(const char *val, int d, int s, const struct afswtch *afp) +setbridge_flushall(if_ctx *ctx, const char *val __unused, int dummy __unused) { struct ifbreq req; memset(&req, 0, sizeof(req)); req.ifbr_ifsflags = IFBF_FLUSHALL; - if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0) + if (do_cmd(ctx, BRDGFLUSH, &req, sizeof(req), 1) < 0) err(1, "BRDGFLUSH"); } static void -setbridge_static(const char *val, const char *mac, int s, - const struct afswtch *afp) +setbridge_static(if_ctx *ctx, const char *val, const char *mac) { struct ifbareq req; struct ether_addr *ea; @@ -410,14 +435,14 @@ setbridge_static(const char *val, const char *mac, int s, memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst)); req.ifba_flags = IFBAF_STATIC; - req.ifba_vlan = 1; /* XXX allow user to specify */ + req.ifba_vlan = 0; /* XXX allow user to specify */ - if (do_cmd(s, BRDGSADDR, &req, sizeof(req), 1) < 0) + if (do_cmd(ctx, BRDGSADDR, &req, sizeof(req), 1) < 0) err(1, "BRDGSADDR %s", val); } static void -setbridge_deladdr(const char *val, int d, int s, const struct afswtch *afp) +setbridge_deladdr(if_ctx *ctx, const char *val, int dummy __unused) { struct ifbareq req; struct ether_addr *ea; @@ -430,19 +455,19 @@ setbridge_deladdr(const char *val, int d, int s, const struct afswtch *afp) memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst)); - if (do_cmd(s, BRDGDADDR, &req, sizeof(req), 1) < 0) + if (do_cmd(ctx, BRDGDADDR, &req, sizeof(req), 1) < 0) err(1, "BRDGDADDR %s", val); } static void -setbridge_addr(const char *val, int d, int s, const struct afswtch *afp) +setbridge_addr(if_ctx *ctx, const char *val __unused, int dummy __unused) { - bridge_addresses(s, ""); + bridge_addresses(ctx, ""); } static void -setbridge_maxaddr(const char *arg, int d, int s, const struct afswtch *afp) +setbridge_maxaddr(if_ctx *ctx, const char *arg, int dummy __unused) { struct ifbrparam param; u_long val; @@ -452,12 +477,12 @@ setbridge_maxaddr(const char *arg, int d, int s, const struct afswtch *afp) param.ifbrp_csize = val & 0xffffffff; - if (do_cmd(s, BRDGSCACHE, ¶m, sizeof(param), 1) < 0) + if (do_cmd(ctx, BRDGSCACHE, ¶m, sizeof(param), 1) < 0) err(1, "BRDGSCACHE %s", arg); } static void -setbridge_hellotime(const char *arg, int d, int s, const struct afswtch *afp) +setbridge_hellotime(if_ctx *ctx, const char *arg, int dummy __unused) { struct ifbrparam param; u_long val; @@ -467,12 +492,12 @@ setbridge_hellotime(const char *arg, int d, int s, const struct afswtch *afp) param.ifbrp_hellotime = val & 0xff; - if (do_cmd(s, BRDGSHT, ¶m, sizeof(param), 1) < 0) + if (do_cmd(ctx, BRDGSHT, ¶m, sizeof(param), 1) < 0) err(1, "BRDGSHT %s", arg); } static void -setbridge_fwddelay(const char *arg, int d, int s, const struct afswtch *afp) +setbridge_fwddelay(if_ctx *ctx, const char *arg, int dummy __unused) { struct ifbrparam param; u_long val; @@ -482,12 +507,12 @@ setbridge_fwddelay(const char *arg, int d, int s, const struct afswtch *afp) param.ifbrp_fwddelay = val & 0xff; - if (do_cmd(s, BRDGSFD, ¶m, sizeof(param), 1) < 0) + if (do_cmd(ctx, BRDGSFD, ¶m, sizeof(param), 1) < 0) err(1, "BRDGSFD %s", arg); } static void -setbridge_maxage(const char *arg, int d, int s, const struct afswtch *afp) +setbridge_maxage(if_ctx *ctx, const char *arg, int dummy __unused) { struct ifbrparam param; u_long val; @@ -497,12 +522,12 @@ setbridge_maxage(const char *arg, int d, int s, const struct afswtch *afp) param.ifbrp_maxage = val & 0xff; - if (do_cmd(s, BRDGSMA, ¶m, sizeof(param), 1) < 0) + if (do_cmd(ctx, BRDGSMA, ¶m, sizeof(param), 1) < 0) err(1, "BRDGSMA %s", arg); } static void -setbridge_priority(const char *arg, int d, int s, const struct afswtch *afp) +setbridge_priority(if_ctx *ctx, const char *arg, int dummy __unused) { struct ifbrparam param; u_long val; @@ -512,12 +537,12 @@ setbridge_priority(const char *arg, int d, int s, const struct afswtch *afp) param.ifbrp_prio = val & 0xffff; - if (do_cmd(s, BRDGSPRI, ¶m, sizeof(param), 1) < 0) + if (do_cmd(ctx, BRDGSPRI, ¶m, sizeof(param), 1) < 0) err(1, "BRDGSPRI %s", arg); } static void -setbridge_protocol(const char *arg, int d, int s, const struct afswtch *afp) +setbridge_protocol(if_ctx *ctx, const char *arg, int dummy __unused) { struct ifbrparam param; @@ -529,12 +554,12 @@ setbridge_protocol(const char *arg, int d, int s, const struct afswtch *afp) errx(1, "unknown stp protocol"); } - if (do_cmd(s, BRDGSPROTO, ¶m, sizeof(param), 1) < 0) + if (do_cmd(ctx, BRDGSPROTO, ¶m, sizeof(param), 1) < 0) err(1, "BRDGSPROTO %s", arg); } static void -setbridge_holdcount(const char *arg, int d, int s, const struct afswtch *afp) +setbridge_holdcount(if_ctx *ctx, const char *arg, int dummy __unused) { struct ifbrparam param; u_long val; @@ -544,13 +569,12 @@ setbridge_holdcount(const char *arg, int d, int s, const struct afswtch *afp) param.ifbrp_txhc = val & 0xff; - if (do_cmd(s, BRDGSTXHC, ¶m, sizeof(param), 1) < 0) + if (do_cmd(ctx, BRDGSTXHC, ¶m, sizeof(param), 1) < 0) err(1, "BRDGSTXHC %s", arg); } static void -setbridge_ifpriority(const char *ifn, const char *pri, int s, - const struct afswtch *afp) +setbridge_ifpriority(if_ctx *ctx, const char *ifn, const char *pri) { struct ifbreq req; u_long val; @@ -563,13 +587,12 @@ setbridge_ifpriority(const char *ifn, const char *pri, int s, strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); req.ifbr_priority = val & 0xff; - if (do_cmd(s, BRDGSIFPRIO, &req, sizeof(req), 1) < 0) + if (do_cmd(ctx, BRDGSIFPRIO, &req, sizeof(req), 1) < 0) err(1, "BRDGSIFPRIO %s", pri); } static void -setbridge_ifpathcost(const char *ifn, const char *cost, int s, - const struct afswtch *afp) +setbridge_ifpathcost(if_ctx *ctx, const char *ifn, const char *cost) { struct ifbreq req; u_long val; @@ -582,13 +605,51 @@ setbridge_ifpathcost(const char *ifn, const char *cost, int s, strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); req.ifbr_path_cost = val; - if (do_cmd(s, BRDGSIFCOST, &req, sizeof(req), 1) < 0) + if (do_cmd(ctx, BRDGSIFCOST, &req, sizeof(req), 1) < 0) err(1, "BRDGSIFCOST %s", cost); } static void -setbridge_ifmaxaddr(const char *ifn, const char *arg, int s, - const struct afswtch *afp) +setbridge_untagged(if_ctx *ctx, const char *ifn, const char *vlanid) +{ + struct ifbreq req; + u_long val; + + memset(&req, 0, sizeof(req)); + + if (get_val(vlanid, &val) < 0) + errx(1, "invalid VLAN identifier: %s", vlanid); + + /* + * Reject vlan 0, since it's not a valid vlan identifier and has a + * special meaning in the kernel interface. + */ + if (val == 0) + errx(1, "invalid VLAN identifier: %lu", val); + + strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); + req.ifbr_untagged = val; + + if (do_cmd(ctx, BRDGSIFUNTAGGED, &req, sizeof(req), 1) < 0) + err(1, "BRDGSIFUNTAGGED %s", vlanid); +} + +static void +unsetbridge_untagged(if_ctx *ctx, const char *ifn, int dummy __unused) +{ + struct ifbreq req; + + memset(&req, 0, sizeof(req)); + + strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); + req.ifbr_untagged = 0; + + if (do_cmd(ctx, BRDGSIFUNTAGGED, &req, sizeof(req), 1) < 0) + err(1, "BRDGSIFUNTAGGED"); +} + +static void +setbridge_ifmaxaddr(if_ctx *ctx, const char *ifn, const char *arg) { struct ifbreq req; u_long val; @@ -601,12 +662,12 @@ setbridge_ifmaxaddr(const char *ifn, const char *arg, int s, strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); req.ifbr_addrmax = val & 0xffffffff; - if (do_cmd(s, BRDGSIFAMAX, &req, sizeof(req), 1) < 0) + if (do_cmd(ctx, BRDGSIFAMAX, &req, sizeof(req), 1) < 0) err(1, "BRDGSIFAMAX %s", arg); } static void -setbridge_timeout(const char *arg, int d, int s, const struct afswtch *afp) +setbridge_timeout(if_ctx *ctx, const char *arg, int dummy __unused) { struct ifbrparam param; u_long val; @@ -616,22 +677,123 @@ setbridge_timeout(const char *arg, int d, int s, const struct afswtch *afp) param.ifbrp_ctime = val & 0xffffffff; - if (do_cmd(s, BRDGSTO, ¶m, sizeof(param), 1) < 0) + if (do_cmd(ctx, BRDGSTO, ¶m, sizeof(param), 1) < 0) err(1, "BRDGSTO %s", arg); } static void -setbridge_private(const char *val, int d, int s, const struct afswtch *afp) +setbridge_private(if_ctx *ctx, const char *val, int dummy __unused) { + do_bridgeflag(ctx, val, IFBIF_PRIVATE, 1); +} - do_bridgeflag(s, val, IFBIF_PRIVATE, 1); +static void +unsetbridge_private(if_ctx *ctx, const char *val, int dummy __unused) +{ + do_bridgeflag(ctx, val, IFBIF_PRIVATE, 0); } static void -unsetbridge_private(const char *val, int d, int s, const struct afswtch *afp) +setbridge_vlanfilter(if_ctx *ctx, const char *val, int dummy __unused) { + do_bridgeflag(ctx, val, IFBIF_VLANFILTER, 1); +} - do_bridgeflag(s, val, IFBIF_PRIVATE, 0); +static void +unsetbridge_vlanfilter(if_ctx *ctx, const char *val, int dummy __unused) +{ + do_bridgeflag(ctx, val, IFBIF_VLANFILTER, 0); +} + +static int +parse_vlans(ifbvlan_set_t *set, const char *str) +{ + char *s, *token; + + /* "none" means the empty vlan set */ + if (strcmp(str, "none") == 0) { + __BIT_ZERO(BRVLAN_SETSIZE, set); + return (0); + } + + /* "all" means all vlans, except for 0 and 4095 which are reserved */ + if (strcmp(str, "all") == 0) { + __BIT_FILL(BRVLAN_SETSIZE, set); + BRVLAN_CLR(set, DOT1Q_VID_NULL); + BRVLAN_CLR(set, DOT1Q_VID_RSVD_IMPL); + return (0); + } + + if ((s = strdup(str)) == NULL) + return (-1); + + while ((token = strsep(&s, ",")) != NULL) { + unsigned long first, last; + char *p, *lastp; + + if ((lastp = strchr(token, '-')) != NULL) + *lastp++ = '\0'; + + first = last = strtoul(token, &p, 10); + if (*p != '\0') + goto err; + if (first < DOT1Q_VID_MIN || first > DOT1Q_VID_MAX) + goto err; + + if (lastp) { + last = strtoul(lastp, &p, 10); + if (*p != '\0') + goto err; + if (last < DOT1Q_VID_MIN || last > DOT1Q_VID_MAX || + last < first) + goto err; + } + + for (unsigned vlan = first; vlan <= last; ++vlan) + BRVLAN_SET(set, vlan); + } + + free(s); + return (0); + +err: + free(s); + return (-1); +} + +static void +set_bridge_vlanset(if_ctx *ctx, const char *ifn, const char *vlans, int op) +{ + struct ifbif_vlan_req req; + + memset(&req, 0, sizeof(req)); + + if (parse_vlans(&req.bv_set, vlans) != 0) + errx(1, "invalid vlan set: %s", vlans); + + strlcpy(req.bv_ifname, ifn, sizeof(req.bv_ifname)); + req.bv_op = op; + + if (do_cmd(ctx, BRDGSIFVLANSET, &req, sizeof(req), 1) < 0) + err(1, "BRDGSIFVLANSET %s", vlans); +} + +static void +setbridge_tagged(if_ctx *ctx, const char *ifn, const char *vlans) +{ + set_bridge_vlanset(ctx, ifn, vlans, BRDG_VLAN_OP_SET); +} + +static void +addbridge_tagged(if_ctx *ctx, const char *ifn, const char *vlans) +{ + set_bridge_vlanset(ctx, ifn, vlans, BRDG_VLAN_OP_ADD); +} + +static void +delbridge_tagged(if_ctx *ctx, const char *ifn, const char *vlans) +{ + set_bridge_vlanset(ctx, ifn, vlans, BRDG_VLAN_OP_DEL); } static struct cmd bridge_cmds[] = { @@ -670,6 +832,13 @@ static struct cmd bridge_cmds[] = { DEF_CMD_ARG2("ifpriority", setbridge_ifpriority), DEF_CMD_ARG2("ifpathcost", setbridge_ifpathcost), DEF_CMD_ARG2("ifmaxaddr", setbridge_ifmaxaddr), + DEF_CMD_ARG("vlanfilter", setbridge_vlanfilter), + DEF_CMD_ARG("-vlanfilter", unsetbridge_vlanfilter), + DEF_CMD_ARG2("untagged", setbridge_untagged), + DEF_CMD_ARG("-untagged", unsetbridge_untagged), + DEF_CMD_ARG2("tagged", setbridge_tagged), + DEF_CMD_ARG2("+tagged", addbridge_tagged), + DEF_CMD_ARG2("-tagged", delbridge_tagged), DEF_CMD_ARG("timeout", setbridge_timeout), DEF_CMD_ARG("private", setbridge_private), DEF_CMD_ARG("-private", unsetbridge_private), @@ -683,9 +852,7 @@ static struct afswtch af_bridge = { static __constructor void bridge_ctor(void) { - int i; - - for (i = 0; i < nitems(bridge_cmds); i++) + for (size_t i = 0; i < nitems(bridge_cmds); i++) cmd_register(&bridge_cmds[i]); af_register(&af_bridge); } diff --git a/sbin/ifconfig/ifclone.c b/sbin/ifconfig/ifclone.c index 9cacff239967..f44d052c97ad 100644 --- a/sbin/ifconfig/ifclone.c +++ b/sbin/ifconfig/ifclone.c @@ -29,11 +29,6 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <sys/param.h> #include <sys/ioctl.h> #include <sys/queue.h> @@ -118,13 +113,12 @@ clone_setdefcallback_filter(clone_match_func *filter, clone_callback_func *p) * no parameters. */ static void -ifclonecreate(int s, void *arg) +ifclonecreate(if_ctx *ctx, void *arg __unused) { - struct ifreq ifr; + struct ifreq ifr = {}; struct clone_defcb *dcp; - memset(&ifr, 0, sizeof(ifr)); - (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + strlcpy(ifr.ifr_name, ctx->ifname, sizeof(ifr.ifr_name)); /* Try to find a default callback by filter */ SLIST_FOREACH(dcp, &clone_defcbh, next) { @@ -145,32 +139,24 @@ ifclonecreate(int s, void *arg) if (dcp == NULL || dcp->clone_cb == NULL) { /* NB: no parameters */ - ioctl_ifcreate(s, &ifr); + ifcreate_ioctl(ctx, &ifr); } else { - dcp->clone_cb(s, &ifr); - } - - /* - * If we get a different name back than we put in, update record and - * indicate it should be printed later. - */ - if (strncmp(name, ifr.ifr_name, sizeof(name)) != 0) { - strlcpy(name, ifr.ifr_name, sizeof(name)); - printifname = 1; + dcp->clone_cb(ctx, &ifr); } } -static -DECL_CMD_FUNC(clone_create, arg, d) +static void +clone_create(if_ctx *ctx __unused, const char *cmd __unused, int d __unused) { callback_register(ifclonecreate, NULL); } -static -DECL_CMD_FUNC(clone_destroy, arg, d) +static void +clone_destroy(if_ctx *ctx, const char *cmd __unused, int d __unused) { - (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); - if (ioctl(s, SIOCIFDESTROY, &ifr) < 0) + struct ifreq ifr = {}; + + if (ioctl_ctx_ifr(ctx, SIOCIFDESTROY, &ifr) < 0) err(1, "SIOCIFDESTROY"); } @@ -182,7 +168,7 @@ static struct cmd clone_cmds[] = { }; static void -clone_Copt_cb(const char *optarg __unused) +clone_Copt_cb(const char *arg __unused) { list_cloners(); exit(exit_code); diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 index 0bedcbfe1c3c..6c61af48abec 100644 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -1,3 +1,6 @@ +.\"- +.\" SPDX-License-Identifier: BSD-3-Clause +.\" .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. All rights reserved. .\" @@ -25,10 +28,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94 -.\" $FreeBSD$ -.\" -.Dd June 24, 2022 +.Dd July 11, 2025 .Dt IFCONFIG 8 .Os .Sh NAME @@ -36,7 +36,8 @@ .Nd configure network interface parameters .Sh SYNOPSIS .Nm -.Op Fl kLmn +.Op Fl j Ar jail +.Op Fl DkLmn .Op Fl f Ar type Ns Cm \&: Ns Ar format .Ar interface .Op Cm create @@ -49,11 +50,13 @@ .Oc .Op Ar parameters .Nm +.Op Fl j Ar jail .Ar interface .Cm destroy .Nm +.Op Fl j Ar jail .Fl a -.Op Fl dkLmuv +.Op Fl dDkLmuv .Op Fl f Ar type Ns Cm \&: Ns Ar format .Op Fl G Ar groupname .Op Fl g Ar groupname @@ -61,13 +64,16 @@ .Nm .Fl C .Nm +.Op Fl j Ar jail .Fl g Ar groupname .Nm +.Op Fl j Ar jail .Fl l .Op Fl du .Op Fl g Ar groupname .Op Ar address_family .Nm +.Op Fl j Ar jail .Op Fl dkLmuv .Op Fl f Ar type Ns Cm \&: Ns Ar format .Sh DESCRIPTION @@ -99,6 +105,12 @@ with no additional information. Use of this flag is mutually exclusive with all other flags and commands. .It Fl d Display only the interfaces that are down. +.It Fl D +Include the driver name and unit number of the interface in the output. +This is normally the original name of the interface, +even if it has been renamed; it may differ from the original name +in some cases, such as +.Xr epair 4 . .It Fl f Xo .Ar type Ns Cm \&: Ns Ar format Ns .Op Cm \&, Ns Ar type Ns Cm \&: Ns Ar format Ar ... @@ -126,7 +138,7 @@ and their associated .Ar format strings are: .Pp -.Bl -tag -width ether +.Bl -tag -width default .It Cm addr Adjust the display of inet and inet6 addresses: .Pp @@ -150,6 +162,9 @@ Adjust the display of link-level ethernet (MAC) addresses: Separate address segments with a colon .It Cm dash Separate address segments with a dash +.It Cm dotted +Dotted notation, for example: +.Ql 5254.0015.4a3b .It Cm default Default format, .Cm colon @@ -188,15 +203,24 @@ Integer format, for example: .Ql prefixlen 64 .El .El +.Pp +In addition, the following shortcuts are accepted: +.Bl -tag -width default +.It Cm default +Resets all formats to their default values. +.It Cm cidr +Shortcut notation for +.Cm inet:cidr,inet6:cidr . +.El +.Pp .It Fl G Ar groupname Exclude members of the specified .Ar groupname from the output. -.Ar groupname . .Pp -Only one option +Only one .Fl G -should be specified as later override previous ones +option should be specified as later ones override earlier ones. .Ar groupname may contain shell patterns in which case it should be quoted. .Pp @@ -218,13 +242,13 @@ or .Fl C , then .Nm -lists names of interfaces beloning to +lists names of interfaces belonging to .Ar groupname . Any other flags and arguments are ignored in this case. .Pp -Only one option +Only one .Fl g -should be specified as later override previous ones +option should be specified as later ones override earlier ones. .Ar groupname may contain shell patterns in which case it should be quoted. .Pp @@ -233,6 +257,22 @@ Setting to .Cm all selects all interfaces. +.It Fl j Ar jail +Perform the actions inside the +.Ar jail . +.Pp +The +.Cm ifconfig +will first attach to the +.Ar jail +(by jail id or jail name) before performing the effects. +.Pp +This allow network interfaces of +.Ar jail +to be configured even if the +.Cm ifconfig +binary is not available in +.Ar jail . .It Fl k Print keying information for the .Ar interface , @@ -277,20 +317,20 @@ of the supported media for the specified interface. .It Fl n Disable automatic loading of network interface drivers. .Pp -If the network interface driver is not present in the kernel then +By default if the network interface driver is not present in the kernel +then .Nm will attempt to load it. -This flag disables this behavior. .It Fl u Display only the interfaces that are up. .It Fl v Get more verbose status for an interface. .It Ar address -For the DARPA-Internet family, +For the inet family, the address is either a host name present in the host name data base, .Xr hosts 5 , -or a DARPA Internet address expressed in the Internet standard +or an IPv4 address expressed in the Internet standard .Dq dot notation . .Pp It is also possible to use the CIDR notation (also known as the @@ -408,17 +448,16 @@ of specifying the host portion, removing all NS addresses will allow you to respecify the host portion. .It Cm anycast (Inet6 only.) -Specify that the address configured is an anycast address. -Based on the current specification, -only routers may configure anycast addresses. -Anycast address will not be used as source address of any of outgoing -IPv6 packets. +Specify that the address configured is an anycast address, +as described in RFC 4291 section 2.6. +Anycast addresses will not be used as source address of any outgoing +IPv6 packets unless an application explicitly binds to the address. .It Cm arp Enable the use of the Address Resolution Protocol .Pq Xr arp 4 in mapping between network level addresses and link level addresses (default). -This is currently implemented for mapping between DARPA Internet addresses +This is currently implemented for mapping between Internet Protocol addresses and IEEE 802 48-bit MAC addresses (Ethernet addresses). .It Fl arp Disable the use of the Address Resolution Protocol @@ -432,20 +471,24 @@ If the Address Resolution Protocol is enabled, the host will perform normally, sending out requests and listening for replies. .It Cm stickyarp -Enable so-called sticky ARP mode for the interface. +Enable the so-called sticky ARP mode for the interface. If this option is enabled on the given interface, any resolved address is -marked as a static one and never expires. This may be used to increase +marked as a static one and never expires. +This may be used to increase security of the network by preventing ARP spoofing or to reduce latency for high-performance Ethernet networks where the time needed for ARP resolution is -too high. Please note that a similar feature is also provided for bridges. See +too high. +Please note that a similar feature is also provided for bridges. +See the sticky option in the .Sx Bridge Interface Parameters -section. Enabling this +section. +Enabling this option may impact techniques which rely on ARP expiration/overwriting feature such as load-balancers or high-availabity solutions such as .Xr carp 4 . .It Fl stickyarp -Disable so-called sticky ARP mode for the interface (default). +Disable the so-called sticky ARP mode for the interface (default). Resolved addresses will expire normally respecting the kernel ARP configuration. .It Cm broadcast @@ -458,6 +501,10 @@ Enable driver dependent debugging code; usually, this turns on extra console error logging. .It Fl debug Disable driver dependent debugging code. +.It Cm allmulti +Enable promiscuous mode for multicast packets. +.It Fl allmulti +Disable promiscuous mode for multicast packets. .It Cm promisc Put interface into permanently promiscuous mode. .It Fl promisc @@ -484,16 +531,16 @@ This action does not automatically disable routes using the interface. .It Cm group Ar groupname Assign the interface to a .Dq group . +The +.Ar groupname +may not be longer than 15 characters and must not end in a digit. Any interface can be in multiple groups. .Pp Cloned interfaces are members of their interface family group by default. -For example, a PPP interface such as -.Em ppp0 -is a member of the PPP interface family group, -.Em ppp . -.\" The interface(s) the default route(s) point to are members of the -.\" .Em egress -.\" interface group. +For example, a VLAN interface such as +.Em vlan10 +is a member of the VLAN interface family group, +.Em vlan . .It Cm -group Ar groupname Remove the interface from the given .Dq group . @@ -520,9 +567,11 @@ Specify tunnel FIB. A FIB .Ar fib_number is assigned to all packets encapsulated by tunnel interface, e.g., -.Xr gif 4 +.Xr gif 4 , +.Xr gre 4 , +.Xr vxlan 4 , and -.Xr gre 4 . +.Xr wg 4 . .It Cm maclabel Ar label If Mandatory Access Control support is enabled in the kernel, set the MAC label to @@ -682,7 +731,7 @@ buffers, enable them on the interface. .It Fl mextpg If the driver supports extended multi-page .Xr mbuf 9 -biffers, disable them on the interface. +buffers, disable them on the interface. .It Cm wol , wol_ucast , wol_mcast , wol_magic Enable Wake On Lan (WOL) support, if available. WOL is a facility whereby a machine in a low power state may be woken @@ -1039,7 +1088,7 @@ Legacy .Cm wds devices have a fixed peer relationship and do not, for example, roam if their peer stops communicating. -For completeness a Dynamic WDS (DWDS) interface may marked as +For completeness a Dynamic WDS (DWDS) interface may be marked as .Fl wdslegacy . .It Cm bssid Request a unique local mac address for the cloned device. @@ -1196,8 +1245,8 @@ Set the interval at which beacon frames are sent when operating in ad-hoc or ap mode. The .Ar interval -parameter is specified in TU's (1024 usecs). -By default beacon frames are transmitted every 100 TU's. +parameter is specified in TUs (1024 usecs). +By default beacon frames are transmitted every 100 TUs. .It Cm bmissthreshold Ar count Set the number of consecutive missed beacons at which the station will attempt to roam (i.e., search for a new access point). @@ -1854,8 +1903,8 @@ Use .Fl powersave to disable powersave operation when operating as a client. .It Cm powersavesleep Ar sleep -Set the desired max powersave sleep time in TU's (1024 usecs). -By default the max powersave sleep time is 100 TU's. +Set the desired max powersave sleep time in TUs (1024 usecs). +By default the max powersave sleep time is 100 TUs. .It Cm protmode Ar technique For interfaces operating in 802.11g, use the specified .Ar technique @@ -2647,6 +2696,57 @@ source addresses are dropped until an existing host cache entry expires or is removed. Set to 0 to disable. .El +.Ss Bridge VLAN Filtering Parameters +The behaviour of these options is described in the +.Dq VLAN SUPPORT +section of +.Xr bridge 4 . +.Bl -tag -width indent +.It Cm vlanfilter Ar interface +Enable VLAN filtering on an interface. +.It Cm -vlanfilter Ar interface +Disable VLAN filtering on an interface. +.It Cm untagged Ar interface Ar vlan-id +Set the untagged VLAN identifier for an interface. +.Pp +Setting +.Cm untagged +will automatically enable VLAN filtering on the interface. +.It Cm -untagged Ar interface Ar vlan-id +Clear the untagged VLAN identifier for an interface. +.It Cm tagged Ar interface Ar vlan-list +Set the interface's VLAN access list to the provided list of VLANs. +The list should be a comma-separated list of one or more VLAN IDs +or ranges formatted as +.Ar first-last , +the value +.Dq none +meaning the empty set, +or the value +.Dq all +meaning all VLANs (1-4094). +.Pp +Setting +.Cm tagged +will automatically enable VLAN filtering on the interface. +.It Cm +tagged Ar interface Ar vlan-list +Add the provided list of VLAN IDs to the interface's VLAN access list. +The list should be formatted as described for +.Cm tagged . +.Pp +Setting +.Cm +tagged +will automatically enable VLAN filtering on the interface. +.It Cm -tagged Ar interface Ar vlan-list +Remove the provided list of VLAN IDs from the interface's VLAN access +list. +The list should be formatted as described for +.Cm tagged . +.Pp +Setting +.Cm -tagged +will automatically enable VLAN filtering on the interface. +.El .Ss Link Aggregation and Link Failover Parameters The following parameters are specific to lagg interfaces: .Bl -tag -width indent @@ -2720,19 +2820,19 @@ Hash is calculated by using flowid bits in a packet header mbuf which are shifted by the number of this parameter. .It Cm use_numa Enable selection of egress ports based on the native -.Xr NUMA 4 +.Xr numa 4 domain for the packets being transmitted. This is currently only implemented for lacp mode. This works only on -.Xr NUMA 4 +.Xr numa 4 hardware, running a kernel compiled with the -.Xr NUMA 4 +.Xr numa 4 option, and when interfaces from multiple -.Xr NUMA 4 +.Xr numa 4 domains are ports of the aggregation interface. .It Cm -use_numa Disable selection of egress ports based on the native -.Xr NUMA 4 +.Xr numa 4 domain for the packets being transmitted. .It Cm lacp_fast_timeout Enable lacp fast-timeout on the interface. @@ -2778,16 +2878,6 @@ interfaces previously configured with Another name for the .Fl tunnel parameter. -.It Cm accept_rev_ethip_ver -Set a flag to accept both correct EtherIP packets and ones -with reversed version field. -Enabled by default. -This is for backward compatibility with -.Fx 6.1 , -6.2, 6.3, 7.0, and 7.1. -.It Cm -accept_rev_ethip_ver -Clear a flag -.Cm accept_rev_ethip_ver . .It Cm ignore_source Set a flag to accept encapsulated packets destined to this host independently from source address. @@ -2796,16 +2886,6 @@ from the load balancers. .It Cm -ignore_source Clear a flag .Cm ignore_source . -.It Cm send_rev_ethip_ver -Set a flag to send EtherIP packets with reversed version -field intentionally. -Disabled by default. -This is for backward compatibility with -.Fx 6.1 , -6.2, 6.3, 7.0, and 7.1. -.It Cm -send_rev_ethip_ver -Clear a flag -.Cm send_rev_ethip_ver . .El .Ss GRE Tunnel Parameters The following parameters apply to GRE tunnel interfaces, @@ -2845,12 +2925,24 @@ to send and receive pfsync state synchronisation messages. .It Fl syncdev Stop sending pfsync state synchronisation messages over the network. .It Cm syncpeer Ar peer_address -Make the pfsync link point-to-point rather than using -multicast to broadcast the state synchronisation messages. -The peer_address is the IP address of the other host taking part in -the pfsync cluster. +Set the destination address for the state synchronization messages sent. +The +.Ar peer_address +is normally the IPv4 or IPv6 address of the other host taking +part in the pfsync cluster. +.Pp +When the +.Ar peer_address +is set to a unicast IP address, the pfsync link will behave +as point-to-point rather than using multicast to broadcast the messages. +.Pp +When the +.Ar peer_address +is set to ff12::f0, the state synchronization +messages will be broadcast using multicast over IPv6. .It Fl syncpeer -Broadcast the packets using multicast. +Unset the syncpeer. +Packets will then be broadcast using multicast over IPv4. .It Cm maxupd Ar n Set the maximum number of updates for a single state which can be collapsed into one. @@ -2861,6 +2953,11 @@ acknowledged that the associated state has been inserted. .It Fl defer Do not defer the first packet in a state. This is the default. +.It Fl version Ar n +Configure message format for compatibility with older versions of FreeBSD. +Refer to +.Xr pfsync 4 +for details. .El .Ss VLAN Parameters The following parameters are specific to @@ -2882,17 +2979,15 @@ must both be set at the same time. .It Cm vlanproto Ar vlan_proto Set the VLAN encapsulation protocol to .Ar vlan_proto . -Supported encapsulation protocols are currently -.Dq 802.1Q -and -.Dq 802.1ad . -The default encapsulation protocol is -.Dq 802.1Q . -The -.Dq 802.1ad -protocol is also commonly known as -.Dq QinQ ; -either name can be used. +Supported encapsulation protocols are currently: +.Bl -tag +.It Cm 802.1Q +Default. +.It Cm 802.1ad +.It Cm QinQ +Same as +.Cm 802.1ad . +.El .It Cm vlanpcp Ar priority_code_point Priority code point .Pq Dv PCP @@ -3090,6 +3185,36 @@ The following states are recognized: .Cm MASTER and .Cm BACKUP . +.It Cm peer Ar address +Set the address to send (IPv4) +.Xr carp 4 +announcements to. +.It Cm mcast +Restore the default destination address for (IPv4) +.Xr carp 4 +announcements, which is 224.0.0.18. +.It Cm peer6 Ar address +Set the address to send (IPv6) +.Xr carp 4 +announcements to. +.It Cm mcast6 +Restore the default destination address for (IPv4) +.Xr carp 4 +announcements, which is ff02::12. +.It Cm carpver +Set the protocol version. +Valid choices are 2 (for +.Xr carp 4) +and 3 (for VRRPv3). +This can only be set when +.Xr carp 4 +is initiated. +.It Cm vrrpprio +Set the VRRPv3 priority. +Valid values are 1-255. +.It Cm vrrpinterval +Set the VRRPv3 Master Advertisement Interval. +Values are in centiseconds. .El .Sh ENVIRONMENT The following environment variables affect the execution of @@ -3231,6 +3356,16 @@ tried to alter an interface's configuration. .Xr rc 8 , .Xr routed 8 , .Xr sysctl 8 +.Rs +.%R RFC 3484 +.%D February 2003 +.%T "Default Address Selection for Internet Protocol version 6 (IPv6)" +.Re +.Rs +.%R RFC 4291 +.%D February 2006 +.%T "IP Version 6 Addressing Architecture" +.Re .Sh HISTORY The .Nm diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c index ec8a3fd52803..a0680d09e54c 100644 --- a/sbin/ifconfig/ifconfig.c +++ b/sbin/ifconfig/ifconfig.c @@ -29,19 +29,11 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char copyright[] = -"@(#) Copyright (c) 1983, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#if 0 -static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <sys/param.h> #include <sys/ioctl.h> +#ifdef JAIL +#include <sys/jail.h> +#endif #include <sys/module.h> #include <sys/linker.h> #include <sys/nv.h> @@ -52,6 +44,7 @@ static const char rcsid[] = #include <net/ethernet.h> #include <net/if.h> #include <net/if_dl.h> +#include <net/if_strings.h> #include <net/if_types.h> #include <net/route.h> @@ -82,48 +75,34 @@ static const char rcsid[] = ifconfig_handle_t *lifh; -/* - * Since "struct ifreq" is composed of various union members, callers - * should pay special attention to interpret the value. - * (.e.g. little/big endian difference in the structure.) - */ -struct ifreq ifr; - -char name[IFNAMSIZ]; -char *descr = NULL; -size_t descrlen = 64; -int setaddr; -int setmask; -int doalias; -int clearaddr; -int newaddr = 1; -int verbose; -int noload; -int printifname = 0; - -int supmedia = 0; -int printkeys = 0; /* Print keying material for interfaces. */ +#ifdef WITHOUT_NETLINK +static char *descr = NULL; +static size_t descrlen = 64; +#endif +static int setaddr; +static int setmask; +static int doalias; +static int clearaddr; +static int newaddr = 1; + int exit_code = 0; +static char ifname_to_print[IFNAMSIZ]; /* Helper for printifnamemaybe() */ + /* Formatter Strings */ char *f_inet, *f_inet6, *f_ether, *f_addr; -static bool group_member(const char *ifname, const char *match, - const char *nomatch); -static int ifconfig(int argc, char *const *argv, int iscreate, - const struct afswtch *afp); -static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl, +#ifdef WITHOUT_NETLINK +static void list_interfaces_ioctl(if_ctx *ctx); +static void status(if_ctx *ctx, const struct sockaddr_dl *sdl, struct ifaddrs *ifa); -static void tunnel_status(int s); +#endif static _Noreturn void usage(void); +static void Perrorc(const char *cmd, int error); static int getifflags(const char *ifname, int us, bool err_ok); static struct afswtch *af_getbyname(const char *name); -static struct afswtch *af_getbyfamily(int af); -static void af_other_status(int); - -void printifnamemaybe(void); static struct option *opts = NULL; @@ -190,29 +169,59 @@ usage(void) } fprintf(stderr, - "usage: ifconfig [-f type:format] %sinterface address_family\n" + "usage: ifconfig [-j jail] [-f type:format] %sinterface address_family\n" " [address [dest_address]] [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", + " ifconfig [-j jail] interface create\n" + " ifconfig [-j jail] -a %s[-d] [-m] [-u] [-v] [address_family]\n" + " ifconfig [-j jail] -l [-d] [-u] [address_family]\n" + " ifconfig [-j jail] %s[-d] [-m] [-u] [-v]\n", options, options, options); exit(1); } +static void +ifname_update(if_ctx *ctx, const char *name) +{ + strlcpy(ctx->_ifname_storage_ioctl, name, sizeof(ctx->_ifname_storage_ioctl)); + ctx->ifname = ctx->_ifname_storage_ioctl; + + strlcpy(ifname_to_print, name, sizeof(ifname_to_print)); +} + +static void +ifr_set_name(struct ifreq *ifr, const char *name) +{ + strlcpy(ifr->ifr_name, name, sizeof(ifr->ifr_name)); +} + +int +ioctl_ctx_ifr(if_ctx *ctx, unsigned long cmd, struct ifreq *ifr) +{ + ifr_set_name(ifr, ctx->ifname); + return (ioctl_ctx(ctx, cmd, ifr)); +} + void -ioctl_ifcreate(int s, struct ifreq *ifr) +ifcreate_ioctl(if_ctx *ctx, struct ifreq *ifr) { - if (ioctl(s, SIOCIFCREATE2, ifr) < 0) { + char ifname_orig[IFNAMSIZ]; + + strlcpy(ifname_orig, ifr->ifr_name, sizeof(ifname_orig)); + + if (ioctl(ctx->io_s, SIOCIFCREATE2, ifr) < 0) { switch (errno) { case EEXIST: errx(1, "interface %s already exists", ifr->ifr_name); default: - err(1, "SIOCIFCREATE2"); + err(1, "SIOCIFCREATE2 (%s)", ifr->ifr_name); } } + + if (strncmp(ifname_orig, ifr->ifr_name, sizeof(ifname_orig)) != 0) + ifname_update(ctx, ifr->ifr_name); } +#ifdef WITHOUT_NETLINK static int calcorders(struct ifaddrs *ifa, struct ifa_queue *q) { @@ -299,18 +308,15 @@ cmpifaddrs(struct ifaddrs *a, struct ifaddrs *b, struct ifa_queue *q) return (0); } +#endif static void freeformat(void) { - if (f_inet != NULL) - free(f_inet); - if (f_inet6 != NULL) - free(f_inet6); - if (f_ether != NULL) - free(f_ether); - if (f_addr != NULL) - free(f_addr); + free(f_inet); + free(f_inet6); + free(f_ether); + free(f_addr); } static void setformat(char *input) @@ -320,9 +326,18 @@ static void setformat(char *input) formatstr = strdup(input); while ((category = strsep(&formatstr, ",")) != NULL) { modifier = strchr(category, ':'); - if (modifier == NULL || modifier[1] == '\0') { - warnx("Skipping invalid format specification: %s\n", - category); + if (modifier == NULL) { + if (strcmp(category, "default") == 0) { + freeformat(); + } else if (strcmp(category, "cidr") == 0) { + free(f_inet); + f_inet = strdup(category); + free(f_inet6); + f_inet6 = strdup(category); + } else { + warnx("Skipping invalid format: %s\n", + category); + } continue; } @@ -330,18 +345,24 @@ static void setformat(char *input) modifier[0] = '\0'; modifier++; - if (strcmp(category, "addr") == 0) + if (strcmp(category, "addr") == 0) { + free(f_addr); f_addr = strdup(modifier); - else if (strcmp(category, "ether") == 0) + } else if (strcmp(category, "ether") == 0) { + free(f_ether); f_ether = strdup(modifier); - else if (strcmp(category, "inet") == 0) + } else if (strcmp(category, "inet") == 0) { + free(f_inet); f_inet = strdup(modifier); - else if (strcmp(category, "inet6") == 0) + } else if (strcmp(category, "inet6") == 0) { + free(f_inet6); f_inet6 = strdup(modifier); + } } free(formatstr); } +#ifdef WITHOUT_NETLINK static struct ifaddrs * sortifaddrs(struct ifaddrs *list, int (*compare)(struct ifaddrs *, struct ifaddrs *, struct ifa_queue *), @@ -396,59 +417,68 @@ sortifaddrs(struct ifaddrs *list, return (result); } +#endif -void printifnamemaybe() +static void +printifnamemaybe(void) { - if (printifname) - printf("%s\n", name); + if (ifname_to_print[0] != '\0') + printf("%s\n", ifname_to_print); } -int -main(int argc, char *argv[]) +static void +list_interfaces(if_ctx *ctx) { - int c, all, namesonly, downonly, uponly; - const struct afswtch *afp = NULL; - int ifindex; - struct ifaddrs *ifap, *sifap, *ifa; - struct ifreq paifr; - const struct sockaddr_dl *sdl; - char options[1024], *cp, *envformat, *namecp = NULL; - struct ifa_queue q = TAILQ_HEAD_INITIALIZER(q); - struct ifa_order_elt *cur, *tmp; - const char *ifname, *matchgroup, *nogroup; - struct option *p; - size_t iflen; - int flags; +#ifdef WITHOUT_NETLINK + list_interfaces_ioctl(ctx); +#else + list_interfaces_nl(ctx->args); +#endif +} + +static char * +args_peek(struct ifconfig_args *args) +{ + if (args->argc > 0) + return (args->argv[0]); + return (NULL); +} - all = downonly = uponly = namesonly = noload = verbose = 0; - f_inet = f_inet6 = f_ether = f_addr = NULL; - matchgroup = nogroup = NULL; +static char * +args_pop(struct ifconfig_args *args) +{ + if (args->argc == 0) + return (NULL); - lifh = ifconfig_open(); - if (lifh == NULL) - err(EXIT_FAILURE, "ifconfig_open"); + char *arg = args->argv[0]; - envformat = getenv("IFCONFIG_FORMAT"); - if (envformat != NULL) - setformat(envformat); + args->argc--; + args->argv++; - /* - * Ensure we print interface name when expected to, - * even if we terminate early due to error. - */ - atexit(printifnamemaybe); + return (arg); +} + +static void +args_parse(struct ifconfig_args *args, int argc, char *argv[]) +{ + char options[1024]; + struct option *p; + int c; /* Parse leading line options */ - strlcpy(options, "G:adf:klmnuv", sizeof(options)); + strlcpy(options, "G:adDf:j:klmnuv", 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++; + args->all = true; break; case 'd': /* restrict scan to "down" interfaces */ - downonly++; + args->downonly = true; + break; + case 'D': /* Print driver name */ + args->drivername = true; break; case 'f': if (optarg == NULL) @@ -456,33 +486,42 @@ main(int argc, char *argv[]) setformat(optarg); break; case 'G': - if (optarg == NULL || all == 0) + if (optarg == NULL || args->all == 0) + usage(); + args->nogroup = optarg; + break; + case 'j': +#ifdef JAIL + if (optarg == NULL) usage(); - nogroup = optarg; + args->jail_name = optarg; +#else + Perror("not built with jail support"); +#endif break; case 'k': - printkeys++; + args->printkeys = true; break; case 'l': /* scan interface names only */ - namesonly++; + args->namesonly = true; break; case 'm': /* show media choices in status */ - supmedia = 1; + args->supmedia = true; break; case 'n': /* suppress module loading */ - noload++; + args->noload = true; break; case 'u': /* restrict scan to "up" interfaces */ - uponly++; + args->uponly = true; break; case 'v': - verbose++; + args->verbose++; break; case 'g': - if (all) { + if (args->all) { if (optarg == NULL) usage(); - matchgroup = optarg; + args->matchgroup = optarg; break; } /* FALLTHROUGH */ @@ -501,26 +540,25 @@ main(int argc, char *argv[]) argv += optind; /* -l cannot be used with -a or -m */ - if (namesonly && (all || supmedia)) + if (args->namesonly && (args->all || args->supmedia)) usage(); /* nonsense.. */ - if (uponly && downonly) + if (args->uponly && args->downonly) usage(); /* no arguments is equivalent to '-a' */ - if (!namesonly && argc < 1) - all = 1; + if (!args->namesonly && argc < 1) + args->all = 1; /* -a and -l allow an address family arg to limit the output */ - if (all || namesonly) { + if (args->all || args->namesonly) { if (argc > 1) usage(); - ifname = NULL; - ifindex = 0; if (argc == 1) { - afp = af_getbyname(*argv); + const struct afswtch *afp = af_getbyname(*argv); + if (afp == NULL) { warnx("Address family '%s' unknown.", *argv); usage(); @@ -528,32 +566,108 @@ main(int argc, char *argv[]) if (afp->af_name != NULL) argc--, argv++; /* leave with afp non-zero */ + args->afp = afp; } } else { /* not listing, need an argument */ if (argc < 1) usage(); + } - ifname = *argv; - argc--, argv++; + args->argc = argc; + args->argv = argv; +} + +static int +ifconfig(if_ctx *ctx, int iscreate, const struct afswtch *uafp) +{ +#ifdef WITHOUT_NETLINK + return (ifconfig_ioctl(ctx, iscreate, uafp)); +#else + return (ifconfig_nl(ctx, iscreate, uafp)); +#endif +} + +static bool +isargcreate(const char *arg) +{ + if (arg == NULL) + return (false); + + if (strcmp(arg, "create") == 0 || strcmp(arg, "plumb") == 0) + return (true); + + return (false); +} + +static bool +isnametoolong(const char *ifname) +{ + return (strlen(ifname) >= IFNAMSIZ); +} + +int +main(int ac, char *av[]) +{ + char *envformat; + int flags; +#ifdef JAIL + int jid; +#endif + struct ifconfig_args _args = {}; + struct ifconfig_args *args = &_args; + + struct ifconfig_context ctx = { + .args = args, + .io_s = -1, + }; + + lifh = ifconfig_open(); + if (lifh == NULL) + err(EXIT_FAILURE, "ifconfig_open"); + + envformat = getenv("IFCONFIG_FORMAT"); + if (envformat != NULL) + setformat(envformat); + + /* + * Ensure we print interface name when expected to, + * even if we terminate early due to error. + */ + atexit(printifnamemaybe); + + args_parse(args, ac, av); + +#ifdef JAIL + if (args->jail_name) { + jid = jail_getid(args->jail_name); + if (jid == -1) + Perror("jail not found"); + if (jail_attach(jid) != 0) + Perror("cannot attach to jail"); + } +#endif + + if (!args->all && !args->namesonly) { + /* not listing, need an argument */ + args->ifname = args_pop(args); + ctx.ifname = args->ifname; /* check and maybe load support for this interface */ - ifmaybeload(ifname); + ifmaybeload(args, args->ifname); - ifindex = if_nametoindex(ifname); - if (ifindex == 0) { + char *arg = args_peek(args); + if (if_nametoindex(args->ifname) == 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)) { - iflen = strlcpy(name, ifname, sizeof(name)); - if (iflen >= sizeof(name)) + if (isargcreate(arg)) { + if (isnametoolong(args->ifname)) errx(1, "%s: cloning name too long", - ifname); - ifconfig(argc, argv, 1, NULL); + args->ifname); + ifconfig(&ctx, 1, NULL); exit(exit_code); } #ifdef JAIL @@ -562,36 +676,34 @@ main(int argc, char *argv[]) * right here as we would otherwise fail when trying * to find the interface as it lives in another vnet. */ - if (argc > 0 && (strcmp(argv[0], "-vnet") == 0)) { - iflen = strlcpy(name, ifname, sizeof(name)); - if (iflen >= sizeof(name)) + if (arg != NULL && (strcmp(arg, "-vnet") == 0)) { + if (isnametoolong(args->ifname)) errx(1, "%s: interface name too long", - ifname); - ifconfig(argc, argv, 0, NULL); + args->ifname); + ifconfig(&ctx, 0, NULL); exit(exit_code); } #endif - errx(1, "interface %s does not exist", ifname); + errx(1, "interface %s does not exist", args->ifname); } else { /* * Do not allow use `create` command as hostname if * address family is not specified. */ - if (argc > 0 && (strcmp(argv[0], "create") == 0 || - strcmp(argv[0], "plumb") == 0)) { - if (argc == 1) + if (isargcreate(arg)) { + if (args->argc == 1) errx(1, "interface %s already exists", - ifname); - argc--, argv++; + args->ifname); + args_pop(args); } } } /* Check for address family */ - if (argc > 0) { - afp = af_getbyname(*argv); - if (afp != NULL) - argc--, argv++; + if (args->argc > 0) { + args->afp = af_getbyname(args_peek(args)); + if (args->afp != NULL) + args_pop(args); } /* @@ -599,24 +711,84 @@ main(int argc, char *argv[]) * which doesn't require building, sorting, and searching the entire * system address list */ - if ((argc > 0) && (ifname != NULL)) { - iflen = strlcpy(name, ifname, sizeof(name)); - if (iflen >= sizeof(name)) { - warnx("%s: interface name too long, skipping", ifname); - } else { - flags = getifflags(name, -1, false); + if ((args->argc > 0) && (args->ifname != NULL)) { + if (isnametoolong(args->ifname)) + warnx("%s: interface name too long, skipping", args->ifname); + else { + flags = getifflags(args->ifname, -1, false); if (!(((flags & IFF_CANTCONFIG) != 0) || - (downonly && (flags & IFF_UP) != 0) || - (uponly && (flags & IFF_UP) == 0))) - ifconfig(argc, argv, 0, afp); + (args->downonly && (flags & IFF_UP) != 0) || + (args->uponly && (flags & IFF_UP) == 0))) + ifconfig(&ctx, 0, args->afp); } goto done; } + args->allfamilies = args->afp == NULL; + + list_interfaces(&ctx); + +done: + freeformat(); + ifconfig_close(lifh); + exit(exit_code); +} + +bool +match_ether(const struct sockaddr_dl *sdl) +{ + switch (sdl->sdl_type) { + case IFT_ETHER: + case IFT_L2VLAN: + case IFT_BRIDGE: + if (sdl->sdl_alen == ETHER_ADDR_LEN) + return (true); + default: + return (false); + } +} + +bool +match_if_flags(struct ifconfig_args *args, int if_flags) +{ + if ((if_flags & IFF_CANTCONFIG) != 0) + return (false); + if (args->downonly && (if_flags & IFF_UP) != 0) + return (false); + if (args->uponly && (if_flags & IFF_UP) == 0) + return (false); + return (true); +} + +#ifdef WITHOUT_NETLINK +static bool +match_afp(const struct afswtch *afp, int sa_family, const struct sockaddr_dl *sdl) +{ + if (afp == NULL) + return (true); + /* special case for "ether" address family */ + if (!strcmp(afp->af_name, "ether")) { + if (sdl == NULL || !match_ether(sdl)) + return (false); + return (true); + } + return (afp->af_af == sa_family); +} + +static void +list_interfaces_ioctl(if_ctx *ctx) +{ + struct ifa_queue q = TAILQ_HEAD_INITIALIZER(q); + struct ifaddrs *ifap, *sifap, *ifa; + struct ifa_order_elt *cur, *tmp; + char *namecp = NULL; + int ifindex; + struct ifconfig_args *args = ctx->args; + if (getifaddrs(&ifap) != 0) err(EXIT_FAILURE, "getifaddrs"); - cp = NULL; + char *cp = NULL; if (calcorders(ifap, &q) != 0) err(EXIT_FAILURE, "calcorders"); @@ -628,95 +800,76 @@ main(int argc, char *argv[]) ifindex = 0; for (ifa = sifap; ifa; ifa = ifa->ifa_next) { - memset(&paifr, 0, sizeof(paifr)); + struct ifreq paifr = {}; + const struct sockaddr_dl *sdl; + strlcpy(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); } - if (ifname != NULL && strcmp(ifname, ifa->ifa_name) != 0) + if (args->ifname != NULL && strcmp(args->ifname, ifa->ifa_name) != 0) continue; if (ifa->ifa_addr->sa_family == AF_LINK) - sdl = (const struct sockaddr_dl *) ifa->ifa_addr; + sdl = satosdl_c(ifa->ifa_addr); else sdl = NULL; - if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0 && !namesonly) + if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0 && !args->namesonly) continue; - iflen = strlcpy(name, ifa->ifa_name, sizeof(name)); - if (iflen >= sizeof(name)) { + if (isnametoolong(ifa->ifa_name)) { warnx("%s: interface name too long, skipping", ifa->ifa_name); continue; } cp = ifa->ifa_name; - if ((ifa->ifa_flags & IFF_CANTCONFIG) != 0) - continue; - if (downonly && (ifa->ifa_flags & IFF_UP) != 0) + if (!match_if_flags(args, ifa->ifa_flags)) continue; - if (uponly && (ifa->ifa_flags & IFF_UP) == 0) - continue; - if (!group_member(ifa->ifa_name, matchgroup, nogroup)) + if (!group_member(ifa->ifa_name, args->matchgroup, args->nogroup)) continue; + ctx->ifname = cp; /* * Are we just listing the interfaces? */ - if (namesonly) { + if (args->namesonly) { if (namecp == cp) continue; - if (afp != NULL) { - /* special case for "ether" address family */ - if (!strcmp(afp->af_name, "ether")) { - if (sdl == NULL || - (sdl->sdl_type != IFT_ETHER && - sdl->sdl_type != IFT_L2VLAN && - sdl->sdl_type != IFT_BRIDGE) || - sdl->sdl_alen != ETHER_ADDR_LEN) - continue; - } else { - if (ifa->ifa_addr->sa_family - != afp->af_af) - continue; - } - } + if (!match_afp(args->afp, ifa->ifa_addr->sa_family, sdl)) + continue; namecp = cp; ifindex++; if (ifindex > 1) printf(" "); - fputs(name, stdout); + fputs(cp, stdout); continue; } ifindex++; - if (argc > 0) - ifconfig(argc, argv, 0, afp); + if (args->argc > 0) + ifconfig(ctx, 0, args->afp); else - status(afp, sdl, ifa); + status(ctx, sdl, ifa); } - if (namesonly) + if (args->namesonly) printf("\n"); freeifaddrs(ifap); - -done: - freeformat(); - ifconfig_close(lifh); - exit(exit_code); } +#endif /* * Returns true if an interface should be listed because any its groups * matches shell pattern "match" and none of groups matches pattern "nomatch". * If any pattern is NULL, corresponding condition is skipped. */ -static bool +bool group_member(const char *ifname, const char *match, const char *nomatch) { static int sock = -1; struct ifgroupreq ifgr; struct ifg_req *ifg; - int len; + unsigned int len; bool matched, nomatched; /* Sanity checks. */ @@ -757,11 +910,11 @@ group_member(const char *ifname, const char *match, const char *nomatch) matched = false; nomatched = true; for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(*ifg); ifg++) { - len -= sizeof(struct ifg_req); - if (match) - matched |= !fnmatch(match, ifg->ifgrq_group, 0); - if (nomatch) - nomatched &= fnmatch(nomatch, ifg->ifgrq_group, 0); + len -= sizeof(*ifg); + if (match && !matched) + matched = !fnmatch(match, ifg->ifgrq_group, 0); + if (nomatch && nomatched) + nomatched = fnmatch(nomatch, ifg->ifgrq_group, 0); } free(ifgr.ifgr_groups); @@ -792,7 +945,7 @@ af_getbyname(const char *name) return NULL; } -static struct afswtch * +struct afswtch * af_getbyfamily(int af) { struct afswtch *afp; @@ -803,8 +956,8 @@ af_getbyfamily(int af) return NULL; } -static void -af_other_status(int s) +void +af_other_status(if_ctx *ctx) { struct afswtch *afp; uint8_t afmask[howmany(AF_MAX, NBBY)]; @@ -815,13 +968,13 @@ af_other_status(int s) continue; if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af)) continue; - afp->af_other_status(s); + afp->af_other_status(ctx); setbit(afmask, afp->af_af); } } static void -af_all_tunnel_status(int s) +af_all_tunnel_status(if_ctx *ctx) { struct afswtch *afp; uint8_t afmask[howmany(AF_MAX, NBBY)]; @@ -832,7 +985,7 @@ af_all_tunnel_status(int s) continue; if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af)) continue; - afp->af_status_tunnel(s); + afp->af_status_tunnel(ctx); setbit(afmask, afp->af_af); } } @@ -886,22 +1039,80 @@ callback_register(callback_func *func, void *arg) } /* specially-handled commands */ -static void setifaddr(const char *, int, int, const struct afswtch *); +static void setifaddr(if_ctx *ctx, const char *addr, int param); static const struct cmd setifaddr_cmd = DEF_CMD("ifaddr", 0, setifaddr); -static void setifdstaddr(const char *, int, int, const struct afswtch *); +static void setifdstaddr(if_ctx *ctx, const char *addr, int param __unused); static const struct cmd setifdstaddr_cmd = DEF_CMD("ifdstaddr", 0, setifdstaddr); -static int -ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *uafp) +int +af_exec_ioctl(if_ctx *ctx, unsigned long action, void *data) +{ + struct ifreq *req = (struct ifreq *)data; + + strlcpy(req->ifr_name, ctx->ifname, sizeof(req->ifr_name)); + if (ioctl_ctx(ctx, action, req) == 0) + return (0); + return (errno); +} + +static void +delifaddr(if_ctx *ctx, const struct afswtch *afp) +{ + int error; + + if (afp->af_exec == NULL) { + warnx("interface %s cannot change %s addresses!", + ctx->ifname, afp->af_name); + clearaddr = 0; + return; + } + + error = afp->af_exec(ctx, afp->af_difaddr, afp->af_ridreq); + if (error != 0) { + if (error == EADDRNOTAVAIL && (doalias >= 0)) { + /* means no previous address for interface */ + } else + Perrorc("ioctl (SIOCDIFADDR)", error); + } +} + +static void +addifaddr(if_ctx *ctx, const struct afswtch *afp) +{ + if (afp->af_exec == NULL) { + warnx("interface %s cannot change %s addresses!", + ctx->ifname, afp->af_name); + newaddr = 0; + return; + } + + if (setaddr || setmask) { + int error = afp->af_exec(ctx, afp->af_aifaddr, afp->af_addreq); + if (error != 0) + Perrorc("ioctl (SIOCAIFADDR)", error); + } +} + +int +ifconfig_ioctl(if_ctx *orig_ctx, int iscreate, const struct afswtch *uafp) { const struct afswtch *afp, *nafp; const struct cmd *p; struct callback *cb; int s; - - strlcpy(ifr.ifr_name, name, sizeof ifr.ifr_name); + int argc = orig_ctx->args->argc; + char *const *argv = orig_ctx->args->argv; + struct ifconfig_context _ctx = { + .args = orig_ctx->args, + .io_ss = orig_ctx->io_ss, + .ifname = orig_ctx->ifname, + }; + struct ifconfig_context *ctx = &_ctx; + + struct ifreq ifr = {}; + strlcpy(ifr.ifr_name, ctx->ifname, sizeof ifr.ifr_name); afp = NULL; if (uafp != NULL) afp = uafp; @@ -926,6 +1137,7 @@ ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *uafp) warnx("Please specify an address_family."); usage(); } + top: ifr.ifr_addr.sa_family = afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ? @@ -936,6 +1148,9 @@ top: (s = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0)) err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family); + ctx->io_s = s; + ctx->afp = afp; + while (argc > 0) { p = cmd_lookup(*argv, iscreate); if (iscreate && p == NULL) { @@ -948,7 +1163,7 @@ top: if (cb == NULL) errx(1, "internal error, no callback"); callbacks = cb->cb_next; - cb->cb_func(s, cb->cb_arg); + cb->cb_func(ctx, cb->cb_arg); iscreate = 0; /* * Handle any address family spec that @@ -980,22 +1195,22 @@ top: if (argv[1] == NULL) errx(1, "'%s' requires argument", p->c_name); - p->c_u.c_func(argv[1], 0, s, afp); + p->c_u.c_func(ctx, argv[1], 0); argc--, argv++; } else if (p->c_parameter == OPTARG && p->c_u.c_func) { - p->c_u.c_func(argv[1], 0, s, afp); + p->c_u.c_func(ctx, argv[1], 0); if (argv[1] != NULL) argc--, argv++; } else if (p->c_parameter == NEXTARG2 && p->c_u.c_func2) { if (argc < 3) errx(1, "'%s' requires 2 arguments", p->c_name); - p->c_u.c_func2(argv[1], argv[2], s, afp); + p->c_u.c_func2(ctx, argv[1], argv[2]); argc -= 2, argv += 2; } else if (p->c_parameter == SPARAM && p->c_u.c_func3) { - p->c_u.c_func3(*argv, p->c_sparameter, s, afp); + p->c_u.c_func3(ctx, *argv, p->c_sparameter); } else if (p->c_u.c_func) - p->c_u.c_func(*argv, p->c_parameter, s, afp); + p->c_u.c_func(ctx, *argv, p->c_parameter); argc--, argv++; } @@ -1003,57 +1218,30 @@ top: * Do any post argument processing required by the address family. */ if (afp->af_postproc != NULL) - afp->af_postproc(s, afp, newaddr, getifflags(name, s, true)); + afp->af_postproc(ctx, newaddr, getifflags(ctx->ifname, s, true)); /* * 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); + cb->cb_func(ctx, 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; - strlcpy(((struct ifreq *)afp->af_ridreq)->ifr_name, 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)) { - strlcpy(((struct ifreq *)afp->af_addreq)->ifr_name, name, - sizeof ifr.ifr_name); - if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0) - Perror("ioctl (SIOCAIFADDR)"); - } + if (clearaddr) + delifaddr(ctx, afp); + if (newaddr) + addifaddr(ctx, afp); close(s); return(0); } -/*ARGSUSED*/ static void -setifaddr(const char *addr, int param, int s, const struct afswtch *afp) +setifaddr(if_ctx *ctx, const char *addr, int param __unused) { + const struct afswtch *afp = ctx->afp; + if (afp->af_getaddr == NULL) return; /* @@ -1068,8 +1256,9 @@ setifaddr(const char *addr, int param, int s, const struct afswtch *afp) } static void -settunnel(const char *src, const char *dst, int s, const struct afswtch *afp) +settunnel(if_ctx *ctx, const char *src, const char *dst) { + const struct afswtch *afp = ctx->afp; struct addrinfo *srcres, *dstres; int ecode; @@ -1091,55 +1280,52 @@ settunnel(const char *src, const char *dst, int s, const struct afswtch *afp) errx(1, "source and destination address families do not match"); - afp->af_settunnel(s, srcres, dstres); + afp->af_settunnel(ctx, srcres, dstres); freeaddrinfo(srcres); freeaddrinfo(dstres); } -/* ARGSUSED */ static void -deletetunnel(const char *vname, int param, int s, const struct afswtch *afp) +deletetunnel(if_ctx *ctx, const char *vname __unused, int param __unused) { + struct ifreq ifr = {}; - if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0) + if (ioctl_ctx_ifr(ctx, SIOCDIFPHYADDR, &ifr) < 0) err(1, "SIOCDIFPHYADDR"); } #ifdef JAIL static void -setifvnet(const char *jname, int dummy __unused, int s, - const struct afswtch *afp) +setifvnet(if_ctx *ctx, const char *jname, int dummy __unused) { - struct ifreq my_ifr; + struct ifreq ifr = {}; - memcpy(&my_ifr, &ifr, sizeof(my_ifr)); - my_ifr.ifr_jid = jail_getid(jname); - if (my_ifr.ifr_jid < 0) + ifr.ifr_jid = jail_getid(jname); + if (ifr.ifr_jid < 0) errx(1, "%s", jail_errmsg); - if (ioctl(s, SIOCSIFVNET, &my_ifr) < 0) + if (ioctl_ctx_ifr(ctx, SIOCSIFVNET, &ifr) < 0) err(1, "SIOCSIFVNET"); } static void -setifrvnet(const char *jname, int dummy __unused, int s, - const struct afswtch *afp) +setifrvnet(if_ctx *ctx, const char *jname, int dummy __unused) { - struct ifreq my_ifr; + struct ifreq ifr = {}; - memcpy(&my_ifr, &ifr, sizeof(my_ifr)); - my_ifr.ifr_jid = jail_getid(jname); - if (my_ifr.ifr_jid < 0) + ifr.ifr_jid = jail_getid(jname); + if (ifr.ifr_jid < 0) errx(1, "%s", jail_errmsg); - if (ioctl(s, SIOCSIFRVNET, &my_ifr) < 0) - err(1, "SIOCSIFRVNET(%d, %s)", my_ifr.ifr_jid, my_ifr.ifr_name); + if (ioctl_ctx_ifr(ctx, SIOCSIFRVNET, &ifr) < 0) + err(1, "SIOCSIFRVNET(%d, %s)", ifr.ifr_jid, ifr.ifr_name); } #endif static void -setifnetmask(const char *addr, int dummy __unused, int s, - const struct afswtch *afp) +setifnetmask(if_ctx *ctx, const char *addr, int dummy __unused) { + const struct afswtch *afp = ctx->afp; + if (afp->af_getaddr != NULL) { setmask++; afp->af_getaddr(addr, MASK); @@ -1147,36 +1333,36 @@ setifnetmask(const char *addr, int dummy __unused, int s, } static void -setifbroadaddr(const char *addr, int dummy __unused, int s, - const struct afswtch *afp) +setifbroadaddr(if_ctx *ctx, const char *addr, int dummy __unused) { + const struct afswtch *afp = ctx->afp; + if (afp->af_getaddr != NULL) - afp->af_getaddr(addr, DSTADDR); + afp->af_getaddr(addr, BRDADDR); } 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); +notealias(if_ctx *ctx, const char *addr __unused, int param) +{ + const struct afswtch *afp = ctx->afp; + + if (setaddr && doalias == 0 && param < 0) { + if (afp->af_copyaddr != NULL) + afp->af_copyaddr(ctx, RIDADDR, ADDR); + } 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) +setifdstaddr(if_ctx *ctx, const char *addr, int param __unused) { + const struct afswtch *afp = ctx->afp; + if (afp->af_getaddr != NULL) afp->af_getaddr(addr, DSTADDR); } @@ -1211,59 +1397,90 @@ getifflags(const char *ifname, int us, bool err_ok) * Make a private copy so we can avoid that. */ static void -setifflags(const char *vname, int value, int s, const struct afswtch *afp) +clearifflags(if_ctx *ctx, const char *vname, int value) { struct ifreq my_ifr; int flags; - flags = getifflags(name, s, false); - if (value < 0) { - value = -value; - flags &= ~value; - } else - flags |= value; + flags = getifflags(ctx->ifname, ctx->io_s, false); + flags &= ~value; + memset(&my_ifr, 0, sizeof(my_ifr)); + strlcpy(my_ifr.ifr_name, ctx->ifname, sizeof(my_ifr.ifr_name)); + my_ifr.ifr_flags = flags & 0xffff; + my_ifr.ifr_flagshigh = flags >> 16; + if (ioctl(ctx->io_s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0) + Perror(vname); +} + +static void +setifflags(if_ctx *ctx, const char *vname, int value) +{ + struct ifreq my_ifr; + int flags; + + flags = getifflags(ctx->ifname, ctx->io_s, false); + flags |= value; memset(&my_ifr, 0, sizeof(my_ifr)); - (void) strlcpy(my_ifr.ifr_name, name, sizeof(my_ifr.ifr_name)); + strlcpy(my_ifr.ifr_name, ctx->ifname, sizeof(my_ifr.ifr_name)); my_ifr.ifr_flags = flags & 0xffff; my_ifr.ifr_flagshigh = flags >> 16; - if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0) + if (ioctl(ctx->io_s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0) Perror(vname); } void -setifcap(const char *vname, int value, int s, const struct afswtch *afp) +clearifcap(if_ctx *ctx, const char *vname, int value) { + struct ifreq ifr = {}; int flags; - if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) { + if (ioctl_ctx_ifr(ctx, SIOCGIFCAP, &ifr) < 0) { Perror("ioctl (SIOCGIFCAP)"); exit(1); } flags = ifr.ifr_curcap; - if (value < 0) { - value = -value; - flags &= ~value; - } else - flags |= value; + flags &= ~value; flags &= ifr.ifr_reqcap; /* Check for no change in capabilities. */ if (ifr.ifr_curcap == flags) return; ifr.ifr_reqcap = flags; - if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0) + if (ioctl_ctx(ctx, SIOCSIFCAP, &ifr) < 0) Perror(vname); } void -setifcapnv(const char *vname, const char *arg, int s, const struct afswtch *afp) +setifcap(if_ctx *ctx, const char *vname, int value) +{ + struct ifreq ifr = {}; + int flags; + + if (ioctl_ctx_ifr(ctx, SIOCGIFCAP, &ifr) < 0) { + Perror("ioctl (SIOCGIFCAP)"); + exit(1); + } + flags = ifr.ifr_curcap; + flags |= value; + flags &= ifr.ifr_reqcap; + /* Check for no change in capabilities. */ + if (ifr.ifr_curcap == flags) + return; + ifr.ifr_reqcap = flags; + if (ioctl_ctx(ctx, SIOCSIFCAP, &ifr) < 0) + Perror(vname); +} + +void +setifcapnv(if_ctx *ctx, const char *vname, const char *arg) { nvlist_t *nvcap; void *buf; char *marg, *mopt; size_t nvbuflen; bool neg; + struct ifreq ifr = {}; - if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) + if (ioctl_ctx_ifr(ctx, SIOCGIFCAP, &ifr) < 0) Perror("ioctl (SIOCGIFCAP)"); if ((ifr.ifr_curcap & IFCAP_NV) == 0) { warnx("IFCAP_NV not supported"); @@ -1294,7 +1511,7 @@ setifcapnv(const char *vname, const char *arg, int s, const struct afswtch *afp) } ifr.ifr_cap_nv.buf_length = ifr.ifr_cap_nv.length = nvbuflen; ifr.ifr_cap_nv.buffer = buf; - if (ioctl(s, SIOCSIFCAPNV, (caddr_t)&ifr) < 0) + if (ioctl_ctx(ctx, SIOCSIFCAPNV, (caddr_t)&ifr) < 0) Perror(vname); free(buf); nvlist_destroy(nvcap); @@ -1302,28 +1519,29 @@ setifcapnv(const char *vname, const char *arg, int s, const struct afswtch *afp) } static void -setifmetric(const char *val, int dummy __unused, int s, - const struct afswtch *afp) +setifmetric(if_ctx *ctx, const char *val, int dummy __unused) { - strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); + struct ifreq ifr = {}; + ifr.ifr_metric = atoi(val); - if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) + if (ioctl_ctx_ifr(ctx, SIOCSIFMETRIC, &ifr) < 0) err(1, "ioctl SIOCSIFMETRIC (set metric)"); } static void -setifmtu(const char *val, int dummy __unused, int s, - const struct afswtch *afp) +setifmtu(if_ctx *ctx, const char *val, int dummy __unused) { - strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); + struct ifreq ifr = {}; + ifr.ifr_mtu = atoi(val); - if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) + if (ioctl_ctx_ifr(ctx, SIOCSIFMTU, &ifr) < 0) err(1, "ioctl SIOCSIFMTU (set mtu)"); } static void -setifpcp(const char *val, int arg __unused, int s, const struct afswtch *afp) +setifpcp(if_ctx *ctx, const char *val, int arg __unused) { + struct ifreq ifr = {}; u_long ul; char *endp; @@ -1333,50 +1551,45 @@ setifpcp(const char *val, int arg __unused, int s, const struct afswtch *afp) if (ul > 7) errx(1, "value for pcp out of range"); ifr.ifr_lan_pcp = ul; - if (ioctl(s, SIOCSLANPCP, (caddr_t)&ifr) == -1) + if (ioctl_ctx_ifr(ctx, SIOCSLANPCP, &ifr) == -1) err(1, "SIOCSLANPCP"); } static void -disableifpcp(const char *val, int arg __unused, int s, - const struct afswtch *afp) +disableifpcp(if_ctx *ctx, const char *val __unused, int arg __unused) { + struct ifreq ifr = {}; ifr.ifr_lan_pcp = IFNET_PCP_NONE; - if (ioctl(s, SIOCSLANPCP, (caddr_t)&ifr) == -1) + if (ioctl_ctx_ifr(ctx, SIOCSLANPCP, &ifr) == -1) err(1, "SIOCSLANPCP"); } static void -setifname(const char *val, int dummy __unused, int s, - const struct afswtch *afp) +setifname(if_ctx *ctx, const char *val, int dummy __unused) { + struct ifreq ifr = {}; char *newname; - - strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + ifr_set_name(&ifr, ctx->ifname); newname = strdup(val); if (newname == NULL) err(1, "no memory to set ifname"); ifr.ifr_data = newname; - if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) { + if (ioctl_ctx(ctx, SIOCSIFNAME, (caddr_t)&ifr) < 0) { free(newname); err(1, "ioctl SIOCSIFNAME (set name)"); } - printifname = 1; - strlcpy(name, newname, sizeof(name)); + ifname_update(ctx, newname); free(newname); } -/* ARGSUSED */ static void -setifdescr(const char *val, int dummy __unused, int s, - const struct afswtch *afp) +setifdescr(if_ctx *ctx, const char *val, int dummy __unused) { + struct ifreq ifr = {}; char *newdescr; - strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); - ifr.ifr_buffer.length = strlen(val) + 1; if (ifr.ifr_buffer.length == 1) { ifr.ifr_buffer.buffer = newdescr = NULL; @@ -1390,75 +1603,197 @@ setifdescr(const char *val, int dummy __unused, int s, } } - if (ioctl(s, SIOCSIFDESCR, (caddr_t)&ifr) < 0) + if (ioctl_ctx_ifr(ctx, SIOCSIFDESCR, &ifr) < 0) err(1, "ioctl SIOCSIFDESCR (set descr)"); free(newdescr); } -/* ARGSUSED */ static void -unsetifdescr(const char *val, int value, int s, const struct afswtch *afp) +unsetifdescr(if_ctx *ctx, const char *val __unused, int value __unused) { - - setifdescr("", 0, s, 0); + setifdescr(ctx, "", 0); } -#define IFFBITS \ -"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\7RUNNING" \ -"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \ -"\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP\25STICKYARP" +#ifdef WITHOUT_NETLINK + +static const char *IFFBITS[] = { + [0] = "UP", + [1] = "BROADCAST", + [2] = "DEBUG", + [3] = "LOOPBACK", + [4] = "POINTOPOINT", + [6] = "RUNNING", + [7] = "NOARP", + [8] = "PROMISC", + [9] = "ALLMULTI", + [10] = "OACTIVE", + [11] = "SIMPLEX", + [12] = "LINK0", + [13] = "LINK1", + [14] = "LINK2", + [15] = "MULTICAST", + [17] = "PPROMISC", + [18] = "MONITOR", + [19] = "STATICARP", + [20] = "STICKYARP", +}; -#define IFCAPBITS \ -"\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \ -"\10VLAN_HWCSUM\11TSO4\12TSO6\13LRO\14WOL_UCAST\15WOL_MCAST\16WOL_MAGIC" \ -"\17TOE4\20TOE6\21VLAN_HWFILTER\23VLAN_HWTSO\24LINKSTATE\25NETMAP" \ -"\26RXCSUM_IPV6\27TXCSUM_IPV6\31TXRTLMT\32HWRXTSTMP\33NOMAP\34TXTLS4\35TXTLS6" \ -"\36VXLAN_HWCSUM\37VXLAN_HWTSO\40TXTLS_RTLMT" +static const char *IFCAPBITS[] = { + [0] = "RXCSUM", + [1] = "TXCSUM", + [2] = "NETCONS", + [3] = "VLAN_MTU", + [4] = "VLAN_HWTAGGING", + [5] = "JUMBO_MTU", + [6] = "POLLING", + [7] = "VLAN_HWCSUM", + [8] = "TSO4", + [9] = "TSO6", + [10] = "LRO", + [11] = "WOL_UCAST", + [12] = "WOL_MCAST", + [13] = "WOL_MAGIC", + [14] = "TOE4", + [15] = "TOE6", + [16] = "VLAN_HWFILTER", + [18] = "VLAN_HWTSO", + [19] = "LINKSTATE", + [20] = "NETMAP", + [21] = "RXCSUM_IPV6", + [22] = "TXCSUM_IPV6", + [24] = "TXRTLMT", + [25] = "HWRXTSTMP", + [26] = "NOMAP", + [27] = "TXTLS4", + [28] = "TXTLS6", + [29] = "VXLAN_HWCSUM", + [30] = "VXLAN_HWTSO", + [31] = "TXTLS_RTLMT", +}; -/* - * 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, const struct sockaddr_dl *sdl, - struct ifaddrs *ifa) +print_ifcap_nv(if_ctx *ctx) { - struct ifaddrs *ift; - struct ifstat ifs; + struct ifreq ifr = {}; nvlist_t *nvcap; const char *nvname; void *buf, *cookie; - int allfamilies, s, type; bool first, val; + int type; - if (afp == NULL) { - allfamilies = 1; - ifr.ifr_addr.sa_family = AF_LOCAL; - } else { - allfamilies = 0; - ifr.ifr_addr.sa_family = - afp->af_af == AF_LINK ? AF_LOCAL : afp->af_af; + buf = malloc(IFR_CAP_NV_MAXBUFSIZE); + if (buf == NULL) + Perror("malloc"); + ifr.ifr_cap_nv.buffer = buf; + ifr.ifr_cap_nv.buf_length = IFR_CAP_NV_MAXBUFSIZE; + if (ioctl_ctx_ifr(ctx, SIOCGIFCAPNV, &ifr) != 0) + Perror("ioctl (SIOCGIFCAPNV)"); + nvcap = nvlist_unpack(ifr.ifr_cap_nv.buffer, + ifr.ifr_cap_nv.length, 0); + if (nvcap == NULL) + Perror("nvlist_unpack"); + printf("\toptions"); + cookie = NULL; + for (first = true;; first = false) { + nvname = nvlist_next(nvcap, &type, &cookie); + if (nvname == NULL) { + printf("\n"); + break; + } + if (type == NV_TYPE_BOOL) { + val = nvlist_get_bool(nvcap, nvname); + if (val) { + printf("%c%s", + first ? ' ' : ',', nvname); + } + } + } + if (ctx->args->supmedia) { + printf("\tcapabilities"); + cookie = NULL; + for (first = true;; first = false) { + nvname = nvlist_next(nvcap, &type, + &cookie); + if (nvname == NULL) { + printf("\n"); + break; + } + if (type == NV_TYPE_BOOL) + printf("%c%s", first ? ' ' : + ',', nvname); + } } - strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + nvlist_destroy(nvcap); + free(buf); - 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); + if (ioctl_ctx(ctx, SIOCGIFCAP, (caddr_t)&ifr) != 0) + Perror("ioctl (SIOCGIFCAP)"); +} + +static void +print_ifcap(if_ctx *ctx) +{ + struct ifreq ifr = {}; + + if (ioctl_ctx_ifr(ctx, SIOCGIFCAP, &ifr) != 0) + return; + + if ((ifr.ifr_curcap & IFCAP_NV) != 0) + print_ifcap_nv(ctx); + else { + printf("\toptions=%x", ifr.ifr_curcap); + print_bits("options", &ifr.ifr_curcap, 1, IFCAPBITS, nitems(IFCAPBITS)); + putchar('\n'); + if (ctx->args->supmedia && ifr.ifr_reqcap != 0) { + printf("\tcapabilities=%x", ifr.ifr_reqcap); + print_bits("capabilities", &ifr.ifr_reqcap, 1, IFCAPBITS, nitems(IFCAPBITS)); + putchar('\n'); + } + } +} +#endif + +void +print_ifstatus(if_ctx *ctx) +{ + struct ifstat ifs; + + strlcpy(ifs.ifs_name, ctx->ifname, sizeof ifs.ifs_name); + if (ioctl_ctx(ctx, SIOCGIFSTATUS, &ifs) == 0) + printf("%s", ifs.ascii); +} + +void +print_metric(if_ctx *ctx) +{ + struct ifreq ifr = {}; - printf("%s: ", name); - printb("flags", ifa->ifa_flags, IFFBITS); - if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1) + if (ioctl_ctx_ifr(ctx, SIOCGIFMETRIC, &ifr) != -1) printf(" metric %d", ifr.ifr_metric); - if (ioctl(s, SIOCGIFMTU, &ifr) != -1) +} + +#ifdef WITHOUT_NETLINK +static void +print_mtu(if_ctx *ctx) +{ + struct ifreq ifr = {}; + + if (ioctl_ctx_ifr(ctx, SIOCGIFMTU, &ifr) != -1) printf(" mtu %d", ifr.ifr_mtu); - putchar('\n'); +} + +static void +print_description(if_ctx *ctx) +{ + struct ifreq ifr = {}; + ifr_set_name(&ifr, ctx->ifname); for (;;) { if ((descr = reallocf(descr, descrlen)) != NULL) { ifr.ifr_buffer.buffer = descr; ifr.ifr_buffer.length = descrlen; - if (ioctl(s, SIOCGIFDESCR, &ifr) == 0) { + if (ioctl_ctx(ctx, SIOCGIFDESCR, &ifr) == 0) { if (ifr.ifr_buffer.buffer == descr) { if (strlen(descr) > 0) printf("\tdescription: %s\n", @@ -1473,68 +1808,44 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl, "description"); break; } +} - if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) { - if ((ifr.ifr_curcap & IFCAP_NV) != 0) { - buf = malloc(IFR_CAP_NV_MAXBUFSIZE); - if (buf == NULL) - Perror("malloc"); - ifr.ifr_cap_nv.buffer = buf; - ifr.ifr_cap_nv.buf_length = IFR_CAP_NV_MAXBUFSIZE; - if (ioctl(s, SIOCGIFCAPNV, (caddr_t)&ifr) != 0) - Perror("ioctl (SIOCGIFCAPNV)"); - nvcap = nvlist_unpack(ifr.ifr_cap_nv.buffer, - ifr.ifr_cap_nv.length, 0); - if (nvcap == NULL) - Perror("nvlist_unpack"); - printf("\toptions"); - cookie = NULL; - for (first = true;; first = false) { - nvname = nvlist_next(nvcap, &type, &cookie); - if (nvname == NULL) { - printf("\n"); - break; - } - if (type == NV_TYPE_BOOL) { - val = nvlist_get_bool(nvcap, nvname); - if (val) { - printf("%c%s", - first ? ' ' : ',', nvname); - } - } - } - if (supmedia) { - printf("\tcapabilities"); - cookie = NULL; - for (first = true;; first = false) { - nvname = nvlist_next(nvcap, &type, - &cookie); - if (nvname == NULL) { - printf("\n"); - break; - } - if (type == NV_TYPE_BOOL) - printf("%c%s", first ? ' ' : - ',', nvname); - } - } - nvlist_destroy(nvcap); - free(buf); +/* + * Print the status of the interface. If an address family was + * specified, show only it; otherwise, show them all. + */ +static void +status(if_ctx *ctx, const struct sockaddr_dl *sdl __unused, struct ifaddrs *ifa) +{ + struct ifaddrs *ift; + int s, old_s; + struct ifconfig_args *args = ctx->args; + bool allfamilies = args->afp == NULL; + struct ifreq ifr = {}; - if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) != 0) - Perror("ioctl (SIOCGIFCAP)"); - } else 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'); - } - } - } + if (args->afp == NULL) + ifr.ifr_addr.sa_family = AF_LOCAL; + else + ifr.ifr_addr.sa_family = + args->afp->af_af == AF_LINK ? AF_LOCAL : args->afp->af_af; + + 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); + old_s = ctx->io_s; + ctx->io_s = s; + + printf("%s: flags=%x", ctx->ifname, ifa->ifa_flags); + print_bits("flags", &ifa->ifa_flags, 1, IFFBITS, nitems(IFFBITS)); + print_metric(ctx); + print_mtu(ctx); + putchar('\n'); + + print_description(ctx); - tunnel_status(s); + print_ifcap(ctx); + + tunnel_status(ctx); for (ift = ifa; ift != NULL; ift = ift->ifa_next) { if (ift->ifa_addr == NULL) @@ -1545,9 +1856,9 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl, const struct afswtch *p; p = af_getbyfamily(ift->ifa_addr->sa_family); if (p != NULL && p->af_status != NULL) - p->af_status(s, ift); - } else if (afp->af_af == ift->ifa_addr->sa_family) - afp->af_status(s, ift); + p->af_status(ctx, ift); + } else if (args->afp->af_af == ift->ifa_addr->sa_family) + args->afp->af_status(ctx, ift); } #if 0 if (allfamilies || afp->af_af == AF_LINK) { @@ -1567,29 +1878,28 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl, } #endif if (allfamilies) - af_other_status(s); - else if (afp->af_other_status != NULL) - afp->af_other_status(s); - - strlcpy(ifs.ifs_name, name, sizeof ifs.ifs_name); - if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) - printf("%s", ifs.ascii); + af_other_status(ctx); + else if (args->afp->af_other_status != NULL) + args->afp->af_other_status(ctx); - if (verbose > 0) - sfp_status(s, &ifr, verbose); + print_ifstatus(ctx); + if (args->verbose > 0) + sfp_status(ctx); close(s); + ctx->io_s = old_s; return; } +#endif -static void -tunnel_status(int s) +void +tunnel_status(if_ctx *ctx) { - af_all_tunnel_status(s); + af_all_tunnel_status(ctx); } -void -Perror(const char *cmd) +static void +Perrorc(const char *cmd, int error) { switch (errno) { @@ -1602,10 +1912,39 @@ Perror(const char *cmd) break; default: - err(1, "%s", cmd); + errc(1, error, "%s", cmd); } } +void +Perror(const char *cmd) +{ + Perrorc(cmd, errno); +} + +void +print_bits(const char *btype, uint32_t *v, const int v_count, + const char **names, const int n_count) +{ + int num = 0; + + for (int i = 0; i < v_count * 32; i++) { + bool is_set = v[i / 32] & (1U << (i % 32)); + if (is_set) { + if (num++ == 0) + printf("<"); + if (num != 1) + printf(","); + if (i < n_count) + printf("%s", names[i]); + else + printf("%s_%d", btype, i); + } + } + if (num > 0) + printf(">"); +} + /* * Print a value a la the %b format of the kernel's printf */ @@ -1638,7 +1977,7 @@ printb(const char *s, unsigned v, const char *bits) } void -print_vhid(const struct ifaddrs *ifa, const char *s) +print_vhid(const struct ifaddrs *ifa) { struct if_data *ifd; @@ -1653,32 +1992,34 @@ print_vhid(const struct ifaddrs *ifa, const char *s) } void -ifmaybeload(const char *name) +ifmaybeload(struct ifconfig_args *args, const char *name) { #define MOD_PREFIX_LEN 3 /* "if_" */ struct module_stat mstat; - int i, fileid, modid; + int fileid, modid; char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp; const char *cp; struct module_map_entry *mme; bool found; /* loading suppressed by the user */ - if (noload) + if (args->noload) return; /* trim the interface number off the end */ strlcpy(ifname, name, sizeof(ifname)); - for (dp = ifname; *dp != 0; dp++) - if (isdigit(*dp)) { - *dp = 0; + dp = ifname + strlen(ifname) - 1; + for (; dp > ifname; dp--) { + if (isdigit(*dp)) + *dp = '\0'; + else break; - } + } /* Either derive it from the map or guess otherwise */ *ifkind = '\0'; found = false; - for (i = 0; i < nitems(module_map); ++i) { + for (unsigned i = 0; i < nitems(module_map); ++i) { mme = &module_map[i]; if (strcmp(mme->ifname, ifname) == 0) { strlcpy(ifkind, mme->kldname, sizeof(ifkind)); @@ -1728,17 +2069,19 @@ ifmaybeload(const char *name) 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("down", IFF_UP, clearifflags), + DEF_CMD("arp", IFF_NOARP, clearifflags), DEF_CMD("-arp", IFF_NOARP, setifflags), DEF_CMD("debug", IFF_DEBUG, setifflags), - DEF_CMD("-debug", -IFF_DEBUG, setifflags), + DEF_CMD("-debug", IFF_DEBUG, clearifflags), DEF_CMD_ARG("description", setifdescr), DEF_CMD_ARG("descr", setifdescr), DEF_CMD("-description", 0, unsetifdescr), DEF_CMD("-descr", 0, unsetifdescr), + DEF_CMD("allmulti", IFF_PALLMULTI, setifflags), + DEF_CMD("-allmulti", IFF_PALLMULTI, clearifflags), DEF_CMD("promisc", IFF_PPROMISC, setifflags), - DEF_CMD("-promisc", -IFF_PPROMISC, setifflags), + DEF_CMD("-promisc", IFF_PPROMISC, clearifflags), DEF_CMD("add", IFF_UP, notealias), DEF_CMD("alias", IFF_UP, notealias), DEF_CMD("-alias", -IFF_UP, notealias), @@ -1747,7 +2090,7 @@ static struct cmd basic_cmds[] = { #ifdef notdef #define EN_SWABIPS 0x1000 DEF_CMD("swabips", EN_SWABIPS, setifflags), - DEF_CMD("-swabips", -EN_SWABIPS, setifflags), + DEF_CMD("-swabips", EN_SWABIPS, clearifflags), #endif DEF_CMD_ARG("netmask", setifnetmask), DEF_CMD_ARG("metric", setifmetric), @@ -1760,64 +2103,66 @@ static struct cmd basic_cmds[] = { DEF_CMD_ARG("-vnet", setifrvnet), #endif DEF_CMD("link0", IFF_LINK0, setifflags), - DEF_CMD("-link0", -IFF_LINK0, setifflags), + DEF_CMD("-link0", IFF_LINK0, clearifflags), DEF_CMD("link1", IFF_LINK1, setifflags), - DEF_CMD("-link1", -IFF_LINK1, setifflags), + DEF_CMD("-link1", IFF_LINK1, clearifflags), DEF_CMD("link2", IFF_LINK2, setifflags), - DEF_CMD("-link2", -IFF_LINK2, setifflags), + DEF_CMD("-link2", IFF_LINK2, clearifflags), DEF_CMD("monitor", IFF_MONITOR, setifflags), - DEF_CMD("-monitor", -IFF_MONITOR, setifflags), + DEF_CMD("-monitor", IFF_MONITOR, clearifflags), DEF_CMD("mextpg", IFCAP_MEXTPG, setifcap), - DEF_CMD("-mextpg", -IFCAP_MEXTPG, setifcap), + DEF_CMD("-mextpg", IFCAP_MEXTPG, clearifcap), DEF_CMD("staticarp", IFF_STATICARP, setifflags), - DEF_CMD("-staticarp", -IFF_STATICARP, setifflags), + DEF_CMD("-staticarp", IFF_STATICARP, clearifflags), DEF_CMD("stickyarp", IFF_STICKYARP, setifflags), - DEF_CMD("-stickyarp", -IFF_STICKYARP, setifflags), + DEF_CMD("-stickyarp", IFF_STICKYARP, clearifflags), DEF_CMD("rxcsum6", IFCAP_RXCSUM_IPV6, setifcap), - DEF_CMD("-rxcsum6", -IFCAP_RXCSUM_IPV6, setifcap), + DEF_CMD("-rxcsum6", IFCAP_RXCSUM_IPV6, clearifcap), DEF_CMD("txcsum6", IFCAP_TXCSUM_IPV6, setifcap), - DEF_CMD("-txcsum6", -IFCAP_TXCSUM_IPV6, setifcap), + DEF_CMD("-txcsum6", IFCAP_TXCSUM_IPV6, clearifcap), DEF_CMD("rxcsum", IFCAP_RXCSUM, setifcap), - DEF_CMD("-rxcsum", -IFCAP_RXCSUM, setifcap), + DEF_CMD("-rxcsum", IFCAP_RXCSUM, clearifcap), DEF_CMD("txcsum", IFCAP_TXCSUM, setifcap), - DEF_CMD("-txcsum", -IFCAP_TXCSUM, setifcap), + DEF_CMD("-txcsum", IFCAP_TXCSUM, clearifcap), DEF_CMD("netcons", IFCAP_NETCONS, setifcap), - DEF_CMD("-netcons", -IFCAP_NETCONS, setifcap), + DEF_CMD("-netcons", IFCAP_NETCONS, clearifcap), DEF_CMD_ARG("pcp", setifpcp), DEF_CMD("-pcp", 0, disableifpcp), DEF_CMD("polling", IFCAP_POLLING, setifcap), - DEF_CMD("-polling", -IFCAP_POLLING, setifcap), + DEF_CMD("-polling", IFCAP_POLLING, clearifcap), DEF_CMD("tso6", IFCAP_TSO6, setifcap), - DEF_CMD("-tso6", -IFCAP_TSO6, setifcap), + DEF_CMD("-tso6", IFCAP_TSO6, clearifcap), DEF_CMD("tso4", IFCAP_TSO4, setifcap), - DEF_CMD("-tso4", -IFCAP_TSO4, setifcap), + DEF_CMD("-tso4", IFCAP_TSO4, clearifcap), DEF_CMD("tso", IFCAP_TSO, setifcap), - DEF_CMD("-tso", -IFCAP_TSO, setifcap), + DEF_CMD("-tso", IFCAP_TSO, clearifcap), DEF_CMD("toe", IFCAP_TOE, setifcap), - DEF_CMD("-toe", -IFCAP_TOE, setifcap), + DEF_CMD("-toe", IFCAP_TOE, clearifcap), DEF_CMD("lro", IFCAP_LRO, setifcap), - DEF_CMD("-lro", -IFCAP_LRO, setifcap), + DEF_CMD("-lro", IFCAP_LRO, clearifcap), DEF_CMD("txtls", IFCAP_TXTLS, setifcap), - DEF_CMD("-txtls", -IFCAP_TXTLS, setifcap), + DEF_CMD("-txtls", IFCAP_TXTLS, clearifcap), DEF_CMD_SARG("rxtls", IFCAP2_RXTLS4_NAME "," IFCAP2_RXTLS6_NAME, setifcapnv), DEF_CMD_SARG("-rxtls", "-"IFCAP2_RXTLS4_NAME ",-" IFCAP2_RXTLS6_NAME, setifcapnv), + DEF_CMD_SARG("ipsec", IFCAP2_IPSEC_OFFLOAD_NAME, setifcapnv), + DEF_CMD_SARG("-ipsec", "-"IFCAP2_IPSEC_OFFLOAD_NAME, setifcapnv), DEF_CMD("wol", IFCAP_WOL, setifcap), - DEF_CMD("-wol", -IFCAP_WOL, setifcap), + DEF_CMD("-wol", IFCAP_WOL, clearifcap), DEF_CMD("wol_ucast", IFCAP_WOL_UCAST, setifcap), - DEF_CMD("-wol_ucast", -IFCAP_WOL_UCAST, setifcap), + DEF_CMD("-wol_ucast", IFCAP_WOL_UCAST, clearifcap), DEF_CMD("wol_mcast", IFCAP_WOL_MCAST, setifcap), - DEF_CMD("-wol_mcast", -IFCAP_WOL_MCAST, setifcap), + DEF_CMD("-wol_mcast", IFCAP_WOL_MCAST, clearifcap), DEF_CMD("wol_magic", IFCAP_WOL_MAGIC, setifcap), - DEF_CMD("-wol_magic", -IFCAP_WOL_MAGIC, setifcap), + DEF_CMD("-wol_magic", IFCAP_WOL_MAGIC, clearifcap), DEF_CMD("txrtlmt", IFCAP_TXRTLMT, setifcap), - DEF_CMD("-txrtlmt", -IFCAP_TXRTLMT, setifcap), + DEF_CMD("-txrtlmt", IFCAP_TXRTLMT, clearifcap), DEF_CMD("txtlsrtlmt", IFCAP_TXTLS_RTLMT, setifcap), - DEF_CMD("-txtlsrtlmt", -IFCAP_TXTLS_RTLMT, setifcap), + DEF_CMD("-txtlsrtlmt", IFCAP_TXTLS_RTLMT, clearifcap), DEF_CMD("hwrxtstmp", IFCAP_HWRXTSTMP, setifcap), - DEF_CMD("-hwrxtstmp", -IFCAP_HWRXTSTMP, setifcap), - DEF_CMD("normal", -IFF_LINK0, setifflags), + DEF_CMD("-hwrxtstmp", IFCAP_HWRXTSTMP, clearifcap), + DEF_CMD("normal", IFF_LINK0, clearifflags), DEF_CMD("compress", IFF_LINK0, setifflags), DEF_CMD("noicmp", IFF_LINK1, setifflags), DEF_CMD_ARG("mtu", setifmtu), diff --git a/sbin/ifconfig/ifconfig.h b/sbin/ifconfig/ifconfig.h index 26f68d67cec2..555e7dbaca64 100644 --- a/sbin/ifconfig/ifconfig.h +++ b/sbin/ifconfig/ifconfig.h @@ -32,24 +32,41 @@ * SUCH DAMAGE. * * so there! - * - * $FreeBSD$ */ #pragma once #include <libifconfig.h> +#include <stdbool.h> +#include <net/if_types.h> #define __constructor __attribute__((constructor)) +#ifdef WITHOUT_NETLINK +#define __netlink_used __unused +#define __netlink_unused +#else +#define __netlink_used +#define __netlink_unused __unused +#endif + struct afswtch; struct cmd; +struct snl_state; +struct ifconfig_args; +struct ifconfig_context { + struct ifconfig_args *args; + const struct afswtch *afp; + int io_s; /* fd to use for ioctl() */ + struct snl_state *io_ss; /* NETLINK_ROUTE socket */ + const char *ifname; /* Current interface name */ + char _ifname_storage_ioctl[IFNAMSIZ]; +}; +typedef struct ifconfig_context if_ctx; -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); -typedef void c_func3(const char *cmd, const char *arg, int s, - const struct afswtch *afp); +typedef void c_func(if_ctx *ctx, const char *cmd, int arg); +typedef void c_func2(if_ctx *ctx, const char *arg1, const char *arg2); +typedef void c_func3(if_ctx *ctx, const char *cmd, const char *arg); struct cmd { const char *c_name; @@ -69,17 +86,12 @@ struct cmd { }; void cmd_register(struct cmd *); -typedef void callback_func(int s, void *); +typedef void callback_func(if_ctx *, void *); void callback_register(callback_func *, void *); /* - * Macros for declaring command functions and initializing entries. + * Macros for initializing command handlers. */ -#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) { \ .c_name = (name), \ @@ -139,16 +151,39 @@ void callback_register(callback_func *, void *); .c_next = NULL, \ } +#define ioctl_ctx(ctx, _req, ...) ioctl((ctx)->io_s, _req, ## __VA_ARGS__) +int ioctl_ctx_ifr(if_ctx *ctx, unsigned long cmd, struct ifreq *ifr); + struct ifaddrs; struct addrinfo; enum { - RIDADDR, - ADDR, - MASK, - DSTADDR, + RIDADDR = 0, + ADDR = 1, + MASK = 2, + DSTADDR = 3, +#ifdef WITHOUT_NETLINK + BRDADDR = 3, +#else + BRDADDR = 4, +#endif }; +struct snl_parsed_addr; +struct snl_parsed_link; +typedef struct snl_parsed_link if_link_t; +typedef struct snl_parsed_addr if_addr_t; + +typedef void af_setvhid_f(int vhid); +typedef void af_status_nl_f(if_ctx *ctx, if_link_t *link, if_addr_t *ifa); +typedef void af_status_f(if_ctx *ctx, const struct ifaddrs *); +typedef void af_other_status_f(if_ctx *ctx); +typedef void af_postproc_f(if_ctx *ctx, int newaddr, int ifflags); +typedef int af_exec_f(if_ctx *ctx, unsigned long action, void *data); +typedef void af_copyaddr_f(if_ctx *ctx, int to, int from); +typedef void af_status_tunnel_f(if_ctx *ctx); +typedef void af_settunnel_f(if_ctx *ctx, struct addrinfo *srcres, struct addrinfo *dstres); + struct afswtch { const char *af_name; /* as given on cmd line, e.g. "inet" */ short af_af; /* AF_* */ @@ -161,14 +196,19 @@ struct afswtch { * is defined then it is invoked after all address status * is presented. */ - void (*af_status)(int, const struct ifaddrs *); - void (*af_other_status)(int); - /* parse address method */ +#ifndef WITHOUT_NETLINK + af_status_nl_f *af_status; +#else + af_status_f *af_status; +#endif + af_other_status_f *af_other_status; void (*af_getaddr)(const char *, int); + af_copyaddr_f *af_copyaddr; /* Copy address between <RID|*>ADDR */ /* parse prefix method (IPv6) */ void (*af_getprefix)(const char *, int); - void (*af_postproc)(int s, const struct afswtch *, - int newaddr, int ifflags); + af_postproc_f *af_postproc; + af_setvhid_f *af_setvhid; /* Set CARP vhid for an address */ + af_exec_f *af_exec; /* Handler to interact with kernel */ u_long af_difaddr; /* set dst if address ioctl */ u_long af_aifaddr; /* set if address ioctl */ void *af_ridreq; /* */ @@ -176,11 +216,31 @@ struct afswtch { 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); + af_status_tunnel_f *af_status_tunnel; + af_settunnel_f *af_settunnel; }; void af_register(struct afswtch *); +int af_exec_ioctl(if_ctx *ctx, unsigned long action, void *data); + +struct ifconfig_args { + bool all; /* Match everything */ + bool downonly; /* Down-only items */ + bool uponly; /* Up-only items */ + bool namesonly; /* Output only names */ + bool noload; /* Do not load relevant kernel modules */ + bool supmedia; /* Supported media */ + bool printkeys; /* Print security keys */ + bool allfamilies; /* Print all families */ + bool drivername; /* Print driver name */ + int verbose; /* verbosity level */ + int argc; + char **argv; + const char *ifname; /* Requested interface name */ + const char *matchgroup; /* Group name to match */ + const char *nogroup; /* Group name to exclude */ + const struct afswtch *afp; /* AF we're operating on */ + const char *jail_name; /* Jail name or jail id specified */ +}; struct option { const char *opt; @@ -191,38 +251,81 @@ struct option { void opt_register(struct option *); extern ifconfig_handle_t *lifh; -extern struct ifreq ifr; -extern char name[IFNAMSIZ]; /* name of interface */ extern int allmedia; -extern int supmedia; -extern int printkeys; -extern int newaddr; -extern int verbose; -extern int printifname; extern int exit_code; +extern char *f_inet, *f_inet6, *f_ether, *f_addr; -void setifcap(const char *, int value, int s, const struct afswtch *); -void setifcapnv(const char *vname, const char *arg, int s, - const struct afswtch *afp); +void clearifcap(if_ctx *ctx, const char *, int value); +void setifcap(if_ctx *ctx, const char *, int value); +void setifcapnv(if_ctx *ctx, const char *vname, const char *arg); void Perror(const char *cmd); +void print_bits(const char *btype, uint32_t *v, const int v_count, + const char **names, const int n_count); void printb(const char *s, unsigned value, const char *bits); -void ifmaybeload(const char *name); +void ifmaybeload(struct ifconfig_args *args, const char *name); typedef int clone_match_func(const char *); -typedef void clone_callback_func(int, struct ifreq *); +typedef void clone_callback_func(if_ctx *, struct ifreq *); void clone_setdefcallback_prefix(const char *, clone_callback_func *); void clone_setdefcallback_filter(clone_match_func *, clone_callback_func *); -void sfp_status(int s, struct ifreq *ifr, int verbose); +void sfp_status(if_ctx *ctx); + +struct sockaddr_dl; +bool match_ether(const struct sockaddr_dl *sdl); +bool match_if_flags(struct ifconfig_args *args, int if_flags); +int ifconfig_ioctl(if_ctx *ctx, int iscreate, const struct afswtch *uafp); +bool group_member(const char *ifname, const char *match, const char *nomatch); +void tunnel_status(if_ctx *ctx); +struct afswtch *af_getbyfamily(int af); +void af_other_status(if_ctx *ctx); +void print_ifstatus(if_ctx *ctx); +void print_metric(if_ctx *ctx); +ifType convert_iftype(ifType iftype); + +/* Netlink-related functions */ +void list_interfaces_nl(struct ifconfig_args *args); +int ifconfig_nl(if_ctx *ctx, int iscreate, + const struct afswtch *uafp); +uint32_t if_nametoindex_nl(struct snl_state *ss, const char *ifname); /* - * XXX expose this so modules that neeed to know of any pending + * XXX expose this so modules that need to know of any pending * operations on ifmedia can avoid cmd line ordering confusion. */ -struct ifmediareq *ifmedia_getstate(void); +struct ifmediareq *ifmedia_getstate(if_ctx *ctx); -void print_vhid(const struct ifaddrs *, const char *); +void print_vhid(const struct ifaddrs *); -void ioctl_ifcreate(int s, struct ifreq *); +void ifcreate_ioctl(if_ctx *ctx, struct ifreq *ifr); + +/* Helpers */ +struct sockaddr_in; +struct sockaddr_in6; +struct sockaddr; + +static inline struct sockaddr_in6 * +satosin6(struct sockaddr *sa) +{ + return ((struct sockaddr_in6 *)(void *)sa); +} + +static inline struct sockaddr_in * +satosin(struct sockaddr *sa) +{ + return ((struct sockaddr_in *)(void *)sa); +} + +static inline struct sockaddr_dl * +satosdl(struct sockaddr *sa) +{ + return ((struct sockaddr_dl *)(void *)sa); +} + +static inline const struct sockaddr_dl * +satosdl_c(const struct sockaddr *sa) +{ + return ((const struct sockaddr_dl *)(const void *)sa); +} diff --git a/sbin/ifconfig/ifconfig_netlink.c b/sbin/ifconfig/ifconfig_netlink.c new file mode 100644 index 000000000000..b5badfd585b8 --- /dev/null +++ b/sbin/ifconfig/ifconfig_netlink.c @@ -0,0 +1,495 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2022 Alexander V. Chernikov <melifaro@FreeBSD.org> + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#define _WANT_IFCAP_BIT_NAMES + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> +#include <err.h> +#include <errno.h> +#include <netdb.h> + +#include <sys/bitcount.h> +#include <sys/param.h> +#include <sys/linker.h> +#include <sys/module.h> +#include <sys/socket.h> +#include <sys/sysctl.h> +#include <sys/time.h> +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <net/ethernet.h> +#include <net/if.h> +#include <net/if_dl.h> +#include <net/if_strings.h> +#include <net/if_types.h> +#include "ifconfig.h" +#include "ifconfig_netlink.h" + +static const char *IFFBITS[] = { + "UP", /* 00:0x1 IFF_UP*/ + "BROADCAST", /* 01:0x2 IFF_BROADCAST*/ + "DEBUG", /* 02:0x4 IFF_DEBUG*/ + "LOOPBACK", /* 03:0x8 IFF_LOOPBACK*/ + "POINTOPOINT", /* 04:0x10 IFF_POINTOPOINT*/ + "NEEDSEPOCH", /* 05:0x20 IFF_NEEDSEPOCH*/ + "RUNNING", /* 06:0x40 IFF_DRV_RUNNING*/ + "NOARP", /* 07:0x80 IFF_NOARP*/ + "PROMISC", /* 08:0x100 IFF_PROMISC*/ + "ALLMULTI", /* 09:0x200 IFF_ALLMULTI*/ + "DRV_OACTIVE", /* 10:0x400 IFF_DRV_OACTIVE*/ + "SIMPLEX", /* 11:0x800 IFF_SIMPLEX*/ + "LINK0", /* 12:0x1000 IFF_LINK0*/ + "LINK1", /* 13:0x2000 IFF_LINK1*/ + "LINK2", /* 14:0x4000 IFF_LINK2*/ + "MULTICAST", /* 15:0x8000 IFF_MULTICAST*/ + "CANTCONFIG", /* 16:0x10000 IFF_CANTCONFIG*/ + "PPROMISC", /* 17:0x20000 IFF_PPROMISC*/ + "MONITOR", /* 18:0x40000 IFF_MONITOR*/ + "STATICARP", /* 19:0x80000 IFF_STATICARP*/ + "STICKYARP", /* 20:0x100000 IFF_STICKYARP*/ + "DYING", /* 21:0x200000 IFF_DYING*/ + "RENAMING", /* 22:0x400000 IFF_RENAMING*/ + "PALLMULTI", /* 23:0x800000 IFF_PALLMULTI*/ + "LOWER_UP", /* 24:0x1000000 IFF_NETLINK_1*/ +}; + +static void +nl_init_socket(struct snl_state *ss) +{ + if (snl_init(ss, NETLINK_ROUTE)) + return; + + if (modfind("netlink") == -1 && errno == ENOENT) { + /* Try to load */ + if (kldload("netlink") == -1) + err(1, "netlink is not loaded and load attempt failed"); + if (snl_init(ss, NETLINK_ROUTE)) + return; + } + + err(1, "unable to open netlink socket"); +} + +int +ifconfig_nl(if_ctx *ctx, int iscreate, + const struct afswtch *uafp) +{ + struct snl_state ss = {}; + + nl_init_socket(&ss); + ctx->io_ss = &ss; + + int error = ifconfig_ioctl(ctx, iscreate, uafp); + + snl_free(&ss); + ctx->io_ss = NULL; + + return (error); +} + +struct ifa { + struct ifa *next; + uint32_t idx; + struct snl_parsed_addr addr; +}; + +struct iface { + struct snl_parsed_link link; + struct ifa *ifa; + uint32_t ifa_count; + uint32_t idx; +}; + +struct ifmap { + uint32_t size; + uint32_t count; + struct iface **ifaces; +}; + +/* + * Returns ifmap ifindex->snl_parsed_link. + * Memory is allocated using snl temporary buffers + */ +static struct ifmap * +prepare_ifmap(struct snl_state *ss, const char *ifname) +{ + struct snl_writer nw = {}; + + snl_init_writer(ss, &nw); + struct nlmsghdr *hdr = snl_create_msg_request(&nw, RTM_GETLINK); + hdr->nlmsg_flags |= NLM_F_DUMP; + snl_reserve_msg_object(&nw, struct ifinfomsg); + if (ifname != NULL) + snl_add_msg_attr_string(&nw, IFLA_IFNAME, ifname); + + if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr)) + return (NULL); + + uint32_t nlmsg_seq = hdr->nlmsg_seq; + struct ifmap *ifmap = snl_allocz(ss, sizeof(*ifmap)); + struct snl_errmsg_data e = {}; + + while ((hdr = snl_read_reply_multi(ss, nlmsg_seq, &e)) != NULL) { + struct iface *iface = snl_allocz(ss, sizeof(*iface)); + + if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_link_parser, &iface->link)) + continue; + if (iface->link.ifi_index >= ifmap->size) { + size_t new_size = MAX(ifmap->size, 32); + + while (new_size <= iface->link.ifi_index + 1) + new_size *= 2; + + struct iface **ifaces= snl_allocz(ss, new_size * sizeof(void *)); + memcpy(ifaces, ifmap->ifaces, ifmap->size * sizeof(void *)); + ifmap->ifaces = ifaces; + ifmap->size = new_size; + } + ifmap->ifaces[iface->link.ifi_index] = iface; + ifmap->count++; + iface->idx = ifmap->count; + } + return (ifmap); +} + +uint32_t +if_nametoindex_nl(struct snl_state *ss, const char *ifname) +{ + struct snl_writer nw = {}; + struct snl_parsed_link_simple link = {}; + + snl_init_writer(ss, &nw); + struct nlmsghdr *hdr = snl_create_msg_request(&nw, RTM_GETLINK); + snl_reserve_msg_object(&nw, struct ifinfomsg); + snl_add_msg_attr_string(&nw, IFLA_IFNAME, ifname); + + if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr)) + return (0); + + hdr = snl_read_reply(ss, hdr->nlmsg_seq); + if (hdr->nlmsg_type != NL_RTM_NEWLINK) + return (0); + if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_link_parser_simple, &link)) + return (0); + + return (link.ifi_index); +} + +ifType +convert_iftype(ifType iftype) +{ + switch (iftype) { + case IFT_IEEE8023ADLAG: + return (IFT_ETHER); + case IFT_INFINIBANDLAG: + return (IFT_INFINIBAND); + default: + return (iftype); + } +} + +static void +prepare_ifaddrs(struct snl_state *ss, struct ifmap *ifmap) +{ + struct snl_writer nw = {}; + + snl_init_writer(ss, &nw); + struct nlmsghdr *hdr = snl_create_msg_request(&nw, RTM_GETADDR); + hdr->nlmsg_flags |= NLM_F_DUMP; + snl_reserve_msg_object(&nw, struct ifaddrmsg); + + if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr)) + return; + + uint32_t nlmsg_seq = hdr->nlmsg_seq; + struct snl_errmsg_data e = {}; + uint32_t count = 0; + + while ((hdr = snl_read_reply_multi(ss, nlmsg_seq, &e)) != NULL) { + struct ifa *ifa = snl_allocz(ss, sizeof(*ifa)); + + if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_addr_parser, &ifa->addr)) + continue; + + const uint32_t ifindex = ifa->addr.ifa_index; + if (ifindex >= ifmap->size || ifmap->ifaces[ifindex] == NULL) + continue; + struct iface *iface = ifmap->ifaces[ifindex]; + ifa->next = iface->ifa; + ifa->idx = ++count; + iface->ifa = ifa; + iface->ifa_count++; + } +} + +static bool +match_iface(struct ifconfig_args *args, struct iface *iface) +{ + if_link_t *link = &iface->link; + + if (args->ifname != NULL && strcmp(args->ifname, link->ifla_ifname)) + return (false); + + if (!match_if_flags(args, link->ifi_flags)) + return (false); + + if (!group_member(link->ifla_ifname, args->matchgroup, args->nogroup)) + return (false); + + if (args->afp == NULL) + return (true); + + if (!strcmp(args->afp->af_name, "ether")) { + if (link->ifla_address == NULL) + return (false); + + struct sockaddr_dl sdl = { + .sdl_len = sizeof(struct sockaddr_dl), + .sdl_family = AF_LINK, + .sdl_type = convert_iftype(link->ifi_type), + .sdl_alen = NLA_DATA_LEN(link->ifla_address), + }; + return (match_ether(&sdl)); + } else if (args->afp->af_af == AF_LINK) + /* + * The rtnetlink(4) RTM_GETADDR does not list link level + * addresses, so latter cycle won't match anything. Short + * circuit on RTM_GETLINK has provided us an address. + */ + return (link->ifla_address != NULL); + + for (struct ifa *ifa = iface->ifa; ifa != NULL; ifa = ifa->next) { + if (args->afp->af_af == ifa->addr.ifa_family) + return (true); + } + + return (false); +} + +/* Sort according to the kernel-provided order */ +static int +cmp_iface(const void *_a, const void *_b) +{ + const struct iface *a = *((const void * const *)_a); + const struct iface *b = *((const void * const *)_b); + + return ((a->idx > b->idx) * 2 - 1); +} + +static int +cmp_ifaddr(const void *_a, const void *_b) +{ + const struct ifa *a = *((const void * const *)_a); + const struct ifa *b = *((const void * const *)_b); + + if (a->addr.ifa_family != b->addr.ifa_family) + return ((a->addr.ifa_family > b->addr.ifa_family) * 2 - 1); + return ((a->idx > b->idx) * 2 - 1); +} + +static void +sort_iface_ifaddrs(struct snl_state *ss, struct iface *iface) +{ + if (iface->ifa_count == 0) + return; + + struct ifa **sorted_ifaddrs = snl_allocz(ss, iface->ifa_count * sizeof(void *)); + struct ifa *ifa = iface->ifa; + + for (uint32_t i = 0; i < iface->ifa_count; i++) { + struct ifa *ifa_next = ifa->next; + + sorted_ifaddrs[i] = ifa; + ifa->next = NULL; + ifa = ifa_next; + } + qsort(sorted_ifaddrs, iface->ifa_count, sizeof(void *), cmp_ifaddr); + ifa = sorted_ifaddrs[0]; + iface->ifa = ifa; + for (uint32_t i = 1; i < iface->ifa_count; i++) { + ifa->next = sorted_ifaddrs[i]; + ifa = sorted_ifaddrs[i]; + } +} + +static void +print_ifcaps(if_ctx *ctx, if_link_t *link) +{ + uint32_t sz_u32 = roundup2(link->iflaf_caps.nla_bitset_size, 32) / 32; + + if (sz_u32 > 0) { + uint32_t *caps = link->iflaf_caps.nla_bitset_value; + + printf("\toptions=%x", caps[0]); + print_bits("IFCAPS", caps, sz_u32, ifcap_bit_names, nitems(ifcap_bit_names)); + putchar('\n'); + } + + if (ctx->args->supmedia && sz_u32 > 0) { + uint32_t *caps = link->iflaf_caps.nla_bitset_mask; + + printf("\tcapabilities=%x", caps[0]); + print_bits("IFCAPS", caps, sz_u32, ifcap_bit_names, nitems(ifcap_bit_names)); + putchar('\n'); + } +} + +static void +status_nl(if_ctx *ctx, struct iface *iface) +{ + if_link_t *link = &iface->link; + struct ifconfig_args *args = ctx->args; + char *drivername = NULL; + + printf("%s: ", link->ifla_ifname); + + printf("flags=%x", link->ifi_flags); + print_bits("IFF", &link->ifi_flags, 1, IFFBITS, nitems(IFFBITS)); + + print_metric(ctx); + printf(" mtu %d\n", link->ifla_mtu); + + if (link->ifla_ifalias != NULL) + printf("\tdescription: %s\n", link->ifla_ifalias); + + print_ifcaps(ctx, link); + tunnel_status(ctx); + + if (args->allfamilies | (args->afp != NULL && args->afp->af_af == AF_LINK)) { + /* Start with link-level */ + const struct afswtch *p = af_getbyfamily(AF_LINK); + if (p != NULL && link->ifla_address != NULL) + p->af_status(ctx, link, NULL); + } + + sort_iface_ifaddrs(ctx->io_ss, iface); + + for (struct ifa *ifa = iface->ifa; ifa != NULL; ifa = ifa->next) { + if (args->allfamilies) { + const struct afswtch *p = af_getbyfamily(ifa->addr.ifa_family); + + if (p != NULL) + p->af_status(ctx, link, &ifa->addr); + } else if (args->afp->af_af == ifa->addr.ifa_family) { + const struct afswtch *p = args->afp; + + p->af_status(ctx, link, &ifa->addr); + } + } + + /* TODO: convert to netlink */ + if (args->allfamilies) + af_other_status(ctx); + else if (args->afp->af_other_status != NULL) + args->afp->af_other_status(ctx); + + print_ifstatus(ctx); + if (args->drivername || args->verbose) { + if (ifconfig_get_orig_name(lifh, link->ifla_ifname, + &drivername) != 0) { + if (ifconfig_err_errtype(lifh) == OTHER) + fprintf(stderr, "get original name: %s\n", + strerror(ifconfig_err_errno(lifh))); + else + fprintf(stderr, + "get original name: error type %d\n", + ifconfig_err_errtype(lifh)); + exit_code = 1; + } + if (drivername != NULL) + printf("\tdrivername: %s\n", drivername); + free(drivername); + } + if (args->verbose > 0) + sfp_status(ctx); +} + +static int +get_local_socket(void) +{ + int s = socket(AF_LOCAL, SOCK_DGRAM, 0); + + if (s < 0) + err(1, "socket(family %u,SOCK_DGRAM)", AF_LOCAL); + return (s); +} + +void +list_interfaces_nl(struct ifconfig_args *args) +{ + struct snl_state ss = {}; + struct ifconfig_context _ctx = { + .args = args, + .io_s = get_local_socket(), + .io_ss = &ss, + }; + struct ifconfig_context *ctx = &_ctx; + + nl_init_socket(&ss); + + struct ifmap *ifmap = prepare_ifmap(&ss, args->ifname); + struct iface **sorted_ifaces = snl_allocz(&ss, ifmap->count * sizeof(void *)); + for (uint32_t i = 0, num = 0; i < ifmap->size; i++) { + if (ifmap->ifaces[i] != NULL) { + sorted_ifaces[num++] = ifmap->ifaces[i]; + if (num == ifmap->count) + break; + } + } + qsort(sorted_ifaces, ifmap->count, sizeof(void *), cmp_iface); + prepare_ifaddrs(&ss, ifmap); + + for (uint32_t i = 0, num = 0; i < ifmap->count; i++) { + struct iface *iface = sorted_ifaces[i]; + + if (!match_iface(args, iface)) + continue; + + ctx->ifname = iface->link.ifla_ifname; + + if (args->namesonly) { + if (num++ != 0) + printf(" "); + fputs(iface->link.ifla_ifname, stdout); + } else if (args->argc == 0) + status_nl(ctx, iface); + else + ifconfig_ioctl(ctx, 0, args->afp); + } + if (args->namesonly) + printf("\n"); + + close(ctx->io_s); + snl_free(&ss); +} + diff --git a/sbin/ifconfig/ifconfig_netlink.h b/sbin/ifconfig/ifconfig_netlink.h new file mode 100644 index 000000000000..1c762619a483 --- /dev/null +++ b/sbin/ifconfig/ifconfig_netlink.h @@ -0,0 +1,37 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2023 Alexander V. Chernikov <melifaro@FreeBSD.org> + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#pragma once + +#ifndef WITHOUT_NETLINK +#include <netlink/netlink.h> +#include <netlink/netlink_route.h> +#include <netlink/netlink_snl.h> +#include <netlink/netlink_snl_route.h> +#include <netlink/netlink_snl_route_compat.h> +#include <netlink/netlink_snl_route_parsers.h> +#endif diff --git a/sbin/ifconfig/iffib.c b/sbin/ifconfig/iffib.c index 7cb21ce54b09..a99dd6885d08 100644 --- a/sbin/ifconfig/iffib.c +++ b/sbin/ifconfig/iffib.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2011 Alexander V. Chernikov * Copyright (c) 2011 Christian S.J. Peron @@ -26,8 +26,6 @@ * 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. - * - * $FreeBSD$ */ #include <sys/param.h> @@ -46,27 +44,27 @@ #include "ifconfig.h" static void -fib_status(int s) +fib_status(if_ctx *ctx) { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); - if (ioctl(s, SIOCGIFFIB, (caddr_t)&ifr) == 0 && + strlcpy(ifr.ifr_name, ctx->ifname, sizeof(ifr.ifr_name)); + if (ioctl_ctx(ctx, SIOCGIFFIB, (caddr_t)&ifr) == 0 && ifr.ifr_fib != RT_DEFAULT_FIB) printf("\tfib: %u\n", ifr.ifr_fib); memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); - if (ioctl(s, SIOCGTUNFIB, (caddr_t)&ifr) == 0 && + strlcpy(ifr.ifr_name, ctx->ifname, sizeof(ifr.ifr_name)); + if (ioctl_ctx(ctx, SIOCGTUNFIB, (caddr_t)&ifr) == 0 && ifr.ifr_fib != RT_DEFAULT_FIB) printf("\ttunnelfib: %u\n", ifr.ifr_fib); } static void -setiffib(const char *val, int dummy __unused, int s, - const struct afswtch *afp) +setiffib(if_ctx *ctx, const char *val, int dummy __unused) { + struct ifreq ifr = {}; unsigned long fib; char *ep; @@ -76,16 +74,15 @@ setiffib(const char *val, int dummy __unused, int s, return; } - strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); ifr.ifr_fib = fib; - if (ioctl(s, SIOCSIFFIB, (caddr_t)&ifr) < 0) + if (ioctl_ctx_ifr(ctx, SIOCSIFFIB, &ifr) < 0) warn("ioctl (SIOCSIFFIB)"); } static void -settunfib(const char *val, int dummy __unused, int s, - const struct afswtch *afp) +settunfib(if_ctx *ctx, const char *val, int dummy __unused) { + struct ifreq ifr = {}; unsigned long fib; char *ep; @@ -95,9 +92,8 @@ settunfib(const char *val, int dummy __unused, int s, return; } - strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); ifr.ifr_fib = fib; - if (ioctl(s, SIOCSTUNFIB, (caddr_t)&ifr) < 0) + if (ioctl_ctx_ifr(ctx, SIOCSTUNFIB, &ifr) < 0) warn("ioctl (SIOCSTUNFIB)"); } diff --git a/sbin/ifconfig/ifgif.c b/sbin/ifconfig/ifgif.c index b75dd4e0a7dd..991cf110678f 100644 --- a/sbin/ifconfig/ifgif.c +++ b/sbin/ifconfig/ifgif.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2009 Hiroki Sato. All rights reserved. * @@ -25,11 +25,6 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif - #include <sys/param.h> #include <sys/ioctl.h> #include <sys/socket.h> @@ -53,31 +48,32 @@ static const char rcsid[] = #include "ifconfig.h" -#define GIFBITS "\020\2IGNORE_SOURCE" - -static void gif_status(int); +static const char *GIFBITS[] = { + [1] = "IGNORE_SOURCE", +}; static void -gif_status(int s) +gif_status(if_ctx *ctx) { int opts; + struct ifreq ifr = { .ifr_data = (caddr_t)&opts }; - ifr.ifr_data = (caddr_t)&opts; - if (ioctl(s, GIFGOPTS, &ifr) == -1) + if (ioctl_ctx_ifr(ctx, GIFGOPTS, &ifr) == -1) return; if (opts == 0) return; - printb("\toptions", opts, GIFBITS); + printf("\toptions=%x", opts); + print_bits("options", &opts, 1, GIFBITS, nitems(GIFBITS)); putchar('\n'); } static void -setgifopts(const char *val, int d, int s, const struct afswtch *afp) +setgifopts(if_ctx *ctx, const char *val __unused, int d) { int opts; + struct ifreq ifr = { .ifr_data = (caddr_t)&opts }; - ifr.ifr_data = (caddr_t)&opts; - if (ioctl(s, GIFGOPTS, &ifr) == -1) { + if (ioctl_ctx_ifr(ctx, GIFGOPTS, &ifr) == -1) { warn("ioctl(GIFGOPTS)"); return; } @@ -87,7 +83,7 @@ setgifopts(const char *val, int d, int s, const struct afswtch *afp) else opts |= d; - if (ioctl(s, GIFSOPTS, &ifr) == -1) { + if (ioctl_ctx(ctx, GIFSOPTS, &ifr) == -1) { warn("ioctl(GIFSOPTS)"); return; } diff --git a/sbin/ifconfig/ifgre.c b/sbin/ifconfig/ifgre.c index d6fc0d5b53a2..43c86a546167 100644 --- a/sbin/ifconfig/ifgre.c +++ b/sbin/ifconfig/ifgre.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2008 Andrew Thompson. All rights reserved. * @@ -25,9 +25,6 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #include <sys/param.h> #include <sys/ioctl.h> #include <sys/socket.h> @@ -44,63 +41,62 @@ __FBSDID("$FreeBSD$"); #include "ifconfig.h" -#define GREBITS "\020\01ENABLE_CSUM\02ENABLE_SEQ\03UDPENCAP" - -static void gre_status(int s); +static const char *GREBITS[] = { + [0] = "ENABLE_CSUM", + [1] = "ENABLE_SEQ", + [2] = "UDPENCAP", +}; static void -gre_status(int s) +gre_status(if_ctx *ctx) { - uint32_t opts, port; + uint32_t opts = 0, port; + struct ifreq ifr = { .ifr_data = (caddr_t)&opts }; - opts = 0; - ifr.ifr_data = (caddr_t)&opts; - if (ioctl(s, GREGKEY, &ifr) == 0) + if (ioctl_ctx(ctx, GREGKEY, &ifr) == 0) if (opts != 0) printf("\tgrekey: 0x%x (%u)\n", opts, opts); opts = 0; - if (ioctl(s, GREGOPTS, &ifr) != 0 || opts == 0) + if (ioctl_ctx(ctx, GREGOPTS, &ifr) != 0 || opts == 0) return; port = 0; ifr.ifr_data = (caddr_t)&port; - if (ioctl(s, GREGPORT, &ifr) == 0 && port != 0) + if (ioctl_ctx_ifr(ctx, GREGPORT, &ifr) == 0 && port != 0) printf("\tudpport: %u\n", port); - printb("\toptions", opts, GREBITS); + printf("\toptions=%x", opts); + print_bits("options", &opts, 1, GREBITS, nitems(GREBITS)); putchar('\n'); } static void -setifgrekey(const char *val, int dummy __unused, int s, - const struct afswtch *afp) +setifgrekey(if_ctx *ctx, const char *val, int dummy __unused) { uint32_t grekey = strtol(val, NULL, 0); + struct ifreq ifr = { .ifr_data = (caddr_t)&grekey }; - strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); ifr.ifr_data = (caddr_t)&grekey; - if (ioctl(s, GRESKEY, (caddr_t)&ifr) < 0) + if (ioctl_ctx_ifr(ctx, GRESKEY, &ifr) < 0) warn("ioctl (set grekey)"); } static void -setifgreport(const char *val, int dummy __unused, int s, - const struct afswtch *afp) +setifgreport(if_ctx *ctx, const char *val, int dummy __unused) { uint32_t udpport = strtol(val, NULL, 0); + struct ifreq ifr = { .ifr_data = (caddr_t)&udpport }; - strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); - ifr.ifr_data = (caddr_t)&udpport; - if (ioctl(s, GRESPORT, (caddr_t)&ifr) < 0) + if (ioctl_ctx_ifr(ctx, GRESPORT, &ifr) < 0) warn("ioctl (set udpport)"); } static void -setifgreopts(const char *val, int d, int s, const struct afswtch *afp) +setifgreopts(if_ctx *ctx, const char *val __unused, int d) { uint32_t opts; + struct ifreq ifr = { .ifr_data = (caddr_t)&opts }; - ifr.ifr_data = (caddr_t)&opts; - if (ioctl(s, GREGOPTS, &ifr) == -1) { + if (ioctl_ctx_ifr(ctx, GREGOPTS, &ifr) == -1) { warn("ioctl(GREGOPTS)"); return; } @@ -110,7 +106,7 @@ setifgreopts(const char *val, int d, int s, const struct afswtch *afp) else opts |= d; - if (ioctl(s, GRESOPTS, &ifr) == -1) { + if (ioctl_ctx(ctx, GRESOPTS, &ifr) == -1) { warn("ioctl(GIFSOPTS)"); return; } diff --git a/sbin/ifconfig/ifgroup.c b/sbin/ifconfig/ifgroup.c index 7f1173c316d7..49cce678bb5e 100644 --- a/sbin/ifconfig/ifgroup.c +++ b/sbin/ifconfig/ifgroup.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2006 Max Laier. All rights reserved. * @@ -25,11 +25,6 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <sys/param.h> #include <sys/ioctl.h> #include <sys/socket.h> @@ -47,49 +42,45 @@ static const char rcsid[] = #include "ifconfig.h" -/* ARGSUSED */ static void -setifgroup(const char *group_name, int d, int s, const struct afswtch *rafp) +setifgroup(if_ctx *ctx, const char *group_name, int dummy __unused) { - struct ifgroupreq ifgr; + struct ifgroupreq ifgr = {}; - memset(&ifgr, 0, sizeof(ifgr)); - strlcpy(ifgr.ifgr_name, name, IFNAMSIZ); + strlcpy(ifgr.ifgr_name, ctx->ifname, IFNAMSIZ); if (group_name[0] && isdigit(group_name[strlen(group_name) - 1])) errx(1, "setifgroup: group names may not end in a digit"); if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ) errx(1, "setifgroup: group name too long"); - if (ioctl(s, SIOCAIFGROUP, (caddr_t)&ifgr) == -1 && errno != EEXIST) + if (ioctl_ctx(ctx, SIOCAIFGROUP, (caddr_t)&ifgr) == -1 && errno != EEXIST) err(1," SIOCAIFGROUP"); } -/* ARGSUSED */ static void -unsetifgroup(const char *group_name, int d, int s, const struct afswtch *rafp) +unsetifgroup(if_ctx *ctx, const char *group_name, int dummy __unused) { - struct ifgroupreq ifgr; + struct ifgroupreq ifgr = {}; - memset(&ifgr, 0, sizeof(ifgr)); - strlcpy(ifgr.ifgr_name, name, IFNAMSIZ); + strlcpy(ifgr.ifgr_name, ctx->ifname, IFNAMSIZ); if (group_name[0] && isdigit(group_name[strlen(group_name) - 1])) errx(1, "unsetifgroup: group names may not end in a digit"); if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ) errx(1, "unsetifgroup: group name too long"); - if (ioctl(s, SIOCDIFGROUP, (caddr_t)&ifgr) == -1 && errno != ENOENT) + if (ioctl_ctx(ctx, SIOCDIFGROUP, (caddr_t)&ifgr) == -1 && errno != ENOENT) err(1, "SIOCDIFGROUP"); } static void -getifgroups(int s) +getifgroups(if_ctx *ctx) { struct ifgroupreq ifgr; size_t cnt; - if (ifconfig_get_groups(lifh, name, &ifgr) == -1) + if (ifconfig_get_groups(lifh, ctx->ifname, &ifgr) == -1) return; cnt = 0; @@ -114,7 +105,7 @@ printgroup(const char *groupname) { struct ifgroupreq ifgr; struct ifg_req *ifg; - int len, cnt = 0; + unsigned int len; int s; s = socket(AF_LOCAL, SOCK_DGRAM, 0); @@ -140,7 +131,6 @@ printgroup(const char *groupname) ifg++) { len -= sizeof(struct ifg_req); printf("%s\n", ifg->ifgrq_member); - cnt++; } free(ifgr.ifgr_groups); @@ -151,19 +141,23 @@ static struct cmd group_cmds[] = { DEF_CMD_ARG("group", setifgroup), DEF_CMD_ARG("-group", unsetifgroup), }; + static struct afswtch af_group = { .af_name = "af_group", .af_af = AF_UNSPEC, .af_other_status = getifgroups, }; -static struct option group_gopt = { "g:", "[-g groupname]", printgroup }; + +static struct option group_gopt = { + .opt = "g:", + .opt_usage = "[-g groupname]", + .cb = printgroup, +}; static __constructor void group_ctor(void) { - int i; - - for (i = 0; i < nitems(group_cmds); i++) + for (size_t i = 0; i < nitems(group_cmds); i++) cmd_register(&group_cmds[i]); af_register(&af_group); opt_register(&group_gopt); diff --git a/sbin/ifconfig/ifieee80211.c b/sbin/ifconfig/ifieee80211.c index ee611a14b45e..e73dcc2c4f24 100644 --- a/sbin/ifconfig/ifieee80211.c +++ b/sbin/ifconfig/ifieee80211.c @@ -25,8 +25,6 @@ * 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. - * - * $FreeBSD$ */ /*- @@ -72,6 +70,7 @@ #include <net/if_media.h> #include <net/route.h> +#define WANT_NET80211 1 #include <net80211/ieee80211_ioctl.h> #include <net80211/ieee80211_freebsd.h> #include <net80211/ieee80211_superg.h> @@ -134,8 +133,10 @@ #define IEEE80211_FVHT_VHT 0x000000001 /* CONF: VHT supported */ #define IEEE80211_FVHT_USEVHT40 0x000000002 /* CONF: Use VHT40 */ #define IEEE80211_FVHT_USEVHT80 0x000000004 /* CONF: Use VHT80 */ -#define IEEE80211_FVHT_USEVHT160 0x000000008 /* CONF: Use VHT160 */ -#define IEEE80211_FVHT_USEVHT80P80 0x000000010 /* CONF: Use VHT 80+80 */ +#define IEEE80211_FVHT_USEVHT80P80 0x000000008 /* CONF: Use VHT 80+80 */ +#define IEEE80211_FVHT_USEVHT160 0x000000010 /* CONF: Use VHT160 */ +#define IEEE80211_FVHT_STBC_TX 0x00000020 /* CONF: STBC tx enabled */ +#define IEEE80211_FVHT_STBC_RX 0x00000040 /* CONF: STBC rx enabled */ #endif /* Helper macros unified. */ @@ -173,17 +174,17 @@ static const char *modename[IEEE80211_MODE_MAX] = { [IEEE80211_MODE_VHT_5GHZ] = "11ac", }; -static void set80211(int s, int type, int val, int len, void *data); -static int get80211(int s, int type, void *data, int len); -static int get80211len(int s, int type, void *data, int len, int *plen); -static int get80211val(int s, int type, int *val); +static void set80211(if_ctx *ctx, int type, int val, int len, void *data); +static int get80211(if_ctx *ctx, int type, void *data, int len); +static int get80211len(if_ctx *ctx, int type, void *data, int len, int *plen); +static int get80211val(if_ctx *ctx, int type, int *val); static const char *get_string(const char *val, const char *sep, u_int8_t *buf, int *lenp); static void print_string(const u_int8_t *buf, int len); static void print_regdomain(const struct ieee80211_regdomain *, int); -static void print_channels(int, const struct ieee80211req_chaninfo *, +static void print_channels(if_ctx *, const struct ieee80211req_chaninfo *, int allchans, int verbose); -static void regdomain_makechannels(struct ieee80211_regdomain_req *, +static void regdomain_makechannels(if_ctx *, struct ieee80211_regdomain_req *, const struct ieee80211_devcaps_req *); static const char *mesh_linkstate_string(uint8_t state); @@ -196,30 +197,32 @@ static struct ieee80211_txparams_req txparams; static int gottxparams = 0; static struct ieee80211_channel curchan; static int gotcurchan = 0; -static struct ifmediareq *ifmr; +static struct ifmediareq *global_ifmr; + +/* HT */ static int htconf = 0; -static int gothtconf = 0; +static int gothtconf = 0; static void -gethtconf(int s) +gethtconf(if_ctx *ctx) { if (gothtconf) return; - if (get80211val(s, IEEE80211_IOC_HTCONF, &htconf) < 0) + if (get80211val(ctx, IEEE80211_IOC_HTCONF, &htconf) < 0) warn("unable to get HT configuration information"); gothtconf = 1; } /* VHT */ static int vhtconf = 0; -static int gotvhtconf = 0; +static int gotvhtconf = 0; static void -getvhtconf(int s) +getvhtconf(if_ctx *ctx) { if (gotvhtconf) return; - if (get80211val(s, IEEE80211_IOC_VHTCONF, &vhtconf) < 0) + if (get80211val(ctx, IEEE80211_IOC_VHTCONF, &vhtconf) < 0) warn("unable to get VHT configuration information"); gotvhtconf = 1; } @@ -229,19 +232,19 @@ getvhtconf(int s) * to handle mapping between frequency and IEEE channel number. */ static void -getchaninfo(int s) +getchaninfo(if_ctx *ctx) { if (chaninfo != NULL) return; chaninfo = malloc(IEEE80211_CHANINFO_SIZE(MAXCHAN)); if (chaninfo == NULL) errx(1, "no space for channel list"); - if (get80211(s, IEEE80211_IOC_CHANINFO, chaninfo, + if (get80211(ctx, IEEE80211_IOC_CHANINFO, chaninfo, IEEE80211_CHANINFO_SIZE(MAXCHAN)) < 0) err(1, "unable to get channel information"); - ifmr = ifmedia_getstate(); - gethtconf(s); - getvhtconf(s); + global_ifmr = ifmedia_getstate(ctx); + gethtconf(ctx); + getvhtconf(ctx); } static struct regdata * @@ -264,7 +267,7 @@ getregdata(void) * 11b > 11g. */ static int -canpromote(int i, int from, int to) +canpromote(unsigned int i, uint32_t from, uint32_t to) { const struct ieee80211_channel *fc = &chaninfo->ic_chans[i]; u_int j; @@ -301,7 +304,7 @@ canpromote(int i, int from, int to) * XXX VHT */ static int -promote(int i) +promote(unsigned int i) { /* * Query the current mode of the interface in case it's @@ -317,7 +320,7 @@ promote(int i) * the socket descriptor down to here so we can make * the ifmedia_getstate call ourselves. */ - int chanmode = ifmr != NULL ? IFM_MODE(ifmr->ifm_current) : IFM_AUTO; + int chanmode = global_ifmr != NULL ? IFM_MODE(global_ifmr->ifm_current) : IFM_AUTO; /* when ambiguous promote to ``best'' */ /* NB: we abitrarily pick HT40+ over HT40- */ @@ -347,7 +350,7 @@ promote(int i) } static void -mapfreq(struct ieee80211_channel *chan, int freq, int flags) +mapfreq(struct ieee80211_channel *chan, uint16_t freq, unsigned int flags) { u_int i; @@ -367,7 +370,7 @@ mapfreq(struct ieee80211_channel *chan, int freq, int flags) } static void -mapchan(struct ieee80211_channel *chan, int ieee, int flags) +mapchan(struct ieee80211_channel *chan, uint8_t ieee, unsigned int flags) { u_int i; @@ -387,16 +390,16 @@ mapchan(struct ieee80211_channel *chan, int ieee, int flags) } static const struct ieee80211_channel * -getcurchan(int s) +getcurchan(if_ctx *ctx) { if (gotcurchan) return &curchan; - if (get80211(s, IEEE80211_IOC_CURCHAN, &curchan, sizeof(curchan)) < 0) { + if (get80211(ctx, IEEE80211_IOC_CURCHAN, &curchan, sizeof(curchan)) < 0) { int val; /* fall back to legacy ioctl */ - if (get80211val(s, IEEE80211_IOC_CHANNEL, &val) < 0) + if (get80211val(ctx, IEEE80211_IOC_CHANNEL, &val) < 0) err(-1, "cannot figure out current channel"); - getchaninfo(s); + getchaninfo(ctx); mapchan(&curchan, val, 0); } gotcurchan = 1; @@ -436,62 +439,62 @@ chan2mode(const struct ieee80211_channel *c) } static void -getroam(int s) +getroam(if_ctx *ctx) { if (gotroam) return; - if (get80211(s, IEEE80211_IOC_ROAM, + if (get80211(ctx, IEEE80211_IOC_ROAM, &roamparams, sizeof(roamparams)) < 0) err(1, "unable to get roaming parameters"); gotroam = 1; } static void -setroam_cb(int s, void *arg) +setroam_cb(if_ctx *ctx, void *arg) { struct ieee80211_roamparams_req *roam = arg; - set80211(s, IEEE80211_IOC_ROAM, 0, sizeof(*roam), roam); + set80211(ctx, IEEE80211_IOC_ROAM, 0, sizeof(*roam), roam); } static void -gettxparams(int s) +gettxparams(if_ctx *ctx) { if (gottxparams) return; - if (get80211(s, IEEE80211_IOC_TXPARAMS, + if (get80211(ctx, IEEE80211_IOC_TXPARAMS, &txparams, sizeof(txparams)) < 0) err(1, "unable to get transmit parameters"); gottxparams = 1; } static void -settxparams_cb(int s, void *arg) +settxparams_cb(if_ctx *ctx, void *arg) { struct ieee80211_txparams_req *txp = arg; - set80211(s, IEEE80211_IOC_TXPARAMS, 0, sizeof(*txp), txp); + set80211(ctx, IEEE80211_IOC_TXPARAMS, 0, sizeof(*txp), txp); } static void -getregdomain(int s) +getregdomain(if_ctx *ctx) { if (gotregdomain) return; - if (get80211(s, IEEE80211_IOC_REGDOMAIN, + if (get80211(ctx, IEEE80211_IOC_REGDOMAIN, ®domain, sizeof(regdomain)) < 0) err(1, "unable to get regulatory domain info"); gotregdomain = 1; } static void -getdevcaps(int s, struct ieee80211_devcaps_req *dc) +getdevcaps(if_ctx *ctx, struct ieee80211_devcaps_req *dc) { - if (get80211(s, IEEE80211_IOC_DEVCAPS, dc, + if (get80211(ctx, IEEE80211_IOC_DEVCAPS, dc, IEEE80211_DEVCAPS_SPACE(dc)) < 0) err(1, "unable to get device capabilities"); } static void -setregdomain_cb(int s, void *arg) +setregdomain_cb(if_ctx *ctx, void *arg) { struct ieee80211_regdomain_req *req; struct ieee80211_regdomain *rd = arg; @@ -545,7 +548,7 @@ setregdomain_cb(int s, void *arg) if (dc == NULL) errx(1, "no space for device capabilities"); dc->dc_chaninfo.ic_nchans = MAXCHAN; - getdevcaps(s, dc); + getdevcaps(ctx, dc); #if 0 if (verbose) { printf("drivercaps: 0x%x\n", dc->dc_drivercaps); @@ -563,8 +566,8 @@ setregdomain_cb(int s, void *arg) if (req == NULL) errx(1, "no space for regdomain request"); req->rd = *rd; - regdomain_makechannels(req, dc); - if (verbose) { + regdomain_makechannels(ctx, req, dc); + if (ctx->args->verbose) { LINE_INIT(':'); print_regdomain(rd, 1/*verbose*/); LINE_BREAK(); @@ -576,11 +579,11 @@ setregdomain_cb(int s, void *arg) errx(1, "no space for channel list"); memcpy(chaninfo, &req->chaninfo, IEEE80211_CHANINFO_SPACE(&req->chaninfo)); - print_channels(s, &req->chaninfo, 1/*allchans*/, 1/*verbose*/); + print_channels(ctx, &req->chaninfo, 1/*allchans*/, 1/*verbose*/); } if (req->chaninfo.ic_nchans == 0) errx(1, "no channels calculated"); - set80211(s, IEEE80211_IOC_REGDOMAIN, 0, + set80211(ctx, IEEE80211_IOC_REGDOMAIN, 0, IEEE80211_REGDOMAIN_SPACE(req), req); free(req); free(dc); @@ -602,7 +605,7 @@ isanyarg(const char *arg) } static void -set80211ssid(const char *val, int d, int s, const struct afswtch *rafp) +set80211ssid(if_ctx *ctx, const char *val, int dummy __unused) { int ssid; int len; @@ -620,11 +623,11 @@ set80211ssid(const char *val, int d, int s, const struct afswtch *rafp) if (get_string(val, NULL, data, &len) == NULL) exit(1); - set80211(s, IEEE80211_IOC_SSID, ssid, len, data); + set80211(ctx, IEEE80211_IOC_SSID, ssid, len, data); } static void -set80211meshid(const char *val, int d, int s, const struct afswtch *rafp) +set80211meshid(if_ctx *ctx, const char *val, int dummy __unused) { int len; u_int8_t data[IEEE80211_NWID_LEN]; @@ -634,11 +637,11 @@ set80211meshid(const char *val, int d, int s, const struct afswtch *rafp) if (get_string(val, NULL, data, &len) == NULL) exit(1); - set80211(s, IEEE80211_IOC_MESH_ID, 0, len, data); + set80211(ctx, IEEE80211_IOC_MESH_ID, 0, len, data); } static void -set80211stationname(const char *val, int d, int s, const struct afswtch *rafp) +set80211stationname(if_ctx *ctx, const char *val, int dummy __unused) { int len; u_int8_t data[33]; @@ -647,7 +650,7 @@ set80211stationname(const char *val, int d, int s, const struct afswtch *rafp) len = sizeof(data); get_string(val, NULL, data, &len); - set80211(s, IEEE80211_IOC_STATIONNAME, 0, len, data); + set80211(ctx, IEEE80211_IOC_STATIONNAME, 0, len, data); } /* @@ -662,7 +665,7 @@ set80211stationname(const char *val, int d, int s, const struct afswtch *rafp) * The result is not validated here; it's assumed to be * checked against the channel table fetched from the kernel. */ -static int +static unsigned int getchannelflags(const char *val, int freq) { #define _CHAN_HT 0x80000000 @@ -806,9 +809,9 @@ getchannelflags(const char *val, int freq) } static void -getchannel(int s, struct ieee80211_channel *chan, const char *val) +getchannel(if_ctx *ctx, struct ieee80211_channel *chan, const char *val) { - int v, flags; + unsigned int v, flags; char *eptr; memset(chan, 0, sizeof(*chan)); @@ -816,7 +819,7 @@ getchannel(int s, struct ieee80211_channel *chan, const char *val) chan->ic_freq = IEEE80211_CHAN_ANY; return; } - getchaninfo(s); + getchaninfo(ctx); errno = 0; v = strtol(val, &eptr, 10); if (val[0] == '\0' || val == eptr || errno == ERANGE || @@ -833,27 +836,27 @@ getchannel(int s, struct ieee80211_channel *chan, const char *val) } static void -set80211channel(const char *val, int d, int s, const struct afswtch *rafp) +set80211channel(if_ctx *ctx, const char *val, int dummy __unused) { struct ieee80211_channel chan; - getchannel(s, &chan, val); - set80211(s, IEEE80211_IOC_CURCHAN, 0, sizeof(chan), &chan); + getchannel(ctx, &chan, val); + set80211(ctx, IEEE80211_IOC_CURCHAN, 0, sizeof(chan), &chan); } static void -set80211chanswitch(const char *val, int d, int s, const struct afswtch *rafp) +set80211chanswitch(if_ctx *ctx, const char *val, int dummy __unused) { struct ieee80211_chanswitch_req csr; - getchannel(s, &csr.csa_chan, val); + getchannel(ctx, &csr.csa_chan, val); csr.csa_mode = 1; csr.csa_count = 5; - set80211(s, IEEE80211_IOC_CHANSWITCH, 0, sizeof(csr), &csr); + set80211(ctx, IEEE80211_IOC_CHANSWITCH, 0, sizeof(csr), &csr); } static void -set80211authmode(const char *val, int d, int s, const struct afswtch *rafp) +set80211authmode(if_ctx *ctx, const char *val, int dummy __unused) { int mode; @@ -871,11 +874,11 @@ set80211authmode(const char *val, int d, int s, const struct afswtch *rafp) errx(1, "unknown authmode"); } - set80211(s, IEEE80211_IOC_AUTHMODE, mode, 0, NULL); + set80211(ctx, IEEE80211_IOC_AUTHMODE, mode, 0, NULL); } static void -set80211powersavemode(const char *val, int d, int s, const struct afswtch *rafp) +set80211powersavemode(if_ctx *ctx, const char *val, int dummy __unused) { int mode; @@ -893,28 +896,28 @@ set80211powersavemode(const char *val, int d, int s, const struct afswtch *rafp) errx(1, "unknown powersavemode"); } - set80211(s, IEEE80211_IOC_POWERSAVE, mode, 0, NULL); + set80211(ctx, IEEE80211_IOC_POWERSAVE, mode, 0, NULL); } static void -set80211powersave(const char *val, int d, int s, const struct afswtch *rafp) +set80211powersave(if_ctx *ctx, const char *val __unused, int d) { if (d == 0) - set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_OFF, + set80211(ctx, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_OFF, 0, NULL); else - set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_ON, + set80211(ctx, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_ON, 0, NULL); } static void -set80211powersavesleep(const char *val, int d, int s, const struct afswtch *rafp) +set80211powersavesleep(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_POWERSAVESLEEP, atoi(val), 0, NULL); + set80211(ctx, IEEE80211_IOC_POWERSAVESLEEP, atoi(val), 0, NULL); } static void -set80211wepmode(const char *val, int d, int s, const struct afswtch *rafp) +set80211wepmode(if_ctx *ctx, const char *val, int dummy __unused) { int mode; @@ -928,13 +931,13 @@ set80211wepmode(const char *val, int d, int s, const struct afswtch *rafp) errx(1, "unknown wep mode"); } - set80211(s, IEEE80211_IOC_WEP, mode, 0, NULL); + set80211(ctx, IEEE80211_IOC_WEP, mode, 0, NULL); } static void -set80211wep(const char *val, int d, int s, const struct afswtch *rafp) +set80211wep(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_WEP, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_WEP, d, 0, NULL); } static int @@ -944,16 +947,16 @@ isundefarg(const char *arg) } static void -set80211weptxkey(const char *val, int d, int s, const struct afswtch *rafp) +set80211weptxkey(if_ctx *ctx, const char *val, int dummy __unused) { if (isundefarg(val)) - set80211(s, IEEE80211_IOC_WEPTXKEY, IEEE80211_KEYIX_NONE, 0, NULL); + set80211(ctx, IEEE80211_IOC_WEPTXKEY, IEEE80211_KEYIX_NONE, 0, NULL); else - set80211(s, IEEE80211_IOC_WEPTXKEY, atoi(val)-1, 0, NULL); + set80211(ctx, IEEE80211_IOC_WEPTXKEY, atoi(val)-1, 0, NULL); } static void -set80211wepkey(const char *val, int d, int s, const struct afswtch *rafp) +set80211wepkey(if_ctx *ctx, const char *val, int dummy __unused) { int key = 0; int len; @@ -968,7 +971,7 @@ set80211wepkey(const char *val, int d, int s, const struct afswtch *rafp) len = sizeof(data); get_string(val, NULL, data, &len); - set80211(s, IEEE80211_IOC_WEPKEY, key, len, data); + set80211(ctx, IEEE80211_IOC_WEPKEY, key, len, data); } /* @@ -977,13 +980,13 @@ set80211wepkey(const char *val, int d, int s, const struct afswtch *rafp) * it's not all that hard. */ static void -set80211nwkey(const char *val, int d, int s, const struct afswtch *rafp) +set80211nwkey(if_ctx *ctx, const char *val, int dummy __unused) { int txkey; int i, len; u_int8_t data[IEEE80211_KEYBUF_SIZE]; - set80211(s, IEEE80211_IOC_WEP, IEEE80211_WEP_ON, 0, NULL); + set80211(ctx, IEEE80211_IOC_WEP, IEEE80211_WEP_ON, 0, NULL); if (isdigit((int)val[0]) && val[1] == ':') { txkey = val[0]-'0'-1; @@ -996,7 +999,7 @@ set80211nwkey(const char *val, int d, int s, const struct afswtch *rafp) if (val == NULL) exit(1); - set80211(s, IEEE80211_IOC_WEPKEY, i, len, data); + set80211(ctx, IEEE80211_IOC_WEPKEY, i, len, data); } } else { bzero(data, sizeof(data)); @@ -1004,25 +1007,25 @@ set80211nwkey(const char *val, int d, int s, const struct afswtch *rafp) get_string(val, NULL, data, &len); txkey = 0; - set80211(s, IEEE80211_IOC_WEPKEY, 0, len, data); + set80211(ctx, IEEE80211_IOC_WEPKEY, 0, len, data); bzero(data, sizeof(data)); for (i = 1; i < 4; i++) - set80211(s, IEEE80211_IOC_WEPKEY, i, 0, data); + set80211(ctx, IEEE80211_IOC_WEPKEY, i, 0, data); } - set80211(s, IEEE80211_IOC_WEPTXKEY, txkey, 0, NULL); + set80211(ctx, IEEE80211_IOC_WEPTXKEY, txkey, 0, NULL); } static void -set80211rtsthreshold(const char *val, int d, int s, const struct afswtch *rafp) +set80211rtsthreshold(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_RTSTHRESHOLD, + set80211(ctx, IEEE80211_IOC_RTSTHRESHOLD, isundefarg(val) ? IEEE80211_RTS_MAX : atoi(val), 0, NULL); } static void -set80211protmode(const char *val, int d, int s, const struct afswtch *rafp) +set80211protmode(if_ctx *ctx, const char *val, int dummy __unused) { int mode; @@ -1036,11 +1039,11 @@ set80211protmode(const char *val, int d, int s, const struct afswtch *rafp) errx(1, "unknown protection mode"); } - set80211(s, IEEE80211_IOC_PROTMODE, mode, 0, NULL); + set80211(ctx, IEEE80211_IOC_PROTMODE, mode, 0, NULL); } static void -set80211htprotmode(const char *val, int d, int s, const struct afswtch *rafp) +set80211htprotmode(if_ctx *ctx, const char *val, int dummy __unused) { int mode; @@ -1052,11 +1055,11 @@ set80211htprotmode(const char *val, int d, int s, const struct afswtch *rafp) errx(1, "unknown protection mode"); } - set80211(s, IEEE80211_IOC_HTPROTMODE, mode, 0, NULL); + set80211(ctx, IEEE80211_IOC_HTPROTMODE, mode, 0, NULL); } static void -set80211txpower(const char *val, int d, int s, const struct afswtch *rafp) +set80211txpower(if_ctx *ctx, const char *val, int dummy __unused) { double v = atof(val); int txpow; @@ -1064,7 +1067,7 @@ set80211txpower(const char *val, int d, int s, const struct afswtch *rafp) txpow = (int) (2*v); if (txpow != 2*v) errx(-1, "invalid tx power (must be .5 dBm units)"); - set80211(s, IEEE80211_IOC_TXPOWER, txpow, 0, NULL); + set80211(ctx, IEEE80211_IOC_TXPOWER, txpow, 0, NULL); } #define IEEE80211_ROAMING_DEVICE 0 @@ -1072,7 +1075,7 @@ set80211txpower(const char *val, int d, int s, const struct afswtch *rafp) #define IEEE80211_ROAMING_MANUAL 2 static void -set80211roaming(const char *val, int d, int s, const struct afswtch *rafp) +set80211roaming(if_ctx *ctx, const char *val, int dummy __unused) { int mode; @@ -1085,41 +1088,41 @@ set80211roaming(const char *val, int d, int s, const struct afswtch *rafp) } else { errx(1, "unknown roaming mode"); } - set80211(s, IEEE80211_IOC_ROAMING, mode, 0, NULL); + set80211(ctx, IEEE80211_IOC_ROAMING, mode, 0, NULL); } static void -set80211wme(const char *val, int d, int s, const struct afswtch *rafp) +set80211wme(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_WME, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_WME, d, 0, NULL); } static void -set80211hidessid(const char *val, int d, int s, const struct afswtch *rafp) +set80211hidessid(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_HIDESSID, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_HIDESSID, d, 0, NULL); } static void -set80211apbridge(const char *val, int d, int s, const struct afswtch *rafp) +set80211apbridge(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_APBRIDGE, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_APBRIDGE, d, 0, NULL); } static void -set80211fastframes(const char *val, int d, int s, const struct afswtch *rafp) +set80211fastframes(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_FF, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_FF, d, 0, NULL); } static void -set80211dturbo(const char *val, int d, int s, const struct afswtch *rafp) +set80211dturbo(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_TURBOP, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_TURBOP, d, 0, NULL); } static void -set80211chanlist(const char *val, int d, int s, const struct afswtch *rafp) +set80211chanlist(if_ctx *ctx, const char *val, int dummy __unused) { struct ieee80211req_chanlist chanlist; char *temp, *cp, *tp; @@ -1166,14 +1169,13 @@ set80211chanlist(const char *val, int d, int s, const struct afswtch *rafp) break; cp = tp; } - set80211(s, IEEE80211_IOC_CHANLIST, 0, sizeof(chanlist), &chanlist); + set80211(ctx, IEEE80211_IOC_CHANLIST, 0, sizeof(chanlist), &chanlist); free(temp); } static void -set80211bssid(const char *val, int d, int s, const struct afswtch *rafp) +set80211bssid(if_ctx *ctx, const char *val, int dummy __unused) { - if (!isanyarg(val)) { char *temp; struct sockaddr_dl sdl; @@ -1188,12 +1190,12 @@ set80211bssid(const char *val, int d, int s, const struct afswtch *rafp) free(temp); if (sdl.sdl_alen != IEEE80211_ADDR_LEN) errx(1, "malformed link-level address"); - set80211(s, IEEE80211_IOC_BSSID, 0, + set80211(ctx, IEEE80211_IOC_BSSID, 0, IEEE80211_ADDR_LEN, LLADDR(&sdl)); } else { uint8_t zerobssid[IEEE80211_ADDR_LEN]; memset(zerobssid, 0, sizeof(zerobssid)); - set80211(s, IEEE80211_IOC_BSSID, 0, + set80211(ctx, IEEE80211_IOC_BSSID, 0, IEEE80211_ADDR_LEN, zerobssid); } } @@ -1212,94 +1214,95 @@ getac(const char *ac) errx(1, "unknown wme access class %s", ac); } -static -DECL_CMD_FUNC2(set80211cwmin, ac, val) +static void +set80211cwmin(if_ctx *ctx, const char *ac, const char *val) { - set80211(s, IEEE80211_IOC_WME_CWMIN, atoi(val), getac(ac), NULL); + set80211(ctx, IEEE80211_IOC_WME_CWMIN, atoi(val), getac(ac), NULL); } -static -DECL_CMD_FUNC2(set80211cwmax, ac, val) +static void +set80211cwmax(if_ctx *ctx, const char *ac, const char *val) { - set80211(s, IEEE80211_IOC_WME_CWMAX, atoi(val), getac(ac), NULL); + set80211(ctx, IEEE80211_IOC_WME_CWMAX, atoi(val), getac(ac), NULL); } -static -DECL_CMD_FUNC2(set80211aifs, ac, val) +static void +set80211aifs(if_ctx *ctx, const char *ac, const char *val) { - set80211(s, IEEE80211_IOC_WME_AIFS, atoi(val), getac(ac), NULL); + set80211(ctx, IEEE80211_IOC_WME_AIFS, atoi(val), getac(ac), NULL); } -static -DECL_CMD_FUNC2(set80211txoplimit, ac, val) +static void +set80211txoplimit(if_ctx *ctx, const char *ac, const char *val) { - set80211(s, IEEE80211_IOC_WME_TXOPLIMIT, atoi(val), getac(ac), NULL); + set80211(ctx, IEEE80211_IOC_WME_TXOPLIMIT, atoi(val), getac(ac), NULL); } -static -DECL_CMD_FUNC(set80211acm, ac, d) +static void +set80211acm(if_ctx *ctx, const char *ac, int dummy __unused) { - set80211(s, IEEE80211_IOC_WME_ACM, 1, getac(ac), NULL); + set80211(ctx, IEEE80211_IOC_WME_ACM, 1, getac(ac), NULL); } -static -DECL_CMD_FUNC(set80211noacm, ac, d) + +static void +set80211noacm(if_ctx *ctx, const char *ac, int dummy __unused) { - set80211(s, IEEE80211_IOC_WME_ACM, 0, getac(ac), NULL); + set80211(ctx, IEEE80211_IOC_WME_ACM, 0, getac(ac), NULL); } -static -DECL_CMD_FUNC(set80211ackpolicy, ac, d) +static void +set80211ackpolicy(if_ctx *ctx, const char *ac, int dummy __unused) { - set80211(s, IEEE80211_IOC_WME_ACKPOLICY, 1, getac(ac), NULL); + set80211(ctx, IEEE80211_IOC_WME_ACKPOLICY, 1, getac(ac), NULL); } -static -DECL_CMD_FUNC(set80211noackpolicy, ac, d) +static void +set80211noackpolicy(if_ctx *ctx, const char *ac, int dummy __unused) { - set80211(s, IEEE80211_IOC_WME_ACKPOLICY, 0, getac(ac), NULL); + set80211(ctx, IEEE80211_IOC_WME_ACKPOLICY, 0, getac(ac), NULL); } -static -DECL_CMD_FUNC2(set80211bsscwmin, ac, val) +static void +set80211bsscwmin(if_ctx *ctx, const char *ac, const char *val) { - set80211(s, IEEE80211_IOC_WME_CWMIN, atoi(val), + set80211(ctx, IEEE80211_IOC_WME_CWMIN, atoi(val), getac(ac)|IEEE80211_WMEPARAM_BSS, NULL); } -static -DECL_CMD_FUNC2(set80211bsscwmax, ac, val) +static void +set80211bsscwmax(if_ctx *ctx, const char *ac, const char *val) { - set80211(s, IEEE80211_IOC_WME_CWMAX, atoi(val), + set80211(ctx, IEEE80211_IOC_WME_CWMAX, atoi(val), getac(ac)|IEEE80211_WMEPARAM_BSS, NULL); } -static -DECL_CMD_FUNC2(set80211bssaifs, ac, val) +static void +set80211bssaifs(if_ctx *ctx, const char *ac, const char *val) { - set80211(s, IEEE80211_IOC_WME_AIFS, atoi(val), + set80211(ctx, IEEE80211_IOC_WME_AIFS, atoi(val), getac(ac)|IEEE80211_WMEPARAM_BSS, NULL); } -static -DECL_CMD_FUNC2(set80211bsstxoplimit, ac, val) +static void +set80211bsstxoplimit(if_ctx *ctx, const char *ac, const char *val) { - set80211(s, IEEE80211_IOC_WME_TXOPLIMIT, atoi(val), + set80211(ctx, IEEE80211_IOC_WME_TXOPLIMIT, atoi(val), getac(ac)|IEEE80211_WMEPARAM_BSS, NULL); } -static -DECL_CMD_FUNC(set80211dtimperiod, val, d) +static void +set80211dtimperiod(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_DTIM_PERIOD, atoi(val), 0, NULL); + set80211(ctx, IEEE80211_IOC_DTIM_PERIOD, atoi(val), 0, NULL); } -static -DECL_CMD_FUNC(set80211bintval, val, d) +static void +set80211bintval(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_BEACON_INTERVAL, atoi(val), 0, NULL); + set80211(ctx, IEEE80211_IOC_BEACON_INTERVAL, atoi(val), 0, NULL); } static void -set80211macmac(int s, int op, const char *val) +set80211macmac(if_ctx *ctx, int op, const char *val) { char *temp; struct sockaddr_dl sdl; @@ -1314,23 +1317,23 @@ set80211macmac(int s, int op, const char *val) free(temp); if (sdl.sdl_alen != IEEE80211_ADDR_LEN) errx(1, "malformed link-level address"); - set80211(s, op, 0, IEEE80211_ADDR_LEN, LLADDR(&sdl)); + set80211(ctx, op, 0, IEEE80211_ADDR_LEN, LLADDR(&sdl)); } -static -DECL_CMD_FUNC(set80211addmac, val, d) +static void +set80211addmac(if_ctx *ctx, const char *val, int dummy __unused) { - set80211macmac(s, IEEE80211_IOC_ADDMAC, val); + set80211macmac(ctx, IEEE80211_IOC_ADDMAC, val); } -static -DECL_CMD_FUNC(set80211delmac, val, d) +static void +set80211delmac(if_ctx *ctx, const char *val, int dummy __unused) { - set80211macmac(s, IEEE80211_IOC_DELMAC, val); + set80211macmac(ctx, IEEE80211_IOC_DELMAC, val); } -static -DECL_CMD_FUNC(set80211kickmac, val, d) +static void +set80211kickmac(if_ctx *ctx, const char *val, int dummy __unused) { char *temp; struct sockaddr_dl sdl; @@ -1350,17 +1353,17 @@ DECL_CMD_FUNC(set80211kickmac, val, d) mlme.im_op = IEEE80211_MLME_DEAUTH; mlme.im_reason = IEEE80211_REASON_AUTH_EXPIRE; memcpy(mlme.im_macaddr, LLADDR(&sdl), IEEE80211_ADDR_LEN); - set80211(s, IEEE80211_IOC_MLME, 0, sizeof(mlme), &mlme); + set80211(ctx, IEEE80211_IOC_MLME, 0, sizeof(mlme), &mlme); } -static -DECL_CMD_FUNC(set80211maccmd, val, d) +static void +set80211maccmd(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_MACCMD, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_MACCMD, d, 0, NULL); } static void -set80211meshrtmac(int s, int req, const char *val) +set80211meshrtmac(if_ctx *ctx, int req, const char *val) { char *temp; struct sockaddr_dl sdl; @@ -1375,30 +1378,30 @@ set80211meshrtmac(int s, int req, const char *val) free(temp); if (sdl.sdl_alen != IEEE80211_ADDR_LEN) errx(1, "malformed link-level address"); - set80211(s, IEEE80211_IOC_MESH_RTCMD, req, + set80211(ctx, IEEE80211_IOC_MESH_RTCMD, req, IEEE80211_ADDR_LEN, LLADDR(&sdl)); } -static -DECL_CMD_FUNC(set80211addmeshrt, val, d) +static void +set80211addmeshrt(if_ctx *ctx, const char *val, int dummy __unused) { - set80211meshrtmac(s, IEEE80211_MESH_RTCMD_ADD, val); + set80211meshrtmac(ctx, IEEE80211_MESH_RTCMD_ADD, val); } -static -DECL_CMD_FUNC(set80211delmeshrt, val, d) +static void +set80211delmeshrt(if_ctx *ctx, const char *val, int dummy __unused) { - set80211meshrtmac(s, IEEE80211_MESH_RTCMD_DELETE, val); + set80211meshrtmac(ctx, IEEE80211_MESH_RTCMD_DELETE, val); } -static -DECL_CMD_FUNC(set80211meshrtcmd, val, d) +static void +set80211meshrtcmd(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_MESH_RTCMD, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_MESH_RTCMD, d, 0, NULL); } -static -DECL_CMD_FUNC(set80211hwmprootmode, val, d) +static void +set80211hwmprootmode(if_ctx *ctx, const char *val, int dummy __unused) { int mode; @@ -1410,73 +1413,73 @@ DECL_CMD_FUNC(set80211hwmprootmode, val, d) mode = IEEE80211_HWMP_ROOTMODE_RANN; else mode = IEEE80211_HWMP_ROOTMODE_DISABLED; - set80211(s, IEEE80211_IOC_HWMP_ROOTMODE, mode, 0, NULL); + set80211(ctx, IEEE80211_IOC_HWMP_ROOTMODE, mode, 0, NULL); } -static -DECL_CMD_FUNC(set80211hwmpmaxhops, val, d) +static void +set80211hwmpmaxhops(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_HWMP_MAXHOPS, atoi(val), 0, NULL); + set80211(ctx, IEEE80211_IOC_HWMP_MAXHOPS, atoi(val), 0, NULL); } static void -set80211pureg(const char *val, int d, int s, const struct afswtch *rafp) +set80211pureg(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_PUREG, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_PUREG, d, 0, NULL); } static void -set80211quiet(const char *val, int d, int s, const struct afswtch *rafp) +set80211quiet(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_QUIET, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_QUIET, d, 0, NULL); } -static -DECL_CMD_FUNC(set80211quietperiod, val, d) +static void +set80211quietperiod(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_QUIET_PERIOD, atoi(val), 0, NULL); + set80211(ctx, IEEE80211_IOC_QUIET_PERIOD, atoi(val), 0, NULL); } -static -DECL_CMD_FUNC(set80211quietcount, val, d) +static void +set80211quietcount(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_QUIET_COUNT, atoi(val), 0, NULL); + set80211(ctx, IEEE80211_IOC_QUIET_COUNT, atoi(val), 0, NULL); } -static -DECL_CMD_FUNC(set80211quietduration, val, d) +static void +set80211quietduration(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_QUIET_DUR, atoi(val), 0, NULL); + set80211(ctx, IEEE80211_IOC_QUIET_DUR, atoi(val), 0, NULL); } -static -DECL_CMD_FUNC(set80211quietoffset, val, d) +static void +set80211quietoffset(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_QUIET_OFFSET, atoi(val), 0, NULL); + set80211(ctx, IEEE80211_IOC_QUIET_OFFSET, atoi(val), 0, NULL); } static void -set80211bgscan(const char *val, int d, int s, const struct afswtch *rafp) +set80211bgscan(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_BGSCAN, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_BGSCAN, d, 0, NULL); } -static -DECL_CMD_FUNC(set80211bgscanidle, val, d) +static void +set80211bgscanidle(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_BGSCAN_IDLE, atoi(val), 0, NULL); + set80211(ctx, IEEE80211_IOC_BGSCAN_IDLE, atoi(val), 0, NULL); } -static -DECL_CMD_FUNC(set80211bgscanintvl, val, d) +static void +set80211bgscanintvl(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_BGSCAN_INTERVAL, atoi(val), 0, NULL); + set80211(ctx, IEEE80211_IOC_BGSCAN_INTERVAL, atoi(val), 0, NULL); } -static -DECL_CMD_FUNC(set80211scanvalid, val, d) +static void +set80211scanvalid(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_SCANVALID, atoi(val), 0, NULL); + set80211(ctx, IEEE80211_IOC_SCANVALID, atoi(val), 0, NULL); } /* @@ -1615,8 +1618,8 @@ getmodeflags(const char *val) _APPLY1(_flags, _base, _param, _v); \ } while (0) -static -DECL_CMD_FUNC(set80211roamrssi, val, d) +static void +set80211roamrssi(if_ctx *ctx, const char *val, int dummy __unused) { double v = atof(val); int rssi, flags; @@ -1625,9 +1628,9 @@ DECL_CMD_FUNC(set80211roamrssi, val, d) if (rssi != 2*v) errx(-1, "invalid rssi (must be .5 dBm units)"); flags = getmodeflags(val); - getroam(s); + getroam(ctx); if (flags == 0) { /* NB: no flags => current channel */ - flags = getcurchan(s)->ic_flags; + flags = getcurchan(ctx)->ic_flags; _APPLY1(flags, roamparams, rssi, rssi); } else _APPLY(flags, roamparams, rssi, rssi); @@ -1646,64 +1649,64 @@ getrate(const char *val, const char *tag) return rate; /* NB: returns 2x the specified value */ } -static -DECL_CMD_FUNC(set80211roamrate, val, d) +static void +set80211roamrate(if_ctx *ctx, const char *val, int dummy __unused) { int rate, flags; rate = getrate(val, "roam"); flags = getmodeflags(val); - getroam(s); + getroam(ctx); if (flags == 0) { /* NB: no flags => current channel */ - flags = getcurchan(s)->ic_flags; + flags = getcurchan(ctx)->ic_flags; _APPLY_RATE1(flags, roamparams, rate, rate); } else _APPLY_RATE(flags, roamparams, rate, rate); callback_register(setroam_cb, &roamparams); } -static -DECL_CMD_FUNC(set80211mcastrate, val, d) +static void +set80211mcastrate(if_ctx *ctx, const char *val, int dummy __unused) { int rate, flags; rate = getrate(val, "mcast"); flags = getmodeflags(val); - gettxparams(s); + gettxparams(ctx); if (flags == 0) { /* NB: no flags => current channel */ - flags = getcurchan(s)->ic_flags; + flags = getcurchan(ctx)->ic_flags; _APPLY_RATE1(flags, txparams, mcastrate, rate); } else _APPLY_RATE(flags, txparams, mcastrate, rate); callback_register(settxparams_cb, &txparams); } -static -DECL_CMD_FUNC(set80211mgtrate, val, d) +static void +set80211mgtrate(if_ctx *ctx, const char *val, int dummy __unused) { int rate, flags; rate = getrate(val, "mgmt"); flags = getmodeflags(val); - gettxparams(s); + gettxparams(ctx); if (flags == 0) { /* NB: no flags => current channel */ - flags = getcurchan(s)->ic_flags; + flags = getcurchan(ctx)->ic_flags; _APPLY_RATE1(flags, txparams, mgmtrate, rate); } else _APPLY_RATE(flags, txparams, mgmtrate, rate); callback_register(settxparams_cb, &txparams); } -static -DECL_CMD_FUNC(set80211ucastrate, val, d) +static void +set80211ucastrate(if_ctx *ctx, const char *val, int dummy __unused) { int flags; - gettxparams(s); + gettxparams(ctx); flags = getmodeflags(val); if (isanyarg(val)) { if (flags == 0) { /* NB: no flags => current channel */ - flags = getcurchan(s)->ic_flags; + flags = getcurchan(ctx)->ic_flags; _APPLY1(flags, txparams, ucastrate, IEEE80211_FIXED_RATE_NONE); } else @@ -1712,7 +1715,7 @@ DECL_CMD_FUNC(set80211ucastrate, val, d) } else { int rate = getrate(val, "ucast"); if (flags == 0) { /* NB: no flags => current channel */ - flags = getcurchan(s)->ic_flags; + flags = getcurchan(ctx)->ic_flags; _APPLY_RATE1(flags, txparams, ucastrate, rate); } else _APPLY_RATE(flags, txparams, ucastrate, rate); @@ -1720,15 +1723,15 @@ DECL_CMD_FUNC(set80211ucastrate, val, d) callback_register(settxparams_cb, &txparams); } -static -DECL_CMD_FUNC(set80211maxretry, val, d) +static void +set80211maxretry(if_ctx *ctx, const char *val, int dummy __unused) { int v = atoi(val), flags; flags = getmodeflags(val); - gettxparams(s); + gettxparams(ctx); if (flags == 0) { /* NB: no flags => current channel */ - flags = getcurchan(s)->ic_flags; + flags = getcurchan(ctx)->ic_flags; _APPLY1(flags, txparams, maxretry, v); } else _APPLY(flags, txparams, maxretry, v); @@ -1737,100 +1740,100 @@ DECL_CMD_FUNC(set80211maxretry, val, d) #undef _APPLY_RATE #undef _APPLY -static -DECL_CMD_FUNC(set80211fragthreshold, val, d) +static void +set80211fragthreshold(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_FRAGTHRESHOLD, + set80211(ctx, IEEE80211_IOC_FRAGTHRESHOLD, isundefarg(val) ? IEEE80211_FRAG_MAX : atoi(val), 0, NULL); } -static -DECL_CMD_FUNC(set80211bmissthreshold, val, d) +static void +set80211bmissthreshold(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_BMISSTHRESHOLD, + set80211(ctx, IEEE80211_IOC_BMISSTHRESHOLD, isundefarg(val) ? IEEE80211_HWBMISS_MAX : atoi(val), 0, NULL); } static void -set80211burst(const char *val, int d, int s, const struct afswtch *rafp) +set80211burst(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_BURST, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_BURST, d, 0, NULL); } static void -set80211doth(const char *val, int d, int s, const struct afswtch *rafp) +set80211doth(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_DOTH, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_DOTH, d, 0, NULL); } static void -set80211dfs(const char *val, int d, int s, const struct afswtch *rafp) +set80211dfs(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_DFS, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_DFS, d, 0, NULL); } static void -set80211shortgi(const char *val, int d, int s, const struct afswtch *rafp) +set80211shortgi(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_SHORTGI, + set80211(ctx, IEEE80211_IOC_SHORTGI, d ? (IEEE80211_HTCAP_SHORTGI20 | IEEE80211_HTCAP_SHORTGI40) : 0, 0, NULL); } /* XXX 11ac density/size is different */ static void -set80211ampdu(const char *val, int d, int s, const struct afswtch *rafp) +set80211ampdu(if_ctx *ctx, const char *val __unused, int d) { int ampdu; - if (get80211val(s, IEEE80211_IOC_AMPDU, &du) < 0) + if (get80211val(ctx, IEEE80211_IOC_AMPDU, &du) < 0) errx(-1, "cannot set AMPDU setting"); if (d < 0) { d = -d; ampdu &= ~d; } else ampdu |= d; - set80211(s, IEEE80211_IOC_AMPDU, ampdu, 0, NULL); + set80211(ctx, IEEE80211_IOC_AMPDU, ampdu, 0, NULL); } static void -set80211stbc(const char *val, int d, int s, const struct afswtch *rafp) +set80211stbc(if_ctx *ctx, const char *val __unused, int d) { int stbc; - if (get80211val(s, IEEE80211_IOC_STBC, &stbc) < 0) + if (get80211val(ctx, IEEE80211_IOC_STBC, &stbc) < 0) errx(-1, "cannot set STBC setting"); if (d < 0) { d = -d; stbc &= ~d; } else stbc |= d; - set80211(s, IEEE80211_IOC_STBC, stbc, 0, NULL); + set80211(ctx, IEEE80211_IOC_STBC, stbc, 0, NULL); } static void -set80211ldpc(const char *val, int d, int s, const struct afswtch *rafp) +set80211ldpc(if_ctx *ctx, const char *val __unused, int d) { int ldpc; - if (get80211val(s, IEEE80211_IOC_LDPC, &ldpc) < 0) + if (get80211val(ctx, IEEE80211_IOC_LDPC, &ldpc) < 0) errx(-1, "cannot set LDPC setting"); if (d < 0) { d = -d; ldpc &= ~d; } else ldpc |= d; - set80211(s, IEEE80211_IOC_LDPC, ldpc, 0, NULL); + set80211(ctx, IEEE80211_IOC_LDPC, ldpc, 0, NULL); } static void -set80211uapsd(const char *val, int d, int s, const struct afswtch *rafp) +set80211uapsd(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_UAPSD, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_UAPSD, d, 0, NULL); } -static -DECL_CMD_FUNC(set80211ampdulimit, val, d) +static void +set80211ampdulimit(if_ctx *ctx, const char *val, int dummy __unused) { int v; @@ -1854,12 +1857,12 @@ DECL_CMD_FUNC(set80211ampdulimit, val, d) default: errx(-1, "invalid A-MPDU limit %s", val); } - set80211(s, IEEE80211_IOC_AMPDU_LIMIT, v, 0, NULL); + set80211(ctx, IEEE80211_IOC_AMPDU_LIMIT, v, 0, NULL); } /* XXX 11ac density/size is different */ -static -DECL_CMD_FUNC(set80211ampdudensity, val, d) +static void +set80211ampdudensity(if_ctx *ctx, const char *val, int dummy __unused) { int v; @@ -1893,164 +1896,162 @@ DECL_CMD_FUNC(set80211ampdudensity, val, d) default: errx(-1, "invalid A-MPDU density %s", val); } - set80211(s, IEEE80211_IOC_AMPDU_DENSITY, v, 0, NULL); + set80211(ctx, IEEE80211_IOC_AMPDU_DENSITY, v, 0, NULL); } static void -set80211amsdu(const char *val, int d, int s, const struct afswtch *rafp) +set80211amsdu(if_ctx *ctx, const char *val __unused, int d) { int amsdu; - if (get80211val(s, IEEE80211_IOC_AMSDU, &amsdu) < 0) + if (get80211val(ctx, IEEE80211_IOC_AMSDU, &amsdu) < 0) err(-1, "cannot get AMSDU setting"); if (d < 0) { d = -d; amsdu &= ~d; } else amsdu |= d; - set80211(s, IEEE80211_IOC_AMSDU, amsdu, 0, NULL); + set80211(ctx, IEEE80211_IOC_AMSDU, amsdu, 0, NULL); } -static -DECL_CMD_FUNC(set80211amsdulimit, val, d) +static void +set80211amsdulimit(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_AMSDU_LIMIT, atoi(val), 0, NULL); + set80211(ctx, IEEE80211_IOC_AMSDU_LIMIT, atoi(val), 0, NULL); } static void -set80211puren(const char *val, int d, int s, const struct afswtch *rafp) +set80211puren(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_PUREN, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_PUREN, d, 0, NULL); } static void -set80211htcompat(const char *val, int d, int s, const struct afswtch *rafp) +set80211htcompat(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_HTCOMPAT, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_HTCOMPAT, d, 0, NULL); } static void -set80211htconf(const char *val, int d, int s, const struct afswtch *rafp) +set80211htconf(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_HTCONF, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_HTCONF, d, 0, NULL); htconf = d; } static void -set80211dwds(const char *val, int d, int s, const struct afswtch *rafp) +set80211dwds(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_DWDS, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_DWDS, d, 0, NULL); } static void -set80211inact(const char *val, int d, int s, const struct afswtch *rafp) +set80211inact(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_INACTIVITY, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_INACTIVITY, d, 0, NULL); } static void -set80211tsn(const char *val, int d, int s, const struct afswtch *rafp) +set80211tsn(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_TSN, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_TSN, d, 0, NULL); } static void -set80211dotd(const char *val, int d, int s, const struct afswtch *rafp) +set80211dotd(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_DOTD, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_DOTD, d, 0, NULL); } static void -set80211smps(const char *val, int d, int s, const struct afswtch *rafp) +set80211smps(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_SMPS, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_SMPS, d, 0, NULL); } static void -set80211rifs(const char *val, int d, int s, const struct afswtch *rafp) +set80211rifs(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_RIFS, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_RIFS, d, 0, NULL); } static void -set80211vhtconf(const char *val, int d, int s, const struct afswtch *rafp) +set80211vhtconf(if_ctx *ctx, const char *val __unused, int d) { - if (get80211val(s, IEEE80211_IOC_VHTCONF, &vhtconf) < 0) + if (get80211val(ctx, IEEE80211_IOC_VHTCONF, &vhtconf) < 0) errx(-1, "cannot set VHT setting"); - printf("%s: vhtconf=0x%08x, d=%d\n", __func__, vhtconf, d); if (d < 0) { d = -d; vhtconf &= ~d; } else vhtconf |= d; - printf("%s: vhtconf is now 0x%08x\n", __func__, vhtconf); - set80211(s, IEEE80211_IOC_VHTCONF, vhtconf, 0, NULL); + set80211(ctx, IEEE80211_IOC_VHTCONF, vhtconf, 0, NULL); } -static -DECL_CMD_FUNC(set80211tdmaslot, val, d) +static void +set80211tdmaslot(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_TDMA_SLOT, atoi(val), 0, NULL); + set80211(ctx, IEEE80211_IOC_TDMA_SLOT, atoi(val), 0, NULL); } -static -DECL_CMD_FUNC(set80211tdmaslotcnt, val, d) +static void +set80211tdmaslotcnt(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_TDMA_SLOTCNT, atoi(val), 0, NULL); + set80211(ctx, IEEE80211_IOC_TDMA_SLOTCNT, atoi(val), 0, NULL); } -static -DECL_CMD_FUNC(set80211tdmaslotlen, val, d) +static void +set80211tdmaslotlen(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_TDMA_SLOTLEN, atoi(val), 0, NULL); + set80211(ctx, IEEE80211_IOC_TDMA_SLOTLEN, atoi(val), 0, NULL); } -static -DECL_CMD_FUNC(set80211tdmabintval, val, d) +static void +set80211tdmabintval(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_TDMA_BINTERVAL, atoi(val), 0, NULL); + set80211(ctx, IEEE80211_IOC_TDMA_BINTERVAL, atoi(val), 0, NULL); } -static -DECL_CMD_FUNC(set80211meshttl, val, d) +static void +set80211meshttl(if_ctx *ctx, const char *val, int dummy __unused) { - set80211(s, IEEE80211_IOC_MESH_TTL, atoi(val), 0, NULL); + set80211(ctx, IEEE80211_IOC_MESH_TTL, atoi(val), 0, NULL); } -static -DECL_CMD_FUNC(set80211meshforward, val, d) +static void +set80211meshforward(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_MESH_FWRD, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_MESH_FWRD, d, 0, NULL); } -static -DECL_CMD_FUNC(set80211meshgate, val, d) +static void +set80211meshgate(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_MESH_GATE, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_MESH_GATE, d, 0, NULL); } -static -DECL_CMD_FUNC(set80211meshpeering, val, d) +static void +set80211meshpeering(if_ctx *ctx, const char *val __unused, int d) { - set80211(s, IEEE80211_IOC_MESH_AP, d, 0, NULL); + set80211(ctx, IEEE80211_IOC_MESH_AP, d, 0, NULL); } -static -DECL_CMD_FUNC(set80211meshmetric, val, d) +static void +set80211meshmetric(if_ctx *ctx, const char *val, int dummy __unused) { char v[12]; memcpy(v, val, sizeof(v)); - set80211(s, IEEE80211_IOC_MESH_PR_METRIC, 0, 0, v); + set80211(ctx, IEEE80211_IOC_MESH_PR_METRIC, 0, 0, v); } -static -DECL_CMD_FUNC(set80211meshpath, val, d) +static void +set80211meshpath(if_ctx *ctx, const char *val, int dummy __unused) { char v[12]; memcpy(v, val, sizeof(v)); - set80211(s, IEEE80211_IOC_MESH_PR_PATH, 0, 0, v); + set80211(ctx, IEEE80211_IOC_MESH_PR_PATH, 0, 0, v); } static int @@ -2062,14 +2063,14 @@ regdomain_sort(const void *a, const void *b) const struct ieee80211_channel *cb = b; return ca->ic_freq == cb->ic_freq ? - (ca->ic_flags & CHAN_ALL) - (cb->ic_flags & CHAN_ALL) : + (int)(ca->ic_flags & CHAN_ALL) - (int)(cb->ic_flags & CHAN_ALL) : ca->ic_freq - cb->ic_freq; #undef CHAN_ALL } static const struct ieee80211_channel * chanlookup(const struct ieee80211_channel chans[], int nchans, - int freq, int flags) + int freq, uint32_t flags) { int i; @@ -2084,11 +2085,9 @@ chanlookup(const struct ieee80211_channel chans[], int nchans, } static int -chanfind(const struct ieee80211_channel chans[], int nchans, int flags) +chanfind(const struct ieee80211_channel chans[], int nchans, uint32_t flags) { - int i; - - for (i = 0; i < nchans; i++) { + for (int i = 0; i < nchans; i++) { const struct ieee80211_channel *c = &chans[i]; if ((c->ic_flags & flags) == flags) return 1; @@ -2100,7 +2099,7 @@ chanfind(const struct ieee80211_channel chans[], int nchans, int flags) * Check channel compatibility. */ static int -checkchan(const struct ieee80211req_chaninfo *avail, int freq, int flags) +checkchan(const struct ieee80211req_chaninfo *avail, int freq, uint32_t flags) { flags &= ~REQ_FLAGS; /* @@ -2144,7 +2143,7 @@ checkchan(const struct ieee80211req_chaninfo *avail, int freq, int flags) } static void -regdomain_addchans(struct ieee80211req_chaninfo *ci, +regdomain_addchans(if_ctx *ctx, struct ieee80211req_chaninfo *ci, const netband_head *bands, const struct ieee80211_regdomain *reg, uint32_t chanFlags, @@ -2155,6 +2154,7 @@ regdomain_addchans(struct ieee80211req_chaninfo *ci, struct ieee80211_channel *c, *prev; int freq, hi_adj, lo_adj, channelSep; uint32_t flags; + const int verbose = ctx->args->verbose; hi_adj = (chanFlags & IEEE80211_CHAN_HT40U) ? -20 : 0; lo_adj = (chanFlags & IEEE80211_CHAN_HT40D) ? 20 : 0; @@ -2298,7 +2298,7 @@ regdomain_addchans(struct ieee80211req_chaninfo *ci, memset(c, 0, sizeof(*c)); c->ic_freq = freq; c->ic_flags = flags; - if (c->ic_flags & IEEE80211_CHAN_DFS) + if (c->ic_flags & IEEE80211_CHAN_DFS) c->ic_maxregpower = nb->maxPowerDFS; else c->ic_maxregpower = nb->maxPower; @@ -2316,6 +2316,7 @@ regdomain_addchans(struct ieee80211req_chaninfo *ci, static void regdomain_makechannels( + if_ctx *ctx, struct ieee80211_regdomain_req *req, const struct ieee80211_devcaps_req *dc) { @@ -2354,40 +2355,40 @@ regdomain_makechannels( */ ci->ic_nchans = 0; if (!LIST_EMPTY(&rd->bands_11b)) - regdomain_addchans(ci, &rd->bands_11b, reg, + regdomain_addchans(ctx, ci, &rd->bands_11b, reg, IEEE80211_CHAN_B, &dc->dc_chaninfo); if (!LIST_EMPTY(&rd->bands_11g)) - regdomain_addchans(ci, &rd->bands_11g, reg, + regdomain_addchans(ctx, ci, &rd->bands_11g, reg, IEEE80211_CHAN_G, &dc->dc_chaninfo); if (!LIST_EMPTY(&rd->bands_11a)) - regdomain_addchans(ci, &rd->bands_11a, reg, + regdomain_addchans(ctx, ci, &rd->bands_11a, reg, IEEE80211_CHAN_A, &dc->dc_chaninfo); if (!LIST_EMPTY(&rd->bands_11na) && dc->dc_htcaps != 0) { - regdomain_addchans(ci, &rd->bands_11na, reg, + regdomain_addchans(ctx, ci, &rd->bands_11na, reg, IEEE80211_CHAN_A | IEEE80211_CHAN_HT20, &dc->dc_chaninfo); if (dc->dc_htcaps & IEEE80211_HTCAP_CHWIDTH40) { - regdomain_addchans(ci, &rd->bands_11na, reg, + regdomain_addchans(ctx, ci, &rd->bands_11na, reg, IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U, &dc->dc_chaninfo); - regdomain_addchans(ci, &rd->bands_11na, reg, + regdomain_addchans(ctx, ci, &rd->bands_11na, reg, IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D, &dc->dc_chaninfo); } } if (!LIST_EMPTY(&rd->bands_11ac) && dc->dc_vhtcaps != 0) { - regdomain_addchans(ci, &rd->bands_11ac, reg, + regdomain_addchans(ctx, ci, &rd->bands_11ac, reg, IEEE80211_CHAN_A | IEEE80211_CHAN_HT20 | IEEE80211_CHAN_VHT20, &dc->dc_chaninfo); /* VHT40 is a function of HT40.. */ if (dc->dc_htcaps & IEEE80211_HTCAP_CHWIDTH40) { - regdomain_addchans(ci, &rd->bands_11ac, reg, + regdomain_addchans(ctx, ci, &rd->bands_11ac, reg, IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U | IEEE80211_CHAN_VHT40U, &dc->dc_chaninfo); - regdomain_addchans(ci, &rd->bands_11ac, reg, + regdomain_addchans(ctx, ci, &rd->bands_11ac, reg, IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D | IEEE80211_CHAN_VHT40D, &dc->dc_chaninfo); @@ -2395,11 +2396,11 @@ regdomain_makechannels( /* VHT80 is mandatory (and so should be VHT40 above). */ if (1) { - regdomain_addchans(ci, &rd->bands_11ac, reg, + regdomain_addchans(ctx, ci, &rd->bands_11ac, reg, IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U | IEEE80211_CHAN_VHT80, &dc->dc_chaninfo); - regdomain_addchans(ci, &rd->bands_11ac, reg, + regdomain_addchans(ctx, ci, &rd->bands_11ac, reg, IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D | IEEE80211_CHAN_VHT80, &dc->dc_chaninfo); @@ -2408,11 +2409,11 @@ regdomain_makechannels( /* VHT160 */ if (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160MHZ( dc->dc_vhtcaps)) { - regdomain_addchans(ci, &rd->bands_11ac, reg, + regdomain_addchans(ctx, ci, &rd->bands_11ac, reg, IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U | IEEE80211_CHAN_VHT160, &dc->dc_chaninfo); - regdomain_addchans(ci, &rd->bands_11ac, reg, + regdomain_addchans(ctx, ci, &rd->bands_11ac, reg, IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D | IEEE80211_CHAN_VHT160, &dc->dc_chaninfo); @@ -2421,11 +2422,11 @@ regdomain_makechannels( /* VHT80P80 */ if (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160_80P80MHZ( dc->dc_vhtcaps)) { - regdomain_addchans(ci, &rd->bands_11ac, reg, + regdomain_addchans(ctx, ci, &rd->bands_11ac, reg, IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U | IEEE80211_CHAN_VHT80P80, &dc->dc_chaninfo); - regdomain_addchans(ci, &rd->bands_11ac, reg, + regdomain_addchans(ctx, ci, &rd->bands_11ac, reg, IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D | IEEE80211_CHAN_VHT80P80, &dc->dc_chaninfo); @@ -2433,14 +2434,14 @@ regdomain_makechannels( } if (!LIST_EMPTY(&rd->bands_11ng) && dc->dc_htcaps != 0) { - regdomain_addchans(ci, &rd->bands_11ng, reg, + regdomain_addchans(ctx, ci, &rd->bands_11ng, reg, IEEE80211_CHAN_G | IEEE80211_CHAN_HT20, &dc->dc_chaninfo); if (dc->dc_htcaps & IEEE80211_HTCAP_CHWIDTH40) { - regdomain_addchans(ci, &rd->bands_11ng, reg, + regdomain_addchans(ctx, ci, &rd->bands_11ng, reg, IEEE80211_CHAN_G | IEEE80211_CHAN_HT40U, &dc->dc_chaninfo); - regdomain_addchans(ci, &rd->bands_11ng, reg, + regdomain_addchans(ctx, ci, &rd->bands_11ng, reg, IEEE80211_CHAN_G | IEEE80211_CHAN_HT40D, &dc->dc_chaninfo); } @@ -2491,8 +2492,8 @@ defaultcountry(const struct regdomain *rd) regdomain.isocc[1] = cc->isoname[1]; } -static -DECL_CMD_FUNC(set80211regdomain, val, d) +static void +set80211regdomain(if_ctx *ctx, const char *val, int dummy __unused) { struct regdata *rdp = getregdata(); const struct regdomain *rd; @@ -2507,7 +2508,7 @@ DECL_CMD_FUNC(set80211regdomain, val, d) if (eptr == val || rd == NULL) errx(1, "unknown regdomain %s", val); } - getregdomain(s); + getregdomain(ctx); regdomain.regdomain = rd->sku; if (regdomain.country == 0 && rd->cc != NULL) { /* @@ -2519,8 +2520,8 @@ DECL_CMD_FUNC(set80211regdomain, val, d) callback_register(setregdomain_cb, ®domain); } -static -DECL_CMD_FUNC(set80211country, val, d) +static void +set80211country(if_ctx *ctx, const char *val, int dummy __unused) { struct regdata *rdp = getregdata(); const struct country *cc; @@ -2535,7 +2536,7 @@ DECL_CMD_FUNC(set80211country, val, d) if (eptr == val || cc == NULL) errx(1, "unknown ISO country code %s", val); } - getregdomain(s); + getregdomain(ctx); regdomain.regdomain = cc->rd->sku; regdomain.country = cc->code; regdomain.isocc[0] = cc->isoname[0]; @@ -2544,17 +2545,17 @@ DECL_CMD_FUNC(set80211country, val, d) } static void -set80211location(const char *val, int d, int s, const struct afswtch *rafp) +set80211location(if_ctx *ctx, const char *val __unused, int d) { - getregdomain(s); + getregdomain(ctx); regdomain.location = d; callback_register(setregdomain_cb, ®domain); } static void -set80211ecm(const char *val, int d, int s, const struct afswtch *rafp) +set80211ecm(if_ctx *ctx, const char *val __unused, int d) { - getregdomain(s); + getregdomain(ctx); regdomain.ecm = d; callback_register(setregdomain_cb, ®domain); } @@ -2699,10 +2700,10 @@ getflags(int flags) } static void -printie(const char* tag, const uint8_t *ie, size_t ielen, int maxlen) +printie(if_ctx *ctx, const char* tag, const uint8_t *ie, size_t ielen, unsigned int maxlen) { printf("%s", tag); - if (verbose) { + if (ctx->args->verbose) { maxlen -= strlen(tag)+2; if (2*ielen > maxlen) maxlen--; @@ -2736,7 +2737,7 @@ printie(const char* tag, const uint8_t *ie, size_t ielen, int maxlen) */ static void -printwmeparam(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) +printwmeparam(if_ctx *ctx, const char *tag, const u_int8_t *ie) { static const char *acnames[] = { "BE", "BK", "VO", "VI" }; const struct ieee80211_wme_param *wme = @@ -2744,7 +2745,7 @@ printwmeparam(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) int i; printf("%s", tag); - if (!verbose) + if (!ctx->args->verbose) return; printf("<qosinfo 0x%x", wme->param_qosInfo); ie += offsetof(struct ieee80211_wme_param, params_acParams); @@ -2766,10 +2767,10 @@ printwmeparam(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) } static void -printwmeinfo(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) +printwmeinfo(if_ctx *ctx, const char *tag, const u_int8_t *ie) { printf("%s", tag); - if (verbose) { + if (ctx->args->verbose) { const struct ieee80211_wme_info *wme = (const struct ieee80211_wme_info *) ie; printf("<version 0x%x info 0x%x>", @@ -2778,14 +2779,193 @@ printwmeinfo(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) } static void -printvhtcap(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) +printhecap(if_ctx *ctx, const char *tag, const uint8_t *ie) { + const struct ieee80211_he_cap_elem *hecap; + const struct ieee80211_he_mcs_nss_supp *mcsnss; + unsigned int i; + uint8_t chw; + printf("%s", tag); - if (verbose) { - const struct ieee80211_ie_vhtcap *vhtcap = - (const struct ieee80211_ie_vhtcap *) ie; - uint32_t vhtcap_info = LE_READ_4(&vhtcap->vht_cap_info); + if (!ctx->args->verbose) + return; + + /* Check that the right size. */ + if (ie[1] < 1 + sizeof(*hecap) + 4) { + printf("<err: he_cap inval. length %#0x>", ie[1]); + return; + } + /* Skip Element ID, Length, EID Extension. */ + hecap = (const struct ieee80211_he_cap_elem *)(ie + 3); + + /* XXX-BZ we need to somehow decode each field? */ + printf("<mac_cap"); + for (i = 0; i < nitems(hecap->mac_cap_info); i++) + printf(" %#04x", hecap->mac_cap_info[i]); + printf(" phy_cap"); + for (i = 0; i < nitems(hecap->phy_cap_info); i++) + printf(" %#04x", hecap->phy_cap_info[i]); + + chw = hecap->phy_cap_info[0]; + ie = (const uint8_t *)(const void *)(hecap + 1); + mcsnss = (const struct ieee80211_he_mcs_nss_supp *)ie; + /* Cannot use <= as < is a delimiter. */ + printf(" rx/tx_he_mcs map: loweq80 %#06x/%#06x", + mcsnss->rx_mcs_80, mcsnss->tx_mcs_80); + ie += 2; + if ((chw & (1<<2)) != 0) { + printf(" 160 %#06x/%#06x", + mcsnss->rx_mcs_160, mcsnss->tx_mcs_160); + ie += 2; + } + if ((chw & (1<<3)) != 0) { + printf(" 80+80 %#06x/%#06x", + mcsnss->rx_mcs_80p80, mcsnss->tx_mcs_80p80); + ie += 2; + } + /* TODO: ppet = (struct ... *)ie; */ + + printf(">"); +} + +static void +printheoper(if_ctx *ctx, const char *tag, const uint8_t *ie) +{ + printf("%s", tag); + if (ctx->args->verbose) { + const struct ieee80211_he_operation *heoper; + uint32_t params; + + /* Check that the right size. */ + if (ie[1] < 1 + sizeof(*heoper)) { + printf("<err: he_oper inval. length %#0x>", ie[1]); + return; + } + /* Skip Element ID, Length, EID Extension. */ + heoper = (const struct ieee80211_he_operation *)(ie + 3); + + /* XXX-BZ we need to somehow decode each field? */ + params = heoper->he_oper_params & 0x00ffffff; + printf("<params %#08x", params); + printf(" bss_col %#04x", (heoper->he_oper_params & 0xff000000) >> 24); + printf(" mcs_nss %#06x", heoper->he_mcs_nss_set); + if ((params & (1 << 14)) != 0) { + printf(" vht_op 0-3"); + } + if ((params & (1 << 15)) != 0) { + printf(" max_coh_bssid 0-1"); + } + if ((params & (1 << 17)) != 0) { + printf(" 6ghz_op 0-5"); + } + printf(">"); + } +} + +static void +printmuedcaparamset(if_ctx *ctx, const char *tag, const uint8_t *ie) +{ + static const char *acnames[] = { "BE", "BK", "VO", "VI" }; + const struct ieee80211_mu_edca_param_set *mu_edca; + int i; + + printf("%s", tag); + if (!ctx->args->verbose) + return; + + /* Check that the right size. */ + if (ie[1] != 1 + sizeof(*mu_edca)) { + printf("<err: mu_edca inval. length %#04x>", ie[1]); + return; + } + /* Skip Element ID, Length, EID Extension. */ + mu_edca = (const struct ieee80211_mu_edca_param_set *)(ie + 3); + + printf("<qosinfo 0x%x", mu_edca->mu_qos_info); + ie++; + for (i = 0; i < WME_NUM_AC; i++) { + const struct ieee80211_he_mu_edca_param_ac_rec *ac = + &mu_edca->param_ac_recs[i]; + + printf(" %s[aifsn %u ecwmin %u ecwmax %u timer %u]", acnames[i], + ac->aifsn, + _IEEE80211_MASKSHIFT(ac->ecw_min_max, WME_PARAM_LOGCWMIN), + _IEEE80211_MASKSHIFT(ac->ecw_min_max, WME_PARAM_LOGCWMAX), + ac->mu_edca_timer); + } + printf(">"); +} + +static void +printsupopclass(if_ctx *ctx, const char *tag, const u_int8_t *ie) +{ + uint8_t len, i; + + printf("%s", tag); + if (!ctx->args->verbose) + return; + + /* Check that the right size. */ + len = ie[1]; + if (len < 2) { + printf("<err: sup_op_class inval. length %#04x>", ie[1]); + return; + } + + ie += 2; + i = 0; + printf("<cur op class %u", *ie); + i++; + if (i < len && *(ie + i) != 130) + printf(" op classes"); + while (i < len && *(ie + i) != 130) { + printf(" %u", *(ie + i)); + i++; + } + if (i > 1 && i < len && *(ie + i) != 130) { + printf(" parsing error at %#0x>", i); + return; + } + /* Skip OneHundredAndThirty Delimiter. */ + i++; + if (i < len && *(ie + i) != 0) + printf(" ext seq"); + while (i < len && *(ie + i) != 0) { + printf(" %u", *(ie + i)); + i++; + } + if (i > 1 && i < len && *(ie + i) != 0) { + printf(" parsing error at %#0x>", i); + return; + } + /* Skip Zero Delimiter. */ + i++; + if ((i + 1) < len) + printf(" duple seq"); + while ((i + 1) < len) { + printf(" %u/%u", *(ie + i), *(ie + i + 1)); + i += 2; + } + printf(">"); +} + +static void +printvhtcap(if_ctx *ctx, const char *tag, const u_int8_t *ie) +{ + printf("%s", tag); + if (ctx->args->verbose) { + const struct ieee80211_vht_cap *vhtcap; + uint32_t vhtcap_info; + /* Check that the right size. */ + if (ie[1] != sizeof(*vhtcap)) { + printf("<err: vht_cap inval. length>"); + return; + } + /* Skip Element ID and Length. */ + vhtcap = (const struct ieee80211_vht_cap *)(ie + 2); + + vhtcap_info = LE_READ_4(&vhtcap->vht_cap_info); printf("<cap 0x%08x", vhtcap_info); printf(" rx_mcs_map 0x%x", LE_READ_2(&vhtcap->supp_mcs.rx_mcs_map)); @@ -2801,23 +2981,30 @@ printvhtcap(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) } static void -printvhtinfo(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) +printvhtinfo(if_ctx *ctx, const char *tag, const u_int8_t *ie) { printf("%s", tag); - if (verbose) { - const struct ieee80211_ie_vht_operation *vhtinfo = - (const struct ieee80211_ie_vht_operation *) ie; + if (ctx->args->verbose) { + const struct ieee80211_vht_operation *vhtinfo; - printf("<chw %d freq1_idx %d freq2_idx %d basic_mcs_set 0x%04x>", + /* Check that the right size. */ + if (ie[1] != sizeof(*vhtinfo)) { + printf("<err: vht_operation inval. length>"); + return; + } + /* Skip Element ID and Length. */ + vhtinfo = (const struct ieee80211_vht_operation *)(ie + 2); + + printf("<chw %d freq0_idx %d freq1_idx %d basic_mcs_set 0x%04x>", vhtinfo->chan_width, - vhtinfo->center_freq_seg1_idx, - vhtinfo->center_freq_seg2_idx, + vhtinfo->center_freq_seq0_idx, + vhtinfo->center_freq_seq1_idx, LE_READ_2(&vhtinfo->basic_mcs_set)); } } static void -printvhtpwrenv(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) +printvhtpwrenv(if_ctx *ctx, const char *tag, const u_int8_t *ie, size_t ielen) { printf("%s", tag); static const char *txpwrmap[] = { @@ -2826,17 +3013,17 @@ printvhtpwrenv(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) "80", "160", }; - if (verbose) { + if (ctx->args->verbose) { const struct ieee80211_ie_vht_txpwrenv *vhtpwr = (const struct ieee80211_ie_vht_txpwrenv *) ie; - int i, n; + size_t i, n; const char *sep = ""; /* Get count; trim at ielen */ n = (vhtpwr->tx_info & IEEE80211_VHT_TXPWRENV_INFO_COUNT_MASK) + 1; /* Trim at ielen */ - if (n > ielen - 3) + if (n + 3 > ielen) n = ielen - 3; printf("<tx_info 0x%02x pwr:[", vhtpwr->tx_info); for (i = 0; i < n; i++) { @@ -2850,10 +3037,10 @@ printvhtpwrenv(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) } static void -printhtcap(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) +printhtcap(if_ctx *ctx, const char *tag, const u_int8_t *ie) { printf("%s", tag); - if (verbose) { + if (ctx->args->verbose) { const struct ieee80211_ie_htcap *htcap = (const struct ieee80211_ie_htcap *) ie; const char *sep; @@ -2884,10 +3071,10 @@ printhtcap(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) } static void -printhtinfo(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) +printhtinfo(if_ctx *ctx, const char *tag, const u_int8_t *ie) { printf("%s", tag); - if (verbose) { + if (ctx->args->verbose) { const struct ieee80211_ie_htinfo *htinfo = (const struct ieee80211_ie_htinfo *) ie; const char *sep; @@ -2916,11 +3103,11 @@ printhtinfo(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) } static void -printathie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) +printathie(if_ctx *ctx, const char *tag, const u_int8_t *ie) { printf("%s", tag); - if (verbose) { + if (ctx->args->verbose) { const struct ieee80211_ath_ie *ath = (const struct ieee80211_ath_ie *)ie; @@ -2947,11 +3134,11 @@ printathie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) static void -printmeshconf(const char *tag, const uint8_t *ie, size_t ielen, int maxlen) +printmeshconf(if_ctx *ctx, const char *tag, const uint8_t *ie) { printf("%s", tag); - if (verbose) { + if (ctx->args->verbose) { const struct ieee80211_meshconf_ie *mconf = (const struct ieee80211_meshconf_ie *)ie; printf("<PATH:"); @@ -2985,10 +3172,10 @@ printmeshconf(const char *tag, const uint8_t *ie, size_t ielen, int maxlen) } static void -printbssload(const char *tag, const uint8_t *ie, size_t ielen, int maxlen) +printbssload(if_ctx *ctx, const char *tag, const uint8_t *ie) { printf("%s", tag); - if (verbose) { + if (ctx->args->verbose) { const struct ieee80211_bss_load_ie *bssload = (const struct ieee80211_bss_load_ie *) ie; printf("<sta count %d, chan load %d, aac %d>", @@ -2999,18 +3186,17 @@ printbssload(const char *tag, const uint8_t *ie, size_t ielen, int maxlen) } static void -printapchanrep(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) +printapchanrep(if_ctx *ctx, const char *tag, const u_int8_t *ie, size_t ielen) { printf("%s", tag); - if (verbose) { + if (ctx->args->verbose) { const struct ieee80211_ap_chan_report_ie *ap = (const struct ieee80211_ap_chan_report_ie *) ie; const char *sep = ""; - int i; printf("<class %u, chan:[", ap->i_class); - for (i = 3; i < ielen; i++) { + for (size_t i = 3; i < ielen; i++) { printf("%s%u", sep, ie[i]); sep = ","; } @@ -3059,12 +3245,12 @@ wpa_keymgmt(const u_int8_t *sel) } static void -printwpaie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) +printwpaie(if_ctx *ctx, const char *tag, const u_int8_t *ie) { u_int8_t len = ie[1]; printf("%s", tag); - if (verbose) { + if (ctx->args->verbose) { const char *sep; int n; @@ -3121,6 +3307,12 @@ rsn_cipher(const u_int8_t *sel) return "AES-CCMP"; case RSN_SEL(RSN_CSE_WRAP): return "AES-OCB"; + case RSN_SEL(RSN_CSE_GCMP_128): + return "AES-GCMP"; + case RSN_SEL(RSN_CSE_CCMP_256): + return "AES-CCMP-256"; + case RSN_SEL(RSN_CSE_GCMP_256): + return "AES-GCMP-256"; } return "?"; #undef WPA_SEL @@ -3137,6 +3329,10 @@ rsn_keymgmt(const u_int8_t *sel) return "8021X-UNSPEC"; case RSN_SEL(RSN_ASE_8021X_PSK): return "8021X-PSK"; + case RSN_SEL(RSN_ASE_8021X_UNSPEC_SHA256): + return "8021X-UNSPEC-SHA256"; + case RSN_SEL(RSN_ASE_8021X_PSK_SHA256): + return "8021X-PSK-256"; case RSN_SEL(RSN_ASE_NONE): return "NONE"; } @@ -3145,10 +3341,10 @@ rsn_keymgmt(const u_int8_t *sel) } static void -printrsnie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) +printrsnie(if_ctx *ctx, const char *tag, const u_int8_t *ie, size_t ielen) { printf("%s", tag); - if (verbose) { + if (ctx->args->verbose) { const char *sep; int n; @@ -3187,18 +3383,45 @@ printrsnie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) } } +static void +printrsnxe(if_ctx *ctx, const char *tag, const u_int8_t *ie, size_t ielen) +{ + size_t n; + + printf("%s", tag); + if (!ctx->args->verbose) + return; + + ie += 2, ielen -= 2; + + n = (*ie & 0x0f); + printf("<%zu", n + 1); + + /* We do not yet know about more than n=1 (0). */ + if (n != 0) + goto end; + + if (*ie & 0x10) + printf(" PTWTOPS"); + if (*ie & 0x20) + printf(" SAE h-t-e"); + +end: + printf(">"); +} + #define BE_READ_2(p) \ ((u_int16_t) \ ((((const u_int8_t *)(p))[1] ) | \ (((const u_int8_t *)(p))[0] << 8))) static void -printwpsie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) +printwpsie(if_ctx *ctx, const char *tag, const u_int8_t *ie) { u_int8_t len = ie[1]; printf("%s", tag); - if (verbose) { + if (ctx->args->verbose) { static const char *dev_pass_id[] = { "D", /* Default (PIN) */ "U", /* User-specified */ @@ -3331,7 +3554,7 @@ printwpsie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) break; case IEEE80211_WPS_ATTR_DEV_PASSWORD_ID: n = LE_READ_2(ie); - if (n < nitems(dev_pass_id)) + if (n < (int)nitems(dev_pass_id)) printf(" dpi:%s", dev_pass_id[n]); break; case IEEE80211_WPS_ATTR_MANUFACTURER: @@ -3423,10 +3646,10 @@ printwpsie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) } static void -printtdmaie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) +printtdmaie(if_ctx *ctx, const char *tag, const u_int8_t *ie, size_t ielen) { printf("%s", tag); - if (verbose && ielen >= sizeof(struct ieee80211_tdma_param)) { + if (ctx->args->verbose && ielen >= sizeof(struct ieee80211_tdma_param)) { const struct ieee80211_tdma_param *tdma = (const struct ieee80211_tdma_param *) ie; @@ -3481,7 +3704,7 @@ copy_essid(char buf[], size_t bufsize, const u_int8_t *essid, size_t essid_len) } static void -printssid(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) +printssid(const char *tag, const u_int8_t *ie, int maxlen) { char ssid[2*IEEE80211_NWID_LEN+1]; @@ -3489,14 +3712,13 @@ printssid(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) } static void -printrates(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) +printrates(const char *tag, const u_int8_t *ie, size_t ielen) { const char *sep; - int i; printf("%s", tag); sep = "<"; - for (i = 2; i < ielen; i++) { + for (size_t i = 2; i < ielen; i++) { printf("%s%s%d", sep, ie[i] & IEEE80211_RATE_BASIC ? "B" : "", ie[i] & IEEE80211_RATE_VAL); @@ -3506,7 +3728,7 @@ printrates(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) } static void -printcountry(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) +printcountry(const char *tag, const u_int8_t *ie) { const struct ieee80211_country_ie *cie = (const struct ieee80211_country_ie *) ie; @@ -3565,7 +3787,22 @@ iswpsoui(const uint8_t *frm) } static const char * -iename(int elemid) +ie_ext_name(uint8_t ext_elemid) +{ + static char iename_buf[32]; + + switch (ext_elemid) { + case IEEE80211_ELEMID_EXT_HE_CAPA: return " HECAP"; + case IEEE80211_ELEMID_EXT_HE_OPER: return " HEOPER"; + case IEEE80211_ELEMID_EXT_MU_EDCA_PARAM_SET: return " MU_EDCA_PARAM_SET"; + } + snprintf(iename_buf, sizeof(iename_buf), " ELEMID_EXT_%d", + ext_elemid & 0xff); + return (const char *) iename_buf; +} + +static const char * +iename(uint8_t elemid, const u_int8_t *vp) { static char iename_buf[64]; switch (elemid) { @@ -3587,6 +3824,8 @@ iename(int elemid) case IEEE80211_ELEMID_IBSSDFS: return " IBSSDFS"; case IEEE80211_ELEMID_RESERVED_47: return " RESERVED_47"; + case IEEE80211_ELEMID_SUP_OP_CLASS: + return " SUP_OP_CLASS"; case IEEE80211_ELEMID_MOBILITY_DOMAIN: return " MOBILITY_DOMAIN"; case IEEE80211_ELEMID_RRM_ENACAPS: @@ -3596,26 +3835,58 @@ iename(int elemid) case IEEE80211_ELEMID_TPC: return " TPC"; case IEEE80211_ELEMID_CCKM: return " CCKM"; case IEEE80211_ELEMID_EXTCAP: return " EXTCAP"; + case IEEE80211_ELEMID_RSN_EXT: return " RSNXE"; + case IEEE80211_ELEMID_EXTFIELD: + if (vp[1] >= 1) + return ie_ext_name(vp[2]); + break; } - snprintf(iename_buf, sizeof(iename_buf), " UNKNOWN_ELEMID_%d", + snprintf(iename_buf, sizeof(iename_buf), " ELEMID_%d", elemid); return (const char *) iename_buf; } static void -printies(const u_int8_t *vp, int ielen, int maxcols) +printexties(if_ctx *ctx, const u_int8_t *vp, unsigned int maxcols) +{ + const int verbose = ctx->args->verbose; + + if (vp[1] < 1) + return; + + switch (vp[2]) { + case IEEE80211_ELEMID_EXT_HE_CAPA: + printhecap(ctx, " HECAP", vp); + break; + case IEEE80211_ELEMID_EXT_HE_OPER: + printheoper(ctx, " HEOPER", vp); + break; + case IEEE80211_ELEMID_EXT_MU_EDCA_PARAM_SET: + printmuedcaparamset(ctx, " MU_EDCA_PARAM_SET", vp); + break; + default: + if (verbose) + printie(ctx, iename(vp[0], vp), vp, 2+vp[1], maxcols); + break; + } +} + +static void +printies(if_ctx *ctx, const u_int8_t *vp, int ielen, unsigned int maxcols) { + const int verbose = ctx->args->verbose; + while (ielen > 0) { switch (vp[0]) { case IEEE80211_ELEMID_SSID: if (verbose) - printssid(" SSID", vp, 2+vp[1], maxcols); + printssid(" SSID", vp, maxcols); break; case IEEE80211_ELEMID_RATES: case IEEE80211_ELEMID_XRATES: if (verbose) printrates(vp[0] == IEEE80211_ELEMID_RATES ? - " RATES" : " XRATES", vp, 2+vp[1], maxcols); + " RATES" : " XRATES", vp, 2+vp[1]); break; case IEEE80211_ELEMID_DSPARMS: if (verbose) @@ -3623,7 +3894,7 @@ printies(const u_int8_t *vp, int ielen, int maxcols) break; case IEEE80211_ELEMID_COUNTRY: if (verbose) - printcountry(" COUNTRY", vp, 2+vp[1], maxcols); + printcountry(" COUNTRY", vp); break; case IEEE80211_ELEMID_ERP: if (verbose) @@ -3631,55 +3902,64 @@ printies(const u_int8_t *vp, int ielen, int maxcols) break; case IEEE80211_ELEMID_VENDOR: if (iswpaoui(vp)) - printwpaie(" WPA", vp, 2+vp[1], maxcols); + printwpaie(ctx, " WPA", vp); else if (iswmeinfo(vp)) - printwmeinfo(" WME", vp, 2+vp[1], maxcols); + printwmeinfo(ctx, " WME", vp); else if (iswmeparam(vp)) - printwmeparam(" WME", vp, 2+vp[1], maxcols); + printwmeparam(ctx, " WME", vp); else if (isatherosoui(vp)) - printathie(" ATH", vp, 2+vp[1], maxcols); + printathie(ctx, " ATH", vp); else if (iswpsoui(vp)) - printwpsie(" WPS", vp, 2+vp[1], maxcols); + printwpsie(ctx, " WPS", vp); else if (istdmaoui(vp)) - printtdmaie(" TDMA", vp, 2+vp[1], maxcols); + printtdmaie(ctx, " TDMA", vp, 2+vp[1]); else if (verbose) - printie(" VEN", vp, 2+vp[1], maxcols); - break; + printie(ctx, " VEN", vp, 2+vp[1], maxcols); + break; case IEEE80211_ELEMID_RSN: - printrsnie(" RSN", vp, 2+vp[1], maxcols); + printrsnie(ctx, " RSN", vp, 2+vp[1]); break; case IEEE80211_ELEMID_HTCAP: - printhtcap(" HTCAP", vp, 2+vp[1], maxcols); + printhtcap(ctx, " HTCAP", vp); + break; + case IEEE80211_ELEMID_SUP_OP_CLASS: + printsupopclass(ctx, " SUP_OP_CLASS", vp); break; case IEEE80211_ELEMID_HTINFO: if (verbose) - printhtinfo(" HTINFO", vp, 2+vp[1], maxcols); + printhtinfo(ctx, " HTINFO", vp); break; case IEEE80211_ELEMID_MESHID: if (verbose) - printssid(" MESHID", vp, 2+vp[1], maxcols); + printssid(" MESHID", vp, maxcols); break; case IEEE80211_ELEMID_MESHCONF: - printmeshconf(" MESHCONF", vp, 2+vp[1], maxcols); + printmeshconf(ctx, " MESHCONF", vp); break; case IEEE80211_ELEMID_VHT_CAP: - printvhtcap(" VHTCAP", vp, 2+vp[1], maxcols); + printvhtcap(ctx, " VHTCAP", vp); break; case IEEE80211_ELEMID_VHT_OPMODE: - printvhtinfo(" VHTOPMODE", vp, 2+vp[1], maxcols); + printvhtinfo(ctx, " VHTOPMODE", vp); break; case IEEE80211_ELEMID_VHT_PWR_ENV: - printvhtpwrenv(" VHTPWRENV", vp, 2+vp[1], maxcols); + printvhtpwrenv(ctx, " VHTPWRENV", vp, 2+vp[1]); break; case IEEE80211_ELEMID_BSSLOAD: - printbssload(" BSSLOAD", vp, 2+vp[1], maxcols); + printbssload(ctx, " BSSLOAD", vp); break; case IEEE80211_ELEMID_APCHANREP: - printapchanrep(" APCHANREP", vp, 2+vp[1], maxcols); + printapchanrep(ctx, " APCHANREP", vp, 2+vp[1]); + break; + case IEEE80211_ELEMID_RSN_EXT: + printrsnxe(ctx, " RSNXE", vp, 2+vp[1]); + break; + case IEEE80211_ELEMID_EXTFIELD: + printexties(ctx, vp, maxcols); break; default: if (verbose) - printie(iename(vp[0]), vp, 2+vp[1], maxcols); + printie(ctx, iename(vp[0], vp), vp, 2+vp[1], maxcols); break; } ielen -= 2+vp[1]; @@ -3694,7 +3974,7 @@ printmimo(const struct ieee80211_mimo_info *mi) int r = 0; for (i = 0; i < IEEE80211_MAX_CHAINS; i++) { - if (mi->ch[i].rssi != 0) { + if (mi->ch[i].rssi[0] != 0) { r = 1; break; } @@ -3717,19 +3997,30 @@ printmimo(const struct ieee80211_mimo_info *mi) } static void -list_scan(int s) +printbssidname(const struct ether_addr *n) +{ + char name[MAXHOSTNAMELEN + 1]; + + if (ether_ntohost(name, n) != 0) + return; + + printf(" (%s)", name); +} + +static void +list_scan(if_ctx *ctx) { uint8_t buf[24*1024]; char ssid[IEEE80211_NWID_LEN+1]; const uint8_t *cp; int len, idlen; - if (get80211len(s, IEEE80211_IOC_SCAN_RESULTS, buf, sizeof(buf), &len) < 0) + if (get80211len(ctx, IEEE80211_IOC_SCAN_RESULTS, buf, sizeof(buf), &len) < 0) errx(1, "unable to get scan results"); - if (len < sizeof(struct ieee80211req_scan_result)) + if (len < (int)sizeof(struct ieee80211req_scan_result)) return; - getchaninfo(s); + getchaninfo(ctx); printf("%-*.*s %-17.17s %4s %4s %-7s %3s %4s\n" , IEEE80211_NWID_LEN, IEEE80211_NWID_LEN, "SSID/MESH ID" @@ -3745,7 +4036,7 @@ list_scan(int s) const struct ieee80211req_scan_result *sr; const uint8_t *vp, *idp; - sr = (const struct ieee80211req_scan_result *) cp; + sr = (const struct ieee80211req_scan_result *)(const void *) cp; vp = cp + sr->isr_ie_off; if (sr->isr_meshid_len) { idp = vp + sr->isr_ssid_len; @@ -3765,15 +4056,16 @@ list_scan(int s) , sr->isr_intval , getcaps(sr->isr_capinfo) ); - printies(vp + sr->isr_ssid_len + sr->isr_meshid_len, + printies(ctx, vp + sr->isr_ssid_len + sr->isr_meshid_len, sr->isr_ie_len, 24); + printbssidname((const struct ether_addr *)sr->isr_bssid); printf("\n"); cp += sr->isr_len, len -= sr->isr_len; - } while (len >= sizeof(struct ieee80211req_scan_result)); + } while (len >= (int)sizeof(struct ieee80211req_scan_result)); } static void -scan_and_wait(int s) +scan_and_wait(if_ctx *ctx) { struct ieee80211_scan_req sr; struct ieee80211req ireq; @@ -3784,8 +4076,8 @@ scan_and_wait(int s) perror("socket(PF_ROUTE,SOCK_RAW)"); return; } - (void) memset(&ireq, 0, sizeof(ireq)); - (void) strlcpy(ireq.i_name, name, sizeof(ireq.i_name)); + memset(&ireq, 0, sizeof(ireq)); + strlcpy(ireq.i_name, ctx->ifname, sizeof(ireq.i_name)); ireq.i_type = IEEE80211_IOC_SCAN_REQ; memset(&sr, 0, sizeof(sr)); @@ -3803,7 +4095,7 @@ scan_and_wait(int s) * possible errors from net80211, even if no new scan could be * started there might still be a valid scan cache. */ - if (ioctl(s, SIOCS80211, &ireq) == 0) { + if (ioctl_ctx(ctx, SIOCS80211, &ireq) == 0) { char buf[2048]; struct if_announcemsghdr *ifan; struct rt_msghdr *rtm; @@ -3813,7 +4105,7 @@ scan_and_wait(int s) perror("read(PF_ROUTE)"); break; } - rtm = (struct rt_msghdr *) buf; + rtm = (struct rt_msghdr *)(void *)buf; if (rtm->rtm_version != RTM_VERSION) break; ifan = (struct if_announcemsghdr *) rtm; @@ -3823,14 +4115,14 @@ scan_and_wait(int s) close(sroute); } -static -DECL_CMD_FUNC(set80211scan, val, d) +static void +set80211scan(if_ctx *ctx, const char *val __unused, int dummy __unused) { - scan_and_wait(s); - list_scan(s); + scan_and_wait(ctx); + list_scan(ctx); } -static enum ieee80211_opmode get80211opmode(int s); +static enum ieee80211_opmode get80211opmode(if_ctx *ctx); static int gettxseq(const struct ieee80211req_sta_info *si) @@ -3850,26 +4142,26 @@ gettxseq(const struct ieee80211req_sta_info *si) static int getrxseq(const struct ieee80211req_sta_info *si) { - int i, rxseq; + int rxseq; if ((si->isi_state & IEEE80211_NODE_QOS) == 0) return si->isi_rxseqs[0]; /* XXX not right but usually what folks want */ rxseq = 0; - for (i = 0; i < IEEE80211_TID_SIZE; i++) + for (unsigned int i = 0; i < IEEE80211_TID_SIZE; i++) if (si->isi_rxseqs[i] > rxseq) rxseq = si->isi_rxseqs[i]; return rxseq; } static void -list_stations(int s) +list_stations(if_ctx *ctx) { union { struct ieee80211req_sta_req req; uint8_t buf[24*1024]; } u; - enum ieee80211_opmode opmode = get80211opmode(s); + enum ieee80211_opmode opmode = get80211opmode(ctx); const uint8_t *cp; int len; @@ -3879,15 +4171,15 @@ list_stations(int s) /* * Get information about the associated AP. */ - (void) get80211(s, IEEE80211_IOC_BSSID, + (void) get80211(ctx, IEEE80211_IOC_BSSID, u.req.is_u.macaddr, IEEE80211_ADDR_LEN); } - if (get80211len(s, IEEE80211_IOC_STA_INFO, &u, sizeof(u), &len) < 0) + if (get80211len(ctx, IEEE80211_IOC_STA_INFO, &u, sizeof(u), &len) < 0) errx(1, "unable to get station information"); - if (len < sizeof(struct ieee80211req_sta_info)) + if (len < (int)sizeof(struct ieee80211req_sta_info)) return; - getchaninfo(s); + getchaninfo(ctx); if (opmode == IEEE80211_M_MBSS) printf("%-17.17s %4s %5s %5s %7s %4s %4s %4s %6s %6s\n" @@ -3919,7 +4211,7 @@ list_stations(int s) do { const struct ieee80211req_sta_info *si; - si = (const struct ieee80211req_sta_info *) cp; + si = (const struct ieee80211req_sta_info *)(const void *)cp; if (si->isi_len < sizeof(*si)) break; if (opmode == IEEE80211_M_MBSS) @@ -3952,11 +4244,11 @@ list_stations(int s) , getcaps(si->isi_capinfo) , getflags(si->isi_state) ); - printies(cp + si->isi_ie_off, si->isi_ie_len, 24); + printies(ctx, cp + si->isi_ie_off, si->isi_ie_len, 24); printmimo(&si->isi_mimo); printf("\n"); cp += si->isi_len, len -= si->isi_len; - } while (len >= sizeof(struct ieee80211req_sta_info)); + } while (len >= (int)sizeof(struct ieee80211req_sta_info)); } static const char * @@ -4090,13 +4382,13 @@ chanpref(const struct ieee80211_channel *c) } static void -print_channels(int s, const struct ieee80211req_chaninfo *chans, +print_channels(if_ctx *ctx, const struct ieee80211req_chaninfo *chans, int allchans, int verb) { struct ieee80211req_chaninfo *achans; uint8_t reported[IEEE80211_CHAN_BYTES]; const struct ieee80211_channel *c; - int i, half; + unsigned int i, half; achans = malloc(IEEE80211_CHANINFO_SPACE(chans)); if (achans == NULL) @@ -4106,7 +4398,7 @@ print_channels(int s, const struct ieee80211req_chaninfo *chans, if (!allchans) { struct ieee80211req_chanlist active; - if (get80211(s, IEEE80211_IOC_CHANLIST, &active, sizeof(active)) < 0) + if (get80211(ctx, IEEE80211_IOC_CHANLIST, &active, sizeof(active)) < 0) errx(1, "unable to get active channel list"); for (i = 0; i < chans->ic_nchans; i++) { c = &chans->ic_chans[i]; @@ -4159,10 +4451,10 @@ print_channels(int s, const struct ieee80211req_chaninfo *chans, } static void -list_channels(int s, int allchans) +list_channels(if_ctx *ctx, int allchans) { - getchaninfo(s); - print_channels(s, chaninfo, allchans, verbose); + getchaninfo(ctx); + print_channels(ctx, chaninfo, allchans, ctx->args->verbose); } static void @@ -4185,14 +4477,14 @@ print_txpow_verbose(const struct ieee80211_channel *c) } static void -list_txpow(int s) +list_txpow(if_ctx *ctx) { struct ieee80211req_chaninfo *achans; uint8_t reported[IEEE80211_CHAN_BYTES]; struct ieee80211_channel *c, *prev; - int i, half; + unsigned int i, half; - getchaninfo(s); + getchaninfo(ctx); achans = malloc(IEEE80211_CHANINFO_SPACE(chaninfo)); if (achans == NULL) errx(1, "no space for active channel list"); @@ -4201,7 +4493,7 @@ list_txpow(int s) for (i = 0; i < chaninfo->ic_nchans; i++) { c = &chaninfo->ic_chans[i]; /* suppress duplicates as above */ - if (isset(reported, c->ic_ieee) && !verbose) { + if (isset(reported, c->ic_ieee) && !ctx->args->verbose) { /* XXX we assume duplicates are adjacent */ assert(achans->ic_nchans > 0); prev = &achans->ic_chans[achans->ic_nchans-1]; @@ -4213,7 +4505,7 @@ list_txpow(int s) setbit(reported, c->ic_ieee); } } - if (!verbose) { + if (!ctx->args->verbose) { half = achans->ic_nchans / 2; if (achans->ic_nchans % 2) half++; @@ -4237,14 +4529,15 @@ list_txpow(int s) } static void -list_keys(int s) +list_keys(int s __unused) { } static void -list_capabilities(int s) +list_capabilities(if_ctx *ctx) { struct ieee80211_devcaps_req *dc; + const int verbose = ctx->args->verbose; if (verbose) dc = malloc(IEEE80211_DEVCAPS_SIZE(MAXCHAN)); @@ -4253,7 +4546,7 @@ list_capabilities(int s) if (dc == NULL) errx(1, "no space for device capabilities"); dc->dc_chaninfo.ic_nchans = verbose ? MAXCHAN : 1; - getdevcaps(s, dc); + getdevcaps(ctx, dc); printb("drivercaps", dc->dc_drivercaps, IEEE80211_C_BITS); if (dc->dc_cryptocaps != 0 || verbose) { putchar('\n'); @@ -4271,21 +4564,20 @@ list_capabilities(int s) putchar('\n'); if (verbose) { chaninfo = &dc->dc_chaninfo; /* XXX */ - print_channels(s, &dc->dc_chaninfo, 1/*allchans*/, verbose); + print_channels(ctx, &dc->dc_chaninfo, 1/*allchans*/, verbose); } free(dc); } static int -get80211wme(int s, int param, int ac, int *val) +get80211wme(if_ctx *ctx, int param, int ac, int *val) { - struct ieee80211req ireq; + struct ieee80211req ireq = {}; - (void) memset(&ireq, 0, sizeof(ireq)); - (void) strlcpy(ireq.i_name, name, sizeof(ireq.i_name)); + strlcpy(ireq.i_name, ctx->ifname, sizeof(ireq.i_name)); ireq.i_type = param; ireq.i_len = ac; - if (ioctl(s, SIOCG80211, &ireq) < 0) { + if (ioctl_ctx(ctx, SIOCG80211, &ireq) < 0) { warn("cannot get WME parameter %d, ac %d%s", param, ac & IEEE80211_WMEPARAM_VAL, ac & IEEE80211_WMEPARAM_BSS ? " (BSS)" : ""); @@ -4296,33 +4588,33 @@ get80211wme(int s, int param, int ac, int *val) } static void -list_wme_aci(int s, const char *tag, int ac) +list_wme_aci(if_ctx *ctx, const char *tag, int ac) { int val; printf("\t%s", tag); /* show WME BSS parameters */ - if (get80211wme(s, IEEE80211_IOC_WME_CWMIN, ac, &val) != -1) + if (get80211wme(ctx, IEEE80211_IOC_WME_CWMIN, ac, &val) != -1) printf(" cwmin %2u", val); - if (get80211wme(s, IEEE80211_IOC_WME_CWMAX, ac, &val) != -1) + if (get80211wme(ctx, IEEE80211_IOC_WME_CWMAX, ac, &val) != -1) printf(" cwmax %2u", val); - if (get80211wme(s, IEEE80211_IOC_WME_AIFS, ac, &val) != -1) + if (get80211wme(ctx, IEEE80211_IOC_WME_AIFS, ac, &val) != -1) printf(" aifs %2u", val); - if (get80211wme(s, IEEE80211_IOC_WME_TXOPLIMIT, ac, &val) != -1) + if (get80211wme(ctx, IEEE80211_IOC_WME_TXOPLIMIT, ac, &val) != -1) printf(" txopLimit %3u", val); - if (get80211wme(s, IEEE80211_IOC_WME_ACM, ac, &val) != -1) { + if (get80211wme(ctx, IEEE80211_IOC_WME_ACM, ac, &val) != -1) { if (val) printf(" acm"); - else if (verbose) + else if (ctx->args->verbose) printf(" -acm"); } /* !BSS only */ if ((ac & IEEE80211_WMEPARAM_BSS) == 0) { - if (get80211wme(s, IEEE80211_IOC_WME_ACKPOLICY, ac, &val) != -1) { + if (get80211wme(ctx, IEEE80211_IOC_WME_ACKPOLICY, ac, &val) != -1) { if (!val) printf(" -ack"); - else if (verbose) + else if (ctx->args->verbose) printf(" ack"); } } @@ -4330,19 +4622,19 @@ list_wme_aci(int s, const char *tag, int ac) } static void -list_wme(int s) +list_wme(if_ctx *ctx) { static const char *acnames[] = { "AC_BE", "AC_BK", "AC_VI", "AC_VO" }; int ac; - if (verbose) { + if (ctx->args->verbose) { /* display both BSS and local settings */ for (ac = WME_AC_BE; ac <= WME_AC_VO; ac++) { again: if (ac & IEEE80211_WMEPARAM_BSS) - list_wme_aci(s, " ", ac); + list_wme_aci(ctx, " ", ac); else - list_wme_aci(s, acnames[ac], ac); + list_wme_aci(ctx, acnames[ac], ac); if ((ac & IEEE80211_WMEPARAM_BSS) == 0) { ac |= IEEE80211_WMEPARAM_BSS; goto again; @@ -4352,17 +4644,17 @@ list_wme(int s) } else { /* display only channel settings */ for (ac = WME_AC_BE; ac <= WME_AC_VO; ac++) - list_wme_aci(s, acnames[ac], ac); + list_wme_aci(ctx, acnames[ac], ac); } } static void -list_roam(int s) +list_roam(if_ctx *ctx) { const struct ieee80211_roamparam *rp; int mode; - getroam(s); + getroam(ctx); for (mode = IEEE80211_MODE_11A; mode < IEEE80211_MODE_MAX; mode++) { rp = &roamparams.params[mode]; if (rp->rssi == 0 && rp->rate == 0) @@ -4406,12 +4698,12 @@ get_rate_value(uint8_t rate) } static void -list_txparams(int s) +list_txparams(if_ctx *ctx) { const struct ieee80211_txparam *tp; int mode; - gettxparams(s); + gettxparams(ctx); for (mode = IEEE80211_MODE_11A; mode < IEEE80211_MODE_MAX; mode++) { tp = &txparams.params[mode]; if (tp->mgmtrate == 0 && tp->mcastrate == 0) @@ -4479,19 +4771,18 @@ printpolicy(int policy) } static void -list_mac(int s) +list_mac(if_ctx *ctx) { - struct ieee80211req ireq; + struct ieee80211req ireq = {}; struct ieee80211req_maclist *acllist; int i, nacls, policy, len; uint8_t *data; char c; - (void) memset(&ireq, 0, sizeof(ireq)); - (void) strlcpy(ireq.i_name, name, sizeof(ireq.i_name)); /* XXX ?? */ + strlcpy(ireq.i_name, ctx->ifname, sizeof(ireq.i_name)); /* XXX ?? */ ireq.i_type = IEEE80211_IOC_MACCMD; ireq.i_val = IEEE80211_MACCMD_POLICY; - if (ioctl(s, SIOCG80211, &ireq) < 0) { + if (ioctl_ctx(ctx, SIOCG80211, &ireq) < 0) { if (errno == EINVAL) { printf("No acl policy loaded\n"); return; @@ -4511,15 +4802,15 @@ list_mac(int s) printf("policy: unknown (%u)\n", policy); c = '?'; } - if (verbose || c == '?') + if (ctx->args->verbose || c == '?') printpolicy(policy); ireq.i_val = IEEE80211_MACCMD_LIST; ireq.i_len = 0; - if (ioctl(s, SIOCG80211, &ireq) < 0) + if (ioctl_ctx(ctx, SIOCG80211, &ireq) < 0) err(1, "unable to get mac acl list size"); if (ireq.i_len == 0) { /* NB: no acls */ - if (!(verbose || c == '?')) + if (!(ctx->args->verbose || c == '?')) printpolicy(policy); return; } @@ -4530,7 +4821,7 @@ list_mac(int s) err(1, "out of memory for acl list"); ireq.i_data = data; - if (ioctl(s, SIOCG80211, &ireq) < 0) + if (ioctl_ctx(ctx, SIOCG80211, &ireq) < 0) err(1, "unable to get mac acl list"); nacls = len / sizeof(*acllist); acllist = (struct ieee80211req_maclist *) data; @@ -4573,33 +4864,32 @@ print_regdomain(const struct ieee80211_regdomain *reg, int verb) } static void -list_regdomain(int s, int channelsalso) +list_regdomain(if_ctx *ctx, int channelsalso) { - getregdomain(s); + getregdomain(ctx); if (channelsalso) { - getchaninfo(s); + getchaninfo(ctx); spacer = ':'; print_regdomain(®domain, 1); LINE_BREAK(); - print_channels(s, chaninfo, 1/*allchans*/, 1/*verbose*/); + print_channels(ctx, chaninfo, 1/*allchans*/, 1/*verbose*/); } else - print_regdomain(®domain, verbose); + print_regdomain(®domain, ctx->args->verbose); } static void -list_mesh(int s) +list_mesh(if_ctx *ctx) { - struct ieee80211req ireq; + struct ieee80211req ireq = {}; struct ieee80211req_mesh_route routes[128]; struct ieee80211req_mesh_route *rt; - (void) memset(&ireq, 0, sizeof(ireq)); - (void) strlcpy(ireq.i_name, name, sizeof(ireq.i_name)); + strlcpy(ireq.i_name, ctx->ifname, sizeof(ireq.i_name)); ireq.i_type = IEEE80211_IOC_MESH_RTCMD; ireq.i_val = IEEE80211_MESH_RTCMD_LIST; ireq.i_data = &routes; ireq.i_len = sizeof(routes); - if (ioctl(s, SIOCG80211, &ireq) < 0) + if (ioctl_ctx(ctx, SIOCG80211, &ireq) < 0) err(1, "unable to get the Mesh routing table"); printf("%-17.17s %-17.17s %4s %4s %4s %6s %s\n" @@ -4611,7 +4901,8 @@ list_mesh(int s) , "MSEQ" , "FLAGS"); - for (rt = &routes[0]; rt - &routes[0] < ireq.i_len / sizeof(*rt); rt++){ + for (unsigned int i = 0; i < ireq.i_len / sizeof(*rt); i++) { + rt = &routes[i]; printf("%s ", ether_ntoa((const struct ether_addr *)rt->imr_dest)); printf("%s %4u %4u %6u %6u %c%c\n", @@ -4629,56 +4920,56 @@ list_mesh(int s) } } -static -DECL_CMD_FUNC(set80211list, arg, d) +static void +set80211list(if_ctx *ctx, const char *arg, int dummy __unused) { + int s = ctx->io_s; #define iseq(a,b) (strncasecmp(a,b,sizeof(b)-1) == 0) LINE_INIT('\t'); if (iseq(arg, "sta")) - list_stations(s); + list_stations(ctx); else if (iseq(arg, "scan") || iseq(arg, "ap")) - list_scan(s); + list_scan(ctx); else if (iseq(arg, "chan") || iseq(arg, "freq")) - list_channels(s, 1); + list_channels(ctx, 1); else if (iseq(arg, "active")) - list_channels(s, 0); + list_channels(ctx, 0); else if (iseq(arg, "keys")) list_keys(s); else if (iseq(arg, "caps")) - list_capabilities(s); + list_capabilities(ctx); else if (iseq(arg, "wme") || iseq(arg, "wmm")) - list_wme(s); + list_wme(ctx); else if (iseq(arg, "mac")) - list_mac(s); + list_mac(ctx); else if (iseq(arg, "txpow")) - list_txpow(s); + list_txpow(ctx); else if (iseq(arg, "roam")) - list_roam(s); + list_roam(ctx); else if (iseq(arg, "txparam") || iseq(arg, "txparm")) - list_txparams(s); + list_txparams(ctx); else if (iseq(arg, "regdomain")) - list_regdomain(s, 1); + list_regdomain(ctx, 1); else if (iseq(arg, "countries")) list_countries(); else if (iseq(arg, "mesh")) - list_mesh(s); + list_mesh(ctx); else - errx(1, "Don't know how to list %s for %s", arg, name); + errx(1, "Don't know how to list %s for %s", arg, ctx->ifname); LINE_BREAK(); #undef iseq } static enum ieee80211_opmode -get80211opmode(int s) +get80211opmode(if_ctx *ctx) { - struct ifmediareq ifmr; + struct ifmediareq ifmr = {}; - (void) memset(&ifmr, 0, sizeof(ifmr)); - (void) strlcpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); + strlcpy(ifmr.ifm_name, ctx->ifname, sizeof(ifmr.ifm_name)); - if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) { + if (ioctl_ctx(ctx, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) { if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) { if (ifmr.ifm_current & IFM_FLAG0) return IEEE80211_M_AHDEMO; @@ -4720,6 +5011,9 @@ printcipher(int s, struct ieee80211req *ireq, int keylenop) case IEEE80211_CIPHER_AES_CCM: printf("AES-CCM"); break; + case IEEE80211_CIPHER_AES_GCM_128: + printf("AES-GCM"); + break; case IEEE80211_CIPHER_CKIP: printf("CKIP"); break; @@ -4734,43 +5028,61 @@ printcipher(int s, struct ieee80211req *ireq, int keylenop) #endif static void -printkey(const struct ieee80211req_key *ik) +printkey_index(uint16_t keyix, char *buf, size_t buflen) +{ + buf[0] = '\0'; + if (keyix == IEEE80211_KEYIX_NONE) { + snprintf(buf, buflen, "ucast"); + } else { + snprintf(buf, buflen, "%u", keyix+1); + } +} + +static void +printkey(if_ctx *ctx, const struct ieee80211req_key *ik) { static const uint8_t zerodata[IEEE80211_KEYBUF_SIZE]; u_int keylen = ik->ik_keylen; int printcontents; + const int verbose = ctx->args->verbose; + const bool printkeys = ctx->args->printkeys; + char keyix[16]; printcontents = printkeys && (memcmp(ik->ik_keydata, zerodata, keylen) != 0 || verbose); if (printcontents) LINE_BREAK(); + printkey_index(ik->ik_keyix, keyix, sizeof(keyix)); switch (ik->ik_type) { case IEEE80211_CIPHER_WEP: /* compatibility */ - LINE_CHECK("wepkey %u:%s", ik->ik_keyix+1, + LINE_CHECK("wepkey %s:%s", keyix, keylen <= 5 ? "40-bit" : keylen <= 13 ? "104-bit" : "128-bit"); break; case IEEE80211_CIPHER_TKIP: if (keylen > 128/8) keylen -= 128/8; /* ignore MIC for now */ - LINE_CHECK("TKIP %u:%u-bit", ik->ik_keyix+1, 8*keylen); + LINE_CHECK("TKIP %s:%u-bit", keyix, 8*keylen); break; case IEEE80211_CIPHER_AES_OCB: - LINE_CHECK("AES-OCB %u:%u-bit", ik->ik_keyix+1, 8*keylen); + LINE_CHECK("AES-OCB %s:%u-bit", keyix, 8*keylen); break; case IEEE80211_CIPHER_AES_CCM: - LINE_CHECK("AES-CCM %u:%u-bit", ik->ik_keyix+1, 8*keylen); + LINE_CHECK("AES-CCM %s:%u-bit", keyix, 8*keylen); + break; + case IEEE80211_CIPHER_AES_GCM_128: + LINE_CHECK("AES-GCM %s:%u-bit", keyix, 8*keylen); break; case IEEE80211_CIPHER_CKIP: - LINE_CHECK("CKIP %u:%u-bit", ik->ik_keyix+1, 8*keylen); + LINE_CHECK("CKIP %s:%u-bit", keyix, 8*keylen); break; case IEEE80211_CIPHER_NONE: - LINE_CHECK("NULL %u:%u-bit", ik->ik_keyix+1, 8*keylen); + LINE_CHECK("NULL %s:%u-bit", keyix, 8*keylen); break; default: - LINE_CHECK("UNKNOWN (0x%x) %u:%u-bit", - ik->ik_type, ik->ik_keyix+1, 8*keylen); + LINE_CHECK("UNKNOWN (0x%x) %s:%u-bit", + ik->ik_type, keyix, 8*keylen); break; } if (printcontents) { @@ -4817,51 +5129,52 @@ printrate(const char *tag, int v, int defrate, int defmcs) } static int -getid(int s, int ix, void *data, size_t len, int *plen, int mesh) +getid(if_ctx *ctx, int ix, void *data, size_t len, int *plen, int mesh) { - struct ieee80211req ireq; + struct ieee80211req ireq = {}; - (void) memset(&ireq, 0, sizeof(ireq)); - (void) strlcpy(ireq.i_name, name, sizeof(ireq.i_name)); + strlcpy(ireq.i_name, ctx->ifname, sizeof(ireq.i_name)); ireq.i_type = (!mesh) ? IEEE80211_IOC_SSID : IEEE80211_IOC_MESH_ID; ireq.i_val = ix; ireq.i_data = data; ireq.i_len = len; - if (ioctl(s, SIOCG80211, &ireq) < 0) + if (ioctl_ctx(ctx, SIOCG80211, &ireq) < 0) return -1; *plen = ireq.i_len; return 0; } static int -getdevicename(int s, void *data, size_t len, int *plen) +getdevicename(if_ctx *ctx, void *data, size_t len, int *plen) { - struct ieee80211req ireq; + struct ieee80211req ireq = {}; - (void) memset(&ireq, 0, sizeof(ireq)); - (void) strlcpy(ireq.i_name, name, sizeof(ireq.i_name)); + strlcpy(ireq.i_name, ctx->ifname, sizeof(ireq.i_name)); ireq.i_type = IEEE80211_IOC_IC_NAME; ireq.i_val = -1; ireq.i_data = data; ireq.i_len = len; - if (ioctl(s, SIOCG80211, &ireq) < 0) + if (ioctl_ctx(ctx, SIOCG80211, &ireq) < 0) return (-1); *plen = ireq.i_len; return (0); } static void -ieee80211_status(int s) +ieee80211_status(if_ctx *ctx) { + int s = ctx->io_s; static const uint8_t zerobssid[IEEE80211_ADDR_LEN]; - enum ieee80211_opmode opmode = get80211opmode(s); + uint8_t bssid[IEEE80211_ADDR_LEN]; + enum ieee80211_opmode opmode = get80211opmode(ctx); int i, num, wpa, wme, bgscan, bgscaninterval, val, len, wepmode; uint8_t data[32]; const struct ieee80211_channel *c; const struct ieee80211_roamparam *rp; const struct ieee80211_txparam *tp; + const int verbose = ctx->args->verbose; - if (getid(s, -1, data, sizeof(data), &len, 0) < 0) { + if (getid(ctx, -1, data, sizeof(data), &len, 0) < 0) { /* If we can't get the SSID, this isn't an 802.11 device. */ return; } @@ -4879,15 +5192,15 @@ ieee80211_status(int s) printf("\t"); if (opmode == IEEE80211_M_MBSS) { printf("meshid "); - getid(s, 0, data, sizeof(data), &len, 1); + getid(ctx, 0, data, sizeof(data), &len, 1); print_string(data, len); } else { - if (get80211val(s, IEEE80211_IOC_NUMSSIDS, &num) < 0) + if (get80211val(ctx, IEEE80211_IOC_NUMSSIDS, &num) < 0) num = 0; printf("ssid "); if (num > 1) { for (i = 0; i < num; i++) { - if (getid(s, i, data, sizeof(data), &len, 0) >= 0 && len > 0) { + if (getid(ctx, i, data, sizeof(data), &len, 0) >= 0 && len > 0) { printf(" %d:", i + 1); print_string(data, len); } @@ -4895,7 +5208,7 @@ ieee80211_status(int s) } else print_string(data, len); } - c = getcurchan(s); + c = getcurchan(ctx); if (c->ic_freq != IEEE80211_CHAN_ANY) { char buf[14]; printf(" channel %d (%u MHz%s)", c->ic_ieee, c->ic_freq, @@ -4903,11 +5216,13 @@ ieee80211_status(int s) } else if (verbose) printf(" channel UNDEF"); - if (get80211(s, IEEE80211_IOC_BSSID, data, IEEE80211_ADDR_LEN) >= 0 && - (memcmp(data, zerobssid, sizeof(zerobssid)) != 0 || verbose)) - printf(" bssid %s", ether_ntoa((struct ether_addr *)data)); + if (get80211(ctx, IEEE80211_IOC_BSSID, bssid, IEEE80211_ADDR_LEN) >= 0 && + (memcmp(bssid, zerobssid, sizeof(zerobssid)) != 0 || verbose)) { + printf(" bssid %s", ether_ntoa((struct ether_addr *)bssid)); + printbssidname((struct ether_addr *)bssid); + } - if (get80211len(s, IEEE80211_IOC_STATIONNAME, data, sizeof(data), &len) != -1) { + if (get80211len(ctx, IEEE80211_IOC_STATIONNAME, data, sizeof(data), &len) != -1) { printf("\n\tstationname "); print_string(data, len); } @@ -4915,10 +5230,10 @@ ieee80211_status(int s) spacer = ' '; /* force first break */ LINE_BREAK(); - list_regdomain(s, 0); + list_regdomain(ctx, 0); wpa = 0; - if (get80211val(s, IEEE80211_IOC_AUTHMODE, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_AUTHMODE, &val) != -1) { switch (val) { case IEEE80211_AUTH_NONE: LINE_CHECK("authmode NONE"); @@ -4933,7 +5248,7 @@ ieee80211_status(int s) LINE_CHECK("authmode 802.1x"); break; case IEEE80211_AUTH_WPA: - if (get80211val(s, IEEE80211_IOC_WPA, &wpa) < 0) + if (get80211val(ctx, IEEE80211_IOC_WPA, &wpa) < 0) wpa = 1; /* default to WPA1 */ switch (wpa) { case 2: @@ -4957,13 +5272,13 @@ ieee80211_status(int s) } if (wpa || verbose) { - if (get80211val(s, IEEE80211_IOC_WPS, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_WPS, &val) != -1) { if (val) LINE_CHECK("wps"); else if (verbose) LINE_CHECK("-wps"); } - if (get80211val(s, IEEE80211_IOC_TSN, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_TSN, &val) != -1) { if (val) LINE_CHECK("tsn"); else if (verbose) @@ -5008,7 +5323,7 @@ ieee80211_status(int s) #endif } - if (get80211val(s, IEEE80211_IOC_WEP, &wepmode) != -1 && + if (get80211val(ctx, IEEE80211_IOC_WEP, &wepmode) != -1 && wepmode != IEEE80211_WEP_NOSUP) { switch (wepmode) { @@ -5031,7 +5346,7 @@ ieee80211_status(int s) * to print WEP status. */ - if (get80211val(s, IEEE80211_IOC_WEPTXKEY, &val) < 0) { + if (get80211val(ctx, IEEE80211_IOC_WEPTXKEY, &val) < 0) { warn("WEP support, but no tx key!"); goto end; } @@ -5040,7 +5355,7 @@ ieee80211_status(int s) else if (wepmode != IEEE80211_WEP_OFF || verbose) LINE_CHECK("deftxkey UNDEF"); - if (get80211val(s, IEEE80211_IOC_NUMWEPKEYS, &num) < 0) { + if (get80211val(ctx, IEEE80211_IOC_NUMWEPKEYS, &num) < 0) { warn("WEP support, but no NUMWEPKEYS support!"); goto end; } @@ -5050,14 +5365,29 @@ ieee80211_status(int s) memset(&ik, 0, sizeof(ik)); ik.ik_keyix = i; - if (get80211(s, IEEE80211_IOC_WPAKEY, &ik, sizeof(ik)) < 0) { - warn("WEP support, but can get keys!"); + if (get80211(ctx, IEEE80211_IOC_WPAKEY, &ik, sizeof(ik)) < 0) { + warn("WEP support, but cannot get keys!"); goto end; } if (ik.ik_keylen != 0) { if (verbose) LINE_BREAK(); - printkey(&ik); + printkey(ctx, &ik); + } + } + if (opmode == IEEE80211_M_STA && wpa >= 2) { + struct ieee80211req_key ik; + int error; + + memset(&ik, 0, sizeof(ik)); + ik.ik_keyix = IEEE80211_KEYIX_NONE; + memcpy(ik.ik_macaddr, bssid, sizeof(ik.ik_macaddr)); + error = get80211(ctx, IEEE80211_IOC_WPAKEY, &ik, sizeof(ik)); + if (error == 0 && ik.ik_keylen != 0) { + if (verbose) + LINE_BREAK(); + printkey(ctx, &ik); + i++; } } if (i > 0 && verbose) @@ -5066,7 +5396,7 @@ end: ; } - if (get80211val(s, IEEE80211_IOC_POWERSAVE, &val) != -1 && + if (get80211val(ctx, IEEE80211_IOC_POWERSAVE, &val) != -1 && val != IEEE80211_POWERSAVE_NOSUP ) { if (val != IEEE80211_POWERSAVE_OFF || verbose) { switch (val) { @@ -5083,47 +5413,47 @@ end: LINE_CHECK("powersavemode PSP-CAM"); break; } - if (get80211val(s, IEEE80211_IOC_POWERSAVESLEEP, &val) != -1) + if (get80211val(ctx, IEEE80211_IOC_POWERSAVESLEEP, &val) != -1) LINE_CHECK("powersavesleep %d", val); } } - if (get80211val(s, IEEE80211_IOC_TXPOWER, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_TXPOWER, &val) != -1) { if (val & 1) LINE_CHECK("txpower %d.5", val/2); else LINE_CHECK("txpower %d", val/2); } if (verbose) { - if (get80211val(s, IEEE80211_IOC_TXPOWMAX, &val) != -1) + if (get80211val(ctx, IEEE80211_IOC_TXPOWMAX, &val) != -1) LINE_CHECK("txpowmax %.1f", val/2.); } - if (get80211val(s, IEEE80211_IOC_DOTD, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_DOTD, &val) != -1) { if (val) LINE_CHECK("dotd"); else if (verbose) LINE_CHECK("-dotd"); } - if (get80211val(s, IEEE80211_IOC_RTSTHRESHOLD, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_RTSTHRESHOLD, &val) != -1) { if (val != IEEE80211_RTS_MAX || verbose) LINE_CHECK("rtsthreshold %d", val); } - if (get80211val(s, IEEE80211_IOC_FRAGTHRESHOLD, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_FRAGTHRESHOLD, &val) != -1) { if (val != IEEE80211_FRAG_MAX || verbose) LINE_CHECK("fragthreshold %d", val); } if (opmode == IEEE80211_M_STA || verbose) { - if (get80211val(s, IEEE80211_IOC_BMISSTHRESHOLD, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_BMISSTHRESHOLD, &val) != -1) { if (val != IEEE80211_HWBMISS_MAX || verbose) LINE_CHECK("bmiss %d", val); } } if (!verbose) { - gettxparams(s); + gettxparams(ctx); tp = &txparams.params[chan2mode(c)]; printrate("ucastrate", tp->ucastrate, IEEE80211_FIXED_RATE_NONE, IEEE80211_FIXED_RATE_NONE); @@ -5135,19 +5465,19 @@ end: LINE_CHECK("maxretry %d", tp->maxretry); } else { LINE_BREAK(); - list_txparams(s); + list_txparams(ctx); } bgscaninterval = -1; - (void) get80211val(s, IEEE80211_IOC_BGSCAN_INTERVAL, &bgscaninterval); + (void) get80211val(ctx, IEEE80211_IOC_BGSCAN_INTERVAL, &bgscaninterval); - if (get80211val(s, IEEE80211_IOC_SCANVALID, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_SCANVALID, &val) != -1) { if (val != bgscaninterval || verbose) LINE_CHECK("scanvalid %u", val); } bgscan = 0; - if (get80211val(s, IEEE80211_IOC_BGSCAN, &bgscan) != -1) { + if (get80211val(ctx, IEEE80211_IOC_BGSCAN, &bgscan) != -1) { if (bgscan) LINE_CHECK("bgscan"); else if (verbose) @@ -5156,10 +5486,10 @@ end: if (bgscan || verbose) { if (bgscaninterval != -1) LINE_CHECK("bgscanintvl %u", bgscaninterval); - if (get80211val(s, IEEE80211_IOC_BGSCAN_IDLE, &val) != -1) + if (get80211val(ctx, IEEE80211_IOC_BGSCAN_IDLE, &val) != -1) LINE_CHECK("bgscanidle %u", val); if (!verbose) { - getroam(s); + getroam(ctx); rp = &roamparams.params[chan2mode(c)]; if (rp->rssi & 1) LINE_CHECK("roam:rssi %u.5", rp->rssi/2); @@ -5170,19 +5500,19 @@ end: get_rate_value(rp->rate)); } else { LINE_BREAK(); - list_roam(s); + list_roam(ctx); LINE_BREAK(); } } if (IEEE80211_IS_CHAN_ANYG(c) || verbose) { - if (get80211val(s, IEEE80211_IOC_PUREG, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_PUREG, &val) != -1) { if (val) LINE_CHECK("pureg"); else if (verbose) LINE_CHECK("-pureg"); } - if (get80211val(s, IEEE80211_IOC_PROTMODE, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_PROTMODE, &val) != -1) { switch (val) { case IEEE80211_PROTMODE_OFF: LINE_CHECK("protmode OFF"); @@ -5201,7 +5531,7 @@ end: } if (IEEE80211_IS_CHAN_HT(c) || verbose) { - gethtconf(s); + gethtconf(ctx); switch (htconf & 3) { case 0: case 2: @@ -5215,13 +5545,13 @@ end: LINE_CHECK("ht"); break; } - if (get80211val(s, IEEE80211_IOC_HTCOMPAT, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_HTCOMPAT, &val) != -1) { if (!val) LINE_CHECK("-htcompat"); else if (verbose) LINE_CHECK("htcompat"); } - if (get80211val(s, IEEE80211_IOC_AMPDU, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_AMPDU, &val) != -1) { switch (val) { case 0: LINE_CHECK("-ampdu"); @@ -5239,7 +5569,7 @@ end: } } /* XXX 11ac density/size is different */ - if (get80211val(s, IEEE80211_IOC_AMPDU_LIMIT, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_AMPDU_LIMIT, &val) != -1) { switch (val) { case IEEE80211_HTCAP_MAXRXAMPDU_8K: LINE_CHECK("ampdulimit 8k"); @@ -5256,7 +5586,7 @@ end: } } /* XXX 11ac density/size is different */ - if (get80211val(s, IEEE80211_IOC_AMPDU_DENSITY, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_AMPDU_DENSITY, &val) != -1) { switch (val) { case IEEE80211_HTCAP_MPDUDENSITY_NA: if (verbose) @@ -5285,7 +5615,7 @@ end: break; } } - if (get80211val(s, IEEE80211_IOC_AMSDU, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_AMSDU, &val) != -1) { switch (val) { case 0: LINE_CHECK("-amsdu"); @@ -5303,13 +5633,13 @@ end: } } /* XXX amsdu limit */ - if (get80211val(s, IEEE80211_IOC_SHORTGI, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_SHORTGI, &val) != -1) { if (val) LINE_CHECK("shortgi"); else if (verbose) LINE_CHECK("-shortgi"); } - if (get80211val(s, IEEE80211_IOC_HTPROTMODE, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_HTPROTMODE, &val) != -1) { if (val == IEEE80211_PROTMODE_OFF) LINE_CHECK("htprotmode OFF"); else if (val != IEEE80211_PROTMODE_RTSCTS) @@ -5317,13 +5647,13 @@ end: else if (verbose) LINE_CHECK("htprotmode RTSCTS"); } - if (get80211val(s, IEEE80211_IOC_PUREN, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_PUREN, &val) != -1) { if (val) LINE_CHECK("puren"); else if (verbose) LINE_CHECK("-puren"); } - if (get80211val(s, IEEE80211_IOC_SMPS, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_SMPS, &val) != -1) { if (val == IEEE80211_HTCAP_SMPS_DYNAMIC) LINE_CHECK("smpsdyn"); else if (val == IEEE80211_HTCAP_SMPS_ENA) @@ -5331,7 +5661,7 @@ end: else if (verbose) LINE_CHECK("-smps"); } - if (get80211val(s, IEEE80211_IOC_RIFS, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_RIFS, &val) != -1) { if (val) LINE_CHECK("rifs"); else if (verbose) @@ -5339,7 +5669,7 @@ end: } /* XXX VHT STBC? */ - if (get80211val(s, IEEE80211_IOC_STBC, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_STBC, &val) != -1) { switch (val) { case 0: LINE_CHECK("-stbc"); @@ -5356,7 +5686,7 @@ end: break; } } - if (get80211val(s, IEEE80211_IOC_LDPC, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_LDPC, &val) != -1) { switch (val) { case 0: LINE_CHECK("-ldpc"); @@ -5373,7 +5703,7 @@ end: break; } } - if (get80211val(s, IEEE80211_IOC_UAPSD, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_UAPSD, &val) != -1) { switch (val) { case 0: LINE_CHECK("-uapsd"); @@ -5386,30 +5716,31 @@ end: } if (IEEE80211_IS_CHAN_VHT(c) || verbose) { - getvhtconf(s); - if (vhtconf & IEEE80211_FVHT_VHT) + getvhtconf(ctx); + if (vhtconf & IEEE80211_FVHT_VHT) { LINE_CHECK("vht"); - else + + if (vhtconf & IEEE80211_FVHT_USEVHT40) + LINE_CHECK("vht40"); + else + LINE_CHECK("-vht40"); + if (vhtconf & IEEE80211_FVHT_USEVHT80) + LINE_CHECK("vht80"); + else + LINE_CHECK("-vht80"); + if (vhtconf & IEEE80211_FVHT_USEVHT160) + LINE_CHECK("vht160"); + else + LINE_CHECK("-vht160"); + if (vhtconf & IEEE80211_FVHT_USEVHT80P80) + LINE_CHECK("vht80p80"); + else + LINE_CHECK("-vht80p80"); + } else if (verbose) LINE_CHECK("-vht"); - if (vhtconf & IEEE80211_FVHT_USEVHT40) - LINE_CHECK("vht40"); - else - LINE_CHECK("-vht40"); - if (vhtconf & IEEE80211_FVHT_USEVHT80) - LINE_CHECK("vht80"); - else - LINE_CHECK("-vht80"); - if (vhtconf & IEEE80211_FVHT_USEVHT160) - LINE_CHECK("vht160"); - else - LINE_CHECK("-vht160"); - if (vhtconf & IEEE80211_FVHT_USEVHT80P80) - LINE_CHECK("vht80p80"); - else - LINE_CHECK("-vht80p80"); } - if (get80211val(s, IEEE80211_IOC_WME, &wme) != -1) { + if (get80211val(ctx, IEEE80211_IOC_WME, &wme) != -1) { if (wme) LINE_CHECK("wme"); else if (verbose) @@ -5417,26 +5748,26 @@ end: } else wme = 0; - if (get80211val(s, IEEE80211_IOC_BURST, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_BURST, &val) != -1) { if (val) LINE_CHECK("burst"); else if (verbose) LINE_CHECK("-burst"); } - if (get80211val(s, IEEE80211_IOC_FF, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_FF, &val) != -1) { if (val) LINE_CHECK("ff"); else if (verbose) LINE_CHECK("-ff"); } - if (get80211val(s, IEEE80211_IOC_TURBOP, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_TURBOP, &val) != -1) { if (val) LINE_CHECK("dturbo"); else if (verbose) LINE_CHECK("-dturbo"); } - if (get80211val(s, IEEE80211_IOC_DWDS, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_DWDS, &val) != -1) { if (val) LINE_CHECK("dwds"); else if (verbose) @@ -5444,41 +5775,41 @@ end: } if (opmode == IEEE80211_M_HOSTAP) { - if (get80211val(s, IEEE80211_IOC_HIDESSID, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_HIDESSID, &val) != -1) { if (val) LINE_CHECK("hidessid"); else if (verbose) LINE_CHECK("-hidessid"); } - if (get80211val(s, IEEE80211_IOC_APBRIDGE, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_APBRIDGE, &val) != -1) { if (!val) LINE_CHECK("-apbridge"); else if (verbose) LINE_CHECK("apbridge"); } - if (get80211val(s, IEEE80211_IOC_DTIM_PERIOD, &val) != -1) + if (get80211val(ctx, IEEE80211_IOC_DTIM_PERIOD, &val) != -1) LINE_CHECK("dtimperiod %u", val); - if (get80211val(s, IEEE80211_IOC_DOTH, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_DOTH, &val) != -1) { if (!val) LINE_CHECK("-doth"); else if (verbose) LINE_CHECK("doth"); } - if (get80211val(s, IEEE80211_IOC_DFS, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_DFS, &val) != -1) { if (!val) LINE_CHECK("-dfs"); else if (verbose) LINE_CHECK("dfs"); } - if (get80211val(s, IEEE80211_IOC_INACTIVITY, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_INACTIVITY, &val) != -1) { if (!val) LINE_CHECK("-inact"); else if (verbose) LINE_CHECK("inact"); } } else { - if (get80211val(s, IEEE80211_IOC_ROAMING, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_ROAMING, &val) != -1) { if (val != IEEE80211_ROAMING_AUTO || verbose) { switch (val) { case IEEE80211_ROAMING_DEVICE: @@ -5500,15 +5831,15 @@ end: } if (opmode == IEEE80211_M_AHDEMO) { - if (get80211val(s, IEEE80211_IOC_TDMA_SLOT, &val) != -1) + if (get80211val(ctx, IEEE80211_IOC_TDMA_SLOT, &val) != -1) LINE_CHECK("tdmaslot %u", val); - if (get80211val(s, IEEE80211_IOC_TDMA_SLOTCNT, &val) != -1) + if (get80211val(ctx, IEEE80211_IOC_TDMA_SLOTCNT, &val) != -1) LINE_CHECK("tdmaslotcnt %u", val); - if (get80211val(s, IEEE80211_IOC_TDMA_SLOTLEN, &val) != -1) + if (get80211val(ctx, IEEE80211_IOC_TDMA_SLOTLEN, &val) != -1) LINE_CHECK("tdmaslotlen %u", val); - if (get80211val(s, IEEE80211_IOC_TDMA_BINTERVAL, &val) != -1) + if (get80211val(ctx, IEEE80211_IOC_TDMA_BINTERVAL, &val) != -1) LINE_CHECK("tdmabintval %u", val); - } else if (get80211val(s, IEEE80211_IOC_BEACON_INTERVAL, &val) != -1) { + } else if (get80211val(ctx, IEEE80211_IOC_BEACON_INTERVAL, &val) != -1) { /* XXX default define not visible */ if (val != 100 || verbose) LINE_CHECK("bintval %u", val); @@ -5516,42 +5847,42 @@ end: if (wme && verbose) { LINE_BREAK(); - list_wme(s); + list_wme(ctx); } if (opmode == IEEE80211_M_MBSS) { - if (get80211val(s, IEEE80211_IOC_MESH_TTL, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_MESH_TTL, &val) != -1) { LINE_CHECK("meshttl %u", val); } - if (get80211val(s, IEEE80211_IOC_MESH_AP, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_MESH_AP, &val) != -1) { if (val) LINE_CHECK("meshpeering"); else LINE_CHECK("-meshpeering"); } - if (get80211val(s, IEEE80211_IOC_MESH_FWRD, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_MESH_FWRD, &val) != -1) { if (val) LINE_CHECK("meshforward"); else LINE_CHECK("-meshforward"); } - if (get80211val(s, IEEE80211_IOC_MESH_GATE, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_MESH_GATE, &val) != -1) { if (val) LINE_CHECK("meshgate"); else LINE_CHECK("-meshgate"); } - if (get80211len(s, IEEE80211_IOC_MESH_PR_METRIC, data, 12, + if (get80211len(ctx, IEEE80211_IOC_MESH_PR_METRIC, data, 12, &len) != -1) { data[len] = '\0'; LINE_CHECK("meshmetric %s", data); } - if (get80211len(s, IEEE80211_IOC_MESH_PR_PATH, data, 12, + if (get80211len(ctx, IEEE80211_IOC_MESH_PR_PATH, data, 12, &len) != -1) { data[len] = '\0'; LINE_CHECK("meshpath %s", data); } - if (get80211val(s, IEEE80211_IOC_HWMP_ROOTMODE, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_HWMP_ROOTMODE, &val) != -1) { switch (val) { case IEEE80211_HWMP_ROOTMODE_DISABLED: LINE_CHECK("hwmprootmode DISABLED"); @@ -5570,14 +5901,14 @@ end: break; } } - if (get80211val(s, IEEE80211_IOC_HWMP_MAXHOPS, &val) != -1) { + if (get80211val(ctx, IEEE80211_IOC_HWMP_MAXHOPS, &val) != -1) { LINE_CHECK("hwmpmaxhops %u", val); } } LINE_BREAK(); - if (getdevicename(s, data, sizeof(data), &len) < 0) + if (getdevicename(ctx, data, sizeof(data), &len) < 0) return; LINE_CHECK("parent interface: %s", data); @@ -5585,32 +5916,32 @@ end: } static int -get80211(int s, int type, void *data, int len) +get80211(if_ctx *ctx, int type, void *data, int len) { - return (lib80211_get80211(s, name, type, data, len)); + return (lib80211_get80211(ctx->io_s, ctx->ifname, type, data, len)); } static int -get80211len(int s, int type, void *data, int len, int *plen) +get80211len(if_ctx *ctx, int type, void *data, int len, int *plen) { - return (lib80211_get80211len(s, name, type, data, len, plen)); + return (lib80211_get80211len(ctx->io_s, ctx->ifname, type, data, len, plen)); } static int -get80211val(int s, int type, int *val) +get80211val(if_ctx *ctx, int type, int *val) { - return (lib80211_get80211val(s, name, type, val)); + return (lib80211_get80211val(ctx->io_s, ctx->ifname, type, val)); } static void -set80211(int s, int type, int val, int len, void *data) +set80211(if_ctx *ctx, int type, int val, int len, void *data) { int ret; - ret = lib80211_set80211(s, name, type, val, len, data); + ret = lib80211_set80211(ctx->io_s, ctx->ifname, type, val, len, data); if (ret < 0) err(1, "SIOCS80211"); } @@ -5703,7 +6034,7 @@ print_string(const u_int8_t *buf, int len) } static void -setdefregdomain(int s) +setdefregdomain(if_ctx *ctx) { struct regdata *rdp = getregdata(); const struct regdomain *rd; @@ -5714,7 +6045,7 @@ setdefregdomain(int s) regdomain.country != CTRY_DEFAULT) return; - getregdomain(s); + getregdomain(ctx); /* Check if it was already set by the driver. */ if (regdomain.regdomain != 0 || @@ -5731,9 +6062,9 @@ setdefregdomain(int s) defaultcountry(rd); /* Send changes to net80211. */ - setregdomain_cb(s, ®domain); + setregdomain_cb(ctx, ®domain); - /* Cleanup (so it can be overriden by subsequent parameters). */ + /* Cleanup (so it can be overridden by subsequent parameters). */ regdomain.regdomain = 0; regdomain.country = CTRY_DEFAULT; regdomain.isocc[0] = 0; @@ -5748,10 +6079,9 @@ static struct ieee80211_clone_params params = { }; static void -wlan_create(int s, struct ifreq *ifr) +wlan_create(if_ctx *ctx, struct ifreq *ifr) { static const uint8_t zerobssid[IEEE80211_ADDR_LEN]; - char orig_name[IFNAMSIZ]; if (params.icp_parent[0] == '\0') errx(1, "must specify a parent device (wlandev) when creating " @@ -5760,25 +6090,19 @@ wlan_create(int s, struct ifreq *ifr) memcmp(params.icp_bssid, zerobssid, sizeof(zerobssid)) == 0) errx(1, "no bssid specified for WDS (use wlanbssid)"); ifr->ifr_data = (caddr_t) ¶ms; - ioctl_ifcreate(s, ifr); - - /* XXX preserve original name for ifclonecreate(). */ - strlcpy(orig_name, name, sizeof(orig_name)); - strlcpy(name, ifr->ifr_name, sizeof(name)); + ifcreate_ioctl(ctx, ifr); - setdefregdomain(s); - - strlcpy(name, orig_name, sizeof(name)); + setdefregdomain(ctx); } -static -DECL_CMD_FUNC(set80211clone_wlandev, arg, d) +static void +set80211clone_wlandev(if_ctx *ctx __unused, const char *arg, int dummy __unused) { strlcpy(params.icp_parent, arg, IFNAMSIZ); } -static -DECL_CMD_FUNC(set80211clone_wlanbssid, arg, d) +static void +set80211clone_wlanbssid(if_ctx *ctx __unused, const char *arg, int dummy __unused) { const struct ether_addr *ea; @@ -5788,8 +6112,8 @@ DECL_CMD_FUNC(set80211clone_wlanbssid, arg, d) memcpy(params.icp_bssid, ea->octet, IEEE80211_ADDR_LEN); } -static -DECL_CMD_FUNC(set80211clone_wlanaddr, arg, d) +static void +set80211clone_wlanaddr(if_ctx *ctx __unused, const char *arg, int dummy __unused) { const struct ether_addr *ea; @@ -5800,8 +6124,8 @@ DECL_CMD_FUNC(set80211clone_wlanaddr, arg, d) params.icp_flags |= IEEE80211_CLONE_MACADDR; } -static -DECL_CMD_FUNC(set80211clone_wlanmode, arg, d) +static void +set80211clone_wlanmode(if_ctx *ctx, const char *arg, int dummy __unused) { #define iseq(a,b) (strncasecmp(a,b,sizeof(b)-1) == 0) if (iseq(arg, "sta")) @@ -5822,12 +6146,12 @@ DECL_CMD_FUNC(set80211clone_wlanmode, arg, d) } else if (iseq(arg, "mesh") || iseq(arg, "mp")) /* mesh point */ params.icp_opmode = IEEE80211_M_MBSS; else - errx(1, "Don't know to create %s for %s", arg, name); + errx(1, "Don't know to create %s for %s", arg, ctx->ifname); #undef iseq } static void -set80211clone_beacons(const char *val, int d, int s, const struct afswtch *rafp) +set80211clone_beacons(if_ctx *ctx __unused, const char *val __unused, int d) { /* NB: inverted sense */ if (d) @@ -5837,7 +6161,7 @@ set80211clone_beacons(const char *val, int d, int s, const struct afswtch *rafp) } static void -set80211clone_bssid(const char *val, int d, int s, const struct afswtch *rafp) +set80211clone_bssid(if_ctx *ctx __unused, const char *val __unused, int d) { if (d) params.icp_flags |= IEEE80211_CLONE_BSSID; @@ -5846,7 +6170,7 @@ set80211clone_bssid(const char *val, int d, int s, const struct afswtch *rafp) } static void -set80211clone_wdslegacy(const char *val, int d, int s, const struct afswtch *rafp) +set80211clone_wdslegacy(if_ctx *ctx __unused, const char *val __unused, int d) { if (d) params.icp_flags |= IEEE80211_CLONE_WDSLEGACY; @@ -6007,7 +6331,7 @@ static struct cmd ieee80211_cmds[] = { DEF_CMD("ht", 3, set80211htconf), /* NB: 20+40 */ DEF_CMD("-ht", 0, set80211htconf), DEF_CMD("vht", IEEE80211_FVHT_VHT, set80211vhtconf), - DEF_CMD("-vht", 0, set80211vhtconf), + DEF_CMD("-vht", -IEEE80211_FVHT_VHT, set80211vhtconf), DEF_CMD("vht40", IEEE80211_FVHT_USEVHT40, set80211vhtconf), DEF_CMD("-vht40", -IEEE80211_FVHT_USEVHT40, set80211vhtconf), DEF_CMD("vht80", IEEE80211_FVHT_USEVHT80, set80211vhtconf), @@ -6016,6 +6340,12 @@ static struct cmd ieee80211_cmds[] = { DEF_CMD("-vht160", -IEEE80211_FVHT_USEVHT160, set80211vhtconf), DEF_CMD("vht80p80", IEEE80211_FVHT_USEVHT80P80, set80211vhtconf), DEF_CMD("-vht80p80", -IEEE80211_FVHT_USEVHT80P80, set80211vhtconf), + DEF_CMD("vhtstbctx", IEEE80211_FVHT_STBC_TX, set80211vhtconf), + DEF_CMD("-vhtstbctx", -IEEE80211_FVHT_STBC_TX, set80211vhtconf), + DEF_CMD("vhtstbcrx", IEEE80211_FVHT_STBC_RX, set80211vhtconf), + DEF_CMD("-vhtstbcrx", -IEEE80211_FVHT_STBC_RX, set80211vhtconf), + DEF_CMD("vhtstbc", (IEEE80211_FVHT_STBC_TX|IEEE80211_FVHT_STBC_RX), set80211vhtconf), + DEF_CMD("-vhtstbc", -(IEEE80211_FVHT_STBC_TX|IEEE80211_FVHT_STBC_RX), set80211vhtconf), DEF_CMD("rifs", 1, set80211rifs), DEF_CMD("-rifs", 0, set80211rifs), DEF_CMD("smps", IEEE80211_HTCAP_SMPS_ENA, set80211smps), @@ -6065,9 +6395,7 @@ static struct afswtch af_ieee80211 = { static __constructor void ieee80211_ctor(void) { - int i; - - for (i = 0; i < nitems(ieee80211_cmds); i++) + for (size_t i = 0; i < nitems(ieee80211_cmds); i++) cmd_register(&ieee80211_cmds[i]); af_register(&af_ieee80211); clone_setdefcallback_prefix("wlan", wlan_create); diff --git a/sbin/ifconfig/ifipsec.c b/sbin/ifconfig/ifipsec.c index 0e615a27e205..b8ab38d6165a 100644 --- a/sbin/ifconfig/ifipsec.c +++ b/sbin/ifconfig/ifipsec.c @@ -25,9 +25,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #include <sys/param.h> #include <sys/ioctl.h> #include <sys/socket.h> @@ -51,30 +48,29 @@ __FBSDID("$FreeBSD$"); #include "ifconfig.h" static void -ipsec_status(int s) +ipsec_status(if_ctx *ctx) { uint32_t reqid; + struct ifreq ifr = { .ifr_data = (caddr_t)&reqid }; - ifr.ifr_data = (caddr_t)&reqid; - if (ioctl(s, IPSECGREQID, &ifr) == -1) + if (ioctl_ctx_ifr(ctx, IPSECGREQID, &ifr) == -1) return; printf("\treqid: %u\n", reqid); } -static -DECL_CMD_FUNC(setreqid, val, arg) +static void +setreqid(if_ctx *ctx, const char *val, int dummy __unused) { char *ep; uint32_t v; + struct ifreq ifr = { .ifr_data = (caddr_t)&v }; v = strtoul(val, &ep, 0); if (*ep != '\0') { warn("Invalid reqid value %s", val); return; } - strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); - ifr.ifr_data = (char *)&v; - if (ioctl(s, IPSECSREQID, &ifr) == -1) { + if (ioctl_ctx_ifr(ctx, IPSECSREQID, &ifr) == -1) { warn("ioctl(IPSECSREQID)"); return; } diff --git a/sbin/ifconfig/iflagg.c b/sbin/ifconfig/iflagg.c index 48d7450076a9..4de437d25bd9 100644 --- a/sbin/ifconfig/iflagg.c +++ b/sbin/ifconfig/iflagg.c @@ -1,11 +1,6 @@ /*- */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <sys/param.h> #include <sys/ioctl.h> #include <sys/socket.h> @@ -39,12 +34,11 @@ static struct iflaggparam params = { static char lacpbuf[120]; /* LACP peer '[(a,a,a),(p,p,p)]' */ static void -setlaggport(const char *val, int d, int s, const struct afswtch *afp) +setlaggport(if_ctx *ctx, const char *val, int dummy __unused) { - struct lagg_reqport rp; + struct lagg_reqport rp = {}; - bzero(&rp, sizeof(rp)); - strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname)); + strlcpy(rp.rp_ifname, ctx->ifname, sizeof(rp.rp_ifname)); strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname)); /* @@ -53,37 +47,35 @@ setlaggport(const char *val, int d, int s, const struct afswtch *afp) * * Don't error at all if the port is already in the lagg. */ - if (ioctl(s, SIOCSLAGGPORT, &rp) && errno != EEXIST) { + if (ioctl_ctx(ctx, SIOCSLAGGPORT, &rp) && errno != EEXIST) { warnx("%s %s: SIOCSLAGGPORT: %s", - name, val, strerror(errno)); + ctx->ifname, val, strerror(errno)); exit_code = 1; } } static void -unsetlaggport(const char *val, int d, int s, const struct afswtch *afp) +unsetlaggport(if_ctx *ctx, const char *val, int dummy __unused) { - struct lagg_reqport rp; + struct lagg_reqport rp = {}; - bzero(&rp, sizeof(rp)); - strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname)); + strlcpy(rp.rp_ifname, ctx->ifname, sizeof(rp.rp_ifname)); strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname)); - if (ioctl(s, SIOCSLAGGDELPORT, &rp)) + if (ioctl_ctx(ctx, SIOCSLAGGDELPORT, &rp)) err(1, "SIOCSLAGGDELPORT"); } static void -setlaggproto(const char *val, int d, int s, const struct afswtch *afp) +setlaggproto(if_ctx *ctx, const char *val, int dummy __unused) { struct lagg_protos lpr[] = LAGG_PROTOS; struct lagg_reqall ra; - int i; bzero(&ra, sizeof(ra)); ra.ra_proto = LAGG_PROTO_MAX; - for (i = 0; i < nitems(lpr); i++) { + for (size_t i = 0; i < nitems(lpr); i++) { if (strcmp(val, lpr[i].lpr_name) == 0) { ra.ra_proto = lpr[i].lpr_proto; break; @@ -92,49 +84,46 @@ setlaggproto(const char *val, int d, int s, const struct afswtch *afp) if (ra.ra_proto == LAGG_PROTO_MAX) errx(1, "Invalid aggregation protocol: %s", val); - strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname)); - if (ioctl(s, SIOCSLAGG, &ra) != 0) + strlcpy(ra.ra_ifname, ctx->ifname, sizeof(ra.ra_ifname)); + if (ioctl_ctx(ctx, SIOCSLAGG, &ra) != 0) err(1, "SIOCSLAGG"); } static void -setlaggflowidshift(const char *val, int d, int s, const struct afswtch *afp) +setlaggflowidshift(if_ctx *ctx, const char *val, int dummy __unused) { - struct lagg_reqopts ro; + struct lagg_reqopts ro = {}; - bzero(&ro, sizeof(ro)); ro.ro_opts = LAGG_OPT_FLOWIDSHIFT; - strlcpy(ro.ro_ifname, name, sizeof(ro.ro_ifname)); + strlcpy(ro.ro_ifname, ctx->ifname, sizeof(ro.ro_ifname)); ro.ro_flowid_shift = (int)strtol(val, NULL, 10); if (ro.ro_flowid_shift & ~LAGG_OPT_FLOWIDSHIFT_MASK) errx(1, "Invalid flowid_shift option: %s", val); - if (ioctl(s, SIOCSLAGGOPTS, &ro) != 0) + if (ioctl_ctx(ctx, SIOCSLAGGOPTS, &ro) != 0) err(1, "SIOCSLAGGOPTS"); } static void -setlaggrr_limit(const char *val, int d, int s, const struct afswtch *afp) +setlaggrr_limit(if_ctx *ctx, const char *val, int dummy __unused) { - struct lagg_reqopts ro; + struct lagg_reqopts ro = {}; - bzero(&ro, sizeof(ro)); - strlcpy(ro.ro_ifname, name, sizeof(ro.ro_ifname)); + strlcpy(ro.ro_ifname, ctx->ifname, sizeof(ro.ro_ifname)); ro.ro_opts = LAGG_OPT_RR_LIMIT; ro.ro_bkt = (uint32_t)strtoul(val, NULL, 10); if (ro.ro_bkt == 0) errx(1, "Invalid round-robin stride: %s", val); - if (ioctl(s, SIOCSLAGGOPTS, &ro) != 0) + if (ioctl_ctx(ctx, SIOCSLAGGOPTS, &ro) != 0) err(1, "SIOCSLAGGOPTS"); } static void -setlaggsetopt(const char *val, int d, int s, const struct afswtch *afp) +setlaggsetopt(if_ctx *ctx, const char *val __unused, int d) { - struct lagg_reqopts ro; + struct lagg_reqopts ro = {}; - bzero(&ro, sizeof(ro)); ro.ro_opts = d; switch (ro.ro_opts) { case LAGG_OPT_USE_FLOWID: @@ -153,14 +142,14 @@ setlaggsetopt(const char *val, int d, int s, const struct afswtch *afp) default: err(1, "Invalid lagg option"); } - strlcpy(ro.ro_ifname, name, sizeof(ro.ro_ifname)); + strlcpy(ro.ro_ifname, ctx->ifname, sizeof(ro.ro_ifname)); - if (ioctl(s, SIOCSLAGGOPTS, &ro) != 0) + if (ioctl_ctx(ctx, SIOCSLAGGOPTS, &ro) != 0) err(1, "SIOCSLAGGOPTS"); } static void -setlagghash(const char *val, int d, int s, const struct afswtch *afp) +setlagghash(if_ctx *ctx, const char *val, int dummy __unused) { struct lagg_reqflags rf; char *str, *tmp, *tok; @@ -182,8 +171,8 @@ setlagghash(const char *val, int d, int s, const struct afswtch *afp) if (rf.rf_flags == 0) errx(1, "No lagghash options supplied"); - strlcpy(rf.rf_ifname, name, sizeof(rf.rf_ifname)); - if (ioctl(s, SIOCSLAGGHASH, &rf)) + strlcpy(rf.rf_ifname, ctx->ifname, sizeof(rf.rf_ifname)); + if (ioctl_ctx(ctx, SIOCSLAGGHASH, &rf)) err(1, "SIOCSLAGGHASH"); } @@ -216,7 +205,7 @@ lacp_format_peer(struct lacp_opreq *req, const char *sep) } static void -lagg_status(int s) +lagg_status(if_ctx *ctx) { struct lagg_protos protos[] = LAGG_PROTOS; struct ifconfig_lagg_status *lagg; @@ -226,8 +215,9 @@ lagg_status(int s) struct lagg_reqport *ports; struct lacp_opreq *lp; const char *proto; + const int verbose = ctx->args->verbose; - if (ifconfig_lagg_get_lagg_status(lifh, name, &lagg) == -1) + if (ifconfig_lagg_get_lagg_status(lifh, ctx->ifname, &lagg) == -1) return; ra = lagg->ra; @@ -279,7 +269,7 @@ lagg_status(int s) } } - for (size_t i = 0; i < ra->ra_ports; ++i) { + for (size_t i = 0; i < (size_t)ra->ra_ports; ++i) { lp = &ports[i].rp_lacpreq; printf("\tlaggport: %s ", ports[i].rp_portname); printb("flags", ports[i].rp_flags, LAGG_PORT_BITS); @@ -294,13 +284,12 @@ lagg_status(int s) ifconfig_lagg_free_lagg_status(lagg); } -static -DECL_CMD_FUNC(setlaggtype, arg, d) +static void +setlaggtype(if_ctx *ctx __unused, const char *arg, int dummy __unused) { static const struct lagg_types lt[] = LAGG_TYPES; - int i; - for (i = 0; i < nitems(lt); i++) { + for (size_t i = 0; i < nitems(lt); i++) { if (strcmp(arg, lt[i].lt_name) == 0) { params.lagg_type = lt[i].lt_value; return; @@ -310,10 +299,10 @@ DECL_CMD_FUNC(setlaggtype, arg, d) } static void -lagg_create(int s, struct ifreq *ifr) +lagg_create(if_ctx *ctx, struct ifreq *ifr) { ifr->ifr_data = (caddr_t) ¶ms; - ioctl_ifcreate(s, ifr); + ifcreate_ioctl(ctx, ifr); } static struct cmd lagg_cmds[] = { @@ -346,9 +335,7 @@ static struct afswtch af_lagg = { static __constructor void lagg_ctor(void) { - int i; - - for (i = 0; i < nitems(lagg_cmds); i++) + for (size_t i = 0; i < nitems(lagg_cmds); i++) cmd_register(&lagg_cmds[i]); af_register(&af_lagg); clone_setdefcallback_prefix("lagg", lagg_create); diff --git a/sbin/ifconfig/ifmac.c b/sbin/ifconfig/ifmac.c index 31f4e970951c..278d2e79592f 100644 --- a/sbin/ifconfig/ifmac.c +++ b/sbin/ifconfig/ifmac.c @@ -32,8 +32,6 @@ * 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. - * - * $FreeBSD$ */ #include <sys/param.h> @@ -52,19 +50,19 @@ #include "ifconfig.h" static void -maclabel_status(int s) +maclabel_status(if_ctx *ctx) { struct ifreq ifr; mac_t label; char *label_text; memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + strlcpy(ifr.ifr_name, ctx->ifname, sizeof(ifr.ifr_name)); if (mac_prepare_ifnet_label(&label) == -1) return; ifr.ifr_ifru.ifru_data = (void *)label; - if (ioctl(s, SIOCGIFMAC, &ifr) == -1) + if (ioctl_ctx(ctx, SIOCGIFMAC, &ifr) == -1) goto mac_free; @@ -80,7 +78,7 @@ mac_free: } static void -setifmaclabel(const char *val, int d, int s, const struct afswtch *rafp) +setifmaclabel(if_ctx *ctx, const char *val, int d __unused) { struct ifreq ifr; mac_t label; @@ -92,10 +90,10 @@ setifmaclabel(const char *val, int d, int s, const struct afswtch *rafp) } memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + strlcpy(ifr.ifr_name, ctx->ifname, sizeof(ifr.ifr_name)); ifr.ifr_ifru.ifru_data = (void *)label; - error = ioctl(s, SIOCSIFMAC, &ifr); + error = ioctl(ctx->io_s, SIOCSIFMAC, &ifr); mac_free(label); if (error == -1) perror("setifmac"); diff --git a/sbin/ifconfig/ifmedia.c b/sbin/ifconfig/ifmedia.c index aacf34a13248..8f355bc5187f 100644 --- a/sbin/ifconfig/ifmedia.c +++ b/sbin/ifconfig/ifmedia.c @@ -1,5 +1,4 @@ /* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */ -/* $FreeBSD$ */ /*- * SPDX-License-Identifier: BSD-4-Clause @@ -90,7 +89,7 @@ #include "ifconfig.h" -static void domediaopt(const char *, bool, int); +static void domediaopt(if_ctx *, const char *, bool); static ifmedia_t get_media_subtype(ifmedia_t, const char *); static ifmedia_t get_media_mode(ifmedia_t, const char *); static ifmedia_t get_media_options(ifmedia_t, const char *); @@ -98,15 +97,15 @@ static void print_media(ifmedia_t, bool); static void print_media_ifconfig(ifmedia_t); static void -media_status(int s) +media_status(if_ctx *ctx) { struct ifmediareq *ifmr; - if (ifconfig_media_get_mediareq(lifh, name, &ifmr) == -1) + if (ifconfig_media_get_mediareq(lifh, ctx->ifname, &ifmr) == -1) return; if (ifmr->ifm_count == 0) { - warnx("%s: no media types?", name); + warnx("%s: no media types?", ctx->ifname); goto free; } @@ -128,7 +127,7 @@ media_status(int s) status = ifconfig_media_get_status(ifmr); printf("\tstatus: %s", status); if (strcmp(status, "no carrier") == 0 && - ifconfig_media_get_downreason(lifh, name, &ifdr) == 0) { + ifconfig_media_get_downreason(lifh, ctx->ifname, &ifdr) == 0) { switch (ifdr.ifdr_reason) { case IFDR_REASON_MSG: printf(" (%s)", ifdr.ifdr_msg); @@ -144,9 +143,9 @@ media_status(int s) putchar('\n'); } - if (supmedia) { + if (ctx->args->supmedia) { printf("\tsupported media:\n"); - for (size_t i = 0; i < ifmr->ifm_count; ++i) { + for (int i = 0; i < ifmr->ifm_count; ++i) { printf("\t\t"); print_media_ifconfig(ifmr->ifm_ulist[i]); putchar('\n'); @@ -157,32 +156,33 @@ free: } struct ifmediareq * -ifmedia_getstate(void) +ifmedia_getstate(if_ctx *ctx) { static struct ifmediareq *ifmr = NULL; if (ifmr != NULL) return (ifmr); - if (ifconfig_media_get_mediareq(lifh, name, &ifmr) == -1) + if (ifconfig_media_get_mediareq(lifh, ctx->ifname, &ifmr) == -1) errc(1, ifconfig_err_errno(lifh), - "%s: ifconfig_media_get_mediareq", name); + "%s: ifconfig_media_get_mediareq", ctx->ifname); if (ifmr->ifm_count == 0) - errx(1, "%s: no media types?", name); + errx(1, "%s: no media types?", ctx->ifname); return (ifmr); } static void -setifmediacallback(int s, void *arg) +setifmediacallback(if_ctx *ctx, void *arg) { struct ifmediareq *ifmr = (struct ifmediareq *)arg; static bool did_it = false; + struct ifreq ifr = {}; if (!did_it) { ifr.ifr_media = ifmr->ifm_current; - if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) + if (ioctl_ctx_ifr(ctx, SIOCSIFMEDIA, &ifr) < 0) err(1, "SIOCSIFMEDIA (media)"); free(ifmr); did_it = true; @@ -190,12 +190,12 @@ setifmediacallback(int s, void *arg) } static void -setmedia(const char *val, int d, int s, const struct afswtch *afp) +setmedia(if_ctx *ctx, const char *val, int d __unused) { struct ifmediareq *ifmr; int subtype; - ifmr = ifmedia_getstate(); + ifmr = ifmedia_getstate(ctx); /* * We are primarily concerned with the top-level type. @@ -208,86 +208,77 @@ setmedia(const char *val, int d, int s, const struct afswtch *afp) */ subtype = get_media_subtype(ifmr->ifm_ulist[0], val); - strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); - ifr.ifr_media = (ifmr->ifm_current & IFM_IMASK) | + ifmr->ifm_current = (ifmr->ifm_current & IFM_IMASK) | IFM_TYPE(ifmr->ifm_ulist[0]) | subtype; - ifmr->ifm_current = ifr.ifr_media; callback_register(setifmediacallback, (void *)ifmr); } static void -setmediaopt(const char *val, int d, int s, const struct afswtch *afp) +setmediaopt(if_ctx *ctx, const char *val, int d __unused) { - domediaopt(val, false, s); + domediaopt(ctx, val, false); } static void -unsetmediaopt(const char *val, int d, int s, const struct afswtch *afp) +unsetmediaopt(if_ctx *ctx, const char *val, int d __unused) { - domediaopt(val, true, s); + domediaopt(ctx, val, true); } static void -domediaopt(const char *val, bool clear, int s) +domediaopt(if_ctx *ctx, const char *val, bool clear) { struct ifmediareq *ifmr; ifmedia_t options; - ifmr = ifmedia_getstate(); + ifmr = ifmedia_getstate(ctx); options = get_media_options(ifmr->ifm_ulist[0], val); - strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); - ifr.ifr_media = ifmr->ifm_current; if (clear) - ifr.ifr_media &= ~options; + ifmr->ifm_current &= ~options; else { if (options & IFM_HDX) { - ifr.ifr_media &= ~IFM_FDX; + ifmr->ifm_current &= ~IFM_FDX; options &= ~IFM_HDX; } - ifr.ifr_media |= options; + ifmr->ifm_current |= options; } - ifmr->ifm_current = ifr.ifr_media; callback_register(setifmediacallback, (void *)ifmr); } static void -setmediainst(const char *val, int d, int s, const struct afswtch *afp) +setmediainst(if_ctx *ctx, const char *val, int d __unused) { struct ifmediareq *ifmr; int inst; - ifmr = ifmedia_getstate(); + ifmr = ifmedia_getstate(ctx); inst = atoi(val); if (inst < 0 || inst > (int)IFM_INST_MAX) errx(1, "invalid media instance: %s", val); - strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); - ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT; + ifmr->ifm_current = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT; - ifmr->ifm_current = ifr.ifr_media; callback_register(setifmediacallback, (void *)ifmr); } static void -setmediamode(const char *val, int d, int s, const struct afswtch *afp) +setmediamode(if_ctx *ctx, const char *val, int d __unused) { struct ifmediareq *ifmr; int mode; - ifmr = ifmedia_getstate(); + ifmr = ifmedia_getstate(ctx); mode = get_media_mode(ifmr->ifm_ulist[0], val); - strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); - ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode; + ifmr->ifm_current = (ifmr->ifm_current & ~IFM_MMASK) | mode; - ifmr->ifm_current = ifr.ifr_media; callback_register(setifmediacallback, (void *)ifmr); } @@ -486,9 +477,7 @@ static struct afswtch af_media = { static __constructor void ifmedia_ctor(void) { - size_t i; - - for (i = 0; i < nitems(media_cmds); i++) + for (size_t i = 0; i < nitems(media_cmds); i++) cmd_register(&media_cmds[i]); af_register(&af_media); } diff --git a/sbin/ifconfig/ifpfsync.c b/sbin/ifconfig/ifpfsync.c index e3b5e6a30bbc..264b1ecd5b56 100644 --- a/sbin/ifconfig/ifpfsync.c +++ b/sbin/ifconfig/ifpfsync.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2003 Ryan McBride. All rights reserved. * Copyright (c) 2004 Max Laier. All rights reserved. @@ -24,12 +24,12 @@ * 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. - * - * $FreeBSD$ */ #include <sys/param.h> +#include <sys/errno.h> #include <sys/ioctl.h> +#include <sys/nv.h> #include <sys/socket.h> #include <net/if.h> @@ -48,169 +48,354 @@ #include "ifconfig.h" -void setpfsync_syncdev(const char *, int, int, const struct afswtch *); -void unsetpfsync_syncdev(const char *, int, int, const struct afswtch *); -void setpfsync_syncpeer(const char *, int, int, const struct afswtch *); -void unsetpfsync_syncpeer(const char *, int, int, const struct afswtch *); -void setpfsync_syncpeer(const char *, int, int, const struct afswtch *); -void setpfsync_maxupd(const char *, int, int, const struct afswtch *); -void setpfsync_defer(const char *, int, int, const struct afswtch *); -void pfsync_status(int); - -void -setpfsync_syncdev(const char *val, int d, int s, const struct afswtch *rafp) +static int +pfsync_do_ioctl(if_ctx *ctx, uint cmd, nvlist_t **nvl) +{ + void *data; + size_t nvlen; + struct ifreq ifr = {}; + + data = nvlist_pack(*nvl, &nvlen); + + ifr.ifr_cap_nv.buffer = malloc(IFR_CAP_NV_MAXBUFSIZE); + memcpy(ifr.ifr_cap_nv.buffer, data, nvlen); + ifr.ifr_cap_nv.buf_length = IFR_CAP_NV_MAXBUFSIZE; + ifr.ifr_cap_nv.length = nvlen; + free(data); + + if (ioctl_ctx_ifr(ctx, cmd, &ifr) == -1) { + free(ifr.ifr_cap_nv.buffer); + return -1; + } + + nvlist_destroy(*nvl); + *nvl = NULL; + + *nvl = nvlist_unpack(ifr.ifr_cap_nv.buffer, ifr.ifr_cap_nv.length, 0); + if (*nvl == NULL) { + free(ifr.ifr_cap_nv.buffer); + return (EIO); + } + + free(ifr.ifr_cap_nv.buffer); + return (errno); +} + +static nvlist_t * +pfsync_sockaddr_to_syncpeer_nvlist(struct sockaddr_storage *sa) { - struct pfsyncreq preq; + nvlist_t *nvl; + + nvl = nvlist_create(0); + if (nvl == NULL) { + return (nvl); + } - bzero((char *)&preq, sizeof(struct pfsyncreq)); - ifr.ifr_data = (caddr_t)&preq; + switch (sa->ss_family) { +#ifdef INET + case AF_INET: { + struct sockaddr_in *in = (struct sockaddr_in *)sa; + nvlist_add_number(nvl, "af", in->sin_family); + nvlist_add_binary(nvl, "address", in, sizeof(*in)); + break; + } +#endif +#ifdef INET6 + case AF_INET6: { + struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa; + nvlist_add_number(nvl, "af", in6->sin6_family); + nvlist_add_binary(nvl, "address", in6, sizeof(*in6)); + break; + } +#endif + default: + nvlist_add_number(nvl, "af", AF_UNSPEC); + nvlist_add_binary(nvl, "address", sa, sizeof(*sa)); + break; + } - if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) - err(1, "SIOCGETPFSYNC"); + return (nvl); +} - strlcpy(preq.pfsyncr_syncdev, val, sizeof(preq.pfsyncr_syncdev)); +static int +pfsync_syncpeer_nvlist_to_sockaddr(const nvlist_t *nvl, + struct sockaddr_storage *sa) +{ + int af; + +#if (!defined INET && !defined INET6) + (void)sa; +#endif + + if (!nvlist_exists_number(nvl, "af")) + return (EINVAL); + if (!nvlist_exists_binary(nvl, "address")) + return (EINVAL); + + af = nvlist_get_number(nvl, "af"); + + switch (af) { +#ifdef INET + case AF_INET: { + struct sockaddr_in *in = (struct sockaddr_in *)sa; + size_t len; + const void *addr = nvlist_get_binary(nvl, "address", &len); + in->sin_family = af; + if (len != sizeof(*in)) + return (EINVAL); + + memcpy(in, addr, sizeof(*in)); + break; + } +#endif +#ifdef INET6 + case AF_INET6: { + struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa; + size_t len; + const void *addr = nvlist_get_binary(nvl, "address", &len); + if (len != sizeof(*in6)) + return (EINVAL); + + memcpy(in6, addr, sizeof(*in6)); + break; + } +#endif + default: + return (EINVAL); + } - if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1) - err(1, "SIOCSETPFSYNC"); + return (0); } -/* ARGSUSED */ -void -unsetpfsync_syncdev(const char *val, int d, int s, const struct afswtch *rafp) +static void +setpfsync_syncdev(if_ctx *ctx, const char *val, int dummy __unused) { - struct pfsyncreq preq; + nvlist_t *nvl = nvlist_create(0); + + if (strlen(val) > IFNAMSIZ) + errx(1, "interface name %s is too long", val); - bzero((char *)&preq, sizeof(struct pfsyncreq)); - ifr.ifr_data = (caddr_t)&preq; + if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1) + err(1, "SIOCGETPFSYNCNV"); - if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) - err(1, "SIOCGETPFSYNC"); + if (nvlist_exists_string(nvl, "syncdev")) + nvlist_free_string(nvl, "syncdev"); - bzero((char *)&preq.pfsyncr_syncdev, sizeof(preq.pfsyncr_syncdev)); + nvlist_add_string(nvl, "syncdev", val); - if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1) - err(1, "SIOCSETPFSYNC"); + if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1) + err(1, "SIOCSETPFSYNCNV"); } -/* ARGSUSED */ -void -setpfsync_syncpeer(const char *val, int d, int s, const struct afswtch *rafp) +static void +unsetpfsync_syncdev(if_ctx *ctx, const char *val __unused, int dummy __unused) { - struct pfsyncreq preq; - struct addrinfo hints, *peerres; - int ecode; + nvlist_t *nvl = nvlist_create(0); + + if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1) + err(1, "SIOCGETPFSYNCNV"); + + if (nvlist_exists_string(nvl, "syncdev")) + nvlist_free_string(nvl, "syncdev"); + + nvlist_add_string(nvl, "syncdev", ""); + + if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1) + err(1, "SIOCSETPFSYNCNV"); +} - bzero((char *)&preq, sizeof(struct pfsyncreq)); - ifr.ifr_data = (caddr_t)&preq; +static void +setpfsync_syncpeer(if_ctx *ctx, const char *val, int dummy __unused) +{ + struct addrinfo *peerres; + struct sockaddr_storage addr; + int ecode; - if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) - err(1, "SIOCGETPFSYNC"); + nvlist_t *nvl = nvlist_create(0); - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1) + err(1, "SIOCGETPFSYNCNV"); - if ((ecode = getaddrinfo(val, NULL, &hints, &peerres)) != 0) + if ((ecode = getaddrinfo(val, NULL, NULL, &peerres)) != 0) errx(1, "error in parsing address string: %s", gai_strerror(ecode)); - if (peerres->ai_addr->sa_family != AF_INET) - errx(1, "only IPv4 addresses supported for the syncpeer"); + switch (peerres->ai_family) { +#ifdef INET + case AF_INET: { + struct sockaddr_in *sin = satosin(peerres->ai_addr); + + memcpy(&addr, sin, sizeof(*sin)); + break; + } +#endif +#ifdef INET6 + case AF_INET6: { + struct sockaddr_in6 *sin6 = satosin6(peerres->ai_addr); + + memcpy(&addr, sin6, sizeof(*sin6)); + break; + } +#endif + default: + errx(1, "syncpeer address %s not supported", val); + } + + if (nvlist_exists_nvlist(nvl, "syncpeer")) + nvlist_free_nvlist(nvl, "syncpeer"); - preq.pfsyncr_syncpeer.s_addr = ((struct sockaddr_in *) - peerres->ai_addr)->sin_addr.s_addr; + nvlist_add_nvlist(nvl, "syncpeer", + pfsync_sockaddr_to_syncpeer_nvlist(&addr)); - if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1) - err(1, "SIOCSETPFSYNC"); + if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1) + err(1, "SIOCSETPFSYNCNV"); + + nvlist_destroy(nvl); freeaddrinfo(peerres); } -/* ARGSUSED */ -void -unsetpfsync_syncpeer(const char *val, int d, int s, const struct afswtch *rafp) +static void +unsetpfsync_syncpeer(if_ctx *ctx, const char *val __unused, int dummy __unused) { - struct pfsyncreq preq; + struct sockaddr_storage addr; + memset(&addr, 0, sizeof(addr)); + + nvlist_t *nvl = nvlist_create(0); - bzero((char *)&preq, sizeof(struct pfsyncreq)); - ifr.ifr_data = (caddr_t)&preq; + if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1) + err(1, "SIOCGETPFSYNCNV"); - if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) - err(1, "SIOCGETPFSYNC"); + if (nvlist_exists_nvlist(nvl, "syncpeer")) + nvlist_free_nvlist(nvl, "syncpeer"); - preq.pfsyncr_syncpeer.s_addr = 0; + nvlist_add_nvlist(nvl, "syncpeer", + pfsync_sockaddr_to_syncpeer_nvlist(&addr)); - if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1) - err(1, "SIOCSETPFSYNC"); + if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1) + err(1, "SIOCSETPFSYNCNV"); + + nvlist_destroy(nvl); } -/* ARGSUSED */ -void -setpfsync_maxupd(const char *val, int d, int s, const struct afswtch *rafp) +static void +setpfsync_maxupd(if_ctx *ctx, const char *val, int dummy __unused) { - struct pfsyncreq preq; int maxupdates; + nvlist_t *nvl = nvlist_create(0); maxupdates = atoi(val); if ((maxupdates < 0) || (maxupdates > 255)) errx(1, "maxupd %s: out of range", val); - memset((char *)&preq, 0, sizeof(struct pfsyncreq)); - ifr.ifr_data = (caddr_t)&preq; + if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1) + err(1, "SIOCGETPFSYNCNV"); - if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) - err(1, "SIOCGETPFSYNC"); + nvlist_free_number(nvl, "maxupdates"); + nvlist_add_number(nvl, "maxupdates", maxupdates); - preq.pfsyncr_maxupdates = maxupdates; + if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1) + err(1, "SIOCSETPFSYNCNV"); - if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1) - err(1, "SIOCSETPFSYNC"); + nvlist_destroy(nvl); } -/* ARGSUSED */ -void -setpfsync_defer(const char *val, int d, int s, const struct afswtch *rafp) +static void +setpfsync_defer(if_ctx *ctx, const char *val __unused, int d) { - struct pfsyncreq preq; + nvlist_t *nvl = nvlist_create(0); + + if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1) + err(1, "SIOCGETPFSYNCNV"); - memset((char *)&preq, 0, sizeof(struct pfsyncreq)); - ifr.ifr_data = (caddr_t)&preq; + nvlist_free_number(nvl, "flags"); + nvlist_add_number(nvl, "flags", d ? PFSYNCF_DEFER : 0); - if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) - err(1, "SIOCGETPFSYNC"); + if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1) + err(1, "SIOCSETPFSYNCNV"); - preq.pfsyncr_defer = d ? PFSYNCF_DEFER : 0; - if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1) - err(1, "SIOCSETPFSYNC"); + nvlist_destroy(nvl); } -void -pfsync_status(int s) +static void +setpfsync_version(if_ctx *ctx, const char *val, int dummy __unused) { - struct pfsyncreq preq; + int version; + nvlist_t *nvl = nvlist_create(0); + + /* Don't verify, kernel knows which versions are supported.*/ + version = atoi(val); - bzero((char *)&preq, sizeof(struct pfsyncreq)); - ifr.ifr_data = (caddr_t)&preq; + if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1) + err(1, "SIOCGETPFSYNCNV"); - if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) + nvlist_free_number(nvl, "version"); + nvlist_add_number(nvl, "version", version); + + if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1) + err(1, "SIOCSETPFSYNCNV"); + + nvlist_destroy(nvl); +} + +static void +pfsync_status(if_ctx *ctx) +{ + nvlist_t *nvl; + char syncdev[IFNAMSIZ]; + char syncpeer_str[NI_MAXHOST]; + struct sockaddr_storage syncpeer; + int maxupdates = 0; + int flags = 0; + int version; + int error; + + nvl = nvlist_create(0); + + if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1) { + nvlist_destroy(nvl); return; + } + + memset((char *)&syncdev, 0, IFNAMSIZ); + if (nvlist_exists_string(nvl, "syncdev")) + strlcpy(syncdev, nvlist_get_string(nvl, "syncdev"), + IFNAMSIZ); + if (nvlist_exists_number(nvl, "maxupdates")) + maxupdates = nvlist_get_number(nvl, "maxupdates"); + if (nvlist_exists_number(nvl, "version")) + version = nvlist_get_number(nvl, "version"); + if (nvlist_exists_number(nvl, "flags")) + flags = nvlist_get_number(nvl, "flags"); + if (nvlist_exists_nvlist(nvl, "syncpeer")) { + pfsync_syncpeer_nvlist_to_sockaddr(nvlist_get_nvlist(nvl, + "syncpeer"), + &syncpeer); + } + + nvlist_destroy(nvl); + + printf("\t"); + + if (syncdev[0] != '\0') + printf("syncdev: %s ", syncdev); - if (preq.pfsyncr_syncdev[0] != '\0' || - preq.pfsyncr_syncpeer.s_addr != htonl(INADDR_PFSYNC_GROUP)) - printf("\t"); - - if (preq.pfsyncr_syncdev[0] != '\0') - printf("pfsync: syncdev: %s ", preq.pfsyncr_syncdev); - if (preq.pfsyncr_syncpeer.s_addr != htonl(INADDR_PFSYNC_GROUP)) - printf("syncpeer: %s ", inet_ntoa(preq.pfsyncr_syncpeer)); - - if (preq.pfsyncr_syncdev[0] != '\0' || - preq.pfsyncr_syncpeer.s_addr != htonl(INADDR_PFSYNC_GROUP)) { - printf("maxupd: %d ", preq.pfsyncr_maxupdates); - printf("defer: %s\n", - (preq.pfsyncr_defer & PFSYNCF_DEFER) ? "on" : "off"); - printf("\tsyncok: %d\n", - (preq.pfsyncr_defer & PFSYNCF_OK) ? 1 : 0); + if ((syncpeer.ss_family == AF_INET && + ((struct sockaddr_in *)&syncpeer)->sin_addr.s_addr != + htonl(INADDR_PFSYNC_GROUP)) || syncpeer.ss_family == AF_INET6) { + + struct sockaddr *syncpeer_sa = + (struct sockaddr *)&syncpeer; + if ((error = getnameinfo(syncpeer_sa, syncpeer_sa->sa_len, + syncpeer_str, sizeof(syncpeer_str), NULL, 0, + NI_NUMERICHOST)) != 0) + errx(1, "getnameinfo: %s", gai_strerror(error)); + printf("syncpeer: %s ", syncpeer_str); } + + printf("maxupd: %d ", maxupdates); + printf("defer: %s ", (flags & PFSYNCF_DEFER) ? "on" : "off"); + printf("version: %d\n", version); + printf("\tsyncok: %d\n", (flags & PFSYNCF_OK) ? 1 : 0); } static struct cmd pfsync_cmds[] = { @@ -223,6 +408,7 @@ static struct cmd pfsync_cmds[] = { DEF_CMD_ARG("maxupd", setpfsync_maxupd), DEF_CMD("defer", 1, setpfsync_defer), DEF_CMD("-defer", 0, setpfsync_defer), + DEF_CMD_ARG("version", setpfsync_version), }; static struct afswtch af_pfsync = { .af_name = "af_pfsync", @@ -233,9 +419,7 @@ static struct afswtch af_pfsync = { static __constructor void pfsync_ctor(void) { - int i; - - for (i = 0; i < nitems(pfsync_cmds); i++) + for (size_t i = 0; i < nitems(pfsync_cmds); i++) cmd_register(&pfsync_cmds[i]); af_register(&af_pfsync); } diff --git a/sbin/ifconfig/ifstf.c b/sbin/ifconfig/ifstf.c index f6c3cb5d5447..a99592b4801f 100644 --- a/sbin/ifconfig/ifstf.c +++ b/sbin/ifconfig/ifstf.c @@ -52,26 +52,24 @@ #include "ifconfig.h" static int -do_cmd(int sock, u_long op, void *arg, size_t argsize, int set) +do_cmd(if_ctx *ctx, u_long op, void *arg, size_t argsize, int set) { - struct ifdrv ifd; + struct ifdrv ifd = {}; - memset(&ifd, 0, sizeof(ifd)); - - strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name)); + strlcpy(ifd.ifd_name, ctx->ifname, sizeof(ifd.ifd_name)); ifd.ifd_cmd = op; ifd.ifd_len = argsize; ifd.ifd_data = arg; - return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd)); + return (ioctl_ctx(ctx, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd)); } static void -stf_status(int s) +stf_status(if_ctx *ctx) { struct stfv4args param; - if (do_cmd(s, STF6RD_GV4NET, ¶m, sizeof(param), 0) < 0) + if (do_cmd(ctx, STF6RD_GV4NET, ¶m, sizeof(param), 0) < 0) return; printf("\tv4net %s/%d -> ", inet_ntoa(param.srcv4_addr), @@ -80,7 +78,7 @@ stf_status(int s) } static void -setstf_br(const char *val, int d, int s, const struct afswtch *afp) +setstf_br(if_ctx *ctx, const char *val, int d __unused) { struct stfv4args req; struct sockaddr_in sin; @@ -94,12 +92,12 @@ setstf_br(const char *val, int d, int s, const struct afswtch *afp) errx(1, "%s: bad value", val); req.braddr = sin.sin_addr; - if (do_cmd(s, STF6RD_SBR, &req, sizeof(req), 1) < 0) + if (do_cmd(ctx, STF6RD_SBR, &req, sizeof(req), 1) < 0) err(1, "STF6RD_SBR%s", val); } static void -setstf_set(const char *val, int d, int s, const struct afswtch *afp) +setstf_set(if_ctx *ctx, const char *val, int d __unused) { struct stfv4args req; struct sockaddr_in sin; @@ -126,7 +124,7 @@ setstf_set(const char *val, int d, int s, const struct afswtch *afp) errx(1, "%s: bad value", val); memcpy(&req.srcv4_addr, &sin.sin_addr, sizeof(req.srcv4_addr)); - if (do_cmd(s, STF6RD_SV4NET, &req, sizeof(req), 1) < 0) + if (do_cmd(ctx, STF6RD_SV4NET, &req, sizeof(req), 1) < 0) err(1, "STF6RD_SV4NET %s", val); } @@ -144,9 +142,7 @@ static struct afswtch af_stf = { static __constructor void stf_ctor(void) { - int i; - - for (i = 0; i < nitems(stf_cmds); i++) + for (size_t i = 0; i < nitems(stf_cmds); i++) cmd_register(&stf_cmds[i]); af_register(&af_stf); } diff --git a/sbin/ifconfig/ifvlan.c b/sbin/ifconfig/ifvlan.c index 8b7b6e9daf9a..0a2603f1736f 100644 --- a/sbin/ifconfig/ifvlan.c +++ b/sbin/ifconfig/ifvlan.c @@ -4,7 +4,7 @@ * Copyright (c) 1999 Bill Paul <wpaul@ctr.columbia.edu> * Copyright (c) 2012 ADARA Networks, Inc. * All rights reserved. - * + * * Portions of this software were developed by Robert N. M. Watson under * contract to ADARA Networks, Inc. * @@ -59,12 +59,8 @@ #include "ifconfig.h" -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif - #define NOTAG ((u_short) -1) +#define NOPROTO ((u_short) -1) static const char proto_8021Q[] = "802.1q"; static const char proto_8021ad[] = "802.1ad"; @@ -72,24 +68,16 @@ static const char proto_qinq[] = "qinq"; static struct vlanreq params = { .vlr_tag = NOTAG, - .vlr_proto = ETHERTYPE_VLAN, + .vlr_proto = NOPROTO, }; -static int -getvlan(int s, struct ifreq *ifr, struct vlanreq *vreq) -{ - bzero((char *)vreq, sizeof(*vreq)); - ifr->ifr_data = (caddr_t)vreq; - - return ioctl(s, SIOCGETVLAN, (caddr_t)ifr); -} - static void -vlan_status(int s) +vlan_status(if_ctx *ctx) { - struct vlanreq vreq; + struct vlanreq vreq = {}; + struct ifreq ifr = { .ifr_data = (caddr_t)&vreq }; - if (getvlan(s, &ifr, &vreq) == -1) + if (ioctl_ctx_ifr(ctx, SIOCGETVLAN, &ifr) == -1) return; printf("\tvlan: %d", vreq.vlr_tag); printf(" vlanproto: "); @@ -103,7 +91,7 @@ vlan_status(int s) default: printf("0x%04x", vreq.vlr_proto); } - if (ioctl(s, SIOCGVLANPCP, (caddr_t)&ifr) != -1) + if (ioctl_ctx_ifr(ctx, SIOCGVLANPCP, &ifr) != -1) printf(" vlanpcp: %u", ifr.ifr_vlan_pcp); printf(" parent interface: %s", vreq.vlr_parent[0] == '\0' ? "<none>" : vreq.vlr_parent); @@ -121,7 +109,7 @@ vlan_parse_ethervid(const char *name) { char ifname[IFNAMSIZ]; char *cp; - int vid; + unsigned int vid; strlcpy(ifname, name, IFNAMSIZ); if ((cp = strrchr(ifname, '.')) == NULL) @@ -134,9 +122,12 @@ vlan_parse_ethervid(const char *name) errx(1, "invalid vlan tag"); vid = *cp++ - '0'; - while ((*cp >= '0') && (*cp <= '9')) + while ((*cp >= '0') && (*cp <= '9')) { vid = (vid * 10) + (*cp++ - '0'); - if ((*cp != '\0') || (vid & ~0xFFF)) + if (vid >= 0xFFF) + errx(1, "invalid vlan tag"); + } + if (*cp != '\0') errx(1, "invalid vlan tag"); /* @@ -155,7 +146,7 @@ vlan_parse_ethervid(const char *name) } static void -vlan_create(int s, struct ifreq *ifr) +vlan_create(if_ctx *ctx, struct ifreq *ifr) { vlan_parse_ethervid(ifr->ifr_name); @@ -167,13 +158,15 @@ vlan_create(int s, struct ifreq *ifr) errx(1, "must specify a tag for vlan create"); if (params.vlr_parent[0] == '\0') errx(1, "must specify a parent device for vlan create"); + if (params.vlr_proto == NOPROTO) + params.vlr_proto = ETHERTYPE_VLAN; ifr->ifr_data = (caddr_t) ¶ms; } - ioctl_ifcreate(s, ifr); + ifcreate_ioctl(ctx, ifr); } static void -vlan_cb(int s, void *arg) +vlan_cb(if_ctx *ctx __unused, void *arg __unused) { if ((params.vlr_tag != NOTAG) ^ (params.vlr_parent[0] != '\0')) errx(1, "both vlan and vlandev must be specified"); @@ -183,16 +176,19 @@ static void vlan_set(int s, struct ifreq *ifr) { if (params.vlr_tag != NOTAG && params.vlr_parent[0] != '\0') { + if (params.vlr_proto == NOPROTO) + params.vlr_proto = ETHERTYPE_VLAN; ifr->ifr_data = (caddr_t) ¶ms; if (ioctl(s, SIOCSETVLAN, (caddr_t)ifr) == -1) err(1, "SIOCSETVLAN"); } } -static -DECL_CMD_FUNC(setvlantag, val, d) +static void +setvlantag(if_ctx *ctx, const char *val, int dummy __unused) { - struct vlanreq vreq; + struct vlanreq vreq = {}; + struct ifreq ifr = { .ifr_data = (caddr_t)&vreq }; u_long ul; char *endp; @@ -204,25 +200,38 @@ DECL_CMD_FUNC(setvlantag, val, d) if (params.vlr_tag != ul) errx(1, "value for vlan out of range"); - if (getvlan(s, &ifr, &vreq) != -1) - vlan_set(s, &ifr); + if (ioctl_ctx_ifr(ctx, SIOCGETVLAN, &ifr) != -1) { + /* + * Retrieve the current settings if the interface has already + * been configured. + */ + if (vreq.vlr_parent[0] != '\0') { + if (params.vlr_parent[0] == '\0') + strlcpy(params.vlr_parent, vreq.vlr_parent, IFNAMSIZ); + if (params.vlr_proto == NOPROTO) + params.vlr_proto = vreq.vlr_proto; + } + vlan_set(ctx->io_s, &ifr); + } } -static -DECL_CMD_FUNC(setvlandev, val, d) +static void +setvlandev(if_ctx *ctx, const char *val, int dummy __unused) { - struct vlanreq vreq; + struct vlanreq vreq = {}; + struct ifreq ifr = { .ifr_data = (caddr_t)&vreq }; strlcpy(params.vlr_parent, val, sizeof(params.vlr_parent)); - if (getvlan(s, &ifr, &vreq) != -1) - vlan_set(s, &ifr); + if (ioctl_ctx_ifr(ctx, SIOCGETVLAN, &ifr) != -1) + vlan_set(ctx->io_s, &ifr); } -static -DECL_CMD_FUNC(setvlanproto, val, d) +static void +setvlanproto(if_ctx *ctx, const char *val, int dummy __unused) { - struct vlanreq vreq; + struct vlanreq vreq = {}; + struct ifreq ifr = { .ifr_data = (caddr_t)&vreq }; if (strncasecmp(proto_8021Q, val, strlen(proto_8021Q)) == 0) { @@ -233,15 +242,27 @@ DECL_CMD_FUNC(setvlanproto, val, d) } else errx(1, "invalid value for vlanproto"); - if (getvlan(s, &ifr, &vreq) != -1) - vlan_set(s, &ifr); + if (ioctl_ctx_ifr(ctx, SIOCGETVLAN, &ifr) != -1) { + /* + * Retrieve the current settings if the interface has already + * been configured. + */ + if (vreq.vlr_parent[0] != '\0') { + if (params.vlr_parent[0] == '\0') + strlcpy(params.vlr_parent, vreq.vlr_parent, IFNAMSIZ); + if (params.vlr_tag == NOTAG) + params.vlr_tag = vreq.vlr_tag; + } + vlan_set(ctx->io_s, &ifr); + } } -static -DECL_CMD_FUNC(setvlanpcp, val, d) +static void +setvlanpcp(if_ctx *ctx, const char *val, int dummy __unused) { u_long ul; char *endp; + struct ifreq ifr = {}; ul = strtoul(val, &endp, 0); if (*endp != '\0') @@ -249,25 +270,23 @@ DECL_CMD_FUNC(setvlanpcp, val, d) if (ul > 7) errx(1, "value for vlanpcp out of range"); ifr.ifr_vlan_pcp = ul; - if (ioctl(s, SIOCSVLANPCP, (caddr_t)&ifr) == -1) + if (ioctl_ctx_ifr(ctx, SIOCSVLANPCP, &ifr) == -1) err(1, "SIOCSVLANPCP"); } -static -DECL_CMD_FUNC(unsetvlandev, val, d) +static void +unsetvlandev(if_ctx *ctx, const char *val __unused, int dummy __unused) { - struct vlanreq vreq; - - bzero((char *)&vreq, sizeof(struct vlanreq)); - ifr.ifr_data = (caddr_t)&vreq; + struct vlanreq vreq = {}; + struct ifreq ifr = { .ifr_data = (caddr_t)&vreq }; - if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) + if (ioctl_ctx_ifr(ctx, SIOCGETVLAN, &ifr) == -1) err(1, "SIOCGETVLAN"); bzero((char *)&vreq.vlr_parent, sizeof(vreq.vlr_parent)); vreq.vlr_tag = 0; - if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) + if (ioctl_ctx(ctx, SIOCSETVLAN, (caddr_t)&ifr) == -1) err(1, "SIOCSETVLAN"); } @@ -283,15 +302,15 @@ static struct cmd vlan_cmds[] = { /* XXX For compatibility. Should become DEF_CMD() some day. */ DEF_CMD_OPTARG("-vlandev", unsetvlandev), DEF_CMD("vlanmtu", IFCAP_VLAN_MTU, setifcap), - DEF_CMD("-vlanmtu", -IFCAP_VLAN_MTU, setifcap), + DEF_CMD("-vlanmtu", IFCAP_VLAN_MTU, clearifcap), DEF_CMD("vlanhwtag", IFCAP_VLAN_HWTAGGING, setifcap), - DEF_CMD("-vlanhwtag", -IFCAP_VLAN_HWTAGGING, setifcap), + DEF_CMD("-vlanhwtag", IFCAP_VLAN_HWTAGGING, clearifcap), DEF_CMD("vlanhwfilter", IFCAP_VLAN_HWFILTER, setifcap), - DEF_CMD("-vlanhwfilter", -IFCAP_VLAN_HWFILTER, setifcap), - DEF_CMD("-vlanhwtso", -IFCAP_VLAN_HWTSO, setifcap), + DEF_CMD("-vlanhwfilter", IFCAP_VLAN_HWFILTER, clearifcap), DEF_CMD("vlanhwtso", IFCAP_VLAN_HWTSO, setifcap), + DEF_CMD("-vlanhwtso", IFCAP_VLAN_HWTSO, clearifcap), DEF_CMD("vlanhwcsum", IFCAP_VLAN_HWCSUM, setifcap), - DEF_CMD("-vlanhwcsum", -IFCAP_VLAN_HWCSUM, setifcap), + DEF_CMD("-vlanhwcsum", IFCAP_VLAN_HWCSUM, clearifcap), }; static struct afswtch af_vlan = { .af_name = "af_vlan", diff --git a/sbin/ifconfig/ifvxlan.c b/sbin/ifconfig/ifvxlan.c index fda435343a16..cbea685b6ba0 100644 --- a/sbin/ifconfig/ifvxlan.c +++ b/sbin/ifconfig/ifvxlan.c @@ -24,9 +24,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #include <sys/param.h> #include <sys/ioctl.h> #include <sys/socket.h> @@ -73,32 +70,30 @@ get_val(const char *cp, u_long *valp) } static int -do_cmd(int sock, u_long op, void *arg, size_t argsize, int set) +do_cmd(if_ctx *ctx, u_long op, void *arg, size_t argsize, int set) { - struct ifdrv ifd; - - bzero(&ifd, sizeof(ifd)); + struct ifdrv ifd = {}; - strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name)); + strlcpy(ifd.ifd_name, ctx->ifname, sizeof(ifd.ifd_name)); ifd.ifd_cmd = op; ifd.ifd_len = argsize; ifd.ifd_data = arg; - return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd)); + return (ioctl_ctx(ctx, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd)); } static int -vxlan_exists(int sock) +vxlan_exists(if_ctx *ctx) { struct ifvxlancfg cfg; bzero(&cfg, sizeof(cfg)); - return (do_cmd(sock, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg), 0) != -1); + return (do_cmd(ctx, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg), 0) != -1); } static void -vxlan_status(int s) +vxlan_status(if_ctx *ctx) { struct ifvxlancfg cfg; char src[NI_MAXHOST], dst[NI_MAXHOST]; @@ -108,7 +103,7 @@ vxlan_status(int s) bzero(&cfg, sizeof(cfg)); - if (do_cmd(s, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg), 0) < 0) + if (do_cmd(ctx, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg), 0) < 0) return; vni = cfg.vxlc_vni; @@ -128,10 +123,10 @@ vxlan_status(int s) dst[0] = dstport[0] = '\0'; if (!ipv6) { - struct sockaddr_in *sin = (struct sockaddr_in *)rsa; + struct sockaddr_in *sin = satosin(rsa); mc = IN_MULTICAST(ntohl(sin->sin_addr.s_addr)); } else { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)rsa; + struct sockaddr_in6 *sin6 = satosin6(rsa); mc = IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr); } @@ -141,7 +136,7 @@ vxlan_status(int s) printf(" %s %s%s%s:%s", mc ? "group" : "remote", ipv6 ? "[" : "", dst, ipv6 ? "]" : "", dstport); - if (verbose) { + if (ctx->args->verbose) { printf("\n\t\tconfig: "); printf("%slearning portrange %d-%d ttl %d", cfg.vxlc_learn ? "" : "no", cfg.vxlc_port_min, @@ -179,23 +174,17 @@ vxlan_check_params(void) #undef _REMOTE_ADDR46 static void -vxlan_cb(int s, void *arg) -{ - -} - -static void -vxlan_create(int s, struct ifreq *ifr) +vxlan_create(if_ctx *ctx, struct ifreq *ifr) { vxlan_check_params(); ifr->ifr_data = (caddr_t) ¶ms; - ioctl_ifcreate(s, ifr); + ifcreate_ioctl(ctx, ifr); } -static -DECL_CMD_FUNC(setvxlan_vni, arg, d) +static void +setvxlan_vni(if_ctx *ctx, const char *arg, int dummy __unused) { struct ifvxlancmd cmd; u_long val; @@ -203,7 +192,7 @@ DECL_CMD_FUNC(setvxlan_vni, arg, d) if (get_val(arg, &val) < 0 || val >= VXLAN_VNI_MAX) errx(1, "invalid network identifier: %s", arg); - if (!vxlan_exists(s)) { + if (!vxlan_exists(ctx)) { params.vxlp_with |= VXLAN_PARAM_WITH_VNI; params.vxlp_vni = val; return; @@ -212,16 +201,18 @@ DECL_CMD_FUNC(setvxlan_vni, arg, d) bzero(&cmd, sizeof(cmd)); cmd.vxlcmd_vni = val; - if (do_cmd(s, VXLAN_CMD_SET_VNI, &cmd, sizeof(cmd), 1) < 0) + if (do_cmd(ctx, VXLAN_CMD_SET_VNI, &cmd, sizeof(cmd), 1) < 0) err(1, "VXLAN_CMD_SET_VNI"); } -static -DECL_CMD_FUNC(setvxlan_local, addr, d) +static void +setvxlan_local(if_ctx *ctx, const char *addr, int dummy __unused) { struct ifvxlancmd cmd; struct addrinfo *ai; +#if (defined INET || defined INET6) struct sockaddr *sa; +#endif int error; bzero(&cmd, sizeof(cmd)); @@ -230,12 +221,14 @@ DECL_CMD_FUNC(setvxlan_local, addr, d) errx(1, "error in parsing local address string: %s", gai_strerror(error)); +#if (defined INET || defined INET6) sa = ai->ai_addr; +#endif switch (ai->ai_family) { #ifdef INET case AF_INET: { - struct sockaddr_in *sin = (struct sockaddr_in *)sa; + struct sockaddr_in *sin = satosin(sa); if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) errx(1, "local address cannot be multicast"); @@ -246,7 +239,7 @@ DECL_CMD_FUNC(setvxlan_local, addr, d) #endif #ifdef INET6 case AF_INET6: { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + struct sockaddr_in6 *sin6 = satosin6(sa); if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) errx(1, "local address cannot be multicast"); @@ -261,7 +254,7 @@ DECL_CMD_FUNC(setvxlan_local, addr, d) freeaddrinfo(ai); - if (!vxlan_exists(s)) { + if (!vxlan_exists(ctx)) { if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) { params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR4; params.vxlp_local_sa.in4 = cmd.vxlcmd_sa.in4; @@ -272,16 +265,18 @@ DECL_CMD_FUNC(setvxlan_local, addr, d) return; } - if (do_cmd(s, VXLAN_CMD_SET_LOCAL_ADDR, &cmd, sizeof(cmd), 1) < 0) + if (do_cmd(ctx, VXLAN_CMD_SET_LOCAL_ADDR, &cmd, sizeof(cmd), 1) < 0) err(1, "VXLAN_CMD_SET_LOCAL_ADDR"); } -static -DECL_CMD_FUNC(setvxlan_remote, addr, d) +static void +setvxlan_remote(if_ctx *ctx, const char *addr, int dummy __unused) { struct ifvxlancmd cmd; struct addrinfo *ai; +#if (defined INET || defined INET6) struct sockaddr *sa; +#endif int error; bzero(&cmd, sizeof(cmd)); @@ -290,12 +285,14 @@ DECL_CMD_FUNC(setvxlan_remote, addr, d) errx(1, "error in parsing remote address string: %s", gai_strerror(error)); +#if (defined INET || defined INET6) sa = ai->ai_addr; +#endif switch (ai->ai_family) { #ifdef INET case AF_INET: { - struct sockaddr_in *sin = (struct sockaddr_in *)sa; + struct sockaddr_in *sin = satosin(sa); if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) errx(1, "remote address cannot be multicast"); @@ -306,7 +303,7 @@ DECL_CMD_FUNC(setvxlan_remote, addr, d) #endif #ifdef INET6 case AF_INET6: { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + struct sockaddr_in6 *sin6 = satosin6(sa); if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) errx(1, "remote address cannot be multicast"); @@ -321,7 +318,7 @@ DECL_CMD_FUNC(setvxlan_remote, addr, d) freeaddrinfo(ai); - if (!vxlan_exists(s)) { + if (!vxlan_exists(ctx)) { if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) { params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4; params.vxlp_remote_sa.in4 = cmd.vxlcmd_sa.in4; @@ -332,16 +329,18 @@ DECL_CMD_FUNC(setvxlan_remote, addr, d) return; } - if (do_cmd(s, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0) + if (do_cmd(ctx, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0) err(1, "VXLAN_CMD_SET_REMOTE_ADDR"); } -static -DECL_CMD_FUNC(setvxlan_group, addr, d) +static void +setvxlan_group(if_ctx *ctx, const char *addr, int dummy __unused) { struct ifvxlancmd cmd; struct addrinfo *ai; +#if (defined INET || defined INET6) struct sockaddr *sa; +#endif int error; bzero(&cmd, sizeof(cmd)); @@ -350,12 +349,14 @@ DECL_CMD_FUNC(setvxlan_group, addr, d) errx(1, "error in parsing group address string: %s", gai_strerror(error)); +#if (defined INET || defined INET6) sa = ai->ai_addr; +#endif switch (ai->ai_family) { #ifdef INET case AF_INET: { - struct sockaddr_in *sin = (struct sockaddr_in *)sa; + struct sockaddr_in *sin = satosin(sa); if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) errx(1, "group address must be multicast"); @@ -366,7 +367,7 @@ DECL_CMD_FUNC(setvxlan_group, addr, d) #endif #ifdef INET6 case AF_INET6: { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + struct sockaddr_in6 *sin6 = satosin6(sa); if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) errx(1, "group address must be multicast"); @@ -381,7 +382,7 @@ DECL_CMD_FUNC(setvxlan_group, addr, d) freeaddrinfo(ai); - if (!vxlan_exists(s)) { + if (!vxlan_exists(ctx)) { if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) { params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4; params.vxlp_remote_sa.in4 = cmd.vxlcmd_sa.in4; @@ -392,12 +393,12 @@ DECL_CMD_FUNC(setvxlan_group, addr, d) return; } - if (do_cmd(s, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0) + if (do_cmd(ctx, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0) err(1, "VXLAN_CMD_SET_REMOTE_ADDR"); } -static -DECL_CMD_FUNC(setvxlan_local_port, arg, d) +static void +setvxlan_local_port(if_ctx *ctx, const char *arg, int dummy __unused) { struct ifvxlancmd cmd; u_long val; @@ -405,7 +406,7 @@ DECL_CMD_FUNC(setvxlan_local_port, arg, d) if (get_val(arg, &val) < 0 || val >= UINT16_MAX) errx(1, "invalid local port: %s", arg); - if (!vxlan_exists(s)) { + if (!vxlan_exists(ctx)) { params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_PORT; params.vxlp_local_port = val; return; @@ -414,12 +415,12 @@ DECL_CMD_FUNC(setvxlan_local_port, arg, d) bzero(&cmd, sizeof(cmd)); cmd.vxlcmd_port = val; - if (do_cmd(s, VXLAN_CMD_SET_LOCAL_PORT, &cmd, sizeof(cmd), 1) < 0) + if (do_cmd(ctx, VXLAN_CMD_SET_LOCAL_PORT, &cmd, sizeof(cmd), 1) < 0) err(1, "VXLAN_CMD_SET_LOCAL_PORT"); } -static -DECL_CMD_FUNC(setvxlan_remote_port, arg, d) +static void +setvxlan_remote_port(if_ctx *ctx, const char *arg, int dummy __unused) { struct ifvxlancmd cmd; u_long val; @@ -427,7 +428,7 @@ DECL_CMD_FUNC(setvxlan_remote_port, arg, d) if (get_val(arg, &val) < 0 || val >= UINT16_MAX) errx(1, "invalid remote port: %s", arg); - if (!vxlan_exists(s)) { + if (!vxlan_exists(ctx)) { params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_PORT; params.vxlp_remote_port = val; return; @@ -436,12 +437,12 @@ DECL_CMD_FUNC(setvxlan_remote_port, arg, d) bzero(&cmd, sizeof(cmd)); cmd.vxlcmd_port = val; - if (do_cmd(s, VXLAN_CMD_SET_REMOTE_PORT, &cmd, sizeof(cmd), 1) < 0) + if (do_cmd(ctx, VXLAN_CMD_SET_REMOTE_PORT, &cmd, sizeof(cmd), 1) < 0) err(1, "VXLAN_CMD_SET_REMOTE_PORT"); } -static -DECL_CMD_FUNC2(setvxlan_port_range, arg1, arg2) +static void +setvxlan_port_range(if_ctx *ctx, const char *arg1, const char *arg2) { struct ifvxlancmd cmd; u_long min, max; @@ -453,7 +454,7 @@ DECL_CMD_FUNC2(setvxlan_port_range, arg1, arg2) if (max < min) errx(1, "invalid port range"); - if (!vxlan_exists(s)) { + if (!vxlan_exists(ctx)) { params.vxlp_with |= VXLAN_PARAM_WITH_PORT_RANGE; params.vxlp_min_port = min; params.vxlp_max_port = max; @@ -464,12 +465,12 @@ DECL_CMD_FUNC2(setvxlan_port_range, arg1, arg2) cmd.vxlcmd_port_min = min; cmd.vxlcmd_port_max = max; - if (do_cmd(s, VXLAN_CMD_SET_PORT_RANGE, &cmd, sizeof(cmd), 1) < 0) + if (do_cmd(ctx, VXLAN_CMD_SET_PORT_RANGE, &cmd, sizeof(cmd), 1) < 0) err(1, "VXLAN_CMD_SET_PORT_RANGE"); } -static -DECL_CMD_FUNC(setvxlan_timeout, arg, d) +static void +setvxlan_timeout(if_ctx *ctx, const char *arg, int dummy __unused) { struct ifvxlancmd cmd; u_long val; @@ -477,7 +478,7 @@ DECL_CMD_FUNC(setvxlan_timeout, arg, d) if (get_val(arg, &val) < 0 || (val & ~0xFFFFFFFF) != 0) errx(1, "invalid timeout value: %s", arg); - if (!vxlan_exists(s)) { + if (!vxlan_exists(ctx)) { params.vxlp_with |= VXLAN_PARAM_WITH_FTABLE_TIMEOUT; params.vxlp_ftable_timeout = val & 0xFFFFFFFF; return; @@ -486,12 +487,12 @@ DECL_CMD_FUNC(setvxlan_timeout, arg, d) bzero(&cmd, sizeof(cmd)); cmd.vxlcmd_ftable_timeout = val & 0xFFFFFFFF; - if (do_cmd(s, VXLAN_CMD_SET_FTABLE_TIMEOUT, &cmd, sizeof(cmd), 1) < 0) + if (do_cmd(ctx, VXLAN_CMD_SET_FTABLE_TIMEOUT, &cmd, sizeof(cmd), 1) < 0) err(1, "VXLAN_CMD_SET_FTABLE_TIMEOUT"); } -static -DECL_CMD_FUNC(setvxlan_maxaddr, arg, d) +static void +setvxlan_maxaddr(if_ctx *ctx, const char *arg, int dummy __unused) { struct ifvxlancmd cmd; u_long val; @@ -499,7 +500,7 @@ DECL_CMD_FUNC(setvxlan_maxaddr, arg, d) if (get_val(arg, &val) < 0 || (val & ~0xFFFFFFFF) != 0) errx(1, "invalid maxaddr value: %s", arg); - if (!vxlan_exists(s)) { + if (!vxlan_exists(ctx)) { params.vxlp_with |= VXLAN_PARAM_WITH_FTABLE_MAX; params.vxlp_ftable_max = val & 0xFFFFFFFF; return; @@ -508,16 +509,16 @@ DECL_CMD_FUNC(setvxlan_maxaddr, arg, d) bzero(&cmd, sizeof(cmd)); cmd.vxlcmd_ftable_max = val & 0xFFFFFFFF; - if (do_cmd(s, VXLAN_CMD_SET_FTABLE_MAX, &cmd, sizeof(cmd), 1) < 0) + if (do_cmd(ctx, VXLAN_CMD_SET_FTABLE_MAX, &cmd, sizeof(cmd), 1) < 0) err(1, "VXLAN_CMD_SET_FTABLE_MAX"); } -static -DECL_CMD_FUNC(setvxlan_dev, arg, d) +static void +setvxlan_dev(if_ctx *ctx, const char *arg, int dummy __unused) { struct ifvxlancmd cmd; - if (!vxlan_exists(s)) { + if (!vxlan_exists(ctx)) { params.vxlp_with |= VXLAN_PARAM_WITH_MULTICAST_IF; strlcpy(params.vxlp_mc_ifname, arg, sizeof(params.vxlp_mc_ifname)); @@ -527,12 +528,12 @@ DECL_CMD_FUNC(setvxlan_dev, arg, d) bzero(&cmd, sizeof(cmd)); strlcpy(cmd.vxlcmd_ifname, arg, sizeof(cmd.vxlcmd_ifname)); - if (do_cmd(s, VXLAN_CMD_SET_MULTICAST_IF, &cmd, sizeof(cmd), 1) < 0) + if (do_cmd(ctx, VXLAN_CMD_SET_MULTICAST_IF, &cmd, sizeof(cmd), 1) < 0) err(1, "VXLAN_CMD_SET_MULTICAST_IF"); } -static -DECL_CMD_FUNC(setvxlan_ttl, arg, d) +static void +setvxlan_ttl(if_ctx *ctx, const char *arg, int dummy __unused) { struct ifvxlancmd cmd; u_long val; @@ -540,7 +541,7 @@ DECL_CMD_FUNC(setvxlan_ttl, arg, d) if (get_val(arg, &val) < 0 || val > 256) errx(1, "invalid TTL value: %s", arg); - if (!vxlan_exists(s)) { + if (!vxlan_exists(ctx)) { params.vxlp_with |= VXLAN_PARAM_WITH_TTL; params.vxlp_ttl = val; return; @@ -549,16 +550,16 @@ DECL_CMD_FUNC(setvxlan_ttl, arg, d) bzero(&cmd, sizeof(cmd)); cmd.vxlcmd_ttl = val; - if (do_cmd(s, VXLAN_CMD_SET_TTL, &cmd, sizeof(cmd), 1) < 0) + if (do_cmd(ctx, VXLAN_CMD_SET_TTL, &cmd, sizeof(cmd), 1) < 0) err(1, "VXLAN_CMD_SET_TTL"); } -static -DECL_CMD_FUNC(setvxlan_learn, arg, d) +static void +setvxlan_learn(if_ctx *ctx, const char *arg __unused, int d) { struct ifvxlancmd cmd; - if (!vxlan_exists(s)) { + if (!vxlan_exists(ctx)) { params.vxlp_with |= VXLAN_PARAM_WITH_LEARN; params.vxlp_learn = d; return; @@ -568,12 +569,12 @@ DECL_CMD_FUNC(setvxlan_learn, arg, d) if (d != 0) cmd.vxlcmd_flags |= VXLAN_CMD_FLAG_LEARN; - if (do_cmd(s, VXLAN_CMD_SET_LEARN, &cmd, sizeof(cmd), 1) < 0) + if (do_cmd(ctx, VXLAN_CMD_SET_LEARN, &cmd, sizeof(cmd), 1) < 0) err(1, "VXLAN_CMD_SET_LEARN"); } static void -setvxlan_flush(const char *val, int d, int s, const struct afswtch *afp) +setvxlan_flush(if_ctx *ctx, const char *val __unused, int d) { struct ifvxlancmd cmd; @@ -581,7 +582,7 @@ setvxlan_flush(const char *val, int d, int s, const struct afswtch *afp) if (d != 0) cmd.vxlcmd_flags |= VXLAN_CMD_FLAG_FLUSH_ALL; - if (do_cmd(s, VXLAN_CMD_FLUSH, &cmd, sizeof(cmd), 1) < 0) + if (do_cmd(ctx, VXLAN_CMD_FLUSH, &cmd, sizeof(cmd), 1) < 0) err(1, "VXLAN_CMD_FLUSH"); } @@ -621,9 +622,9 @@ static struct cmd vxlan_cmds[] = { DEF_CMD("vxlanflushall", 1, setvxlan_flush), DEF_CMD("vxlanhwcsum", IFCAP_VXLAN_HWCSUM, setifcap), - DEF_CMD("-vxlanhwcsum", -IFCAP_VXLAN_HWCSUM, setifcap), + DEF_CMD("-vxlanhwcsum", IFCAP_VXLAN_HWCSUM, clearifcap), DEF_CMD("vxlanhwtso", IFCAP_VXLAN_HWTSO, setifcap), - DEF_CMD("-vxlanhwtso", -IFCAP_VXLAN_HWTSO, setifcap), + DEF_CMD("-vxlanhwtso", IFCAP_VXLAN_HWTSO, clearifcap), }; static struct afswtch af_vxlan = { @@ -640,6 +641,5 @@ vxlan_ctor(void) for (i = 0; i < nitems(vxlan_cmds); i++) cmd_register(&vxlan_cmds[i]); af_register(&af_vxlan); - callback_register(vxlan_cb, NULL); clone_setdefcallback_prefix("vxlan", vxlan_create); } diff --git a/sbin/ifconfig/sfp.c b/sbin/ifconfig/sfp.c index 4900b18ff2c8..0dc1def751b1 100644 --- a/sbin/ifconfig/sfp.c +++ b/sbin/ifconfig/sfp.c @@ -23,11 +23,6 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <sys/types.h> #include <sys/param.h> #include <sys/ioctl.h> @@ -55,15 +50,16 @@ static const char rcsid[] = #include "ifconfig.h" void -sfp_status(int s, struct ifreq *ifr, int verbose) +sfp_status(if_ctx *ctx) { struct ifconfig_sfp_info info; struct ifconfig_sfp_info_strings strings; struct ifconfig_sfp_vendor_info vendor_info; struct ifconfig_sfp_status status; size_t channel_count; + int verbose = ctx->args->verbose; - if (ifconfig_sfp_get_sfp_info(lifh, name, &info) == -1) + if (ifconfig_sfp_get_sfp_info(lifh, ctx->ifname, &info) == -1) return; ifconfig_sfp_get_sfp_info_strings(&info, &strings); @@ -73,7 +69,7 @@ sfp_status(int s, struct ifreq *ifr, int verbose) ifconfig_sfp_physical_spec(&info, &strings), strings.sfp_conn); - if (ifconfig_sfp_get_sfp_vendor_info(lifh, name, &vendor_info) == -1) + if (ifconfig_sfp_get_sfp_vendor_info(lifh, ctx->ifname, &vendor_info) == -1) return; printf("\tvendor: %s PN: %s SN: %s DATE: %s\n", @@ -93,7 +89,7 @@ sfp_status(int s, struct ifreq *ifr, int verbose) } } - if (ifconfig_sfp_get_sfp_status(lifh, name, &status) == 0) { + if (ifconfig_sfp_get_sfp_status(lifh, ctx->ifname, &status) == 0) { if (ifconfig_sfp_id_is_qsfp(info.sfp_id) && verbose > 1) printf("\tnominal bitrate: %u Mbps\n", status.bitrate); printf("\tmodule temperature: %.2f C voltage: %.2f Volts\n", @@ -112,7 +108,7 @@ sfp_status(int s, struct ifreq *ifr, int verbose) if (verbose > 2) { struct ifconfig_sfp_dump dump; - if (ifconfig_sfp_get_sfp_dump(lifh, name, &dump) == -1) + if (ifconfig_sfp_get_sfp_dump(lifh, ctx->ifname, &dump) == -1) return; if (ifconfig_sfp_id_is_qsfp(info.sfp_id)) { diff --git a/sbin/ifconfig/tests/Makefile b/sbin/ifconfig/tests/Makefile index 93967c705175..e902f262552a 100644 --- a/sbin/ifconfig/tests/Makefile +++ b/sbin/ifconfig/tests/Makefile @@ -1,7 +1,8 @@ -# $FreeBSD$ +NETBSD_ATF_TESTS_SH= nonexistent_test +ATF_TESTS_SH+= inet6 -NETBSD_ATF_TESTS_SH= nonexistent_test +TEST_METADATA+= execenv="jail" +TEST_METADATA+= execenv_jail_params="vnet allow.raw_sockets" .include <netbsd-tests.test.mk> - .include <bsd.test.mk> diff --git a/sbin/ifconfig/tests/Makefile.depend b/sbin/ifconfig/tests/Makefile.depend index f80275d86ab1..11aba52f82cf 100644 --- a/sbin/ifconfig/tests/Makefile.depend +++ b/sbin/ifconfig/tests/Makefile.depend @@ -1,4 +1,3 @@ -# $FreeBSD$ # Autogenerated - do NOT edit! DIRDEPS = \ diff --git a/sbin/ifconfig/tests/inet6.sh b/sbin/ifconfig/tests/inet6.sh new file mode 100644 index 000000000000..edfd88d93af7 --- /dev/null +++ b/sbin/ifconfig/tests/inet6.sh @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: ISC +# +# Copyright (c) 2025 Lexi Winter + +. $(atf_get_srcdir)/../../sys/common/vnet.subr + +# Bug 286910: adding 'netmask' or 'broadcast' to an IPv6 address crashed +# ifconfig. + +atf_test_case "netmask" "cleanup" +netmask_head() +{ + atf_set descr "Test invalid 'netmask' option" + atf_set require.user root +} + +netmask_body() +{ + vnet_init + + ep=$(vnet_mkepair) + vnet_mkjail ifcjail ${ep}a + + # Add the address the wrong way + atf_check -s exit:1 \ + -e match:"ifconfig: netmask: invalid option for inet6" \ + jexec ifcjail ifconfig ${ep}a inet6 2001:db8:1::1 netmask 64 + + # Add the address the correct way + atf_check -s exit:0 \ + jexec ifcjail ifconfig ${ep}a inet6 2001:db8:1::1/64 + atf_check -s exit:0 -o match:"2001:db8:1::1 prefixlen 64" \ + jexec ifcjail ifconfig ${ep}a + + # Remove the address the wrong way + atf_check -s exit:1 \ + -e match:"ifconfig: netmask: invalid option for inet6" \ + jexec ifcjail ifconfig ${ep}a inet6 2001:db8:1::1 netmask 64 -alias +} + +netmask_cleanup() +{ + vnet_cleanup +} + +atf_test_case "broadcast" "cleanup" +broadcast_head() +{ + atf_set descr "Test invalid 'broadcast' option" + atf_set require.user root +} + +broadcast_body() +{ + vnet_init + + ep=$(vnet_mkepair) + vnet_mkjail ifcjail ${ep}a + + atf_check -s exit:1 \ + -e match:"ifconfig: broadcast: invalid option for inet6" \ + jexec ifcjail ifconfig ${ep}a \ + inet6 2001:db8:1::1 broadcast 2001:db8:1::ffff + + atf_check -s exit:0 \ + jexec ifcjail ifconfig ${ep}a inet6 2001:db8:1::1/64 + + atf_check -s exit:1 \ + -e match:"ifconfig: broadcast: invalid option for inet6" \ + jexec ifcjail ifconfig ${ep}a \ + inet6 2001:db8:1::1 broadcast 2001:db:1::ffff -alias +} + +broadcast_cleanup() +{ + vnet_cleanup +} + +atf_init_test_cases() +{ + atf_add_test_case netmask + atf_add_test_case broadcast +} |