Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
umcast_kern.c
Go to the documentation of this file.
1 /*
2  * user-mode-linux networking multicast transport
3  * Copyright (C) 2001 by Harald Welte <[email protected]>
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 ([email protected]) and
8  * James Leu ([email protected]).
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 
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);