Root/
1 | /* |
2 | * llc_core.c - Minimum needed routines for sap handling and module init/exit |
3 | * |
4 | * Copyright (c) 1997 by Procom Technology, Inc. |
5 | * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br> |
6 | * |
7 | * This program can be redistributed or modified under the terms of the |
8 | * GNU General Public License as published by the Free Software Foundation. |
9 | * This program is distributed without any warranty or implied warranty |
10 | * of merchantability or fitness for a particular purpose. |
11 | * |
12 | * See the GNU General Public License for more details. |
13 | */ |
14 | |
15 | #include <linux/module.h> |
16 | #include <linux/interrupt.h> |
17 | #include <linux/if_ether.h> |
18 | #include <linux/netdevice.h> |
19 | #include <linux/slab.h> |
20 | #include <linux/string.h> |
21 | #include <linux/init.h> |
22 | #include <net/net_namespace.h> |
23 | #include <net/llc.h> |
24 | |
25 | LIST_HEAD(llc_sap_list); |
26 | static DEFINE_SPINLOCK(llc_sap_list_lock); |
27 | |
28 | /** |
29 | * llc_sap_alloc - allocates and initializes sap. |
30 | * |
31 | * Allocates and initializes sap. |
32 | */ |
33 | static struct llc_sap *llc_sap_alloc(void) |
34 | { |
35 | struct llc_sap *sap = kzalloc(sizeof(*sap), GFP_ATOMIC); |
36 | int i; |
37 | |
38 | if (sap) { |
39 | /* sap->laddr.mac - leave as a null, it's filled by bind */ |
40 | sap->state = LLC_SAP_STATE_ACTIVE; |
41 | spin_lock_init(&sap->sk_lock); |
42 | for (i = 0; i < LLC_SK_LADDR_HASH_ENTRIES; i++) |
43 | INIT_HLIST_NULLS_HEAD(&sap->sk_laddr_hash[i], i); |
44 | atomic_set(&sap->refcnt, 1); |
45 | } |
46 | return sap; |
47 | } |
48 | |
49 | static struct llc_sap *__llc_sap_find(unsigned char sap_value) |
50 | { |
51 | struct llc_sap *sap; |
52 | |
53 | list_for_each_entry(sap, &llc_sap_list, node) |
54 | if (sap->laddr.lsap == sap_value) |
55 | goto out; |
56 | sap = NULL; |
57 | out: |
58 | return sap; |
59 | } |
60 | |
61 | /** |
62 | * llc_sap_find - searchs a SAP in station |
63 | * @sap_value: sap to be found |
64 | * |
65 | * Searchs for a sap in the sap list of the LLC's station upon the sap ID. |
66 | * If the sap is found it will be refcounted and the user will have to do |
67 | * a llc_sap_put after use. |
68 | * Returns the sap or %NULL if not found. |
69 | */ |
70 | struct llc_sap *llc_sap_find(unsigned char sap_value) |
71 | { |
72 | struct llc_sap *sap; |
73 | |
74 | rcu_read_lock_bh(); |
75 | sap = __llc_sap_find(sap_value); |
76 | if (sap) |
77 | llc_sap_hold(sap); |
78 | rcu_read_unlock_bh(); |
79 | return sap; |
80 | } |
81 | |
82 | /** |
83 | * llc_sap_open - open interface to the upper layers. |
84 | * @lsap: SAP number. |
85 | * @func: rcv func for datalink protos |
86 | * |
87 | * Interface function to upper layer. Each one who wants to get a SAP |
88 | * (for example NetBEUI) should call this function. Returns the opened |
89 | * SAP for success, NULL for failure. |
90 | */ |
91 | struct llc_sap *llc_sap_open(unsigned char lsap, |
92 | int (*func)(struct sk_buff *skb, |
93 | struct net_device *dev, |
94 | struct packet_type *pt, |
95 | struct net_device *orig_dev)) |
96 | { |
97 | struct llc_sap *sap = NULL; |
98 | |
99 | spin_lock_bh(&llc_sap_list_lock); |
100 | if (__llc_sap_find(lsap)) /* SAP already exists */ |
101 | goto out; |
102 | sap = llc_sap_alloc(); |
103 | if (!sap) |
104 | goto out; |
105 | sap->laddr.lsap = lsap; |
106 | sap->rcv_func = func; |
107 | list_add_tail_rcu(&sap->node, &llc_sap_list); |
108 | out: |
109 | spin_unlock_bh(&llc_sap_list_lock); |
110 | return sap; |
111 | } |
112 | |
113 | /** |
114 | * llc_sap_close - close interface for upper layers. |
115 | * @sap: SAP to be closed. |
116 | * |
117 | * Close interface function to upper layer. Each one who wants to |
118 | * close an open SAP (for example NetBEUI) should call this function. |
119 | * Removes this sap from the list of saps in the station and then |
120 | * frees the memory for this sap. |
121 | */ |
122 | void llc_sap_close(struct llc_sap *sap) |
123 | { |
124 | WARN_ON(sap->sk_count); |
125 | |
126 | spin_lock_bh(&llc_sap_list_lock); |
127 | list_del_rcu(&sap->node); |
128 | spin_unlock_bh(&llc_sap_list_lock); |
129 | |
130 | synchronize_rcu(); |
131 | |
132 | kfree(sap); |
133 | } |
134 | |
135 | static struct packet_type llc_packet_type __read_mostly = { |
136 | .type = cpu_to_be16(ETH_P_802_2), |
137 | .func = llc_rcv, |
138 | }; |
139 | |
140 | static struct packet_type llc_tr_packet_type __read_mostly = { |
141 | .type = cpu_to_be16(ETH_P_TR_802_2), |
142 | .func = llc_rcv, |
143 | }; |
144 | |
145 | static int __init llc_init(void) |
146 | { |
147 | dev_add_pack(&llc_packet_type); |
148 | dev_add_pack(&llc_tr_packet_type); |
149 | return 0; |
150 | } |
151 | |
152 | static void __exit llc_exit(void) |
153 | { |
154 | dev_remove_pack(&llc_packet_type); |
155 | dev_remove_pack(&llc_tr_packet_type); |
156 | } |
157 | |
158 | module_init(llc_init); |
159 | module_exit(llc_exit); |
160 | |
161 | EXPORT_SYMBOL(llc_sap_list); |
162 | EXPORT_SYMBOL(llc_sap_find); |
163 | EXPORT_SYMBOL(llc_sap_open); |
164 | EXPORT_SYMBOL(llc_sap_close); |
165 | |
166 | MODULE_LICENSE("GPL"); |
167 | MODULE_AUTHOR("Procom 1997, Jay Schullist 2001, Arnaldo C. Melo 2001-2003"); |
168 | MODULE_DESCRIPTION("LLC IEEE 802.2 core support"); |
169 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9