miniupnpd/natpmp.c: Remove pointer casting, avoid possibility of unaligned memory access

This commit is contained in:
Thomas Bernard 2014-04-14 22:50:11 +02:00
parent db6de93f34
commit 67c28e7f8b
1 changed files with 19 additions and 8 deletions

View File

@ -28,6 +28,17 @@
#ifdef ENABLE_NATPMP #ifdef ENABLE_NATPMP
/* theses macros are designed to read/write unsigned short/long int
* from an unsigned char array in network order (big endian).
* Avoid pointer casting, so avoid accessing unaligned memory, which
* can crash with some cpu's */
#define READNU32(p) ((p)[0] << 24 | (p)[1] << 16 | (p)[2] << 8 | (p)[3])
#define READNU16(p) ((p)[0] << 8 | (p)[1])
#define WRITENU32(p, n) do { (p)[0] = ((n) & 0xff000000) >> 24; \
(p)[1] = ((n) & 0xff0000) >> 16; (p)[2] = ((n) & 0xff00) >> 8; \
(p)[3] = (n) & 0xff; } while(0)
#define WRITENU16(p, n) do { (p)[0] = ((n) < 0xff00) >> 8; \
(p)[1] = (n) & 0xff; } while(0)
int OpenAndConfNATPMPSocket(in_addr_t addr) int OpenAndConfNATPMPSocket(in_addr_t addr)
{ {
@ -189,7 +200,7 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
/* setting response TIME STAMP : /* setting response TIME STAMP :
* time elapsed since its port mapping table was initialized on * time elapsed since its port mapping table was initialized on
* startup or reset for any other reason */ * startup or reset for any other reason */
*((uint32_t *)(resp+4)) = htonl(time(NULL) - startup_time); WRITENU32(resp+4, time(NULL) - startup_time);
if(req[0] > 0) { if(req[0] > 0) {
/* invalid version */ /* invalid version */
syslog(LOG_WARNING, "unsupported NAT-PMP version : %u", syslog(LOG_WARNING, "unsupported NAT-PMP version : %u",
@ -213,9 +224,9 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
unsigned short iport_old; unsigned short iport_old;
unsigned int timestamp; unsigned int timestamp;
iport = ntohs(*((uint16_t *)(req+4))); iport = READNU16(req+4);
eport = ntohs(*((uint16_t *)(req+6))); eport = READNU16(req+6);
lifetime = ntohl(*((uint32_t *)(req+8))); lifetime = READNU32(req+8);
proto = (req[1]==1)?IPPROTO_UDP:IPPROTO_TCP; proto = (req[1]==1)?IPPROTO_UDP:IPPROTO_TCP;
syslog(LOG_INFO, "NAT-PMP port mapping request : " syslog(LOG_INFO, "NAT-PMP port mapping request : "
"%hu->%s:%hu %s lifetime=%us", "%hu->%s:%hu %s lifetime=%us",
@ -347,9 +358,9 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
break; break;
} }
} }
*((uint16_t *)(resp+8)) = htons(iport); /* private port */ WRITENU16(resp+8, iport); /* private port */
*((uint16_t *)(resp+10)) = htons(eport); /* public port */ WRITENU16(resp+10, eport); /* public port */
*((uint32_t *)(resp+12)) = htonl(lifetime); /* Port Mapping lifetime */ WRITENU32(resp+12, lifetime); /* Port Mapping lifetime */
} }
resplen = 16; resplen = 16;
break; break;
@ -381,7 +392,7 @@ void SendNATPMPPublicAddressChangeNotification(int * sockets, int n_sockets)
/* seconds since "start of epoch" : /* seconds since "start of epoch" :
* time elapsed since the port mapping table was initialized on * time elapsed since the port mapping table was initialized on
* startup or reset for any other reason */ * startup or reset for any other reason */
*((uint32_t *)(notif+4)) = htonl(time(NULL) - startup_time); WRITENU32(notif+4, time(NULL) - startup_time);
#ifndef MULTIPLE_EXTERNAL_IP #ifndef MULTIPLE_EXTERNAL_IP
FillPublicAddressResponse(notif, 0); FillPublicAddressResponse(notif, 0);
if(notif[3]) if(notif[3])