11da177e4SLinus Torvalds /* 2*cd1ae0e4SJeff 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" 7*cd1ae0e4SJeff 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 241da177e4SLinus Torvalds pri = dev->priv; 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 341da177e4SLinus Torvalds static int pcap_read(int fd, struct sk_buff **skb, 351da177e4SLinus Torvalds struct uml_net_private *lp) 361da177e4SLinus Torvalds { 371da177e4SLinus Torvalds *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); 387d98230aSJeff Dike if (*skb == NULL) 397d98230aSJeff Dike return -ENOMEM; 407d98230aSJeff Dike 417d98230aSJeff Dike return pcap_user_read(fd, skb_mac_header(*skb), 421da177e4SLinus Torvalds (*skb)->dev->mtu + ETH_HEADER_OTHER, 437d98230aSJeff Dike (struct pcap_data *) &lp->user); 441da177e4SLinus Torvalds } 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) 471da177e4SLinus Torvalds { 487d98230aSJeff Dike return -EPERM; 491da177e4SLinus Torvalds } 501da177e4SLinus Torvalds 515e7672ecSJeff Dike static const struct net_kern_info pcap_kern_info = { 521da177e4SLinus Torvalds .init = pcap_init, 531da177e4SLinus Torvalds .protocol = eth_protocol, 541da177e4SLinus Torvalds .read = pcap_read, 551da177e4SLinus Torvalds .write = pcap_write, 561da177e4SLinus Torvalds }; 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds int pcap_setup(char *str, char **mac_out, void *data) 591da177e4SLinus Torvalds { 601da177e4SLinus Torvalds struct pcap_init *init = data; 611da177e4SLinus Torvalds char *remain, *host_if = NULL, *options[2] = { NULL, NULL }; 621da177e4SLinus Torvalds int i; 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds *init = ((struct pcap_init) 651da177e4SLinus Torvalds { .host_if = "eth0", 661da177e4SLinus Torvalds .promisc = 1, 671da177e4SLinus Torvalds .optimize = 0, 681da177e4SLinus Torvalds .filter = NULL }); 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds remain = split_if_spec(str, &host_if, &init->filter, 710ba34e19SJeff Dike &options[0], &options[1], mac_out, NULL); 721da177e4SLinus Torvalds if (remain != NULL) { 731da177e4SLinus Torvalds printk(KERN_ERR "pcap_setup - Extra garbage on " 741da177e4SLinus Torvalds "specification : '%s'\n", remain); 757d98230aSJeff Dike return 0; 761da177e4SLinus Torvalds } 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds if (host_if != NULL) 791da177e4SLinus Torvalds init->host_if = host_if; 801da177e4SLinus Torvalds 8191b165c0SJeff Dike for (i = 0; i < ARRAY_SIZE(options); i++) { 821da177e4SLinus Torvalds if (options[i] == NULL) 831da177e4SLinus Torvalds continue; 841da177e4SLinus Torvalds if (!strcmp(options[i], "promisc")) 851da177e4SLinus Torvalds init->promisc = 1; 861da177e4SLinus Torvalds else if (!strcmp(options[i], "nopromisc")) 871da177e4SLinus Torvalds init->promisc = 0; 881da177e4SLinus Torvalds else if (!strcmp(options[i], "optimize")) 891da177e4SLinus Torvalds init->optimize = 1; 901da177e4SLinus Torvalds else if (!strcmp(options[i], "nooptimize")) 911da177e4SLinus Torvalds init->optimize = 0; 927d98230aSJeff Dike else { 93*cd1ae0e4SJeff Dike printk(KERN_ERR "pcap_setup : bad option - '%s'\n", 94*cd1ae0e4SJeff Dike options[i]); 957d98230aSJeff Dike return 0; 967d98230aSJeff Dike } 971da177e4SLinus Torvalds } 981da177e4SLinus Torvalds 997d98230aSJeff Dike return 1; 1001da177e4SLinus Torvalds } 1011da177e4SLinus Torvalds 1021da177e4SLinus Torvalds static struct transport pcap_transport = { 1031da177e4SLinus Torvalds .list = LIST_HEAD_INIT(pcap_transport.list), 1041da177e4SLinus Torvalds .name = "pcap", 1051da177e4SLinus Torvalds .setup = pcap_setup, 1061da177e4SLinus Torvalds .user = &pcap_user_info, 1071da177e4SLinus Torvalds .kern = &pcap_kern_info, 1081da177e4SLinus Torvalds .private_size = sizeof(struct pcap_data), 1091da177e4SLinus Torvalds .setup_size = sizeof(struct pcap_init), 1101da177e4SLinus Torvalds }; 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds static int register_pcap(void) 1131da177e4SLinus Torvalds { 1141da177e4SLinus Torvalds register_transport(&pcap_transport); 115f4c57a78SJeff Dike return 0; 1161da177e4SLinus Torvalds } 1171da177e4SLinus Torvalds 1188210fd2aSJeff Dike late_initcall(register_pcap); 119