static int exp_parse_ip(struct nfnl_exp *exp, int tuple, struct nlattr *attr) { struct nlattr *tb[CTA_IP_MAX+1]; struct nl_addr *addr; int err; err = nla_parse_nested(tb, CTA_IP_MAX, attr, exp_ip_policy); if (err < 0) goto errout; if (tb[CTA_IP_V4_SRC]) { addr = nl_addr_alloc_attr(tb[CTA_IP_V4_SRC], AF_INET); if (addr == NULL) goto errout_enomem; err = nfnl_exp_set_src(exp, tuple, addr); nl_addr_put(addr); if (err < 0) goto errout; } if (tb[CTA_IP_V4_DST]) { addr = nl_addr_alloc_attr(tb[CTA_IP_V4_DST], AF_INET); if (addr == NULL) goto errout_enomem; err = nfnl_exp_set_dst(exp, tuple, addr); nl_addr_put(addr); if (err < 0) goto errout; } if (tb[CTA_IP_V6_SRC]) { addr = nl_addr_alloc_attr(tb[CTA_IP_V6_SRC], AF_INET6); if (addr == NULL) goto errout_enomem; err = nfnl_exp_set_src(exp, tuple, addr); nl_addr_put(addr); if (err < 0) goto errout; } if (tb[CTA_IP_V6_DST]) { addr = nl_addr_alloc_attr(tb[CTA_IP_V6_DST], AF_INET6); if (addr == NULL) goto errout_enomem; err = nfnl_exp_set_dst(exp, tuple, addr); nl_addr_put(addr); if (err < 0) goto errout; } return 0; errout_enomem: err = -NLE_NOMEM; errout: return err; }
static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, struct nlmsghdr *n, struct nl_parser_param *pp) { struct rtnl_rule *rule; struct fib_rule_hdr *frh; struct nlattr *tb[FRA_MAX+1]; int err = 1, family; rule = rtnl_rule_alloc(); if (!rule) { err = -NLE_NOMEM; goto errout; } rule->ce_msgtype = n->nlmsg_type; frh = nlmsg_data(n); err = nlmsg_parse(n, sizeof(*frh), tb, FRA_MAX, rule_policy); if (err < 0) goto errout; rule->r_family = family = frh->family; rule->r_table = frh->table; rule->r_action = frh->action; rule->r_flags = frh->flags; rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_TABLE | RULE_ATTR_ACTION | RULE_ATTR_FLAGS); /* ipv4 only */ if (frh->tos) { rule->r_dsfield = frh->tos; rule->ce_mask |= RULE_ATTR_DSFIELD; } if (tb[FRA_TABLE]) { rule->r_table = nla_get_u32(tb[FRA_TABLE]); rule->ce_mask |= RULE_ATTR_TABLE; } if (tb[FRA_IIFNAME]) { nla_strlcpy(rule->r_iifname, tb[FRA_IIFNAME], IFNAMSIZ); rule->ce_mask |= RULE_ATTR_IIFNAME; } if (tb[FRA_OIFNAME]) { nla_strlcpy(rule->r_oifname, tb[FRA_OIFNAME], IFNAMSIZ); rule->ce_mask |= RULE_ATTR_OIFNAME; } if (tb[FRA_PRIORITY]) { rule->r_prio = nla_get_u32(tb[FRA_PRIORITY]); rule->ce_mask |= RULE_ATTR_PRIO; } if (tb[FRA_FWMARK]) { rule->r_mark = nla_get_u32(tb[FRA_FWMARK]); rule->ce_mask |= RULE_ATTR_MARK; } if (tb[FRA_FWMASK]) { rule->r_mask = nla_get_u32(tb[FRA_FWMASK]); rule->ce_mask |= RULE_ATTR_MASK; } if (tb[FRA_GOTO]) { rule->r_goto = nla_get_u32(tb[FRA_GOTO]); rule->ce_mask |= RULE_ATTR_GOTO; } if (tb[FRA_SRC]) { if (!(rule->r_src = nl_addr_alloc_attr(tb[FRA_SRC], family))) goto errout_enomem; nl_addr_set_prefixlen(rule->r_src, frh->src_len); rule->ce_mask |= RULE_ATTR_SRC; } if (tb[FRA_DST]) { if (!(rule->r_dst = nl_addr_alloc_attr(tb[FRA_DST], family))) goto errout_enomem; nl_addr_set_prefixlen(rule->r_dst, frh->dst_len); rule->ce_mask |= RULE_ATTR_DST; } /* ipv4 only */ if (tb[FRA_FLOW]) { rule->r_flow = nla_get_u32(tb[FRA_FLOW]); rule->ce_mask |= RULE_ATTR_FLOW; } err = pp->pp_cb((struct nl_object *) rule, pp); errout: rtnl_rule_put(rule); return err; errout_enomem: err = -NLE_NOMEM; goto errout; }
static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, struct nlmsghdr *n, struct nl_parser_param *pp) { struct rtnl_rule *rule; struct rtmsg *r; struct nlattr *tb[RTA_MAX+1]; int err = 1, family; rule = rtnl_rule_alloc(); if (!rule) { err = -NLE_NOMEM; goto errout; } rule->ce_msgtype = n->nlmsg_type; r = nlmsg_data(n); err = nlmsg_parse(n, sizeof(*r), tb, RTA_MAX, rule_policy); if (err < 0) goto errout; rule->r_family = family = r->rtm_family; rule->r_type = r->rtm_type; rule->r_dsfield = r->rtm_tos; rule->r_src_len = r->rtm_src_len; rule->r_dst_len = r->rtm_dst_len; rule->r_table = r->rtm_table; rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_TYPE | RULE_ATTR_DSFIELD | RULE_ATTR_SRC_LEN | RULE_ATTR_DST_LEN |RULE_ATTR_TYPE | RULE_ATTR_TABLE); if (tb[RTA_PRIORITY]) { rule->r_prio = nla_get_u32(tb[RTA_PRIORITY]); rule->ce_mask |= RULE_ATTR_PRIO; } if (tb[RTA_SRC]) { if (!(rule->r_src = nl_addr_alloc_attr(tb[RTA_SRC], family))) goto errout_enomem; nl_addr_set_prefixlen(rule->r_src, r->rtm_src_len); rule->ce_mask |= RULE_ATTR_SRC; } if (tb[RTA_DST]) { if (!(rule->r_dst = nl_addr_alloc_attr(tb[RTA_DST], family))) goto errout_enomem; nl_addr_set_prefixlen(rule->r_dst, r->rtm_dst_len); rule->ce_mask |= RULE_ATTR_DST; } if (tb[RTA_PROTOINFO]) { rule->r_mark = nla_get_u32(tb[RTA_PROTOINFO]); rule->ce_mask |= RULE_ATTR_MARK; } if (tb[RTA_IIF]) { nla_strlcpy(rule->r_iif, tb[RTA_IIF], IFNAMSIZ); rule->ce_mask |= RULE_ATTR_IIF; } if (tb[RTA_FLOW]) { rule->r_realms = nla_get_u32(tb[RTA_FLOW]); rule->ce_mask |= RULE_ATTR_REALMS; } if (tb[RTA_GATEWAY]) { rule->r_srcmap = nl_addr_alloc_attr(tb[RTA_GATEWAY], family); if (!rule->r_srcmap) goto errout_enomem; rule->ce_mask |= RULE_ATTR_SRCMAP; } if (tb[RTA_TABLE]) { rule->r_table = nla_get_u32(tb[RTA_TABLE]); rule->ce_mask |= RULE_ATTR_TABLE; } err = pp->pp_cb((struct nl_object *) rule, pp); errout: rtnl_rule_put(rule); return err; errout_enomem: err = -NLE_NOMEM; goto errout; }