---
Hi,

this patch fixes possible memory alignment issue when dealing with
DNS packet. I will send the fixed DNS cache patch after this has
been commited.

Regards,
Jukka

 src/dnsproxy.c |   85 +++++++++++++++++++++++++++++++------------------------
 1 files changed, 48 insertions(+), 37 deletions(-)

diff --git a/src/dnsproxy.c b/src/dnsproxy.c
index d9e291c..af3d8b4 100644
--- a/src/dnsproxy.c
+++ b/src/dnsproxy.c
@@ -192,7 +192,7 @@ static void send_response(int sk, unsigned char *buf, int 
len,
                                const struct sockaddr *to, socklen_t tolen,
                                int protocol)
 {
-       struct domain_hdr *hdr;
+       unsigned char *hdr;
        int err, offset = protocol_offset(protocol);
 
        DBG("");
@@ -205,14 +205,15 @@ static void send_response(int sk, unsigned char *buf, int 
len,
 
        hdr = (void *) (buf + offset);
 
-       DBG("id 0x%04x qr %d opcode %d", hdr->id, hdr->qr, hdr->opcode);
+       DBG("id 0x%04x qr %d opcode %d", hdr[0] << 8 | hdr[1],
+               (hdr[2] & 0x80) >> 8, (hdr[2] & 0x78) >> 3);
 
-       hdr->qr = 1;
-       hdr->rcode = 2;
+       hdr[2] |= 0x80;  /* qr */
+       hdr[3] = (hdr[3] & 0xf0) | 0x02; /* rcode */
 
-       hdr->ancount = 0;
-       hdr->nscount = 0;
-       hdr->arcount = 0;
+       hdr[6] = hdr[7] = 0;   /* ancount */
+       hdr[8] = hdr[9] = 0;   /* nscount */
+       hdr[10] = hdr[11] = 0; /* arcount */
 
        err = sendto(sk, buf, len, 0, to, tolen);
        if (err < 0) {
@@ -247,11 +248,12 @@ static gboolean request_timeout(gpointer user_data)
                if (err < 0)
                        return FALSE;
        } else if (req->request && req->numserv == 0) {
-               struct domain_hdr *hdr;
+               unsigned char *hdr;
 
                if (req->protocol == IPPROTO_TCP) {
                        hdr = (void *) (req->request + 2);
-                       hdr->id = req->srcid;
+                       hdr[0] = req->srcid >> 8;
+                       hdr[1] = req->srcid;
                        send_response(req->client_sk, req->request,
                                req->request_len, NULL, 0, IPPROTO_TCP);
 
@@ -259,7 +261,8 @@ static gboolean request_timeout(gpointer user_data)
                        int sk;
 
                        hdr = (void *) (req->request);
-                       hdr->id = req->srcid;
+                       hdr[0] = req->srcid >> 8;
+                       hdr[1] = req->srcid;
                        sk = g_io_channel_unix_get_fd(
                                                ifdata->udp_listener_channel);
                        send_response(sk, req->request, req->request_len,
@@ -349,7 +352,7 @@ static int ns_resolv(struct server_data *server, struct 
request_data *req,
        for (list = server->domains; list; list = list->next) {
                char *domain;
                unsigned char alt[1024];
-               struct domain_hdr *hdr = (void *) &alt;
+               unsigned char *hdr = (void *) &alt;
                int altlen, domlen, offset;
 
                domain = list->data;
@@ -365,11 +368,11 @@ static int ns_resolv(struct server_data *server, struct 
request_data *req,
                if (domlen < 5)
                        return -EINVAL;
 
-               alt[offset] = req->altid & 0xff;
-               alt[offset + 1] = req->altid >> 8;
+               alt[offset] = req->altid >> 8;
+               alt[offset + 1] = req->altid;
 
                memcpy(alt + offset + 2, request + offset + 2, 10);
-               hdr->qdcount = htons(1);
+               hdr[5] = 1;  /* qdcount */
 
                altlen = append_query(alt + offset + 12, sizeof(alt) - 12,
                                        name, domain);
@@ -401,16 +404,17 @@ static int ns_resolv(struct server_data *server, struct 
request_data *req,
 
 static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol)
 {
-       struct domain_hdr *hdr;
+       unsigned char *hdr;
        struct request_data *req;
        int dns_id, sk, err, offset = protocol_offset(protocol);
        struct listener_data *ifdata;
+       int rcode;
 
        if (offset < 0)
                return offset;
 
        hdr = (void *)(reply + offset);
-       dns_id = reply[offset] | reply[offset + 1] << 8;
+       dns_id = reply[offset] << 8 | reply[offset + 1];
 
        DBG("Received %d bytes (id 0x%04x)", reply_len, dns_id);
 
@@ -418,16 +422,18 @@ static int forward_dns_reply(unsigned char *reply, int 
reply_len, int protocol)
        if (req == NULL)
                return -EINVAL;
 
-       DBG("id 0x%04x rcode %d", hdr->id, hdr->rcode);
+       rcode = hdr[3] & 0x0f;
+
+       DBG("id 0x%04x rcode %d", hdr[0] << 8 | hdr[1], rcode);
 
        ifdata = req->ifdata;
 
-       reply[offset] = req->srcid & 0xff;
-       reply[offset + 1] = req->srcid >> 8;
+       reply[offset] = req->srcid >> 8;
+       reply[offset + 1] = req->srcid;
 
        req->numresp++;
 
-       if (hdr->rcode == 0 || req->resp == NULL) {
+       if (rcode == 0 || req->resp == NULL) {
                g_free(req->resp);
                req->resplen = 0;
 
@@ -439,7 +445,7 @@ static int forward_dns_reply(unsigned char *reply, int 
reply_len, int protocol)
                req->resplen = reply_len;
        }
 
-       if (hdr->rcode > 0 && req->numresp < req->numserv)
+       if (rcode > 0 && req->numresp < req->numserv)
                return -EINVAL;
 
        if (req->timeout > 0)
@@ -545,7 +551,7 @@ hangup:
 
                for (list = request_list; list; list = list->next) {
                        struct request_data *req = list->data;
-                       struct domain_hdr *hdr;
+                       unsigned char *hdr;
 
                        if (req->protocol == IPPROTO_UDP)
                                continue;
@@ -562,7 +568,8 @@ hangup:
                                continue;
 
                        hdr = (void *) (req->request + 2);
-                       hdr->id = req->srcid;
+                       hdr[0] = req->srcid >> 8;
+                       hdr[1] = req->srcid;
                        send_response(req->client_sk, req->request,
                                req->request_len, NULL, 0, IPPROTO_TCP);
 
@@ -1038,21 +1045,25 @@ static unsigned char opt_edns0_type[2] = { 0x00, 0x29 };
 static int parse_request(unsigned char *buf, int len,
                                        char *name, unsigned int size)
 {
-       struct domain_hdr *hdr = (void *) buf;
-       uint16_t qdcount = ntohs(hdr->qdcount);
-       uint16_t arcount = ntohs(hdr->arcount);
+       unsigned char *hdr = (void *) buf;
+       uint16_t qdcount, arcount;
        unsigned char *ptr;
        char *last_label = NULL;
        unsigned int remain, used = 0;
+       int qr;
 
        if (len < 12)
                return -EINVAL;
 
+       qdcount = hdr[4] << 8 | hdr[5];
+       arcount = hdr[10] << 8 | hdr[11];
+       qr = hdr[2] & 0x80 ? 1 : 0;
+
        DBG("id 0x%04x qr %d opcode %d qdcount %d arcount %d",
-                                       hdr->id, hdr->qr, hdr->opcode,
-                                                       qdcount, arcount);
+               hdr[0] << 8 | hdr[1], qr, (hdr[2] & 0x78) >> 3,
+               qdcount, arcount);
 
-       if (hdr->qr != 0 || qdcount != 1)
+       if (qr != 0 || qdcount != 1)
                return -EINVAL;
 
        memset(name, 0, size);
@@ -1145,7 +1156,7 @@ static gboolean tcp_listener_event(GIOChannel *channel, 
GIOCondition condition,
        if (len < 2)
                return TRUE;
 
-       DBG("Received %d bytes (id 0x%04x)", len, buf[2] | buf[3] << 8);
+       DBG("Received %d bytes (id 0x%04x)", len, buf[2] << 8 | buf[3]);
 
        err = parse_request(buf + 2, len - 2, query, sizeof(query));
        if (err < 0 || (g_slist_length(server_list) == 0)) {
@@ -1166,13 +1177,13 @@ static gboolean tcp_listener_event(GIOChannel *channel, 
GIOCondition condition,
        if (request_id == 0x0000 || request_id == 0xffff)
                request_id += 2;
 
-       req->srcid = buf[2] | (buf[3] << 8);
+       req->srcid = buf[2] << 8 | buf[3];
        req->dstid = request_id;
        req->altid = request_id + 1;
        req->request_len = len;
 
-       buf[2] = req->dstid & 0xff;
-       buf[3] = req->dstid >> 8;
+       buf[2] = req->dstid >> 8;
+       buf[3] = req->dstid;
 
        req->numserv = 0;
        req->ifdata = (struct listener_data *) ifdata;
@@ -1257,7 +1268,7 @@ static gboolean udp_listener_event(GIOChannel *channel, 
GIOCondition condition,
        if (len < 2)
                return TRUE;
 
-       DBG("Received %d bytes (id 0x%04x)", len, buf[0] | buf[1] << 8);
+       DBG("Received %d bytes (id 0x%04x)", len, buf[0] << 8 | buf[1]);
 
        err = parse_request(buf, len, query, sizeof(query));
        if (err < 0 || (g_slist_length(server_list) == 0)) {
@@ -1279,13 +1290,13 @@ static gboolean udp_listener_event(GIOChannel *channel, 
GIOCondition condition,
        if (request_id == 0x0000 || request_id == 0xffff)
                request_id += 2;
 
-       req->srcid = buf[0] | (buf[1] << 8);
+       req->srcid = buf[0] << 8 | buf[1];
        req->dstid = request_id;
        req->altid = request_id + 1;
        req->request_len = len;
 
-       buf[0] = req->dstid & 0xff;
-       buf[1] = req->dstid >> 8;
+       buf[0] = req->dstid >> 8;
+       buf[1] = req->dstid;
 
        req->numserv = 0;
        req->ifdata = (struct listener_data *) ifdata;
-- 
1.7.1

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

Reply via email to