linux/drivers/net/tap.c

// SPDX-License-Identifier: GPL-2.0-only
#include <linux/etherdevice.h>
#include <linux/if_tap.h>
#include <linux/if_vlan.h>
#include <linux/interrupt.h>
#include <linux/nsproxy.h>
#include <linux/compat.h>
#include <linux/if_tun.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/cache.h>
#include <linux/sched/signal.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/cdev.h>
#include <linux/idr.h>
#include <linux/fs.h>
#include <linux/uio.h>

#include <net/gso.h>
#include <net/net_namespace.h>
#include <net/rtnetlink.h>
#include <net/sock.h>
#include <net/xdp.h>
#include <linux/virtio_net.h>
#include <linux/skb_array.h>

#define TAP_IFFEATURES

#define TAP_VNET_LE
#define TAP_VNET_BE

#ifdef CONFIG_TUN_VNET_CROSS_LE
static inline bool tap_legacy_is_little_endian(struct tap_queue *q)
{}

static long tap_get_vnet_be(struct tap_queue *q, int __user *sp)
{}

static long tap_set_vnet_be(struct tap_queue *q, int __user *sp)
{}
#else
static inline bool tap_legacy_is_little_endian(struct tap_queue *q)
{
	return virtio_legacy_is_little_endian();
}

static long tap_get_vnet_be(struct tap_queue *q, int __user *argp)
{
	return -EINVAL;
}

static long tap_set_vnet_be(struct tap_queue *q, int __user *argp)
{
	return -EINVAL;
}
#endif /* CONFIG_TUN_VNET_CROSS_LE */

static inline bool tap_is_little_endian(struct tap_queue *q)
{}

static inline u16 tap16_to_cpu(struct tap_queue *q, __virtio16 val)
{}

static inline __virtio16 cpu_to_tap16(struct tap_queue *q, u16 val)
{}

static struct proto tap_proto =;

#define TAP_NUM_DEVS

static LIST_HEAD(major_list);

struct major_info {};

#define GOODCOPY_LEN

static const struct proto_ops tap_socket_ops;

#define RX_OFFLOADS
#define TAP_FEATURES

static struct tap_dev *tap_dev_get_rcu(const struct net_device *dev)
{}

/*
 * RCU usage:
 * The tap_queue and the macvlan_dev are loosely coupled, the
 * pointers from one to the other can only be read while rcu_read_lock
 * or rtnl is held.
 *
 * Both the file and the macvlan_dev hold a reference on the tap_queue
 * through sock_hold(&q->sk). When the macvlan_dev goes away first,
 * q->vlan becomes inaccessible. When the files gets closed,
 * tap_get_queue() fails.
 *
 * There may still be references to the struct sock inside of the
 * queue from outbound SKBs, but these never reference back to the
 * file or the dev. The data structure is freed through __sk_free
 * when both our references and any pending SKBs are gone.
 */

static int tap_enable_queue(struct tap_dev *tap, struct file *file,
			    struct tap_queue *q)
{}

/* Requires RTNL */
static int tap_set_queue(struct tap_dev *tap, struct file *file,
			 struct tap_queue *q)
{}

static int tap_disable_queue(struct tap_queue *q)
{}

/*
 * The file owning the queue got closed, give up both
 * the reference that the files holds as well as the
 * one from the macvlan_dev if that still exists.
 *
 * Using the spinlock makes sure that we don't get
 * to the queue again after destroying it.
 */
static void tap_put_queue(struct tap_queue *q)
{}

/*
 * Select a queue based on the rxq of the device on which this packet
 * arrived. If the incoming device is not mq, calculate a flow hash
 * to select a queue. If all fails, find the first available queue.
 * Cache vlan->numvtaps since it can become zero during the execution
 * of this function.
 */
static struct tap_queue *tap_get_queue(struct tap_dev *tap,
				       struct sk_buff *skb)
{}

/*
 * The net_device is going away, give up the reference
 * that it holds on all queues and safely set the pointer
 * from the queues to NULL.
 */
void tap_del_queues(struct tap_dev *tap)
{}
EXPORT_SYMBOL_GPL();

rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)
{}
EXPORT_SYMBOL_GPL();

static struct major_info *tap_get_major(int major)
{}

int tap_get_minor(dev_t major, struct tap_dev *tap)
{}
EXPORT_SYMBOL_GPL();

void tap_free_minor(dev_t major, struct tap_dev *tap)
{}
EXPORT_SYMBOL_GPL();

static struct tap_dev *dev_get_by_tap_file(int major, int minor)
{}

static void tap_sock_write_space(struct sock *sk)
{}

static void tap_sock_destruct(struct sock *sk)
{}

static int tap_open(struct inode *inode, struct file *file)
{}

static int tap_release(struct inode *inode, struct file *file)
{}

static __poll_t tap_poll(struct file *file, poll_table *wait)
{}

static inline struct sk_buff *tap_alloc_skb(struct sock *sk, size_t prepad,
					    size_t len, size_t linear,
						int noblock, int *err)
{}

/* Neighbour code has some assumptions on HH_DATA_MOD alignment */
#define TAP_RESERVE

/* Get packet from user space buffer */
static ssize_t tap_get_user(struct tap_queue *q, void *msg_control,
			    struct iov_iter *from, int noblock)
{}

static ssize_t tap_write_iter(struct kiocb *iocb, struct iov_iter *from)
{}

/* Put packet to the user space buffer */
static ssize_t tap_put_user(struct tap_queue *q,
			    const struct sk_buff *skb,
			    struct iov_iter *iter)
{}

static ssize_t tap_do_read(struct tap_queue *q,
			   struct iov_iter *to,
			   int noblock, struct sk_buff *skb)
{}

static ssize_t tap_read_iter(struct kiocb *iocb, struct iov_iter *to)
{}

static struct tap_dev *tap_get_tap_dev(struct tap_queue *q)
{}

static void tap_put_tap_dev(struct tap_dev *tap)
{}

static int tap_ioctl_set_queue(struct file *file, unsigned int flags)
{}

static int set_offload(struct tap_queue *q, unsigned long arg)
{}

/*
 * provide compatibility with generic tun/tap interface
 */
static long tap_ioctl(struct file *file, unsigned int cmd,
		      unsigned long arg)
{}

static const struct file_operations tap_fops =;

static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp)
{}

static int tap_sendmsg(struct socket *sock, struct msghdr *m,
		       size_t total_len)
{}

static int tap_recvmsg(struct socket *sock, struct msghdr *m,
		       size_t total_len, int flags)
{}

static int tap_peek_len(struct socket *sock)
{}

/* Ops structure to mimic raw sockets with tun */
static const struct proto_ops tap_socket_ops =;

/* Get an underlying socket object from tun file.  Returns error unless file is
 * attached to a device.  The returned object works like a packet socket, it
 * can be used for sock_sendmsg/sock_recvmsg.  The caller is responsible for
 * holding a reference to the file for as long as the socket is in use. */
struct socket *tap_get_socket(struct file *file)
{}
EXPORT_SYMBOL_GPL();

struct ptr_ring *tap_get_ptr_ring(struct file *file)
{}
EXPORT_SYMBOL_GPL();

int tap_queue_resize(struct tap_dev *tap)
{}
EXPORT_SYMBOL_GPL();

static int tap_list_add(dev_t major, const char *device_name)
{}

int tap_create_cdev(struct cdev *tap_cdev, dev_t *tap_major,
		    const char *device_name, struct module *module)
{}
EXPORT_SYMBOL_GPL();

void tap_destroy_cdev(dev_t major, struct cdev *tap_cdev)
{}
EXPORT_SYMBOL_GPL();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_LICENSE();