Import 2.1.37pre7
[davej-history.git] / drivers / net / dlci.c
blob08d9901ba210554ef2321e3df2f1c8cfe92dabdd
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.
8 * Version: @(#)dlci.c 0.35 4 Jan 1997
10 * Author: Mike McLagan <mike.mclagan@linux.org>
12 * Changes:
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 whic 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
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.
31 #include <linux/module.h>
33 #include <linux/kernel.h>
34 #include <linux/sched.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/malloc.h>
42 #include <linux/string.h>
43 #include <linux/init.h>
44 #include <asm/system.h>
45 #include <asm/bitops.h>
46 #include <asm/io.h>
47 #include <asm/dma.h>
48 #include <asm/uaccess.h>
50 #include <linux/errno.h>
52 #include <linux/netdevice.h>
53 #include <linux/skbuff.h>
54 #include <linux/if_arp.h>
55 #include <linux/if_frad.h>
57 #include <net/sock.h>
59 static const char *devname = "dlci";
60 static const char *version = "DLCI driver v0.35, 4 Jan 1997, mike.mclagan@linux.org";
62 static struct device *open_dev[CONFIG_DLCI_COUNT];
64 static char *basename[16];
66 int dlci_init(struct device *dev);
68 /* allow FRAD's to register their name as a valid FRAD */
69 int register_frad(const char *name)
71 int i;
73 if (!name)
74 return(-EINVAL);
76 for (i=0;i<sizeof(basename) / sizeof(char *);i++)
78 if (!basename[i])
79 break;
81 /* take care of multiple registrations */
82 if (strcmp(basename[i], name) == 0)
83 return(0);
86 if (i == sizeof(basename) / sizeof(char *))
87 return(-EMLINK);
89 basename[i] = kmalloc(strlen(name) + 1, GFP_KERNEL);
90 if (!basename[i])
91 return(-ENOMEM);
93 strcpy(basename[i], name);
95 return(0);
98 int unregister_frad(const char *name)
100 int i;
102 if (!name)
103 return(-EINVAL);
105 for (i=0;i<sizeof(basename) / sizeof(char *);i++)
106 if (basename[i] && (strcmp(basename[i], name) == 0))
107 break;
109 if (i == sizeof(basename) / sizeof(char *))
110 return(-EINVAL);
112 kfree(basename[i]);
113 basename[i] = NULL;
115 return(0);
119 * these encapsulate the RFC 1490 requirements as well as
120 * deal with packet transmission and reception, working with
121 * the upper network layers
124 static int dlci_header(struct sk_buff *skb, struct device *dev,
125 unsigned short type, void *daddr, void *saddr,
126 unsigned len)
128 struct frhdr hdr;
129 struct dlci_local *dlp;
130 unsigned int hlen;
131 char *dest;
133 dlp = dev->priv;
135 hdr.control = FRAD_I_UI;
136 switch(type)
138 case ETH_P_IP:
139 hdr.IP_NLPID = FRAD_P_IP;
140 hlen = sizeof(hdr.control) + sizeof(hdr.IP_NLPID);
141 break;
143 /* feel free to add other types, if necessary */
145 default:
146 hdr.pad = FRAD_P_PADDING;
147 hdr.NLPID = FRAD_P_SNAP;
148 memset(hdr.OUI, 0, sizeof(hdr.OUI));
149 hdr.PID = htons(type);
150 hlen = sizeof(hdr);
151 break;
154 dest = skb_push(skb, hlen);
155 if (!dest)
156 return(0);
158 memcpy(dest, &hdr, hlen);
160 return(hlen);
163 static void dlci_receive(struct sk_buff *skb, struct device *dev)
165 struct dlci_local *dlp;
166 struct frhdr *hdr;
167 int process, header;
169 dlp = dev->priv;
170 hdr = (struct frhdr *) skb->data;
171 process = 0;
172 header = 0;
173 skb->dev = dev;
175 if (hdr->control != FRAD_I_UI)
177 printk(KERN_NOTICE "%s: Invalid header flag 0x%02X.\n", dev->name, hdr->control);
178 dlp->stats.rx_errors++;
180 else
181 switch(hdr->IP_NLPID)
183 case FRAD_P_PADDING:
184 if (hdr->NLPID != FRAD_P_SNAP)
186 printk(KERN_NOTICE "%s: Unsupported NLPID 0x%02X.\n", dev->name, hdr->NLPID);
187 dlp->stats.rx_errors++;
188 break;
191 if (hdr->OUI[0] + hdr->OUI[1] + hdr->OUI[2] != 0)
193 printk(KERN_NOTICE "%s: Unsupported organizationally unique identifier 0x%02X-%02X-%02X.\n", dev->name, hdr->OUI[0], hdr->OUI[1], hdr->OUI[2]);
194 dlp->stats.rx_errors++;
195 break;
198 /* at this point, it's an EtherType frame */
199 header = sizeof(struct frhdr);
200 /* Already in network order ! */
201 skb->protocol = hdr->PID;
202 process = 1;
203 break;
205 case FRAD_P_IP:
206 header = sizeof(hdr->control) + sizeof(hdr->IP_NLPID);
207 skb->protocol = htons(ETH_P_IP);
208 process = 1;
209 break;
211 case FRAD_P_SNAP:
212 case FRAD_P_Q933:
213 case FRAD_P_CLNP:
214 printk(KERN_NOTICE "%s: Unsupported NLPID 0x%02X.\n", dev->name, hdr->pad);
215 dlp->stats.rx_errors++;
216 break;
218 default:
219 printk(KERN_NOTICE "%s: Invalid pad byte 0x%02X.\n", dev->name, hdr->pad);
220 dlp->stats.rx_errors++;
221 break;
224 if (process)
226 /* we've set up the protocol, so discard the header */
227 skb->mac.raw = skb->data;
228 skb_pull(skb, header);
229 netif_rx(skb);
230 dlp->stats.rx_packets++;
232 else
233 dev_kfree_skb(skb, FREE_WRITE);
236 static int dlci_transmit(struct sk_buff *skb, struct device *dev)
238 struct dlci_local *dlp;
239 int ret;
241 ret = 0;
243 if (!skb || !dev)
244 return(0);
246 if (dev->tbusy)
247 return(1);
249 dlp = dev->priv;
251 if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
252 printk(KERN_WARNING "%s: transmitter access conflict.\n", dev->name);
253 else
255 ret = dlp->slave->hard_start_xmit(skb, dlp->slave);
256 switch (ret)
258 case DLCI_RET_OK:
259 dlp->stats.tx_packets++;
260 ret = 0;
261 break;
263 case DLCI_RET_ERR:
264 dlp->stats.tx_errors++;
265 ret = 0;
266 break;
268 case DLCI_RET_DROP:
269 dlp->stats.tx_dropped++;
270 ret = 1;
271 break;
274 /* Alan Cox recommends always returning 0, and always freeing the packet */
275 /* experience suggest a slightly more conservative approach */
277 if (!ret)
278 dev_kfree_skb(skb, FREE_WRITE);
280 dev->tbusy = 0;
283 return(ret);
286 int dlci_config(struct device *dev, struct dlci_conf *conf, int get)
288 struct dlci_conf config;
289 struct dlci_local *dlp;
290 struct frad_local *flp;
291 int err;
293 dlp = dev->priv;
295 flp = dlp->slave->priv;
297 if (!get)
299 if(copy_from_user(&config, conf, sizeof(struct dlci_conf)))
300 return -EFAULT;
301 if (config.flags & ~DLCI_VALID_FLAGS)
302 return(-EINVAL);
303 memcpy(&dlp->config, &config, sizeof(struct dlci_conf));
304 dlp->configured = 1;
307 err = (*flp->dlci_conf)(dlp->slave, dev, get);
308 if (err)
309 return(err);
311 if (get)
313 if(copy_to_user(conf, &dlp->config, sizeof(struct dlci_conf)))
314 return -EFAULT;
317 return(0);
320 int dlci_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
322 struct dlci_local *dlp;
324 if (!suser())
325 return(-EPERM);
327 dlp = dev->priv;
329 switch(cmd)
331 case DLCI_GET_SLAVE:
332 if (!*(short *)(dev->dev_addr))
333 return(-EINVAL);
335 strncpy(ifr->ifr_slave, dlp->slave->name, sizeof(ifr->ifr_slave));
336 break;
338 case DLCI_GET_CONF:
339 case DLCI_SET_CONF:
340 if (!*(short *)(dev->dev_addr))
341 return(-EINVAL);
343 return(dlci_config(dev, (struct dlci_conf *) ifr->ifr_data, cmd == DLCI_GET_CONF));
344 break;
346 default:
347 return(-EOPNOTSUPP);
349 return(0);
352 static int dlci_change_mtu(struct device *dev, int new_mtu)
354 struct dlci_local *dlp;
356 dlp = dev->priv;
358 return((*dlp->slave->change_mtu)(dlp->slave, new_mtu));
361 static int dlci_open(struct device *dev)
363 struct dlci_local *dlp;
364 struct frad_local *flp;
365 int err;
367 dlp = dev->priv;
369 if (!*(short *)(dev->dev_addr))
370 return(-EINVAL);
372 if (!dlp->slave->start)
373 return(-ENOTCONN);
375 dev->flags = 0;
376 dev->tbusy = 0;
377 dev->interrupt = 0;
378 dev->start = 1;
380 flp = dlp->slave->priv;
381 err = (*flp->activate)(dlp->slave, dev);
382 if (err)
383 return(err);
385 return 0;
388 static int dlci_close(struct device *dev)
390 struct dlci_local *dlp;
391 struct frad_local *flp;
392 int err;
394 dlp = dev->priv;
396 flp = dlp->slave->priv;
397 err = (*flp->deactivate)(dlp->slave, dev);
399 dev->start = 0;
400 dev->tbusy = 1;
402 return 0;
405 static struct net_device_stats *dlci_get_stats(struct device *dev)
407 struct dlci_local *dlp;
409 dlp = dev->priv;
411 return(&dlp->stats);
414 int dlci_add(struct dlci_add *dlci)
416 struct device *master, *slave;
417 struct dlci_local *dlp;
418 struct frad_local *flp;
419 int err, i;
420 char buf[10];
422 /* validate slave device */
423 slave = dev_get(dlci->devname);
424 if (!slave)
425 return(-ENODEV);
427 if (slave->type != ARPHRD_FRAD)
428 return(-EINVAL);
430 /* check for registration */
431 for (i=0;i<sizeof(basename) / sizeof(char *); i++)
432 if ((basename[i]) &&
433 (strncmp(dlci->devname, basename[i], strlen(basename[i])) == 0) &&
434 (strlen(dlci->devname) > strlen(basename[i])))
435 break;
437 if (i == sizeof(basename) / sizeof(char *))
438 return(-EINVAL);
440 /* check for too many open devices : should this be dynamic ? */
441 for(i=0;i<CONFIG_DLCI_COUNT;i++)
442 if (!open_dev[i])
443 break;
445 if (i == CONFIG_DLCI_COUNT)
446 return(-ENOSPC); /* #### Alan: Comments on this?? */
448 /* create device name */
449 sprintf(buf, "%s%02i", devname, i);
451 master = kmalloc(sizeof(*master), GFP_KERNEL);
452 if (!master)
453 return(-ENOMEM);
455 memset(master, 0, sizeof(*master));
456 master->name = kmalloc(strlen(buf) + 1, GFP_KERNEL);
458 if (!master->name)
460 kfree(master);
461 return(-ENOMEM);
464 strcpy(master->name, buf);
465 master->init = dlci_init;
466 master->flags = 0;
468 err = register_netdev(master);
469 if (err < 0)
471 kfree(master->name);
472 kfree(master);
473 return(err);
476 *(short *)(master->dev_addr) = dlci->dlci;
478 dlp = (struct dlci_local *) master->priv;
479 dlp->slave = slave;
481 flp = slave->priv;
482 err = flp ? (*flp->assoc)(slave, master) : -EINVAL;
483 if (err < 0)
485 unregister_netdev(master);
486 kfree(master->priv);
487 kfree(master->name);
488 kfree(master);
489 return(err);
492 strcpy(dlci->devname, buf);
493 open_dev[i] = master;
494 MOD_INC_USE_COUNT;
495 return(0);
498 int dlci_del(struct dlci_add *dlci)
500 struct dlci_local *dlp;
501 struct frad_local *flp;
502 struct device *master, *slave;
503 int i, err;
505 /* validate slave device */
506 master = dev_get(dlci->devname);
507 if (!master)
508 return(-ENODEV);
510 if (master->start)
511 return(-EBUSY);
513 dlp = master->priv;
514 slave = dlp->slave;
515 flp = slave->priv;
517 err = (*flp->deassoc)(slave, master);
518 if (err)
519 return(err);
521 unregister_netdev(master);
523 for(i=0;i<CONFIG_DLCI_COUNT;i++)
524 if (master == open_dev[i])
525 break;
527 if (i<CONFIG_DLCI_COUNT)
528 open_dev[i] = NULL;
530 kfree(master->priv);
531 kfree(master->name);
532 kfree(master);
534 MOD_DEC_USE_COUNT;
536 return(0);
539 int dlci_ioctl(unsigned int cmd, void *arg)
541 struct dlci_add add;
542 int err;
544 if (!suser())
545 return(-EPERM);
547 if(copy_from_user(&add, arg, sizeof(struct dlci_add)))
548 return -EFAULT;
550 switch (cmd)
552 case SIOCADDDLCI:
553 err = dlci_add(&add);
555 if (!err)
556 if(copy_to_user(arg, &add, sizeof(struct dlci_add)))
557 return -EFAULT;
558 break;
560 case SIOCDELDLCI:
561 err = dlci_del(&add);
562 break;
564 default:
565 err = -EINVAL;
568 return(err);
571 int dlci_init(struct device *dev)
573 struct dlci_local *dlp;
575 dev->priv = kmalloc(sizeof(struct dlci_local), GFP_KERNEL);
576 if (!dev->priv)
577 return(-ENOMEM);
579 memset(dev->priv, 0, sizeof(struct dlci_local));
580 dlp = dev->priv;
582 dev->flags = 0;
583 dev->open = dlci_open;
584 dev->stop = dlci_close;
585 dev->do_ioctl = dlci_dev_ioctl;
586 dev->hard_start_xmit = dlci_transmit;
587 dev->hard_header = dlci_header;
588 dev->get_stats = dlci_get_stats;
589 dev->change_mtu = dlci_change_mtu;
591 dlp->receive = dlci_receive;
593 dev->type = ARPHRD_DLCI;
594 dev->family = AF_INET;
595 dev->hard_header_len = sizeof(struct frhdr);
596 dev->pa_alen = 4;
597 dev->addr_len = sizeof(short);
598 memset(dev->dev_addr, 0, sizeof(dev->dev_addr));
600 dev->pa_addr = 0;
601 dev->pa_dstaddr = 0;
602 dev->pa_brdaddr = 0;
603 dev->pa_mask = 0;
605 dev_init_buffers(dev);
607 return(0);
610 __initfunc(int dlci_setup(void))
612 int i;
614 printk("%s.\n", version);
616 for(i=0;i<CONFIG_DLCI_COUNT;i++)
617 open_dev[i] = NULL;
619 for(i=0;i<sizeof(basename) / sizeof(char *);i++)
620 basename[i] = NULL;
622 return(0);
625 #ifdef MODULE
627 extern int (*dlci_ioctl_hook)(unsigned int, void *);
629 int init_module(void)
631 dlci_ioctl_hook = dlci_ioctl;
633 return(dlci_setup());
636 void cleanup_module(void)
638 dlci_ioctl_hook = NULL;
640 #endif /* MODULE */