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