1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
4 | */ |
5 | |
6 | #include <linux/init.h> |
7 | #include <linux/netdevice.h> |
8 | #include <net_kern.h> |
9 | #include "pcap_user.h" |
10 | |
11 | struct pcap_init { |
12 | char *host_if; |
13 | int promisc; |
14 | int optimize; |
15 | char *filter; |
16 | }; |
17 | |
18 | void pcap_init_kern(struct net_device *dev, void *data) |
19 | { |
20 | struct uml_net_private *pri; |
21 | struct pcap_data *ppri; |
22 | struct pcap_init *init = data; |
23 | |
24 | pri = netdev_priv(dev); |
25 | ppri = (struct pcap_data *) pri->user; |
26 | ppri->host_if = init->host_if; |
27 | ppri->promisc = init->promisc; |
28 | ppri->optimize = init->optimize; |
29 | ppri->filter = init->filter; |
30 | |
31 | printk("pcap backend, host interface %s\n" , ppri->host_if); |
32 | } |
33 | |
34 | static int pcap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) |
35 | { |
36 | return pcap_user_read(fd, buf: skb_mac_header(skb), |
37 | len: skb->dev->mtu + ETH_HEADER_OTHER, |
38 | pri: (struct pcap_data *) &lp->user); |
39 | } |
40 | |
41 | static int pcap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) |
42 | { |
43 | return -EPERM; |
44 | } |
45 | |
46 | static const struct net_kern_info pcap_kern_info = { |
47 | .init = pcap_init_kern, |
48 | .protocol = eth_protocol, |
49 | .read = pcap_read, |
50 | .write = pcap_write, |
51 | }; |
52 | |
53 | int pcap_setup(char *str, char **mac_out, void *data) |
54 | { |
55 | struct pcap_init *init = data; |
56 | char *remain, *host_if = NULL, *options[2] = { NULL, NULL }; |
57 | int i; |
58 | |
59 | *init = ((struct pcap_init) |
60 | { .host_if = "eth0" , |
61 | .promisc = 1, |
62 | .optimize = 0, |
63 | .filter = NULL }); |
64 | |
65 | remain = split_if_spec(str, &host_if, &init->filter, |
66 | &options[0], &options[1], mac_out, NULL); |
67 | if (remain != NULL) { |
68 | printk(KERN_ERR "pcap_setup - Extra garbage on " |
69 | "specification : '%s'\n" , remain); |
70 | return 0; |
71 | } |
72 | |
73 | if (host_if != NULL) |
74 | init->host_if = host_if; |
75 | |
76 | for (i = 0; i < ARRAY_SIZE(options); i++) { |
77 | if (options[i] == NULL) |
78 | continue; |
79 | if (!strcmp(options[i], "promisc" )) |
80 | init->promisc = 1; |
81 | else if (!strcmp(options[i], "nopromisc" )) |
82 | init->promisc = 0; |
83 | else if (!strcmp(options[i], "optimize" )) |
84 | init->optimize = 1; |
85 | else if (!strcmp(options[i], "nooptimize" )) |
86 | init->optimize = 0; |
87 | else { |
88 | printk(KERN_ERR "pcap_setup : bad option - '%s'\n" , |
89 | options[i]); |
90 | return 0; |
91 | } |
92 | } |
93 | |
94 | return 1; |
95 | } |
96 | |
97 | static struct transport pcap_transport = { |
98 | .list = LIST_HEAD_INIT(pcap_transport.list), |
99 | .name = "pcap" , |
100 | .setup = pcap_setup, |
101 | .user = &pcap_user_info, |
102 | .kern = &pcap_kern_info, |
103 | .private_size = sizeof(struct pcap_data), |
104 | .setup_size = sizeof(struct pcap_init), |
105 | }; |
106 | |
107 | static int register_pcap(void) |
108 | { |
109 | register_transport(&pcap_transport); |
110 | return 0; |
111 | } |
112 | |
113 | late_initcall(register_pcap); |
114 | |