1/* 2 * X.25 Packet Layer release 002 3 * 4 * This is ALPHA test software. This code may break your machine, randomly fail to work with new 5 * releases, misbehave and/or generally screw up. It might even work. 6 * 7 * This code REQUIRES 2.1.15 or higher 8 * 9 * This module: 10 * This module is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License 12 * as published by the Free Software Foundation; either version 13 * 2 of the License, or (at your option) any later version. 14 * 15 * History 16 * X.25 001 Jonathan Naylor Started coding. 17 * X.25 002 Jonathan Naylor New timer architecture. 18 * Centralised disconnection processing. 19 */ 20 21#include <linux/errno.h> 22#include <linux/types.h> 23#include <linux/socket.h> 24#include <linux/in.h> 25#include <linux/kernel.h> 26#include <linux/sched.h> 27#include <linux/timer.h> 28#include <linux/string.h> 29#include <linux/sockios.h> 30#include <linux/net.h> 31#include <linux/inet.h> 32#include <linux/netdevice.h> 33#include <linux/skbuff.h> 34#include <net/sock.h> 35#include <asm/segment.h> 36#include <asm/system.h> 37#include <linux/fcntl.h> 38#include <linux/mm.h> 39#include <linux/interrupt.h> 40#include <net/x25.h> 41 42static void x25_heartbeat_expiry(unsigned long); 43static void x25_timer_expiry(unsigned long); 44 45void x25_start_heartbeat(struct sock *sk) 46{ 47 del_timer(&sk->timer); 48 49 sk->timer.data = (unsigned long)sk; 50 sk->timer.function = &x25_heartbeat_expiry; 51 sk->timer.expires = jiffies + 5 * HZ; 52 53 add_timer(&sk->timer); 54} 55 56void x25_stop_heartbeat(struct sock *sk) 57{ 58 del_timer(&sk->timer); 59} 60 61void x25_start_t2timer(struct sock *sk) 62{ 63 del_timer(&sk->protinfo.x25->timer); 64 65 sk->protinfo.x25->timer.data = (unsigned long)sk; 66 sk->protinfo.x25->timer.function = &x25_timer_expiry; 67 sk->protinfo.x25->timer.expires = jiffies + sk->protinfo.x25->t2; 68 69 add_timer(&sk->protinfo.x25->timer); 70} 71 72void x25_start_t21timer(struct sock *sk) 73{ 74 del_timer(&sk->protinfo.x25->timer); 75 76 sk->protinfo.x25->timer.data = (unsigned long)sk; 77 sk->protinfo.x25->timer.function = &x25_timer_expiry; 78 sk->protinfo.x25->timer.expires = jiffies + sk->protinfo.x25->t21; 79 80 add_timer(&sk->protinfo.x25->timer); 81} 82 83void x25_start_t22timer(struct sock *sk) 84{ 85 del_timer(&sk->protinfo.x25->timer); 86 87 sk->protinfo.x25->timer.data = (unsigned long)sk; 88 sk->protinfo.x25->timer.function = &x25_timer_expiry; 89 sk->protinfo.x25->timer.expires = jiffies + sk->protinfo.x25->t22; 90 91 add_timer(&sk->protinfo.x25->timer); 92} 93 94void x25_start_t23timer(struct sock *sk) 95{ 96 del_timer(&sk->protinfo.x25->timer); 97 98 sk->protinfo.x25->timer.data = (unsigned long)sk; 99 sk->protinfo.x25->timer.function = &x25_timer_expiry; 100 sk->protinfo.x25->timer.expires = jiffies + sk->protinfo.x25->t23; 101 102 add_timer(&sk->protinfo.x25->timer); 103} 104 105void x25_stop_timer(struct sock *sk) 106{ 107 del_timer(&sk->protinfo.x25->timer); 108} 109 110unsigned long x25_display_timer(struct sock *sk) 111{ 112 if (!timer_pending(&sk->protinfo.x25->timer)) 113 return 0; 114 115 return sk->protinfo.x25->timer.expires - jiffies; 116} 117 118static void x25_heartbeat_expiry(unsigned long param) 119{ 120 struct sock *sk = (struct sock *)param; 121 122 bh_lock_sock(sk); 123 if (sk->lock.users) { /* can currently only occur in state 3 */ 124 goto restart_heartbeat; 125 } 126 127 switch (sk->protinfo.x25->state) { 128 129 case X25_STATE_0: 130 /* Magic here: If we listen() and a new link dies before it 131 is accepted() it isn't 'dead' so doesn't get removed. */ 132 if (sk->destroy || (sk->state == TCP_LISTEN && sk->dead)) { 133 x25_destroy_socket(sk); 134 goto unlock; 135 } 136 break; 137 138 case X25_STATE_3: 139 /* 140 * Check for the state of the receive buffer. 141 */ 142 x25_check_rbuf(sk); 143 break; 144 } 145 restart_heartbeat: 146 x25_start_heartbeat(sk); 147 unlock: 148 bh_unlock_sock(sk); 149} 150 151/* 152 * Timer has expired, it may have been T2, T21, T22, or T23. We can tell 153 * by the state machine state. 154 */ 155static inline void x25_do_timer_expiry(struct sock * sk) 156{ 157 switch (sk->protinfo.x25->state) { 158 159 case X25_STATE_3: /* T2 */ 160 if (sk->protinfo.x25->condition & X25_COND_ACK_PENDING) { 161 sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING; 162 x25_enquiry_response(sk); 163 } 164 break; 165 166 case X25_STATE_1: /* T21 */ 167 case X25_STATE_4: /* T22 */ 168 x25_write_internal(sk, X25_CLEAR_REQUEST); 169 sk->protinfo.x25->state = X25_STATE_2; 170 x25_start_t23timer(sk); 171 break; 172 173 case X25_STATE_2: /* T23 */ 174 x25_disconnect(sk, ETIMEDOUT, 0, 0); 175 break; 176 } 177} 178 179static void x25_timer_expiry(unsigned long param) 180{ 181 struct sock *sk = (struct sock *)param; 182 183 bh_lock_sock(sk); 184 if (sk->lock.users) { /* can currently only occur in state 3 */ 185 if (sk->protinfo.x25->state == X25_STATE_3) { 186 x25_start_t2timer(sk); 187 } 188 } else { 189 x25_do_timer_expiry(sk); 190 } 191 bh_unlock_sock(sk); 192} 193

