Skip to content

Commit

Permalink
Merge pull request #15968 from donaldsharp/parse_attr_problems
Browse files Browse the repository at this point in the history
Parse attr problems
  • Loading branch information
ton31337 committed May 11, 2024
2 parents b3600d8 + bd4fca1 commit 5f8759a
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 58 deletions.
117 changes: 112 additions & 5 deletions zebra/fpm_listener.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/if_link.h>

#include "rt_netlink.h"
#include "fpm/fpm.h"
Expand All @@ -42,6 +43,7 @@ struct glob {
int server_sock;
int sock;
bool reflect;
bool dump_hex;
};

struct glob glob_space;
Expand Down Expand Up @@ -292,6 +294,8 @@ netlink_prot_to_s(unsigned char prot)
struct netlink_nh {
struct rtattr *gateway;
int if_index;
uint16_t encap_type;
uint32_t vxlan_vni;
};

struct netlink_msg_ctx {
Expand Down Expand Up @@ -341,7 +345,7 @@ static inline void netlink_msg_ctx_set_err(struct netlink_msg_ctx *ctx,
* parse_rtattrs_
*/
static int parse_rtattrs_(struct rtattr *rta, size_t len, struct rtattr **rtas,
int num_rtas, const char **err_msg)
uint16_t num_rtas, const char **err_msg)
{
memset(rtas, 0, num_rtas * sizeof(rtas[0]));

Expand Down Expand Up @@ -387,7 +391,8 @@ static int parse_rtattrs(struct netlink_msg_ctx *ctx, struct rtattr *rta,
* netlink_msg_ctx_add_nh
*/
static int netlink_msg_ctx_add_nh(struct netlink_msg_ctx *ctx, int if_index,
struct rtattr *gateway)
struct rtattr *gateway, uint16_t encap_type,
uint32_t vxlan_vni)
{
struct netlink_nh *nh;

Expand All @@ -400,6 +405,9 @@ static int netlink_msg_ctx_add_nh(struct netlink_msg_ctx *ctx, int if_index,

nh->gateway = gateway;
nh->if_index = if_index;

nh->encap_type = encap_type;
nh->vxlan_vni = vxlan_vni;
return 1;
}

Expand All @@ -412,6 +420,7 @@ static int parse_multipath_attr(struct netlink_msg_ctx *ctx,
size_t len;
struct rtnexthop *rtnh;
struct rtattr *rtattrs[RTA_MAX + 1];
struct rtattr *tb[RTA_MAX + 1];
struct rtattr *gateway;
const char *err_msg;

Expand All @@ -420,6 +429,8 @@ static int parse_multipath_attr(struct netlink_msg_ctx *ctx,

for (; len > 0;
len -= NLMSG_ALIGN(rtnh->rtnh_len), rtnh = RTNH_NEXT(rtnh)) {
uint32_t vxlan_vni;
uint16_t encap_type;

if (!RTNH_OK(rtnh, len)) {
netlink_msg_ctx_set_err(ctx, "Malformed nh");
Expand All @@ -443,7 +454,27 @@ static int parse_multipath_attr(struct netlink_msg_ctx *ctx,
}

gateway = rtattrs[RTA_GATEWAY];
netlink_msg_ctx_add_nh(ctx, rtnh->rtnh_ifindex, gateway);
memset(tb, 0, sizeof(tb));
if (rtattrs[RTA_ENCAP]) {
parse_rtattrs_(RTA_DATA(rtattrs[RTA_ENCAP]),
rtattrs[RTA_ENCAP]->rta_len -
sizeof(struct rtattr),
tb, ARRAY_SIZE(tb), &err_msg);
}

if (rtattrs[RTA_ENCAP_TYPE])
encap_type =
*(uint16_t *)RTA_DATA(rtattrs[RTA_ENCAP_TYPE]);
else
encap_type = 0;

if (tb[0])
vxlan_vni = *(uint32_t *)RTA_DATA(tb[0]);
else
vxlan_vni = 0;

netlink_msg_ctx_add_nh(ctx, rtnh->rtnh_ifindex, gateway,
encap_type, vxlan_vni);
}

return 1;
Expand Down Expand Up @@ -485,11 +516,33 @@ static int parse_route_msg(struct netlink_msg_ctx *ctx)
gateway = rtattrs[RTA_GATEWAY];
oif = rtattrs[RTA_OIF];
if (gateway || oif) {
struct rtattr *tb[RTA_MAX + 1] = { 0 };
uint16_t encap_type = 0;
uint32_t vxlan_vni = 0;

if_index = 0;
if (oif)
if_index = *((int *)RTA_DATA(oif));

netlink_msg_ctx_add_nh(ctx, if_index, gateway);

if (rtattrs[RTA_ENCAP]) {
const char *err_msg;

parse_rtattrs_(RTA_DATA(rtattrs[RTA_ENCAP]),
rtattrs[RTA_ENCAP]->rta_len -
sizeof(struct rtattr),
tb, ARRAY_SIZE(tb), &err_msg);
}

if (rtattrs[RTA_ENCAP_TYPE])
encap_type =
*(uint16_t *)RTA_DATA(rtattrs[RTA_ENCAP_TYPE]);

if (tb[0])
vxlan_vni = *(uint32_t *)RTA_DATA(tb[0]);

netlink_msg_ctx_add_nh(ctx, if_index, gateway, encap_type,
vxlan_vni);
}

rtattr = rtattrs[RTA_MULTIPATH];
Expand Down Expand Up @@ -557,6 +610,11 @@ static int netlink_msg_ctx_snprint(struct netlink_msg_ctx *ctx, char *buf,
cur += snprintf(cur, end - cur, " via interface %d",
nh->if_index);
}

if (nh->encap_type)
cur += snprintf(cur, end - cur,
", Encap Type: %u Vxlan vni %u",
nh->encap_type, nh->vxlan_vni);
}

return cur - buf;
Expand All @@ -573,6 +631,51 @@ static void print_netlink_msg_ctx(struct netlink_msg_ctx *ctx)
printf("%s\n", buf);
}

static void fpm_listener_hexdump(const void *mem, size_t len)
{
char line[64];
const uint8_t *src = mem;
const uint8_t *end = src + len;

if (!glob->dump_hex)
return;

if (len == 0) {
printf("%016lx: (zero length / no data)\n", (long)src);
return;
}

while (src < end) {
struct fbuf fb = {
.buf = line,
.pos = line,
.len = sizeof(line),
};
const uint8_t *lineend = src + 8;
uint32_t line_bytes = 0;

printf("%016lx: ", (long)src);

while (src < lineend && src < end) {
printf("%02x ", *src++);
line_bytes++;
}
if (line_bytes < 8)
printf("%*s", (8 - line_bytes) * 3, "");

src -= line_bytes;
while (src < lineend && src < end && fb.pos < fb.buf + fb.len) {
uint8_t byte = *src++;

if (isprint(byte))
*fb.pos++ = byte;
else
*fb.pos++ = '.';
}
printf("\n");
}
}

/*
* parse_netlink_msg
*/
Expand All @@ -582,6 +685,7 @@ static void parse_netlink_msg(char *buf, size_t buf_len, fpm_msg_hdr_t *fpm)
struct nlmsghdr *hdr;
unsigned int len;

fpm_listener_hexdump(buf, buf_len);
ctx = &ctx_space;

hdr = (struct nlmsghdr *)buf;
Expand Down Expand Up @@ -667,14 +771,17 @@ int main(int argc, char **argv)

memset(glob, 0, sizeof(*glob));

while ((r = getopt(argc, argv, "rd")) != -1) {
while ((r = getopt(argc, argv, "rdv")) != -1) {
switch (r) {
case 'r':
glob->reflect = true;
break;
case 'd':
fork_daemon = true;
break;
case 'v':
glob->dump_hex = true;
break;
}
}

Expand Down
110 changes: 57 additions & 53 deletions zebra/rt_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1891,6 +1891,36 @@ static inline bool _netlink_set_tag(struct nlmsghdr *n, unsigned int maxlen,
return true;
}

/*
* The function returns true if the attribute could be added
* to the message, otherwise false is returned.
*/
static int netlink_route_nexthop_encap(bool fpm, struct nlmsghdr *n,
size_t nlen, const struct nexthop *nh)
{
struct rtattr *nest;

if (!fpm)
return true;

switch (nh->nh_encap_type) {
case NET_VXLAN:
if (!nl_attr_put16(n, nlen, RTA_ENCAP_TYPE, nh->nh_encap_type))
return false;

nest = nl_attr_nest(n, nlen, RTA_ENCAP);
if (!nest)
return false;

if (!nl_attr_put32(n, nlen, 0 /* VXLAN_VNI */, nh->nh_encap.vni))
return false;
nl_attr_nest_end(n, nest);
break;
}

return true;
}

/* This function takes a nexthop as argument and
* appends to the given netlink msg. If the nexthop
* defines a preferred source, the src parameter
Expand All @@ -1909,10 +1939,13 @@ static inline bool _netlink_set_tag(struct nlmsghdr *n, unsigned int maxlen,
* The function returns true if the nexthop could be added
* to the message, otherwise false is returned.
*/
static bool _netlink_route_build_multipath(
const struct prefix *p, const char *routedesc, int bytelen,
const struct nexthop *nexthop, struct nlmsghdr *nlmsg, size_t req_size,
struct rtmsg *rtmsg, const union g_addr **src, route_tag_t tag)
static bool _netlink_route_build_multipath(const struct prefix *p,
const char *routedesc, int bytelen,
const struct nexthop *nexthop,
struct nlmsghdr *nlmsg,
size_t req_size, struct rtmsg *rtmsg,
const union g_addr **src,
route_tag_t tag, bool fpm)
{
char label_buf[256];
struct vrf *vrf;
Expand Down Expand Up @@ -2020,6 +2053,13 @@ static bool _netlink_route_build_multipath(
if (!_netlink_set_tag(nlmsg, req_size, tag))
return false;

/*
* Add encapsulation information when installing via
* FPM.
*/
if (!netlink_route_nexthop_encap(fpm, nlmsg, req_size, nexthop))
return false;

nl_attr_rtnh_end(nlmsg, rtnh);
return true;
}
Expand Down Expand Up @@ -2054,7 +2094,7 @@ _netlink_mpls_build_multipath(const struct prefix *p, const char *routedesc,
bytelen = (family == AF_INET ? 4 : 16);
return _netlink_route_build_multipath(p, routedesc, bytelen,
nhlfe->nexthop, nlmsg, req_size,
rtmsg, src, 0);
rtmsg, src, 0, false);
}

static void _netlink_mpls_debug(int cmd, uint32_t label, const char *routedesc)
Expand Down Expand Up @@ -2149,34 +2189,6 @@ static bool nexthop_set_src(const struct nexthop *nexthop, int family,
return false;
}

/*
* The function returns true if the attribute could be added
* to the message, otherwise false is returned.
*/
static int netlink_route_nexthop_encap(struct nlmsghdr *n, size_t nlen,
struct nexthop *nh)
{
struct rtattr *nest;

switch (nh->nh_encap_type) {
case NET_VXLAN:
if (!nl_attr_put16(n, nlen, RTA_ENCAP_TYPE, nh->nh_encap_type))
return false;

nest = nl_attr_nest(n, nlen, RTA_ENCAP);
if (!nest)
return false;

if (!nl_attr_put32(n, nlen, 0 /* VXLAN_VNI */,
nh->nh_encap.vni))
return false;
nl_attr_nest_end(n, nest);
break;
}

return true;
}

/*
* Routing table change via netlink interface, using a dataplane context object
*
Expand Down Expand Up @@ -2431,12 +2443,10 @@ ssize_t netlink_route_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx
* Add encapsulation information when
* installing via FPM.
*/
if (fpm) {
if (!netlink_route_nexthop_encap(&req->n,
datalen,
nexthop))
return 0;
}
if (!netlink_route_nexthop_encap(fpm, &req->n,
datalen,
nexthop))
return 0;

nexthop_num++;
break;
Expand Down Expand Up @@ -2481,22 +2491,16 @@ ssize_t netlink_route_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx
: "multipath";
nexthop_num++;

if (!_netlink_route_build_multipath(
p, routedesc, bytelen, nexthop,
&req->n, datalen, &req->r, &src1,
tag))
if (!_netlink_route_build_multipath(p, routedesc,
bytelen,
nexthop,
&req->n,
datalen,
&req->r,
&src1, tag,
fpm))
return 0;

/*
* Add encapsulation information when installing via
* FPM.
*/
if (fpm) {
if (!netlink_route_nexthop_encap(
&req->n, datalen, nexthop))
return 0;
}

if (!setsrc && src1) {
if (p->family == AF_INET)
src.ipv4 = src1->ipv4;
Expand Down

0 comments on commit 5f8759a

Please sign in to comment.