]> granicus.if.org Git - libnl/commitdiff
single nexthop flags bug
authorJustin Mayfield <jmayfield@cradlepoint.com>
Fri, 17 Aug 2012 01:03:48 +0000 (19:03 -0600)
committerThomas Graf <tgraf@redhat.com>
Wed, 29 Aug 2012 10:27:06 +0000 (12:27 +0200)
I ran into a bug today related to how Linux handles a route's nexthop
flags when there is just one nexthop.  Namely Linux expects the flags
to be OR'd into the rtm_flags field when there is only one nexthop and
so rtnl_route_build_msg needs to check the number of nexthops and
store the nexthops flags into this field prior to calling
nlmsg_append(...&rtmsg).

Conversely the rtnl_route_parse function needs to pull these lower
0xff bits when a single nexthop is detected.

Attached is my patch.  I don't like the slight duplication of doing
the rtnl_route_get_nnexthops check twice but it seemed to be the least
turmoil of any solution I thought of.

lib/route/route_obj.c

index 62669a9ec2fd7fe203aa14c5043bcfaf24bd86e2..7ea4fffc1318e40d8042af960906a262c3fa86ef 100644 (file)
@@ -986,6 +986,7 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result)
        }
 
        if (old_nh) {
+               rtnl_route_nh_set_flags(old_nh, rtm->rtm_flags & 0xff);
                if (route->rt_nr_nh == 0) {
                        /* If no nexthops have been provided via RTA_MULTIPATH
                         * we add it as regular nexthop to maintain backwards
@@ -1045,10 +1046,15 @@ int rtnl_route_build_msg(struct nl_msg *msg, struct rtnl_route *route)
        if (route->rt_src)
                rtmsg.rtm_src_len = nl_addr_get_prefixlen(route->rt_src);
 
-
        if (rtmsg.rtm_scope == RT_SCOPE_NOWHERE)
                rtmsg.rtm_scope = rtnl_route_guess_scope(route);
 
+       if (rtnl_route_get_nnexthops(route) == 1) {
+               struct rtnl_nexthop *nh;
+               nh = rtnl_route_nexthop_n(route, 0);
+               rtmsg.rtm_flags |= nh->rtnh_flags;
+       }
+
        if (nlmsg_append(msg, &rtmsg, sizeof(rtmsg), NLMSG_ALIGNTO) < 0)
                goto nla_put_failure;