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