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
connman-11281de04f7707ebcaf4050ae6ad5d48907b956a.tar.bz2
connman-11281de04f7707ebcaf4050ae6ad5d48907b956a.zip
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) {