1/* 2 * user-mode-linux networking multicast transport 3 * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org> 4 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 5 * 6 * based on the existing uml-networking code, which is 7 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and 8 * James Leu (jleu@mindspring.net). 9 * Copyright (C) 2001 by various other people who didn't put their name here. 10 * 11 * Licensed under the GPL. 12 */ 13 14#include <linux/init.h> 15#include <linux/netdevice.h> 16#include "umcast.h" 17#include <net_kern.h> 18 19struct umcast_init { 20 char *addr; 21 int lport; 22 int rport; 23 int ttl; 24 bool unicast; 25}; 26 27static 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 51static 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 57static 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 63static 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 70static 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 116static 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 161static 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 171static 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 181static int register_umcast(void) 182{ 183 register_transport(&mcast_transport); 184 register_transport(&ucast_transport); 185 return 0; 186} 187 188late_initcall(register_umcast); 189