net: ipv6: routing: decide whether to set interface's LL address

While routing between interfaces source Link-Local L2 address is set
for a packet. However, it should not be done for some of the interfaces.

This commit adds helper function to check this condition in runtime.

Signed-off-by: Konrad Derda <konrad.derda@nordicsemi.no>
This commit is contained in:
Konrad Derda 2024-07-29 12:28:49 +02:00 committed by Carles Cufí
parent 0ac5ab4a4e
commit 4e7bf281a1

View file

@ -1008,6 +1008,27 @@ exit:
return ret;
}
static bool is_ll_addr_supported(struct net_if *iface)
{
#if defined(CONFIG_NET_L2_DUMMY)
if (net_if_l2(iface) == &NET_L2_GET_NAME(DUMMY)) {
return false;
}
#endif
#if defined(CONFIG_NET_L2_PPP)
if (net_if_l2(iface) == &NET_L2_GET_NAME(PPP)) {
return false;
}
#endif
#if defined(CONFIG_NET_L2_OPENTHREAD)
if (net_if_l2(iface) == &NET_L2_GET_NAME(OPENTHREAD)) {
return false;
}
#endif
return true;
}
int net_route_packet(struct net_pkt *pkt, struct in6_addr *nexthop)
{
struct net_linkaddr_storage *lladdr;
@ -1032,48 +1053,36 @@ int net_route_packet(struct net_pkt *pkt, struct in6_addr *nexthop)
goto error;
}
#if defined(CONFIG_NET_L2_DUMMY)
/* No need to do this check for dummy L2 as it does not have any
* link layer. This is done at runtime because we can have multiple
* network technologies enabled.
*/
if (net_if_l2(net_pkt_iface(pkt)) != &NET_L2_GET_NAME(DUMMY)) {
#endif
#if defined(CONFIG_NET_L2_PPP)
/* PPP does not populate the lladdr fields */
if (net_if_l2(net_pkt_iface(pkt)) != &NET_L2_GET_NAME(PPP)) {
#endif
if (!net_pkt_lladdr_src(pkt)->addr) {
NET_DBG("Link layer source address not set");
err = -EINVAL;
goto error;
}
/* Sanitycheck: If src and dst ll addresses are going
* to be same, then something went wrong in route
* lookup.
*/
if (!memcmp(net_pkt_lladdr_src(pkt)->addr, lladdr->addr,
lladdr->len)) {
NET_ERR("Src ll and Dst ll are same");
err = -EINVAL;
goto error;
}
#if defined(CONFIG_NET_L2_PPP)
if (is_ll_addr_supported(net_pkt_iface(pkt)) &&
is_ll_addr_supported(net_pkt_orig_iface(pkt))) {
if (!net_pkt_lladdr_src(pkt)->addr) {
NET_DBG("Link layer source address not set");
err = -EINVAL;
goto error;
}
/* Sanitycheck: If src and dst ll addresses are going
* to be same, then something went wrong in route
* lookup.
*/
if (!memcmp(net_pkt_lladdr_src(pkt)->addr, lladdr->addr,
lladdr->len)) {
NET_ERR("Src ll and Dst ll are same");
err = -EINVAL;
goto error;
}
#endif
#if defined(CONFIG_NET_L2_DUMMY)
}
#endif
net_pkt_set_forwarding(pkt, true);
/* Set the destination and source ll address in the packet.
* We set the destination address to be the nexthop recipient.
/* Set the source ll address of the iface (if relevant) and the
* destination address to be the nexthop recipient.
*/
net_pkt_lladdr_src(pkt)->addr = net_pkt_lladdr_if(pkt)->addr;
net_pkt_lladdr_src(pkt)->type = net_pkt_lladdr_if(pkt)->type;
net_pkt_lladdr_src(pkt)->len = net_pkt_lladdr_if(pkt)->len;
if (is_ll_addr_supported(net_pkt_iface(pkt))) {
net_pkt_lladdr_src(pkt)->addr = net_pkt_lladdr_if(pkt)->addr;
net_pkt_lladdr_src(pkt)->type = net_pkt_lladdr_if(pkt)->type;
net_pkt_lladdr_src(pkt)->len = net_pkt_lladdr_if(pkt)->len;
}
net_pkt_lladdr_dst(pkt)->addr = lladdr->addr;
net_pkt_lladdr_dst(pkt)->type = lladdr->type;
@ -1082,6 +1091,7 @@ int net_route_packet(struct net_pkt *pkt, struct in6_addr *nexthop)
net_pkt_set_iface(pkt, nbr->iface);
net_ipv6_nbr_unlock();
return net_send_data(pkt);
error:
@ -1094,15 +1104,17 @@ int net_route_packet_if(struct net_pkt *pkt, struct net_if *iface)
/* The destination is reachable via iface. But since no valid nexthop
* is known, net_pkt_lladdr_dst(pkt) cannot be set here.
*/
net_pkt_set_orig_iface(pkt, net_pkt_iface(pkt));
net_pkt_set_iface(pkt, iface);
net_pkt_set_forwarding(pkt, true);
net_pkt_lladdr_src(pkt)->addr = net_pkt_lladdr_if(pkt)->addr;
net_pkt_lladdr_src(pkt)->type = net_pkt_lladdr_if(pkt)->type;
net_pkt_lladdr_src(pkt)->len = net_pkt_lladdr_if(pkt)->len;
/* Set source LL address if only if relevant */
if (is_ll_addr_supported(iface)) {
net_pkt_lladdr_src(pkt)->addr = net_pkt_lladdr_if(pkt)->addr;
net_pkt_lladdr_src(pkt)->type = net_pkt_lladdr_if(pkt)->type;
net_pkt_lladdr_src(pkt)->len = net_pkt_lladdr_if(pkt)->len;
}
return net_send_data(pkt);
}