^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/netlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <net/net_namespace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <net/rtnetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) static netdev_tx_t nlmon_xmit(struct sk_buff *skb, struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) dev_lstats_add(dev, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static int nlmon_dev_init(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) return dev->lstats == NULL ? -ENOMEM : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static void nlmon_dev_uninit(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) free_percpu(dev->lstats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct nlmon {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct netlink_tap nt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static int nlmon_open(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct nlmon *nlmon = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) nlmon->nt.dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) nlmon->nt.module = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return netlink_add_tap(&nlmon->nt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static int nlmon_close(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct nlmon *nlmon = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return netlink_remove_tap(&nlmon->nt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) nlmon_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) u64 packets, bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) dev_lstats_read(dev, &packets, &bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) stats->rx_packets = packets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) stats->tx_packets = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) stats->rx_bytes = bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) stats->tx_bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static u32 always_on(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static const struct ethtool_ops nlmon_ethtool_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) .get_link = always_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static const struct net_device_ops nlmon_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) .ndo_init = nlmon_dev_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .ndo_uninit = nlmon_dev_uninit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) .ndo_open = nlmon_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .ndo_stop = nlmon_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .ndo_start_xmit = nlmon_xmit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .ndo_get_stats64 = nlmon_get_stats64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static void nlmon_setup(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) dev->type = ARPHRD_NETLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) dev->priv_flags |= IFF_NO_QUEUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) dev->netdev_ops = &nlmon_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) dev->ethtool_ops = &nlmon_ethtool_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) dev->needs_free_netdev = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) dev->features = NETIF_F_SG | NETIF_F_FRAGLIST |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) NETIF_F_HIGHDMA | NETIF_F_LLTX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) dev->flags = IFF_NOARP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /* That's rather a softlimit here, which, of course,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * can be altered. Not a real MTU, but what is to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * expected in most cases.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) dev->mtu = NLMSG_GOODSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) dev->min_mtu = sizeof(struct nlmsghdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static int nlmon_validate(struct nlattr *tb[], struct nlattr *data[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (tb[IFLA_ADDRESS])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static struct rtnl_link_ops nlmon_link_ops __read_mostly = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .kind = "nlmon",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .priv_size = sizeof(struct nlmon),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .setup = nlmon_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .validate = nlmon_validate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static __init int nlmon_register(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return rtnl_link_register(&nlmon_link_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static __exit void nlmon_unregister(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) rtnl_link_unregister(&nlmon_link_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) module_init(nlmon_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) module_exit(nlmon_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) MODULE_AUTHOR("Daniel Borkmann <dborkman@redhat.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) MODULE_AUTHOR("Mathieu Geli <geli@enseirb.fr>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) MODULE_DESCRIPTION("Netlink monitoring device");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) MODULE_ALIAS_RTNL_LINK("nlmon");