X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fdnsproxy.c;h=d7ef63bbb8a43f3d80a4fc4da23bc9d1d6bdd394;hb=b93f2462a3dc6cc00810ed28b87a5c05516c0921;hp=4e08d1cec6137ff36e2c64c90ef0d8bbb33e0d9f;hpb=f0105bfb82abb054ad7269ab623434e9581a30e6;p=framework%2Fconnectivity%2Fconnman.git diff --git a/src/dnsproxy.c b/src/dnsproxy.c index 4e08d1c..d7ef63b 100644 --- a/src/dnsproxy.c +++ b/src/dnsproxy.c @@ -24,6 +24,7 @@ #endif #include +#include #include #include #include @@ -183,10 +184,14 @@ static int cache_refcount; static GSList *server_list = NULL; static GSList *request_list = NULL; static GSList *request_pending_list = NULL; -static guint16 request_id = 0x0000; static GHashTable *listener_table = NULL; static time_t next_refresh; +static guint16 get_id() +{ + return random(); +} + static int protocol_offset(int protocol) { switch (protocol) { @@ -494,53 +499,50 @@ static int append_query(unsigned char *buf, unsigned int size, const char *query, const char *domain) { unsigned char *ptr = buf; - char *offset; int len; DBG("query %s domain %s", query, domain); - offset = (char *) query; - while (offset != NULL) { - char *tmp; + while (query != NULL) { + const char *tmp; - tmp = strchr(offset, '.'); + tmp = strchr(query, '.'); if (tmp == NULL) { - len = strlen(offset); + len = strlen(query); if (len == 0) break; *ptr = len; - memcpy(ptr + 1, offset, len); + memcpy(ptr + 1, query, len); ptr += len + 1; break; } - *ptr = tmp - offset; - memcpy(ptr + 1, offset, tmp - offset); - ptr += tmp - offset + 1; + *ptr = tmp - query; + memcpy(ptr + 1, query, tmp - query); + ptr += tmp - query + 1; - offset = tmp + 1; + query = tmp + 1; } - offset = (char *) domain; - while (offset != NULL) { - char *tmp; + while (domain != NULL) { + const char *tmp; - tmp = strchr(offset, '.'); + tmp = strchr(domain, '.'); if (tmp == NULL) { - len = strlen(offset); + len = strlen(domain); if (len == 0) break; *ptr = len; - memcpy(ptr + 1, offset, len); + memcpy(ptr + 1, domain, len); ptr += len + 1; break; } - *ptr = tmp - offset; - memcpy(ptr + 1, offset, tmp - offset); - ptr += tmp - offset + 1; + *ptr = tmp - domain; + memcpy(ptr + 1, domain, tmp - domain); + ptr += tmp - domain + 1; - offset = tmp + 1; + domain = tmp + 1; } *ptr++ = 0x00; @@ -1201,7 +1203,6 @@ static int reply_query_type(unsigned char *msg, int len) /* now the query, which is a name and 2 16 bit words */ l = dns_name_length(c) + 1; c += l; - len -= l; w = (uint16_t *) c; type = ntohs(*w); @@ -1555,17 +1556,30 @@ static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol, */ ptr = reply + offset + sizeof(struct domain_hdr); host_len = *ptr; - domain_len = strlen((const char *)ptr) - host_len - 1; + domain_len = strlen((const char *)ptr + host_len + 1); /* - * remove the domain name and replaced it by the end - * of reply. + * Remove the domain name and replace it by the end + * of reply. Check if the domain is really there + * before trying to copy the data. The domain_len can + * be 0 because if the original query did not contain + * a domain name, then we are sending two packets, + * first without the domain name and the second packet + * with domain name. The append_domain is set to true + * even if we sent the first packet without domain + * name. In this case we end up in this branch. */ - memmove(ptr + host_len + 1, - ptr + host_len + domain_len + 1, - reply_len - (ptr - reply + domain_len)); + if (domain_len > 0) { + /* + * Note that we must use memmove() here, + * because the memory areas can overlap. + */ + memmove(ptr + host_len + 1, + ptr + host_len + domain_len + 1, + reply_len - (ptr - reply + domain_len)); - reply_len = reply_len - domain_len; + reply_len = reply_len - domain_len; + } } g_free(req->resp); @@ -1658,7 +1672,7 @@ static void destroy_server(struct server_data *server) g_io_channel_unref(server->channel); if (server->protocol == IPPROTO_UDP) - connman_info("Removing DNS server %s", server->server); + DBG("Removing DNS server %s", server->server); g_free(server->incoming_reply); g_free(server->server); @@ -2029,7 +2043,7 @@ static struct server_data *create_server(const char *interface, if (protocol == IPPROTO_UDP) { /* Enable new servers by default */ data->enabled = TRUE; - connman_info("Adding DNS server %s", data->server); + DBG("Adding DNS server %s", data->server); server_list = g_slist_append(server_list, data); @@ -2043,7 +2057,6 @@ static gboolean resolv(struct request_data *req, gpointer request, gpointer name) { GSList *list; - int status; for (list = server_list; list; list = list->next) { struct server_data *data = list->data; @@ -2058,19 +2071,11 @@ static gboolean resolv(struct request_data *req, G_IO_IN | G_IO_NVAL | G_IO_ERR | G_IO_HUP, udp_server_event, data); - status = ns_resolv(data, req, request, name); - if (status < 0) - continue; - - if (status > 0) { - if (req->timeout > 0) { - g_source_remove(req->timeout); - req->timeout = 0; - } - } + if (ns_resolv(data, req, request, name) > 0) + return TRUE; } - return TRUE; + return FALSE; } static void append_domain(const char *interface, const char *domain) @@ -2200,12 +2205,12 @@ static void dnsproxy_offline_mode(connman_bool_t enabled) struct server_data *data = list->data; if (enabled == FALSE) { - connman_info("Enabling DNS server %s", data->server); + DBG("Enabling DNS server %s", data->server); data->enabled = TRUE; cache_invalidate(); cache_refresh(); } else { - connman_info("Disabling DNS server %s", data->server); + DBG("Disabling DNS server %s", data->server); data->enabled = FALSE; cache_invalidate(); } @@ -2236,10 +2241,10 @@ static void dnsproxy_default_changed(struct connman_service *service) struct server_data *data = list->data; if (g_strcmp0(data->interface, interface) == 0) { - connman_info("Enabling DNS server %s", data->server); + DBG("Enabling DNS server %s", data->server); data->enabled = TRUE; } else { - connman_info("Disabling DNS server %s", data->server); + DBG("Disabling DNS server %s", data->server); data->enabled = FALSE; } } @@ -2276,7 +2281,7 @@ static int parse_request(unsigned char *buf, int len, if (hdr->qr != 0 || qdcount != 1) return -EINVAL; - memset(name, 0, size); + name[0] = '\0'; ptr = buf + sizeof(struct domain_hdr); remain = len - sizeof(struct domain_hdr); @@ -2383,13 +2388,9 @@ static gboolean tcp_listener_event(GIOChannel *channel, GIOCondition condition, req->client_sk = client_sk; req->protocol = IPPROTO_TCP; - request_id += 2; - if (request_id == 0x0000 || request_id == 0xffff) - request_id += 2; - req->srcid = buf[2] | (buf[3] << 8); - req->dstid = request_id; - req->altid = request_id + 1; + req->dstid = get_id(); + req->altid = get_id(); req->request_len = len; buf[2] = req->dstid & 0xff; @@ -2502,13 +2503,9 @@ static gboolean udp_listener_event(GIOChannel *channel, GIOCondition condition, req->client_sk = 0; req->protocol = IPPROTO_UDP; - request_id += 2; - if (request_id == 0x0000 || request_id == 0xffff) - request_id += 2; - req->srcid = buf[0] | (buf[1] << 8); - req->dstid = request_id; - req->altid = request_id + 1; + req->dstid = get_id(); + req->altid = get_id(); req->request_len = len; buf[0] = req->dstid & 0xff; @@ -2516,11 +2513,18 @@ static gboolean udp_listener_event(GIOChannel *channel, GIOCondition condition, req->numserv = 0; req->ifdata = (struct listener_data *) ifdata; - req->timeout = g_timeout_add_seconds(5, request_timeout, req); req->append_domain = FALSE; + + if (resolv(req, buf, query) == TRUE) { + /* a cached result was sent, so the request can be released */ + g_free(req); + return TRUE; + } + + req->timeout = g_timeout_add_seconds(5, request_timeout, req); request_list = g_slist_append(request_list, req); - return resolv(req, buf, query); + return TRUE; } static int create_dns_listener(int protocol, struct listener_data *ifdata) @@ -2779,6 +2783,8 @@ int __connman_dnsproxy_init(void) DBG(""); + srandom(time(NULL)); + listener_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); err = __connman_dnsproxy_add_listener("lo");