xref: /linux/net/llc/llc_core.c (revision 0e59523b440c90ed1899476f32ad4e949282f43e)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * llc_core.c - Minimum needed routines for sap handling and module init/exit
4  *
5  * Copyright (c) 1997 by Procom Technology, Inc.
6  * 		 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
7  */
8 
9 #include <linux/module.h>
10 #include <linux/if_ether.h>
11 #include <linux/netdevice.h>
12 #include <linux/slab.h>
13 #include <linux/init.h>
14 #include <net/llc.h>
15 
16 static LIST_HEAD(llc_sap_list);
17 static DEFINE_SPINLOCK(llc_sap_list_lock);
18 
19 /**
20  *	llc_sap_alloc - allocates and initializes sap.
21  *
22  *	Allocates and initializes sap.
23  */
24 static struct llc_sap *llc_sap_alloc(void)
25 {
26 	struct llc_sap *sap = kzalloc_obj(*sap, GFP_ATOMIC);
27 
28 	if (sap)
29 		refcount_set(&sap->refcnt, 1);
30 	return sap;
31 }
32 
33 static struct llc_sap *__llc_sap_find(unsigned char sap_value)
34 {
35 	struct llc_sap *sap;
36 
37 	list_for_each_entry(sap, &llc_sap_list, node)
38 		if (sap->lsap == sap_value)
39 			goto out;
40 	sap = NULL;
41 out:
42 	return sap;
43 }
44 
45 /**
46  *	llc_sap_find - searches for a SAP by its number
47  *	@sap_value: sap to be found
48  *
49  *	If the sap is found it will be refcounted and the user will have to do
50  *	a llc_sap_put after use.
51  *	Returns the sap or %NULL if not found.
52  */
53 struct llc_sap *llc_sap_find(unsigned char sap_value)
54 {
55 	struct llc_sap *sap;
56 
57 	rcu_read_lock_bh();
58 	sap = __llc_sap_find(sap_value);
59 	if (!sap || !llc_sap_hold_safe(sap))
60 		sap = NULL;
61 	rcu_read_unlock_bh();
62 	return sap;
63 }
64 
65 /**
66  *	llc_sap_open - open interface to the upper layers.
67  *	@lsap: SAP number.
68  *	@func: rcv func for datalink protos
69  *
70  *	Interface function to upper layer. Each one who wants to get a SAP
71  *	(for example NetBEUI) should call this function. Returns the opened
72  *	SAP for success, NULL for failure.
73  */
74 struct llc_sap *llc_sap_open(unsigned char lsap,
75 			     int (*func)(struct sk_buff *skb,
76 					 struct net_device *dev,
77 					 struct packet_type *pt,
78 					 struct net_device *orig_dev))
79 {
80 	struct llc_sap *sap = NULL;
81 
82 	spin_lock_bh(&llc_sap_list_lock);
83 	if (__llc_sap_find(lsap)) /* SAP already exists */
84 		goto out;
85 	sap = llc_sap_alloc();
86 	if (!sap)
87 		goto out;
88 	sap->lsap	= lsap;
89 	sap->rcv_func	= func;
90 	list_add_tail_rcu(&sap->node, &llc_sap_list);
91 out:
92 	spin_unlock_bh(&llc_sap_list_lock);
93 	return sap;
94 }
95 
96 /**
97  *	llc_sap_close - close interface for upper layers.
98  *	@sap: SAP to be closed.
99  *
100  *	Close interface function to upper layer. Each one who wants to
101  *	close an open SAP (for example NetBEUI) should call this function.
102  *	Removes this sap from the SAP list and then frees the memory for it.
103  */
104 void llc_sap_close(struct llc_sap *sap)
105 {
106 	spin_lock_bh(&llc_sap_list_lock);
107 	list_del_rcu(&sap->node);
108 	spin_unlock_bh(&llc_sap_list_lock);
109 
110 	kfree_rcu(sap, rcu);
111 }
112 
113 static struct packet_type llc_packet_type __read_mostly = {
114 	.type = cpu_to_be16(ETH_P_802_2),
115 	.func = llc_rcv,
116 };
117 
118 static int __init llc_init(void)
119 {
120 	dev_add_pack(&llc_packet_type);
121 	return 0;
122 }
123 
124 static void __exit llc_exit(void)
125 {
126 	dev_remove_pack(&llc_packet_type);
127 }
128 
129 module_init(llc_init);
130 module_exit(llc_exit);
131 
132 EXPORT_SYMBOL(llc_sap_open);
133 EXPORT_SYMBOL(llc_sap_close);
134 
135 MODULE_LICENSE("GPL");
136 MODULE_AUTHOR("Procom 1997, Jay Schullist 2001, Arnaldo C. Melo 2001-2003");
137 MODULE_DESCRIPTION("LLC IEEE 802.2 core support");
138