diff --git a/include/utils.h b/include/utils.h index d7653273..2d1a587c 100644 --- a/include/utils.h +++ b/include/utils.h @@ -329,4 +329,8 @@ int parse_one_of(const char *msg, const char *realval, const char * const *list, size_t len, int *p_err); bool parse_on_off(const char *msg, const char *realval, int *p_err); +int parse_mapping(int *argcp, char ***argvp, + int (*mapping_cb)(__u32 key, char *value, void *data), + void *mapping_cb_data); + #endif /* __UTILS_H__ */ diff --git a/ip/iplink_vlan.c b/ip/iplink_vlan.c index 1e6817f5..dadc349d 100644 --- a/ip/iplink_vlan.c +++ b/ip/iplink_vlan.c @@ -49,36 +49,30 @@ static int on_off(const char *msg, const char *arg) return -1; } +static int parse_qos_mapping(__u32 key, char *value, void *data) +{ + struct nlmsghdr *n = data; + struct ifla_vlan_qos_mapping m = { + .from = key, + }; + + if (get_u32(&m.to, value, 0)) + return 1; + + return addattr_l(n, 1024, IFLA_VLAN_QOS_MAPPING, &m, sizeof(m)); +} + static int vlan_parse_qos_map(int *argcp, char ***argvp, struct nlmsghdr *n, int attrtype) { - int argc = *argcp; - char **argv = *argvp; - struct ifla_vlan_qos_mapping m; struct rtattr *tail; tail = addattr_nest(n, 1024, attrtype); - while (argc > 0) { - char *colon = strchr(*argv, ':'); - - if (!colon) - break; - *colon = '\0'; - - if (get_u32(&m.from, *argv, 0)) - return 1; - if (get_u32(&m.to, colon + 1, 0)) - return 1; - argc--, argv++; - - addattr_l(n, 1024, IFLA_VLAN_QOS_MAPPING, &m, sizeof(m)); - } + if (parse_mapping(argcp, argvp, &parse_qos_mapping, n)) + return 1; addattr_nest_end(n, tail); - - *argcp = argc; - *argvp = argv; return 0; } diff --git a/lib/utils.c b/lib/utils.c index eab0839a..1dfaaf56 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -1763,3 +1763,31 @@ bool parse_on_off(const char *msg, const char *realval, int *p_err) return parse_one_of(msg, realval, values_on_off, ARRAY_SIZE(values_on_off), p_err); } + +int parse_mapping(int *argcp, char ***argvp, + int (*mapping_cb)(__u32 key, char *value, void *data), + void *mapping_cb_data) +{ + int argc = *argcp; + char **argv = *argvp; + + while (argc > 0) { + char *colon = strchr(*argv, ':'); + __u32 key; + + if (!colon) + break; + *colon = '\0'; + + if (get_u32(&key, *argv, 0)) + return 1; + if (mapping_cb(key, colon + 1, mapping_cb_data)) + return 1; + + argc--, argv++; + } + + *argcp = argc; + *argvp = argv; + return 0; +}