1*97870c34SAlex Dewar // SPDX-License-Identifier: GPL-2.0 21da177e4SLinus Torvalds /* 3cd1ae0e4SJeff Dike * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 41da177e4SLinus Torvalds */ 51da177e4SLinus Torvalds 6cd1ae0e4SJeff Dike #include <linux/netdevice.h> 7cd1ae0e4SJeff Dike #include <linux/init.h> 8cd1ae0e4SJeff Dike #include <linux/skbuff.h> 9cd1ae0e4SJeff Dike #include <asm/errno.h> 1037185b33SAl Viro #include <net_kern.h> 111da177e4SLinus Torvalds #include "tuntap.h" 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds struct tuntap_init { 141da177e4SLinus Torvalds char *dev_name; 151da177e4SLinus Torvalds char *gate_addr; 161da177e4SLinus Torvalds }; 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds static void tuntap_init(struct net_device *dev, void *data) 191da177e4SLinus Torvalds { 201da177e4SLinus Torvalds struct uml_net_private *pri; 211da177e4SLinus Torvalds struct tuntap_data *tpri; 221da177e4SLinus Torvalds struct tuntap_init *init = data; 231da177e4SLinus Torvalds 2417c324faSWang Chen pri = netdev_priv(dev); 251da177e4SLinus Torvalds tpri = (struct tuntap_data *) pri->user; 261da177e4SLinus Torvalds tpri->dev_name = init->dev_name; 271da177e4SLinus Torvalds tpri->fixed_config = (init->dev_name != NULL); 281da177e4SLinus Torvalds tpri->gate_addr = init->gate_addr; 291da177e4SLinus Torvalds tpri->fd = -1; 301da177e4SLinus Torvalds tpri->dev = dev; 311da177e4SLinus Torvalds 325134d8feSJeff Dike printk(KERN_INFO "TUN/TAP backend - "); 331da177e4SLinus Torvalds if (tpri->gate_addr != NULL) 345134d8feSJeff Dike printk(KERN_CONT "IP = %s", tpri->gate_addr); 355134d8feSJeff Dike printk(KERN_CONT "\n"); 361da177e4SLinus Torvalds } 371da177e4SLinus Torvalds 38b53f35a8SJeff Dike static int tuntap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) 391da177e4SLinus Torvalds { 40b53f35a8SJeff Dike return net_read(fd, skb_mac_header(skb), 41b53f35a8SJeff Dike skb->dev->mtu + ETH_HEADER_OTHER); 421da177e4SLinus Torvalds } 431da177e4SLinus Torvalds 44b53f35a8SJeff Dike static int tuntap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) 451da177e4SLinus Torvalds { 46b53f35a8SJeff Dike return net_write(fd, skb->data, skb->len); 471da177e4SLinus Torvalds } 481da177e4SLinus Torvalds 495e7672ecSJeff Dike const struct net_kern_info tuntap_kern_info = { 501da177e4SLinus Torvalds .init = tuntap_init, 511da177e4SLinus Torvalds .protocol = eth_protocol, 521da177e4SLinus Torvalds .read = tuntap_read, 531da177e4SLinus Torvalds .write = tuntap_write, 541da177e4SLinus Torvalds }; 551da177e4SLinus Torvalds 561da177e4SLinus Torvalds int tuntap_setup(char *str, char **mac_out, void *data) 571da177e4SLinus Torvalds { 581da177e4SLinus Torvalds struct tuntap_init *init = data; 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds *init = ((struct tuntap_init) 611da177e4SLinus Torvalds { .dev_name = NULL, 621da177e4SLinus Torvalds .gate_addr = NULL }); 631da177e4SLinus Torvalds if (tap_setup_common(str, "tuntap", &init->dev_name, mac_out, 641da177e4SLinus Torvalds &init->gate_addr)) 65cd1ae0e4SJeff Dike return 0; 661da177e4SLinus Torvalds 67cd1ae0e4SJeff Dike return 1; 681da177e4SLinus Torvalds } 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds static struct transport tuntap_transport = { 711da177e4SLinus Torvalds .list = LIST_HEAD_INIT(tuntap_transport.list), 721da177e4SLinus Torvalds .name = "tuntap", 731da177e4SLinus Torvalds .setup = tuntap_setup, 741da177e4SLinus Torvalds .user = &tuntap_user_info, 751da177e4SLinus Torvalds .kern = &tuntap_kern_info, 761da177e4SLinus Torvalds .private_size = sizeof(struct tuntap_data), 771da177e4SLinus Torvalds .setup_size = sizeof(struct tuntap_init), 781da177e4SLinus Torvalds }; 791da177e4SLinus Torvalds 801da177e4SLinus Torvalds static int register_tuntap(void) 811da177e4SLinus Torvalds { 821da177e4SLinus Torvalds register_transport(&tuntap_transport); 83f4c57a78SJeff Dike return 0; 841da177e4SLinus Torvalds } 851da177e4SLinus Torvalds 868210fd2aSJeff Dike late_initcall(register_tuntap); 87