OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [net/] [bpqether.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 *      G8BPQ compatible "AX.25 via ethernet" driver release 003
3
 *
4
 *      This is ALPHA test software. This code may break your machine, randomly
5
 *      fail to work with new releases, misbehave and/or generally screw up.
6
 *      It might even work.
7
 *
8
 *      This code REQUIRES 2.0.0 or higher/ NET3.029
9
 *
10
 *      This module:
11
 *              This module is free software; you can redistribute it and/or
12
 *              modify it under the terms of the GNU General Public License
13
 *              as published by the Free Software Foundation; either version
14
 *              2 of the License, or (at your option) any later version.
15
 *
16
 *      This is a "pseudo" network driver to allow AX.25 over Ethernet
17
 *      using G8BPQ encapsulation. It has been extracted from the protocol
18
 *      implementation because
19
 *
20
 *              - things got unreadable within the protocol stack
21
 *              - to cure the protocol stack from "feature-ism"
22
 *              - a protocol implementation shouldn't need to know on
23
 *                which hardware it is running
24
 *              - user-level programs like the AX.25 utilities shouldn't
25
 *                need to know about the hardware.
26
 *              - IP over ethernet encapsulated AX.25 was impossible
27
 *              - rxecho.c did not work
28
 *              - to have room for extensions
29
 *              - it just deserves to "live" as an own driver
30
 *
31
 *      This driver can use any ethernet destination address, and can be
32
 *      limited to accept frames from one dedicated ethernet card only.
33
 *
34
 *      Note that the driver sets up the BPQ devices automagically on
35
 *      startup or (if started before the "insmod" of an ethernet device)
36
 *      on "ifconfig up". It hopefully will remove the BPQ on "rmmod"ing
37
 *      the ethernet device (in fact: as soon as another ethernet or bpq
38
 *      device gets "ifconfig"ured).
39
 *
40
 *      I have heard that several people are thinking of experiments
41
 *      with highspeed packet radio using existing ethernet cards.
42
 *      Well, this driver is prepared for this purpose, just add
43
 *      your tx key control and a txdelay / tailtime algorithm,
44
 *      probably some buffering, and /voila/...
45
 *
46
 *      History
47
 *      BPQ   001       Joerg(DL1BKE)           Extracted BPQ code from AX.25
48
 *                                              protocol stack and added my own
49
 *                                              yet existing patches
50
 *      BPQ   002       Joerg(DL1BKE)           Scan network device list on
51
 *                                              startup.
52
 *      BPQ   003       Joerg(DL1BKE)           Ethernet destination address
53
 *                                              and accepted source address
54
 *                                              can be configured by an ioctl()
55
 *                                              call.
56
 */
57
 
58
#include <linux/config.h>
59
#include <linux/errno.h>
60
#include <linux/types.h>
61
#include <linux/socket.h>
62
#include <linux/in.h>
63
#include <linux/kernel.h>
64
#include <linux/string.h>
65
#include <linux/net.h>
66
#include <net/ax25.h>
67
#include <linux/inet.h>
68
#include <linux/netdevice.h>
69
#include <linux/if_arp.h>
70
#include <linux/skbuff.h>
71
#include <net/sock.h>
72
#include <asm/segment.h>
73
#include <asm/system.h>
74
#include <linux/mm.h>
75
#include <linux/interrupt.h>
76
#include <linux/notifier.h>
77
#include <linux/proc_fs.h>
78
#include <linux/stat.h>
79
#include <linux/firewall.h>
80
#include <linux/module.h>
81
#include <linux/net_alias.h>
82
 
83
#include <net/ip.h>
84
#include <net/arp.h>
85
 
86
#include <linux/bpqether.h>
87
 
88
static unsigned char ax25_bcast[AX25_ADDR_LEN] =
89
        {'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
90
static unsigned char ax25_defaddr[AX25_ADDR_LEN] =
91
        {'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
92
 
93
static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
94
 
95
static char bpq_eth_addr[6];
96
 
97
static int bpq_rcv(struct sk_buff *, struct device *, struct packet_type *);
98
static int bpq_device_event(struct notifier_block *, unsigned long, void *);
99
static char *bpq_print_ethaddr(unsigned char *);
100
 
101
static struct packet_type bpq_packet_type = {
102
        0,               /* ntohs(ETH_P_BPQ),*/
103
        0,               /* copy */
104
        bpq_rcv,
105
        NULL,
106
        NULL,
107
};
108
 
109
static struct notifier_block bpq_dev_notifier = {
110
        bpq_device_event,
111
 
112
};
113
 
114
 
115
#define MAXBPQDEV 100
116
 
117
static struct bpqdev {
118
        struct bpqdev *next;
119
        char   ethname[14];             /* ether device name */
120
        struct device *ethdev;          /* link to ethernet device */
121
        struct device axdev;            /* bpq device (bpq#) */
122
        struct enet_statistics stats;   /* some statistics */
123
        char   dest_addr[6];            /* ether destination address */
124
        char   acpt_addr[6];            /* accept ether frames from this address only */
125
} *bpq_devices = NULL;
126
 
127
 
128
/* ------------------------------------------------------------------------ */
129
 
130
 
131
/*
132
 *      Get the ethernet device for a BPQ device
133
 */
134
static __inline__ struct device *bpq_get_ether_dev(struct device *dev)
135
{
136
        struct bpqdev *bpq;
137
 
138
        bpq = (struct bpqdev *)dev->priv;
139
 
140
        return (bpq != NULL) ? bpq->ethdev : NULL;
141
}
142
 
143
/*
144
 *      Get the BPQ device for the ethernet device
145
 */
146
static __inline__ struct device *bpq_get_ax25_dev(struct device *dev)
147
{
148
        struct bpqdev *bpq;
149
 
150
        for (bpq = bpq_devices; bpq != NULL; bpq = bpq->next)
151
                if (bpq->ethdev == dev)
152
                        return &bpq->axdev;
153
 
154
        return NULL;
155
}
156
 
157
static __inline__ int dev_is_ethdev(struct device *dev)
158
{
159
        return (
160
                        dev->type == ARPHRD_ETHER
161
                        && strncmp(dev->name, "dummy", 5)
162
#ifdef CONFIG_NET_ALIAS
163
                        && !net_alias_is(dev)
164
#endif
165
        );
166
}
167
 
168
/*
169
 *      Sanity check: remove all devices that ceased to exists and
170
 *      return '1' if the given BPQ device was affected.
171
 */
172
static int bpq_check_devices(struct device *dev)
173
{
174
        struct bpqdev *bpq, *bpq_prev;
175
        int result = 0;
176
        unsigned long flags;
177
 
178
        save_flags(flags);
179
        cli();
180
 
181
        bpq_prev = NULL;
182
 
183
        for (bpq = bpq_devices; bpq != NULL; bpq = bpq->next) {
184
                if (!dev_get(bpq->ethname)) {
185
                        if (bpq_prev)
186
                                bpq_prev->next = bpq->next;
187
                        else
188
                                bpq_devices = bpq->next;
189
 
190
                        if (&bpq->axdev == dev)
191
                                result = 1;
192
 
193
                        unregister_netdev(&bpq->axdev);
194
                        kfree(bpq);
195
                }
196
 
197
                bpq_prev = bpq;
198
        }
199
 
200
        restore_flags(flags);
201
 
202
        return result;
203
}
204
 
205
 
206
/* ------------------------------------------------------------------------ */
207
 
208
 
209
/*
210
 *      Receive an AX.25 frame via an ethernet interface.
211
 */
212
static int bpq_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *ptype)
213
{
214
        int len;
215
        char * ptr;
216
        struct ethhdr *eth = (struct ethhdr *)skb->mac.raw;
217
        struct bpqdev *bpq;
218
 
219
        skb->sk = NULL;         /* Initially we don't know who it's for */
220
 
221
        dev = bpq_get_ax25_dev(dev);
222
 
223
        if (dev == NULL || dev->start == 0) {
224
                kfree_skb(skb, FREE_READ);
225
                return 0;
226
        }
227
 
228
        /*
229
         * if we want to accept frames from just one ethernet device
230
         * we check the source address of the sender.
231
         */
232
 
233
        bpq = (struct bpqdev *)dev->priv;
234
 
235
        if (!(bpq->acpt_addr[0] & 0x01) && memcmp(eth->h_source, bpq->acpt_addr, ETH_ALEN)) {
236
                printk(KERN_DEBUG "bpqether: wrong dest %s\n", bpq_print_ethaddr(eth->h_source));
237
                kfree_skb(skb, FREE_READ);
238
                return 0;
239
        }
240
 
241
        ((struct bpqdev *)dev->priv)->stats.rx_packets++;
242
 
243
        len = skb->data[0] + skb->data[1] * 256 - 5;
244
 
245
        skb_pull(skb, 2);       /* Remove the length bytes */
246
        skb_trim(skb, len);     /* Set the length of the data */
247
 
248
        ptr = skb_push(skb, 1);
249
        *ptr = 0;
250
 
251
        skb->dev = dev;
252
        skb->protocol = htons(ETH_P_AX25);
253
        skb->mac.raw = skb->data;
254
        skb->pkt_type = PACKET_HOST;
255
 
256
        netif_rx(skb);
257
 
258
        return 0;
259
}
260
 
261
/*
262
 *      Send an AX.25 frame via an ethernet interface
263
 */
264
static int bpq_xmit(struct sk_buff *skb, struct device *dev)
265
{
266
        unsigned char *ptr;
267
        struct bpqdev *bpq;
268
        int size;
269
 
270
        /*
271
         * Just to be *really* sure not to send anything if the interface
272
         * is down, the ethernet device may have gone.
273
         */
274
        if (!dev->start) {
275
                bpq_check_devices(dev);
276
                dev_kfree_skb(skb, FREE_WRITE);
277
                return -ENODEV;
278
        }
279
 
280
        skb_pull(skb, 1);
281
        size = skb->len;
282
 
283
        /*
284
         * The AX.25 code leaves enough room for the ethernet header, but
285
         * sendto() does not.
286
         */
287
        if (skb_headroom(skb) < AX25_BPQ_HEADER_LEN) {  /* Ough! */
288
                struct sk_buff *newskb = alloc_skb(skb->len + AX25_BPQ_HEADER_LEN, GFP_ATOMIC);
289
 
290
                if (newskb == NULL) {                   /* Argh! */
291
                        printk(KERN_WARNING "bpq_xmit: not enough space to add BPQ Ether header\n");
292
                        dev_kfree_skb(skb, FREE_WRITE);
293
                        return -ENOMEM;
294
                }
295
 
296
                newskb->free = 1;
297
                newskb->arp  = 1;
298
                if (skb->sk != NULL)
299
                        atomic_add(newskb->truesize, &skb->sk->wmem_alloc);
300
                newskb->sk   = skb->sk;
301
 
302
                skb_reserve(newskb, AX25_BPQ_HEADER_LEN);
303
                memcpy(skb_put(newskb, size), skb->data, size);
304
                dev_kfree_skb(skb, FREE_WRITE);
305
                skb = newskb;
306
        }
307
 
308
        skb->protocol = htons(ETH_P_AX25);
309
 
310
        ptr = skb_push(skb, 2);
311
 
312
        *ptr++ = (size + 5) % 256;
313
        *ptr++ = (size + 5) / 256;
314
 
315
        bpq = (struct bpqdev *)dev->priv;
316
        bpq->stats.tx_packets++;
317
 
318
        if ((dev = bpq_get_ether_dev(dev)) == NULL) {
319
                bpq->stats.tx_dropped++;
320
                dev_kfree_skb(skb, FREE_WRITE);
321
                return -ENODEV;
322
        }
323
 
324
        skb->dev = dev;
325
        dev->hard_header(skb, dev, ETH_P_BPQ, bpq->dest_addr, NULL, 0);
326
 
327
        dev_queue_xmit(skb, dev, SOPRI_NORMAL);
328
 
329
        return 0;
330
}
331
 
332
/*
333
 *      Statistics
334
 */
335
static struct enet_statistics *bpq_get_stats(struct device *dev)
336
{
337
        struct bpqdev *bpq;
338
 
339
        bpq = (struct bpqdev *)dev->priv;
340
 
341
        return &bpq->stats;
342
}
343
 
344
/*
345
 *      Set AX.25 callsign
346
 */
347
static int bpq_set_mac_address(struct device *dev, void *addr)
348
{
349
    struct sockaddr *sa = (struct sockaddr *)addr;
350
 
351
    memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
352
 
353
    return 0;
354
}
355
 
356
/*      Ioctl commands
357
 *
358
 *              SIOCSBPQETHOPT          reserved for enhancements
359
 *              SIOCSBPQETHADDR         set the destination and accepted
360
 *                                      source ethernet address (broadcast
361
 *                                      or multicast: accept all)
362
 */
363
static int bpq_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
364
{
365
        int err;
366
        struct bpq_ethaddr *ethaddr = (struct bpq_ethaddr *)ifr->ifr_data;
367
        struct bpqdev *bpq = dev->priv;
368
        struct bpq_req req;
369
 
370
        if (!suser())
371
                return -EPERM;
372
 
373
        if (bpq == NULL)                /* woops! */
374
                return -ENODEV;
375
 
376
        switch (cmd) {
377
                case SIOCSBPQETHOPT:
378
                        if ((err = verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(struct bpq_req))) != 0)
379
                                return err;
380
                        memcpy_fromfs(&req, ifr->ifr_data, sizeof(struct bpq_req));
381
                        switch (req.cmd) {
382
                                case SIOCGBPQETHPARAM:
383
                                case SIOCSBPQETHPARAM:
384
                                default:
385
                                        return -EINVAL;
386
                        }
387
 
388
                        break;
389
 
390
                case SIOCSBPQETHADDR:
391
                        if ((err = verify_area(VERIFY_READ, ethaddr, sizeof(struct bpq_ethaddr))) != 0)
392
                                return err;
393
                        memcpy_fromfs(bpq->dest_addr, ethaddr->destination, ETH_ALEN);
394
                        memcpy_fromfs(bpq->acpt_addr, ethaddr->accept, ETH_ALEN);
395
                        break;
396
 
397
                default:
398
                        return -EINVAL;
399
        }
400
 
401
        return 0;
402
}
403
 
404
/*
405
 * open/close a device
406
 */
407
static int bpq_open(struct device *dev)
408
{
409
        if (bpq_check_devices(dev))
410
                return -ENODEV;         /* oops, it's gone */
411
 
412
        dev->tbusy = 0;
413
        dev->start = 1;
414
 
415
        MOD_INC_USE_COUNT;
416
 
417
        return 0;
418
}
419
 
420
static int bpq_close(struct device *dev)
421
{
422
        dev->tbusy = 1;
423
        dev->start = 0;
424
 
425
        MOD_DEC_USE_COUNT;
426
 
427
        return 0;
428
}
429
 
430
/*
431
 * currently unused
432
 */
433
static int bpq_dev_init(struct device *dev)
434
{
435
        return 0;
436
}
437
 
438
 
439
/* ------------------------------------------------------------------------ */
440
 
441
 
442
/*
443
 *      Proc filesystem
444
 */
445
static char * bpq_print_ethaddr(unsigned char *e)
446
{
447
        static char buf[18];
448
 
449
        sprintf(buf, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
450
                e[0], e[1], e[2], e[3], e[4], e[5]);
451
 
452
        return buf;
453
}
454
 
455
int bpq_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
456
{
457
        struct bpqdev *bpqdev;
458
        int len     = 0;
459
        off_t pos   = 0;
460
        off_t begin = 0;
461
 
462
        cli();
463
 
464
        len += sprintf(buffer, "dev   ether      destination        accept from\n");
465
 
466
        for (bpqdev = bpq_devices; bpqdev != NULL; bpqdev = bpqdev->next) {
467
                len += sprintf(buffer + len, "%-5s %-10s %s  ",
468
                        bpqdev->axdev.name, bpqdev->ethname,
469
                        bpq_print_ethaddr(bpqdev->dest_addr));
470
 
471
                len += sprintf(buffer + len, "%s\n",
472
                        (bpqdev->acpt_addr[0] & 0x01) ? "*" : bpq_print_ethaddr(bpqdev->acpt_addr));
473
 
474
                pos = begin + len;
475
 
476
                if (pos < offset) {
477
                        len   = 0;
478
                        begin = pos;
479
                }
480
 
481
                if (pos > offset + length)
482
                        break;
483
        }
484
 
485
        sti();
486
 
487
        *start = buffer + (offset - begin);
488
        len   -= (offset - begin);
489
 
490
        if (len > length) len = length;
491
 
492
        return len;
493
}
494
 
495
 
496
/* ------------------------------------------------------------------------ */
497
 
498
 
499
/*
500
 *      Setup a new device.
501
 */
502
static int bpq_new_device(struct device *dev)
503
{
504
        int k;
505
        unsigned char *buf;
506
        struct bpqdev *bpq, *bpq2;
507
 
508
        if ((bpq = (struct bpqdev *)kmalloc(sizeof(struct bpqdev), GFP_KERNEL)) == NULL)
509
                return -ENOMEM;
510
 
511
        memset(bpq, 0, sizeof(struct bpqdev));
512
 
513
        bpq->ethdev = dev;
514
 
515
        bpq->ethname[sizeof(bpq->ethname)-1] = '\0';
516
        strncpy(bpq->ethname, dev->name, sizeof(bpq->ethname)-1);
517
 
518
        memcpy(bpq->dest_addr, bcast_addr, sizeof(bpq_eth_addr));
519
        memcpy(bpq->acpt_addr, bcast_addr, sizeof(bpq_eth_addr));
520
 
521
        dev = &bpq->axdev;
522
        buf = (unsigned char *)kmalloc(14, GFP_KERNEL);
523
 
524
        for (k = 0; k < MAXBPQDEV; k++) {
525
                struct device *odev;
526
 
527
                sprintf(buf, "bpq%d", k);
528
 
529
                if ((odev = dev_get(buf)) == NULL || bpq_check_devices(odev))
530
                        break;
531
        }
532
 
533
        if (k == MAXBPQDEV) {
534
                kfree(bpq);
535
                return -ENODEV;
536
        }
537
 
538
        dev->priv = (void *)bpq;        /* pointer back */
539
        dev->name = buf;
540
        dev->init = bpq_dev_init;
541
 
542
        if (register_netdev(dev) != 0) {
543
                kfree(bpq);
544
                return -EIO;
545
        }
546
 
547
        for (k=0; k < DEV_NUMBUFFS; k++)
548
                skb_queue_head_init(&dev->buffs[k]);
549
 
550
        dev->hard_start_xmit = bpq_xmit;
551
        dev->open            = bpq_open;
552
        dev->stop            = bpq_close;
553
        dev->set_mac_address = bpq_set_mac_address;
554
        dev->get_stats       = bpq_get_stats;
555
        dev->do_ioctl        = bpq_ioctl;
556
 
557
        memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
558
        memcpy(dev->dev_addr,  ax25_defaddr, AX25_ADDR_LEN);
559
 
560
        /* preset with reasonable values */
561
 
562
        dev->flags      = 0;
563
        dev->family     = AF_INET;
564
 
565
#ifdef CONFIG_INET
566
        dev->pa_addr    = in_aton("192.168.0.1");
567
        dev->pa_brdaddr = in_aton("192.168.0.255");
568
        dev->pa_mask    = in_aton("255.255.255.0");
569
        dev->pa_alen    = 4;
570
#endif
571
 
572
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
573
        dev->hard_header     = ax25_encapsulate;
574
        dev->rebuild_header  = ax25_rebuild_header;
575
#endif
576
 
577
        dev->type            = ARPHRD_AX25;
578
        dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
579
        dev->mtu             = AX25_DEF_PACLEN;
580
        dev->addr_len        = AX25_ADDR_LEN;
581
 
582
        cli();
583
 
584
        if (bpq_devices == NULL) {
585
                bpq_devices = bpq;
586
        } else {
587
                for (bpq2 = bpq_devices; bpq2->next != NULL; bpq2 = bpq2->next);
588
                bpq2->next = bpq;
589
        }
590
 
591
        sti();
592
 
593
        return 0;
594
}
595
 
596
 
597
/*
598
 *      Handle device status changes.
599
 */
600
static int bpq_device_event(struct notifier_block *this,unsigned long event, void *ptr)
601
{
602
        struct device *dev = (struct device *)ptr;
603
 
604
        if (!dev_is_ethdev(dev))
605
                return NOTIFY_DONE;
606
 
607
        bpq_check_devices(NULL);
608
 
609
        switch (event) {
610
                case NETDEV_UP:         /* new ethernet device -> new BPQ interface */
611
                        if (bpq_get_ax25_dev(dev) == NULL)
612
                                bpq_new_device(dev);
613
                        break;
614
 
615
                case NETDEV_DOWN:       /* ethernet device closed -> close BPQ interface */
616
                        if ((dev = bpq_get_ax25_dev(dev)) != NULL)
617
                                dev_close(dev);
618
                        break;
619
 
620
                default:
621
                        break;
622
        }
623
 
624
        return NOTIFY_DONE;
625
}
626
 
627
 
628
/* ------------------------------------------------------------------------ */
629
 
630
/*
631
 * Initialize driver. To be called from af_ax25 if not compiled as a
632
 * module
633
 */
634
int bpq_init(void)
635
{
636
        struct device *dev;
637
 
638
        bpq_packet_type.type  = htons(ETH_P_BPQ);
639
        dev_add_pack(&bpq_packet_type);
640
 
641
        register_netdevice_notifier(&bpq_dev_notifier);
642
 
643
        printk(KERN_INFO "AX.25 ethernet driver version 0.01\n");
644
 
645
#ifdef CONFIG_PROC_FS
646
        proc_net_register(&(struct proc_dir_entry) {
647
                PROC_NET_AX25_BPQETHER, 8, "bpqether",
648
                S_IFREG | S_IRUGO, 1, 0, 0,
649
                0, &proc_net_inode_operations,
650
                bpq_get_info
651
        });
652
#endif
653
 
654
        for (dev = dev_base; dev != NULL; dev = dev->next) {
655
                if (dev_is_ethdev(dev))
656
                        bpq_new_device(dev);
657
        }
658
 
659
        return 0;
660
}
661
 
662
#ifdef MODULE
663
int init_module(void)
664
{
665
        register_symtab(NULL);
666
 
667
        return bpq_init();
668
}
669
 
670
void cleanup_module(void)
671
{
672
        struct bpqdev *bpq;
673
 
674
        dev_remove_pack(&bpq_packet_type);
675
 
676
        unregister_netdevice_notifier(&bpq_dev_notifier);
677
 
678
#ifdef CONFIG_PROC_FS
679
        proc_net_unregister(PROC_NET_AX25_BPQETHER);
680
#endif
681
 
682
        for (bpq = bpq_devices; bpq != NULL; bpq = bpq->next)
683
                unregister_netdev(&bpq->axdev);
684
}
685
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.