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 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 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 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 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 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 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