xref: /linux/arch/um/os-Linux/drivers/ethertap_kern.c (revision c771600c6af14749609b49565ffb4cac2959710d)
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 		= &ethertap_user_info,
891da177e4SLinus Torvalds 	.kern 		= &ethertap_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(&ethertap_transport);
97f4c57a78SJeff Dike 	return 0;
981da177e4SLinus Torvalds }
991da177e4SLinus Torvalds 
1008210fd2aSJeff Dike late_initcall(register_ethertap);
101