|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
| 2 | +/* |
| 3 | + * This module tests the blackhole_dev that is created during the |
| 4 | + * net subsystem initialization. The test this module performs is |
| 5 | + * by injecting an skb into the stack with skb->dev as the |
| 6 | + * blackhole_dev and expects kernel to behave in a sane manner |
| 7 | + * (in other words, *not crash*)! |
| 8 | + * |
| 9 | + * Copyright (c) 2018, Mahesh Bandewar <[email protected]> |
| 10 | + */ |
| 11 | + |
| 12 | +#include <linux/init.h> |
| 13 | +#include <linux/module.h> |
| 14 | +#include <linux/printk.h> |
| 15 | +#include <linux/skbuff.h> |
| 16 | +#include <linux/netdevice.h> |
| 17 | +#include <linux/udp.h> |
| 18 | +#include <linux/ipv6.h> |
| 19 | + |
| 20 | +#include <net/dst.h> |
| 21 | + |
| 22 | +#define SKB_SIZE 256 |
| 23 | +#define HEAD_SIZE (14+40+8) /* Ether + IPv6 + UDP */ |
| 24 | +#define TAIL_SIZE 32 /* random tail-room */ |
| 25 | + |
| 26 | +#define UDP_PORT 1234 |
| 27 | + |
| 28 | +static int __init test_blackholedev_init(void) |
| 29 | +{ |
| 30 | + struct ipv6hdr *ip6h; |
| 31 | + struct sk_buff *skb; |
| 32 | + struct ethhdr *ethh; |
| 33 | + struct udphdr *uh; |
| 34 | + int data_len; |
| 35 | + int ret; |
| 36 | + |
| 37 | + skb = alloc_skb(SKB_SIZE, GFP_KERNEL); |
| 38 | + if (!skb) |
| 39 | + return -ENOMEM; |
| 40 | + |
| 41 | + /* Reserve head-room for the headers */ |
| 42 | + skb_reserve(skb, HEAD_SIZE); |
| 43 | + |
| 44 | + /* Add data to the skb */ |
| 45 | + data_len = SKB_SIZE - (HEAD_SIZE + TAIL_SIZE); |
| 46 | + memset(__skb_put(skb, data_len), 0xf, data_len); |
| 47 | + |
| 48 | + /* Add protocol data */ |
| 49 | + /* (Transport) UDP */ |
| 50 | + uh = (struct udphdr *)skb_push(skb, sizeof(struct udphdr)); |
| 51 | + skb_set_transport_header(skb, 0); |
| 52 | + uh->source = uh->dest = htons(UDP_PORT); |
| 53 | + uh->len = htons(data_len); |
| 54 | + uh->check = 0; |
| 55 | + /* (Network) IPv6 */ |
| 56 | + ip6h = (struct ipv6hdr *)skb_push(skb, sizeof(struct ipv6hdr)); |
| 57 | + skb_set_network_header(skb, 0); |
| 58 | + ip6h->hop_limit = 32; |
| 59 | + ip6h->payload_len = data_len + sizeof(struct udphdr); |
| 60 | + ip6h->nexthdr = IPPROTO_UDP; |
| 61 | + ip6h->saddr = in6addr_loopback; |
| 62 | + ip6h->daddr = in6addr_loopback; |
| 63 | + /* Ether */ |
| 64 | + ethh = (struct ethhdr *)skb_push(skb, sizeof(struct ethhdr)); |
| 65 | + skb_set_mac_header(skb, 0); |
| 66 | + |
| 67 | + skb->protocol = htons(ETH_P_IPV6); |
| 68 | + skb->pkt_type = PACKET_HOST; |
| 69 | + skb->dev = blackhole_netdev; |
| 70 | + |
| 71 | + /* Now attempt to send the packet */ |
| 72 | + ret = dev_queue_xmit(skb); |
| 73 | + |
| 74 | + switch (ret) { |
| 75 | + case NET_XMIT_SUCCESS: |
| 76 | + pr_warn("dev_queue_xmit() returned NET_XMIT_SUCCESS\n"); |
| 77 | + break; |
| 78 | + case NET_XMIT_DROP: |
| 79 | + pr_warn("dev_queue_xmit() returned NET_XMIT_DROP\n"); |
| 80 | + break; |
| 81 | + case NET_XMIT_CN: |
| 82 | + pr_warn("dev_queue_xmit() returned NET_XMIT_CN\n"); |
| 83 | + break; |
| 84 | + default: |
| 85 | + pr_err("dev_queue_xmit() returned UNKNOWN(%d)\n", ret); |
| 86 | + } |
| 87 | + |
| 88 | + return 0; |
| 89 | +} |
| 90 | + |
| 91 | +static void __exit test_blackholedev_exit(void) |
| 92 | +{ |
| 93 | + pr_warn("test_blackholedev module terminating.\n"); |
| 94 | +} |
| 95 | + |
| 96 | +module_init(test_blackholedev_init); |
| 97 | +module_exit(test_blackholedev_exit); |
| 98 | + |
| 99 | +MODULE_AUTHOR( "Mahesh Bandewar <[email protected]>"); |
| 100 | +MODULE_LICENSE("GPL"); |
0 commit comments