Skip to content

Commit 8124032

Browse files
rlubosdanieldegrasse
authored andcommitted
net: ipv4: Avoid casting unaligned address to struct in_addr
Rework the IPv4-related code to avoid casting. Use raw variants of IPv4-related functions whenever possible (especially on the critical data path). Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
1 parent f549bfc commit 8124032

File tree

7 files changed

+82
-79
lines changed

7 files changed

+82
-79
lines changed

subsys/net/ip/connection.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -576,8 +576,7 @@ static bool conn_are_endpoints_valid(struct net_pkt *pkt, uint8_t family,
576576
bool is_same_src_and_dst_addr;
577577

578578
if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
579-
is_my_src_addr = net_ipv4_is_my_addr(
580-
(struct in_addr *)ip_hdr->ipv4->src);
579+
is_my_src_addr = net_ipv4_is_my_addr_raw(ip_hdr->ipv4->src);
581580
is_same_src_and_dst_addr = net_ipv4_addr_cmp_raw(
582581
ip_hdr->ipv4->src, ip_hdr->ipv4->dst);
583582
} else if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
@@ -925,10 +924,10 @@ enum net_verdict net_conn_input(struct net_pkt *pkt,
925924
* need to deliver the packet to multiple recipients.
926925
*/
927926
if (IS_ENABLED(CONFIG_NET_IPV4) && pkt_family == AF_INET) {
928-
if (net_ipv4_is_addr_mcast((struct in_addr *)ip_hdr->ipv4->dst)) {
927+
if (net_ipv4_is_addr_mcast_raw(ip_hdr->ipv4->dst)) {
929928
is_mcast_pkt = true;
930-
} else if (net_if_ipv4_is_addr_bcast(pkt_iface,
931-
(struct in_addr *)ip_hdr->ipv4->dst)) {
929+
} else if (net_if_ipv4_is_addr_bcast_raw(pkt_iface,
930+
ip_hdr->ipv4->dst)) {
932931
is_bcast_pkt = true;
933932
}
934933
} else if (IS_ENABLED(CONFIG_NET_IPV6) && pkt_family == AF_INET6) {

subsys/net/ip/icmpv4.c

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -420,20 +420,24 @@ static int icmpv4_handle_echo_request(struct net_icmp_ctx *ctx,
420420
{
421421
struct net_pkt *reply = NULL;
422422
struct net_ipv4_hdr *ip_hdr = hdr->ipv4;
423+
struct in_addr req_src, req_dst;
423424
const struct in_addr *src;
424425
int16_t payload_len;
425426

427+
net_ipv4_addr_copy_raw(req_src.s4_addr, ip_hdr->src);
428+
net_ipv4_addr_copy_raw(req_dst.s4_addr, ip_hdr->dst);
429+
426430
/* If interface can not select src address based on dst addr
427431
* and src address is unspecified, drop the echo request.
428432
*/
429-
if (net_ipv4_is_addr_unspecified((struct in_addr *)ip_hdr->src)) {
433+
if (net_ipv4_is_addr_unspecified(&req_src)) {
430434
NET_DBG("DROP: src addr is unspecified");
431435
goto drop;
432436
}
433437

434438
NET_DBG("Received Echo Request from %s to %s",
435-
net_sprint_ipv4_addr(&ip_hdr->src),
436-
net_sprint_ipv4_addr(&ip_hdr->dst));
439+
net_sprint_ipv4_addr(&req_src),
440+
net_sprint_ipv4_addr(&req_dst));
437441

438442
payload_len = net_pkt_get_len(pkt) -
439443
net_pkt_ip_hdr_len(pkt) -
@@ -453,24 +457,22 @@ static int icmpv4_handle_echo_request(struct net_icmp_ctx *ctx,
453457
goto drop;
454458
}
455459

456-
if (net_ipv4_is_addr_mcast((struct in_addr *)ip_hdr->dst) ||
457-
net_ipv4_is_addr_bcast(net_pkt_iface(pkt),
458-
(struct in_addr *)ip_hdr->dst)) {
459-
src = net_if_ipv4_select_src_addr(net_pkt_iface(pkt),
460-
(struct in_addr *)ip_hdr->src);
460+
if (net_ipv4_is_addr_mcast(&req_dst) ||
461+
net_ipv4_is_addr_bcast(net_pkt_iface(pkt), &req_dst)) {
462+
src = net_if_ipv4_select_src_addr(net_pkt_iface(pkt), &req_src);
461463

462464
if (net_ipv4_is_addr_unspecified(src)) {
463465
NET_DBG("DROP: No src address match");
464466
goto drop;
465467
}
466468
} else {
467-
src = (struct in_addr *)ip_hdr->dst;
469+
src = &req_dst;
468470
}
469471

470472
net_pkt_set_ip_dscp(reply, net_pkt_ip_dscp(pkt));
471473
net_pkt_set_ip_ecn(reply, net_pkt_ip_ecn(pkt));
472474

473-
if (net_ipv4_create(reply, src, (struct in_addr *)ip_hdr->src)) {
475+
if (net_ipv4_create(reply, src, &req_src)) {
474476
goto drop;
475477
}
476478

@@ -491,7 +493,7 @@ static int icmpv4_handle_echo_request(struct net_icmp_ctx *ctx,
491493

492494
NET_DBG("Sending Echo Reply from %s to %s",
493495
net_sprint_ipv4_addr(src),
494-
net_sprint_ipv4_addr(&ip_hdr->src));
496+
net_sprint_ipv4_addr(&req_src));
495497

496498
if (net_try_send_data(reply, K_NO_WAIT) < 0) {
497499
goto drop;
@@ -515,6 +517,7 @@ int net_icmpv4_send_error(struct net_pkt *orig, uint8_t type, uint8_t code)
515517
NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv4_access, struct net_ipv4_hdr);
516518
int err = -EIO;
517519
struct net_ipv4_hdr *ip_hdr;
520+
struct in_addr orig_src, orig_dst;
518521
struct net_pkt *pkt;
519522
size_t copy_len;
520523

@@ -539,13 +542,15 @@ int net_icmpv4_send_error(struct net_pkt *orig, uint8_t type, uint8_t code)
539542
}
540543
}
541544

542-
if (net_ipv4_is_addr_bcast(net_pkt_iface(orig),
543-
(struct in_addr *)ip_hdr->dst)) {
545+
net_ipv4_addr_copy_raw(orig_src.s4_addr, ip_hdr->src);
546+
net_ipv4_addr_copy_raw(orig_dst.s4_addr, ip_hdr->dst);
547+
548+
if (net_ipv4_is_addr_bcast(net_pkt_iface(orig), &orig_dst)) {
544549
/* We should not send an error to packet that
545550
* were sent to broadcast
546551
*/
547552
NET_DBG("Not sending error to bcast pkt from %s on proto %s",
548-
net_sprint_ipv4_addr(&ip_hdr->src),
553+
net_sprint_ipv4_addr(&orig_src),
549554
net_proto2str(AF_INET, ip_hdr->proto));
550555
goto drop_no_pkt;
551556
}
@@ -569,8 +574,7 @@ int net_icmpv4_send_error(struct net_pkt *orig, uint8_t type, uint8_t code)
569574
goto drop_no_pkt;
570575
}
571576

572-
if (net_ipv4_create(pkt, (struct in_addr *)ip_hdr->dst,
573-
(struct in_addr *)ip_hdr->src) ||
577+
if (net_ipv4_create(pkt, &orig_dst, &orig_src) ||
574578
net_icmpv4_create(pkt, type, code) ||
575579
net_pkt_memset(pkt, 0, NET_ICMPV4_UNUSED_LEN) ||
576580
net_pkt_copy(pkt, orig, copy_len)) {
@@ -586,8 +590,8 @@ int net_icmpv4_send_error(struct net_pkt *orig, uint8_t type, uint8_t code)
586590

587591
NET_DBG("Sending ICMPv4 Error Message type %d code %d from %s to %s",
588592
type, code,
589-
net_sprint_ipv4_addr(&ip_hdr->dst),
590-
net_sprint_ipv4_addr(&ip_hdr->src));
593+
net_sprint_ipv4_addr(&orig_dst),
594+
net_sprint_ipv4_addr(&orig_src));
591595

592596
if (net_try_send_data(pkt, K_NO_WAIT) >= 0) {
593597
net_stats_update_icmp_sent(net_pkt_iface(orig));
@@ -626,8 +630,7 @@ enum net_verdict net_icmpv4_input(struct net_pkt *pkt,
626630
}
627631
}
628632

629-
if (net_ipv4_is_addr_bcast(net_pkt_iface(pkt),
630-
(struct in_addr *)ip_hdr->dst) &&
633+
if (net_ipv4_is_addr_bcast_raw(net_pkt_iface(pkt), ip_hdr->dst) &&
631634
(!IS_ENABLED(CONFIG_NET_ICMPV4_ACCEPT_BROADCAST) ||
632635
icmp_hdr->type != NET_ICMPV4_ECHO_REQUEST)) {
633636
NET_DBG("DROP: broadcast pkt");

subsys/net/ip/ipv4.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -302,30 +302,30 @@ enum net_verdict net_ipv4_input(struct net_pkt *pkt, bool is_loopback)
302302
}
303303

304304
if (!is_loopback) {
305-
if (net_ipv4_is_addr_loopback((struct in_addr *)hdr->dst) ||
306-
net_ipv4_is_addr_loopback((struct in_addr *)hdr->src)) {
305+
if (net_ipv4_is_addr_loopback_raw(hdr->dst) ||
306+
net_ipv4_is_addr_loopback_raw(hdr->src)) {
307307
NET_DBG("DROP: localhost packet");
308308
goto drop;
309309
}
310310

311-
if (net_ipv4_is_my_addr((struct in_addr *)hdr->src)) {
311+
if (net_ipv4_is_my_addr_raw(hdr->src)) {
312312
NET_DBG("DROP: src addr is %s", "mine");
313313
goto drop;
314314
}
315315
}
316316

317-
if (net_ipv4_is_addr_mcast((struct in_addr *)hdr->src)) {
317+
if (net_ipv4_is_addr_mcast_raw(hdr->src)) {
318318
NET_DBG("DROP: src addr is %s", "mcast");
319319
goto drop;
320320
}
321321

322-
if (net_ipv4_is_addr_bcast(net_pkt_iface(pkt), (struct in_addr *)hdr->src)) {
322+
if (net_ipv4_is_addr_bcast_raw(net_pkt_iface(pkt), hdr->src)) {
323323
NET_DBG("DROP: src addr is %s", "bcast");
324324
goto drop;
325325
}
326326

327-
if (net_ipv4_is_addr_unspecified((struct in_addr *)hdr->src) &&
328-
!net_ipv4_is_addr_bcast(net_pkt_iface(pkt), (struct in_addr *)hdr->dst) &&
327+
if (net_ipv4_is_addr_unspecified_raw(hdr->src) &&
328+
!net_ipv4_is_addr_bcast_raw(net_pkt_iface(pkt), hdr->dst) &&
329329
(hdr->proto != IPPROTO_IGMP)) {
330330
NET_DBG("DROP: src addr is %s", "unspecified");
331331
goto drop;
@@ -347,17 +347,17 @@ enum net_verdict net_ipv4_input(struct net_pkt *pkt, bool is_loopback)
347347
return NET_DROP;
348348
}
349349

350-
if ((!net_ipv4_is_my_addr((struct in_addr *)hdr->dst) &&
351-
!net_ipv4_is_addr_mcast((struct in_addr *)hdr->dst) &&
350+
if ((!net_ipv4_is_my_addr_raw(hdr->dst) &&
351+
!net_ipv4_is_addr_mcast_raw(hdr->dst) &&
352352
!(hdr->proto == IPPROTO_UDP &&
353-
(net_ipv4_addr_cmp((struct in_addr *)hdr->dst, net_ipv4_broadcast_address()) ||
353+
(net_ipv4_addr_cmp_raw(hdr->dst, net_ipv4_broadcast_address()->s4_addr) ||
354354
/* RFC 1122 ch. 3.3.6 The 0.0.0.0 is non-standard bcast addr */
355355
(IS_ENABLED(CONFIG_NET_IPV4_ACCEPT_ZERO_BROADCAST) &&
356-
net_ipv4_addr_cmp((struct in_addr *)hdr->dst,
357-
net_ipv4_unspecified_address())) ||
356+
net_ipv4_addr_cmp_raw(hdr->dst,
357+
net_ipv4_unspecified_address()->s4_addr)) ||
358358
net_dhcpv4_accept_unicast(pkt)))) ||
359359
(hdr->proto == IPPROTO_TCP &&
360-
net_ipv4_is_addr_bcast(net_pkt_iface(pkt), (struct in_addr *)hdr->dst))) {
360+
net_ipv4_is_addr_bcast_raw(net_pkt_iface(pkt), hdr->dst))) {
361361
NET_DBG("DROP: not for me");
362362
goto drop;
363363
}

subsys/net/ip/ipv4_fragment.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,16 @@ static void reassembly_timeout(struct k_work *work);
3232

3333
static struct net_ipv4_reassembly reassembly[CONFIG_NET_IPV4_FRAGMENT_MAX_COUNT];
3434

35-
static struct net_ipv4_reassembly *reassembly_get(uint16_t id, struct in_addr *src,
36-
struct in_addr *dst, uint8_t protocol)
35+
static struct net_ipv4_reassembly *reassembly_get(uint16_t id, const uint8_t *src,
36+
const uint8_t *dst, uint8_t protocol)
3737
{
3838
int i, avail = -1;
3939

4040
for (i = 0; i < CONFIG_NET_IPV4_FRAGMENT_MAX_COUNT; i++) {
4141
if (k_work_delayable_remaining_get(&reassembly[i].timer) &&
4242
reassembly[i].id == id &&
43-
net_ipv4_addr_cmp(src, &reassembly[i].src) &&
44-
net_ipv4_addr_cmp(dst, &reassembly[i].dst) &&
43+
net_ipv4_addr_cmp_raw(src, reassembly[i].src.s4_addr) &&
44+
net_ipv4_addr_cmp_raw(dst, reassembly[i].dst.s4_addr) &&
4545
reassembly[i].protocol == protocol) {
4646
return &reassembly[i];
4747
}
@@ -61,8 +61,8 @@ static struct net_ipv4_reassembly *reassembly_get(uint16_t id, struct in_addr *s
6161

6262
k_work_reschedule(&reassembly[avail].timer, K_SECONDS(CONFIG_NET_IPV4_FRAGMENT_TIMEOUT));
6363

64-
net_ipaddr_copy(&reassembly[avail].src, src);
65-
net_ipaddr_copy(&reassembly[avail].dst, dst);
64+
net_ipv4_addr_copy_raw(reassembly[avail].src.s4_addr, src);
65+
net_ipv4_addr_copy_raw(reassembly[avail].dst.s4_addr, dst);
6666

6767
reassembly[avail].protocol = protocol;
6868
reassembly[avail].id = id;
@@ -331,8 +331,7 @@ enum net_verdict net_ipv4_handle_fragment_hdr(struct net_pkt *pkt, struct net_ip
331331
flag = ntohs(*((uint16_t *)&hdr->offset));
332332
id = ntohs(*((uint16_t *)&hdr->id));
333333

334-
reass = reassembly_get(id, (struct in_addr *)hdr->src,
335-
(struct in_addr *)hdr->dst, hdr->proto);
334+
reass = reassembly_get(id, hdr->src, hdr->dst, hdr->proto);
336335
if (!reass) {
337336
LOG_ERR("Cannot get reassembly slot, dropping pkt %p", pkt);
338337
goto drop;

subsys/net/ip/net_core.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,8 @@ static inline int check_ip(struct net_pkt *pkt)
300300
return 0;
301301
}
302302
#endif
303-
if (net_ipv4_addr_cmp((struct in_addr *)NET_IPV4_HDR(pkt)->dst,
304-
net_ipv4_unspecified_address())) {
303+
if (net_ipv4_addr_cmp_raw(NET_IPV4_HDR(pkt)->dst,
304+
net_ipv4_unspecified_address()->s4_addr)) {
305305
NET_DBG("DROP: IPv4 dst address missing");
306306
ret = -EADDRNOTAVAIL;
307307
goto drop;
@@ -310,10 +310,10 @@ static inline int check_ip(struct net_pkt *pkt)
310310
/* If the destination address is our own, then route it
311311
* back to us.
312312
*/
313-
if (net_ipv4_is_addr_loopback((struct in_addr *)NET_IPV4_HDR(pkt)->dst) ||
314-
(net_ipv4_is_addr_bcast(net_pkt_iface(pkt),
315-
(struct in_addr *)NET_IPV4_HDR(pkt)->dst) == false &&
316-
net_ipv4_is_my_addr((struct in_addr *)NET_IPV4_HDR(pkt)->dst))) {
313+
if (net_ipv4_is_addr_loopback_raw(NET_IPV4_HDR(pkt)->dst) ||
314+
(net_ipv4_is_addr_bcast_raw(net_pkt_iface(pkt),
315+
NET_IPV4_HDR(pkt)->dst) == false &&
316+
net_ipv4_is_my_addr_raw(NET_IPV4_HDR(pkt)->dst))) {
317317
struct in_addr addr;
318318

319319
/* Swap the addresses so that in receiving side
@@ -334,7 +334,7 @@ static inline int check_ip(struct net_pkt *pkt)
334334
* as having src 127.0.0.0/8 is perfectly ok if dst is in
335335
* localhost subnet too.
336336
*/
337-
if (net_ipv4_is_addr_loopback((struct in_addr *)NET_IPV4_HDR(pkt)->src)) {
337+
if (net_ipv4_is_addr_loopback_raw(NET_IPV4_HDR(pkt)->src)) {
338338
NET_DBG("DROP: IPv4 loopback src address");
339339
ret = -EADDRNOTAVAIL;
340340
goto drop;

0 commit comments

Comments
 (0)