linux/lib/test_blackhole_dev.c
<<
>>
Prefs
   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
  28static 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
  91static void __exit test_blackholedev_exit(void)
  92{
  93        pr_warn("test_blackholedev module terminating.\n");
  94}
  95
  96module_init(test_blackholedev_init);
  97module_exit(test_blackholedev_exit);
  98
  99MODULE_AUTHOR("Mahesh Bandewar <maheshb@google.com>");
 100MODULE_LICENSE("GPL");
 101