Blame view
net/llc/llc_core.c
4.13 KB
1da177e4c
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/* * llc_core.c - Minimum needed routines for sap handling and module init/exit * * Copyright (c) 1997 by Procom Technology, Inc. * 2001-2003 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/module.h> #include <linux/interrupt.h> #include <linux/if_ether.h> #include <linux/netdevice.h> #include <linux/slab.h> #include <linux/string.h> #include <linux/init.h> |
881d966b4
|
22 |
#include <net/net_namespace.h> |
1da177e4c
|
23 24 25 |
#include <net/llc.h> LIST_HEAD(llc_sap_list); |
5e419e68a
|
26 |
static DEFINE_SPINLOCK(llc_sap_list_lock); |
1da177e4c
|
27 |
|
1da177e4c
|
28 29 30 31 32 33 34 |
/** * llc_sap_alloc - allocates and initializes sap. * * Allocates and initializes sap. */ static struct llc_sap *llc_sap_alloc(void) { |
0da974f4f
|
35 |
struct llc_sap *sap = kzalloc(sizeof(*sap), GFP_ATOMIC); |
52d58aef5
|
36 |
int i; |
1da177e4c
|
37 38 |
if (sap) { |
a5a04819c
|
39 |
/* sap->laddr.mac - leave as a null, it's filled by bind */ |
1da177e4c
|
40 |
sap->state = LLC_SAP_STATE_ACTIVE; |
b76f5a842
|
41 |
spin_lock_init(&sap->sk_lock); |
52d58aef5
|
42 43 |
for (i = 0; i < LLC_SK_LADDR_HASH_ENTRIES; i++) INIT_HLIST_NULLS_HEAD(&sap->sk_laddr_hash[i], i); |
6e2144b76
|
44 |
atomic_set(&sap->refcnt, 1); |
1da177e4c
|
45 46 47 |
} return sap; } |
2928c19e1
|
48 |
static struct llc_sap *__llc_sap_find(unsigned char sap_value) |
6e2144b76
|
49 |
{ |
3cdba604d
|
50 |
struct llc_sap *sap; |
6e2144b76
|
51 52 53 54 55 56 57 58 |
list_for_each_entry(sap, &llc_sap_list, node) if (sap->laddr.lsap == sap_value) goto out; sap = NULL; out: return sap; } |
1da177e4c
|
59 60 61 62 63 |
/** * llc_sap_find - searchs a SAP in station * @sap_value: sap to be found * * Searchs for a sap in the sap list of the LLC's station upon the sap ID. |
6e2144b76
|
64 65 |
* If the sap is found it will be refcounted and the user will have to do * a llc_sap_put after use. |
1da177e4c
|
66 67 68 69 |
* Returns the sap or %NULL if not found. */ struct llc_sap *llc_sap_find(unsigned char sap_value) { |
8beb9ab6c
|
70 |
struct llc_sap *sap; |
1da177e4c
|
71 |
|
8beb9ab6c
|
72 |
rcu_read_lock_bh(); |
6e2144b76
|
73 74 75 |
sap = __llc_sap_find(sap_value); if (sap) llc_sap_hold(sap); |
8beb9ab6c
|
76 |
rcu_read_unlock_bh(); |
1da177e4c
|
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
return sap; } /** * llc_sap_open - open interface to the upper layers. * @lsap: SAP number. * @func: rcv func for datalink protos * * Interface function to upper layer. Each one who wants to get a SAP * (for example NetBEUI) should call this function. Returns the opened * SAP for success, NULL for failure. */ struct llc_sap *llc_sap_open(unsigned char lsap, int (*func)(struct sk_buff *skb, struct net_device *dev, |
f2ccd8fa0
|
92 93 |
struct packet_type *pt, struct net_device *orig_dev)) |
1da177e4c
|
94 |
{ |
6e2144b76
|
95 |
struct llc_sap *sap = NULL; |
1da177e4c
|
96 |
|
8beb9ab6c
|
97 |
spin_lock_bh(&llc_sap_list_lock); |
6e2144b76
|
98 |
if (__llc_sap_find(lsap)) /* SAP already exists */ |
1da177e4c
|
99 |
goto out; |
1da177e4c
|
100 101 102 103 104 |
sap = llc_sap_alloc(); if (!sap) goto out; sap->laddr.lsap = lsap; sap->rcv_func = func; |
8beb9ab6c
|
105 |
list_add_tail_rcu(&sap->node, &llc_sap_list); |
1da177e4c
|
106 |
out: |
8beb9ab6c
|
107 |
spin_unlock_bh(&llc_sap_list_lock); |
1da177e4c
|
108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
return sap; } /** * llc_sap_close - close interface for upper layers. * @sap: SAP to be closed. * * Close interface function to upper layer. Each one who wants to * close an open SAP (for example NetBEUI) should call this function. * Removes this sap from the list of saps in the station and then * frees the memory for this sap. */ void llc_sap_close(struct llc_sap *sap) { |
52d58aef5
|
122 |
WARN_ON(sap->sk_count); |
8beb9ab6c
|
123 124 125 126 127 128 |
spin_lock_bh(&llc_sap_list_lock); list_del_rcu(&sap->node); spin_unlock_bh(&llc_sap_list_lock); synchronize_rcu(); |
1da177e4c
|
129 130 |
kfree(sap); } |
7546dd97d
|
131 |
static struct packet_type llc_packet_type __read_mostly = { |
09640e636
|
132 |
.type = cpu_to_be16(ETH_P_802_2), |
1da177e4c
|
133 134 |
.func = llc_rcv, }; |
7546dd97d
|
135 |
static struct packet_type llc_tr_packet_type __read_mostly = { |
09640e636
|
136 |
.type = cpu_to_be16(ETH_P_TR_802_2), |
1da177e4c
|
137 138 139 140 141 |
.func = llc_rcv, }; static int __init llc_init(void) { |
1da177e4c
|
142 143 144 145 146 147 148 149 150 151 152 153 154 |
dev_add_pack(&llc_packet_type); dev_add_pack(&llc_tr_packet_type); return 0; } static void __exit llc_exit(void) { dev_remove_pack(&llc_packet_type); dev_remove_pack(&llc_tr_packet_type); } module_init(llc_init); module_exit(llc_exit); |
1da177e4c
|
155 |
EXPORT_SYMBOL(llc_sap_list); |
1da177e4c
|
156 157 158 159 160 161 162 |
EXPORT_SYMBOL(llc_sap_find); EXPORT_SYMBOL(llc_sap_open); EXPORT_SYMBOL(llc_sap_close); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Procom 1997, Jay Schullist 2001, Arnaldo C. Melo 2001-2003"); MODULE_DESCRIPTION("LLC IEEE 802.2 core support"); |