diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2019-09-24 11:05:03 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2019-11-13 10:47:04 +0100 |
commit | a5ddb0ea69f21c16b7697a935d7a0c16bb3cffcf (patch) | |
tree | db091fb0f7d091804482156c9f3f55879ac93d5b /freebsd/sbin | |
parent | test/syscalls01: Fix sporadic test failures (diff) | |
download | rtems-libbsd-a5ddb0ea69f21c16b7697a935d7a0c16bb3cffcf.tar.bz2 |
Update to FreeBSD head 2019-09-24
Git mirror commit 6b0307a0a5184339393f555d5d424190d8a8277a.
Diffstat (limited to 'freebsd/sbin')
31 files changed, 1569 insertions, 901 deletions
diff --git a/freebsd/sbin/dhclient/dhclient.c b/freebsd/sbin/dhclient/dhclient.c index 2aedd2f7..3b5b8849 100644 --- a/freebsd/sbin/dhclient/dhclient.c +++ b/freebsd/sbin/dhclient/dhclient.c @@ -865,6 +865,7 @@ bind_lease(struct interface_info *ip) opt = &ip->client->new->options[DHO_INTERFACE_MTU]; if (opt->len == sizeof(u_int16_t)) { u_int16_t mtu = 0; + u_int16_t old_mtu = 0; bool supersede = (ip->client->config->default_actions[DHO_INTERFACE_MTU] == ACTION_SUPERSEDE); @@ -873,12 +874,19 @@ bind_lease(struct interface_info *ip) else mtu = be16dec(opt->data); + if (ip->client->active) { + opt = &ip->client->active->options[DHO_INTERFACE_MTU]; + if (opt->len == sizeof(u_int16_t)) { + old_mtu = be16dec(opt->data); + } + } + if (mtu < MIN_MTU) { /* Treat 0 like a user intentionally doesn't want to change MTU and, * therefore, warning is not needed */ if (!supersede || mtu != 0) warning("mtu size %u < %d: ignored", (unsigned)mtu, MIN_MTU); - } else { + } else if (ip->client->state != S_RENEWING || mtu != old_mtu) { interface_set_mtu_unpriv(privfd, mtu); } } @@ -2350,7 +2358,8 @@ priv_script_go(void) if (ip) script_flush_env(ip->client); - return (wstatus & 0xff); + return (WIFEXITED(wstatus) ? + WEXITSTATUS(wstatus) : 128 + WTERMSIG(wstatus)); } void diff --git a/freebsd/sbin/dhclient/options.c b/freebsd/sbin/dhclient/options.c index b31ab32a..a38d6440 100644 --- a/freebsd/sbin/dhclient/options.c +++ b/freebsd/sbin/dhclient/options.c @@ -898,6 +898,5 @@ do_packet(struct interface_info *interface, struct dhcp_packet *packet, /* Free the data associated with the options. */ for (i = 0; i < 256; i++) - if (tp.options[i].len && tp.options[i].data) - free(tp.options[i].data); + free(tp.options[i].data); } diff --git a/freebsd/sbin/dhclient/packet.c b/freebsd/sbin/dhclient/packet.c index b3c719b2..51f7e1ab 100644 --- a/freebsd/sbin/dhclient/packet.c +++ b/freebsd/sbin/dhclient/packet.c @@ -185,7 +185,7 @@ decode_udp_ip_header(unsigned char *buf, int bufix, struct sockaddr_in *from, ip_packets_seen++; if (wrapsum(checksum(buf + bufix, ip_len, 0)) != 0) { ip_packets_bad_checksum++; - if (ip_packets_seen > 4 && + if (ip_packets_seen > 4 && ip_packets_bad_checksum != 0 && (ip_packets_seen / ip_packets_bad_checksum) < 2) { note("%d bad IP checksums seen in %d packets", ip_packets_bad_checksum, ip_packets_seen); @@ -237,7 +237,7 @@ decode_udp_ip_header(unsigned char *buf, int bufix, struct sockaddr_in *from, udp_packets_seen++; if (usum && usum != sum) { udp_packets_bad_checksum++; - if (udp_packets_seen > 4 && + if (udp_packets_seen > 4 && udp_packets_bad_checksum != 0 && (udp_packets_seen / udp_packets_bad_checksum) < 2) { note("%d bad udp checksums in %d packets", udp_packets_bad_checksum, udp_packets_seen); diff --git a/freebsd/sbin/ifconfig/af_inet.c b/freebsd/sbin/ifconfig/af_inet.c index 050ceb80..a6e95683 100644 --- a/freebsd/sbin/ifconfig/af_inet.c +++ b/freebsd/sbin/ifconfig/af_inet.c @@ -119,16 +119,16 @@ in_status(int s __unused, const struct ifaddrs *ifa) if (cidr == 0) break; } - printf("/%d ", cidr); + printf("/%d", cidr); } else if (f_inet != NULL && strcmp(f_inet, "dotted") == 0) - printf(" netmask %s ", inet_ntoa(sin->sin_addr)); + printf(" netmask %s", inet_ntoa(sin->sin_addr)); else - printf(" netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr)); + 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; if (sin != NULL && sin->sin_addr.s_addr != 0) - printf("broadcast %s ", inet_ntoa(sin->sin_addr)); + printf(" broadcast %s", inet_ntoa(sin->sin_addr)); } print_vhid(ifa, " "); diff --git a/freebsd/sbin/ifconfig/af_inet6.c b/freebsd/sbin/ifconfig/af_inet6.c index cae6c326..f3b1b6bc 100644 --- a/freebsd/sbin/ifconfig/af_inet6.c +++ b/freebsd/sbin/ifconfig/af_inet6.c @@ -259,49 +259,49 @@ in6_status(int s __unused, const struct ifaddrs *ifa) if (sin == NULL) sin = &null_sin; if (f_inet6 != NULL && strcmp(f_inet6, "cidr") == 0) - printf("/%d ", prefix(&sin->sin6_addr, + printf("/%d", prefix(&sin->sin6_addr, sizeof(struct in6_addr))); else - printf(" prefixlen %d ", prefix(&sin->sin6_addr, + printf(" prefixlen %d", prefix(&sin->sin6_addr, sizeof(struct in6_addr))); if ((flags6 & IN6_IFF_ANYCAST) != 0) - printf("anycast "); + printf(" anycast"); if ((flags6 & IN6_IFF_TENTATIVE) != 0) - printf("tentative "); + printf(" tentative"); if ((flags6 & IN6_IFF_DUPLICATED) != 0) - printf("duplicated "); + printf(" duplicated"); if ((flags6 & IN6_IFF_DETACHED) != 0) - printf("detached "); + printf(" detached"); if ((flags6 & IN6_IFF_DEPRECATED) != 0) - printf("deprecated "); + printf(" deprecated"); if ((flags6 & IN6_IFF_AUTOCONF) != 0) - printf("autoconf "); + printf(" autoconf"); if ((flags6 & IN6_IFF_TEMPORARY) != 0) - printf("temporary "); + printf(" temporary"); if ((flags6 & IN6_IFF_PREFER_SOURCE) != 0) - printf("prefer_source "); + printf(" prefer_source"); if (((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_scope_id) - printf("scopeid 0x%x ", + printf(" scopeid 0x%x", ((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_scope_id); if (ip6lifetime && (lifetime.ia6t_preferred || lifetime.ia6t_expire)) { - printf("pltime "); + printf(" pltime"); if (lifetime.ia6t_preferred) { - printf("%s ", lifetime.ia6t_preferred < now.tv_sec + printf(" %s", lifetime.ia6t_preferred < now.tv_sec ? "0" : sec2str(lifetime.ia6t_preferred - now.tv_sec)); } else - printf("infty "); + printf(" infty"); - printf("vltime "); + printf(" vltime"); if (lifetime.ia6t_expire) { - printf("%s ", lifetime.ia6t_expire < now.tv_sec + printf(" %s", lifetime.ia6t_expire < now.tv_sec ? "0" : sec2str(lifetime.ia6t_expire - now.tv_sec)); } else - printf("infty "); + printf(" infty"); } print_vhid(ifa, " "); @@ -524,6 +524,10 @@ static struct cmd inet6_cmds[] = { DEF_CMD_ARG("pltime", setip6pltime), DEF_CMD_ARG("vltime", setip6vltime), DEF_CMD("eui64", 0, setip6eui64), +#ifdef EXPERIMENTAL + DEF_CMD("ipv6_only", ND6_IFF_IPV6_ONLY_MANUAL,setnd6flags), + DEF_CMD("-ipv6_only", -ND6_IFF_IPV6_ONLY_MANUAL,setnd6flags), +#endif }; static struct afswtch af_inet6 = { diff --git a/freebsd/sbin/ifconfig/af_nd6.c b/freebsd/sbin/ifconfig/af_nd6.c index 964c96b0..c900e787 100644 --- a/freebsd/sbin/ifconfig/af_nd6.c +++ b/freebsd/sbin/ifconfig/af_nd6.c @@ -73,7 +73,7 @@ static const char rcsid[] = #define ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \ "\004IFDISABLED\005DONT_SET_IFROUTE\006AUTO_LINKLOCAL" \ "\007NO_RADR\010NO_PREFER_IFACE\011NO_DAD" \ - "\012IPV6_ONLY" \ + "\012IPV6_ONLY\013IPV6_ONLY_MANUAL" \ "\020DEFAULTIF" #else #define ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \ diff --git a/freebsd/sbin/ifconfig/ifconfig.c b/freebsd/sbin/ifconfig/ifconfig.c index 1e79e0cd..2a04b8cf 100644 --- a/freebsd/sbin/ifconfig/ifconfig.c +++ b/freebsd/sbin/ifconfig/ifconfig.c @@ -86,6 +86,7 @@ static const char rcsid[] = #ifdef JAIL #include <jail.h> #endif +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -129,6 +130,8 @@ static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl, static void tunnel_status(int s); static _Noreturn void usage(void); +static int getifflags(const char *ifname, int us); + static struct afswtch *af_getbyname(const char *name); static struct afswtch *af_getbyfamily(int af); static void af_other_status(int); @@ -146,6 +149,39 @@ struct ifa_order_elt { TAILQ_HEAD(ifa_queue, ifa_order_elt); +static struct module_map_entry { + const char *ifname; + const char *kldname; +} module_map[] = { + { + .ifname = "tun", + .kldname = "if_tuntap", + }, + { + .ifname = "tap", + .kldname = "if_tuntap", + }, + { + .ifname = "vmnet", + .kldname = "if_tuntap", + }, + { + .ifname = "ipsec", + .kldname = "ipsec", + }, + { + /* + * This mapping exists because there is a conflicting enc module + * in CAM. ifconfig's guessing behavior will attempt to match + * the ifname to a module as well as if_${ifname} and clash with + * CAM enc. This is an assertion of the correct module to load. + */ + .ifname = "enc", + .kldname = "if_enc", + }, +}; + + void opt_register(struct option *p) { @@ -437,6 +473,7 @@ main(int argc, char *argv[]) const char *ifname; struct option *p; size_t iflen; + int flags; #ifdef __rtems__ struct getopt_data getopt_data; memset(&getopt_data, 0, sizeof(getopt_data)); @@ -607,6 +644,25 @@ main(int argc, char *argv[]) argc--, argv++; } + /* + * Check for a requested configuration action on a single interface, + * 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); + if (!(((flags & IFF_CANTCONFIG) != 0) || + (downonly && (flags & IFF_UP) != 0) || + (uponly && (flags & IFF_UP) == 0))) + ifconfig(argc, argv, 0, afp); + } + goto done; + } + if (getifaddrs(&ifap) != 0) err(EXIT_FAILURE, "getifaddrs"); @@ -690,6 +746,7 @@ main(int argc, char *argv[]) printf("\n"); freeifaddrs(ifap); +done: freeformat(); exit(exit_code); } @@ -1101,6 +1158,28 @@ setifdstaddr(const char *addr, int param __unused, int s, afp->af_getaddr(addr, DSTADDR); } +static int +getifflags(const char *ifname, int us) +{ + struct ifreq my_ifr; + int s; + + memset(&my_ifr, 0, sizeof(my_ifr)); + (void) strlcpy(my_ifr.ifr_name, ifname, sizeof(my_ifr.ifr_name)); + if (us < 0) { + if ((s = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0) + err(1, "socket(family AF_LOCAL,SOCK_DGRAM"); + } else + s = us; + if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) { + Perror("ioctl (SIOCGIFFLAGS)"); + exit(1); + } + if (us < 0) + close(s); + return ((my_ifr.ifr_flags & 0xffff) | (my_ifr.ifr_flagshigh << 16)); +} + /* * Note: doing an SIOCIGIFFLAGS scribbles on the union portion * of the ifreq structure, which may confuse other parts of ifconfig. @@ -1112,20 +1191,14 @@ setifflags(const char *vname, int value, int s, const struct afswtch *afp) struct ifreq my_ifr; int flags; - memset(&my_ifr, 0, sizeof(my_ifr)); - (void) strlcpy(my_ifr.ifr_name, name, sizeof(my_ifr.ifr_name)); - - if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) { - Perror("ioctl (SIOCGIFFLAGS)"); - exit(1); - } - flags = (my_ifr.ifr_flags & 0xffff) | (my_ifr.ifr_flagshigh << 16); - + flags = getifflags(name, s); if (value < 0) { value = -value; flags &= ~value; } else flags |= value; + memset(&my_ifr, 0, sizeof(my_ifr)); + (void) strlcpy(my_ifr.ifr_name, name, 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) @@ -1265,7 +1338,7 @@ unsetifdescr(const char *val, int value, int s, const struct afswtch *afp) "\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" +"\26RXCSUM_IPV6\27TXCSUM_IPV6\31TXRTLMT\32HWRXTSTMP\33NOMAP\34TXTLS4\35TXTLS6" /* * Print the status of the interface. If an address family was @@ -1451,7 +1524,7 @@ print_vhid(const struct ifaddrs *ifa, const char *s) if (ifd->ifi_vhid == 0) return; - printf("vhid %d ", ifd->ifi_vhid); + printf(" vhid %d", ifd->ifi_vhid); } void @@ -1460,9 +1533,11 @@ ifmaybeload(const char *name) #ifndef __rtems__ #define MOD_PREFIX_LEN 3 /* "if_" */ struct module_stat mstat; - int fileid, modid; + int i, 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) @@ -1476,9 +1551,24 @@ ifmaybeload(const char *name) break; } - /* turn interface and unit into module name */ - strlcpy(ifkind, "if_", sizeof(ifkind)); - strlcat(ifkind, ifname, sizeof(ifkind)); + /* Either derive it from the map or guess otherwise */ + *ifkind = '\0'; + found = false; + for (i = 0; i < nitems(module_map); ++i) { + mme = &module_map[i]; + if (strcmp(mme->ifname, ifname) == 0) { + strlcpy(ifkind, mme->kldname, sizeof(ifkind)); + found = true; + break; + } + } + + /* We didn't have an alias for it... we'll guess. */ + if (!found) { + /* turn interface and unit into module name */ + strlcpy(ifkind, "if_", sizeof(ifkind)); + strlcat(ifkind, ifname, sizeof(ifkind)); + } /* scan files in kernel */ mstat.version = sizeof(struct module_stat); @@ -1494,8 +1584,12 @@ ifmaybeload(const char *name) } else { cp = mstat.name; } - /* already loaded? */ - if (strcmp(ifname, cp) == 0 || + /* + * Is it already loaded? Don't compare with ifname if + * we were specifically told which kld to use. Doing + * so could lead to conflicts not trivially solved. + */ + if ((!found && strcmp(ifname, cp) == 0) || strcmp(ifkind, cp) == 0) return; } @@ -1550,6 +1644,8 @@ static struct cmd basic_cmds[] = { DEF_CMD("-link2", -IFF_LINK2, setifflags), DEF_CMD("monitor", IFF_MONITOR, setifflags), DEF_CMD("-monitor", -IFF_MONITOR, setifflags), + DEF_CMD("nomap", IFCAP_NOMAP, setifcap), + DEF_CMD("-nomap", -IFCAP_NOMAP, setifcap), DEF_CMD("staticarp", IFF_STATICARP, setifflags), DEF_CMD("-staticarp", -IFF_STATICARP, setifflags), DEF_CMD("rxcsum6", IFCAP_RXCSUM_IPV6, setifcap), @@ -1576,6 +1672,8 @@ static struct cmd basic_cmds[] = { DEF_CMD("-toe", -IFCAP_TOE, setifcap), DEF_CMD("lro", IFCAP_LRO, setifcap), DEF_CMD("-lro", -IFCAP_LRO, setifcap), + DEF_CMD("txtls", IFCAP_TXTLS, setifcap), + DEF_CMD("-txtls", -IFCAP_TXTLS, setifcap), DEF_CMD("wol", IFCAP_WOL, setifcap), DEF_CMD("-wol", -IFCAP_WOL, setifcap), DEF_CMD("wol_ucast", IFCAP_WOL_UCAST, setifcap), diff --git a/freebsd/sbin/ifconfig/ifgre.c b/freebsd/sbin/ifconfig/ifgre.c index 2adc6d76..092e70c2 100644 --- a/freebsd/sbin/ifconfig/ifgre.c +++ b/freebsd/sbin/ifconfig/ifgre.c @@ -56,15 +56,16 @@ __FBSDID("$FreeBSD$"); #include "rtems-bsd-ifconfig-ifgre-data.h" #endif /* __rtems__ */ -#define GREBITS "\020\01ENABLE_CSUM\02ENABLE_SEQ" +#define GREBITS "\020\01ENABLE_CSUM\02ENABLE_SEQ\03UDPENCAP" static void gre_status(int s); static void gre_status(int s) { - uint32_t opts = 0; + uint32_t opts, port; + opts = 0; ifr.ifr_data = (caddr_t)&opts; if (ioctl(s, GREGKEY, &ifr) == 0) if (opts != 0) @@ -72,6 +73,11 @@ gre_status(int s) opts = 0; if (ioctl(s, GREGOPTS, &ifr) != 0 || opts == 0) return; + + port = 0; + ifr.ifr_data = (caddr_t)&port; + if (ioctl(s, GREGPORT, &ifr) == 0 && port != 0) + printf("\tudpport: %u\n", port); printb("\toptions", opts, GREBITS); putchar('\n'); } @@ -89,6 +95,18 @@ setifgrekey(const char *val, int dummy __unused, int s, } static void +setifgreport(const char *val, int dummy __unused, int s, + const struct afswtch *afp) +{ + uint32_t udpport = strtol(val, NULL, 0); + + strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); + ifr.ifr_data = (caddr_t)&udpport; + if (ioctl(s, GRESPORT, (caddr_t)&ifr) < 0) + warn("ioctl (set udpport)"); +} + +static void setifgreopts(const char *val, int d, int s, const struct afswtch *afp) { uint32_t opts; @@ -113,10 +131,13 @@ setifgreopts(const char *val, int d, int s, const struct afswtch *afp) static struct cmd gre_cmds[] = { DEF_CMD_ARG("grekey", setifgrekey), + DEF_CMD_ARG("udpport", setifgreport), DEF_CMD("enable_csum", GRE_ENABLE_CSUM, setifgreopts), DEF_CMD("-enable_csum",-GRE_ENABLE_CSUM,setifgreopts), DEF_CMD("enable_seq", GRE_ENABLE_SEQ, setifgreopts), DEF_CMD("-enable_seq",-GRE_ENABLE_SEQ, setifgreopts), + DEF_CMD("udpencap", GRE_UDPENCAP, setifgreopts), + DEF_CMD("-udpencap",-GRE_UDPENCAP, setifgreopts), }; static struct afswtch af_gre = { .af_name = "af_gre", diff --git a/freebsd/sbin/ifconfig/ifgroup.c b/freebsd/sbin/ifconfig/ifgroup.c index a487f060..fc1b826c 100644 --- a/freebsd/sbin/ifconfig/ifgroup.c +++ b/freebsd/sbin/ifconfig/ifgroup.c @@ -135,9 +135,9 @@ getifgroups(int s) len -= sizeof(struct ifg_req); if (strcmp(ifg->ifgrq_group, "all")) { if (cnt == 0) - printf("\tgroups: "); + printf("\tgroups:"); cnt++; - printf("%s ", ifg->ifgrq_group); + printf(" %s", ifg->ifgrq_group); } } if (cnt) diff --git a/freebsd/sbin/ifconfig/ifieee80211.c b/freebsd/sbin/ifconfig/ifieee80211.c index fa407957..08c91443 100644 --- a/freebsd/sbin/ifconfig/ifieee80211.c +++ b/freebsd/sbin/ifconfig/ifieee80211.c @@ -86,6 +86,7 @@ #include <net80211/ieee80211_superg.h> #include <net80211/ieee80211_tdma.h> #include <net80211/ieee80211_mesh.h> +#include <net80211/ieee80211_wps.h> #include <assert.h> #include <ctype.h> @@ -1539,9 +1540,6 @@ getmodeflags(const char *val) return flags; } -#define IEEE80211_CHAN_HTA (IEEE80211_CHAN_HT|IEEE80211_CHAN_5GHZ) -#define IEEE80211_CHAN_HTG (IEEE80211_CHAN_HT|IEEE80211_CHAN_2GHZ) - #define _APPLY(_flags, _base, _param, _v) do { \ if (_flags & IEEE80211_CHAN_HT) { \ if ((_flags & (IEEE80211_CHAN_5GHZ|IEEE80211_CHAN_2GHZ)) == 0) {\ @@ -1731,8 +1729,6 @@ DECL_CMD_FUNC(set80211maxretry, val, d) } #undef _APPLY_RATE #undef _APPLY -#undef IEEE80211_CHAN_HTA -#undef IEEE80211_CHAN_HTG static DECL_CMD_FUNC(set80211fragthreshold, val, d) @@ -3141,13 +3137,6 @@ printrsnie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) } } -/* XXX move to a public include file */ -#define IEEE80211_WPS_DEV_PASS_ID 0x1012 -#define IEEE80211_WPS_SELECTED_REG 0x1041 -#define IEEE80211_WPS_SETUP_STATE 0x1044 -#define IEEE80211_WPS_UUID_E 0x1047 -#define IEEE80211_WPS_VERSION 0x104a - #define BE_READ_2(p) \ ((u_int16_t) \ ((((const u_int8_t *)(p))[1] ) | \ @@ -3169,6 +3158,7 @@ printwpsie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) "R" /* Registrar-specified */ }; int n; + int f; ie +=6, len -= 4; /* NB: len is payload only */ @@ -3177,6 +3167,7 @@ printwpsie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) while (len) { uint16_t tlv_type = BE_READ_2(ie); uint16_t tlv_len = BE_READ_2(ie + 2); + uint16_t cfg_mthd; /* some devices broadcast invalid WPS frames */ if (tlv_len > len) { @@ -3189,30 +3180,191 @@ printwpsie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen) ie += 4, len -= 4; switch (tlv_type) { - case IEEE80211_WPS_VERSION: + case IEEE80211_WPS_ATTR_VERSION: printf("v:%d.%d", *ie >> 4, *ie & 0xf); break; - case IEEE80211_WPS_SETUP_STATE: - /* Only 1 and 2 are valid */ - if (*ie == 0 || *ie >= 3) - printf(" state:B"); + case IEEE80211_WPS_ATTR_AP_SETUP_LOCKED: + printf(" ap_setup:%s", *ie ? "locked" : + "unlocked"); + break; + case IEEE80211_WPS_ATTR_CONFIG_METHODS: + case IEEE80211_WPS_ATTR_SELECTED_REGISTRAR_CONFIG_METHODS: + if (tlv_type == IEEE80211_WPS_ATTR_SELECTED_REGISTRAR_CONFIG_METHODS) + printf(" sel_reg_cfg_mthd:"); else - printf(" st:%s", *ie == 1 ? "N" : "C"); + printf(" cfg_mthd:" ); + cfg_mthd = BE_READ_2(ie); + f = 0; + for (n = 15; n >= 0; n--) { + if (f) { + printf(","); + f = 0; + } + switch (cfg_mthd & (1 << n)) { + case 0: + break; + case IEEE80211_WPS_CONFIG_USBA: + printf("usba"); + f++; + break; + case IEEE80211_WPS_CONFIG_ETHERNET: + printf("ethernet"); + f++; + break; + case IEEE80211_WPS_CONFIG_LABEL: + printf("label"); + f++; + break; + case IEEE80211_WPS_CONFIG_DISPLAY: + if (!(cfg_mthd & + (IEEE80211_WPS_CONFIG_VIRT_DISPLAY | + IEEE80211_WPS_CONFIG_PHY_DISPLAY))) + { + printf("display"); + f++; + } + break; + case IEEE80211_WPS_CONFIG_EXT_NFC_TOKEN: + printf("ext_nfc_tokenk"); + f++; + break; + case IEEE80211_WPS_CONFIG_INT_NFC_TOKEN: + printf("int_nfc_token"); + f++; + break; + case IEEE80211_WPS_CONFIG_NFC_INTERFACE: + printf("nfc_interface"); + f++; + break; + case IEEE80211_WPS_CONFIG_PUSHBUTTON: + if (!(cfg_mthd & + (IEEE80211_WPS_CONFIG_VIRT_PUSHBUTTON | + IEEE80211_WPS_CONFIG_PHY_PUSHBUTTON))) { + printf("push_button"); + f++; + } + break; + case IEEE80211_WPS_CONFIG_KEYPAD: + printf("keypad"); + f++; + break; + case IEEE80211_WPS_CONFIG_VIRT_PUSHBUTTON: + printf("virtual_push_button"); + f++; + break; + case IEEE80211_WPS_CONFIG_PHY_PUSHBUTTON: + printf("physical_push_button"); + f++; + break; + case IEEE80211_WPS_CONFIG_P2PS: + printf("p2ps"); + f++; + break; + case IEEE80211_WPS_CONFIG_VIRT_DISPLAY: + printf("virtual_display"); + f++; + break; + case IEEE80211_WPS_CONFIG_PHY_DISPLAY: + printf("physical_display"); + f++; + break; + default: + printf("unknown_wps_config<%04x>", + cfg_mthd & (1 << n)); + f++; + break; + } + } break; - case IEEE80211_WPS_SELECTED_REG: - printf(" sel:%s", *ie ? "T" : "F"); + case IEEE80211_WPS_ATTR_DEV_NAME: + printf(" device_name:<%.*s>", tlv_len, ie); break; - case IEEE80211_WPS_DEV_PASS_ID: + case IEEE80211_WPS_ATTR_DEV_PASSWORD_ID: n = LE_READ_2(ie); if (n < nitems(dev_pass_id)) printf(" dpi:%s", dev_pass_id[n]); break; - case IEEE80211_WPS_UUID_E: + case IEEE80211_WPS_ATTR_MANUFACTURER: + printf(" manufacturer:<%.*s>", tlv_len, ie); + break; + case IEEE80211_WPS_ATTR_MODEL_NAME: + printf(" model_name:<%.*s>", tlv_len, ie); + break; + case IEEE80211_WPS_ATTR_MODEL_NUMBER: + printf(" model_number:<%.*s>", tlv_len, ie); + break; + case IEEE80211_WPS_ATTR_PRIMARY_DEV_TYPE: + printf(" prim_dev:"); + for (n = 0; n < tlv_len; n++) + printf("%02x", ie[n]); + break; + case IEEE80211_WPS_ATTR_RF_BANDS: + printf(" rf:"); + f = 0; + for (n = 7; n >= 0; n--) { + if (f) { + printf(","); + f = 0; + } + switch (*ie & (1 << n)) { + case 0: + break; + case IEEE80211_WPS_RF_BAND_24GHZ: + printf("2.4Ghz"); + f++; + break; + case IEEE80211_WPS_RF_BAND_50GHZ: + printf("5Ghz"); + f++; + break; + case IEEE80211_WPS_RF_BAND_600GHZ: + printf("60Ghz"); + f++; + break; + default: + printf("unknown<%02x>", + *ie & (1 << n)); + f++; + break; + } + } + break; + case IEEE80211_WPS_ATTR_RESPONSE_TYPE: + printf(" resp_type:0x%02x", *ie); + break; + case IEEE80211_WPS_ATTR_SELECTED_REGISTRAR: + printf(" sel:%s", *ie ? "T" : "F"); + break; + case IEEE80211_WPS_ATTR_SERIAL_NUMBER: + printf(" serial_number:<%.*s>", tlv_len, ie); + break; + case IEEE80211_WPS_ATTR_UUID_E: printf(" uuid-e:"); for (n = 0; n < (tlv_len - 1); n++) printf("%02x-", ie[n]); printf("%02x", ie[n]); break; + case IEEE80211_WPS_ATTR_VENDOR_EXT: + printf(" vendor:"); + for (n = 0; n < tlv_len; n++) + printf("%02x", ie[n]); + break; + case IEEE80211_WPS_ATTR_WPS_STATE: + switch (*ie) { + case IEEE80211_WPS_STATE_NOT_CONFIGURED: + printf(" state:N"); + break; + case IEEE80211_WPS_STATE_CONFIGURED: + printf(" state:C"); + break; + default: + printf(" state:B<%02x>", *ie); + break; + } + break; + default: + printf(" unknown_wps_attr:0x%x", tlv_type); + break; } ie += tlv_len, len -= tlv_len; } @@ -3365,6 +3517,7 @@ iswpsoui(const uint8_t *frm) static const char * iename(int elemid) { + static char iename_buf[64]; switch (elemid) { case IEEE80211_ELEMID_FHPARMS: return " FHPARMS"; case IEEE80211_ELEMID_CFPARMS: return " CFPARMS"; @@ -3382,10 +3535,21 @@ iename(int elemid) case IEEE80211_ELEMID_MEASREP: return " MEASREP"; case IEEE80211_ELEMID_QUIET: return " QUIET"; case IEEE80211_ELEMID_IBSSDFS: return " IBSSDFS"; + case IEEE80211_ELEMID_RESERVED_47: + return " RESERVED_47"; + case IEEE80211_ELEMID_MOBILITY_DOMAIN: + return " MOBILITY_DOMAIN"; + case IEEE80211_ELEMID_RRM_ENACAPS: + return " RRM_ENCAPS"; + case IEEE80211_ELEMID_OVERLAP_BSS_SCAN_PARAM: + return " OVERLAP_BSS"; case IEEE80211_ELEMID_TPC: return " TPC"; case IEEE80211_ELEMID_CCKM: return " CCKM"; + case IEEE80211_ELEMID_EXTCAP: return " EXTCAP"; } - return " ???"; + snprintf(iename_buf, sizeof(iename_buf), " UNKNOWN_ELEMID_%d", + elemid); + return (const char *) iename_buf; } static void @@ -4153,7 +4317,10 @@ list_roam(int s) rp = &roamparams.params[mode]; if (rp->rssi == 0 && rp->rate == 0) continue; - if (mode == IEEE80211_MODE_11NA || mode == IEEE80211_MODE_11NG) { + if (mode == IEEE80211_MODE_11NA || + mode == IEEE80211_MODE_11NG || + mode == IEEE80211_MODE_VHT_2GHZ || + mode == IEEE80211_MODE_VHT_5GHZ) { if (rp->rssi & 1) LINE_CHECK("roam:%-7.7s rssi %2u.5dBm MCS %2u ", modename[mode], rp->rssi/2, @@ -4173,6 +4340,21 @@ list_roam(int s) } } +/* XXX TODO: rate-to-string method... */ +static const char* +get_mcs_mbs_rate_str(uint8_t rate) +{ + return (rate & IEEE80211_RATE_MCS) ? "MCS " : "Mb/s"; +} + +static uint8_t +get_rate_value(uint8_t rate) +{ + if (rate & IEEE80211_RATE_MCS) + return (rate &~ IEEE80211_RATE_MCS); + return (rate / 2); +} + static void list_txparams(int s) { @@ -4184,21 +4366,28 @@ list_txparams(int s) tp = &txparams.params[mode]; if (tp->mgmtrate == 0 && tp->mcastrate == 0) continue; - if (mode == IEEE80211_MODE_11NA || mode == IEEE80211_MODE_11NG) { + if (mode == IEEE80211_MODE_11NA || + mode == IEEE80211_MODE_11NG || + mode == IEEE80211_MODE_VHT_2GHZ || + mode == IEEE80211_MODE_VHT_5GHZ) { if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) - LINE_CHECK("%-7.7s ucast NONE mgmt %2u MCS " - "mcast %2u MCS maxretry %u", + LINE_CHECK("%-7.7s ucast NONE mgmt %2u %s " + "mcast %2u %s maxretry %u", modename[mode], - tp->mgmtrate &~ IEEE80211_RATE_MCS, - tp->mcastrate &~ IEEE80211_RATE_MCS, + get_rate_value(tp->mgmtrate), + get_mcs_mbs_rate_str(tp->mgmtrate), + get_rate_value(tp->mcastrate), + get_mcs_mbs_rate_str(tp->mcastrate), tp->maxretry); else - LINE_CHECK("%-7.7s ucast %2u MCS mgmt %2u MCS " - "mcast %2u MCS maxretry %u", + LINE_CHECK("%-7.7s ucast %2u MCS mgmt %2u %s " + "mcast %2u %s maxretry %u", modename[mode], tp->ucastrate &~ IEEE80211_RATE_MCS, - tp->mgmtrate &~ IEEE80211_RATE_MCS, - tp->mcastrate &~ IEEE80211_RATE_MCS, + get_rate_value(tp->mgmtrate), + get_mcs_mbs_rate_str(tp->mgmtrate), + get_rate_value(tp->mcastrate), + get_mcs_mbs_rate_str(tp->mcastrate), tp->maxretry); } else { if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) @@ -4907,7 +5096,9 @@ end: LINE_CHECK("roam:rssi %u.5", rp->rssi/2); else LINE_CHECK("roam:rssi %u", rp->rssi/2); - LINE_CHECK("roam:rate %u", rp->rate/2); + LINE_CHECK("roam:rate %s%u", + (rp->rate & IEEE80211_RATE_MCS) ? "MCS " : "", + get_rate_value(rp->rate)); } else { LINE_BREAK(); list_roam(s); diff --git a/freebsd/sbin/ifconfig/iflagg.c b/freebsd/sbin/ifconfig/iflagg.c index 4952196a..14a7a7bf 100644 --- a/freebsd/sbin/ifconfig/iflagg.c +++ b/freebsd/sbin/ifconfig/iflagg.c @@ -142,6 +142,8 @@ setlaggsetopt(const char *val, int d, int s, const struct afswtch *afp) switch (ro.ro_opts) { case LAGG_OPT_USE_FLOWID: case -LAGG_OPT_USE_FLOWID: + case LAGG_OPT_USE_NUMA: + case -LAGG_OPT_USE_NUMA: case LAGG_OPT_LACP_STRICT: case -LAGG_OPT_LACP_STRICT: case LAGG_OPT_LACP_TXTEST: @@ -315,6 +317,8 @@ static struct cmd lagg_cmds[] = { DEF_CMD_ARG("lagghash", setlagghash), DEF_CMD("use_flowid", LAGG_OPT_USE_FLOWID, setlaggsetopt), DEF_CMD("-use_flowid", -LAGG_OPT_USE_FLOWID, setlaggsetopt), + DEF_CMD("use_numa", LAGG_OPT_USE_NUMA, setlaggsetopt), + DEF_CMD("-use_numa", -LAGG_OPT_USE_NUMA, setlaggsetopt), DEF_CMD("lacp_strict", LAGG_OPT_LACP_STRICT, setlaggsetopt), DEF_CMD("-lacp_strict", -LAGG_OPT_LACP_STRICT, setlaggsetopt), DEF_CMD("lacp_txtest", LAGG_OPT_LACP_TXTEST, setlaggsetopt), diff --git a/freebsd/sbin/ifconfig/ifmedia.c b/freebsd/sbin/ifconfig/ifmedia.c index ac2af8b6..02893547 100644 --- a/freebsd/sbin/ifconfig/ifmedia.c +++ b/freebsd/sbin/ifconfig/ifmedia.c @@ -89,6 +89,7 @@ #include <err.h> #include <errno.h> #include <fcntl.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -137,18 +138,20 @@ static void media_status(int s) { struct ifmediareq ifmr; + struct ifdownreason ifdr; int *media_list, i; - int xmedia = 1; + bool no_carrier, xmedia; (void) memset(&ifmr, 0, sizeof(ifmr)); (void) strlcpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); + xmedia = true; /* * Check if interface supports extended media types. */ if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)&ifmr) < 0) - xmedia = 0; - if (xmedia == 0 && ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { + xmedia = false; + if (!xmedia && ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { /* * Interface doesn't support SIOC{G,S}IFMEDIA. */ @@ -185,6 +188,7 @@ media_status(int s) putchar('\n'); if (ifmr.ifm_status & IFM_AVALID) { + no_carrier = false; printf("\tstatus: "); switch (IFM_TYPE(ifmr.ifm_active)) { case IFM_ETHER: @@ -192,7 +196,7 @@ media_status(int s) if (ifmr.ifm_status & IFM_ACTIVE) printf("active"); else - printf("no carrier"); + no_carrier = true; break; case IFM_IEEE80211: @@ -203,9 +207,27 @@ media_status(int s) else printf("running"); } else - printf("no carrier"); + no_carrier = true; break; } + if (no_carrier) { + printf("no carrier"); + memset(&ifdr, 0, sizeof(ifdr)); + strlcpy(ifdr.ifdr_name, name, sizeof(ifdr.ifdr_name)); + if (ioctl(s, SIOCGIFDOWNREASON, (caddr_t)&ifdr) == 0) { + switch (ifdr.ifdr_reason) { + case IFDR_REASON_MSG: + printf(" (%s)", ifdr.ifdr_msg); + break; + case IFDR_REASON_VENDOR: + printf(" (vendor code %d)", + ifdr.ifdr_vendor); + break; + default: + break; + } + } + } putchar('\n'); } diff --git a/freebsd/sbin/ifconfig/ifpfsync.c b/freebsd/sbin/ifconfig/ifpfsync.c index c2c91687..944a1b26 100644 --- a/freebsd/sbin/ifconfig/ifpfsync.c +++ b/freebsd/sbin/ifconfig/ifpfsync.c @@ -207,16 +207,16 @@ pfsync_status(int s) return; if (preq.pfsyncr_syncdev[0] != '\0' || - preq.pfsyncr_syncpeer.s_addr != INADDR_PFSYNC_GROUP) + 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 != INADDR_PFSYNC_GROUP) + 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 != INADDR_PFSYNC_GROUP) { + preq.pfsyncr_syncpeer.s_addr != htonl(INADDR_PFSYNC_GROUP)) { printf("maxupd: %d ", preq.pfsyncr_maxupdates); printf("defer: %s\n", preq.pfsyncr_defer ? "on" : "off"); } diff --git a/freebsd/sbin/ifconfig/sfp.c b/freebsd/sbin/ifconfig/sfp.c index 0aa3300d..6444736f 100644 --- a/freebsd/sbin/ifconfig/sfp.c +++ b/freebsd/sbin/ifconfig/sfp.c @@ -88,7 +88,7 @@ struct _nv { const char *find_value(struct _nv *x, int value); const char *find_zero_bit(struct _nv *x, int value, int sz); -/* SFF-8024 Rev. 4.1 Table 4-3: Connector Types */ +/* SFF-8024 Rev. 4.6 Table 4-3: Connector Types */ static struct _nv conn[] = { { 0x00, "Unknown" }, { 0x01, "SC" }, @@ -96,18 +96,23 @@ static struct _nv conn[] = { { 0x03, "Fibre Channel Style 2 copper" }, { 0x04, "BNC/TNC" }, { 0x05, "Fibre Channel coaxial" }, - { 0x06, "FiberJack" }, + { 0x06, "Fiber Jack" }, { 0x07, "LC" }, { 0x08, "MT-RJ" }, { 0x09, "MU" }, { 0x0A, "SG" }, { 0x0B, "Optical pigtail" }, - { 0x0C, "MPO Parallel Optic" }, + { 0x0C, "MPO 1x12 Parallel Optic" }, + { 0x0D, "MPO 2x16 Parallel Optic" }, { 0x20, "HSSDC II" }, { 0x21, "Copper pigtail" }, { 0x22, "RJ45" }, { 0x23, "No separable connector" }, { 0x24, "MXC 2x16" }, + { 0x25, "CS optical connector" }, + { 0x26, "Mini CS optical connector" }, + { 0x27, "MPO 2x12 Parallel Optic" }, + { 0x28, "MPO 1x16 Parallel Optic" }, { 0, NULL } }; @@ -203,9 +208,61 @@ static struct _nv eth_1040g[] = { }; #define SFF_8636_EXT_COMPLIANCE 0x80 -/* SFF-8024 Rev. 4.2 table 4-4: Extended Specification Compliance */ +/* SFF-8024 Rev. 4.6 table 4-4: Extended Specification Compliance */ static struct _nv eth_extended_comp[] = { { 0xFF, "Reserved" }, + { 0x55, "128GFC LW" }, + { 0x54, "128GFC SW" }, + { 0x53, "128GFC EA" }, + { 0x52, "64GFC LW" }, + { 0x51, "64GFC SW" }, + { 0x50, "64GFC EA" }, + { 0x4F, "Reserved" }, + { 0x4E, "Reserved" }, + { 0x4D, "Reserved" }, + { 0x4C, "Reserved" }, + { 0x4B, "Reserved" }, + { 0x4A, "Reserved" }, + { 0x49, "Reserved" }, + { 0x48, "Reserved" }, + { 0x47, "Reserved" }, + { 0x46, "200GBASE-LR4" }, + { 0x45, "50GBASE-LR" }, + { 0x44, "200G 1550nm PSM4" }, + { 0x43, "200GBASE-FR4" }, + { 0x42, "50GBASE-FR or 200GBASE-DR4" }, + { 0x41, "50GBASE-SR/100GBASE-SR2/200GBASE-SR4" }, + { 0x40, "50GBASE-CR/100GBASE-CR2/200GBASE-CR4" }, + { 0x3F, "Reserved" }, + { 0x3E, "Reserved" }, + { 0x3D, "Reserved" }, + { 0x3C, "Reserved" }, + { 0x3B, "Reserved" }, + { 0x3A, "Reserved" }, + { 0x39, "Reserved" }, + { 0x38, "Reserved" }, + { 0x37, "Reserved" }, + { 0x36, "Reserved" }, + { 0x35, "Reserved" }, + { 0x34, "Reserved" }, + { 0x33, "50GAUI/100GAUI-2/200GAUI-4 AOC (BER <2.6e-4)" }, + { 0x32, "50GAUI/100GAUI-2/200GAUI-4 ACC (BER <2.6e-4)" }, + { 0x31, "50GAUI/100GAUI-2/200GAUI-4 AOC (BER <1e-6)" }, + { 0x30, "50GAUI/100GAUI-2/200GAUI-4 ACC (BER <1e-6)" }, + { 0x2F, "Reserved" }, + { 0x2E, "Reserved" }, + { 0x2D, "Reserved" }, + { 0x2C, "Reserved" }, + { 0x2B, "Reserved" }, + { 0x2A, "Reserved" }, + { 0x29, "Reserved" }, + { 0x28, "Reserved" }, + { 0x27, "100G-LR" }, + { 0x26, "100G-FR" }, + { 0x25, "100GBASE-DR" }, + { 0x24, "4WDM-40 MSA" }, + { 0x23, "4WDM-20 MSA" }, + { 0x22, "4WDM-10 MSA" }, { 0x21, "100G PAM4 BiDi" }, { 0x20, "100G SWDM4" }, { 0x1F, "40G SWDM4" }, @@ -226,8 +283,8 @@ static struct _nv eth_extended_comp[] = { { 0x10, "40GBASE-ER4" }, { 0x0F, "Reserved" }, { 0x0E, "Reserved" }, - { 0x0D, "25GBASE-CR CA-N" }, - { 0x0C, "25GBASE-CR CA-S" }, + { 0x0D, "25GBASE-CR CA-25G-N" }, + { 0x0C, "25GBASE-CR CA-25G-S" }, { 0x0B, "100GBASE-CR4 or 25GBASE-CR CA-L" }, { 0x0A, "Reserved" }, { 0x09, "Obsolete" }, diff --git a/freebsd/sbin/pfctl/parse.c b/freebsd/sbin/pfctl/parse.c index 83002a82..9cd303fb 100644 --- a/freebsd/sbin/pfctl/parse.c +++ b/freebsd/sbin/pfctl/parse.c @@ -157,6 +157,7 @@ __FBSDID("$FreeBSD$"); #include "pfctl_parser.h" #include "pfctl.h" #ifdef __rtems__ +#include <sys/limits.h> #include "rtems-bsd-pfctl-parse-data.h" #endif /* __rtems__ */ diff --git a/freebsd/sbin/pfctl/parse.y b/freebsd/sbin/pfctl/parse.y index 8b6808a6..856f7b2a 100644 --- a/freebsd/sbin/pfctl/parse.y +++ b/freebsd/sbin/pfctl/parse.y @@ -4764,6 +4764,8 @@ process_tabledef(char *name, struct table_opts *opts) { struct pfr_buffer ab; struct node_tinit *ti; + unsigned long maxcount; + size_t s = sizeof(maxcount); bzero(&ab, sizeof(ab)); ab.pfrb_type = PFRB_ADDRS; @@ -4791,8 +4793,19 @@ process_tabledef(char *name, struct table_opts *opts) if (!(pf->opts & PF_OPT_NOACTION) && pfctl_define_table(name, opts->flags, opts->init_addr, pf->anchor->name, &ab, pf->anchor->ruleset.tticket)) { - yyerror("cannot define table %s: %s", name, - pfr_strerror(errno)); + + if (sysctlbyname("net.pf.request_maxcount", &maxcount, &s, + NULL, 0) == -1) + maxcount = 65535; + + if (ab.pfrb_size > maxcount) + yyerror("cannot define table %s: too many elements.\n" + "Consider increasing net.pf.request_maxcount.", + name); + else + yyerror("cannot define table %s: %s", name, + pfr_strerror(errno)); + goto _error; } pf->tdirty = 1; diff --git a/freebsd/sbin/pfctl/pfctl.c b/freebsd/sbin/pfctl/pfctl.c index 6b57dd00..274ea26f 100644 --- a/freebsd/sbin/pfctl/pfctl.c +++ b/freebsd/sbin/pfctl/pfctl.c @@ -2005,6 +2005,7 @@ int pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how) { struct pfioc_iface pi; + struct node_host *h = NULL, *n = NULL; if ((loadopt & PFCTL_FLAG_OPTION) == 0) return (0); @@ -2013,6 +2014,12 @@ pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how) pi.pfiio_flags = flags; + /* Make sure our cache matches the kernel. If we set or clear the flag + * for a group this applies to all members. */ + h = ifa_grouplookup(ifname, 0); + for (n = h; n != NULL; n = n->next) + pfctl_set_interface_flags(pf, n->ifname, flags, how); + if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >= sizeof(pi.pfiio_name)) errx(1, "pfctl_set_interface_flags: strlcpy"); diff --git a/freebsd/sbin/pfctl/pfctl.h b/freebsd/sbin/pfctl/pfctl.h index a432f109..f43b71e1 100644 --- a/freebsd/sbin/pfctl/pfctl.h +++ b/freebsd/sbin/pfctl/pfctl.h @@ -114,7 +114,6 @@ extern int loadopt; int check_commit_altq(int, int); void pfaltq_store(struct pf_altq *); -struct pf_altq *pfaltq_lookup(const char *); char *rate2str(double); void print_addr(struct pf_addr_wrap *, sa_family_t, int); diff --git a/freebsd/sbin/pfctl/pfctl_altq.c b/freebsd/sbin/pfctl/pfctl_altq.c index 1220cfc6..7cf72b43 100644 --- a/freebsd/sbin/pfctl/pfctl_altq.c +++ b/freebsd/sbin/pfctl/pfctl_altq.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #define PFIOC_USE_LATEST #include <sys/types.h> +#include <sys/bitset.h> #include <sys/ioctl.h> #include <sys/socket.h> @@ -45,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include <inttypes.h> #include <limits.h> #include <math.h> +#include <search.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -65,38 +67,44 @@ __FBSDID("$FreeBSD$"); #define is_sc_null(sc) (((sc) == NULL) || ((sc)->m1 == 0 && (sc)->m2 == 0)) -static TAILQ_HEAD(altqs, pf_altq) altqs = TAILQ_HEAD_INITIALIZER(altqs); -static LIST_HEAD(gen_sc, segment) rtsc, lssc; +static STAILQ_HEAD(interfaces, pfctl_altq) interfaces = STAILQ_HEAD_INITIALIZER(interfaces); +static struct hsearch_data queue_map; +static struct hsearch_data if_map; +static struct hsearch_data qid_map; -struct pf_altq *qname_to_pfaltq(const char *, const char *); -u_int32_t qname_to_qid(const char *); +static struct pfctl_altq *pfaltq_lookup(char *ifname); +static struct pfctl_altq *qname_to_pfaltq(const char *, const char *); +static u_int32_t qname_to_qid(char *); -static int eval_pfqueue_cbq(struct pfctl *, struct pf_altq *); +static int eval_pfqueue_cbq(struct pfctl *, struct pf_altq *, + struct pfctl_altq *); static int cbq_compute_idletime(struct pfctl *, struct pf_altq *); -static int check_commit_cbq(int, int, struct pf_altq *); +static int check_commit_cbq(int, int, struct pfctl_altq *); static int print_cbq_opts(const struct pf_altq *); static int print_codel_opts(const struct pf_altq *, const struct node_queue_opt *); -static int eval_pfqueue_priq(struct pfctl *, struct pf_altq *); -static int check_commit_priq(int, int, struct pf_altq *); +static int eval_pfqueue_priq(struct pfctl *, struct pf_altq *, + struct pfctl_altq *); +static int check_commit_priq(int, int, struct pfctl_altq *); static int print_priq_opts(const struct pf_altq *); -static int eval_pfqueue_hfsc(struct pfctl *, struct pf_altq *); -static int check_commit_hfsc(int, int, struct pf_altq *); +static int eval_pfqueue_hfsc(struct pfctl *, struct pf_altq *, + struct pfctl_altq *, struct pfctl_altq *); +static int check_commit_hfsc(int, int, struct pfctl_altq *); static int print_hfsc_opts(const struct pf_altq *, const struct node_queue_opt *); -static int eval_pfqueue_fairq(struct pfctl *, struct pf_altq *); +static int eval_pfqueue_fairq(struct pfctl *, struct pf_altq *, + struct pfctl_altq *, struct pfctl_altq *); static int print_fairq_opts(const struct pf_altq *, const struct node_queue_opt *); -static int check_commit_fairq(int, int, struct pf_altq *); +static int check_commit_fairq(int, int, struct pfctl_altq *); static void gsc_add_sc(struct gen_sc *, struct service_curve *); static int is_gsc_under_sc(struct gen_sc *, struct service_curve *); -static void gsc_destroy(struct gen_sc *); static struct segment *gsc_getentry(struct gen_sc *, double); static int gsc_add_seg(struct gen_sc *, double, double, double, double); @@ -116,59 +124,101 @@ void print_hfsc_sc(const char *, u_int, u_int, u_int, void print_fairq_sc(const char *, u_int, u_int, u_int, const struct node_fairq_sc *); +static __attribute__((constructor)) void +pfctl_altq_init(void) +{ + /* + * As hdestroy() will never be called on these tables, it will be + * safe to use references into the stored data as keys. + */ + if (hcreate_r(0, &queue_map) == 0) + err(1, "Failed to create altq queue map"); + if (hcreate_r(0, &if_map) == 0) + err(1, "Failed to create altq interface map"); + if (hcreate_r(0, &qid_map) == 0) + err(1, "Failed to create altq queue id map"); +} + void pfaltq_store(struct pf_altq *a) { - struct pf_altq *altq; - + struct pfctl_altq *altq; + ENTRY item; + ENTRY *ret_item; + size_t key_size; + if ((altq = malloc(sizeof(*altq))) == NULL) - err(1, "malloc"); - memcpy(altq, a, sizeof(struct pf_altq)); - TAILQ_INSERT_TAIL(&altqs, altq, entries); + err(1, "queue malloc"); + memcpy(&altq->pa, a, sizeof(struct pf_altq)); + memset(&altq->meta, 0, sizeof(altq->meta)); + + if (a->qname[0] == 0) { + item.key = altq->pa.ifname; + item.data = altq; + if (hsearch_r(item, ENTER, &ret_item, &if_map) == 0) + err(1, "interface map insert"); + STAILQ_INSERT_TAIL(&interfaces, altq, meta.link); + } else { + key_size = sizeof(a->ifname) + sizeof(a->qname); + if ((item.key = malloc(key_size)) == NULL) + err(1, "queue map key malloc"); + snprintf(item.key, key_size, "%s:%s", a->ifname, a->qname); + item.data = altq; + if (hsearch_r(item, ENTER, &ret_item, &queue_map) == 0) + err(1, "queue map insert"); + + item.key = altq->pa.qname; + item.data = &altq->pa.qid; + if (hsearch_r(item, ENTER, &ret_item, &qid_map) == 0) + err(1, "qid map insert"); + } } -struct pf_altq * -pfaltq_lookup(const char *ifname) +static struct pfctl_altq * +pfaltq_lookup(char *ifname) { - struct pf_altq *altq; + ENTRY item; + ENTRY *ret_item; - TAILQ_FOREACH(altq, &altqs, entries) { - if (strncmp(ifname, altq->ifname, IFNAMSIZ) == 0 && - altq->qname[0] == 0) - return (altq); - } - return (NULL); + item.key = ifname; + if (hsearch_r(item, FIND, &ret_item, &if_map) == 0) + return (NULL); + + return (ret_item->data); } -struct pf_altq * +static struct pfctl_altq * qname_to_pfaltq(const char *qname, const char *ifname) { - struct pf_altq *altq; + ENTRY item; + ENTRY *ret_item; + char key[IFNAMSIZ + PF_QNAME_SIZE]; - TAILQ_FOREACH(altq, &altqs, entries) { - if (strncmp(ifname, altq->ifname, IFNAMSIZ) == 0 && - strncmp(qname, altq->qname, PF_QNAME_SIZE) == 0) - return (altq); - } - return (NULL); + item.key = key; + snprintf(item.key, sizeof(key), "%s:%s", ifname, qname); + if (hsearch_r(item, FIND, &ret_item, &queue_map) == 0) + return (NULL); + + return (ret_item->data); } -u_int32_t -qname_to_qid(const char *qname) +static u_int32_t +qname_to_qid(char *qname) { - struct pf_altq *altq; - + ENTRY item; + ENTRY *ret_item; + uint32_t qid; + /* * We guarantee that same named queues on different interfaces - * have the same qid, so we do NOT need to limit matching on - * one interface! + * have the same qid. */ + item.key = qname; + if (hsearch_r(item, FIND, &ret_item, &qid_map) == 0) + return (0); - TAILQ_FOREACH(altq, &altqs, entries) { - if (strncmp(qname, altq->qname, PF_QNAME_SIZE) == 0) - return (altq->qid); - } - return (0); + qid = *(uint32_t *)ret_item->data; + return (qid); } void @@ -327,28 +377,26 @@ eval_pfaltq(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw, int check_commit_altq(int dev, int opts) { - struct pf_altq *altq; - int error = 0; + struct pfctl_altq *if_ppa; + int error = 0; /* call the discipline check for each interface. */ - TAILQ_FOREACH(altq, &altqs, entries) { - if (altq->qname[0] == 0) { - switch (altq->scheduler) { - case ALTQT_CBQ: - error = check_commit_cbq(dev, opts, altq); - break; - case ALTQT_PRIQ: - error = check_commit_priq(dev, opts, altq); - break; - case ALTQT_HFSC: - error = check_commit_hfsc(dev, opts, altq); - break; - case ALTQT_FAIRQ: - error = check_commit_fairq(dev, opts, altq); - break; - default: - break; - } + STAILQ_FOREACH(if_ppa, &interfaces, meta.link) { + switch (if_ppa->pa.scheduler) { + case ALTQT_CBQ: + error = check_commit_cbq(dev, opts, if_ppa); + break; + case ALTQT_PRIQ: + error = check_commit_priq(dev, opts, if_ppa); + break; + case ALTQT_HFSC: + error = check_commit_hfsc(dev, opts, if_ppa); + break; + case ALTQT_FAIRQ: + error = check_commit_fairq(dev, opts, if_ppa); + break; + default: + break; } } return (error); @@ -362,17 +410,16 @@ eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw, struct node_queue_opt *opts) { /* should be merged with expand_queue */ - struct pf_altq *if_pa, *parent, *altq; - u_int64_t bwsum; - int error = 0; + struct pfctl_altq *if_ppa, *parent; + int error = 0; /* find the corresponding interface and copy fields used by queues */ - if ((if_pa = pfaltq_lookup(pa->ifname)) == NULL) { + if ((if_ppa = pfaltq_lookup(pa->ifname)) == NULL) { fprintf(stderr, "altq not defined on %s\n", pa->ifname); return (1); } - pa->scheduler = if_pa->scheduler; - pa->ifbandwidth = if_pa->ifbandwidth; + pa->scheduler = if_ppa->pa.scheduler; + pa->ifbandwidth = if_ppa->pa.ifbandwidth; if (qname_to_pfaltq(pa->qname, pa->ifname) != NULL) { fprintf(stderr, "queue %s already exists on interface %s\n", @@ -389,7 +436,7 @@ eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw, pa->parent, pa->qname); return (1); } - pa->parent_qid = parent->qid; + pa->parent_qid = parent->pa.qid; } if (pa->qlimit == 0) pa->qlimit = DEFAULT_QLIMIT; @@ -397,53 +444,56 @@ eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw, if (pa->scheduler == ALTQT_CBQ || pa->scheduler == ALTQT_HFSC || pa->scheduler == ALTQT_FAIRQ) { pa->bandwidth = eval_bwspec(bw, - parent == NULL ? pa->ifbandwidth : parent->bandwidth); + parent == NULL ? pa->ifbandwidth : parent->pa.bandwidth); if (pa->bandwidth > pa->ifbandwidth) { fprintf(stderr, "bandwidth for %s higher than " "interface\n", pa->qname); return (1); } - /* check the sum of the child bandwidth is under parent's */ - if (parent != NULL) { - if (pa->bandwidth > parent->bandwidth) { + /* + * If not HFSC, then check that the sum of the child + * bandwidths is less than the parent's bandwidth. For + * HFSC, the equivalent concept is to check that the sum of + * the child linkshare service curves are under the parent's + * linkshare service curve, and that check is performed by + * eval_pfqueue_hfsc(). + */ + if ((parent != NULL) && (pa->scheduler != ALTQT_HFSC)) { + if (pa->bandwidth > parent->pa.bandwidth) { warnx("bandwidth for %s higher than parent", pa->qname); return (1); } - bwsum = 0; - TAILQ_FOREACH(altq, &altqs, entries) { - if (strncmp(altq->ifname, pa->ifname, - IFNAMSIZ) == 0 && - altq->qname[0] != 0 && - strncmp(altq->parent, pa->parent, - PF_QNAME_SIZE) == 0) - bwsum += altq->bandwidth; - } - bwsum += pa->bandwidth; - if (bwsum > parent->bandwidth) { - warnx("the sum of the child bandwidth higher" - " than parent \"%s\"", parent->qname); + parent->meta.bwsum += pa->bandwidth; + if (parent->meta.bwsum > parent->pa.bandwidth) { + warnx("the sum of the child bandwidth (%" PRIu64 + ") higher than parent \"%s\" (%" PRIu64 ")", + parent->meta.bwsum, parent->pa.qname, + parent->pa.bandwidth); } } } if (eval_queue_opts(pa, opts, - parent == NULL ? pa->ifbandwidth : parent->bandwidth)) + parent == NULL ? pa->ifbandwidth : parent->pa.bandwidth)) return (1); + if (parent != NULL) + parent->meta.children++; + switch (pa->scheduler) { case ALTQT_CBQ: - error = eval_pfqueue_cbq(pf, pa); + error = eval_pfqueue_cbq(pf, pa, if_ppa); break; case ALTQT_PRIQ: - error = eval_pfqueue_priq(pf, pa); + error = eval_pfqueue_priq(pf, pa, if_ppa); break; case ALTQT_HFSC: - error = eval_pfqueue_hfsc(pf, pa); + error = eval_pfqueue_hfsc(pf, pa, if_ppa, parent); break; case ALTQT_FAIRQ: - error = eval_pfqueue_fairq(pf, pa); + error = eval_pfqueue_fairq(pf, pa, if_ppa, parent); break; default: break; @@ -458,7 +508,7 @@ eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw, #define RM_NS_PER_SEC (1000000000) static int -eval_pfqueue_cbq(struct pfctl *pf, struct pf_altq *pa) +eval_pfqueue_cbq(struct pfctl *pf, struct pf_altq *pa, struct pfctl_altq *if_ppa) { struct cbq_opts *opts; u_int ifmtu; @@ -488,6 +538,11 @@ eval_pfqueue_cbq(struct pfctl *pf, struct pf_altq *pa) if (pa->parent[0] == 0) opts->flags |= (CBQCLF_ROOTCLASS | CBQCLF_WRR); + if (pa->pq_u.cbq_opts.flags & CBQCLF_ROOTCLASS) + if_ppa->meta.root_classes++; + if (pa->pq_u.cbq_opts.flags & CBQCLF_DEFCLASS) + if_ppa->meta.default_classes++; + cbq_compute_idletime(pf, pa); return (0); } @@ -580,33 +635,20 @@ cbq_compute_idletime(struct pfctl *pf, struct pf_altq *pa) } static int -check_commit_cbq(int dev, int opts, struct pf_altq *pa) +check_commit_cbq(int dev, int opts, struct pfctl_altq *if_ppa) { - struct pf_altq *altq; - int root_class, default_class; - int error = 0; + int error = 0; /* * check if cbq has one root queue and one default queue * for this interface */ - root_class = default_class = 0; - TAILQ_FOREACH(altq, &altqs, entries) { - if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) - continue; - if (altq->qname[0] == 0) /* this is for interface */ - continue; - if (altq->pq_u.cbq_opts.flags & CBQCLF_ROOTCLASS) - root_class++; - if (altq->pq_u.cbq_opts.flags & CBQCLF_DEFCLASS) - default_class++; - } - if (root_class != 1) { - warnx("should have one root queue on %s", pa->ifname); + if (if_ppa->meta.root_classes != 1) { + warnx("should have one root queue on %s", if_ppa->pa.ifname); error++; } - if (default_class != 1) { - warnx("should have one default queue on %s", pa->ifname); + if (if_ppa->meta.default_classes != 1) { + warnx("should have one default queue on %s", if_ppa->pa.ifname); error++; } return (error); @@ -653,51 +695,37 @@ print_cbq_opts(const struct pf_altq *a) * PRIQ support functions */ static int -eval_pfqueue_priq(struct pfctl *pf, struct pf_altq *pa) +eval_pfqueue_priq(struct pfctl *pf, struct pf_altq *pa, struct pfctl_altq *if_ppa) { - struct pf_altq *altq; if (pa->priority >= PRIQ_MAXPRI) { warnx("priority out of range: max %d", PRIQ_MAXPRI - 1); return (-1); } - /* the priority should be unique for the interface */ - TAILQ_FOREACH(altq, &altqs, entries) { - if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) == 0 && - altq->qname[0] != 0 && altq->priority == pa->priority) { - warnx("%s and %s have the same priority", - altq->qname, pa->qname); - return (-1); - } - } + if (BIT_ISSET(QPRI_BITSET_SIZE, pa->priority, &if_ppa->meta.qpris)) { + warnx("%s does not have a unique priority on interface %s", + pa->qname, pa->ifname); + return (-1); + } else + BIT_SET(QPRI_BITSET_SIZE, pa->priority, &if_ppa->meta.qpris); + if (pa->pq_u.priq_opts.flags & PRCF_DEFAULTCLASS) + if_ppa->meta.default_classes++; return (0); } static int -check_commit_priq(int dev, int opts, struct pf_altq *pa) +check_commit_priq(int dev, int opts, struct pfctl_altq *if_ppa) { - struct pf_altq *altq; - int default_class; - int error = 0; /* * check if priq has one default class for this interface */ - default_class = 0; - TAILQ_FOREACH(altq, &altqs, entries) { - if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) - continue; - if (altq->qname[0] == 0) /* this is for interface */ - continue; - if (altq->pq_u.priq_opts.flags & PRCF_DEFAULTCLASS) - default_class++; - } - if (default_class != 1) { - warnx("should have one default queue on %s", pa->ifname); - error++; + if (if_ppa->meta.default_classes != 1) { + warnx("should have one default queue on %s", if_ppa->pa.ifname); + return (1); } - return (error); + return (0); } static int @@ -732,15 +760,15 @@ print_priq_opts(const struct pf_altq *a) * HFSC support functions */ static int -eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa) +eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa, struct pfctl_altq *if_ppa, + struct pfctl_altq *parent) { - struct pf_altq *altq, *parent; struct hfsc_opts_v1 *opts; struct service_curve sc; opts = &pa->pq_u.hfsc_opts; - if (pa->parent[0] == 0) { + if (parent == NULL) { /* root queue */ opts->lssc_m1 = pa->ifbandwidth; opts->lssc_m2 = pa->ifbandwidth; @@ -748,9 +776,21 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa) return (0); } - LIST_INIT(&rtsc); - LIST_INIT(&lssc); + /* First child initializes the parent's service curve accumulators. */ + if (parent->meta.children == 1) { + LIST_INIT(&parent->meta.rtsc); + LIST_INIT(&parent->meta.lssc); + } + if (parent->pa.pq_u.hfsc_opts.flags & HFCF_DEFAULTCLASS) { + warnx("adding %s would make default queue %s not a leaf", + pa->qname, pa->parent); + return (-1); + } + + if (pa->pq_u.hfsc_opts.flags & HFCF_DEFAULTCLASS) + if_ppa->meta.default_classes++; + /* if link_share is not specified, use bandwidth */ if (opts->lssc_m2 == 0) opts->lssc_m2 = pa->bandwidth; @@ -780,51 +820,22 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa) * be smaller than the interface bandwidth, and the upper-limit should * be larger than the real-time service curve when both are defined. */ - parent = qname_to_pfaltq(pa->parent, pa->ifname); - if (parent == NULL) - errx(1, "parent %s not found for %s", pa->parent, pa->qname); - - TAILQ_FOREACH(altq, &altqs, entries) { - if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) - continue; - if (altq->qname[0] == 0) /* this is for interface */ - continue; - - /* if the class has a real-time service curve, add it. */ - if (opts->rtsc_m2 != 0 && altq->pq_u.hfsc_opts.rtsc_m2 != 0) { - sc.m1 = altq->pq_u.hfsc_opts.rtsc_m1; - sc.d = altq->pq_u.hfsc_opts.rtsc_d; - sc.m2 = altq->pq_u.hfsc_opts.rtsc_m2; - gsc_add_sc(&rtsc, &sc); - } - - if (strncmp(altq->parent, pa->parent, PF_QNAME_SIZE) != 0) - continue; - - /* if the class has a linkshare service curve, add it. */ - if (opts->lssc_m2 != 0 && altq->pq_u.hfsc_opts.lssc_m2 != 0) { - sc.m1 = altq->pq_u.hfsc_opts.lssc_m1; - sc.d = altq->pq_u.hfsc_opts.lssc_d; - sc.m2 = altq->pq_u.hfsc_opts.lssc_m2; - gsc_add_sc(&lssc, &sc); - } - } - + /* check the real-time service curve. reserve 20% of interface bw */ if (opts->rtsc_m2 != 0) { /* add this queue to the sum */ sc.m1 = opts->rtsc_m1; sc.d = opts->rtsc_d; sc.m2 = opts->rtsc_m2; - gsc_add_sc(&rtsc, &sc); + gsc_add_sc(&parent->meta.rtsc, &sc); /* compare the sum with 80% of the interface */ sc.m1 = 0; sc.d = 0; sc.m2 = pa->ifbandwidth / 100 * 80; - if (!is_gsc_under_sc(&rtsc, &sc)) { + if (!is_gsc_under_sc(&parent->meta.rtsc, &sc)) { warnx("real-time sc exceeds 80%% of the interface " "bandwidth (%s)", rate2str((double)sc.m2)); - goto err_ret; + return (-1); } } @@ -834,14 +845,14 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa) sc.m1 = opts->lssc_m1; sc.d = opts->lssc_d; sc.m2 = opts->lssc_m2; - gsc_add_sc(&lssc, &sc); + gsc_add_sc(&parent->meta.lssc, &sc); /* compare the sum of the children with parent's sc */ - sc.m1 = parent->pq_u.hfsc_opts.lssc_m1; - sc.d = parent->pq_u.hfsc_opts.lssc_d; - sc.m2 = parent->pq_u.hfsc_opts.lssc_m2; - if (!is_gsc_under_sc(&lssc, &sc)) { + sc.m1 = parent->pa.pq_u.hfsc_opts.lssc_m1; + sc.d = parent->pa.pq_u.hfsc_opts.lssc_d; + sc.m2 = parent->pa.pq_u.hfsc_opts.lssc_m2; + if (!is_gsc_under_sc(&parent->meta.lssc, &sc)) { warnx("linkshare sc exceeds parent's sc"); - goto err_ret; + return (-1); } } @@ -850,38 +861,30 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa) if (opts->ulsc_m1 > pa->ifbandwidth || opts->ulsc_m2 > pa->ifbandwidth) { warnx("upper-limit larger than interface bandwidth"); - goto err_ret; + return (-1); } if (opts->rtsc_m2 != 0 && opts->rtsc_m2 > opts->ulsc_m2) { warnx("upper-limit sc smaller than real-time sc"); - goto err_ret; + return (-1); } } - gsc_destroy(&rtsc); - gsc_destroy(&lssc); - return (0); - -err_ret: - gsc_destroy(&rtsc); - gsc_destroy(&lssc); - return (-1); } /* * FAIRQ support functions */ static int -eval_pfqueue_fairq(struct pfctl *pf __unused, struct pf_altq *pa) +eval_pfqueue_fairq(struct pfctl *pf __unused, struct pf_altq *pa, + struct pfctl_altq *if_ppa, struct pfctl_altq *parent) { - struct pf_altq *altq, *parent; struct fairq_opts *opts; struct service_curve sc; opts = &pa->pq_u.fairq_opts; - if (pa->parent[0] == 0) { + if (pa->parent == NULL) { /* root queue */ opts->lssc_m1 = pa->ifbandwidth; opts->lssc_m2 = pa->ifbandwidth; @@ -889,7 +892,18 @@ eval_pfqueue_fairq(struct pfctl *pf __unused, struct pf_altq *pa) return (0); } - LIST_INIT(&lssc); + /* First child initializes the parent's service curve accumulator. */ + if (parent->meta.children == 1) + LIST_INIT(&parent->meta.lssc); + + if (parent->pa.pq_u.fairq_opts.flags & FARF_DEFAULTCLASS) { + warnx("adding %s would make default queue %s not a leaf", + pa->qname, pa->parent); + return (-1); + } + + if (pa->pq_u.fairq_opts.flags & FARF_DEFAULTCLASS) + if_ppa->meta.default_classes++; /* if link_share is not specified, use bandwidth */ if (opts->lssc_m2 == 0) @@ -906,122 +920,49 @@ eval_pfqueue_fairq(struct pfctl *pf __unused, struct pf_altq *pa) * be smaller than the interface bandwidth, and the upper-limit should * be larger than the real-time service curve when both are defined. */ - parent = qname_to_pfaltq(pa->parent, pa->ifname); - if (parent == NULL) - errx(1, "parent %s not found for %s", pa->parent, pa->qname); - - TAILQ_FOREACH(altq, &altqs, entries) { - if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) - continue; - if (altq->qname[0] == 0) /* this is for interface */ - continue; - - if (strncmp(altq->parent, pa->parent, PF_QNAME_SIZE) != 0) - continue; - - /* if the class has a link-sharing service curve, add it. */ - if (opts->lssc_m2 != 0 && altq->pq_u.fairq_opts.lssc_m2 != 0) { - sc.m1 = altq->pq_u.fairq_opts.lssc_m1; - sc.d = altq->pq_u.fairq_opts.lssc_d; - sc.m2 = altq->pq_u.fairq_opts.lssc_m2; - gsc_add_sc(&lssc, &sc); - } - } - /* check the link-sharing service curve. */ + /* check the linkshare service curve. */ if (opts->lssc_m2 != 0) { - sc.m1 = parent->pq_u.fairq_opts.lssc_m1; - sc.d = parent->pq_u.fairq_opts.lssc_d; - sc.m2 = parent->pq_u.fairq_opts.lssc_m2; - if (!is_gsc_under_sc(&lssc, &sc)) { + /* add this queue to the child sum */ + sc.m1 = opts->lssc_m1; + sc.d = opts->lssc_d; + sc.m2 = opts->lssc_m2; + gsc_add_sc(&parent->meta.lssc, &sc); + /* compare the sum of the children with parent's sc */ + sc.m1 = parent->pa.pq_u.fairq_opts.lssc_m1; + sc.d = parent->pa.pq_u.fairq_opts.lssc_d; + sc.m2 = parent->pa.pq_u.fairq_opts.lssc_m2; + if (!is_gsc_under_sc(&parent->meta.lssc, &sc)) { warnx("link-sharing sc exceeds parent's sc"); - goto err_ret; + return (-1); } } - gsc_destroy(&lssc); - return (0); - -err_ret: - gsc_destroy(&lssc); - return (-1); } static int -check_commit_hfsc(int dev, int opts, struct pf_altq *pa) +check_commit_hfsc(int dev, int opts, struct pfctl_altq *if_ppa) { - struct pf_altq *altq, *def = NULL; - int default_class; - int error = 0; /* check if hfsc has one default queue for this interface */ - default_class = 0; - TAILQ_FOREACH(altq, &altqs, entries) { - if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) - continue; - if (altq->qname[0] == 0) /* this is for interface */ - continue; - if (altq->parent[0] == 0) /* dummy root */ - continue; - if (altq->pq_u.hfsc_opts.flags & HFCF_DEFAULTCLASS) { - default_class++; - def = altq; - } - } - if (default_class != 1) { - warnx("should have one default queue on %s", pa->ifname); + if (if_ppa->meta.default_classes != 1) { + warnx("should have one default queue on %s", if_ppa->pa.ifname); return (1); } - /* make sure the default queue is a leaf */ - TAILQ_FOREACH(altq, &altqs, entries) { - if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) - continue; - if (altq->qname[0] == 0) /* this is for interface */ - continue; - if (strncmp(altq->parent, def->qname, PF_QNAME_SIZE) == 0) { - warnx("default queue is not a leaf"); - error++; - } - } - return (error); + return (0); } static int -check_commit_fairq(int dev __unused, int opts __unused, struct pf_altq *pa) +check_commit_fairq(int dev __unused, int opts __unused, struct pfctl_altq *if_ppa) { - struct pf_altq *altq, *def = NULL; - int default_class; - int error = 0; /* check if fairq has one default queue for this interface */ - default_class = 0; - TAILQ_FOREACH(altq, &altqs, entries) { - if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) - continue; - if (altq->qname[0] == 0) /* this is for interface */ - continue; - if (altq->pq_u.fairq_opts.flags & FARF_DEFAULTCLASS) { - default_class++; - def = altq; - } - } - if (default_class != 1) { - warnx("should have one default queue on %s", pa->ifname); + if (if_ppa->meta.default_classes != 1) { + warnx("should have one default queue on %s", if_ppa->pa.ifname); return (1); } - /* make sure the default queue is a leaf */ - TAILQ_FOREACH(altq, &altqs, entries) { - if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) - continue; - if (altq->qname[0] == 0) /* this is for interface */ - continue; - if (strncmp(altq->parent, def->qname, PF_QNAME_SIZE) == 0) { - warnx("default queue is not a leaf"); - error++; - } - } - return (error); + return (0); } static int @@ -1194,17 +1135,6 @@ is_gsc_under_sc(struct gen_sc *gsc, struct service_curve *sc) return (1); } -static void -gsc_destroy(struct gen_sc *gsc) -{ - struct segment *s; - - while ((s = LIST_FIRST(gsc)) != NULL) { - LIST_REMOVE(s, _next); - free(s); - } -} - /* * return a segment entry starting at x. * if gsc has no entry starting at x, a new entry is created at x. @@ -1369,8 +1299,7 @@ getifspeed(char *ifname) struct ifreq ifr; struct if_data ifrdat; - if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) < 0) - err(1, "socket"); + s = get_query_socket(); bzero(&ifr, sizeof(ifr)); if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= sizeof(ifr.ifr_name)) @@ -1378,8 +1307,6 @@ getifspeed(char *ifname) ifr.ifr_data = (caddr_t)&ifrdat; if (ioctl(s, SIOCGIFDATA, (caddr_t)&ifr) == -1) err(1, "SIOCGIFDATA"); - if (close(s)) - err(1, "close"); return ((u_int32_t)ifrdat.ifi_baudrate); } #endif @@ -1390,8 +1317,7 @@ getifmtu(char *ifname) int s; struct ifreq ifr; - if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) < 0) - err(1, "socket"); + s = get_query_socket(); bzero(&ifr, sizeof(ifr)); if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= sizeof(ifr.ifr_name)) @@ -1402,8 +1328,6 @@ getifmtu(char *ifname) #else err(1, "SIOCGIFMTU"); #endif - if (close(s)) - err(1, "close"); if (ifr.ifr_mtu > 0) return (ifr.ifr_mtu); else { diff --git a/freebsd/sbin/pfctl/pfctl_optimize.c b/freebsd/sbin/pfctl/pfctl_optimize.c index cbf94e80..02a1018c 100644 --- a/freebsd/sbin/pfctl/pfctl_optimize.c +++ b/freebsd/sbin/pfctl/pfctl_optimize.c @@ -1549,14 +1549,24 @@ superblock_inclusive(struct superblock *block, struct pf_opt_rule *por) int interface_group(const char *ifname) { + int s; + struct ifgroupreq ifgr; + if (ifname == NULL || !ifname[0]) return (0); - /* Real interfaces must end in a number, interface groups do not */ - if (isdigit(ifname[strlen(ifname) - 1])) - return (0); - else - return (1); + s = get_query_socket(); + + memset(&ifgr, 0, sizeof(ifgr)); + strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ); + if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) { + if (errno == ENOENT) + return (0); + else + err(1, "SIOCGIFGMEMB"); + } + + return (1); } diff --git a/freebsd/sbin/pfctl/pfctl_parser.c b/freebsd/sbin/pfctl/pfctl_parser.c index 25e2a59b..f339d972 100644 --- a/freebsd/sbin/pfctl/pfctl_parser.c +++ b/freebsd/sbin/pfctl/pfctl_parser.c @@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$"); #include <net/pfvar.h> #include <arpa/inet.h> +#include <search.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -86,7 +87,6 @@ void print_fromto(struct pf_rule_addr *, pf_osfp_t, struct pf_rule_addr *, u_int8_t, u_int8_t, int, int); int ifa_skip_if(const char *filter, struct node_host *p); -struct node_host *ifa_grouplookup(const char *, int); struct node_host *host_if(const char *, int); struct node_host *host_v4(const char *, int); struct node_host *host_v6(const char *, int); @@ -223,6 +223,19 @@ const struct pf_timeout pf_timeouts[] = { { NULL, 0 } }; +static struct hsearch_data isgroup_map; + +static __attribute__((constructor)) void +pfctl_parser_init(void) +{ + /* + * As hdestroy() will never be called on these tables, it will be + * safe to use references into the stored data as keys. + */ + if (hcreate_r(0, &isgroup_map) == 0) + err(1, "Failed to create interface group query response map"); +} + const struct icmptypeent * geticmptypebynumber(u_int8_t type, sa_family_t af) { @@ -1167,6 +1180,71 @@ check_netmask(struct node_host *h, sa_family_t af) static struct node_host *iftab; +/* + * Retrieve the list of groups this interface is a member of and make sure + * each group is in the group map. + */ +static void +ifa_add_groups_to_map(char *ifa_name) +{ + int s, len; + struct ifgroupreq ifgr; + struct ifg_req *ifg; + + s = get_query_socket(); + + /* Get size of group list for this interface */ + memset(&ifgr, 0, sizeof(ifgr)); + strlcpy(ifgr.ifgr_name, ifa_name, IFNAMSIZ); + if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) + err(1, "SIOCGIFGROUP"); + + /* Retrieve group list for this interface */ + len = ifgr.ifgr_len; + ifgr.ifgr_groups = + (struct ifg_req *)calloc(len / sizeof(struct ifg_req), + sizeof(struct ifg_req)); + if (ifgr.ifgr_groups == NULL) + err(1, "calloc"); + if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) + err(1, "SIOCGIFGROUP"); + + ifg = ifgr.ifgr_groups; + for (; ifg && len >= sizeof(struct ifg_req); ifg++) { + len -= sizeof(struct ifg_req); + if (strcmp(ifg->ifgrq_group, "all")) { + ENTRY item; + ENTRY *ret_item; + int *answer; + + item.key = ifg->ifgrq_group; + if (hsearch_r(item, FIND, &ret_item, &isgroup_map) == 0) { + struct ifgroupreq ifgr2; + + /* Don't know the answer yet */ + if ((answer = malloc(sizeof(int))) == NULL) + err(1, "malloc"); + + bzero(&ifgr2, sizeof(ifgr2)); + strlcpy(ifgr2.ifgr_name, ifg->ifgrq_group, + sizeof(ifgr2.ifgr_name)); + if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr2) == 0) + *answer = ifgr2.ifgr_len; + else + *answer = 0; + + item.key = strdup(ifg->ifgrq_group); + item.data = answer; + if (hsearch_r(item, ENTER, &ret_item, + &isgroup_map) == 0) + err(1, "interface group query response" + " map insert"); + } + } + } + free(ifgr.ifgr_groups); +} + void ifa_load(void) { @@ -1234,6 +1312,8 @@ ifa_load(void) sizeof(struct in6_addr)); n->ifindex = ((struct sockaddr_in6 *) ifa->ifa_addr)->sin6_scope_id; + } else if (n->af == AF_LINK) { + ifa_add_groups_to_map(ifa->ifa_name); } if ((n->ifname = strdup(ifa->ifa_name)) == NULL) err(1, "ifa_load: strdup"); @@ -1251,7 +1331,7 @@ ifa_load(void) freeifaddrs(ifap); } -int +static int get_socket_domain(void) { int sdom; @@ -1271,31 +1351,54 @@ get_socket_domain(void) return (sdom); } +int +get_query_socket(void) +{ + static int s = -1; + + if (s == -1) { + if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) == -1) + err(1, "socket"); + } + + return (s); +} + +/* + * Returns the response len if the name is a group, otherwise returns 0. + */ +static int +is_a_group(char *name) +{ + ENTRY item; + ENTRY *ret_item; + + item.key = name; + if (hsearch_r(item, FIND, &ret_item, &isgroup_map) == 0) + return (0); + + return (*(int *)ret_item->data); +} + struct node_host * -ifa_exists(const char *ifa_name) +ifa_exists(char *ifa_name) { struct node_host *n; - struct ifgroupreq ifgr; int s; if (iftab == NULL) ifa_load(); - /* check wether this is a group */ - if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) == -1) - err(1, "socket"); - bzero(&ifgr, sizeof(ifgr)); - strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name)); - if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == 0) { + /* check whether this is a group */ + s = get_query_socket(); + if (is_a_group(ifa_name)) { /* fake a node_host */ if ((n = calloc(1, sizeof(*n))) == NULL) err(1, "calloc"); if ((n->ifname = strdup(ifa_name)) == NULL) err(1, "strdup"); - close(s); return (n); } - close(s); for (n = iftab; n; n = n->next) { if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ)) @@ -1306,23 +1409,20 @@ ifa_exists(const char *ifa_name) } struct node_host * -ifa_grouplookup(const char *ifa_name, int flags) +ifa_grouplookup(char *ifa_name, int flags) { struct ifg_req *ifg; struct ifgroupreq ifgr; int s, len; struct node_host *n, *h = NULL; - if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) == -1) - err(1, "socket"); + s = get_query_socket(); + len = is_a_group(ifa_name); + if (len == 0) + return (NULL); bzero(&ifgr, sizeof(ifgr)); strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name)); - if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) { - close(s); - return (NULL); - } - - len = ifgr.ifgr_len; + ifgr.ifgr_len = len; if ((ifgr.ifgr_groups = calloc(1, len)) == NULL) err(1, "calloc"); if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) @@ -1341,13 +1441,12 @@ ifa_grouplookup(const char *ifa_name, int flags) } } free(ifgr.ifgr_groups); - close(s); return (h); } struct node_host * -ifa_lookup(const char *ifa_name, int flags) +ifa_lookup(char *ifa_name, int flags) { struct node_host *p = NULL, *h = NULL, *n = NULL; int got4 = 0, got6 = 0; diff --git a/freebsd/sbin/pfctl/pfctl_parser.h b/freebsd/sbin/pfctl/pfctl_parser.h index 05ebdf29..aa6d98d7 100644 --- a/freebsd/sbin/pfctl/pfctl_parser.h +++ b/freebsd/sbin/pfctl/pfctl_parser.h @@ -177,6 +177,24 @@ struct node_queue_opt { } data; }; +#define QPRI_BITSET_SIZE 256 +BITSET_DEFINE(qpri_bitset, QPRI_BITSET_SIZE); +LIST_HEAD(gen_sc, segment); + +struct pfctl_altq { + struct pf_altq pa; + struct { + STAILQ_ENTRY(pfctl_altq) link; + u_int64_t bwsum; + struct qpri_bitset qpris; + int children; + int root_classes; + int default_classes; + struct gen_sc lssc; + struct gen_sc rtsc; + } meta; +}; + #ifdef __FreeBSD__ /* * XXX @@ -313,10 +331,10 @@ void set_ipmask(struct node_host *, u_int8_t); int check_netmask(struct node_host *, sa_family_t); int unmask(struct pf_addr *, sa_family_t); void ifa_load(void); -int get_socket_domain(void); -struct node_host *ifa_exists(const char *); -struct node_host *ifa_grouplookup(const char *ifa_name, int flags); -struct node_host *ifa_lookup(const char *, int); +int get_query_socket(void); +struct node_host *ifa_exists(char *); +struct node_host *ifa_grouplookup(char *ifa_name, int flags); +struct node_host *ifa_lookup(char *, int); struct node_host *host(const char *); int append_addr(struct pfr_buffer *, char *, int); diff --git a/freebsd/sbin/pfctl/rtems-bsd-pfctl-pfctl_altq-data.h b/freebsd/sbin/pfctl/rtems-bsd-pfctl-pfctl_altq-data.h index fb03f2b6..64f95aaf 100644 --- a/freebsd/sbin/pfctl/rtems-bsd-pfctl-pfctl_altq-data.h +++ b/freebsd/sbin/pfctl/rtems-bsd-pfctl-pfctl_altq-data.h @@ -4,6 +4,3 @@ /* pfctl_altq.c */ RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static char r2sbuf[][16]); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int idx); -RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct altqs altqs); -RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct gen_sc lssc); -RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct gen_sc rtsc); diff --git a/freebsd/sbin/ping/ping.c b/freebsd/sbin/ping/ping.c index 5df1e875..e31941b8 100644 --- a/freebsd/sbin/ping/ping.c +++ b/freebsd/sbin/ping/ping.c @@ -104,16 +104,20 @@ __FBSDID("$FreeBSD$"); #include <errno.h> #include <math.h> #include <netdb.h> +#include <stddef.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sysexits.h> +#include <time.h> #include <unistd.h> #ifdef __rtems__ #include "rtems-bsd-ping-ping-data.h" #endif /* __rtems__ */ +#include "utils.h" + #define INADDR_LEN ((int)sizeof(in_addr_t)) #define TIMEVAL_LEN ((int)sizeof(struct tv32)) #define MASK_LEN (ICMP_MASKLEN - ICMP_MINLEN) @@ -135,7 +139,7 @@ __FBSDID("$FreeBSD$"); struct tv32 { int32_t tv32_sec; - int32_t tv32_usec; + int32_t tv32_nsec; }; /* various options */ @@ -235,7 +239,6 @@ static char hnamebuf[MAXHOSTNAMELEN], snamebuf[MAXHOSTNAMELEN]; #endif /* __rtems__ */ static void fill(char *, char *); -static u_short in_cksum(u_short *, int); #ifndef __rtems__ static cap_channel_t *capdns_setup(void); #endif /* __rtems__ */ @@ -244,15 +247,14 @@ static void finish(void) __dead2; static void pinger(void); static char *pr_addr(struct in_addr); static char *pr_ntime(n_time); -static void pr_icmph(struct icmp *); +static void pr_icmph(struct icmp *, struct ip *, const u_char *const); static void pr_iph(struct ip *); -static void pr_pack(char *, int, struct sockaddr_in *, struct timeval *); -static void pr_retip(struct ip *); +static void pr_pack(char *, ssize_t, struct sockaddr_in *, struct timespec *); +static void pr_retip(struct ip *, const u_char *); #ifndef __rtems__ static void status(int); static void stopit(int); #endif /* __rtems__ */ -static void tvsub(struct timeval *, const struct timeval *); static void usage(void) __dead2; #ifdef __rtems__ @@ -286,9 +288,8 @@ main(int argc, char *const *argv) { struct sockaddr_in from, sock_in; struct in_addr ifaddr; - struct timeval last, intvl; + struct timespec last, intvl; struct iovec iov; - struct ip *ip; struct msghdr msg; #ifndef __rtems__ struct sigaction si_sa; @@ -310,7 +311,7 @@ main(int argc, char *const *argv) long ltmp; int almost_done, ch, df, hold, i, icmp_len, mib[4], preload; int ssend_errno, srecv_errno, tos, ttl; - char ctrl[CMSG_SPACE(sizeof(struct timeval))]; + char ctrl[CMSG_SPACE(sizeof(struct timespec))]; #ifndef __rtems__ char hnamebuf[MAXHOSTNAMELEN], snamebuf[MAXHOSTNAMELEN]; #endif /* __rtems__ */ @@ -335,6 +336,8 @@ main(int argc, char *const *argv) #define getopt(argc, argv, opt) getopt_r(argc, argv, "+" opt, &getopt_data) #endif /* __rtems__ */ + options |= F_NUMERIC; + /* * Do the stuff that we need root priv's for *first*, and * then drop our setuid bit. Save error reporting for @@ -371,7 +374,7 @@ main(int argc, char *const *argv) outpack = outpackhdr + sizeof(struct ip); while ((ch = getopt(argc, argv, - "Aac:DdfG:g:h:I:i:Ll:M:m:nop:QqRrS:s:T:t:vW:z:" + "Aac:DdfG:g:Hh:I:i:Ll:M:m:nop:QqRrS:s:T:t:vW:z:" #ifdef IPSEC #ifdef IPSEC_POLICY_IPSEC "P:" @@ -437,6 +440,9 @@ main(int argc, char *const *argv) options |= F_SWEEP; sweepmin = ltmp; break; + case 'H': + options &= ~F_NUMERIC; + break; case 'h': /* Packet size increment for ping sweep */ ltmp = strtol(optarg, &ep, 0); if (*ep || ep == optarg || ltmp < 1) @@ -685,8 +691,8 @@ main(int argc, char *const *argv) hostname = hnamebuf; } -#ifndef __rtems__ /* From now on we will use only reverse DNS lookups. */ +#ifdef WITH_CASPER if (capdns != NULL) { const char *types[1]; @@ -694,7 +700,7 @@ main(int argc, char *const *argv) if (cap_dns_type_limit(capdns, types, 1) < 0) err(1, "unable to limit access to system.dns service"); } -#endif /* __rtems__ */ +#endif if (connect(ssend, (struct sockaddr *)&whereto, sizeof(whereto)) != 0) err(1, "connect"); @@ -759,7 +765,9 @@ main(int argc, char *const *argv) #endif /*IPSEC*/ if (options & F_HDRINCL) { - ip = (struct ip*)outpackhdr; + struct ip ip; + + memcpy(&ip, outpackhdr, sizeof(ip)); if (!(options & (F_TTL | F_MTTL))) { mib[0] = CTL_NET; mib[1] = PF_INET; @@ -770,15 +778,16 @@ main(int argc, char *const *argv) err(1, "sysctl(net.inet.ip.ttl)"); } setsockopt(ssend, IPPROTO_IP, IP_HDRINCL, &hold, sizeof(hold)); - ip->ip_v = IPVERSION; - ip->ip_hl = sizeof(struct ip) >> 2; - ip->ip_tos = tos; - ip->ip_id = 0; - ip->ip_off = htons(df ? IP_DF : 0); - ip->ip_ttl = ttl; - ip->ip_p = IPPROTO_ICMP; - ip->ip_src.s_addr = source ? sock_in.sin_addr.s_addr : INADDR_ANY; - ip->ip_dst = to->sin_addr; + ip.ip_v = IPVERSION; + ip.ip_hl = sizeof(struct ip) >> 2; + ip.ip_tos = tos; + ip.ip_id = 0; + ip.ip_off = htons(df ? IP_DF : 0); + ip.ip_ttl = ttl; + ip.ip_p = IPPROTO_ICMP; + ip.ip_src.s_addr = source ? sock_in.sin_addr.s_addr : INADDR_ANY; + ip.ip_dst = to->sin_addr; + memcpy(outpackhdr, &ip, sizeof(ip)); } #ifndef __rtems__ @@ -789,7 +798,7 @@ main(int argc, char *const *argv) */ caph_cache_catpages(); if (caph_enter_casper() < 0) - err(1, "cap_enter"); + err(1, "caph_enter_casper"); cap_rights_init(&rights, CAP_RECV, CAP_EVENT, CAP_SETSOCKOPT); if (caph_rights_limit(srecv, &rights) < 0) @@ -841,9 +850,15 @@ main(int argc, char *const *argv) } } #ifdef SO_TIMESTAMP - { int on = 1; - if (setsockopt(srecv, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)) < 0) - err(EX_OSERR, "setsockopt SO_TIMESTAMP"); + { + int on = 1; + int ts_clock = SO_TS_MONOTONIC; + if (setsockopt(srecv, SOL_SOCKET, SO_TIMESTAMP, &on, + sizeof(on)) < 0) + err(EX_OSERR, "setsockopt SO_TIMESTAMP"); + if (setsockopt(srecv, SOL_SOCKET, SO_TS_CLOCK, &ts_clock, + sizeof(ts_clock)) < 0) + err(EX_OSERR, "setsockopt SO_TS_CLOCK"); } #endif if (sweepmax) { @@ -946,6 +961,7 @@ main(int argc, char *const *argv) msg.msg_iovlen = 1; #ifdef SO_TIMESTAMP msg.msg_control = (caddr_t)ctrl; + msg.msg_controllen = sizeof(ctrl); #endif iov.iov_base = packet; iov.iov_len = IP_MAXPACKET; @@ -958,19 +974,19 @@ main(int argc, char *const *argv) while (preload--) /* fire off them quickies */ pinger(); } - (void)gettimeofday(&last, NULL); + (void)clock_gettime(CLOCK_MONOTONIC, &last); if (options & F_FLOOD) { intvl.tv_sec = 0; - intvl.tv_usec = 10000; + intvl.tv_nsec = 10000000; } else { intvl.tv_sec = interval / 1000; - intvl.tv_usec = interval % 1000 * 1000; + intvl.tv_nsec = interval % 1000 * 1000000; } almost_done = 0; while (!finish_up) { - struct timeval now, timeout; + struct timespec now, timeout; #ifndef __rtems__ fd_set rfds; #else /* __rtems__ */ @@ -978,7 +994,8 @@ main(int argc, char *const *argv) sizeof(fd_set) * 8)]; #define rfds (*(fd_set *)(&big_enough_rfds[0])) #endif /* __rtems__ */ - int cc, n; + int n; + ssize_t cc; check_status(); #ifndef __rtems__ @@ -989,28 +1006,18 @@ main(int argc, char *const *argv) memset(big_enough_rfds, 0, sizeof(big_enough_rfds)); #endif /* __rtems__ */ FD_SET(srecv, &rfds); - (void)gettimeofday(&now, NULL); - timeout.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec; - timeout.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec; - while (timeout.tv_usec < 0) { - timeout.tv_usec += 1000000; - timeout.tv_sec--; - } - while (timeout.tv_usec >= 1000000) { - timeout.tv_usec -= 1000000; - timeout.tv_sec++; - } + (void)clock_gettime(CLOCK_MONOTONIC, &now); + timespecadd(&last, &intvl, &timeout); + timespecsub(&timeout, &now, &timeout); if (timeout.tv_sec < 0) - timerclear(&timeout); - n = select(srecv + 1, &rfds, NULL, NULL, &timeout); + timespecclear(&timeout); + n = pselect(srecv + 1, &rfds, NULL, NULL, &timeout, NULL); if (n < 0) continue; /* Must be EINTR. */ if (n == 1) { - struct timeval *tv = NULL; + struct timespec *tv = NULL; #ifdef SO_TIMESTAMP - struct cmsghdr *cmsg = (struct cmsghdr *)&ctrl; - - msg.msg_controllen = sizeof(ctrl); + struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); #endif msg.msg_namelen = sizeof(from); if ((cc = recvmsg(srecv, &msg, 0)) < 0) { @@ -1020,7 +1027,8 @@ main(int argc, char *const *argv) continue; } #ifdef SO_TIMESTAMP - if (cmsg->cmsg_level == SOL_SOCKET && + if (cmsg != NULL && + cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMP && cmsg->cmsg_len == CMSG_LEN(sizeof *tv)) { /* Copy to avoid alignment problems: */ @@ -1029,7 +1037,7 @@ main(int argc, char *const *argv) } #endif if (tv == NULL) { - (void)gettimeofday(&now, NULL); + (void)clock_gettime(CLOCK_MONOTONIC, &now); tv = &now; } pr_pack((char *)packet, cc, &from, tv); @@ -1053,17 +1061,17 @@ main(int argc, char *const *argv) if (almost_done) break; almost_done = 1; - intvl.tv_usec = 0; + intvl.tv_nsec = 0; if (nreceived) { intvl.tv_sec = 2 * tmax / 1000; if (!intvl.tv_sec) intvl.tv_sec = 1; } else { intvl.tv_sec = waittime / 1000; - intvl.tv_usec = waittime % 1000 * 1000; + intvl.tv_nsec = waittime % 1000 * 1000000; } } - (void)gettimeofday(&last, NULL); + (void)clock_gettime(CLOCK_MONOTONIC, &last); if (ntransmitted - nreceived - 1 > nmissedmax) { nmissedmax = ntransmitted - nreceived - 1; if (options & F_MISSED) @@ -1102,53 +1110,69 @@ stopit(int sig __unused) * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet * will be added on by the kernel. The ID field is our UNIX process ID, * and the sequence number is an ascending integer. The first TIMEVAL_LEN - * bytes of the data portion are used to hold a UNIX "timeval" struct in + * bytes of the data portion are used to hold a UNIX "timespec" struct in * host byte-order, to compute the round-trip time. */ static void pinger(void) { - struct timeval now; + struct timespec now; struct tv32 tv32; - struct ip *ip; - struct icmp *icp; + struct icmp icp; int cc, i; u_char *packet; packet = outpack; - icp = (struct icmp *)outpack; - icp->icmp_type = icmp_type; - icp->icmp_code = 0; - icp->icmp_cksum = 0; - icp->icmp_seq = htons(ntransmitted); - icp->icmp_id = ident; /* ID */ + memcpy(&icp, outpack, ICMP_MINLEN + phdr_len); + icp.icmp_type = icmp_type; + icp.icmp_code = 0; + icp.icmp_cksum = 0; + icp.icmp_seq = htons(ntransmitted); + icp.icmp_id = ident; /* ID */ CLR(ntransmitted % MAX_DUP_CHK); if ((options & F_TIME) || timing) { - (void)gettimeofday(&now, NULL); - - tv32.tv32_sec = htonl(now.tv_sec); - tv32.tv32_usec = htonl(now.tv_usec); + (void)clock_gettime(CLOCK_MONOTONIC, &now); + /* + * Truncate seconds down to 32 bits in order + * to fit the timestamp within 8 bytes of the + * packet. We're only concerned with + * durations, not absolute times. + */ + tv32.tv32_sec = (uint32_t)htonl(now.tv_sec); + tv32.tv32_nsec = (uint32_t)htonl(now.tv_nsec); if (options & F_TIME) - icp->icmp_otime = htonl((now.tv_sec % (24*60*60)) - * 1000 + now.tv_usec / 1000); + icp.icmp_otime = htonl((now.tv_sec % (24*60*60)) + * 1000 + now.tv_nsec / 1000000); if (timing) bcopy((void *)&tv32, (void *)&outpack[ICMP_MINLEN + phdr_len], sizeof(tv32)); } + memcpy(outpack, &icp, ICMP_MINLEN + phdr_len); + cc = ICMP_MINLEN + phdr_len + datalen; /* compute ICMP checksum here */ - icp->icmp_cksum = in_cksum((u_short *)icp, cc); + icp.icmp_cksum = in_cksum(outpack, cc); + /* Update icmp_cksum in the raw packet data buffer. */ + memcpy(outpack + offsetof(struct icmp, icmp_cksum), &icp.icmp_cksum, + sizeof(icp.icmp_cksum)); if (options & F_HDRINCL) { + struct ip ip; + cc += sizeof(struct ip); - ip = (struct ip *)outpackhdr; - ip->ip_len = htons(cc); - ip->ip_sum = in_cksum((u_short *)outpackhdr, cc); + ip.ip_len = htons(cc); + /* Update ip_len in the raw packet data buffer. */ + memcpy(outpackhdr + offsetof(struct ip, ip_len), &ip.ip_len, + sizeof(ip.ip_len)); + ip.ip_sum = in_cksum(outpackhdr, cc); + /* Update ip_sum in the raw packet data buffer. */ + memcpy(outpackhdr + offsetof(struct ip, ip_sum), &ip.ip_sum, + sizeof(ip.ip_sum)); packet = outpackhdr; } i = send(ssend, (char *)packet, cc, 0); @@ -1178,56 +1202,71 @@ pinger(void) * program to be run without having intermingled output (or statistics!). */ static void -pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timeval *tv) +pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv) { struct in_addr ina; - u_char *cp, *dp; - struct icmp *icp; - struct ip *ip; - const void *tp; + u_char *cp, *dp, l; + struct icmp icp; + struct ip ip; + const u_char *icmp_data_raw; double triptime; - int dupflag, hlen, i, j, recv_len, seq; + int dupflag, hlen, i, j, recv_len; + uint16_t seq; static int old_rrlen; static char old_rr[MAX_IPOPTLEN]; + struct ip oip; + u_char oip_header_len; + struct icmp oicmp; + const u_char *oicmp_raw; + + /* + * Get size of IP header of the received packet. The + * information is contained in the lower four bits of the + * first byte. + */ + memcpy(&l, buf, sizeof(l)); + hlen = (l & 0x0f) << 2; + memcpy(&ip, buf, hlen); /* Check the IP header */ - ip = (struct ip *)buf; - hlen = ip->ip_hl << 2; recv_len = cc; if (cc < hlen + ICMP_MINLEN) { if (options & F_VERBOSE) - warn("packet too short (%d bytes) from %s", cc, + warn("packet too short (%zd bytes) from %s", cc, inet_ntoa(from->sin_addr)); return; } +#ifndef icmp_data + icmp_data_raw = buf + hlen + offsetof(struct icmp, icmp_ip); +#else + icmp_data_raw = buf + hlen + offsetof(struct icmp, icmp_data); +#endif + /* Now the ICMP part */ cc -= hlen; - icp = (struct icmp *)(buf + hlen); - if (icp->icmp_type == icmp_type_rsp) { - if (icp->icmp_id != ident) + memcpy(&icp, buf + hlen, MIN((ssize_t)sizeof(icp), cc)); + if (icp.icmp_type == icmp_type_rsp) { + if (icp.icmp_id != ident) return; /* 'Twas not our ECHO */ ++nreceived; triptime = 0.0; if (timing) { - struct timeval tv1; + struct timespec tv1; struct tv32 tv32; -#ifndef icmp_data - tp = &icp->icmp_ip; -#else - tp = icp->icmp_data; -#endif - tp = (const char *)tp + phdr_len; + const u_char *tp; + + tp = icmp_data_raw + phdr_len; if ((size_t)(cc - ICMP_MINLEN - phdr_len) >= sizeof(tv1)) { /* Copy to avoid alignment problems: */ memcpy(&tv32, tp, sizeof(tv32)); tv1.tv_sec = ntohl(tv32.tv32_sec); - tv1.tv_usec = ntohl(tv32.tv32_usec); - tvsub(tv, &tv1); + tv1.tv_nsec = ntohl(tv32.tv32_nsec); + timespecsub(tv, &tv1, tv); triptime = ((double)tv->tv_sec) * 1000.0 + - ((double)tv->tv_usec) / 1000.0; + ((double)tv->tv_nsec) / 1000000.0; tsum += triptime; tsumsq += triptime * triptime; if (triptime < tmin) @@ -1238,7 +1277,7 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timeval *tv) timing = 0; } - seq = ntohs(icp->icmp_seq); + seq = ntohs(icp.icmp_seq); if (TST(seq % MAX_DUP_CHK)) { ++nrepeats; @@ -1260,10 +1299,9 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timeval *tv) if (options & F_FLOOD) (void)write(STDOUT_FILENO, &BSPACE, 1); else { - (void)printf("%d bytes from %s: icmp_seq=%u", cc, - inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr), - seq); - (void)printf(" ttl=%d", ip->ip_ttl); + (void)printf("%zd bytes from %s: icmp_seq=%u", cc, + pr_addr(from->sin_addr), seq); + (void)printf(" ttl=%d", ip.ip_ttl); if (timing) (void)printf(" time=%.3f ms", triptime); if (dupflag) @@ -1273,12 +1311,12 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timeval *tv) if (options & F_MASK) { /* Just prentend this cast isn't ugly */ (void)printf(" mask=%s", - inet_ntoa(*(struct in_addr *)&(icp->icmp_mask))); + inet_ntoa(*(struct in_addr *)&(icp.icmp_mask))); } if (options & F_TIME) { - (void)printf(" tso=%s", pr_ntime(icp->icmp_otime)); - (void)printf(" tsr=%s", pr_ntime(icp->icmp_rtime)); - (void)printf(" tst=%s", pr_ntime(icp->icmp_ttime)); + (void)printf(" tso=%s", pr_ntime(icp.icmp_otime)); + (void)printf(" tsr=%s", pr_ntime(icp.icmp_rtime)); + (void)printf(" tst=%s", pr_ntime(icp.icmp_ttime)); } if (recv_len != send_len) { (void)printf( @@ -1286,7 +1324,8 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timeval *tv) recv_len, send_len); } /* check the data */ - cp = (u_char*)&icp->icmp_data[phdr_len]; + cp = (u_char*)(buf + hlen + offsetof(struct icmp, + icmp_data) + phdr_len); dp = &outpack[ICMP_MINLEN + phdr_len]; cc -= ICMP_MINLEN + phdr_len; i = 0; @@ -1301,7 +1340,8 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timeval *tv) (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", i, *dp, *cp); (void)printf("\ncp:"); - cp = (u_char*)&icp->icmp_data[0]; + cp = (u_char*)(buf + hlen + + offsetof(struct icmp, icmp_data)); for (i = 0; i < datalen; ++i, ++cp) { if ((i % 16) == 8) (void)printf("\n\t"); @@ -1329,22 +1369,22 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timeval *tv) * as root to avoid leaking information not normally * available to those not running as root. */ -#ifndef icmp_data - struct ip *oip = &icp->icmp_ip; -#else - struct ip *oip = (struct ip *)icp->icmp_data; -#endif - struct icmp *oicmp = (struct icmp *)(oip + 1); + memcpy(&oip_header_len, icmp_data_raw, sizeof(oip_header_len)); + oip_header_len = (oip_header_len & 0x0f) << 2; + memcpy(&oip, icmp_data_raw, oip_header_len); + oicmp_raw = icmp_data_raw + oip_header_len; + memcpy(&oicmp, oicmp_raw, offsetof(struct icmp, icmp_id) + + sizeof(oicmp.icmp_id)); if (((options & F_VERBOSE) && uid == 0) || (!(options & F_QUIET2) && - (oip->ip_dst.s_addr == whereto.sin_addr.s_addr) && - (oip->ip_p == IPPROTO_ICMP) && - (oicmp->icmp_type == ICMP_ECHO) && - (oicmp->icmp_id == ident))) { - (void)printf("%d bytes from %s: ", cc, + (oip.ip_dst.s_addr == whereto.sin_addr.s_addr) && + (oip.ip_p == IPPROTO_ICMP) && + (oicmp.icmp_type == ICMP_ECHO) && + (oicmp.icmp_id == ident))) { + (void)printf("%zd bytes from %s: ", cc, pr_addr(from->sin_addr)); - pr_icmph(icp); + pr_icmph(&icp, &oip, oicmp_raw); } else return; } @@ -1438,65 +1478,6 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timeval *tv) } } -/* - * in_cksum -- - * Checksum routine for Internet Protocol family headers (C Version) - */ -u_short -in_cksum(u_short *addr, int len) -{ - int nleft, sum; - u_short *w; - union { - u_short us; - u_char uc[2]; - } last; - u_short answer; - - nleft = len; - sum = 0; - w = addr; - - /* - * Our algorithm is simple, using a 32 bit accumulator (sum), we add - * sequential 16 bit words to it, and at the end, fold back all the - * carry bits from the top 16 bits into the lower 16 bits. - */ - while (nleft > 1) { - sum += *w++; - nleft -= 2; - } - - /* mop up an odd byte, if necessary */ - if (nleft == 1) { - last.uc[0] = *(u_char *)w; - last.uc[1] = 0; - sum += last.us; - } - - /* add back carry outs from top 16 bits to low 16 bits */ - sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ - sum += (sum >> 16); /* add carry */ - answer = ~sum; /* truncate to 16 bits */ - return(answer); -} - -/* - * tvsub -- - * Subtract 2 timeval structs: out = out - in. Out is assumed to - * be >= in. - */ -static void -tvsub(struct timeval *out, const struct timeval *in) -{ - - if ((out->tv_usec -= in->tv_usec) < 0) { - --out->tv_sec; - out->tv_usec += 1000000; - } - out->tv_sec -= in->tv_sec; -} - #ifndef __rtems__ /* * status -- @@ -1593,7 +1574,7 @@ static char *ttab[] = { * Print a descriptive string about an ICMP header. */ static void -pr_icmph(struct icmp *icp) +pr_icmph(struct icmp *icp, struct ip *oip, const u_char *const oicmp_raw) { switch(icp->icmp_type) { @@ -1631,19 +1612,11 @@ pr_icmph(struct icmp *icp) break; } /* Print returned IP header information */ -#ifndef icmp_data - pr_retip(&icp->icmp_ip); -#else - pr_retip((struct ip *)icp->icmp_data); -#endif + pr_retip(oip, oicmp_raw); break; case ICMP_SOURCEQUENCH: (void)printf("Source Quench\n"); -#ifndef icmp_data - pr_retip(&icp->icmp_ip); -#else - pr_retip((struct ip *)icp->icmp_data); -#endif + pr_retip(oip, oicmp_raw); break; case ICMP_REDIRECT: switch(icp->icmp_code) { @@ -1664,11 +1637,7 @@ pr_icmph(struct icmp *icp) break; } (void)printf("(New addr: %s)\n", inet_ntoa(icp->icmp_gwaddr)); -#ifndef icmp_data - pr_retip(&icp->icmp_ip); -#else - pr_retip((struct ip *)icp->icmp_data); -#endif + pr_retip(oip, oicmp_raw); break; case ICMP_ECHO: (void)printf("Echo Request\n"); @@ -1687,20 +1656,12 @@ pr_icmph(struct icmp *icp) icp->icmp_code); break; } -#ifndef icmp_data - pr_retip(&icp->icmp_ip); -#else - pr_retip((struct ip *)icp->icmp_data); -#endif + pr_retip(oip, oicmp_raw); break; case ICMP_PARAMPROB: (void)printf("Parameter problem: pointer = 0x%02x\n", icp->icmp_hun.ih_pptr); -#ifndef icmp_data - pr_retip(&icp->icmp_ip); -#else - pr_retip((struct ip *)icp->icmp_data); -#endif + pr_retip(oip, oicmp_raw); break; case ICMP_TSTAMP: (void)printf("Timestamp\n"); @@ -1798,14 +1759,9 @@ pr_addr(struct in_addr ina) * Dump some info on a returned (via ICMP) IP packet. */ static void -pr_retip(struct ip *ip) +pr_retip(struct ip *ip, const u_char *cp) { - u_char *cp; - int hlen; - pr_iph(ip); - hlen = ip->ip_hl << 2; - cp = (u_char *)ip + hlen; if (ip->ip_p == 6) (void)printf("TCP: from port %u, to port %u (decimal)\n", @@ -1818,7 +1774,7 @@ pr_retip(struct ip *ip) static char * pr_ntime(n_time timestamp) { - static char buf[10]; + static char buf[11]; int hour, min, sec; sec = ntohl(timestamp) / 1000; @@ -1867,9 +1823,10 @@ static cap_channel_t * capdns_setup(void) { cap_channel_t *capcas, *capdnsloc; +#ifdef WITH_CASPER const char *types[2]; int families[1]; - +#endif capcas = cap_init(); if (capcas == NULL) err(1, "unable to create casper process"); @@ -1878,6 +1835,7 @@ capdns_setup(void) cap_close(capcas); if (capdnsloc == NULL) err(1, "unable to open system.dns service"); +#ifdef WITH_CASPER types[0] = "NAME2ADDR"; types[1] = "ADDR2NAME"; if (cap_dns_type_limit(capdnsloc, types, 2) < 0) @@ -1885,7 +1843,7 @@ capdns_setup(void) families[0] = AF_INET; if (cap_dns_family_limit(capdnsloc, families, 1) < 0) err(1, "unable to limit access to system.dns service"); - +#endif return (capdnsloc); } #endif /* __rtems__ */ @@ -1900,11 +1858,11 @@ usage(void) { (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", -"usage: ping [-AaDdfnoQqRrv] [-c count] [-G sweepmaxsize] [-g sweepminsize]", +"usage: ping [-AaDdfHnoQqRrv] [-c count] [-G sweepmaxsize] [-g sweepminsize]", " [-h sweepincrsize] [-i wait] [-l preload] [-M mask | time] [-m ttl]", " " SECOPT " [-p pattern] [-S src_addr] [-s packetsize] [-t timeout]", " [-W waittime] [-z tos] host", -" ping [-AaDdfLnoQqRrv] [-c count] [-I iface] [-i wait] [-l preload]", +" ping [-AaDdfHLnoQqRrv] [-c count] [-I iface] [-i wait] [-l preload]", " [-M mask | time] [-m ttl]" SECOPT " [-p pattern] [-S src_addr]", " [-s packetsize] [-T ttl] [-t timeout] [-W waittime]", " [-z tos] mcast-group"); diff --git a/freebsd/sbin/ping/utils.c b/freebsd/sbin/ping/utils.c new file mode 100644 index 00000000..3e0fe2b1 --- /dev/null +++ b/freebsd/sbin/ping/utils.c @@ -0,0 +1,100 @@ +#include <machine/rtems-bsd-user-space.h> + +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Muuss. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1989, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93"; +#endif /* not lint */ +#endif +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <string.h> + +#include "utils.h" + +/* + * in_cksum -- + * Checksum routine for Internet Protocol family headers (C Version) + */ +u_short +in_cksum(u_char *addr, int len) +{ + int nleft, sum; + u_char *w; + union { + u_short us; + u_char uc[2]; + } last; + u_short answer; + + nleft = len; + sum = 0; + w = addr; + + /* + * Our algorithm is simple, using a 32 bit accumulator (sum), we add + * sequential 16 bit words to it, and at the end, fold back all the + * carry bits from the top 16 bits into the lower 16 bits. + */ + while (nleft > 1) { + u_short data; + + memcpy(&data, w, sizeof(data)); + sum += data; + w += sizeof(data); + nleft -= sizeof(data); + } + + /* mop up an odd byte, if necessary */ + if (nleft == 1) { + last.uc[0] = *w; + last.uc[1] = 0; + sum += last.us; + } + + /* add back carry outs from top 16 bits to low 16 bits */ + sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* truncate to 16 bits */ + return(answer); +} diff --git a/freebsd/sbin/ping/utils.h b/freebsd/sbin/ping/utils.h new file mode 100644 index 00000000..cb56e587 --- /dev/null +++ b/freebsd/sbin/ping/utils.h @@ -0,0 +1,38 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (C) 2019 Jan Sucan <jansucan@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + * + * $FreeBSD$ + */ + +#ifndef UTILS_H +#define UTILS_H 1 + +#include <sys/types.h> + +u_short in_cksum(u_char *, int); + +#endif diff --git a/freebsd/sbin/ping6/ping6.c b/freebsd/sbin/ping6/ping6.c index c95572b0..a56aae1d 100644 --- a/freebsd/sbin/ping6/ping6.c +++ b/freebsd/sbin/ping6/ping6.c @@ -72,6 +72,7 @@ */ #if defined(__rtems__) && defined(INET6) +#if 0 #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1989, 1993\n\ @@ -79,10 +80,9 @@ static const char copyright[] = #endif /* not lint */ #ifndef lint -#if 0 static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93"; -#endif #endif /* not lint */ +#endif #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); @@ -117,9 +117,9 @@ __FBSDID("$FreeBSD$"); #include <machine/rtems-bsd-commands.h> #endif /* __rtems__ */ #include <sys/param.h> +#include <sys/capsicum.h> #include <sys/uio.h> #include <sys/socket.h> -#include <sys/time.h> #include <net/if.h> #include <net/route.h> @@ -131,6 +131,10 @@ __FBSDID("$FreeBSD$"); #include <arpa/nameser.h> #include <netdb.h> +#include <capsicum_helpers.h> +#include <casper/cap_dns.h> +#include <libcasper.h> + #include <ctype.h> #include <err.h> #include <errno.h> @@ -141,6 +145,7 @@ __FBSDID("$FreeBSD$"); #include <stdlib.h> #include <string.h> #include <sysexits.h> +#include <time.h> #include <unistd.h> #ifdef IPSEC @@ -155,7 +160,7 @@ __FBSDID("$FreeBSD$"); struct tv32 { u_int32_t tv32_sec; - u_int32_t tv32_usec; + u_int32_t tv32_nsec; }; #define MAXPACKETLEN 131072 @@ -209,7 +214,7 @@ struct tv32 { #define F_DONTFRAG 0x1000000 #define F_NOUSERDATA (F_NODEADDR | F_FQDN | F_FQDNOLD | F_SUPTYPES) #define F_WAITTIME 0x2000000 -u_int options; +static u_int options; #define IN6LEN sizeof(struct in6_addr) #define SA6LEN sizeof(struct sockaddr_in6) @@ -230,7 +235,8 @@ static struct sockaddr_in6 dst; /* who to ping6 */ static struct sockaddr_in6 src; /* src addr of this packet */ static socklen_t srclen; static size_t datalen = DEFDATALEN; -static int s; /* socket file descriptor */ +static int ssend; /* send socket file descriptor */ +static int srecv; /* receive socket file descriptor */ static u_char outpack[MAXPACKETLEN]; static char BSPACE = '\b'; /* characters written for flood */ static char BBELL = '\a'; /* characters written for AUDIBLE */ @@ -240,6 +246,7 @@ static int ident; /* process id to identify our packets */ static u_int8_t nonce[8]; /* nonce field for node information */ static int hoplimit = -1; /* hoplimit */ static u_char *packet = NULL; +static cap_channel_t *capdns; /* counters */ static long nmissedmax; /* max value of ntransmitted - nreceived - 1 */ @@ -274,6 +281,7 @@ static volatile sig_atomic_t seeninfo; #ifndef __rtems__ int main(int, char *[]); #endif /* __rtems__ */ +static cap_channel_t *capdns_setup(void); static void fill(char *, char *); static int get_hoplim(struct msghdr *); static int get_pathmtu(struct msghdr *); @@ -289,7 +297,7 @@ static void pr_suptypes(struct icmp6_nodeinfo *, size_t); static void pr_nodeaddr(struct icmp6_nodeinfo *, int); static int myechoreply(const struct icmp6_hdr *); static int mynireply(const struct icmp6_nodeinfo *); -static char *dnsdecode(const u_char **, const u_char *, const u_char *, +static const char *dnsdecode(const u_char *, const u_char *, const u_char *, char *, size_t); static void pr_pack(u_char *, int, struct msghdr *); static void pr_exthdrs(struct msghdr *); @@ -298,8 +306,11 @@ static void pr_rthdr(void *, size_t); static int pr_bitrange(u_int32_t, int, int); static void pr_retip(struct ip6_hdr *, u_char *); static void summary(void); -static void tvsub(struct timeval *, struct timeval *); +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC static int setpolicy(int, char *); +#endif +#endif static char *nigroup(char *, int); static void usage(void); @@ -332,7 +343,7 @@ rtems_bsd_command_ping6(int argc, char *argv[]) int main(int argc, char *argv[]) { - struct timeval last, intvl; + struct timespec last, intvl; struct sockaddr_in6 from, *sin6; struct addrinfo hints, *res; struct sigaction si_sa; @@ -345,19 +356,18 @@ main(int argc, char *argv[]) struct cmsghdr *scmsgp = NULL; /* For control (ancillary) data received from recvmsg() */ #ifndef __rtems__ - struct cmsghdr cm[CONTROLLEN]; + u_char cm[CONTROLLEN]; #else /* __rtems__ */ - static struct cmsghdr cm[CONTROLLEN]; + static u_char cm[CONTROLLEN]; #endif /* __rtems__ */ #if defined(SO_SNDBUF) && defined(SO_RCVBUF) u_long lsockbufsize; int sockbufsize = 0; #endif int usepktinfo = 0; - struct in6_pktinfo *pktinfo = NULL; -#ifdef USE_RFC2292BIS + struct in6_pktinfo pktinfo; + char *cmsg_pktinfo = NULL; struct ip6_rthdr *rthdr = NULL; -#endif #ifdef IPSEC_POLICY_IPSEC char *policy_in = NULL; char *policy_out = NULL; @@ -368,6 +378,9 @@ main(int argc, char *argv[]) #ifdef IPV6_USE_MIN_MTU int mflag = 0; #endif + cap_rights_t rights_srecv; + cap_rights_t rights_ssend; + cap_rights_t rights_stdin; #ifdef __rtems__ struct getopt_data getopt_data; memset(&getopt_data, 0, sizeof(getopt_data)); @@ -381,23 +394,28 @@ main(int argc, char *argv[]) /* just to be sure */ memset(&smsghdr, 0, sizeof(smsghdr)); memset(&smsgiov, 0, sizeof(smsgiov)); + memset(&pktinfo, 0, sizeof(pktinfo)); + + intvl.tv_sec = interval / 1000; + intvl.tv_nsec = interval % 1000 * 1000000; alarmtimeout = preload = 0; datap = &outpack[ICMP6ECHOLEN + ICMP6ECHOTMLEN]; + capdns = capdns_setup(); #ifndef IPSEC #define ADDOPTS #else #ifdef IPSEC_POLICY_IPSEC #define ADDOPTS "P:" #else -#define ADDOPTS "AE" +#define ADDOPTS "ZE" #endif /*IPSEC_POLICY_IPSEC*/ #endif while ((ch = getopt(argc, argv, - "a:b:c:DdfHg:h:I:i:l:mnNop:qrRS:s:tvwWx:X:" ADDOPTS)) != -1) { + "k:b:c:DdfHe:m:I:i:l:unNop:qaAS:s:OvyYW:t:" ADDOPTS)) != -1) { #undef ADDOPTS switch (ch) { - case 'a': + case 'k': { char *cp; @@ -474,13 +492,13 @@ main(int argc, char *argv[]) options |= F_FLOOD; setbuf(stdout, (char *)NULL); break; - case 'g': + case 'e': gateway = optarg; break; case 'H': options |= F_HOSTNAME; break; - case 'h': /* hoplimit */ + case 'm': /* hoplimit */ hoplimit = strtol(optarg, &e, 10); if (*optarg == '\0' || *e != '\0') errx(1, "illegal hoplimit %s", optarg); @@ -503,15 +521,15 @@ main(int argc, char *argv[]) errx(1, "%s: only root may use interval < 1s", strerror(EPERM)); } - intvl.tv_sec = (long)t; - intvl.tv_usec = - (long)((t - intvl.tv_sec) * 1000000); + intvl.tv_sec = (time_t)t; + intvl.tv_nsec = + (long)((t - intvl.tv_sec) * 1000000000); if (intvl.tv_sec < 0) errx(1, "illegal timing interval %s", optarg); /* less than 1/hz does not make sense */ - if (intvl.tv_sec == 0 && intvl.tv_usec < 1) { + if (intvl.tv_sec == 0 && intvl.tv_nsec < 1000) { warnx("too small interval, raised to .000001"); - intvl.tv_usec = 1; + intvl.tv_nsec = 1000; } options |= F_INTERVAL; break; @@ -524,7 +542,7 @@ main(int argc, char *argv[]) if (preload < 0 || *optarg == '\0' || *e != '\0') errx(1, "illegal preload value -- %s", optarg); break; - case 'm': + case 'u': #ifdef IPV6_USE_MIN_MTU mflag++; break; @@ -549,10 +567,10 @@ main(int argc, char *argv[]) case 'q': options |= F_QUIET; break; - case 'r': + case 'a': options |= F_AUDIBLE; break; - case 'R': + case 'A': options |= F_MISSED; break; case 'S': @@ -562,7 +580,7 @@ main(int argc, char *argv[]) hints.ai_socktype = SOCK_RAW; hints.ai_protocol = IPPROTO_ICMPV6; - error = getaddrinfo(optarg, NULL, &hints, &res); + error = cap_getaddrinfo(capdns, optarg, NULL, &hints, &res); if (error) { errx(1, "invalid source address: %s", gai_strerror(error)); @@ -586,22 +604,22 @@ main(int argc, char *argv[]) MAXDATALEN); } break; - case 't': + case 'O': options &= ~F_NOUSERDATA; options |= F_SUPTYPES; break; case 'v': options |= F_VERBOSE; break; - case 'w': + case 'y': options &= ~F_NOUSERDATA; options |= F_FQDN; break; - case 'W': + case 'Y': options &= ~F_NOUSERDATA; options |= F_FQDNOLD; break; - case 'x': + case 'W': t = strtod(optarg, &e); if (*e || e == optarg || t > (double)INT_MAX) err(EX_USAGE, "invalid timing interval: `%s'", @@ -609,7 +627,7 @@ main(int argc, char *argv[]) options |= F_WAITTIME; waittime = (int)t; break; - case 'X': + case 't': alarmtimeout = strtoul(optarg, &e, 0); if ((alarmtimeout < 1) || (alarmtimeout == ULONG_MAX)) errx(EX_USAGE, "invalid timeout: `%s'", @@ -633,7 +651,7 @@ main(int argc, char *argv[]) errx(1, "invalid security policy"); break; #else - case 'A': + case 'Z': options |= F_AUTHHDR; break; case 'E': @@ -678,14 +696,14 @@ main(int argc, char *argv[]) } else target = argv[argc - 1]; - /* getaddrinfo */ + /* cap_getaddrinfo */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_flags = AI_CANONNAME; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_RAW; hints.ai_protocol = IPPROTO_ICMPV6; - error = getaddrinfo(target, NULL, &hints, &res); + error = cap_getaddrinfo(capdns, target, NULL, &hints, &res); if (error) errx(1, "%s", gai_strerror(error)); if (res->ai_canonname) @@ -694,13 +712,16 @@ main(int argc, char *argv[]) hostname = target; if (!res->ai_addr) - errx(1, "getaddrinfo failed"); + errx(1, "cap_getaddrinfo failed"); (void)memcpy(&dst, res->ai_addr, res->ai_addrlen); - if ((s = socket(res->ai_family, res->ai_socktype, + if ((ssend = socket(res->ai_family, res->ai_socktype, + res->ai_protocol)) < 0) + err(1, "socket ssend"); + if ((srecv = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) - err(1, "socket"); + err(1, "socket srecv"); freeaddrinfo(res); /* set the source address if specified. */ @@ -715,7 +736,7 @@ main(int argc, char *argv[]) if (dst.sin6_scope_id == 0) dst.sin6_scope_id = src.sin6_scope_id; } - if (bind(s, (struct sockaddr *)&src, srclen) != 0) + if (bind(ssend, (struct sockaddr *)&src, srclen) != 0) err(1, "bind"); } /* set the gateway (next hop) if specified */ @@ -725,15 +746,15 @@ main(int argc, char *argv[]) hints.ai_socktype = SOCK_RAW; hints.ai_protocol = IPPROTO_ICMPV6; - error = getaddrinfo(gateway, NULL, &hints, &res); + error = cap_getaddrinfo(capdns, gateway, NULL, &hints, &res); if (error) { - errx(1, "getaddrinfo for the gateway %s: %s", + errx(1, "cap_getaddrinfo for the gateway %s: %s", gateway, gai_strerror(error)); } if (res->ai_next && (options & F_VERBOSE)) warnx("gateway resolves to multiple addresses"); - if (setsockopt(s, IPPROTO_IPV6, IPV6_NEXTHOP, + if (setsockopt(ssend, IPPROTO_IPV6, IPV6_NEXTHOP, res->ai_addr, res->ai_addrlen)) { err(1, "setsockopt(IPV6_NEXTHOP)"); } @@ -749,25 +770,25 @@ main(int argc, char *argv[]) int opton = 1; #ifdef IPV6_RECVHOPOPTS - if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &opton, + if (setsockopt(srecv, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &opton, sizeof(opton))) err(1, "setsockopt(IPV6_RECVHOPOPTS)"); #else /* old adv. API */ - if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPOPTS, &opton, + if (setsockopt(srecv, IPPROTO_IPV6, IPV6_HOPOPTS, &opton, sizeof(opton))) err(1, "setsockopt(IPV6_HOPOPTS)"); #endif #ifdef IPV6_RECVDSTOPTS - if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVDSTOPTS, &opton, + if (setsockopt(srecv, IPPROTO_IPV6, IPV6_RECVDSTOPTS, &opton, sizeof(opton))) err(1, "setsockopt(IPV6_RECVDSTOPTS)"); #else /* old adv. API */ - if (setsockopt(s, IPPROTO_IPV6, IPV6_DSTOPTS, &opton, + if (setsockopt(srecv, IPPROTO_IPV6, IPV6_DSTOPTS, &opton, sizeof(opton))) err(1, "setsockopt(IPV6_DSTOPTS)"); #endif #ifdef IPV6_RECVRTHDRDSTOPTS - if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDRDSTOPTS, &opton, + if (setsockopt(srecv, IPPROTO_IPV6, IPV6_RECVRTHDRDSTOPTS, &opton, sizeof(opton))) err(1, "setsockopt(IPV6_RECVRTHDRDSTOPTS)"); #endif @@ -810,31 +831,34 @@ main(int argc, char *argv[]) arc4random_buf(nonce, sizeof(nonce)); optval = 1; if (options & F_DONTFRAG) - if (setsockopt(s, IPPROTO_IPV6, IPV6_DONTFRAG, + if (setsockopt(ssend, IPPROTO_IPV6, IPV6_DONTFRAG, &optval, sizeof(optval)) == -1) err(1, "IPV6_DONTFRAG"); hold = 1; - if (options & F_SO_DEBUG) - (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&hold, + if (options & F_SO_DEBUG) { + (void)setsockopt(ssend, SOL_SOCKET, SO_DEBUG, (char *)&hold, sizeof(hold)); + (void)setsockopt(srecv, SOL_SOCKET, SO_DEBUG, (char *)&hold, + sizeof(hold)); + } optval = IPV6_DEFHLIM; if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) - if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, + if (setsockopt(ssend, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &optval, sizeof(optval)) == -1) err(1, "IPV6_MULTICAST_HOPS"); #ifdef IPV6_USE_MIN_MTU if (mflag != 1) { optval = mflag > 1 ? 0 : 1; - if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU, + if (setsockopt(ssend, IPPROTO_IPV6, IPV6_USE_MIN_MTU, &optval, sizeof(optval)) == -1) err(1, "setsockopt(IPV6_USE_MIN_MTU)"); } #ifdef IPV6_RECVPATHMTU else { optval = 1; - if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPATHMTU, + if (setsockopt(srecv, IPPROTO_IPV6, IPV6_RECVPATHMTU, &optval, sizeof(optval)) == -1) err(1, "setsockopt(IPV6_RECVPATHMTU)"); } @@ -844,27 +868,36 @@ main(int argc, char *argv[]) #ifdef IPSEC #ifdef IPSEC_POLICY_IPSEC if (options & F_POLICY) { - if (setpolicy(s, policy_in) < 0) + if (setpolicy(srecv, policy_in) < 0) errx(1, "%s", ipsec_strerror()); - if (setpolicy(s, policy_out) < 0) + if (setpolicy(ssend, policy_out) < 0) errx(1, "%s", ipsec_strerror()); } #else if (options & F_AUTHHDR) { optval = IPSEC_LEVEL_REQUIRE; #ifdef IPV6_AUTH_TRANS_LEVEL - if (setsockopt(s, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, + if (setsockopt(ssend, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &optval, sizeof(optval)) == -1) err(1, "setsockopt(IPV6_AUTH_TRANS_LEVEL)"); + if (setsockopt(srecv, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, + &optval, sizeof(optval)) == -1) + err(1, "setsockopt(IPV6_AUTH_TRANS_LEVEL)"); #else /* old def */ - if (setsockopt(s, IPPROTO_IPV6, IPV6_AUTH_LEVEL, + if (setsockopt(ssend, IPPROTO_IPV6, IPV6_AUTH_LEVEL, + &optval, sizeof(optval)) == -1) + err(1, "setsockopt(IPV6_AUTH_LEVEL)"); + if (setsockopt(srecv, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &optval, sizeof(optval)) == -1) err(1, "setsockopt(IPV6_AUTH_LEVEL)"); #endif } if (options & F_ENCRYPT) { optval = IPSEC_LEVEL_REQUIRE; - if (setsockopt(s, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, + if (setsockopt(ssend, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, + &optval, sizeof(optval)) == -1) + err(1, "setsockopt(IPV6_ESP_TRANS_LEVEL)"); + if (setsockopt(srecv, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &optval, sizeof(optval)) == -1) err(1, "setsockopt(IPV6_ESP_TRANS_LEVEL)"); } @@ -884,7 +917,7 @@ main(int argc, char *argv[]) } else { ICMP6_FILTER_SETPASSALL(&filt); } - if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, + if (setsockopt(srecv, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, sizeof(filt)) < 0) err(1, "setsockopt(ICMP6_FILTER)"); } @@ -895,11 +928,11 @@ main(int argc, char *argv[]) int opton = 1; #ifdef IPV6_RECVRTHDR - if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDR, &opton, + if (setsockopt(srecv, IPPROTO_IPV6, IPV6_RECVRTHDR, &opton, sizeof(opton))) err(1, "setsockopt(IPV6_RECVRTHDR)"); #else /* old adv. API */ - if (setsockopt(s, IPPROTO_IPV6, IPV6_RTHDR, &opton, + if (setsockopt(srecv, IPPROTO_IPV6, IPV6_RTHDR, &opton, sizeof(opton))) err(1, "setsockopt(IPV6_RTHDR)"); #endif @@ -908,7 +941,7 @@ main(int argc, char *argv[]) /* optval = 1; if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) - if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, + if (setsockopt(ssend, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &optval, sizeof(optval)) == -1) err(1, "IPV6_MULTICAST_LOOP"); */ @@ -926,11 +959,10 @@ main(int argc, char *argv[]) errx(1, "can't allocate enough memory"); smsghdr.msg_control = (caddr_t)scmsg; smsghdr.msg_controllen = ip6optlen; - scmsgp = (struct cmsghdr *)scmsg; + scmsgp = CMSG_FIRSTHDR(&smsghdr); } if (usepktinfo) { - pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp)); - memset(pktinfo, 0, sizeof(*pktinfo)); + cmsg_pktinfo = CMSG_DATA(scmsgp); scmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); scmsgp->cmsg_level = IPPROTO_IPV6; scmsgp->cmsg_type = IPV6_PKTINFO; @@ -941,7 +973,7 @@ main(int argc, char *argv[]) if (ifname) { #ifndef USE_SIN6_SCOPE_ID /* pktinfo must have already been allocated */ - if ((pktinfo->ipi6_ifindex = if_nametoindex(ifname)) == 0) + if ((pktinfo.ipi6_ifindex = if_nametoindex(ifname)) == 0) errx(1, "%s: invalid interface name", ifname); #else if ((dst.sin6_scope_id = if_nametoindex(ifname)) == 0) @@ -952,18 +984,15 @@ main(int argc, char *argv[]) scmsgp->cmsg_len = CMSG_LEN(sizeof(int)); scmsgp->cmsg_level = IPPROTO_IPV6; scmsgp->cmsg_type = IPV6_HOPLIMIT; - *(int *)(CMSG_DATA(scmsgp)) = hoplimit; + memcpy(CMSG_DATA(scmsgp), &hoplimit, sizeof(hoplimit)); scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp); } if (argc > 1) { /* some intermediate addrs are specified */ int hops; -#ifdef USE_RFC2292BIS int rthdrlen; -#endif -#ifdef USE_RFC2292BIS rthdrlen = inet6_rth_space(IPV6_RTHDR_TYPE_0, argc - 1); scmsgp->cmsg_len = CMSG_LEN(rthdrlen); scmsgp->cmsg_level = IPPROTO_IPV6; @@ -973,42 +1002,36 @@ main(int argc, char *argv[]) IPV6_RTHDR_TYPE_0, argc - 1); if (rthdr == NULL) errx(1, "can't initialize rthdr"); -#else /* old advanced API */ - if ((scmsgp = (struct cmsghdr *)inet6_rthdr_init(scmsgp, - IPV6_RTHDR_TYPE_0)) == NULL) - errx(1, "can't initialize rthdr"); -#endif /* USE_RFC2292BIS */ for (hops = 0; hops < argc - 1; hops++) { memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; - if ((error = getaddrinfo(argv[hops], NULL, &hints, + if ((error = cap_getaddrinfo(capdns, argv[hops], NULL, &hints, &res))) errx(1, "%s", gai_strerror(error)); if (res->ai_addr->sa_family != AF_INET6) errx(1, "bad addr family of an intermediate addr"); sin6 = (struct sockaddr_in6 *)(void *)res->ai_addr; -#ifdef USE_RFC2292BIS if (inet6_rth_add(rthdr, &sin6->sin6_addr)) errx(1, "can't add an intermediate node"); -#else /* old advanced API */ - if (inet6_rthdr_add(scmsg, &sin6->sin6_addr, - IPV6_RTHDR_LOOSE)) - errx(1, "can't add an intermediate node"); -#endif /* USE_RFC2292BIS */ freeaddrinfo(res); } -#ifndef USE_RFC2292BIS - if (inet6_rthdr_lasthop(scmsgp, IPV6_RTHDR_LOOSE)) - errx(1, "can't set the last flag"); -#endif - scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp); } + /* From now on we will use only reverse DNS lookups. */ +#ifdef WITH_CASPER + if (capdns != NULL) { + const char *types[1]; + + types[0] = "ADDR2NAME"; + if (cap_dns_type_limit(capdns, types, nitems(types)) < 0) + err(1, "unable to limit access to system.dns service"); + } +#endif if (!(options & F_SRCADDR)) { /* * get the source address. XXX since we revoked the root @@ -1025,10 +1048,9 @@ main(int argc, char *argv[]) src.sin6_port = ntohs(DUMMY_PORT); src.sin6_scope_id = dst.sin6_scope_id; -#ifdef USE_RFC2292BIS - if (pktinfo && + if (usepktinfo && setsockopt(dummy, IPPROTO_IPV6, IPV6_PKTINFO, - (void *)pktinfo, sizeof(*pktinfo))) + (void *)&pktinfo, sizeof(pktinfo))) err(1, "UDP setsockopt(IPV6_PKTINFO)"); if (hoplimit != -1 && @@ -1045,12 +1067,6 @@ main(int argc, char *argv[]) setsockopt(dummy, IPPROTO_IPV6, IPV6_RTHDR, (void *)rthdr, (rthdr->ip6r_len + 1) << 3)) err(1, "UDP setsockopt(IPV6_RTHDR)"); -#else /* old advanced API */ - if (smsghdr.msg_control && - setsockopt(dummy, IPPROTO_IPV6, IPV6_PKTOPTIONS, - (void *)smsghdr.msg_control, smsghdr.msg_controllen)) - err(1, "UDP setsockopt(IPV6_PKTOPTIONS)"); -#endif if (connect(dummy, (struct sockaddr *)&src, len) < 0) err(1, "UDP connect"); @@ -1061,14 +1077,40 @@ main(int argc, char *argv[]) close(dummy); } + /* Save pktinfo in the ancillary data. */ + if (usepktinfo) + memcpy(cmsg_pktinfo, &pktinfo, sizeof(pktinfo)); + + if (connect(ssend, (struct sockaddr *)&dst, sizeof(dst)) != 0) + err(1, "connect() ssend"); + + caph_cache_catpages(); + if (caph_enter_casper() < 0) + err(1, "caph_enter_casper"); + + cap_rights_init(&rights_stdin); + if (caph_rights_limit(STDIN_FILENO, &rights_stdin) < 0) + err(1, "caph_rights_limit stdin"); + if (caph_limit_stdout() < 0) + err(1, "caph_limit_stdout"); + if (caph_limit_stderr() < 0) + err(1, "caph_limit_stderr"); + + cap_rights_init(&rights_srecv, CAP_RECV, CAP_EVENT, CAP_SETSOCKOPT); + if (caph_rights_limit(srecv, &rights_srecv) < 0) + err(1, "caph_rights_limit srecv"); + cap_rights_init(&rights_ssend, CAP_SEND, CAP_SETSOCKOPT); + if (caph_rights_limit(ssend, &rights_ssend) < 0) + err(1, "caph_rights_limit ssend"); + #if defined(SO_SNDBUF) && defined(SO_RCVBUF) if (sockbufsize) { if (datalen > (size_t)sockbufsize) warnx("you need -b to increase socket buffer size"); - if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sockbufsize, + if (setsockopt(ssend, SOL_SOCKET, SO_SNDBUF, &sockbufsize, sizeof(sockbufsize)) < 0) err(1, "setsockopt(SO_SNDBUF)"); - if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &sockbufsize, + if (setsockopt(srecv, SOL_SOCKET, SO_RCVBUF, &sockbufsize, sizeof(sockbufsize)) < 0) err(1, "setsockopt(SO_RCVBUF)"); } @@ -1082,7 +1124,7 @@ main(int argc, char *argv[]) * to get some stuff for /etc/ethers. */ hold = 48 * 1024; - setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold, + setsockopt(srecv, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof(hold)); } #endif @@ -1090,25 +1132,32 @@ main(int argc, char *argv[]) optval = 1; #ifndef USE_SIN6_SCOPE_ID #ifdef IPV6_RECVPKTINFO - if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &optval, + if (setsockopt(srecv, IPPROTO_IPV6, IPV6_RECVPKTINFO, &optval, sizeof(optval)) < 0) warn("setsockopt(IPV6_RECVPKTINFO)"); /* XXX err? */ #else /* old adv. API */ - if (setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, &optval, + if (setsockopt(srecv, IPPROTO_IPV6, IPV6_PKTINFO, &optval, sizeof(optval)) < 0) warn("setsockopt(IPV6_PKTINFO)"); /* XXX err? */ #endif #endif /* USE_SIN6_SCOPE_ID */ #ifdef IPV6_RECVHOPLIMIT - if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &optval, + if (setsockopt(srecv, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &optval, sizeof(optval)) < 0) warn("setsockopt(IPV6_RECVHOPLIMIT)"); /* XXX err? */ #else /* old adv. API */ - if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPLIMIT, &optval, + if (setsockopt(srecv, IPPROTO_IPV6, IPV6_HOPLIMIT, &optval, sizeof(optval)) < 0) warn("setsockopt(IPV6_HOPLIMIT)"); /* XXX err? */ #endif + cap_rights_clear(&rights_srecv, CAP_SETSOCKOPT); + if (caph_rights_limit(srecv, &rights_srecv) < 0) + err(1, "caph_rights_limit srecv setsockopt"); + cap_rights_clear(&rights_ssend, CAP_SETSOCKOPT); + if (caph_rights_limit(ssend, &rights_ssend) < 0) + err(1, "caph_rights_limit ssend setsockopt"); + printf("PING6(%lu=40+8+%lu bytes) ", (unsigned long)(40 + pingerlen()), (unsigned long)(pingerlen() - 8)); printf("%s --> ", pr_addr((struct sockaddr *)&src, sizeof(src))); @@ -1122,7 +1171,7 @@ main(int argc, char *argv[]) while (preload--) pinger(); } - gettimeofday(&last, NULL); + clock_gettime(CLOCK_MONOTONIC, &last); sigemptyset(&si_sa.sa_mask); si_sa.sa_flags = 0; @@ -1141,15 +1190,12 @@ main(int argc, char *argv[]) } if (options & F_FLOOD) { intvl.tv_sec = 0; - intvl.tv_usec = 10000; - } else if ((options & F_INTERVAL) == 0) { - intvl.tv_sec = interval / 1000; - intvl.tv_usec = interval % 1000 * 1000; + intvl.tv_nsec = 10000000; } almost_done = 0; while (seenint == 0) { - struct timeval now, timeout; + struct timespec now, timeout; struct msghdr m; struct iovec iov[2]; fd_set rfds; @@ -1166,22 +1212,14 @@ main(int argc, char *argv[]) } #endif FD_ZERO(&rfds); - FD_SET(s, &rfds); - gettimeofday(&now, NULL); - timeout.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec; - timeout.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec; - while (timeout.tv_usec < 0) { - timeout.tv_usec += 1000000; - timeout.tv_sec--; - } - while (timeout.tv_usec > 1000000) { - timeout.tv_usec -= 1000000; - timeout.tv_sec++; - } + FD_SET(srecv, &rfds); + clock_gettime(CLOCK_MONOTONIC, &now); + timespecadd(&last, &intvl, &timeout); + timespecsub(&timeout, &now, &timeout); if (timeout.tv_sec < 0) - timeout.tv_sec = timeout.tv_usec = 0; + timespecclear(&timeout); - n = select(s + 1, &rfds, NULL, NULL, &timeout); + n = pselect(srecv + 1, &rfds, NULL, NULL, &timeout, NULL); if (n < 0) continue; /* EINTR */ if (n == 1) { @@ -1196,7 +1234,7 @@ main(int argc, char *argv[]) m.msg_control = (void *)cm; m.msg_controllen = CONTROLLEN; - cc = recvmsg(s, &m, 0); + cc = recvmsg(srecv, &m, 0); if (cc < 0) { if (errno != EINTR) { warn("recvmsg"); @@ -1242,17 +1280,18 @@ main(int argc, char *argv[]) * if we've received any packets or (waittime) * milliseconds if we haven't. */ - intvl.tv_usec = 0; + intvl.tv_nsec = 0; if (nreceived) { intvl.tv_sec = 2 * tmax / 1000; if (intvl.tv_sec == 0) intvl.tv_sec = 1; } else { intvl.tv_sec = waittime / 1000; - intvl.tv_usec = waittime % 1000 * 1000; + intvl.tv_nsec = + waittime % 1000 * 1000000; } } - gettimeofday(&last, NULL); + clock_gettime(CLOCK_MONOTONIC, &last); if (ntransmitted - nreceived - 1 > nmissedmax) { nmissedmax = ntransmitted - nreceived - 1; if (options & F_MISSED) @@ -1295,7 +1334,7 @@ onsignal(int sig) * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet * will be added on by the kernel. The ID field is our UNIX process ID, * and the sequence number is an ascending integer. The first 8 bytes - * of the data portion are used to hold a UNIX "timeval" struct in VAX + * of the data portion are used to hold a UNIX "timespec" struct in VAX * byte-order, to compute the round-trip time. */ static size_t @@ -1324,7 +1363,7 @@ pinger(void) struct iovec iov[2]; int i, cc; struct icmp6_nodeinfo *nip; - int seq; + uint16_t seq; if (npackets && ntransmitted >= npackets) return(-1); /* no more transmission */ @@ -1337,6 +1376,8 @@ pinger(void) CLR(seq % mx_dup_ck); if (options & F_FQDN) { + uint16_t s; + icp->icmp6_type = ICMP6_NI_QUERY; icp->icmp6_code = ICMP6_NI_SUBJ_IPV6; nip->ni_qtype = htons(NI_QTYPE_FQDN); @@ -1344,13 +1385,15 @@ pinger(void) memcpy(nip->icmp6_ni_nonce, nonce, sizeof(nip->icmp6_ni_nonce)); - *(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq); + s = htons(seq); + memcpy(nip->icmp6_ni_nonce, &s, sizeof(s)); memcpy(&outpack[ICMP6_NIQLEN], &dst.sin6_addr, sizeof(dst.sin6_addr)); cc = ICMP6_NIQLEN + sizeof(dst.sin6_addr); datalen = 0; } else if (options & F_FQDNOLD) { + uint16_t s; /* packet format in 03 draft - no Subject data on queries */ icp->icmp6_type = ICMP6_NI_QUERY; icp->icmp6_code = 0; /* code field is always 0 */ @@ -1359,11 +1402,14 @@ pinger(void) memcpy(nip->icmp6_ni_nonce, nonce, sizeof(nip->icmp6_ni_nonce)); - *(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq); + s = htons(seq); + memcpy(nip->icmp6_ni_nonce, &s, sizeof(s)); cc = ICMP6_NIQLEN; datalen = 0; } else if (options & F_NODEADDR) { + uint16_t s; + icp->icmp6_type = ICMP6_NI_QUERY; icp->icmp6_code = ICMP6_NI_SUBJ_IPV6; nip->ni_qtype = htons(NI_QTYPE_NODEADDR); @@ -1371,13 +1417,16 @@ pinger(void) memcpy(nip->icmp6_ni_nonce, nonce, sizeof(nip->icmp6_ni_nonce)); - *(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq); + s = htons(seq); + memcpy(nip->icmp6_ni_nonce, &s, sizeof(s)); memcpy(&outpack[ICMP6_NIQLEN], &dst.sin6_addr, sizeof(dst.sin6_addr)); cc = ICMP6_NIQLEN + sizeof(dst.sin6_addr); datalen = 0; } else if (options & F_SUPTYPES) { + uint16_t s; + icp->icmp6_type = ICMP6_NI_QUERY; icp->icmp6_code = ICMP6_NI_SUBJ_FQDN; /*empty*/ nip->ni_qtype = htons(NI_QTYPE_SUPTYPES); @@ -1386,21 +1435,29 @@ pinger(void) memcpy(nip->icmp6_ni_nonce, nonce, sizeof(nip->icmp6_ni_nonce)); - *(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq); + s = htons(seq); + memcpy(nip->icmp6_ni_nonce, &s, sizeof(s)); + cc = ICMP6_NIQLEN; datalen = 0; } else { icp->icmp6_type = ICMP6_ECHO_REQUEST; icp->icmp6_code = 0; icp->icmp6_id = htons(ident); - icp->icmp6_seq = ntohs(seq); + icp->icmp6_seq = htons(seq); if (timing) { - struct timeval tv; - struct tv32 *tv32; - (void)gettimeofday(&tv, NULL); - tv32 = (struct tv32 *)&outpack[ICMP6ECHOLEN]; - tv32->tv32_sec = htonl(tv.tv_sec); - tv32->tv32_usec = htonl(tv.tv_usec); + struct timespec tv; + struct tv32 tv32; + (void)clock_gettime(CLOCK_MONOTONIC, &tv); + /* + * Truncate seconds down to 32 bits in order + * to fit the timestamp within 8 bytes of the + * packet. We're only concerned with + * durations, not absolute times. + */ + tv32.tv32_sec = (uint32_t)htonl(tv.tv_sec); + tv32.tv32_nsec = (uint32_t)htonl(tv.tv_nsec); + memcpy(&outpack[ICMP6ECHOLEN], &tv32, sizeof(tv32)); } cc = ICMP6ECHOLEN + datalen; } @@ -1410,15 +1467,13 @@ pinger(void) errx(1, "internal error; length mismatch"); #endif - smsghdr.msg_name = (caddr_t)&dst; - smsghdr.msg_namelen = sizeof(dst); memset(&iov, 0, sizeof(iov)); iov[0].iov_base = (caddr_t)outpack; iov[0].iov_len = cc; smsghdr.msg_iov = iov; smsghdr.msg_iovlen = 1; - i = sendmsg(s, &smsghdr, 0); + i = sendmsg(ssend, &smsghdr, 0); if (i < 0 || i != cc) { if (i < 0) @@ -1452,10 +1507,26 @@ mynireply(const struct icmp6_nodeinfo *nip) return 0; } -static char * -dnsdecode(const u_char **sp, const u_char *ep, const u_char *base, char *buf, +/* + * Decode a name from a DNS message. + * + * Format of the message is described in RFC 1035 subsection 4.1.4. + * + * Arguments: + * sp - Pointer to a DNS pointer octet or to the first octet of a label + * in the message. + * ep - Pointer to the end of the message (one step past the last octet). + * base - Pointer to the beginning of the message. + * buf - Buffer into which the decoded name will be saved. + * bufsiz - Size of the buffer 'buf'. + * + * Return value: + * Pointer to an octet immediately following the ending zero octet + * of the decoded label, or NULL if an error occured. + */ +static const char * +dnsdecode(const u_char *sp, const u_char *ep, const u_char *base, char *buf, size_t bufsiz) - /*base for compressed name*/ { int i; const u_char *cp; @@ -1463,14 +1534,14 @@ dnsdecode(const u_char **sp, const u_char *ep, const u_char *base, char *buf, const u_char *comp; int l; - cp = *sp; + cp = sp; *buf = '\0'; if (cp >= ep) return NULL; while (cp < ep) { i = *cp; - if (i == 0 || cp != *sp) { + if (i == 0 || cp != sp) { if (strlcat((char *)buf, ".", bufsiz) >= bufsiz) return NULL; /*result overrun*/ } @@ -1484,7 +1555,7 @@ dnsdecode(const u_char **sp, const u_char *ep, const u_char *base, char *buf, return NULL; comp = base + (i & 0x3f); - if (dnsdecode(&comp, cp, base, cresult, + if (dnsdecode(comp, cp, base, cresult, sizeof(cresult)) == NULL) return NULL; if (strlcat(buf, cresult, bufsiz) >= bufsiz) @@ -1508,8 +1579,7 @@ dnsdecode(const u_char **sp, const u_char *ep, const u_char *base, char *buf, if (i != 0) return NULL; /*not terminated*/ cp++; - *sp = cp; - return buf; + return cp; } /* @@ -1529,10 +1599,11 @@ pr_pack(u_char *buf, int cc, struct msghdr *mhdr) int hoplim; struct sockaddr *from; int fromlen; - u_char *cp = NULL, *dp, *end = buf + cc; + const u_char *cp = NULL; + u_char *dp, *end = buf + cc; struct in6_pktinfo *pktinfo = NULL; - struct timeval tv, tp; - struct tv32 *tpp; + struct timespec tv, tp; + struct tv32 tpp; double triptime = 0; int dupflag; size_t off; @@ -1540,7 +1611,7 @@ pr_pack(u_char *buf, int cc, struct msghdr *mhdr) u_int16_t seq; char dnsname[MAXDNAME + 1]; - (void)gettimeofday(&tv, NULL); + (void)clock_gettime(CLOCK_MONOTONIC, &tv); if (!mhdr || !mhdr->msg_name || mhdr->msg_namelen != sizeof(struct sockaddr_in6) || @@ -1577,12 +1648,12 @@ pr_pack(u_char *buf, int cc, struct msghdr *mhdr) seq = ntohs(icp->icmp6_seq); ++nreceived; if (timing) { - tpp = (struct tv32 *)(icp + 1); - tp.tv_sec = ntohl(tpp->tv32_sec); - tp.tv_usec = ntohl(tpp->tv32_usec); - tvsub(&tv, &tp); + memcpy(&tpp, icp + 1, sizeof(tpp)); + tp.tv_sec = ntohl(tpp.tv32_sec); + tp.tv_nsec = ntohl(tpp.tv32_nsec); + timespecsub(&tv, &tp, &tv); triptime = ((double)tv.tv_sec) * 1000.0 + - ((double)tv.tv_usec) / 1000.0; + ((double)tv.tv_nsec) / 1000000.0; tsum += triptime; tsumsq += triptime * triptime; if (triptime < tmin) @@ -1643,7 +1714,8 @@ pr_pack(u_char *buf, int cc, struct msghdr *mhdr) } } } else if (icp->icmp6_type == ICMP6_NI_REPLY && mynireply(ni)) { - seq = ntohs(*(u_int16_t *)ni->icmp6_ni_nonce); + memcpy(&seq, ni->icmp6_ni_nonce, sizeof(seq)); + seq = ntohs(seq); ++nreceived; if (TST(seq % mx_dup_ck)) { ++nrepeats; @@ -1701,9 +1773,10 @@ pr_pack(u_char *buf, int cc, struct msghdr *mhdr) } else { i = 0; while (cp < end) { - if (dnsdecode((const u_char **)&cp, end, + cp = dnsdecode((const u_char *)cp, end, (const u_char *)(ni + 1), dnsname, - sizeof(dnsname)) == NULL) { + sizeof(dnsname)); + if (cp == NULL) { printf("???"); break; } @@ -1721,6 +1794,7 @@ pr_pack(u_char *buf, int cc, struct msghdr *mhdr) } } if (options & F_VERBOSE) { + u_long t; int32_t ttl; int comma = 0; @@ -1743,7 +1817,8 @@ pr_pack(u_char *buf, int cc, struct msghdr *mhdr) putchar(')'); goto fqdnend; } - ttl = (int32_t)ntohl(*(u_long *)&buf[off+ICMP6ECHOLEN+8]); + memcpy(&t, &buf[off+ICMP6ECHOLEN+8], sizeof(t)); + ttl = (int32_t)ntohl(t); if (comma) printf(","); if (!(ni->ni_flags & NI_FQDN_FLAG_VALIDTTL)) { @@ -1821,7 +1896,7 @@ pr_exthdrs(struct msghdr *mhdr) bufsize = CONTROLLEN - ((caddr_t)CMSG_DATA(cm) - (caddr_t)bufp); if (bufsize <= 0) - continue; + continue; switch (cm->cmsg_type) { case IPV6_HOPOPTS: printf(" HbH Options: "); @@ -1842,7 +1917,6 @@ pr_exthdrs(struct msghdr *mhdr) } } -#ifdef USE_RFC2292BIS static void pr_ip6opt(void *extbuf, size_t bufsize) { @@ -1904,17 +1978,7 @@ pr_ip6opt(void *extbuf, size_t bufsize) } return; } -#else /* !USE_RFC2292BIS */ -/* ARGSUSED */ -static void -pr_ip6opt(void *extbuf, size_t bufsize __unused) -{ - putchar('\n'); - return; -} -#endif /* USE_RFC2292BIS */ -#ifdef USE_RFC2292BIS static void pr_rthdr(void *extbuf, size_t bufsize) { @@ -1970,16 +2034,6 @@ pr_rthdr(void *extbuf, size_t bufsize) } -#else /* !USE_RFC2292BIS */ -/* ARGSUSED */ -static void -pr_rthdr(void *extbuf, size_t bufsize __unused) -{ - putchar('\n'); - return; -} -#endif /* USE_RFC2292BIS */ - static int pr_bitrange(u_int32_t v, int soff, int ii) { @@ -2127,11 +2181,13 @@ pr_nodeaddr(struct icmp6_nodeinfo *ni, int nilen) if (nilen % (sizeof(u_int32_t) + sizeof(struct in6_addr)) == 0) withttl = 1; while (nilen > 0) { - u_int32_t ttl; + u_int32_t ttl = 0; if (withttl) { - /* XXX: alignment? */ - ttl = (u_int32_t)ntohl(*(u_int32_t *)cp); + uint32_t t; + + memcpy(&t, cp, sizeof(t)); + ttl = (u_int32_t)ntohl(t); cp += sizeof(u_int32_t); nilen -= sizeof(u_int32_t); } @@ -2170,8 +2226,12 @@ get_hoplim(struct msghdr *mhdr) if (cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_HOPLIMIT && - cm->cmsg_len == CMSG_LEN(sizeof(int))) - return(*(int *)CMSG_DATA(cm)); + cm->cmsg_len == CMSG_LEN(sizeof(int))) { + int r; + + memcpy(&r, CMSG_DATA(cm), sizeof(r)); + return(r); + } } return(-1); @@ -2180,6 +2240,7 @@ get_hoplim(struct msghdr *mhdr) static struct in6_pktinfo * get_rcvpktinfo(struct msghdr *mhdr) { + static struct in6_pktinfo pi; struct cmsghdr *cm; for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; @@ -2189,8 +2250,10 @@ get_rcvpktinfo(struct msghdr *mhdr) if (cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_PKTINFO && - cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) - return((struct in6_pktinfo *)CMSG_DATA(cm)); + cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) { + memcpy(&pi, CMSG_DATA(cm), sizeof(pi)); + return(&pi); + } } return(NULL); @@ -2201,7 +2264,7 @@ get_pathmtu(struct msghdr *mhdr) { #ifdef IPV6_RECVPATHMTU struct cmsghdr *cm; - struct ip6_mtuinfo *mtuctl = NULL; + struct ip6_mtuinfo mtuctl; for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { @@ -2211,7 +2274,7 @@ get_pathmtu(struct msghdr *mhdr) if (cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_PATHMTU && cm->cmsg_len == CMSG_LEN(sizeof(struct ip6_mtuinfo))) { - mtuctl = (struct ip6_mtuinfo *)CMSG_DATA(cm); + memcpy(&mtuctl, CMSG_DATA(cm), sizeof(mtuctl)); /* * If the notified destination is different from @@ -2221,17 +2284,17 @@ get_pathmtu(struct msghdr *mhdr) * have used the default scope zone ID for sending, * in which case the scope ID value is 0. */ - if (!IN6_ARE_ADDR_EQUAL(&mtuctl->ip6m_addr.sin6_addr, + if (!IN6_ARE_ADDR_EQUAL(&mtuctl.ip6m_addr.sin6_addr, &dst.sin6_addr) || - (mtuctl->ip6m_addr.sin6_scope_id && + (mtuctl.ip6m_addr.sin6_scope_id && dst.sin6_scope_id && - mtuctl->ip6m_addr.sin6_scope_id != + mtuctl.ip6m_addr.sin6_scope_id != dst.sin6_scope_id)) { if ((options & F_VERBOSE) != 0) { printf("path MTU for %s is notified. " "(ignored)\n", - pr_addr((struct sockaddr *)&mtuctl->ip6m_addr, - sizeof(mtuctl->ip6m_addr))); + pr_addr((struct sockaddr *)&mtuctl.ip6m_addr, + sizeof(mtuctl.ip6m_addr))); } return(0); } @@ -2240,11 +2303,11 @@ get_pathmtu(struct msghdr *mhdr) * Ignore an invalid MTU. XXX: can we just believe * the kernel check? */ - if (mtuctl->ip6m_mtu < IPV6_MMTU) + if (mtuctl.ip6m_mtu < IPV6_MMTU) return(0); /* notification for our destination. return the MTU. */ - return((int)mtuctl->ip6m_mtu); + return((int)mtuctl.ip6m_mtu); } } #endif @@ -2252,21 +2315,6 @@ get_pathmtu(struct msghdr *mhdr) } /* - * tvsub -- - * Subtract 2 timeval structs: out = out - in. Out is assumed to - * be >= in. - */ -static void -tvsub(struct timeval *out, struct timeval *in) -{ - if ((out->tv_usec -= in->tv_usec) < 0) { - --out->tv_sec; - out->tv_usec += 1000000; - } - out->tv_sec -= in->tv_sec; -} - -/* * onint -- * SIGINT handler. */ @@ -2504,8 +2552,9 @@ pr_icmph(struct icmp6_hdr *icp, u_char *end) } printf(", subject=%s", niqcode[ni->ni_code]); cp = (const u_char *)(ni + 1); - if (dnsdecode(&cp, end, NULL, dnsname, - sizeof(dnsname)) != NULL) + cp = dnsdecode(cp, end, NULL, dnsname, + sizeof(dnsname)); + if (cp != NULL) printf("(%s)", dnsname); else printf("(invalid)"); @@ -2603,7 +2652,8 @@ pr_addr(struct sockaddr *addr, int addrlen) if ((options & F_HOSTNAME) == 0) flag |= NI_NUMERICHOST; - if (getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, flag) == 0) + if (cap_getnameinfo(capdns, addr, addrlen, buf, sizeof(buf), NULL, 0, + flag) == 0) return (buf); else return "?"; @@ -2629,6 +2679,10 @@ pr_retip(struct ip6_hdr *ip6, u_char *end) nh = ip6->ip6_nxt; cp += hlen; while (end - cp >= 8) { +#ifdef IPSEC + struct ah ah; +#endif + switch (nh) { case IPPROTO_HOPOPTS: printf("HBH "); @@ -2653,8 +2707,9 @@ pr_retip(struct ip6_hdr *ip6, u_char *end) #ifdef IPSEC case IPPROTO_AH: printf("AH "); - hlen = (((struct ah *)cp)->ah_len+2) << 2; - nh = ((struct ah *)cp)->ah_nxt; + memcpy(&ah, cp, sizeof(ah)); + hlen = (ah.ah_len+2) << 2; + nh = ah.ah_nxt; break; #endif case IPPROTO_ICMPV6: @@ -2741,7 +2796,7 @@ setpolicy(int so __unused, char *policy) buf = ipsec_set_policy(policy, strlen(policy)); if (buf == NULL) errx(1, "%s", ipsec_strerror()); - if (setsockopt(s, IPPROTO_IPV6, IPV6_IPSEC_POLICY, buf, + if (setsockopt(ssend, IPPROTO_IPV6, IPV6_IPSEC_POLICY, buf, ipsec_get_policylen(buf)) < 0) warnx("Unable to set IPsec policy"); free(buf); @@ -2795,7 +2850,7 @@ nigroup(char *name, int nig_oldmcprefix) } if (valid != 1) return NULL; /*XXX*/ - + if (nig_oldmcprefix) { /* draft-ietf-ipngwg-icmp-name-lookup */ bcopy(digest, &in6.s6_addr[12], 4); @@ -2815,27 +2870,55 @@ usage(void) { (void)fprintf(stderr, #if defined(IPSEC) && !defined(IPSEC_POLICY_IPSEC) - "A" + "Z" #endif "usage: ping6 [-" - "Dd" + "aADd" #if defined(IPSEC) && !defined(IPSEC_POLICY_IPSEC) "E" #endif - "fH" + "fHnNoOq" #ifdef IPV6_USE_MIN_MTU - "m" + "u" #endif - "nNoqrRtvwW] " - "[-a addrtype] [-b bufsiz] [-c count] [-g gateway]\n" - " [-h hoplimit] [-I interface] [-i wait] [-l preload]" + "vyY] " + "[-b bufsiz] [-c count] [-e gateway]\n" + " [-I interface] [-i wait] [-k addrtype] [-l preload] " + "[-m hoplimit]\n" + " [-p pattern]" #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) " [-P policy]" #endif - "\n" - " [-p pattern] [-S sourceaddr] [-s packetsize] " - "[-x waittime]\n" - " [-X timeout] [hops ...] host\n"); + " [-S sourceaddr] [-s packetsize]\n" + " [-t timeout] [-W waittime] [hops ...] host\n"); exit(1); } + +static cap_channel_t * +capdns_setup(void) +{ + cap_channel_t *capcas, *capdnsloc; +#ifdef WITH_CASPER + const char *types[2]; + int families[1]; +#endif + capcas = cap_init(); + if (capcas == NULL) + err(1, "unable to create casper process"); + capdnsloc = cap_service_open(capcas, "system.dns"); + /* Casper capability no longer needed. */ + cap_close(capcas); + if (capdnsloc == NULL) + err(1, "unable to open system.dns service"); +#ifdef WITH_CASPER + types[0] = "NAME2ADDR"; + types[1] = "ADDR2NAME"; + if (cap_dns_type_limit(capdnsloc, types, nitems(types)) < 0) + err(1, "unable to limit access to system.dns service"); + families[0] = AF_INET6; + if (cap_dns_family_limit(capdnsloc, families, nitems(families)) < 0) + err(1, "unable to limit access to system.dns service"); +#endif + return (capdnsloc); +} #endif /* defined(__rtems__) && defined(INET6) */ diff --git a/freebsd/sbin/ping6/rtems-bsd-ping6-data.h b/freebsd/sbin/ping6/rtems-bsd-ping6-data.h index 40e781b8..e140c085 100644 --- a/freebsd/sbin/ping6/rtems-bsd-ping6-data.h +++ b/freebsd/sbin/ping6/rtems-bsd-ping6-data.h @@ -1,4 +1,3 @@ /* generated by userspace-header-gen.py */ #include <rtems/linkersets.h> /* ping6.c */ -RTEMS_LINKER_RWSET_CONTENT(bsd_prog_ping6, extern u_int options); diff --git a/freebsd/sbin/ping6/rtems-bsd-ping6-namespace.h b/freebsd/sbin/ping6/rtems-bsd-ping6-namespace.h index 8b875692..54f15fad 100644 --- a/freebsd/sbin/ping6/rtems-bsd-ping6-namespace.h +++ b/freebsd/sbin/ping6/rtems-bsd-ping6-namespace.h @@ -1,3 +1,2 @@ /* generated by userspace-header-gen.py */ /* ping6.c */ -#define options _bsd_ping6_options diff --git a/freebsd/sbin/ping6/rtems-bsd-ping6-ping6-data.h b/freebsd/sbin/ping6/rtems-bsd-ping6-ping6-data.h index 9793bc1c..335fe731 100644 --- a/freebsd/sbin/ping6/rtems-bsd-ping6-ping6-data.h +++ b/freebsd/sbin/ping6/rtems-bsd-ping6-ping6-data.h @@ -18,7 +18,6 @@ RTEMS_LINKER_RWSET_CONTENT(bsd_prog_ping6, static int hoplimit); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_ping6, static int ident); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_ping6, static int interval); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_ping6, static int mx_dup_ck); -RTEMS_LINKER_RWSET_CONTENT(bsd_prog_ping6, static int s); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_ping6, static int timing); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_ping6, static int waittime); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_ping6, static long int nmissedmax); diff --git a/freebsd/sbin/sysctl/sysctl.c b/freebsd/sbin/sysctl/sysctl.c index f298da0c..30ebe5fd 100644 --- a/freebsd/sbin/sysctl/sysctl.c +++ b/freebsd/sbin/sysctl/sysctl.c @@ -61,6 +61,7 @@ static const char rcsid[] = #include <sys/stat.h> #include <sys/sysctl.h> #include <sys/vmmeter.h> +#include <dev/evdev/input.h> #ifdef __amd64__ #include <sys/efi.h> @@ -729,6 +730,22 @@ S_vmtotal(size_t l2, void *p) return (0); } +static int +S_input_id(size_t l2, void *p) +{ + struct input_id *id = p; + + if (l2 != sizeof(*id)) { + warnx("S_input_id %zu != %zu", l2, sizeof(*id)); + return (1); + } + + printf("{ bustype = 0x%04x, vendor = 0x%04x, " + "product = 0x%04x, version = 0x%04x }", + id->bustype, id->vendor, id->product, id->version); + return (0); +} + #ifdef __amd64__ static int S_efi_map(size_t l2, void *p) @@ -1036,6 +1053,8 @@ show_var(int *oid, int nlen) func = S_loadavg; else if (strcmp(fmt, "S,vmtotal") == 0) func = S_vmtotal; + else if (strcmp(fmt, "S,input_id") == 0) + func = S_input_id; #ifdef __amd64__ else if (strcmp(fmt, "S,efi_map_header") == 0) func = S_efi_map; |