0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/module.h>
0016 #include <linux/interrupt.h>
0017 #include <linux/if_ether.h>
0018 #include <linux/netdevice.h>
0019 #include <linux/slab.h>
0020 #include <linux/string.h>
0021 #include <linux/init.h>
0022 #include <net/net_namespace.h>
0023 #include <net/llc.h>
0024
0025 LIST_HEAD(llc_sap_list);
0026 static DEFINE_SPINLOCK(llc_sap_list_lock);
0027
0028
0029
0030
0031
0032
0033 static struct llc_sap *llc_sap_alloc(void)
0034 {
0035 struct llc_sap *sap = kzalloc(sizeof(*sap), GFP_ATOMIC);
0036 int i;
0037
0038 if (sap) {
0039
0040 sap->state = LLC_SAP_STATE_ACTIVE;
0041 spin_lock_init(&sap->sk_lock);
0042 for (i = 0; i < LLC_SK_LADDR_HASH_ENTRIES; i++)
0043 INIT_HLIST_NULLS_HEAD(&sap->sk_laddr_hash[i], i);
0044 refcount_set(&sap->refcnt, 1);
0045 }
0046 return sap;
0047 }
0048
0049 static struct llc_sap *__llc_sap_find(unsigned char sap_value)
0050 {
0051 struct llc_sap *sap;
0052
0053 list_for_each_entry(sap, &llc_sap_list, node)
0054 if (sap->laddr.lsap == sap_value)
0055 goto out;
0056 sap = NULL;
0057 out:
0058 return sap;
0059 }
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070 struct llc_sap *llc_sap_find(unsigned char sap_value)
0071 {
0072 struct llc_sap *sap;
0073
0074 rcu_read_lock_bh();
0075 sap = __llc_sap_find(sap_value);
0076 if (!sap || !llc_sap_hold_safe(sap))
0077 sap = NULL;
0078 rcu_read_unlock_bh();
0079 return sap;
0080 }
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091 struct llc_sap *llc_sap_open(unsigned char lsap,
0092 int (*func)(struct sk_buff *skb,
0093 struct net_device *dev,
0094 struct packet_type *pt,
0095 struct net_device *orig_dev))
0096 {
0097 struct llc_sap *sap = NULL;
0098
0099 spin_lock_bh(&llc_sap_list_lock);
0100 if (__llc_sap_find(lsap))
0101 goto out;
0102 sap = llc_sap_alloc();
0103 if (!sap)
0104 goto out;
0105 sap->laddr.lsap = lsap;
0106 sap->rcv_func = func;
0107 list_add_tail_rcu(&sap->node, &llc_sap_list);
0108 out:
0109 spin_unlock_bh(&llc_sap_list_lock);
0110 return sap;
0111 }
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122 void llc_sap_close(struct llc_sap *sap)
0123 {
0124 WARN_ON(sap->sk_count);
0125
0126 spin_lock_bh(&llc_sap_list_lock);
0127 list_del_rcu(&sap->node);
0128 spin_unlock_bh(&llc_sap_list_lock);
0129
0130 kfree_rcu(sap, rcu);
0131 }
0132
0133 static struct packet_type llc_packet_type __read_mostly = {
0134 .type = cpu_to_be16(ETH_P_802_2),
0135 .func = llc_rcv,
0136 };
0137
0138 static struct packet_type llc_tr_packet_type __read_mostly = {
0139 .type = cpu_to_be16(ETH_P_TR_802_2),
0140 .func = llc_rcv,
0141 };
0142
0143 static int __init llc_init(void)
0144 {
0145 dev_add_pack(&llc_packet_type);
0146 dev_add_pack(&llc_tr_packet_type);
0147 return 0;
0148 }
0149
0150 static void __exit llc_exit(void)
0151 {
0152 dev_remove_pack(&llc_packet_type);
0153 dev_remove_pack(&llc_tr_packet_type);
0154 }
0155
0156 module_init(llc_init);
0157 module_exit(llc_exit);
0158
0159 EXPORT_SYMBOL(llc_sap_list);
0160 EXPORT_SYMBOL(llc_sap_find);
0161 EXPORT_SYMBOL(llc_sap_open);
0162 EXPORT_SYMBOL(llc_sap_close);
0163
0164 MODULE_LICENSE("GPL");
0165 MODULE_AUTHOR("Procom 1997, Jay Schullist 2001, Arnaldo C. Melo 2001-2003");
0166 MODULE_DESCRIPTION("LLC IEEE 802.2 core support");