2008-04-25 Dan Williams <dcbw@redhat.com>

Patch from Benoit Boissinot <bboissin+networkmanager@gmail.com>

	* src/NetworkManagerSystem.c
		- (nm_system_device_set_ip4_route): reimplement using libnl, not ioctls



git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3598 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Dan Williams 2008-04-25 19:35:27 +00:00
parent ad96e82e8b
commit d42eed2b81
2 changed files with 64 additions and 54 deletions

View file

@ -1,3 +1,10 @@
2008-04-25 Dan Williams <dcbw@redhat.com>
Patch from Benoit Boissinot <bboissin+networkmanager@gmail.com>
* src/NetworkManagerSystem.c
- (nm_system_device_set_ip4_route): reimplement using libnl, not ioctls
2008-04-25 Dan Williams <dcbw@redhat.com>
Patch from Benoit Boissinot <bboissin+networkmanager@gmail.com>

View file

@ -68,17 +68,19 @@
*/
static gboolean
nm_system_device_set_ip4_route (const char *iface,
NMIP4Config *iface_config,
int ip4_gateway,
int ip4_dest,
int ip4_netmask,
NMIP4Config *iface_config,
guint32 ip4_gateway,
guint32 ip4_dest,
int prefix,
int mss)
{
int fd, err;
gboolean success = FALSE;
struct rtentry rtent;
struct sockaddr_in *p;
struct rtentry rtent2;
gboolean success = FALSE;
struct rtnl_route *route = NULL;
struct rtnl_route *route2 = NULL;
struct nl_handle *nlh = NULL;
struct nl_addr *gw_addr = NULL;
struct nl_addr *dest_addr = NULL;
int err, iface_idx;
/*
* Zero is not a legal gateway and the ioctl will fail. But zero is a
@ -96,87 +98,88 @@ nm_system_device_set_ip4_route (const char *iface,
(nm_ip4_config_get_address (iface_config) & nm_ip4_config_get_netmask (iface_config)))
return TRUE;
nlh = nm_netlink_get_default_handle ();
g_return_val_if_fail (nlh != NULL, FALSE);
fd = socket (AF_PACKET, SOCK_PACKET, htons (ETH_P_ALL));
if (fd < 0) {
nm_warning ("couldn't open control socket.");
return FALSE;
}
iface_idx = nm_netlink_iface_to_index (iface);
g_return_val_if_fail (iface_idx >= 0, FALSE);
memset (&rtent, 0, sizeof (struct rtentry));
p = (struct sockaddr_in *) &rtent.rt_dst;
p->sin_family = AF_INET;
p->sin_addr.s_addr = ip4_dest;
p = (struct sockaddr_in *) &rtent.rt_gateway;
p->sin_family = AF_INET;
p->sin_addr.s_addr = ip4_gateway;
p = (struct sockaddr_in *) &rtent.rt_genmask;
p->sin_family = AF_INET;
p->sin_addr.s_addr = ip4_netmask;
rtent.rt_dev = (char *)iface;
rtent.rt_metric = 1;
rtent.rt_window = 0;
rtent.rt_flags = RTF_UP | RTF_GATEWAY | (rtent.rt_window ? RTF_WINDOW : 0);
route = rtnl_route_alloc ();
g_return_val_if_fail (route != NULL, FALSE);
rtnl_route_set_scope (route, RT_SCOPE_UNIVERSE);
rtnl_route_set_oif (route, iface_idx);
gw_addr = nl_addr_build (AF_INET, &ip4_gateway, sizeof (ip4_gateway));
if (gw_addr == NULL)
goto out;
rtnl_route_set_gateway (route, gw_addr);
dest_addr = nl_addr_build (AF_INET, &ip4_dest, sizeof (ip4_dest));
if (dest_addr == NULL)
goto out;
nl_addr_set_prefixlen (dest_addr, prefix);
rtnl_route_set_dst (route, dest_addr);
nl_addr_put (dest_addr);
if (mss) {
rtent.rt_flags |= RTF_MTU;
rtent.rt_mtu = mss;
if (rtnl_route_set_metric (route, RTAX_ADVMSS, mss) < 0)
goto out;
}
err = ioctl (fd, SIOCADDRT, &rtent);
err = rtnl_route_add (nlh, route, 0);
if (err == 0) {
/* Everything good */
success = TRUE;
goto out;
}
if (errno != ENETUNREACH) {
if (err != ESRCH) {
nm_warning ("Failed to set IPv4 default route on '%s': %s",
iface,
strerror (errno));
nl_geterror ());
goto out;
}
/* Gateway might be over a bridge; try adding a route to gateway first */
memset (&rtent2, 0, sizeof(struct rtentry));
p = (struct sockaddr_in *)&rtent2.rt_dst;
p->sin_family = AF_INET;
p = (struct sockaddr_in *)&rtent2.rt_gateway;
p->sin_family = AF_INET;
p->sin_addr.s_addr = ip4_gateway;
p = (struct sockaddr_in *)&rtent2.rt_genmask;
p->sin_family = AF_INET;
p->sin_addr.s_addr = 0xffffffff;
rtent2.rt_dev = (char *)iface;
rtent2.rt_metric = 0;
rtent2.rt_flags = RTF_UP | RTF_HOST;
route2 = rtnl_route_alloc ();
if (route2 == NULL)
goto out;
rtnl_route_set_oif (route2, iface_idx);
rtnl_route_set_dst (route2, gw_addr);
if (mss) {
rtent2.rt_flags |= RTF_MTU;
rtent2.rt_mtu = mss;
if (rtnl_route_set_metric (route2, RTAX_ADVMSS, mss) < 0)
goto out;
}
/* Add route to gateway over bridge */
err = ioctl (fd, SIOCADDRT, &rtent2);
err = rtnl_route_add (nlh, route2, 0);
if (err) {
nm_warning ("Failed to add IPv4 default route on '%s': %s",
iface,
strerror (errno));
nl_geterror ());
goto out;
}
/* Try adding the route again */
err = ioctl (fd, SIOCADDRT, &rtent);
err = rtnl_route_add (nlh, route, 0);
if (!err) {
success = TRUE;
} else {
rtnl_route_del (nlh, route2, 0);
nm_warning ("Failed to set IPv4 default route on '%s': %s",
iface,
strerror (errno));
nl_geterror ());
}
out:
close (fd);
if (gw_addr)
nl_addr_put (gw_addr);
if (route2)
rtnl_route_put (route2);
if (route)
rtnl_route_put (route);
return success;
}
@ -272,7 +275,7 @@ nm_system_device_set_from_ip4_config (const char *iface,
guint32 route = nm_ip4_config_get_static_route (config, (i * 2) + 1);
guint32 saddr = nm_ip4_config_get_static_route (config, i * 2);
nm_system_device_set_ip4_route (iface, config, route, saddr, 0xffffffff, mss);
nm_system_device_set_ip4_route (iface, config, route, saddr, 32, mss);
}
if (nm_ip4_config_get_mtu (config))
@ -314,7 +317,7 @@ nm_system_vpn_device_set_from_ip4_config (NMDevice *active_device,
ad_config,
nm_ip4_config_get_gateway (ad_config),
nm_ip4_config_get_gateway (config),
0xFFFFFFFF,
32,
nm_ip4_config_get_mss (config));
}