Skip to content

Commit 74ccd5f

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

File tree

3 files changed

+206
-56
lines changed

3 files changed

+206
-56
lines changed

include/zephyr/net/net_if.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,6 +1522,12 @@ int net_if_config_ipv6_get(struct net_if *iface,
15221522
*/
15231523
int net_if_config_ipv6_put(struct net_if *iface);
15241524

1525+
1526+
/** @cond INTERNAL_HIDDEN */
1527+
struct net_if_addr *net_if_ipv6_addr_lookup_raw(const uint8_t *addr,
1528+
struct net_if **ret);
1529+
/** @endcond */
1530+
15251531
/**
15261532
* @brief Check if this IPv6 address belongs to one of the interfaces.
15271533
*
@@ -1533,6 +1539,11 @@ int net_if_config_ipv6_put(struct net_if *iface);
15331539
struct net_if_addr *net_if_ipv6_addr_lookup(const struct in6_addr *addr,
15341540
struct net_if **iface);
15351541

1542+
/** @cond INTERNAL_HIDDEN */
1543+
struct net_if_addr *net_if_ipv6_addr_lookup_by_iface_raw(struct net_if *iface,
1544+
const uint8_t *addr);
1545+
/** @endcond */
1546+
15361547
/**
15371548
* @brief Check if this IPv6 address belongs to this specific interfaces.
15381549
*
@@ -1681,6 +1692,12 @@ typedef void (*net_if_ip_maddr_cb_t)(struct net_if *iface,
16811692
void net_if_ipv6_maddr_foreach(struct net_if *iface, net_if_ip_maddr_cb_t cb,
16821693
void *user_data);
16831694

1695+
1696+
/** @cond INTERNAL_HIDDEN */
1697+
struct net_if_mcast_addr *net_if_ipv6_maddr_lookup_raw(const uint8_t *maddr,
1698+
struct net_if **ret);
1699+
/** @endcond */
1700+
16841701
/**
16851702
* @brief Check if this IPv6 multicast address belongs to a specific interface
16861703
* or one of the interfaces.

include/zephyr/net/net_ip.h

Lines changed: 162 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,16 @@ union net_proto_header {
673673

674674
/** @endcond */
675675

676+
/** @cond INTERNAL_HIDDEN */
677+
static inline bool net_ipv6_is_addr_loopback_raw(const uint8_t *addr)
678+
{
679+
return UNALIGNED_GET((uint32_t *)addr) == 0 &&
680+
UNALIGNED_GET((uint32_t *)addr + 1) == 0 &&
681+
UNALIGNED_GET((uint32_t *)addr + 2) == 0 &&
682+
ntohl(UNALIGNED_GET((uint32_t *)addr + 3)) == 1;
683+
}
684+
/** @endcond */
685+
676686
/**
677687
* @brief Check if the IPv6 address is a loopback address (::1).
678688
*
@@ -682,11 +692,15 @@ union net_proto_header {
682692
*/
683693
static inline bool net_ipv6_is_addr_loopback(struct in6_addr *addr)
684694
{
685-
return UNALIGNED_GET(&addr->s6_addr32[0]) == 0 &&
686-
UNALIGNED_GET(&addr->s6_addr32[1]) == 0 &&
687-
UNALIGNED_GET(&addr->s6_addr32[2]) == 0 &&
688-
ntohl(UNALIGNED_GET(&addr->s6_addr32[3])) == 1;
695+
return net_ipv6_is_addr_loopback_raw(addr->s6_addr);
696+
}
697+
698+
/** @cond INTERNAL_HIDDEN */
699+
static inline bool net_ipv6_is_addr_mcast_raw(const uint8_t *addr)
700+
{
701+
return addr[0] == 0xff;
689702
}
703+
/** @endcond */
690704

691705
/**
692706
* @brief Check if the IPv6 address is a multicast address.
@@ -697,12 +711,22 @@ static inline bool net_ipv6_is_addr_loopback(struct in6_addr *addr)
697711
*/
698712
static inline bool net_ipv6_is_addr_mcast(const struct in6_addr *addr)
699713
{
700-
return addr->s6_addr[0] == 0xFF;
714+
return net_ipv6_is_addr_mcast_raw(addr->s6_addr);
701715
}
702716

703717
struct net_if;
704718
struct net_if_config;
705719

720+
/** @cond INTERNAL_HIDDEN */
721+
extern struct net_if_addr *net_if_ipv6_addr_lookup_raw(const uint8_t *addr,
722+
struct net_if **ret);
723+
724+
static inline bool net_ipv6_is_my_addr_raw(const uint8_t *addr)
725+
{
726+
return net_if_ipv6_addr_lookup_raw(addr, NULL) != NULL;
727+
}
728+
/** @endcond */
729+
706730
extern struct net_if_addr *net_if_ipv6_addr_lookup(const struct in6_addr *addr,
707731
struct net_if **iface);
708732

@@ -974,6 +998,13 @@ static inline bool net_ipv6_addr_cmp_raw(const uint8_t *addr1,
974998
(const struct in6_addr *)addr2);
975999
}
9761000

1001+
/** @cond INTERNAL_HIDDEN */
1002+
static inline bool net_ipv6_is_ll_addr_raw(const uint8_t *addr)
1003+
{
1004+
return UNALIGNED_GET((uint16_t *)addr) == htons(0xFE80);
1005+
}
1006+
/** @endcond */
1007+
9771008
/**
9781009
* @brief Check if the given IPv6 address is a link local address.
9791010
*
@@ -983,7 +1014,7 @@ static inline bool net_ipv6_addr_cmp_raw(const uint8_t *addr1,
9831014
*/
9841015
static inline bool net_ipv6_is_ll_addr(const struct in6_addr *addr)
9851016
{
986-
return UNALIGNED_GET(&addr->s6_addr16[0]) == htons(0xFE80);
1017+
return net_ipv6_is_ll_addr_raw(addr->s6_addr);
9871018
}
9881019

9891020
/**
@@ -1139,6 +1170,16 @@ static inline bool net_ipv4_is_my_addr(const struct in_addr *addr)
11391170
return ret;
11401171
}
11411172

1173+
/** @cond INTERNAL_HIDDEN */
1174+
static inline bool net_ipv6_is_addr_unspecified_raw(const uint8_t *addr)
1175+
{
1176+
return UNALIGNED_GET((uint32_t *)addr) == 0 &&
1177+
UNALIGNED_GET((uint32_t *)addr + 1) == 0 &&
1178+
UNALIGNED_GET((uint32_t *)addr + 2) == 0 &&
1179+
UNALIGNED_GET((uint32_t *)addr + 3) == 0;
1180+
}
1181+
/** @endcond */
1182+
11421183
/**
11431184
* @brief Check if the IPv6 address is unspecified (all bits zero)
11441185
*
@@ -1148,11 +1189,19 @@ static inline bool net_ipv4_is_my_addr(const struct in_addr *addr)
11481189
*/
11491190
static inline bool net_ipv6_is_addr_unspecified(const struct in6_addr *addr)
11501191
{
1151-
return UNALIGNED_GET(&addr->s6_addr32[0]) == 0 &&
1152-
UNALIGNED_GET(&addr->s6_addr32[1]) == 0 &&
1153-
UNALIGNED_GET(&addr->s6_addr32[2]) == 0 &&
1154-
UNALIGNED_GET(&addr->s6_addr32[3]) == 0;
1192+
return net_ipv6_is_addr_unspecified_raw(addr->s6_addr);
1193+
}
1194+
1195+
/** @cond INTERNAL_HIDDEN */
1196+
static inline bool net_ipv6_is_addr_solicited_node_raw(const uint8_t *addr)
1197+
{
1198+
return UNALIGNED_GET((uint32_t *)addr) == htonl(0xff020000) &&
1199+
UNALIGNED_GET((uint32_t *)addr + 1) == 0x00000000 &&
1200+
UNALIGNED_GET((uint32_t *)addr + 2) == htonl(0x00000001) &&
1201+
((UNALIGNED_GET((uint32_t *)addr + 3) & htonl(0xff000000)) ==
1202+
htonl(0xff000000));
11551203
}
1204+
/** @endcond */
11561205

11571206
/**
11581207
* @brief Check if the IPv6 address is solicited node multicast address
@@ -1164,12 +1213,16 @@ static inline bool net_ipv6_is_addr_unspecified(const struct in6_addr *addr)
11641213
*/
11651214
static inline bool net_ipv6_is_addr_solicited_node(const struct in6_addr *addr)
11661215
{
1167-
return UNALIGNED_GET(&addr->s6_addr32[0]) == htonl(0xff020000) &&
1168-
UNALIGNED_GET(&addr->s6_addr32[1]) == 0x00000000 &&
1169-
UNALIGNED_GET(&addr->s6_addr32[2]) == htonl(0x00000001) &&
1170-
((UNALIGNED_GET(&addr->s6_addr32[3]) & htonl(0xff000000)) ==
1171-
htonl(0xff000000));
1216+
return net_ipv6_is_addr_solicited_node_raw(addr->s6_addr);
1217+
}
1218+
1219+
/** @cond INTERNAL_HIDDEN */
1220+
static inline bool net_ipv6_is_addr_mcast_scope_raw(const uint8_t *addr,
1221+
int scope)
1222+
{
1223+
return (addr[0] == 0xff) && ((addr[1] & 0xF) == scope);
11721224
}
1225+
/** @endcond */
11731226

11741227
/**
11751228
* @brief Check if the IPv6 address is a given scope multicast
@@ -1184,7 +1237,7 @@ static inline bool net_ipv6_is_addr_solicited_node(const struct in6_addr *addr)
11841237
static inline bool net_ipv6_is_addr_mcast_scope(const struct in6_addr *addr,
11851238
int scope)
11861239
{
1187-
return (addr->s6_addr[0] == 0xff) && ((addr->s6_addr[1] & 0xF) == scope);
1240+
return net_ipv6_is_addr_mcast_scope_raw(addr->s6_addr, scope);
11881241
}
11891242

11901243
/**
@@ -1203,6 +1256,33 @@ static inline bool net_ipv6_is_same_mcast_scope(const struct in6_addr *addr_1,
12031256
(addr_1->s6_addr[1] == addr_2->s6_addr[1]);
12041257
}
12051258

1259+
/** @cond INTERNAL_HIDDEN */
1260+
static inline bool net_ipv6_is_addr_mcast_iface_raw(const uint8_t *addr)
1261+
{
1262+
return net_ipv6_is_addr_mcast_scope_raw(addr, 0x01);
1263+
}
1264+
1265+
static inline bool net_ipv6_is_addr_mcast_link_raw(const uint8_t *addr)
1266+
{
1267+
return net_ipv6_is_addr_mcast_scope_raw(addr, 0x02);
1268+
}
1269+
1270+
static inline bool net_ipv6_is_addr_mcast_mesh_raw(const uint8_t *addr)
1271+
{
1272+
return net_ipv6_is_addr_mcast_scope_raw(addr, 0x03);
1273+
}
1274+
1275+
static inline bool net_ipv6_is_addr_mcast_site_raw(const uint8_t *addr)
1276+
{
1277+
return net_ipv6_is_addr_mcast_scope_raw(addr, 0x05);
1278+
}
1279+
1280+
static inline bool net_ipv6_is_addr_mcast_org_raw(const uint8_t *addr)
1281+
{
1282+
return net_ipv6_is_addr_mcast_scope_raw(addr, 0x08);
1283+
}
1284+
/** @endcond */
1285+
12061286
/**
12071287
* @brief Check if the IPv6 address is a global multicast address (FFxE::/16).
12081288
*
@@ -1285,6 +1365,17 @@ static inline bool net_ipv6_is_addr_mcast_org(const struct in6_addr *addr)
12851365
return net_ipv6_is_addr_mcast_scope(addr, 0x08);
12861366
}
12871367

1368+
/** @cond INTERNAL_HIDDEN */
1369+
static inline bool net_ipv6_is_addr_mcast_group_raw(const uint8_t *addr,
1370+
const uint8_t *group)
1371+
{
1372+
return UNALIGNED_GET((uint16_t *)addr + 1) == UNALIGNED_GET((uint16_t *)group + 1) &&
1373+
UNALIGNED_GET((uint32_t *)addr + 1) == UNALIGNED_GET((uint32_t *)group + 1) &&
1374+
UNALIGNED_GET((uint32_t *)addr + 2) == UNALIGNED_GET((uint32_t *)group + 2) &&
1375+
UNALIGNED_GET((uint32_t *)addr + 3) == UNALIGNED_GET((uint32_t *)group + 3);
1376+
}
1377+
/** @endcond */
1378+
12881379
/**
12891380
* @brief Check if the IPv6 address belongs to certain multicast group
12901381
*
@@ -1298,11 +1389,20 @@ static inline bool net_ipv6_is_addr_mcast_org(const struct in6_addr *addr)
12981389
static inline bool net_ipv6_is_addr_mcast_group(const struct in6_addr *addr,
12991390
const struct in6_addr *group)
13001391
{
1301-
return UNALIGNED_GET(&addr->s6_addr16[1]) == group->s6_addr16[1] &&
1302-
UNALIGNED_GET(&addr->s6_addr32[1]) == group->s6_addr32[1] &&
1303-
UNALIGNED_GET(&addr->s6_addr32[2]) == group->s6_addr32[2] &&
1304-
UNALIGNED_GET(&addr->s6_addr32[3]) == group->s6_addr32[3];
1392+
return net_ipv6_is_addr_mcast_group_raw(addr->s6_addr, group->s6_addr);
1393+
}
1394+
1395+
/** @cond INTERNAL_HIDDEN */
1396+
static inline bool net_ipv6_is_addr_mcast_all_nodes_group_raw(const uint8_t *addr)
1397+
{
1398+
static const uint8_t all_nodes_mcast_group[NET_IPV6_ADDR_SIZE] = {
1399+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1400+
0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1401+
};
1402+
1403+
return net_ipv6_is_addr_mcast_group_raw(addr, all_nodes_mcast_group);
13051404
}
1405+
/** @endcond */
13061406

13071407
/**
13081408
* @brief Check if the IPv6 address belongs to the all nodes multicast group
@@ -1315,12 +1415,7 @@ static inline bool net_ipv6_is_addr_mcast_group(const struct in6_addr *addr,
13151415
static inline bool
13161416
net_ipv6_is_addr_mcast_all_nodes_group(const struct in6_addr *addr)
13171417
{
1318-
static const struct in6_addr all_nodes_mcast_group = {
1319-
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1320-
0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1321-
};
1322-
1323-
return net_ipv6_is_addr_mcast_group(addr, &all_nodes_mcast_group);
1418+
return net_ipv6_is_addr_mcast_all_nodes_group_raw(addr->s6_addr);
13241419
}
13251420

13261421
/**
@@ -1339,6 +1434,14 @@ net_ipv6_is_addr_mcast_iface_all_nodes(const struct in6_addr *addr)
13391434
net_ipv6_is_addr_mcast_all_nodes_group(addr);
13401435
}
13411436

1437+
/** @cond INTERNAL_HIDDEN */
1438+
static inline bool net_ipv6_is_addr_mcast_link_all_nodes_raw(const uint8_t *addr)
1439+
{
1440+
return net_ipv6_is_addr_mcast_link_raw(addr) &&
1441+
net_ipv6_is_addr_mcast_all_nodes_group_raw(addr);
1442+
}
1443+
/** @endcond */
1444+
13421445
/**
13431446
* @brief Check if the IPv6 address is a link local scope all nodes multicast
13441447
* address (FF02::1).
@@ -1497,37 +1600,33 @@ static inline void net_ipv6_addr_create_iid(struct in6_addr *addr,
14971600
(void)net_ipv6_addr_generate_iid(NULL, NULL, NULL, 0, 0, addr, lladdr);
14981601
}
14991602

1500-
/**
1501-
* @brief Check if given address is based on link layer address
1502-
*
1503-
* @return True if it is, False otherwise
1504-
*/
1505-
static inline bool net_ipv6_addr_based_on_ll(const struct in6_addr *addr,
1506-
const struct net_linkaddr *lladdr)
1603+
/** @cond INTERNAL_HIDDEN */
1604+
static inline bool net_ipv6_addr_based_on_ll_raw(const uint8_t *addr,
1605+
const struct net_linkaddr *lladdr)
15071606
{
1508-
if (!addr || !lladdr) {
1607+
if (addr == NULL || lladdr == NULL) {
15091608
return false;
15101609
}
15111610

15121611
switch (lladdr->len) {
15131612
case 2:
1514-
if (!memcmp(&addr->s6_addr[14], lladdr->addr, lladdr->len) &&
1515-
addr->s6_addr[8] == 0U &&
1516-
addr->s6_addr[9] == 0U &&
1517-
addr->s6_addr[10] == 0U &&
1518-
addr->s6_addr[11] == 0xff &&
1519-
addr->s6_addr[12] == 0xfe) {
1613+
if (!memcmp(&addr[14], lladdr->addr, lladdr->len) &&
1614+
addr[8] == 0U &&
1615+
addr[9] == 0U &&
1616+
addr[10] == 0U &&
1617+
addr[11] == 0xff &&
1618+
addr[12] == 0xfe) {
15201619
return true;
15211620
}
15221621

15231622
break;
15241623
case 6:
15251624
if (lladdr->type == NET_LINK_ETHERNET) {
1526-
if (!memcmp(&addr->s6_addr[9], &lladdr->addr[1], 2) &&
1527-
!memcmp(&addr->s6_addr[13], &lladdr->addr[3], 3) &&
1528-
addr->s6_addr[11] == 0xff &&
1529-
addr->s6_addr[12] == 0xfe &&
1530-
(addr->s6_addr[8] ^ 0x02) == lladdr->addr[0]) {
1625+
if (!memcmp(&addr[9], &lladdr->addr[1], 2) &&
1626+
!memcmp(&addr[13], &lladdr->addr[3], 3) &&
1627+
addr[11] == 0xff &&
1628+
addr[12] == 0xfe &&
1629+
(addr[8] ^ 0x02) == lladdr->addr[0]) {
15311630
return true;
15321631
}
15331632
}
@@ -1538,9 +1637,9 @@ static inline bool net_ipv6_addr_based_on_ll(const struct in6_addr *addr,
15381637
return false;
15391638
}
15401639

1541-
if (!memcmp(&addr->s6_addr[9], &lladdr->addr[1],
1640+
if (!memcmp(&addr[9], &lladdr->addr[1],
15421641
lladdr->len - 1) &&
1543-
(addr->s6_addr[8] ^ 0x02) == lladdr->addr[0]) {
1642+
(addr[8] ^ 0x02) == lladdr->addr[0]) {
15441643
return true;
15451644
}
15461645

@@ -1551,6 +1650,22 @@ static inline bool net_ipv6_addr_based_on_ll(const struct in6_addr *addr,
15511650

15521651
return false;
15531652
}
1653+
/** @endcond */
1654+
1655+
/**
1656+
* @brief Check if given address is based on link layer address
1657+
*
1658+
* @return True if it is, False otherwise
1659+
*/
1660+
static inline bool net_ipv6_addr_based_on_ll(const struct in6_addr *addr,
1661+
const struct net_linkaddr *lladdr)
1662+
{
1663+
if (addr == NULL || lladdr == NULL) {
1664+
return false;
1665+
}
1666+
1667+
return net_ipv6_addr_based_on_ll_raw(addr->s6_addr, lladdr);
1668+
}
15541669

15551670
/**
15561671
* @brief Get sockaddr from sockaddr_storage. This is a helper so that

0 commit comments

Comments
 (0)