11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * James Leu (jleu@mindspring.net). 4cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001 by various other people who didn't put their name here. 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Licensed under the GPL. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 95134d8fea06ab51459fd095d091d1e6f73a44553Jeff Dike#include <linux/init.h> 10cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike#include <linux/netdevice.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "etap.h" 1237185b33240870719b6b5913a46e6a441f1ae96fAl Viro#include <net_kern.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct ethertap_init { 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *dev_name; 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *gate_addr; 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void etap_init(struct net_device *dev, void *data) 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct uml_net_private *pri; 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ethertap_data *epri; 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ethertap_init *init = data; 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2517c324fa80914e5b39d423dfd1a3cd61a3ec9866Wang Chen pri = netdev_priv(dev); 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds epri = (struct ethertap_data *) pri->user; 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds epri->dev_name = init->dev_name; 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds epri->gate_addr = init->gate_addr; 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds epri->data_fd = -1; 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds epri->control_fd = -1; 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds epri->dev = dev; 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 335134d8fea06ab51459fd095d091d1e6f73a44553Jeff Dike printk(KERN_INFO "ethertap backend - %s", epri->dev_name); 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (epri->gate_addr != NULL) 355134d8fea06ab51459fd095d091d1e6f73a44553Jeff Dike printk(KERN_CONT ", IP = %s", epri->gate_addr); 365134d8fea06ab51459fd095d091d1e6f73a44553Jeff Dike printk(KERN_CONT "\n"); 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39b53f35a8093e6aed7e8e880eaa0b89a3d2fdfb0aJeff Dikestatic int etap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43b53f35a8093e6aed7e8e880eaa0b89a3d2fdfb0aJeff Dike len = net_recvfrom(fd, skb_mac_header(skb), 44b53f35a8093e6aed7e8e880eaa0b89a3d2fdfb0aJeff Dike skb->dev->mtu + 2 + ETH_HEADER_ETHERTAP); 45cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (len <= 0) 46b53f35a8093e6aed7e8e880eaa0b89a3d2fdfb0aJeff Dike return(len); 47b53f35a8093e6aed7e8e880eaa0b89a3d2fdfb0aJeff Dike 48b53f35a8093e6aed7e8e880eaa0b89a3d2fdfb0aJeff Dike skb_pull(skb, 2); 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len -= 2; 50cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike return len; 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 53b53f35a8093e6aed7e8e880eaa0b89a3d2fdfb0aJeff Dikestatic int etap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 55b53f35a8093e6aed7e8e880eaa0b89a3d2fdfb0aJeff Dike skb_push(skb, 2); 56b53f35a8093e6aed7e8e880eaa0b89a3d2fdfb0aJeff Dike return net_send(fd, skb->data, skb->len); 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 595e7672ec3f059f764fcc5c78216e24bb16c44dbaJeff Dikeconst struct net_kern_info ethertap_kern_info = { 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .init = etap_init, 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .protocol = eth_protocol, 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read = etap_read, 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .write = etap_write, 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ethertap_setup(char *str, char **mac_out, void *data) 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ethertap_init *init = data; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *init = ((struct ethertap_init) 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { .dev_name = NULL, 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .gate_addr = NULL }); 73cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (tap_setup_common(str, "ethertap", &init->dev_name, mac_out, 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &init->gate_addr)) 75cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike return 0; 76cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (init->dev_name == NULL) { 77cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike printk(KERN_ERR "ethertap_setup : Missing tap device name\n"); 78cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike return 0; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 81cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike return 1; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct transport ethertap_transport = { 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .list = LIST_HEAD_INIT(ethertap_transport.list), 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "ethertap", 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .setup = ethertap_setup, 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .user = ðertap_user_info, 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .kern = ðertap_kern_info, 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .private_size = sizeof(struct ethertap_data), 91b53f35a8093e6aed7e8e880eaa0b89a3d2fdfb0aJeff Dike .setup_size = sizeof(struct ethertap_init), 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int register_ethertap(void) 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register_transport(ðertap_transport); 97f4c57a78e2c49f188babf675ba0a9264b5374c26Jeff Dike return 0; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1008210fd2a9fe4b36e99ab777a1a81eb47b703c235Jeff Dikelate_initcall(register_ethertap); 101