Remove gateway setup into the core connection handling
authorMarcel Holtmann <marcel@holtmann.org>
Mon, 5 Jan 2009 16:50:04 +0000 (17:50 +0100)
committerMarcel Holtmann <marcel@holtmann.org>
Mon, 5 Jan 2009 16:50:04 +0000 (17:50 +0100)
plugins/ipv4.c
src/connection.c

index b611fb0..c73c729 100644 (file)
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <net/if.h>
-#include <net/route.h>
-
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
 
 #define CONNMAN_API_SUBJECT_TO_CHANGE
 #include <connman/plugin.h>
@@ -58,34 +54,6 @@ struct connman_ipv4 {
        struct in_addr broadcast;
 };
 
-struct gateway_data {
-       int index;
-       char *gateway;
-};
-
-static GSList *gateway_list = NULL;
-
-static struct gateway_data *find_gateway(int index, const char *gateway)
-{
-       GSList *list;
-
-       if (gateway == NULL)
-               return NULL;
-
-       for (list = gateway_list; list; list = list->next) {
-               struct gateway_data *data = list->data;
-
-               if (data->gateway == NULL)
-                       continue;
-
-               if (data->index == index &&
-                               g_str_equal(data->gateway, gateway) == TRUE)
-                       return data;
-       }
-
-       return NULL;
-}
-
 static int set_ipv4(struct connman_element *element,
                        struct connman_ipv4 *ipv4, const char *nameserver)
 {
@@ -184,184 +152,6 @@ static int clear_ipv4(struct connman_element *element)
        return 0;
 }
 
-static int set_route(struct connman_element *element, const char *gateway)
-{
-       struct ifreq ifr;
-       struct rtentry rt;
-       struct sockaddr_in *addr;
-       int sk, err;
-
-       DBG("element %p", element);
-
-       sk = socket(PF_INET, SOCK_DGRAM, 0);
-       if (sk < 0)
-               return -1;
-
-       memset(&ifr, 0, sizeof(ifr));
-       ifr.ifr_ifindex = element->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 | RTF_GATEWAY;
-
-       addr = (struct sockaddr_in *) &rt.rt_dst;
-       addr->sin_family = AF_INET;
-       addr->sin_addr.s_addr = INADDR_ANY;
-
-       addr = (struct sockaddr_in *) &rt.rt_gateway;
-       addr->sin_family = AF_INET;
-       addr->sin_addr.s_addr = inet_addr(gateway);
-
-       addr = (struct sockaddr_in *) &rt.rt_genmask;
-       addr->sin_family = AF_INET;
-       addr->sin_addr.s_addr = INADDR_ANY;
-
-       err = ioctl(sk, SIOCADDRT, &rt);
-       if (err < 0)
-               DBG("default route setting failed (%s)", strerror(errno));
-
-       close(sk);
-
-       return err;
-}
-
-static int del_route(struct connman_element *element, const char *gateway)
-{
-       struct ifreq ifr;
-       struct rtentry rt;
-       struct sockaddr_in *addr;
-       int sk, err;
-
-       DBG("element %p", element);
-
-       sk = socket(PF_INET, SOCK_DGRAM, 0);
-       if (sk < 0)
-               return -1;
-
-       memset(&ifr, 0, sizeof(ifr));
-       ifr.ifr_ifindex = element->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 | RTF_GATEWAY;
-
-       addr = (struct sockaddr_in *) &rt.rt_dst;
-       addr->sin_family = AF_INET;
-       addr->sin_addr.s_addr = INADDR_ANY;
-
-       addr = (struct sockaddr_in *) &rt.rt_gateway;
-       addr->sin_family = AF_INET;
-       addr->sin_addr.s_addr = inet_addr(gateway);
-
-       addr = (struct sockaddr_in *) &rt.rt_genmask;
-       addr->sin_family = AF_INET;
-       addr->sin_addr.s_addr = INADDR_ANY;
-
-       err = ioctl(sk, SIOCDELRT, &rt);
-       if (err < 0)
-               DBG("default route removal failed (%s)", strerror(errno));
-
-       close(sk);
-
-       return err;
-}
-
-static int conn_probe(struct connman_element *element)
-{
-       const char *gateway = NULL;
-
-       DBG("element %p name %s", element, element->name);
-
-       if (element->parent == NULL)
-               return -ENODEV;
-
-       if (element->parent->type != CONNMAN_ELEMENT_TYPE_IPV4)
-               return -ENODEV;
-
-       connman_element_get_value(element,
-                               CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway);
-
-       DBG("gateway %s", gateway);
-
-       if (gateway == NULL)
-               return 0;
-
-       if (g_slist_length(gateway_list) > 0) {
-               DBG("default already present");
-               return 0;
-       }
-
-       set_route(element, gateway);
-
-       connman_element_set_enabled(element, TRUE);
-
-       return 0;
-}
-
-static void conn_remove(struct connman_element *element)
-{
-       DBG("element %p name %s", element, element->name);
-}
-
-static int conn_enable(struct connman_element *element)
-{
-       const char *gateway = NULL;
-
-       DBG("element %p name %s", element, element->name);
-
-       connman_element_get_value(element,
-                               CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway);
-
-       DBG("gateway %s", gateway);
-
-       if (gateway == NULL)
-               return -EINVAL;
-
-       set_route(element, gateway);
-
-       return 0;
-}
-
-static int conn_disable(struct connman_element *element)
-{
-       const char *gateway = NULL;
-
-       DBG("element %p name %s", element, element->name);
-
-       connman_element_get_value(element,
-                               CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway);
-
-       DBG("gateway %s", gateway);
-
-       if (gateway == NULL)
-               return -EINVAL;
-
-       del_route(element, gateway);
-
-       return 0;
-}
-
-static struct connman_driver conn_driver = {
-       .name           = "ipv4-connection",
-       .type           = CONNMAN_ELEMENT_TYPE_CONNECTION,
-       .probe          = conn_probe,
-       .remove         = conn_remove,
-       .enable         = conn_enable,
-       .disable        = conn_disable,
-};
-
 static int ipv4_probe(struct connman_element *element)
 {
        struct connman_element *connection;
@@ -415,100 +205,20 @@ static void ipv4_remove(struct connman_element *element)
 }
 
 static struct connman_driver ipv4_driver = {
-       .name           = "ipv4-address",
+       .name           = "ipv4",
        .type           = CONNMAN_ELEMENT_TYPE_IPV4,
        .probe          = ipv4_probe,
        .remove         = ipv4_remove,
 };
 
-static void ipv4_newgateway(int index, const char *gateway)
-{
-       struct gateway_data *data;
-
-       DBG("index %d gateway %s", index, gateway);
-
-       data = find_gateway(index, gateway);
-       if (data != NULL)
-               return;
-
-       data = g_try_new0(struct gateway_data, 1);
-       if (data == NULL)
-               return;
-
-       data->index = index;
-       data->gateway = g_strdup(gateway);
-
-       gateway_list = g_slist_append(gateway_list, data);
-}
-
-static void ipv4_delgateway(int index, const char *gateway)
-{
-       struct gateway_data *data;
-
-       DBG("index %d gateway %s", index, gateway);
-
-       data = find_gateway(index, gateway);
-       if (data == NULL)
-               return;
-
-       gateway_list = g_slist_remove(gateway_list, data);
-
-       g_free(data->gateway);
-       g_free(data);
-}
-
-static struct connman_rtnl ipv4_rtnl = {
-       .name           = "ipv4-rtnl",
-       .newgateway     = ipv4_newgateway,
-       .delgateway     = ipv4_delgateway,
-};
-
 static int ipv4_init(void)
 {
-       int err;
-
-       err = connman_rtnl_register(&ipv4_rtnl);
-       if (err < 0)
-               return err;
-
-       connman_rtnl_send_getroute();
-
-       err = connman_driver_register(&conn_driver);
-       if (err < 0) {
-               connman_rtnl_unregister(&ipv4_rtnl);
-               return err;
-       }
-
-       err = connman_driver_register(&ipv4_driver);
-       if (err < 0) {
-               connman_driver_unregister(&conn_driver);
-               connman_rtnl_unregister(&ipv4_rtnl);
-       }
-
-       return err;
+       return connman_driver_register(&ipv4_driver);
 }
 
 static void ipv4_exit(void)
 {
-       GSList *list;
-
-       connman_driver_unregister(&conn_driver);
        connman_driver_unregister(&ipv4_driver);
-
-       connman_rtnl_unregister(&ipv4_rtnl);
-
-       for (list = gateway_list; list; list = list->next) {
-               struct gateway_data *data = list->data;
-
-               DBG("index %d gateway %s", data->index, data->gateway);
-
-               g_free(data->gateway);
-               g_free(data);
-               list->data = NULL;
-       }
-
-       g_slist_free(gateway_list);
-       gateway_list = NULL;
 }
 
 CONNMAN_PLUGIN_DEFINE(ipv4, "IPv4 configuration plugin", VERSION,
index 6c7e03b..9cd0f64 100644 (file)
 #include <config.h>
 #endif
 
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <net/route.h>
+
 #include <gdbus.h>
 
 #include "connman.h"
 
+struct gateway_data {
+       int index;
+       char *gateway;
+};
+
+static GSList *gateway_list = NULL;
+
+static struct gateway_data *find_gateway(int index, const char *gateway)
+{
+       GSList *list;
+
+       if (gateway == NULL)
+               return NULL;
+
+       for (list = gateway_list; list; list = list->next) {
+               struct gateway_data *data = list->data;
+
+               if (data->gateway == NULL)
+                       continue;
+
+               if (data->index == index &&
+                               g_str_equal(data->gateway, gateway) == TRUE)
+                       return data;
+       }
+
+       return NULL;
+}
+
+static void connection_newgateway(int index, const char *gateway)
+{
+       struct gateway_data *data;
+
+       DBG("index %d gateway %s", index, gateway);
+
+       data = find_gateway(index, gateway);
+       if (data != NULL)
+               return;
+
+       data = g_try_new0(struct gateway_data, 1);
+       if (data == NULL)
+               return;
+
+       data->index = index;
+       data->gateway = g_strdup(gateway);
+
+       gateway_list = g_slist_append(gateway_list, data);
+}
+
+static void connection_delgateway(int index, const char *gateway)
+{
+       struct gateway_data *data;
+
+       DBG("index %d gateway %s", index, gateway);
+
+       data = find_gateway(index, gateway);
+       if (data == NULL)
+               return;
+
+       gateway_list = g_slist_remove(gateway_list, data);
+
+       g_free(data->gateway);
+       g_free(data);
+}
+
+static struct connman_rtnl connection_rtnl = {
+       .name           = "connection",
+       .newgateway     = connection_newgateway,
+       .delgateway     = connection_delgateway,
+};
+
+static int set_route(struct connman_element *element, const char *gateway)
+{
+       struct ifreq ifr;
+       struct rtentry rt;
+       struct sockaddr_in *addr;
+       int sk, err;
+
+       DBG("element %p", element);
+
+       sk = socket(PF_INET, SOCK_DGRAM, 0);
+       if (sk < 0)
+               return -1;
+
+       memset(&ifr, 0, sizeof(ifr));
+       ifr.ifr_ifindex = element->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 | RTF_GATEWAY;
+
+       addr = (struct sockaddr_in *) &rt.rt_dst;
+       addr->sin_family = AF_INET;
+       addr->sin_addr.s_addr = INADDR_ANY;
+
+       addr = (struct sockaddr_in *) &rt.rt_gateway;
+       addr->sin_family = AF_INET;
+       addr->sin_addr.s_addr = inet_addr(gateway);
+
+       addr = (struct sockaddr_in *) &rt.rt_genmask;
+       addr->sin_family = AF_INET;
+       addr->sin_addr.s_addr = INADDR_ANY;
+
+       err = ioctl(sk, SIOCADDRT, &rt);
+       if (err < 0)
+               DBG("default route setting failed (%s)", strerror(errno));
+
+       close(sk);
+
+       return err;
+}
+
+static int del_route(struct connman_element *element, const char *gateway)
+{
+       struct ifreq ifr;
+       struct rtentry rt;
+       struct sockaddr_in *addr;
+       int sk, err;
+
+       DBG("element %p", element);
+
+       sk = socket(PF_INET, SOCK_DGRAM, 0);
+       if (sk < 0)
+               return -1;
+
+       memset(&ifr, 0, sizeof(ifr));
+       ifr.ifr_ifindex = element->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 | RTF_GATEWAY;
+
+       addr = (struct sockaddr_in *) &rt.rt_dst;
+       addr->sin_family = AF_INET;
+       addr->sin_addr.s_addr = INADDR_ANY;
+
+       addr = (struct sockaddr_in *) &rt.rt_gateway;
+       addr->sin_family = AF_INET;
+       addr->sin_addr.s_addr = inet_addr(gateway);
+
+       addr = (struct sockaddr_in *) &rt.rt_genmask;
+       addr->sin_family = AF_INET;
+       addr->sin_addr.s_addr = INADDR_ANY;
+
+       err = ioctl(sk, SIOCDELRT, &rt);
+       if (err < 0)
+               DBG("default route removal failed (%s)", strerror(errno));
+
+       close(sk);
+
+       return err;
+}
+
 static DBusMessage *get_properties(DBusConnection *conn,
                                        DBusMessage *msg, void *data)
 {
@@ -118,16 +290,56 @@ static void unregister_interface(struct connman_element *element)
 
 static int connection_probe(struct connman_element *element)
 {
+       const char *gateway = NULL;
+
        DBG("element %p name %s", element, element->name);
 
-       return register_interface(element);
+       if (element->parent == NULL)
+               return -ENODEV;
+
+       if (element->parent->type != CONNMAN_ELEMENT_TYPE_IPV4)
+               return -ENODEV;
+
+       connman_element_get_value(element,
+                               CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway);
+
+       DBG("gateway %s", gateway);
+
+       if (register_interface(element) < 0)
+               return -ENODEV;
+
+       if (gateway == NULL)
+               return 0;
+
+       if (g_slist_length(gateway_list) > 0) {
+               DBG("default gateway already present");
+               return 0;
+       }
+
+       set_route(element, gateway);
+
+       connman_element_set_enabled(element, TRUE);
+
+       return 0;
 }
 
 static void connection_remove(struct connman_element *element)
 {
+       const char *gateway = NULL;
+
        DBG("element %p name %s", element, element->name);
 
        unregister_interface(element);
+
+       connman_element_get_value(element,
+                               CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway);
+
+       DBG("gateway %s", gateway);
+
+       if (gateway == NULL)
+               return;
+
+       del_route(element, gateway);
 }
 
 static struct connman_driver connection_driver = {
@@ -144,14 +356,36 @@ int __connman_connection_init(void)
 
        connection = connman_dbus_get_connection();
 
+       if (connman_rtnl_register(&connection_rtnl) < 0)
+               connman_error("Failed to setup RTNL gateway driver");
+
+       connman_rtnl_send_getroute();
+
        return connman_driver_register(&connection_driver);
 }
 
 void __connman_connection_cleanup(void)
 {
+       GSList *list;
+
        DBG("");
 
        connman_driver_unregister(&connection_driver);
 
+       connman_rtnl_unregister(&connection_rtnl);
+
+       for (list = gateway_list; list; list = list->next) {
+               struct gateway_data *data = list->data;
+
+               DBG("index %d gateway %s", data->index, data->gateway);
+
+               g_free(data->gateway);
+               g_free(data);
+               list->data = NULL;
+       }
+
+       g_slist_free(gateway_list);
+       gateway_list = NULL;
+
        dbus_connection_unref(connection);
 }