11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright (C) 2002 Jeff Dike <jdike@karaya.com> 31da177e4SLinus Torvalds * Licensed under the GPL. 41da177e4SLinus Torvalds */ 51da177e4SLinus Torvalds 61da177e4SLinus Torvalds #include "linux/init.h" 71da177e4SLinus Torvalds #include "linux/netdevice.h" 81da177e4SLinus Torvalds #include "linux/etherdevice.h" 91da177e4SLinus Torvalds #include "net_kern.h" 101da177e4SLinus Torvalds #include "net_user.h" 111da177e4SLinus Torvalds #include "pcap_user.h" 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds struct pcap_init { 141da177e4SLinus Torvalds char *host_if; 151da177e4SLinus Torvalds int promisc; 161da177e4SLinus Torvalds int optimize; 171da177e4SLinus Torvalds char *filter; 181da177e4SLinus Torvalds }; 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds void pcap_init(struct net_device *dev, void *data) 211da177e4SLinus Torvalds { 221da177e4SLinus Torvalds struct uml_net_private *pri; 231da177e4SLinus Torvalds struct pcap_data *ppri; 241da177e4SLinus Torvalds struct pcap_init *init = data; 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds pri = dev->priv; 271da177e4SLinus Torvalds ppri = (struct pcap_data *) pri->user; 281da177e4SLinus Torvalds ppri->host_if = init->host_if; 291da177e4SLinus Torvalds ppri->promisc = init->promisc; 301da177e4SLinus Torvalds ppri->optimize = init->optimize; 311da177e4SLinus Torvalds ppri->filter = init->filter; 32*7d98230aSJeff Dike 33*7d98230aSJeff Dike printk("pcap backend, host interface %s\n", ppri->host_if); 341da177e4SLinus Torvalds } 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds static int pcap_read(int fd, struct sk_buff **skb, 371da177e4SLinus Torvalds struct uml_net_private *lp) 381da177e4SLinus Torvalds { 391da177e4SLinus Torvalds *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); 40*7d98230aSJeff Dike if(*skb == NULL) 41*7d98230aSJeff Dike return -ENOMEM; 42*7d98230aSJeff Dike 43*7d98230aSJeff Dike return pcap_user_read(fd, skb_mac_header(*skb), 441da177e4SLinus Torvalds (*skb)->dev->mtu + ETH_HEADER_OTHER, 45*7d98230aSJeff Dike (struct pcap_data *) &lp->user); 461da177e4SLinus Torvalds } 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) 491da177e4SLinus Torvalds { 50*7d98230aSJeff Dike return -EPERM; 511da177e4SLinus Torvalds } 521da177e4SLinus Torvalds 535e7672ecSJeff Dike static const struct net_kern_info pcap_kern_info = { 541da177e4SLinus Torvalds .init = pcap_init, 551da177e4SLinus Torvalds .protocol = eth_protocol, 561da177e4SLinus Torvalds .read = pcap_read, 571da177e4SLinus Torvalds .write = pcap_write, 581da177e4SLinus Torvalds }; 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds int pcap_setup(char *str, char **mac_out, void *data) 611da177e4SLinus Torvalds { 621da177e4SLinus Torvalds struct pcap_init *init = data; 631da177e4SLinus Torvalds char *remain, *host_if = NULL, *options[2] = { NULL, NULL }; 641da177e4SLinus Torvalds int i; 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds *init = ((struct pcap_init) 671da177e4SLinus Torvalds { .host_if = "eth0", 681da177e4SLinus Torvalds .promisc = 1, 691da177e4SLinus Torvalds .optimize = 0, 701da177e4SLinus Torvalds .filter = NULL }); 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds remain = split_if_spec(str, &host_if, &init->filter, 731da177e4SLinus Torvalds &options[0], &options[1], NULL); 741da177e4SLinus Torvalds if(remain != NULL){ 751da177e4SLinus Torvalds printk(KERN_ERR "pcap_setup - Extra garbage on " 761da177e4SLinus Torvalds "specification : '%s'\n", remain); 77*7d98230aSJeff Dike return 0; 781da177e4SLinus Torvalds } 791da177e4SLinus Torvalds 801da177e4SLinus Torvalds if(host_if != NULL) 811da177e4SLinus Torvalds init->host_if = host_if; 821da177e4SLinus Torvalds 8391b165c0SJeff Dike for(i = 0; i < ARRAY_SIZE(options); i++){ 841da177e4SLinus Torvalds if(options[i] == NULL) 851da177e4SLinus Torvalds continue; 861da177e4SLinus Torvalds if(!strcmp(options[i], "promisc")) 871da177e4SLinus Torvalds init->promisc = 1; 881da177e4SLinus Torvalds else if(!strcmp(options[i], "nopromisc")) 891da177e4SLinus Torvalds init->promisc = 0; 901da177e4SLinus Torvalds else if(!strcmp(options[i], "optimize")) 911da177e4SLinus Torvalds init->optimize = 1; 921da177e4SLinus Torvalds else if(!strcmp(options[i], "nooptimize")) 931da177e4SLinus Torvalds init->optimize = 0; 94*7d98230aSJeff Dike else { 95*7d98230aSJeff Dike printk("pcap_setup : bad option - '%s'\n", options[i]); 96*7d98230aSJeff Dike return 0; 97*7d98230aSJeff Dike } 981da177e4SLinus Torvalds } 991da177e4SLinus Torvalds 100*7d98230aSJeff Dike return 1; 1011da177e4SLinus Torvalds } 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds static struct transport pcap_transport = { 1041da177e4SLinus Torvalds .list = LIST_HEAD_INIT(pcap_transport.list), 1051da177e4SLinus Torvalds .name = "pcap", 1061da177e4SLinus Torvalds .setup = pcap_setup, 1071da177e4SLinus Torvalds .user = &pcap_user_info, 1081da177e4SLinus Torvalds .kern = &pcap_kern_info, 1091da177e4SLinus Torvalds .private_size = sizeof(struct pcap_data), 1101da177e4SLinus Torvalds .setup_size = sizeof(struct pcap_init), 1111da177e4SLinus Torvalds }; 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds static int register_pcap(void) 1141da177e4SLinus Torvalds { 1151da177e4SLinus Torvalds register_transport(&pcap_transport); 116f4c57a78SJeff Dike return 0; 1171da177e4SLinus Torvalds } 1181da177e4SLinus Torvalds 1198210fd2aSJeff Dike late_initcall(register_pcap); 120