linux/net/llc/llc_core.c
<<
>>
Prefs
   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
  25LIST_HEAD(llc_sap_list);
  26DEFINE_RWLOCK(llc_sap_list_lock);
  27
  28/**
  29 *      llc_sap_alloc - allocates and initializes sap.
  30 *
  31 *      Allocates and initializes sap.
  32 */
  33static struct llc_sap *llc_sap_alloc(void)
  34{
  35        struct llc_sap *sap = kzalloc(sizeof(*sap), GFP_ATOMIC);
  36
  37        if (sap) {
  38                /* sap->laddr.mac - leave as a null, it's filled by bind */
  39                sap->state = LLC_SAP_STATE_ACTIVE;
  40                rwlock_init(&sap->sk_list.lock);
  41                atomic_set(&sap->refcnt, 1);
  42        }
  43        return sap;
  44}
  45
  46/**
  47 *      llc_add_sap - add sap to station list
  48 *      @sap: Address of the sap
  49 *
  50 *      Adds a sap to the LLC's station sap list.
  51 */
  52static void llc_add_sap(struct llc_sap *sap)
  53{
  54        list_add_tail(&sap->node, &llc_sap_list);
  55}
  56
  57/**
  58 *      llc_del_sap - del sap from station list
  59 *      @sap: Address of the sap
  60 *
  61 *      Removes a sap to the LLC's station sap list.
  62 */
  63static void llc_del_sap(struct llc_sap *sap)
  64{
  65        write_lock_bh(&llc_sap_list_lock);
  66        list_del(&sap->node);
  67        write_unlock_bh(&llc_sap_list_lock);
  68}
  69
  70static struct llc_sap *__llc_sap_find(unsigned char sap_value)
  71{
  72        struct llc_sap* sap;
  73
  74        list_for_each_entry(sap, &llc_sap_list, node)
  75                if (sap->laddr.lsap == sap_value)
  76                        goto out;
  77        sap = NULL;
  78out:
  79        return sap;
  80}
  81
  82/**
  83 *      llc_sap_find - searchs a SAP in station
  84 *      @sap_value: sap to be found
  85 *
  86 *      Searchs for a sap in the sap list of the LLC's station upon the sap ID.
  87 *      If the sap is found it will be refcounted and the user will have to do
  88 *      a llc_sap_put after use.
  89 *      Returns the sap or %NULL if not found.
  90 */
  91struct llc_sap *llc_sap_find(unsigned char sap_value)
  92{
  93        struct llc_sap* sap;
  94
  95        read_lock_bh(&llc_sap_list_lock);
  96        sap = __llc_sap_find(sap_value);
  97        if (sap)
  98                llc_sap_hold(sap);
  99        read_unlock_bh(&llc_sap_list_lock);
 100        return sap;
 101}
 102
 103/**
 104 *      llc_sap_open - open interface to the upper layers.
 105 *      @lsap: SAP number.
 106 *      @func: rcv func for datalink protos
 107 *
 108 *      Interface function to upper layer. Each one who wants to get a SAP
 109 *      (for example NetBEUI) should call this function. Returns the opened
 110 *      SAP for success, NULL for failure.
 111 */
 112struct llc_sap *llc_sap_open(unsigned char lsap,
 113                             int (*func)(struct sk_buff *skb,
 114                                         struct net_device *dev,
 115                                         struct packet_type *pt,
 116                                         struct net_device *orig_dev))
 117{
 118        struct llc_sap *sap = NULL;
 119
 120        write_lock_bh(&llc_sap_list_lock);
 121        if (__llc_sap_find(lsap)) /* SAP already exists */
 122                goto out;
 123        sap = llc_sap_alloc();
 124        if (!sap)
 125                goto out;
 126        sap->laddr.lsap = lsap;
 127        sap->rcv_func   = func;
 128        llc_add_sap(sap);
 129out:
 130        write_unlock_bh(&llc_sap_list_lock);
 131        return sap;
 132}
 133
 134/**
 135 *      llc_sap_close - close interface for upper layers.
 136 *      @sap: SAP to be closed.
 137 *
 138 *      Close interface function to upper layer. Each one who wants to
 139 *      close an open SAP (for example NetBEUI) should call this function.
 140 *      Removes this sap from the list of saps in the station and then
 141 *      frees the memory for this sap.
 142 */
 143void llc_sap_close(struct llc_sap *sap)
 144{
 145        WARN_ON(!hlist_empty(&sap->sk_list.list));
 146        llc_del_sap(sap);
 147        kfree(sap);
 148}
 149
 150static struct packet_type llc_packet_type __read_mostly = {
 151        .type = cpu_to_be16(ETH_P_802_2),
 152        .func = llc_rcv,
 153};
 154
 155static struct packet_type llc_tr_packet_type __read_mostly = {
 156        .type = cpu_to_be16(ETH_P_TR_802_2),
 157        .func = llc_rcv,
 158};
 159
 160static int __init llc_init(void)
 161{
 162        struct net_device *dev;
 163
 164        dev = first_net_device(&init_net);
 165        if (dev != NULL)
 166                dev = next_net_device(dev);
 167
 168        dev_add_pack(&llc_packet_type);
 169        dev_add_pack(&llc_tr_packet_type);
 170        return 0;
 171}
 172
 173static void __exit llc_exit(void)
 174{
 175        dev_remove_pack(&llc_packet_type);
 176        dev_remove_pack(&llc_tr_packet_type);
 177}
 178
 179module_init(llc_init);
 180module_exit(llc_exit);
 181
 182EXPORT_SYMBOL(llc_sap_list);
 183EXPORT_SYMBOL(llc_sap_list_lock);
 184EXPORT_SYMBOL(llc_sap_find);
 185EXPORT_SYMBOL(llc_sap_open);
 186EXPORT_SYMBOL(llc_sap_close);
 187
 188MODULE_LICENSE("GPL");
 189MODULE_AUTHOR("Procom 1997, Jay Schullist 2001, Arnaldo C. Melo 2001-2003");
 190MODULE_DESCRIPTION("LLC IEEE 802.2 core support");
 191