+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
+setdisableoutput(const char *val, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ struct ifreq ifr;
+ char *cp;
+ errno = 0;
+ bzero(&ifr, sizeof (ifr));
+ strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
+
+ ifr.ifr_ifru.ifru_disable_output = strtold(val, &cp);
+ if (val == cp || errno != 0) {
+ warn("Invalid value '%s'", val);
+ return;
+ }
+
+ if (ioctl(s, SIOCSIFDISABLEOUTPUT, &ifr) < 0 && errno != ENXIO) {
+ warn("ioctl set disable output");
+ } else if (errno == ENXIO) {
+ printf("output thread can not be disabled on %s\n", name);
+ } else {
+ printf("output %s on %s\n",
+ ((ifr.ifr_ifru.ifru_disable_output == 0) ? "enabled" : "disabled"),
+ name);
+ }
+}
+
+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
+settimestamp(const char *vname, int value, int s, const struct afswtch *afp)
+{
+ strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+
+ if (value == 0) {
+ if (ioctl(s, SIOCSIFTIMESTAMPDISABLE, (caddr_t)&ifr) < 0)
+ Perror(vname);
+ } else {
+ if (ioctl(s, SIOCSIFTIMESTAMPENABLE, (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)");
+}
+
+void
+setprobeconnectivity(const char *vname, int value, int s, const struct afswtch *afp)
+{
+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ ifr.ifr_ifru.ifru_probe_connectivity = value;
+
+ if (ioctl(s, SIOCSIFPROBECONNECTIVITY, (caddr_t)&ifr) < 0)
+ Perror(vname);
+}
+
+#if defined(SIOCSQOSMARKINGMODE) && defined(SIOCSQOSMARKINGENABLED)
+
+void
+setqosmarking(const char *cmd, const char *arg, int s, const struct afswtch *afp)
+{
+ u_long ioc;
+
+#if (DEBUG | DEVELOPMENT)
+ printf("%s(%s, %s)\n", __func__, cmd, arg);
+#endif /* (DEBUG | DEVELOPMENT) */
+
+ strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+
+ if (strcmp(cmd, "mode") == 0) {
+ ioc = SIOCSQOSMARKINGMODE;
+
+ if (strcmp(arg, "fastlane") == 0)
+ ifr.ifr_qosmarking_mode = IFRTYPE_QOSMARKING_FASTLANE;
+ else if (strcasecmp(arg, "none") == 0 || strcasecmp(arg, "off") == 0)
+ ifr.ifr_qosmarking_mode = IFRTYPE_QOSMARKING_MODE_NONE;
+ else
+ err(EX_USAGE, "bad value for qosmarking mode: %s", arg);
+ } else if (strcmp(cmd, "enabled") == 0) {
+ ioc = SIOCSQOSMARKINGENABLED;
+ if (strcmp(arg, "1") == 0 || strcasecmp(arg, "on") == 0||
+ strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0)
+ ifr.ifr_qosmarking_enabled = 1;
+ else if (strcmp(arg, "0") == 0 || strcasecmp(arg, "off") == 0||
+ strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0)
+ ifr.ifr_qosmarking_enabled = 0;
+ else
+ err(EX_USAGE, "bad value for qosmarking enabled: %s", arg);
+ } else {
+ err(EX_USAGE, "qosmarking takes mode or enabled");
+ }
+
+ if (ioctl(s, ioc, (caddr_t)&ifr) < 0)
+ err(EX_OSERR, "ioctl(%s, %s)", cmd, arg);
+}
+
+void
+setfastlane(const char *cmd, const char *arg, int s, const struct afswtch *afp)
+{
+ strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+
+ warnx("### fastlane is obsolete, use qosmarking ###");
+
+ if (strcmp(cmd, "capable") == 0) {
+ if (strcmp(arg, "1") == 0 || strcasecmp(arg, "on") == 0||
+ strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0)
+ setqosmarking("mode", "fastlane", s, afp);
+ else if (strcmp(arg, "0") == 0 || strcasecmp(arg, "off") == 0||
+ strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0)
+ setqosmarking("mode", "off", s, afp);
+ else
+ err(EX_USAGE, "bad value for fastlane %s", cmd);
+ } else if (strcmp(cmd, "enable") == 0) {
+ if (strcmp(arg, "1") == 0 || strcasecmp(arg, "on") == 0||
+ strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0)
+ setqosmarking("enabled", "1", s, afp);
+ else if (strcmp(arg, "0") == 0 || strcasecmp(arg, "off") == 0||
+ strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0)
+ setqosmarking("enabled", "0", s, afp);
+ else
+ err(EX_USAGE, "bad value for fastlane %s", cmd);
+ } else {
+ err(EX_USAGE, "fastlane takes capable or enable");
+ }
+}
+
+#else /* defined(SIOCSQOSMARKINGMODE) && defined(SIOCSQOSMARKINGENABLED) */
+
+void
+setfastlane(const char *cmd, const char *arg, int s, const struct afswtch *afp)
+{
+ int value;
+ u_long ioc;
+
+ strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+
+ if (strcmp(cmd, "capable") == 0)
+ ioc = SIOCSFASTLANECAPABLE;
+ else if (strcmp(cmd, "enable") == 0)
+ ioc = SIOCSFASTLEENABLED;
+ else
+ err(EX_USAGE, "fastlane takes capable or enabled");
+
+ if (strcmp(arg, "1") == 0 || strcasecmp(arg, "on") == 0||
+ strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0)
+ value = 1;
+ else if (strcmp(arg, "0") == 0 || strcasecmp(arg, "off") == 0||
+ strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0)
+ value = 0;
+ else
+ err(EX_USAGE, "bad value for fastlane %s", cmd);
+
+ if (ioc == SIOCSFASTLANECAPABLE)
+ ifr.ifr_fastlane_capable = value;
+ else
+ ifr.ifr_fastlane_enabled = value;
+
+ if (ioctl(s, ioc, (caddr_t)&ifr) < 0)
+ err(EX_OSERR, "ioctl(%s, %s)", cmd, arg);
+}
+
+
+void
+setqosmarking(const char *cmd, const char *arg, int s, const struct afswtch *afp)
+{
+ if (strcmp(cmd, "mode") == 0) {
+ if (strcmp(arg, "fastlane") == 0)
+ setfastlane("capable", "on", s, afp);
+ else if (strcmp(arg, "none") == 0)
+ setfastlane("capable", "off", s, afp);
+ else
+ err(EX_USAGE, "bad value for qosmarking mode: %s", arg);
+ } else if (strcmp(cmd, "enabled") == 0) {
+ if (strcmp(arg, "1") == 0 || strcasecmp(arg, "on") == 0||
+ strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0)
+ setfastlane("enable", "on", s, afp);
+ else if (strcmp(arg, "0") == 0 || strcasecmp(arg, "off") == 0||
+ strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0)
+ setfastlane("enable", "off", s, afp);
+ else
+ err(EX_USAGE, "bad value for qosmarking enabled: %s", arg);
+ } else {
+ err(EX_USAGE, "qosmarking takes mode or enabled");
+ }
+}
+
+#endif /* defined(SIOCSQOSMARKINGMODE) && defined(SIOCSQOSMARKINGENABLED) */
+
+void
+setlowpowermode(const char *vname, int value, int s, const struct afswtch *afp)
+{
+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ ifr.ifr_low_power_mode = !!value;
+
+ if (ioctl(s, SIOCSIFLOWPOWER, (caddr_t)&ifr) < 0)
+ Perror(vname);
+}
+