Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dlci.c
Go to the documentation of this file.
1 /*
2  * DLCI Implementation of Frame Relay protocol for Linux, according to
3  * RFC 1490. This generic device provides en/decapsulation for an
4  * underlying hardware driver. Routes & IPs are assigned to these
5  * interfaces. Requires 'dlcicfg' program to create usable
6  * interfaces, the initial one, 'dlci' is for IOCTL use only.
7  *
8  * Version: @(#)dlci.c 0.35 4 Jan 1997
9  *
10  * Author: Mike McLagan <[email protected]>
11  *
12  * Changes:
13  *
14  * 0.15 Mike Mclagan Packet freeing, bug in kmalloc call
15  * DLCI_RET handling
16  * 0.20 Mike McLagan More conservative on which packets
17  * are returned for retry and which are
18  * are dropped. If DLCI_RET_DROP is
19  * returned from the FRAD, the packet is
20  * sent back to Linux for re-transmission
21  * 0.25 Mike McLagan Converted to use SIOC IOCTL calls
22  * 0.30 Jim Freeman Fixed to allow IPX traffic
23  * 0.35 Michael Elizabeth Fixed incorrect memcpy_fromfs
24  *
25  * This program is free software; you can redistribute it and/or
26  * modify it under the terms of the GNU General Public License
27  * as published by the Free Software Foundation; either version
28  * 2 of the License, or (at your option) any later version.
29  */
30 
31 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
32 
33 #include <linux/module.h>
34 #include <linux/kernel.h>
35 #include <linux/types.h>
36 #include <linux/fcntl.h>
37 #include <linux/interrupt.h>
38 #include <linux/ptrace.h>
39 #include <linux/ioport.h>
40 #include <linux/in.h>
41 #include <linux/init.h>
42 #include <linux/slab.h>
43 #include <linux/string.h>
44 #include <linux/errno.h>
45 #include <linux/netdevice.h>
46 #include <linux/skbuff.h>
47 #include <linux/if_arp.h>
48 #include <linux/if_frad.h>
49 #include <linux/bitops.h>
50 
51 #include <net/sock.h>
52 
53 #include <asm/io.h>
54 #include <asm/dma.h>
55 #include <asm/uaccess.h>
56 
57 static const char version[] = "DLCI driver v0.35, 4 Jan 1997, [email protected]";
58 
59 static LIST_HEAD(dlci_devs);
60 
61 static void dlci_setup(struct net_device *);
62 
63 /*
64  * these encapsulate the RFC 1490 requirements as well as
65  * deal with packet transmission and reception, working with
66  * the upper network layers
67  */
68 
69 static int dlci_header(struct sk_buff *skb, struct net_device *dev,
70  unsigned short type, const void *daddr,
71  const void *saddr, unsigned len)
72 {
73  struct frhdr hdr;
74  struct dlci_local *dlp;
75  unsigned int hlen;
76  char *dest;
77 
78  dlp = netdev_priv(dev);
79 
80  hdr.control = FRAD_I_UI;
81  switch (type)
82  {
83  case ETH_P_IP:
84  hdr.IP_NLPID = FRAD_P_IP;
85  hlen = sizeof(hdr.control) + sizeof(hdr.IP_NLPID);
86  break;
87 
88  /* feel free to add other types, if necessary */
89 
90  default:
91  hdr.pad = FRAD_P_PADDING;
92  hdr.NLPID = FRAD_P_SNAP;
93  memset(hdr.OUI, 0, sizeof(hdr.OUI));
94  hdr.PID = htons(type);
95  hlen = sizeof(hdr);
96  break;
97  }
98 
99  dest = skb_push(skb, hlen);
100  if (!dest)
101  return 0;
102 
103  memcpy(dest, &hdr, hlen);
104 
105  return hlen;
106 }
107 
108 static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
109 {
110  struct dlci_local *dlp;
111  struct frhdr *hdr;
112  int process, header;
113 
114  dlp = netdev_priv(dev);
115  if (!pskb_may_pull(skb, sizeof(*hdr))) {
116  netdev_notice(dev, "invalid data no header\n");
117  dev->stats.rx_errors++;
118  kfree_skb(skb);
119  return;
120  }
121 
122  hdr = (struct frhdr *) skb->data;
123  process = 0;
124  header = 0;
125  skb->dev = dev;
126 
127  if (hdr->control != FRAD_I_UI)
128  {
129  netdev_notice(dev, "Invalid header flag 0x%02X\n",
130  hdr->control);
131  dev->stats.rx_errors++;
132  }
133  else
134  switch (hdr->IP_NLPID)
135  {
136  case FRAD_P_PADDING:
137  if (hdr->NLPID != FRAD_P_SNAP)
138  {
139  netdev_notice(dev, "Unsupported NLPID 0x%02X\n",
140  hdr->NLPID);
141  dev->stats.rx_errors++;
142  break;
143  }
144 
145  if (hdr->OUI[0] + hdr->OUI[1] + hdr->OUI[2] != 0)
146  {
147  netdev_notice(dev, "Unsupported organizationally unique identifier 0x%02X-%02X-%02X\n",
148  hdr->OUI[0],
149  hdr->OUI[1],
150  hdr->OUI[2]);
151  dev->stats.rx_errors++;
152  break;
153  }
154 
155  /* at this point, it's an EtherType frame */
156  header = sizeof(struct frhdr);
157  /* Already in network order ! */
158  skb->protocol = hdr->PID;
159  process = 1;
160  break;
161 
162  case FRAD_P_IP:
163  header = sizeof(hdr->control) + sizeof(hdr->IP_NLPID);
164  skb->protocol = htons(ETH_P_IP);
165  process = 1;
166  break;
167 
168  case FRAD_P_SNAP:
169  case FRAD_P_Q933:
170  case FRAD_P_CLNP:
171  netdev_notice(dev, "Unsupported NLPID 0x%02X\n",
172  hdr->pad);
173  dev->stats.rx_errors++;
174  break;
175 
176  default:
177  netdev_notice(dev, "Invalid pad byte 0x%02X\n",
178  hdr->pad);
179  dev->stats.rx_errors++;
180  break;
181  }
182 
183  if (process)
184  {
185  /* we've set up the protocol, so discard the header */
186  skb_reset_mac_header(skb);
187  skb_pull(skb, header);
188  dev->stats.rx_bytes += skb->len;
189  netif_rx(skb);
190  dev->stats.rx_packets++;
191  }
192  else
193  dev_kfree_skb(skb);
194 }
195 
196 static netdev_tx_t dlci_transmit(struct sk_buff *skb, struct net_device *dev)
197 {
198  struct dlci_local *dlp = netdev_priv(dev);
199 
200  if (skb)
201  dlp->slave->netdev_ops->ndo_start_xmit(skb, dlp->slave);
202  return NETDEV_TX_OK;
203 }
204 
205 static int dlci_config(struct net_device *dev, struct dlci_conf __user *conf, int get)
206 {
207  struct dlci_conf config;
208  struct dlci_local *dlp;
209  struct frad_local *flp;
210  int err;
211 
212  dlp = netdev_priv(dev);
213 
214  flp = netdev_priv(dlp->slave);
215 
216  if (!get)
217  {
218  if (copy_from_user(&config, conf, sizeof(struct dlci_conf)))
219  return -EFAULT;
220  if (config.flags & ~DLCI_VALID_FLAGS)
221  return -EINVAL;
222  memcpy(&dlp->config, &config, sizeof(struct dlci_conf));
223  dlp->configured = 1;
224  }
225 
226  err = (*flp->dlci_conf)(dlp->slave, dev, get);
227  if (err)
228  return err;
229 
230  if (get)
231  {
232  if (copy_to_user(conf, &dlp->config, sizeof(struct dlci_conf)))
233  return -EFAULT;
234  }
235 
236  return 0;
237 }
238 
239 static int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
240 {
241  struct dlci_local *dlp;
242 
243  if (!capable(CAP_NET_ADMIN))
244  return -EPERM;
245 
246  dlp = netdev_priv(dev);
247 
248  switch (cmd)
249  {
250  case DLCI_GET_SLAVE:
251  if (!*(short *)(dev->dev_addr))
252  return -EINVAL;
253 
254  strncpy(ifr->ifr_slave, dlp->slave->name, sizeof(ifr->ifr_slave));
255  break;
256 
257  case DLCI_GET_CONF:
258  case DLCI_SET_CONF:
259  if (!*(short *)(dev->dev_addr))
260  return -EINVAL;
261 
262  return dlci_config(dev, ifr->ifr_data, cmd == DLCI_GET_CONF);
263  break;
264 
265  default:
266  return -EOPNOTSUPP;
267  }
268  return 0;
269 }
270 
271 static int dlci_change_mtu(struct net_device *dev, int new_mtu)
272 {
273  struct dlci_local *dlp = netdev_priv(dev);
274 
275  return dev_set_mtu(dlp->slave, new_mtu);
276 }
277 
278 static int dlci_open(struct net_device *dev)
279 {
280  struct dlci_local *dlp;
281  struct frad_local *flp;
282  int err;
283 
284  dlp = netdev_priv(dev);
285 
286  if (!*(short *)(dev->dev_addr))
287  return -EINVAL;
288 
289  if (!netif_running(dlp->slave))
290  return -ENOTCONN;
291 
292  flp = netdev_priv(dlp->slave);
293  err = (*flp->activate)(dlp->slave, dev);
294  if (err)
295  return err;
296 
297  netif_start_queue(dev);
298 
299  return 0;
300 }
301 
302 static int dlci_close(struct net_device *dev)
303 {
304  struct dlci_local *dlp;
305  struct frad_local *flp;
306  int err;
307 
308  netif_stop_queue(dev);
309 
310  dlp = netdev_priv(dev);
311 
312  flp = netdev_priv(dlp->slave);
313  err = (*flp->deactivate)(dlp->slave, dev);
314 
315  return 0;
316 }
317 
318 static int dlci_add(struct dlci_add *dlci)
319 {
320  struct net_device *master, *slave;
321  struct dlci_local *dlp;
322  struct frad_local *flp;
323  int err = -EINVAL;
324 
325 
326  /* validate slave device */
327  slave = dev_get_by_name(&init_net, dlci->devname);
328  if (!slave)
329  return -ENODEV;
330 
331  if (slave->type != ARPHRD_FRAD || netdev_priv(slave) == NULL)
332  goto err1;
333 
334  /* create device name */
335  master = alloc_netdev( sizeof(struct dlci_local), "dlci%d",
336  dlci_setup);
337  if (!master) {
338  err = -ENOMEM;
339  goto err1;
340  }
341 
342  /* make sure same slave not already registered */
343  rtnl_lock();
344  list_for_each_entry(dlp, &dlci_devs, list) {
345  if (dlp->slave == slave) {
346  err = -EBUSY;
347  goto err2;
348  }
349  }
350 
351  *(short *)(master->dev_addr) = dlci->dlci;
352 
353  dlp = netdev_priv(master);
354  dlp->slave = slave;
355  dlp->master = master;
356 
357  flp = netdev_priv(slave);
358  err = (*flp->assoc)(slave, master);
359  if (err < 0)
360  goto err2;
361 
362  err = register_netdevice(master);
363  if (err < 0)
364  goto err2;
365 
366  strcpy(dlci->devname, master->name);
367 
368  list_add(&dlp->list, &dlci_devs);
369  rtnl_unlock();
370 
371  return 0;
372 
373  err2:
374  rtnl_unlock();
375  free_netdev(master);
376  err1:
377  dev_put(slave);
378  return err;
379 }
380 
381 static int dlci_del(struct dlci_add *dlci)
382 {
383  struct dlci_local *dlp;
384  struct frad_local *flp;
385  struct net_device *master, *slave;
386  int err;
387 
388  /* validate slave device */
389  master = __dev_get_by_name(&init_net, dlci->devname);
390  if (!master)
391  return -ENODEV;
392 
393  if (netif_running(master)) {
394  return -EBUSY;
395  }
396 
397  dlp = netdev_priv(master);
398  slave = dlp->slave;
399  flp = netdev_priv(slave);
400 
401  rtnl_lock();
402  err = (*flp->deassoc)(slave, master);
403  if (!err) {
404  list_del(&dlp->list);
405 
406  unregister_netdevice(master);
407 
408  dev_put(slave);
409  }
410  rtnl_unlock();
411 
412  return err;
413 }
414 
415 static int dlci_ioctl(unsigned int cmd, void __user *arg)
416 {
417  struct dlci_add add;
418  int err;
419 
420  if (!capable(CAP_NET_ADMIN))
421  return -EPERM;
422 
423  if (copy_from_user(&add, arg, sizeof(struct dlci_add)))
424  return -EFAULT;
425 
426  switch (cmd)
427  {
428  case SIOCADDDLCI:
429  err = dlci_add(&add);
430 
431  if (!err)
432  if (copy_to_user(arg, &add, sizeof(struct dlci_add)))
433  return -EFAULT;
434  break;
435 
436  case SIOCDELDLCI:
437  err = dlci_del(&add);
438  break;
439 
440  default:
441  err = -EINVAL;
442  }
443 
444  return err;
445 }
446 
447 static const struct header_ops dlci_header_ops = {
448  .create = dlci_header,
449 };
450 
451 static const struct net_device_ops dlci_netdev_ops = {
452  .ndo_open = dlci_open,
453  .ndo_stop = dlci_close,
454  .ndo_do_ioctl = dlci_dev_ioctl,
455  .ndo_start_xmit = dlci_transmit,
456  .ndo_change_mtu = dlci_change_mtu,
457 };
458 
459 static void dlci_setup(struct net_device *dev)
460 {
461  struct dlci_local *dlp = netdev_priv(dev);
462 
463  dev->flags = 0;
464  dev->header_ops = &dlci_header_ops;
465  dev->netdev_ops = &dlci_netdev_ops;
466  dev->destructor = free_netdev;
467 
468  dlp->receive = dlci_receive;
469 
470  dev->type = ARPHRD_DLCI;
471  dev->hard_header_len = sizeof(struct frhdr);
472  dev->addr_len = sizeof(short);
473 
474 }
475 
476 /* if slave is unregistering, then cleanup master */
477 static int dlci_dev_event(struct notifier_block *unused,
478  unsigned long event, void *ptr)
479 {
480  struct net_device *dev = (struct net_device *) ptr;
481 
482  if (dev_net(dev) != &init_net)
483  return NOTIFY_DONE;
484 
485  if (event == NETDEV_UNREGISTER) {
486  struct dlci_local *dlp;
487 
488  list_for_each_entry(dlp, &dlci_devs, list) {
489  if (dlp->slave == dev) {
490  list_del(&dlp->list);
491  unregister_netdevice(dlp->master);
492  dev_put(dlp->slave);
493  break;
494  }
495  }
496  }
497  return NOTIFY_DONE;
498 }
499 
500 static struct notifier_block dlci_notifier = {
501  .notifier_call = dlci_dev_event,
502 };
503 
504 static int __init init_dlci(void)
505 {
506  dlci_ioctl_set(dlci_ioctl);
507  register_netdevice_notifier(&dlci_notifier);
508 
509  printk("%s.\n", version);
510 
511  return 0;
512 }
513 
514 static void __exit dlci_exit(void)
515 {
516  struct dlci_local *dlp, *nxt;
517 
519  unregister_netdevice_notifier(&dlci_notifier);
520 
521  rtnl_lock();
522  list_for_each_entry_safe(dlp, nxt, &dlci_devs, list) {
523  unregister_netdevice(dlp->master);
524  dev_put(dlp->slave);
525  }
526  rtnl_unlock();
527 }
528 
529 module_init(init_dlci);
530 module_exit(dlci_exit);
531 
532 MODULE_AUTHOR("Mike McLagan");
533 MODULE_DESCRIPTION("Frame Relay DLCI layer");
534 MODULE_LICENSE("GPL");