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_WRITE, new, sizeof(*new));
290 if (err)
291 return(err);
292
293 memcpy_fromfs(&dlci, new, sizeof(dlci));
294
295
296 slave = dev_get(dlci.devname);
297 if (!slave)
298 return(-ENODEV);
299
300 if (slave->type != ARPHRD_FRAD)
301 return(-EINVAL);
302
303
304 for (i=0;i<sizeof(basename) / sizeof(char *); i++)
305 if ((basename[i]) &&
306 (strncmp(dlci.devname, basename[i], strlen(basename[i])) == 0) &&
307 (strlen(dlci.devname) > strlen(basename[i])))
308 break;
309
310 if (i == sizeof(basename) / sizeof(char *))
311 return(-EINVAL);
312
313
314 for(i=0;i<CONFIG_DLCI_COUNT;i++)
315 if (!open_dev[i])
316 break;
317
318 if (i == CONFIG_DLCI_COUNT)
319 return(-ENOSPC);
320
321
322 sprintf(buf, "%s%02i", devname, i);
323
324 master = kmalloc(sizeof(*master), GFP_KERNEL);
325 if (!master)
326 return(-ENOMEM);
327
328 memset(master, 0, sizeof(*master));
329 master->name = kmalloc(strlen(buf) + 1, GFP_KERNEL);
330
331 if (!master->name)
332 {
333 kfree(master);
334 return(-ENOMEM);
335 }
336
337 strcpy(master->name, buf);
338 master->init = dlci_init;
339 master->flags = 0;
340
341 err = register_netdev(master);
342 if (err < 0)
343 {
344 kfree(master->name);
345 kfree(master);
346 return(err);
347 }
348
349 *(short *)(master->dev_addr) = dlci.dlci;
350
351 dlp = (struct dlci_local *) master->priv;
352 dlp->slave = slave;
353
354 flp = slave->priv;
355 err = flp ? (*flp->assoc)(slave, master) : -EINVAL;
356 if (err < 0)
357 {
358 unregister_netdev(master);
359 kfree(master->priv);
360 kfree(master->name);
361 kfree(master);
362 return(err);
363 }
364
365 memcpy_tofs(new->devname, buf, strlen(buf) + 1);
366 open_dev[i] = master;
367
368 MOD_INC_USE_COUNT;
369
370 return(0);
371 }
372
373 int dlci_del(struct device *master)
374 {
375 struct dlci_local *dlp;
376 struct frad_local *flp;
377 struct device *slave;
378 int i, err;
379
380 if (master->start)
381 return(-EBUSY);
382
383 dlp = master->priv;
384 slave = dlp->slave;
385 flp = slave->priv;
386
387 err = (*flp->deassoc)(slave, master);
388 if (err)
389 return(err);
390
391 unregister_netdev(master);
392
393 for(i=0;i<CONFIG_DLCI_COUNT;i++)
394 if (master == open_dev[i])
395 break;
396
397 if (i<CONFIG_DLCI_COUNT)
398 open_dev[i] = NULL;
399
400 kfree(master->priv);
401 kfree(master->name);
402 kfree(master);
403
404 MOD_DEC_USE_COUNT;
405
406 return(0);
407 }
408
409 int dlci_config(struct device *dev, struct dlci_conf *conf, int get)
410 {
411 struct dlci_conf config;
412 struct dlci_local *dlp;
413 struct frad_local *flp;
414 int err;
415
416 dlp = dev->priv;
417
418 flp = dlp->slave->priv;
419
420 if (!get)
421 {
422 err = verify_area(VERIFY_READ, conf, sizeof(struct dlci_conf));
423 if (err)
424 return(err);
425
426 memcpy_fromfs(&config, conf, sizeof(struct dlci_conf));
427 if (config.flags & ~DLCI_VALID_FLAGS)
428 return(-EINVAL);
429 memcpy(&dlp->config, &config, sizeof(struct dlci_conf));
430 dlp->configured = 1;
431 }
432
433 err = (*flp->dlci_conf)(dlp->slave, dev, get);
434 if (err)
435 return(err);
436
437 if (get)
438 {
439 err = verify_area(VERIFY_WRITE, conf, sizeof(struct dlci_conf));
440 if (err)
441 return(err);
442
443 memcpy_tofs(conf, &dlp->config, sizeof(struct dlci_conf));
444 }
445
446 return(0);
447 }
448
449 int dlci_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
450 {
451 struct dlci_local *dlp;
452
453 if (!suser())
454 return(-EPERM);
455
456 dlp = dev->priv;
457
458 switch(cmd)
459 {
460 case DLCI_GET_SLAVE:
461 if (!*(short *)(dev->dev_addr))
462 return(-EINVAL);
463
464 strcpy(ifr->ifr_slave, dlp->slave->name);
465 break;
466
467 case DLCI_DEVADD:
468
469 if (*(short *)(dev->dev_addr))
470 return(-EINVAL);
471
472 return(dlci_add((struct dlci_add *) ifr->ifr_data));
473 break;
474
475 case DLCI_DEVDEL:
476
477 if (!*(short *)(dev->dev_addr))
478 return(-EINVAL);
479
480 if (dev->start)
481 return(-EBUSY);
482
483 return(dlci_del(dev));
484 break;
485
486 case DLCI_GET_CONF:
487 case DLCI_SET_CONF:
488 if (!*(short *)(dev->dev_addr))
489 return(-EINVAL);
490
491 return(dlci_config(dev, (struct dlci_conf *) ifr->ifr_data, cmd == DLCI_GET_CONF));
492 break;
493
494 default:
495 return(-EOPNOTSUPP);
496 }
497 return(0);
498 }
499
500 static int dlci_change_mtu(struct device *dev, int new_mtu)
501 {
502 struct dlci_local *dlp;
503
504 dlp = dev->priv;
505
506 return((*dlp->slave->change_mtu)(dlp->slave, new_mtu));
507 }
508
509 static int dlci_open(struct device *dev)
510 {
511 struct dlci_local *dlp;
512 struct frad_local *flp;
513 int err;
514
515 dlp = dev->priv;
516
517 if (!*(short *)(dev->dev_addr))
518 return(-EINVAL);
519
520 if (!dlp->slave->start)
521 return(-ENOTCONN);
522
523 dev->flags = 0;
524 dev->tbusy = 0;
525 dev->interrupt = 0;
526 dev->start = 1;
527
528 flp = dlp->slave->priv;
529 err = (*flp->activate)(dlp->slave, dev);
530 if (err)
531 return(err);
532
533 return 0;
534 }
535
536 static int dlci_close(struct device *dev)
537 {
538 struct dlci_local *dlp;
539 struct frad_local *flp;
540 int err;
541
542 dlp = dev->priv;
543
544 flp = dlp->slave->priv;
545 err = (*flp->deactivate)(dlp->slave, dev);
546
547 dev->start = 0;
548 dev->tbusy = 1;
549
550 return 0;
551 }
552
553 static struct enet_statistics *dlci_get_stats(struct device *dev)
554 {
555 struct dlci_local *dlp;
556
557 dlp = dev->priv;
558
559 return(&dlp->stats);
560 }
561
562 int dlci_init(struct device *dev)
563 {
564 struct dlci_local *dlp;
565 int i;
566
567 dev->priv = kmalloc(sizeof(struct dlci_local), GFP_KERNEL);
568 if (!dev->priv)
569 return(-ENOMEM);
570
571 memset(dev->priv, 0, sizeof(struct dlci_local));
572 dlp = dev->priv;
573
574 dev->flags = 0;
575 dev->open = dlci_open;
576 dev->stop = dlci_close;
577 dev->do_ioctl = dlci_ioctl;
578 dev->hard_start_xmit = dlci_transmit;
579 dev->hard_header = dlci_header;
580 dev->get_stats = dlci_get_stats;
581 dev->change_mtu = dlci_change_mtu;
582
583 dlp->receive = dlci_receive;
584
585 dev->type = ARPHRD_DLCI;
586 dev->family = AF_INET;
587 dev->hard_header_len = sizeof(struct frhdr);
588 dev->pa_alen = sizeof(unsigned long);
589 dev->addr_len = sizeof(short);
590 memset(dev->dev_addr, 0, sizeof(dev->dev_addr));
591
592 dev->pa_addr = 0;
593 dev->pa_dstaddr = 0;
594 dev->pa_brdaddr = 0;
595 dev->pa_mask = 0;
596
597 for (i = 0; i < DEV_NUMBUFFS; i++)
598 skb_queue_head_init(&dev->buffs[i]);
599
600 if (strcmp(dev->name, devname) == 0)
601 {
602 dev->type = 0xFFFF;
603 dev->family = AF_UNSPEC;
604 }
605
606 return(0);
607 }
608
609 int dlci_setup(void)
610 {
611 int i;
612
613 printk("%s.\n", version);
614
615 for(i=0;i<CONFIG_DLCI_COUNT;i++)
616 open_dev[i] = NULL;
617
618 for(i=0;i<sizeof(basename) / sizeof(char *);i++)
619 basename[i] = NULL;
620
621 return(0);
622 }
623
624 #ifdef MODULE
625 static struct device dlci = {"dlci", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, dlci_init, };
626
627 int init_module(void)
628 {
629 dlci_setup();
630 return(register_netdev(&dlci));
631 }
632
633 void cleanup_module(void)
634 {
635 unregister_netdev(&dlci);
636 if (dlci.priv)
637 kfree(dlci.priv);
638 }
639 #endif