*
* Connection Manager
*
- * Copyright (C) 2007-2010 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
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;
/* 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);
sk = g_io_channel_unix_get_fd(server->channel);
err = send(sk, request, req->request_len, 0);
+ if (err < 0)
+ return -EIO;
req->numserv++;
*/
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
+ * remove the domain name and replace it by the end
* of reply.
*/
- memmove(ptr + host_len + 1,
+ memcpy(ptr + host_len + 1,
ptr + host_len + domain_len + 1,
reply_len - (ptr - reply + domain_len));
cache_size = 0;
}
+static gboolean try_remove_cache(gpointer user_data)
+{
+ if (__sync_fetch_and_sub(&cache_refcount, 1) == 1) {
+ DBG("No cache users, removing it.");
+
+ g_hash_table_destroy(cache);
+ cache = NULL;
+ }
+
+ return FALSE;
+}
+
static void destroy_server(struct server_data *server)
{
GList *list;
}
g_free(server->interface);
- if (__sync_fetch_and_sub(&cache_refcount, 1) == 1) {
- g_hash_table_destroy(cache);
- cache = NULL;
- }
+ /*
+ * We do not remove cache right away but delay it few seconds.
+ * The idea is that when IPv6 DNS server is added via RDNSS, it has a
+ * lifetime. When the lifetime expires we decrease the refcount so it
+ * is possible that the cache is then removed. Because a new DNS server
+ * is usually created almost immediately we would then loose the cache
+ * without any good reason. The small delay allows the new RDNSS to
+ * create a new DNS server instance and the refcount does not go to 0.
+ */
+ g_timeout_add_seconds(3, try_remove_cache, NULL);
g_free(server);
}
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);
return 0;
}
+static void destroy_request_data(struct request_data *req)
+{
+ if (req->timeout > 0)
+ g_source_remove(req->timeout);
+
+ g_free(req->resp);
+ g_free(req->request);
+ g_free(req->name);
+ g_free(req);
+}
+
static void destroy_listener(struct listener_data *ifdata)
{
GSList *list;
DBG("Dropping pending request (id 0x%04x -> 0x%04x)",
req->srcid, req->dstid);
- if (req->timeout > 0)
- g_source_remove(req->timeout);
-
- g_free(req->resp);
- g_free(req->request);
- g_free(req->name);
- g_free(req);
+ destroy_request_data(req);
list->data = NULL;
}
DBG("Dropping request (id 0x%04x -> 0x%04x)",
req->srcid, req->dstid);
- if (req->timeout > 0)
- g_source_remove(req->timeout);
-
- g_free(req->resp);
- g_free(req->request);
- g_free(req->name);
- g_free(req);
+ destroy_request_data(req);
list->data = NULL;
}