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 <maheshb@google.com> 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 <maheshb@google.com>"); 100 MODULE_LICENSE("GPL"); 101