This fixes the primitive parsing route of settimeslot() to allow any
possible list of slots and/or ranges, see the update manual section.
The old code would happily mask "1,2-" into 0b11, settimeslot() now fails
on such broken ranges and also checks for inconsistencies like "4-1",
etc.
get_ts_map() has been heavily simplified to fit into a small macro
TS_RANGE_MASK().
strsep(3) is used instead of the deprecated strtok(3).
While here, remove trailing spaces and align function prototypes for
better readability.
Feedback/OK?
Index: ifconfig.8
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.8,v
retrieving revision 1.285
diff -u -p -r1.285 ifconfig.8
--- ifconfig.8 8 Jun 2017 00:46:42 -0000 1.285
+++ ifconfig.8 8 Jun 2017 15:23:54 -0000
@@ -450,9 +450,18 @@ and
.Xr pf.conf 5 .
.It Cm -rtlabel
Clear the route label.
-.It Cm timeslot Ar timeslot_range
+.It Cm timeslot Ar n-m,n-m,...
Set the timeslot range map, which is used to control which channels
an interface device uses.
+.Ar n
+and
+.Ar m
+must range from 0 to 31. Multiple ranges may overlap.
+.Ar m
+must be
+greater than n if given.
+.Dq all
+can be used as alias to denote all timeslots.
.It Cm up
Mark an interface
.Dq up .
Index: ifconfig.c
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v
retrieving revision 1.343
diff -u -p -r1.343 ifconfig.c
--- ifconfig.c 6 Jun 2017 04:52:40 -0000 1.343
+++ ifconfig.c 8 Jun 2017 15:23:54 -0000
@@ -326,13 +326,13 @@ int actions; /* Actions
performed */
#define NEXTARG2 0xfffffd
const struct cmd {
- char *c_name;
- int c_parameter; /* NEXTARG means next argv */
- int c_action; /* defered action */
+ char *c_name;
+ int c_parameter; /* NEXTARG means next argv */
+ int c_action; /* defered action */
void (*c_func)(const char *, int);
void (*c_func2)(const char *, const char *);
} cmds[] = {
- { "up", IFF_UP, 0, setifflags } ,
+ { "up", IFF_UP, 0, setifflags },
{ "down", -IFF_UP, 0, setifflags },
{ "arp", -IFF_NOARP, 0, setifflags },
{ "-arp", IFF_NOARP, 0, setifflags },
@@ -427,11 +427,11 @@ const struct cmd {
{ "defer", 1, 0, setpfsync_defer },
{ "-defer", 0, 0, setpfsync_defer },
/* giftunnel is for backward compat */
- { "giftunnel", NEXTARG2, 0, NULL, settunnel } ,
- { "tunnel", NEXTARG2, 0, NULL, settunnel } ,
- { "deletetunnel", 0, 0, deletetunnel } ,
- { "tunneldomain", NEXTARG, 0, settunnelinst } ,
- { "tunnelttl", NEXTARG, 0, settunnelttl } ,
+ { "giftunnel", NEXTARG2, 0, NULL, settunnel },
+ { "tunnel", NEXTARG2, 0, NULL, settunnel },
+ { "deletetunnel", 0, 0, deletetunnel },
+ { "tunneldomain", NEXTARG, 0, settunnelinst },
+ { "tunnelttl", NEXTARG, 0, settunnelttl },
{ "pppoedev", NEXTARG, 0, setpppoe_dev },
{ "pppoesvc", NEXTARG, 0, setpppoe_svc },
{ "-pppoesvc", 1, 0, setpppoe_svc },
@@ -537,15 +537,15 @@ const struct cmd {
#endif /* SMALL */
#if 0
/* XXX `create' special-cased below */
- { "create", 0, 0, clone_create } ,
+ { "create", 0, 0, clone_create },
#endif
- { "destroy", 0, 0, clone_destroy } ,
- { "link0", IFF_LINK0, 0, setifflags } ,
- { "-link0", -IFF_LINK0, 0, setifflags } ,
- { "link1", IFF_LINK1, 0, setifflags } ,
- { "-link1", -IFF_LINK1, 0, setifflags } ,
- { "link2", IFF_LINK2, 0, setifflags } ,
- { "-link2", -IFF_LINK2, 0, setifflags } ,
+ { "destroy", 0, 0, clone_destroy },
+ { "link0", IFF_LINK0, 0, setifflags },
+ { "-link0", -IFF_LINK0, 0, setifflags },
+ { "link1", IFF_LINK1, 0, setifflags },
+ { "-link1", -IFF_LINK1, 0, setifflags },
+ { "link2", IFF_LINK2, 0, setifflags },
+ { "-link2", -IFF_LINK2, 0, setifflags },
{ "media", NEXTARG0, A_MEDIA, setmedia },
{ "mediaopt", NEXTARG, A_MEDIAOPTSET, setmediaopt },
{ "-mediaopt", NEXTARG, A_MEDIAOPTCLR, unsetmediaopt },
@@ -560,30 +560,28 @@ const struct cmd {
{ NULL, /*illegal*/0, 0, NULL },
};
-int getinfo(struct ifreq *, int);
-void getsock(int);
-void printgroupattribs(char *);
-void printif(char *, int);
-void printb_status(unsigned short, unsigned char *);
-const char *get_linkstate(int, int);
-void status(int, struct sockaddr_dl *, int);
-__dead void usage(void);
-const char *get_string(const char *, const char *, u_int8_t *, int *);
-void print_string(const u_int8_t *, int);
-char *sec2str(time_t);
-
-const char *get_media_type_string(uint64_t);
-const char *get_media_subtype_string(uint64_t);
-uint64_t get_media_mode(uint64_t, const char *);
-uint64_t get_media_subtype(uint64_t, const char *);
-uint64_t get_media_options(uint64_t, const char *);
-uint64_t lookup_media_word(const struct ifmedia_description *, uint64_t,
- const char *);
-void print_media_word(uint64_t, int, int);
-void process_media_commands(void);
-void init_current_media(void);
-
-unsigned long get_ts_map(int, int, int);
+int getinfo(struct ifreq *, int);
+void getsock(int);
+void printgroupattribs(char *);
+void printif(char *, int);
+void printb_status(unsigned short, unsigned char *);
+const char *get_linkstate(int, int);
+void status(int, struct sockaddr_dl *, int);
+__dead void usage(void);
+const char *get_string(const char *, const char *, u_int8_t *, int *);
+void print_string(const u_int8_t *, int);
+char *sec2str(time_t);
+
+const char *get_media_type_string(uint64_t);
+const char *get_media_subtype_string(uint64_t);
+uint64_t get_media_mode(uint64_t, const char *);
+uint64_t get_media_subtype(uint64_t, const char *);
+uint64_t get_media_options(uint64_t, const char *);
+uint64_t lookup_media_word(const struct ifmedia_description *, uint64_t,
+ const char *);
+void print_media_word(uint64_t, int, int);
+void process_media_commands(void);
+void init_current_media(void);
void in_status(int);
void in_getaddr(const char *, int);
@@ -2596,7 +2594,7 @@ setmediainst(const char *val, int d)
errx(1, "only one `instance' command may be issued");
/* Must have already specified `media' */
- if ((actions & A_MEDIA) == 0)
+ if (!(actions & A_MEDIA))
errx(1, "must specify `media' before `instance'");
type = IFM_TYPE(media_current);
@@ -2605,7 +2603,7 @@ setmediainst(const char *val, int d)
inst = strtonum(val, 0, IFM_INST_MAX, &errmsg);
if (errmsg)
- errx(1, "media instance %s: %s", val, errmsg);
+ errx(1, "%s media instance: %s", errmsg, val);
media_current = IFM_MAKEWORD(type, subtype, options, inst);
@@ -2623,37 +2621,44 @@ setmediainst(const char *val, int d)
void
settimeslot(const char *val, int d)
{
-#define SINGLE_CHANNEL 0x1
-#define RANGE_CHANNEL 0x2
-#define ALL_CHANNELS 0xFFFFFFFF
- unsigned long ts_map = 0;
- char *ptr = (char *)val;
- int ts_flag = 0;
- int ts = 0, ts_start = 0;
+#define TS_BITS 32
+#define TS_ALL 0xffffffff
+#define TS_RANGE_MASK(i, j) (((1 << (j - i + 1)) - 1) << i)
+ char *buf, *ts_list[TS_BITS], **ts;
+ unsigned long v, ts_start, ts_map = 0;
- if (strcmp(val,"all") == 0) {
- ts_map = ALL_CHANNELS;
- } else {
- while (*ptr != '\0') {
- if (isdigit((unsigned char)*ptr)) {
- ts = strtoul(ptr, &ptr, 10);
- ts_flag |= SINGLE_CHANNEL;
- } else {
- if (*ptr == '-') {
- ts_flag |= RANGE_CHANNEL;
- ts_start = ts;
- } else {
- ts_map |= get_ts_map(ts_flag,
- ts_start, ts);
- ts_flag = 0;
- }
- ptr++;
- }
- }
- if (ts_flag)
- ts_map |= get_ts_map(ts_flag, ts_start, ts);
+ if (strcmp(val, "all") == 0)
+ ts_map = TS_ALL;
+ else {
+ if ((buf = strdup(val)) == NULL)
+ err(1, "strdup");
+ for (ts = ts_list; ts < &ts_list[TS_BITS - 1] &&
+ (*ts = strsep(&buf, ",")) != NULL; ++ts)
+ if (**ts == '\0')
+ errx(1, "invalid arg for timeout: %s", val);
+
+ while (ts-- > ts_list) {
+ if (**ts == '-')
+ errx(1, "invalid arg for timeslot: %s", val);
+ v = strtoul(*ts, &buf, 10); /* first
number */
+ if (v > 31)
+ errx(1, "invalid arg for timeslot: %s", val);
+ if (*buf == '\0') /* slot */
+ ts_map |= 1 << v;
+ else if (*buf == '-') { /* range */
+ ts_start = v;
+ v = strtoul(buf + 1, &buf, 10); /* second
number */
+ if (v == 0 || *buf != '\0' ||
+ v <= ts_start || v > TS_BITS - 1)
+ errx(1, "invalid arg for "
+ "timeslot: %s", val);
+ ts_map |= TS_RANGE_MASK(ts_start, v);
+ } else
+ errx(1, "invalid arg for timeslot: %s", val);
+ }
}
+
(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
ifr.ifr_data = (caddr_t)&ts_map;
@@ -2661,26 +2666,6 @@ settimeslot(const char *val, int d)
err(1, "SIOCSIFTIMESLOT");
}
-unsigned long
-get_ts_map(int ts_flag, int ts_start, int ts_stop)
-{
- int i = 0;
- unsigned long map = 0, mask = 0;
-
- if ((ts_flag & (SINGLE_CHANNEL | RANGE_CHANNEL)) == 0)
- return 0;
- if (ts_flag & RANGE_CHANNEL) { /* Range of channels */
- for (i = ts_start; i <= ts_stop; i++) {
- mask = 1 << i;
- map |=mask;
- }
- } else { /* Single channel */
- mask = 1 << ts_stop;
- map |= mask;
- }
- return map;
-}
-
void
timeslot_status(void)
{
@@ -2714,7 +2699,7 @@ timeslot_status(void)
}
printf("\n");
}
-#endif
+#endif /* SMALL */
const struct ifmedia_description ifm_type_descriptions[] =
@@ -2778,6 +2763,7 @@ get_media_mode(uint64_t type, const char
if (rval == -1)
errx(1, "unknown %s media mode: %s",
get_media_type_string(type), val);
+
return (rval);
}