X-Git-Url: https://git.saurik.com/apple/network_cmds.git/blobdiff_plain/7d983f59f7d83614b94866000bdf59d1f7501008..fa34b6f5f32f696bb2fe92a877dfaec960fcd850:/ifconfig.tproj/ifconfig.c diff --git a/ifconfig.tproj/ifconfig.c b/ifconfig.tproj/ifconfig.c index 62bfd19..1a708da 100644 --- a/ifconfig.tproj/ifconfig.c +++ b/ifconfig.tproj/ifconfig.c @@ -1,3 +1,31 @@ +/* + * Copyright (c) 2009-2014 Apple Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ + /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -27,20 +55,14 @@ * SUCH DAMAGE. */ +#include + #ifndef lint -static const char copyright[] = +__unused static const char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ -#ifndef lint -#if 0 -static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; -#endif -static const char rcsid[] = - "$FreeBSD: src/sbin/ifconfig/ifconfig.c,v 1.134.2.2.2.1 2008/11/25 02:59:29 kensmith Exp $"; -#endif /* not lint */ - #include #include #include @@ -56,7 +78,10 @@ static const char rcsid[] = #include #include #include +#include #include +#include +#include /* IP */ #include @@ -89,21 +114,32 @@ int setmask; int doalias; int clearaddr; int newaddr = 1; -int verbose; int noload; int all; int bond_details = 0; int supmedia = 0; +#if TARGET_OS_EMBEDDED +int verbose = 1; +int showrtref = 1; +#else /* !TARGET_OS_EMBEDDED */ +int verbose = 0; int showrtref = 0; +#endif /* !TARGET_OS_EMBEDDED */ int printkeys = 0; /* Print keying material for interfaces. */ static int ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *afp); static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl, struct ifaddrs *ifa); +static char *bytes_to_str(unsigned long long bytes); +static char *bps_to_str(unsigned long long rate); +static char *ns_to_str(unsigned long long nsec); static void tunnel_status(int s); static void usage(void); +static char *sched2str(unsigned int s); +static char *tl2str(unsigned int s); +static char *ift2str(unsigned int t, unsigned int f, unsigned int sf); static struct afswtch *af_getbyname(const char *name); static struct afswtch *af_getbyfamily(int af); @@ -156,7 +192,7 @@ main(int argc, char *argv[]) struct option *p; size_t iflen; - all = downonly = uponly = namesonly = noload = verbose = 0; + all = downonly = uponly = namesonly = noload = 0; /* Parse leading line options */ #ifndef __APPLE__ @@ -216,8 +252,9 @@ main(int argc, char *argv[]) argc -= optind; argv += optind; - /* -l cannot be used with -a or -r or -m or -b */ - if (namesonly && (all || supmedia || showrtref || bond_details)) + /* -l cannot be used with -a or -q or -m or -b */ + if (namesonly && + (all || supmedia || bond_details)) usage(); /* nonsense.. */ @@ -234,7 +271,6 @@ main(int argc, char *argv[]) usage(); ifname = NULL; - ifindex = 0; if (argc == 1) { afp = af_getbyname(*argv); if (afp == NULL) @@ -726,7 +762,7 @@ setifflags(const char *vname, int value, int s, const struct afswtch *afp) Perror(vname); } -#ifndef __APPLE__ +#ifdef SIOCGIFCAP void setifcap(const char *vname, int value, int s, const struct afswtch *afp) { @@ -792,14 +828,204 @@ setifname(const char *val, int dummy __unused, int s, } #endif +static void +setrouter(const char *vname, int value, int s, const struct afswtch *afp) +{ + if (afp->af_setrouter == NULL) { + warn("address family %s does not support router mode", + afp->af_name); + return; + } + + afp->af_setrouter(s, value); +} + +static void +setifdesc(const char *val, int dummy __unused, int s, const struct afswtch *afp) +{ + struct if_descreq ifdr; + + bzero(&ifdr, sizeof (ifdr)); + strncpy(ifdr.ifdr_name, name, sizeof (ifdr.ifdr_name)); + ifdr.ifdr_len = strlen(val); + strncpy((char *)ifdr.ifdr_desc, val, sizeof (ifdr.ifdr_desc)); + + if (ioctl(s, SIOCSIFDESC, (caddr_t)&ifdr) < 0) { + warn("ioctl (set desc)"); + } +} + +static void +settbr(const char *val, int dummy __unused, int s, const struct afswtch *afp) +{ + struct if_linkparamsreq iflpr; + long double bps; + u_int64_t rate; + u_int32_t percent = 0; + char *cp; + + errno = 0; + bzero(&iflpr, sizeof (iflpr)); + strncpy(iflpr.iflpr_name, name, sizeof (iflpr.iflpr_name)); + + bps = strtold(val, &cp); + if (val == cp || errno != 0) { + warn("Invalid value '%s'", val); + return; + } + rate = (u_int64_t)bps; + if (cp != NULL) { + if (!strcmp(cp, "b") || !strcmp(cp, "bps")) { + ; /* nothing */ + } else if (!strcmp(cp, "Kb") || !strcmp(cp, "Kbps")) { + rate *= 1000; + } else if (!strcmp(cp, "Mb") || !strcmp(cp, "Mbps")) { + rate *= 1000 * 1000; + } else if (!strcmp(cp, "Gb") || !strcmp(cp, "Gbps")) { + rate *= 1000 * 1000 * 1000; + } else if (!strcmp(cp, "%")) { + percent = rate; + if (percent == 0 || percent > 100) { + printf("Value out of range '%s'", val); + return; + } + } else if (*cp != '\0') { + printf("Unknown unit '%s'", cp); + return; + } + } + iflpr.iflpr_output_tbr_rate = rate; + iflpr.iflpr_output_tbr_percent = percent; + if (ioctl(s, SIOCSIFLINKPARAMS, &iflpr) < 0 && + errno != ENOENT && errno != ENXIO && errno != ENODEV) { + warn("ioctl (set link params)"); + } else if (errno == ENXIO) { + printf("TBR cannot be set on %s\n", name); + } else if (errno == ENOENT || rate == 0) { + printf("%s: TBR is now disabled\n", name); + } else if (errno == ENODEV) { + printf("%s: requires absolute TBR rate\n", name); + } else if (percent != 0) { + printf("%s: TBR rate set to %u%% of effective link rate\n", + name, percent); + } else { + printf("%s: TBR rate set to %s\n", name, bps_to_str(rate)); + } +} + +static void +setthrottle(const char *val, int dummy __unused, int s, + const struct afswtch *afp) +{ + struct if_throttlereq iftr; + char *cp; + + errno = 0; + bzero(&iftr, sizeof (iftr)); + strncpy(iftr.ifthr_name, name, sizeof (iftr.ifthr_name)); + + iftr.ifthr_level = strtold(val, &cp); + if (val == cp || errno != 0) { + warn("Invalid value '%s'", val); + return; + } + + if (ioctl(s, SIOCSIFTHROTTLE, &iftr) < 0 && errno != ENXIO) { + warn("ioctl (set throttling level)"); + } else if (errno == ENXIO) { + printf("throttling level cannot be set on %s\n", name); + } else { + printf("%s: throttling level set to %d\n", name, + iftr.ifthr_level); + } +} + +static void +setlog(const char *val, int dummy __unused, int s, + const struct afswtch *afp) +{ + char *cp; + + errno = 0; + strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + + ifr.ifr_log.ifl_level = strtold(val, &cp); + if (val == cp || errno != 0) { + warn("Invalid value '%s'", val); + return; + } + ifr.ifr_log.ifl_flags = (IFRLOGF_DLIL|IFRLOGF_FAMILY|IFRLOGF_DRIVER| + IFRLOGF_FIRMWARE); + + if (ioctl(s, SIOCSIFLOG, &ifr) < 0) + warn("ioctl (set logging parameters)"); +} + +void +setcl2k(const char *vname, int value, int s, const struct afswtch *afp) +{ + strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + ifr.ifr_ifru.ifru_2kcl = value; + + if (ioctl(s, SIOCSIF2KCL, (caddr_t)&ifr) < 0) + Perror(vname); +} + +void +setexpensive(const char *vname, int value, int s, const struct afswtch *afp) +{ + strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + ifr.ifr_ifru.ifru_expensive = value; + + if (ioctl(s, SIOCSIFEXPENSIVE, (caddr_t)&ifr) < 0) + Perror(vname); +} + + +void +setecnmode(const char *val, int dummy __unused, int s, + const struct afswtch *afp) +{ + char *cp; + + if (strcmp(val, "default") == 0) + ifr.ifr_ifru.ifru_ecn_mode = IFRTYPE_ECN_DEFAULT; + else if (strcmp(val, "enable") == 0) + ifr.ifr_ifru.ifru_ecn_mode = IFRTYPE_ECN_ENABLE; + else if (strcmp(val, "disable") == 0) + ifr.ifr_ifru.ifru_ecn_mode = IFRTYPE_ECN_DISABLE; + else { + ifr.ifr_ifru.ifru_ecn_mode = strtold(val, &cp); + if (val == cp || errno != 0) { + warn("Invalid ECN mode value '%s'", val); + return; + } + } + + strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + + if (ioctl(s, SIOCSECNMODE, (caddr_t)&ifr) < 0) + Perror("ioctl(SIOCSECNMODE)"); +} + + #define IFFBITS \ "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \ "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \ -"\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP\25NEEDSGIANT" +"\20MULTICAST" + +#define IFEFBITS \ +"\020\1AUTOCONFIGURING\6IPV6_DISABLED\7ACCEPT_RTADV\10TXSTART\11RXPOLL" \ +"\12VLAN\13BOND\14ARPLL\15NOWINDOWSCALE\16NOAUTOIPV6LL\17EXPENSIVE\20ROUTER4" \ +"\21ROUTER6\22LOCALNET_PRIVATE\23ND6ALT\24RESTRICTED_RECV\25AWDL\26NOACKPRI" \ +"\27AWDL_RESTRICTED\30CL2K\31ECN_ENABLE\32ECN_DISABLE\35SENDLIST\36DIRECTLINK\40UPDOWNCHANGE" #define IFCAPBITS \ -"\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \ -"\10VLAN_HWCSUM\11TSO4\12TSO6\13LRO\14WOL_UCAST\15WOL_MCAST\16WOL_MAGIC" +"\020\1RXCSUM\2TXCSUM\3VLAN_MTU\4VLAN_HWTAGGING\5JUMBO_MTU" \ +"\6TSO4\7TSO6\10LRO\11AV\12TXSTATUS" + +#define IFRLOGF_BITS \ +"\020\1DLIL\21FAMILY\31DRIVER\35FIRMWARE" /* * Print the status of the interface. If an address family was @@ -812,6 +1038,12 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl, struct ifaddrs *ift; int allfamilies, s; struct ifstat ifs; + struct if_descreq ifdr; + struct if_linkparamsreq iflpr; + int mib[6]; + struct ifmibdata_supplemental ifmsupp; + size_t miblen = sizeof(struct ifmibdata_supplemental); + u_int64_t eflags = 0; if (afp == NULL) { allfamilies = 1; @@ -833,13 +1065,22 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl, printf(" metric %d", ifr.ifr_metric); if (ioctl(s, SIOCGIFMTU, &ifr) != -1) printf(" mtu %d", ifr.ifr_mtu); -#ifdef SIOCGIFGETRTREFCNT if (showrtref && ioctl(s, SIOCGIFGETRTREFCNT, &ifr) != -1) printf(" rtref %d", ifr.ifr_route_refcnt); -#endif + if (verbose) { + unsigned int ifindex = if_nametoindex(ifa->ifa_name); + if (ifindex != 0) + printf(" index %u", ifindex); + } putchar('\n'); -#ifndef __APPLE__ + if (verbose && ioctl(s, SIOCGIFEFLAGS, (caddr_t)&ifr) != -1 && + (eflags = ifr.ifr_eflags) != 0) { + printb("\teflags", eflags, IFEFBITS); + putchar('\n'); + } + +#ifdef SIOCGIFCAP if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) { if (ifr.ifr_curcap != 0) { printb("\toptions", ifr.ifr_curcap, IFCAPBITS); @@ -893,10 +1134,376 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl, if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) printf("%s", ifs.ascii); + /* The rest is for when verbose is set; if not set, we're done */ + if (!verbose) + goto done; + + if (ioctl(s, SIOCGIFTYPE, &ifr) != -1) { + char *c = ift2str(ifr.ifr_type.ift_type, + ifr.ifr_type.ift_family, ifr.ifr_type.ift_subfamily); + if (c != NULL) + printf("\ttype: %s\n", c); + } + + if (verbose > 0) { + struct if_agentidsreq ifar; + memset(&ifar, 0, sizeof(ifar)); + + strlcpy(ifar.ifar_name, name, sizeof(ifar.ifar_name)); + + if (ioctl(s, SIOCGIFAGENTIDS, &ifar) != -1) { + if (ifar.ifar_count != 0) { + ifar.ifar_uuids = calloc(ifar.ifar_count, sizeof(uuid_t)); + if (ifar.ifar_uuids != NULL) { + if (ioctl(s, SIOCGIFAGENTIDS, &ifar) != 1) { + for (int agent_i = 0; agent_i < ifar.ifar_count; agent_i++) { + struct netagent_req nar; + memset(&nar, 0, sizeof(nar)); + + uuid_copy(nar.netagent_uuid, ifar.ifar_uuids[agent_i]); + + if (ioctl(s, SIOCGIFAGENTDATA, &nar) != 1) { + printf("\tagent domain:%s type:%s flags:0x%x desc:\"%s\"\n", + nar.netagent_domain, nar.netagent_type, + nar.netagent_flags, nar.netagent_desc); + } + } + } + free(ifar.ifar_uuids); + } + } + } + } + + if (ioctl(s, SIOCGIFLINKQUALITYMETRIC, &ifr) != -1) { + int lqm = ifr.ifr_link_quality_metric; + if (verbose > 1) { + printf("\tlink quality: %d ", lqm); + if (lqm == IFNET_LQM_THRESH_OFF) + printf("(off)"); + else if (lqm == IFNET_LQM_THRESH_UNKNOWN) + printf("(unknown)"); + else if (lqm > IFNET_LQM_THRESH_UNKNOWN && + lqm <= IFNET_LQM_THRESH_BAD) + printf("(bad)"); + else if (lqm > IFNET_LQM_THRESH_UNKNOWN && + lqm <= IFNET_LQM_THRESH_POOR) + printf("(poor)"); + else if (lqm > IFNET_LQM_THRESH_POOR && + lqm <= IFNET_LQM_THRESH_GOOD) + printf("(good)"); + else + printf("(?)"); + printf("\n"); + } else if (lqm > IFNET_LQM_THRESH_UNKNOWN) { + printf("\tlink quality: %d ", lqm); + if (lqm <= IFNET_LQM_THRESH_BAD) + printf("(bad)"); + else if (lqm <= IFNET_LQM_THRESH_POOR) + printf("(poor)"); + else if (lqm <= IFNET_LQM_THRESH_GOOD) + printf("(good)"); + else + printf("(?)"); + printf("\n"); + } + } + + if (verbose > 0) { + if (ioctl(s, SIOCGIFINTERFACESTATE, &ifr) != -1) { + printf("\tstate"); + if (ifr.ifr_interface_state.valid_bitmask & + IF_INTERFACE_STATE_RRC_STATE_VALID) { + uint8_t rrc_state = ifr.ifr_interface_state.rrc_state; + + printf(" rrc: %u ", rrc_state); + if (rrc_state == IF_INTERFACE_STATE_RRC_STATE_CONNECTED) + printf("(connected)"); + else if (rrc_state == IF_INTERFACE_STATE_RRC_STATE_IDLE) + printf("(idle)"); + else + printf("(?)"); + } + if (ifr.ifr_interface_state.valid_bitmask & + IF_INTERFACE_STATE_INTERFACE_AVAILABILITY_VALID) { + uint8_t ifavail = ifr.ifr_interface_state.interface_availability; + + printf(" availability: %u ", ifavail); + if (ifavail == IF_INTERFACE_STATE_INTERFACE_AVAILABLE) + printf("(true)"); + else if (ifavail == IF_INTERFACE_STATE_INTERFACE_UNAVAILABLE) + printf("(false)"); + else + printf("(?)"); + } else { + printf(" availability: (not valid)"); + } + if (verbose > 1 && + ifr.ifr_interface_state.valid_bitmask & + IF_INTERFACE_STATE_LQM_STATE_VALID) { + int8_t lqm = ifr.ifr_interface_state.lqm_state; + + printf(" lqm: %d", lqm); + + if (lqm == IFNET_LQM_THRESH_OFF) + printf("(off)"); + else if (lqm == IFNET_LQM_THRESH_UNKNOWN) + printf("(unknown)"); + else if (lqm == IFNET_LQM_THRESH_BAD) + printf("(bad)"); + else if (lqm == IFNET_LQM_THRESH_POOR) + printf("(poor)"); + else if (lqm == IFNET_LQM_THRESH_GOOD) + printf("(good)"); + else + printf("(?)"); + } + } + printf("\n"); + } + + bzero(&iflpr, sizeof (iflpr)); + strncpy(iflpr.iflpr_name, name, sizeof (iflpr.iflpr_name)); + if (ioctl(s, SIOCGIFLINKPARAMS, &iflpr) != -1) { + u_int64_t ibw_max = iflpr.iflpr_input_bw.max_bw; + u_int64_t ibw_eff = iflpr.iflpr_input_bw.eff_bw; + u_int64_t obw_max = iflpr.iflpr_output_bw.max_bw; + u_int64_t obw_eff = iflpr.iflpr_output_bw.eff_bw; + u_int64_t obw_tbr = iflpr.iflpr_output_tbr_rate; + u_int32_t obw_pct = iflpr.iflpr_output_tbr_percent; + u_int64_t ilt_max = iflpr.iflpr_input_lt.max_lt; + u_int64_t ilt_eff = iflpr.iflpr_input_lt.eff_lt; + u_int64_t olt_max = iflpr.iflpr_output_lt.max_lt; + u_int64_t olt_eff = iflpr.iflpr_output_lt.eff_lt; + + + if (eflags & IFEF_TXSTART) { + u_int32_t flags = iflpr.iflpr_flags; + u_int32_t sched = iflpr.iflpr_output_sched; + struct if_throttlereq iftr; + + printf("\tscheduler: %s%s ", + (flags & IFLPRF_ALTQ) ? "ALTQ_" : "", + sched2str(sched)); + if (flags & IFLPRF_DRVMANAGED) + printf("(driver managed)"); + printf("\n"); + + bzero(&iftr, sizeof (iftr)); + strncpy(iftr.ifthr_name, name, + sizeof (iftr.ifthr_name)); + if (ioctl(s, SIOCGIFTHROTTLE, &iftr) != -1 && + iftr.ifthr_level != IFNET_THROTTLE_OFF) + printf("\tthrottling: level %d (%s)\n", + iftr.ifthr_level, tl2str(iftr.ifthr_level)); + } + + if (obw_tbr != 0 && obw_eff > obw_tbr) + obw_eff = obw_tbr; + + if (ibw_max != 0 || obw_max != 0) { + if (ibw_max == obw_max && ibw_eff == obw_eff && + ibw_max == ibw_eff && obw_tbr == 0) { + printf("\tlink rate: %s\n", + bps_to_str(ibw_max)); + } else { + printf("\tuplink rate: %s [eff] / ", + bps_to_str(obw_eff)); + if (obw_tbr != 0) { + if (obw_pct == 0) + printf("%s [tbr] / ", + bps_to_str(obw_tbr)); + else + printf("%s [tbr %u%%] / ", + bps_to_str(obw_tbr), + obw_pct); + } + printf("%s", bps_to_str(obw_max)); + if (obw_tbr != 0) + printf(" [max]"); + printf("\n"); + if (ibw_eff == ibw_max) { + printf("\tdownlink rate: %s\n", + bps_to_str(ibw_max)); + } else { + printf("\tdownlink rate: " + "%s [eff] / ", bps_to_str(ibw_eff)); + printf("%s [max]\n", + bps_to_str(ibw_max)); + } + } + } else if (obw_tbr != 0) { + printf("\tuplink rate: %s [tbr]\n", + bps_to_str(obw_tbr)); + } + + if (ilt_max != 0 || olt_max != 0) { + if (ilt_max == olt_max && ilt_eff == olt_eff && + ilt_max == ilt_eff) { + printf("\tlink latency: %s\n", + ns_to_str(ilt_max)); + } else { + if (olt_max != 0 && olt_eff == olt_max) { + printf("\tuplink latency: %s\n", + ns_to_str(olt_max)); + } else if (olt_max != 0) { + printf("\tuplink latency: " + "%s [eff] / ", ns_to_str(olt_eff)); + printf("%s [max]\n", + ns_to_str(olt_max)); + } + if (ilt_max != 0 && ilt_eff == ilt_max) { + printf("\tdownlink latency: %s\n", + ns_to_str(ilt_max)); + } else if (ilt_max != 0) { + printf("\tdownlink latency: " + "%s [eff] / ", ns_to_str(ilt_eff)); + printf("%s [max]\n", + ns_to_str(ilt_max)); + } + } + } + } + + /* Common OID prefix */ + mib[0] = CTL_NET; + mib[1] = PF_LINK; + mib[2] = NETLINK_GENERIC; + mib[3] = IFMIB_IFDATA; + mib[4] = if_nametoindex(name); + mib[5] = IFDATA_SUPPLEMENTAL; + if (sysctl(mib, 6, &ifmsupp, &miblen, (void *)0, 0) == -1) + err(1, "sysctl IFDATA_SUPPLEMENTAL"); + + if (ifmsupp.ifmd_data_extended.ifi_alignerrs != 0) { + printf("\tunaligned pkts: %llu\n", + ifmsupp.ifmd_data_extended.ifi_alignerrs); + } + if (ifmsupp.ifmd_data_extended.ifi_dt_bytes != 0) { + printf("\tdata milestone interval: %s\n", + bytes_to_str(ifmsupp.ifmd_data_extended.ifi_dt_bytes)); + } + + bzero(&ifdr, sizeof (ifdr)); + strncpy(ifdr.ifdr_name, name, sizeof (ifdr.ifdr_name)); + if (ioctl(s, SIOCGIFDESC, &ifdr) != -1 && ifdr.ifdr_len) { + printf("\tdesc: %s\n", ifdr.ifdr_desc); + } + + if (ioctl(s, SIOCGIFLOG, &ifr) != -1 && ifr.ifr_log.ifl_level) { + printf("\tlogging: level %d ", ifr.ifr_log.ifl_level); + printb("facilities", ifr.ifr_log.ifl_flags, IFRLOGF_BITS); + putchar('\n'); + } + + if (ioctl(s, SIOCGIFDELEGATE, &ifr) != -1 && ifr.ifr_delegated) { + char delegatedif[IFNAMSIZ+1]; + if (if_indextoname(ifr.ifr_delegated, delegatedif) != NULL) + printf("\teffective interface: %s\n", delegatedif); + } + + if(ioctl(s, SIOCGSTARTDELAY, &ifr) != -1) { + if (ifr.ifr_start_delay_qlen > 0 && + ifr.ifr_start_delay_timeout > 0) { + printf("\ttxstart qlen: %u packets " + "timeout: %u microseconds\n", + ifr.ifr_start_delay_qlen, + ifr.ifr_start_delay_timeout/1000); + } + } + +done: close(s); return; } +#define KILOBYTES 1024 +#define MEGABYTES (KILOBYTES * KILOBYTES) +#define GIGABYTES (KILOBYTES * KILOBYTES * KILOBYTES) + +static char * +bytes_to_str(unsigned long long bytes) +{ + static char buf[32]; + const char *u; + long double n = bytes, t; + + if (bytes >= GIGABYTES) { + t = n / GIGABYTES; + u = "GB"; + } else if (n >= MEGABYTES) { + t = n / MEGABYTES; + u = "MB"; + } else if (n >= KILOBYTES) { + t = n / KILOBYTES; + u = "KB"; + } else { + t = n; + u = "bytes"; + } + + snprintf(buf, sizeof (buf), "%-4.2Lf %s", t, u); + return (buf); +} + +#define GIGABIT_PER_SEC 1000000000 /* gigabit per second */ +#define MEGABIT_PER_SEC 1000000 /* megabit per second */ +#define KILOBIT_PER_SEC 1000 /* kilobit per second */ + +static char * +bps_to_str(unsigned long long rate) +{ + static char buf[32]; + const char *u; + long double n = rate, t; + + if (rate >= GIGABIT_PER_SEC) { + t = n / GIGABIT_PER_SEC; + u = "Gbps"; + } else if (n >= MEGABIT_PER_SEC) { + t = n / MEGABIT_PER_SEC; + u = "Mbps"; + } else if (n >= KILOBIT_PER_SEC) { + t = n / KILOBIT_PER_SEC; + u = "Kbps"; + } else { + t = n; + u = "bps "; + } + + snprintf(buf, sizeof (buf), "%-4.2Lf %4s", t, u); + return (buf); +} + +#define NSEC_PER_SEC 1000000000 /* nanosecond per second */ +#define USEC_PER_SEC 1000000 /* microsecond per second */ +#define MSEC_PER_SEC 1000 /* millisecond per second */ + +static char * +ns_to_str(unsigned long long nsec) +{ + static char buf[32]; + const char *u; + long double n = nsec, t; + + if (nsec >= NSEC_PER_SEC) { + t = n / NSEC_PER_SEC; + u = "sec "; + } else if (n >= USEC_PER_SEC) { + t = n / USEC_PER_SEC; + u = "msec"; + } else if (n >= MSEC_PER_SEC) { + t = n / MSEC_PER_SEC; + u = "usec"; + } else { + t = n; + u = "nsec"; + } + + snprintf(buf, sizeof (buf), "%-4.2Lf %4s", t, u); + return (buf); +} + static void tunnel_status(int s) { @@ -975,7 +1582,7 @@ ifmaybeload(const char *name) } /* turn interface and unit into module name */ - strcpy(ifkind, "if_"); + strlcpy(ifkind, "if_", sizeof(ifkind)); strlcpy(ifkind + MOD_PREFIX_LEN, ifname, sizeof(ifkind) - MOD_PREFIX_LEN); @@ -1012,10 +1619,10 @@ static struct cmd basic_cmds[] = { DEF_CMD("-arp", IFF_NOARP, setifflags), DEF_CMD("debug", IFF_DEBUG, setifflags), DEF_CMD("-debug", -IFF_DEBUG, setifflags), -#ifdef notdef +#ifdef IFF_PPROMISC DEF_CMD("promisc", IFF_PPROMISC, setifflags), DEF_CMD("-promisc", -IFF_PPROMISC, setifflags), -#endif +#endif /* IFF_PPROMISC */ DEF_CMD("add", IFF_UP, notealias), DEF_CMD("alias", IFF_UP, notealias), DEF_CMD("-alias", -IFF_UP, notealias), @@ -1039,39 +1646,76 @@ static struct cmd basic_cmds[] = { DEF_CMD("-link1", -IFF_LINK1, setifflags), DEF_CMD("link2", IFF_LINK2, setifflags), DEF_CMD("-link2", -IFF_LINK2, setifflags), -#ifdef notdef +#ifdef IFF_MONITOR DEF_CMD("monitor", IFF_MONITOR:, setifflags), DEF_CMD("-monitor", -IFF_MONITOR, setifflags), +#endif /* IFF_MONITOR */ +#ifdef IFF_STATICARP DEF_CMD("staticarp", IFF_STATICARP, setifflags), DEF_CMD("-staticarp", -IFF_STATICARP, setifflags), +#endif /* IFF_STATICARP */ +#ifdef IFCAP_RXCSUM DEF_CMD("rxcsum", IFCAP_RXCSUM, setifcap), DEF_CMD("-rxcsum", -IFCAP_RXCSUM, setifcap), +#endif /* IFCAP_RXCSUM */ +#ifdef IFCAP_TXCSUM DEF_CMD("txcsum", IFCAP_TXCSUM, setifcap), DEF_CMD("-txcsum", -IFCAP_TXCSUM, setifcap), +#endif /* IFCAP_TXCSUM */ +#ifdef IFCAP_NETCONS DEF_CMD("netcons", IFCAP_NETCONS, setifcap), DEF_CMD("-netcons", -IFCAP_NETCONS, setifcap), +#endif /* IFCAP_NETCONS */ +#ifdef IFCAP_POLLING DEF_CMD("polling", IFCAP_POLLING, setifcap), DEF_CMD("-polling", -IFCAP_POLLING, setifcap), +#endif /* IFCAP_POLLING */ +#ifdef IFCAP_TSO DEF_CMD("tso", IFCAP_TSO, setifcap), DEF_CMD("-tso", -IFCAP_TSO, setifcap), +#endif /* IFCAP_TSO */ +#ifdef IFCAP_LRO DEF_CMD("lro", IFCAP_LRO, setifcap), DEF_CMD("-lro", -IFCAP_LRO, setifcap), +#endif /* IFCAP_LRO */ +#ifdef IFCAP_WOL DEF_CMD("wol", IFCAP_WOL, setifcap), DEF_CMD("-wol", -IFCAP_WOL, setifcap), +#endif /* IFCAP_WOL */ +#ifdef IFCAP_WOL_UCAST DEF_CMD("wol_ucast", IFCAP_WOL_UCAST, setifcap), DEF_CMD("-wol_ucast", -IFCAP_WOL_UCAST, setifcap), +#endif /* IFCAP_WOL_UCAST */ +#ifdef IFCAP_WOL_MCAST DEF_CMD("wol_mcast", IFCAP_WOL_MCAST, setifcap), DEF_CMD("-wol_mcast", -IFCAP_WOL_MCAST, setifcap), +#endif /* IFCAP_WOL_MCAST */ +#ifdef IFCAP_WOL_MAGIC DEF_CMD("wol_magic", IFCAP_WOL_MAGIC, setifcap), DEF_CMD("-wol_magic", -IFCAP_WOL_MAGIC, setifcap), -#endif +#endif /* IFCAP_WOL_MAGIC */ DEF_CMD("normal", -IFF_LINK0, setifflags), DEF_CMD("compress", IFF_LINK0, setifflags), DEF_CMD("noicmp", IFF_LINK1, setifflags), DEF_CMD_ARG("mtu", setifmtu), #ifdef notdef DEF_CMD_ARG("name", setifname), -#endif +#endif /* notdef */ +#ifdef IFCAP_AV + DEF_CMD("av", IFCAP_AV, setifcap), + DEF_CMD("-av", -IFCAP_AV, setifcap), +#endif /* IFCAP_AV */ + DEF_CMD("router", 1, setrouter), + DEF_CMD("-router", 0, setrouter), + DEF_CMD_ARG("desc", setifdesc), + DEF_CMD_ARG("tbr", settbr), + DEF_CMD_ARG("throttle", setthrottle), + DEF_CMD_ARG("log", setlog), + DEF_CMD("cl2k", 1, setcl2k), + DEF_CMD("-cl2k", 0, setcl2k), + DEF_CMD("expensive", 1, setexpensive), + DEF_CMD("-expensive", 0, setexpensive), + DEF_CMD_ARG("ecn", setecnmode), }; static __constructor void @@ -1084,3 +1728,130 @@ ifconfig_ctor(void) cmd_register(&basic_cmds[i]); #undef N } + +static char * +sched2str(unsigned int s) +{ + char *c; + + switch (s) { + case PKTSCHEDT_NONE: + c = "NONE"; + break; + case PKTSCHEDT_CBQ: + c = "CBQ"; + break; + case PKTSCHEDT_HFSC: + c = "HFSC"; + break; + case PKTSCHEDT_PRIQ: + c = "PRIQ"; + break; + case PKTSCHEDT_FAIRQ: + c = "FAIRQ"; + break; + case PKTSCHEDT_TCQ: + c = "TCQ"; + break; + case PKTSCHEDT_QFQ: + c = "QFQ"; + break; + default: + c = "UNKNOWN"; + break; + } + + return (c); +} + +static char * +tl2str(unsigned int s) +{ + char *c; + + switch (s) { + case IFNET_THROTTLE_OFF: + c = "off"; + break; + case IFNET_THROTTLE_OPPORTUNISTIC: + c = "opportunistic"; + break; + default: + c = "unknown"; + break; + } + + return (c); +} + +static char * +ift2str(unsigned int t, unsigned int f, unsigned int sf) +{ + static char buf[256]; + char *c = NULL; + + switch (t) { + case IFT_ETHER: + switch (sf) { + case IFRTYPE_SUBFAMILY_USB: + c = "USB Ethernet"; + break; + case IFRTYPE_SUBFAMILY_BLUETOOTH: + c = "Bluetooth PAN"; + break; + case IFRTYPE_SUBFAMILY_WIFI: + c = "Wi-Fi"; + break; + case IFRTYPE_SUBFAMILY_THUNDERBOLT: + c = "IP over Thunderbolt"; + break; + case IFRTYPE_SUBFAMILY_ANY: + default: + c = "Ethernet"; + break; + } + break; + + case IFT_IEEE1394: + c = "IP over FireWire"; + break; + + case IFT_PKTAP: + c = "Packet capture"; + break; + + case IFT_CELLULAR: + c = "Cellular"; + break; + + case IFT_BRIDGE: + case IFT_PFLOG: + case IFT_PFSYNC: + case IFT_OTHER: + case IFT_PPP: + case IFT_LOOP: + case IFT_GIF: + case IFT_STF: + case IFT_L2VLAN: + case IFT_IEEE8023ADLAG: + default: + break; + } + + if (verbose > 1) { + if (c == NULL) { + (void) snprintf(buf, sizeof (buf), + "0x%x family: %u subfamily: %u", + ifr.ifr_type.ift_type, ifr.ifr_type.ift_family, + ifr.ifr_type.ift_subfamily); + } else { + (void) snprintf(buf, sizeof (buf), + "%s (0x%x) family: %u subfamily: %u", c, + ifr.ifr_type.ift_type, ifr.ifr_type.ift_family, + ifr.ifr_type.ift_subfamily); + } + c = buf; + } + + return (c); +}