1 /*
2  *	AX.25 release 037
3  *
4  *	This code REQUIRES 2.1.15 or higher/ NET3.038
5  *
6  *	This module:
7  *		This module is free software; you can redistribute it and/or
8  *		modify it under the terms of the GNU General Public License
9  *		as published by the Free Software Foundation; either version
10  *		2 of the License, or (at your option) any later version.
11  *
12  *	History
13  *	AX.25 028a	Jonathan(G4KLX)	New state machine based on SDL diagrams.
14  *	AX.25 028b	Jonathan(G4KLX)	Extracted AX25 control block from the
15  *					sock structure.
16  *	AX.25 029	Alan(GW4PTS)	Switched to KA9Q constant names.
17  *	AX.25 031	Joerg(DL1BKE)	Added DAMA support
18  *	AX.25 032	Joerg(DL1BKE)	Fixed DAMA timeout bug
19  *	AX.25 033	Jonathan(G4KLX)	Modularisation functions.
20  *	AX.25 035	Frederic(F1OAT)	Support for pseudo-digipeating.
21  *	AX.25 036	Jonathan(G4KLX)	Split from ax25_timer.c.
22  *	AX.25 037	Jonathan(G4KLX)	New timer architecture.
23  */
24 
25 #include <linux/errno.h>
26 #include <linux/types.h>
27 #include <linux/socket.h>
28 #include <linux/in.h>
29 #include <linux/kernel.h>
30 #include <linux/sched.h>
31 #include <linux/timer.h>
32 #include <linux/string.h>
33 #include <linux/sockios.h>
34 #include <linux/net.h>
35 #include <net/ax25.h>
36 #include <linux/inet.h>
37 #include <linux/netdevice.h>
38 #include <linux/skbuff.h>
39 #include <net/sock.h>
40 #include <asm/uaccess.h>
41 #include <asm/system.h>
42 #include <linux/fcntl.h>
43 #include <linux/mm.h>
44 #include <linux/interrupt.h>
45 
ax25_std_heartbeat_expiry(ax25_cb * ax25)46 void ax25_std_heartbeat_expiry(ax25_cb *ax25)
47 {
48 	switch (ax25->state) {
49 
50 		case AX25_STATE_0:
51 			/* Magic here: If we listen() and a new link dies before it
52 			   is accepted() it isn't 'dead' so doesn't get removed. */
53 			if (ax25->sk == NULL || ax25->sk->destroy || (ax25->sk->state == TCP_LISTEN && ax25->sk->dead)) {
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 (ax25->sk != NULL) {
65 				if (atomic_read(&ax25->sk->rmem_alloc) < (ax25->sk->rcvbuf / 2) &&
66 				    (ax25->condition & AX25_COND_OWN_RX_BUSY)) {
67 					ax25->condition &= ~AX25_COND_OWN_RX_BUSY;
68 					ax25->condition &= ~AX25_COND_ACK_PENDING;
69 					ax25_send_control(ax25, AX25_RR, AX25_POLLOFF, AX25_RESPONSE);
70 					break;
71 				}
72 			}
73 	}
74 
75 	ax25_start_heartbeat(ax25);
76 }
77 
ax25_std_t2timer_expiry(ax25_cb * ax25)78 void ax25_std_t2timer_expiry(ax25_cb *ax25)
79 {
80 	if (ax25->condition & AX25_COND_ACK_PENDING) {
81 		ax25->condition &= ~AX25_COND_ACK_PENDING;
82 		ax25_std_timeout_response(ax25);
83 	}
84 }
85 
ax25_std_t3timer_expiry(ax25_cb * ax25)86 void ax25_std_t3timer_expiry(ax25_cb *ax25)
87 {
88 	ax25->n2count = 0;
89 	ax25_std_transmit_enquiry(ax25);
90 	ax25->state   = AX25_STATE_4;
91 }
92 
ax25_std_idletimer_expiry(ax25_cb * ax25)93 void ax25_std_idletimer_expiry(ax25_cb *ax25)
94 {
95 	ax25_clear_queues(ax25);
96 
97 	ax25->n2count = 0;
98 	ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
99 	ax25->state   = AX25_STATE_2;
100 
101 	ax25_calculate_t1(ax25);
102 	ax25_start_t1timer(ax25);
103 	ax25_stop_t2timer(ax25);
104 	ax25_stop_t3timer(ax25);
105 
106 	if (ax25->sk != NULL) {
107 		ax25->sk->state     = TCP_CLOSE;
108 		ax25->sk->err       = 0;
109 		ax25->sk->shutdown |= SEND_SHUTDOWN;
110 		if (!ax25->sk->dead)
111 			ax25->sk->state_change(ax25->sk);
112 		ax25->sk->dead      = 1;
113 	}
114 }
115 
ax25_std_t1timer_expiry(ax25_cb * ax25)116 void ax25_std_t1timer_expiry(ax25_cb *ax25)
117 {
118 	switch (ax25->state) {
119 		case AX25_STATE_1:
120 			if (ax25->n2count == ax25->n2) {
121 				if (ax25->modulus == AX25_MODULUS) {
122 					ax25_disconnect(ax25, ETIMEDOUT);
123 					return;
124 				} else {
125 					ax25->modulus = AX25_MODULUS;
126 					ax25->window  = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
127 					ax25->n2count = 0;
128 					ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
129 				}
130 			} else {
131 				ax25->n2count++;
132 				if (ax25->modulus == AX25_MODULUS)
133 					ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
134 				else
135 					ax25_send_control(ax25, AX25_SABME, AX25_POLLON, AX25_COMMAND);
136 			}
137 			break;
138 
139 		case AX25_STATE_2:
140 			if (ax25->n2count == ax25->n2) {
141 				ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
142 				ax25_disconnect(ax25, ETIMEDOUT);
143 				return;
144 			} else {
145 				ax25->n2count++;
146 				ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
147 			}
148 			break;
149 
150 		case AX25_STATE_3:
151 			ax25->n2count = 1;
152 			ax25_std_transmit_enquiry(ax25);
153 			ax25->state   = AX25_STATE_4;
154 			break;
155 
156 		case AX25_STATE_4:
157 			if (ax25->n2count == ax25->n2) {
158 				ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE);
159 				ax25_disconnect(ax25, ETIMEDOUT);
160 				return;
161 			} else {
162 				ax25->n2count++;
163 				ax25_std_transmit_enquiry(ax25);
164 			}
165 			break;
166 	}
167 
168 	ax25_calculate_t1(ax25);
169 	ax25_start_t1timer(ax25);
170 }
171