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