summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKalle Valo <kalle.valo@canonical.com>2010-06-15 01:17:36 +0200
committerSamuel Ortiz <sameo@linux.intel.com>2010-06-16 00:11:07 +0200
commit11281de04f7707ebcaf4050ae6ad5d48907b956a (patch)
treee51a31af617de0640059931c85b8602fd939811f
parent460513c7edcbd14e830cb9f0dd9da3a7ee79f3db (diff)
downloadconnman-11281de04f7707ebcaf4050ae6ad5d48907b956a.tar.gz
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.
-rw-r--r--include/inet.h1
-rw-r--r--src/connection.c33
-rw-r--r--src/inet.c45
-rw-r--r--src/rtnl.c14
4 files changed, 75 insertions, 18 deletions
diff --git a/include/inet.h b/include/inet.h
index 1e95ac6e..b5bf8a5f 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 41c9585a..154076b0 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 ec0850a4..980bd481 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 edeae4ca..9238dde0 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) {