---
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