Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * llc_core.c - Minimum needed routines for sap handling and module init/exit
0003  *
0004  * Copyright (c) 1997 by Procom Technology, Inc.
0005  *       2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
0006  *
0007  * This program can be redistributed or modified under the terms of the
0008  * GNU General Public License as published by the Free Software Foundation.
0009  * This program is distributed without any warranty or implied warranty
0010  * of merchantability or fitness for a particular purpose.
0011  *
0012  * See the GNU General Public License for more details.
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  *  llc_sap_alloc - allocates and initializes sap.
0030  *
0031  *  Allocates and initializes sap.
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         /* sap->laddr.mac - leave as a null, it's filled by bind */
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  *  llc_sap_find - searches a SAP in station
0063  *  @sap_value: sap to be found
0064  *
0065  *  Searches for a sap in the sap list of the LLC's station upon the sap ID.
0066  *  If the sap is found it will be refcounted and the user will have to do
0067  *  a llc_sap_put after use.
0068  *  Returns the sap or %NULL if not found.
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  *  llc_sap_open - open interface to the upper layers.
0084  *  @lsap: SAP number.
0085  *  @func: rcv func for datalink protos
0086  *
0087  *  Interface function to upper layer. Each one who wants to get a SAP
0088  *  (for example NetBEUI) should call this function. Returns the opened
0089  *  SAP for success, NULL for failure.
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)) /* SAP already exists */
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  *  llc_sap_close - close interface for upper layers.
0115  *  @sap: SAP to be closed.
0116  *
0117  *  Close interface function to upper layer. Each one who wants to
0118  *  close an open SAP (for example NetBEUI) should call this function.
0119  *  Removes this sap from the list of saps in the station and then
0120  *  frees the memory for this sap.
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");