Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions include/net/net_if.h
Original file line number Diff line number Diff line change
Expand Up @@ -1428,7 +1428,18 @@ struct net_if_router *net_if_ipv4_router_add(struct net_if *iface,
* @return True if address is part of local subnet, false otherwise.
*/
bool net_if_ipv4_addr_mask_cmp(struct net_if *iface,
struct in_addr *addr);
const struct in_addr *addr);

/**
* @brief Check if the given IPv4 address is a broadcast address.
*
* @param iface Interface to use. Must be a valid pointer to an interface.
* @param addr IPv4 address, this should be in network byte order
*
* @return True if address is a broadcast address, false otherwise.
*/
bool net_if_ipv4_is_addr_bcast(struct net_if *iface,
const struct in_addr *addr);

/**
* @brief Get a network interface that should be used when sending
Expand Down Expand Up @@ -1474,7 +1485,7 @@ struct in_addr *net_if_ipv4_get_ll(struct net_if *iface,
* @param netmask IPv4 netmask
*/
static inline void net_if_ipv4_set_netmask(struct net_if *iface,
struct in_addr *netmask)
const struct in_addr *netmask)
{
if (net_if_config_ipv4_get(iface, NULL) < 0) {
return;
Expand Down
68 changes: 48 additions & 20 deletions include/net/net_ip.h
Original file line number Diff line number Diff line change
Expand Up @@ -477,23 +477,6 @@ static inline bool net_is_ipv4_ll_addr(const struct in_addr *addr)
return (ntohl(UNALIGNED_GET(&addr->s_addr)) & 0xA9FE0000) == 0xA9FE0000;
}

extern struct net_if_addr *net_if_ipv4_addr_lookup(const struct in_addr *addr,
struct net_if **iface);

/**
* @brief Check if the IPv4 address is assigned to any network interface
* in the system.
*
* @param addr A valid pointer on an IPv4 address
*
* @return True if IPv4 address is found in one of the network interfaces,
* False otherwise.
*/
static inline bool net_is_my_ipv4_addr(const struct in_addr *addr)
{
return net_if_ipv4_addr_lookup(addr, NULL) != NULL;
}

/**
* @def net_ipaddr_copy
* @brief Copy an IPv4 or IPv6 address
Expand Down Expand Up @@ -569,23 +552,68 @@ const struct in_addr *net_ipv4_broadcast_address(void);

struct net_if;
extern bool net_if_ipv4_addr_mask_cmp(struct net_if *iface,
struct in_addr *addr);
const struct in_addr *addr);

/**
* @brief Check if the given address belongs to same subnet that
* has been configured for the interface.
*
* @param iface A valid pointer on an interface
* @param addr pointer on an address
* @param addr IPv4 address
*
* @return True if address is in same subnet, false otherwise.
*/
static inline bool net_ipv4_addr_mask_cmp(struct net_if *iface,
struct in_addr *addr)
const struct in_addr *addr)
{
return net_if_ipv4_addr_mask_cmp(iface, addr);
}

extern bool net_if_ipv4_is_addr_bcast(struct net_if *iface,
const struct in_addr *addr);

/**
* @brief Check if the given IPv4 address is a broadcast address.
*
* @param iface Interface to use. Must be a valid pointer to an interface.
* @param addr IPv4 address
*
* @return True if address is a broadcast address, false otherwise.
*/
static inline bool net_is_ipv4_addr_bcast(struct net_if *iface,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/net_is_ipv4_addr_bcast/net_ipv4_is_addr_bcast

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets not change this in this case, this function name is following the same format as the other net_is_ipv4_*() functions in that file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

his function name is following the same format as the other net_is_ipv4_*() functions in that file.

Would be good to rename them all then (in another PR).

const struct in_addr *addr)
{
if (net_ipv4_addr_cmp(addr, net_ipv4_broadcast_address())) {
return true;
}

return net_if_ipv4_is_addr_bcast(iface, addr);
}

extern struct net_if_addr *net_if_ipv4_addr_lookup(const struct in_addr *addr,
struct net_if **iface);

/**
* @brief Check if the IPv4 address is assigned to any network interface
* in the system.
*
* @param addr A valid pointer on an IPv4 address
*
* @return True if IPv4 address is found in one of the network interfaces,
* False otherwise.
*/
static inline bool net_is_my_ipv4_addr(const struct in_addr *addr)
{
bool ret;

ret = net_if_ipv4_addr_lookup(addr, NULL) != NULL;
if (!ret) {
ret = net_is_ipv4_addr_bcast(NULL, addr);
}

return ret;
}

/**
* @brief Check if the IPv6 address is unspecified (all bits zero)
*
Expand Down
7 changes: 7 additions & 0 deletions subsys/net/ip/Kconfig.ipv4
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ config NET_IF_MCAST_IPV4_ADDR_COUNT
int "Max number of multicast IPv4 addresses per network interface"
default 1

config NET_ICMPV4_ACCEPT_BROADCAST
bool "Accept broadcast ICMPv4 echo-request"
default y
help
If set, then respond to ICMPv4 echo-request that is sent to
broadcast address.

config NET_DHCPV4
bool "Enable DHCPv4 client"
depends on NET_IPV4
Expand Down
18 changes: 13 additions & 5 deletions subsys/net/ip/icmpv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ static inline enum net_verdict icmpv4_handle_echo_request(struct net_pkt *pkt)

net_ipaddr_copy(&addr, &NET_IPV4_HDR(pkt)->src);
net_ipaddr_copy(&NET_IPV4_HDR(pkt)->src,
&NET_IPV4_HDR(pkt)->dst);
net_if_ipv4_select_src_addr(net_pkt_iface(pkt),
&addr));
net_ipaddr_copy(&NET_IPV4_HDR(pkt)->dst, &addr);

icmp_hdr.type = NET_ICMPV4_ECHO_REPLY;
Expand All @@ -121,10 +122,7 @@ static inline enum net_verdict icmpv4_handle_echo_request(struct net_pkt *pkt)
return NET_DROP;
}

ret = net_icmpv4_set_chksum(pkt);
if (ret < 0) {
return NET_DROP;
}
net_ipv4_finalize(pkt, IPPROTO_ICMP);

NET_DBG("Sending Echo Reply from %s to %s",
log_strdup(net_sprint_ipv4_addr(&NET_IPV4_HDR(pkt)->src)),
Expand Down Expand Up @@ -342,6 +340,15 @@ enum net_verdict net_icmpv4_input(struct net_pkt *pkt)
return NET_DROP;
}

if (net_is_ipv4_addr_bcast(net_pkt_iface(pkt),
&NET_IPV4_HDR(pkt)->dst)) {
if (!IS_ENABLED(CONFIG_NET_ICMPV4_ACCEPT_BROADCAST) ||
icmp_hdr.type != NET_ICMPV4_ECHO_REQUEST) {
NET_DBG("Dropping broadcast pkt");
goto drop;
}
}

NET_DBG("ICMPv4 packet received type %d code %d",
icmp_hdr.type, icmp_hdr.code);

Expand All @@ -354,6 +361,7 @@ enum net_verdict net_icmpv4_input(struct net_pkt *pkt)
}
}

drop:
net_stats_update_icmp_drop(net_pkt_iface(pkt));

return NET_DROP;
Expand Down
9 changes: 9 additions & 0 deletions subsys/net/ip/ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ enum net_verdict net_ipv4_process_pkt(struct net_pkt *pkt)
goto drop;
}

if (net_is_ipv4_addr_bcast(net_pkt_iface(pkt), &hdr->src)) {
goto drop;
}

NET_DBG("IPv4 packet received from %s to %s",
log_strdup(net_sprint_ipv4_addr(&hdr->src)),
log_strdup(net_sprint_ipv4_addr(&hdr->dst)));
Expand Down Expand Up @@ -151,6 +155,11 @@ enum net_verdict net_ipv4_process_pkt(struct net_pkt *pkt)
verdict = net_icmpv4_input(pkt);
break;
case IPPROTO_TCP:
if (net_is_ipv4_addr_bcast(net_pkt_iface(pkt), &hdr->dst)) {
goto drop;
}

/* Fall through */
case IPPROTO_UDP:
verdict = net_conn_input(hdr->proto, pkt);
break;
Expand Down
4 changes: 3 additions & 1 deletion subsys/net/ip/net_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,9 @@ static inline int check_ip_addr(struct net_pkt *pkt)
* back to us.
*/
if (net_is_ipv4_addr_loopback(&NET_IPV4_HDR(pkt)->dst) ||
net_is_my_ipv4_addr(&NET_IPV4_HDR(pkt)->dst)) {
(net_is_ipv4_addr_bcast(net_pkt_iface(pkt),
&NET_IPV4_HDR(pkt)->dst) == false &&
net_is_my_ipv4_addr(&NET_IPV4_HDR(pkt)->dst))) {
struct in_addr addr;

/* Swap the addresses so that in receiving side
Expand Down
49 changes: 44 additions & 5 deletions subsys/net/ip/net_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -2128,7 +2128,7 @@ struct net_if_router *net_if_ipv4_router_add(struct net_if *iface,
}

bool net_if_ipv4_addr_mask_cmp(struct net_if *iface,
struct in_addr *addr)
const struct in_addr *addr)
{
struct net_if_ipv4 *ipv4 = iface->config.ip.ipv4;
u32_t subnet;
Expand All @@ -2138,24 +2138,63 @@ bool net_if_ipv4_addr_mask_cmp(struct net_if *iface,
return false;
}

subnet = ntohl(UNALIGNED_GET(&addr->s_addr)) &
ntohl(ipv4->netmask.s_addr);
subnet = UNALIGNED_GET(&addr->s_addr) & ipv4->netmask.s_addr;

for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
if (!ipv4->unicast[i].is_used ||
ipv4->unicast[i].address.family != AF_INET) {
continue;
}

if ((ntohl(ipv4->unicast[i].address.in_addr.s_addr) &
ntohl(ipv4->netmask.s_addr)) == subnet) {
if ((ipv4->unicast[i].address.in_addr.s_addr &
ipv4->netmask.s_addr) == subnet) {
return true;
}
}

return false;
}

static bool ipv4_is_broadcast_address(struct net_if *iface,
const struct in_addr *addr)
{
struct net_if_ipv4 *ipv4 = iface->config.ip.ipv4;

if (!ipv4) {
return false;
}

if (!net_if_ipv4_addr_mask_cmp(iface, addr)) {
return false;
}

if ((UNALIGNED_GET(&addr->s_addr) & ~ipv4->netmask.s_addr) ==
~ipv4->netmask.s_addr) {
return true;
}

return false;
}

bool net_if_ipv4_is_addr_bcast(struct net_if *iface,
const struct in_addr *addr)
{
if (iface) {
return ipv4_is_broadcast_address(iface, addr);
}

for (iface = __net_if_start; iface != __net_if_end; iface++) {
bool ret;

ret = ipv4_is_broadcast_address(iface, addr);
if (ret) {
return ret;
}
}

return false;
}

struct net_if *net_if_ipv4_select_src_iface(struct in_addr *dst)
{
struct net_if *iface;
Expand Down
3 changes: 1 addition & 2 deletions subsys/net/l2/ethernet/ethernet.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,7 @@ static inline bool check_if_dst_is_broadcast_or_mcast(struct net_if *iface,
{
struct net_eth_hdr *hdr = NET_ETH_HDR(pkt);

if (net_ipv4_addr_cmp(&NET_IPV4_HDR(pkt)->dst,
net_ipv4_broadcast_address())) {
if (net_is_ipv4_addr_bcast(iface, &NET_IPV4_HDR(pkt)->dst)) {
/* Broadcast address */
net_pkt_lladdr_dst(pkt)->addr = (u8_t *)broadcast_eth_addr.addr;
net_pkt_lladdr_dst(pkt)->len = sizeof(struct net_eth_addr);
Expand Down
31 changes: 30 additions & 1 deletion tests/net/ip-addr/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,8 +371,14 @@ static void test_ipv4_addresses(void)
struct in_addr match_addr = { { { 192, 168, 0, 2 } } };
struct in_addr fail_addr = { { { 10, 1, 0, 2 } } };
struct in_addr netmask = { { { 255, 255, 255, 0 } } };
struct in_addr netmask2 = { { { 255, 255, 0, 0 } } };
struct in_addr gw = { { { 192, 168, 0, 42 } } };
struct in_addr loopback4 = { { { 127, 0, 0, 1 } } };
struct in_addr bcast_addr1 = { { { 255, 255, 255, 255 } } };
struct in_addr bcast_addr2 = { { { 192, 168, 1, 255 } } };
struct in_addr bcast_addr3 = { { { 192, 168, 255, 255 } } };
struct in_addr bcast_addr4 = { { { 192, 0, 2, 255 } } };
struct in_addr bcast_addr5 = { { { 192, 168, 0, 255 } } };
struct net_if *iface, *iface1, *iface2;
int i, ret;

Expand Down Expand Up @@ -458,7 +464,7 @@ static void test_ipv4_addresses(void)
"IPv4 wrong match failed");

zassert_true(net_ipv4_addr_mask_cmp(iface, &match_addr),
"IPv4 match failed");
"IPv4 match failed");

zassert_true(net_is_ipv4_addr_mcast(&maddr4a),
"IPv4 multicast address");
Expand Down Expand Up @@ -504,6 +510,29 @@ static void test_ipv4_addresses(void)

ifmaddr1 = net_if_ipv4_maddr_lookup(&maddr4b, &iface1);
zassert_is_null(ifmaddr1, "IPv4 multicast address lookup succeed");

ret = net_is_ipv4_addr_bcast(iface, &bcast_addr1);
zassert_true(ret, "IPv4 address 1 is not broadcast address");

ret = net_is_ipv4_addr_bcast(iface, &bcast_addr2);
zassert_false(ret, "IPv4 address 2 is broadcast address");

ret = net_is_ipv4_addr_bcast(iface, &bcast_addr4);
zassert_false(ret, "IPv4 address 4 is broadcast address");

ret = net_is_ipv4_addr_bcast(iface, &maddr4b);
zassert_false(ret, "IPv4 address is broadcast address");

ret = net_is_ipv4_addr_bcast(iface, &bcast_addr5);
zassert_true(ret, "IPv4 address 5 is not broadcast address");

net_if_ipv4_set_netmask(iface, &netmask2);

ret = net_is_ipv4_addr_bcast(iface, &bcast_addr2);
zassert_false(ret, "IPv4 address 2 is broadcast address");

ret = net_is_ipv4_addr_bcast(iface, &bcast_addr3);
zassert_true(ret, "IPv4 address 3 is not broadcast address");
}

void test_main(void)
Expand Down