summaryrefslogtreecommitdiff
path: root/net/core/ext8022.c
blob: e6415d51accb016578fc10ef14dbce85ea7b0987 (plain)
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
 * (ext8022.c)
 * 
 * Copyright (c) 1997 by Procom Technology, Inc.
 * 		 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
 *
 * This program can be redistributed or modified under the terms of the 
 * GNU General Public License as published by the Free Software Foundation.
 * This program is distributed without any warranty or implied warranty
 * of merchantability or fitness for a particular purpose.
 *
 * See the GNU General Public License for more details.
 */
#include <linux/config.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/brlock.h>

typedef int (*func_type)(struct sk_buff *skb, struct net_device *dev,
			 struct packet_type *pt);
static int llc_rcv(struct sk_buff *skb, struct net_device *dev,
		   struct packet_type *);

static func_type llc_sap_table[128];
static int llc_users;

static struct packet_type llc_packet_type = {
	type:	__constant_htons(ETH_P_802_2),
	func:	llc_rcv,
};
static struct packet_type llc_tr_packet_type = {
	type:	__constant_htons(ETH_P_TR_802_2),
	func:	llc_rcv,
};

static int llc_rcv(struct sk_buff *skb, struct net_device *dev,
		   struct packet_type *pt)
{
 	unsigned char n = (*(skb->h.raw)) >> 1;

	br_read_lock(BR_LLC_LOCK);
	if (llc_sap_table[n])
            llc_sap_table[n](skb, dev, pt);
        else
            kfree_skb(skb);
	br_read_unlock(BR_LLC_LOCK);
        return 0;
}

void llc_register_sap(unsigned char sap, func_type rcvfunc)
{
	sap >>= 1;
	br_write_lock_bh(BR_LLC_LOCK);
	llc_sap_table[sap] = rcvfunc;            
	if (!llc_users) {
		dev_add_pack(&llc_packet_type);
		dev_add_pack(&llc_tr_packet_type);
        }
	llc_users++;
	br_write_unlock_bh(BR_LLC_LOCK);
}

void llc_unregister_sap(unsigned char sap)
{
	sap >>= 1;
	br_write_lock_bh(BR_LLC_LOCK);
        llc_sap_table[sap] = NULL;
	if (!--llc_users) {
		dev_remove_pack(&llc_packet_type);
		dev_remove_pack(&llc_tr_packet_type);
        } 
	br_write_unlock_bh(BR_LLC_LOCK);
}

EXPORT_SYMBOL(llc_register_sap);
EXPORT_SYMBOL(llc_unregister_sap);