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 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/timer.h> 15#include <linux/string.h> 16#include <linux/sockios.h> 17#include <linux/net.h> 18#include <linux/slab.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 <net/tcp_states.h> 25#include <linux/uaccess.h> 26#include <linux/fcntl.h> 27#include <linux/mm.h> 28#include <linux/interrupt.h> 29#include <net/netrom.h> 30 31/* 32 * This routine purges all of the queues of frames. 33 */ 34void nr_clear_queues(struct sock *sk) 35{ 36 struct nr_sock *nr = nr_sk(sk); 37 38 skb_queue_purge(&sk->sk_write_queue); 39 skb_queue_purge(&nr->ack_queue); 40 skb_queue_purge(&nr->reseq_queue); 41 skb_queue_purge(&nr->frag_queue); 42} 43 44/* 45 * This routine purges the input queue of those frames that have been 46 * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the 47 * SDL diagram. 48 */ 49void nr_frames_acked(struct sock *sk, unsigned short nr) 50{ 51 struct nr_sock *nrom = nr_sk(sk); 52 struct sk_buff *skb; 53 54 /* 55 * Remove all the ack-ed frames from the ack queue. 56 */ 57 if (nrom->va != nr) { 58 while (skb_peek(&nrom->ack_queue) != NULL && nrom->va != nr) { 59 skb = skb_dequeue(&nrom->ack_queue); 60 kfree_skb(skb); 61 nrom->va = (nrom->va + 1) % NR_MODULUS; 62 } 63 } 64} 65 66/* 67 * Requeue all the un-ack-ed frames on the output queue to be picked 68 * up by nr_kick called from the timer. This arrangement handles the 69 * possibility of an empty output queue. 70 */ 71void nr_requeue_frames(struct sock *sk) 72{ 73 struct sk_buff *skb, *skb_prev = NULL; 74 75 while ((skb = skb_dequeue(&nr_sk(sk)->ack_queue)) != NULL) { 76 if (skb_prev == NULL) 77 skb_queue_head(&sk->sk_write_queue, skb); 78 else 79 skb_append(skb_prev, skb, &sk->sk_write_queue); 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 nr_validate_nr(struct sock *sk, unsigned short nr) 89{ 90 struct nr_sock *nrom = nr_sk(sk); 91 unsigned short vc = nrom->va; 92 93 while (vc != nrom->vs) { 94 if (nr == vc) return 1; 95 vc = (vc + 1) % NR_MODULUS; 96 } 97 98 return nr == nrom->vs; 99} 100 101/* 102 * Check that ns is within the receive window. 103 */ 104int nr_in_rx_window(struct sock *sk, unsigned short ns) 105{ 106 struct nr_sock *nr = nr_sk(sk); 107 unsigned short vc = nr->vr; 108 unsigned short vt = (nr->vl + nr->window) % NR_MODULUS; 109 110 while (vc != vt) { 111 if (ns == vc) return 1; 112 vc = (vc + 1) % NR_MODULUS; 113 } 114 115 return 0; 116} 117 118/* 119 * This routine is called when the HDLC layer internally generates a 120 * control frame. 121 */ 122void nr_write_internal(struct sock *sk, int frametype) 123{ 124 struct nr_sock *nr = nr_sk(sk); 125 struct sk_buff *skb; 126 unsigned char *dptr; 127 int len, timeout; 128 129 len = NR_NETWORK_LEN + NR_TRANSPORT_LEN; 130 131 switch (frametype & 0x0F) { 132 case NR_CONNREQ: 133 len += 17; 134 break; 135 case NR_CONNACK: 136 len += (nr->bpqext) ? 2 : 1; 137 break; 138 case NR_DISCREQ: 139 case NR_DISCACK: 140 case NR_INFOACK: 141 break; 142 default: 143 printk(KERN_ERR "NET/ROM: nr_write_internal - invalid frame type %d\n", frametype); 144 return; 145 } 146 147 if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL) 148 return; 149 150 /* 151 * Space for AX.25 and NET/ROM network header 152 */ 153 skb_reserve(skb, NR_NETWORK_LEN); 154 155 dptr = skb_put(skb, skb_tailroom(skb)); 156 157 switch (frametype & 0x0F) { 158 case NR_CONNREQ: 159 timeout = nr->t1 / HZ; 160 *dptr++ = nr->my_index; 161 *dptr++ = nr->my_id; 162 *dptr++ = 0; 163 *dptr++ = 0; 164 *dptr++ = frametype; 165 *dptr++ = nr->window; 166 memcpy(dptr, &nr->user_addr, AX25_ADDR_LEN); 167 dptr[6] &= ~AX25_CBIT; 168 dptr[6] &= ~AX25_EBIT; 169 dptr[6] |= AX25_SSSID_SPARE; 170 dptr += AX25_ADDR_LEN; 171 memcpy(dptr, &nr->source_addr, AX25_ADDR_LEN); 172 dptr[6] &= ~AX25_CBIT; 173 dptr[6] &= ~AX25_EBIT; 174 dptr[6] |= AX25_SSSID_SPARE; 175 dptr += AX25_ADDR_LEN; 176 *dptr++ = timeout % 256; 177 *dptr++ = timeout / 256; 178 break; 179 180 case NR_CONNACK: 181 *dptr++ = nr->your_index; 182 *dptr++ = nr->your_id; 183 *dptr++ = nr->my_index; 184 *dptr++ = nr->my_id; 185 *dptr++ = frametype; 186 *dptr++ = nr->window; 187 if (nr->bpqext) *dptr++ = sysctl_netrom_network_ttl_initialiser; 188 break; 189 190 case NR_DISCREQ: 191 case NR_DISCACK: 192 *dptr++ = nr->your_index; 193 *dptr++ = nr->your_id; 194 *dptr++ = 0; 195 *dptr++ = 0; 196 *dptr++ = frametype; 197 break; 198 199 case NR_INFOACK: 200 *dptr++ = nr->your_index; 201 *dptr++ = nr->your_id; 202 *dptr++ = 0; 203 *dptr++ = nr->vr; 204 *dptr++ = frametype; 205 break; 206 } 207 208 nr_transmit_buffer(sk, skb); 209} 210 211/* 212 * This routine is called to send an error reply. 213 */ 214void __nr_transmit_reply(struct sk_buff *skb, int mine, unsigned char cmdflags) 215{ 216 struct sk_buff *skbn; 217 unsigned char *dptr; 218 int len; 219 220 len = NR_NETWORK_LEN + NR_TRANSPORT_LEN + 1; 221 222 if ((skbn = alloc_skb(len, GFP_ATOMIC)) == NULL) 223 return; 224 225 skb_reserve(skbn, 0); 226 227 dptr = skb_put(skbn, NR_NETWORK_LEN + NR_TRANSPORT_LEN); 228 229 skb_copy_from_linear_data_offset(skb, 7, dptr, AX25_ADDR_LEN); 230 dptr[6] &= ~AX25_CBIT; 231 dptr[6] &= ~AX25_EBIT; 232 dptr[6] |= AX25_SSSID_SPARE; 233 dptr += AX25_ADDR_LEN; 234 235 skb_copy_from_linear_data(skb, dptr, AX25_ADDR_LEN); 236 dptr[6] &= ~AX25_CBIT; 237 dptr[6] |= AX25_EBIT; 238 dptr[6] |= AX25_SSSID_SPARE; 239 dptr += AX25_ADDR_LEN; 240 241 *dptr++ = sysctl_netrom_network_ttl_initialiser; 242 243 if (mine) { 244 *dptr++ = 0; 245 *dptr++ = 0; 246 *dptr++ = skb->data[15]; 247 *dptr++ = skb->data[16]; 248 } else { 249 *dptr++ = skb->data[15]; 250 *dptr++ = skb->data[16]; 251 *dptr++ = 0; 252 *dptr++ = 0; 253 } 254 255 *dptr++ = cmdflags; 256 *dptr++ = 0; 257 258 if (!nr_route_frame(skbn, NULL)) 259 kfree_skb(skbn); 260} 261 262void nr_disconnect(struct sock *sk, int reason) 263{ 264 nr_stop_t1timer(sk); 265 nr_stop_t2timer(sk); 266 nr_stop_t4timer(sk); 267 nr_stop_idletimer(sk); 268 269 nr_clear_queues(sk); 270 271 nr_sk(sk)->state = NR_STATE_0; 272 273 sk->sk_state = TCP_CLOSE; 274 sk->sk_err = reason; 275 sk->sk_shutdown |= SEND_SHUTDOWN; 276 277 if (!sock_flag(sk, SOCK_DEAD)) { 278 sk->sk_state_change(sk); 279 sock_set_flag(sk, SOCK_DEAD); 280 } 281} 282