X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Futils%2Futil.c;h=e4dbc3f778235dec9be1262c5722f37fa1de806e;hb=7d7ce644137d20f7893dd25f3c772618bfaf0504;hp=336e6bee2189c364f946b51d9e3e27018d8969ef;hpb=fd186fc26f79431c35c6114377ad8dcdf7dfac7d;p=platform%2Fcore%2Fconnectivity%2Fnet-config.git diff --git a/src/utils/util.c b/src/utils/util.c index 336e6be..e4dbc3f 100755 --- a/src/utils/util.c +++ b/src/utils/util.c @@ -17,7 +17,7 @@ * */ -#include +#include #include #include #include @@ -30,23 +30,89 @@ #include #include #include +#include #include -#include -#include -#include -#include #include +#include +#include +#include +#include #include "log.h" #include "util.h" #include "neterror.h" #include "wifi-state.h" +#include "netdbus.h" +#define DBUS_SERVICE_DBUS "org.freedesktop.DBus" +#define DBUS_INTERFACE_DBUS "org.freedesktop.DBus" #define MAC_INFO_FILEPATH tzplatform_mkpath(TZ_SYS_ETC, "/.mac.info") +#define MAC_ADDRESS_FILEPATH "/sys/class/net/wlan0/address" #define MAC_ADDRESS_MAX_LEN 18 +#define HEADED_PLUGIN_FILEPATH "/usr/lib/net-config-plugin-headed.so" +#define TELEPHONY_PLUGIN_FILEPATH "/usr/lib/net-config-plugin-telephony.so" + +typedef struct { + uint8_t family; + uint8_t bytelen; + int16_t bitlen; + uint32_t flags; + uint32_t data[8]; +} netconfig_inet_prefix_s; + +typedef struct { + int fd; + struct sockaddr_nl local; + struct sockaddr_nl peer; + uint32_t seq; + uint32_t dump; +} netconfig_rtnl_s; +netconfig_rtnl_s rth = { .fd = -1 }; static gboolean netconfig_device_picker_test = FALSE; static int mdnsd_ref_count = 0; +typedef struct { + char *conn_name; + int conn_id; +} dnssd_conn_destroy_data; + +static gboolean netconfig_plugin_headed_enabled = FALSE; +static gboolean netconfig_plugin_telephony_enabled = FALSE; +static void *handle_headed; +static void *handle_telephony; +static struct netconfig_headed_plugin_t *headed_plugin; +static struct netconfig_telephony_plugin_t *telephony_plugin; + +static bool is_feature_checked[NETCONFIG_SUPPORTED_FEATURE_MAX] = {0, }; +static bool feature_supported[NETCONFIG_SUPPORTED_FEATURE_MAX] = {0, }; + +gboolean netconfig_check_passphrase(const gchar *service, const char *passphrase) +{ + gsize length; + + if (!passphrase) + return FALSE; + + length = strlen(passphrase); + + if (g_str_has_suffix(service, "psk") == TRUE) { + if (length == 64) { + for (int i = 0; i < 64; i++) + if (!isxdigit((unsigned char)passphrase[i])) + return FALSE; + } else if (length < 8 || length > 63) + return FALSE; + } else if (g_str_has_suffix(service, "wep") == TRUE) { + if (length == 10 || length == 26) { + for (int i = 0; i < length; i++) + if (!isxdigit((unsigned char)passphrase[i])) + return FALSE; + } else if (length != 5 && length != 13) + return FALSE; + } + + return TRUE; +} GKeyFile *netconfig_keyfile_load(const char *pathname) { @@ -62,6 +128,7 @@ GKeyFile *netconfig_keyfile_load(const char *pathname) keyfile = NULL; } + DBG("loaded keyfile %s", pathname); return keyfile; } @@ -80,6 +147,7 @@ void netconfig_keyfile_save(GKeyFile *keyfile, const char *pathname) if (directory == NULL || (*directory) == '\0') { g_free(directory); + ERR("directory is NULL"); return; } @@ -87,6 +155,7 @@ void netconfig_keyfile_save(GKeyFile *keyfile, const char *pathname) if (g_mkdir_with_parents(directory, S_IRUSR | S_IWUSR | S_IXUSR) != 0) { g_free(directory); + ERR("failed to make directory"); return; } } @@ -94,11 +163,12 @@ void netconfig_keyfile_save(GKeyFile *keyfile, const char *pathname) keydata = g_key_file_to_data(keyfile, &size, &error); if (g_file_set_contents(pathname, keydata, size, &error) != TRUE) { - DBG("Unable to save %s, error %s", pathname, error->message); + ERR("Unable to save %s, error %s", pathname, error->message); g_error_free(error); } chmod(pathname, S_IRUSR | S_IWUSR); + DBG("Successfully saved keyfile %s", pathname); g_free(keydata); } @@ -186,39 +256,13 @@ static gboolean __netconfig_test_device_picker() static void __netconfig_pop_device_picker(void) { -#if defined TIZEN_WEARABLE - int ret = 0; - app_control_h control = NULL; - - ret = app_control_create(&control); - if (APP_CONTROL_ERROR_NONE != ret) { - DBG("failed to create app control"); - return ; - } - - app_control_add_extra_data(control, "viewtype", "scanlist"); - - app_control_set_app_id(control, "org.tizen.wifi"); - ret = app_control_send_launch_request(control, NULL, NULL); - if (APP_CONTROL_ERROR_NONE == ret) - DBG("Launch request sent successfully"); - - app_control_destroy(control); -#else - bundle *b = NULL; - int wifi_ug_state = 0; - - netconfig_vconf_get_int(VCONFKEY_WIFI_UG_RUN_STATE, &wifi_ug_state); - if (wifi_ug_state == VCONFKEY_WIFI_UG_RUN_STATE_ON_FOREGROUND) + if (!netconfig_plugin_headed_enabled) return; - b = bundle_create(); - - DBG("Launch Wi-Fi device picker"); - syspopup_launch("wifi-qs", b); + if (!headed_plugin) + return; - bundle_free(b); -#endif + headed_plugin->pop_device_picker(); } static gboolean __netconfig_wifi_try_device_picker(gpointer data) @@ -296,28 +340,32 @@ void netconfig_wifi_device_picker_service_stop(void) gboolean netconfig_is_wifi_direct_on(void) { -#if defined TIZEN_P2P_ENABLE + if (!netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_WIFI_DIRECT)) + return FALSE; + int wifi_direct_state = 0; netconfig_vconf_get_int(VCONFKEY_WIFI_DIRECT_STATE, &wifi_direct_state); DBG("Wi-Fi direct mode %d", wifi_direct_state); return (wifi_direct_state != 0) ? TRUE : FALSE; -#else - return FALSE; -#endif } gboolean netconfig_is_wifi_tethering_on(void) { -#if defined TIZEN_TETHERING_ENABLE - int wifi_tethering_state = 0; + if (netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_TETHERING)) { + int wifi_tethering_state = 0; + + netconfig_vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &wifi_tethering_state); + DBG("Wi-Ti tethering mode %d", wifi_tethering_state); + if ((wifi_tethering_state & VCONFKEY_MOBILE_HOTSPOT_MODE_WIFI) + || (wifi_tethering_state & VCONFKEY_MOBILE_HOTSPOT_MODE_WIFI_AP)) { + DBG("Mobile AP is on"); + return TRUE; + } + } - netconfig_vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &wifi_tethering_state); - DBG("Wi-Ti tethering mode %d", wifi_tethering_state); - if (wifi_tethering_state & VCONFKEY_MOBILE_HOTSPOT_MODE_WIFI) - return TRUE; -#endif + DBG("Mobile AP is off"); return FALSE; } @@ -346,7 +394,7 @@ gboolean netconfig_interface_up(const char *ifname) close(fd); - DBG("Successfully activated wireless interface"); + DBG("Successfully activated wireless interface %s", ifname); return TRUE; } @@ -375,7 +423,7 @@ gboolean netconfig_interface_down(const char *ifname) close(fd); - DBG("Successfully de-activated wireless interface"); + DBG("Successfully de-activated wireless interface %s", ifname); return TRUE; } @@ -427,6 +475,58 @@ int netconfig_execute_file(const char *file_path, return -EIO; } +int netconfig_execute_cmd(const char *cmd) +{ + if (cmd == NULL) + return -EIO; + + pid_t pid = 0; + int status = 0; + int rv = 0; + errno = 0; + char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, }; + gchar **args = NULL; + + DBG("command: %s", cmd); + + args = g_strsplit_set(cmd, " ", -1); + + if (!(pid = fork())) { + DBG("pid(%d), ppid (%d)", getpid(), getppid()); + + errno = 0; + if (execv(args[0], args) == -1) { + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER); + DBG("Fail to execute command (%s)", error_buf); + g_strfreev(args); + exit(1); + } + } else if (pid > 0) { + if (waitpid(pid, &status, 0) == -1) + DBG("wait pid (%u) status (%d)", pid, status); + + if (WIFEXITED(status)) { + rv = WEXITSTATUS(status); + DBG("exited, status=%d", rv); + } else if (WIFSIGNALED(status)) { + DBG("killed by signal %d", WTERMSIG(status)); + } else if (WIFSTOPPED(status)) { + DBG("stopped by signal %d", WSTOPSIG(status)); + } else if (WIFCONTINUED(status)) { + DBG("continued"); + } + + g_strfreev(args); + return rv; + } + + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER); + DBG("failed to fork(%s)", error_buf); + g_strfreev(args); + + return -EIO; +} + static void on_clat_handler() { pid_t clat_pid = 0; @@ -483,6 +583,62 @@ int netconfig_execute_clatd(const char *file_path, char *const args[]) return -EIO; } +static void no_wait_signal_handler() +{ + pid_t child_pid = 0; + int state = 0; + + child_pid = waitpid(-1, &state, WNOHANG); + + DBG("child_id(%d) state(%d)", child_pid, WEXITSTATUS(state)); +} + +int netconfig_execute_file_no_wait(const char *file_path, char *const args[]) +{ + pid_t pid = 0; + int rv = 0; + errno = 0; + register unsigned int index = 0; + + struct sigaction act; + int state = 0; + char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, }; + + act.sa_handler = no_wait_signal_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + + state = sigaction(SIGCHLD, &act, 0); + if (state != 0) { + DBG("sigaction() : %d"); + return -1; + } + + while (args[index] != NULL) { + DBG("%s", args[index]); + index++; + } + + if (!(pid = fork())) { + DBG("pid(%d), ppid (%d)", getpid(), getppid()); + DBG("Inside child, exec (%s) command", file_path); + + errno = 0; + if (execvp(file_path, args) == -1) { + ERR("Fail to execute command (%s)", + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER)); + return -1; + } + } else if (pid > 0) { + ERR("Successfully launched child process"); + return rv; + } + + DBG("failed to fork(%s)", + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER)); + return -EIO; +} + int __netconfig_get_interface_index(const char *interface_name) { struct ifreq ifr; @@ -509,6 +665,7 @@ int __netconfig_get_interface_index(const char *interface_name) close(sock); if (result < 0) { + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER); DBG("Failed to get ifr index: %s", error_buf); return -1; } @@ -625,36 +782,190 @@ int netconfig_del_route_ipv4(gchar *ip_addr, gchar *subnet, gchar *interface, gi return 1; } -int netconfig_add_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len) +static int __netconfig_rtnl_talk(netconfig_rtnl_s *rtnl, struct nlmsghdr *n, pid_t peer, + unsigned groups, struct nlmsghdr *answer) { - struct in6_rtmsg rt; - int fd = 0; - int err = 0; + struct nlmsghdr *h; + struct sockaddr_nl nladdr; + struct iovec iov = { + .iov_base = (void*)n, + .iov_len = n->nlmsg_len + }; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + int status; + unsigned seq; + char buf[16384]; char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, }; - memset(&rt, 0, sizeof(rt)); + memset(&nladdr, 0, sizeof(nladdr)); + nladdr.nl_family = AF_NETLINK; + nladdr.nl_pid = peer; + nladdr.nl_groups = groups; - rt.rtmsg_dst_len = prefix_len; + n->nlmsg_seq = seq = ++rtnl->seq; - rt.rtmsg_flags = RTF_UP | RTF_HOST; + if (answer == NULL) + n->nlmsg_flags |= NLM_F_ACK; - errno = 0; - if (inet_pton(AF_INET6, ip_addr, &rt.rtmsg_dst) < 0) { - strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER); - DBG("inet_pton failed : %s", error_buf); + status = sendmsg(rtnl->fd, &msg, 0); + if (status < 0) { + DBG("failed to send message to kernel, status: %d", status); return -1; } - if (gateway != NULL) { - rt.rtmsg_flags |= RTF_GATEWAY; - if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) { + memset(buf, 0, sizeof(buf)); + + iov.iov_base = buf; + + while (1) { + iov.iov_len = sizeof(buf); + status = recvmsg(rtnl->fd, &msg, 0); + DBG("status: %d", status); + + if (status < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER); - DBG("inet_pton failed : %s", error_buf); + DBG("netlink receive error %s (%d)", error_buf, errno); + return -1; + } + if (status == 0) { + DBG("EOF on netlink"); + return -1; + } + if (msg.msg_namelen != sizeof(nladdr)) { + DBG("sender address length == %d", msg.msg_namelen); + return -1; + } + for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { + int len = h->nlmsg_len; + int l = len - sizeof(*h); + + if (l < 0 || len > status) { + if (msg.msg_flags & MSG_TRUNC) { + DBG("truncated message"); + return -1; + } + DBG("malformed message: len=%d", len); + return -1; + } + + if (nladdr.nl_pid != peer || + h->nlmsg_pid != rtnl->local.nl_pid || + h->nlmsg_seq != seq) { + /** Don't forget to skip that message. */ + status -= NLMSG_ALIGN(len); + h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); + continue; + } + + if (h->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); + if (l < sizeof(struct nlmsgerr)) { + DBG("Error truncated message"); + } else { + if (!err->error) { + if (answer) + memcpy(answer, h, h->nlmsg_len); + return 0; + } + + errno = -err->error; + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER); + DBG("RTNETLINK answers: %s", error_buf); + } + return -1; + } + if (answer) { + memcpy(answer, h, h->nlmsg_len); + return 0; + } + + DBG("Unexpected reply"); + + status -= NLMSG_ALIGN(len); + h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); + } + if (msg.msg_flags & MSG_TRUNC) { + DBG("Message truncated"); + continue; + } + if (status) { + DBG("Remnant of size %d", status); return -1; } } +} + +static int __netconfig_get_prefix(netconfig_inet_prefix_s *dst, char *arg, int family) +{ + if (family != AF_UNSPEC && family != AF_INET6) { + DBG("Error: invalid address family."); + return -1; + } + + memset(dst, 0, sizeof(*dst)); + + if (strchr(arg, ':')) { + dst->family = AF_INET6; + if (inet_pton(AF_INET6, arg, dst->data) <= 0) { + DBG("Error: invalid ipv6 address."); + return -1; + } + dst->bytelen = 16; + dst->bitlen = 128; + } + + return 0; +} + +static int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, + int alen) +{ + int len = RTA_LENGTH(alen); + struct rtattr *rta; + + if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { + DBG("Error message exceeded bound of %d", maxlen); + return -1; + } + rta = NLMSG_TAIL(n); + rta->rta_type = type; + rta->rta_len = len; + memcpy(RTA_DATA(rta), data, alen); + n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); + + return 0; +} + +static int __netconfig_iproute_modify(int cmd, unsigned flags, char *interface, char *ip_addr) +{ + struct { + struct nlmsghdr n; + struct rtmsg r; + char buf[1024]; + } req; + + struct ifreq ifr; + int fd, idx, ret; + char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, }; - rt.rtmsg_metric = 1; + memset(&req, 0, sizeof(req)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST|flags; + req.n.nlmsg_type = cmd; + req.r.rtm_family = AF_INET6; + + if (cmd != RTM_DELROUTE) { + req.r.rtm_protocol = RTPROT_BOOT; + req.r.rtm_type = RTN_UNICAST; + } fd = socket(AF_INET6, SOCK_DGRAM, 0); if (fd < 0) { @@ -663,83 +974,153 @@ int netconfig_add_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, u return -1; } - rt.rtmsg_ifindex = 0; + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)-1); + ioctl(fd, SIOCGIFINDEX, &ifr); + idx = ifr.ifr_ifindex; + close(fd); - if (interface) { - struct ifreq ifr; - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)-1); - ioctl(fd, SIOCGIFINDEX, &ifr); - rt.rtmsg_ifindex = ifr.ifr_ifindex; + if (ifr.ifr_ifindex == 0) { + DBG("Cannot find device %s", interface); + return -1; } - if ((err = ioctl(fd, SIOCADDRT, &rt)) < 0) { - strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER); - DBG("Failed to add route: %s", error_buf); - close(fd); + netconfig_inet_prefix_s dst; + + ret = __netconfig_get_prefix(&dst, ip_addr, req.r.rtm_family); + if (ret < 0) return -1; + + req.r.rtm_dst_len = dst.bitlen; + if (dst.bytelen) { + ret = addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen); + if (ret < 0) + return -1; } - close(fd); + ret = addattr_l(&req.n, sizeof(req), RTA_OIF, &idx, sizeof(uint32_t)); + if (ret < 0) + return -1; - return 1; + if (__netconfig_rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) { + DBG("__netconfig_rtnl_talk failed"); + return -1; + } + + return 0; } -int netconfig_del_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len) +static void __netconfig_rtnl_close() { - struct in6_rtmsg rt; - int fd = 0; - int err = 0; + if (rth.fd >= 0) { + close(rth.fd); + rth.fd = -1; + } +} - memset(&rt, 0, sizeof(rt)); +static int __netconfig_rtnl_open(netconfig_rtnl_s *rth, unsigned subscriptions, + int protocol) +{ + socklen_t addr_len; + int sndbuf = 32768; + int rcvbuf = 1024 * 1024; + char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, }; - rt.rtmsg_dst_len = prefix_len; + memset(rth, 0, sizeof(*rth)); - rt.rtmsg_flags = RTF_UP | RTF_HOST; + rth->fd = socket(AF_NETLINK, SOCK_RAW, protocol); + if (rth->fd < 0) { + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER); + DBG("Failed to open netlink socket: %s", error_buf); + return -1; + } - if (inet_pton(AF_INET6, ip_addr, &rt.rtmsg_dst) < 0) { - err = -errno; - return err; + if (setsockopt(rth->fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) < 0) { + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER); + DBG("Failed to set option(SO_SNDBUF) on socket [Error: %s]", error_buf); + return -1; } - if (gateway != NULL) { - rt.rtmsg_flags |= RTF_GATEWAY; - if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) { - err = -errno; - return err; - } + if (setsockopt(rth->fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) < 0) { + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER); + DBG("Failed to set option(SO_RCVBUF) on socket [Error: %s]", error_buf); + return -1; } - rt.rtmsg_metric = 1; + memset(&rth->local, 0, sizeof(rth->local)); + rth->local.nl_family = AF_NETLINK; + rth->local.nl_groups = subscriptions; - fd = socket(AF_INET6, SOCK_DGRAM, 0); - if (fd < 0) + if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) { + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER); + DBG("Failed to bind netlink socket [Error: %s]", error_buf); return -1; + } - rt.rtmsg_ifindex = 0; + addr_len = sizeof(rth->local); + if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) { + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER); + DBG("Failed to getsockname [Error: %s]", error_buf); + return -1; + } + if (addr_len != sizeof(rth->local)) { + DBG("Wrong address length %d", addr_len); + return -1; + } + if (rth->local.nl_family != AF_NETLINK) { + DBG("Wrong address family %d", rth->local.nl_family); + return -1; + } + rth->seq = time(NULL); + + return 0; +} - if (interface) { - struct ifreq ifr; - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)-1); - ioctl(fd, SIOCGIFINDEX, &ifr); - rt.rtmsg_ifindex = ifr.ifr_ifindex; +int netconfig_add_route_ipv6(gchar *interface, gchar *gateway) +{ + int ret = __netconfig_rtnl_open(&rth, 0, NETLINK_ROUTE); + if (ret < 0) { + DBG("Failed to open rtnl socket"); + return -1; } - if ((err = ioctl(fd, SIOCDELRT, &rt)) < 0) { - DBG("Failed to del route: %d\n", err); - close(fd); + ret = __netconfig_iproute_modify(RTM_NEWROUTE, NLM_F_CREATE|NLM_F_EXCL, interface, gateway); + if (ret < 0) { + DBG("Failed to modify ipv6 route."); + __netconfig_rtnl_close(); return -1; } - close(fd); + __netconfig_rtnl_close(); + return 0; +} - return 1; +int netconfig_del_route_ipv6(gchar *interface, gchar *gateway) +{ + int ret = __netconfig_rtnl_open(&rth, 0, NETLINK_ROUTE); + if (ret < 0) { + DBG("Failed to open rtnl socket"); + return -1; + } + + ret = __netconfig_iproute_modify(RTM_DELROUTE, NLM_F_CREATE|NLM_F_EXCL, interface, gateway); + if (ret < 0) { + DBG("Failed to delete ipv6 route."); + __netconfig_rtnl_close(); + return -1; + } + + __netconfig_rtnl_close(); + return 0; } gboolean handle_launch_direct(Wifi *wifi, GDBusMethodInvocation *context) { -#if defined TIZEN_P2P_ENABLE + if (!netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_WIFI_DIRECT)) { + wifi_complete_launch_direct(wifi, context); + return TRUE; + } + int ret = 0; DBG("Launch Wi-Fi direct daemon"); @@ -751,18 +1132,15 @@ gboolean handle_launch_direct(Wifi *wifi, GDBusMethodInvocation *context) if (ret < 0) { ERR("Failed to launch Wi-Fi direct daemon"); netconfig_error_wifi_direct_failed(context); - return FALSE; + return TRUE; } wifi_complete_launch_direct(wifi, context); return TRUE; -#else - wifi_complete_launch_direct(wifi, context); - return FALSE; -#endif } -int execute_mdnsd_script(char* op) { +int execute_mdnsd_script(char* op) +{ const char *path = "/usr/bin/mdnsresponder-server.sh"; char *const args[] = { "mdnsresponder-server.sh", op, NULL }; char *const envs[] = { NULL }; @@ -770,161 +1148,223 @@ int execute_mdnsd_script(char* op) { return netconfig_execute_file(path, args, envs); } -gboolean handle_launch_mdns(Network *object, GDBusMethodInvocation *context) +static void __dnssd_conn_destroyed_cb(GDBusConnection *conn, + const gchar *Name, const gchar *path, const gchar *interface, + const gchar *sig, GVariant *param, gpointer user_data) { - DBG("Launch mdnsresponder daemon"); + gchar *name = NULL; + gchar *old = NULL; + gchar *new = NULL; + dnssd_conn_destroy_data *data = user_data; + GDBusConnection *connection = NULL; + connection = netdbus_get_connection(); + + if (param == NULL) + return; - if (mdnsd_ref_count != 0) { - ERR("Invalid access"); - netconfig_error_invalid_parameter(context); - return FALSE; + g_variant_get(param, "(sss)", &name, &old, &new); + + if (g_strcmp0(name, data->conn_name) == 0 && *new == '\0') { + DBG("Connection %s Destroyed: name %s id %d", data->conn_name, name, + data->conn_id); + mdnsd_ref_count--; + g_dbus_connection_signal_unsubscribe(connection, data->conn_id); + if (mdnsd_ref_count == 0) { + if (execute_mdnsd_script("stop") < 0) + ERR("Failed to stop mdnsresponder daemon"); + } + } + g_free(name); + g_free(old); + g_free(new); + g_free(data->conn_name); + g_free(data); + return; +} + +static void register_dnssd_conn_destroy_signal(gchar *name) +{ + dnssd_conn_destroy_data *data; + GDBusConnection *connection = NULL; + connection = netdbus_get_connection(); + + if (connection == NULL) { + ERR("Failed to get GDbus Connection"); + return; + } + + data = g_try_malloc0(sizeof(dnssd_conn_destroy_data)); + + if (data == NULL) { + ERR("Out of Memory!"); + return; } + data->conn_name = g_strdup(name); + + data->conn_id = g_dbus_connection_signal_subscribe(connection, + DBUS_SERVICE_DBUS, DBUS_INTERFACE_DBUS, + "NameOwnerChanged", NULL, name, + G_DBUS_SIGNAL_FLAGS_NONE, __dnssd_conn_destroyed_cb, + data, NULL); + return; +} + +gboolean handle_launch_mdns(Network *object, GDBusMethodInvocation *context, + gchar *name) +{ + DBG("Launch mdnsresponder daemon"); + if (execute_mdnsd_script("start") < 0) { ERR("Failed to launch mdnsresponder daemon"); netconfig_error_invalid_parameter(context); - return FALSE; + return TRUE; } + mdnsd_ref_count++; + register_dnssd_conn_destroy_signal(name); + DBG("Ref mdnsresponder daemon. ref count: %d", mdnsd_ref_count); + network_complete_launch_mdns(object, context); return TRUE; } -gboolean handle_ref_mdns(Network *object, GDBusMethodInvocation *context) +gboolean netconfig_send_notification_to_net_popup(const char * noti, const char * ssid) { - mdnsd_ref_count++; + if (!netconfig_plugin_headed_enabled) + return FALSE; - DBG("Ref mdnsresponder daemon. ref count: %d", mdnsd_ref_count); - network_complete_ref_mdns(object, context); - return TRUE; + if (!headed_plugin) + return FALSE; + + return headed_plugin->send_notification_to_net_popup(noti, ssid); } -gboolean handle_unref_mdns(Network *object, GDBusMethodInvocation *context) +int netconfig_send_message_to_net_popup(const char *title, + const char *content, const char *type, const char *ssid) { - DBG("Unef mdnsresponder daemon"); + if (!netconfig_plugin_headed_enabled) + return 0; - if (mdnsd_ref_count <= 0) { - ERR("Invalid access"); - netconfig_error_invalid_parameter(context); - return FALSE; - } + if (!headed_plugin) + return 0; - mdnsd_ref_count--; + return headed_plugin->send_message_to_net_popup(title, content, type, ssid); +} - DBG("Unref mdnsresponder daemon. ref count: %d", mdnsd_ref_count); - if (mdnsd_ref_count == 0) { - if (execute_mdnsd_script("stop") < 0) { - ERR("Failed to stop mdnsresponder daemon"); - netconfig_error_invalid_parameter(context); - return FALSE; - } - } +int netconfig_send_restriction_to_net_popup(const char *title, + const char *type, const char *restriction) +{ + if (!netconfig_plugin_headed_enabled) + return 0; - network_complete_unref_mdns(object, context); - return TRUE; + if (!headed_plugin) + return 0; + + return headed_plugin->send_restriction_to_net_popup(title, type, restriction); } -gboolean netconfig_send_notification_to_net_popup(const char * noti, const char * ssid) +void netconfig_set_system_event(int sys_evt, int evt_key, int evt_val) { - int ret = 0; - bundle *b; - static gboolean is_found_noti_exists = FALSE; - static gboolean is_portal_noti_exists = FALSE; - - if (noti == NULL) { - ERR("Invalid notification"); - return FALSE; - } + if (!netconfig_plugin_headed_enabled) + return; - if (g_strcmp0(noti, NETCONFIG_DEL_FOUND_AP_NOTI) == 0) { - if (is_found_noti_exists == FALSE) - return TRUE; + if (!headed_plugin) + return; - is_found_noti_exists = FALSE; - } else if (g_strcmp0(noti, NETCONFIG_ADD_FOUND_AP_NOTI) == 0) { - if (is_found_noti_exists == TRUE) - return TRUE; + headed_plugin->set_system_event(sys_evt, evt_key, evt_val); +} - is_found_noti_exists = TRUE; - } else if (g_strcmp0(noti, NETCONFIG_ADD_PORTAL_NOTI) == 0) { - if (is_portal_noti_exists == TRUE) - return TRUE; +void __netconfig_pop_wifi_connected_poppup(const char *ssid) +{ + if (!netconfig_plugin_headed_enabled) + return; - is_portal_noti_exists = TRUE; - } else if (g_strcmp0(noti, NETCONFIG_DEL_PORTAL_NOTI) == 0) { - if (is_portal_noti_exists == FALSE) - return TRUE; + if (!headed_plugin) + return; - is_portal_noti_exists = FALSE; - } + headed_plugin->pop_wifi_connected_poppup(ssid); +} - b = bundle_create(); - bundle_add(b, "_SYSPOPUP_TYPE_", noti); +void netconfig_get_telephony_network_type(int *svctype, int *pstype) +{ + if (!netconfig_plugin_telephony_enabled) + return; - if (ssid != NULL) { - DBG("ssid (%s)", ssid); - bundle_add(b, "_AP_NAME_", ssid); - } + if (!telephony_plugin) + return; - ret = syspopup_launch("net-popup", b); + telephony_plugin->get_telephony_network_type(svctype, pstype); +} - bundle_free(b); +gboolean __netconfig_wifi_get_sim_imsi(Wifi *wifi, GDBusMethodInvocation *context) +{ + if (!netconfig_plugin_telephony_enabled) + return FALSE; - if (ret < 0) { - ERR("Unable to launch noti-popup. Err = %d", ret); + if (!telephony_plugin) return FALSE; - } - DBG("Successfully sent notification (%s)", noti); - return TRUE; + return telephony_plugin->wifi_get_sim_imsi(wifi, context); } -int netconfig_send_message_to_net_popup(const char *title, - const char *content, const char *type, const char *ssid) +netconfig_error_e __netconfig_wifi_req_aka_auth(GArray *rand_data, GArray *autn_data, + GDBusMethodInvocation *context, struct wifi_authentication_data **data) { - int ret = 0; - bundle *b = bundle_create(); + if (!netconfig_plugin_telephony_enabled) + return NETCONFIG_ERROR_INTERNAL; - bundle_add(b, "_SYSPOPUP_TITLE_", title); - bundle_add(b, "_SYSPOPUP_CONTENT_", content); - bundle_add(b, "_SYSPOPUP_TYPE_", type); - bundle_add(b, "_AP_NAME_", ssid); + if (!telephony_plugin) + return NETCONFIG_ERROR_INTERNAL; - ret = syspopup_launch("net-popup", b); + return telephony_plugin->wifi_req_aka_auth(rand_data, autn_data, context, data); +} - bundle_free(b); +gboolean __netconfig_wifi_req_sim_auth(GArray *rand_data, + GDBusMethodInvocation *context, struct wifi_authentication_data **data) +{ + if (!netconfig_plugin_telephony_enabled) + return FALSE; - return ret; + if (!telephony_plugin) + return FALSE; + + return telephony_plugin->wifi_req_sim_auth(rand_data, context, data); } -int netconfig_send_restriction_to_net_popup(const char *title, - const char *type, const char *restriction) +gboolean netconfig_tapi_check_sim_state(void) { - int ret = 0; - bundle *b = bundle_create(); + if (!netconfig_plugin_telephony_enabled) + return FALSE; - bundle_add(b, "_SYSPOPUP_TITLE_", title); - bundle_add(b, "_SYSPOPUP_CONTENT_", "security restriction"); - bundle_add(b, "_SYSPOPUP_TYPE_", type); - bundle_add(b, "_RESTRICTED_TYPE_", restriction); + if (!telephony_plugin) + return FALSE; + + return telephony_plugin->tapi_check_sim_state(); +} - ret = syspopup_launch("net-popup", b); +gboolean __netconfig_wifi_get_aka_authdata(Wifi *wifi, + GDBusMethodInvocation *context, struct wifi_authentication_data **data) +{ + if (!netconfig_plugin_telephony_enabled) + return FALSE; - bundle_free(b); + if (!telephony_plugin) + return FALSE; - return ret; + return telephony_plugin->wifi_get_aka_authdata(wifi, context, data); } -void netconfig_set_system_event(const char * sys_evt, const char * evt_key, const char * evt_val) +gboolean __netconfig_wifi_get_sim_authdata(Wifi *wifi, + GDBusMethodInvocation *context, struct wifi_authentication_data **data) { - bundle *b = NULL; + if (!netconfig_plugin_telephony_enabled) + return FALSE; - DBG("System event set [%s : %s : %s]", sys_evt, evt_key, evt_val); + if (!telephony_plugin) + return FALSE; - b = bundle_create(); - bundle_add_str(b, evt_key, evt_val); - eventsystem_send_system_event(sys_evt, b); - bundle_free(b); + return telephony_plugin->wifi_get_sim_authdata(wifi, context, data); } void netconfig_set_vconf_int(const char * key, int value) @@ -1021,7 +1461,11 @@ void netconfig_set_mac_address_from_file(void) file = fopen(MAC_INFO_FILEPATH, "r"); if (file == NULL) { ERR("Fail to open %s", MAC_INFO_FILEPATH); - return; + file = fopen(MAC_ADDRESS_FILEPATH, "r"); + if (file == NULL) { + ERR("Fail to open %s", MAC_ADDRESS_FILEPATH); + return; + } } if (fgets(mac_str, sizeof(mac_str), file) == NULL) { ERR("Fail to read mac address"); @@ -1042,3 +1486,117 @@ void netconfig_set_mac_address_from_file(void) g_free(mac_lower_str); fclose(file); } + +tizen_profile_t _get_tizen_profile() +{ + static tizen_profile_t profile = TIZEN_PROFILE_UNKNOWN; + if (__builtin_expect(profile != TIZEN_PROFILE_UNKNOWN, 1)) + return profile; + + char *profileName; + system_info_get_platform_string("http://tizen.org/feature/profile", &profileName); + switch (*profileName) { + case 'm': + case 'M': + profile = TIZEN_PROFILE_MOBILE; + break; + case 'w': + case 'W': + profile = TIZEN_PROFILE_WEARABLE; + break; + case 't': + case 'T': + profile = TIZEN_PROFILE_TV; + break; + case 'i': + case 'I': + profile = TIZEN_PROFILE_IVI; + break; + default: // common or unknown ==> ALL ARE COMMON. + profile = TIZEN_PROFILE_COMMON; + } + free(profileName); + + return profile; +} + +void netconfig_plugin_init() +{ + handle_headed = dlopen(HEADED_PLUGIN_FILEPATH, RTLD_NOW); + if (!handle_headed) { + ERR("Can't load %s: %s", HEADED_PLUGIN_FILEPATH, dlerror()); + } else { + headed_plugin = dlsym(handle_headed, "netconfig_headed_plugin"); + if (!headed_plugin) { + ERR("Can't load symbol: %s", dlerror()); + dlclose(handle_headed); + } else { + netconfig_plugin_headed_enabled = TRUE; + } + } + + handle_telephony = dlopen(TELEPHONY_PLUGIN_FILEPATH, RTLD_NOW); + if (!handle_telephony) { + ERR("Can't load %s: %s", TELEPHONY_PLUGIN_FILEPATH, dlerror()); + } else { + telephony_plugin = dlsym(handle_telephony, "netconfig_telephony_plugin"); + if (!telephony_plugin) { + ERR("Can't load symbol: %s", dlerror()); + dlclose(handle_telephony); + } else { + netconfig_plugin_telephony_enabled = TRUE; + } + } +} + +void netconfig_plugin_deinit() +{ + if (netconfig_plugin_headed_enabled) { + netconfig_plugin_headed_enabled = FALSE; + dlclose(handle_headed); + } + + if (netconfig_plugin_telephony_enabled) { + netconfig_plugin_telephony_enabled = FALSE; + dlclose(handle_telephony); + } +} + +gboolean netconfig_get_headed_plugin_flag() +{ + return netconfig_plugin_headed_enabled; +} + +gboolean netconfig_get_telephony_plugin_flag() +{ + return netconfig_plugin_telephony_enabled; +} + +bool netconfig_check_feature_supported(netconfig_supported_feature_e feature) +{ + const char *key = NULL; + + if (!is_feature_checked[feature]) { + switch (feature) { + case NETCONFIG_SUPPORTED_FEATURE_ETHERNET: + key = ETHERNET_FEATURE; + break; + case NETCONFIG_SUPPORTED_FEATURE_TETHERING: + key = TETHERING_FEATURE; + break; + case NETCONFIG_SUPPORTED_FEATURE_WIFI_DIRECT: + key = WIFI_DIRECT_FEATURE; + break; + default: + ERR("Uknown feature"); + return false; + } + + if (system_info_get_platform_bool(key, &feature_supported[feature]) < 0) { + ERR("Get feature is failed"); + return false; + } + is_feature_checked[feature] = true; + } + return feature_supported[feature]; +}