X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gweb%2Fgresolv.c;h=954e7cfeff77cc32dd9ed7a329cd81e025b5dbec;hb=dd3cccc5e67548dcc2dd6c6254ed6c97859085d5;hp=d30e2f1684f772a247a6590f38f4dbf8301bdfd2;hpb=dcce19f15b225cc98341cd84f3d70d20b34a5406;p=platform%2Fupstream%2Fconnman.git diff --git a/gweb/gresolv.c b/gweb/gresolv.c index d30e2f1..954e7cf 100644 --- a/gweb/gresolv.c +++ b/gweb/gresolv.c @@ -2,7 +2,7 @@ * * Resolver library with GLib integration * - * Copyright (C) 2009-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2009-2013 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 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -44,7 +45,7 @@ struct sort_result { int dst_scope; int src_label; int dst_label; - gboolean reachable; + bool reachable; union { struct sockaddr sa; struct sockaddr_in sin; @@ -79,6 +80,7 @@ struct resolv_lookup { struct resolv_query { GResolv *resolv; + int nr_ns; guint timeout; uint16_t msgid; @@ -125,7 +127,7 @@ static void _debug(GResolv *resolv, const char *file, const char *caller, va_list ap; int len; - if (resolv->debug_func == NULL) + if (!resolv->debug_func) return; va_start(ap, format); @@ -154,13 +156,13 @@ static void destroy_lookup(struct resolv_lookup *lookup) debug(lookup->resolv, "lookup %p id %d ipv4 %p ipv6 %p", lookup, lookup->id, lookup->ipv4_query, lookup->ipv6_query); - if (lookup->ipv4_query != NULL) { + if (lookup->ipv4_query) { g_queue_remove(lookup->resolv->query_queue, lookup->ipv4_query); destroy_query(lookup->ipv4_query); } - if (lookup->ipv6_query != NULL) { + if (lookup->ipv6_query) { g_queue_remove(lookup->resolv->query_queue, lookup->ipv6_query); destroy_query(lookup->ipv6_query); @@ -180,17 +182,15 @@ static void find_srcaddr(struct sort_result *res) if (fd < 0) return; - if (connect(fd, &res->dst.sa, sizeof(res->dst)) < 0) { - close(fd); - return; - } + if (connect(fd, &res->dst.sa, sizeof(res->dst)) < 0) + goto out; - if (getsockname(fd, &res->src.sa, &sl) < 0) { - close(fd); - return; - } + if (getsockname(fd, &res->src.sa, &sl) < 0) + goto out; - res->reachable = TRUE; + res->reachable = true; + +out: close(fd); } @@ -279,21 +279,21 @@ static const struct gai_table gai_precedences[] = { static unsigned char v4mapped[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }; -static gboolean mask_compare(const unsigned char *one, +static bool mask_compare(const unsigned char *one, const unsigned char *two, int mask) { if (mask > 8) { if (memcmp(one, two, mask / 8)) - return FALSE; + return false; one += mask / 8; two += mask / 8; mask %= 8; } if (mask && ((*one ^ *two) >> (8 - mask))) - return FALSE; + return false; - return TRUE; + return true; } static int match_gai_table(struct sockaddr *sa, const struct gai_table *tbl) @@ -315,7 +315,8 @@ static int match_gai_table(struct sockaddr *sa, const struct gai_table *tbl) } } -#define DQUAD(_a,_b,_c,_d) ( ((_a)<<24) | ((_b)<<16) | ((_c)<<8) | (_d) ) +#define DQUAD(_a,_b,_c,_d) ( (((uint32_t)_a)<<24) | (((uint32_t)_b)<<16) | \ + (((uint32_t)_c)<<8) | ((uint32_t)_d) ) #define V4MATCH(addr, a,b,c,d, m) ( ((addr) ^ DQUAD(a,b,c,d)) >> (32 - (m)) ) #define RFC3484_SCOPE_LINK 2 @@ -326,7 +327,7 @@ static int addr_scope(struct sockaddr *sa) { if (sa->sa_family == AF_INET) { struct sockaddr_in *sin = (void *)sa; - guint32 addr = ntohl(sin->sin_addr.s_addr); + uint32_t addr = ntohl(sin->sin_addr.s_addr); if (V4MATCH(addr, 169,254,0,0, 16) || V4MATCH(addr, 127,0,0,0, 8)) @@ -471,6 +472,8 @@ static void sort_and_return_results(struct resolv_lookup *lookup) char buf[INET6_ADDRSTRLEN + 1]; GResolvResultStatus status; char **results = g_try_new0(char *, lookup->nr_results + 1); + GResolvResultFunc result_func = lookup->result_func; + void *result_data = lookup->result_data; int i, n = 0; if (!results) @@ -482,19 +485,19 @@ static void sort_and_return_results(struct resolv_lookup *lookup) for (i = 0; i < lookup->nr_results; i++) { if (lookup->results[i].dst.sa.sa_family == AF_INET) { - if (inet_ntop(AF_INET, + if (!inet_ntop(AF_INET, &lookup->results[i].dst.sin.sin_addr, - buf, sizeof(buf) - 1) == NULL) + buf, sizeof(buf) - 1)) continue; } else if (lookup->results[i].dst.sa.sa_family == AF_INET6) { - if (inet_ntop(AF_INET6, + if (!inet_ntop(AF_INET6, &lookup->results[i].dst.sin6.sin6_addr, - buf, sizeof(buf) - 1) == NULL) + buf, sizeof(buf) - 1)) continue; } else continue; - results[n++] = strdup(buf); + results[n++] = g_strdup(buf); } results[n++] = NULL; @@ -510,14 +513,14 @@ static void sort_and_return_results(struct resolv_lookup *lookup) status = lookup->ipv4_status; } - debug(lookup->resolv, "lookup %p received %d results", lookup, n); + debug(lookup->resolv, "lookup %p received %d results", lookup, n-1); g_queue_remove(lookup->resolv->lookup_queue, lookup); + destroy_lookup(lookup); - lookup->result_func(status, results, lookup->result_data); + result_func(status, results, result_data); g_strfreev(results); - destroy_lookup(lookup); } static gboolean query_timeout(gpointer user_data) @@ -537,24 +540,23 @@ static gboolean query_timeout(gpointer user_data) } g_queue_remove(resolv->query_queue, query); + destroy_query(query); - if (lookup->ipv4_query == NULL && lookup->ipv6_query == NULL) + if (!lookup->ipv4_query && !lookup->ipv6_query) sort_and_return_results(lookup); - destroy_query(query); - return FALSE; } static void free_nameserver(struct resolv_nameserver *nameserver) { - if (nameserver == NULL) + if (!nameserver) return; if (nameserver->udp_watch > 0) g_source_remove(nameserver->udp_watch); - if (nameserver->udp_channel != NULL) { + if (nameserver->udp_channel) { g_io_channel_shutdown(nameserver->udp_channel, TRUE, NULL); g_io_channel_unref(nameserver->udp_channel); } @@ -578,16 +580,17 @@ static void flush_nameservers(GResolv *resolv) static int send_query(GResolv *resolv, const unsigned char *buf, int len) { GList *list; + int nr_ns; - if (resolv->nameserver_list == NULL) + if (!resolv->nameserver_list) return -ENOENT; - for (list = g_list_first(resolv->nameserver_list); - list; list = g_list_next(list)) { + for (list = g_list_first(resolv->nameserver_list), nr_ns = 0; + list; list = g_list_next(list), nr_ns++) { struct resolv_nameserver *nameserver = list->data; int sk, sent; - if (nameserver->udp_channel == NULL) + if (!nameserver->udp_channel) continue; sk = g_io_channel_unix_get_fd(nameserver->udp_channel); @@ -597,7 +600,7 @@ static int send_query(GResolv *resolv, const unsigned char *buf, int len) continue; } - return 0; + return nr_ns; } static gint compare_lookup_id(gconstpointer a, gconstpointer b) @@ -634,7 +637,7 @@ static void add_result(struct resolv_lookup *lookup, int family, int n = lookup->nr_results++; lookup->results = g_try_realloc(lookup->results, sizeof(struct sort_result) * (n + 1)); - if (lookup->results == NULL) + if (!lookup->results) return; memset(&lookup->results[n], 0, sizeof(struct sort_result)); @@ -662,7 +665,13 @@ static void parse_response(struct resolv_nameserver *nameserver, debug(resolv, "response from %s", nameserver->address); - ns_initparse(buf, len, &msg); + if (ns_initparse(buf, len, &msg) < 0) + return; + + list = g_queue_find_custom(resolv->query_queue, + GUINT_TO_POINTER(ns_msg_id(msg)), compare_query_msgid); + if (!list) + return; rcode = ns_msg_getflag(msg, ns_f_rcode); count = ns_msg_count(msg, ns_s_an); @@ -672,7 +681,10 @@ static void parse_response(struct resolv_nameserver *nameserver, switch (rcode) { case ns_r_noerror: - status = G_RESOLV_RESULT_STATUS_SUCCESS; + if (count > 0) + status = G_RESOLV_RESULT_STATUS_SUCCESS; + else + status = G_RESOLV_RESULT_STATUS_NO_ANSWER; break; case ns_r_formerr: status = G_RESOLV_RESULT_STATUS_FORMAT_ERROR; @@ -694,24 +706,19 @@ static void parse_response(struct resolv_nameserver *nameserver, break; } - list = g_queue_find_custom(resolv->query_queue, - GUINT_TO_POINTER(ns_msg_id(msg)), compare_query_msgid); - if (!list) - return; - query = list->data; + query->nr_ns--; + lookup = query->lookup; - if (query == lookup->ipv6_query) { + if (query == lookup->ipv6_query) lookup->ipv6_status = status; - lookup->ipv6_query = NULL; - } else if (query == lookup->ipv4_query) { + else if (query == lookup->ipv4_query) lookup->ipv4_status = status; - lookup->ipv4_query = NULL; - } for (i = 0; i < count; i++) { - ns_parserr(&msg, ns_s_an, i, &rr); + if (ns_parserr(&msg, ns_s_an, i, &rr) < 0) + continue; if (ns_rr_class(rr) != ns_c_in) continue; @@ -728,12 +735,19 @@ static void parse_response(struct resolv_nameserver *nameserver, } } - g_queue_remove(resolv->query_queue, query); + if (status != G_RESOLV_RESULT_STATUS_SUCCESS && query->nr_ns > 0) + return; - if (lookup->ipv4_query == NULL && lookup->ipv6_query == NULL) - sort_and_return_results(lookup); + if (query == lookup->ipv6_query) + lookup->ipv6_query = NULL; + else + lookup->ipv4_query = NULL; + g_queue_remove(resolv->query_queue, query); destroy_query(query); + + if (!lookup->ipv4_query && !lookup->ipv6_query) + sort_and_return_results(lookup); } static gboolean received_udp_data(GIOChannel *channel, GIOCondition cond, @@ -798,8 +812,7 @@ static int connect_udp_channel(struct resolv_nameserver *nameserver) char interface[IF_NAMESIZE]; memset(interface, 0, IF_NAMESIZE); - if (if_indextoname(nameserver->resolv->index, - interface) != NULL) { + if (if_indextoname(nameserver->resolv->index, interface)) { if (setsockopt(sk, SOL_SOCKET, SO_BINDTODEVICE, interface, IF_NAMESIZE) < 0) { close(sk); @@ -818,7 +831,7 @@ static int connect_udp_channel(struct resolv_nameserver *nameserver) freeaddrinfo(rp); nameserver->udp_channel = g_io_channel_unix_new(sk); - if (nameserver->udp_channel == NULL) { + if (!nameserver->udp_channel) { close(sk); return -ENOMEM; } @@ -840,7 +853,7 @@ GResolv *g_resolv_new(int index) return NULL; resolv = g_try_new0(GResolv, 1); - if (resolv == NULL) + if (!resolv) return NULL; resolv->ref_count = 1; @@ -850,13 +863,13 @@ GResolv *g_resolv_new(int index) resolv->next_lookup_id = 1; resolv->query_queue = g_queue_new(); - if (resolv->query_queue == NULL) { + if (!resolv->query_queue) { g_free(resolv); return NULL; } resolv->lookup_queue = g_queue_new(); - if (resolv->lookup_queue == NULL) { + if (!resolv->lookup_queue) { g_queue_free(resolv->query_queue); g_free(resolv); return NULL; @@ -872,7 +885,7 @@ GResolv *g_resolv_new(int index) GResolv *g_resolv_ref(GResolv *resolv) { - if (resolv == NULL) + if (!resolv) return NULL; __sync_fetch_and_add(&resolv->ref_count, 1); @@ -885,7 +898,7 @@ void g_resolv_unref(GResolv *resolv) struct resolv_query *query; struct resolv_lookup *lookup; - if (resolv == NULL) + if (!resolv) return; if (__sync_fetch_and_sub(&resolv->ref_count, 1) != 1) @@ -914,24 +927,24 @@ void g_resolv_unref(GResolv *resolv) void g_resolv_set_debug(GResolv *resolv, GResolvDebugFunc func, gpointer user_data) { - if (resolv == NULL) + if (!resolv) return; resolv->debug_func = func; resolv->debug_data = user_data; } -gboolean g_resolv_add_nameserver(GResolv *resolv, const char *address, +bool g_resolv_add_nameserver(GResolv *resolv, const char *address, uint16_t port, unsigned long flags) { struct resolv_nameserver *nameserver; - if (resolv == NULL) - return FALSE; + if (!resolv) + return false; nameserver = g_try_new0(struct resolv_nameserver, 1); - if (nameserver == NULL) - return FALSE; + if (!nameserver) + return false; nameserver->address = g_strdup(address); nameserver->port = port; @@ -940,7 +953,7 @@ gboolean g_resolv_add_nameserver(GResolv *resolv, const char *address, if (connect_udp_channel(nameserver) < 0) { free_nameserver(nameserver); - return FALSE; + return false; } resolv->nameserver_list = g_list_append(resolv->nameserver_list, @@ -948,12 +961,12 @@ gboolean g_resolv_add_nameserver(GResolv *resolv, const char *address, debug(resolv, "setting nameserver %s", address); - return TRUE; + return true; } void g_resolv_flush_nameservers(GResolv *resolv) { - if (resolv == NULL) + if (!resolv) return; flush_nameservers(resolv); @@ -965,7 +978,7 @@ static gint add_query(struct resolv_lookup *lookup, const char *hostname, int ty unsigned char buf[4096]; int len; - if (query == NULL) + if (!query) return -ENOMEM; len = res_mkquery(ns_o_query, hostname, ns_c_in, type, @@ -975,7 +988,8 @@ static gint add_query(struct resolv_lookup *lookup, const char *hostname, int ty debug(lookup->resolv, "sending %d bytes", len); - if (send_query(lookup->resolv, buf, len) < 0) { + query->nr_ns = send_query(lookup->resolv, buf, len); + if (query->nr_ns <= 0) { g_free(query); return -EIO; } @@ -1003,12 +1017,12 @@ guint g_resolv_lookup_hostname(GResolv *resolv, const char *hostname, { struct resolv_lookup *lookup; - debug(resolv, "hostname %s", hostname); - - if (resolv == NULL) + if (!resolv) return 0; - if (resolv->nameserver_list == NULL) { + debug(resolv, "hostname %s", hostname); + + if (!resolv->nameserver_list) { int i; for (i = 0; i < resolv->res.nscount; i++) { @@ -1029,12 +1043,12 @@ guint g_resolv_lookup_hostname(GResolv *resolv, const char *hostname, g_resolv_add_nameserver(resolv, buf, 53, 0); } - if (resolv->nameserver_list == NULL) + if (!resolv->nameserver_list) g_resolv_add_nameserver(resolv, "127.0.0.1", 53, 0); } lookup = g_try_new0(struct resolv_lookup, 1); - if (lookup == NULL) + if (!lookup) return 0; lookup->resolv = resolv; @@ -1069,7 +1083,7 @@ guint g_resolv_lookup_hostname(GResolv *resolv, const char *hostname, return lookup->id; } -gboolean g_resolv_cancel_lookup(GResolv *resolv, guint id) +bool g_resolv_cancel_lookup(GResolv *resolv, guint id) { struct resolv_lookup *lookup; GList *list; @@ -1079,8 +1093,8 @@ gboolean g_resolv_cancel_lookup(GResolv *resolv, guint id) list = g_queue_find_custom(resolv->lookup_queue, GUINT_TO_POINTER(id), compare_lookup_id); - if (list == NULL) - return FALSE; + if (!list) + return false; lookup = list->data; @@ -1089,18 +1103,18 @@ gboolean g_resolv_cancel_lookup(GResolv *resolv, guint id) g_queue_remove(resolv->lookup_queue, lookup); destroy_lookup(lookup); - return TRUE; + return true; } -gboolean g_resolv_set_address_family(GResolv *resolv, int family) +bool g_resolv_set_address_family(GResolv *resolv, int family) { - if (resolv == NULL) - return FALSE; + if (!resolv) + return false; if (family != AF_UNSPEC && family != AF_INET && family != AF_INET6) - return FALSE; + return false; resolv->result_family = family; - return TRUE; + return true; }