---
Hi,

this 3rd version fixes the alignment macro namespace issue.

Jukka


 include/types.h |   16 ++++++++
 src/dnsproxy.c  |  114 +++++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 97 insertions(+), 33 deletions(-)

diff --git a/include/types.h b/include/types.h
index 70aff9e..f722e65 100644
--- a/include/types.h
+++ b/include/types.h
@@ -38,6 +38,22 @@ typedef int          connman_bool_t;
 typedef unsigned char  connman_uint8_t;
 typedef unsigned short connman_uint16_t;
 
+#define connman_get_unaligned(ptr)             \
+({                                             \
+       struct __attribute__((packed)) {        \
+               typeof(*(ptr)) __v;             \
+       } *__p = (void *) (ptr);                \
+       __p->__v;                               \
+})
+
+#define connman_put_unaligned(val, ptr)                \
+do {                                           \
+       struct __attribute__((packed)) {        \
+               typeof(*(ptr)) __v;             \
+       } *__p = (void *) (ptr);                \
+       __p->__v = (val);                       \
+} while(0)
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/dnsproxy.c b/src/dnsproxy.c
index d9e291c..dd67aff 100644
--- a/src/dnsproxy.c
+++ b/src/dnsproxy.c
@@ -187,12 +187,56 @@ static struct server_data *find_server(const char 
*interface,
        return NULL;
 }
 
+static struct domain_hdr *get_hdr(unsigned char *buf, struct domain_hdr *hdr)
+{
+       if (hdr == NULL)
+               return NULL;
+
+       hdr->id = ntohs(connman_get_unaligned((uint16_t *)buf));
+       hdr->qr = (buf[2] & 0x80) >> 7;
+       hdr->opcode = (buf[2] & 0x78) >> 3;
+       hdr->aa = (buf[2] & 0x04) >> 2;
+       hdr->tc = (buf[2] & 0x02) >> 1;
+       hdr->rd = buf[2] & 0x01;
+       hdr->ra = (buf[3] & 0x80) >> 7;
+       hdr->z = 0;
+       hdr->rcode = buf[3] & 0x0f;
+
+       hdr->qdcount = ntohs(connman_get_unaligned((uint16_t *)&buf[4]));
+       hdr->ancount = ntohs(connman_get_unaligned((uint16_t *)&buf[6]));
+       hdr->nscount = ntohs(connman_get_unaligned((uint16_t *)&buf[8]));
+       hdr->arcount = ntohs(connman_get_unaligned((uint16_t *)&buf[10]));
+
+       return hdr;
+}
+
+static void put_hdr(struct domain_hdr *hdr, unsigned char *buf)
+{
+       if (hdr == NULL)
+               return;
+
+       connman_put_unaligned(htons(hdr->id), (uint16_t *)buf);
+
+       buf[2] |= hdr->qr << 7;
+       buf[2] |= hdr->opcode << 3;
+       buf[2] |= hdr->aa << 2;
+       buf[2] |= hdr->tc << 1;
+       buf[2] |= hdr->rd << 0;
+       buf[3] |= hdr->ra << 7;
+       buf[3] &= ~0x70;
+       buf[3] |= hdr->rcode;
+
+       connman_put_unaligned(htons(hdr->qdcount), (uint16_t *)&buf[4]);
+       connman_put_unaligned(htons(hdr->ancount), (uint16_t *)&buf[6]);
+       connman_put_unaligned(htons(hdr->nscount), (uint16_t *)&buf[8]);
+       connman_put_unaligned(htons(hdr->arcount), (uint16_t *)&buf[10]);
+}
 
 static void send_response(int sk, unsigned char *buf, int len,
                                const struct sockaddr *to, socklen_t tolen,
                                int protocol)
 {
-       struct domain_hdr *hdr;
+       struct domain_hdr *hdr, header;
        int err, offset = protocol_offset(protocol);
 
        DBG("");
@@ -203,7 +247,7 @@ static void send_response(int sk, unsigned char *buf, int 
len,
        if (len < 12)
                return;
 
-       hdr = (void *) (buf + offset);
+       hdr = get_hdr(buf + offset, &header);
 
        DBG("id 0x%04x qr %d opcode %d", hdr->id, hdr->qr, hdr->opcode);
 
@@ -214,6 +258,8 @@ static void send_response(int sk, unsigned char *buf, int 
len,
        hdr->nscount = 0;
        hdr->arcount = 0;
 
+       put_hdr(hdr, buf + offset);
+
        err = sendto(sk, buf, len, 0, to, tolen);
        if (err < 0) {
                connman_error("Failed to send DNS response: %s",
@@ -247,19 +293,18 @@ static gboolean request_timeout(gpointer user_data)
                if (err < 0)
                        return FALSE;
        } else if (req->request && req->numserv == 0) {
-               struct domain_hdr *hdr;
 
                if (req->protocol == IPPROTO_TCP) {
-                       hdr = (void *) (req->request + 2);
-                       hdr->id = req->srcid;
+                       connman_put_unaligned(htons(req->srcid),
+                                       (uint16_t *)(req->request + 2));
                        send_response(req->client_sk, req->request,
                                req->request_len, NULL, 0, IPPROTO_TCP);
 
                } else if (req->protocol == IPPROTO_UDP) {
                        int sk;
 
-                       hdr = (void *) (req->request);
-                       hdr->id = req->srcid;
+                       connman_put_unaligned(htons(req->srcid),
+                                       (uint16_t *)req->request);
                        sk = g_io_channel_unix_get_fd(
                                                ifdata->udp_listener_channel);
                        send_response(sk, req->request, req->request_len,
@@ -349,7 +394,6 @@ 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;
                int altlen, domlen, offset;
 
                domain = list->data;
@@ -365,11 +409,12 @@ 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;
+               connman_put_unaligned(htons(req->altid),
+                               (uint16_t *)(alt + offset));
 
                memcpy(alt + offset + 2, request + offset + 2, 10);
-               hdr->qdcount = htons(1);
+
+               alt[5] = 1;  /* qdcount */
 
                altlen = append_query(alt + offset + 12, sizeof(alt) - 12,
                                        name, domain);
@@ -401,7 +446,7 @@ 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;
+       struct domain_hdr *hdr, header;
        struct request_data *req;
        int dns_id, sk, err, offset = protocol_offset(protocol);
        struct listener_data *ifdata;
@@ -409,8 +454,7 @@ static int forward_dns_reply(unsigned char *reply, int 
reply_len, int protocol)
        if (offset < 0)
                return offset;
 
-       hdr = (void *)(reply + offset);
-       dns_id = reply[offset] | reply[offset + 1] << 8;
+       dns_id = ntohs(connman_get_unaligned((uint16_t *)(reply + offset)));
 
        DBG("Received %d bytes (id 0x%04x)", reply_len, dns_id);
 
@@ -418,12 +462,12 @@ static int forward_dns_reply(unsigned char *reply, int 
reply_len, int protocol)
        if (req == NULL)
                return -EINVAL;
 
+       hdr = get_hdr(reply + offset, &header);
        DBG("id 0x%04x rcode %d", hdr->id, hdr->rcode);
 
        ifdata = req->ifdata;
 
-       reply[offset] = req->srcid & 0xff;
-       reply[offset + 1] = req->srcid >> 8;
+       connman_put_unaligned(htons(req->srcid), (uint16_t *)(reply + offset));
 
        req->numresp++;
 
@@ -545,7 +589,6 @@ hangup:
 
                for (list = request_list; list; list = list->next) {
                        struct request_data *req = list->data;
-                       struct domain_hdr *hdr;
 
                        if (req->protocol == IPPROTO_UDP)
                                continue;
@@ -561,8 +604,8 @@ hangup:
                        if (req->numserv && --(req->numserv))
                                continue;
 
-                       hdr = (void *) (req->request + 2);
-                       hdr->id = req->srcid;
+                       connman_put_unaligned(htons(req->srcid),
+                                       (uint16_t *)(req->request + 2));
                        send_response(req->client_sk, req->request,
                                req->request_len, NULL, 0, IPPROTO_TCP);
 
@@ -1038,9 +1081,7 @@ 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);
+       struct domain_hdr *hdr, header;
        unsigned char *ptr;
        char *last_label = NULL;
        unsigned int remain, used = 0;
@@ -1048,11 +1089,12 @@ static int parse_request(unsigned char *buf, int len,
        if (len < 12)
                return -EINVAL;
 
+       hdr = get_hdr(buf, &header);
        DBG("id 0x%04x qr %d opcode %d qdcount %d arcount %d",
                                        hdr->id, hdr->qr, hdr->opcode,
-                                                       qdcount, arcount);
+                                       hdr->qdcount, hdr->arcount);
 
-       if (hdr->qr != 0 || qdcount != 1)
+       if (hdr->qr != 0 || hdr->qdcount != 1)
                return -EINVAL;
 
        memset(name, 0, size);
@@ -1080,7 +1122,7 @@ static int parse_request(unsigned char *buf, int len,
                remain -= len + 1;
        }
 
-       if (last_label && arcount && remain >= 9 && last_label[4] == 0 &&
+       if (last_label && hdr->arcount && remain >= 9 && last_label[4] == 0 &&
                                !memcmp(last_label + 5, opt_edns0_type, 2)) {
                uint16_t edns0_bufsize;
 
@@ -1119,6 +1161,7 @@ static gboolean tcp_listener_event(GIOChannel *channel, 
GIOCondition condition,
        socklen_t client_addr_len = sizeof(client_addr);
        GSList *list;
        struct listener_data *ifdata = user_data;
+       uint16_t id;
 
        DBG("condition 0x%x", condition);
 
@@ -1145,7 +1188,9 @@ 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);
+       id = buf[2] << 8 | buf[3];
+
+       DBG("Received %d bytes (id 0x%04x)", len, id);
 
        err = parse_request(buf + 2, len - 2, query, sizeof(query));
        if (err < 0 || (g_slist_length(server_list) == 0)) {
@@ -1166,13 +1211,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 = id;
        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;
@@ -1242,6 +1287,7 @@ static gboolean udp_listener_event(GIOChannel *channel, 
GIOCondition condition,
        socklen_t client_addr_len = sizeof(client_addr);
        int sk, err, len;
        struct listener_data *ifdata = user_data;
+       uint16_t id;
 
        if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
                connman_error("Error with UDP listener channel");
@@ -1257,7 +1303,9 @@ 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);
+       id = buf[0] << 8 | buf[1];
+
+       DBG("Received %d bytes (id 0x%04x)", len, id);
 
        err = parse_request(buf, len, query, sizeof(query));
        if (err < 0 || (g_slist_length(server_list) == 0)) {
@@ -1279,13 +1327,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 = id;
        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
connman@connman.net
http://lists.connman.net/listinfo/connman

Reply via email to