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 udphdr *uh; 33 int data_len; 34 int ret; 35 36 skb = alloc_skb(SKB_SIZE, GFP_KERNEL); 37 if (!skb) 38 return -ENOMEM; 39 40 /* Reserve head-room for the headers */ 41 skb_reserve(skb, HEAD_SIZE); 42 43 /* Add data to the skb */ 44 data_len = SKB_SIZE - (HEAD_SIZE + TAIL_SIZE); 45 memset(__skb_put(skb, data_len), 0xf, data_len); 46 47 /* Add protocol data */ 48 /* (Transport) UDP */ 49 uh = (struct udphdr *)skb_push(skb, sizeof(struct udphdr)); 50 skb_set_transport_header(skb, 0); 51 uh->source = uh->dest = htons(UDP_PORT); 52 uh->len = htons(data_len); 53 uh->check = 0; 54 /* (Network) IPv6 */ 55 ip6h = (struct ipv6hdr *)skb_push(skb, sizeof(struct ipv6hdr)); 56 skb_set_network_header(skb, 0); 57 ip6h->hop_limit = 32; 58 ip6h->payload_len = data_len + sizeof(struct udphdr); 59 ip6h->nexthdr = IPPROTO_UDP; 60 ip6h->saddr = in6addr_loopback; 61 ip6h->daddr = in6addr_loopback; 62 /* Ether */ 63 skb_push(skb, sizeof(struct ethhdr)); 64 skb_set_mac_header(skb, 0); 65 66 skb->protocol = htons(ETH_P_IPV6); 67 skb->pkt_type = PACKET_HOST; 68 skb->dev = blackhole_netdev; 69 70 /* Now attempt to send the packet */ 71 ret = dev_queue_xmit(skb); 72 73 switch (ret) { 74 case NET_XMIT_SUCCESS: 75 pr_warn("dev_queue_xmit() returned NET_XMIT_SUCCESS\n"); 76 break; 77 case NET_XMIT_DROP: 78 pr_warn("dev_queue_xmit() returned NET_XMIT_DROP\n"); 79 break; 80 case NET_XMIT_CN: 81 pr_warn("dev_queue_xmit() returned NET_XMIT_CN\n"); 82 break; 83 default: 84 pr_err("dev_queue_xmit() returned UNKNOWN(%d)\n", ret); 85 } 86 87 return 0; 88 } 89 90 static void __exit test_blackholedev_exit(void) 91 { 92 pr_warn("test_blackholedev module terminating.\n"); 93 } 94 95 module_init(test_blackholedev_init); 96 module_exit(test_blackholedev_exit); 97 98 MODULE_AUTHOR("Mahesh Bandewar <maheshb@google.com>"); 99 MODULE_LICENSE("GPL"); 100