Hi Marcel,

On 07/04/2011 09:47 PM, Marcel Holtmann wrote:
Hi Jukka,

diff --git a/src/dnsproxy.c b/src/dnsproxy.c

+struct cache_entry {
+       GHashTable *cache;

why do you have a cache hast table inside the cache entry?

Hmm, it seems not to be needed, I will remove it.


+static struct cache_entry *cache_check(struct server_data *server,
+                                       gpointer request)
+{
+       uint16_t type;
+       unsigned int offset = 0;
+       unsigned char *dns_body = (unsigned char *)request + 12;
+       unsigned char *question =&dns_body[offset];
+       struct cache_entry *entry;
+
+       offset = strlen((char *)question) + 1;
+       type = ntohs(*(uint16_t *)(&dns_body[offset]));

Are we sure that we do not need unaligned access here?

Good point. I did not see any problems with Atom but there might be alignment issues in other processors.



+static int parse_response(unsigned char *buf, int buflen,
+                       unsigned char *question, int qlen,
+                       int *type, int *class, int *ttl,
+                       unsigned char *response, unsigned int *resp_len,
+                       int *answers)
+{
+       struct domain_hdr *hdr = (void *) buf;
+       unsigned char *ptr;
+       uint16_t qdcount = ntohs(hdr->qdcount);
+       uint16_t ancount = ntohs(hdr->ancount);
+       int err, i, qtype, qclass;
+       unsigned char *next = NULL;
+
+       if (buflen<  12)
+               return -EINVAL;
+
+       DBG("qr %d qdcount %d", hdr->qr, qdcount);
+
+       /* We currently only cache responses where question count is 1 */
+       if (hdr->qr != 1 || qdcount != 1)
+               return -EINVAL;
+
+       ptr = buf + sizeof(struct domain_hdr);
+
+       strncpy((char *)question, (char *)ptr, qlen);
+       qlen = strlen((char *)question);
+       ptr += qlen + 1;
+       qtype = ntohs(*(uint16_t *)ptr);
+
+       /* We cache only A and AAAA records */
+       if (qtype != 1&&  qtype != 28)
+               return -ENOMSG;
+
+       ptr += 2;
+       qclass = ntohs(*(uint16_t *)ptr);
+       ptr += 2; /* ptr points now to answers */
+
+       err = -ENOMSG;
+       *resp_len = 0;
+       *answers = 0;
+
+       for (i = 0; i<  ancount; i++) {
+               unsigned char rsp[128];
+               unsigned int rsp_len = sizeof(rsp) - 1;
+               int len = 0;
+
+               memset(rsp, 0, sizeof(rsp));
+               err = parse_rr(buf, ptr, buf + buflen, rsp,&rsp_len,&len,
+                       type, class, ttl,&next);
+               if (err != 0)
+                       return err;
+
+               if ((strncmp((char *)question, (char *)rsp, len) == 0)&&
+                               *type == qtype&&  *class == qclass) {

Should we also check that the len of question and rsp is well in the
limits here.

Yep, I will fix that.


+       rsplen = sizeof(response) - 1;
+       err = parse_response(msg + offset, msg_len - offset,
+                               question, sizeof(question) - 1,
+                               &type,&class,&ttl,
+                               response,&rsplen,&answers);
+       if (err<  0)
+               return 0;
+
+       if (g_hash_table_lookup(data->cache, question) == NULL) {

Why not just != NULL and just leave the function then?

Sure, why not :)


+               int qlen = strlen((char *)question);
+               unsigned char *ptr;
+
+               entry = g_try_new0(struct cache_entry, 1);

When using g_try_new0 you need to check the result and abort nicely.

Yes, I will add that.


+               entry->cache = data->cache;
+               entry->key = (unsigned char *)g_strdup((char *)question);
+               entry->type = type;
+               entry->answers = answers;
+               entry->data_len = 12 + qlen + 1 + 2 + 2 + rsplen;
+               entry->data = ptr = g_malloc0(entry->data_len);

Here we really wanna check the result and abort nicely.

True, will do that.


+
+               memcpy(ptr, msg, 12);
+               ptr += 12;
+               memcpy(ptr, question, qlen);
+               ptr += qlen + 1;
+               *(uint16_t *)ptr = htons(type);
+               ptr += 2;
+               *(uint16_t *)ptr = htons(class);
+               ptr += 2;
+               memcpy(ptr, response, rsplen);

If you copy data in the allocated buffer anyway, then setting it to zero
first is waste.

I skipped the \0 at the end of the question (ptr += qlen + 1) because the buffer was set to 0. I can remove the zeroing, that is fine, I just need to remember to add the \0 in the buffer.


And no need to keep moving the pointer forward. Just use memcpy(ptr + ..
style operation.

Sure.


Also what about unaligned access. Do we need to care?

Probably it makes sense to try to play safe here, I will change that.


+               /*
+                * Restrict the cached dns entry ttl to some sane value
+                * in order to prevent data staying in the cache too long.
+                */
+               if (ttl>  MAX_CACHE_TTL)
+                       ttl = MAX_CACHE_TTL;
+
+               entry->timeout = g_timeout_add_seconds(ttl,
+                                               cache_entry_timeout,
+                                               entry);
+               g_hash_table_insert(data->cache, g_strdup((char *)entry->key),
+                               entry);

The double allocation on entry->key is not a good idea.

Ok.


+       data->cache = g_hash_table_new_full(g_str_hash,
+                                               g_str_equal,
+                                               g_free,
+                                               cache_element_destroy);

I prefer to not double allocated the keys. Just have the key point to
cache->key and free it via cache_element_destroy callback.

Sure, np.


However you need to use g_hash_table_replace instead of
g_hash_table_insert to make this work properly. Otherwise you have
invalid memory access.

Ok.



Regards

Marcel



Jukka
_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman

Reply via email to