From d68748fc6f4e5b87f88b73519e353d4c2f21f4ba Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 5 Jan 2009 17:50:04 +0100 Subject: [PATCH] Remove gateway setup into the core connection handling --- plugins/ipv4.c | 294 +------------------------------------------------------ src/connection.c | 236 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 237 insertions(+), 293 deletions(-) diff --git a/plugins/ipv4.c b/plugins/ipv4.c index b611fb0..c73c729 100644 --- a/plugins/ipv4.c +++ b/plugins/ipv4.c @@ -30,10 +30,6 @@ #include #include #include -#include - -#include -#include #define CONNMAN_API_SUBJECT_TO_CHANGE #include @@ -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, diff --git a/src/connection.c b/src/connection.c index 6c7e03b..9cd0f64 100644 --- a/src/connection.c +++ b/src/connection.c @@ -23,10 +23,182 @@ #include #endif +#include +#include +#include +#include +#include +#include +#include + #include #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); } -- 2.7.4