xref: /openbmc/linux/net/ax25/ax25_iface.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or modify
3*1da177e4SLinus Torvalds  * it under the terms of the GNU General Public License as published by
4*1da177e4SLinus Torvalds  * the Free Software Foundation; either version 2 of the License, or
5*1da177e4SLinus Torvalds  * (at your option) any later version.
6*1da177e4SLinus Torvalds  *
7*1da177e4SLinus Torvalds  * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
8*1da177e4SLinus Torvalds  */
9*1da177e4SLinus Torvalds #include <linux/config.h>
10*1da177e4SLinus Torvalds #include <linux/errno.h>
11*1da177e4SLinus Torvalds #include <linux/types.h>
12*1da177e4SLinus Torvalds #include <linux/socket.h>
13*1da177e4SLinus Torvalds #include <linux/in.h>
14*1da177e4SLinus Torvalds #include <linux/kernel.h>
15*1da177e4SLinus Torvalds #include <linux/sched.h>
16*1da177e4SLinus Torvalds #include <linux/spinlock.h>
17*1da177e4SLinus Torvalds #include <linux/timer.h>
18*1da177e4SLinus Torvalds #include <linux/string.h>
19*1da177e4SLinus Torvalds #include <linux/sockios.h>
20*1da177e4SLinus Torvalds #include <linux/net.h>
21*1da177e4SLinus Torvalds #include <net/ax25.h>
22*1da177e4SLinus Torvalds #include <linux/inet.h>
23*1da177e4SLinus Torvalds #include <linux/netdevice.h>
24*1da177e4SLinus Torvalds #include <linux/skbuff.h>
25*1da177e4SLinus Torvalds #include <net/sock.h>
26*1da177e4SLinus Torvalds #include <asm/uaccess.h>
27*1da177e4SLinus Torvalds #include <asm/system.h>
28*1da177e4SLinus Torvalds #include <linux/fcntl.h>
29*1da177e4SLinus Torvalds #include <linux/mm.h>
30*1da177e4SLinus Torvalds #include <linux/interrupt.h>
31*1da177e4SLinus Torvalds 
32*1da177e4SLinus Torvalds static struct protocol_struct {
33*1da177e4SLinus Torvalds 	struct protocol_struct *next;
34*1da177e4SLinus Torvalds 	unsigned int pid;
35*1da177e4SLinus Torvalds 	int (*func)(struct sk_buff *, ax25_cb *);
36*1da177e4SLinus Torvalds } *protocol_list = NULL;
37*1da177e4SLinus Torvalds static DEFINE_RWLOCK(protocol_list_lock);
38*1da177e4SLinus Torvalds 
39*1da177e4SLinus Torvalds static struct linkfail_struct {
40*1da177e4SLinus Torvalds 	struct linkfail_struct *next;
41*1da177e4SLinus Torvalds 	void (*func)(ax25_cb *, int);
42*1da177e4SLinus Torvalds } *linkfail_list = NULL;
43*1da177e4SLinus Torvalds static DEFINE_SPINLOCK(linkfail_lock);
44*1da177e4SLinus Torvalds 
45*1da177e4SLinus Torvalds static struct listen_struct {
46*1da177e4SLinus Torvalds 	struct listen_struct *next;
47*1da177e4SLinus Torvalds 	ax25_address  callsign;
48*1da177e4SLinus Torvalds 	struct net_device *dev;
49*1da177e4SLinus Torvalds } *listen_list = NULL;
50*1da177e4SLinus Torvalds static DEFINE_SPINLOCK(listen_lock);
51*1da177e4SLinus Torvalds 
52*1da177e4SLinus Torvalds int ax25_protocol_register(unsigned int pid,
53*1da177e4SLinus Torvalds 	int (*func)(struct sk_buff *, ax25_cb *))
54*1da177e4SLinus Torvalds {
55*1da177e4SLinus Torvalds 	struct protocol_struct *protocol;
56*1da177e4SLinus Torvalds 
57*1da177e4SLinus Torvalds 	if (pid == AX25_P_TEXT || pid == AX25_P_SEGMENT)
58*1da177e4SLinus Torvalds 		return 0;
59*1da177e4SLinus Torvalds #ifdef CONFIG_INET
60*1da177e4SLinus Torvalds 	if (pid == AX25_P_IP || pid == AX25_P_ARP)
61*1da177e4SLinus Torvalds 		return 0;
62*1da177e4SLinus Torvalds #endif
63*1da177e4SLinus Torvalds 	if ((protocol = kmalloc(sizeof(*protocol), GFP_ATOMIC)) == NULL)
64*1da177e4SLinus Torvalds 		return 0;
65*1da177e4SLinus Torvalds 
66*1da177e4SLinus Torvalds 	protocol->pid  = pid;
67*1da177e4SLinus Torvalds 	protocol->func = func;
68*1da177e4SLinus Torvalds 
69*1da177e4SLinus Torvalds 	write_lock(&protocol_list_lock);
70*1da177e4SLinus Torvalds 	protocol->next = protocol_list;
71*1da177e4SLinus Torvalds 	protocol_list  = protocol;
72*1da177e4SLinus Torvalds 	write_unlock(&protocol_list_lock);
73*1da177e4SLinus Torvalds 
74*1da177e4SLinus Torvalds 	return 1;
75*1da177e4SLinus Torvalds }
76*1da177e4SLinus Torvalds 
77*1da177e4SLinus Torvalds void ax25_protocol_release(unsigned int pid)
78*1da177e4SLinus Torvalds {
79*1da177e4SLinus Torvalds 	struct protocol_struct *s, *protocol;
80*1da177e4SLinus Torvalds 
81*1da177e4SLinus Torvalds 	write_lock(&protocol_list_lock);
82*1da177e4SLinus Torvalds 	protocol = protocol_list;
83*1da177e4SLinus Torvalds 	if (protocol == NULL) {
84*1da177e4SLinus Torvalds 		write_unlock(&protocol_list_lock);
85*1da177e4SLinus Torvalds 		return;
86*1da177e4SLinus Torvalds 	}
87*1da177e4SLinus Torvalds 
88*1da177e4SLinus Torvalds 	if (protocol->pid == pid) {
89*1da177e4SLinus Torvalds 		protocol_list = protocol->next;
90*1da177e4SLinus Torvalds 		write_unlock(&protocol_list_lock);
91*1da177e4SLinus Torvalds 		kfree(protocol);
92*1da177e4SLinus Torvalds 		return;
93*1da177e4SLinus Torvalds 	}
94*1da177e4SLinus Torvalds 
95*1da177e4SLinus Torvalds 	while (protocol != NULL && protocol->next != NULL) {
96*1da177e4SLinus Torvalds 		if (protocol->next->pid == pid) {
97*1da177e4SLinus Torvalds 			s = protocol->next;
98*1da177e4SLinus Torvalds 			protocol->next = protocol->next->next;
99*1da177e4SLinus Torvalds 			write_unlock(&protocol_list_lock);
100*1da177e4SLinus Torvalds 			kfree(s);
101*1da177e4SLinus Torvalds 			return;
102*1da177e4SLinus Torvalds 		}
103*1da177e4SLinus Torvalds 
104*1da177e4SLinus Torvalds 		protocol = protocol->next;
105*1da177e4SLinus Torvalds 	}
106*1da177e4SLinus Torvalds 	write_unlock(&protocol_list_lock);
107*1da177e4SLinus Torvalds }
108*1da177e4SLinus Torvalds 
109*1da177e4SLinus Torvalds int ax25_linkfail_register(void (*func)(ax25_cb *, int))
110*1da177e4SLinus Torvalds {
111*1da177e4SLinus Torvalds 	struct linkfail_struct *linkfail;
112*1da177e4SLinus Torvalds 
113*1da177e4SLinus Torvalds 	if ((linkfail = kmalloc(sizeof(*linkfail), GFP_ATOMIC)) == NULL)
114*1da177e4SLinus Torvalds 		return 0;
115*1da177e4SLinus Torvalds 
116*1da177e4SLinus Torvalds 	linkfail->func = func;
117*1da177e4SLinus Torvalds 
118*1da177e4SLinus Torvalds 	spin_lock_bh(&linkfail_lock);
119*1da177e4SLinus Torvalds 	linkfail->next = linkfail_list;
120*1da177e4SLinus Torvalds 	linkfail_list  = linkfail;
121*1da177e4SLinus Torvalds 	spin_unlock_bh(&linkfail_lock);
122*1da177e4SLinus Torvalds 
123*1da177e4SLinus Torvalds 	return 1;
124*1da177e4SLinus Torvalds }
125*1da177e4SLinus Torvalds 
126*1da177e4SLinus Torvalds void ax25_linkfail_release(void (*func)(ax25_cb *, int))
127*1da177e4SLinus Torvalds {
128*1da177e4SLinus Torvalds 	struct linkfail_struct *s, *linkfail;
129*1da177e4SLinus Torvalds 
130*1da177e4SLinus Torvalds 	spin_lock_bh(&linkfail_lock);
131*1da177e4SLinus Torvalds 	linkfail = linkfail_list;
132*1da177e4SLinus Torvalds 	if (linkfail == NULL) {
133*1da177e4SLinus Torvalds 		spin_unlock_bh(&linkfail_lock);
134*1da177e4SLinus Torvalds 		return;
135*1da177e4SLinus Torvalds 	}
136*1da177e4SLinus Torvalds 
137*1da177e4SLinus Torvalds 	if (linkfail->func == func) {
138*1da177e4SLinus Torvalds 		linkfail_list = linkfail->next;
139*1da177e4SLinus Torvalds 		spin_unlock_bh(&linkfail_lock);
140*1da177e4SLinus Torvalds 		kfree(linkfail);
141*1da177e4SLinus Torvalds 		return;
142*1da177e4SLinus Torvalds 	}
143*1da177e4SLinus Torvalds 
144*1da177e4SLinus Torvalds 	while (linkfail != NULL && linkfail->next != NULL) {
145*1da177e4SLinus Torvalds 		if (linkfail->next->func == func) {
146*1da177e4SLinus Torvalds 			s = linkfail->next;
147*1da177e4SLinus Torvalds 			linkfail->next = linkfail->next->next;
148*1da177e4SLinus Torvalds 			spin_unlock_bh(&linkfail_lock);
149*1da177e4SLinus Torvalds 			kfree(s);
150*1da177e4SLinus Torvalds 			return;
151*1da177e4SLinus Torvalds 		}
152*1da177e4SLinus Torvalds 
153*1da177e4SLinus Torvalds 		linkfail = linkfail->next;
154*1da177e4SLinus Torvalds 	}
155*1da177e4SLinus Torvalds 	spin_unlock_bh(&linkfail_lock);
156*1da177e4SLinus Torvalds }
157*1da177e4SLinus Torvalds 
158*1da177e4SLinus Torvalds int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
159*1da177e4SLinus Torvalds {
160*1da177e4SLinus Torvalds 	struct listen_struct *listen;
161*1da177e4SLinus Torvalds 
162*1da177e4SLinus Torvalds 	if (ax25_listen_mine(callsign, dev))
163*1da177e4SLinus Torvalds 		return 0;
164*1da177e4SLinus Torvalds 
165*1da177e4SLinus Torvalds 	if ((listen = kmalloc(sizeof(*listen), GFP_ATOMIC)) == NULL)
166*1da177e4SLinus Torvalds 		return 0;
167*1da177e4SLinus Torvalds 
168*1da177e4SLinus Torvalds 	listen->callsign = *callsign;
169*1da177e4SLinus Torvalds 	listen->dev      = dev;
170*1da177e4SLinus Torvalds 
171*1da177e4SLinus Torvalds 	spin_lock_bh(&listen_lock);
172*1da177e4SLinus Torvalds 	listen->next = listen_list;
173*1da177e4SLinus Torvalds 	listen_list  = listen;
174*1da177e4SLinus Torvalds 	spin_unlock_bh(&listen_lock);
175*1da177e4SLinus Torvalds 
176*1da177e4SLinus Torvalds 	return 1;
177*1da177e4SLinus Torvalds }
178*1da177e4SLinus Torvalds 
179*1da177e4SLinus Torvalds void ax25_listen_release(ax25_address *callsign, struct net_device *dev)
180*1da177e4SLinus Torvalds {
181*1da177e4SLinus Torvalds 	struct listen_struct *s, *listen;
182*1da177e4SLinus Torvalds 
183*1da177e4SLinus Torvalds 	spin_lock_bh(&listen_lock);
184*1da177e4SLinus Torvalds 	listen = listen_list;
185*1da177e4SLinus Torvalds 	if (listen == NULL) {
186*1da177e4SLinus Torvalds 		spin_unlock_bh(&listen_lock);
187*1da177e4SLinus Torvalds 		return;
188*1da177e4SLinus Torvalds 	}
189*1da177e4SLinus Torvalds 
190*1da177e4SLinus Torvalds 	if (ax25cmp(&listen->callsign, callsign) == 0 && listen->dev == dev) {
191*1da177e4SLinus Torvalds 		listen_list = listen->next;
192*1da177e4SLinus Torvalds 		spin_unlock_bh(&listen_lock);
193*1da177e4SLinus Torvalds 		kfree(listen);
194*1da177e4SLinus Torvalds 		return;
195*1da177e4SLinus Torvalds 	}
196*1da177e4SLinus Torvalds 
197*1da177e4SLinus Torvalds 	while (listen != NULL && listen->next != NULL) {
198*1da177e4SLinus Torvalds 		if (ax25cmp(&listen->next->callsign, callsign) == 0 && listen->next->dev == dev) {
199*1da177e4SLinus Torvalds 			s = listen->next;
200*1da177e4SLinus Torvalds 			listen->next = listen->next->next;
201*1da177e4SLinus Torvalds 			spin_unlock_bh(&listen_lock);
202*1da177e4SLinus Torvalds 			kfree(s);
203*1da177e4SLinus Torvalds 			return;
204*1da177e4SLinus Torvalds 		}
205*1da177e4SLinus Torvalds 
206*1da177e4SLinus Torvalds 		listen = listen->next;
207*1da177e4SLinus Torvalds 	}
208*1da177e4SLinus Torvalds 	spin_unlock_bh(&listen_lock);
209*1da177e4SLinus Torvalds }
210*1da177e4SLinus Torvalds 
211*1da177e4SLinus Torvalds int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *)
212*1da177e4SLinus Torvalds {
213*1da177e4SLinus Torvalds 	int (*res)(struct sk_buff *, ax25_cb *) = NULL;
214*1da177e4SLinus Torvalds 	struct protocol_struct *protocol;
215*1da177e4SLinus Torvalds 
216*1da177e4SLinus Torvalds 	read_lock(&protocol_list_lock);
217*1da177e4SLinus Torvalds 	for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
218*1da177e4SLinus Torvalds 		if (protocol->pid == pid) {
219*1da177e4SLinus Torvalds 			res = protocol->func;
220*1da177e4SLinus Torvalds 			break;
221*1da177e4SLinus Torvalds 		}
222*1da177e4SLinus Torvalds 	read_unlock(&protocol_list_lock);
223*1da177e4SLinus Torvalds 
224*1da177e4SLinus Torvalds 	return res;
225*1da177e4SLinus Torvalds }
226*1da177e4SLinus Torvalds 
227*1da177e4SLinus Torvalds int ax25_listen_mine(ax25_address *callsign, struct net_device *dev)
228*1da177e4SLinus Torvalds {
229*1da177e4SLinus Torvalds 	struct listen_struct *listen;
230*1da177e4SLinus Torvalds 
231*1da177e4SLinus Torvalds 	spin_lock_bh(&listen_lock);
232*1da177e4SLinus Torvalds 	for (listen = listen_list; listen != NULL; listen = listen->next)
233*1da177e4SLinus Torvalds 		if (ax25cmp(&listen->callsign, callsign) == 0 && (listen->dev == dev || listen->dev == NULL)) {
234*1da177e4SLinus Torvalds 			spin_unlock_bh(&listen_lock);
235*1da177e4SLinus Torvalds 			return 1;
236*1da177e4SLinus Torvalds 	}
237*1da177e4SLinus Torvalds 	spin_unlock_bh(&listen_lock);
238*1da177e4SLinus Torvalds 
239*1da177e4SLinus Torvalds 	return 0;
240*1da177e4SLinus Torvalds }
241*1da177e4SLinus Torvalds 
242*1da177e4SLinus Torvalds void ax25_link_failed(ax25_cb *ax25, int reason)
243*1da177e4SLinus Torvalds {
244*1da177e4SLinus Torvalds 	struct linkfail_struct *linkfail;
245*1da177e4SLinus Torvalds 
246*1da177e4SLinus Torvalds 	spin_lock_bh(&linkfail_lock);
247*1da177e4SLinus Torvalds 	for (linkfail = linkfail_list; linkfail != NULL; linkfail = linkfail->next)
248*1da177e4SLinus Torvalds 		(linkfail->func)(ax25, reason);
249*1da177e4SLinus Torvalds 	spin_unlock_bh(&linkfail_lock);
250*1da177e4SLinus Torvalds }
251*1da177e4SLinus Torvalds 
252*1da177e4SLinus Torvalds int ax25_protocol_is_registered(unsigned int pid)
253*1da177e4SLinus Torvalds {
254*1da177e4SLinus Torvalds 	struct protocol_struct *protocol;
255*1da177e4SLinus Torvalds 	int res = 0;
256*1da177e4SLinus Torvalds 
257*1da177e4SLinus Torvalds 	read_lock(&protocol_list_lock);
258*1da177e4SLinus Torvalds 	for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
259*1da177e4SLinus Torvalds 		if (protocol->pid == pid) {
260*1da177e4SLinus Torvalds 			res = 1;
261*1da177e4SLinus Torvalds 			break;
262*1da177e4SLinus Torvalds 		}
263*1da177e4SLinus Torvalds 	read_unlock(&protocol_list_lock);
264*1da177e4SLinus Torvalds 
265*1da177e4SLinus Torvalds 	return res;
266*1da177e4SLinus Torvalds }
267