Skip to content

Commit 0f6dcb3

Browse files
rlubosdanieldegrasse
authored andcommitted
net: ipv6: Avoid casting unaligned address to struct in6_addr
Rework the rest of the IPv6-related code to avoid casting. Use raw variants of IPv6-related functions whenever possible (especially on the critical data path). For the routing case, use a copy of the address to avoid massive rework of the routing module. Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
1 parent edf5319 commit 0f6dcb3

File tree

8 files changed

+94
-95
lines changed

8 files changed

+94
-95
lines changed

subsys/net/ip/connection.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -581,8 +581,7 @@ static bool conn_are_endpoints_valid(struct net_pkt *pkt, uint8_t family,
581581
is_same_src_and_dst_addr = net_ipv4_addr_cmp_raw(
582582
ip_hdr->ipv4->src, ip_hdr->ipv4->dst);
583583
} else if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
584-
is_my_src_addr = net_ipv6_is_my_addr(
585-
(struct in6_addr *)ip_hdr->ipv6->src);
584+
is_my_src_addr = net_ipv6_is_my_addr_raw(ip_hdr->ipv6->src);
586585
is_same_src_and_dst_addr = net_ipv6_addr_cmp_raw(
587586
ip_hdr->ipv6->src, ip_hdr->ipv6->dst);
588587
} else {
@@ -933,7 +932,7 @@ enum net_verdict net_conn_input(struct net_pkt *pkt,
933932
is_bcast_pkt = true;
934933
}
935934
} else if (IS_ENABLED(CONFIG_NET_IPV6) && pkt_family == AF_INET6) {
936-
is_mcast_pkt = net_ipv6_is_addr_mcast((struct in6_addr *)ip_hdr->ipv6->dst);
935+
is_mcast_pkt = net_ipv6_is_addr_mcast_raw(ip_hdr->ipv6->dst);
937936
}
938937

939938
k_mutex_lock(&conn_lock, K_FOREVER);

subsys/net/ip/icmpv6.c

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,19 @@ static int icmpv6_handle_echo_request(struct net_icmp_ctx *ctx,
104104
{
105105
struct net_pkt *reply = NULL;
106106
struct net_ipv6_hdr *ip_hdr = hdr->ipv6;
107+
struct in6_addr req_src, req_dst;
107108
const struct in6_addr *src;
108109
int16_t payload_len;
109110

110111
ARG_UNUSED(user_data);
111112
ARG_UNUSED(icmp_hdr);
112113

114+
net_ipv6_addr_copy_raw(req_src.s6_addr, ip_hdr->src);
115+
net_ipv6_addr_copy_raw(req_dst.s6_addr, ip_hdr->dst);
116+
113117
NET_DBG("Received Echo Request from %s to %s",
114-
net_sprint_ipv6_addr(&ip_hdr->src),
115-
net_sprint_ipv6_addr(&ip_hdr->dst));
118+
net_sprint_ipv6_addr(&req_src),
119+
net_sprint_ipv6_addr(&req_dst));
116120

117121
payload_len = ntohs(ip_hdr->len) -
118122
net_pkt_ipv6_ext_len(pkt) - NET_ICMPH_LEN;
@@ -129,16 +133,16 @@ static int icmpv6_handle_echo_request(struct net_icmp_ctx *ctx,
129133
goto drop;
130134
}
131135

132-
if (net_ipv6_is_addr_mcast((struct in6_addr *)ip_hdr->dst)) {
136+
if (net_ipv6_is_addr_mcast_raw(ip_hdr->dst)) {
133137
src = net_if_ipv6_select_src_addr(net_pkt_iface(pkt),
134-
(struct in6_addr *)ip_hdr->src);
138+
&req_src);
135139

136140
if (net_ipv6_is_addr_unspecified(src)) {
137141
NET_DBG("DROP: No src address match");
138142
goto drop;
139143
}
140144
} else {
141-
src = (struct in6_addr *)ip_hdr->dst;
145+
src = &req_dst;
142146
}
143147

144148
/* We must not set the destination ll address here but trust
@@ -151,7 +155,7 @@ static int icmpv6_handle_echo_request(struct net_icmp_ctx *ctx,
151155
net_pkt_set_ip_dscp(reply, net_pkt_ip_dscp(pkt));
152156
net_pkt_set_ip_ecn(reply, net_pkt_ip_ecn(pkt));
153157

154-
if (net_ipv6_create(reply, src, (struct in6_addr *)ip_hdr->src)) {
158+
if (net_ipv6_create(reply, src, &req_src)) {
155159
NET_DBG("DROP: wrong buffer");
156160
goto drop;
157161
}
@@ -167,7 +171,7 @@ static int icmpv6_handle_echo_request(struct net_icmp_ctx *ctx,
167171

168172
NET_DBG("Sending Echo Reply from %s to %s",
169173
net_sprint_ipv6_addr(src),
170-
net_sprint_ipv6_addr(&ip_hdr->src));
174+
net_sprint_ipv6_addr(&req_src));
171175

172176
if (net_try_send_data(reply, K_NO_WAIT) < 0) {
173177
goto drop;
@@ -192,6 +196,7 @@ int net_icmpv6_send_error(struct net_pkt *orig, uint8_t type, uint8_t code,
192196
{
193197
NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv6_access, struct net_ipv6_hdr);
194198
int err = -EIO;
199+
struct in6_addr orig_src, orig_dst;
195200
struct net_ipv6_hdr *ip_hdr;
196201
const struct in6_addr *src;
197202
struct net_pkt *pkt;
@@ -223,6 +228,9 @@ int net_icmpv6_send_error(struct net_pkt *orig, uint8_t type, uint8_t code,
223228
net_pkt_cursor_init(orig);
224229
}
225230

231+
net_ipv6_addr_copy_raw(orig_src.s6_addr, ip_hdr->src);
232+
net_ipv6_addr_copy_raw(orig_dst.s6_addr, ip_hdr->dst);
233+
226234
if (ip_hdr->nexthdr == IPPROTO_UDP) {
227235
copy_len = sizeof(struct net_ipv6_hdr) +
228236
sizeof(struct net_udp_hdr);
@@ -284,14 +292,14 @@ int net_icmpv6_send_error(struct net_pkt *orig, uint8_t type, uint8_t code,
284292
net_pkt_lladdr_src(pkt)->len = net_pkt_lladdr_dst(orig)->len;
285293
net_pkt_lladdr_dst(pkt)->len = net_pkt_lladdr_src(orig)->len;
286294

287-
if (net_ipv6_is_addr_mcast((struct in6_addr *)ip_hdr->dst)) {
295+
if (net_ipv6_is_addr_mcast_raw(ip_hdr->dst)) {
288296
src = net_if_ipv6_select_src_addr(net_pkt_iface(pkt),
289-
(struct in6_addr *)ip_hdr->dst);
297+
&orig_dst);
290298
} else {
291-
src = (struct in6_addr *)ip_hdr->dst;
299+
src = &orig_dst;
292300
}
293301

294-
if (net_ipv6_create(pkt, src, (struct in6_addr *)ip_hdr->src) ||
302+
if (net_ipv6_create(pkt, src, &orig_src) ||
295303
net_icmpv6_create(pkt, type, code)) {
296304
goto drop;
297305
}
@@ -319,7 +327,7 @@ int net_icmpv6_send_error(struct net_pkt *orig, uint8_t type, uint8_t code,
319327
NET_DBG("Sending ICMPv6 Error Message type %d code %d param %d"
320328
" from %s to %s", type, code, param,
321329
net_sprint_ipv6_addr(src),
322-
net_sprint_ipv6_addr(&ip_hdr->src));
330+
net_sprint_ipv6_addr(&orig_src));
323331

324332
if (net_try_send_data(pkt, K_NO_WAIT) >= 0) {
325333
net_stats_update_icmp_sent(net_pkt_iface(pkt));

subsys/net/ip/ipv6.c

Lines changed: 46 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ static inline bool ipv6_drop_on_unknown_option(struct net_pkt *pkt,
186186
case 0x40:
187187
break;
188188
case 0xc0:
189-
if (net_ipv6_is_addr_mcast((struct in6_addr *)hdr->dst)) {
189+
if (net_ipv6_is_addr_mcast_raw(hdr->dst)) {
190190
break;
191191
}
192192

@@ -307,8 +307,8 @@ static struct net_route_entry *add_route(struct net_if *iface,
307307
#endif /* CONFIG_NET_ROUTE */
308308

309309
static void ipv6_no_route_info(struct net_pkt *pkt,
310-
struct in6_addr *src,
311-
struct in6_addr *dst)
310+
const uint8_t *src,
311+
const uint8_t *dst)
312312
{
313313
NET_DBG("Will not route pkt %p ll src %s to dst %s between interfaces",
314314
pkt, net_sprint_ipv6_addr(src),
@@ -321,27 +321,29 @@ static enum net_verdict ipv6_route_packet(struct net_pkt *pkt,
321321
{
322322
struct net_route_entry *route;
323323
struct in6_addr *nexthop;
324+
struct in6_addr src_ip, dst_ip;
324325
bool found;
325326

327+
net_ipv6_addr_copy_raw(src_ip.s6_addr, hdr->src);
328+
net_ipv6_addr_copy_raw(dst_ip.s6_addr, hdr->dst);
329+
326330
/* Check if the packet can be routed */
327331
if (IS_ENABLED(CONFIG_NET_ROUTING)) {
328-
found = net_route_get_info(NULL, (struct in6_addr *)hdr->dst,
329-
&route, &nexthop);
332+
found = net_route_get_info(NULL, &dst_ip, &route, &nexthop);
330333
} else {
331-
found = net_route_get_info(net_pkt_iface(pkt),
332-
(struct in6_addr *)hdr->dst,
334+
found = net_route_get_info(net_pkt_iface(pkt), &dst_ip,
333335
&route, &nexthop);
334336
}
335337

336338
if (found) {
337339
int ret;
338340

339341
if (IS_ENABLED(CONFIG_NET_ROUTING) &&
340-
(net_ipv6_is_ll_addr((struct in6_addr *)hdr->src) ||
341-
net_ipv6_is_ll_addr((struct in6_addr *)hdr->dst))) {
342+
(net_ipv6_is_ll_addr(&src_ip) ||
343+
net_ipv6_is_ll_addr(&dst_ip))) {
342344
/* RFC 4291 ch 2.5.6 */
343-
ipv6_no_route_info(pkt, (struct in6_addr *)hdr->src,
344-
(struct in6_addr *)hdr->dst);
345+
ipv6_no_route_info(pkt, hdr->src, hdr->dst);
346+
345347
goto drop;
346348
}
347349

@@ -365,8 +367,7 @@ static enum net_verdict ipv6_route_packet(struct net_pkt *pkt,
365367
pkt, net_pkt_orig_iface(pkt),
366368
net_pkt_iface(pkt));
367369

368-
add_route(net_pkt_orig_iface(pkt),
369-
(struct in6_addr *)hdr->src, 128);
370+
add_route(net_pkt_orig_iface(pkt), &src_ip, 128);
370371
}
371372

372373
ret = net_route_packet(pkt, nexthop);
@@ -382,7 +383,7 @@ static enum net_verdict ipv6_route_packet(struct net_pkt *pkt,
382383
struct net_if *iface = NULL;
383384
int ret;
384385

385-
if (net_if_ipv6_addr_onlink(&iface, (struct in6_addr *)hdr->dst)) {
386+
if (net_if_ipv6_addr_onlink(&iface, &dst_ip)) {
386387
ret = net_route_packet_if(pkt, iface);
387388
if (ret < 0) {
388389
NET_DBG("Cannot re-route pkt %p "
@@ -394,7 +395,7 @@ static enum net_verdict ipv6_route_packet(struct net_pkt *pkt,
394395
}
395396

396397
NET_DBG("No route to %s pkt %p dropped",
397-
net_sprint_ipv6_addr(&hdr->dst), pkt);
398+
net_sprint_ipv6_addr(&dst_ip), pkt);
398399
}
399400

400401
drop:
@@ -427,9 +428,9 @@ static enum net_verdict ipv6_forward_mcast_packet(struct net_pkt *pkt,
427428
* 3. is from link local source
428429
* 4. hop limit is or would become zero
429430
*/
430-
if (net_ipv6_is_addr_mcast((struct in6_addr *)hdr->src) ||
431-
net_ipv6_is_addr_mcast_iface((struct in6_addr *)hdr->dst) ||
432-
net_ipv6_is_ll_addr((struct in6_addr *)hdr->src) || hdr->hop_limit <= 1) {
431+
if (net_ipv6_is_addr_mcast_raw(hdr->src) ||
432+
net_ipv6_is_addr_mcast_iface_raw(hdr->dst) ||
433+
net_ipv6_is_ll_addr_raw(hdr->src) || hdr->hop_limit <= 1) {
433434
return NET_CONTINUE;
434435
}
435436

@@ -462,11 +463,11 @@ static uint8_t extension_to_bitmap(uint8_t header, uint8_t ext_bitmap)
462463
}
463464
}
464465

465-
static inline bool is_src_non_tentative_itself(struct in6_addr *src)
466+
static inline bool is_src_non_tentative_itself(const uint8_t *src)
466467
{
467468
struct net_if_addr *ifaddr;
468469

469-
ifaddr = net_if_ipv6_addr_lookup(src, NULL);
470+
ifaddr = net_if_ipv6_addr_lookup_raw(src, NULL);
470471
if (ifaddr != NULL && ifaddr->addr_state != NET_ADDR_TENTATIVE) {
471472
return true;
472473
}
@@ -518,37 +519,37 @@ enum net_verdict net_ipv6_input(struct net_pkt *pkt, bool is_loopback)
518519
net_sprint_ipv6_addr(&hdr->src),
519520
net_sprint_ipv6_addr(&hdr->dst));
520521

521-
if (net_ipv6_is_addr_unspecified((struct in6_addr *)hdr->src)) {
522+
if (net_ipv6_is_addr_unspecified_raw(hdr->src)) {
522523
/* If this is a possible DAD message, let it pass. Extra checks
523524
* are done in duplicate address detection code to verify that
524525
* the packet is ok.
525526
*/
526527
if (!(IS_ENABLED(CONFIG_NET_IPV6_DAD) &&
527-
net_ipv6_is_addr_solicited_node((struct in6_addr *)hdr->dst))) {
528+
net_ipv6_is_addr_solicited_node_raw(hdr->dst))) {
528529
NET_DBG("DROP: src addr is %s", "unspecified");
529530
goto drop;
530531
}
531532
}
532533

533-
if (net_ipv6_is_addr_mcast((struct in6_addr *)hdr->src) ||
534-
net_ipv6_is_addr_mcast_scope((struct in6_addr *)hdr->dst, 0)) {
534+
if (net_ipv6_is_addr_mcast_raw(hdr->src) ||
535+
net_ipv6_is_addr_mcast_scope_raw(hdr->dst, 0)) {
535536
NET_DBG("DROP: multicast packet");
536537
goto drop;
537538
}
538539

539540
if (!is_loopback) {
540-
if (net_ipv6_is_addr_loopback((struct in6_addr *)hdr->dst) ||
541-
net_ipv6_is_addr_loopback((struct in6_addr *)hdr->src)) {
541+
if (net_ipv6_is_addr_loopback_raw(hdr->dst) ||
542+
net_ipv6_is_addr_loopback_raw(hdr->src)) {
542543
NET_DBG("DROP: ::1 packet");
543544
goto drop;
544545
}
545546

546-
if (net_ipv6_is_addr_mcast_iface((struct in6_addr *)hdr->dst) ||
547-
(net_ipv6_is_addr_mcast_group(
548-
(struct in6_addr *)hdr->dst,
549-
net_ipv6_unspecified_address()) &&
550-
(net_ipv6_is_addr_mcast_site((struct in6_addr *)hdr->dst) ||
551-
net_ipv6_is_addr_mcast_org((struct in6_addr *)hdr->dst)))) {
547+
if (net_ipv6_is_addr_mcast_iface_raw(hdr->dst) ||
548+
(net_ipv6_is_addr_mcast_group_raw(
549+
hdr->dst,
550+
(const uint8_t *)net_ipv6_unspecified_address()) &&
551+
(net_ipv6_is_addr_mcast_site_raw(hdr->dst) ||
552+
net_ipv6_is_addr_mcast_org_raw(hdr->dst)))) {
552553
NET_DBG("DROP: invalid scope multicast packet");
553554
goto drop;
554555
}
@@ -559,7 +560,7 @@ enum net_verdict net_ipv6_input(struct net_pkt *pkt, bool is_loopback)
559560
* This check is done later on if routing features are enabled.
560561
*/
561562
if (!IS_ENABLED(CONFIG_NET_ROUTING) && !IS_ENABLED(CONFIG_NET_ROUTE_MCAST) &&
562-
is_src_non_tentative_itself((struct in6_addr *)hdr->src)) {
563+
is_src_non_tentative_itself(hdr->src)) {
563564
NET_DBG("DROP: src addr is %s", "mine");
564565
goto drop;
565566
}
@@ -589,7 +590,7 @@ enum net_verdict net_ipv6_input(struct net_pkt *pkt, bool is_loopback)
589590
}
590591

591592
if (IS_ENABLED(CONFIG_NET_ROUTE_MCAST) &&
592-
net_ipv6_is_addr_mcast((struct in6_addr *)hdr->dst) && !net_pkt_forwarding(pkt)) {
593+
net_ipv6_is_addr_mcast_raw(hdr->dst) && !net_pkt_forwarding(pkt)) {
593594
/* If the packet is a multicast packet and multicast routing
594595
* is activated, we give the packet to the routing engine.
595596
*
@@ -603,14 +604,14 @@ enum net_verdict net_ipv6_input(struct net_pkt *pkt, bool is_loopback)
603604
}
604605
}
605606

606-
if (!net_ipv6_is_addr_mcast((struct in6_addr *)hdr->dst)) {
607-
if (!net_if_ipv6_addr_lookup_by_iface(pkt_iface, (struct in6_addr *)hdr->dst)) {
607+
if (!net_ipv6_is_addr_mcast_raw(hdr->dst)) {
608+
if (!net_if_ipv6_addr_lookup_by_iface_raw(pkt_iface, hdr->dst)) {
608609
if (ipv6_route_packet(pkt, hdr) == NET_OK) {
609610
return NET_OK;
610611
}
611612

612613
NET_DBG("DROP: no such address %s in iface %d",
613-
net_sprint_ipv6_addr((struct in6_addr *)hdr->dst),
614+
net_sprint_ipv6_addr(hdr->dst),
614615
net_if_get_by_iface(pkt_iface));
615616
goto drop;
616617
}
@@ -621,25 +622,23 @@ enum net_verdict net_ipv6_input(struct net_pkt *pkt, bool is_loopback)
621622
* RFC 4291 ch 2.5.6
622623
*/
623624
if (IS_ENABLED(CONFIG_NET_ROUTING) &&
624-
net_ipv6_is_ll_addr((struct in6_addr *)hdr->src) &&
625-
!net_if_ipv6_addr_lookup_by_iface(
626-
pkt_iface, (struct in6_addr *)hdr->dst)) {
627-
ipv6_no_route_info(pkt, (struct in6_addr *)hdr->src,
628-
(struct in6_addr *)hdr->dst);
625+
net_ipv6_is_ll_addr_raw(hdr->src) &&
626+
!net_if_ipv6_addr_lookup_by_iface_raw(pkt_iface, hdr->dst)) {
627+
ipv6_no_route_info(pkt, hdr->src, hdr->dst);
629628
NET_DBG("DROP: cross interface boundary");
630629
goto drop;
631630
}
632631
}
633632

634633
if ((IS_ENABLED(CONFIG_NET_ROUTING) || IS_ENABLED(CONFIG_NET_ROUTE_MCAST)) &&
635-
!is_loopback && is_src_non_tentative_itself((struct in6_addr *)hdr->src)) {
634+
!is_loopback && is_src_non_tentative_itself(hdr->src)) {
636635
NET_DBG("DROP: src addr is %s", "mine");
637636
goto drop;
638637
}
639638

640-
if (net_ipv6_is_addr_mcast((struct in6_addr *)hdr->dst) &&
641-
!(net_ipv6_is_addr_mcast_iface((struct in6_addr *)hdr->dst) ||
642-
net_ipv6_is_addr_mcast_link_all_nodes((struct in6_addr *)hdr->dst))) {
639+
if (net_ipv6_is_addr_mcast_raw(hdr->dst) &&
640+
!(net_ipv6_is_addr_mcast_iface_raw(hdr->dst) ||
641+
net_ipv6_is_addr_mcast_link_all_nodes_raw(hdr->dst))) {
643642
/* If we receive a packet with a interface-local or
644643
* link-local all-nodes multicast destination address we
645644
* always have to pass it to the upper layer.
@@ -650,9 +649,7 @@ enum net_verdict net_ipv6_input(struct net_pkt *pkt, bool is_loopback)
650649
* packet will be dropped.
651650
* RFC4291 ch 2.7.1, ch 2.8
652651
*/
653-
if_mcast_addr = net_if_ipv6_maddr_lookup(
654-
(struct in6_addr *)hdr->dst, &pkt_iface);
655-
652+
if_mcast_addr = net_if_ipv6_maddr_lookup_raw(hdr->dst, &pkt_iface);
656653
if (!if_mcast_addr ||
657654
!net_if_ipv6_maddr_is_joined(if_mcast_addr)) {
658655
NET_DBG("DROP: packet for unjoined multicast address");

0 commit comments

Comments
 (0)