From 11281de04f7707ebcaf4050ae6ad5d48907b956a Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 15 Jun 2010 01:17:36 +0200 Subject: [PATCH] Support for ppp default route setting When gateway is NULL, we need to properly set our connection and element string to 0.0.0.0 so that the interface is the default route. --- include/inet.h | 1 + src/connection.c | 33 +++++++++++++++++---------------- src/inet.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/rtnl.c | 14 ++++++++++++-- 4 files changed, 75 insertions(+), 18 deletions(-) diff --git a/include/inet.h b/include/inet.h index 1e95ac6..b5bf8a5 100644 --- a/include/inet.h +++ b/include/inet.h @@ -50,6 +50,7 @@ int connman_inet_del_host_route(int index, const char *host); int connman_inet_set_gateway_address(int index, const char *gateway); int connman_inet_clear_gateway_address(int index, const char *gateway); int connman_inet_set_gateway_interface(int index); +int connman_inet_clear_gateway_interface(int index); #ifdef __cplusplus } diff --git a/src/connection.c b/src/connection.c index 41c9585..154076b 100644 --- a/src/connection.c +++ b/src/connection.c @@ -66,18 +66,19 @@ static struct gateway_data *find_gateway(int index, const char *gateway) static int del_routes(struct gateway_data *data) { - const char *address; - if (data->vpn) { if (data->vpn_phy_index >= 0) connman_inet_del_host_route(data->vpn_phy_index, data->gateway); - address = data->vpn_ip; + return connman_inet_clear_gateway_address(data->index, + data->vpn_ip); + } else if (g_strcmp0(data->gateway, "0.0.0.0") == 0) { + return connman_inet_clear_gateway_interface(data->index); } else { connman_inet_del_host_route(data->index, data->gateway); - address = data->gateway; + return connman_inet_clear_gateway_address(data->index, + data->gateway); } - return connman_inet_clear_gateway_address(data->index, address); } static void find_element(struct connman_element *element, gpointer user_data) @@ -140,7 +141,6 @@ static void set_default_gateway(struct gateway_data *data) { struct connman_element *element = data->element; struct connman_service *service = NULL; - short int ifflags; DBG("gateway %s", data->gateway); @@ -151,13 +151,7 @@ static void set_default_gateway(struct gateway_data *data) return; } - ifflags = connman_inet_ifflags(element->index); - if (ifflags < 0) { - connman_error("Fail to get network interface flags"); - return; - } - - if (ifflags & IFF_POINTOPOINT) { + if (g_strcmp0(data->gateway, "0.0.0.0") == 0) { if (connman_inet_set_gateway_interface(element->index) < 0) return; goto done; @@ -240,6 +234,7 @@ static struct gateway_data *find_active_gateway(void) for (list = gateway_list; list; list = list->next) { struct gateway_data *data = list->data; + if (data->active == TRUE) return data; } @@ -272,15 +267,21 @@ static int connection_probe(struct connman_element *element) DBG("gateway %s", gateway); + /* + * If gateway is NULL, it's a point to point link and the default + * gateway is 0.0.0.0, meaning the interface. + */ + if (gateway == NULL) { + gateway = "0.0.0.0"; + element->ipv4.gateway = g_strdup(gateway); + } + service = __connman_element_get_service(element); __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_READY); connman_element_set_enabled(element, TRUE); - if (gateway == NULL) - return 0; - active_gateway = find_active_gateway(); new_gateway = add_gateway(element->index, gateway); diff --git a/src/inet.c b/src/inet.c index ec0850a..980bd48 100644 --- a/src/inet.c +++ b/src/inet.c @@ -899,3 +899,48 @@ int connman_inet_clear_gateway_address(int index, const char *gateway) return err; } + +int connman_inet_clear_gateway_interface(int index) +{ + struct ifreq ifr; + struct rtentry rt; + struct sockaddr_in addr; + int sk, err; + + DBG(""); + + sk = socket(PF_INET, SOCK_DGRAM, 0); + if (sk < 0) + return -1; + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_ifindex = index; + + if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) { + close(sk); + return -1; + } + + DBG("ifname %s", ifr.ifr_name); + + memset(&rt, 0, sizeof(rt)); + rt.rt_flags = RTF_UP; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + + memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask)); + memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst)); + memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway)); + + rt.rt_dev = ifr.ifr_name; + + err = ioctl(sk, SIOCDELRT, &rt); + if (err < 0) + connman_error("Removing default interface route failed (%s)", + strerror(errno)); + close(sk); + + return err; +} diff --git a/src/rtnl.c b/src/rtnl.c index edeae4c..9238dde 100644 --- a/src/rtnl.c +++ b/src/rtnl.c @@ -485,7 +485,12 @@ static void process_newroute(unsigned char family, unsigned char scope, __connman_ipconfig_newroute(index, scope, dststr, gatewaystr); - if (scope != RT_SCOPE_UNIVERSE || dst.s_addr != INADDR_ANY) + /* skip host specific routes */ + if (scope != RT_SCOPE_UNIVERSE && + !(scope == RT_SCOPE_LINK && dst.s_addr == INADDR_ANY)) + return; + + if (dst.s_addr != INADDR_ANY) return; for (list = rtnl_list; list; list = list->next) { @@ -514,7 +519,12 @@ static void process_delroute(unsigned char family, unsigned char scope, __connman_ipconfig_delroute(index, scope, dststr, gatewaystr); - if (scope != RT_SCOPE_UNIVERSE || dst.s_addr != INADDR_ANY) + /* skip host specific routes */ + if (scope != RT_SCOPE_UNIVERSE && + !(scope == RT_SCOPE_LINK && dst.s_addr == INADDR_ANY)) + return; + + if (dst.s_addr != INADDR_ANY) return; for (list = rtnl_list; list; list = list->next) { -- 2.7.4