aboutsummaryrefslogtreecommitdiffstats
path: root/net/ax25
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /net/ax25
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'net/ax25')
-rw-r--r--net/ax25/Kconfig110
-rw-r--r--net/ax25/Makefile11
-rw-r--r--net/ax25/TODO24
-rw-r--r--net/ax25/af_ax25.c2050
-rw-r--r--net/ax25/ax25_addr.c290
-rw-r--r--net/ax25/ax25_dev.c208
-rw-r--r--net/ax25/ax25_ds_in.c305
-rw-r--r--net/ax25/ax25_ds_subr.c212
-rw-r--r--net/ax25/ax25_ds_timer.c241
-rw-r--r--net/ax25/ax25_iface.c266
-rw-r--r--net/ax25/ax25_in.c470
-rw-r--r--net/ax25/ax25_ip.c225
-rw-r--r--net/ax25/ax25_out.c383
-rw-r--r--net/ax25/ax25_route.c534
-rw-r--r--net/ax25/ax25_std_in.c449
-rw-r--r--net/ax25/ax25_std_subr.c88
-rw-r--r--net/ax25/ax25_std_timer.c177
-rw-r--r--net/ax25/ax25_subr.c295
-rw-r--r--net/ax25/ax25_timer.c243
-rw-r--r--net/ax25/ax25_uid.c228
-rw-r--r--net/ax25/sysctl_net_ax25.c262
21 files changed, 7071 insertions, 0 deletions
diff --git a/net/ax25/Kconfig b/net/ax25/Kconfig
new file mode 100644
index 000000000000..a8993a041724
--- /dev/null
+++ b/net/ax25/Kconfig
@@ -0,0 +1,110 @@
1#
2# Amateur Radio protocols and AX.25 device configuration
3#
4# 19971130 Now in an own category to make correct compilation of the
5# AX.25 stuff easier...
6# Joerg Reuter DL1BKE <jreuter@yaina.de>
7# 19980129 Moved to net/ax25/Config.in, sourcing device drivers.
8
9menuconfig HAMRADIO
10 depends on NET
11 bool "Amateur Radio support"
12 help
13 If you want to connect your Linux box to an amateur radio, answer Y
14 here. You want to read <http://www.tapr.org/tapr/html/pkthome.html> and
15 the AX25-HOWTO, available from <http://www.tldp.org/docs.html#howto>.
16
17 Note that the answer to this question won't directly affect the
18 kernel: saying N will just cause the configurator to skip all
19 the questions about amateur radio.
20
21comment "Packet Radio protocols"
22 depends on HAMRADIO && NET
23
24config AX25
25 tristate "Amateur Radio AX.25 Level 2 protocol"
26 depends on HAMRADIO && NET
27 ---help---
28 This is the protocol used for computer communication over amateur
29 radio. It is either used by itself for point-to-point links, or to
30 carry other protocols such as tcp/ip. To use it, you need a device
31 that connects your Linux box to your amateur radio. You can either
32 use a low speed TNC (a Terminal Node Controller acts as a kind of
33 modem connecting your computer's serial port to your radio's
34 microphone input and speaker output) supporting the KISS protocol or
35 one of the various SCC cards that are supported by the generic Z8530
36 or the DMA SCC driver. Another option are the Baycom modem serial
37 and parallel port hacks or the sound card modem (supported by their
38 own drivers). If you say Y here, you also have to say Y to one of
39 those drivers.
40
41 Information about where to get supporting software for Linux amateur
42 radio as well as information about how to configure an AX.25 port is
43 contained in the AX25-HOWTO, available from
44 <http://www.tldp.org/docs.html#howto>. You might also want to
45 check out the file <file:Documentation/networking/ax25.txt> in the
46 kernel source. More information about digital amateur radio in
47 general is on the WWW at
48 <http://www.tapr.org/tapr/html/pkthome.html>.
49
50 To compile this driver as a module, choose M here: the
51 module will be called ax25.
52
53config AX25_DAMA_SLAVE
54 bool "AX.25 DAMA Slave support"
55 depends on AX25
56 help
57 DAMA is a mechanism to prevent collisions when doing AX.25
58 networking. A DAMA server (called "master") accepts incoming traffic
59 from clients (called "slaves") and redistributes it to other slaves.
60 If you say Y here, your Linux box will act as a DAMA slave; this is
61 transparent in that you don't have to do any special DAMA
62 configuration. (Linux cannot yet act as a DAMA server.) If unsure,
63 say N.
64
65# bool ' AX.25 DAMA Master support' CONFIG_AX25_DAMA_MASTER
66config NETROM
67 tristate "Amateur Radio NET/ROM protocol"
68 depends on AX25
69 ---help---
70 NET/ROM is a network layer protocol on top of AX.25 useful for
71 routing.
72
73 A comprehensive listing of all the software for Linux amateur radio
74 users as well as information about how to configure an AX.25 port is
75 contained in the AX25-HOWTO, available from
76 <http://www.tldp.org/docs.html#howto>. You also might want to
77 check out the file <file:Documentation/networking/ax25.txt>. More
78 information about digital amateur radio in general is on the WWW at
79 <http://www.tapr.org/tapr/html/pkthome.html>.
80
81 To compile this driver as a module, choose M here: the
82 module will be called netrom.
83
84config ROSE
85 tristate "Amateur Radio X.25 PLP (Rose)"
86 depends on AX25
87 ---help---
88 The Packet Layer Protocol (PLP) is a way to route packets over X.25
89 connections in general and amateur radio AX.25 connections in
90 particular, essentially an alternative to NET/ROM.
91
92 A comprehensive listing of all the software for Linux amateur radio
93 users as well as information about how to configure an AX.25 port is
94 contained in the AX25-HOWTO, available from
95 <http://www.tldp.org/docs.html#howto>. You also might want to
96 check out the file <file:Documentation/networking/ax25.txt>. More
97 information about digital amateur radio in general is on the WWW at
98 <http://www.tapr.org/tapr/html/pkthome.html>.
99
100 To compile this driver as a module, choose M here: the
101 module will be called rose.
102
103
104menu "AX.25 network device drivers"
105 depends on HAMRADIO && NET && AX25!=n
106
107source "drivers/net/hamradio/Kconfig"
108
109endmenu
110
diff --git a/net/ax25/Makefile b/net/ax25/Makefile
new file mode 100644
index 000000000000..43c46d2cafb6
--- /dev/null
+++ b/net/ax25/Makefile
@@ -0,0 +1,11 @@
1#
2# Makefile for the Linux AX.25 layer.
3#
4
5obj-$(CONFIG_AX25) += ax25.o
6
7ax25-y := ax25_addr.o ax25_dev.o ax25_iface.o ax25_in.o ax25_ip.o ax25_out.o \
8 ax25_route.o ax25_std_in.o ax25_std_subr.o ax25_std_timer.o \
9 ax25_subr.o ax25_timer.o ax25_uid.o af_ax25.o
10ax25-$(CONFIG_AX25_DAMA_SLAVE) += ax25_ds_in.o ax25_ds_subr.o ax25_ds_timer.o
11ax25-$(CONFIG_SYSCTL) += sysctl_net_ax25.o
diff --git a/net/ax25/TODO b/net/ax25/TODO
new file mode 100644
index 000000000000..4089c49e45cc
--- /dev/null
+++ b/net/ax25/TODO
@@ -0,0 +1,24 @@
1Do the ax25_list_lock, ax25_dev_lock, linkfail_lockreally, ax25_frag_lock and
2listen_lock have to be bh-safe?
3
4Do the netrom and rose locks have to be bh-safe?
5
6A device might be deleted after lookup in the SIOCADDRT ioctl but before it's
7being used.
8
9Routes to a device being taken down might be deleted by ax25_rt_device_down
10but added by somebody else before the device has been deleted fully.
11
12Massive amounts of lock_kernel / unlock_kernel are just a temporary solution to
13get around the removal of SOCKOPS_WRAP. A serious locking strategy has to be
14implemented.
15
16The ax25_rt_find_route synopsys is pervert but I somehow had to deal with
17the race caused by the static variable in it's previous implementation.
18
19Implement proper socket locking in netrom and rose.
20
21Check socket locking when ax25_rcv is sending to raw sockets. In particular
22ax25_send_to_raw() seems fishy. Heck - ax25_rcv is fishy.
23
24Handle XID and TEST frames properly.
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
new file mode 100644
index 000000000000..33b1a3763027
--- /dev/null
+++ b/net/ax25/af_ax25.c
@@ -0,0 +1,2050 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
8 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
9 * Copyright (C) Darryl Miles G7LED (dlm@g7led.demon.co.uk)
10 * Copyright (C) Steven Whitehouse GW7RRM (stevew@acm.org)
11 * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
12 * Copyright (C) Hans-Joachim Hetscher DD8NE (dd8ne@bnv-bamberg.de)
13 * Copyright (C) Hans Alblas PE1AYX (hans@esrac.ele.tue.nl)
14 * Copyright (C) Frederic Rible F1OAT (frible@teaser.fr)
15 */
16#include <linux/config.h>
17#include <linux/module.h>
18#include <linux/errno.h>
19#include <linux/types.h>
20#include <linux/socket.h>
21#include <linux/in.h>
22#include <linux/kernel.h>
23#include <linux/sched.h>
24#include <linux/timer.h>
25#include <linux/string.h>
26#include <linux/smp_lock.h>
27#include <linux/sockios.h>
28#include <linux/net.h>
29#include <net/ax25.h>
30#include <linux/inet.h>
31#include <linux/netdevice.h>
32#include <linux/if_arp.h>
33#include <linux/skbuff.h>
34#include <net/sock.h>
35#include <asm/uaccess.h>
36#include <asm/system.h>
37#include <linux/fcntl.h>
38#include <linux/termios.h> /* For TIOCINQ/OUTQ */
39#include <linux/mm.h>
40#include <linux/interrupt.h>
41#include <linux/notifier.h>
42#include <linux/proc_fs.h>
43#include <linux/stat.h>
44#include <linux/netfilter.h>
45#include <linux/sysctl.h>
46#include <linux/init.h>
47#include <linux/spinlock.h>
48#include <net/tcp.h>
49#include <net/ip.h>
50#include <net/arp.h>
51
52
53
54HLIST_HEAD(ax25_list);
55DEFINE_SPINLOCK(ax25_list_lock);
56
57static struct proto_ops ax25_proto_ops;
58
59static void ax25_free_sock(struct sock *sk)
60{
61 ax25_cb_put(ax25_sk(sk));
62}
63
64/*
65 * Socket removal during an interrupt is now safe.
66 */
67static void ax25_cb_del(ax25_cb *ax25)
68{
69 if (!hlist_unhashed(&ax25->ax25_node)) {
70 spin_lock_bh(&ax25_list_lock);
71 hlist_del_init(&ax25->ax25_node);
72 spin_unlock_bh(&ax25_list_lock);
73 ax25_cb_put(ax25);
74 }
75}
76
77/*
78 * Kill all bound sockets on a dropped device.
79 */
80static void ax25_kill_by_device(struct net_device *dev)
81{
82 ax25_dev *ax25_dev;
83 ax25_cb *s;
84 struct hlist_node *node;
85
86 if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
87 return;
88
89 spin_lock_bh(&ax25_list_lock);
90 ax25_for_each(s, node, &ax25_list) {
91 if (s->ax25_dev == ax25_dev) {
92 s->ax25_dev = NULL;
93 ax25_disconnect(s, ENETUNREACH);
94 }
95 }
96 spin_unlock_bh(&ax25_list_lock);
97}
98
99/*
100 * Handle device status changes.
101 */
102static int ax25_device_event(struct notifier_block *this, unsigned long event,
103 void *ptr)
104{
105 struct net_device *dev = (struct net_device *)ptr;
106
107 /* Reject non AX.25 devices */
108 if (dev->type != ARPHRD_AX25)
109 return NOTIFY_DONE;
110
111 switch (event) {
112 case NETDEV_UP:
113 ax25_dev_device_up(dev);
114 break;
115 case NETDEV_DOWN:
116 ax25_kill_by_device(dev);
117 ax25_rt_device_down(dev);
118 ax25_dev_device_down(dev);
119 break;
120 default:
121 break;
122 }
123
124 return NOTIFY_DONE;
125}
126
127/*
128 * Add a socket to the bound sockets list.
129 */
130void ax25_cb_add(ax25_cb *ax25)
131{
132 spin_lock_bh(&ax25_list_lock);
133 ax25_cb_hold(ax25);
134 hlist_add_head(&ax25->ax25_node, &ax25_list);
135 spin_unlock_bh(&ax25_list_lock);
136}
137
138/*
139 * Find a socket that wants to accept the SABM we have just
140 * received.
141 */
142struct sock *ax25_find_listener(ax25_address *addr, int digi,
143 struct net_device *dev, int type)
144{
145 ax25_cb *s;
146 struct hlist_node *node;
147
148 spin_lock_bh(&ax25_list_lock);
149 ax25_for_each(s, node, &ax25_list) {
150 if ((s->iamdigi && !digi) || (!s->iamdigi && digi))
151 continue;
152 if (s->sk && !ax25cmp(&s->source_addr, addr) &&
153 s->sk->sk_type == type && s->sk->sk_state == TCP_LISTEN) {
154 /* If device is null we match any device */
155 if (s->ax25_dev == NULL || s->ax25_dev->dev == dev) {
156 sock_hold(s->sk);
157 spin_unlock_bh(&ax25_list_lock);
158 return s->sk;
159 }
160 }
161 }
162 spin_unlock_bh(&ax25_list_lock);
163
164 return NULL;
165}
166
167/*
168 * Find an AX.25 socket given both ends.
169 */
170struct sock *ax25_get_socket(ax25_address *my_addr, ax25_address *dest_addr,
171 int type)
172{
173 struct sock *sk = NULL;
174 ax25_cb *s;
175 struct hlist_node *node;
176
177 spin_lock_bh(&ax25_list_lock);
178 ax25_for_each(s, node, &ax25_list) {
179 if (s->sk && !ax25cmp(&s->source_addr, my_addr) &&
180 !ax25cmp(&s->dest_addr, dest_addr) &&
181 s->sk->sk_type == type) {
182 sk = s->sk;
183 sock_hold(sk);
184 break;
185 }
186 }
187
188 spin_unlock_bh(&ax25_list_lock);
189
190 return sk;
191}
192
193/*
194 * Find an AX.25 control block given both ends. It will only pick up
195 * floating AX.25 control blocks or non Raw socket bound control blocks.
196 */
197ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr,
198 ax25_digi *digi, struct net_device *dev)
199{
200 ax25_cb *s;
201 struct hlist_node *node;
202
203 spin_lock_bh(&ax25_list_lock);
204 ax25_for_each(s, node, &ax25_list) {
205 if (s->sk && s->sk->sk_type != SOCK_SEQPACKET)
206 continue;
207 if (s->ax25_dev == NULL)
208 continue;
209 if (ax25cmp(&s->source_addr, src_addr) == 0 && ax25cmp(&s->dest_addr, dest_addr) == 0 && s->ax25_dev->dev == dev) {
210 if (digi != NULL && digi->ndigi != 0) {
211 if (s->digipeat == NULL)
212 continue;
213 if (ax25digicmp(s->digipeat, digi) != 0)
214 continue;
215 } else {
216 if (s->digipeat != NULL && s->digipeat->ndigi != 0)
217 continue;
218 }
219 ax25_cb_hold(s);
220 spin_unlock_bh(&ax25_list_lock);
221
222 return s;
223 }
224 }
225 spin_unlock_bh(&ax25_list_lock);
226
227 return NULL;
228}
229
230void ax25_send_to_raw(ax25_address *addr, struct sk_buff *skb, int proto)
231{
232 ax25_cb *s;
233 struct sk_buff *copy;
234 struct hlist_node *node;
235
236 spin_lock_bh(&ax25_list_lock);
237 ax25_for_each(s, node, &ax25_list) {
238 if (s->sk != NULL && ax25cmp(&s->source_addr, addr) == 0 &&
239 s->sk->sk_type == SOCK_RAW &&
240 s->sk->sk_protocol == proto &&
241 s->ax25_dev->dev == skb->dev &&
242 atomic_read(&s->sk->sk_rmem_alloc) <= s->sk->sk_rcvbuf) {
243 if ((copy = skb_clone(skb, GFP_ATOMIC)) == NULL)
244 continue;
245 if (sock_queue_rcv_skb(s->sk, copy) != 0)
246 kfree_skb(copy);
247 }
248 }
249 spin_unlock_bh(&ax25_list_lock);
250}
251
252/*
253 * Deferred destroy.
254 */
255void ax25_destroy_socket(ax25_cb *);
256
257/*
258 * Handler for deferred kills.
259 */
260static void ax25_destroy_timer(unsigned long data)
261{
262 ax25_cb *ax25=(ax25_cb *)data;
263 struct sock *sk;
264
265 sk=ax25->sk;
266
267 bh_lock_sock(sk);
268 sock_hold(sk);
269 ax25_destroy_socket(ax25);
270 bh_unlock_sock(sk);
271 sock_put(sk);
272}
273
274/*
275 * This is called from user mode and the timers. Thus it protects itself
276 * against interrupt users but doesn't worry about being called during
277 * work. Once it is removed from the queue no interrupt or bottom half
278 * will touch it and we are (fairly 8-) ) safe.
279 */
280void ax25_destroy_socket(ax25_cb *ax25)
281{
282 struct sk_buff *skb;
283
284 ax25_cb_del(ax25);
285
286 ax25_stop_heartbeat(ax25);
287 ax25_stop_t1timer(ax25);
288 ax25_stop_t2timer(ax25);
289 ax25_stop_t3timer(ax25);
290 ax25_stop_idletimer(ax25);
291
292 ax25_clear_queues(ax25); /* Flush the queues */
293
294 if (ax25->sk != NULL) {
295 while ((skb = skb_dequeue(&ax25->sk->sk_receive_queue)) != NULL) {
296 if (skb->sk != ax25->sk) {
297 /* A pending connection */
298 ax25_cb *sax25 = ax25_sk(skb->sk);
299
300 /* Queue the unaccepted socket for death */
301 sock_orphan(skb->sk);
302
303 ax25_start_heartbeat(sax25);
304 sax25->state = AX25_STATE_0;
305 }
306
307 kfree_skb(skb);
308 }
309 skb_queue_purge(&ax25->sk->sk_write_queue);
310 }
311
312 if (ax25->sk != NULL) {
313 if (atomic_read(&ax25->sk->sk_wmem_alloc) ||
314 atomic_read(&ax25->sk->sk_rmem_alloc)) {
315 /* Defer: outstanding buffers */
316 init_timer(&ax25->dtimer);
317 ax25->dtimer.expires = jiffies + 2 * HZ;
318 ax25->dtimer.function = ax25_destroy_timer;
319 ax25->dtimer.data = (unsigned long)ax25;
320 add_timer(&ax25->dtimer);
321 } else {
322 struct sock *sk=ax25->sk;
323 ax25->sk=NULL;
324 sock_put(sk);
325 }
326 } else {
327 ax25_cb_put(ax25);
328 }
329}
330
331/*
332 * dl1bke 960311: set parameters for existing AX.25 connections,
333 * includes a KILL command to abort any connection.
334 * VERY useful for debugging ;-)
335 */
336static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg)
337{
338 struct ax25_ctl_struct ax25_ctl;
339 ax25_digi digi;
340 ax25_dev *ax25_dev;
341 ax25_cb *ax25;
342 unsigned int k;
343
344 if (copy_from_user(&ax25_ctl, arg, sizeof(ax25_ctl)))
345 return -EFAULT;
346
347 if ((ax25_dev = ax25_addr_ax25dev(&ax25_ctl.port_addr)) == NULL)
348 return -ENODEV;
349
350 if (ax25_ctl.digi_count > AX25_MAX_DIGIS)
351 return -EINVAL;
352
353 digi.ndigi = ax25_ctl.digi_count;
354 for (k = 0; k < digi.ndigi; k++)
355 digi.calls[k] = ax25_ctl.digi_addr[k];
356
357 if ((ax25 = ax25_find_cb(&ax25_ctl.source_addr, &ax25_ctl.dest_addr, &digi, ax25_dev->dev)) == NULL)
358 return -ENOTCONN;
359
360 switch (ax25_ctl.cmd) {
361 case AX25_KILL:
362 ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
363#ifdef CONFIG_AX25_DAMA_SLAVE
364 if (ax25_dev->dama.slave && ax25->ax25_dev->values[AX25_VALUES_PROTOCOL] == AX25_PROTO_DAMA_SLAVE)
365 ax25_dama_off(ax25);
366#endif
367 ax25_disconnect(ax25, ENETRESET);
368 break;
369
370 case AX25_WINDOW:
371 if (ax25->modulus == AX25_MODULUS) {
372 if (ax25_ctl.arg < 1 || ax25_ctl.arg > 7)
373 return -EINVAL;
374 } else {
375 if (ax25_ctl.arg < 1 || ax25_ctl.arg > 63)
376 return -EINVAL;
377 }
378 ax25->window = ax25_ctl.arg;
379 break;
380
381 case AX25_T1:
382 if (ax25_ctl.arg < 1)
383 return -EINVAL;
384 ax25->rtt = (ax25_ctl.arg * HZ) / 2;
385 ax25->t1 = ax25_ctl.arg * HZ;
386 break;
387
388 case AX25_T2:
389 if (ax25_ctl.arg < 1)
390 return -EINVAL;
391 ax25->t2 = ax25_ctl.arg * HZ;
392 break;
393
394 case AX25_N2:
395 if (ax25_ctl.arg < 1 || ax25_ctl.arg > 31)
396 return -EINVAL;
397 ax25->n2count = 0;
398 ax25->n2 = ax25_ctl.arg;
399 break;
400
401 case AX25_T3:
402 if (ax25_ctl.arg < 0)
403 return -EINVAL;
404 ax25->t3 = ax25_ctl.arg * HZ;
405 break;
406
407 case AX25_IDLE:
408 if (ax25_ctl.arg < 0)
409 return -EINVAL;
410 ax25->idle = ax25_ctl.arg * 60 * HZ;
411 break;
412
413 case AX25_PACLEN:
414 if (ax25_ctl.arg < 16 || ax25_ctl.arg > 65535)
415 return -EINVAL;
416 ax25->paclen = ax25_ctl.arg;
417 break;
418
419 default:
420 return -EINVAL;
421 }
422
423 return 0;
424}
425
426/*
427 * Fill in a created AX.25 created control block with the default
428 * values for a particular device.
429 */
430void ax25_fillin_cb(ax25_cb *ax25, ax25_dev *ax25_dev)
431{
432 ax25->ax25_dev = ax25_dev;
433
434 if (ax25->ax25_dev != NULL) {
435 ax25->rtt = ax25_dev->values[AX25_VALUES_T1] / 2;
436 ax25->t1 = ax25_dev->values[AX25_VALUES_T1];
437 ax25->t2 = ax25_dev->values[AX25_VALUES_T2];
438 ax25->t3 = ax25_dev->values[AX25_VALUES_T3];
439 ax25->n2 = ax25_dev->values[AX25_VALUES_N2];
440 ax25->paclen = ax25_dev->values[AX25_VALUES_PACLEN];
441 ax25->idle = ax25_dev->values[AX25_VALUES_IDLE];
442 ax25->backoff = ax25_dev->values[AX25_VALUES_BACKOFF];
443
444 if (ax25_dev->values[AX25_VALUES_AXDEFMODE]) {
445 ax25->modulus = AX25_EMODULUS;
446 ax25->window = ax25_dev->values[AX25_VALUES_EWINDOW];
447 } else {
448 ax25->modulus = AX25_MODULUS;
449 ax25->window = ax25_dev->values[AX25_VALUES_WINDOW];
450 }
451 } else {
452 ax25->rtt = AX25_DEF_T1 / 2;
453 ax25->t1 = AX25_DEF_T1;
454 ax25->t2 = AX25_DEF_T2;
455 ax25->t3 = AX25_DEF_T3;
456 ax25->n2 = AX25_DEF_N2;
457 ax25->paclen = AX25_DEF_PACLEN;
458 ax25->idle = AX25_DEF_IDLE;
459 ax25->backoff = AX25_DEF_BACKOFF;
460
461 if (AX25_DEF_AXDEFMODE) {
462 ax25->modulus = AX25_EMODULUS;
463 ax25->window = AX25_DEF_EWINDOW;
464 } else {
465 ax25->modulus = AX25_MODULUS;
466 ax25->window = AX25_DEF_WINDOW;
467 }
468 }
469}
470
471/*
472 * Create an empty AX.25 control block.
473 */
474ax25_cb *ax25_create_cb(void)
475{
476 ax25_cb *ax25;
477
478 if ((ax25 = kmalloc(sizeof(*ax25), GFP_ATOMIC)) == NULL)
479 return NULL;
480
481 memset(ax25, 0x00, sizeof(*ax25));
482 atomic_set(&ax25->refcount, 1);
483
484 skb_queue_head_init(&ax25->write_queue);
485 skb_queue_head_init(&ax25->frag_queue);
486 skb_queue_head_init(&ax25->ack_queue);
487 skb_queue_head_init(&ax25->reseq_queue);
488
489 init_timer(&ax25->timer);
490 init_timer(&ax25->t1timer);
491 init_timer(&ax25->t2timer);
492 init_timer(&ax25->t3timer);
493 init_timer(&ax25->idletimer);
494
495 ax25_fillin_cb(ax25, NULL);
496
497 ax25->state = AX25_STATE_0;
498
499 return ax25;
500}
501
502/*
503 * Handling for system calls applied via the various interfaces to an
504 * AX25 socket object
505 */
506
507static int ax25_setsockopt(struct socket *sock, int level, int optname,
508 char __user *optval, int optlen)
509{
510 struct sock *sk = sock->sk;
511 ax25_cb *ax25;
512 struct net_device *dev;
513 char devname[IFNAMSIZ];
514 int opt, res = 0;
515
516 if (level != SOL_AX25)
517 return -ENOPROTOOPT;
518
519 if (optlen < sizeof(int))
520 return -EINVAL;
521
522 if (get_user(opt, (int __user *)optval))
523 return -EFAULT;
524
525 lock_sock(sk);
526 ax25 = ax25_sk(sk);
527
528 switch (optname) {
529 case AX25_WINDOW:
530 if (ax25->modulus == AX25_MODULUS) {
531 if (opt < 1 || opt > 7) {
532 res = -EINVAL;
533 break;
534 }
535 } else {
536 if (opt < 1 || opt > 63) {
537 res = -EINVAL;
538 break;
539 }
540 }
541 ax25->window = opt;
542 break;
543
544 case AX25_T1:
545 if (opt < 1) {
546 res = -EINVAL;
547 break;
548 }
549 ax25->rtt = (opt * HZ) / 2;
550 ax25->t1 = opt * HZ;
551 break;
552
553 case AX25_T2:
554 if (opt < 1) {
555 res = -EINVAL;
556 break;
557 }
558 ax25->t2 = opt * HZ;
559 break;
560
561 case AX25_N2:
562 if (opt < 1 || opt > 31) {
563 res = -EINVAL;
564 break;
565 }
566 ax25->n2 = opt;
567 break;
568
569 case AX25_T3:
570 if (opt < 1) {
571 res = -EINVAL;
572 break;
573 }
574 ax25->t3 = opt * HZ;
575 break;
576
577 case AX25_IDLE:
578 if (opt < 0) {
579 res = -EINVAL;
580 break;
581 }
582 ax25->idle = opt * 60 * HZ;
583 break;
584
585 case AX25_BACKOFF:
586 if (opt < 0 || opt > 2) {
587 res = -EINVAL;
588 break;
589 }
590 ax25->backoff = opt;
591 break;
592
593 case AX25_EXTSEQ:
594 ax25->modulus = opt ? AX25_EMODULUS : AX25_MODULUS;
595 break;
596
597 case AX25_PIDINCL:
598 ax25->pidincl = opt ? 1 : 0;
599 break;
600
601 case AX25_IAMDIGI:
602 ax25->iamdigi = opt ? 1 : 0;
603 break;
604
605 case AX25_PACLEN:
606 if (opt < 16 || opt > 65535) {
607 res = -EINVAL;
608 break;
609 }
610 ax25->paclen = opt;
611 break;
612
613 case SO_BINDTODEVICE:
614 if (optlen > IFNAMSIZ)
615 optlen=IFNAMSIZ;
616 if (copy_from_user(devname, optval, optlen)) {
617 res = -EFAULT;
618 break;
619 }
620
621 dev = dev_get_by_name(devname);
622 if (dev == NULL) {
623 res = -ENODEV;
624 break;
625 }
626
627 if (sk->sk_type == SOCK_SEQPACKET &&
628 (sock->state != SS_UNCONNECTED ||
629 sk->sk_state == TCP_LISTEN)) {
630 res = -EADDRNOTAVAIL;
631 dev_put(dev);
632 break;
633 }
634
635 ax25->ax25_dev = ax25_dev_ax25dev(dev);
636 ax25_fillin_cb(ax25, ax25->ax25_dev);
637 break;
638
639 default:
640 res = -ENOPROTOOPT;
641 }
642 release_sock(sk);
643
644 return res;
645}
646
647static int ax25_getsockopt(struct socket *sock, int level, int optname,
648 char __user *optval, int __user *optlen)
649{
650 struct sock *sk = sock->sk;
651 ax25_cb *ax25;
652 struct ax25_dev *ax25_dev;
653 char devname[IFNAMSIZ];
654 void *valptr;
655 int val = 0;
656 int maxlen, length;
657
658 if (level != SOL_AX25)
659 return -ENOPROTOOPT;
660
661 if (get_user(maxlen, optlen))
662 return -EFAULT;
663
664 if (maxlen < 1)
665 return -EFAULT;
666
667 valptr = (void *) &val;
668 length = min_t(unsigned int, maxlen, sizeof(int));
669
670 lock_sock(sk);
671 ax25 = ax25_sk(sk);
672
673 switch (optname) {
674 case AX25_WINDOW:
675 val = ax25->window;
676 break;
677
678 case AX25_T1:
679 val = ax25->t1 / HZ;
680 break;
681
682 case AX25_T2:
683 val = ax25->t2 / HZ;
684 break;
685
686 case AX25_N2:
687 val = ax25->n2;
688 break;
689
690 case AX25_T3:
691 val = ax25->t3 / HZ;
692 break;
693
694 case AX25_IDLE:
695 val = ax25->idle / (60 * HZ);
696 break;
697
698 case AX25_BACKOFF:
699 val = ax25->backoff;
700 break;
701
702 case AX25_EXTSEQ:
703 val = (ax25->modulus == AX25_EMODULUS);
704 break;
705
706 case AX25_PIDINCL:
707 val = ax25->pidincl;
708 break;
709
710 case AX25_IAMDIGI:
711 val = ax25->iamdigi;
712 break;
713
714 case AX25_PACLEN:
715 val = ax25->paclen;
716 break;
717
718 case SO_BINDTODEVICE:
719 ax25_dev = ax25->ax25_dev;
720
721 if (ax25_dev != NULL && ax25_dev->dev != NULL) {
722 strlcpy(devname, ax25_dev->dev->name, sizeof(devname));
723 length = strlen(devname) + 1;
724 } else {
725 *devname = '\0';
726 length = 1;
727 }
728
729 valptr = (void *) devname;
730 break;
731
732 default:
733 release_sock(sk);
734 return -ENOPROTOOPT;
735 }
736 release_sock(sk);
737
738 if (put_user(length, optlen))
739 return -EFAULT;
740
741 return copy_to_user(optval, valptr, length) ? -EFAULT : 0;
742}
743
744static int ax25_listen(struct socket *sock, int backlog)
745{
746 struct sock *sk = sock->sk;
747 int res = 0;
748
749 lock_sock(sk);
750 if (sk->sk_type == SOCK_SEQPACKET && sk->sk_state != TCP_LISTEN) {
751 sk->sk_max_ack_backlog = backlog;
752 sk->sk_state = TCP_LISTEN;
753 goto out;
754 }
755 res = -EOPNOTSUPP;
756
757out:
758 release_sock(sk);
759
760 return res;
761}
762
763/*
764 * XXX: when creating ax25_sock we should update the .obj_size setting
765 * below.
766 */
767static struct proto ax25_proto = {
768 .name = "AX25",
769 .owner = THIS_MODULE,
770 .obj_size = sizeof(struct sock),
771};
772
773static int ax25_create(struct socket *sock, int protocol)
774{
775 struct sock *sk;
776 ax25_cb *ax25;
777
778 switch (sock->type) {
779 case SOCK_DGRAM:
780 if (protocol == 0 || protocol == PF_AX25)
781 protocol = AX25_P_TEXT;
782 break;
783
784 case SOCK_SEQPACKET:
785 switch (protocol) {
786 case 0:
787 case PF_AX25: /* For CLX */
788 protocol = AX25_P_TEXT;
789 break;
790 case AX25_P_SEGMENT:
791#ifdef CONFIG_INET
792 case AX25_P_ARP:
793 case AX25_P_IP:
794#endif
795#ifdef CONFIG_NETROM
796 case AX25_P_NETROM:
797#endif
798#ifdef CONFIG_ROSE
799 case AX25_P_ROSE:
800#endif
801 return -ESOCKTNOSUPPORT;
802#ifdef CONFIG_NETROM_MODULE
803 case AX25_P_NETROM:
804 if (ax25_protocol_is_registered(AX25_P_NETROM))
805 return -ESOCKTNOSUPPORT;
806#endif
807#ifdef CONFIG_ROSE_MODULE
808 case AX25_P_ROSE:
809 if (ax25_protocol_is_registered(AX25_P_ROSE))
810 return -ESOCKTNOSUPPORT;
811#endif
812 default:
813 break;
814 }
815 break;
816
817 case SOCK_RAW:
818 break;
819 default:
820 return -ESOCKTNOSUPPORT;
821 }
822
823 if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, &ax25_proto, 1)) == NULL)
824 return -ENOMEM;
825
826 ax25 = sk->sk_protinfo = ax25_create_cb();
827 if (!ax25) {
828 sk_free(sk);
829 return -ENOMEM;
830 }
831
832 sock_init_data(sock, sk);
833
834 sk->sk_destruct = ax25_free_sock;
835 sock->ops = &ax25_proto_ops;
836 sk->sk_protocol = protocol;
837
838 ax25->sk = sk;
839
840 return 0;
841}
842
843struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
844{
845 struct sock *sk;
846 ax25_cb *ax25, *oax25;
847
848 if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, osk->sk_prot, 1)) == NULL)
849 return NULL;
850
851 if ((ax25 = ax25_create_cb()) == NULL) {
852 sk_free(sk);
853 return NULL;
854 }
855
856 switch (osk->sk_type) {
857 case SOCK_DGRAM:
858 break;
859 case SOCK_SEQPACKET:
860 break;
861 default:
862 sk_free(sk);
863 ax25_cb_put(ax25);
864 return NULL;
865 }
866
867 sock_init_data(NULL, sk);
868
869 sk->sk_destruct = ax25_free_sock;
870 sk->sk_type = osk->sk_type;
871 sk->sk_socket = osk->sk_socket;
872 sk->sk_priority = osk->sk_priority;
873 sk->sk_protocol = osk->sk_protocol;
874 sk->sk_rcvbuf = osk->sk_rcvbuf;
875 sk->sk_sndbuf = osk->sk_sndbuf;
876 sk->sk_state = TCP_ESTABLISHED;
877 sk->sk_sleep = osk->sk_sleep;
878
879 if (sock_flag(osk, SOCK_DBG))
880 sock_set_flag(sk, SOCK_DBG);
881
882 if (sock_flag(osk, SOCK_ZAPPED))
883 sock_set_flag(sk, SOCK_ZAPPED);
884
885 oax25 = ax25_sk(osk);
886
887 ax25->modulus = oax25->modulus;
888 ax25->backoff = oax25->backoff;
889 ax25->pidincl = oax25->pidincl;
890 ax25->iamdigi = oax25->iamdigi;
891 ax25->rtt = oax25->rtt;
892 ax25->t1 = oax25->t1;
893 ax25->t2 = oax25->t2;
894 ax25->t3 = oax25->t3;
895 ax25->n2 = oax25->n2;
896 ax25->idle = oax25->idle;
897 ax25->paclen = oax25->paclen;
898 ax25->window = oax25->window;
899
900 ax25->ax25_dev = ax25_dev;
901 ax25->source_addr = oax25->source_addr;
902
903 if (oax25->digipeat != NULL) {
904 if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
905 sk_free(sk);
906 ax25_cb_put(ax25);
907 return NULL;
908 }
909
910 memcpy(ax25->digipeat, oax25->digipeat, sizeof(ax25_digi));
911 }
912
913 sk->sk_protinfo = ax25;
914 ax25->sk = sk;
915
916 return sk;
917}
918
919static int ax25_release(struct socket *sock)
920{
921 struct sock *sk = sock->sk;
922 ax25_cb *ax25;
923
924 if (sk == NULL)
925 return 0;
926
927 sock_hold(sk);
928 sock_orphan(sk);
929 lock_sock(sk);
930 ax25 = ax25_sk(sk);
931
932 if (sk->sk_type == SOCK_SEQPACKET) {
933 switch (ax25->state) {
934 case AX25_STATE_0:
935 release_sock(sk);
936 ax25_disconnect(ax25, 0);
937 lock_sock(sk);
938 ax25_destroy_socket(ax25);
939 break;
940
941 case AX25_STATE_1:
942 case AX25_STATE_2:
943 ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
944 release_sock(sk);
945 ax25_disconnect(ax25, 0);
946 lock_sock(sk);
947 ax25_destroy_socket(ax25);
948 break;
949
950 case AX25_STATE_3:
951 case AX25_STATE_4:
952 ax25_clear_queues(ax25);
953 ax25->n2count = 0;
954
955 switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
956 case AX25_PROTO_STD_SIMPLEX:
957 case AX25_PROTO_STD_DUPLEX:
958 ax25_send_control(ax25,
959 AX25_DISC,
960 AX25_POLLON,
961 AX25_COMMAND);
962 ax25_stop_t2timer(ax25);
963 ax25_stop_t3timer(ax25);
964 ax25_stop_idletimer(ax25);
965 break;
966#ifdef CONFIG_AX25_DAMA_SLAVE
967 case AX25_PROTO_DAMA_SLAVE:
968 ax25_stop_t3timer(ax25);
969 ax25_stop_idletimer(ax25);
970 break;
971#endif
972 }
973 ax25_calculate_t1(ax25);
974 ax25_start_t1timer(ax25);
975 ax25->state = AX25_STATE_2;
976 sk->sk_state = TCP_CLOSE;
977 sk->sk_shutdown |= SEND_SHUTDOWN;
978 sk->sk_state_change(sk);
979 sock_set_flag(sk, SOCK_DESTROY);
980 break;
981
982 default:
983 break;
984 }
985 } else {
986 sk->sk_state = TCP_CLOSE;
987 sk->sk_shutdown |= SEND_SHUTDOWN;
988 sk->sk_state_change(sk);
989 ax25_destroy_socket(ax25);
990 }
991
992 sock->sk = NULL;
993 release_sock(sk);
994 sock_put(sk);
995
996 return 0;
997}
998
999/*
1000 * We support a funny extension here so you can (as root) give any callsign
1001 * digipeated via a local address as source. This hack is obsolete now
1002 * that we've implemented support for SO_BINDTODEVICE. It is however small
1003 * and trivially backward compatible.
1004 */
1005static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
1006{
1007 struct sock *sk = sock->sk;
1008 struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr;
1009 ax25_dev *ax25_dev = NULL;
1010 ax25_address *call;
1011 ax25_cb *ax25;
1012 int err = 0;
1013
1014 if (addr_len != sizeof(struct sockaddr_ax25) &&
1015 addr_len != sizeof(struct full_sockaddr_ax25)) {
1016 /* support for old structure may go away some time */
1017 if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) ||
1018 (addr_len > sizeof(struct full_sockaddr_ax25))) {
1019 return -EINVAL;
1020 }
1021
1022 printk(KERN_WARNING "ax25_bind(): %s uses old (6 digipeater) socket structure.\n",
1023 current->comm);
1024 }
1025
1026 if (addr->fsa_ax25.sax25_family != AF_AX25)
1027 return -EINVAL;
1028
1029 call = ax25_findbyuid(current->euid);
1030 if (call == NULL && ax25_uid_policy && !capable(CAP_NET_ADMIN)) {
1031 return -EACCES;
1032 }
1033
1034 lock_sock(sk);
1035
1036 ax25 = ax25_sk(sk);
1037 if (!sock_flag(sk, SOCK_ZAPPED)) {
1038 err = -EINVAL;
1039 goto out;
1040 }
1041
1042 if (call == NULL)
1043 ax25->source_addr = addr->fsa_ax25.sax25_call;
1044 else
1045 ax25->source_addr = *call;
1046
1047 /*
1048 * User already set interface with SO_BINDTODEVICE
1049 */
1050 if (ax25->ax25_dev != NULL)
1051 goto done;
1052
1053 if (addr_len > sizeof(struct sockaddr_ax25) && addr->fsa_ax25.sax25_ndigis == 1) {
1054 if (ax25cmp(&addr->fsa_digipeater[0], &null_ax25_address) != 0 &&
1055 (ax25_dev = ax25_addr_ax25dev(&addr->fsa_digipeater[0])) == NULL) {
1056 err = -EADDRNOTAVAIL;
1057 goto out;
1058 }
1059 } else {
1060 if ((ax25_dev = ax25_addr_ax25dev(&addr->fsa_ax25.sax25_call)) == NULL) {
1061 err = -EADDRNOTAVAIL;
1062 goto out;
1063 }
1064 }
1065
1066 if (ax25_dev != NULL)
1067 ax25_fillin_cb(ax25, ax25_dev);
1068
1069done:
1070 ax25_cb_add(ax25);
1071 sock_reset_flag(sk, SOCK_ZAPPED);
1072
1073out:
1074 release_sock(sk);
1075
1076 return 0;
1077}
1078
1079/*
1080 * FIXME: nonblock behaviour looks like it may have a bug.
1081 */
1082static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
1083 int addr_len, int flags)
1084{
1085 struct sock *sk = sock->sk;
1086 ax25_cb *ax25 = ax25_sk(sk), *ax25t;
1087 struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)uaddr;
1088 ax25_digi *digi = NULL;
1089 int ct = 0, err = 0;
1090
1091 /*
1092 * some sanity checks. code further down depends on this
1093 */
1094
1095 if (addr_len == sizeof(struct sockaddr_ax25)) {
1096 /* support for this will go away in early 2.5.x */
1097 printk(KERN_WARNING "ax25_connect(): %s uses obsolete socket structure\n",
1098 current->comm);
1099 }
1100 else if (addr_len != sizeof(struct full_sockaddr_ax25)) {
1101 /* support for old structure may go away some time */
1102 if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) ||
1103 (addr_len > sizeof(struct full_sockaddr_ax25))) {
1104 return -EINVAL;
1105 }
1106
1107 printk(KERN_WARNING "ax25_connect(): %s uses old (6 digipeater) socket structure.\n",
1108 current->comm);
1109 }
1110
1111 if (fsa->fsa_ax25.sax25_family != AF_AX25)
1112 return -EINVAL;
1113
1114 lock_sock(sk);
1115
1116 /* deal with restarts */
1117 if (sock->state == SS_CONNECTING) {
1118 switch (sk->sk_state) {
1119 case TCP_SYN_SENT: /* still trying */
1120 err = -EINPROGRESS;
1121 goto out;
1122
1123 case TCP_ESTABLISHED: /* connection established */
1124 sock->state = SS_CONNECTED;
1125 goto out;
1126
1127 case TCP_CLOSE: /* connection refused */
1128 sock->state = SS_UNCONNECTED;
1129 err = -ECONNREFUSED;
1130 goto out;
1131 }
1132 }
1133
1134 if (sk->sk_state == TCP_ESTABLISHED && sk->sk_type == SOCK_SEQPACKET) {
1135 err = -EISCONN; /* No reconnect on a seqpacket socket */
1136 goto out;
1137 }
1138
1139 sk->sk_state = TCP_CLOSE;
1140 sock->state = SS_UNCONNECTED;
1141
1142 if (ax25->digipeat != NULL) {
1143 kfree(ax25->digipeat);
1144 ax25->digipeat = NULL;
1145 }
1146
1147 /*
1148 * Handle digi-peaters to be used.
1149 */
1150 if (addr_len > sizeof(struct sockaddr_ax25) &&
1151 fsa->fsa_ax25.sax25_ndigis != 0) {
1152 /* Valid number of digipeaters ? */
1153 if (fsa->fsa_ax25.sax25_ndigis < 1 || fsa->fsa_ax25.sax25_ndigis > AX25_MAX_DIGIS) {
1154 err = -EINVAL;
1155 goto out;
1156 }
1157
1158 if ((digi = kmalloc(sizeof(ax25_digi), GFP_KERNEL)) == NULL) {
1159 err = -ENOBUFS;
1160 goto out;
1161 }
1162
1163 digi->ndigi = fsa->fsa_ax25.sax25_ndigis;
1164 digi->lastrepeat = -1;
1165
1166 while (ct < fsa->fsa_ax25.sax25_ndigis) {
1167 if ((fsa->fsa_digipeater[ct].ax25_call[6] &
1168 AX25_HBIT) && ax25->iamdigi) {
1169 digi->repeated[ct] = 1;
1170 digi->lastrepeat = ct;
1171 } else {
1172 digi->repeated[ct] = 0;
1173 }
1174 digi->calls[ct] = fsa->fsa_digipeater[ct];
1175 ct++;
1176 }
1177 }
1178
1179 /*
1180 * Must bind first - autobinding in this may or may not work. If
1181 * the socket is already bound, check to see if the device has
1182 * been filled in, error if it hasn't.
1183 */
1184 if (sock_flag(sk, SOCK_ZAPPED)) {
1185 /* check if we can remove this feature. It is broken. */
1186 printk(KERN_WARNING "ax25_connect(): %s uses autobind, please contact jreuter@yaina.de\n",
1187 current->comm);
1188 if ((err = ax25_rt_autobind(ax25, &fsa->fsa_ax25.sax25_call)) < 0) {
1189 kfree(digi);
1190 goto out;
1191 }
1192
1193 ax25_fillin_cb(ax25, ax25->ax25_dev);
1194 ax25_cb_add(ax25);
1195 } else {
1196 if (ax25->ax25_dev == NULL) {
1197 kfree(digi);
1198 err = -EHOSTUNREACH;
1199 goto out;
1200 }
1201 }
1202
1203 if (sk->sk_type == SOCK_SEQPACKET &&
1204 (ax25t=ax25_find_cb(&ax25->source_addr, &fsa->fsa_ax25.sax25_call, digi,
1205 ax25->ax25_dev->dev))) {
1206 kfree(digi);
1207 err = -EADDRINUSE; /* Already such a connection */
1208 ax25_cb_put(ax25t);
1209 goto out;
1210 }
1211
1212 ax25->dest_addr = fsa->fsa_ax25.sax25_call;
1213 ax25->digipeat = digi;
1214
1215 /* First the easy one */
1216 if (sk->sk_type != SOCK_SEQPACKET) {
1217 sock->state = SS_CONNECTED;
1218 sk->sk_state = TCP_ESTABLISHED;
1219 goto out;
1220 }
1221
1222 /* Move to connecting socket, ax.25 lapb WAIT_UA.. */
1223 sock->state = SS_CONNECTING;
1224 sk->sk_state = TCP_SYN_SENT;
1225
1226 switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
1227 case AX25_PROTO_STD_SIMPLEX:
1228 case AX25_PROTO_STD_DUPLEX:
1229 ax25_std_establish_data_link(ax25);
1230 break;
1231
1232#ifdef CONFIG_AX25_DAMA_SLAVE
1233 case AX25_PROTO_DAMA_SLAVE:
1234 ax25->modulus = AX25_MODULUS;
1235 ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
1236 if (ax25->ax25_dev->dama.slave)
1237 ax25_ds_establish_data_link(ax25);
1238 else
1239 ax25_std_establish_data_link(ax25);
1240 break;
1241#endif
1242 }
1243
1244 ax25->state = AX25_STATE_1;
1245
1246 ax25_start_heartbeat(ax25);
1247
1248 /* Now the loop */
1249 if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) {
1250 err = -EINPROGRESS;
1251 goto out;
1252 }
1253
1254 if (sk->sk_state == TCP_SYN_SENT) {
1255 struct task_struct *tsk = current;
1256 DECLARE_WAITQUEUE(wait, tsk);
1257
1258 add_wait_queue(sk->sk_sleep, &wait);
1259 for (;;) {
1260 if (sk->sk_state != TCP_SYN_SENT)
1261 break;
1262 set_current_state(TASK_INTERRUPTIBLE);
1263 release_sock(sk);
1264 if (!signal_pending(tsk)) {
1265 schedule();
1266 lock_sock(sk);
1267 continue;
1268 }
1269 current->state = TASK_RUNNING;
1270 remove_wait_queue(sk->sk_sleep, &wait);
1271 return -ERESTARTSYS;
1272 }
1273 current->state = TASK_RUNNING;
1274 remove_wait_queue(sk->sk_sleep, &wait);
1275 }
1276
1277 if (sk->sk_state != TCP_ESTABLISHED) {
1278 /* Not in ABM, not in WAIT_UA -> failed */
1279 sock->state = SS_UNCONNECTED;
1280 err = sock_error(sk); /* Always set at this point */
1281 goto out;
1282 }
1283
1284 sock->state = SS_CONNECTED;
1285
1286 err=0;
1287out:
1288 release_sock(sk);
1289
1290 return err;
1291}
1292
1293
1294static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
1295{
1296 struct task_struct *tsk = current;
1297 DECLARE_WAITQUEUE(wait, tsk);
1298 struct sk_buff *skb;
1299 struct sock *newsk;
1300 struct sock *sk;
1301 int err = 0;
1302
1303 if (sock->state != SS_UNCONNECTED)
1304 return -EINVAL;
1305
1306 if ((sk = sock->sk) == NULL)
1307 return -EINVAL;
1308
1309 lock_sock(sk);
1310 if (sk->sk_type != SOCK_SEQPACKET) {
1311 err = -EOPNOTSUPP;
1312 goto out;
1313 }
1314
1315 if (sk->sk_state != TCP_LISTEN) {
1316 err = -EINVAL;
1317 goto out;
1318 }
1319
1320 /*
1321 * The read queue this time is holding sockets ready to use
1322 * hooked into the SABM we saved
1323 */
1324 add_wait_queue(sk->sk_sleep, &wait);
1325 for (;;) {
1326 skb = skb_dequeue(&sk->sk_receive_queue);
1327 if (skb)
1328 break;
1329
1330 release_sock(sk);
1331 current->state = TASK_INTERRUPTIBLE;
1332 if (flags & O_NONBLOCK) {
1333 current->state = TASK_RUNNING;
1334 remove_wait_queue(sk->sk_sleep, &wait);
1335 return -EWOULDBLOCK;
1336 }
1337 if (!signal_pending(tsk)) {
1338 schedule();
1339 lock_sock(sk);
1340 continue;
1341 }
1342 current->state = TASK_RUNNING;
1343 remove_wait_queue(sk->sk_sleep, &wait);
1344 return -ERESTARTSYS;
1345 }
1346 current->state = TASK_RUNNING;
1347 remove_wait_queue(sk->sk_sleep, &wait);
1348
1349 newsk = skb->sk;
1350 newsk->sk_socket = newsock;
1351 newsk->sk_sleep = &newsock->wait;
1352
1353 /* Now attach up the new socket */
1354 kfree_skb(skb);
1355 sk->sk_ack_backlog--;
1356 newsock->sk = newsk;
1357 newsock->state = SS_CONNECTED;
1358
1359out:
1360 release_sock(sk);
1361
1362 return err;
1363}
1364
1365static int ax25_getname(struct socket *sock, struct sockaddr *uaddr,
1366 int *uaddr_len, int peer)
1367{
1368 struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)uaddr;
1369 struct sock *sk = sock->sk;
1370 unsigned char ndigi, i;
1371 ax25_cb *ax25;
1372 int err = 0;
1373
1374 lock_sock(sk);
1375 ax25 = ax25_sk(sk);
1376
1377 if (peer != 0) {
1378 if (sk->sk_state != TCP_ESTABLISHED) {
1379 err = -ENOTCONN;
1380 goto out;
1381 }
1382
1383 fsa->fsa_ax25.sax25_family = AF_AX25;
1384 fsa->fsa_ax25.sax25_call = ax25->dest_addr;
1385 fsa->fsa_ax25.sax25_ndigis = 0;
1386
1387 if (ax25->digipeat != NULL) {
1388 ndigi = ax25->digipeat->ndigi;
1389 fsa->fsa_ax25.sax25_ndigis = ndigi;
1390 for (i = 0; i < ndigi; i++)
1391 fsa->fsa_digipeater[i] =
1392 ax25->digipeat->calls[i];
1393 }
1394 } else {
1395 fsa->fsa_ax25.sax25_family = AF_AX25;
1396 fsa->fsa_ax25.sax25_call = ax25->source_addr;
1397 fsa->fsa_ax25.sax25_ndigis = 1;
1398 if (ax25->ax25_dev != NULL) {
1399 memcpy(&fsa->fsa_digipeater[0],
1400 ax25->ax25_dev->dev->dev_addr, AX25_ADDR_LEN);
1401 } else {
1402 fsa->fsa_digipeater[0] = null_ax25_address;
1403 }
1404 }
1405 *uaddr_len = sizeof (struct full_sockaddr_ax25);
1406
1407out:
1408 release_sock(sk);
1409
1410 return err;
1411}
1412
1413static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock,
1414 struct msghdr *msg, size_t len)
1415{
1416 struct sockaddr_ax25 *usax = (struct sockaddr_ax25 *)msg->msg_name;
1417 struct sock *sk = sock->sk;
1418 struct sockaddr_ax25 sax;
1419 struct sk_buff *skb;
1420 ax25_digi dtmp, *dp;
1421 unsigned char *asmptr;
1422 ax25_cb *ax25;
1423 size_t size;
1424 int lv, err, addr_len = msg->msg_namelen;
1425
1426 if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_CMSG_COMPAT))
1427 return -EINVAL;
1428
1429 lock_sock(sk);
1430 ax25 = ax25_sk(sk);
1431
1432 if (sock_flag(sk, SOCK_ZAPPED)) {
1433 err = -EADDRNOTAVAIL;
1434 goto out;
1435 }
1436
1437 if (sk->sk_shutdown & SEND_SHUTDOWN) {
1438 send_sig(SIGPIPE, current, 0);
1439 err = -EPIPE;
1440 goto out;
1441 }
1442
1443 if (ax25->ax25_dev == NULL) {
1444 err = -ENETUNREACH;
1445 goto out;
1446 }
1447
1448 if (len > ax25->ax25_dev->dev->mtu) {
1449 err = -EMSGSIZE;
1450 goto out;
1451 }
1452
1453 if (usax != NULL) {
1454 if (usax->sax25_family != AF_AX25) {
1455 err = -EINVAL;
1456 goto out;
1457 }
1458
1459 if (addr_len == sizeof(struct sockaddr_ax25)) {
1460 printk(KERN_WARNING "ax25_sendmsg(): %s uses obsolete socket structure\n",
1461 current->comm);
1462 }
1463 else if (addr_len != sizeof(struct full_sockaddr_ax25)) {
1464 /* support for old structure may go away some time */
1465 if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) ||
1466 (addr_len > sizeof(struct full_sockaddr_ax25))) {
1467 err = -EINVAL;
1468 goto out;
1469 }
1470
1471 printk(KERN_WARNING "ax25_sendmsg(): %s uses old (6 digipeater) socket structure.\n",
1472 current->comm);
1473 }
1474
1475 if (addr_len > sizeof(struct sockaddr_ax25) && usax->sax25_ndigis != 0) {
1476 int ct = 0;
1477 struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)usax;
1478
1479 /* Valid number of digipeaters ? */
1480 if (usax->sax25_ndigis < 1 || usax->sax25_ndigis > AX25_MAX_DIGIS) {
1481 err = -EINVAL;
1482 goto out;
1483 }
1484
1485 dtmp.ndigi = usax->sax25_ndigis;
1486
1487 while (ct < usax->sax25_ndigis) {
1488 dtmp.repeated[ct] = 0;
1489 dtmp.calls[ct] = fsa->fsa_digipeater[ct];
1490 ct++;
1491 }
1492
1493 dtmp.lastrepeat = 0;
1494 }
1495
1496 sax = *usax;
1497 if (sk->sk_type == SOCK_SEQPACKET &&
1498 ax25cmp(&ax25->dest_addr, &sax.sax25_call)) {
1499 err = -EISCONN;
1500 goto out;
1501 }
1502 if (usax->sax25_ndigis == 0)
1503 dp = NULL;
1504 else
1505 dp = &dtmp;
1506 } else {
1507 /*
1508 * FIXME: 1003.1g - if the socket is like this because
1509 * it has become closed (not started closed) and is VC
1510 * we ought to SIGPIPE, EPIPE
1511 */
1512 if (sk->sk_state != TCP_ESTABLISHED) {
1513 err = -ENOTCONN;
1514 goto out;
1515 }
1516 sax.sax25_family = AF_AX25;
1517 sax.sax25_call = ax25->dest_addr;
1518 dp = ax25->digipeat;
1519 }
1520
1521 SOCK_DEBUG(sk, "AX.25: sendto: Addresses built.\n");
1522
1523 /* Build a packet */
1524 SOCK_DEBUG(sk, "AX.25: sendto: building packet.\n");
1525
1526 /* Assume the worst case */
1527 size = len + ax25->ax25_dev->dev->hard_header_len;
1528
1529 skb = sock_alloc_send_skb(sk, size, msg->msg_flags&MSG_DONTWAIT, &err);
1530 if (skb == NULL)
1531 goto out;
1532
1533 skb_reserve(skb, size - len);
1534
1535 SOCK_DEBUG(sk, "AX.25: Appending user data\n");
1536
1537 /* User data follows immediately after the AX.25 data */
1538 if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
1539 err = -EFAULT;
1540 kfree_skb(skb);
1541 goto out;
1542 }
1543
1544 skb->nh.raw = skb->data;
1545
1546 /* Add the PID if one is not supplied by the user in the skb */
1547 if (!ax25->pidincl) {
1548 asmptr = skb_push(skb, 1);
1549 *asmptr = sk->sk_protocol;
1550 }
1551
1552 SOCK_DEBUG(sk, "AX.25: Transmitting buffer\n");
1553
1554 if (sk->sk_type == SOCK_SEQPACKET) {
1555 /* Connected mode sockets go via the LAPB machine */
1556 if (sk->sk_state != TCP_ESTABLISHED) {
1557 kfree_skb(skb);
1558 err = -ENOTCONN;
1559 goto out;
1560 }
1561
1562 /* Shove it onto the queue and kick */
1563 ax25_output(ax25, ax25->paclen, skb);
1564
1565 err = len;
1566 goto out;
1567 }
1568
1569 asmptr = skb_push(skb, 1 + ax25_addr_size(dp));
1570
1571 SOCK_DEBUG(sk, "Building AX.25 Header (dp=%p).\n", dp);
1572
1573 if (dp != NULL)
1574 SOCK_DEBUG(sk, "Num digipeaters=%d\n", dp->ndigi);
1575
1576 /* Build an AX.25 header */
1577 asmptr += (lv = ax25_addr_build(asmptr, &ax25->source_addr,
1578 &sax.sax25_call, dp,
1579 AX25_COMMAND, AX25_MODULUS));
1580
1581 SOCK_DEBUG(sk, "Built header (%d bytes)\n",lv);
1582
1583 skb->h.raw = asmptr;
1584
1585 SOCK_DEBUG(sk, "base=%p pos=%p\n", skb->data, asmptr);
1586
1587 *asmptr = AX25_UI;
1588
1589 /* Datagram frames go straight out of the door as UI */
1590 skb->dev = ax25->ax25_dev->dev;
1591
1592 ax25_queue_xmit(skb);
1593
1594 err = len;
1595
1596out:
1597 release_sock(sk);
1598
1599 return err;
1600}
1601
1602static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock,
1603 struct msghdr *msg, size_t size, int flags)
1604{
1605 struct sock *sk = sock->sk;
1606 struct sk_buff *skb;
1607 int copied;
1608 int err = 0;
1609
1610 lock_sock(sk);
1611 /*
1612 * This works for seqpacket too. The receiver has ordered the
1613 * queue for us! We do one quick check first though
1614 */
1615 if (sk->sk_type == SOCK_SEQPACKET && sk->sk_state != TCP_ESTABLISHED) {
1616 err = -ENOTCONN;
1617 goto out;
1618 }
1619
1620 /* Now we can treat all alike */
1621 skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
1622 flags & MSG_DONTWAIT, &err);
1623 if (skb == NULL)
1624 goto out;
1625
1626 if (!ax25_sk(sk)->pidincl)
1627 skb_pull(skb, 1); /* Remove PID */
1628
1629 skb->h.raw = skb->data;
1630 copied = skb->len;
1631
1632 if (copied > size) {
1633 copied = size;
1634 msg->msg_flags |= MSG_TRUNC;
1635 }
1636
1637 skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
1638
1639 if (msg->msg_namelen != 0) {
1640 struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name;
1641 ax25_digi digi;
1642 ax25_address src;
1643
1644 ax25_addr_parse(skb->mac.raw+1, skb->data-skb->mac.raw-1, &src, NULL, &digi, NULL, NULL);
1645
1646 sax->sax25_family = AF_AX25;
1647 /* We set this correctly, even though we may not let the
1648 application know the digi calls further down (because it
1649 did NOT ask to know them). This could get political... **/
1650 sax->sax25_ndigis = digi.ndigi;
1651 sax->sax25_call = src;
1652
1653 if (sax->sax25_ndigis != 0) {
1654 int ct;
1655 struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)sax;
1656
1657 for (ct = 0; ct < digi.ndigi; ct++)
1658 fsa->fsa_digipeater[ct] = digi.calls[ct];
1659 }
1660 msg->msg_namelen = sizeof(struct full_sockaddr_ax25);
1661 }
1662
1663 skb_free_datagram(sk, skb);
1664 err = copied;
1665
1666out:
1667 release_sock(sk);
1668
1669 return err;
1670}
1671
1672static int ax25_shutdown(struct socket *sk, int how)
1673{
1674 /* FIXME - generate DM and RNR states */
1675 return -EOPNOTSUPP;
1676}
1677
1678static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
1679{
1680 struct sock *sk = sock->sk;
1681 void __user *argp = (void __user *)arg;
1682 int res = 0;
1683
1684 lock_sock(sk);
1685 switch (cmd) {
1686 case TIOCOUTQ: {
1687 long amount;
1688 amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
1689 if (amount < 0)
1690 amount = 0;
1691 res = put_user(amount, (int __user *)argp);
1692 break;
1693 }
1694
1695 case TIOCINQ: {
1696 struct sk_buff *skb;
1697 long amount = 0L;
1698 /* These two are safe on a single CPU system as only user tasks fiddle here */
1699 if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
1700 amount = skb->len;
1701 res = put_user(amount, (int __user *)argp);
1702 break;
1703 }
1704
1705 case SIOCGSTAMP:
1706 if (sk != NULL) {
1707 res = sock_get_timestamp(sk, argp);
1708 break;
1709 }
1710 res = -EINVAL;
1711 break;
1712
1713 case SIOCAX25ADDUID: /* Add a uid to the uid/call map table */
1714 case SIOCAX25DELUID: /* Delete a uid from the uid/call map table */
1715 case SIOCAX25GETUID: {
1716 struct sockaddr_ax25 sax25;
1717 if (copy_from_user(&sax25, argp, sizeof(sax25))) {
1718 res = -EFAULT;
1719 break;
1720 }
1721 res = ax25_uid_ioctl(cmd, &sax25);
1722 break;
1723 }
1724
1725 case SIOCAX25NOUID: { /* Set the default policy (default/bar) */
1726 long amount;
1727 if (!capable(CAP_NET_ADMIN)) {
1728 res = -EPERM;
1729 break;
1730 }
1731 if (get_user(amount, (long __user *)argp)) {
1732 res = -EFAULT;
1733 break;
1734 }
1735 if (amount > AX25_NOUID_BLOCK) {
1736 res = -EINVAL;
1737 break;
1738 }
1739 ax25_uid_policy = amount;
1740 res = 0;
1741 break;
1742 }
1743
1744 case SIOCADDRT:
1745 case SIOCDELRT:
1746 case SIOCAX25OPTRT:
1747 if (!capable(CAP_NET_ADMIN)) {
1748 res = -EPERM;
1749 break;
1750 }
1751 res = ax25_rt_ioctl(cmd, argp);
1752 break;
1753
1754 case SIOCAX25CTLCON:
1755 if (!capable(CAP_NET_ADMIN)) {
1756 res = -EPERM;
1757 break;
1758 }
1759 res = ax25_ctl_ioctl(cmd, argp);
1760 break;
1761
1762 case SIOCAX25GETINFO:
1763 case SIOCAX25GETINFOOLD: {
1764 ax25_cb *ax25 = ax25_sk(sk);
1765 struct ax25_info_struct ax25_info;
1766
1767 ax25_info.t1 = ax25->t1 / HZ;
1768 ax25_info.t2 = ax25->t2 / HZ;
1769 ax25_info.t3 = ax25->t3 / HZ;
1770 ax25_info.idle = ax25->idle / (60 * HZ);
1771 ax25_info.n2 = ax25->n2;
1772 ax25_info.t1timer = ax25_display_timer(&ax25->t1timer) / HZ;
1773 ax25_info.t2timer = ax25_display_timer(&ax25->t2timer) / HZ;
1774 ax25_info.t3timer = ax25_display_timer(&ax25->t3timer) / HZ;
1775 ax25_info.idletimer = ax25_display_timer(&ax25->idletimer) / (60 * HZ);
1776 ax25_info.n2count = ax25->n2count;
1777 ax25_info.state = ax25->state;
1778 ax25_info.rcv_q = atomic_read(&sk->sk_rmem_alloc);
1779 ax25_info.snd_q = atomic_read(&sk->sk_wmem_alloc);
1780 ax25_info.vs = ax25->vs;
1781 ax25_info.vr = ax25->vr;
1782 ax25_info.va = ax25->va;
1783 ax25_info.vs_max = ax25->vs; /* reserved */
1784 ax25_info.paclen = ax25->paclen;
1785 ax25_info.window = ax25->window;
1786
1787 /* old structure? */
1788 if (cmd == SIOCAX25GETINFOOLD) {
1789 static int warned = 0;
1790 if (!warned) {
1791 printk(KERN_INFO "%s uses old SIOCAX25GETINFO\n",
1792 current->comm);
1793 warned=1;
1794 }
1795
1796 if (copy_to_user(argp, &ax25_info, sizeof(struct ax25_info_struct_deprecated))) {
1797 res = -EFAULT;
1798 break;
1799 }
1800 } else {
1801 if (copy_to_user(argp, &ax25_info, sizeof(struct ax25_info_struct))) {
1802 res = -EINVAL;
1803 break;
1804 }
1805 }
1806 res = 0;
1807 break;
1808 }
1809
1810 case SIOCAX25ADDFWD:
1811 case SIOCAX25DELFWD: {
1812 struct ax25_fwd_struct ax25_fwd;
1813 if (!capable(CAP_NET_ADMIN)) {
1814 res = -EPERM;
1815 break;
1816 }
1817 if (copy_from_user(&ax25_fwd, argp, sizeof(ax25_fwd))) {
1818 res = -EFAULT;
1819 break;
1820 }
1821 res = ax25_fwd_ioctl(cmd, &ax25_fwd);
1822 break;
1823 }
1824
1825 case SIOCGIFADDR:
1826 case SIOCSIFADDR:
1827 case SIOCGIFDSTADDR:
1828 case SIOCSIFDSTADDR:
1829 case SIOCGIFBRDADDR:
1830 case SIOCSIFBRDADDR:
1831 case SIOCGIFNETMASK:
1832 case SIOCSIFNETMASK:
1833 case SIOCGIFMETRIC:
1834 case SIOCSIFMETRIC:
1835 res = -EINVAL;
1836 break;
1837
1838 default:
1839 res = dev_ioctl(cmd, argp);
1840 break;
1841 }
1842 release_sock(sk);
1843
1844 return res;
1845}
1846
1847#ifdef CONFIG_PROC_FS
1848
1849static void *ax25_info_start(struct seq_file *seq, loff_t *pos)
1850{
1851 struct ax25_cb *ax25;
1852 struct hlist_node *node;
1853 int i = 0;
1854
1855 spin_lock_bh(&ax25_list_lock);
1856 ax25_for_each(ax25, node, &ax25_list) {
1857 if (i == *pos)
1858 return ax25;
1859 ++i;
1860 }
1861 return NULL;
1862}
1863
1864static void *ax25_info_next(struct seq_file *seq, void *v, loff_t *pos)
1865{
1866 ++*pos;
1867
1868 return hlist_entry( ((struct ax25_cb *)v)->ax25_node.next,
1869 struct ax25_cb, ax25_node);
1870}
1871
1872static void ax25_info_stop(struct seq_file *seq, void *v)
1873{
1874 spin_unlock_bh(&ax25_list_lock);
1875}
1876
1877static int ax25_info_show(struct seq_file *seq, void *v)
1878{
1879 ax25_cb *ax25 = v;
1880 int k;
1881
1882
1883 /*
1884 * New format:
1885 * magic dev src_addr dest_addr,digi1,digi2,.. st vs vr va t1 t1 t2 t2 t3 t3 idle idle n2 n2 rtt window paclen Snd-Q Rcv-Q inode
1886 */
1887
1888 seq_printf(seq, "%8.8lx %s %s%s ",
1889 (long) ax25,
1890 ax25->ax25_dev == NULL? "???" : ax25->ax25_dev->dev->name,
1891 ax2asc(&ax25->source_addr),
1892 ax25->iamdigi? "*":"");
1893 seq_printf(seq, "%s", ax2asc(&ax25->dest_addr));
1894
1895 for (k=0; (ax25->digipeat != NULL) && (k < ax25->digipeat->ndigi); k++) {
1896 seq_printf(seq, ",%s%s",
1897 ax2asc(&ax25->digipeat->calls[k]),
1898 ax25->digipeat->repeated[k]? "*":"");
1899 }
1900
1901 seq_printf(seq, " %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %d %d",
1902 ax25->state,
1903 ax25->vs, ax25->vr, ax25->va,
1904 ax25_display_timer(&ax25->t1timer) / HZ, ax25->t1 / HZ,
1905 ax25_display_timer(&ax25->t2timer) / HZ, ax25->t2 / HZ,
1906 ax25_display_timer(&ax25->t3timer) / HZ, ax25->t3 / HZ,
1907 ax25_display_timer(&ax25->idletimer) / (60 * HZ),
1908 ax25->idle / (60 * HZ),
1909 ax25->n2count, ax25->n2,
1910 ax25->rtt / HZ,
1911 ax25->window,
1912 ax25->paclen);
1913
1914 if (ax25->sk != NULL) {
1915 bh_lock_sock(ax25->sk);
1916 seq_printf(seq," %d %d %ld\n",
1917 atomic_read(&ax25->sk->sk_wmem_alloc),
1918 atomic_read(&ax25->sk->sk_rmem_alloc),
1919 ax25->sk->sk_socket != NULL ? SOCK_INODE(ax25->sk->sk_socket)->i_ino : 0L);
1920 bh_unlock_sock(ax25->sk);
1921 } else {
1922 seq_puts(seq, " * * *\n");
1923 }
1924 return 0;
1925}
1926
1927static struct seq_operations ax25_info_seqops = {
1928 .start = ax25_info_start,
1929 .next = ax25_info_next,
1930 .stop = ax25_info_stop,
1931 .show = ax25_info_show,
1932};
1933
1934static int ax25_info_open(struct inode *inode, struct file *file)
1935{
1936 return seq_open(file, &ax25_info_seqops);
1937}
1938
1939static struct file_operations ax25_info_fops = {
1940 .owner = THIS_MODULE,
1941 .open = ax25_info_open,
1942 .read = seq_read,
1943 .llseek = seq_lseek,
1944 .release = seq_release,
1945};
1946
1947#endif
1948
1949static struct net_proto_family ax25_family_ops = {
1950 .family = PF_AX25,
1951 .create = ax25_create,
1952 .owner = THIS_MODULE,
1953};
1954
1955static struct proto_ops ax25_proto_ops = {
1956 .family = PF_AX25,
1957 .owner = THIS_MODULE,
1958 .release = ax25_release,
1959 .bind = ax25_bind,
1960 .connect = ax25_connect,
1961 .socketpair = sock_no_socketpair,
1962 .accept = ax25_accept,
1963 .getname = ax25_getname,
1964 .poll = datagram_poll,
1965 .ioctl = ax25_ioctl,
1966 .listen = ax25_listen,
1967 .shutdown = ax25_shutdown,
1968 .setsockopt = ax25_setsockopt,
1969 .getsockopt = ax25_getsockopt,
1970 .sendmsg = ax25_sendmsg,
1971 .recvmsg = ax25_recvmsg,
1972 .mmap = sock_no_mmap,
1973 .sendpage = sock_no_sendpage,
1974};
1975
1976/*
1977 * Called by socket.c on kernel start up
1978 */
1979static struct packet_type ax25_packet_type = {
1980 .type = __constant_htons(ETH_P_AX25),
1981 .dev = NULL, /* All devices */
1982 .func = ax25_kiss_rcv,
1983};
1984
1985static struct notifier_block ax25_dev_notifier = {
1986 .notifier_call =ax25_device_event,
1987};
1988
1989EXPORT_SYMBOL(ax25_encapsulate);
1990EXPORT_SYMBOL(ax25_rebuild_header);
1991EXPORT_SYMBOL(ax25_findbyuid);
1992EXPORT_SYMBOL(ax25_find_cb);
1993EXPORT_SYMBOL(ax25_linkfail_register);
1994EXPORT_SYMBOL(ax25_linkfail_release);
1995EXPORT_SYMBOL(ax25_listen_register);
1996EXPORT_SYMBOL(ax25_listen_release);
1997EXPORT_SYMBOL(ax25_protocol_register);
1998EXPORT_SYMBOL(ax25_protocol_release);
1999EXPORT_SYMBOL(ax25_send_frame);
2000EXPORT_SYMBOL(ax25_uid_policy);
2001EXPORT_SYMBOL(ax25cmp);
2002EXPORT_SYMBOL(ax2asc);
2003EXPORT_SYMBOL(asc2ax);
2004EXPORT_SYMBOL(null_ax25_address);
2005EXPORT_SYMBOL(ax25_display_timer);
2006
2007static int __init ax25_init(void)
2008{
2009 int rc = proto_register(&ax25_proto, 0);
2010
2011 if (rc != 0)
2012 goto out;
2013
2014 sock_register(&ax25_family_ops);
2015 dev_add_pack(&ax25_packet_type);
2016 register_netdevice_notifier(&ax25_dev_notifier);
2017 ax25_register_sysctl();
2018
2019 proc_net_fops_create("ax25_route", S_IRUGO, &ax25_route_fops);
2020 proc_net_fops_create("ax25", S_IRUGO, &ax25_info_fops);
2021 proc_net_fops_create("ax25_calls", S_IRUGO, &ax25_uid_fops);
2022out:
2023 return rc;
2024}
2025module_init(ax25_init);
2026
2027
2028MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");
2029MODULE_DESCRIPTION("The amateur radio AX.25 link layer protocol");
2030MODULE_LICENSE("GPL");
2031MODULE_ALIAS_NETPROTO(PF_AX25);
2032
2033static void __exit ax25_exit(void)
2034{
2035 proc_net_remove("ax25_route");
2036 proc_net_remove("ax25");
2037 proc_net_remove("ax25_calls");
2038 ax25_rt_free();
2039 ax25_uid_free();
2040 ax25_dev_free();
2041
2042 ax25_unregister_sysctl();
2043 unregister_netdevice_notifier(&ax25_dev_notifier);
2044
2045 dev_remove_pack(&ax25_packet_type);
2046
2047 sock_unregister(PF_AX25);
2048 proto_unregister(&ax25_proto);
2049}
2050module_exit(ax25_exit);
diff --git a/net/ax25/ax25_addr.c b/net/ax25/ax25_addr.c
new file mode 100644
index 000000000000..f4fa6dfb846e
--- /dev/null
+++ b/net/ax25/ax25_addr.c
@@ -0,0 +1,290 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
8 */
9#include <linux/errno.h>
10#include <linux/types.h>
11#include <linux/socket.h>
12#include <linux/in.h>
13#include <linux/kernel.h>
14#include <linux/sched.h>
15#include <linux/timer.h>
16#include <linux/string.h>
17#include <linux/sockios.h>
18#include <linux/net.h>
19#include <net/ax25.h>
20#include <linux/inet.h>
21#include <linux/netdevice.h>
22#include <linux/skbuff.h>
23#include <net/sock.h>
24#include <asm/uaccess.h>
25#include <asm/system.h>
26#include <linux/fcntl.h>
27#include <linux/mm.h>
28#include <linux/interrupt.h>
29
30/*
31 * The null address is defined as a callsign of all spaces with an
32 * SSID of zero.
33 */
34ax25_address null_ax25_address = {{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00}};
35
36/*
37 * ax25 -> ascii conversion
38 */
39char *ax2asc(ax25_address *a)
40{
41 static char buf[11];
42 char c, *s;
43 int n;
44
45 for (n = 0, s = buf; n < 6; n++) {
46 c = (a->ax25_call[n] >> 1) & 0x7F;
47
48 if (c != ' ') *s++ = c;
49 }
50
51 *s++ = '-';
52
53 if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9) {
54 *s++ = '1';
55 n -= 10;
56 }
57
58 *s++ = n + '0';
59 *s++ = '\0';
60
61 if (*buf == '\0' || *buf == '-')
62 return "*";
63
64 return buf;
65
66}
67
68/*
69 * ascii -> ax25 conversion
70 */
71ax25_address *asc2ax(char *callsign)
72{
73 static ax25_address addr;
74 char *s;
75 int n;
76
77 for (s = callsign, n = 0; n < 6; n++) {
78 if (*s != '\0' && *s != '-')
79 addr.ax25_call[n] = *s++;
80 else
81 addr.ax25_call[n] = ' ';
82 addr.ax25_call[n] <<= 1;
83 addr.ax25_call[n] &= 0xFE;
84 }
85
86 if (*s++ == '\0') {
87 addr.ax25_call[6] = 0x00;
88 return &addr;
89 }
90
91 addr.ax25_call[6] = *s++ - '0';
92
93 if (*s != '\0') {
94 addr.ax25_call[6] *= 10;
95 addr.ax25_call[6] += *s++ - '0';
96 }
97
98 addr.ax25_call[6] <<= 1;
99 addr.ax25_call[6] &= 0x1E;
100
101 return &addr;
102}
103
104/*
105 * Compare two ax.25 addresses
106 */
107int ax25cmp(ax25_address *a, ax25_address *b)
108{
109 int ct = 0;
110
111 while (ct < 6) {
112 if ((a->ax25_call[ct] & 0xFE) != (b->ax25_call[ct] & 0xFE)) /* Clean off repeater bits */
113 return 1;
114 ct++;
115 }
116
117 if ((a->ax25_call[ct] & 0x1E) == (b->ax25_call[ct] & 0x1E)) /* SSID without control bit */
118 return 0;
119
120 return 2; /* Partial match */
121}
122
123/*
124 * Compare two AX.25 digipeater paths.
125 */
126int ax25digicmp(ax25_digi *digi1, ax25_digi *digi2)
127{
128 int i;
129
130 if (digi1->ndigi != digi2->ndigi)
131 return 1;
132
133 if (digi1->lastrepeat != digi2->lastrepeat)
134 return 1;
135
136 for (i = 0; i < digi1->ndigi; i++)
137 if (ax25cmp(&digi1->calls[i], &digi2->calls[i]) != 0)
138 return 1;
139
140 return 0;
141}
142
143/*
144 * Given an AX.25 address pull of to, from, digi list, command/response and the start of data
145 *
146 */
147unsigned char *ax25_addr_parse(unsigned char *buf, int len, ax25_address *src, ax25_address *dest, ax25_digi *digi, int *flags, int *dama)
148{
149 int d = 0;
150
151 if (len < 14) return NULL;
152
153 if (flags != NULL) {
154 *flags = 0;
155
156 if (buf[6] & AX25_CBIT)
157 *flags = AX25_COMMAND;
158 if (buf[13] & AX25_CBIT)
159 *flags = AX25_RESPONSE;
160 }
161
162 if (dama != NULL)
163 *dama = ~buf[13] & AX25_DAMA_FLAG;
164
165 /* Copy to, from */
166 if (dest != NULL)
167 memcpy(dest, buf + 0, AX25_ADDR_LEN);
168 if (src != NULL)
169 memcpy(src, buf + 7, AX25_ADDR_LEN);
170
171 buf += 2 * AX25_ADDR_LEN;
172 len -= 2 * AX25_ADDR_LEN;
173
174 digi->lastrepeat = -1;
175 digi->ndigi = 0;
176
177 while (!(buf[-1] & AX25_EBIT)) {
178 if (d >= AX25_MAX_DIGIS) return NULL; /* Max of 6 digis */
179 if (len < 7) return NULL; /* Short packet */
180
181 memcpy(&digi->calls[d], buf, AX25_ADDR_LEN);
182 digi->ndigi = d + 1;
183
184 if (buf[6] & AX25_HBIT) {
185 digi->repeated[d] = 1;
186 digi->lastrepeat = d;
187 } else {
188 digi->repeated[d] = 0;
189 }
190
191 buf += AX25_ADDR_LEN;
192 len -= AX25_ADDR_LEN;
193 d++;
194 }
195
196 return buf;
197}
198
199/*
200 * Assemble an AX.25 header from the bits
201 */
202int ax25_addr_build(unsigned char *buf, ax25_address *src, ax25_address *dest, ax25_digi *d, int flag, int modulus)
203{
204 int len = 0;
205 int ct = 0;
206
207 memcpy(buf, dest, AX25_ADDR_LEN);
208 buf[6] &= ~(AX25_EBIT | AX25_CBIT);
209 buf[6] |= AX25_SSSID_SPARE;
210
211 if (flag == AX25_COMMAND) buf[6] |= AX25_CBIT;
212
213 buf += AX25_ADDR_LEN;
214 len += AX25_ADDR_LEN;
215
216 memcpy(buf, src, AX25_ADDR_LEN);
217 buf[6] &= ~(AX25_EBIT | AX25_CBIT);
218 buf[6] &= ~AX25_SSSID_SPARE;
219
220 if (modulus == AX25_MODULUS)
221 buf[6] |= AX25_SSSID_SPARE;
222 else
223 buf[6] |= AX25_ESSID_SPARE;
224
225 if (flag == AX25_RESPONSE) buf[6] |= AX25_CBIT;
226
227 /*
228 * Fast path the normal digiless path
229 */
230 if (d == NULL || d->ndigi == 0) {
231 buf[6] |= AX25_EBIT;
232 return 2 * AX25_ADDR_LEN;
233 }
234
235 buf += AX25_ADDR_LEN;
236 len += AX25_ADDR_LEN;
237
238 while (ct < d->ndigi) {
239 memcpy(buf, &d->calls[ct], AX25_ADDR_LEN);
240
241 if (d->repeated[ct])
242 buf[6] |= AX25_HBIT;
243 else
244 buf[6] &= ~AX25_HBIT;
245
246 buf[6] &= ~AX25_EBIT;
247 buf[6] |= AX25_SSSID_SPARE;
248
249 buf += AX25_ADDR_LEN;
250 len += AX25_ADDR_LEN;
251 ct++;
252 }
253
254 buf[-1] |= AX25_EBIT;
255
256 return len;
257}
258
259int ax25_addr_size(ax25_digi *dp)
260{
261 if (dp == NULL)
262 return 2 * AX25_ADDR_LEN;
263
264 return AX25_ADDR_LEN * (2 + dp->ndigi);
265}
266
267/*
268 * Reverse Digipeat List. May not pass both parameters as same struct
269 */
270void ax25_digi_invert(ax25_digi *in, ax25_digi *out)
271{
272 int ct;
273
274 out->ndigi = in->ndigi;
275 out->lastrepeat = in->ndigi - in->lastrepeat - 2;
276
277 /* Invert the digipeaters */
278 for (ct = 0; ct < in->ndigi; ct++) {
279 out->calls[ct] = in->calls[in->ndigi - ct - 1];
280
281 if (ct <= out->lastrepeat) {
282 out->calls[ct].ax25_call[6] |= AX25_HBIT;
283 out->repeated[ct] = 1;
284 } else {
285 out->calls[ct].ax25_call[6] &= ~AX25_HBIT;
286 out->repeated[ct] = 0;
287 }
288 }
289}
290
diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c
new file mode 100644
index 000000000000..dab77efe34a6
--- /dev/null
+++ b/net/ax25/ax25_dev.c
@@ -0,0 +1,208 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
8 */
9#include <linux/config.h>
10#include <linux/errno.h>
11#include <linux/types.h>
12#include <linux/socket.h>
13#include <linux/in.h>
14#include <linux/kernel.h>
15#include <linux/sched.h>
16#include <linux/timer.h>
17#include <linux/string.h>
18#include <linux/sockios.h>
19#include <linux/net.h>
20#include <linux/spinlock.h>
21#include <net/ax25.h>
22#include <linux/inet.h>
23#include <linux/netdevice.h>
24#include <linux/if_arp.h>
25#include <linux/skbuff.h>
26#include <net/sock.h>
27#include <asm/uaccess.h>
28#include <asm/system.h>
29#include <linux/fcntl.h>
30#include <linux/mm.h>
31#include <linux/interrupt.h>
32#include <linux/init.h>
33
34ax25_dev *ax25_dev_list;
35DEFINE_SPINLOCK(ax25_dev_lock);
36
37ax25_dev *ax25_addr_ax25dev(ax25_address *addr)
38{
39 ax25_dev *ax25_dev, *res = NULL;
40
41 spin_lock_bh(&ax25_dev_lock);
42 for (ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
43 if (ax25cmp(addr, (ax25_address *)ax25_dev->dev->dev_addr) == 0) {
44 res = ax25_dev;
45 }
46 spin_unlock_bh(&ax25_dev_lock);
47
48 return res;
49}
50
51/*
52 * This is called when an interface is brought up. These are
53 * reasonable defaults.
54 */
55void ax25_dev_device_up(struct net_device *dev)
56{
57 ax25_dev *ax25_dev;
58
59 if ((ax25_dev = kmalloc(sizeof(*ax25_dev), GFP_ATOMIC)) == NULL) {
60 printk(KERN_ERR "AX.25: ax25_dev_device_up - out of memory\n");
61 return;
62 }
63
64 ax25_unregister_sysctl();
65
66 memset(ax25_dev, 0x00, sizeof(*ax25_dev));
67
68 dev->ax25_ptr = ax25_dev;
69 ax25_dev->dev = dev;
70 dev_hold(dev);
71 ax25_dev->forward = NULL;
72
73 ax25_dev->values[AX25_VALUES_IPDEFMODE] = AX25_DEF_IPDEFMODE;
74 ax25_dev->values[AX25_VALUES_AXDEFMODE] = AX25_DEF_AXDEFMODE;
75 ax25_dev->values[AX25_VALUES_BACKOFF] = AX25_DEF_BACKOFF;
76 ax25_dev->values[AX25_VALUES_CONMODE] = AX25_DEF_CONMODE;
77 ax25_dev->values[AX25_VALUES_WINDOW] = AX25_DEF_WINDOW;
78 ax25_dev->values[AX25_VALUES_EWINDOW] = AX25_DEF_EWINDOW;
79 ax25_dev->values[AX25_VALUES_T1] = AX25_DEF_T1;
80 ax25_dev->values[AX25_VALUES_T2] = AX25_DEF_T2;
81 ax25_dev->values[AX25_VALUES_T3] = AX25_DEF_T3;
82 ax25_dev->values[AX25_VALUES_IDLE] = AX25_DEF_IDLE;
83 ax25_dev->values[AX25_VALUES_N2] = AX25_DEF_N2;
84 ax25_dev->values[AX25_VALUES_PACLEN] = AX25_DEF_PACLEN;
85 ax25_dev->values[AX25_VALUES_PROTOCOL] = AX25_DEF_PROTOCOL;
86 ax25_dev->values[AX25_VALUES_DS_TIMEOUT]= AX25_DEF_DS_TIMEOUT;
87
88#if defined(CONFIG_AX25_DAMA_SLAVE) || defined(CONFIG_AX25_DAMA_MASTER)
89 init_timer(&ax25_dev->dama.slave_timer);
90#endif
91
92 spin_lock_bh(&ax25_dev_lock);
93 ax25_dev->next = ax25_dev_list;
94 ax25_dev_list = ax25_dev;
95 spin_unlock_bh(&ax25_dev_lock);
96
97 ax25_register_sysctl();
98}
99
100void ax25_dev_device_down(struct net_device *dev)
101{
102 ax25_dev *s, *ax25_dev;
103
104 if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
105 return;
106
107 ax25_unregister_sysctl();
108
109 spin_lock_bh(&ax25_dev_lock);
110
111#ifdef CONFIG_AX25_DAMA_SLAVE
112 ax25_ds_del_timer(ax25_dev);
113#endif
114
115 /*
116 * Remove any packet forwarding that points to this device.
117 */
118 for (s = ax25_dev_list; s != NULL; s = s->next)
119 if (s->forward == dev)
120 s->forward = NULL;
121
122 if ((s = ax25_dev_list) == ax25_dev) {
123 ax25_dev_list = s->next;
124 spin_unlock_bh(&ax25_dev_lock);
125 dev_put(dev);
126 kfree(ax25_dev);
127 ax25_register_sysctl();
128 return;
129 }
130
131 while (s != NULL && s->next != NULL) {
132 if (s->next == ax25_dev) {
133 s->next = ax25_dev->next;
134 spin_unlock_bh(&ax25_dev_lock);
135 dev_put(dev);
136 kfree(ax25_dev);
137 ax25_register_sysctl();
138 return;
139 }
140
141 s = s->next;
142 }
143 spin_unlock_bh(&ax25_dev_lock);
144 dev->ax25_ptr = NULL;
145
146 ax25_register_sysctl();
147}
148
149int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd)
150{
151 ax25_dev *ax25_dev, *fwd_dev;
152
153 if ((ax25_dev = ax25_addr_ax25dev(&fwd->port_from)) == NULL)
154 return -EINVAL;
155
156 switch (cmd) {
157 case SIOCAX25ADDFWD:
158 if ((fwd_dev = ax25_addr_ax25dev(&fwd->port_to)) == NULL)
159 return -EINVAL;
160 if (ax25_dev->forward != NULL)
161 return -EINVAL;
162 ax25_dev->forward = fwd_dev->dev;
163 break;
164
165 case SIOCAX25DELFWD:
166 if (ax25_dev->forward == NULL)
167 return -EINVAL;
168 ax25_dev->forward = NULL;
169 break;
170
171 default:
172 return -EINVAL;
173 }
174
175 return 0;
176}
177
178struct net_device *ax25_fwd_dev(struct net_device *dev)
179{
180 ax25_dev *ax25_dev;
181
182 if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
183 return dev;
184
185 if (ax25_dev->forward == NULL)
186 return dev;
187
188 return ax25_dev->forward;
189}
190
191/*
192 * Free all memory associated with device structures.
193 */
194void __exit ax25_dev_free(void)
195{
196 ax25_dev *s, *ax25_dev;
197
198 spin_lock_bh(&ax25_dev_lock);
199 ax25_dev = ax25_dev_list;
200 while (ax25_dev != NULL) {
201 s = ax25_dev;
202 dev_put(ax25_dev->dev);
203 ax25_dev = ax25_dev->next;
204 kfree(s);
205 }
206 ax25_dev_list = NULL;
207 spin_unlock_bh(&ax25_dev_lock);
208}
diff --git a/net/ax25/ax25_ds_in.c b/net/ax25/ax25_ds_in.c
new file mode 100644
index 000000000000..8adc0022cf58
--- /dev/null
+++ b/net/ax25/ax25_ds_in.c
@@ -0,0 +1,305 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
8 * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
9 */
10#include <linux/errno.h>
11#include <linux/types.h>
12#include <linux/socket.h>
13#include <linux/in.h>
14#include <linux/kernel.h>
15#include <linux/sched.h>
16#include <linux/timer.h>
17#include <linux/string.h>
18#include <linux/sockios.h>
19#include <linux/net.h>
20#include <net/ax25.h>
21#include <linux/inet.h>
22#include <linux/netdevice.h>
23#include <linux/skbuff.h>
24#include <net/sock.h>
25#include <net/ip.h> /* For ip_rcv */
26#include <net/tcp.h>
27#include <asm/uaccess.h>
28#include <asm/system.h>
29#include <linux/fcntl.h>
30#include <linux/mm.h>
31#include <linux/interrupt.h>
32
33/*
34 * State machine for state 1, Awaiting Connection State.
35 * The handling of the timer(s) is in file ax25_ds_timer.c.
36 * Handling of state 0 and connection release is in ax25.c.
37 */
38static int ax25_ds_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type)
39{
40 switch (frametype) {
41 case AX25_SABM:
42 ax25->modulus = AX25_MODULUS;
43 ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
44 ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
45 break;
46
47 case AX25_SABME:
48 ax25->modulus = AX25_EMODULUS;
49 ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
50 ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
51 break;
52
53 case AX25_DISC:
54 ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE);
55 break;
56
57 case AX25_UA:
58 ax25_calculate_rtt(ax25);
59 ax25_stop_t1timer(ax25);
60 ax25_start_t3timer(ax25);
61 ax25_start_idletimer(ax25);
62 ax25->vs = 0;
63 ax25->va = 0;
64 ax25->vr = 0;
65 ax25->state = AX25_STATE_3;
66 ax25->n2count = 0;
67 if (ax25->sk != NULL) {
68 bh_lock_sock(ax25->sk);
69 ax25->sk->sk_state = TCP_ESTABLISHED;
70 /*
71 * For WAIT_SABM connections we will produce an accept
72 * ready socket here
73 */
74 if (!sock_flag(ax25->sk, SOCK_DEAD))
75 ax25->sk->sk_state_change(ax25->sk);
76 bh_unlock_sock(ax25->sk);
77 }
78 ax25_dama_on(ax25);
79
80 /* according to DK4EG´s spec we are required to
81 * send a RR RESPONSE FINAL NR=0.
82 */
83
84 ax25_std_enquiry_response(ax25);
85 break;
86
87 case AX25_DM:
88 if (pf)
89 ax25_disconnect(ax25, ECONNREFUSED);
90 break;
91
92 default:
93 if (pf)
94 ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
95 break;
96 }
97
98 return 0;
99}
100
101/*
102 * State machine for state 2, Awaiting Release State.
103 * The handling of the timer(s) is in file ax25_ds_timer.c
104 * Handling of state 0 and connection release is in ax25.c.
105 */
106static int ax25_ds_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type)
107{
108 switch (frametype) {
109 case AX25_SABM:
110 case AX25_SABME:
111 ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
112 ax25_dama_off(ax25);
113 break;
114
115 case AX25_DISC:
116 ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
117 ax25_dama_off(ax25);
118 ax25_disconnect(ax25, 0);
119 break;
120
121 case AX25_DM:
122 case AX25_UA:
123 if (pf) {
124 ax25_dama_off(ax25);
125 ax25_disconnect(ax25, 0);
126 }
127 break;
128
129 case AX25_I:
130 case AX25_REJ:
131 case AX25_RNR:
132 case AX25_RR:
133 if (pf) {
134 ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
135 ax25_dama_off(ax25);
136 }
137 break;
138
139 default:
140 break;
141 }
142
143 return 0;
144}
145
146/*
147 * State machine for state 3, Connected State.
148 * The handling of the timer(s) is in file ax25_timer.c
149 * Handling of state 0 and connection release is in ax25.c.
150 */
151static int ax25_ds_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int ns, int nr, int pf, int type)
152{
153 int queued = 0;
154
155 switch (frametype) {
156 case AX25_SABM:
157 case AX25_SABME:
158 if (frametype == AX25_SABM) {
159 ax25->modulus = AX25_MODULUS;
160 ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
161 } else {
162 ax25->modulus = AX25_EMODULUS;
163 ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
164 }
165 ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
166 ax25_stop_t1timer(ax25);
167 ax25_start_t3timer(ax25);
168 ax25_start_idletimer(ax25);
169 ax25->condition = 0x00;
170 ax25->vs = 0;
171 ax25->va = 0;
172 ax25->vr = 0;
173 ax25_requeue_frames(ax25);
174 ax25_dama_on(ax25);
175 break;
176
177 case AX25_DISC:
178 ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
179 ax25_dama_off(ax25);
180 ax25_disconnect(ax25, 0);
181 break;
182
183 case AX25_DM:
184 ax25_dama_off(ax25);
185 ax25_disconnect(ax25, ECONNRESET);
186 break;
187
188 case AX25_RR:
189 case AX25_RNR:
190 if (frametype == AX25_RR)
191 ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
192 else
193 ax25->condition |= AX25_COND_PEER_RX_BUSY;
194
195 if (ax25_validate_nr(ax25, nr)) {
196 if (ax25_check_iframes_acked(ax25, nr))
197 ax25->n2count=0;
198 if (type == AX25_COMMAND && pf)
199 ax25_ds_enquiry_response(ax25);
200 } else {
201 ax25_ds_nr_error_recovery(ax25);
202 ax25->state = AX25_STATE_1;
203 }
204 break;
205
206 case AX25_REJ:
207 ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
208
209 if (ax25_validate_nr(ax25, nr)) {
210 if (ax25->va != nr)
211 ax25->n2count=0;
212
213 ax25_frames_acked(ax25, nr);
214 ax25_calculate_rtt(ax25);
215 ax25_stop_t1timer(ax25);
216 ax25_start_t3timer(ax25);
217 ax25_requeue_frames(ax25);
218
219 if (type == AX25_COMMAND && pf)
220 ax25_ds_enquiry_response(ax25);
221 } else {
222 ax25_ds_nr_error_recovery(ax25);
223 ax25->state = AX25_STATE_1;
224 }
225 break;
226
227 case AX25_I:
228 if (!ax25_validate_nr(ax25, nr)) {
229 ax25_ds_nr_error_recovery(ax25);
230 ax25->state = AX25_STATE_1;
231 break;
232 }
233 if (ax25->condition & AX25_COND_PEER_RX_BUSY) {
234 ax25_frames_acked(ax25, nr);
235 ax25->n2count = 0;
236 } else {
237 if (ax25_check_iframes_acked(ax25, nr))
238 ax25->n2count = 0;
239 }
240 if (ax25->condition & AX25_COND_OWN_RX_BUSY) {
241 if (pf) ax25_ds_enquiry_response(ax25);
242 break;
243 }
244 if (ns == ax25->vr) {
245 ax25->vr = (ax25->vr + 1) % ax25->modulus;
246 queued = ax25_rx_iframe(ax25, skb);
247 if (ax25->condition & AX25_COND_OWN_RX_BUSY)
248 ax25->vr = ns; /* ax25->vr - 1 */
249 ax25->condition &= ~AX25_COND_REJECT;
250 if (pf) {
251 ax25_ds_enquiry_response(ax25);
252 } else {
253 if (!(ax25->condition & AX25_COND_ACK_PENDING)) {
254 ax25->condition |= AX25_COND_ACK_PENDING;
255 ax25_start_t2timer(ax25);
256 }
257 }
258 } else {
259 if (ax25->condition & AX25_COND_REJECT) {
260 if (pf) ax25_ds_enquiry_response(ax25);
261 } else {
262 ax25->condition |= AX25_COND_REJECT;
263 ax25_ds_enquiry_response(ax25);
264 ax25->condition &= ~AX25_COND_ACK_PENDING;
265 }
266 }
267 break;
268
269 case AX25_FRMR:
270 case AX25_ILLEGAL:
271 ax25_ds_establish_data_link(ax25);
272 ax25->state = AX25_STATE_1;
273 break;
274
275 default:
276 break;
277 }
278
279 return queued;
280}
281
282/*
283 * Higher level upcall for a LAPB frame
284 */
285int ax25_ds_frame_in(ax25_cb *ax25, struct sk_buff *skb, int type)
286{
287 int queued = 0, frametype, ns, nr, pf;
288
289 frametype = ax25_decode(ax25, skb, &ns, &nr, &pf);
290
291 switch (ax25->state) {
292 case AX25_STATE_1:
293 queued = ax25_ds_state1_machine(ax25, skb, frametype, pf, type);
294 break;
295 case AX25_STATE_2:
296 queued = ax25_ds_state2_machine(ax25, skb, frametype, pf, type);
297 break;
298 case AX25_STATE_3:
299 queued = ax25_ds_state3_machine(ax25, skb, frametype, ns, nr, pf, type);
300 break;
301 }
302
303 return queued;
304}
305
diff --git a/net/ax25/ax25_ds_subr.c b/net/ax25/ax25_ds_subr.c
new file mode 100644
index 000000000000..10ffd2beba3f
--- /dev/null
+++ b/net/ax25/ax25_ds_subr.c
@@ -0,0 +1,212 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
8 * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
9 */
10#include <linux/errno.h>
11#include <linux/types.h>
12#include <linux/socket.h>
13#include <linux/in.h>
14#include <linux/kernel.h>
15#include <linux/sched.h>
16#include <linux/timer.h>
17#include <linux/string.h>
18#include <linux/sockios.h>
19#include <linux/spinlock.h>
20#include <linux/net.h>
21#include <net/ax25.h>
22#include <linux/inet.h>
23#include <linux/netdevice.h>
24#include <linux/skbuff.h>
25#include <net/sock.h>
26#include <asm/uaccess.h>
27#include <asm/system.h>
28#include <linux/fcntl.h>
29#include <linux/mm.h>
30#include <linux/interrupt.h>
31
32void ax25_ds_nr_error_recovery(ax25_cb *ax25)
33{
34 ax25_ds_establish_data_link(ax25);
35}
36
37/*
38 * dl1bke 960114: transmit I frames on DAMA poll
39 */
40void ax25_ds_enquiry_response(ax25_cb *ax25)
41{
42 ax25_cb *ax25o;
43 struct hlist_node *node;
44
45 /* Please note that neither DK4EG´s nor DG2FEF´s
46 * DAMA spec mention the following behaviour as seen
47 * with TheFirmware:
48 *
49 * DB0ACH->DL1BKE <RR C P R0> [DAMA]
50 * DL1BKE->DB0ACH <I NR=0 NS=0>
51 * DL1BKE-7->DB0PRA-6 DB0ACH <I C S3 R5>
52 * DL1BKE->DB0ACH <RR R F R0>
53 *
54 * The Flexnet DAMA Master implementation apparently
55 * insists on the "proper" AX.25 behaviour:
56 *
57 * DB0ACH->DL1BKE <RR C P R0> [DAMA]
58 * DL1BKE->DB0ACH <RR R F R0>
59 * DL1BKE->DB0ACH <I NR=0 NS=0>
60 * DL1BKE-7->DB0PRA-6 DB0ACH <I C S3 R5>
61 *
62 * Flexnet refuses to send us *any* I frame if we send
63 * a REJ in case AX25_COND_REJECT is set. It is superfluous in
64 * this mode anyway (a RR or RNR invokes the retransmission).
65 * Is this a Flexnet bug?
66 */
67
68 ax25_std_enquiry_response(ax25);
69
70 if (!(ax25->condition & AX25_COND_PEER_RX_BUSY)) {
71 ax25_requeue_frames(ax25);
72 ax25_kick(ax25);
73 }
74
75 if (ax25->state == AX25_STATE_1 || ax25->state == AX25_STATE_2 || skb_peek(&ax25->ack_queue) != NULL)
76 ax25_ds_t1_timeout(ax25);
77 else
78 ax25->n2count = 0;
79
80 ax25_start_t3timer(ax25);
81 ax25_ds_set_timer(ax25->ax25_dev);
82
83 spin_lock_bh(&ax25_list_lock);
84 ax25_for_each(ax25o, node, &ax25_list) {
85 if (ax25o == ax25)
86 continue;
87
88 if (ax25o->ax25_dev != ax25->ax25_dev)
89 continue;
90
91 if (ax25o->state == AX25_STATE_1 || ax25o->state == AX25_STATE_2) {
92 ax25_ds_t1_timeout(ax25o);
93 continue;
94 }
95
96 if (!(ax25o->condition & AX25_COND_PEER_RX_BUSY) && ax25o->state == AX25_STATE_3) {
97 ax25_requeue_frames(ax25o);
98 ax25_kick(ax25o);
99 }
100
101 if (ax25o->state == AX25_STATE_1 || ax25o->state == AX25_STATE_2 || skb_peek(&ax25o->ack_queue) != NULL)
102 ax25_ds_t1_timeout(ax25o);
103
104 /* do not start T3 for listening sockets (tnx DD8NE) */
105
106 if (ax25o->state != AX25_STATE_0)
107 ax25_start_t3timer(ax25o);
108 }
109 spin_unlock_bh(&ax25_list_lock);
110}
111
112void ax25_ds_establish_data_link(ax25_cb *ax25)
113{
114 ax25->condition &= AX25_COND_DAMA_MODE;
115 ax25->n2count = 0;
116 ax25_calculate_t1(ax25);
117 ax25_start_t1timer(ax25);
118 ax25_stop_t2timer(ax25);
119 ax25_start_t3timer(ax25);
120}
121
122/*
123 * :::FIXME:::
124 * This is a kludge. Not all drivers recognize kiss commands.
125 * We need a driver level request to switch duplex mode, that does
126 * either SCC changing, PI config or KISS as required. Currently
127 * this request isn't reliable.
128 */
129static void ax25_kiss_cmd(ax25_dev *ax25_dev, unsigned char cmd, unsigned char param)
130{
131 struct sk_buff *skb;
132 unsigned char *p;
133
134 if (ax25_dev->dev == NULL)
135 return;
136
137 if ((skb = alloc_skb(2, GFP_ATOMIC)) == NULL)
138 return;
139
140 skb->nh.raw = skb->data;
141 p = skb_put(skb, 2);
142
143 *p++ = cmd;
144 *p++ = param;
145
146 skb->dev = ax25_dev->dev;
147 skb->protocol = htons(ETH_P_AX25);
148
149 dev_queue_xmit(skb);
150}
151
152/*
153 * A nasty problem arises if we count the number of DAMA connections
154 * wrong, especially when connections on the device already existed
155 * and our network node (or the sysop) decides to turn on DAMA Master
156 * mode. We thus flag the 'real' slave connections with
157 * ax25->dama_slave=1 and look on every disconnect if still slave
158 * connections exist.
159 */
160static int ax25_check_dama_slave(ax25_dev *ax25_dev)
161{
162 ax25_cb *ax25;
163 int res = 0;
164 struct hlist_node *node;
165
166 spin_lock_bh(&ax25_list_lock);
167 ax25_for_each(ax25, node, &ax25_list)
168 if (ax25->ax25_dev == ax25_dev && (ax25->condition & AX25_COND_DAMA_MODE) && ax25->state > AX25_STATE_1) {
169 res = 1;
170 break;
171 }
172 spin_unlock_bh(&ax25_list_lock);
173
174 return res;
175}
176
177static void ax25_dev_dama_on(ax25_dev *ax25_dev)
178{
179 if (ax25_dev == NULL)
180 return;
181
182 if (ax25_dev->dama.slave == 0)
183 ax25_kiss_cmd(ax25_dev, 5, 1);
184
185 ax25_dev->dama.slave = 1;
186 ax25_ds_set_timer(ax25_dev);
187}
188
189void ax25_dev_dama_off(ax25_dev *ax25_dev)
190{
191 if (ax25_dev == NULL)
192 return;
193
194 if (ax25_dev->dama.slave && !ax25_check_dama_slave(ax25_dev)) {
195 ax25_kiss_cmd(ax25_dev, 5, 0);
196 ax25_dev->dama.slave = 0;
197 ax25_ds_del_timer(ax25_dev);
198 }
199}
200
201void ax25_dama_on(ax25_cb *ax25)
202{
203 ax25_dev_dama_on(ax25->ax25_dev);
204 ax25->condition |= AX25_COND_DAMA_MODE;
205}
206
207void ax25_dama_off(ax25_cb *ax25)
208{
209 ax25->condition &= ~AX25_COND_DAMA_MODE;
210 ax25_dev_dama_off(ax25->ax25_dev);
211}
212
diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c
new file mode 100644
index 000000000000..3a8b67316fc3
--- /dev/null
+++ b/net/ax25/ax25_ds_timer.c
@@ -0,0 +1,241 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
8 * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
9 */
10#include <linux/errno.h>
11#include <linux/types.h>
12#include <linux/socket.h>
13#include <linux/spinlock.h>
14#include <linux/in.h>
15#include <linux/kernel.h>
16#include <linux/jiffies.h>
17#include <linux/timer.h>
18#include <linux/string.h>
19#include <linux/sockios.h>
20#include <linux/net.h>
21#include <net/tcp.h>
22#include <net/ax25.h>
23#include <linux/inet.h>
24#include <linux/netdevice.h>
25#include <linux/skbuff.h>
26#include <net/sock.h>
27#include <asm/uaccess.h>
28#include <asm/system.h>
29#include <linux/fcntl.h>
30#include <linux/mm.h>
31#include <linux/interrupt.h>
32
33static void ax25_ds_timeout(unsigned long);
34
35/*
36 * Add DAMA slave timeout timer to timer list.
37 * Unlike the connection based timers the timeout function gets
38 * triggered every second. Please note that NET_AX25_DAMA_SLAVE_TIMEOUT
39 * (aka /proc/sys/net/ax25/{dev}/dama_slave_timeout) is still in
40 * 1/10th of a second.
41 */
42
43static void ax25_ds_add_timer(ax25_dev *ax25_dev)
44{
45 struct timer_list *t = &ax25_dev->dama.slave_timer;
46 t->data = (unsigned long) ax25_dev;
47 t->function = &ax25_ds_timeout;
48 t->expires = jiffies + HZ;
49 add_timer(t);
50}
51
52void ax25_ds_del_timer(ax25_dev *ax25_dev)
53{
54 if (ax25_dev)
55 del_timer(&ax25_dev->dama.slave_timer);
56}
57
58void ax25_ds_set_timer(ax25_dev *ax25_dev)
59{
60 if (ax25_dev == NULL) /* paranoia */
61 return;
62
63 del_timer(&ax25_dev->dama.slave_timer);
64 ax25_dev->dama.slave_timeout = ax25_dev->values[AX25_VALUES_DS_TIMEOUT] / 10;
65 ax25_ds_add_timer(ax25_dev);
66}
67
68/*
69 * DAMA Slave Timeout
70 * Silently discard all (slave) connections in case our master forgot us...
71 */
72
73static void ax25_ds_timeout(unsigned long arg)
74{
75 ax25_dev *ax25_dev = (struct ax25_dev *) arg;
76 ax25_cb *ax25;
77 struct hlist_node *node;
78
79 if (ax25_dev == NULL || !ax25_dev->dama.slave)
80 return; /* Yikes! */
81
82 if (!ax25_dev->dama.slave_timeout || --ax25_dev->dama.slave_timeout) {
83 ax25_ds_set_timer(ax25_dev);
84 return;
85 }
86
87 spin_lock_bh(&ax25_list_lock);
88 ax25_for_each(ax25, node, &ax25_list) {
89 if (ax25->ax25_dev != ax25_dev || !(ax25->condition & AX25_COND_DAMA_MODE))
90 continue;
91
92 ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
93 ax25_disconnect(ax25, ETIMEDOUT);
94 }
95 spin_unlock_bh(&ax25_list_lock);
96
97 ax25_dev_dama_off(ax25_dev);
98}
99
100void ax25_ds_heartbeat_expiry(ax25_cb *ax25)
101{
102 struct sock *sk=ax25->sk;
103
104 if (sk)
105 bh_lock_sock(sk);
106
107 switch (ax25->state) {
108
109 case AX25_STATE_0:
110 /* Magic here: If we listen() and a new link dies before it
111 is accepted() it isn't 'dead' so doesn't get removed. */
112 if (!sk || sock_flag(sk, SOCK_DESTROY) ||
113 (sk->sk_state == TCP_LISTEN &&
114 sock_flag(sk, SOCK_DEAD))) {
115 if (sk) {
116 sock_hold(sk);
117 ax25_destroy_socket(ax25);
118 sock_put(sk);
119 bh_unlock_sock(sk);
120 } else
121 ax25_destroy_socket(ax25);
122 return;
123 }
124 break;
125
126 case AX25_STATE_3:
127 /*
128 * Check the state of the receive buffer.
129 */
130 if (sk != NULL) {
131 if (atomic_read(&sk->sk_rmem_alloc) <
132 (sk->sk_rcvbuf / 2) &&
133 (ax25->condition & AX25_COND_OWN_RX_BUSY)) {
134 ax25->condition &= ~AX25_COND_OWN_RX_BUSY;
135 ax25->condition &= ~AX25_COND_ACK_PENDING;
136 break;
137 }
138 }
139 break;
140 }
141
142 if (sk)
143 bh_unlock_sock(sk);
144
145 ax25_start_heartbeat(ax25);
146}
147
148/* dl1bke 960114: T3 works much like the IDLE timeout, but
149 * gets reloaded with every frame for this
150 * connection.
151 */
152void ax25_ds_t3timer_expiry(ax25_cb *ax25)
153{
154 ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
155 ax25_dama_off(ax25);
156 ax25_disconnect(ax25, ETIMEDOUT);
157}
158
159/* dl1bke 960228: close the connection when IDLE expires.
160 * unlike T3 this timer gets reloaded only on
161 * I frames.
162 */
163void ax25_ds_idletimer_expiry(ax25_cb *ax25)
164{
165 ax25_clear_queues(ax25);
166
167 ax25->n2count = 0;
168 ax25->state = AX25_STATE_2;
169
170 ax25_calculate_t1(ax25);
171 ax25_start_t1timer(ax25);
172 ax25_stop_t3timer(ax25);
173
174 if (ax25->sk != NULL) {
175 bh_lock_sock(ax25->sk);
176 ax25->sk->sk_state = TCP_CLOSE;
177 ax25->sk->sk_err = 0;
178 ax25->sk->sk_shutdown |= SEND_SHUTDOWN;
179 if (!sock_flag(ax25->sk, SOCK_DEAD)) {
180 ax25->sk->sk_state_change(ax25->sk);
181 sock_set_flag(ax25->sk, SOCK_DEAD);
182 }
183 bh_unlock_sock(ax25->sk);
184 }
185}
186
187/* dl1bke 960114: The DAMA protocol requires to send data and SABM/DISC
188 * within the poll of any connected channel. Remember
189 * that we are not allowed to send anything unless we
190 * get polled by the Master.
191 *
192 * Thus we'll have to do parts of our T1 handling in
193 * ax25_enquiry_response().
194 */
195void ax25_ds_t1_timeout(ax25_cb *ax25)
196{
197 switch (ax25->state) {
198 case AX25_STATE_1:
199 if (ax25->n2count == ax25->n2) {
200 if (ax25->modulus == AX25_MODULUS) {
201 ax25_disconnect(ax25, ETIMEDOUT);
202 return;
203 } else {
204 ax25->modulus = AX25_MODULUS;
205 ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
206 ax25->n2count = 0;
207 ax25_send_control(ax25, AX25_SABM, AX25_POLLOFF, AX25_COMMAND);
208 }
209 } else {
210 ax25->n2count++;
211 if (ax25->modulus == AX25_MODULUS)
212 ax25_send_control(ax25, AX25_SABM, AX25_POLLOFF, AX25_COMMAND);
213 else
214 ax25_send_control(ax25, AX25_SABME, AX25_POLLOFF, AX25_COMMAND);
215 }
216 break;
217
218 case AX25_STATE_2:
219 if (ax25->n2count == ax25->n2) {
220 ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
221 ax25_disconnect(ax25, ETIMEDOUT);
222 return;
223 } else {
224 ax25->n2count++;
225 }
226 break;
227
228 case AX25_STATE_3:
229 if (ax25->n2count == ax25->n2) {
230 ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE);
231 ax25_disconnect(ax25, ETIMEDOUT);
232 return;
233 } else {
234 ax25->n2count++;
235 }
236 break;
237 }
238
239 ax25_calculate_t1(ax25);
240 ax25_start_t1timer(ax25);
241}
diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c
new file mode 100644
index 000000000000..d68aff100729
--- /dev/null
+++ b/net/ax25/ax25_iface.c
@@ -0,0 +1,266 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
8 */
9#include <linux/config.h>
10#include <linux/errno.h>
11#include <linux/types.h>
12#include <linux/socket.h>
13#include <linux/in.h>
14#include <linux/kernel.h>
15#include <linux/sched.h>
16#include <linux/spinlock.h>
17#include <linux/timer.h>
18#include <linux/string.h>
19#include <linux/sockios.h>
20#include <linux/net.h>
21#include <net/ax25.h>
22#include <linux/inet.h>
23#include <linux/netdevice.h>
24#include <linux/skbuff.h>
25#include <net/sock.h>
26#include <asm/uaccess.h>
27#include <asm/system.h>
28#include <linux/fcntl.h>
29#include <linux/mm.h>
30#include <linux/interrupt.h>
31
32static struct protocol_struct {
33 struct protocol_struct *next;
34 unsigned int pid;
35 int (*func)(struct sk_buff *, ax25_cb *);
36} *protocol_list = NULL;
37static DEFINE_RWLOCK(protocol_list_lock);
38
39static struct linkfail_struct {
40 struct linkfail_struct *next;
41 void (*func)(ax25_cb *, int);
42} *linkfail_list = NULL;
43static DEFINE_SPINLOCK(linkfail_lock);
44
45static struct listen_struct {
46 struct listen_struct *next;
47 ax25_address callsign;
48 struct net_device *dev;
49} *listen_list = NULL;
50static DEFINE_SPINLOCK(listen_lock);
51
52int ax25_protocol_register(unsigned int pid,
53 int (*func)(struct sk_buff *, ax25_cb *))
54{
55 struct protocol_struct *protocol;
56
57 if (pid == AX25_P_TEXT || pid == AX25_P_SEGMENT)
58 return 0;
59#ifdef CONFIG_INET
60 if (pid == AX25_P_IP || pid == AX25_P_ARP)
61 return 0;
62#endif
63 if ((protocol = kmalloc(sizeof(*protocol), GFP_ATOMIC)) == NULL)
64 return 0;
65
66 protocol->pid = pid;
67 protocol->func = func;
68
69 write_lock(&protocol_list_lock);
70 protocol->next = protocol_list;
71 protocol_list = protocol;
72 write_unlock(&protocol_list_lock);
73
74 return 1;
75}
76
77void ax25_protocol_release(unsigned int pid)
78{
79 struct protocol_struct *s, *protocol;
80
81 write_lock(&protocol_list_lock);
82 protocol = protocol_list;
83 if (protocol == NULL) {
84 write_unlock(&protocol_list_lock);
85 return;
86 }
87
88 if (protocol->pid == pid) {
89 protocol_list = protocol->next;
90 write_unlock(&protocol_list_lock);
91 kfree(protocol);
92 return;
93 }
94
95 while (protocol != NULL && protocol->next != NULL) {
96 if (protocol->next->pid == pid) {
97 s = protocol->next;
98 protocol->next = protocol->next->next;
99 write_unlock(&protocol_list_lock);
100 kfree(s);
101 return;
102 }
103
104 protocol = protocol->next;
105 }
106 write_unlock(&protocol_list_lock);
107}
108
109int ax25_linkfail_register(void (*func)(ax25_cb *, int))
110{
111 struct linkfail_struct *linkfail;
112
113 if ((linkfail = kmalloc(sizeof(*linkfail), GFP_ATOMIC)) == NULL)
114 return 0;
115
116 linkfail->func = func;
117
118 spin_lock_bh(&linkfail_lock);
119 linkfail->next = linkfail_list;
120 linkfail_list = linkfail;
121 spin_unlock_bh(&linkfail_lock);
122
123 return 1;
124}
125
126void ax25_linkfail_release(void (*func)(ax25_cb *, int))
127{
128 struct linkfail_struct *s, *linkfail;
129
130 spin_lock_bh(&linkfail_lock);
131 linkfail = linkfail_list;
132 if (linkfail == NULL) {
133 spin_unlock_bh(&linkfail_lock);
134 return;
135 }
136
137 if (linkfail->func == func) {
138 linkfail_list = linkfail->next;
139 spin_unlock_bh(&linkfail_lock);
140 kfree(linkfail);
141 return;
142 }
143
144 while (linkfail != NULL && linkfail->next != NULL) {
145 if (linkfail->next->func == func) {
146 s = linkfail->next;
147 linkfail->next = linkfail->next->next;
148 spin_unlock_bh(&linkfail_lock);
149 kfree(s);
150 return;
151 }
152
153 linkfail = linkfail->next;
154 }
155 spin_unlock_bh(&linkfail_lock);
156}
157
158int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
159{
160 struct listen_struct *listen;
161
162 if (ax25_listen_mine(callsign, dev))
163 return 0;
164
165 if ((listen = kmalloc(sizeof(*listen), GFP_ATOMIC)) == NULL)
166 return 0;
167
168 listen->callsign = *callsign;
169 listen->dev = dev;
170
171 spin_lock_bh(&listen_lock);
172 listen->next = listen_list;
173 listen_list = listen;
174 spin_unlock_bh(&listen_lock);
175
176 return 1;
177}
178
179void ax25_listen_release(ax25_address *callsign, struct net_device *dev)
180{
181 struct listen_struct *s, *listen;
182
183 spin_lock_bh(&listen_lock);
184 listen = listen_list;
185 if (listen == NULL) {
186 spin_unlock_bh(&listen_lock);
187 return;
188 }
189
190 if (ax25cmp(&listen->callsign, callsign) == 0 && listen->dev == dev) {
191 listen_list = listen->next;
192 spin_unlock_bh(&listen_lock);
193 kfree(listen);
194 return;
195 }
196
197 while (listen != NULL && listen->next != NULL) {
198 if (ax25cmp(&listen->next->callsign, callsign) == 0 && listen->next->dev == dev) {
199 s = listen->next;
200 listen->next = listen->next->next;
201 spin_unlock_bh(&listen_lock);
202 kfree(s);
203 return;
204 }
205
206 listen = listen->next;
207 }
208 spin_unlock_bh(&listen_lock);
209}
210
211int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *)
212{
213 int (*res)(struct sk_buff *, ax25_cb *) = NULL;
214 struct protocol_struct *protocol;
215
216 read_lock(&protocol_list_lock);
217 for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
218 if (protocol->pid == pid) {
219 res = protocol->func;
220 break;
221 }
222 read_unlock(&protocol_list_lock);
223
224 return res;
225}
226
227int ax25_listen_mine(ax25_address *callsign, struct net_device *dev)
228{
229 struct listen_struct *listen;
230
231 spin_lock_bh(&listen_lock);
232 for (listen = listen_list; listen != NULL; listen = listen->next)
233 if (ax25cmp(&listen->callsign, callsign) == 0 && (listen->dev == dev || listen->dev == NULL)) {
234 spin_unlock_bh(&listen_lock);
235 return 1;
236 }
237 spin_unlock_bh(&listen_lock);
238
239 return 0;
240}
241
242void ax25_link_failed(ax25_cb *ax25, int reason)
243{
244 struct linkfail_struct *linkfail;
245
246 spin_lock_bh(&linkfail_lock);
247 for (linkfail = linkfail_list; linkfail != NULL; linkfail = linkfail->next)
248 (linkfail->func)(ax25, reason);
249 spin_unlock_bh(&linkfail_lock);
250}
251
252int ax25_protocol_is_registered(unsigned int pid)
253{
254 struct protocol_struct *protocol;
255 int res = 0;
256
257 read_lock(&protocol_list_lock);
258 for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
259 if (protocol->pid == pid) {
260 res = 1;
261 break;
262 }
263 read_unlock(&protocol_list_lock);
264
265 return res;
266}
diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c
new file mode 100644
index 000000000000..3dc808fde33f
--- /dev/null
+++ b/net/ax25/ax25_in.c
@@ -0,0 +1,470 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
8 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
9 * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
10 * Copyright (C) Hans-Joachim Hetscher DD8NE (dd8ne@bnv-bamberg.de)
11 */
12#include <linux/config.h>
13#include <linux/errno.h>
14#include <linux/types.h>
15#include <linux/socket.h>
16#include <linux/in.h>
17#include <linux/kernel.h>
18#include <linux/sched.h>
19#include <linux/timer.h>
20#include <linux/string.h>
21#include <linux/sockios.h>
22#include <linux/net.h>
23#include <net/ax25.h>
24#include <linux/inet.h>
25#include <linux/netdevice.h>
26#include <linux/skbuff.h>
27#include <linux/netfilter.h>
28#include <net/sock.h>
29#include <net/ip.h> /* For ip_rcv */
30#include <net/tcp.h>
31#include <net/arp.h> /* For arp_rcv */
32#include <asm/uaccess.h>
33#include <asm/system.h>
34#include <linux/fcntl.h>
35#include <linux/mm.h>
36#include <linux/interrupt.h>
37
38/*
39 * Given a fragment, queue it on the fragment queue and if the fragment
40 * is complete, send it back to ax25_rx_iframe.
41 */
42static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb)
43{
44 struct sk_buff *skbn, *skbo;
45
46 if (ax25->fragno != 0) {
47 if (!(*skb->data & AX25_SEG_FIRST)) {
48 if ((ax25->fragno - 1) == (*skb->data & AX25_SEG_REM)) {
49 /* Enqueue fragment */
50 ax25->fragno = *skb->data & AX25_SEG_REM;
51 skb_pull(skb, 1); /* skip fragno */
52 ax25->fraglen += skb->len;
53 skb_queue_tail(&ax25->frag_queue, skb);
54
55 /* Last fragment received ? */
56 if (ax25->fragno == 0) {
57 skbn = alloc_skb(AX25_MAX_HEADER_LEN +
58 ax25->fraglen,
59 GFP_ATOMIC);
60 if (!skbn) {
61 skb_queue_purge(&ax25->frag_queue);
62 return 1;
63 }
64
65 skb_reserve(skbn, AX25_MAX_HEADER_LEN);
66
67 skbn->dev = ax25->ax25_dev->dev;
68 skbn->h.raw = skbn->data;
69 skbn->nh.raw = skbn->data;
70
71 /* Copy data from the fragments */
72 while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL) {
73 memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
74 kfree_skb(skbo);
75 }
76
77 ax25->fraglen = 0;
78
79 if (ax25_rx_iframe(ax25, skbn) == 0)
80 kfree_skb(skbn);
81 }
82
83 return 1;
84 }
85 }
86 } else {
87 /* First fragment received */
88 if (*skb->data & AX25_SEG_FIRST) {
89 skb_queue_purge(&ax25->frag_queue);
90 ax25->fragno = *skb->data & AX25_SEG_REM;
91 skb_pull(skb, 1); /* skip fragno */
92 ax25->fraglen = skb->len;
93 skb_queue_tail(&ax25->frag_queue, skb);
94 return 1;
95 }
96 }
97
98 return 0;
99}
100
101/*
102 * This is where all valid I frames are sent to, to be dispatched to
103 * whichever protocol requires them.
104 */
105int ax25_rx_iframe(ax25_cb *ax25, struct sk_buff *skb)
106{
107 int (*func)(struct sk_buff *, ax25_cb *);
108 volatile int queued = 0;
109 unsigned char pid;
110
111 if (skb == NULL) return 0;
112
113 ax25_start_idletimer(ax25);
114
115 pid = *skb->data;
116
117#ifdef CONFIG_INET
118 if (pid == AX25_P_IP) {
119 /* working around a TCP bug to keep additional listeners
120 * happy. TCP re-uses the buffer and destroys the original
121 * content.
122 */
123 struct sk_buff *skbn = skb_copy(skb, GFP_ATOMIC);
124 if (skbn != NULL) {
125 kfree_skb(skb);
126 skb = skbn;
127 }
128
129 skb_pull(skb, 1); /* Remove PID */
130 skb->h.raw = skb->data;
131 skb->nh.raw = skb->data;
132 skb->dev = ax25->ax25_dev->dev;
133 skb->pkt_type = PACKET_HOST;
134 skb->protocol = htons(ETH_P_IP);
135 ip_rcv(skb, skb->dev, NULL); /* Wrong ptype */
136 return 1;
137 }
138#endif
139 if (pid == AX25_P_SEGMENT) {
140 skb_pull(skb, 1); /* Remove PID */
141 return ax25_rx_fragment(ax25, skb);
142 }
143
144 if ((func = ax25_protocol_function(pid)) != NULL) {
145 skb_pull(skb, 1); /* Remove PID */
146 return (*func)(skb, ax25);
147 }
148
149 if (ax25->sk != NULL && ax25->ax25_dev->values[AX25_VALUES_CONMODE] == 2) {
150 if ((!ax25->pidincl && ax25->sk->sk_protocol == pid) ||
151 ax25->pidincl) {
152 if (sock_queue_rcv_skb(ax25->sk, skb) == 0)
153 queued = 1;
154 else
155 ax25->condition |= AX25_COND_OWN_RX_BUSY;
156 }
157 }
158
159 return queued;
160}
161
162/*
163 * Higher level upcall for a LAPB frame
164 */
165static int ax25_process_rx_frame(ax25_cb *ax25, struct sk_buff *skb, int type, int dama)
166{
167 int queued = 0;
168
169 if (ax25->state == AX25_STATE_0)
170 return 0;
171
172 switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
173 case AX25_PROTO_STD_SIMPLEX:
174 case AX25_PROTO_STD_DUPLEX:
175 queued = ax25_std_frame_in(ax25, skb, type);
176 break;
177
178#ifdef CONFIG_AX25_DAMA_SLAVE
179 case AX25_PROTO_DAMA_SLAVE:
180 if (dama || ax25->ax25_dev->dama.slave)
181 queued = ax25_ds_frame_in(ax25, skb, type);
182 else
183 queued = ax25_std_frame_in(ax25, skb, type);
184 break;
185#endif
186 }
187
188 return queued;
189}
190
191static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
192 ax25_address *dev_addr, struct packet_type *ptype)
193{
194 ax25_address src, dest, *next_digi = NULL;
195 int type = 0, mine = 0, dama;
196 struct sock *make, *sk;
197 ax25_digi dp, reverse_dp;
198 ax25_cb *ax25;
199 ax25_dev *ax25_dev;
200
201 /*
202 * Process the AX.25/LAPB frame.
203 */
204
205 skb->h.raw = skb->data;
206
207 if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) {
208 kfree_skb(skb);
209 return 0;
210 }
211
212 /*
213 * Parse the address header.
214 */
215
216 if (ax25_addr_parse(skb->data, skb->len, &src, &dest, &dp, &type, &dama) == NULL) {
217 kfree_skb(skb);
218 return 0;
219 }
220
221 /*
222 * Ours perhaps ?
223 */
224 if (dp.lastrepeat + 1 < dp.ndigi) /* Not yet digipeated completely */
225 next_digi = &dp.calls[dp.lastrepeat + 1];
226
227 /*
228 * Pull of the AX.25 headers leaving the CTRL/PID bytes
229 */
230 skb_pull(skb, ax25_addr_size(&dp));
231
232 /* For our port addresses ? */
233 if (ax25cmp(&dest, dev_addr) == 0 && dp.lastrepeat + 1 == dp.ndigi)
234 mine = 1;
235
236 /* Also match on any registered callsign from L3/4 */
237 if (!mine && ax25_listen_mine(&dest, dev) && dp.lastrepeat + 1 == dp.ndigi)
238 mine = 1;
239
240 /* UI frame - bypass LAPB processing */
241 if ((*skb->data & ~0x10) == AX25_UI && dp.lastrepeat + 1 == dp.ndigi) {
242 skb->h.raw = skb->data + 2; /* skip control and pid */
243
244 ax25_send_to_raw(&dest, skb, skb->data[1]);
245
246 if (!mine && ax25cmp(&dest, (ax25_address *)dev->broadcast) != 0) {
247 kfree_skb(skb);
248 return 0;
249 }
250
251 /* Now we are pointing at the pid byte */
252 switch (skb->data[1]) {
253#ifdef CONFIG_INET
254 case AX25_P_IP:
255 skb_pull(skb,2); /* drop PID/CTRL */
256 skb->h.raw = skb->data;
257 skb->nh.raw = skb->data;
258 skb->dev = dev;
259 skb->pkt_type = PACKET_HOST;
260 skb->protocol = htons(ETH_P_IP);
261 ip_rcv(skb, dev, ptype); /* Note ptype here is the wrong one, fix me later */
262 break;
263
264 case AX25_P_ARP:
265 skb_pull(skb,2);
266 skb->h.raw = skb->data;
267 skb->nh.raw = skb->data;
268 skb->dev = dev;
269 skb->pkt_type = PACKET_HOST;
270 skb->protocol = htons(ETH_P_ARP);
271 arp_rcv(skb, dev, ptype); /* Note ptype here is wrong... */
272 break;
273#endif
274 case AX25_P_TEXT:
275 /* Now find a suitable dgram socket */
276 sk = ax25_get_socket(&dest, &src, SOCK_DGRAM);
277 if (sk != NULL) {
278 bh_lock_sock(sk);
279 if (atomic_read(&sk->sk_rmem_alloc) >=
280 sk->sk_rcvbuf) {
281 kfree_skb(skb);
282 } else {
283 /*
284 * Remove the control and PID.
285 */
286 skb_pull(skb, 2);
287 if (sock_queue_rcv_skb(sk, skb) != 0)
288 kfree_skb(skb);
289 }
290 bh_unlock_sock(sk);
291 sock_put(sk);
292 } else {
293 kfree_skb(skb);
294 }
295 break;
296
297 default:
298 kfree_skb(skb); /* Will scan SOCK_AX25 RAW sockets */
299 break;
300 }
301
302 return 0;
303 }
304
305 /*
306 * Is connected mode supported on this device ?
307 * If not, should we DM the incoming frame (except DMs) or
308 * silently ignore them. For now we stay quiet.
309 */
310 if (ax25_dev->values[AX25_VALUES_CONMODE] == 0) {
311 kfree_skb(skb);
312 return 0;
313 }
314
315 /* LAPB */
316
317 /* AX.25 state 1-4 */
318
319 ax25_digi_invert(&dp, &reverse_dp);
320
321 if ((ax25 = ax25_find_cb(&dest, &src, &reverse_dp, dev)) != NULL) {
322 /*
323 * Process the frame. If it is queued up internally it
324 * returns one otherwise we free it immediately. This
325 * routine itself wakes the user context layers so we do
326 * no further work
327 */
328 if (ax25_process_rx_frame(ax25, skb, type, dama) == 0)
329 kfree_skb(skb);
330
331 ax25_cb_put(ax25);
332 return 0;
333 }
334
335 /* AX.25 state 0 (disconnected) */
336
337 /* a) received not a SABM(E) */
338
339 if ((*skb->data & ~AX25_PF) != AX25_SABM &&
340 (*skb->data & ~AX25_PF) != AX25_SABME) {
341 /*
342 * Never reply to a DM. Also ignore any connects for
343 * addresses that are not our interfaces and not a socket.
344 */
345 if ((*skb->data & ~AX25_PF) != AX25_DM && mine)
346 ax25_return_dm(dev, &src, &dest, &dp);
347
348 kfree_skb(skb);
349 return 0;
350 }
351
352 /* b) received SABM(E) */
353
354 if (dp.lastrepeat + 1 == dp.ndigi)
355 sk = ax25_find_listener(&dest, 0, dev, SOCK_SEQPACKET);
356 else
357 sk = ax25_find_listener(next_digi, 1, dev, SOCK_SEQPACKET);
358
359 if (sk != NULL) {
360 bh_lock_sock(sk);
361 if (sk_acceptq_is_full(sk) ||
362 (make = ax25_make_new(sk, ax25_dev)) == NULL) {
363 if (mine)
364 ax25_return_dm(dev, &src, &dest, &dp);
365 kfree_skb(skb);
366 bh_unlock_sock(sk);
367 sock_put(sk);
368
369 return 0;
370 }
371
372 ax25 = ax25_sk(make);
373 skb_set_owner_r(skb, make);
374 skb_queue_head(&sk->sk_receive_queue, skb);
375
376 make->sk_state = TCP_ESTABLISHED;
377
378 sk->sk_ack_backlog++;
379 bh_unlock_sock(sk);
380 } else {
381 if (!mine) {
382 kfree_skb(skb);
383 return 0;
384 }
385
386 if ((ax25 = ax25_create_cb()) == NULL) {
387 ax25_return_dm(dev, &src, &dest, &dp);
388 kfree_skb(skb);
389 return 0;
390 }
391
392 ax25_fillin_cb(ax25, ax25_dev);
393 }
394
395 ax25->source_addr = dest;
396 ax25->dest_addr = src;
397
398 /*
399 * Sort out any digipeated paths.
400 */
401 if (dp.ndigi && !ax25->digipeat &&
402 (ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
403 kfree_skb(skb);
404 ax25_destroy_socket(ax25);
405 if (sk)
406 sock_put(sk);
407 return 0;
408 }
409
410 if (dp.ndigi == 0) {
411 if (ax25->digipeat != NULL) {
412 kfree(ax25->digipeat);
413 ax25->digipeat = NULL;
414 }
415 } else {
416 /* Reverse the source SABM's path */
417 memcpy(ax25->digipeat, &reverse_dp, sizeof(ax25_digi));
418 }
419
420 if ((*skb->data & ~AX25_PF) == AX25_SABME) {
421 ax25->modulus = AX25_EMODULUS;
422 ax25->window = ax25_dev->values[AX25_VALUES_EWINDOW];
423 } else {
424 ax25->modulus = AX25_MODULUS;
425 ax25->window = ax25_dev->values[AX25_VALUES_WINDOW];
426 }
427
428 ax25_send_control(ax25, AX25_UA, AX25_POLLON, AX25_RESPONSE);
429
430#ifdef CONFIG_AX25_DAMA_SLAVE
431 if (dama && ax25->ax25_dev->values[AX25_VALUES_PROTOCOL] == AX25_PROTO_DAMA_SLAVE)
432 ax25_dama_on(ax25);
433#endif
434
435 ax25->state = AX25_STATE_3;
436
437 ax25_cb_add(ax25);
438
439 ax25_start_heartbeat(ax25);
440 ax25_start_t3timer(ax25);
441 ax25_start_idletimer(ax25);
442
443 if (sk) {
444 if (!sock_flag(sk, SOCK_DEAD))
445 sk->sk_data_ready(sk, skb->len);
446 sock_put(sk);
447 } else
448 kfree_skb(skb);
449
450 return 0;
451}
452
453/*
454 * Receive an AX.25 frame via a SLIP interface.
455 */
456int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev,
457 struct packet_type *ptype)
458{
459 skb->sk = NULL; /* Initially we don't know who it's for */
460 skb->destructor = NULL; /* Who initializes this, dammit?! */
461
462 if ((*skb->data & 0x0F) != 0) {
463 kfree_skb(skb); /* Not a KISS data frame */
464 return 0;
465 }
466
467 skb_pull(skb, AX25_KISS_HEADER_LEN); /* Remove the KISS byte */
468
469 return ax25_rcv(skb, dev, (ax25_address *)dev->dev_addr, ptype);
470}
diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c
new file mode 100644
index 000000000000..04d711344d55
--- /dev/null
+++ b/net/ax25/ax25_ip.c
@@ -0,0 +1,225 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
8 */
9#include <linux/config.h>
10#include <linux/errno.h>
11#include <linux/types.h>
12#include <linux/socket.h>
13#include <linux/in.h>
14#include <linux/kernel.h>
15#include <linux/sched.h>
16#include <linux/timer.h>
17#include <linux/string.h>
18#include <linux/sockios.h>
19#include <linux/net.h>
20#include <net/ax25.h>
21#include <linux/inet.h>
22#include <linux/netdevice.h>
23#include <linux/if_arp.h>
24#include <linux/skbuff.h>
25#include <net/sock.h>
26#include <asm/uaccess.h>
27#include <asm/system.h>
28#include <linux/fcntl.h>
29#include <linux/termios.h> /* For TIOCINQ/OUTQ */
30#include <linux/mm.h>
31#include <linux/interrupt.h>
32#include <linux/notifier.h>
33#include <linux/proc_fs.h>
34#include <linux/stat.h>
35#include <linux/netfilter.h>
36#include <linux/sysctl.h>
37#include <net/ip.h>
38#include <net/arp.h>
39
40/*
41 * IP over AX.25 encapsulation.
42 */
43
44/*
45 * Shove an AX.25 UI header on an IP packet and handle ARP
46 */
47
48#ifdef CONFIG_INET
49
50int ax25_encapsulate(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len)
51{
52 unsigned char *buff;
53
54 /* they sometimes come back to us... */
55 if (type == ETH_P_AX25)
56 return 0;
57
58 /* header is an AX.25 UI frame from us to them */
59 buff = skb_push(skb, AX25_HEADER_LEN);
60 *buff++ = 0x00; /* KISS DATA */
61
62 if (daddr != NULL)
63 memcpy(buff, daddr, dev->addr_len); /* Address specified */
64
65 buff[6] &= ~AX25_CBIT;
66 buff[6] &= ~AX25_EBIT;
67 buff[6] |= AX25_SSSID_SPARE;
68 buff += AX25_ADDR_LEN;
69
70 if (saddr != NULL)
71 memcpy(buff, saddr, dev->addr_len);
72 else
73 memcpy(buff, dev->dev_addr, dev->addr_len);
74
75 buff[6] &= ~AX25_CBIT;
76 buff[6] |= AX25_EBIT;
77 buff[6] |= AX25_SSSID_SPARE;
78 buff += AX25_ADDR_LEN;
79
80 *buff++ = AX25_UI; /* UI */
81
82 /* Append a suitable AX.25 PID */
83 switch (type) {
84 case ETH_P_IP:
85 *buff++ = AX25_P_IP;
86 break;
87 case ETH_P_ARP:
88 *buff++ = AX25_P_ARP;
89 break;
90 default:
91 printk(KERN_ERR "AX.25: ax25_encapsulate - wrong protocol type 0x%2.2x\n", type);
92 *buff++ = 0;
93 break;
94 }
95
96 if (daddr != NULL)
97 return AX25_HEADER_LEN;
98
99 return -AX25_HEADER_LEN; /* Unfinished header */
100}
101
102int ax25_rebuild_header(struct sk_buff *skb)
103{
104 struct sk_buff *ourskb;
105 unsigned char *bp = skb->data;
106 struct net_device *dev;
107 ax25_address *src, *dst;
108 ax25_dev *ax25_dev;
109 ax25_route _route, *route = &_route;
110 ax25_cb *ax25;
111
112 dst = (ax25_address *)(bp + 1);
113 src = (ax25_address *)(bp + 8);
114
115 if (arp_find(bp + 1, skb))
116 return 1;
117
118 route = ax25_rt_find_route(route, dst, NULL);
119 dev = route->dev;
120
121 if (dev == NULL)
122 dev = skb->dev;
123
124 if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) {
125 goto put;
126 }
127
128 if (bp[16] == AX25_P_IP) {
129 if (route->ip_mode == 'V' || (route->ip_mode == ' ' && ax25_dev->values[AX25_VALUES_IPDEFMODE])) {
130 /*
131 * We copy the buffer and release the original thereby
132 * keeping it straight
133 *
134 * Note: we report 1 back so the caller will
135 * not feed the frame direct to the physical device
136 * We don't want that to happen. (It won't be upset
137 * as we have pulled the frame from the queue by
138 * freeing it).
139 *
140 * NB: TCP modifies buffers that are still
141 * on a device queue, thus we use skb_copy()
142 * instead of using skb_clone() unless this
143 * gets fixed.
144 */
145
146 ax25_address src_c;
147 ax25_address dst_c;
148
149 if ((ourskb = skb_copy(skb, GFP_ATOMIC)) == NULL) {
150 kfree_skb(skb);
151 goto put;
152 }
153
154 if (skb->sk != NULL)
155 skb_set_owner_w(ourskb, skb->sk);
156
157 kfree_skb(skb);
158 /* dl9sau: bugfix
159 * after kfree_skb(), dst and src which were pointer
160 * to bp which is part of skb->data would not be valid
161 * anymore hope that after skb_pull(ourskb, ..) our
162 * dsc_c and src_c will not become invalid
163 */
164 bp = ourskb->data;
165 dst_c = *(ax25_address *)(bp + 1);
166 src_c = *(ax25_address *)(bp + 8);
167
168 skb_pull(ourskb, AX25_HEADER_LEN - 1); /* Keep PID */
169 ourskb->nh.raw = ourskb->data;
170
171 ax25=ax25_send_frame(
172 ourskb,
173 ax25_dev->values[AX25_VALUES_PACLEN],
174 &src_c,
175 &dst_c, route->digipeat, dev);
176 if (ax25) {
177 ax25_cb_put(ax25);
178 }
179 goto put;
180 }
181 }
182
183 bp[7] &= ~AX25_CBIT;
184 bp[7] &= ~AX25_EBIT;
185 bp[7] |= AX25_SSSID_SPARE;
186
187 bp[14] &= ~AX25_CBIT;
188 bp[14] |= AX25_EBIT;
189 bp[14] |= AX25_SSSID_SPARE;
190
191 skb_pull(skb, AX25_KISS_HEADER_LEN);
192
193 if (route->digipeat != NULL) {
194 if ((ourskb = ax25_rt_build_path(skb, src, dst, route->digipeat)) == NULL) {
195 kfree_skb(skb);
196 goto put;
197 }
198
199 skb = ourskb;
200 }
201
202 skb->dev = dev;
203
204 ax25_queue_xmit(skb);
205
206put:
207 ax25_put_route(route);
208
209 return 1;
210}
211
212#else /* INET */
213
214int ax25_encapsulate(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len)
215{
216 return -AX25_HEADER_LEN;
217}
218
219int ax25_rebuild_header(struct sk_buff *skb)
220{
221 return 1;
222}
223
224#endif
225
diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c
new file mode 100644
index 000000000000..3475a3ac9343
--- /dev/null
+++ b/net/ax25/ax25_out.c
@@ -0,0 +1,383 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
8 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
9 * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
10 */
11#include <linux/config.h>
12#include <linux/errno.h>
13#include <linux/types.h>
14#include <linux/socket.h>
15#include <linux/in.h>
16#include <linux/kernel.h>
17#include <linux/sched.h>
18#include <linux/timer.h>
19#include <linux/string.h>
20#include <linux/sockios.h>
21#include <linux/spinlock.h>
22#include <linux/net.h>
23#include <net/ax25.h>
24#include <linux/inet.h>
25#include <linux/netdevice.h>
26#include <linux/skbuff.h>
27#include <linux/netfilter.h>
28#include <net/sock.h>
29#include <asm/uaccess.h>
30#include <asm/system.h>
31#include <linux/fcntl.h>
32#include <linux/mm.h>
33#include <linux/interrupt.h>
34
35static DEFINE_SPINLOCK(ax25_frag_lock);
36
37ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax25_address *dest, ax25_digi *digi, struct net_device *dev)
38{
39 ax25_dev *ax25_dev;
40 ax25_cb *ax25;
41
42 /*
43 * Take the default packet length for the device if zero is
44 * specified.
45 */
46 if (paclen == 0) {
47 if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
48 return NULL;
49
50 paclen = ax25_dev->values[AX25_VALUES_PACLEN];
51 }
52
53 /*
54 * Look for an existing connection.
55 */
56 if ((ax25 = ax25_find_cb(src, dest, digi, dev)) != NULL) {
57 ax25_output(ax25, paclen, skb);
58 return ax25; /* It already existed */
59 }
60
61 if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
62 return NULL;
63
64 if ((ax25 = ax25_create_cb()) == NULL)
65 return NULL;
66
67 ax25_fillin_cb(ax25, ax25_dev);
68
69 ax25->source_addr = *src;
70 ax25->dest_addr = *dest;
71
72 if (digi != NULL) {
73 if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
74 ax25_cb_put(ax25);
75 return NULL;
76 }
77 memcpy(ax25->digipeat, digi, sizeof(ax25_digi));
78 }
79
80 switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
81 case AX25_PROTO_STD_SIMPLEX:
82 case AX25_PROTO_STD_DUPLEX:
83 ax25_std_establish_data_link(ax25);
84 break;
85
86#ifdef CONFIG_AX25_DAMA_SLAVE
87 case AX25_PROTO_DAMA_SLAVE:
88 if (ax25_dev->dama.slave)
89 ax25_ds_establish_data_link(ax25);
90 else
91 ax25_std_establish_data_link(ax25);
92 break;
93#endif
94 }
95
96 ax25_cb_add(ax25);
97
98 ax25->state = AX25_STATE_1;
99
100 ax25_start_heartbeat(ax25);
101
102 ax25_output(ax25, paclen, skb);
103
104 return ax25; /* We had to create it */
105}
106
107/*
108 * All outgoing AX.25 I frames pass via this routine. Therefore this is
109 * where the fragmentation of frames takes place. If fragment is set to
110 * zero then we are not allowed to do fragmentation, even if the frame
111 * is too large.
112 */
113void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb)
114{
115 struct sk_buff *skbn;
116 unsigned char *p;
117 int frontlen, len, fragno, ka9qfrag, first = 1;
118
119 if ((skb->len - 1) > paclen) {
120 if (*skb->data == AX25_P_TEXT) {
121 skb_pull(skb, 1); /* skip PID */
122 ka9qfrag = 0;
123 } else {
124 paclen -= 2; /* Allow for fragment control info */
125 ka9qfrag = 1;
126 }
127
128 fragno = skb->len / paclen;
129 if (skb->len % paclen == 0) fragno--;
130
131 frontlen = skb_headroom(skb); /* Address space + CTRL */
132
133 while (skb->len > 0) {
134 spin_lock_bh(&ax25_frag_lock);
135 if ((skbn = alloc_skb(paclen + 2 + frontlen, GFP_ATOMIC)) == NULL) {
136 spin_unlock_bh(&ax25_frag_lock);
137 printk(KERN_CRIT "AX.25: ax25_output - out of memory\n");
138 return;
139 }
140
141 if (skb->sk != NULL)
142 skb_set_owner_w(skbn, skb->sk);
143
144 spin_unlock_bh(&ax25_frag_lock);
145
146 len = (paclen > skb->len) ? skb->len : paclen;
147
148 if (ka9qfrag == 1) {
149 skb_reserve(skbn, frontlen + 2);
150 skbn->nh.raw = skbn->data + (skb->nh.raw - skb->data);
151 memcpy(skb_put(skbn, len), skb->data, len);
152 p = skb_push(skbn, 2);
153
154 *p++ = AX25_P_SEGMENT;
155
156 *p = fragno--;
157 if (first) {
158 *p |= AX25_SEG_FIRST;
159 first = 0;
160 }
161 } else {
162 skb_reserve(skbn, frontlen + 1);
163 skbn->nh.raw = skbn->data + (skb->nh.raw - skb->data);
164 memcpy(skb_put(skbn, len), skb->data, len);
165 p = skb_push(skbn, 1);
166 *p = AX25_P_TEXT;
167 }
168
169 skb_pull(skb, len);
170 skb_queue_tail(&ax25->write_queue, skbn); /* Throw it on the queue */
171 }
172
173 kfree_skb(skb);
174 } else {
175 skb_queue_tail(&ax25->write_queue, skb); /* Throw it on the queue */
176 }
177
178 switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
179 case AX25_PROTO_STD_SIMPLEX:
180 case AX25_PROTO_STD_DUPLEX:
181 ax25_kick(ax25);
182 break;
183
184#ifdef CONFIG_AX25_DAMA_SLAVE
185 /*
186 * A DAMA slave is _required_ to work as normal AX.25L2V2
187 * if no DAMA master is available.
188 */
189 case AX25_PROTO_DAMA_SLAVE:
190 if (!ax25->ax25_dev->dama.slave) ax25_kick(ax25);
191 break;
192#endif
193 }
194}
195
196/*
197 * This procedure is passed a buffer descriptor for an iframe. It builds
198 * the rest of the control part of the frame and then writes it out.
199 */
200static void ax25_send_iframe(ax25_cb *ax25, struct sk_buff *skb, int poll_bit)
201{
202 unsigned char *frame;
203
204 if (skb == NULL)
205 return;
206
207 skb->nh.raw = skb->data;
208
209 if (ax25->modulus == AX25_MODULUS) {
210 frame = skb_push(skb, 1);
211
212 *frame = AX25_I;
213 *frame |= (poll_bit) ? AX25_PF : 0;
214 *frame |= (ax25->vr << 5);
215 *frame |= (ax25->vs << 1);
216 } else {
217 frame = skb_push(skb, 2);
218
219 frame[0] = AX25_I;
220 frame[0] |= (ax25->vs << 1);
221 frame[1] = (poll_bit) ? AX25_EPF : 0;
222 frame[1] |= (ax25->vr << 1);
223 }
224
225 ax25_start_idletimer(ax25);
226
227 ax25_transmit_buffer(ax25, skb, AX25_COMMAND);
228}
229
230void ax25_kick(ax25_cb *ax25)
231{
232 struct sk_buff *skb, *skbn;
233 int last = 1;
234 unsigned short start, end, next;
235
236 if (ax25->state != AX25_STATE_3 && ax25->state != AX25_STATE_4)
237 return;
238
239 if (ax25->condition & AX25_COND_PEER_RX_BUSY)
240 return;
241
242 if (skb_peek(&ax25->write_queue) == NULL)
243 return;
244
245 start = (skb_peek(&ax25->ack_queue) == NULL) ? ax25->va : ax25->vs;
246 end = (ax25->va + ax25->window) % ax25->modulus;
247
248 if (start == end)
249 return;
250
251 ax25->vs = start;
252
253 /*
254 * Transmit data until either we're out of data to send or
255 * the window is full. Send a poll on the final I frame if
256 * the window is filled.
257 */
258
259 /*
260 * Dequeue the frame and copy it.
261 */
262 skb = skb_dequeue(&ax25->write_queue);
263
264 do {
265 if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
266 skb_queue_head(&ax25->write_queue, skb);
267 break;
268 }
269
270 if (skb->sk != NULL)
271 skb_set_owner_w(skbn, skb->sk);
272
273 next = (ax25->vs + 1) % ax25->modulus;
274 last = (next == end);
275
276 /*
277 * Transmit the frame copy.
278 * bke 960114: do not set the Poll bit on the last frame
279 * in DAMA mode.
280 */
281 switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
282 case AX25_PROTO_STD_SIMPLEX:
283 case AX25_PROTO_STD_DUPLEX:
284 ax25_send_iframe(ax25, skbn, (last) ? AX25_POLLON : AX25_POLLOFF);
285 break;
286
287#ifdef CONFIG_AX25_DAMA_SLAVE
288 case AX25_PROTO_DAMA_SLAVE:
289 ax25_send_iframe(ax25, skbn, AX25_POLLOFF);
290 break;
291#endif
292 }
293
294 ax25->vs = next;
295
296 /*
297 * Requeue the original data frame.
298 */
299 skb_queue_tail(&ax25->ack_queue, skb);
300
301 } while (!last && (skb = skb_dequeue(&ax25->write_queue)) != NULL);
302
303 ax25->condition &= ~AX25_COND_ACK_PENDING;
304
305 if (!ax25_t1timer_running(ax25)) {
306 ax25_stop_t3timer(ax25);
307 ax25_calculate_t1(ax25);
308 ax25_start_t1timer(ax25);
309 }
310}
311
312void ax25_transmit_buffer(ax25_cb *ax25, struct sk_buff *skb, int type)
313{
314 struct sk_buff *skbn;
315 unsigned char *ptr;
316 int headroom;
317
318 if (ax25->ax25_dev == NULL) {
319 ax25_disconnect(ax25, ENETUNREACH);
320 return;
321 }
322
323 headroom = ax25_addr_size(ax25->digipeat);
324
325 if (skb_headroom(skb) < headroom) {
326 if ((skbn = skb_realloc_headroom(skb, headroom)) == NULL) {
327 printk(KERN_CRIT "AX.25: ax25_transmit_buffer - out of memory\n");
328 kfree_skb(skb);
329 return;
330 }
331
332 if (skb->sk != NULL)
333 skb_set_owner_w(skbn, skb->sk);
334
335 kfree_skb(skb);
336 skb = skbn;
337 }
338
339 ptr = skb_push(skb, headroom);
340
341 ax25_addr_build(ptr, &ax25->source_addr, &ax25->dest_addr, ax25->digipeat, type, ax25->modulus);
342
343 skb->dev = ax25->ax25_dev->dev;
344
345 ax25_queue_xmit(skb);
346}
347
348/*
349 * A small shim to dev_queue_xmit to add the KISS control byte, and do
350 * any packet forwarding in operation.
351 */
352void ax25_queue_xmit(struct sk_buff *skb)
353{
354 unsigned char *ptr;
355
356 skb->protocol = htons(ETH_P_AX25);
357 skb->dev = ax25_fwd_dev(skb->dev);
358
359 ptr = skb_push(skb, 1);
360 *ptr = 0x00; /* KISS */
361
362 dev_queue_xmit(skb);
363}
364
365int ax25_check_iframes_acked(ax25_cb *ax25, unsigned short nr)
366{
367 if (ax25->vs == nr) {
368 ax25_frames_acked(ax25, nr);
369 ax25_calculate_rtt(ax25);
370 ax25_stop_t1timer(ax25);
371 ax25_start_t3timer(ax25);
372 return 1;
373 } else {
374 if (ax25->va != nr) {
375 ax25_frames_acked(ax25, nr);
376 ax25_calculate_t1(ax25);
377 ax25_start_t1timer(ax25);
378 return 1;
379 }
380 }
381 return 0;
382}
383
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
new file mode 100644
index 000000000000..44b99b1ff9f8
--- /dev/null
+++ b/net/ax25/ax25_route.c
@@ -0,0 +1,534 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
8 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
9 * Copyright (C) Steven Whitehouse GW7RRM (stevew@acm.org)
10 * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
11 * Copyright (C) Hans-Joachim Hetscher DD8NE (dd8ne@bnv-bamberg.de)
12 * Copyright (C) Frederic Rible F1OAT (frible@teaser.fr)
13 */
14#include <linux/errno.h>
15#include <linux/types.h>
16#include <linux/socket.h>
17#include <linux/timer.h>
18#include <linux/in.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/string.h>
22#include <linux/sockios.h>
23#include <linux/net.h>
24#include <net/ax25.h>
25#include <linux/inet.h>
26#include <linux/netdevice.h>
27#include <linux/if_arp.h>
28#include <linux/skbuff.h>
29#include <linux/spinlock.h>
30#include <net/sock.h>
31#include <asm/uaccess.h>
32#include <asm/system.h>
33#include <linux/fcntl.h>
34#include <linux/mm.h>
35#include <linux/interrupt.h>
36#include <linux/init.h>
37#include <linux/seq_file.h>
38
39static ax25_route *ax25_route_list;
40static DEFINE_RWLOCK(ax25_route_lock);
41
42static ax25_route *ax25_get_route(ax25_address *, struct net_device *);
43
44void ax25_rt_device_down(struct net_device *dev)
45{
46 ax25_route *s, *t, *ax25_rt;
47
48 write_lock(&ax25_route_lock);
49 ax25_rt = ax25_route_list;
50 while (ax25_rt != NULL) {
51 s = ax25_rt;
52 ax25_rt = ax25_rt->next;
53
54 if (s->dev == dev) {
55 if (ax25_route_list == s) {
56 ax25_route_list = s->next;
57 if (s->digipeat != NULL)
58 kfree(s->digipeat);
59 kfree(s);
60 } else {
61 for (t = ax25_route_list; t != NULL; t = t->next) {
62 if (t->next == s) {
63 t->next = s->next;
64 if (s->digipeat != NULL)
65 kfree(s->digipeat);
66 kfree(s);
67 break;
68 }
69 }
70 }
71 }
72 }
73 write_unlock(&ax25_route_lock);
74}
75
76static int ax25_rt_add(struct ax25_routes_struct *route)
77{
78 ax25_route *ax25_rt;
79 ax25_dev *ax25_dev;
80 int i;
81
82 if ((ax25_dev = ax25_addr_ax25dev(&route->port_addr)) == NULL)
83 return -EINVAL;
84 if (route->digi_count > AX25_MAX_DIGIS)
85 return -EINVAL;
86
87 write_lock(&ax25_route_lock);
88
89 ax25_rt = ax25_route_list;
90 while (ax25_rt != NULL) {
91 if (ax25cmp(&ax25_rt->callsign, &route->dest_addr) == 0 &&
92 ax25_rt->dev == ax25_dev->dev) {
93 if (ax25_rt->digipeat != NULL) {
94 kfree(ax25_rt->digipeat);
95 ax25_rt->digipeat = NULL;
96 }
97 if (route->digi_count != 0) {
98 if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
99 write_unlock(&ax25_route_lock);
100 return -ENOMEM;
101 }
102 ax25_rt->digipeat->lastrepeat = -1;
103 ax25_rt->digipeat->ndigi = route->digi_count;
104 for (i = 0; i < route->digi_count; i++) {
105 ax25_rt->digipeat->repeated[i] = 0;
106 ax25_rt->digipeat->calls[i] = route->digi_addr[i];
107 }
108 }
109 write_unlock(&ax25_route_lock);
110 return 0;
111 }
112 ax25_rt = ax25_rt->next;
113 }
114
115 if ((ax25_rt = kmalloc(sizeof(ax25_route), GFP_ATOMIC)) == NULL) {
116 write_unlock(&ax25_route_lock);
117 return -ENOMEM;
118 }
119
120 atomic_set(&ax25_rt->ref, 0);
121 ax25_rt->callsign = route->dest_addr;
122 ax25_rt->dev = ax25_dev->dev;
123 ax25_rt->digipeat = NULL;
124 ax25_rt->ip_mode = ' ';
125 if (route->digi_count != 0) {
126 if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
127 write_unlock(&ax25_route_lock);
128 kfree(ax25_rt);
129 return -ENOMEM;
130 }
131 ax25_rt->digipeat->lastrepeat = -1;
132 ax25_rt->digipeat->ndigi = route->digi_count;
133 for (i = 0; i < route->digi_count; i++) {
134 ax25_rt->digipeat->repeated[i] = 0;
135 ax25_rt->digipeat->calls[i] = route->digi_addr[i];
136 }
137 }
138 ax25_rt->next = ax25_route_list;
139 ax25_route_list = ax25_rt;
140 write_unlock(&ax25_route_lock);
141
142 return 0;
143}
144
145static void ax25_rt_destroy(ax25_route *ax25_rt)
146{
147 if (atomic_read(&ax25_rt->ref) == 0) {
148 if (ax25_rt->digipeat != NULL)
149 kfree(ax25_rt->digipeat);
150 kfree(ax25_rt);
151 return;
152 }
153
154 /*
155 * Uh... Route is still in use; we can't yet destroy it. Retry later.
156 */
157 init_timer(&ax25_rt->timer);
158 ax25_rt->timer.data = (unsigned long) ax25_rt;
159 ax25_rt->timer.function = (void *) ax25_rt_destroy;
160 ax25_rt->timer.expires = jiffies + 5 * HZ;
161
162 add_timer(&ax25_rt->timer);
163}
164
165static int ax25_rt_del(struct ax25_routes_struct *route)
166{
167 ax25_route *s, *t, *ax25_rt;
168 ax25_dev *ax25_dev;
169
170 if ((ax25_dev = ax25_addr_ax25dev(&route->port_addr)) == NULL)
171 return -EINVAL;
172
173 write_lock(&ax25_route_lock);
174
175 ax25_rt = ax25_route_list;
176 while (ax25_rt != NULL) {
177 s = ax25_rt;
178 ax25_rt = ax25_rt->next;
179 if (s->dev == ax25_dev->dev &&
180 ax25cmp(&route->dest_addr, &s->callsign) == 0) {
181 if (ax25_route_list == s) {
182 ax25_route_list = s->next;
183 ax25_rt_destroy(s);
184 } else {
185 for (t = ax25_route_list; t != NULL; t = t->next) {
186 if (t->next == s) {
187 t->next = s->next;
188 ax25_rt_destroy(s);
189 break;
190 }
191 }
192 }
193 }
194 }
195 write_unlock(&ax25_route_lock);
196
197 return 0;
198}
199
200static int ax25_rt_opt(struct ax25_route_opt_struct *rt_option)
201{
202 ax25_route *ax25_rt;
203 ax25_dev *ax25_dev;
204 int err = 0;
205
206 if ((ax25_dev = ax25_addr_ax25dev(&rt_option->port_addr)) == NULL)
207 return -EINVAL;
208
209 write_lock(&ax25_route_lock);
210
211 ax25_rt = ax25_route_list;
212 while (ax25_rt != NULL) {
213 if (ax25_rt->dev == ax25_dev->dev &&
214 ax25cmp(&rt_option->dest_addr, &ax25_rt->callsign) == 0) {
215 switch (rt_option->cmd) {
216 case AX25_SET_RT_IPMODE:
217 switch (rt_option->arg) {
218 case ' ':
219 case 'D':
220 case 'V':
221 ax25_rt->ip_mode = rt_option->arg;
222 break;
223 default:
224 err = -EINVAL;
225 goto out;
226 }
227 break;
228 default:
229 err = -EINVAL;
230 goto out;
231 }
232 }
233 ax25_rt = ax25_rt->next;
234 }
235
236out:
237 write_unlock(&ax25_route_lock);
238 return err;
239}
240
241int ax25_rt_ioctl(unsigned int cmd, void __user *arg)
242{
243 struct ax25_route_opt_struct rt_option;
244 struct ax25_routes_struct route;
245
246 switch (cmd) {
247 case SIOCADDRT:
248 if (copy_from_user(&route, arg, sizeof(route)))
249 return -EFAULT;
250 return ax25_rt_add(&route);
251
252 case SIOCDELRT:
253 if (copy_from_user(&route, arg, sizeof(route)))
254 return -EFAULT;
255 return ax25_rt_del(&route);
256
257 case SIOCAX25OPTRT:
258 if (copy_from_user(&rt_option, arg, sizeof(rt_option)))
259 return -EFAULT;
260 return ax25_rt_opt(&rt_option);
261
262 default:
263 return -EINVAL;
264 }
265}
266
267#ifdef CONFIG_PROC_FS
268
269static void *ax25_rt_seq_start(struct seq_file *seq, loff_t *pos)
270{
271 struct ax25_route *ax25_rt;
272 int i = 1;
273
274 read_lock(&ax25_route_lock);
275 if (*pos == 0)
276 return SEQ_START_TOKEN;
277
278 for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
279 if (i == *pos)
280 return ax25_rt;
281 ++i;
282 }
283
284 return NULL;
285}
286
287static void *ax25_rt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
288{
289 ++*pos;
290 return (v == SEQ_START_TOKEN) ? ax25_route_list :
291 ((struct ax25_route *) v)->next;
292}
293
294static void ax25_rt_seq_stop(struct seq_file *seq, void *v)
295{
296 read_unlock(&ax25_route_lock);
297}
298
299static int ax25_rt_seq_show(struct seq_file *seq, void *v)
300{
301 if (v == SEQ_START_TOKEN)
302 seq_puts(seq, "callsign dev mode digipeaters\n");
303 else {
304 struct ax25_route *ax25_rt = v;
305 const char *callsign;
306 int i;
307
308 if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0)
309 callsign = "default";
310 else
311 callsign = ax2asc(&ax25_rt->callsign);
312
313 seq_printf(seq, "%-9s %-4s",
314 callsign,
315 ax25_rt->dev ? ax25_rt->dev->name : "???");
316
317 switch (ax25_rt->ip_mode) {
318 case 'V':
319 seq_puts(seq, " vc");
320 break;
321 case 'D':
322 seq_puts(seq, " dg");
323 break;
324 default:
325 seq_puts(seq, " *");
326 break;
327 }
328
329 if (ax25_rt->digipeat != NULL)
330 for (i = 0; i < ax25_rt->digipeat->ndigi; i++)
331 seq_printf(seq, " %s", ax2asc(&ax25_rt->digipeat->calls[i]));
332
333 seq_puts(seq, "\n");
334 }
335 return 0;
336}
337
338static struct seq_operations ax25_rt_seqops = {
339 .start = ax25_rt_seq_start,
340 .next = ax25_rt_seq_next,
341 .stop = ax25_rt_seq_stop,
342 .show = ax25_rt_seq_show,
343};
344
345static int ax25_rt_info_open(struct inode *inode, struct file *file)
346{
347 return seq_open(file, &ax25_rt_seqops);
348}
349
350struct file_operations ax25_route_fops = {
351 .owner = THIS_MODULE,
352 .open = ax25_rt_info_open,
353 .read = seq_read,
354 .llseek = seq_lseek,
355 .release = seq_release,
356};
357
358#endif
359
360/*
361 * Find AX.25 route
362 *
363 * Only routes with a refernce rout of zero can be destroyed.
364 */
365static ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)
366{
367 ax25_route *ax25_spe_rt = NULL;
368 ax25_route *ax25_def_rt = NULL;
369 ax25_route *ax25_rt;
370
371 read_lock(&ax25_route_lock);
372 /*
373 * Bind to the physical interface we heard them on, or the default
374 * route if none is found;
375 */
376 for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
377 if (dev == NULL) {
378 if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev != NULL)
379 ax25_spe_rt = ax25_rt;
380 if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev != NULL)
381 ax25_def_rt = ax25_rt;
382 } else {
383 if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev == dev)
384 ax25_spe_rt = ax25_rt;
385 if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev == dev)
386 ax25_def_rt = ax25_rt;
387 }
388 }
389
390 ax25_rt = ax25_def_rt;
391 if (ax25_spe_rt != NULL)
392 ax25_rt = ax25_spe_rt;
393
394 if (ax25_rt != NULL)
395 atomic_inc(&ax25_rt->ref);
396
397 read_unlock(&ax25_route_lock);
398
399 return ax25_rt;
400}
401
402/*
403 * Adjust path: If you specify a default route and want to connect
404 * a target on the digipeater path but w/o having a special route
405 * set before, the path has to be truncated from your target on.
406 */
407static inline void ax25_adjust_path(ax25_address *addr, ax25_digi *digipeat)
408{
409 int k;
410
411 for (k = 0; k < digipeat->ndigi; k++) {
412 if (ax25cmp(addr, &digipeat->calls[k]) == 0)
413 break;
414 }
415
416 digipeat->ndigi = k;
417}
418
419
420/*
421 * Find which interface to use.
422 */
423int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
424{
425 ax25_route *ax25_rt;
426 ax25_address *call;
427 int err;
428
429 if ((ax25_rt = ax25_get_route(addr, NULL)) == NULL)
430 return -EHOSTUNREACH;
431
432 if ((ax25->ax25_dev = ax25_dev_ax25dev(ax25_rt->dev)) == NULL) {
433 err = -EHOSTUNREACH;
434 goto put;
435 }
436
437 if ((call = ax25_findbyuid(current->euid)) == NULL) {
438 if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) {
439 err = -EPERM;
440 goto put;
441 }
442 call = (ax25_address *)ax25->ax25_dev->dev->dev_addr;
443 }
444
445 ax25->source_addr = *call;
446
447 if (ax25_rt->digipeat != NULL) {
448 if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
449 err = -ENOMEM;
450 goto put;
451 }
452 memcpy(ax25->digipeat, ax25_rt->digipeat, sizeof(ax25_digi));
453 ax25_adjust_path(addr, ax25->digipeat);
454 }
455
456 if (ax25->sk != NULL) {
457 bh_lock_sock(ax25->sk);
458 sock_reset_flag(ax25->sk, SOCK_ZAPPED);
459 bh_unlock_sock(ax25->sk);
460 }
461
462put:
463 ax25_put_route(ax25_rt);
464
465 return 0;
466}
467
468ax25_route *ax25_rt_find_route(ax25_route * route, ax25_address *addr,
469 struct net_device *dev)
470{
471 ax25_route *ax25_rt;
472
473 if ((ax25_rt = ax25_get_route(addr, dev)))
474 return ax25_rt;
475
476 route->next = NULL;
477 atomic_set(&route->ref, 1);
478 route->callsign = *addr;
479 route->dev = dev;
480 route->digipeat = NULL;
481 route->ip_mode = ' ';
482
483 return route;
484}
485
486struct sk_buff *ax25_rt_build_path(struct sk_buff *skb, ax25_address *src,
487 ax25_address *dest, ax25_digi *digi)
488{
489 struct sk_buff *skbn;
490 unsigned char *bp;
491 int len;
492
493 len = digi->ndigi * AX25_ADDR_LEN;
494
495 if (skb_headroom(skb) < len) {
496 if ((skbn = skb_realloc_headroom(skb, len)) == NULL) {
497 printk(KERN_CRIT "AX.25: ax25_dg_build_path - out of memory\n");
498 return NULL;
499 }
500
501 if (skb->sk != NULL)
502 skb_set_owner_w(skbn, skb->sk);
503
504 kfree_skb(skb);
505
506 skb = skbn;
507 }
508
509 bp = skb_push(skb, len);
510
511 ax25_addr_build(bp, src, dest, digi, AX25_COMMAND, AX25_MODULUS);
512
513 return skb;
514}
515
516/*
517 * Free all memory associated with routing structures.
518 */
519void __exit ax25_rt_free(void)
520{
521 ax25_route *s, *ax25_rt = ax25_route_list;
522
523 write_lock(&ax25_route_lock);
524 while (ax25_rt != NULL) {
525 s = ax25_rt;
526 ax25_rt = ax25_rt->next;
527
528 if (s->digipeat != NULL)
529 kfree(s->digipeat);
530
531 kfree(s);
532 }
533 write_unlock(&ax25_route_lock);
534}
diff --git a/net/ax25/ax25_std_in.c b/net/ax25/ax25_std_in.c
new file mode 100644
index 000000000000..7131873322c4
--- /dev/null
+++ b/net/ax25/ax25_std_in.c
@@ -0,0 +1,449 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
8 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
9 * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
10 * Copyright (C) Hans-Joachim Hetscher DD8NE (dd8ne@bnv-bamberg.de)
11 *
12 * Most of this code is based on the SDL diagrams published in the 7th ARRL
13 * Computer Networking Conference papers. The diagrams have mistakes in them,
14 * but are mostly correct. Before you modify the code could you read the SDL
15 * diagrams as the code is not obvious and probably very easy to break.
16 */
17#include <linux/errno.h>
18#include <linux/types.h>
19#include <linux/socket.h>
20#include <linux/in.h>
21#include <linux/kernel.h>
22#include <linux/sched.h>
23#include <linux/timer.h>
24#include <linux/string.h>
25#include <linux/sockios.h>
26#include <linux/net.h>
27#include <net/ax25.h>
28#include <linux/inet.h>
29#include <linux/netdevice.h>
30#include <linux/skbuff.h>
31#include <net/sock.h>
32#include <net/ip.h> /* For ip_rcv */
33#include <net/tcp.h>
34#include <asm/uaccess.h>
35#include <asm/system.h>
36#include <linux/fcntl.h>
37#include <linux/mm.h>
38#include <linux/interrupt.h>
39
40/*
41 * State machine for state 1, Awaiting Connection State.
42 * The handling of the timer(s) is in file ax25_std_timer.c.
43 * Handling of state 0 and connection release is in ax25.c.
44 */
45static int ax25_std_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type)
46{
47 switch (frametype) {
48 case AX25_SABM:
49 ax25->modulus = AX25_MODULUS;
50 ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
51 ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
52 break;
53
54 case AX25_SABME:
55 ax25->modulus = AX25_EMODULUS;
56 ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
57 ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
58 break;
59
60 case AX25_DISC:
61 ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE);
62 break;
63
64 case AX25_UA:
65 if (pf) {
66 ax25_calculate_rtt(ax25);
67 ax25_stop_t1timer(ax25);
68 ax25_start_t3timer(ax25);
69 ax25_start_idletimer(ax25);
70 ax25->vs = 0;
71 ax25->va = 0;
72 ax25->vr = 0;
73 ax25->state = AX25_STATE_3;
74 ax25->n2count = 0;
75 if (ax25->sk != NULL) {
76 bh_lock_sock(ax25->sk);
77 ax25->sk->sk_state = TCP_ESTABLISHED;
78 /* For WAIT_SABM connections we will produce an accept ready socket here */
79 if (!sock_flag(ax25->sk, SOCK_DEAD))
80 ax25->sk->sk_state_change(ax25->sk);
81 bh_unlock_sock(ax25->sk);
82 }
83 }
84 break;
85
86 case AX25_DM:
87 if (pf) {
88 if (ax25->modulus == AX25_MODULUS) {
89 ax25_disconnect(ax25, ECONNREFUSED);
90 } else {
91 ax25->modulus = AX25_MODULUS;
92 ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
93 }
94 }
95 break;
96
97 default:
98 break;
99 }
100
101 return 0;
102}
103
104/*
105 * State machine for state 2, Awaiting Release State.
106 * The handling of the timer(s) is in file ax25_std_timer.c
107 * Handling of state 0 and connection release is in ax25.c.
108 */
109static int ax25_std_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type)
110{
111 switch (frametype) {
112 case AX25_SABM:
113 case AX25_SABME:
114 ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE);
115 break;
116
117 case AX25_DISC:
118 ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
119 ax25_disconnect(ax25, 0);
120 break;
121
122 case AX25_DM:
123 case AX25_UA:
124 if (pf)
125 ax25_disconnect(ax25, 0);
126 break;
127
128 case AX25_I:
129 case AX25_REJ:
130 case AX25_RNR:
131 case AX25_RR:
132 if (pf) ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE);
133 break;
134
135 default:
136 break;
137 }
138
139 return 0;
140}
141
142/*
143 * State machine for state 3, Connected State.
144 * The handling of the timer(s) is in file ax25_std_timer.c
145 * Handling of state 0 and connection release is in ax25.c.
146 */
147static int ax25_std_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int ns, int nr, int pf, int type)
148{
149 int queued = 0;
150
151 switch (frametype) {
152 case AX25_SABM:
153 case AX25_SABME:
154 if (frametype == AX25_SABM) {
155 ax25->modulus = AX25_MODULUS;
156 ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
157 } else {
158 ax25->modulus = AX25_EMODULUS;
159 ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
160 }
161 ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
162 ax25_stop_t1timer(ax25);
163 ax25_stop_t2timer(ax25);
164 ax25_start_t3timer(ax25);
165 ax25_start_idletimer(ax25);
166 ax25->condition = 0x00;
167 ax25->vs = 0;
168 ax25->va = 0;
169 ax25->vr = 0;
170 ax25_requeue_frames(ax25);
171 break;
172
173 case AX25_DISC:
174 ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
175 ax25_disconnect(ax25, 0);
176 break;
177
178 case AX25_DM:
179 ax25_disconnect(ax25, ECONNRESET);
180 break;
181
182 case AX25_RR:
183 case AX25_RNR:
184 if (frametype == AX25_RR)
185 ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
186 else
187 ax25->condition |= AX25_COND_PEER_RX_BUSY;
188 if (type == AX25_COMMAND && pf)
189 ax25_std_enquiry_response(ax25);
190 if (ax25_validate_nr(ax25, nr)) {
191 ax25_check_iframes_acked(ax25, nr);
192 } else {
193 ax25_std_nr_error_recovery(ax25);
194 ax25->state = AX25_STATE_1;
195 }
196 break;
197
198 case AX25_REJ:
199 ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
200 if (type == AX25_COMMAND && pf)
201 ax25_std_enquiry_response(ax25);
202 if (ax25_validate_nr(ax25, nr)) {
203 ax25_frames_acked(ax25, nr);
204 ax25_calculate_rtt(ax25);
205 ax25_stop_t1timer(ax25);
206 ax25_start_t3timer(ax25);
207 ax25_requeue_frames(ax25);
208 } else {
209 ax25_std_nr_error_recovery(ax25);
210 ax25->state = AX25_STATE_1;
211 }
212 break;
213
214 case AX25_I:
215 if (!ax25_validate_nr(ax25, nr)) {
216 ax25_std_nr_error_recovery(ax25);
217 ax25->state = AX25_STATE_1;
218 break;
219 }
220 if (ax25->condition & AX25_COND_PEER_RX_BUSY) {
221 ax25_frames_acked(ax25, nr);
222 } else {
223 ax25_check_iframes_acked(ax25, nr);
224 }
225 if (ax25->condition & AX25_COND_OWN_RX_BUSY) {
226 if (pf) ax25_std_enquiry_response(ax25);
227 break;
228 }
229 if (ns == ax25->vr) {
230 ax25->vr = (ax25->vr + 1) % ax25->modulus;
231 queued = ax25_rx_iframe(ax25, skb);
232 if (ax25->condition & AX25_COND_OWN_RX_BUSY)
233 ax25->vr = ns; /* ax25->vr - 1 */
234 ax25->condition &= ~AX25_COND_REJECT;
235 if (pf) {
236 ax25_std_enquiry_response(ax25);
237 } else {
238 if (!(ax25->condition & AX25_COND_ACK_PENDING)) {
239 ax25->condition |= AX25_COND_ACK_PENDING;
240 ax25_start_t2timer(ax25);
241 }
242 }
243 } else {
244 if (ax25->condition & AX25_COND_REJECT) {
245 if (pf) ax25_std_enquiry_response(ax25);
246 } else {
247 ax25->condition |= AX25_COND_REJECT;
248 ax25_send_control(ax25, AX25_REJ, pf, AX25_RESPONSE);
249 ax25->condition &= ~AX25_COND_ACK_PENDING;
250 }
251 }
252 break;
253
254 case AX25_FRMR:
255 case AX25_ILLEGAL:
256 ax25_std_establish_data_link(ax25);
257 ax25->state = AX25_STATE_1;
258 break;
259
260 default:
261 break;
262 }
263
264 return queued;
265}
266
267/*
268 * State machine for state 4, Timer Recovery State.
269 * The handling of the timer(s) is in file ax25_std_timer.c
270 * Handling of state 0 and connection release is in ax25.c.
271 */
272static int ax25_std_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int ns, int nr, int pf, int type)
273{
274 int queued = 0;
275
276 switch (frametype) {
277 case AX25_SABM:
278 case AX25_SABME:
279 if (frametype == AX25_SABM) {
280 ax25->modulus = AX25_MODULUS;
281 ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
282 } else {
283 ax25->modulus = AX25_EMODULUS;
284 ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
285 }
286 ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
287 ax25_stop_t1timer(ax25);
288 ax25_stop_t2timer(ax25);
289 ax25_start_t3timer(ax25);
290 ax25_start_idletimer(ax25);
291 ax25->condition = 0x00;
292 ax25->vs = 0;
293 ax25->va = 0;
294 ax25->vr = 0;
295 ax25->state = AX25_STATE_3;
296 ax25->n2count = 0;
297 ax25_requeue_frames(ax25);
298 break;
299
300 case AX25_DISC:
301 ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
302 ax25_disconnect(ax25, 0);
303 break;
304
305 case AX25_DM:
306 ax25_disconnect(ax25, ECONNRESET);
307 break;
308
309 case AX25_RR:
310 case AX25_RNR:
311 if (frametype == AX25_RR)
312 ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
313 else
314 ax25->condition |= AX25_COND_PEER_RX_BUSY;
315 if (type == AX25_RESPONSE && pf) {
316 ax25_stop_t1timer(ax25);
317 ax25->n2count = 0;
318 if (ax25_validate_nr(ax25, nr)) {
319 ax25_frames_acked(ax25, nr);
320 if (ax25->vs == ax25->va) {
321 ax25_start_t3timer(ax25);
322 ax25->state = AX25_STATE_3;
323 } else {
324 ax25_requeue_frames(ax25);
325 }
326 } else {
327 ax25_std_nr_error_recovery(ax25);
328 ax25->state = AX25_STATE_1;
329 }
330 break;
331 }
332 if (type == AX25_COMMAND && pf)
333 ax25_std_enquiry_response(ax25);
334 if (ax25_validate_nr(ax25, nr)) {
335 ax25_frames_acked(ax25, nr);
336 } else {
337 ax25_std_nr_error_recovery(ax25);
338 ax25->state = AX25_STATE_1;
339 }
340 break;
341
342 case AX25_REJ:
343 ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
344 if (pf && type == AX25_RESPONSE) {
345 ax25_stop_t1timer(ax25);
346 ax25->n2count = 0;
347 if (ax25_validate_nr(ax25, nr)) {
348 ax25_frames_acked(ax25, nr);
349 if (ax25->vs == ax25->va) {
350 ax25_start_t3timer(ax25);
351 ax25->state = AX25_STATE_3;
352 } else {
353 ax25_requeue_frames(ax25);
354 }
355 } else {
356 ax25_std_nr_error_recovery(ax25);
357 ax25->state = AX25_STATE_1;
358 }
359 break;
360 }
361 if (type == AX25_COMMAND && pf)
362 ax25_std_enquiry_response(ax25);
363 if (ax25_validate_nr(ax25, nr)) {
364 ax25_frames_acked(ax25, nr);
365 ax25_requeue_frames(ax25);
366 } else {
367 ax25_std_nr_error_recovery(ax25);
368 ax25->state = AX25_STATE_1;
369 }
370 break;
371
372 case AX25_I:
373 if (!ax25_validate_nr(ax25, nr)) {
374 ax25_std_nr_error_recovery(ax25);
375 ax25->state = AX25_STATE_1;
376 break;
377 }
378 ax25_frames_acked(ax25, nr);
379 if (ax25->condition & AX25_COND_OWN_RX_BUSY) {
380 if (pf)
381 ax25_std_enquiry_response(ax25);
382 break;
383 }
384 if (ns == ax25->vr) {
385 ax25->vr = (ax25->vr + 1) % ax25->modulus;
386 queued = ax25_rx_iframe(ax25, skb);
387 if (ax25->condition & AX25_COND_OWN_RX_BUSY)
388 ax25->vr = ns; /* ax25->vr - 1 */
389 ax25->condition &= ~AX25_COND_REJECT;
390 if (pf) {
391 ax25_std_enquiry_response(ax25);
392 } else {
393 if (!(ax25->condition & AX25_COND_ACK_PENDING)) {
394 ax25->condition |= AX25_COND_ACK_PENDING;
395 ax25_start_t2timer(ax25);
396 }
397 }
398 } else {
399 if (ax25->condition & AX25_COND_REJECT) {
400 if (pf) ax25_std_enquiry_response(ax25);
401 } else {
402 ax25->condition |= AX25_COND_REJECT;
403 ax25_send_control(ax25, AX25_REJ, pf, AX25_RESPONSE);
404 ax25->condition &= ~AX25_COND_ACK_PENDING;
405 }
406 }
407 break;
408
409 case AX25_FRMR:
410 case AX25_ILLEGAL:
411 ax25_std_establish_data_link(ax25);
412 ax25->state = AX25_STATE_1;
413 break;
414
415 default:
416 break;
417 }
418
419 return queued;
420}
421
422/*
423 * Higher level upcall for a LAPB frame
424 */
425int ax25_std_frame_in(ax25_cb *ax25, struct sk_buff *skb, int type)
426{
427 int queued = 0, frametype, ns, nr, pf;
428
429 frametype = ax25_decode(ax25, skb, &ns, &nr, &pf);
430
431 switch (ax25->state) {
432 case AX25_STATE_1:
433 queued = ax25_std_state1_machine(ax25, skb, frametype, pf, type);
434 break;
435 case AX25_STATE_2:
436 queued = ax25_std_state2_machine(ax25, skb, frametype, pf, type);
437 break;
438 case AX25_STATE_3:
439 queued = ax25_std_state3_machine(ax25, skb, frametype, ns, nr, pf, type);
440 break;
441 case AX25_STATE_4:
442 queued = ax25_std_state4_machine(ax25, skb, frametype, ns, nr, pf, type);
443 break;
444 }
445
446 ax25_kick(ax25);
447
448 return queued;
449}
diff --git a/net/ax25/ax25_std_subr.c b/net/ax25/ax25_std_subr.c
new file mode 100644
index 000000000000..2b3c801ae486
--- /dev/null
+++ b/net/ax25/ax25_std_subr.c
@@ -0,0 +1,88 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
8 */
9#include <linux/errno.h>
10#include <linux/types.h>
11#include <linux/socket.h>
12#include <linux/in.h>
13#include <linux/kernel.h>
14#include <linux/sched.h>
15#include <linux/timer.h>
16#include <linux/string.h>
17#include <linux/sockios.h>
18#include <linux/net.h>
19#include <net/ax25.h>
20#include <linux/inet.h>
21#include <linux/netdevice.h>
22#include <linux/skbuff.h>
23#include <net/sock.h>
24#include <asm/uaccess.h>
25#include <asm/system.h>
26#include <linux/fcntl.h>
27#include <linux/mm.h>
28#include <linux/interrupt.h>
29
30/*
31 * The following routines are taken from page 170 of the 7th ARRL Computer
32 * Networking Conference paper, as is the whole state machine.
33 */
34
35void ax25_std_nr_error_recovery(ax25_cb *ax25)
36{
37 ax25_std_establish_data_link(ax25);
38}
39
40void ax25_std_establish_data_link(ax25_cb *ax25)
41{
42 ax25->condition = 0x00;
43 ax25->n2count = 0;
44
45 if (ax25->modulus == AX25_MODULUS)
46 ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
47 else
48 ax25_send_control(ax25, AX25_SABME, AX25_POLLON, AX25_COMMAND);
49
50 ax25_calculate_t1(ax25);
51 ax25_stop_idletimer(ax25);
52 ax25_stop_t3timer(ax25);
53 ax25_stop_t2timer(ax25);
54 ax25_start_t1timer(ax25);
55}
56
57void ax25_std_transmit_enquiry(ax25_cb *ax25)
58{
59 if (ax25->condition & AX25_COND_OWN_RX_BUSY)
60 ax25_send_control(ax25, AX25_RNR, AX25_POLLON, AX25_COMMAND);
61 else
62 ax25_send_control(ax25, AX25_RR, AX25_POLLON, AX25_COMMAND);
63
64 ax25->condition &= ~AX25_COND_ACK_PENDING;
65
66 ax25_calculate_t1(ax25);
67 ax25_start_t1timer(ax25);
68}
69
70void ax25_std_enquiry_response(ax25_cb *ax25)
71{
72 if (ax25->condition & AX25_COND_OWN_RX_BUSY)
73 ax25_send_control(ax25, AX25_RNR, AX25_POLLON, AX25_RESPONSE);
74 else
75 ax25_send_control(ax25, AX25_RR, AX25_POLLON, AX25_RESPONSE);
76
77 ax25->condition &= ~AX25_COND_ACK_PENDING;
78}
79
80void ax25_std_timeout_response(ax25_cb *ax25)
81{
82 if (ax25->condition & AX25_COND_OWN_RX_BUSY)
83 ax25_send_control(ax25, AX25_RNR, AX25_POLLOFF, AX25_RESPONSE);
84 else
85 ax25_send_control(ax25, AX25_RR, AX25_POLLOFF, AX25_RESPONSE);
86
87 ax25->condition &= ~AX25_COND_ACK_PENDING;
88}
diff --git a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.c
new file mode 100644
index 000000000000..066897bc0749
--- /dev/null
+++ b/net/ax25/ax25_std_timer.c
@@ -0,0 +1,177 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
8 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
9 * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
10 * Copyright (C) Frederic Rible F1OAT (frible@teaser.fr)
11 */
12#include <linux/errno.h>
13#include <linux/types.h>
14#include <linux/socket.h>
15#include <linux/in.h>
16#include <linux/kernel.h>
17#include <linux/sched.h>
18#include <linux/timer.h>
19#include <linux/string.h>
20#include <linux/sockios.h>
21#include <linux/net.h>
22#include <net/ax25.h>
23#include <linux/inet.h>
24#include <linux/netdevice.h>
25#include <linux/skbuff.h>
26#include <net/sock.h>
27#include <net/tcp.h>
28#include <asm/uaccess.h>
29#include <asm/system.h>
30#include <linux/fcntl.h>
31#include <linux/mm.h>
32#include <linux/interrupt.h>
33
34void ax25_std_heartbeat_expiry(ax25_cb *ax25)
35{
36 struct sock *sk=ax25->sk;
37
38 if (sk)
39 bh_lock_sock(sk);
40
41 switch (ax25->state) {
42 case AX25_STATE_0:
43 /* Magic here: If we listen() and a new link dies before it
44 is accepted() it isn't 'dead' so doesn't get removed. */
45 if (!sk || sock_flag(sk, SOCK_DESTROY) ||
46 (sk->sk_state == TCP_LISTEN &&
47 sock_flag(sk, SOCK_DEAD))) {
48 if (sk) {
49 sock_hold(sk);
50 ax25_destroy_socket(ax25);
51 bh_unlock_sock(sk);
52 sock_put(sk);
53 } else
54 ax25_destroy_socket(ax25);
55 return;
56 }
57 break;
58
59 case AX25_STATE_3:
60 case AX25_STATE_4:
61 /*
62 * Check the state of the receive buffer.
63 */
64 if (sk != NULL) {
65 if (atomic_read(&sk->sk_rmem_alloc) <
66 (sk->sk_rcvbuf / 2) &&
67 (ax25->condition & AX25_COND_OWN_RX_BUSY)) {
68 ax25->condition &= ~AX25_COND_OWN_RX_BUSY;
69 ax25->condition &= ~AX25_COND_ACK_PENDING;
70 ax25_send_control(ax25, AX25_RR, AX25_POLLOFF, AX25_RESPONSE);
71 break;
72 }
73 }
74 }
75
76 if (sk)
77 bh_unlock_sock(sk);
78
79 ax25_start_heartbeat(ax25);
80}
81
82void ax25_std_t2timer_expiry(ax25_cb *ax25)
83{
84 if (ax25->condition & AX25_COND_ACK_PENDING) {
85 ax25->condition &= ~AX25_COND_ACK_PENDING;
86 ax25_std_timeout_response(ax25);
87 }
88}
89
90void ax25_std_t3timer_expiry(ax25_cb *ax25)
91{
92 ax25->n2count = 0;
93 ax25_std_transmit_enquiry(ax25);
94 ax25->state = AX25_STATE_4;
95}
96
97void ax25_std_idletimer_expiry(ax25_cb *ax25)
98{
99 ax25_clear_queues(ax25);
100
101 ax25->n2count = 0;
102 ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
103 ax25->state = AX25_STATE_2;
104
105 ax25_calculate_t1(ax25);
106 ax25_start_t1timer(ax25);
107 ax25_stop_t2timer(ax25);
108 ax25_stop_t3timer(ax25);
109
110 if (ax25->sk != NULL) {
111 bh_lock_sock(ax25->sk);
112 ax25->sk->sk_state = TCP_CLOSE;
113 ax25->sk->sk_err = 0;
114 ax25->sk->sk_shutdown |= SEND_SHUTDOWN;
115 if (!sock_flag(ax25->sk, SOCK_DEAD)) {
116 ax25->sk->sk_state_change(ax25->sk);
117 sock_set_flag(ax25->sk, SOCK_DEAD);
118 }
119 bh_unlock_sock(ax25->sk);
120 }
121}
122
123void ax25_std_t1timer_expiry(ax25_cb *ax25)
124{
125 switch (ax25->state) {
126 case AX25_STATE_1:
127 if (ax25->n2count == ax25->n2) {
128 if (ax25->modulus == AX25_MODULUS) {
129 ax25_disconnect(ax25, ETIMEDOUT);
130 return;
131 } else {
132 ax25->modulus = AX25_MODULUS;
133 ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
134 ax25->n2count = 0;
135 ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
136 }
137 } else {
138 ax25->n2count++;
139 if (ax25->modulus == AX25_MODULUS)
140 ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
141 else
142 ax25_send_control(ax25, AX25_SABME, AX25_POLLON, AX25_COMMAND);
143 }
144 break;
145
146 case AX25_STATE_2:
147 if (ax25->n2count == ax25->n2) {
148 ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
149 ax25_disconnect(ax25, ETIMEDOUT);
150 return;
151 } else {
152 ax25->n2count++;
153 ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
154 }
155 break;
156
157 case AX25_STATE_3:
158 ax25->n2count = 1;
159 ax25_std_transmit_enquiry(ax25);
160 ax25->state = AX25_STATE_4;
161 break;
162
163 case AX25_STATE_4:
164 if (ax25->n2count == ax25->n2) {
165 ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE);
166 ax25_disconnect(ax25, ETIMEDOUT);
167 return;
168 } else {
169 ax25->n2count++;
170 ax25_std_transmit_enquiry(ax25);
171 }
172 break;
173 }
174
175 ax25_calculate_t1(ax25);
176 ax25_start_t1timer(ax25);
177}
diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
new file mode 100644
index 000000000000..8cf72707af8b
--- /dev/null
+++ b/net/ax25/ax25_subr.c
@@ -0,0 +1,295 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
8 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
9 * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
10 * Copyright (C) Frederic Rible F1OAT (frible@teaser.fr)
11 */
12#include <linux/errno.h>
13#include <linux/types.h>
14#include <linux/socket.h>
15#include <linux/in.h>
16#include <linux/kernel.h>
17#include <linux/sched.h>
18#include <linux/timer.h>
19#include <linux/string.h>
20#include <linux/sockios.h>
21#include <linux/net.h>
22#include <net/ax25.h>
23#include <linux/inet.h>
24#include <linux/netdevice.h>
25#include <linux/skbuff.h>
26#include <net/sock.h>
27#include <net/tcp.h>
28#include <asm/uaccess.h>
29#include <asm/system.h>
30#include <linux/fcntl.h>
31#include <linux/mm.h>
32#include <linux/interrupt.h>
33
34/*
35 * This routine purges all the queues of frames.
36 */
37void ax25_clear_queues(ax25_cb *ax25)
38{
39 skb_queue_purge(&ax25->write_queue);
40 skb_queue_purge(&ax25->ack_queue);
41 skb_queue_purge(&ax25->reseq_queue);
42 skb_queue_purge(&ax25->frag_queue);
43}
44
45/*
46 * This routine purges the input queue of those frames that have been
47 * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the
48 * SDL diagram.
49 */
50void ax25_frames_acked(ax25_cb *ax25, unsigned short nr)
51{
52 struct sk_buff *skb;
53
54 /*
55 * Remove all the ack-ed frames from the ack queue.
56 */
57 if (ax25->va != nr) {
58 while (skb_peek(&ax25->ack_queue) != NULL && ax25->va != nr) {
59 skb = skb_dequeue(&ax25->ack_queue);
60 kfree_skb(skb);
61 ax25->va = (ax25->va + 1) % ax25->modulus;
62 }
63 }
64}
65
66void ax25_requeue_frames(ax25_cb *ax25)
67{
68 struct sk_buff *skb, *skb_prev = NULL;
69
70 /*
71 * Requeue all the un-ack-ed frames on the output queue to be picked
72 * up by ax25_kick called from the timer. This arrangement handles the
73 * possibility of an empty output queue.
74 */
75 while ((skb = skb_dequeue(&ax25->ack_queue)) != NULL) {
76 if (skb_prev == NULL)
77 skb_queue_head(&ax25->write_queue, skb);
78 else
79 skb_append(skb_prev, skb);
80 skb_prev = skb;
81 }
82}
83
84/*
85 * Validate that the value of nr is between va and vs. Return true or
86 * false for testing.
87 */
88int ax25_validate_nr(ax25_cb *ax25, unsigned short nr)
89{
90 unsigned short vc = ax25->va;
91
92 while (vc != ax25->vs) {
93 if (nr == vc) return 1;
94 vc = (vc + 1) % ax25->modulus;
95 }
96
97 if (nr == ax25->vs) return 1;
98
99 return 0;
100}
101
102/*
103 * This routine is the centralised routine for parsing the control
104 * information for the different frame formats.
105 */
106int ax25_decode(ax25_cb *ax25, struct sk_buff *skb, int *ns, int *nr, int *pf)
107{
108 unsigned char *frame;
109 int frametype = AX25_ILLEGAL;
110
111 frame = skb->data;
112 *ns = *nr = *pf = 0;
113
114 if (ax25->modulus == AX25_MODULUS) {
115 if ((frame[0] & AX25_S) == 0) {
116 frametype = AX25_I; /* I frame - carries NR/NS/PF */
117 *ns = (frame[0] >> 1) & 0x07;
118 *nr = (frame[0] >> 5) & 0x07;
119 *pf = frame[0] & AX25_PF;
120 } else if ((frame[0] & AX25_U) == 1) { /* S frame - take out PF/NR */
121 frametype = frame[0] & 0x0F;
122 *nr = (frame[0] >> 5) & 0x07;
123 *pf = frame[0] & AX25_PF;
124 } else if ((frame[0] & AX25_U) == 3) { /* U frame - take out PF */
125 frametype = frame[0] & ~AX25_PF;
126 *pf = frame[0] & AX25_PF;
127 }
128 skb_pull(skb, 1);
129 } else {
130 if ((frame[0] & AX25_S) == 0) {
131 frametype = AX25_I; /* I frame - carries NR/NS/PF */
132 *ns = (frame[0] >> 1) & 0x7F;
133 *nr = (frame[1] >> 1) & 0x7F;
134 *pf = frame[1] & AX25_EPF;
135 skb_pull(skb, 2);
136 } else if ((frame[0] & AX25_U) == 1) { /* S frame - take out PF/NR */
137 frametype = frame[0] & 0x0F;
138 *nr = (frame[1] >> 1) & 0x7F;
139 *pf = frame[1] & AX25_EPF;
140 skb_pull(skb, 2);
141 } else if ((frame[0] & AX25_U) == 3) { /* U frame - take out PF */
142 frametype = frame[0] & ~AX25_PF;
143 *pf = frame[0] & AX25_PF;
144 skb_pull(skb, 1);
145 }
146 }
147
148 return frametype;
149}
150
151/*
152 * This routine is called when the HDLC layer internally generates a
153 * command or response for the remote machine ( eg. RR, UA etc. ).
154 * Only supervisory or unnumbered frames are processed.
155 */
156void ax25_send_control(ax25_cb *ax25, int frametype, int poll_bit, int type)
157{
158 struct sk_buff *skb;
159 unsigned char *dptr;
160
161 if ((skb = alloc_skb(ax25->ax25_dev->dev->hard_header_len + 2, GFP_ATOMIC)) == NULL)
162 return;
163
164 skb_reserve(skb, ax25->ax25_dev->dev->hard_header_len);
165
166 skb->nh.raw = skb->data;
167
168 /* Assume a response - address structure for DTE */
169 if (ax25->modulus == AX25_MODULUS) {
170 dptr = skb_put(skb, 1);
171 *dptr = frametype;
172 *dptr |= (poll_bit) ? AX25_PF : 0;
173 if ((frametype & AX25_U) == AX25_S) /* S frames carry NR */
174 *dptr |= (ax25->vr << 5);
175 } else {
176 if ((frametype & AX25_U) == AX25_U) {
177 dptr = skb_put(skb, 1);
178 *dptr = frametype;
179 *dptr |= (poll_bit) ? AX25_PF : 0;
180 } else {
181 dptr = skb_put(skb, 2);
182 dptr[0] = frametype;
183 dptr[1] = (ax25->vr << 1);
184 dptr[1] |= (poll_bit) ? AX25_EPF : 0;
185 }
186 }
187
188 ax25_transmit_buffer(ax25, skb, type);
189}
190
191/*
192 * Send a 'DM' to an unknown connection attempt, or an invalid caller.
193 *
194 * Note: src here is the sender, thus it's the target of the DM
195 */
196void ax25_return_dm(struct net_device *dev, ax25_address *src, ax25_address *dest, ax25_digi *digi)
197{
198 struct sk_buff *skb;
199 char *dptr;
200 ax25_digi retdigi;
201
202 if (dev == NULL)
203 return;
204
205 if ((skb = alloc_skb(dev->hard_header_len + 1, GFP_ATOMIC)) == NULL)
206 return; /* Next SABM will get DM'd */
207
208 skb_reserve(skb, dev->hard_header_len);
209 skb->nh.raw = skb->data;
210
211 ax25_digi_invert(digi, &retdigi);
212
213 dptr = skb_put(skb, 1);
214
215 *dptr = AX25_DM | AX25_PF;
216
217 /*
218 * Do the address ourselves
219 */
220 dptr = skb_push(skb, ax25_addr_size(digi));
221 dptr += ax25_addr_build(dptr, dest, src, &retdigi, AX25_RESPONSE, AX25_MODULUS);
222
223 skb->dev = dev;
224
225 ax25_queue_xmit(skb);
226}
227
228/*
229 * Exponential backoff for AX.25
230 */
231void ax25_calculate_t1(ax25_cb *ax25)
232{
233 int n, t = 2;
234
235 switch (ax25->backoff) {
236 case 0:
237 break;
238
239 case 1:
240 t += 2 * ax25->n2count;
241 break;
242
243 case 2:
244 for (n = 0; n < ax25->n2count; n++)
245 t *= 2;
246 if (t > 8) t = 8;
247 break;
248 }
249
250 ax25->t1 = t * ax25->rtt;
251}
252
253/*
254 * Calculate the Round Trip Time
255 */
256void ax25_calculate_rtt(ax25_cb *ax25)
257{
258 if (ax25->backoff == 0)
259 return;
260
261 if (ax25_t1timer_running(ax25) && ax25->n2count == 0)
262 ax25->rtt = (9 * ax25->rtt + ax25->t1 - ax25_display_timer(&ax25->t1timer)) / 10;
263
264 if (ax25->rtt < AX25_T1CLAMPLO)
265 ax25->rtt = AX25_T1CLAMPLO;
266
267 if (ax25->rtt > AX25_T1CLAMPHI)
268 ax25->rtt = AX25_T1CLAMPHI;
269}
270
271void ax25_disconnect(ax25_cb *ax25, int reason)
272{
273 ax25_clear_queues(ax25);
274
275 ax25_stop_t1timer(ax25);
276 ax25_stop_t2timer(ax25);
277 ax25_stop_t3timer(ax25);
278 ax25_stop_idletimer(ax25);
279
280 ax25->state = AX25_STATE_0;
281
282 ax25_link_failed(ax25, reason);
283
284 if (ax25->sk != NULL) {
285 bh_lock_sock(ax25->sk);
286 ax25->sk->sk_state = TCP_CLOSE;
287 ax25->sk->sk_err = reason;
288 ax25->sk->sk_shutdown |= SEND_SHUTDOWN;
289 if (!sock_flag(ax25->sk, SOCK_DEAD)) {
290 ax25->sk->sk_state_change(ax25->sk);
291 sock_set_flag(ax25->sk, SOCK_DEAD);
292 }
293 bh_unlock_sock(ax25->sk);
294 }
295}
diff --git a/net/ax25/ax25_timer.c b/net/ax25/ax25_timer.c
new file mode 100644
index 000000000000..7a6b50a14554
--- /dev/null
+++ b/net/ax25/ax25_timer.c
@@ -0,0 +1,243 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
8 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
9 * Copyright (C) Tomi Manninen OH2BNS (oh2bns@sral.fi)
10 * Copyright (C) Darryl Miles G7LED (dlm@g7led.demon.co.uk)
11 * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
12 * Copyright (C) Frederic Rible F1OAT (frible@teaser.fr)
13 * Copyright (C) 2002 Ralf Baechle DO1GRB (ralf@gnu.org)
14 */
15#include <linux/config.h>
16#include <linux/errno.h>
17#include <linux/types.h>
18#include <linux/socket.h>
19#include <linux/in.h>
20#include <linux/kernel.h>
21#include <linux/jiffies.h>
22#include <linux/timer.h>
23#include <linux/string.h>
24#include <linux/sockios.h>
25#include <linux/net.h>
26#include <net/ax25.h>
27#include <linux/inet.h>
28#include <linux/netdevice.h>
29#include <linux/skbuff.h>
30#include <net/sock.h>
31#include <asm/uaccess.h>
32#include <asm/system.h>
33#include <linux/fcntl.h>
34#include <linux/mm.h>
35#include <linux/interrupt.h>
36
37static void ax25_heartbeat_expiry(unsigned long);
38static void ax25_t1timer_expiry(unsigned long);
39static void ax25_t2timer_expiry(unsigned long);
40static void ax25_t3timer_expiry(unsigned long);
41static void ax25_idletimer_expiry(unsigned long);
42
43void ax25_start_heartbeat(ax25_cb *ax25)
44{
45 del_timer(&ax25->timer);
46
47 ax25->timer.data = (unsigned long)ax25;
48 ax25->timer.function = &ax25_heartbeat_expiry;
49 ax25->timer.expires = jiffies + 5 * HZ;
50
51 add_timer(&ax25->timer);
52}
53
54void ax25_start_t1timer(ax25_cb *ax25)
55{
56 del_timer(&ax25->t1timer);
57
58 ax25->t1timer.data = (unsigned long)ax25;
59 ax25->t1timer.function = &ax25_t1timer_expiry;
60 ax25->t1timer.expires = jiffies + ax25->t1;
61
62 add_timer(&ax25->t1timer);
63}
64
65void ax25_start_t2timer(ax25_cb *ax25)
66{
67 del_timer(&ax25->t2timer);
68
69 ax25->t2timer.data = (unsigned long)ax25;
70 ax25->t2timer.function = &ax25_t2timer_expiry;
71 ax25->t2timer.expires = jiffies + ax25->t2;
72
73 add_timer(&ax25->t2timer);
74}
75
76void ax25_start_t3timer(ax25_cb *ax25)
77{
78 del_timer(&ax25->t3timer);
79
80 if (ax25->t3 > 0) {
81 ax25->t3timer.data = (unsigned long)ax25;
82 ax25->t3timer.function = &ax25_t3timer_expiry;
83 ax25->t3timer.expires = jiffies + ax25->t3;
84
85 add_timer(&ax25->t3timer);
86 }
87}
88
89void ax25_start_idletimer(ax25_cb *ax25)
90{
91 del_timer(&ax25->idletimer);
92
93 if (ax25->idle > 0) {
94 ax25->idletimer.data = (unsigned long)ax25;
95 ax25->idletimer.function = &ax25_idletimer_expiry;
96 ax25->idletimer.expires = jiffies + ax25->idle;
97
98 add_timer(&ax25->idletimer);
99 }
100}
101
102void ax25_stop_heartbeat(ax25_cb *ax25)
103{
104 del_timer(&ax25->timer);
105}
106
107void ax25_stop_t1timer(ax25_cb *ax25)
108{
109 del_timer(&ax25->t1timer);
110}
111
112void ax25_stop_t2timer(ax25_cb *ax25)
113{
114 del_timer(&ax25->t2timer);
115}
116
117void ax25_stop_t3timer(ax25_cb *ax25)
118{
119 del_timer(&ax25->t3timer);
120}
121
122void ax25_stop_idletimer(ax25_cb *ax25)
123{
124 del_timer(&ax25->idletimer);
125}
126
127int ax25_t1timer_running(ax25_cb *ax25)
128{
129 return timer_pending(&ax25->t1timer);
130}
131
132unsigned long ax25_display_timer(struct timer_list *timer)
133{
134 if (!timer_pending(timer))
135 return 0;
136
137 return timer->expires - jiffies;
138}
139
140static void ax25_heartbeat_expiry(unsigned long param)
141{
142 int proto = AX25_PROTO_STD_SIMPLEX;
143 ax25_cb *ax25 = (ax25_cb *)param;
144
145 if (ax25->ax25_dev)
146 proto = ax25->ax25_dev->values[AX25_VALUES_PROTOCOL];
147
148 switch (proto) {
149 case AX25_PROTO_STD_SIMPLEX:
150 case AX25_PROTO_STD_DUPLEX:
151 ax25_std_heartbeat_expiry(ax25);
152 break;
153
154#ifdef CONFIG_AX25_DAMA_SLAVE
155 case AX25_PROTO_DAMA_SLAVE:
156 if (ax25->ax25_dev->dama.slave)
157 ax25_ds_heartbeat_expiry(ax25);
158 else
159 ax25_std_heartbeat_expiry(ax25);
160 break;
161#endif
162 }
163}
164
165static void ax25_t1timer_expiry(unsigned long param)
166{
167 ax25_cb *ax25 = (ax25_cb *)param;
168
169 switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
170 case AX25_PROTO_STD_SIMPLEX:
171 case AX25_PROTO_STD_DUPLEX:
172 ax25_std_t1timer_expiry(ax25);
173 break;
174
175#ifdef CONFIG_AX25_DAMA_SLAVE
176 case AX25_PROTO_DAMA_SLAVE:
177 if (!ax25->ax25_dev->dama.slave)
178 ax25_std_t1timer_expiry(ax25);
179 break;
180#endif
181 }
182}
183
184static void ax25_t2timer_expiry(unsigned long param)
185{
186 ax25_cb *ax25 = (ax25_cb *)param;
187
188 switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
189 case AX25_PROTO_STD_SIMPLEX:
190 case AX25_PROTO_STD_DUPLEX:
191 ax25_std_t2timer_expiry(ax25);
192 break;
193
194#ifdef CONFIG_AX25_DAMA_SLAVE
195 case AX25_PROTO_DAMA_SLAVE:
196 if (!ax25->ax25_dev->dama.slave)
197 ax25_std_t2timer_expiry(ax25);
198 break;
199#endif
200 }
201}
202
203static void ax25_t3timer_expiry(unsigned long param)
204{
205 ax25_cb *ax25 = (ax25_cb *)param;
206
207 switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
208 case AX25_PROTO_STD_SIMPLEX:
209 case AX25_PROTO_STD_DUPLEX:
210 ax25_std_t3timer_expiry(ax25);
211 break;
212
213#ifdef CONFIG_AX25_DAMA_SLAVE
214 case AX25_PROTO_DAMA_SLAVE:
215 if (ax25->ax25_dev->dama.slave)
216 ax25_ds_t3timer_expiry(ax25);
217 else
218 ax25_std_t3timer_expiry(ax25);
219 break;
220#endif
221 }
222}
223
224static void ax25_idletimer_expiry(unsigned long param)
225{
226 ax25_cb *ax25 = (ax25_cb *)param;
227
228 switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
229 case AX25_PROTO_STD_SIMPLEX:
230 case AX25_PROTO_STD_DUPLEX:
231 ax25_std_idletimer_expiry(ax25);
232 break;
233
234#ifdef CONFIG_AX25_DAMA_SLAVE
235 case AX25_PROTO_DAMA_SLAVE:
236 if (ax25->ax25_dev->dama.slave)
237 ax25_ds_idletimer_expiry(ax25);
238 else
239 ax25_std_idletimer_expiry(ax25);
240 break;
241#endif
242 }
243}
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c
new file mode 100644
index 000000000000..cea6b7d19729
--- /dev/null
+++ b/net/ax25/ax25_uid.c
@@ -0,0 +1,228 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
8 */
9#include <linux/errno.h>
10#include <linux/types.h>
11#include <linux/socket.h>
12#include <linux/in.h>
13#include <linux/kernel.h>
14#include <linux/sched.h>
15#include <linux/timer.h>
16#include <linux/string.h>
17#include <linux/sockios.h>
18#include <linux/net.h>
19#include <linux/spinlock.h>
20#include <net/ax25.h>
21#include <linux/inet.h>
22#include <linux/netdevice.h>
23#include <linux/if_arp.h>
24#include <linux/skbuff.h>
25#include <net/sock.h>
26#include <asm/uaccess.h>
27#include <asm/system.h>
28#include <linux/fcntl.h>
29#include <linux/mm.h>
30#include <linux/interrupt.h>
31#include <linux/notifier.h>
32#include <linux/proc_fs.h>
33#include <linux/seq_file.h>
34#include <linux/stat.h>
35#include <linux/netfilter.h>
36#include <linux/sysctl.h>
37#include <net/ip.h>
38#include <net/arp.h>
39
40/*
41 * Callsign/UID mapper. This is in kernel space for security on multi-amateur machines.
42 */
43
44static ax25_uid_assoc *ax25_uid_list;
45static DEFINE_RWLOCK(ax25_uid_lock);
46
47int ax25_uid_policy = 0;
48
49ax25_address *ax25_findbyuid(uid_t uid)
50{
51 ax25_uid_assoc *ax25_uid;
52 ax25_address *res = NULL;
53
54 read_lock(&ax25_uid_lock);
55 for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
56 if (ax25_uid->uid == uid) {
57 res = &ax25_uid->call;
58 break;
59 }
60 }
61 read_unlock(&ax25_uid_lock);
62
63 return NULL;
64}
65
66int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
67{
68 ax25_uid_assoc *s, *ax25_uid;
69 unsigned long res;
70
71 switch (cmd) {
72 case SIOCAX25GETUID:
73 res = -ENOENT;
74 read_lock(&ax25_uid_lock);
75 for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
76 if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) {
77 res = ax25_uid->uid;
78 break;
79 }
80 }
81 read_unlock(&ax25_uid_lock);
82
83 return res;
84
85 case SIOCAX25ADDUID:
86 if (!capable(CAP_NET_ADMIN))
87 return -EPERM;
88 if (ax25_findbyuid(sax->sax25_uid))
89 return -EEXIST;
90 if (sax->sax25_uid == 0)
91 return -EINVAL;
92 if ((ax25_uid = kmalloc(sizeof(*ax25_uid), GFP_KERNEL)) == NULL)
93 return -ENOMEM;
94
95 ax25_uid->uid = sax->sax25_uid;
96 ax25_uid->call = sax->sax25_call;
97
98 write_lock(&ax25_uid_lock);
99 ax25_uid->next = ax25_uid_list;
100 ax25_uid_list = ax25_uid;
101 write_unlock(&ax25_uid_lock);
102
103 return 0;
104
105 case SIOCAX25DELUID:
106 if (!capable(CAP_NET_ADMIN))
107 return -EPERM;
108
109 write_lock(&ax25_uid_lock);
110 for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
111 if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) {
112 break;
113 }
114 }
115 if (ax25_uid == NULL) {
116 write_unlock(&ax25_uid_lock);
117 return -ENOENT;
118 }
119 if ((s = ax25_uid_list) == ax25_uid) {
120 ax25_uid_list = s->next;
121 write_unlock(&ax25_uid_lock);
122 kfree(ax25_uid);
123 return 0;
124 }
125 while (s != NULL && s->next != NULL) {
126 if (s->next == ax25_uid) {
127 s->next = ax25_uid->next;
128 write_unlock(&ax25_uid_lock);
129 kfree(ax25_uid);
130 return 0;
131 }
132 s = s->next;
133 }
134 write_unlock(&ax25_uid_lock);
135
136 return -ENOENT;
137
138 default:
139 return -EINVAL;
140 }
141
142 return -EINVAL; /*NOTREACHED */
143}
144
145#ifdef CONFIG_PROC_FS
146
147static void *ax25_uid_seq_start(struct seq_file *seq, loff_t *pos)
148{
149 struct ax25_uid_assoc *pt;
150 int i = 1;
151
152 read_lock(&ax25_uid_lock);
153 if (*pos == 0)
154 return SEQ_START_TOKEN;
155
156 for (pt = ax25_uid_list; pt != NULL; pt = pt->next) {
157 if (i == *pos)
158 return pt;
159 ++i;
160 }
161 return NULL;
162}
163
164static void *ax25_uid_seq_next(struct seq_file *seq, void *v, loff_t *pos)
165{
166 ++*pos;
167 return (v == SEQ_START_TOKEN) ? ax25_uid_list :
168 ((struct ax25_uid_assoc *) v)->next;
169}
170
171static void ax25_uid_seq_stop(struct seq_file *seq, void *v)
172{
173 read_unlock(&ax25_uid_lock);
174}
175
176static int ax25_uid_seq_show(struct seq_file *seq, void *v)
177{
178 if (v == SEQ_START_TOKEN)
179 seq_printf(seq, "Policy: %d\n", ax25_uid_policy);
180 else {
181 struct ax25_uid_assoc *pt = v;
182
183
184 seq_printf(seq, "%6d %s\n", pt->uid, ax2asc(&pt->call));
185 }
186 return 0;
187}
188
189static struct seq_operations ax25_uid_seqops = {
190 .start = ax25_uid_seq_start,
191 .next = ax25_uid_seq_next,
192 .stop = ax25_uid_seq_stop,
193 .show = ax25_uid_seq_show,
194};
195
196static int ax25_uid_info_open(struct inode *inode, struct file *file)
197{
198 return seq_open(file, &ax25_uid_seqops);
199}
200
201struct file_operations ax25_uid_fops = {
202 .owner = THIS_MODULE,
203 .open = ax25_uid_info_open,
204 .read = seq_read,
205 .llseek = seq_lseek,
206 .release = seq_release,
207};
208
209#endif
210
211/*
212 * Free all memory associated with UID/Callsign structures.
213 */
214void __exit ax25_uid_free(void)
215{
216 ax25_uid_assoc *s, *ax25_uid;
217
218 write_lock(&ax25_uid_lock);
219 ax25_uid = ax25_uid_list;
220 while (ax25_uid != NULL) {
221 s = ax25_uid;
222 ax25_uid = ax25_uid->next;
223
224 kfree(s);
225 }
226 ax25_uid_list = NULL;
227 write_unlock(&ax25_uid_lock);
228}
diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c
new file mode 100644
index 000000000000..f67711f2ee96
--- /dev/null
+++ b/net/ax25/sysctl_net_ax25.c
@@ -0,0 +1,262 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * Copyright (C) 1996 Mike Shaver (shaver@zeroknowledge.com)
8 */
9#include <linux/config.h>
10#include <linux/mm.h>
11#include <linux/sysctl.h>
12#include <linux/spinlock.h>
13#include <net/ax25.h>
14
15static int min_ipdefmode[1], max_ipdefmode[] = {1};
16static int min_axdefmode[1], max_axdefmode[] = {1};
17static int min_backoff[1], max_backoff[] = {2};
18static int min_conmode[1], max_conmode[] = {2};
19static int min_window[] = {1}, max_window[] = {7};
20static int min_ewindow[] = {1}, max_ewindow[] = {63};
21static int min_t1[] = {1}, max_t1[] = {30 * HZ};
22static int min_t2[] = {1}, max_t2[] = {20 * HZ};
23static int min_t3[1], max_t3[] = {3600 * HZ};
24static int min_idle[1], max_idle[] = {65535 * HZ};
25static int min_n2[] = {1}, max_n2[] = {31};
26static int min_paclen[] = {1}, max_paclen[] = {512};
27static int min_proto[1], max_proto[] = {3};
28static int min_ds_timeout[1], max_ds_timeout[] = {65535 * HZ};
29
30static struct ctl_table_header *ax25_table_header;
31
32static ctl_table *ax25_table;
33static int ax25_table_size;
34
35static ctl_table ax25_dir_table[] = {
36 {
37 .ctl_name = NET_AX25,
38 .procname = "ax25",
39 .mode = 0555,
40 },
41 { .ctl_name = 0 }
42};
43
44static ctl_table ax25_root_table[] = {
45 {
46 .ctl_name = CTL_NET,
47 .procname = "net",
48 .mode = 0555,
49 .child = ax25_dir_table
50 },
51 { .ctl_name = 0 }
52};
53
54static const ctl_table ax25_param_table[] = {
55 {
56 .ctl_name = NET_AX25_IP_DEFAULT_MODE,
57 .procname = "ip_default_mode",
58 .maxlen = sizeof(int),
59 .mode = 0644,
60 .proc_handler = &proc_dointvec_minmax,
61 .strategy = &sysctl_intvec,
62 .extra1 = &min_ipdefmode,
63 .extra2 = &max_ipdefmode
64 },
65 {
66 .ctl_name = NET_AX25_DEFAULT_MODE,
67 .procname = "ax25_default_mode",
68 .maxlen = sizeof(int),
69 .mode = 0644,
70 .proc_handler = &proc_dointvec_minmax,
71 .strategy = &sysctl_intvec,
72 .extra1 = &min_axdefmode,
73 .extra2 = &max_axdefmode
74 },
75 {
76 .ctl_name = NET_AX25_BACKOFF_TYPE,
77 .procname = "backoff_type",
78 .maxlen = sizeof(int),
79 .mode = 0644,
80 .proc_handler = &proc_dointvec_minmax,
81 .strategy = &sysctl_intvec,
82 .extra1 = &min_backoff,
83 .extra2 = &max_backoff
84 },
85 {
86 .ctl_name = NET_AX25_CONNECT_MODE,
87 .procname = "connect_mode",
88 .maxlen = sizeof(int),
89 .mode = 0644,
90 .proc_handler = &proc_dointvec_minmax,
91 .strategy = &sysctl_intvec,
92 .extra1 = &min_conmode,
93 .extra2 = &max_conmode
94 },
95 {
96 .ctl_name = NET_AX25_STANDARD_WINDOW,
97 .procname = "standard_window_size",
98 .maxlen = sizeof(int),
99 .mode = 0644,
100 .proc_handler = &proc_dointvec_minmax,
101 .strategy = &sysctl_intvec,
102 .extra1 = &min_window,
103 .extra2 = &max_window
104 },
105 {
106 .ctl_name = NET_AX25_EXTENDED_WINDOW,
107 .procname = "extended_window_size",
108 .maxlen = sizeof(int),
109 .mode = 0644,
110 .proc_handler = &proc_dointvec_minmax,
111 .strategy = &sysctl_intvec,
112 .extra1 = &min_ewindow,
113 .extra2 = &max_ewindow
114 },
115 {
116 .ctl_name = NET_AX25_T1_TIMEOUT,
117 .procname = "t1_timeout",
118 .maxlen = sizeof(int),
119 .mode = 0644,
120 .proc_handler = &proc_dointvec_minmax,
121 .strategy = &sysctl_intvec,
122 .extra1 = &min_t1,
123 .extra2 = &max_t1
124 },
125 {
126 .ctl_name = NET_AX25_T2_TIMEOUT,
127 .procname = "t2_timeout",
128 .maxlen = sizeof(int),
129 .mode = 0644,
130 .proc_handler = &proc_dointvec_minmax,
131 .strategy = &sysctl_intvec,
132 .extra1 = &min_t2,
133 .extra2 = &max_t2
134 },
135 {
136 .ctl_name = NET_AX25_T3_TIMEOUT,
137 .procname = "t3_timeout",
138 .maxlen = sizeof(int),
139 .mode = 0644,
140 .proc_handler = &proc_dointvec_minmax,
141 .strategy = &sysctl_intvec,
142 .extra1 = &min_t3,
143 .extra2 = &max_t3
144 },
145 {
146 .ctl_name = NET_AX25_IDLE_TIMEOUT,
147 .procname = "idle_timeout",
148 .maxlen = sizeof(int),
149 .mode = 0644,
150 .proc_handler = &proc_dointvec_minmax,
151 .strategy = &sysctl_intvec,
152 .extra1 = &min_idle,
153 .extra2 = &max_idle
154 },
155 {
156 .ctl_name = NET_AX25_N2,
157 .procname = "maximum_retry_count",
158 .maxlen = sizeof(int),
159 .mode = 0644,
160 .proc_handler = &proc_dointvec_minmax,
161 .strategy = &sysctl_intvec,
162 .extra1 = &min_n2,
163 .extra2 = &max_n2
164 },
165 {
166 .ctl_name = NET_AX25_PACLEN,
167 .procname = "maximum_packet_length",
168 .maxlen = sizeof(int),
169 .mode = 0644,
170 .proc_handler = &proc_dointvec_minmax,
171 .strategy = &sysctl_intvec,
172 .extra1 = &min_paclen,
173 .extra2 = &max_paclen
174 },
175 {
176 .ctl_name = NET_AX25_PROTOCOL,
177 .procname = "protocol",
178 .maxlen = sizeof(int),
179 .mode = 0644,
180 .proc_handler = &proc_dointvec_minmax,
181 .strategy = &sysctl_intvec,
182 .extra1 = &min_proto,
183 .extra2 = &max_proto
184 },
185 {
186 .ctl_name = NET_AX25_DAMA_SLAVE_TIMEOUT,
187 .procname = "dama_slave_timeout",
188 .maxlen = sizeof(int),
189 .mode = 0644,
190 .proc_handler = &proc_dointvec_minmax,
191 .strategy = &sysctl_intvec,
192 .extra1 = &min_ds_timeout,
193 .extra2 = &max_ds_timeout
194 },
195 { .ctl_name = 0 } /* that's all, folks! */
196};
197
198void ax25_register_sysctl(void)
199{
200 ax25_dev *ax25_dev;
201 int n, k;
202
203 spin_lock_bh(&ax25_dev_lock);
204 for (ax25_table_size = sizeof(ctl_table), ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
205 ax25_table_size += sizeof(ctl_table);
206
207 if ((ax25_table = kmalloc(ax25_table_size, GFP_ATOMIC)) == NULL) {
208 spin_unlock_bh(&ax25_dev_lock);
209 return;
210 }
211
212 memset(ax25_table, 0x00, ax25_table_size);
213
214 for (n = 0, ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next) {
215 ctl_table *child = kmalloc(sizeof(ax25_param_table), GFP_ATOMIC);
216 if (!child) {
217 while (n--)
218 kfree(ax25_table[n].child);
219 kfree(ax25_table);
220 spin_unlock_bh(&ax25_dev_lock);
221 return;
222 }
223 memcpy(child, ax25_param_table, sizeof(ax25_param_table));
224 ax25_table[n].child = ax25_dev->systable = child;
225 ax25_table[n].ctl_name = n + 1;
226 ax25_table[n].procname = ax25_dev->dev->name;
227 ax25_table[n].mode = 0555;
228
229#ifndef CONFIG_AX25_DAMA_SLAVE
230 /*
231 * We do not wish to have a representation of this parameter
232 * in /proc/sys/ when configured *not* to include the
233 * AX.25 DAMA slave code, do we?
234 */
235
236 child[AX25_VALUES_DS_TIMEOUT].procname = NULL;
237#endif
238
239 child[AX25_MAX_VALUES].ctl_name = 0; /* just in case... */
240
241 for (k = 0; k < AX25_MAX_VALUES; k++)
242 child[k].data = &ax25_dev->values[k];
243
244 n++;
245 }
246 spin_unlock_bh(&ax25_dev_lock);
247
248 ax25_dir_table[0].child = ax25_table;
249
250 ax25_table_header = register_sysctl_table(ax25_root_table, 1);
251}
252
253void ax25_unregister_sysctl(void)
254{
255 ctl_table *p;
256 unregister_sysctl_table(ax25_table_header);
257
258 ax25_dir_table[0].child = NULL;
259 for (p = ax25_table; p->ctl_name; p++)
260 kfree(p->child);
261 kfree(ax25_table);
262}