99 lines
1.5 KiB
C
99 lines
1.5 KiB
C
/** @file
|
|
* @brief Promiscuous mode support
|
|
*
|
|
* Allow user to receive all network packets that are seen by a
|
|
* network interface. This requires that network device driver
|
|
* supports promiscuous mode.
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 2018 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <logging/log.h>
|
|
LOG_MODULE_REGISTER(net_promisc, CONFIG_NET_PROMISC_LOG_LEVEL);
|
|
|
|
#include <kernel.h>
|
|
#include <errno.h>
|
|
|
|
#include <net/net_if.h>
|
|
#include <net/net_core.h>
|
|
#include <net/net_pkt.h>
|
|
|
|
static K_FIFO_DEFINE(promiscuous_queue);
|
|
static atomic_t enabled = ATOMIC_INIT(0);
|
|
|
|
struct net_pkt *net_promisc_mode_wait_data(k_timeout_t timeout)
|
|
{
|
|
return k_fifo_get(&promiscuous_queue, timeout);
|
|
}
|
|
|
|
int net_promisc_mode_on(struct net_if *iface)
|
|
{
|
|
int ret;
|
|
|
|
if (!iface) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = net_if_set_promisc(iface);
|
|
if (!ret) {
|
|
atomic_inc(&enabled);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void flush_queue(void)
|
|
{
|
|
struct net_pkt *pkt;
|
|
|
|
while (1) {
|
|
pkt = k_fifo_get(&promiscuous_queue, K_NO_WAIT);
|
|
if (!pkt) {
|
|
return;
|
|
}
|
|
|
|
net_pkt_unref(pkt);
|
|
}
|
|
}
|
|
|
|
int net_promisc_mode_off(struct net_if *iface)
|
|
{
|
|
atomic_val_t prev;
|
|
bool ret;
|
|
|
|
ret = net_if_is_promisc(iface);
|
|
if (ret) {
|
|
net_if_unset_promisc(iface);
|
|
|
|
prev = atomic_dec(&enabled);
|
|
if (prev == 1) {
|
|
atomic_clear(&enabled);
|
|
|
|
flush_queue();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
return -EALREADY;
|
|
}
|
|
|
|
enum net_verdict net_promisc_mode_input(struct net_pkt *pkt)
|
|
{
|
|
if (!pkt) {
|
|
return NET_CONTINUE;
|
|
}
|
|
|
|
if (!atomic_get(&enabled)) {
|
|
return NET_DROP;
|
|
}
|
|
|
|
k_fifo_put(&promiscuous_queue, pkt);
|
|
|
|
return NET_OK;
|
|
}
|