xref: /openbmc/linux/arch/um/drivers/pcap_kern.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  * Copyright (C) 2002 Jeff Dike <jdike@karaya.com>
3*1da177e4SLinus Torvalds  * Licensed under the GPL.
4*1da177e4SLinus Torvalds  */
5*1da177e4SLinus Torvalds 
6*1da177e4SLinus Torvalds #include "linux/init.h"
7*1da177e4SLinus Torvalds #include "linux/netdevice.h"
8*1da177e4SLinus Torvalds #include "linux/etherdevice.h"
9*1da177e4SLinus Torvalds #include "net_kern.h"
10*1da177e4SLinus Torvalds #include "net_user.h"
11*1da177e4SLinus Torvalds #include "pcap_user.h"
12*1da177e4SLinus Torvalds 
13*1da177e4SLinus Torvalds struct pcap_init {
14*1da177e4SLinus Torvalds 	char *host_if;
15*1da177e4SLinus Torvalds 	int promisc;
16*1da177e4SLinus Torvalds 	int optimize;
17*1da177e4SLinus Torvalds 	char *filter;
18*1da177e4SLinus Torvalds };
19*1da177e4SLinus Torvalds 
20*1da177e4SLinus Torvalds void pcap_init(struct net_device *dev, void *data)
21*1da177e4SLinus Torvalds {
22*1da177e4SLinus Torvalds 	struct uml_net_private *pri;
23*1da177e4SLinus Torvalds 	struct pcap_data *ppri;
24*1da177e4SLinus Torvalds 	struct pcap_init *init = data;
25*1da177e4SLinus Torvalds 
26*1da177e4SLinus Torvalds 	pri = dev->priv;
27*1da177e4SLinus Torvalds 	ppri = (struct pcap_data *) pri->user;
28*1da177e4SLinus Torvalds 	ppri->host_if = init->host_if;
29*1da177e4SLinus Torvalds 	ppri->promisc = init->promisc;
30*1da177e4SLinus Torvalds 	ppri->optimize = init->optimize;
31*1da177e4SLinus Torvalds 	ppri->filter = init->filter;
32*1da177e4SLinus Torvalds }
33*1da177e4SLinus Torvalds 
34*1da177e4SLinus Torvalds static int pcap_read(int fd, struct sk_buff **skb,
35*1da177e4SLinus Torvalds 		       struct uml_net_private *lp)
36*1da177e4SLinus Torvalds {
37*1da177e4SLinus Torvalds 	*skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
38*1da177e4SLinus Torvalds 	if(*skb == NULL) return(-ENOMEM);
39*1da177e4SLinus Torvalds 	return(pcap_user_read(fd, (*skb)->mac.raw,
40*1da177e4SLinus Torvalds 			      (*skb)->dev->mtu + ETH_HEADER_OTHER,
41*1da177e4SLinus Torvalds 			      (struct pcap_data *) &lp->user));
42*1da177e4SLinus Torvalds }
43*1da177e4SLinus Torvalds 
44*1da177e4SLinus Torvalds static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
45*1da177e4SLinus Torvalds {
46*1da177e4SLinus Torvalds 	return(-EPERM);
47*1da177e4SLinus Torvalds }
48*1da177e4SLinus Torvalds 
49*1da177e4SLinus Torvalds static struct net_kern_info pcap_kern_info = {
50*1da177e4SLinus Torvalds 	.init			= pcap_init,
51*1da177e4SLinus Torvalds 	.protocol		= eth_protocol,
52*1da177e4SLinus Torvalds 	.read			= pcap_read,
53*1da177e4SLinus Torvalds 	.write			= pcap_write,
54*1da177e4SLinus Torvalds };
55*1da177e4SLinus Torvalds 
56*1da177e4SLinus Torvalds int pcap_setup(char *str, char **mac_out, void *data)
57*1da177e4SLinus Torvalds {
58*1da177e4SLinus Torvalds 	struct pcap_init *init = data;
59*1da177e4SLinus Torvalds 	char *remain, *host_if = NULL, *options[2] = { NULL, NULL };
60*1da177e4SLinus Torvalds 	int i;
61*1da177e4SLinus Torvalds 
62*1da177e4SLinus Torvalds 	*init = ((struct pcap_init)
63*1da177e4SLinus Torvalds 		{ .host_if 	= "eth0",
64*1da177e4SLinus Torvalds 		  .promisc 	= 1,
65*1da177e4SLinus Torvalds 		  .optimize 	= 0,
66*1da177e4SLinus Torvalds 		  .filter 	= NULL });
67*1da177e4SLinus Torvalds 
68*1da177e4SLinus Torvalds 	remain = split_if_spec(str, &host_if, &init->filter,
69*1da177e4SLinus Torvalds 			       &options[0], &options[1], NULL);
70*1da177e4SLinus Torvalds 	if(remain != NULL){
71*1da177e4SLinus Torvalds 		printk(KERN_ERR "pcap_setup - Extra garbage on "
72*1da177e4SLinus Torvalds 		       "specification : '%s'\n", remain);
73*1da177e4SLinus Torvalds 		return(0);
74*1da177e4SLinus Torvalds 	}
75*1da177e4SLinus Torvalds 
76*1da177e4SLinus Torvalds 	if(host_if != NULL)
77*1da177e4SLinus Torvalds 		init->host_if = host_if;
78*1da177e4SLinus Torvalds 
79*1da177e4SLinus Torvalds 	for(i = 0; i < sizeof(options)/sizeof(options[0]); i++){
80*1da177e4SLinus Torvalds 		if(options[i] == NULL)
81*1da177e4SLinus Torvalds 			continue;
82*1da177e4SLinus Torvalds 		if(!strcmp(options[i], "promisc"))
83*1da177e4SLinus Torvalds 			init->promisc = 1;
84*1da177e4SLinus Torvalds 		else if(!strcmp(options[i], "nopromisc"))
85*1da177e4SLinus Torvalds 			init->promisc = 0;
86*1da177e4SLinus Torvalds 		else if(!strcmp(options[i], "optimize"))
87*1da177e4SLinus Torvalds 			init->optimize = 1;
88*1da177e4SLinus Torvalds 		else if(!strcmp(options[i], "nooptimize"))
89*1da177e4SLinus Torvalds 			init->optimize = 0;
90*1da177e4SLinus Torvalds 		else printk("pcap_setup : bad option - '%s'\n", options[i]);
91*1da177e4SLinus Torvalds 	}
92*1da177e4SLinus Torvalds 
93*1da177e4SLinus Torvalds 	return(1);
94*1da177e4SLinus Torvalds }
95*1da177e4SLinus Torvalds 
96*1da177e4SLinus Torvalds static struct transport pcap_transport = {
97*1da177e4SLinus Torvalds 	.list 		= LIST_HEAD_INIT(pcap_transport.list),
98*1da177e4SLinus Torvalds 	.name 		= "pcap",
99*1da177e4SLinus Torvalds 	.setup  	= pcap_setup,
100*1da177e4SLinus Torvalds 	.user 		= &pcap_user_info,
101*1da177e4SLinus Torvalds 	.kern 		= &pcap_kern_info,
102*1da177e4SLinus Torvalds 	.private_size 	= sizeof(struct pcap_data),
103*1da177e4SLinus Torvalds 	.setup_size 	= sizeof(struct pcap_init),
104*1da177e4SLinus Torvalds };
105*1da177e4SLinus Torvalds 
106*1da177e4SLinus Torvalds static int register_pcap(void)
107*1da177e4SLinus Torvalds {
108*1da177e4SLinus Torvalds 	register_transport(&pcap_transport);
109*1da177e4SLinus Torvalds 	return(1);
110*1da177e4SLinus Torvalds }
111*1da177e4SLinus Torvalds 
112*1da177e4SLinus Torvalds __initcall(register_pcap);
113*1da177e4SLinus Torvalds 
114*1da177e4SLinus Torvalds /*
115*1da177e4SLinus Torvalds  * Overrides for Emacs so that we follow Linus's tabbing style.
116*1da177e4SLinus Torvalds  * Emacs will notice this stuff at the end of the file and automatically
117*1da177e4SLinus Torvalds  * adjust the settings for this buffer only.  This must remain at the end
118*1da177e4SLinus Torvalds  * of the file.
119*1da177e4SLinus Torvalds  * ---------------------------------------------------------------------------
120*1da177e4SLinus Torvalds  * Local variables:
121*1da177e4SLinus Torvalds  * c-file-style: "linux"
122*1da177e4SLinus Torvalds  * End:
123*1da177e4SLinus Torvalds  */
124