Blame view

net/ax25/ax25_iface.c 4.69 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
5
   *
   * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
10
  #include <linux/errno.h>
  #include <linux/types.h>
  #include <linux/socket.h>
  #include <linux/in.h>
  #include <linux/kernel.h>
70868eace   Ralf Baechle   [AX.25]: Move AX....
11
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
  #include <linux/spinlock.h>
  #include <linux/timer.h>
  #include <linux/string.h>
  #include <linux/sockios.h>
  #include <linux/net.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
17
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
22
  #include <net/ax25.h>
  #include <linux/inet.h>
  #include <linux/netdevice.h>
  #include <linux/skbuff.h>
  #include <net/sock.h>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
23
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
  #include <linux/fcntl.h>
  #include <linux/mm.h>
  #include <linux/interrupt.h>
8d5cf596d   Ralf Baechle   [AX.25]: Fix unch...
27
  static struct ax25_protocol *protocol_list;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  static DEFINE_RWLOCK(protocol_list_lock);
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
29
  static HLIST_HEAD(ax25_linkfail_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
33
34
35
36
37
  static DEFINE_SPINLOCK(linkfail_lock);
  
  static struct listen_struct {
  	struct listen_struct *next;
  	ax25_address  callsign;
  	struct net_device *dev;
  } *listen_list = NULL;
  static DEFINE_SPINLOCK(listen_lock);
8d5cf596d   Ralf Baechle   [AX.25]: Fix unch...
38
39
40
41
42
  /*
   * Do not register the internal protocols AX25_P_TEXT, AX25_P_SEGMENT,
   * AX25_P_IP or AX25_P_ARP ...
   */
  void ax25_register_pid(struct ax25_protocol *ap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
  {
95ff9f4d3   Ralf Baechle   [AX.25]: Fix lock...
44
  	write_lock_bh(&protocol_list_lock);
8d5cf596d   Ralf Baechle   [AX.25]: Fix unch...
45
46
  	ap->next = protocol_list;
  	protocol_list = ap;
95ff9f4d3   Ralf Baechle   [AX.25]: Fix lock...
47
  	write_unlock_bh(&protocol_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
  }
8d5cf596d   Ralf Baechle   [AX.25]: Fix unch...
49
  EXPORT_SYMBOL_GPL(ax25_register_pid);
70868eace   Ralf Baechle   [AX.25]: Move AX....
50

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
  void ax25_protocol_release(unsigned int pid)
  {
d8f969e60   David S. Miller   ax25: Fix set-but...
53
  	struct ax25_protocol *protocol;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54

95ff9f4d3   Ralf Baechle   [AX.25]: Fix lock...
55
  	write_lock_bh(&protocol_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
  	protocol = protocol_list;
910d30b70   Ilpo Järvinen   ax25: more common...
57
58
  	if (protocol == NULL)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
  
  	if (protocol->pid == pid) {
  		protocol_list = protocol->next;
910d30b70   Ilpo Järvinen   ax25: more common...
62
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
64
65
66
  	}
  
  	while (protocol != NULL && protocol->next != NULL) {
  		if (protocol->next->pid == pid) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
  			protocol->next = protocol->next->next;
910d30b70   Ilpo Järvinen   ax25: more common...
68
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
71
72
  		}
  
  		protocol = protocol->next;
  	}
910d30b70   Ilpo Järvinen   ax25: more common...
73
  out:
95ff9f4d3   Ralf Baechle   [AX.25]: Fix lock...
74
  	write_unlock_bh(&protocol_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
76
  EXPORT_SYMBOL(ax25_protocol_release);
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
77
  void ax25_linkfail_register(struct ax25_linkfail *lf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
  	spin_lock_bh(&linkfail_lock);
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
80
  	hlist_add_head(&lf->lf_node, &ax25_linkfail_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
  	spin_unlock_bh(&linkfail_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
83
  EXPORT_SYMBOL(ax25_linkfail_register);
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
84
  void ax25_linkfail_release(struct ax25_linkfail *lf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
  	spin_lock_bh(&linkfail_lock);
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
87
  	hlist_del_init(&lf->lf_node);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
  	spin_unlock_bh(&linkfail_lock);
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
90
  EXPORT_SYMBOL(ax25_linkfail_release);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
93
94
95
96
97
98
  int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
  {
  	struct listen_struct *listen;
  
  	if (ax25_listen_mine(callsign, dev))
  		return 0;
  
  	if ((listen = kmalloc(sizeof(*listen), GFP_ATOMIC)) == NULL)
81dcd1690   Ralf Baechle   [AX.25]: Fix unch...
99
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
103
104
105
106
107
  
  	listen->callsign = *callsign;
  	listen->dev      = dev;
  
  	spin_lock_bh(&listen_lock);
  	listen->next = listen_list;
  	listen_list  = listen;
  	spin_unlock_bh(&listen_lock);
81dcd1690   Ralf Baechle   [AX.25]: Fix unch...
108
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
110
  EXPORT_SYMBOL(ax25_listen_register);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
  void ax25_listen_release(ax25_address *callsign, struct net_device *dev)
  {
  	struct listen_struct *s, *listen;
  
  	spin_lock_bh(&listen_lock);
  	listen = listen_list;
  	if (listen == NULL) {
  		spin_unlock_bh(&listen_lock);
  		return;
  	}
  
  	if (ax25cmp(&listen->callsign, callsign) == 0 && listen->dev == dev) {
  		listen_list = listen->next;
  		spin_unlock_bh(&listen_lock);
  		kfree(listen);
  		return;
  	}
  
  	while (listen != NULL && listen->next != NULL) {
  		if (ax25cmp(&listen->next->callsign, callsign) == 0 && listen->next->dev == dev) {
  			s = listen->next;
  			listen->next = listen->next->next;
  			spin_unlock_bh(&listen_lock);
  			kfree(s);
  			return;
  		}
  
  		listen = listen->next;
  	}
  	spin_unlock_bh(&listen_lock);
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
142
  EXPORT_SYMBOL(ax25_listen_release);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
144
145
  int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *)
  {
  	int (*res)(struct sk_buff *, ax25_cb *) = NULL;
8d5cf596d   Ralf Baechle   [AX.25]: Fix unch...
146
  	struct ax25_protocol *protocol;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
  
  	read_lock(&protocol_list_lock);
  	for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
  		if (protocol->pid == pid) {
  			res = protocol->func;
  			break;
  		}
  	read_unlock(&protocol_list_lock);
  
  	return res;
  }
  
  int ax25_listen_mine(ax25_address *callsign, struct net_device *dev)
  {
  	struct listen_struct *listen;
  
  	spin_lock_bh(&listen_lock);
  	for (listen = listen_list; listen != NULL; listen = listen->next)
81dcd1690   Ralf Baechle   [AX.25]: Fix unch...
165
166
  		if (ax25cmp(&listen->callsign, callsign) == 0 &&
  		    (listen->dev == dev || listen->dev == NULL)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
168
169
170
171
172
173
174
175
176
  			spin_unlock_bh(&listen_lock);
  			return 1;
  	}
  	spin_unlock_bh(&listen_lock);
  
  	return 0;
  }
  
  void ax25_link_failed(ax25_cb *ax25, int reason)
  {
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
177
  	struct ax25_linkfail *lf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
  
  	spin_lock_bh(&linkfail_lock);
b67bfe0d4   Sasha Levin   hlist: drop the n...
180
  	hlist_for_each_entry(lf, &ax25_linkfail_list, lf_node)
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
181
  		lf->func(ax25, reason);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
183
184
185
186
  	spin_unlock_bh(&linkfail_lock);
  }
  
  int ax25_protocol_is_registered(unsigned int pid)
  {
8d5cf596d   Ralf Baechle   [AX.25]: Fix unch...
187
  	struct ax25_protocol *protocol;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
  	int res = 0;
95ff9f4d3   Ralf Baechle   [AX.25]: Fix lock...
189
  	read_lock_bh(&protocol_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
191
192
193
194
  	for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
  		if (protocol->pid == pid) {
  			res = 1;
  			break;
  		}
95ff9f4d3   Ralf Baechle   [AX.25]: Fix lock...
195
  	read_unlock_bh(&protocol_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
197
198
  
  	return res;
  }