Jelajahi Sumber

fix many potential aliasing issues

ambrop7 13 tahun lalu
induk
melakukan
2185655723

+ 14 - 10
client/DPReceive.c

@@ -29,6 +29,7 @@
 
 #include <stddef.h>
 #include <limits.h>
+#include <string.h>
 
 #include <protocol/dataproto.h>
 #include <misc/byteorder.h>
@@ -71,12 +72,13 @@ static void receiver_recv_handler_send (DPReceiveReceiver *o, uint8_t *packet, i
         BLog(BLOG_WARNING, "no dataproto header");
         goto out;
     }
-    struct dataproto_header *header = (struct dataproto_header *)data;
-    data += sizeof(*header);
-    data_len -= sizeof(*header);
-    uint8_t flags = ltoh8(header->flags);
-    peerid_t from_id = ltoh16(header->from_id);
-    int num_ids = ltoh16(header->num_peer_ids);
+    struct dataproto_header header;
+    memcpy(&header, data, sizeof(header));
+    data += sizeof(header);
+    data_len -= sizeof(header);
+    uint8_t flags = ltoh8(header.flags);
+    peerid_t from_id = ltoh16(header.from_id);
+    int num_ids = ltoh16(header.num_peer_ids);
     
     // check destination ID
     if (!(num_ids == 0 || num_ids == 1)) {
@@ -85,13 +87,15 @@ static void receiver_recv_handler_send (DPReceiveReceiver *o, uint8_t *packet, i
     }
     peerid_t to_id = 0; // to remove warning
     if (num_ids == 1) {
-        if (data_len < sizeof(to_id)) {
+        if (data_len < sizeof(struct dataproto_peer_id)) {
             BLog(BLOG_WARNING, "missing destination");
             goto out;
         }
-        to_id = ((struct dataproto_peer_id *)data)->id;
-        data += sizeof(to_id);
-        data_len -= sizeof(to_id);
+        struct dataproto_peer_id id;
+        memcpy(&id, data, sizeof(id));
+        to_id = ltoh16(id.id);
+        data += sizeof(id);
+        data_len -= sizeof(id);
     }
     
     // check remaining data

+ 12 - 9
client/DataProto.c

@@ -91,8 +91,10 @@ void notifier_handler (DataProtoSink *o, uint8_t *data, int data_len)
     }
     
     // modify existing packet here
-    struct dataproto_header *header = (struct dataproto_header *)data;
-    header->flags = htol8(flags);
+    struct dataproto_header header;
+    memcpy(&header, data, sizeof(header));
+    header.flags = hton8(flags);
+    memcpy(data, &header, sizeof(header));
 }
 
 void up_job_handler (DataProtoSink *o)
@@ -489,13 +491,14 @@ void DataProtoFlow_Route (DataProtoFlow *o, int more)
     ASSERT(more == 0 || more == 1)
     struct DataProtoFlow_buffer *b = o->b;
     
-    // write header
-    struct dataproto_header *header = (struct dataproto_header *)o->source->current_buf;
-    // don't set flags, it will be set in notifier_handler
-    header->from_id = htol16(o->source_id);
-    header->num_peer_ids = htol16(1);
-    struct dataproto_peer_id *id = (struct dataproto_peer_id *)(header + 1);
-    id->id = htol16(o->dest_id);
+    // write header. Don't set flags, it will be set in notifier_handler.
+    struct dataproto_header header;
+    struct dataproto_peer_id id;
+    header.from_id = htol16(o->source_id);
+    header.num_peer_ids = htol16(1);
+    id.id = htol16(o->dest_id);
+    memcpy(o->source->current_buf, &header, sizeof(header));
+    memcpy(o->source->current_buf + sizeof(header), &id, sizeof(id));
     
     // route
     uint8_t *next_buf;

+ 7 - 4
client/DataProtoKeepaliveSource.c

@@ -27,6 +27,8 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <string.h>
+
 #include <protocol/dataproto.h>
 #include <misc/byteorder.h>
 
@@ -36,10 +38,11 @@ static void output_handler_recv (DataProtoKeepaliveSource *o, uint8_t *data)
 {
     DebugObject_Access(&o->d_obj);
     
-    struct dataproto_header *header = (struct dataproto_header *)data;
-    header->flags = htol8(0);
-    header->from_id = htol16(0);
-    header->num_peer_ids = htol16(0);
+    struct dataproto_header header;
+    header.flags = htol8(0);
+    header.from_id = htol16(0);
+    header.num_peer_ids = htol16(0);
+    memcpy(data, &header, sizeof(header));
     
     // finish packet
     PacketRecvInterface_Done(&o->output, sizeof(struct dataproto_header));

+ 6 - 5
client/FragmentProtoAssembler.c

@@ -293,12 +293,13 @@ static void process_input (FragmentProtoAssembler *o)
             PeerLog(o, BLOG_INFO, "too little data for chunk header");
             break;
         }
-        struct fragmentproto_chunk_header *header = (struct fragmentproto_chunk_header *)(o->in + o->in_pos);
+        struct fragmentproto_chunk_header header;
+        memcpy(&header, o->in + o->in_pos, sizeof(header));
         o->in_pos += sizeof(struct fragmentproto_chunk_header);
-        fragmentproto_frameid frame_id = ltoh16(header->frame_id);
-        int chunk_start = ltoh16(header->chunk_start);
-        int chunk_len = ltoh16(header->chunk_len);
-        int is_last = ltoh8(header->is_last);
+        fragmentproto_frameid frame_id = ltoh16(header.frame_id);
+        int chunk_start = ltoh16(header.chunk_start);
+        int chunk_len = ltoh16(header.chunk_len);
+        int is_last = ltoh8(header.is_last);
         
         // check is_last field
         if (!(is_last == 0 || is_last == 1)) {

+ 6 - 5
client/FragmentProtoDisassembler.c

@@ -54,11 +54,12 @@ static void write_chunks (FragmentProtoDisassembler *o)
         }
         
         // write chunk header
-        struct fragmentproto_chunk_header *header = (struct fragmentproto_chunk_header *)(o->out + o->out_used);
-        header->frame_id = htol16(o->frame_id);
-        header->chunk_start = htol16(o->in_used);
-        header->chunk_len = htol16(chunk_len);
-        header->is_last = (chunk_len == IN_AVAIL);
+        struct fragmentproto_chunk_header header;
+        header.frame_id = htol16(o->frame_id);
+        header.chunk_start = htol16(o->in_used);
+        header.chunk_len = htol16(chunk_len);
+        header.is_last = (chunk_len == IN_AVAIL);
+        memcpy(o->out + o->out_used, &header, sizeof(header));
         
         // write chunk data
         memcpy(o->out + o->out_used + sizeof(struct fragmentproto_chunk_header), o->in + o->in_used, chunk_len);

+ 44 - 35
client/FrameDecider.c

@@ -388,23 +388,24 @@ void FrameDecider_AnalyzeAndDecide (FrameDecider *o, const uint8_t *frame, int f
     if (len < sizeof(struct ethernet_header)) {
         return;
     }
-    struct ethernet_header *eh = (struct ethernet_header *)pos;
+    struct ethernet_header eh;
+    memcpy(&eh, pos, sizeof(eh));
     pos += sizeof(struct ethernet_header);
     len -= sizeof(struct ethernet_header);
     
     int is_igmp = 0;
     
-    switch (ntoh16(eh->type)) {
+    switch (ntoh16(eh.type)) {
         case ETHERTYPE_IPV4: {
             // check IPv4 header
-            struct ipv4_header *ipv4_header;
+            struct ipv4_header ipv4_header;
             if (!ipv4_check((uint8_t *)pos, len, &ipv4_header, (uint8_t **)&pos, &len)) {
                 BLog(BLOG_INFO, "decide: wrong IP packet");
                 goto out;
             }
             
             // check if it's IGMP
-            if (ntoh8(ipv4_header->protocol) != IPV4_PROTOCOL_IGMP) {
+            if (ntoh8(ipv4_header.protocol) != IPV4_PROTOCOL_IGMP) {
                 goto out;
             }
             
@@ -416,31 +417,34 @@ void FrameDecider_AnalyzeAndDecide (FrameDecider *o, const uint8_t *frame, int f
                 BLog(BLOG_INFO, "decide: IGMP: short packet");
                 goto out;
             }
-            struct igmp_base *igmp_base = (struct igmp_base *)pos;
+            struct igmp_base igmp_base;
+            memcpy(&igmp_base, pos, sizeof(igmp_base));
             pos += sizeof(struct igmp_base);
             len -= sizeof(struct igmp_base);
             
-            switch (ntoh8(igmp_base->type)) {
+            switch (ntoh8(igmp_base.type)) {
                 case IGMP_TYPE_MEMBERSHIP_QUERY: {
-                    if (len == sizeof(struct igmp_v2_extra) && ntoh8(igmp_base->max_resp_code) != 0) {
+                    if (len == sizeof(struct igmp_v2_extra) && ntoh8(igmp_base.max_resp_code) != 0) {
                         // V2 query
-                        struct igmp_v2_extra *query = (struct igmp_v2_extra *)pos;
+                        struct igmp_v2_extra query;
+                        memcpy(&query, pos, sizeof(query));
                         pos += sizeof(struct igmp_v2_extra);
                         len -= sizeof(struct igmp_v2_extra);
                         
-                        if (ntoh32(query->group) != 0) {
+                        if (ntoh32(query.group) != 0) {
                             // got a Group-Specific Query, lower group timers to LMQT
-                            lower_group_timers_to_lmqt(o, query->group);
+                            lower_group_timers_to_lmqt(o, query.group);
                         }
                     }
                     else if (len >= sizeof(struct igmp_v3_query_extra)) {
                         // V3 query
-                        struct igmp_v3_query_extra *query = (struct igmp_v3_query_extra *)pos;
+                        struct igmp_v3_query_extra query;
+                        memcpy(&query, pos, sizeof(query));
                         pos += sizeof(struct igmp_v3_query_extra);
                         len -= sizeof(struct igmp_v3_query_extra);
                         
                         // iterate sources
-                        uint16_t num_sources = ntoh16(query->number_of_sources);
+                        uint16_t num_sources = ntoh16(query.number_of_sources);
                         int i;
                         for (i = 0; i < num_sources; i++) {
                             // check source
@@ -452,9 +456,9 @@ void FrameDecider_AnalyzeAndDecide (FrameDecider *o, const uint8_t *frame, int f
                             len -= sizeof(struct igmp_source);
                         }
                         
-                        if (ntoh32(query->group) != 0 && num_sources == 0) {
+                        if (ntoh32(query.group) != 0 && num_sources == 0) {
                             // got a Group-Specific Query, lower group timers to LMQT
-                            lower_group_timers_to_lmqt(o, query->group);
+                            lower_group_timers_to_lmqt(o, query.group);
                         }
                     }
                 } break;
@@ -468,16 +472,16 @@ out:;
     const uint8_t multicast_mac_header[] = {0x01, 0x00, 0x5e};
     
     // if it's broadcast or IGMP, flood it
-    if (is_igmp || !memcmp(eh->dest, broadcast_mac, sizeof(broadcast_mac))) {
+    if (is_igmp || !memcmp(eh.dest, broadcast_mac, sizeof(broadcast_mac))) {
         o->decide_state = DECIDE_STATE_FLOOD;
         o->decide_flood_current = LinkedList1_GetFirst(&o->peers_list);
         return;
     }
     
     // if it's multicast, forward to all peers with the given sig
-    if (!memcmp(eh->dest, multicast_mac_header, sizeof(multicast_mac_header))) {
+    if (!memcmp(eh.dest, multicast_mac_header, sizeof(multicast_mac_header))) {
         // extract group's sig from destination MAC
-        uint32_t sig = compute_sig_for_mac(eh->dest);
+        uint32_t sig = compute_sig_for_mac(eh.dest);
         
         // look up the sig in multicast tree
         struct _FrameDecider_group_entry *master = FDMulticastTree_LookupExact(&o->multicast_tree, 0, sig);
@@ -492,7 +496,7 @@ out:;
     }
     
     // look for MAC entry
-    struct _FrameDecider_mac_entry *entry = FDMacsTree_LookupExact(&o->macs_tree, 0, eh->dest);
+    struct _FrameDecider_mac_entry *entry = FDMacsTree_LookupExact(&o->macs_tree, 0, eh.dest);
     if (entry) {
         o->decide_state = DECIDE_STATE_UNICAST;
         o->decide_unicast_peer = entry->peer;
@@ -675,24 +679,25 @@ void FrameDeciderPeer_Analyze (FrameDeciderPeer *o, const uint8_t *frame, int fr
     if (len < sizeof(struct ethernet_header)) {
         goto out;
     }
-    struct ethernet_header *eh = (struct ethernet_header *)pos;
+    struct ethernet_header eh;
+    memcpy(&eh, pos, sizeof(eh));
     pos += sizeof(struct ethernet_header);
     len -= sizeof(struct ethernet_header);
     
     // register source MAC address with this peer
-    add_mac_to_peer(o, eh->source);
+    add_mac_to_peer(o, eh.source);
     
-    switch (ntoh16(eh->type)) {
+    switch (ntoh16(eh.type)) {
         case ETHERTYPE_IPV4: {
             // check IPv4 header
-            struct ipv4_header *ipv4_header;
+            struct ipv4_header ipv4_header;
             if (!ipv4_check((uint8_t *)pos, len, &ipv4_header, (uint8_t **)&pos, &len)) {
                 PeerLog(o, BLOG_INFO, "analyze: wrong IP packet");
                 goto out;
             }
             
             // check if it's IGMP
-            if (ntoh8(ipv4_header->protocol) != IPV4_PROTOCOL_IGMP) {
+            if (ntoh8(ipv4_header.protocol) != IPV4_PROTOCOL_IGMP) {
                 goto out;
             }
             
@@ -701,23 +706,25 @@ void FrameDeciderPeer_Analyze (FrameDeciderPeer *o, const uint8_t *frame, int fr
                 PeerLog(o, BLOG_INFO, "analyze: IGMP: short packet");
                 goto out;
             }
-            struct igmp_base *igmp_base = (struct igmp_base *)pos;
+            struct igmp_base igmp_base;
+            memcpy(&igmp_base, pos, sizeof(igmp_base));
             pos += sizeof(struct igmp_base);
             len -= sizeof(struct igmp_base);
             
-            switch (ntoh8(igmp_base->type)) {
+            switch (ntoh8(igmp_base.type)) {
                 case IGMP_TYPE_V2_MEMBERSHIP_REPORT: {
                     // check extra
                     if (len < sizeof(struct igmp_v2_extra)) {
                         PeerLog(o, BLOG_INFO, "analyze: IGMP: short v2 report");
                         goto out;
                     }
-                    struct igmp_v2_extra *report = (struct igmp_v2_extra *)pos;
+                    struct igmp_v2_extra report;
+                    memcpy(&report, pos, sizeof(report));
                     pos += sizeof(struct igmp_v2_extra);
                     len -= sizeof(struct igmp_v2_extra);
                     
                     // add to group
-                    add_group_to_peer(o, report->group);
+                    add_group_to_peer(o, report.group);
                 } break;
                 
                 case IGMP_TYPE_V3_MEMBERSHIP_REPORT: {
@@ -726,24 +733,26 @@ void FrameDeciderPeer_Analyze (FrameDeciderPeer *o, const uint8_t *frame, int fr
                         PeerLog(o, BLOG_INFO, "analyze: IGMP: short v3 report");
                         goto out;
                     }
-                    struct igmp_v3_report_extra *report = (struct igmp_v3_report_extra *)pos;
+                    struct igmp_v3_report_extra report;
+                    memcpy(&report, pos, sizeof(report));
                     pos += sizeof(struct igmp_v3_report_extra);
                     len -= sizeof(struct igmp_v3_report_extra);
                     
                     // iterate records
-                    uint16_t num_records = ntoh16(report->number_of_group_records);
+                    uint16_t num_records = ntoh16(report.number_of_group_records);
                     for (int i = 0; i < num_records; i++) {
                         // check record
                         if (len < sizeof(struct igmp_v3_report_record)) {
                             PeerLog(o, BLOG_INFO, "analyze: IGMP: short record header");
                             goto out;
                         }
-                        struct igmp_v3_report_record *record = (struct igmp_v3_report_record *)pos;
+                        struct igmp_v3_report_record record;
+                        memcpy(&record, pos, sizeof(record));
                         pos += sizeof(struct igmp_v3_report_record);
                         len -= sizeof(struct igmp_v3_report_record);
                         
                         // iterate sources
-                        uint16_t num_sources = ntoh16(record->number_of_sources);
+                        uint16_t num_sources = ntoh16(record.number_of_sources);
                         int j;
                         for (j = 0; j < num_sources; j++) {
                             // check source
@@ -756,7 +765,7 @@ void FrameDeciderPeer_Analyze (FrameDeciderPeer *o, const uint8_t *frame, int fr
                         }
                         
                         // check aux data
-                        uint16_t aux_len = ntoh16(record->aux_data_len);
+                        uint16_t aux_len = ntoh16(record.aux_data_len);
                         if (len < aux_len) {
                             PeerLog(o, BLOG_INFO, "analyze: IGMP: short record aux data");
                             goto out;
@@ -764,16 +773,16 @@ void FrameDeciderPeer_Analyze (FrameDeciderPeer *o, const uint8_t *frame, int fr
                         pos += aux_len;
                         len -= aux_len;
                         
-                        switch (record->type) {
+                        switch (record.type) {
                             case IGMP_RECORD_TYPE_MODE_IS_INCLUDE:
                             case IGMP_RECORD_TYPE_CHANGE_TO_INCLUDE_MODE:
                                 if (num_sources != 0) {
-                                    add_group_to_peer(o, record->group);
+                                    add_group_to_peer(o, record.group);
                                 }
                                 break;
                             case IGMP_RECORD_TYPE_MODE_IS_EXCLUDE:
                             case IGMP_RECORD_TYPE_CHANGE_TO_EXCLUDE_MODE:
-                                add_group_to_peer(o, record->group);
+                                add_group_to_peer(o, record.group);
                                 break;
                         }
                     }

+ 7 - 4
client/SCOutmsgEncoder.c

@@ -29,6 +29,7 @@
 
 #include <stddef.h>
 #include <limits.h>
+#include <string.h>
 
 #include <misc/balign.h>
 #include <misc/debug.h>
@@ -53,12 +54,14 @@ static void input_handler_done (SCOutmsgEncoder *o, int in_len)
     ASSERT(o->output_packet)
     
     // write SC header
-    struct sc_header *header = (struct sc_header *)o->output_packet;
-    header->type = htol8(SCID_OUTMSG);
+    struct sc_header header;
+    header.type = htol8(SCID_OUTMSG);
+    memcpy(o->output_packet, &header, sizeof(header));
     
     // write outmsg
-    struct sc_client_outmsg *outmsg = (struct sc_client_outmsg *)(header + 1);
-    outmsg->clientid = htol16(o->peer_id);
+    struct sc_client_outmsg outmsg;
+    outmsg.clientid = htol16(o->peer_id);
+    memcpy(o->output_packet + sizeof(header), &outmsg, sizeof(outmsg));
     
     // finish output packet
     o->output_packet = NULL;

+ 4 - 3
client/SPProtoDecoder.c

@@ -123,9 +123,10 @@ static void decode_work_func (SPProtoDecoder *o)
     // check OTP
     if (SPPROTO_HAVE_OTP(o->sp_params)) {
         // remember seed and OTP (can't check from here)
-        struct spproto_otpdata *header_otpd = (struct spproto_otpdata *)(header + SPPROTO_HEADER_OTPDATA_OFF(o->sp_params));
-        o->tw_out_seed_id = ltoh16(header_otpd->seed_id);
-        o->tw_out_otp = header_otpd->otp;
+        struct spproto_otpdata header_otpd;
+        memcpy(&header_otpd, header + SPPROTO_HEADER_OTPDATA_OFF(o->sp_params), sizeof(header_otpd));
+        o->tw_out_seed_id = ltoh16(header_otpd.seed_id);
+        o->tw_out_otp = header_otpd.otp;
     }
     
     // check hash

+ 4 - 3
client/SPProtoEncoder.c

@@ -103,9 +103,10 @@ static void encode_work_func (SPProtoEncoder *o)
     
     // write OTP
     if (SPPROTO_HAVE_OTP(o->sp_params)) {
-        struct spproto_otpdata *header_otpd = (struct spproto_otpdata *)(header + SPPROTO_HEADER_OTPDATA_OFF(o->sp_params));
-        header_otpd->seed_id = htol16(o->tw_seed_id);
-        header_otpd->otp = o->tw_otp;
+        struct spproto_otpdata header_otpd;
+        header_otpd.seed_id = htol16(o->tw_seed_id);
+        header_otpd.otp = o->tw_otp;
+        memcpy(header + SPPROTO_HEADER_OTPDATA_OFF(o->sp_params), &header_otpd, sizeof(header_otpd));
     }
     
     // write hash

+ 9 - 6
client/client.c

@@ -1877,12 +1877,15 @@ void peer_resetpeer (struct peer_data *peer)
     peer_free_chat(peer);
     
     // build resetpeer packet
-    struct packetproto_header *pp_header = (struct packetproto_header *)peer->resetpeer_packet;
-    pp_header->len = htol16(sizeof(struct sc_header) + sizeof(struct sc_client_resetpeer));
-    struct sc_header *sc_header = (struct sc_header *)(pp_header + 1);
-    sc_header->type = htol8(SCID_RESETPEER);
-    struct sc_client_resetpeer *sc_resetpeer = (struct sc_client_resetpeer *)(sc_header + 1);
-    sc_resetpeer->clientid = htol16(peer->id);
+    struct packetproto_header pp_header;
+    struct sc_header sc_header;
+    struct sc_client_resetpeer sc_resetpeer;
+    pp_header.len = htol16(sizeof(struct sc_header) + sizeof(struct sc_client_resetpeer));
+    sc_header.type = htol8(SCID_RESETPEER);
+    sc_resetpeer.clientid = htol16(peer->id);
+    memcpy(peer->resetpeer_packet, &pp_header, sizeof(pp_header));
+    memcpy(peer->resetpeer_packet + sizeof(pp_header), &sc_header, sizeof(sc_header));
+    memcpy(peer->resetpeer_packet + sizeof(pp_header) + sizeof(sc_header), &sc_resetpeer, sizeof(sc_resetpeer));
     
     // init resetpeer sourse
     SinglePacketSource_Init(&peer->resetpeer_source, peer->resetpeer_packet, sizeof(peer->resetpeer_packet), BReactor_PendingGroup(&ss));

+ 14 - 13
dhcpclient/DHCPIpUdpDecoder.c

@@ -28,6 +28,7 @@
  */
 
 #include <limits.h>
+#include <string.h>
 
 #include <misc/ipv4_proto.h>
 #include <misc/udp_proto.h>
@@ -48,7 +49,7 @@ static void input_handler_send (DHCPIpUdpDecoder *o, uint8_t *data, int data_len
     ASSERT(data_len >= 0)
     DebugObject_Access(&o->d_obj);
     
-    struct ipv4_header *iph;
+    struct ipv4_header iph;
     uint8_t *pl;
     int pl_len;
     
@@ -56,43 +57,43 @@ static void input_handler_send (DHCPIpUdpDecoder *o, uint8_t *data, int data_len
         goto fail;
     }
     
-    if (ntoh8(iph->protocol) != IPV4_PROTOCOL_UDP) {
+    if (ntoh8(iph.protocol) != IPV4_PROTOCOL_UDP) {
         goto fail;
     }
     
     if (pl_len < sizeof(struct udp_header)) {
         goto fail;
     }
-    struct udp_header *udph = (void *)pl;
+    struct udp_header udph;
+    memcpy(&udph, pl, sizeof(udph));
     
-    if (ntoh16(udph->source_port) != DHCP_SERVER_PORT) {
+    if (ntoh16(udph.source_port) != DHCP_SERVER_PORT) {
         goto fail;
     }
     
-    if (ntoh16(udph->dest_port) != DHCP_CLIENT_PORT) {
+    if (ntoh16(udph.dest_port) != DHCP_CLIENT_PORT) {
         goto fail;
     }
     
-    int udph_length = ntoh16(udph->length);
-    if (udph_length < sizeof(*udph)) {
+    int udph_length = ntoh16(udph.length);
+    if (udph_length < sizeof(udph)) {
         goto fail;
     }
     if (udph_length > data_len - (pl - data)) {
         goto fail;
     }
     
-    if (ntoh16(udph->checksum) != 0) {
-        uint16_t checksum_in_packet = udph->checksum;
-        udph->checksum = 0;
-        uint16_t checksum_computed = udp_checksum((uint8_t *)udph, udph_length, iph->source_address, iph->destination_address);
-        udph->checksum = checksum_in_packet;
+    if (ntoh16(udph.checksum) != 0) {
+        uint16_t checksum_in_packet = udph.checksum;
+        udph.checksum = 0;
+        uint16_t checksum_computed = udp_checksum(&udph, pl + sizeof(udph), udph_length - sizeof(udph), iph.source_address, iph.destination_address);
         if (checksum_in_packet != checksum_computed) {
             goto fail;
         }
     }
     
     // pass payload to output
-    PacketPassInterface_Sender_Send(o->output, (uint8_t *)(udph + 1), udph_length - sizeof(*udph));
+    PacketPassInterface_Sender_Send(o->output, pl + sizeof(udph), udph_length - sizeof(udph));
     
     return;
     

+ 9 - 10
dhcpclient/DHCPIpUdpEncoder.c

@@ -28,6 +28,8 @@
  */
 
 #include <limits.h>
+#include <string.h>
+#include <stddef.h>
 
 #include <misc/ipv4_proto.h>
 #include <misc/udp_proto.h>
@@ -58,10 +60,10 @@ static void input_handler_done (DHCPIpUdpEncoder *o, int data_len)
 {
     DebugObject_Access(&o->d_obj);
     
-    struct combined_header *header = (void *)o->data;
+    struct combined_header header;
     
     // write IP header
-    struct ipv4_header *iph = &header->ip;
+    struct ipv4_header *iph = &header.ip;
     iph->version4_ihl4 = IPV4_MAKE_VERSION_IHL(sizeof(*iph));
     iph->ds = hton8(0);
     iph->total_length = hton16(sizeof(struct combined_header) + data_len);
@@ -72,21 +74,18 @@ static void input_handler_done (DHCPIpUdpEncoder *o, int data_len)
     iph->checksum = hton16(0);
     iph->source_address = hton32(0x00000000);
     iph->destination_address = hton32(0xFFFFFFFF);
-    
-    // compute and write IP header checksum
-    uint32_t checksum = ipv4_checksum((uint8_t *)iph, sizeof(*iph));
-    iph->checksum = checksum;
+    iph->checksum = ipv4_checksum(iph, NULL, 0);
     
     // write UDP header
-    struct udp_header *udph = &header->udp;
+    struct udp_header *udph = &header.udp;
     udph->source_port = hton16(DHCP_CLIENT_PORT);
     udph->dest_port = hton16(DHCP_SERVER_PORT);
     udph->length = hton16(sizeof(*udph) + data_len);
     udph->checksum = hton16(0);
+    udph->checksum = udp_checksum(udph, o->data + sizeof(struct combined_header), data_len, iph->source_address, iph->destination_address);
     
-    // compute checksum
-    checksum = udp_checksum((uint8_t *)udph, sizeof(*udph) + data_len, iph->source_address, iph->destination_address);
-    udph->checksum = checksum;
+    // write header
+    memcpy(o->data, &header, sizeof(header));
     
     // finish packet
     PacketRecvInterface_Done(&o->output, sizeof(struct combined_header) + data_len);

+ 6 - 4
flooder/flooder.c

@@ -656,11 +656,13 @@ void flood_source_handler_recv (void *user, uint8_t *data)
     
     BLog(BLOG_INFO, "message to %d", (int)peer_id);
     
-    struct sc_header *header = (struct sc_header *)data;
-    header->type = SCID_OUTMSG;
+    struct sc_header header;
+    header.type = SCID_OUTMSG;
+    memcpy(data, &header, sizeof(header));
     
-    struct sc_client_outmsg *msg = (struct sc_client_outmsg *)(data + sizeof(struct sc_header));
-    msg->clientid = htol16(peer_id);
+    struct sc_client_outmsg omsg;
+    omsg.clientid = htol16(peer_id);
+    memcpy(data + sizeof(header), &omsg, sizeof(omsg));
     
     memset(data + sizeof(struct sc_header) + sizeof(struct sc_client_outmsg), 0, SC_MAX_MSGLEN);
     

+ 3 - 2
flow/PacketProtoDecoder.c

@@ -55,10 +55,11 @@ void process_data (PacketProtoDecoder *enc)
         if (left < sizeof(struct packetproto_header)) {
             break;
         }
-        struct packetproto_header *header = (struct packetproto_header *)data;
+        struct packetproto_header header;
+        memcpy(&header, data, sizeof(header));
         data += sizeof(struct packetproto_header);
         left -= sizeof(struct packetproto_header);
-        int data_len = ltoh16(header->len);
+        int data_len = ltoh16(header.len);
         
         // check data length
         if (data_len > enc->output_mtu) {

+ 4 - 1
flow/PacketProtoEncoder.c

@@ -28,6 +28,7 @@
  */
 
 #include <stddef.h>
+#include <string.h>
 
 #include <protocol/packetproto.h>
 #include <misc/balign.h>
@@ -53,7 +54,9 @@ static void input_handler_done (PacketProtoEncoder *enc, int in_len)
     DebugObject_Access(&enc->d_obj);
     
     // write length
-    ((struct packetproto_header *)enc->output_packet)->len = htol16(in_len);
+    struct packetproto_header pp;
+    pp.len = htol16(in_len);
+    memcpy(enc->output_packet, &pp, sizeof(pp));
     
     // finish output packet
     enc->output_packet = NULL;

+ 22 - 14
misc/ipv4_proto.h

@@ -35,6 +35,7 @@
 #define BADVPN_MISC_IPV4_PROTO_H
 
 #include <stdint.h>
+#include <string.h>
 
 #include <misc/debug.h>
 #include <misc/byteorder.h>
@@ -68,14 +69,19 @@ B_END_PACKED
 
 #define IPV4_MAKE_VERSION_IHL(size) (((size)/4) + (4 << 4))
 
-static uint16_t ipv4_checksum (uint8_t *ip_hdr, uint16_t len)
+static uint16_t ipv4_checksum (const struct ipv4_header *header, const char *extra, uint16_t extra_len)
 {
-    ASSERT(len % 2 == 0)
+    ASSERT(extra_len % 2 == 0)
+    ASSERT(extra_len == 0 || extra)
     
     uint32_t t = 0;
     
-    for (uint16_t i = 0; i < len / 2; i++) {
-        t += badvpn_read_be16((const char *)ip_hdr + 2 * i);
+    for (uint16_t i = 0; i < sizeof(*header) / 2; i++) {
+        t += badvpn_read_be16((const char *)header + 2 * i);
+    }
+    
+    for (uint16_t i = 0; i < extra_len / 2; i++) {
+        t += badvpn_read_be16((const char *)extra + 2 * i);
     }
     
     while (t >> 16) {
@@ -85,23 +91,26 @@ static uint16_t ipv4_checksum (uint8_t *ip_hdr, uint16_t len)
     return hton16(~t);
 }
 
-static int ipv4_check (uint8_t *data, int data_len, struct ipv4_header **out_header, uint8_t **out_payload, int *out_payload_len)
+static int ipv4_check (uint8_t *data, int data_len, struct ipv4_header *out_header, uint8_t **out_payload, int *out_payload_len)
 {
     ASSERT(data_len >= 0)
+    ASSERT(out_header)
+    ASSERT(out_payload)
+    ASSERT(out_payload_len)
     
     // check base header
     if (data_len < sizeof(struct ipv4_header)) {
         return 0;
     }
-    struct ipv4_header *header = (struct ipv4_header *)data;
+    memcpy(out_header, data, sizeof(*out_header));
     
     // check version
-    if (IPV4_GET_VERSION(*header) != 4) {
+    if (IPV4_GET_VERSION(*out_header) != 4) {
         return 0;
     }
     
     // check options
-    uint16_t header_len = IPV4_GET_IHL(*header) * 4;
+    uint16_t header_len = IPV4_GET_IHL(*out_header) * 4;
     if (header_len < sizeof(struct ipv4_header)) {
         return 0;
     }
@@ -110,7 +119,7 @@ static int ipv4_check (uint8_t *data, int data_len, struct ipv4_header **out_hea
     }
     
     // check total length
-    uint16_t total_length = ntoh16(header->total_length);
+    uint16_t total_length = ntoh16(out_header->total_length);
     if (total_length < header_len) {
         return 0;
     }
@@ -119,15 +128,14 @@ static int ipv4_check (uint8_t *data, int data_len, struct ipv4_header **out_hea
     }
     
     // check checksum
-    uint16_t checksum_in_packet = header->checksum;
-    header->checksum = hton16(0);
-    uint16_t checksum_computed = ipv4_checksum(data, header_len);
-    header->checksum = checksum_in_packet;
+    uint16_t checksum_in_packet = out_header->checksum;
+    out_header->checksum = hton16(0);
+    uint16_t checksum_computed = ipv4_checksum(out_header, (char *)data + sizeof(*out_header), header_len - sizeof(*out_header));
+    out_header->checksum = checksum_in_packet;
     if (checksum_in_packet != checksum_computed) {
         return 0;
     }
     
-    *out_header = header;
     *out_payload = data + header_len;
     *out_payload_len = total_length - header_len;
     

+ 15 - 13
misc/udp_proto.h

@@ -50,39 +50,41 @@ struct udp_header {
 } B_PACKED;
 B_END_PACKED
 
-static uint32_t udp_checksum_summer (uint8_t *data, uint16_t len)
+static uint32_t udp_checksum_summer (const char *data, uint16_t len)
 {
     ASSERT(len % 2 == 0)
     
     uint32_t t = 0;
     
     for (uint16_t i = 0; i < len / 2; i++) {
-        t += badvpn_read_be16((const char *)data + 2 * i);
+        t += badvpn_read_be16(data + 2 * i);
     }
     
     return t;
 }
 
-static uint16_t udp_checksum (uint8_t *udp, uint16_t len, uint32_t source_addr, uint32_t dest_addr)
+static uint16_t udp_checksum (const struct udp_header *header, const uint8_t *payload, uint16_t payload_len, uint32_t source_addr, uint32_t dest_addr)
 {
     uint32_t t = 0;
     
-    t += udp_checksum_summer((uint8_t *)&source_addr, sizeof(source_addr));
-    t += udp_checksum_summer((uint8_t *)&dest_addr, sizeof(dest_addr));
+    t += udp_checksum_summer((char *)&source_addr, sizeof(source_addr));
+    t += udp_checksum_summer((char *)&dest_addr, sizeof(dest_addr));
     
     uint16_t x;
     x = hton16(IPV4_PROTOCOL_UDP);
-    t += udp_checksum_summer((uint8_t *)&x, sizeof(x));
-    x = hton16(len);
-    t += udp_checksum_summer((uint8_t *)&x, sizeof(x));
+    t += udp_checksum_summer((char *)&x, sizeof(x));
+    x = hton16(sizeof(*header) + payload_len);
+    t += udp_checksum_summer((char *)&x, sizeof(x));
     
-    if (len % 2 == 0) {
-        t += udp_checksum_summer(udp, len);
+    t += udp_checksum_summer((const char *)header, sizeof(*header));
+    
+    if (payload_len % 2 == 0) {
+        t += udp_checksum_summer((const char *)payload, payload_len);
     } else {
-        t += udp_checksum_summer(udp, len - 1);
+        t += udp_checksum_summer((const char *)payload, payload_len - 1);
         
-        x = hton16(((uint16_t)udp[len - 1]) << 8);
-        t += udp_checksum_summer((uint8_t *)&x, sizeof(x));
+        x = hton16(((uint16_t)payload[payload_len - 1]) << 8);
+        t += udp_checksum_summer((char *)&x, sizeof(x));
     }
     
     while (t >> 16) {

+ 12 - 9
ncd/extra/NCDRequestClient.c

@@ -32,6 +32,7 @@
 #include <stdint.h>
 #include <limits.h>
 #include <inttypes.h>
+#include <string.h>
 
 #include <misc/byteorder.h>
 #include <misc/expstring.h>
@@ -344,10 +345,11 @@ static int build_requestproto_packet (uint32_t request_id, uint32_t type, NCDVal
     
     uint8_t *packet = (uint8_t *)ExpString_Get(&str);
     
-    struct header *header = (void *)packet;
-    header->pp.len = htol16(len - sizeof(struct packetproto_header));
-    header->rp.request_id = htol32(request_id);
-    header->rp.type = htol32(type);
+    struct header header;
+    header.pp.len = htol16(len - sizeof(struct packetproto_header));
+    header.rp.request_id = htol32(request_id);
+    header.rp.type = htol32(type);
+    memcpy(packet, &header, sizeof(header));
     
     *out_data = packet;
     *out_len = len;
@@ -366,12 +368,13 @@ static void build_nodata_packet (uint32_t request_id, uint32_t type, uint8_t *da
         struct requestproto_header rp;
     } __attribute__((packed));
     
-    struct header *header = (void *)data;
-    header->pp.len = htol16(sizeof(header->rp));
-    header->rp.request_id = htol32(request_id);
-    header->rp.type = htol32(type);
+    struct header header;
+    header.pp.len = htol16(sizeof(header.rp));
+    header.rp.request_id = htol32(request_id);
+    header.rp.type = htol32(type);
+    memcpy(data, &header, sizeof(header));
     
-    *out_len = sizeof(*header);
+    *out_len = sizeof(header);
 }
 
 static int req_is_aborted (struct NCDRequestClient_req *req)

+ 10 - 6
ncd/modules/sys_request_server.c

@@ -565,9 +565,10 @@ static struct reply * reply_init (struct connection *c, uint32_t request_id, NCD
     
     r->send_buf = (uint8_t *)ExpString_Get(&str);
     
-    struct reply_header *header = (void *)r->send_buf;
-    header->pp.len = htol16(len - sizeof(header->pp));
-    header->rp.request_id = htol32(request_id);
+    struct reply_header header;
+    header.pp.len = htol16(len - sizeof(header.pp));
+    header.rp.request_id = htol32(request_id);
+    memcpy(r->send_buf, &header, sizeof(header));
     
     return r;
     
@@ -588,9 +589,12 @@ static void reply_start (struct reply *r, uint32_t type)
         struct requestproto_header rp;
     } __attribute__((packed));
     
-    struct reply_header *header = (void *)r->send_buf;
-    header->rp.type = htol32(type);
-    int len = ltoh16(header->pp.len) + sizeof(struct packetproto_header);
+    struct reply_header header;
+    memcpy(&header, r->send_buf, sizeof(header));
+    header.rp.type = htol32(type);
+    memcpy(r->send_buf, &header, sizeof(header));
+    
+    int len = ltoh16(header.pp.len) + sizeof(struct packetproto_header);
     
     PacketPassInterface_Sender_Send(r->send_qflow_if, r->send_buf, len);
 }

+ 48 - 33
server/server.c

@@ -1333,8 +1333,9 @@ void client_end_control_packet (struct client_data *client, uint8_t type)
     ASSERT(client->output_control_packet_len <= SC_MAX_PAYLOAD)
     
     // write header
-    struct sc_header *header = (struct sc_header *)client->output_control_packet;
-    header->type = htol8(type);
+    struct sc_header header;
+    header.type = htol8(type);
+    memcpy(client->output_control_packet, &header, sizeof(header));
     
     // finish writing packet
     BufferWriter_EndPacket(client->output_control_input, sizeof(struct sc_header) + client->output_control_packet_len);
@@ -1367,14 +1368,16 @@ int client_send_newclient (struct client_data *client, struct client_data *nc, i
         cert_len = (client->version == SC_OLDVERSION_BROKENCERT ?  nc->cert_old_len : nc->cert_len);
     }
     
-    struct sc_server_newclient *pack;
-    if (client_start_control_packet(client, (void **)&pack, sizeof(struct sc_server_newclient) + cert_len) < 0) {
+    struct sc_server_newclient omsg;
+    void *pack;
+    if (client_start_control_packet(client, &pack, sizeof(omsg) + cert_len) < 0) {
         return -1;
     }
-    pack->id = htol16(nc->id);
-    pack->flags = htol16(flags);
+    omsg.id = htol16(nc->id);
+    omsg.flags = htol16(flags);
+    memcpy(pack, &omsg, sizeof(omsg));
     if (cert_len > 0) {
-        memcpy(pack + 1, cert_data, cert_len);
+        memcpy((char *)pack + sizeof(omsg), cert_data, cert_len);
     }
     client_end_control_packet(client, SCID_NEWCLIENT);
     
@@ -1386,11 +1389,13 @@ int client_send_endclient (struct client_data *client, peerid_t end_id)
     ASSERT(client->initstatus == INITSTATUS_COMPLETE)
     ASSERT(!client->dying)
     
-    struct sc_server_endclient *pack;
-    if (client_start_control_packet(client, (void **)&pack, sizeof(struct sc_server_endclient)) < 0) {
+    struct sc_server_endclient omsg;
+    void *pack;
+    if (client_start_control_packet(client, &pack, sizeof(omsg)) < 0) {
         return -1;
     }
-    pack->id = htol16(end_id);
+    omsg.id = htol16(end_id);
+    memcpy(pack, &omsg, sizeof(omsg));
     client_end_control_packet(client, SCID_ENDCLIENT);
     
     return 0;
@@ -1415,10 +1420,11 @@ void client_input_handler_send (struct client_data *client, uint8_t *data, int d
         client_remove(client);
         return;
     }
-    struct sc_header *header = (struct sc_header *)data;
-    data += sizeof(*header);
-    data_len -= sizeof(*header);
-    uint8_t type = ltoh8(header->type);
+    struct sc_header header;
+    memcpy(&header, data, sizeof(header));
+    data += sizeof(header);
+    data_len -= sizeof(header);
+    uint8_t type = ltoh8(header.type);
     
     ASSERT(data_len >= 0)
     ASSERT(data_len <= SC_MAX_PAYLOAD)
@@ -1461,8 +1467,9 @@ void process_packet_hello (struct client_data *client, uint8_t *data, int data_l
         return;
     }
     
-    struct sc_client_hello *msg = (struct sc_client_hello *)data;
-    client->version = ltoh16(msg->version);
+    struct sc_client_hello msg;
+    memcpy(&msg, data, sizeof(msg));
+    client->version = ltoh16(msg.version);
     
     switch (client->version) {
         case SC_VERSION:
@@ -1512,13 +1519,15 @@ void process_packet_hello (struct client_data *client, uint8_t *data, int data_l
     }
     
     // send hello
-    struct sc_server_hello *pack;
-    if (client_start_control_packet(client, (void **)&pack, sizeof(struct sc_server_hello)) < 0) {
+    struct sc_server_hello omsg;
+    void *pack;
+    if (client_start_control_packet(client, &pack, sizeof(omsg)) < 0) {
         return;
     }
-    pack->flags = htol16(0);
-    pack->id = htol16(client->id);
-    pack->clientAddr = (client->addr.type == BADDR_TYPE_IPV4 ? client->addr.ipv4.ip : hton32(0));
+    omsg.flags = htol16(0);
+    omsg.id = htol16(client->id);
+    omsg.clientAddr = (client->addr.type == BADDR_TYPE_IPV4 ? client->addr.ipv4.ip : hton32(0));
+    memcpy(pack, &omsg, sizeof(omsg));
     client_end_control_packet(client, SCID_SERVERHELLO);
     
     return;
@@ -1541,8 +1550,9 @@ void process_packet_outmsg (struct client_data *client, uint8_t *data, int data_
         return;
     }
     
-    struct sc_client_outmsg *msg = (struct sc_client_outmsg *)data;
-    peerid_t id = ltoh16(msg->clientid);
+    struct sc_client_outmsg msg;
+    memcpy(&msg, data, sizeof(msg));
+    peerid_t id = ltoh16(msg.clientid);
     int payload_size = data_len - sizeof(struct sc_client_outmsg);
     
     if (payload_size > SC_MAX_MSGLEN) {
@@ -1583,15 +1593,17 @@ void process_packet_outmsg (struct client_data *client, uint8_t *data, int data_
 #endif
     
     // send packet
-    struct sc_server_inmsg *pack;
-    if (!peer_flow_start_packet(flow, (void **)&pack, sizeof(struct sc_server_inmsg) + payload_size)) {
+    struct sc_server_inmsg omsg;
+    void *pack;
+    if (!peer_flow_start_packet(flow, &pack, sizeof(omsg) + payload_size)) {
         // out of buffer, reset these two clients
         client_log(client, BLOG_WARNING, "out of buffer; resetting to %d", (int)flow->dest_client->id);
         peer_flow_start_reset(flow);
         return;
     }
-    pack->clientid = htol16(client->id);
-    memcpy((uint8_t *)(pack + 1), payload, payload_size);
+    omsg.clientid = htol16(client->id);
+    memcpy(pack, &omsg, sizeof(omsg));
+    memcpy((char *)pack + sizeof(omsg), payload, payload_size);
     peer_flow_end_packet(flow, SCID_INMSG);
 }
 
@@ -1609,8 +1621,9 @@ void process_packet_resetpeer (struct client_data *client, uint8_t *data, int da
         return;
     }
     
-    struct sc_client_resetpeer *msg = (struct sc_client_resetpeer *)data;
-    peerid_t id = ltoh16(msg->clientid);
+    struct sc_client_resetpeer msg;
+    memcpy(&msg, data, sizeof(msg));
+    peerid_t id = ltoh16(msg.clientid);
     
     // lookup flow to destination client
     struct peer_flow *flow = find_flow(client, id);
@@ -1651,8 +1664,9 @@ void process_packet_acceptpeer (struct client_data *client, uint8_t *data, int d
         return;
     }
     
-    struct sc_client_acceptpeer *msg = (struct sc_client_acceptpeer *)data;
-    peerid_t id = ltoh16(msg->clientid);
+    struct sc_client_acceptpeer msg;
+    memcpy(&msg, data, sizeof(msg));
+    peerid_t id = ltoh16(msg.clientid);
     
     // lookup flow to destination client
     struct peer_flow *flow = find_flow(client, id);
@@ -1851,8 +1865,9 @@ void peer_flow_end_packet (struct peer_flow *flow, uint8_t type)
     ASSERT(flow->packet_len <= SC_MAX_PAYLOAD)
     
     // write header
-    struct sc_header *header = (struct sc_header *)flow->packet;
-    header->type = type;
+    struct sc_header header;
+    header.type = type;
+    memcpy(flow->packet, &header, sizeof(header));
     
     // finish writing packet
     BufferWriter_EndPacket(flow->input, sizeof(struct sc_header) + flow->packet_len);

+ 5 - 2
server_connection/SCKeepaliveSource.c

@@ -27,6 +27,8 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <string.h>
+
 #include <protocol/scproto.h>
 #include <misc/byteorder.h>
 
@@ -36,8 +38,9 @@ static void output_handler_recv (SCKeepaliveSource *o, uint8_t *data)
 {
     DebugObject_Access(&o->d_obj);
     
-    struct sc_header *header = (struct sc_header *)data;
-    header->type = htol8(SCID_KEEPALIVE);
+    struct sc_header header;
+    header.type = htol8(SCID_KEEPALIVE);
+    memcpy(data, &header, sizeof(header));
     
     PacketRecvInterface_Done(&o->output, sizeof(struct sc_header));
 }

+ 38 - 26
server_connection/ServerConnection.c

@@ -28,6 +28,7 @@
  */
 
 #include <stdio.h>
+#include <string.h>
 
 #include <misc/debug.h>
 #include <misc/strdup.h>
@@ -213,13 +214,15 @@ void pending_handler (ServerConnection *o)
     DebugObject_Access(&o->d_obj);
     
     // send hello
-    struct sc_client_hello *packet;
-    if (!start_packet(o, (void **)&packet, sizeof(struct sc_client_hello))) {
+    struct sc_client_hello omsg;
+    void *packet;
+    if (!start_packet(o, &packet, sizeof(omsg))) {
         BLog(BLOG_ERROR, "no buffer for hello");
         report_error(o);
         return;
     }
-    packet->version = htol16(SC_VERSION);
+    omsg.version = htol16(SC_VERSION);
+    memcpy(packet, &omsg, sizeof(omsg));
     end_packet(o, SCID_CLIENTHELLO);
 }
 
@@ -299,10 +302,11 @@ void input_handler_send (ServerConnection *o, uint8_t *data, int data_len)
         report_error(o);
         return;
     }
-    struct sc_header *header = (struct sc_header *)data;
-    data += sizeof(*header);
-    data_len -= sizeof(*header);
-    uint8_t type = ltoh8(header->type);
+    struct sc_header header;
+    memcpy(&header, data, sizeof(header));
+    data += sizeof(header);
+    data_len -= sizeof(header);
+    uint8_t type = ltoh8(header.type);
     
     // call appropriate handler based on packet type
     switch (type) {
@@ -338,14 +342,15 @@ void packet_hello (ServerConnection *o, uint8_t *data, int data_len)
         report_error(o);
         return;
     }
-    struct sc_server_hello *msg = (struct sc_server_hello *)data;
-    peerid_t id = ltoh16(msg->id);
+    struct sc_server_hello msg;
+    memcpy(&msg, data, sizeof(msg));
+    peerid_t id = ltoh16(msg.id);
     
     // change state
     o->state = STATE_COMPLETE;
     
     // report
-    o->handler_ready(o->user, id, msg->clientAddr);
+    o->handler_ready(o->user, id, msg.clientAddr);
     return;
 }
 
@@ -363,8 +368,9 @@ void packet_newclient (ServerConnection *o, uint8_t *data, int data_len)
         return;
     }
     
-    struct sc_server_newclient *msg = (struct sc_server_newclient *)data;
-    peerid_t id = ltoh16(msg->id);
+    struct sc_server_newclient msg;
+    memcpy(&msg, data, sizeof(msg));
+    peerid_t id = ltoh16(msg.id);
     
     // schedule reporting new client
     o->newclient_data = data;
@@ -372,13 +378,15 @@ void packet_newclient (ServerConnection *o, uint8_t *data, int data_len)
     BPending_Set(&o->newclient_job);
     
     // send acceptpeer
-    struct sc_client_acceptpeer *packet;
-    if (!start_packet(o, (void **)&packet, sizeof(*packet))) {
+    struct sc_client_acceptpeer omsg;
+    void *packet;
+    if (!start_packet(o, &packet, sizeof(omsg))) {
         BLog(BLOG_ERROR, "newclient: out of buffer for acceptpeer");
         report_error(o);
         return;
     }
-    packet->clientid = htol16(id);
+    omsg.clientid = htol16(id);
+    memcpy(packet, &omsg, sizeof(omsg));
     end_packet(o, SCID_ACCEPTPEER);
 }
 
@@ -396,8 +404,9 @@ void packet_endclient (ServerConnection *o, uint8_t *data, int data_len)
         return;
     }
     
-    struct sc_server_endclient *msg = (struct sc_server_endclient *)data;
-    peerid_t id = ltoh16(msg->id);
+    struct sc_server_endclient msg;
+    memcpy(&msg, data, sizeof(msg));
+    peerid_t id = ltoh16(msg.id);
     
     // report
     o->handler_endclient(o->user, id);
@@ -424,8 +433,9 @@ void packet_inmsg (ServerConnection *o, uint8_t *data, int data_len)
         return;
     }
     
-    struct sc_server_inmsg *msg = (struct sc_server_inmsg *)data;
-    peerid_t peer_id = ltoh16(msg->clientid);
+    struct sc_server_inmsg msg;
+    memcpy(&msg, data, sizeof(msg));
+    peerid_t peer_id = ltoh16(msg.clientid);
     uint8_t *payload = data + sizeof(struct sc_server_inmsg);
     int payload_len = data_len - sizeof(struct sc_server_inmsg);
     
@@ -464,8 +474,9 @@ void end_packet (ServerConnection *o, uint8_t type)
     ASSERT(o->output_local_packet_len <= SC_MAX_PAYLOAD)
     
     // write header
-    struct sc_header *header = (struct sc_header *)o->output_local_packet;
-    header->type = htol8(type);
+    struct sc_header header;
+    header.type = htol8(type);
+    memcpy(o->output_local_packet, &header, sizeof(header));
     
     // finish writing packet
     BufferWriter_EndPacket(o->output_local_if, sizeof(struct sc_header) + o->output_local_packet_len);
@@ -615,12 +626,13 @@ void newclient_job_handler (ServerConnection *o)
     DebugObject_Access(&o->d_obj);
     ASSERT(o->state == STATE_COMPLETE)
     
-    struct sc_server_newclient *msg = (struct sc_server_newclient *)o->newclient_data;
-    peerid_t id = ltoh16(msg->id);
-    int flags = ltoh16(msg->flags);
+    struct sc_server_newclient msg;
+    memcpy(&msg, o->newclient_data, sizeof(msg));
+    peerid_t id = ltoh16(msg.id);
+    int flags = ltoh16(msg.flags);
     
-    uint8_t *cert_data = (uint8_t *)(msg + 1);
-    int cert_len = o->newclient_data_len - sizeof(*msg);
+    uint8_t *cert_data = o->newclient_data + sizeof(msg);
+    int cert_len = o->newclient_data_len - sizeof(msg);
     
     // report new client
     o->handler_newclient(o->user, id, flags, cert_data, cert_len);

+ 49 - 30
socksclient/BSocksClient.c

@@ -27,6 +27,8 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <string.h>
+
 #include <misc/byteorder.h>
 #include <misc/balloc.h>
 #include <base/BLog.h>
@@ -172,7 +174,7 @@ void connector_handler (BSocksClient* o, int is_error)
     
     // allocate buffer for sending hello
     bsize_t size = bsize_add(
-        bsize_fromsize(sizeof(struct BSocksClient__client_hello)), 
+        bsize_fromsize(sizeof(struct socks_client_hello_header)), 
         bsize_mul(
             bsize_fromsize(o->num_auth_info),
             bsize_fromsize(sizeof(struct socks_client_hello_method))
@@ -182,12 +184,17 @@ void connector_handler (BSocksClient* o, int is_error)
         goto fail1;
     }
     
-    // build hello
-    struct BSocksClient__client_hello *omsg = (void *)o->buffer;
-    omsg->header.ver = hton8(SOCKS_VERSION);
-    omsg->header.nmethods = hton8(o->num_auth_info);
+    // write hello header
+    struct socks_client_hello_header header;
+    header.ver = hton8(SOCKS_VERSION);
+    header.nmethods = hton8(o->num_auth_info);
+    memcpy(o->buffer, &header, sizeof(header));
+    
+    // write hello methods
     for (size_t i = 0; i < o->num_auth_info; i++) {
-        omsg->methods[i].method = hton8(o->auth_info[i].auth_type);
+        struct socks_client_hello_method method;
+        method.method = hton8(o->auth_info[i].auth_type);
+        memcpy(o->buffer + sizeof(header) + i * sizeof(method), &method, sizeof(method));
     }
     
     // send
@@ -237,16 +244,17 @@ void recv_handler_done (BSocksClient *o, int data_len)
         case STATE_SENT_HELLO: {
             BLog(BLOG_DEBUG, "received hello");
             
-            struct socks_server_hello *imsg = (void *)o->buffer;
+            struct socks_server_hello imsg;
+            memcpy(&imsg, o->buffer, sizeof(imsg));
             
-            if (ntoh8(imsg->ver) != SOCKS_VERSION) {
+            if (ntoh8(imsg.ver) != SOCKS_VERSION) {
                 BLog(BLOG_NOTICE, "wrong version");
                 goto fail;
             }
             
             size_t auth_index;
             for (auth_index = 0; auth_index < o->num_auth_info; auth_index++) {
-                if (o->auth_info[auth_index].auth_type == ntoh8(imsg->method)) {
+                if (o->auth_info[auth_index].auth_type == ntoh8(imsg.method)) {
                     break;
                 }
             }
@@ -305,20 +313,21 @@ void recv_handler_done (BSocksClient *o, int data_len)
         case STATE_SENT_REQUEST: {
             BLog(BLOG_DEBUG, "received reply header");
             
-            struct BSocksClient__reply *imsg = (void *)o->buffer;
+            struct socks_reply_header imsg;
+            memcpy(&imsg, o->buffer, sizeof(imsg));
             
-            if (ntoh8(imsg->header.ver) != SOCKS_VERSION) {
+            if (ntoh8(imsg.ver) != SOCKS_VERSION) {
                 BLog(BLOG_NOTICE, "wrong version");
                 goto fail;
             }
             
-            if (ntoh8(imsg->header.rep) != SOCKS_REP_SUCCEEDED) {
+            if (ntoh8(imsg.rep) != SOCKS_REP_SUCCEEDED) {
                 BLog(BLOG_NOTICE, "reply not successful");
                 goto fail;
             }
             
             int addr_len;
-            switch (ntoh8(imsg->header.atyp)) {
+            switch (ntoh8(imsg.atyp)) {
                 case SOCKS_ATYP_IPV4:
                     addr_len = sizeof(struct socks_addr_ipv4);
                     break;
@@ -331,7 +340,7 @@ void recv_handler_done (BSocksClient *o, int data_len)
             }
             
             // receive the rest of the reply
-            start_receive(o, (uint8_t *)&imsg->addr, addr_len);
+            start_receive(o, (uint8_t *)o->buffer + sizeof(imsg), addr_len);
             
             // set state
             o->state = STATE_RECEIVED_REPLY_HEADER;
@@ -410,7 +419,10 @@ void send_handler_done (BSocksClient *o)
             BLog(BLOG_DEBUG, "sent request");
             
             // allocate buffer for receiving reply
-            bsize_t size = bsize_fromsize(sizeof(struct BSocksClient__reply));
+            bsize_t size = bsize_add(
+                bsize_fromsize(sizeof(struct socks_reply_header)),
+                bsize_max(bsize_fromsize(sizeof(struct socks_addr_ipv4)), bsize_fromsize(sizeof(struct socks_addr_ipv6)))
+            );
             if (!reserve_buffer(o, size)) {
                 goto fail;
             }
@@ -461,25 +473,32 @@ void auth_finished (BSocksClient *o)
         return;
     }
     
-    // send request
-    struct BSocksClient__request *omsg = (void *)o->buffer;
-    omsg->header.ver = hton8(SOCKS_VERSION);
-    omsg->header.cmd = hton8(SOCKS_CMD_CONNECT);
-    omsg->header.rsv = hton8(0);
+    // write request
+    struct socks_request_header header;
+    header.ver = hton8(SOCKS_VERSION);
+    header.cmd = hton8(SOCKS_CMD_CONNECT);
+    header.rsv = hton8(0);
     switch (o->dest_addr.type) {
-        case BADDR_TYPE_IPV4:
-            omsg->header.atyp = hton8(SOCKS_ATYP_IPV4);
-            omsg->addr.ipv4.addr = o->dest_addr.ipv4.ip;
-            omsg->addr.ipv4.port = o->dest_addr.ipv4.port;
-            break;
-        case BADDR_TYPE_IPV6:
-            omsg->header.atyp = hton8(SOCKS_ATYP_IPV6);
-            memcpy(omsg->addr.ipv6.addr, o->dest_addr.ipv6.ip, sizeof(o->dest_addr.ipv6.ip));
-            omsg->addr.ipv6.port = o->dest_addr.ipv6.port;
-            break;
+        case BADDR_TYPE_IPV4: {
+            header.atyp = hton8(SOCKS_ATYP_IPV4);
+            struct socks_addr_ipv4 addr;
+            addr.addr = o->dest_addr.ipv4.ip;
+            addr.port = o->dest_addr.ipv4.port;
+            memcpy(o->buffer + sizeof(header), &addr, sizeof(addr));
+        } break;
+        case BADDR_TYPE_IPV6: {
+            header.atyp = hton8(SOCKS_ATYP_IPV6);
+            struct socks_addr_ipv6 addr;
+            memcpy(addr.addr, o->dest_addr.ipv6.ip, sizeof(o->dest_addr.ipv6.ip));
+            addr.port = o->dest_addr.ipv6.port;
+            memcpy(o->buffer + sizeof(header), &addr, sizeof(addr));
+        } break;
         default:
             ASSERT(0);
     }
+    memcpy(o->buffer, &header, sizeof(header));
+    
+    // send request
     PacketPassInterface_Sender_Send(o->control.send_if, (uint8_t *)o->buffer, size.value);
     
     // set state

+ 0 - 27
socksclient/BSocksClient.h

@@ -62,33 +62,6 @@
  */
 typedef void (*BSocksClient_handler) (void *user, int event);
 
-B_START_PACKED
-struct BSocksClient__client_hello {
-    struct socks_client_hello_header header;
-    struct socks_client_hello_method methods[];
-} B_PACKED;
-B_END_PACKED
-
-B_START_PACKED
-struct BSocksClient__request {
-    struct socks_request_header header;
-    union {
-        struct socks_addr_ipv4 ipv4;
-        struct socks_addr_ipv6 ipv6;
-    } addr;
-} B_PACKED;
-B_END_PACKED
-
-B_START_PACKED
-struct BSocksClient__reply {
-    struct socks_reply_header header;
-    union {
-        struct socks_addr_ipv4 ipv4;
-        struct socks_addr_ipv6 ipv6;
-    } addr;
-} B_PACKED;
-B_END_PACKED
-
 struct BSocksClient_auth_info {
     int auth_type;
     union {

+ 10 - 17
system/BAddr.h

@@ -52,7 +52,7 @@
 #include <misc/byteorder.h>
 #include <misc/debug.h>
 #include <misc/print_macros.h>
-#include <misc/packed.h>
+#include <misc/read_write_int.h>
 
 #define BADDR_TYPE_NONE 0
 #define BADDR_TYPE_IPV4 1
@@ -422,13 +422,6 @@ void BAddr_SetPort (BAddr *addr, uint16_t port)
     }
 }
 
-B_START_PACKED
-struct _BAddr_ipv6_addr
-{
-    uint16_t addr[8];
-} B_PACKED;
-B_END_PACKED
-
 void BIPAddr_Print (BIPAddr *addr, char *out)
 {
     switch (addr->type) {
@@ -444,18 +437,18 @@ void BIPAddr_Print (BIPAddr *addr, char *out)
             );
             break;
         case BADDR_TYPE_IPV6: {
-            struct _BAddr_ipv6_addr *s = (struct _BAddr_ipv6_addr *)addr->ipv6;
+            const char *ptr = (void *)addr->ipv6;
             sprintf(out,
                 "%"PRIx16":%"PRIx16":%"PRIx16":%"PRIx16":"
                 "%"PRIx16":%"PRIx16":%"PRIx16":%"PRIx16,
-                ntoh16(s->addr[0]),
-                ntoh16(s->addr[1]),
-                ntoh16(s->addr[2]),
-                ntoh16(s->addr[3]),
-                ntoh16(s->addr[4]),
-                ntoh16(s->addr[5]),
-                ntoh16(s->addr[6]),
-                ntoh16(s->addr[7])
+                badvpn_read_be16(ptr + 0),
+                badvpn_read_be16(ptr + 2),
+                badvpn_read_be16(ptr + 4),
+                badvpn_read_be16(ptr + 6),
+                badvpn_read_be16(ptr + 8),
+                badvpn_read_be16(ptr + 10),
+                badvpn_read_be16(ptr + 12),
+                badvpn_read_be16(ptr + 14)
             );
         } break;
         default:

+ 41 - 45
tun2socks/tun2socks.c

@@ -915,7 +915,7 @@ int process_device_udp_packet (uint8_t *data, int data_len)
     }
     
     // parse IPv4 header
-    struct ipv4_header *ipv4_header;
+    struct ipv4_header ipv4_header;
     if (!ipv4_check(data, data_len, &ipv4_header, &data, &data_len)) {
         goto fail;
     }
@@ -924,21 +924,22 @@ int process_device_udp_packet (uint8_t *data, int data_len)
     if (data_len < sizeof(struct udp_header)) {
         goto fail;
     }
-    struct udp_header *udp_header = (struct udp_header *)data;
-    data += sizeof(*udp_header);
-    data_len -= sizeof(*udp_header);
+    struct udp_header udp_header;
+    memcpy(&udp_header, data, sizeof(udp_header));
+    data += sizeof(udp_header);
+    data_len -= sizeof(udp_header);
     
     // verify UDP payload
-    int udp_length = ntoh16(udp_header->length);
-    if (udp_length < sizeof(*udp_header)) {
+    int udp_length = ntoh16(udp_header.length);
+    if (udp_length < sizeof(udp_header)) {
         goto fail;
     }
-    if (udp_length > sizeof(*udp_header) + data_len) {
+    if (udp_length > sizeof(udp_header) + data_len) {
         goto fail;
     }
     
     // ignore stray data
-    data_len = udp_length - sizeof(*udp_header);
+    data_len = udp_length - sizeof(udp_header);
     
     // check payload length
     if (data_len > udp_mtu) {
@@ -946,10 +947,9 @@ int process_device_udp_packet (uint8_t *data, int data_len)
     }
     
     // verify UDP checksum
-    uint16_t checksum_in_packet = udp_header->checksum;
-    udp_header->checksum = 0;
-    uint16_t checksum_computed = udp_checksum((uint8_t *)udp_header, udp_length, ipv4_header->source_address, ipv4_header->destination_address);
-    udp_header->checksum = checksum_in_packet;
+    uint16_t checksum_in_packet = udp_header.checksum;
+    udp_header.checksum = 0;
+    uint16_t checksum_computed = udp_checksum(&udp_header, data, data_len, ipv4_header.source_address, ipv4_header.destination_address);
     if (checksum_in_packet != checksum_computed) {
         goto fail;
     }
@@ -958,9 +958,9 @@ int process_device_udp_packet (uint8_t *data, int data_len)
     
     // construct addresses
     BAddr local_addr;
-    BAddr_InitIPv4(&local_addr, ipv4_header->source_address, udp_header->source_port);
+    BAddr_InitIPv4(&local_addr, ipv4_header.source_address, udp_header.source_port);
     BAddr remote_addr;
-    BAddr_InitIPv4(&remote_addr, ipv4_header->destination_address, udp_header->dest_port);
+    BAddr_InitIPv4(&remote_addr, ipv4_header.destination_address, udp_header.dest_port);
     
     // submit packet to udpgw
     SocksUdpGwClient_SubmitPacket(&udpgw_client, local_addr, remote_addr, data, data_len);
@@ -1582,37 +1582,33 @@ void udpgw_client_handler_received (void *unused, BAddr local_addr, BAddr remote
     
     BLog(BLOG_INFO, "UDP: from udpgw %d bytes", data_len);
     
-    // write IP header
-    struct ipv4_header *iph = (struct ipv4_header *)device_write_buf;
-    iph->version4_ihl4 = IPV4_MAKE_VERSION_IHL(sizeof(*iph));
-    iph->ds = hton8(0);
-    iph->total_length = hton16(sizeof(*iph) + sizeof(struct udp_header) + data_len);
-    iph->identification = hton16(0);
-    iph->flags3_fragmentoffset13 = hton16(0);
-    iph->ttl = hton8(64);
-    iph->protocol = hton8(IPV4_PROTOCOL_UDP);
-    iph->checksum = hton16(0);
-    iph->source_address = remote_addr.ipv4.ip;
-    iph->destination_address = local_addr.ipv4.ip;
-    
-    // compute and write IP header checksum
-    uint32_t checksum = ipv4_checksum((uint8_t *)iph, sizeof(*iph));
-    iph->checksum = checksum;
-    
-    // write UDP header
-    struct udp_header *udph = (struct udp_header *)(device_write_buf + sizeof(*iph));
-    udph->source_port = remote_addr.ipv4.port;
-    udph->dest_port = local_addr.ipv4.port;
-    udph->length = hton16(sizeof(*udph) + data_len);
-    udph->checksum = hton16(0);
-    
-    // write data
-    memcpy(device_write_buf + sizeof(*iph) + sizeof(struct udp_header), data, data_len);
-    
-    // compute checksum
-    checksum = udp_checksum((uint8_t *)udph, sizeof(*udph) + data_len, iph->source_address, iph->destination_address);
-    udph->checksum = checksum;
+    // build IP header
+    struct ipv4_header iph;
+    iph.version4_ihl4 = IPV4_MAKE_VERSION_IHL(sizeof(iph));
+    iph.ds = hton8(0);
+    iph.total_length = hton16(sizeof(iph) + sizeof(struct udp_header) + data_len);
+    iph.identification = hton16(0);
+    iph.flags3_fragmentoffset13 = hton16(0);
+    iph.ttl = hton8(64);
+    iph.protocol = hton8(IPV4_PROTOCOL_UDP);
+    iph.checksum = hton16(0);
+    iph.source_address = remote_addr.ipv4.ip;
+    iph.destination_address = local_addr.ipv4.ip;
+    iph.checksum = ipv4_checksum(&iph, NULL, 0);
+    
+    // build UDP header
+    struct udp_header udph;
+    udph.source_port = remote_addr.ipv4.port;
+    udph.dest_port = local_addr.ipv4.port;
+    udph.length = hton16(sizeof(udph) + data_len);
+    udph.checksum = hton16(0);
+    udph.checksum = udp_checksum(&udph, data, data_len, iph.source_address, iph.destination_address);
+    
+    // write packet
+    memcpy(device_write_buf, &iph, sizeof(iph));
+    memcpy(device_write_buf + sizeof(iph), &udph, sizeof(udph));
+    memcpy(device_write_buf + sizeof(iph) + sizeof(udph), data, data_len);
     
     // submit packet
-    BTap_Send(&device, device_write_buf, sizeof(*iph) + sizeof(*udph) + data_len);
+    BTap_Send(&device, device_write_buf, sizeof(iph) + sizeof(udph) + data_len);
 }

+ 16 - 14
udpgw/udpgw.c

@@ -772,11 +772,12 @@ void client_recv_if_handler_send (struct client *client, uint8_t *data, int data
         client_log(client, BLOG_ERROR, "missing header");
         return;
     }
-    struct udpgw_header *header = (struct udpgw_header *)data;
-    data += sizeof(*header);
-    data_len -= sizeof(*header);
-    uint8_t flags = ltoh8(header->flags);
-    uint16_t conid = ltoh16(header->conid);
+    struct udpgw_header header;
+    memcpy(&header, data, sizeof(header));
+    data += sizeof(header);
+    data_len -= sizeof(header);
+    uint8_t flags = ltoh8(header.flags);
+    uint16_t conid = ltoh16(header.conid);
     
     // reset disconnect timer
     BReactor_SetTimer(&ss, &client->disconnect_timer);
@@ -798,7 +799,7 @@ void client_recv_if_handler_send (struct client *client, uint8_t *data, int data
     ASSERT(!con || !con->closing)
     
     // if connection exists, close it if needed
-    if (con && ((flags & UDPGW_CLIENT_FLAG_REBIND) || con->addr.ipv4.ip != header->addr_ip || con->addr.ipv4.port != header->addr_port)) {
+    if (con && ((flags & UDPGW_CLIENT_FLAG_REBIND) || con->addr.ipv4.ip != header.addr_ip || con->addr.ipv4.port != header.addr_port)) {
         connection_log(con, BLOG_DEBUG, "close old");
         
         connection_close(con);
@@ -816,7 +817,7 @@ void client_recv_if_handler_send (struct client *client, uint8_t *data, int data
         
         // read address
         BAddr addr;
-        BAddr_InitIPv4(&addr, header->addr_ip, header->addr_port);
+        BAddr_InitIPv4(&addr, header.addr_ip, header.addr_port);
         
         // create new connection
         connection_init(client, conid, addr, data, data_len);
@@ -1147,17 +1148,18 @@ int connection_send_to_client (struct connection *con, uint8_t flags, const uint
     }
     
     // write header
-    struct udpgw_header *header = (struct udpgw_header *)out;
-    header->flags = htol8(flags);
-    header->conid = htol16(con->conid);
-    header->addr_ip = con->addr.ipv4.ip;
-    header->addr_port = con->addr.ipv4.port;
+    struct udpgw_header header;
+    header.flags = htol8(flags);
+    header.conid = htol16(con->conid);
+    header.addr_ip = con->addr.ipv4.ip;
+    header.addr_port = con->addr.ipv4.port;
+    memcpy(out, &header, sizeof(header));
     
     // write message
-    memcpy(out + sizeof(*header), data, data_len);
+    memcpy(out + sizeof(header), data, data_len);
     
     // submit written message
-    BufferWriter_EndPacket(con->send_if, sizeof(*header) + data_len);
+    BufferWriter_EndPacket(con->send_if, sizeof(header) + data_len);
     
     return 1;
 }

+ 14 - 12
udpgw_client/UdpGwClient.c

@@ -130,10 +130,11 @@ static void recv_interface_handler_send (UdpGwClient *o, uint8_t *data, int data
         BLog(BLOG_ERROR, "missing header");
         return;
     }
-    struct udpgw_header *header = (struct udpgw_header *)data;
-    data += sizeof(*header);
-    data_len -= sizeof(*header);
-    uint16_t conid = ltoh16(header->conid);
+    struct udpgw_header header;
+    memcpy(&header, data, sizeof(header));
+    data += sizeof(header);
+    data_len -= sizeof(header);
+    uint16_t conid = ltoh16(header.conid);
     
     // check remaining data
     if (data_len > o->udp_mtu) {
@@ -149,7 +150,7 @@ static void recv_interface_handler_send (UdpGwClient *o, uint8_t *data, int data
     }
     
     // check remote address
-    if (con->conaddr.remote_addr.ipv4.port != header->addr_port || con->conaddr.remote_addr.ipv4.ip != header->addr_ip) {
+    if (con->conaddr.remote_addr.ipv4.port != header.addr_port || con->conaddr.remote_addr.ipv4.ip != header.addr_ip) {
         BLog(BLOG_ERROR, "wrong remote address");
         return;
     }
@@ -335,17 +336,18 @@ static void connection_send (struct UdpGwClient_connection *con, uint8_t flags,
     }
     
     // write header
-    struct udpgw_header *header = (struct udpgw_header *)out;
-    header->flags = ltoh8(flags);
-    header->conid = ltoh16(con->conid);
-    header->addr_ip = con->conaddr.remote_addr.ipv4.ip;
-    header->addr_port = con->conaddr.remote_addr.ipv4.port;
+    struct udpgw_header header;
+    header.flags = ltoh8(flags);
+    header.conid = ltoh16(con->conid);
+    header.addr_ip = con->conaddr.remote_addr.ipv4.ip;
+    header.addr_port = con->conaddr.remote_addr.ipv4.port;
+    memcpy(out, &header, sizeof(header));
     
     // write packet to buffer
-    memcpy(out + sizeof(*header), data, data_len);
+    memcpy(out + sizeof(header), data, data_len);
     
     // submit packet to buffer
-    BufferWriter_EndPacket(con->send_if, sizeof(*header) + data_len);
+    BufferWriter_EndPacket(con->send_if, sizeof(header) + data_len);
 }
 
 static struct UdpGwClient_connection * reuse_connection (UdpGwClient *o, struct UdpGwClient_conaddr conaddr)