From: Nikolay Aleksandrov Date: Thu, 30 Sep 2021 11:38:38 +0000 (+0300) Subject: ip: nexthop: parse attributes into nh entry structure before printing X-Git-Tag: v5.16.0~33^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=945c26db686b607cea50779240e96b066ae43b07;p=thirdparty%2Fiproute2.git ip: nexthop: parse attributes into nh entry structure before printing Factor out the nexthop attribute parsing and parse attributes into a nexthop entry structure which is then used to print. Signed-off-by: Nikolay Aleksandrov Signed-off-by: David Ahern --- diff --git a/ip/ipnexthop.c b/ip/ipnexthop.c index 7094d6cbb..0edb3c265 100644 --- a/ip/ipnexthop.c +++ b/ip/ipnexthop.c @@ -213,28 +213,29 @@ out: return rc; } -static void print_nh_group(FILE *fp, const struct rtattr *grps_attr) +static bool __valid_nh_group_attr(const struct rtattr *g_attr) { - struct nexthop_grp *nhg = RTA_DATA(grps_attr); - int num = RTA_PAYLOAD(grps_attr) / sizeof(*nhg); - int i; + int num = RTA_PAYLOAD(g_attr) / sizeof(struct nexthop_grp); - if (!num || num * sizeof(*nhg) != RTA_PAYLOAD(grps_attr)) { - fprintf(fp, ""); - return; - } + return num && num * sizeof(struct nexthop_grp) == RTA_PAYLOAD(g_attr); +} + +static void print_nh_group(const struct nh_entry *nhe) +{ + int i; open_json_array(PRINT_JSON, "group"); print_string(PRINT_FP, NULL, "%s", "group "); - for (i = 0; i < num; ++i) { + for (i = 0; i < nhe->nh_groups_cnt; ++i) { open_json_object(NULL); if (i) print_string(PRINT_FP, NULL, "%s", "/"); - print_uint(PRINT_ANY, "id", "%u", nhg[i].id); - if (nhg[i].weight) - print_uint(PRINT_ANY, "weight", ",%u", nhg[i].weight + 1); + print_uint(PRINT_ANY, "id", "%u", nhe->nh_groups[i].id); + if (nhe->nh_groups[i].weight) + print_uint(PRINT_ANY, "weight", ",%u", + nhe->nh_groups[i].weight + 1); close_json_object(); } @@ -254,15 +255,13 @@ static const char *nh_group_type_name(__u16 type) } } -static void print_nh_group_type(FILE *fp, const struct rtattr *grp_type_attr) +static void print_nh_group_type(__u16 nh_grp_type) { - __u16 type = rta_getattr_u16(grp_type_attr); - - if (type == NEXTHOP_GRP_TYPE_MPATH) + if (nh_grp_type == NEXTHOP_GRP_TYPE_MPATH) /* Do not print type in order not to break existing output. */ return; - print_string(PRINT_ANY, "type", "type %s ", nh_group_type_name(type)); + print_string(PRINT_ANY, "type", "type %s ", nh_group_type_name(nh_grp_type)); } static void parse_nh_res_group_rta(const struct rtattr *res_grp_attr, @@ -340,12 +339,104 @@ static void print_nh_res_bucket(FILE *fp, const struct rtattr *res_bucket_attr) close_json_object(); } +static void ipnh_destroy_entry(struct nh_entry *nhe) +{ + if (nhe->nh_encap) + free(nhe->nh_encap); + if (nhe->nh_groups) + free(nhe->nh_groups); +} + +/* parse nhmsg into nexthop entry struct which must be destroyed by + * ipnh_destroy_enty when it's not needed anymore + */ +static int ipnh_parse_nhmsg(FILE *fp, const struct nhmsg *nhm, int len, + struct nh_entry *nhe) +{ + struct rtattr *tb[NHA_MAX+1]; + int err = 0; + + memset(nhe, 0, sizeof(*nhe)); + parse_rtattr_flags(tb, NHA_MAX, RTM_NHA(nhm), len, NLA_F_NESTED); + + if (tb[NHA_ID]) + nhe->nh_id = rta_getattr_u32(tb[NHA_ID]); + + if (tb[NHA_OIF]) + nhe->nh_oif = rta_getattr_u32(tb[NHA_OIF]); + + if (tb[NHA_GROUP_TYPE]) + nhe->nh_grp_type = rta_getattr_u16(tb[NHA_GROUP_TYPE]); + + if (tb[NHA_GATEWAY]) { + if (RTA_PAYLOAD(tb[NHA_GATEWAY]) > sizeof(nhe->nh_gateway)) { + fprintf(fp, "\n", + nhe->nh_id, RTA_PAYLOAD(tb[NHA_GATEWAY])); + err = -EINVAL; + goto out_err; + } + nhe->nh_gateway_len = RTA_PAYLOAD(tb[NHA_GATEWAY]); + memcpy(&nhe->nh_gateway, RTA_DATA(tb[NHA_GATEWAY]), + RTA_PAYLOAD(tb[NHA_GATEWAY])); + } + + if (tb[NHA_ENCAP]) { + nhe->nh_encap = malloc(RTA_LENGTH(RTA_PAYLOAD(tb[NHA_ENCAP]))); + if (!nhe->nh_encap) { + err = -ENOMEM; + goto out_err; + } + memcpy(nhe->nh_encap, tb[NHA_ENCAP], + RTA_LENGTH(RTA_PAYLOAD(tb[NHA_ENCAP]))); + memcpy(&nhe->nh_encap_type, tb[NHA_ENCAP_TYPE], + sizeof(nhe->nh_encap_type)); + } + + if (tb[NHA_GROUP]) { + if (!__valid_nh_group_attr(tb[NHA_GROUP])) { + fprintf(fp, "", + nhe->nh_id); + err = -EINVAL; + goto out_err; + } + + nhe->nh_groups = malloc(RTA_PAYLOAD(tb[NHA_GROUP])); + if (!nhe->nh_groups) { + err = -ENOMEM; + goto out_err; + } + nhe->nh_groups_cnt = RTA_PAYLOAD(tb[NHA_GROUP]) / + sizeof(struct nexthop_grp); + memcpy(nhe->nh_groups, RTA_DATA(tb[NHA_GROUP]), + RTA_PAYLOAD(tb[NHA_GROUP])); + } + + if (tb[NHA_RES_GROUP]) { + parse_nh_res_group_rta(tb[NHA_RES_GROUP], &nhe->nh_res_grp); + nhe->nh_has_res_grp = true; + } + + nhe->nh_blackhole = !!tb[NHA_BLACKHOLE]; + nhe->nh_fdb = !!tb[NHA_FDB]; + + nhe->nh_family = nhm->nh_family; + nhe->nh_protocol = nhm->nh_protocol; + nhe->nh_scope = nhm->nh_scope; + nhe->nh_flags = nhm->nh_flags; + + return 0; + +out_err: + ipnh_destroy_entry(nhe); + return err; +} + int print_nexthop(struct nlmsghdr *n, void *arg) { struct nhmsg *nhm = NLMSG_DATA(n); - struct rtattr *tb[NHA_MAX+1]; FILE *fp = (FILE *)arg; - int len; + struct nh_entry nhe; + int len, err; SPRINT_BUF(b1); @@ -366,60 +457,61 @@ int print_nexthop(struct nlmsghdr *n, void *arg) if (filter.proto && filter.proto != nhm->nh_protocol) return 0; - parse_rtattr_flags(tb, NHA_MAX, RTM_NHA(nhm), len, NLA_F_NESTED); - + err = ipnh_parse_nhmsg(fp, nhm, len, &nhe); + if (err) { + close_json_object(); + fprintf(stderr, "Error parsing nexthop: %s\n", strerror(-err)); + return -1; + } open_json_object(NULL); if (n->nlmsg_type == RTM_DELNEXTHOP) print_bool(PRINT_ANY, "deleted", "Deleted ", true); - if (tb[NHA_ID]) - print_uint(PRINT_ANY, "id", "id %u ", - rta_getattr_u32(tb[NHA_ID])); + print_uint(PRINT_ANY, "id", "id %u ", nhe.nh_id); - if (tb[NHA_GROUP]) - print_nh_group(fp, tb[NHA_GROUP]); + if (nhe.nh_groups) + print_nh_group(&nhe); - if (tb[NHA_GROUP_TYPE]) - print_nh_group_type(fp, tb[NHA_GROUP_TYPE]); + print_nh_group_type(nhe.nh_grp_type); - if (tb[NHA_RES_GROUP]) { - struct nha_res_grp res_grp; + if (nhe.nh_has_res_grp) + print_nh_res_group(&nhe.nh_res_grp); - parse_nh_res_group_rta(tb[NHA_RES_GROUP], &res_grp); - print_nh_res_group(&res_grp); - } + if (nhe.nh_encap) + lwt_print_encap(fp, &nhe.nh_encap_type.rta, nhe.nh_encap); - if (tb[NHA_ENCAP]) - lwt_print_encap(fp, tb[NHA_ENCAP_TYPE], tb[NHA_ENCAP]); + if (nhe.nh_gateway_len) + __print_rta_gateway(fp, nhe.nh_family, + format_host(nhe.nh_family, + nhe.nh_gateway_len, + &nhe.nh_gateway)); - if (tb[NHA_GATEWAY]) - print_rta_gateway(fp, nhm->nh_family, tb[NHA_GATEWAY]); + if (nhe.nh_oif) + print_rta_ifidx(fp, nhe.nh_oif, "dev"); - if (tb[NHA_OIF]) - print_rta_ifidx(fp, rta_getattr_u32(tb[NHA_OIF]), "dev"); - - if (nhm->nh_scope != RT_SCOPE_UNIVERSE || show_details > 0) { + if (nhe.nh_scope != RT_SCOPE_UNIVERSE || show_details > 0) { print_string(PRINT_ANY, "scope", "scope %s ", - rtnl_rtscope_n2a(nhm->nh_scope, b1, sizeof(b1))); + rtnl_rtscope_n2a(nhe.nh_scope, b1, sizeof(b1))); } - if (tb[NHA_BLACKHOLE]) + if (nhe.nh_blackhole) print_null(PRINT_ANY, "blackhole", "blackhole ", NULL); - if (nhm->nh_protocol != RTPROT_UNSPEC || show_details > 0) { + if (nhe.nh_protocol != RTPROT_UNSPEC || show_details > 0) { print_string(PRINT_ANY, "protocol", "proto %s ", - rtnl_rtprot_n2a(nhm->nh_protocol, b1, sizeof(b1))); + rtnl_rtprot_n2a(nhe.nh_protocol, b1, sizeof(b1))); } - print_rt_flags(fp, nhm->nh_flags); + print_rt_flags(fp, nhe.nh_flags); - if (tb[NHA_FDB]) + if (nhe.nh_fdb) print_null(PRINT_ANY, "fdb", "fdb", NULL); print_string(PRINT_FP, NULL, "%s", "\n"); close_json_object(); fflush(fp); + ipnh_destroy_entry(&nhe); return 0; }