Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions include/zephyr/toolchain/gcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,16 @@ do { \

#endif

/*
* Get the address of a structure member even if the member may not be properly
* aligned. Note that accessing such an address must be done with care (for
* example with UNALIGNED_GET/PUT) and cannot be in general de-referenced to
* access the member directly, as that would cause a fault in architectures
* which have alignment requirements.
*/
#define UNALIGNED_MEMBER_ADDR(_p, _member) ((__typeof__(_p->_member) *) \
(((intptr_t)(_p)) + offsetof(__typeof__(*_p), _member)))

/* Double indirection to ensure section names are expanded before
* stringification
*/
Expand Down
2 changes: 1 addition & 1 deletion subsys/net/ip/igmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ static int igmp_v2_create(struct net_pkt *pkt, const struct in_addr *addr,

igmp->type = type;
igmp->max_rsp = 0U;
net_ipaddr_copy(&igmp->address, addr);
net_ipaddr_copy(UNALIGNED_MEMBER_ADDR(igmp, address), addr);
igmp->chksum = 0;

if (net_pkt_set_data(pkt, &igmp_access)) {
Expand Down
18 changes: 9 additions & 9 deletions subsys/net/ip/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1262,20 +1262,20 @@ static int tcp_header_add(struct tcp *conn, struct net_pkt *pkt, uint8_t flags,

memset(th, 0, sizeof(struct tcphdr));

UNALIGNED_PUT(conn->src.sin.sin_port, &th->th_sport);
UNALIGNED_PUT(conn->dst.sin.sin_port, &th->th_dport);
UNALIGNED_PUT(conn->src.sin.sin_port, UNALIGNED_MEMBER_ADDR(th, th_sport));
UNALIGNED_PUT(conn->dst.sin.sin_port, UNALIGNED_MEMBER_ADDR(th, th_dport));
th->th_off = 5;

if (conn->send_options.mss_found) {
th->th_off++;
}

UNALIGNED_PUT(flags, &th->th_flags);
UNALIGNED_PUT(htons(conn->recv_win), &th->th_win);
UNALIGNED_PUT(htonl(seq), &th->th_seq);
UNALIGNED_PUT(htons(conn->recv_win), UNALIGNED_MEMBER_ADDR(th, th_win));
UNALIGNED_PUT(htonl(seq), UNALIGNED_MEMBER_ADDR(th, th_seq));

if (ACK & flags) {
UNALIGNED_PUT(htonl(conn->ack), &th->th_ack);
UNALIGNED_PUT(htonl(conn->ack), UNALIGNED_MEMBER_ADDR(th, th_ack));
}

return net_pkt_set_data(pkt, &tcp_access);
Expand Down Expand Up @@ -1415,13 +1415,13 @@ void net_tcp_reply_rst(struct net_pkt *pkt)

memset(th_rst, 0, sizeof(struct tcphdr));

UNALIGNED_PUT(th_pkt->th_dport, &th_rst->th_sport);
UNALIGNED_PUT(th_pkt->th_sport, &th_rst->th_dport);
UNALIGNED_PUT(th_pkt->th_dport, UNALIGNED_MEMBER_ADDR(th_rst, th_sport));
UNALIGNED_PUT(th_pkt->th_sport, UNALIGNED_MEMBER_ADDR(th_rst, th_dport));
th_rst->th_off = 5;

if (th_flags(th_pkt) & ACK) {
UNALIGNED_PUT(RST, &th_rst->th_flags);
UNALIGNED_PUT(th_pkt->th_ack, &th_rst->th_seq);
UNALIGNED_PUT(th_pkt->th_ack, UNALIGNED_MEMBER_ADDR(th_rst, th_seq));
} else {
uint32_t ack = ntohl(th_pkt->th_seq) + tcp_data_len(pkt);

Expand All @@ -1430,7 +1430,7 @@ void net_tcp_reply_rst(struct net_pkt *pkt)
}

UNALIGNED_PUT(RST | ACK, &th_rst->th_flags);
UNALIGNED_PUT(htonl(ack), &th_rst->th_ack);
UNALIGNED_PUT(htonl(ack), UNALIGNED_MEMBER_ADDR(th_rst, th_ack));
}

ret = net_pkt_set_data(rst, &tcp_access_rst);
Expand Down
14 changes: 8 additions & 6 deletions subsys/net/ip/tcp_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,22 @@
*/

#include "tp.h"
#include <zephyr/toolchain/gcc.h>

#define is(_a, _b) (strcmp((_a), (_b)) == 0)

#ifndef MIN3
#define MIN3(_a, _b, _c) MIN((_a), MIN((_b), (_c)))
#endif

#define th_sport(_x) UNALIGNED_GET(&(_x)->th_sport)
#define th_dport(_x) UNALIGNED_GET(&(_x)->th_dport)
#define th_seq(_x) ntohl(UNALIGNED_GET(&(_x)->th_seq))
#define th_ack(_x) ntohl(UNALIGNED_GET(&(_x)->th_ack))
#define th_sport(_x) UNALIGNED_GET(UNALIGNED_MEMBER_ADDR((_x), th_sport))
#define th_dport(_x) UNALIGNED_GET(UNALIGNED_MEMBER_ADDR((_x), th_dport))
#define th_seq(_x) ntohl(UNALIGNED_GET(UNALIGNED_MEMBER_ADDR((_x), th_seq)))
#define th_ack(_x) ntohl(UNALIGNED_GET(UNALIGNED_MEMBER_ADDR((_x), th_ack)))

#define th_off(_x) ((_x)->th_off)
#define th_flags(_x) UNALIGNED_GET(&(_x)->th_flags)
#define th_win(_x) UNALIGNED_GET(&(_x)->th_win)
#define th_flags(_x) UNALIGNED_GET(UNALIGNED_MEMBER_ADDR((_x), th_flags))
#define th_win(_x) UNALIGNED_GET(UNALIGNED_MEMBER_ADDR((_x), th_win))

#define tcp_slist(_conn, _slist, _op, _type, _link) \
({ \
Expand Down
4 changes: 3 additions & 1 deletion subsys/net/l2/ieee802154/ieee802154.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ LOG_MODULE_REGISTER(net_ieee802154, CONFIG_NET_L2_IEEE802154_LOG_LEVEL);

#include <errno.h>

#include <zephyr/toolchain/gcc.h>
#include <zephyr/net/capture.h>
#include <zephyr/net/ethernet.h>
#include <zephyr/net/net_core.h>
Expand Down Expand Up @@ -264,7 +265,8 @@ static inline void swap_and_set_pkt_ll_addr(struct net_linkaddr *addr, bool has_
(void)net_linkaddr_create(
addr,
(const uint8_t *)(has_pan_id ?
&ll->plain.addr.short_addr : &ll->comp.addr.short_addr),
UNALIGNED_MEMBER_ADDR(ll, plain.addr.short_addr) :
UNALIGNED_MEMBER_ADDR(ll, comp.addr.short_addr)),
IEEE802154_SHORT_ADDR_LENGTH,
NET_LINK_IEEE802154);
break;
Expand Down
6 changes: 4 additions & 2 deletions subsys/net/lib/dhcpv6/dhcpv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -2250,8 +2250,10 @@ static void dhcpv6_generate_client_duid(struct net_if *iface)

memset(clientid, 0, sizeof(*clientid));

UNALIGNED_PUT(htons(DHCPV6_DUID_TYPE_LL), &clientid->duid.type);
UNALIGNED_PUT(htons(DHCPV6_HARDWARE_ETHERNET_TYPE), &duid_ll->hw_type);
UNALIGNED_PUT(htons(DHCPV6_DUID_TYPE_LL),
UNALIGNED_MEMBER_ADDR(clientid, duid.type));
UNALIGNED_PUT(htons(DHCPV6_HARDWARE_ETHERNET_TYPE),
UNALIGNED_MEMBER_ADDR(duid_ll, hw_type));
memcpy(duid_ll->ll_addr, lladdr->addr, lladdr->len);

clientid->length = DHCPV6_DUID_LL_HEADER_SIZE + lladdr->len;
Expand Down
8 changes: 4 additions & 4 deletions subsys/net/lib/http/http_server_http2.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,14 @@ int send_settings_frame(struct http_client_ctx *client, bool ack)
setting = (struct http2_settings_field *)
(settings_frame + HTTP2_FRAME_HEADER_SIZE);
UNALIGNED_PUT(htons(HTTP2_SETTINGS_HEADER_TABLE_SIZE),
&setting->id);
UNALIGNED_PUT(0, &setting->value);
UNALIGNED_MEMBER_ADDR(setting, id));
UNALIGNED_PUT(0, UNALIGNED_MEMBER_ADDR(setting, value));

setting++;
UNALIGNED_PUT(htons(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS),
&setting->id);
UNALIGNED_MEMBER_ADDR(setting, id));
UNALIGNED_PUT(htonl(CONFIG_HTTP_SERVER_MAX_STREAMS),
&setting->value);
UNALIGNED_MEMBER_ADDR(setting, value));

len = HTTP2_FRAME_HEADER_SIZE +
2 * sizeof(struct http2_settings_field);
Expand Down
6 changes: 4 additions & 2 deletions tests/net/dhcpv6/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,10 @@ static void generate_fake_server_duid(void)

memset(serverid, 0, sizeof(*serverid));

UNALIGNED_PUT(htons(DHCPV6_DUID_TYPE_LL), &serverid->duid.type);
UNALIGNED_PUT(htons(DHCPV6_HARDWARE_ETHERNET_TYPE), &duid_ll->hw_type);
UNALIGNED_PUT(htons(DHCPV6_DUID_TYPE_LL),
UNALIGNED_MEMBER_ADDR(serverid, duid.type));
UNALIGNED_PUT(htons(DHCPV6_HARDWARE_ETHERNET_TYPE),
UNALIGNED_MEMBER_ADDR(duid_ll, hw_type));
memcpy(duid_ll->ll_addr, fake_mac, sizeof(fake_mac));

serverid->length = DHCPV6_DUID_LL_HEADER_SIZE + sizeof(fake_mac);
Expand Down