X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=plugins%2Floopback.c;h=28a59c9c6919dbaaafd8f0fa595fc19966b659c7;hb=770ed7e6a3173290e071662a385b892756ff5072;hp=c0a8f3b93b76b8bfd07d7ad00d9bf80f70d2dd07;hpb=991fe1e5f6458aa30ee82ad73b2f0411b74b1d3e;p=platform%2Fupstream%2Fconnman.git diff --git a/plugins/loopback.c b/plugins/loopback.c old mode 100644 new mode 100755 index c0a8f3b..28a59c9 --- a/plugins/loopback.c +++ b/plugins/loopback.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2009 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 @@ -25,25 +25,162 @@ #include #include +#include #include #include +#include #include #include #include +#include + +#include +#include #define CONNMAN_API_SUBJECT_TO_CHANGE #include +#include #include +#include -static int loopback_init(void) +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 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, 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"); @@ -54,14 +191,19 @@ static int loopback_init(void) } if (ifr.ifr_flags & IFF_UP) { - err = -EALREADY; - connman_info("The loopback interface is already up"); - goto done; + connman_info("Checking loopback interface settings"); + if (valid_loopback(sk, &ifr)) { + err = -EALREADY; + goto done; + } + + connman_warn("Correcting wrong loopback settings"); } - addr = (struct sockaddr_in *) &ifr.ifr_addr; - addr->sin_family = AF_INET; - addr->sin_addr.s_addr = inet_addr("127.0.0.0"); + 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) { @@ -70,9 +212,10 @@ static int loopback_init(void) goto done; } - addr = (struct sockaddr_in *) &ifr.ifr_netmask; - addr->sin_family = AF_INET; - addr->sin_addr.s_addr = inet_addr("255.0.0.0"); + 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) { @@ -101,9 +244,83 @@ done: 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_PRIORITY_HIGH, loopback_init, loopback_exit)