Support for ppp default route setting
authorKalle Valo <kalle.valo@canonical.com>
Mon, 14 Jun 2010 23:17:36 +0000 (01:17 +0200)
committerSamuel Ortiz <sameo@linux.intel.com>
Tue, 15 Jun 2010 22:11:07 +0000 (00:11 +0200)
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
src/connection.c
src/inet.c
src/rtnl.c

index 1e95ac6..b5bf8a5 100644 (file)
@@ -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
 }
index 41c9585..154076b 100644 (file)
@@ -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);
 
index ec0850a..980bd48 100644 (file)
@@ -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;
+}
index edeae4c..9238dde 100644 (file)
@@ -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) {