Merge branch 'get_addr_rta' into iproute2-next

Serhey Popovych  says:

====================

Now we enhance get_addr() to return additional information about address
(e.g. if it unspecified or multicast) we want to have same functionality
for attributes in netlink message.

Introduce and use get_addr_rta() that parses given netlink attribute
into @inet_prefix data structure in the same way similar get_addr()
parses address from it's string representation.

Use attribute length to guess address family: force it by giving non
AF_UNSPEC @family to get_addr_rta() to ensure address is of expected
family.

Introduce and use inet_addr_match_rta() to further simplify and unify
code where get_addr_rta() intended to be used together with
inet_addr_match().

This is next step in ipv4 and ipv6 modules unification to prepare for
merge in the future.

====================

Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
David Ahern 2018-01-25 09:32:27 -08:00
commit db9fd71038
16 changed files with 206 additions and 246 deletions

View File

@ -120,6 +120,7 @@ int get_prefix_1(inet_prefix *dst, char *arg, int family);
int get_addr(inet_prefix *dst, const char *arg, int family); int get_addr(inet_prefix *dst, const char *arg, int family);
int get_prefix(inet_prefix *dst, char *arg, int family); int get_prefix(inet_prefix *dst, char *arg, int family);
int mask2bits(__u32 netmask); int mask2bits(__u32 netmask);
int get_addr_rta(inet_prefix *dst, const struct rtattr *rta, int family);
int get_addr_ila(__u64 *val, const char *arg); int get_addr_ila(__u64 *val, const char *arg);
int read_prop(const char *dev, char *prop, long *value); int read_prop(const char *dev, char *prop, long *value);
@ -174,6 +175,7 @@ int check_ifname(const char *);
int get_ifname(char *, const char *); int get_ifname(char *, const char *);
int matches(const char *arg, const char *pattern); int matches(const char *arg, const char *pattern);
int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits); int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits);
int inet_addr_match_rta(const inet_prefix *m, const struct rtattr *rta);
const char *dnet_ntop(int af, const void *addr, char *str, size_t len); const char *dnet_ntop(int af, const void *addr, char *str, size_t len);
int dnet_pton(int af, const char *src, void *addr); int dnet_pton(int af, const char *src, void *addr);

View File

@ -1523,19 +1523,13 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
if (fnmatch(filter.label, label, 0) != 0) if (fnmatch(filter.label, label, 0) != 0)
return 0; return 0;
} }
if (filter.pfx.family) {
if (rta_tb[IFA_LOCAL]) {
inet_prefix dst = { .family = ifa->ifa_family };
memcpy(&dst.data, RTA_DATA(rta_tb[IFA_LOCAL]), RTA_PAYLOAD(rta_tb[IFA_LOCAL]));
if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
return 0;
}
}
if (filter.family && filter.family != ifa->ifa_family) if (filter.family && filter.family != ifa->ifa_family)
return 0; return 0;
if (inet_addr_match_rta(&filter.pfx, rta_tb[IFA_LOCAL]))
return 0;
if (filter.flushb) { if (filter.flushb) {
struct nlmsghdr *fn; struct nlmsghdr *fn;
@ -1889,18 +1883,12 @@ static void ipaddr_filter(struct nlmsg_chain *linfo, struct nlmsg_chain *ainfo)
if ((filter.flags ^ ifa_flags) & filter.flagmask) if ((filter.flags ^ ifa_flags) & filter.flagmask)
continue; continue;
if (filter.pfx.family || filter.label) { if (filter.pfx.family || filter.label) {
if (!tb[IFA_LOCAL]) struct rtattr *rta =
tb[IFA_LOCAL] = tb[IFA_ADDRESS]; tb[IFA_LOCAL] ? : tb[IFA_ADDRESS];
if (filter.pfx.family && tb[IFA_LOCAL]) { if (inet_addr_match_rta(&filter.pfx, rta))
inet_prefix dst = { continue;
.family = ifa->ifa_family
};
memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL]));
if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
continue;
}
if (filter.label) { if (filter.label) {
SPRINT_BUF(b1); SPRINT_BUF(b1);
const char *label; const char *label;
@ -2072,7 +2060,8 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
while (argc > 0) { while (argc > 0) {
if (strcmp(*argv, "to") == 0) { if (strcmp(*argv, "to") == 0) {
NEXT_ARG(); NEXT_ARG();
get_prefix(&filter.pfx, *argv, filter.family); if (get_prefix(&filter.pfx, *argv, filter.family))
invarg("invalid \"to\"\n", *argv);
if (filter.family == AF_UNSPEC) if (filter.family == AF_UNSPEC)
filter.family = filter.pfx.family; filter.family = filter.pfx.family;
} else if (strcmp(*argv, "scope") == 0) { } else if (strcmp(*argv, "scope") == 0) {

View File

@ -296,7 +296,7 @@ static int get_response(struct nlmsghdr *n, void *arg)
struct l2tp_data *data = arg; struct l2tp_data *data = arg;
struct l2tp_parm *p = &data->config; struct l2tp_parm *p = &data->config;
struct rtattr *attrs[L2TP_ATTR_MAX + 1]; struct rtattr *attrs[L2TP_ATTR_MAX + 1];
struct rtattr *nla_stats; struct rtattr *nla_stats, *rta;
int len; int len;
/* Validate message and parse attributes */ /* Validate message and parse attributes */
@ -352,30 +352,25 @@ static int get_response(struct nlmsghdr *n, void *arg)
if (attrs[L2TP_ATTR_RECV_TIMEOUT]) if (attrs[L2TP_ATTR_RECV_TIMEOUT])
p->reorder_timeout = rta_getattr_u64(attrs[L2TP_ATTR_RECV_TIMEOUT]); p->reorder_timeout = rta_getattr_u64(attrs[L2TP_ATTR_RECV_TIMEOUT]);
if (attrs[L2TP_ATTR_IP_SADDR]) {
p->local_ip.family = AF_INET; rta = attrs[L2TP_ATTR_IP_SADDR];
p->local_ip.data[0] = rta_getattr_u32(attrs[L2TP_ATTR_IP_SADDR]); p->local_ip.family = AF_INET;
p->local_ip.bytelen = 4; if (!rta) {
p->local_ip.bitlen = -1; rta = attrs[L2TP_ATTR_IP6_SADDR];
}
if (attrs[L2TP_ATTR_IP_DADDR]) {
p->peer_ip.family = AF_INET;
p->peer_ip.data[0] = rta_getattr_u32(attrs[L2TP_ATTR_IP_DADDR]);
p->peer_ip.bytelen = 4;
p->peer_ip.bitlen = -1;
}
if (attrs[L2TP_ATTR_IP6_SADDR]) {
p->local_ip.family = AF_INET6; p->local_ip.family = AF_INET6;
memcpy(&p->local_ip.data, RTA_DATA(attrs[L2TP_ATTR_IP6_SADDR]),
p->local_ip.bytelen = 16);
p->local_ip.bitlen = -1;
} }
if (attrs[L2TP_ATTR_IP6_DADDR]) { if (rta && get_addr_rta(&p->local_ip, rta, p->local_ip.family))
return -1;
rta = attrs[L2TP_ATTR_IP_DADDR];
p->peer_ip.family = AF_INET;
if (!rta) {
rta = attrs[L2TP_ATTR_IP6_DADDR];
p->peer_ip.family = AF_INET6; p->peer_ip.family = AF_INET6;
memcpy(&p->peer_ip.data, RTA_DATA(attrs[L2TP_ATTR_IP6_DADDR]),
p->peer_ip.bytelen = 16);
p->peer_ip.bitlen = -1;
} }
if (rta && get_addr_rta(&p->peer_ip, rta, p->peer_ip.family))
return -1;
if (attrs[L2TP_ATTR_UDP_SPORT]) if (attrs[L2TP_ATTR_UDP_SPORT])
p->local_udp_port = rta_getattr_u16(attrs[L2TP_ATTR_UDP_SPORT]); p->local_udp_port = rta_getattr_u16(attrs[L2TP_ATTR_UDP_SPORT]);
if (attrs[L2TP_ATTR_UDP_DPORT]) if (attrs[L2TP_ATTR_UDP_DPORT])

View File

@ -95,21 +95,11 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
if (filter.af && filter.af != r->rtm_family) if (filter.af && filter.af != r->rtm_family)
return 0; return 0;
if (tb[RTA_DST] && filter.mdst.bitlen > 0) { if (inet_addr_match_rta(&filter.mdst, tb[RTA_DST]))
inet_prefix dst = { .family = r->rtm_family }; return 0;
memcpy(&dst.data, RTA_DATA(tb[RTA_DST]), RTA_PAYLOAD(tb[RTA_DST])); if (inet_addr_match_rta(&filter.msrc, tb[RTA_SRC]))
if (inet_addr_match(&dst, &filter.mdst, filter.mdst.bitlen)) return 0;
return 0;
}
if (tb[RTA_SRC] && filter.msrc.bitlen > 0) {
inet_prefix src = { .family = r->rtm_family };
memcpy(&src.data, RTA_DATA(tb[RTA_SRC]), RTA_PAYLOAD(tb[RTA_SRC]));
if (inet_addr_match(&src, &filter.msrc, filter.msrc.bitlen))
return 0;
}
family = get_real_family(r->rtm_type, r->rtm_family); family = get_real_family(r->rtm_type, r->rtm_family);
@ -213,6 +203,8 @@ static int mroute_list(int argc, char **argv)
} else } else
filter.af = RTNL_FAMILY_IP6MR; filter.af = RTNL_FAMILY_IP6MR;
filter.msrc.family = filter.mdst.family = family;
while (argc > 0) { while (argc > 0) {
if (matches(*argv, "table") == 0) { if (matches(*argv, "table") == 0) {
__u32 tid; __u32 tid;
@ -233,14 +225,16 @@ static int mroute_list(int argc, char **argv)
id = *argv; id = *argv;
} else if (matches(*argv, "from") == 0) { } else if (matches(*argv, "from") == 0) {
NEXT_ARG(); NEXT_ARG();
get_prefix(&filter.msrc, *argv, family); if (get_prefix(&filter.msrc, *argv, family))
invarg("from value is invalid\n", *argv);
} else { } else {
if (strcmp(*argv, "to") == 0) { if (strcmp(*argv, "to") == 0) {
NEXT_ARG(); NEXT_ARG();
} }
if (matches(*argv, "help") == 0) if (matches(*argv, "help") == 0)
usage(); usage();
get_prefix(&filter.mdst, *argv, family); if (get_prefix(&filter.mdst, *argv, family))
invarg("to value is invalid\n", *argv);
} }
argc--; argv++; argc--; argv++;
} }

View File

@ -234,15 +234,9 @@ int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
parse_rtattr(tb, NDA_MAX, NDA_RTA(r), n->nlmsg_len - NLMSG_LENGTH(sizeof(*r))); parse_rtattr(tb, NDA_MAX, NDA_RTA(r), n->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
if (tb[NDA_DST]) { if (inet_addr_match_rta(&filter.pfx, tb[NDA_DST]))
if (filter.pfx.family) { return 0;
inet_prefix dst = { .family = r->ndm_family };
memcpy(&dst.data, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
return 0;
}
}
if (filter.unused_only && tb[NDA_CACHEINFO]) { if (filter.unused_only && tb[NDA_CACHEINFO]) {
struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]); struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]);
@ -418,7 +412,8 @@ static int do_show_or_flush(int argc, char **argv, int flush)
} }
if (matches(*argv, "help") == 0) if (matches(*argv, "help") == 0)
usage(); usage();
get_prefix(&filter.pfx, *argv, filter.family); if (get_prefix(&filter.pfx, *argv, filter.family))
invarg("to value is invalid\n", *argv);
if (filter.family == AF_UNSPEC) if (filter.family == AF_UNSPEC)
filter.family = filter.pfx.family; filter.family = filter.pfx.family;
} }

View File

@ -76,8 +76,6 @@ static struct
static bool filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len) static bool filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
{ {
struct rtmsg *r = NLMSG_DATA(n); struct rtmsg *r = NLMSG_DATA(n);
inet_prefix src = { .family = r->rtm_family };
inet_prefix dst = { .family = r->rtm_family };
__u32 table; __u32 table;
if (preferred_family != AF_UNSPEC && r->rtm_family != preferred_family) if (preferred_family != AF_UNSPEC && r->rtm_family != preferred_family)
@ -90,24 +88,24 @@ static bool filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
return false; return false;
if (filter.src.family) { if (filter.src.family) {
if (tb[FRA_SRC]) { inet_prefix *f_src = &filter.src;
memcpy(&src.data, RTA_DATA(tb[FRA_SRC]),
(r->rtm_src_len + 7) / 8); if (f_src->family != r->rtm_family ||
} f_src->bitlen > r->rtm_src_len)
if (filter.src.family != r->rtm_family || return false;
filter.src.bitlen > r->rtm_src_len ||
inet_addr_match(&src, &filter.src, filter.src.bitlen)) if (inet_addr_match_rta(f_src, tb[FRA_SRC]))
return false; return false;
} }
if (filter.dst.family) { if (filter.dst.family) {
if (tb[FRA_DST]) { inet_prefix *f_dst = &filter.dst;
memcpy(&dst.data, RTA_DATA(tb[FRA_DST]),
(r->rtm_dst_len + 7) / 8); if (f_dst->family != r->rtm_family ||
} f_dst->bitlen > r->rtm_dst_len)
if (filter.dst.family != r->rtm_family || return false;
filter.dst.bitlen > r->rtm_dst_len ||
inet_addr_match(&dst, &filter.dst, filter.dst.bitlen)) if (inet_addr_match_rta(f_dst, tb[FRA_DST]))
return false; return false;
} }
@ -500,13 +498,15 @@ static int iprule_list_flush_or_save(int argc, char **argv, int action)
} else if (matches(*argv, "from") == 0 || } else if (matches(*argv, "from") == 0 ||
matches(*argv, "src") == 0) { matches(*argv, "src") == 0) {
NEXT_ARG(); NEXT_ARG();
get_prefix(&filter.src, *argv, af); if (get_prefix(&filter.src, *argv, af))
invarg("from value is invalid\n", *argv);
} else { } else {
if (matches(*argv, "dst") == 0 || if (matches(*argv, "dst") == 0 ||
matches(*argv, "to") == 0) { matches(*argv, "to") == 0) {
NEXT_ARG(); NEXT_ARG();
} }
get_prefix(&filter.dst, *argv, af); if (get_prefix(&filter.dst, *argv, af))
invarg("to value is invalid\n", *argv);
} }
argc--; argv++; argc--; argv++;
} }

View File

@ -395,8 +395,6 @@ get_failed:
static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{ {
char s2[64]; char s2[64];
const char *local = "any";
const char *remote = "any";
unsigned int iflags = 0; unsigned int iflags = 0;
unsigned int oflags = 0; unsigned int oflags = 0;
__u8 ttl = 0; __u8 ttl = 0;
@ -410,23 +408,8 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
return; return;
} }
if (tb[IFLA_GRE_REMOTE]) { tnl_print_endpoint("remote", tb[IFLA_GRE_REMOTE], AF_INET);
unsigned int addr = rta_getattr_u32(tb[IFLA_GRE_REMOTE]); tnl_print_endpoint("local", tb[IFLA_GRE_LOCAL], AF_INET);
if (addr)
remote = format_host(AF_INET, 4, &addr);
}
print_string(PRINT_ANY, "remote", "remote %s ", remote);
if (tb[IFLA_GRE_LOCAL]) {
unsigned int addr = rta_getattr_u32(tb[IFLA_GRE_LOCAL]);
if (addr)
local = format_host(AF_INET, 4, &addr);
}
print_string(PRINT_ANY, "local", "local %s ", local);
if (tb[IFLA_GRE_LINK]) { if (tb[IFLA_GRE_LINK]) {
unsigned int link = rta_getattr_u32(tb[IFLA_GRE_LINK]); unsigned int link = rta_getattr_u32(tb[IFLA_GRE_LINK]);

View File

@ -429,13 +429,10 @@ get_failed:
static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{ {
char s2[64]; char s2[64];
const char *local = "any";
const char *remote = "any";
unsigned int iflags = 0; unsigned int iflags = 0;
unsigned int oflags = 0; unsigned int oflags = 0;
unsigned int flags = 0; unsigned int flags = 0;
__u32 flowinfo = 0; __u32 flowinfo = 0;
struct in6_addr in6_addr_any = IN6ADDR_ANY_INIT;
__u8 ttl = 0; __u8 ttl = 0;
if (!tb) if (!tb)
@ -452,27 +449,8 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
if (tb[IFLA_GRE_FLOWINFO]) if (tb[IFLA_GRE_FLOWINFO])
flowinfo = rta_getattr_u32(tb[IFLA_GRE_FLOWINFO]); flowinfo = rta_getattr_u32(tb[IFLA_GRE_FLOWINFO]);
if (tb[IFLA_GRE_REMOTE]) { tnl_print_endpoint("remote", tb[IFLA_GRE_REMOTE], AF_INET6);
struct in6_addr addr; tnl_print_endpoint("local", tb[IFLA_GRE_LOCAL], AF_INET6);
memcpy(&addr, RTA_DATA(tb[IFLA_GRE_REMOTE]), sizeof(addr));
if (memcmp(&addr, &in6_addr_any, sizeof(addr)))
remote = format_host(AF_INET6, sizeof(addr), &addr);
}
print_string(PRINT_ANY, "remote", "remote %s ", remote);
if (tb[IFLA_GRE_LOCAL]) {
struct in6_addr addr;
memcpy(&addr, RTA_DATA(tb[IFLA_GRE_LOCAL]), sizeof(addr));
if (memcmp(&addr, &in6_addr_any, sizeof(addr)))
local = format_host(AF_INET6, sizeof(addr), &addr);
}
print_string(PRINT_ANY, "local", "local %s ", local);
if (tb[IFLA_GRE_LINK]) { if (tb[IFLA_GRE_LINK]) {
unsigned int link = rta_getattr_u32(tb[IFLA_GRE_LINK]); unsigned int link = rta_getattr_u32(tb[IFLA_GRE_LINK]);

View File

@ -366,19 +366,8 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb
} }
} }
if (tb[IFLA_IPTUN_REMOTE]) { tnl_print_endpoint("remote", tb[IFLA_IPTUN_REMOTE], AF_INET6);
print_string(PRINT_ANY, tnl_print_endpoint("local", tb[IFLA_IPTUN_LOCAL], AF_INET6);
"remote",
"remote %s ",
rt_addr_n2a_rta(AF_INET6, tb[IFLA_IPTUN_REMOTE]));
}
if (tb[IFLA_IPTUN_LOCAL]) {
print_string(PRINT_ANY,
"local",
"local %s ",
rt_addr_n2a_rta(AF_INET6, tb[IFLA_IPTUN_LOCAL]));
}
if (tb[IFLA_IPTUN_LINK]) { if (tb[IFLA_IPTUN_LINK]) {
unsigned int link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]); unsigned int link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]);

View File

@ -362,8 +362,6 @@ get_failed:
static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{ {
char s2[64]; char s2[64];
const char *local = "any";
const char *remote = "any";
__u16 prefixlen; __u16 prefixlen;
__u8 ttl = 0; __u8 ttl = 0;
__u8 tos = 0; __u8 tos = 0;
@ -393,23 +391,8 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[
} }
} }
if (tb[IFLA_IPTUN_REMOTE]) { tnl_print_endpoint("remote", tb[IFLA_IPTUN_REMOTE], AF_INET);
unsigned int addr = rta_getattr_u32(tb[IFLA_IPTUN_REMOTE]); tnl_print_endpoint("local", tb[IFLA_IPTUN_LOCAL], AF_INET);
if (addr)
remote = format_host(AF_INET, 4, &addr);
}
print_string(PRINT_ANY, "remote", "remote %s ", remote);
if (tb[IFLA_IPTUN_LOCAL]) {
unsigned int addr = rta_getattr_u32(tb[IFLA_IPTUN_LOCAL]);
if (addr)
local = format_host(AF_INET, 4, &addr);
}
print_string(PRINT_ANY, "local", "local %s ", local);
if (tb[IFLA_IPTUN_LINK]) { if (tb[IFLA_IPTUN_LINK]) {
unsigned int link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]); unsigned int link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]);

View File

@ -165,30 +165,13 @@ get_failed:
static void vti_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) static void vti_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{ {
const char *local = "any";
const char *remote = "any";
char s2[64]; char s2[64];
if (!tb) if (!tb)
return; return;
if (tb[IFLA_VTI_REMOTE]) { tnl_print_endpoint("remote", tb[IFLA_VTI_REMOTE], AF_INET);
unsigned int addr = rta_getattr_u32(tb[IFLA_VTI_REMOTE]); tnl_print_endpoint("local", tb[IFLA_VTI_LOCAL], AF_INET);
if (addr)
remote = format_host(AF_INET, 4, &addr);
}
print_string(PRINT_ANY, "remote", "remote %s ", remote);
if (tb[IFLA_VTI_LOCAL]) {
unsigned int addr = rta_getattr_u32(tb[IFLA_VTI_LOCAL]);
if (addr)
local = format_host(AF_INET, 4, &addr);
}
print_string(PRINT_ANY, "local", "local %s ", local);
if (tb[IFLA_VTI_LINK]) { if (tb[IFLA_VTI_LINK]) {
unsigned int link = rta_getattr_u32(tb[IFLA_VTI_LINK]); unsigned int link = rta_getattr_u32(tb[IFLA_VTI_LINK]);

View File

@ -171,30 +171,13 @@ get_failed:
static void vti6_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) static void vti6_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{ {
const char *local = "any";
const char *remote = "any";
struct in6_addr saddr;
struct in6_addr daddr;
char s2[64]; char s2[64];
if (!tb) if (!tb)
return; return;
if (tb[IFLA_VTI_REMOTE]) { tnl_print_endpoint("remote", tb[IFLA_VTI_REMOTE], AF_INET6);
memcpy(&daddr, RTA_DATA(tb[IFLA_VTI_REMOTE]), sizeof(daddr)); tnl_print_endpoint("local", tb[IFLA_VTI_LOCAL], AF_INET6);
remote = format_host(AF_INET6, 16, &daddr);
}
print_string(PRINT_ANY, "remote", "remote %s ", remote);
if (tb[IFLA_VTI_LOCAL]) {
memcpy(&saddr, RTA_DATA(tb[IFLA_VTI_LOCAL]), sizeof(saddr));
local = format_host(AF_INET6, 16, &saddr);
}
print_string(PRINT_ANY, "local", "local %s ", local);
if (tb[IFLA_VTI_LINK]) { if (tb[IFLA_VTI_LINK]) {
unsigned int link = rta_getattr_u32(tb[IFLA_VTI_LINK]); unsigned int link = rta_getattr_u32(tb[IFLA_VTI_LINK]);

View File

@ -96,7 +96,7 @@ static int process_msg(const struct sockaddr_nl *who, struct nlmsghdr *n,
struct rtattr *attrs[TCP_METRICS_ATTR_MAX + 1], *a; struct rtattr *attrs[TCP_METRICS_ATTR_MAX + 1], *a;
int len = n->nlmsg_len; int len = n->nlmsg_len;
inet_prefix daddr, saddr; inet_prefix daddr, saddr;
int family, i, atype, stype, dlen = 0, slen = 0; int i, atype, stype;
if (n->nlmsg_type != genl_family) if (n->nlmsg_type != genl_family)
return -1; return -1;
@ -116,61 +116,61 @@ static int process_msg(const struct sockaddr_nl *who, struct nlmsghdr *n,
if (f.daddr.family && f.daddr.family != AF_INET) if (f.daddr.family && f.daddr.family != AF_INET)
return 0; return 0;
a = attrs[TCP_METRICS_ATTR_ADDR_IPV4]; a = attrs[TCP_METRICS_ATTR_ADDR_IPV4];
memcpy(&daddr.data, RTA_DATA(a), 4); daddr.family = AF_INET;
daddr.bytelen = 4;
family = AF_INET;
atype = TCP_METRICS_ATTR_ADDR_IPV4; atype = TCP_METRICS_ATTR_ADDR_IPV4;
dlen = RTA_PAYLOAD(a);
} else if (attrs[TCP_METRICS_ATTR_ADDR_IPV6]) { } else if (attrs[TCP_METRICS_ATTR_ADDR_IPV6]) {
if (f.daddr.family && f.daddr.family != AF_INET6) if (f.daddr.family && f.daddr.family != AF_INET6)
return 0; return 0;
a = attrs[TCP_METRICS_ATTR_ADDR_IPV6]; a = attrs[TCP_METRICS_ATTR_ADDR_IPV6];
memcpy(&daddr.data, RTA_DATA(a), 16); daddr.family = AF_INET6;
daddr.bytelen = 16;
family = AF_INET6;
atype = TCP_METRICS_ATTR_ADDR_IPV6; atype = TCP_METRICS_ATTR_ADDR_IPV6;
dlen = RTA_PAYLOAD(a);
} else { } else {
return 0; return 0;
} }
if (get_addr_rta(&daddr, a, daddr.family))
return 0;
if (f.daddr.family && f.daddr.bitlen >= 0 &&
inet_addr_match(&daddr, &f.daddr, f.daddr.bitlen))
return 0;
if (attrs[TCP_METRICS_ATTR_SADDR_IPV4]) { if (attrs[TCP_METRICS_ATTR_SADDR_IPV4]) {
if (f.saddr.family && f.saddr.family != AF_INET) if (f.saddr.family && f.saddr.family != AF_INET)
return 0; return 0;
a = attrs[TCP_METRICS_ATTR_SADDR_IPV4]; a = attrs[TCP_METRICS_ATTR_SADDR_IPV4];
memcpy(&saddr.data, RTA_DATA(a), 4); saddr.family = AF_INET;
saddr.bytelen = 4;
stype = TCP_METRICS_ATTR_SADDR_IPV4; stype = TCP_METRICS_ATTR_SADDR_IPV4;
slen = RTA_PAYLOAD(a);
} else if (attrs[TCP_METRICS_ATTR_SADDR_IPV6]) { } else if (attrs[TCP_METRICS_ATTR_SADDR_IPV6]) {
if (f.saddr.family && f.saddr.family != AF_INET6) if (f.saddr.family && f.saddr.family != AF_INET6)
return 0; return 0;
a = attrs[TCP_METRICS_ATTR_SADDR_IPV6]; a = attrs[TCP_METRICS_ATTR_SADDR_IPV6];
memcpy(&saddr.data, RTA_DATA(a), 16); saddr.family = AF_INET6;
saddr.bytelen = 16;
stype = TCP_METRICS_ATTR_SADDR_IPV6; stype = TCP_METRICS_ATTR_SADDR_IPV6;
slen = RTA_PAYLOAD(a); } else {
saddr.family = AF_UNSPEC;
stype = 0;
} }
if (f.daddr.family && f.daddr.bitlen >= 0 && /* Only get/check for the source-address if the kernel supports it. */
inet_addr_match(&daddr, &f.daddr, f.daddr.bitlen)) if (saddr.family) {
return 0; if (get_addr_rta(&saddr, a, saddr.family))
/* Only check for the source-address if the kernel supports it, return 0;
* meaning slen != 0.
*/ if (f.saddr.family && f.saddr.bitlen >= 0 &&
if (slen && f.saddr.family && f.saddr.bitlen >= 0 && inet_addr_match(&saddr, &f.saddr, f.saddr.bitlen))
inet_addr_match(&saddr, &f.saddr, f.saddr.bitlen)) return 0;
return 0; }
if (f.flushb) { if (f.flushb) {
struct nlmsghdr *fn; struct nlmsghdr *fn;
TCPM_REQUEST(req2, 128, TCP_METRICS_CMD_DEL, NLM_F_REQUEST); TCPM_REQUEST(req2, 128, TCP_METRICS_CMD_DEL, NLM_F_REQUEST);
addattr_l(&req2.n, sizeof(req2), atype, &daddr.data, addattr_l(&req2.n, sizeof(req2), atype, daddr.data,
daddr.bytelen); daddr.bytelen);
if (slen) if (saddr.family)
addattr_l(&req2.n, sizeof(req2), stype, &saddr.data, addattr_l(&req2.n, sizeof(req2), stype, saddr.data,
saddr.bytelen); saddr.bytelen);
if (NLMSG_ALIGN(f.flushp) + req2.n.nlmsg_len > f.flushe) { if (NLMSG_ALIGN(f.flushp) + req2.n.nlmsg_len > f.flushe) {
@ -190,7 +190,7 @@ static int process_msg(const struct sockaddr_nl *who, struct nlmsghdr *n,
fprintf(fp, "Deleted "); fprintf(fp, "Deleted ");
fprintf(fp, "%s", fprintf(fp, "%s",
format_host(family, dlen, &daddr.data)); format_host(daddr.family, daddr.bytelen, daddr.data));
a = attrs[TCP_METRICS_ATTR_AGE]; a = attrs[TCP_METRICS_ATTR_AGE];
if (a) { if (a) {
@ -292,9 +292,9 @@ static int process_msg(const struct sockaddr_nl *who, struct nlmsghdr *n,
fprintf(fp, " fo_cookie %s", cookie); fprintf(fp, " fo_cookie %s", cookie);
} }
if (slen) { if (saddr.family) {
fprintf(fp, " source %s", fprintf(fp, " source %s",
format_host(family, slen, &saddr.data)); format_host(saddr.family, saddr.bytelen, saddr.data));
} }
fprintf(fp, "\n"); fprintf(fp, "\n");

View File

@ -280,6 +280,33 @@ void tnl_print_encap(struct rtattr *tb[],
} }
} }
void tnl_print_endpoint(const char *name, const struct rtattr *rta, int family)
{
const char *value;
inet_prefix dst;
if (!rta) {
value = "any";
} else if (get_addr_rta(&dst, rta, family)) {
value = "unknown";
} else if (dst.flags & ADDRTYPE_UNSPEC) {
value = "any";
} else {
value = format_host(family, dst.bytelen, dst.data);
if (!value)
value = "unknown";
}
if (is_json_context()) {
print_string(PRINT_JSON, name, NULL, value);
} else {
SPRINT_BUF(b1);
snprintf(b1, sizeof(b1), "%s %%s ", name);
print_string(PRINT_FP, NULL, b1, value);
}
}
/* tnl_print_stats - print tunnel statistics /* tnl_print_stats - print tunnel statistics
* *
* @buf - tunnel interface's line in /proc/net/dev, * @buf - tunnel interface's line in /proc/net/dev,

View File

@ -37,6 +37,8 @@ __be32 tnl_parse_key(const char *name, const char *key);
void tnl_print_encap(struct rtattr *tb[], void tnl_print_encap(struct rtattr *tb[],
int encap_type, int encap_flags, int encap_type, int encap_flags,
int encap_sport, int encap_dport); int encap_sport, int encap_dport);
void tnl_print_endpoint(const char *name,
const struct rtattr *rta, int family);
void tnl_print_stats(const char *buf); void tnl_print_stats(const char *buf);
#endif #endif

View File

@ -534,6 +534,28 @@ int get_addr64(__u64 *ap, const char *cp)
return 1; return 1;
} }
static void set_address_type(inet_prefix *addr)
{
switch (addr->family) {
case AF_INET:
if (!addr->data[0])
addr->flags |= ADDRTYPE_INET_UNSPEC;
else if (IN_MULTICAST(ntohl(addr->data[0])))
addr->flags |= ADDRTYPE_INET_MULTI;
else
addr->flags |= ADDRTYPE_INET;
break;
case AF_INET6:
if (IN6_IS_ADDR_UNSPECIFIED(addr->data))
addr->flags |= ADDRTYPE_INET_UNSPEC;
else if (IN6_IS_ADDR_MULTICAST(addr->data))
addr->flags |= ADDRTYPE_INET_MULTI;
else
addr->flags |= ADDRTYPE_INET;
break;
}
}
static int __get_addr_1(inet_prefix *addr, const char *name, int family) static int __get_addr_1(inet_prefix *addr, const char *name, int family)
{ {
memset(addr, 0, sizeof(*addr)); memset(addr, 0, sizeof(*addr));
@ -627,25 +649,7 @@ int get_addr_1(inet_prefix *addr, const char *name, int family)
if (ret) if (ret)
return ret; return ret;
switch (addr->family) { set_address_type(addr);
case AF_INET:
if (!addr->data[0])
addr->flags |= ADDRTYPE_INET_UNSPEC;
else if (IN_MULTICAST(ntohl(addr->data[0])))
addr->flags |= ADDRTYPE_INET_MULTI;
else
addr->flags |= ADDRTYPE_INET;
break;
case AF_INET6:
if (IN6_IS_ADDR_UNSPECIFIED(addr->data))
addr->flags |= ADDRTYPE_INET_UNSPEC;
else if (IN6_IS_ADDR_MULTICAST(addr->data))
addr->flags |= ADDRTYPE_INET_MULTI;
else
addr->flags |= ADDRTYPE_INET;
break;
}
return 0; return 0;
} }
@ -734,6 +738,46 @@ int get_addr(inet_prefix *dst, const char *arg, int family)
return 0; return 0;
} }
int get_addr_rta(inet_prefix *dst, const struct rtattr *rta, int family)
{
const int len = RTA_PAYLOAD(rta);
const void *data = RTA_DATA(rta);
switch (len) {
case 4:
dst->family = AF_INET;
dst->bytelen = 4;
memcpy(dst->data, data, 4);
break;
case 16:
dst->family = AF_INET6;
dst->bytelen = 16;
memcpy(dst->data, data, 16);
break;
case 2:
dst->family = AF_DECnet;
dst->bytelen = 2;
memcpy(dst->data, data, 2);
break;
case 10:
dst->family = AF_IPX;
dst->bytelen = 10;
memcpy(dst->data, data, 10);
break;
default:
return -1;
}
if (family != AF_UNSPEC && family != dst->family)
return -2;
dst->bitlen = -1;
dst->flags = 0;
set_address_type(dst);
return 0;
}
int get_prefix(inet_prefix *dst, char *arg, int family) int get_prefix(inet_prefix *dst, char *arg, int family)
{ {
if (family == AF_PACKET) { if (family == AF_PACKET) {
@ -864,6 +908,19 @@ int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits)
return 0; return 0;
} }
int inet_addr_match_rta(const inet_prefix *m, const struct rtattr *rta)
{
inet_prefix dst;
if (!rta || m->family == AF_UNSPEC || m->bitlen <= 0)
return 0;
if (get_addr_rta(&dst, rta, m->family))
return -1;
return inet_addr_match(&dst, m, m->bitlen);
}
int __iproute2_hz_internal; int __iproute2_hz_internal;
int __get_hz(void) int __get_hz(void)