Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
llc_core.c
Go to the documentation of this file.
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 <[email protected]>
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 DEFINE_SPINLOCK(llc_sap_list_lock);
27 
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 */
41  spin_lock_init(&sap->sk_lock);
42  for (i = 0; i < LLC_SK_LADDR_HASH_ENTRIES; 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 
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 
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 
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 = {
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_list_lock);
166 
167 MODULE_LICENSE("GPL");
168 MODULE_AUTHOR("Procom 1997, Jay Schullist 2001, Arnaldo C. Melo 2001-2003");
169 MODULE_DESCRIPTION("LLC IEEE 802.2 core support");