X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=plugins%2Fethernet.c;h=4ef163c6e7a68f8915f034b60ea89c59ebfa172e;hb=ee789c58f87dc413529f51342b75fef525604aac;hp=0f248bca6dda2f30f24986975458e478a9c92700;hpb=d3073cdb94002354fe6e37e39557402ddfb30561;p=connman diff --git a/plugins/ethernet.c b/plugins/ethernet.c index 0f248bc..4ef163c 100644 --- a/plugins/ethernet.c +++ b/plugins/ethernet.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -23,350 +23,131 @@ #include #endif -#include -#include -#include -#include -#include -#include -#include +#include +#include -#include -#include -#include - -static GStaticMutex ethernet_mutex = G_STATIC_MUTEX_INIT; -static GSList *ethernet_list = NULL; - -static void create_element(struct connman_element *parent, - enum connman_element_type type) -{ - struct connman_element *element; +#ifndef IFF_LOWER_UP +#define IFF_LOWER_UP 0x10000 +#endif - DBG("parent %p name %s", parent, parent->name); +#include - element = connman_element_create(); +#define CONNMAN_API_SUBJECT_TO_CHANGE +#include +#include +#include +#include - element->type = type; - element->netdev.index = parent->netdev.index; - element->netdev.name = g_strdup(parent->netdev.name); +#include "inet.h" - connman_element_register(element, parent); -} +struct ethernet_data { + int index; + unsigned flags; + unsigned int watch; +}; -static void rtnl_link(struct nlmsghdr *hdr, const char *type) +static void ethernet_newlink(unsigned flags, unsigned change, void *user_data) { - GSList *list; - struct ifinfomsg *msg; - int bytes; - - msg = (struct ifinfomsg *) NLMSG_DATA(hdr); - bytes = IFLA_PAYLOAD(hdr); - - DBG("%s ifi_index %d ifi_flags 0x%04x", - type, msg->ifi_index, msg->ifi_flags); + struct connman_device *device = user_data; + struct ethernet_data *ethernet = connman_device_get_data(device); - g_static_mutex_lock(ðernet_mutex); + DBG("index %d flags %ld change %ld", ethernet->index, flags, change); - for (list = ethernet_list; list; list = list->next) { - struct connman_element *element = list->data; - - if (element->type != CONNMAN_ELEMENT_TYPE_DEVICE) - continue; - - if (element->netdev.index != msg->ifi_index) - continue; - - if ((element->netdev.flags & IFF_RUNNING) == - (msg->ifi_flags & IFF_RUNNING)) - continue; - - element->netdev.flags = msg->ifi_flags; - - if (msg->ifi_flags & IFF_RUNNING) { - DBG("carrier on"); - - create_element(element, CONNMAN_ELEMENT_TYPE_DHCP); - create_element(element, CONNMAN_ELEMENT_TYPE_ZEROCONF); + if ((ethernet->flags & IFF_UP) != (flags & IFF_UP)) { + if (flags & IFF_UP) { + DBG("power on"); + connman_device_set_powered(device, TRUE); } else { - DBG("carrier off"); - - connman_element_unregister_children(element); + DBG("power off"); + connman_device_set_powered(device, FALSE); } } - g_static_mutex_unlock(ðernet_mutex); -} - -static gboolean rtnl_event(GIOChannel *chan, GIOCondition cond, gpointer data) -{ - unsigned char buf[1024]; - void *ptr = buf; - gsize len; - GIOError err; - - if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) - return FALSE; - - memset(buf, 0, sizeof(buf)); - - err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len); - if (err) { - if (err == G_IO_ERROR_AGAIN) - return TRUE; - return FALSE; - } - - DBG("buf %p len %zd", buf, len); - - while (len > 0) { - struct nlmsghdr *hdr = ptr; - struct nlmsgerr *err; - - if (!NLMSG_OK(hdr, len)) - break; - - DBG("len %d type %d flags 0x%04x seq %d", - hdr->nlmsg_len, hdr->nlmsg_type, - hdr->nlmsg_flags, hdr->nlmsg_seq); - - switch (hdr->nlmsg_type) { - case NLMSG_ERROR: - err = NLMSG_DATA(hdr); - DBG("ERROR %d (%s)", -err->error, - strerror(-err->error)); - break; - - case RTM_NEWLINK: - rtnl_link(hdr, "NEWLINK"); - break; - - case RTM_DELLINK: - rtnl_link(hdr, "DELLINK"); - break; + if ((ethernet->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) { + if (flags & IFF_LOWER_UP) { + DBG("carrier on"); + connman_device_set_carrier(device, TRUE); + } else { + DBG("carrier off"); + connman_device_set_carrier(device, FALSE); } - - len -= hdr->nlmsg_len; - ptr += hdr->nlmsg_len; } - return TRUE; + ethernet->flags = flags; } -static GIOChannel *channel = NULL; - -static int rtnl_request(void) +static int ethernet_probe(struct connman_device *device) { - struct { - struct nlmsghdr hdr; - struct rtgenmsg msg; - } req; + struct ethernet_data *ethernet; - struct sockaddr_nl addr; - int sk; + DBG("device %p", device); - DBG(""); + ethernet = g_try_new0(struct ethernet_data, 1); + if (ethernet == NULL) + return -ENOMEM; - memset(&req, 0, sizeof(req)); - req.hdr.nlmsg_len = sizeof(req.hdr) + sizeof(req.msg); - req.hdr.nlmsg_type = RTM_GETLINK; - req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; - req.hdr.nlmsg_pid = 0; - req.hdr.nlmsg_seq = 42; - req.msg.rtgen_family = AF_INET; + connman_device_set_data(device, ethernet); - sk = g_io_channel_unix_get_fd(channel); + ethernet->index = connman_device_get_index(device); + ethernet->flags = 0; - memset(&addr, 0, sizeof(addr)); - addr.nl_family = AF_NETLINK; + ethernet->watch = connman_rtnl_add_newlink_watch(ethernet->index, + ethernet_newlink, device); - return sendto(sk, &req, sizeof(req), 0, - (struct sockaddr *) &addr, sizeof(addr)); -} + connman_rtnl_send_getlink(); -static int iface_up(struct connman_element *element) -{ - struct ifreq ifr; - int sk, err; - - DBG("element %p", element); - - sk = socket(PF_INET, SOCK_DGRAM, 0); - if (sk < 0) - return -errno; - - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_ifindex = element->netdev.index; - - if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) { - err = -errno; - goto done; - } - - if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) { - err = -errno; - goto done; - } - - if (ifr.ifr_flags & IFF_UP) { - err = -EALREADY; - goto done; - } - - ifr.ifr_flags |= IFF_UP; - - if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0) { - err = -errno; - goto done; - } - - err = 0; - -done: - close(sk); - - return err; + return 0; } -static int iface_down(struct connman_element *element) +static void ethernet_remove(struct connman_device *device) { - struct ifreq ifr; - int sk, err; + struct ethernet_data *ethernet = connman_device_get_data(device); - DBG("element %p", element); + DBG("device %p", device); - sk = socket(PF_INET, SOCK_DGRAM, 0); - if (sk < 0) - return -errno; + connman_device_set_data(device, NULL); - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_ifindex = element->netdev.index; + connman_rtnl_remove_watch(ethernet->watch); - if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) { - err = -errno; - goto done; - } - - if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) { - err = -errno; - goto done; - } - - if (!(ifr.ifr_flags & IFF_UP)) { - err = -EALREADY; - goto done; - } - - ifr.ifr_flags &= ~IFF_UP; - - if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0) - err = -errno; - else - err = 0; - -done: - close(sk); - - return err; + g_free(ethernet); } -static int ethernet_probe(struct connman_element *element) +static int ethernet_enable(struct connman_device *device) { - DBG("element %p name %s", element, element->name); - - g_static_mutex_lock(ðernet_mutex); - ethernet_list = g_slist_append(ethernet_list, element); - g_static_mutex_unlock(ðernet_mutex); + struct ethernet_data *ethernet = connman_device_get_data(device); - iface_up(element); + DBG("device %p", device); - rtnl_request(); - - return 0; + return inet_ifup(ethernet->index); } -static void ethernet_remove(struct connman_element *element) +static int ethernet_disable(struct connman_device *device) { - DBG("element %p name %s", element, element->name); + struct ethernet_data *ethernet = connman_device_get_data(device); - iface_down(element); + DBG("device %p", device); - g_static_mutex_lock(ðernet_mutex); - ethernet_list = g_slist_remove(ethernet_list, element); - g_static_mutex_unlock(ðernet_mutex); + return inet_ifdown(ethernet->index); } -static struct connman_driver ethernet_driver = { +static struct connman_device_driver ethernet_driver = { .name = "ethernet", - .type = CONNMAN_ELEMENT_TYPE_DEVICE, - .subtype = CONNMAN_ELEMENT_SUBTYPE_ETHERNET, + .type = CONNMAN_DEVICE_TYPE_ETHERNET, .probe = ethernet_probe, .remove = ethernet_remove, + .enable = ethernet_enable, + .disable = ethernet_disable, }; -static int rtnl_init(void) -{ - struct sockaddr_nl addr; - int sk, err; - - DBG(""); - - sk = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (sk < 0) - return -errno; - - memset(&addr, 0, sizeof(addr)); - addr.nl_family = AF_NETLINK; - addr.nl_groups = RTMGRP_LINK; - - if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - err = -errno; - close(sk); - return err; - } - - channel = g_io_channel_unix_new(sk); - g_io_channel_set_close_on_unref(channel, TRUE); - - g_io_add_watch(channel, G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR, - rtnl_event, NULL); - - return 0; -} - -static void rtnl_cleanup(void) -{ - DBG(""); - - g_io_channel_shutdown(channel, TRUE, NULL); - g_io_channel_unref(channel); - - channel = NULL; -} - static int ethernet_init(void) { - int err; - - err = rtnl_init(); - if (err < 0) - return err; - - err = connman_driver_register(ðernet_driver); - if (err < 0) { - rtnl_cleanup(); - return err; - } - - return 0; + return connman_device_driver_register(ðernet_driver); } static void ethernet_exit(void) { - connman_driver_unregister(ðernet_driver); - - rtnl_cleanup(); + connman_device_driver_unregister(ðernet_driver); } -CONNMAN_PLUGIN_DEFINE("ethernet", "Ethernet interface plugin", VERSION, +CONNMAN_PLUGIN_DEFINE(ethernet, "Ethernet interface plugin", VERSION, ethernet_init, ethernet_exit)