Skip to content

Commit f549bfc

Browse files
rlubosdanieldegrasse
authored andcommitted
net: ipv4: Add raw variants of various IPv4 functions
To address the misaligned access issues reported by UBSAN, introduce raw variant of certain IPv4 functions used in the critical data path of the network stack, operating on plain uint8_t buffers in stead of IPv4 address struct. Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
1 parent 0f6dcb3 commit f549bfc

File tree

2 files changed

+106
-24
lines changed

2 files changed

+106
-24
lines changed

include/zephyr/net/net_ip.h

Lines changed: 87 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,13 @@ static inline void net_ipv6_addr_prefix_mask(const uint8_t *inaddr,
829829
outaddr[bytes] = inaddr[bytes] & mask;
830830
}
831831

832+
/** @cond INTERNAL_HIDDEN */
833+
static inline bool net_ipv4_is_addr_loopback_raw(const uint8_t *addr)
834+
{
835+
return addr[0] == 127U;
836+
}
837+
/** @endcond */
838+
832839
/**
833840
* @brief Check if the IPv4 address is a loopback address (127.0.0.0/8).
834841
*
@@ -838,8 +845,15 @@ static inline void net_ipv6_addr_prefix_mask(const uint8_t *inaddr,
838845
*/
839846
static inline bool net_ipv4_is_addr_loopback(struct in_addr *addr)
840847
{
841-
return addr->s4_addr[0] == 127U;
848+
return net_ipv4_is_addr_loopback_raw(addr->s4_addr);
849+
}
850+
851+
/** @cond INTERNAL_HIDDEN */
852+
static inline bool net_ipv4_is_addr_unspecified_raw(const uint8_t *addr)
853+
{
854+
return UNALIGNED_GET((uint32_t *)addr) == 0;
842855
}
856+
/** @endcond */
843857

844858
/**
845859
* @brief Check if the IPv4 address is unspecified (all bits zero)
@@ -850,9 +864,16 @@ static inline bool net_ipv4_is_addr_loopback(struct in_addr *addr)
850864
*/
851865
static inline bool net_ipv4_is_addr_unspecified(const struct in_addr *addr)
852866
{
853-
return UNALIGNED_GET(&addr->s_addr) == 0;
867+
return net_ipv4_is_addr_unspecified_raw(addr->s4_addr);
854868
}
855869

870+
/** @cond INTERNAL_HIDDEN */
871+
static inline bool net_ipv4_is_addr_mcast_raw(const uint8_t *addr)
872+
{
873+
return (ntohl(UNALIGNED_GET((uint32_t *)addr)) & 0xF0000000) == 0xE0000000;
874+
}
875+
/** @endcond */
876+
856877
/**
857878
* @brief Check if the IPv4 address is a multicast address.
858879
*
@@ -862,8 +883,15 @@ static inline bool net_ipv4_is_addr_unspecified(const struct in_addr *addr)
862883
*/
863884
static inline bool net_ipv4_is_addr_mcast(const struct in_addr *addr)
864885
{
865-
return (ntohl(UNALIGNED_GET(&addr->s_addr)) & 0xF0000000) == 0xE0000000;
886+
return net_ipv4_is_addr_mcast_raw(addr->s4_addr);
887+
}
888+
889+
/** @cond INTERNAL_HIDDEN */
890+
static inline bool net_ipv4_is_ll_addr_raw(const uint8_t *addr)
891+
{
892+
return (ntohl(UNALIGNED_GET((uint32_t *)addr)) & 0xFFFF0000) == 0xA9FE0000;
866893
}
894+
/** @endcond */
867895

868896
/**
869897
* @brief Check if the given IPv4 address is a link local address.
@@ -874,7 +902,7 @@ static inline bool net_ipv4_is_addr_mcast(const struct in_addr *addr)
874902
*/
875903
static inline bool net_ipv4_is_ll_addr(const struct in_addr *addr)
876904
{
877-
return (ntohl(UNALIGNED_GET(&addr->s_addr)) & 0xFFFF0000) == 0xA9FE0000;
905+
return net_ipv4_is_ll_addr_raw(addr->s4_addr);
878906
}
879907

880908
/**
@@ -941,32 +969,31 @@ static inline void net_ipv6_addr_copy_raw(uint8_t *dest,
941969
}
942970

943971
/**
944-
* @brief Compare two IPv4 addresses
972+
* @brief Compare two raw IPv4 address buffers
945973
*
946-
* @param addr1 Pointer to IPv4 address.
947-
* @param addr2 Pointer to IPv4 address.
974+
* @param addr1 Pointer to IPv4 address buffer.
975+
* @param addr2 Pointer to IPv4 address buffer.
948976
*
949977
* @return True if the addresses are the same, false otherwise.
950978
*/
951-
static inline bool net_ipv4_addr_cmp(const struct in_addr *addr1,
952-
const struct in_addr *addr2)
979+
static inline bool net_ipv4_addr_cmp_raw(const uint8_t *addr1,
980+
const uint8_t *addr2)
953981
{
954-
return UNALIGNED_GET(&addr1->s_addr) == UNALIGNED_GET(&addr2->s_addr);
982+
return UNALIGNED_GET((uint32_t *)addr1) == UNALIGNED_GET((uint32_t *)addr2);
955983
}
956984

957985
/**
958-
* @brief Compare two raw IPv4 address buffers
986+
* @brief Compare two IPv4 addresses
959987
*
960-
* @param addr1 Pointer to IPv4 address buffer.
961-
* @param addr2 Pointer to IPv4 address buffer.
988+
* @param addr1 Pointer to IPv4 address.
989+
* @param addr2 Pointer to IPv4 address.
962990
*
963991
* @return True if the addresses are the same, false otherwise.
964992
*/
965-
static inline bool net_ipv4_addr_cmp_raw(const uint8_t *addr1,
966-
const uint8_t *addr2)
993+
static inline bool net_ipv4_addr_cmp(const struct in_addr *addr1,
994+
const struct in_addr *addr2)
967995
{
968-
return net_ipv4_addr_cmp((const struct in_addr *)addr1,
969-
(const struct in_addr *)addr2);
996+
return net_ipv4_addr_cmp_raw(addr1->s4_addr, addr2->s4_addr);
970997
}
971998

972999
/**
@@ -1114,6 +1141,32 @@ static inline bool net_ipv4_addr_mask_cmp(struct net_if *iface,
11141141
return net_if_ipv4_addr_mask_cmp(iface, addr);
11151142
}
11161143

1144+
/** @cond INTERNAL_HIDDEN */
1145+
extern bool net_if_ipv4_is_addr_bcast_raw(struct net_if *iface,
1146+
const uint8_t *addr);
1147+
1148+
#if defined(CONFIG_NET_NATIVE_IPV4)
1149+
static inline bool net_ipv4_is_addr_bcast_raw(struct net_if *iface,
1150+
const uint8_t *addr)
1151+
{
1152+
if (net_ipv4_addr_cmp_raw(addr, net_ipv4_broadcast_address()->s4_addr)) {
1153+
return true;
1154+
}
1155+
1156+
return net_if_ipv4_is_addr_bcast_raw(iface, addr);
1157+
}
1158+
#else
1159+
static inline bool net_ipv4_is_addr_bcast_raw(struct net_if *iface,
1160+
const uint8_t *addr)
1161+
{
1162+
ARG_UNUSED(iface);
1163+
ARG_UNUSED(addr);
1164+
1165+
return false;
1166+
}
1167+
#endif
1168+
/** @endcond */
1169+
11171170
extern bool net_if_ipv4_is_addr_bcast(struct net_if *iface,
11181171
const struct in_addr *addr);
11191172

@@ -1146,6 +1199,23 @@ static inline bool net_ipv4_is_addr_bcast(struct net_if *iface,
11461199
}
11471200
#endif
11481201

1202+
/** @cond INTERNAL_HIDDEN */
1203+
extern struct net_if_addr *net_if_ipv4_addr_lookup_raw(const uint8_t *addr,
1204+
struct net_if **ret);
1205+
1206+
static inline bool net_ipv4_is_my_addr_raw(const uint8_t *addr)
1207+
{
1208+
bool ret;
1209+
1210+
ret = net_if_ipv4_addr_lookup_raw(addr, NULL) != NULL;
1211+
if (!ret) {
1212+
ret = net_ipv4_is_addr_bcast_raw(NULL, addr);
1213+
}
1214+
1215+
return ret;
1216+
}
1217+
/** @endcond */
1218+
11491219
extern struct net_if_addr *net_if_ipv4_addr_lookup(const struct in_addr *addr,
11501220
struct net_if **iface);
11511221

subsys/net/ip/net_if.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3658,7 +3658,7 @@ bool net_if_ipv4_addr_mask_cmp(struct net_if *iface,
36583658
}
36593659

36603660
static bool ipv4_is_broadcast_address(struct net_if *iface,
3661-
const struct in_addr *addr)
3661+
const uint8_t *addr)
36623662
{
36633663
struct net_if_ipv4 *ipv4;
36643664
bool ret = false;
@@ -3681,7 +3681,7 @@ static bool ipv4_is_broadcast_address(struct net_if *iface,
36813681
bcast.s_addr = ipv4->unicast[i].ipv4.address.in_addr.s_addr |
36823682
~ipv4->unicast[i].netmask.s_addr;
36833683

3684-
if (bcast.s_addr == UNALIGNED_GET(&addr->s_addr)) {
3684+
if (bcast.s_addr == UNALIGNED_GET((uint32_t *)addr)) {
36853685
ret = true;
36863686
goto out;
36873687
}
@@ -3692,8 +3692,8 @@ static bool ipv4_is_broadcast_address(struct net_if *iface,
36923692
return ret;
36933693
}
36943694

3695-
bool net_if_ipv4_is_addr_bcast(struct net_if *iface,
3696-
const struct in_addr *addr)
3695+
bool net_if_ipv4_is_addr_bcast_raw(struct net_if *iface,
3696+
const uint8_t *addr)
36973697
{
36983698
bool ret = false;
36993699

@@ -3713,6 +3713,12 @@ bool net_if_ipv4_is_addr_bcast(struct net_if *iface,
37133713
return ret;
37143714
}
37153715

3716+
bool net_if_ipv4_is_addr_bcast(struct net_if *iface,
3717+
const struct in_addr *addr)
3718+
{
3719+
return net_if_ipv4_is_addr_bcast_raw(iface, addr->s4_addr);
3720+
}
3721+
37163722
struct net_if *net_if_ipv4_select_src_iface_addr(const struct in_addr *dst,
37173723
const struct in_addr **src_addr)
37183724
{
@@ -3987,8 +3993,8 @@ struct net_if_addr *net_if_ipv4_addr_get_first_by_index(int ifindex)
39873993
return ifaddr;
39883994
}
39893995

3990-
struct net_if_addr *net_if_ipv4_addr_lookup(const struct in_addr *addr,
3991-
struct net_if **ret)
3996+
struct net_if_addr *net_if_ipv4_addr_lookup_raw(const uint8_t *addr,
3997+
struct net_if **ret)
39923998
{
39933999
struct net_if_addr *ifaddr = NULL;
39944000

@@ -4009,7 +4015,7 @@ struct net_if_addr *net_if_ipv4_addr_lookup(const struct in_addr *addr,
40094015
continue;
40104016
}
40114017

4012-
if (UNALIGNED_GET(&addr->s4_addr32[0]) ==
4018+
if (UNALIGNED_GET((uint32_t *)addr) ==
40134019
ipv4->unicast[i].ipv4.address.in_addr.s_addr) {
40144020

40154021
if (ret) {
@@ -4029,6 +4035,12 @@ struct net_if_addr *net_if_ipv4_addr_lookup(const struct in_addr *addr,
40294035
return ifaddr;
40304036
}
40314037

4038+
struct net_if_addr *net_if_ipv4_addr_lookup(const struct in_addr *addr,
4039+
struct net_if **ret)
4040+
{
4041+
return net_if_ipv4_addr_lookup_raw(addr->s4_addr, ret);
4042+
}
4043+
40324044
int z_impl_net_if_ipv4_addr_lookup_by_index(const struct in_addr *addr)
40334045
{
40344046
struct net_if_addr *if_addr;

0 commit comments

Comments
 (0)