Добрый день, прошу помощи.
Написал простейший драйвер с функцией перехвата пакетов на интерфейсе(drop_packet
). Зарегистрировал ее с помощью netdev_rx_handler_register
. И для пакетов, пришедших извне(при посылке с ноутбука на интерфейс) drop_packet
дергается исправно, но при посылке пакета, сформированного локально(пробовал scapy и ping) drop_packet
не вызывается.
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/ctype.h>
#include <linux/uaccess.h>
#include <linux/string.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ip.h>
#include <linux/if_ether.h>
#include <net/arp.h>
#define MODULE_NAME "drop_packets"
#define VERSION "1.0.0"
#define PFX MODULE_NAME": "
#define TARGET_DEV "enp0s8"
#define DBG_PRINT(fmt, args...) \
do \
{ \
printk(KERN_ERR PFX "%s(%d)-%s:\n"fmt"\n", __FILE__,__LINE__,__FUNCTION__,##args); \
} while (0)
typedef struct {
struct net_device *ndev;
int promisc_old, promisc_count;
int old_netpoll;
} netif_info;
static netif_info pt_netif;
#define netif_info_get_rcu(dev) \
(rcu_dereference(dev->rx_handler_data))
static rx_handler_result_t drop_packet(struct sk_buff **pskb)
{
struct sk_buff *const skb = *pskb;
DBG_PRINT("LALALA %u", skb->len);
kfree_skb(*pskb);
*pskb = NULL;
return RX_HANDLER_CONSUMED;
}
static int __init the_init(void)
{
int err = 0;
struct net *const net = current->nsproxy->net_ns;
struct net_device *const ndev = dev_get_by_name(net, TARGET_DEV);
DBG_PRINT("dev_name=%s %s %i", TARGET_DEV, NULL != ndev ? "OK" : "FAIL", ndev->addr_len);
pt_netif.ndev = ndev;
pt_netif.promisc_old = ndev->flags & IFF_PROMISC;
pt_netif.promisc_count = 0;
pt_netif.old_netpoll = ndev->priv_flags & IFF_DISABLE_NETPOLL;
DBG_PRINT("priv_flags is %hx %hx", ndev->priv_flags, ndev->flags);
rtnl_lock();
if(!pt_netif.promisc_old) {
err = dev_set_promiscuity(ndev, 1);
DBG_PRINT("dev_set_promiscuity(1) %i", err);
DBG_PRINT("priv_flags is %x %x", ndev->priv_flags, ndev->flags);
}
if(!pt_netif.old_netpoll) {
ndev->priv_flags |= IFF_DISABLE_NETPOLL;
}
//ndev->priv_flags |= IFF_DISABLE_NETPOLL;
//ndev->flags |= IFF_PROMISC;
err = netdev_rx_handler_register(ndev, drop_packet, &pt_netif);
rtnl_unlock();
return err;
}
static void __exit the_exit(void)
{
int err;
struct net_device *const ndev = pt_netif.ndev;
rtnl_lock();
if(!pt_netif.promisc_old) {
err = dev_set_promiscuity(ndev, -1);
DBG_PRINT("dev_set_promiscuity(-1) %i", err);
DBG_PRINT("priv_flags is %x %x", ndev->priv_flags, ndev->flags);
}
if(!pt_netif.old_netpoll) {
ndev->priv_flags &= ~(IFF_DISABLE_NETPOLL);
}
netdev_rx_handler_unregister(ndev);
rtnl_unlock();
dev_put(ndev);
}
module_init(the_init);
module_exit(the_exit);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Serg");
MODULE_DESCRIPTION("drop all packets received from specified net device");