From ae34fa900b0a8410002f6f96b0bd27d807489dfa Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 13 Feb 2012 13:06:52 -0600 Subject: [PATCH] core: fix erroneous IPv6 routes by making route addition typesafe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add two helper functions, one for IPv4 and one for IPv6, to ensure that the core code benefits from compiler type checking when adding routes. Previously nm_netlink_route_add() took a void* which meant we messed up adding IPv6 routes sometimes due to confusion over what was supposed to be passed to it. Also fixes what appears to be a C&P error with add_ip6_route_to_gateway(). Reported by Tomáš Trnka --- src/nm-netlink-utils.c | 66 +++++++++++++++++++++++++++++++++++++----- src/nm-netlink-utils.h | 13 ++++++--- src/nm-system.c | 22 +++++++------- 3 files changed, 79 insertions(+), 22 deletions(-) diff --git a/src/nm-netlink-utils.c b/src/nm-netlink-utils.c index c8adc9609b..c807f77112 100644 --- a/src/nm-netlink-utils.c +++ b/src/nm-netlink-utils.c @@ -165,17 +165,25 @@ nm_netlink_route_new (int ifindex, } /** - * nm_netlink_route_add: + * _route_add: * @route: the route to add + * @family: address family, either %AF_INET or %AF_INET6 + * @dest: the route destination address, either a struct in_addr or a struct + * in6_addr depending on @family + * @dest_prefix: the CIDR prefix of @dest + * @gateway: the gateway through which to reach @dest, if any; given as a + * struct in_addr or struct in6_addr depending on @family + * @flags: flags to pass to rtnl_route_add(), eg %NLM_F_REPLACE * * Returns: zero if succeeded or the netlink error otherwise. **/ -int nm_netlink_route_add (struct rtnl_route * route, - int family, - const void * dest, /* in_addr or in6_addr */ - int dest_prefix, - const void * gateway, /* in_addr or in6_addr */ - int flags) +static int +_route_add (struct rtnl_route *route, + int family, + const void *dest, /* in_addr or in6_addr */ + int dest_prefix, + const void *gateway, /* in_addr or in6_addr */ + int flags) { struct nl_sock * sk; struct nl_addr * dest_addr, * gw_addr; @@ -239,6 +247,50 @@ int nm_netlink_route_add (struct rtnl_route * route, return err; } +/** + * nm_netlink_route4_add: + * @route: the route to add + * @dest: the route destination address in network byte order + * @dest_prefix: the CIDR prefix of @dest + * @gateway: the gateway through which to reach @dest, if any, in network byte order + * @flags: flags to pass to rtnl_route_add(), eg %NLM_F_REPLACE + * + * Adds an IPv4 route with the given parameters. + * + * Returns: zero if succeeded or the netlink error otherwise. + **/ +int +nm_netlink_route4_add (struct rtnl_route *route, + guint32 *dst, + int prefix, + guint32 *gw, + int flags) +{ + return _route_add (route, AF_INET, dst, prefix, gw, flags); +} + +/** + * nm_netlink_route6_add: + * @route: the route to add + * @dest: the route destination address + * @dest_prefix: the CIDR prefix of @dest + * @gateway: the gateway through which to reach @dest, if any + * @flags: flags to pass to rtnl_route_add(), eg %NLM_F_REPLACE + * + * Adds an IPv6 route with the given parameters. + * + * Returns: zero if succeeded or the netlink error otherwise. + **/ +int +nm_netlink_route6_add (struct rtnl_route *route, + const struct in6_addr *dst, + int prefix, + const struct in6_addr *gw, + int flags) +{ + return _route_add (route, AF_INET6, dst, prefix, gw, flags); +} + /** * nm_netlink_route_delete: * @route: the route to delete diff --git a/src/nm-netlink-utils.h b/src/nm-netlink-utils.h index cf998f3027..d751c0a91d 100644 --- a/src/nm-netlink-utils.h +++ b/src/nm-netlink-utils.h @@ -43,11 +43,16 @@ struct rtnl_route * nm_netlink_route_new (int ifindex, int mss, ...) __attribute__((__sentinel__)); -int nm_netlink_route_add (struct rtnl_route *route, - int family, - const void * dst, /* struct in_addr or struct in6_addr */ +int nm_netlink_route4_add (struct rtnl_route *route, + guint32 *dst, + int prefix, + guint32 *gw, + int flags); + +int nm_netlink_route6_add (struct rtnl_route *route, + const struct in6_addr *dst, int prefix, - const void * gw, /* struct in_addr or struct in6_addr */ + const struct in6_addr *gw, int flags); gboolean nm_netlink_route_delete (struct rtnl_route *route); diff --git a/src/nm-system.c b/src/nm-system.c index c72566791d..43f43cf494 100644 --- a/src/nm-system.c +++ b/src/nm-system.c @@ -115,7 +115,7 @@ nm_system_device_set_ip4_route (int ifindex, g_return_val_if_fail (route != NULL, NULL); /* Add the route */ - err = nm_netlink_route_add(route, AF_INET, &ip4_dest, ip4_prefix, &ip4_gateway, 0); + err = nm_netlink_route4_add (route, &ip4_dest, ip4_prefix, &ip4_gateway, 0); if (err == -NLE_OBJ_NOTFOUND && ip4_gateway) { /* Gateway might be over a bridge; try adding a route to gateway first */ struct rtnl_route *route2; @@ -123,9 +123,9 @@ nm_system_device_set_ip4_route (int ifindex, route2 = nm_netlink_route_new (ifindex, AF_INET, mss, NULL); if (route2) { /* Add route to gateway over bridge */ - err = nm_netlink_route_add(route2, AF_INET, &ip4_gateway, 32, NULL, 0); + err = nm_netlink_route4_add (route2, &ip4_gateway, 32, NULL, 0); if (!err) { - err = nm_netlink_route_add(route, AF_INET, &ip4_dest, ip4_prefix, &ip4_gateway, 0); + err = nm_netlink_route4_add (route, &ip4_dest, ip4_prefix, &ip4_gateway, 0); if (err) nm_netlink_route_delete (route2); } @@ -486,18 +486,18 @@ nm_system_set_ip6_route (int ifindex, g_return_val_if_fail (route != NULL, -1); /* Add the route */ - err = nm_netlink_route_add(route, AF_INET6, &ip6_dest, ip6_prefix, &ip6_gateway, 0); + err = nm_netlink_route6_add (route, ip6_dest, ip6_prefix, ip6_gateway, 0); if (err == -NLE_OBJ_NOTFOUND && ip6_gateway) { /* Gateway might be over a bridge; try adding a route to gateway first */ struct rtnl_route *route2; route2 = nm_netlink_route_new (ifindex, AF_INET6, mss, NULL); if (route2) { - err = nm_netlink_route_add(route, AF_INET6, &ip6_gateway, 128, NULL, 0); + err = nm_netlink_route6_add (route, ip6_gateway, 128, NULL, 0); /* Add route to gateway over bridge */ if (!err) { /* Try adding the route again */ - err = nm_netlink_route_add(route, AF_INET6, &ip6_dest, ip6_prefix, &ip6_gateway, 0); + err = nm_netlink_route6_add (route, ip6_dest, ip6_prefix, ip6_gateway, 0); if (err) nm_netlink_route_delete (route2); } @@ -825,7 +825,7 @@ add_ip4_route_to_gateway (int ifindex, guint32 gw, guint32 mss) g_return_val_if_fail (route != NULL, NULL); /* Add direct route to the gateway */ - err = nm_netlink_route_add(route, AF_INET, &gw, 32, NULL, 0); + err = nm_netlink_route4_add (route, &gw, 32, NULL, 0); if (err) { char *iface = nm_netlink_index_to_iface (ifindex); @@ -849,7 +849,7 @@ replace_default_ip4_route (int ifindex, guint32 gw, guint32 mss) struct rtnl_route *route = NULL; struct nl_sock *nlh; int err = -1; - int dst = 0; + guint32 dst = 0; g_return_val_if_fail (ifindex > 0, -ENODEV); @@ -863,7 +863,7 @@ replace_default_ip4_route (int ifindex, guint32 gw, guint32 mss) g_return_val_if_fail (route != NULL, -ENOMEM); /* Add the new default route */ - err = nm_netlink_route_add (route, AF_INET, &dst, 0, &gw, NLM_F_REPLACE); + err = nm_netlink_route4_add (route, &dst, 0, &gw, NLM_F_REPLACE); if (err == -NLE_EXIST) err = 0; @@ -1000,7 +1000,7 @@ add_ip6_route_to_gateway (int ifindex, const struct in6_addr *gw) g_return_val_if_fail (route != NULL, NULL); /* Add direct route to the gateway */ - err = nm_netlink_route_add(route, AF_INET, gw, 128, NULL, 0); + err = nm_netlink_route6_add (route, gw, 128, NULL, 0); if (err) { char *iface = nm_netlink_index_to_iface (ifindex); @@ -1035,7 +1035,7 @@ replace_default_ip6_route (int ifindex, const struct in6_addr *gw) g_return_val_if_fail (route != NULL, -ENOMEM); /* Add the new default route */ - err = nm_netlink_route_add (route, AF_INET6, NULL, 0, gw, NLM_F_REPLACE); + err = nm_netlink_route6_add (route, NULL, 0, gw, NLM_F_REPLACE); if (err == -NLE_EXIST) { /* FIXME: even though we use NLM_F_REPLACE the kernel won't replace * the route if it's the same. Should try to remove it first, then