diff options
Diffstat (limited to 'plugins/ethernet.c')
-rw-r--r-- | plugins/ethernet.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/plugins/ethernet.c b/plugins/ethernet.c index 21ca7fcb..b9089409 100644 --- a/plugins/ethernet.c +++ b/plugins/ethernet.c @@ -25,6 +25,7 @@ #include <unistd.h> #include <string.h> +#include <sys/ioctl.h> #include <sys/socket.h> #include <linux/if.h> #include <linux/netlink.h> @@ -219,6 +220,92 @@ static int rtnl_request(void) (struct sockaddr *) &addr, sizeof(addr)); } +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; +} + +static int iface_down(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; + else + err = 0; + +done: + close(sk); + + return err; +} + static int ethernet_probe(struct connman_element *element) { DBG("element %p name %s", element, element->name); @@ -227,6 +314,8 @@ static int ethernet_probe(struct connman_element *element) ethernet_list = g_slist_append(ethernet_list, element); g_static_mutex_unlock(ðernet_mutex); + iface_up(element); + rtnl_request(); return 0; @@ -236,6 +325,8 @@ static void ethernet_remove(struct connman_element *element) { DBG("element %p name %s", element, element->name); + iface_down(element); + remove_elements(element); g_static_mutex_lock(ðernet_mutex); |