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