X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=plugins%2Floopback.c;h=28a59c9c6919dbaaafd8f0fa595fc19966b659c7;hb=77c8a136d2088d75c5c1fc477604908f72460e6c;hp=255d2bf4dd959651748a471b3366d753f6de20a0;hpb=555b6e45c2746818d2c2a8816b4069c7b4a967f9;p=platform%2Fupstream%2Fconnman.git diff --git a/plugins/loopback.c b/plugins/loopback.c old mode 100644 new mode 100755 index 255d2bf..28a59c9 --- a/plugins/loopback.c +++ b/plugins/loopback.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2008 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 @@ -23,16 +23,304 @@ #include #endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define CONNMAN_API_SUBJECT_TO_CHANGE #include +#include +#include +#include + +static in_addr_t loopback_address; +static in_addr_t loopback_netmask; + +static char system_hostname[HOST_NAME_MAX + 1]; + +static void create_hostname(void) +{ + const char *name = "localhost"; + + if (sethostname(name, strlen(name)) < 0) + connman_error("Failed to set hostname to %s", name); + + strncpy(system_hostname, name, HOST_NAME_MAX); +} + +#if defined TIZEN_EXT +static void _create_hostname(void) +{ + FILE *fp = NULL; +#define WIFI_MAC "/opt/etc/.mac.info" + + memset(system_hostname, 0, sizeof(system_hostname)); + + char* rv = 0; + gchar* dev_id = "TIZEN"; + char wifi_mac[HOST_NAME_MAX + 1]; + + fp = fopen(WIFI_MAC, "r"); + if(!fp){ + connman_error("Failed to get current hostname"); + strncpy(system_hostname, dev_id, strlen(dev_id)); + return; + } + + rv = fgets(wifi_mac, HOST_NAME_MAX, fp); + if(!rv){ + connman_error("Failed to get current hostname"); + strncpy(system_hostname, dev_id, strlen(dev_id)); + fclose(fp); + return; + } + + dev_id = g_base64_encode((const guchar *)wifi_mac, strlen(wifi_mac)); + g_sprintf(system_hostname, "TIZEN-%s", dev_id); + g_free(dev_id); + fclose(fp); +} +#endif + +static int setup_hostname(void) +{ + char name[HOST_NAME_MAX + 1]; + + memset(system_hostname, 0, sizeof(system_hostname)); + + if (gethostname(system_hostname, HOST_NAME_MAX) < 0) { + connman_error("Failed to get current hostname"); + return -EIO; + } +#if defined TIZEN_EXT + if (strlen(system_hostname) > 0 && + strcmp(system_hostname, "(none)") != 0 && + strcmp(system_hostname, "localhost") != 0) + connman_info("System hostname is %s", system_hostname); + else + _create_hostname(); +#else + if (strlen(system_hostname) > 0 && + strcmp(system_hostname, "(none)") != 0) + connman_info("System hostname is %s", system_hostname); + else + create_hostname(); +#endif + + memset(name, 0, sizeof(name)); + + if (getdomainname(name, HOST_NAME_MAX) < 0) { + connman_error("Failed to get current domainname"); + return -EIO; + } + + if (strlen(name) > 0 && strcmp(name, "(none)") != 0) + connman_info("System domainname is %s", name); + + return 0; +} + +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 err != -EADDRNOTAVAIL ? TRUE : FALSE; + } + + addr = (struct sockaddr_in *) &ifr->ifr_addr; + 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; + } + + addr = (struct sockaddr_in *) &ifr->ifr_netmask; + 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; +} + +static int setup_loopback(void) +{ + struct ifreq ifr; + struct sockaddr_in addr; + int sk, err; + + sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (sk < 0) + return -errno; + + memset(&ifr, 0, sizeof(ifr)); + strcpy(ifr.ifr_name, "lo"); + + if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) { + err = -errno; + goto done; + } + + if (ifr.ifr_flags & IFF_UP) { + connman_info("Checking loopback interface settings"); + if (valid_loopback(sk, &ifr)) { + err = -EALREADY; + goto done; + } + + connman_warn("Correcting wrong loopback settings"); + } + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = loopback_address; + memcpy(&ifr.ifr_addr, &addr, sizeof(ifr.ifr_addr)); + + err = ioctl(sk, SIOCSIFADDR, &ifr); + if (err < 0) { + err = -errno; + connman_error("Setting address failed (%s)", strerror(-err)); + goto done; + } + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = loopback_netmask; + memcpy(&ifr.ifr_netmask, &addr, sizeof(ifr.ifr_netmask)); + + err = ioctl(sk, SIOCSIFNETMASK, &ifr); + if (err < 0) { + err = -errno; + connman_error("Setting netmask failed (%s)", strerror(-err)); + goto done; + } + + if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) { + err = -errno; + goto done; + } + + ifr.ifr_flags |= IFF_UP; + + if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0) { + err = -errno; + connman_error("Activating loopback interface failed (%s)", + strerror(-err)); + goto done; + } + +done: + close(sk); + + return err; +} + +static const char *loopback_get_hostname(void) +{ + return system_hostname; +} + +static int loopback_set_hostname(const char *hostname) +{ + const char *ptr; + int err, len; + + if (g_strcmp0(hostname, "") == 0) + return 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; + } + + connman_info("Setting hostname to %s", hostname); + + return 0; +} + +static int loopback_set_domainname(const char *domainname) +{ + int err, len; + + len = strlen(domainname); + + 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; + } + + connman_info("Setting domainname to %s", domainname); + + return 0; +} + +static struct connman_utsname_driver loopback_driver = { + .name = "loopback", + .get_hostname = loopback_get_hostname, + .set_hostname = loopback_set_hostname, + .set_domainname = loopback_set_domainname, +}; static int loopback_init(void) { + loopback_address = inet_addr("127.0.0.1"); + loopback_netmask = inet_addr("255.0.0.0"); + + setup_loopback(); + + setup_hostname(); + + connman_utsname_driver_register(&loopback_driver); + return 0; } static void loopback_exit(void) { + connman_utsname_driver_unregister(&loopback_driver); } -CONNMAN_PLUGIN_DEFINE("loopback", "Loopback device plugin", VERSION, - loopback_init, loopback_exit) +CONNMAN_PLUGIN_DEFINE(loopback, "Loopback device plugin", VERSION, + CONNMAN_PLUGIN_PRIORITY_HIGH, loopback_init, loopback_exit)