Beispiel #1
0
static void nr_send_iframe(struct sock *sk, struct sk_buff *skb)
{
	struct nr_sock *nr = nr_sk(sk);

	if (skb == NULL)
		return;

	skb->data[2] = nr->vs;
	skb->data[3] = nr->vr;

	if (nr->condition & NR_COND_OWN_RX_BUSY)
		skb->data[4] |= NR_CHOKE_FLAG;

	nr_start_idletimer(sk);

	nr_transmit_buffer(sk, skb);
}
Beispiel #2
0
void nr_send_nak_frame(struct sock *sk)
{
	struct sk_buff *skb, *skbn;
	struct nr_sock *nr = nr_sk(sk);

	if ((skb = skb_peek(&nr->ack_queue)) == NULL)
		return;

	if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL)
		return;

	skbn->data[2] = nr->va;
	skbn->data[3] = nr->vr;

	if (nr->condition & NR_COND_OWN_RX_BUSY)
		skbn->data[4] |= NR_CHOKE_FLAG;

	nr_transmit_buffer(sk, skbn);

	nr->condition &= ~NR_COND_ACK_PENDING;
	nr->vl         = nr->vr;

	nr_stop_t1timer(sk);
}
Beispiel #3
0
/*
 *  This routine is called when the HDLC layer internally generates a
 *  control frame.
 */
void nr_write_internal(struct sock *sk, int frametype)
{
	struct nr_sock *nr = nr_sk(sk);
	struct sk_buff *skb;
	unsigned char  *dptr;
	int len, timeout;

	len = NR_NETWORK_LEN + NR_TRANSPORT_LEN;

	switch (frametype & 0x0F) {
	case NR_CONNREQ:
		len += 17;
		break;
	case NR_CONNACK:
		len += (nr->bpqext) ? 2 : 1;
		break;
	case NR_DISCREQ:
	case NR_DISCACK:
	case NR_INFOACK:
		break;
	default:
;
		return;
	}

	if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
		return;

	/*
	 *	Space for AX.25 and NET/ROM network header
	 */
	skb_reserve(skb, NR_NETWORK_LEN);

	dptr = skb_put(skb, skb_tailroom(skb));

	switch (frametype & 0x0F) {
	case NR_CONNREQ:
		timeout  = nr->t1 / HZ;
		*dptr++  = nr->my_index;
		*dptr++  = nr->my_id;
		*dptr++  = 0;
		*dptr++  = 0;
		*dptr++  = frametype;
		*dptr++  = nr->window;
		memcpy(dptr, &nr->user_addr, AX25_ADDR_LEN);
		dptr[6] &= ~AX25_CBIT;
		dptr[6] &= ~AX25_EBIT;
		dptr[6] |= AX25_SSSID_SPARE;
		dptr    += AX25_ADDR_LEN;
		memcpy(dptr, &nr->source_addr, AX25_ADDR_LEN);
		dptr[6] &= ~AX25_CBIT;
		dptr[6] &= ~AX25_EBIT;
		dptr[6] |= AX25_SSSID_SPARE;
		dptr    += AX25_ADDR_LEN;
		*dptr++  = timeout % 256;
		*dptr++  = timeout / 256;
		break;

	case NR_CONNACK:
		*dptr++ = nr->your_index;
		*dptr++ = nr->your_id;
		*dptr++ = nr->my_index;
		*dptr++ = nr->my_id;
		*dptr++ = frametype;
		*dptr++ = nr->window;
		if (nr->bpqext) *dptr++ = sysctl_netrom_network_ttl_initialiser;
		break;

	case NR_DISCREQ:
	case NR_DISCACK:
		*dptr++ = nr->your_index;
		*dptr++ = nr->your_id;
		*dptr++ = 0;
		*dptr++ = 0;
		*dptr++ = frametype;
		break;

	case NR_INFOACK:
		*dptr++ = nr->your_index;
		*dptr++ = nr->your_id;
		*dptr++ = 0;
		*dptr++ = nr->vr;
		*dptr++ = frametype;
		break;
	}

	nr_transmit_buffer(sk, skb);
}
Beispiel #4
0
/* 
 *  This routine is called when the HDLC layer internally generates a
 *  control frame.
 */
void nr_write_internal(struct sock *sk, int frametype)
{
	struct sk_buff *skb;
	unsigned char  *dptr;
	int len, timeout;

	len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + NR_NETWORK_LEN + NR_TRANSPORT_LEN;
	
	switch (frametype & 0x0F) {
		case NR_CONNREQ:
			len += 17;
			break;
		case NR_CONNACK:
			len += (sk->nr->bpqext) ? 2 : 1;
			break;
		case NR_DISCREQ:
		case NR_DISCACK:
		case NR_INFOACK:
			break;
		default:
			printk(KERN_ERR "nr_write_internal: invalid frame type %d\n", frametype);
			return;
	}
	
	if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
		return;

	/*
	 *	Space for AX.25 and NET/ROM network header
	 */
	skb_reserve(skb, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + NR_NETWORK_LEN);
	
	dptr = skb_put(skb, skb_tailroom(skb));

	switch (frametype & 0x0F) {

		case NR_CONNREQ:
			timeout  = (sk->nr->rtt / PR_SLOWHZ) * 2;
			*dptr++  = sk->nr->my_index;
			*dptr++  = sk->nr->my_id;
			*dptr++  = 0;
			*dptr++  = 0;
			*dptr++  = frametype;
			*dptr++  = sk->window;
			memcpy(dptr, &sk->nr->user_addr, AX25_ADDR_LEN);
			dptr[6] &= ~LAPB_C;
			dptr[6] &= ~LAPB_E;
			dptr[6] |= SSSID_SPARE;
			dptr    += AX25_ADDR_LEN;
			memcpy(dptr, &sk->nr->source_addr, AX25_ADDR_LEN);
			dptr[6] &= ~LAPB_C;
			dptr[6] &= ~LAPB_E;
			dptr[6] |= SSSID_SPARE;
			dptr    += AX25_ADDR_LEN;
			*dptr++  = timeout % 256;
			*dptr++  = timeout / 256;
			break;

		case NR_CONNACK:
			*dptr++ = sk->nr->your_index;
			*dptr++ = sk->nr->your_id;
			*dptr++ = sk->nr->my_index;
			*dptr++ = sk->nr->my_id;
			*dptr++ = frametype;
			*dptr++ = sk->window;
			if (sk->nr->bpqext) *dptr++ = nr_default.ttl;
			break;

		case NR_DISCREQ:
		case NR_DISCACK:
			*dptr++ = sk->nr->your_index;
			*dptr++ = sk->nr->your_id;
			*dptr++ = 0;
			*dptr++ = 0;
			*dptr++ = frametype;
			break;

		case NR_INFOACK:
			*dptr++ = sk->nr->your_index;
			*dptr++ = sk->nr->your_id;
			*dptr++ = 0;
			*dptr++ = sk->nr->vr;
			*dptr++ = frametype;
			break;
	}

	skb->free = 1;

	nr_transmit_buffer(sk, skb);
}