X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=plugins%2Floopback.c;h=e113887d10863cd358b406ae2be7571d71b6f760;hb=6b2381a2adabea7d8309ff158ef675ff88184305;hp=94059e05efa84c14e8594aa28ee9a452848769da;hpb=49fb5a015eb88cbbcaf89d49ac11ab2eb3d68b7e;p=platform%2Fupstream%2Fconnman.git diff --git a/plugins/loopback.c b/plugins/loopback.c index 94059e0..e113887 100644 --- a/plugins/loopback.c +++ b/plugins/loopback.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2012 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 @@ -39,106 +39,12 @@ #include #include #include +#include static in_addr_t loopback_address; static in_addr_t loopback_netmask; -#if 0 -static GIOChannel *inotify_channel = NULL; - -static int hostname_descriptor = -1; - -static gboolean inotify_event(GIOChannel *channel, - GIOCondition condition, gpointer data) -{ - unsigned char buf[129], *ptr = buf; - gsize len; - GIOError err; - - if (condition & (G_IO_HUP | G_IO_ERR)) - return FALSE; - - memset(buf, 0, sizeof(buf)); - - err = g_io_channel_read(channel, (gchar *) buf, sizeof(buf) - 1, &len); - if (err != G_IO_ERROR_NONE) { - if (err == G_IO_ERROR_AGAIN) - return TRUE; - connman_error("Reading from inotify channel failed"); - return FALSE; - } - - while (len >= sizeof(struct inotify_event)) { - struct inotify_event *evt = (struct inotify_event *) ptr; - - if (evt->wd == hostname_descriptor) { - if (evt->mask & (IN_CREATE | IN_MOVED_TO)) - connman_info("create hostname file"); - - if (evt->mask & (IN_DELETE | IN_MOVED_FROM)) - connman_info("delete hostname file"); - - if (evt->mask & (IN_MODIFY | IN_MOVE_SELF)) - connman_info("modify hostname file"); - } - - len -= sizeof(struct inotify_event) + evt->len; - ptr += sizeof(struct inotify_event) + evt->len; - } - - return TRUE; -} - -static int create_watch(void) -{ - int fd; - - fd = inotify_init(); - if (fd < 0) { - connman_error("Creation of inotify context failed"); - return -EIO; - } - - inotify_channel = g_io_channel_unix_new(fd); - if (inotify_channel == NULL) { - connman_error("Creation of inotify channel failed"); - close(fd); - return -EIO; - } - - hostname_descriptor = inotify_add_watch(fd, "/etc/hostname", - IN_MODIFY | IN_DELETE_SELF | IN_MOVE_SELF); - if (hostname_descriptor < 0) { - connman_error("Creation of hostname watch failed"); - g_io_channel_unref(inotify_channel); - inotify_channel = NULL; - close(fd); - return -EIO; - } - - g_io_add_watch(inotify_channel, G_IO_IN | G_IO_ERR | G_IO_HUP, - inotify_event, NULL); - - return 0; -} - -static void remove_watch(void) -{ - int fd; - - if (inotify_channel == NULL) - return; - - fd = g_io_channel_unix_get_fd(inotify_channel); - - if (hostname_descriptor >= 0) - inotify_rm_watch(fd, hostname_descriptor); - - g_io_channel_unref(inotify_channel); - - close(fd); -} -#endif +static char system_hostname[HOST_NAME_MAX + 1]; static void create_hostname(void) { @@ -146,21 +52,24 @@ static void create_hostname(void) if (sethostname(name, strlen(name)) < 0) connman_error("Failed to set hostname to %s", name); + + strncpy(system_hostname, name, HOST_NAME_MAX); } static int setup_hostname(void) { char name[HOST_NAME_MAX + 1]; - memset(name, 0, sizeof(name)); + memset(system_hostname, 0, sizeof(system_hostname)); - if (gethostname(name, HOST_NAME_MAX) < 0) { + if (gethostname(system_hostname, HOST_NAME_MAX) < 0) { connman_error("Failed to get current hostname"); return -EIO; } - if (strlen(name) > 0 && strcmp(name, "(none)") != 0) - connman_info("System hostname is %s", name); + if (strlen(system_hostname) > 0 && + strcmp(system_hostname, "(none)") != 0) + connman_info("System hostname is %s", system_hostname); else create_hostname(); @@ -177,34 +86,46 @@ static int setup_hostname(void) return 0; } -static gboolean valid_loopback(int sk, struct ifreq *ifr) +static bool valid_loopback(int sk, struct ifreq *ifr) { struct sockaddr_in *addr; int err; + char buf[INET_ADDRSTRLEN]; + + /* It is possible to end up in situations in which the + * loopback interface is up but has no valid address. In that + * case, we expect EADDRNOTAVAIL and should return FALSE. + */ err = ioctl(sk, SIOCGIFADDR, ifr); if (err < 0) { err = -errno; connman_error("Getting address failed (%s)", strerror(-err)); - return TRUE; + return err != -EADDRNOTAVAIL ? TRUE : FALSE; } addr = (struct sockaddr_in *) &ifr->ifr_addr; - if (addr->sin_addr.s_addr != loopback_address) - return FALSE; + if (addr->sin_addr.s_addr != loopback_address) { + connman_warn("Invalid loopback address %s", + inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf))); + return false; + } err = ioctl(sk, SIOCGIFNETMASK, ifr); if (err < 0) { err = -errno; connman_error("Getting netmask failed (%s)", strerror(-err)); - return TRUE; + return true; } addr = (struct sockaddr_in *) &ifr->ifr_netmask; - if (addr->sin_addr.s_addr != loopback_netmask) - return FALSE; + if (addr->sin_addr.s_addr != loopback_netmask) { + connman_warn("Invalid loopback netmask %s", + inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf))); + return false; + } - return TRUE; + return true; } static int setup_loopback(void) @@ -213,9 +134,9 @@ static int setup_loopback(void) struct sockaddr_in addr; int sk, err; - sk = socket(PF_INET, SOCK_DGRAM, 0); + sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (sk < 0) - return -1; + return -errno; memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, "lo"); @@ -227,17 +148,17 @@ static int setup_loopback(void) if (ifr.ifr_flags & IFF_UP) { connman_info("Checking loopback interface settings"); - if (valid_loopback(sk, &ifr) == TRUE) { + if (valid_loopback(sk, &ifr)) { err = -EALREADY; goto done; } - connman_warn("Correcting wrong lookback settings"); + connman_warn("Correcting wrong loopback settings"); } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; - addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + addr.sin_addr.s_addr = loopback_address; memcpy(&ifr.ifr_addr, &addr, sizeof(ifr.ifr_addr)); err = ioctl(sk, SIOCSIFADDR, &ifr); @@ -249,7 +170,7 @@ static int setup_loopback(void) memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; - addr.sin_addr.s_addr = inet_addr("255.0.0.0"); + addr.sin_addr.s_addr = loopback_netmask; memcpy(&ifr.ifr_netmask, &addr, sizeof(ifr.ifr_netmask)); err = ioctl(sk, SIOCSIFNETMASK, &ifr); @@ -279,14 +200,28 @@ done: return err; } +static const char *loopback_get_hostname(void) +{ + return system_hostname; +} + static int loopback_set_hostname(const char *hostname) { - int err; + const char *ptr; + int err, len; if (g_strcmp0(hostname, "") == 0) return 0; - if (sethostname(hostname, strlen(hostname)) < 0) { + len = strlen(hostname); + + if (!connman_inet_check_hostname(hostname, len)) + return -EINVAL; + + if ((ptr = strstr(hostname, "."))) + len = ptr - hostname; + + if (sethostname(hostname, len) < 0) { err = -errno; connman_error("Failed to set hostname to %s", hostname); return err; @@ -299,9 +234,14 @@ static int loopback_set_hostname(const char *hostname) static int loopback_set_domainname(const char *domainname) { - int err; + int err, len; + + len = strlen(domainname); - if (setdomainname(domainname, strlen(domainname)) < 0) { + if (!connman_inet_check_hostname(domainname, len)) + return -EINVAL; + + if (setdomainname(domainname, len) < 0) { err = -errno; connman_error("Failed to set domainname to %s", domainname); return err; @@ -314,6 +254,7 @@ static int loopback_set_domainname(const char *domainname) static struct connman_utsname_driver loopback_driver = { .name = "loopback", + .get_hostname = loopback_get_hostname, .set_hostname = loopback_set_hostname, .set_domainname = loopback_set_domainname, }; @@ -327,8 +268,6 @@ static int loopback_init(void) setup_hostname(); - //create_watch(); - connman_utsname_driver_register(&loopback_driver); return 0; @@ -337,8 +276,6 @@ static int loopback_init(void) static void loopback_exit(void) { connman_utsname_driver_unregister(&loopback_driver); - - //remove_watch(); } CONNMAN_PLUGIN_DEFINE(loopback, "Loopback device plugin", VERSION,