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);
}

Reply via email to