This source file includes following definitions.
- register_frad
- unregister_frad
- dlci_header
- dlci_receive
- dlci_transmit
- dlci_add
- dlci_del
- dlci_config
- dlci_ioctl
- dlci_change_mtu
- dlci_open
- dlci_close
- dlci_get_stats
- dlci_init
- dlci_setup
- init_module
- cleanup_module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include <linux/module.h>
30
31 #include <linux/kernel.h>
32 #include <linux/sched.h>
33 #include <linux/types.h>
34 #include <linux/fcntl.h>
35 #include <linux/interrupt.h>
36 #include <linux/ptrace.h>
37 #include <linux/ioport.h>
38 #include <linux/in.h>
39 #include <linux/malloc.h>
40 #include <linux/string.h>
41 #include <asm/system.h>
42 #include <asm/bitops.h>
43 #include <asm/io.h>
44 #include <asm/dma.h>
45 #include <linux/errno.h>
46
47 #include <linux/netdevice.h>
48 #include <linux/skbuff.h>
49 #include <linux/if_arp.h>
50 #include <linux/if_frad.h>
51
52 #include <net/sock.h>
53
54 static const char *devname = "dlci";
55 static const char *version = "DLCI driver v0.20, 13 Apr 1996, mike.mclagan@linux.org";
56
57 static struct device *open_dev[CONFIG_DLCI_COUNT];
58
59 static char *basename[16];
60
61 int dlci_init(struct device *dev);
62
63
64 int register_frad(const char *name)
65 {
66 int i;
67
68 if (!name)
69 return(-EINVAL);
70
71 for (i=0;i<sizeof(basename) / sizeof(char *);i++)
72 {
73 if (!basename[i])
74 break;
75
76
77 if (strcmp(basename[i], name) == 0)
78 return(0);
79 }
80
81 if (i == sizeof(basename) / sizeof(char *))
82 return(-EMLINK);
83
84 basename[i] = kmalloc(strlen(name) + 1, GFP_KERNEL);
85 if (!basename[i])
86 return(-ENOMEM);
87
88 strcpy(basename[i], name);
89
90 return(0);
91 }
92
93 int unregister_frad(const char *name)
94 {
95 int i;
96
97 if (!name)
98 return(-EINVAL);
99
100 for (i=0;i<sizeof(basename) / sizeof(char *);i++)
101 if (basename[i] && (strcmp(basename[i], name) == 0))
102 break;
103
104 if (i == sizeof(basename) / sizeof(char *))
105 return(-EINVAL);
106
107 kfree(basename[i]);
108 basename[i] = NULL;
109
110 return(0);
111 }
112
113
114
115
116
117
118
119 static int dlci_header(struct sk_buff *skb, struct device *dev,
120 unsigned short type, void *daddr, void *saddr,
121 unsigned len)
122 {
123 struct frhdr hdr;
124 struct dlci_local *dlp;
125 unsigned hlen;
126 char *dest;
127
128 dlp = dev->priv;
129
130 hdr.control = FRAD_I_UI;
131 switch(type)
132 {
133 case ETH_P_IP:
134 hdr.IP_NLPID = FRAD_P_IP;
135 hlen = sizeof(hdr.control) + sizeof(hdr.IP_NLPID);
136 break;
137
138
139
140 default:
141 hdr.pad = FRAD_P_PADDING;
142 hdr.NLPID = FRAD_P_SNAP;
143 memset(hdr.OUI, 0, sizeof(hdr.OUI));
144 hdr.PID = type;
145 hlen = sizeof(hdr);
146 break;
147 }
148
149 dest = skb_push(skb, hlen);
150 if (!dest)
151 return(0);
152
153 memcpy(dest, &hdr, hlen);
154
155 return(hlen);
156 }
157
158 static void dlci_receive(struct sk_buff *skb, struct device *dev)
159 {
160 struct dlci_local *dlp;
161 struct frhdr *hdr;
162 int process, header;
163
164 dlp = dev->priv;
165 hdr = (struct frhdr *) skb->data;
166 process = 0;
167 header = 0;
168 skb->dev = dev;
169
170 if (hdr->control != FRAD_I_UI)
171 {
172 printk(KERN_NOTICE "%s: Invalid header flag 0x%02X.\n", dev->name, hdr->control);
173 dlp->stats.rx_errors++;
174 }
175 else
176 switch(hdr->IP_NLPID)
177 {
178 case FRAD_P_PADDING:
179 if (hdr->NLPID != FRAD_P_SNAP)
180 {
181 printk(KERN_NOTICE "%s: Unsupported NLPID 0x%02X.\n", dev->name, hdr->NLPID);
182 dlp->stats.rx_errors++;
183 break;
184 }
185
186 if (hdr->OUI[0] + hdr->OUI[1] + hdr->OUI[2] != 0)
187 {
188 printk(KERN_NOTICE "%s: Unsupported organizationally unique identifier 0x%02X-%02X-%02X.\n", dev->name, hdr->OUI[0], hdr->OUI[1], hdr->OUI[2]);
189 dlp->stats.rx_errors++;
190 break;
191 }
192
193
194 header = sizeof(struct frhdr);
195 skb->protocol = htons(hdr->PID);
196 process = 1;
197 break;
198
199 case FRAD_P_IP:
200 header = sizeof(hdr->control) + sizeof(hdr->IP_NLPID);
201 skb->protocol = htons(ETH_P_IP);
202 process = 1;
203 break;
204
205 case FRAD_P_SNAP:
206 case FRAD_P_Q933:
207 case FRAD_P_CLNP:
208 printk(KERN_NOTICE "%s: Unsupported NLPID 0x%02X.\n", dev->name, hdr->pad);
209 dlp->stats.rx_errors++;
210 break;
211
212 default:
213 printk(KERN_NOTICE "%s: Invalid pad byte 0x%02X.\n", dev->name, hdr->pad);
214 dlp->stats.rx_errors++;
215 break;
216 }
217
218 if (process)
219 {
220
221 skb->mac.raw = skb->data;
222 skb_pull(skb, header);
223 netif_rx(skb);
224 dlp->stats.rx_packets++;
225 }
226 else
227 dev_kfree_skb(skb, FREE_WRITE);
228 }
229
230 static int dlci_transmit(struct sk_buff *skb, struct device *dev)
231 {
232 struct dlci_local *dlp;
233 int ret;
234
235 ret = 0;
236
237 if (!skb || !dev)
238 return(0);
239
240 if (dev->tbusy)
241 return(1);
242
243 dlp = dev->priv;
244
245 if (set_bit(0, (void*)&dev->tbusy) != 0)
246 printk(KERN_WARNING "%s: transmitter access conflict.\n", dev->name);
247 else
248 {
249 ret = dlp->slave->hard_start_xmit(skb, dlp->slave);
250 switch (ret)
251 {
252 case DLCI_RET_OK:
253 dlp->stats.tx_packets++;
254 ret = 0;
255 break;
256
257 case DLCI_RET_ERR:
258 dlp->stats.tx_errors++;
259 ret = 0;
260 break;
261
262 case DLCI_RET_DROP:
263 dlp->stats.tx_dropped++;
264 ret = 1;
265 break;
266 }
267
268
269
270
271 if (!ret)
272 dev_kfree_skb(skb, FREE_WRITE);
273
274 dev->tbusy = 0;
275 }
276
277 return(ret);
278 }
279
280 int dlci_add(struct dlci_add *new)
281 {
282 struct device *master, *slave;
283 struct dlci_local *dlp;
284 struct frad_local *flp;
285 struct dlci_add dlci;
286 int err, i;
287 char buf[10];
288
289 err = verify_area(VERIFY_READ, new, sizeof(*new));
290 if (err)
291 return(err);
292
293 err = verify_area(VERIFY_WRITE, new, sizeof(*new));
294 if (err)
295 return(err);
296
297 memcpy_fromfs(&dlci, new, sizeof(dlci));
298
299
300 slave = dev_get(dlci.devname);
301 if (!slave)
302 return(-ENODEV);
303
304 if (slave->type != ARPHRD_FRAD)
305 return(-EINVAL);
306
307
308 for (i=0;i<sizeof(basename) / sizeof(char *); i++)
309 if ((basename[i]) &&
310 (strncmp(dlci.devname, basename[i], strlen(basename[i])) == 0) &&
311 (strlen(dlci.devname) > strlen(basename[i])))
312 break;
313
314 if (i == sizeof(basename) / sizeof(char *))
315 return(-EINVAL);
316
317
318 for(i=0;i<CONFIG_DLCI_COUNT;i++)
319 if (!open_dev[i])
320 break;
321
322 if (i == CONFIG_DLCI_COUNT)
323 return(-ENOSPC);
324
325
326 sprintf(buf, "%s%02i", devname, i);
327
328 master = kmalloc(sizeof(*master), GFP_KERNEL);
329 if (!master)
330 return(-ENOMEM);
331
332 memset(master, 0, sizeof(*master));
333 master->name = kmalloc(strlen(buf) + 1, GFP_KERNEL);
334
335 if (!master->name)
336 {
337 kfree(master);
338 return(-ENOMEM);
339 }
340
341 strcpy(master->name, buf);
342 master->init = dlci_init;
343 master->flags = 0;
344
345 err = register_netdev(master);
346 if (err < 0)
347 {
348 kfree(master->name);
349 kfree(master);
350 return(err);
351 }
352
353 *(short *)(master->dev_addr) = dlci.dlci;
354
355 dlp = (struct dlci_local *) master->priv;
356 dlp->slave = slave;
357
358 flp = slave->priv;
359 err = flp ? (*flp->assoc)(slave, master) : -EINVAL;
360 if (err < 0)
361 {
362 unregister_netdev(master);
363 kfree(master->priv);
364 kfree(master->name);
365 kfree(master);
366 return(err);
367 }
368
369 memcpy_tofs(new->devname, buf, strlen(buf) + 1);
370 open_dev[i] = master;
371
372 MOD_INC_USE_COUNT;
373
374 return(0);
375 }
376
377 int dlci_del(struct device *master)
378 {
379 struct dlci_local *dlp;
380 struct frad_local *flp;
381 struct device *slave;
382 int i, err;
383
384 if (master->start)
385 return(-EBUSY);
386
387 dlp = master->priv;
388 slave = dlp->slave;
389 flp = slave->priv;
390
391 err = (*flp->deassoc)(slave, master);
392 if (err)
393 return(err);
394
395 unregister_netdev(master);
396
397 for(i=0;i<CONFIG_DLCI_COUNT;i++)
398 if (master == open_dev[i])
399 break;
400
401 if (i<CONFIG_DLCI_COUNT)
402 open_dev[i] = NULL;
403
404 kfree(master->priv);
405 kfree(master->name);
406 kfree(master);
407
408 MOD_DEC_USE_COUNT;
409
410 return(0);
411 }
412
413 int dlci_config(struct device *dev, struct dlci_conf *conf, int get)
414 {
415 struct dlci_conf config;
416 struct dlci_local *dlp;
417 struct frad_local *flp;
418 int err;
419
420 dlp = dev->priv;
421
422 flp = dlp->slave->priv;
423
424 if (!get)
425 {
426 err = verify_area(VERIFY_READ, conf, sizeof(struct dlci_conf));
427 if (err)
428 return(err);
429
430 memcpy_fromfs(&config, conf, sizeof(struct dlci_conf));
431 if (config.flags & ~DLCI_VALID_FLAGS)
432 return(-EINVAL);
433 memcpy(&dlp->config, &config, sizeof(struct dlci_conf));
434 dlp->configured = 1;
435 }
436
437 err = (*flp->dlci_conf)(dlp->slave, dev, get);
438 if (err)
439 return(err);
440
441 if (get)
442 {
443 err = verify_area(VERIFY_WRITE, conf, sizeof(struct dlci_conf));
444 if (err)
445 return(err);
446
447 memcpy_tofs(conf, &dlp->config, sizeof(struct dlci_conf));
448 }
449
450 return(0);
451 }
452
453 int dlci_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
454 {
455 struct dlci_local *dlp;
456
457 if (!suser())
458 return(-EPERM);
459
460 dlp = dev->priv;
461
462 switch(cmd)
463 {
464 case DLCI_GET_SLAVE:
465 if (!*(short *)(dev->dev_addr))
466 return(-EINVAL);
467
468 strcpy(ifr->ifr_slave, dlp->slave->name);
469 break;
470
471 case DLCI_DEVADD:
472
473 if (*(short *)(dev->dev_addr))
474 return(-EINVAL);
475
476 return(dlci_add((struct dlci_add *) ifr->ifr_data));
477 break;
478
479 case DLCI_DEVDEL:
480
481 if (!*(short *)(dev->dev_addr))
482 return(-EINVAL);
483
484 if (dev->start)
485 return(-EBUSY);
486
487 return(dlci_del(dev));
488 break;
489
490 case DLCI_GET_CONF:
491 case DLCI_SET_CONF:
492 if (!*(short *)(dev->dev_addr))
493 return(-EINVAL);
494
495 return(dlci_config(dev, (struct dlci_conf *) ifr->ifr_data, cmd == DLCI_GET_CONF));
496 break;
497
498 default:
499 return(-EOPNOTSUPP);
500 }
501 return(0);
502 }
503
504 static int dlci_change_mtu(struct device *dev, int new_mtu)
505 {
506 struct dlci_local *dlp;
507
508 dlp = dev->priv;
509
510 return((*dlp->slave->change_mtu)(dlp->slave, new_mtu));
511 }
512
513 static int dlci_open(struct device *dev)
514 {
515 struct dlci_local *dlp;
516 struct frad_local *flp;
517 int err;
518
519 dlp = dev->priv;
520
521 if (!*(short *)(dev->dev_addr))
522 return(-EINVAL);
523
524 if (!dlp->slave->start)
525 return(-ENOTCONN);
526
527 dev->flags = 0;
528 dev->tbusy = 0;
529 dev->interrupt = 0;
530 dev->start = 1;
531
532 flp = dlp->slave->priv;
533 err = (*flp->activate)(dlp->slave, dev);
534 if (err)
535 return(err);
536
537 return 0;
538 }
539
540 static int dlci_close(struct device *dev)
541 {
542 struct dlci_local *dlp;
543 struct frad_local *flp;
544 int err;
545
546 dlp = dev->priv;
547
548 flp = dlp->slave->priv;
549 err = (*flp->deactivate)(dlp->slave, dev);
550
551 dev->start = 0;
552 dev->tbusy = 1;
553
554 return 0;
555 }
556
557 static struct enet_statistics *dlci_get_stats(struct device *dev)
558 {
559 struct dlci_local *dlp;
560
561 dlp = dev->priv;
562
563 return(&dlp->stats);
564 }
565
566 int dlci_init(struct device *dev)
567 {
568 struct dlci_local *dlp;
569 int i;
570
571 dev->priv = kmalloc(sizeof(struct dlci_local), GFP_KERNEL);
572 if (!dev->priv)
573 return(-ENOMEM);
574
575 memset(dev->priv, 0, sizeof(struct dlci_local));
576 dlp = dev->priv;
577
578 dev->flags = 0;
579 dev->open = dlci_open;
580 dev->stop = dlci_close;
581 dev->do_ioctl = dlci_ioctl;
582 dev->hard_start_xmit = dlci_transmit;
583 dev->hard_header = dlci_header;
584 dev->get_stats = dlci_get_stats;
585 dev->change_mtu = dlci_change_mtu;
586
587 dlp->receive = dlci_receive;
588
589 dev->type = ARPHRD_DLCI;
590 dev->family = AF_INET;
591 dev->hard_header_len = sizeof(struct frhdr);
592 dev->pa_alen = sizeof(unsigned long);
593 dev->addr_len = sizeof(short);
594 memset(dev->dev_addr, 0, sizeof(dev->dev_addr));
595
596 dev->pa_addr = 0;
597 dev->pa_dstaddr = 0;
598 dev->pa_brdaddr = 0;
599 dev->pa_mask = 0;
600
601 for (i = 0; i < DEV_NUMBUFFS; i++)
602 skb_queue_head_init(&dev->buffs[i]);
603
604 if (strcmp(dev->name, devname) == 0)
605 {
606 dev->type = 0xFFFF;
607 dev->family = AF_UNSPEC;
608 }
609
610 return(0);
611 }
612
613 int dlci_setup(void)
614 {
615 int i;
616
617 printk("%s.\n", version);
618
619 for(i=0;i<CONFIG_DLCI_COUNT;i++)
620 open_dev[i] = NULL;
621
622 for(i=0;i<sizeof(basename) / sizeof(char *);i++)
623 basename[i] = NULL;
624
625 return(0);
626 }
627
628 #ifdef MODULE
629 static struct device dlci = {"dlci", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, dlci_init, };
630
631 int init_module(void)
632 {
633 dlci_setup();
634 return(register_netdev(&dlci));
635 }
636
637 void cleanup_module(void)
638 {
639 unregister_netdev(&dlci);
640 if (dlci.priv)
641 kfree(dlci.priv);
642 }
643 #endif