xref: /openbmc/linux/arch/um/drivers/umcast_kern.c (revision 976e3645923bdd2fe7893aae33fd7a21098bfb28)
1*dbddf429SAlex Dewar // SPDX-License-Identifier: GPL-2.0
24ff4d8d3SNolan Leake /*
34ff4d8d3SNolan Leake  * user-mode-linux networking multicast transport
44ff4d8d3SNolan Leake  * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org>
54ff4d8d3SNolan Leake  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
64ff4d8d3SNolan Leake  *
74ff4d8d3SNolan Leake  * based on the existing uml-networking code, which is
84ff4d8d3SNolan Leake  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
94ff4d8d3SNolan Leake  * James Leu (jleu@mindspring.net).
104ff4d8d3SNolan Leake  * Copyright (C) 2001 by various other people who didn't put their name here.
114ff4d8d3SNolan Leake  *
124ff4d8d3SNolan Leake  */
134ff4d8d3SNolan Leake 
1437185b33SAl Viro #include <linux/init.h>
154ff4d8d3SNolan Leake #include <linux/netdevice.h>
164ff4d8d3SNolan Leake #include "umcast.h"
1737185b33SAl Viro #include <net_kern.h>
184ff4d8d3SNolan Leake 
194ff4d8d3SNolan Leake struct umcast_init {
204ff4d8d3SNolan Leake 	char *addr;
214ff4d8d3SNolan Leake 	int lport;
224ff4d8d3SNolan Leake 	int rport;
234ff4d8d3SNolan Leake 	int ttl;
244ff4d8d3SNolan Leake 	bool unicast;
254ff4d8d3SNolan Leake };
264ff4d8d3SNolan Leake 
umcast_init(struct net_device * dev,void * data)274ff4d8d3SNolan Leake static void umcast_init(struct net_device *dev, void *data)
284ff4d8d3SNolan Leake {
294ff4d8d3SNolan Leake 	struct uml_net_private *pri;
304ff4d8d3SNolan Leake 	struct umcast_data *dpri;
314ff4d8d3SNolan Leake 	struct umcast_init *init = data;
324ff4d8d3SNolan Leake 
334ff4d8d3SNolan Leake 	pri = netdev_priv(dev);
344ff4d8d3SNolan Leake 	dpri = (struct umcast_data *) pri->user;
354ff4d8d3SNolan Leake 	dpri->addr = init->addr;
364ff4d8d3SNolan Leake 	dpri->lport = init->lport;
374ff4d8d3SNolan Leake 	dpri->rport = init->rport;
384ff4d8d3SNolan Leake 	dpri->unicast = init->unicast;
394ff4d8d3SNolan Leake 	dpri->ttl = init->ttl;
404ff4d8d3SNolan Leake 	dpri->dev = dev;
414ff4d8d3SNolan Leake 
424ff4d8d3SNolan Leake 	if (dpri->unicast) {
434ff4d8d3SNolan Leake 		printk(KERN_INFO "ucast backend address: %s:%u listen port: "
444ff4d8d3SNolan Leake 		       "%u\n", dpri->addr, dpri->rport, dpri->lport);
454ff4d8d3SNolan Leake 	} else {
464ff4d8d3SNolan Leake 		printk(KERN_INFO "mcast backend multicast address: %s:%u, "
474ff4d8d3SNolan Leake 		       "TTL:%u\n", dpri->addr, dpri->lport, dpri->ttl);
484ff4d8d3SNolan Leake 	}
494ff4d8d3SNolan Leake }
504ff4d8d3SNolan Leake 
umcast_read(int fd,struct sk_buff * skb,struct uml_net_private * lp)514ff4d8d3SNolan Leake static int umcast_read(int fd, struct sk_buff *skb, struct uml_net_private *lp)
524ff4d8d3SNolan Leake {
534ff4d8d3SNolan Leake 	return net_recvfrom(fd, skb_mac_header(skb),
544ff4d8d3SNolan Leake 			    skb->dev->mtu + ETH_HEADER_OTHER);
554ff4d8d3SNolan Leake }
564ff4d8d3SNolan Leake 
umcast_write(int fd,struct sk_buff * skb,struct uml_net_private * lp)574ff4d8d3SNolan Leake static int umcast_write(int fd, struct sk_buff *skb, struct uml_net_private *lp)
584ff4d8d3SNolan Leake {
594ff4d8d3SNolan Leake 	return umcast_user_write(fd, skb->data, skb->len,
604ff4d8d3SNolan Leake 				(struct umcast_data *) &lp->user);
614ff4d8d3SNolan Leake }
624ff4d8d3SNolan Leake 
634ff4d8d3SNolan Leake static const struct net_kern_info umcast_kern_info = {
644ff4d8d3SNolan Leake 	.init			= umcast_init,
654ff4d8d3SNolan Leake 	.protocol		= eth_protocol,
664ff4d8d3SNolan Leake 	.read			= umcast_read,
674ff4d8d3SNolan Leake 	.write			= umcast_write,
684ff4d8d3SNolan Leake };
694ff4d8d3SNolan Leake 
mcast_setup(char * str,char ** mac_out,void * data)704ff4d8d3SNolan Leake static int mcast_setup(char *str, char **mac_out, void *data)
714ff4d8d3SNolan Leake {
724ff4d8d3SNolan Leake 	struct umcast_init *init = data;
734ff4d8d3SNolan Leake 	char *port_str = NULL, *ttl_str = NULL, *remain;
744ff4d8d3SNolan Leake 	char *last;
754ff4d8d3SNolan Leake 
764ff4d8d3SNolan Leake 	*init = ((struct umcast_init)
774ff4d8d3SNolan Leake 		{ .addr	= "239.192.168.1",
784ff4d8d3SNolan Leake 		  .lport	= 1102,
794ff4d8d3SNolan Leake 		  .ttl	= 1 });
804ff4d8d3SNolan Leake 
814ff4d8d3SNolan Leake 	remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str,
824ff4d8d3SNolan Leake 			       NULL);
834ff4d8d3SNolan Leake 	if (remain != NULL) {
844ff4d8d3SNolan Leake 		printk(KERN_ERR "mcast_setup - Extra garbage on "
854ff4d8d3SNolan Leake 		       "specification : '%s'\n", remain);
864ff4d8d3SNolan Leake 		return 0;
874ff4d8d3SNolan Leake 	}
884ff4d8d3SNolan Leake 
894ff4d8d3SNolan Leake 	if (port_str != NULL) {
904ff4d8d3SNolan Leake 		init->lport = simple_strtoul(port_str, &last, 10);
914ff4d8d3SNolan Leake 		if ((*last != '\0') || (last == port_str)) {
924ff4d8d3SNolan Leake 			printk(KERN_ERR "mcast_setup - Bad port : '%s'\n",
934ff4d8d3SNolan Leake 			       port_str);
944ff4d8d3SNolan Leake 			return 0;
954ff4d8d3SNolan Leake 		}
964ff4d8d3SNolan Leake 	}
974ff4d8d3SNolan Leake 
984ff4d8d3SNolan Leake 	if (ttl_str != NULL) {
994ff4d8d3SNolan Leake 		init->ttl = simple_strtoul(ttl_str, &last, 10);
1004ff4d8d3SNolan Leake 		if ((*last != '\0') || (last == ttl_str)) {
1014ff4d8d3SNolan Leake 			printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n",
1024ff4d8d3SNolan Leake 			       ttl_str);
1034ff4d8d3SNolan Leake 			return 0;
1044ff4d8d3SNolan Leake 		}
1054ff4d8d3SNolan Leake 	}
1064ff4d8d3SNolan Leake 
1074ff4d8d3SNolan Leake 	init->unicast = false;
1084ff4d8d3SNolan Leake 	init->rport = init->lport;
1094ff4d8d3SNolan Leake 
1104ff4d8d3SNolan Leake 	printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr,
1114ff4d8d3SNolan Leake 	       init->lport, init->ttl);
1124ff4d8d3SNolan Leake 
1134ff4d8d3SNolan Leake 	return 1;
1144ff4d8d3SNolan Leake }
1154ff4d8d3SNolan Leake 
ucast_setup(char * str,char ** mac_out,void * data)1164ff4d8d3SNolan Leake static int ucast_setup(char *str, char **mac_out, void *data)
1174ff4d8d3SNolan Leake {
1184ff4d8d3SNolan Leake 	struct umcast_init *init = data;
1194ff4d8d3SNolan Leake 	char *lport_str = NULL, *rport_str = NULL, *remain;
1204ff4d8d3SNolan Leake 	char *last;
1214ff4d8d3SNolan Leake 
1224ff4d8d3SNolan Leake 	*init = ((struct umcast_init)
1234ff4d8d3SNolan Leake 		{ .addr		= "",
1244ff4d8d3SNolan Leake 		  .lport	= 1102,
1254ff4d8d3SNolan Leake 		  .rport	= 1102 });
1264ff4d8d3SNolan Leake 
1274ff4d8d3SNolan Leake 	remain = split_if_spec(str, mac_out, &init->addr,
1284ff4d8d3SNolan Leake 			       &lport_str, &rport_str, NULL);
1294ff4d8d3SNolan Leake 	if (remain != NULL) {
1304ff4d8d3SNolan Leake 		printk(KERN_ERR "ucast_setup - Extra garbage on "
1314ff4d8d3SNolan Leake 		       "specification : '%s'\n", remain);
1324ff4d8d3SNolan Leake 		return 0;
1334ff4d8d3SNolan Leake 	}
1344ff4d8d3SNolan Leake 
1354ff4d8d3SNolan Leake 	if (lport_str != NULL) {
1364ff4d8d3SNolan Leake 		init->lport = simple_strtoul(lport_str, &last, 10);
1374ff4d8d3SNolan Leake 		if ((*last != '\0') || (last == lport_str)) {
1384ff4d8d3SNolan Leake 			printk(KERN_ERR "ucast_setup - Bad listen port : "
1394ff4d8d3SNolan Leake 			       "'%s'\n", lport_str);
1404ff4d8d3SNolan Leake 			return 0;
1414ff4d8d3SNolan Leake 		}
1424ff4d8d3SNolan Leake 	}
1434ff4d8d3SNolan Leake 
1444ff4d8d3SNolan Leake 	if (rport_str != NULL) {
1454ff4d8d3SNolan Leake 		init->rport = simple_strtoul(rport_str, &last, 10);
1464ff4d8d3SNolan Leake 		if ((*last != '\0') || (last == rport_str)) {
1474ff4d8d3SNolan Leake 			printk(KERN_ERR "ucast_setup - Bad remote port : "
1484ff4d8d3SNolan Leake 			       "'%s'\n", rport_str);
1494ff4d8d3SNolan Leake 			return 0;
1504ff4d8d3SNolan Leake 		}
1514ff4d8d3SNolan Leake 	}
1524ff4d8d3SNolan Leake 
1534ff4d8d3SNolan Leake 	init->unicast = true;
1544ff4d8d3SNolan Leake 
1554ff4d8d3SNolan Leake 	printk(KERN_INFO "Configured ucast device: :%u -> %s:%u\n",
1564ff4d8d3SNolan Leake 	       init->lport, init->addr, init->rport);
1574ff4d8d3SNolan Leake 
1584ff4d8d3SNolan Leake 	return 1;
1594ff4d8d3SNolan Leake }
1604ff4d8d3SNolan Leake 
1614ff4d8d3SNolan Leake static struct transport mcast_transport = {
1624ff4d8d3SNolan Leake 	.list	= LIST_HEAD_INIT(mcast_transport.list),
1634ff4d8d3SNolan Leake 	.name	= "mcast",
1644ff4d8d3SNolan Leake 	.setup	= mcast_setup,
1654ff4d8d3SNolan Leake 	.user	= &umcast_user_info,
1664ff4d8d3SNolan Leake 	.kern	= &umcast_kern_info,
1674ff4d8d3SNolan Leake 	.private_size	= sizeof(struct umcast_data),
1684ff4d8d3SNolan Leake 	.setup_size	= sizeof(struct umcast_init),
1694ff4d8d3SNolan Leake };
1704ff4d8d3SNolan Leake 
1714ff4d8d3SNolan Leake static struct transport ucast_transport = {
1724ff4d8d3SNolan Leake 	.list	= LIST_HEAD_INIT(ucast_transport.list),
1734ff4d8d3SNolan Leake 	.name	= "ucast",
1744ff4d8d3SNolan Leake 	.setup	= ucast_setup,
1754ff4d8d3SNolan Leake 	.user	= &umcast_user_info,
1764ff4d8d3SNolan Leake 	.kern	= &umcast_kern_info,
1774ff4d8d3SNolan Leake 	.private_size	= sizeof(struct umcast_data),
1784ff4d8d3SNolan Leake 	.setup_size	= sizeof(struct umcast_init),
1794ff4d8d3SNolan Leake };
1804ff4d8d3SNolan Leake 
register_umcast(void)1814ff4d8d3SNolan Leake static int register_umcast(void)
1824ff4d8d3SNolan Leake {
1834ff4d8d3SNolan Leake 	register_transport(&mcast_transport);
1844ff4d8d3SNolan Leake 	register_transport(&ucast_transport);
1854ff4d8d3SNolan Leake 	return 0;
1864ff4d8d3SNolan Leake }
1874ff4d8d3SNolan Leake 
1884ff4d8d3SNolan Leake late_initcall(register_umcast);
189