1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * user-mode-linux networking multicast transport
4  * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org>
5  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
6  *
7  * based on the existing uml-networking code, which is
8  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
9  * James Leu (jleu@mindspring.net).
10  * Copyright (C) 2001 by various other people who didn't put their name here.
11  *
12  */
13 
14 #include <linux/init.h>
15 #include <linux/netdevice.h>
16 #include "umcast.h"
17 #include <net_kern.h>
18 
19 struct umcast_init {
20 	char *addr;
21 	int lport;
22 	int rport;
23 	int ttl;
24 	bool unicast;
25 };
26 
umcast_init(struct net_device * dev,void * data)27 static void umcast_init(struct net_device *dev, void *data)
28 {
29 	struct uml_net_private *pri;
30 	struct umcast_data *dpri;
31 	struct umcast_init *init = data;
32 
33 	pri = netdev_priv(dev);
34 	dpri = (struct umcast_data *) pri->user;
35 	dpri->addr = init->addr;
36 	dpri->lport = init->lport;
37 	dpri->rport = init->rport;
38 	dpri->unicast = init->unicast;
39 	dpri->ttl = init->ttl;
40 	dpri->dev = dev;
41 
42 	if (dpri->unicast) {
43 		printk(KERN_INFO "ucast backend address: %s:%u listen port: "
44 		       "%u\n", dpri->addr, dpri->rport, dpri->lport);
45 	} else {
46 		printk(KERN_INFO "mcast backend multicast address: %s:%u, "
47 		       "TTL:%u\n", dpri->addr, dpri->lport, dpri->ttl);
48 	}
49 }
50 
umcast_read(int fd,struct sk_buff * skb,struct uml_net_private * lp)51 static int umcast_read(int fd, struct sk_buff *skb, struct uml_net_private *lp)
52 {
53 	return net_recvfrom(fd, skb_mac_header(skb),
54 			    skb->dev->mtu + ETH_HEADER_OTHER);
55 }
56 
umcast_write(int fd,struct sk_buff * skb,struct uml_net_private * lp)57 static int umcast_write(int fd, struct sk_buff *skb, struct uml_net_private *lp)
58 {
59 	return umcast_user_write(fd, skb->data, skb->len,
60 				(struct umcast_data *) &lp->user);
61 }
62 
63 static const struct net_kern_info umcast_kern_info = {
64 	.init			= umcast_init,
65 	.protocol		= eth_protocol,
66 	.read			= umcast_read,
67 	.write			= umcast_write,
68 };
69 
mcast_setup(char * str,char ** mac_out,void * data)70 static int mcast_setup(char *str, char **mac_out, void *data)
71 {
72 	struct umcast_init *init = data;
73 	char *port_str = NULL, *ttl_str = NULL, *remain;
74 	char *last;
75 
76 	*init = ((struct umcast_init)
77 		{ .addr	= "239.192.168.1",
78 		  .lport	= 1102,
79 		  .ttl	= 1 });
80 
81 	remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str,
82 			       NULL);
83 	if (remain != NULL) {
84 		printk(KERN_ERR "mcast_setup - Extra garbage on "
85 		       "specification : '%s'\n", remain);
86 		return 0;
87 	}
88 
89 	if (port_str != NULL) {
90 		init->lport = simple_strtoul(port_str, &last, 10);
91 		if ((*last != '\0') || (last == port_str)) {
92 			printk(KERN_ERR "mcast_setup - Bad port : '%s'\n",
93 			       port_str);
94 			return 0;
95 		}
96 	}
97 
98 	if (ttl_str != NULL) {
99 		init->ttl = simple_strtoul(ttl_str, &last, 10);
100 		if ((*last != '\0') || (last == ttl_str)) {
101 			printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n",
102 			       ttl_str);
103 			return 0;
104 		}
105 	}
106 
107 	init->unicast = false;
108 	init->rport = init->lport;
109 
110 	printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr,
111 	       init->lport, init->ttl);
112 
113 	return 1;
114 }
115 
ucast_setup(char * str,char ** mac_out,void * data)116 static int ucast_setup(char *str, char **mac_out, void *data)
117 {
118 	struct umcast_init *init = data;
119 	char *lport_str = NULL, *rport_str = NULL, *remain;
120 	char *last;
121 
122 	*init = ((struct umcast_init)
123 		{ .addr		= "",
124 		  .lport	= 1102,
125 		  .rport	= 1102 });
126 
127 	remain = split_if_spec(str, mac_out, &init->addr,
128 			       &lport_str, &rport_str, NULL);
129 	if (remain != NULL) {
130 		printk(KERN_ERR "ucast_setup - Extra garbage on "
131 		       "specification : '%s'\n", remain);
132 		return 0;
133 	}
134 
135 	if (lport_str != NULL) {
136 		init->lport = simple_strtoul(lport_str, &last, 10);
137 		if ((*last != '\0') || (last == lport_str)) {
138 			printk(KERN_ERR "ucast_setup - Bad listen port : "
139 			       "'%s'\n", lport_str);
140 			return 0;
141 		}
142 	}
143 
144 	if (rport_str != NULL) {
145 		init->rport = simple_strtoul(rport_str, &last, 10);
146 		if ((*last != '\0') || (last == rport_str)) {
147 			printk(KERN_ERR "ucast_setup - Bad remote port : "
148 			       "'%s'\n", rport_str);
149 			return 0;
150 		}
151 	}
152 
153 	init->unicast = true;
154 
155 	printk(KERN_INFO "Configured ucast device: :%u -> %s:%u\n",
156 	       init->lport, init->addr, init->rport);
157 
158 	return 1;
159 }
160 
161 static struct transport mcast_transport = {
162 	.list	= LIST_HEAD_INIT(mcast_transport.list),
163 	.name	= "mcast",
164 	.setup	= mcast_setup,
165 	.user	= &umcast_user_info,
166 	.kern	= &umcast_kern_info,
167 	.private_size	= sizeof(struct umcast_data),
168 	.setup_size	= sizeof(struct umcast_init),
169 };
170 
171 static struct transport ucast_transport = {
172 	.list	= LIST_HEAD_INIT(ucast_transport.list),
173 	.name	= "ucast",
174 	.setup	= ucast_setup,
175 	.user	= &umcast_user_info,
176 	.kern	= &umcast_kern_info,
177 	.private_size	= sizeof(struct umcast_data),
178 	.setup_size	= sizeof(struct umcast_init),
179 };
180 
register_umcast(void)181 static int register_umcast(void)
182 {
183 	register_transport(&mcast_transport);
184 	register_transport(&ucast_transport);
185 	return 0;
186 }
187 
188 late_initcall(register_umcast);
189