aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurelien Jarno <aurelien@aurel32.net>2011-01-06 22:43:13 +0100
committerAurelien Jarno <aurelien@aurel32.net>2011-01-10 10:56:25 +0100
commit529f51e8950f1c03777c89f19007c41695b6229e (patch)
tree8a21892597e7e452f0e47a61c42e59c7554da5df
parentd7d31ab977e5bbca2e52706234f1e6d009b158ca (diff)
downloadslirp-529f51e8950f1c03777c89f19007c41695b6229e.zip
slirp-529f51e8950f1c03777c89f19007c41695b6229e.tar.gz
slirp-529f51e8950f1c03777c89f19007c41695b6229e.tar.bz2
slirp: fix unaligned access in bootp code
Slirp code tries to be smart an avoid data copy by using pointer to the data. This solution leads to unaligned access, in this case preq_addr, which is a 32-bit long structure. There is no real point of avoiding data copy in a such case, as the value itself is smaller or the same size as a pointer. The patch replaces pointers to the preq_addr structure by the strcture itself, and use the address 0.0.0.0 if no address has been requested (this is not a valid address in such a request). It compares it with htonl(0L) for correctness reasons, in case a code checker look for such mistakes. It also uses memcpy() for copying the data, which takes care of alignement issues. This fixes an unaligned access on IA64 host while requesting a DHCP address. Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
-rw-r--r--bootp.c32
1 files changed, 17 insertions, 15 deletions
diff --git a/bootp.c b/bootp.c
index 556768c..11604c0 100644
--- a/bootp.c
+++ b/bootp.c
@@ -98,13 +98,13 @@ found:
}
static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
- const struct in_addr **preq_addr)
+ struct in_addr *preq_addr)
{
const uint8_t *p, *p_end;
int len, tag;
*pmsg_type = 0;
- *preq_addr = NULL;
+ preq_addr->s_addr = htonl(0L);
p = bp->bp_vend;
p_end = p + DHCP_OPT_LEN;
@@ -130,8 +130,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
*pmsg_type = p[0];
break;
case RFC2132_REQ_ADDR:
- if (len >= 4)
- *preq_addr = (struct in_addr *)p;
+ if (len >= 4) {
+ memcpy(&(preq_addr->s_addr), p, 4);
+ }
break;
default:
break;
@@ -139,8 +140,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
p += len;
}
}
- if (*pmsg_type == DHCPREQUEST && !*preq_addr && bp->bp_ciaddr.s_addr) {
- *preq_addr = &bp->bp_ciaddr;
+ if (*pmsg_type == DHCPREQUEST && preq_addr->s_addr == htonl(0L) &&
+ bp->bp_ciaddr.s_addr) {
+ memcpy(&(preq_addr->s_addr), &bp->bp_ciaddr, 4);
}
}
@@ -150,15 +152,15 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
struct mbuf *m;
struct bootp_t *rbp;
struct sockaddr_in saddr, daddr;
- const struct in_addr *preq_addr;
+ struct in_addr preq_addr;
int dhcp_msg_type, val;
uint8_t *q;
/* extract exact DHCP msg type */
dhcp_decode(bp, &dhcp_msg_type, &preq_addr);
DPRINTF("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type);
- if (preq_addr)
- DPRINTF(" req_addr=%08x\n", ntohl(preq_addr->s_addr));
+ if (preq_addr.s_addr != htonl(0L))
+ DPRINTF(" req_addr=%08x\n", ntohl(preq_addr.s_addr));
else
DPRINTF("\n");
@@ -180,10 +182,10 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
memset(rbp, 0, sizeof(struct bootp_t));
if (dhcp_msg_type == DHCPDISCOVER) {
- if (preq_addr) {
- bc = request_addr(slirp, preq_addr, slirp->client_ethaddr);
+ if (preq_addr.s_addr != htonl(0L)) {
+ bc = request_addr(slirp, &preq_addr, slirp->client_ethaddr);
if (bc) {
- daddr.sin_addr = *preq_addr;
+ daddr.sin_addr = preq_addr;
}
}
if (!bc) {
@@ -195,10 +197,10 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
}
}
memcpy(bc->macaddr, slirp->client_ethaddr, 6);
- } else if (preq_addr) {
- bc = request_addr(slirp, preq_addr, slirp->client_ethaddr);
+ } else if (preq_addr.s_addr != htonl(0L)) {
+ bc = request_addr(slirp, &preq_addr, slirp->client_ethaddr);
if (bc) {
- daddr.sin_addr = *preq_addr;
+ daddr.sin_addr = preq_addr;
memcpy(bc->macaddr, slirp->client_ethaddr, 6);
} else {
daddr.sin_addr.s_addr = 0;