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