Mercurial > hg > freeDiameter
comparison libfdproto/messages.c @ 791:42fa209a8cc4
Attempt at fixing unaligned 64b direct memory access (sigbus on sparc)
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Thu, 12 Jul 2012 22:31:20 +0200 |
parents | edbdb35a603f |
children | 0f566e550813 |
comparison
equal
deleted
inserted
replaced
790:b38384733ad2 | 791:42fa209a8cc4 |
---|---|
1320 | 1320 |
1321 /* Following macros are used to store 32 and 64 bit fields into a buffer in network byte order */ | 1321 /* Following macros are used to store 32 and 64 bit fields into a buffer in network byte order */ |
1322 #define PUT_in_buf_32( _u32data, _bufptr ) { \ | 1322 #define PUT_in_buf_32( _u32data, _bufptr ) { \ |
1323 *(uint32_t *)(_bufptr) = htonl((uint32_t)(_u32data)); \ | 1323 *(uint32_t *)(_bufptr) = htonl((uint32_t)(_u32data)); \ |
1324 } | 1324 } |
1325 | |
1326 /* The location is not on 64b boundary, so we split the writing in two operations to avoid sigbus */ | |
1325 #define PUT_in_buf_64( _u64data, _bufptr ) { \ | 1327 #define PUT_in_buf_64( _u64data, _bufptr ) { \ |
1326 *(uint64_t *)(_bufptr) = htonll((uint64_t)(_u64data)); \ | 1328 uint64_t __v = htonll((uint64_t)(_u64data)); \ |
1329 *(uint32_t *)(_bufptr) = (uint32_t)(__v); \ | |
1330 *(((uint32_t *)(_bufptr))+1) = (uint32_t)(__v >> 32); \ | |
1327 } | 1331 } |
1328 | 1332 |
1329 /* Write a message header in the buffer */ | 1333 /* Write a message header in the buffer */ |
1330 static int bufferize_msg(unsigned char * buffer, size_t buflen, size_t * offset, struct msg * msg) | 1334 static int bufferize_msg(unsigned char * buffer, size_t buflen, size_t * offset, struct msg * msg) |
1331 { | 1335 { |
1771 case AVP_TYPE_INTEGER32: | 1775 case AVP_TYPE_INTEGER32: |
1772 avp->avp_storage.i32 = (int32_t)ntohl(*(uint32_t *)avp->avp_source); | 1776 avp->avp_storage.i32 = (int32_t)ntohl(*(uint32_t *)avp->avp_source); |
1773 break; | 1777 break; |
1774 | 1778 |
1775 case AVP_TYPE_INTEGER64: | 1779 case AVP_TYPE_INTEGER64: |
1776 avp->avp_storage.i64 = (int64_t)ntohll(*(uint64_t *)avp->avp_source); | 1780 /* the storage might not be aligned on 64b boundary, so no direct indirection here is possible */ |
1781 { | |
1782 uint64_t __stor; | |
1783 memcpy(&__stor, avp->avp_source, sizeof(__stor)); | |
1784 avp->avp_storage.i64 = (int64_t)ntohll(__stor); | |
1785 } | |
1777 break; | 1786 break; |
1778 | 1787 |
1779 case AVP_TYPE_UNSIGNED32: | 1788 case AVP_TYPE_UNSIGNED32: |
1780 case AVP_TYPE_FLOAT32: /* For float, we must not cast, or the value is changed. Instead we use implicit cast by changing the member of the union */ | 1789 case AVP_TYPE_FLOAT32: /* For float, we must not cast, or the value is changed. Instead we use implicit cast by changing the member of the union */ |
1781 avp->avp_storage.u32 = (uint32_t)ntohl(*(uint32_t *)avp->avp_source); | 1790 avp->avp_storage.u32 = (uint32_t)ntohl(*(uint32_t *)avp->avp_source); |
1782 break; | 1791 break; |
1783 | 1792 |
1784 case AVP_TYPE_UNSIGNED64: | 1793 case AVP_TYPE_UNSIGNED64: |
1785 case AVP_TYPE_FLOAT64: /* same as 32 bits */ | 1794 case AVP_TYPE_FLOAT64: /* same as 32 bits */ |
1786 avp->avp_storage.u64 = (uint64_t)ntohll(*(uint64_t *)avp->avp_source); | 1795 { |
1796 uint64_t __stor; | |
1797 memcpy(&__stor, avp->avp_source, sizeof(__stor)); | |
1798 avp->avp_storage.u64 = (uint64_t)ntohll(__stor); | |
1799 } | |
1787 break; | 1800 break; |
1788 | 1801 |
1789 } | 1802 } |
1790 | 1803 |
1791 /* The value is now set, so set the data pointer and return 0 */ | 1804 /* The value is now set, so set the data pointer and return 0 */ |