162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org).
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <stddef.h>
762306a36Sopenharmony_ci#include <errno.h>
862306a36Sopenharmony_ci#include <libvdeplug.h>
962306a36Sopenharmony_ci#include <net_user.h>
1062306a36Sopenharmony_ci#include <um_malloc.h>
1162306a36Sopenharmony_ci#include "vde.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistatic int vde_user_init(void *data, void *dev)
1462306a36Sopenharmony_ci{
1562306a36Sopenharmony_ci	struct vde_data *pri = data;
1662306a36Sopenharmony_ci	VDECONN *conn = NULL;
1762306a36Sopenharmony_ci	int err = -EINVAL;
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci	pri->dev = dev;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	conn = vde_open(pri->vde_switch, pri->descr, pri->args);
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci	if (conn == NULL) {
2462306a36Sopenharmony_ci		err = -errno;
2562306a36Sopenharmony_ci		printk(UM_KERN_ERR "vde_user_init: vde_open failed, "
2662306a36Sopenharmony_ci		       "errno = %d\n", errno);
2762306a36Sopenharmony_ci		return err;
2862306a36Sopenharmony_ci	}
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	printk(UM_KERN_INFO "vde backend - connection opened\n");
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	pri->conn = conn;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	return 0;
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic int vde_user_open(void *data)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	struct vde_data *pri = data;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	if (pri->conn != NULL)
4262306a36Sopenharmony_ci		return vde_datafd(pri->conn);
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	printk(UM_KERN_WARNING "vde_open - we have no VDECONN to open");
4562306a36Sopenharmony_ci	return -EINVAL;
4662306a36Sopenharmony_ci}
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistatic void vde_remove(void *data)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	struct vde_data *pri = data;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	if (pri->conn != NULL) {
5362306a36Sopenharmony_ci		printk(UM_KERN_INFO "vde backend - closing connection\n");
5462306a36Sopenharmony_ci		vde_close(pri->conn);
5562306a36Sopenharmony_ci		pri->conn = NULL;
5662306a36Sopenharmony_ci		kfree(pri->args);
5762306a36Sopenharmony_ci		pri->args = NULL;
5862306a36Sopenharmony_ci		return;
5962306a36Sopenharmony_ci	}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	printk(UM_KERN_WARNING "vde_remove - we have no VDECONN to remove");
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ciconst struct net_user_info vde_user_info = {
6562306a36Sopenharmony_ci	.init		= vde_user_init,
6662306a36Sopenharmony_ci	.open		= vde_user_open,
6762306a36Sopenharmony_ci	.close	 	= NULL,
6862306a36Sopenharmony_ci	.remove	 	= vde_remove,
6962306a36Sopenharmony_ci	.add_address	= NULL,
7062306a36Sopenharmony_ci	.delete_address = NULL,
7162306a36Sopenharmony_ci	.mtu		= ETH_MAX_PACKET,
7262306a36Sopenharmony_ci	.max_packet	= ETH_MAX_PACKET + ETH_HEADER_OTHER,
7362306a36Sopenharmony_ci};
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_civoid vde_init_libstuff(struct vde_data *vpri, struct vde_init *init)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	struct vde_open_args *args;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	vpri->args = uml_kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL);
8062306a36Sopenharmony_ci	if (vpri->args == NULL) {
8162306a36Sopenharmony_ci		printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args "
8262306a36Sopenharmony_ci		       "allocation failed");
8362306a36Sopenharmony_ci		return;
8462306a36Sopenharmony_ci	}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	args = vpri->args;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	args->port = init->port;
8962306a36Sopenharmony_ci	args->group = init->group;
9062306a36Sopenharmony_ci	args->mode = init->mode ? init->mode : 0700;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	args->port ?  printk("port %d", args->port) :
9362306a36Sopenharmony_ci		printk("undefined port");
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ciint vde_user_read(void *conn, void *buf, int len)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	VDECONN *vconn = conn;
9962306a36Sopenharmony_ci	int rv;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	if (vconn == NULL)
10262306a36Sopenharmony_ci		return 0;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	rv = vde_recv(vconn, buf, len, 0);
10562306a36Sopenharmony_ci	if (rv < 0) {
10662306a36Sopenharmony_ci		if (errno == EAGAIN)
10762306a36Sopenharmony_ci			return 0;
10862306a36Sopenharmony_ci		return -errno;
10962306a36Sopenharmony_ci	}
11062306a36Sopenharmony_ci	else if (rv == 0)
11162306a36Sopenharmony_ci		return -ENOTCONN;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	return rv;
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ciint vde_user_write(void *conn, void *buf, int len)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	VDECONN *vconn = conn;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	if (vconn == NULL)
12162306a36Sopenharmony_ci		return 0;
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	return vde_send(vconn, buf, len, 0);
12462306a36Sopenharmony_ci}
12562306a36Sopenharmony_ci
126