11da177e4SLinus Torvalds /* 2cd1ae0e4SJeff Dike * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 31da177e4SLinus Torvalds * Licensed under the GPL. 41da177e4SLinus Torvalds */ 51da177e4SLinus Torvalds 61da177e4SLinus Torvalds #include "linux/init.h" 7cd1ae0e4SJeff Dike #include <linux/netdevice.h> 81da177e4SLinus Torvalds #include "net_kern.h" 91da177e4SLinus Torvalds #include "pcap_user.h" 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds struct pcap_init { 121da177e4SLinus Torvalds char *host_if; 131da177e4SLinus Torvalds int promisc; 141da177e4SLinus Torvalds int optimize; 151da177e4SLinus Torvalds char *filter; 161da177e4SLinus Torvalds }; 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds void pcap_init(struct net_device *dev, void *data) 191da177e4SLinus Torvalds { 201da177e4SLinus Torvalds struct uml_net_private *pri; 211da177e4SLinus Torvalds struct pcap_data *ppri; 221da177e4SLinus Torvalds struct pcap_init *init = data; 231da177e4SLinus Torvalds 24*17c324faSWang Chen pri = netdev_priv(dev); 251da177e4SLinus Torvalds ppri = (struct pcap_data *) pri->user; 261da177e4SLinus Torvalds ppri->host_if = init->host_if; 271da177e4SLinus Torvalds ppri->promisc = init->promisc; 281da177e4SLinus Torvalds ppri->optimize = init->optimize; 291da177e4SLinus Torvalds ppri->filter = init->filter; 307d98230aSJeff Dike 317d98230aSJeff Dike printk("pcap backend, host interface %s\n", ppri->host_if); 321da177e4SLinus Torvalds } 331da177e4SLinus Torvalds 34b53f35a8SJeff Dike static int pcap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) 351da177e4SLinus Torvalds { 36b53f35a8SJeff Dike return pcap_user_read(fd, skb_mac_header(skb), 37b53f35a8SJeff Dike skb->dev->mtu + ETH_HEADER_OTHER, 387d98230aSJeff Dike (struct pcap_data *) &lp->user); 391da177e4SLinus Torvalds } 401da177e4SLinus Torvalds 41b53f35a8SJeff Dike static int pcap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) 421da177e4SLinus Torvalds { 437d98230aSJeff Dike return -EPERM; 441da177e4SLinus Torvalds } 451da177e4SLinus Torvalds 465e7672ecSJeff Dike static const struct net_kern_info pcap_kern_info = { 471da177e4SLinus Torvalds .init = pcap_init, 481da177e4SLinus Torvalds .protocol = eth_protocol, 491da177e4SLinus Torvalds .read = pcap_read, 501da177e4SLinus Torvalds .write = pcap_write, 511da177e4SLinus Torvalds }; 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds int pcap_setup(char *str, char **mac_out, void *data) 541da177e4SLinus Torvalds { 551da177e4SLinus Torvalds struct pcap_init *init = data; 561da177e4SLinus Torvalds char *remain, *host_if = NULL, *options[2] = { NULL, NULL }; 571da177e4SLinus Torvalds int i; 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds *init = ((struct pcap_init) 601da177e4SLinus Torvalds { .host_if = "eth0", 611da177e4SLinus Torvalds .promisc = 1, 621da177e4SLinus Torvalds .optimize = 0, 631da177e4SLinus Torvalds .filter = NULL }); 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds remain = split_if_spec(str, &host_if, &init->filter, 660ba34e19SJeff Dike &options[0], &options[1], mac_out, NULL); 671da177e4SLinus Torvalds if (remain != NULL) { 681da177e4SLinus Torvalds printk(KERN_ERR "pcap_setup - Extra garbage on " 691da177e4SLinus Torvalds "specification : '%s'\n", remain); 707d98230aSJeff Dike return 0; 711da177e4SLinus Torvalds } 721da177e4SLinus Torvalds 731da177e4SLinus Torvalds if (host_if != NULL) 741da177e4SLinus Torvalds init->host_if = host_if; 751da177e4SLinus Torvalds 7691b165c0SJeff Dike for (i = 0; i < ARRAY_SIZE(options); i++) { 771da177e4SLinus Torvalds if (options[i] == NULL) 781da177e4SLinus Torvalds continue; 791da177e4SLinus Torvalds if (!strcmp(options[i], "promisc")) 801da177e4SLinus Torvalds init->promisc = 1; 811da177e4SLinus Torvalds else if (!strcmp(options[i], "nopromisc")) 821da177e4SLinus Torvalds init->promisc = 0; 831da177e4SLinus Torvalds else if (!strcmp(options[i], "optimize")) 841da177e4SLinus Torvalds init->optimize = 1; 851da177e4SLinus Torvalds else if (!strcmp(options[i], "nooptimize")) 861da177e4SLinus Torvalds init->optimize = 0; 877d98230aSJeff Dike else { 88cd1ae0e4SJeff Dike printk(KERN_ERR "pcap_setup : bad option - '%s'\n", 89cd1ae0e4SJeff Dike options[i]); 907d98230aSJeff Dike return 0; 917d98230aSJeff Dike } 921da177e4SLinus Torvalds } 931da177e4SLinus Torvalds 947d98230aSJeff Dike return 1; 951da177e4SLinus Torvalds } 961da177e4SLinus Torvalds 971da177e4SLinus Torvalds static struct transport pcap_transport = { 981da177e4SLinus Torvalds .list = LIST_HEAD_INIT(pcap_transport.list), 991da177e4SLinus Torvalds .name = "pcap", 1001da177e4SLinus Torvalds .setup = pcap_setup, 1011da177e4SLinus Torvalds .user = &pcap_user_info, 1021da177e4SLinus Torvalds .kern = &pcap_kern_info, 1031da177e4SLinus Torvalds .private_size = sizeof(struct pcap_data), 1041da177e4SLinus Torvalds .setup_size = sizeof(struct pcap_init), 1051da177e4SLinus Torvalds }; 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds static int register_pcap(void) 1081da177e4SLinus Torvalds { 1091da177e4SLinus Torvalds register_transport(&pcap_transport); 110f4c57a78SJeff Dike return 0; 1111da177e4SLinus Torvalds } 1121da177e4SLinus Torvalds 1138210fd2aSJeff Dike late_initcall(register_pcap); 114