1 #include <linux/module.h> 2 #include <linux/kernel.h> 3 #include <linux/netdevice.h> 4 #include <linux/netlink.h> 5 #include <net/net_namespace.h> 6 #include <linux/if_arp.h> 7 8 struct pcpu_lstats { 9 u64 packets; 10 u64 bytes; 11 struct u64_stats_sync syncp; 12 }; 13 14 static netdev_tx_t nlmon_xmit(struct sk_buff *skb, struct net_device *dev) 15 { 16 int len = skb->len; 17 struct pcpu_lstats *stats = this_cpu_ptr(dev->lstats); 18 19 u64_stats_update_begin(&stats->syncp); 20 stats->bytes += len; 21 stats->packets++; 22 u64_stats_update_end(&stats->syncp); 23 24 dev_kfree_skb(skb); 25 26 return NETDEV_TX_OK; 27 } 28 29 static int nlmon_is_valid_mtu(int new_mtu) 30 { 31 /* Note that in netlink we do not really have an upper limit. On 32 * default, we use NLMSG_GOODSIZE. Here at least we should make 33 * sure that it's at least the header size. 34 */ 35 return new_mtu >= (int) sizeof(struct nlmsghdr); 36 } 37 38 static int nlmon_change_mtu(struct net_device *dev, int new_mtu) 39 { 40 if (!nlmon_is_valid_mtu(new_mtu)) 41 return -EINVAL; 42 43 dev->mtu = new_mtu; 44 return 0; 45 } 46 47 static int nlmon_dev_init(struct net_device *dev) 48 { 49 dev->lstats = alloc_percpu(struct pcpu_lstats); 50 51 return dev->lstats == NULL ? -ENOMEM : 0; 52 } 53 54 static void nlmon_dev_uninit(struct net_device *dev) 55 { 56 free_percpu(dev->lstats); 57 } 58 59 static struct netlink_tap nlmon_tap; 60 61 static int nlmon_open(struct net_device *dev) 62 { 63 return netlink_add_tap(&nlmon_tap); 64 } 65 66 static int nlmon_close(struct net_device *dev) 67 { 68 return netlink_remove_tap(&nlmon_tap); 69 } 70 71 static struct rtnl_link_stats64 * 72 nlmon_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) 73 { 74 int i; 75 u64 bytes = 0, packets = 0; 76 77 for_each_possible_cpu(i) { 78 const struct pcpu_lstats *nl_stats; 79 u64 tbytes, tpackets; 80 unsigned int start; 81 82 nl_stats = per_cpu_ptr(dev->lstats, i); 83 84 do { 85 start = u64_stats_fetch_begin_bh(&nl_stats->syncp); 86 tbytes = nl_stats->bytes; 87 tpackets = nl_stats->packets; 88 } while (u64_stats_fetch_retry_bh(&nl_stats->syncp, start)); 89 90 packets += tpackets; 91 bytes += tbytes; 92 } 93 94 stats->rx_packets = packets; 95 stats->tx_packets = 0; 96 97 stats->rx_bytes = bytes; 98 stats->tx_bytes = 0; 99 100 return stats; 101 } 102 103 static u32 always_on(struct net_device *dev) 104 { 105 return 1; 106 } 107 108 static const struct ethtool_ops nlmon_ethtool_ops = { 109 .get_link = always_on, 110 }; 111 112 static const struct net_device_ops nlmon_ops = { 113 .ndo_init = nlmon_dev_init, 114 .ndo_uninit = nlmon_dev_uninit, 115 .ndo_open = nlmon_open, 116 .ndo_stop = nlmon_close, 117 .ndo_start_xmit = nlmon_xmit, 118 .ndo_get_stats64 = nlmon_get_stats64, 119 .ndo_change_mtu = nlmon_change_mtu, 120 }; 121 122 static struct netlink_tap nlmon_tap __read_mostly = { 123 .module = THIS_MODULE, 124 }; 125 126 static void nlmon_setup(struct net_device *dev) 127 { 128 dev->type = ARPHRD_NETLINK; 129 dev->tx_queue_len = 0; 130 131 dev->netdev_ops = &nlmon_ops; 132 dev->ethtool_ops = &nlmon_ethtool_ops; 133 dev->destructor = free_netdev; 134 135 dev->features = NETIF_F_FRAGLIST | NETIF_F_HIGHDMA; 136 dev->flags = IFF_NOARP; 137 138 /* That's rather a softlimit here, which, of course, 139 * can be altered. Not a real MTU, but what is to be 140 * expected in most cases. 141 */ 142 dev->mtu = NLMSG_GOODSIZE; 143 } 144 145 static __init int nlmon_register(void) 146 { 147 int err; 148 struct net_device *nldev; 149 150 nldev = nlmon_tap.dev = alloc_netdev(0, "netlink", nlmon_setup); 151 if (unlikely(nldev == NULL)) 152 return -ENOMEM; 153 154 err = register_netdev(nldev); 155 if (unlikely(err)) 156 free_netdev(nldev); 157 158 return err; 159 } 160 161 static __exit void nlmon_unregister(void) 162 { 163 struct net_device *nldev = nlmon_tap.dev; 164 165 unregister_netdev(nldev); 166 } 167 168 module_init(nlmon_register); 169 module_exit(nlmon_unregister); 170 171 MODULE_LICENSE("GPL v2"); 172 MODULE_AUTHOR("Daniel Borkmann <dborkman@redhat.com>"); 173 MODULE_AUTHOR("Mathieu Geli <geli@enseirb.fr>"); 174 MODULE_DESCRIPTION("Netlink monitoring device"); 175