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) 2002 Ralf Baechle DO1GRB (ralf@gnu.org) 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/jiffies.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/tcp_states.h> 26#include <linux/uaccess.h> 27#include <linux/fcntl.h> 28#include <linux/mm.h> 29#include <linux/interrupt.h> 30#include <net/netrom.h> 31 32static void nr_heartbeat_expiry(unsigned long); 33static void nr_t1timer_expiry(unsigned long); 34static void nr_t2timer_expiry(unsigned long); 35static void nr_t4timer_expiry(unsigned long); 36static void nr_idletimer_expiry(unsigned long); 37 38void nr_init_timers(struct sock *sk) 39{ 40 struct nr_sock *nr = nr_sk(sk); 41 42 setup_timer(&nr->t1timer, nr_t1timer_expiry, (unsigned long)sk); 43 setup_timer(&nr->t2timer, nr_t2timer_expiry, (unsigned long)sk); 44 setup_timer(&nr->t4timer, nr_t4timer_expiry, (unsigned long)sk); 45 setup_timer(&nr->idletimer, nr_idletimer_expiry, (unsigned long)sk); 46 47 /* initialized by sock_init_data */ 48 sk->sk_timer.data = (unsigned long)sk; 49 sk->sk_timer.function = &nr_heartbeat_expiry; 50} 51 52void nr_start_t1timer(struct sock *sk) 53{ 54 struct nr_sock *nr = nr_sk(sk); 55 56 mod_timer(&nr->t1timer, jiffies + nr->t1); 57} 58 59void nr_start_t2timer(struct sock *sk) 60{ 61 struct nr_sock *nr = nr_sk(sk); 62 63 mod_timer(&nr->t2timer, jiffies + nr->t2); 64} 65 66void nr_start_t4timer(struct sock *sk) 67{ 68 struct nr_sock *nr = nr_sk(sk); 69 70 mod_timer(&nr->t4timer, jiffies + nr->t4); 71} 72 73void nr_start_idletimer(struct sock *sk) 74{ 75 struct nr_sock *nr = nr_sk(sk); 76 77 if (nr->idle > 0) 78 mod_timer(&nr->idletimer, jiffies + nr->idle); 79} 80 81void nr_start_heartbeat(struct sock *sk) 82{ 83 mod_timer(&sk->sk_timer, jiffies + 5 * HZ); 84} 85 86void nr_stop_t1timer(struct sock *sk) 87{ 88 del_timer(&nr_sk(sk)->t1timer); 89} 90 91void nr_stop_t2timer(struct sock *sk) 92{ 93 del_timer(&nr_sk(sk)->t2timer); 94} 95 96void nr_stop_t4timer(struct sock *sk) 97{ 98 del_timer(&nr_sk(sk)->t4timer); 99} 100 101void nr_stop_idletimer(struct sock *sk) 102{ 103 del_timer(&nr_sk(sk)->idletimer); 104} 105 106void nr_stop_heartbeat(struct sock *sk) 107{ 108 del_timer(&sk->sk_timer); 109} 110 111int nr_t1timer_running(struct sock *sk) 112{ 113 return timer_pending(&nr_sk(sk)->t1timer); 114} 115 116static void nr_heartbeat_expiry(unsigned long param) 117{ 118 struct sock *sk = (struct sock *)param; 119 struct nr_sock *nr = nr_sk(sk); 120 121 bh_lock_sock(sk); 122 switch (nr->state) { 123 case NR_STATE_0: 124 /* Magic here: If we listen() and a new link dies before it 125 is accepted() it isn't 'dead' so doesn't get removed. */ 126 if (sock_flag(sk, SOCK_DESTROY) || 127 (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) { 128 sock_hold(sk); 129 bh_unlock_sock(sk); 130 nr_destroy_socket(sk); 131 sock_put(sk); 132 return; 133 } 134 break; 135 136 case NR_STATE_3: 137 /* 138 * Check for the state of the receive buffer. 139 */ 140 if (atomic_read(&sk->sk_rmem_alloc) < (sk->sk_rcvbuf / 2) && 141 (nr->condition & NR_COND_OWN_RX_BUSY)) { 142 nr->condition &= ~NR_COND_OWN_RX_BUSY; 143 nr->condition &= ~NR_COND_ACK_PENDING; 144 nr->vl = nr->vr; 145 nr_write_internal(sk, NR_INFOACK); 146 break; 147 } 148 break; 149 } 150 151 nr_start_heartbeat(sk); 152 bh_unlock_sock(sk); 153} 154 155static void nr_t2timer_expiry(unsigned long param) 156{ 157 struct sock *sk = (struct sock *)param; 158 struct nr_sock *nr = nr_sk(sk); 159 160 bh_lock_sock(sk); 161 if (nr->condition & NR_COND_ACK_PENDING) { 162 nr->condition &= ~NR_COND_ACK_PENDING; 163 nr_enquiry_response(sk); 164 } 165 bh_unlock_sock(sk); 166} 167 168static void nr_t4timer_expiry(unsigned long param) 169{ 170 struct sock *sk = (struct sock *)param; 171 172 bh_lock_sock(sk); 173 nr_sk(sk)->condition &= ~NR_COND_PEER_RX_BUSY; 174 bh_unlock_sock(sk); 175} 176 177static void nr_idletimer_expiry(unsigned long param) 178{ 179 struct sock *sk = (struct sock *)param; 180 struct nr_sock *nr = nr_sk(sk); 181 182 bh_lock_sock(sk); 183 184 nr_clear_queues(sk); 185 186 nr->n2count = 0; 187 nr_write_internal(sk, NR_DISCREQ); 188 nr->state = NR_STATE_2; 189 190 nr_start_t1timer(sk); 191 nr_stop_t2timer(sk); 192 nr_stop_t4timer(sk); 193 194 sk->sk_state = TCP_CLOSE; 195 sk->sk_err = 0; 196 sk->sk_shutdown |= SEND_SHUTDOWN; 197 198 if (!sock_flag(sk, SOCK_DEAD)) { 199 sk->sk_state_change(sk); 200 sock_set_flag(sk, SOCK_DEAD); 201 } 202 bh_unlock_sock(sk); 203} 204 205static void nr_t1timer_expiry(unsigned long param) 206{ 207 struct sock *sk = (struct sock *)param; 208 struct nr_sock *nr = nr_sk(sk); 209 210 bh_lock_sock(sk); 211 switch (nr->state) { 212 case NR_STATE_1: 213 if (nr->n2count == nr->n2) { 214 nr_disconnect(sk, ETIMEDOUT); 215 bh_unlock_sock(sk); 216 return; 217 } else { 218 nr->n2count++; 219 nr_write_internal(sk, NR_CONNREQ); 220 } 221 break; 222 223 case NR_STATE_2: 224 if (nr->n2count == nr->n2) { 225 nr_disconnect(sk, ETIMEDOUT); 226 bh_unlock_sock(sk); 227 return; 228 } else { 229 nr->n2count++; 230 nr_write_internal(sk, NR_DISCREQ); 231 } 232 break; 233 234 case NR_STATE_3: 235 if (nr->n2count == nr->n2) { 236 nr_disconnect(sk, ETIMEDOUT); 237 bh_unlock_sock(sk); 238 return; 239 } else { 240 nr->n2count++; 241 nr_requeue_frames(sk); 242 } 243 break; 244 } 245 246 nr_start_t1timer(sk); 247 bh_unlock_sock(sk); 248} 249