示例#1
0
static int dn_nsp_rx_packet(struct sk_buff *skb)
{
	struct dn_skb_cb *cb = DN_SKB_CB(skb);
	struct sock *sk = NULL;
	unsigned char *ptr = (unsigned char *)skb->data;
	unsigned short reason = NSP_REASON_NL;

	skb->h.raw    = skb->data;
	cb->nsp_flags = *ptr++;

	if (decnet_debug_level & 2)
		printk(KERN_DEBUG "dn_nsp_rx: Message type 0x%02x\n", (int)cb->nsp_flags);

	if (skb->len < 2) 
		goto free_out;

	if (cb->nsp_flags & 0x83) 
		goto free_out;

	/*
	 * Returned packets...
	 * Swap src & dst and look up in the normal way.
	 */
	if (cb->rt_flags & DN_RT_F_RTS) {
		unsigned short tmp = cb->dst_port;
		cb->dst_port = cb->src_port;
		cb->src_port = tmp;
		tmp = cb->dst;
		cb->dst = cb->src;
		cb->src = tmp;
		sk = dn_find_by_skb(skb);
		goto got_it;
	}

	/*
	 * Filter out conninits and useless packet types
	 */
	if ((cb->nsp_flags & 0x0c) == 0x08) {
		switch(cb->nsp_flags & 0x70) {
			case 0x00: /* NOP */
			case 0x70: /* Reserved */
			case 0x50: /* Reserved, Phase II node init */
				goto free_out;
			case 0x10:
			case 0x60:
				sk = dn_find_listener(skb, &reason);
				goto got_it;
		}
	}

	if (skb->len < 3)
		goto free_out;

	/*
	 * Grab the destination address.
	 */
	cb->dst_port = *(unsigned short *)ptr;
	cb->src_port = 0;
	ptr += 2;

	/*
	 * If not a connack, grab the source address too.
	 */
	if (skb->len >= 5) {
		cb->src_port = *(unsigned short *)ptr;
		ptr += 2;
		skb_pull(skb, 5);
	}

	/*
	 * Find the socket to which this skb is destined.
	 */
	sk = dn_find_by_skb(skb);
got_it:
	if (sk != NULL) {
		struct dn_scp *scp = DN_SK(sk);
		int ret;

		/* Reset backoff */
		scp->nsp_rxtshift = 0;

		bh_lock_sock(sk);
		ret = NET_RX_SUCCESS;
		if (decnet_debug_level & 8)
			printk(KERN_DEBUG "NSP: 0x%02x 0x%02x 0x%04x 0x%04x %d\n",
				(int)cb->rt_flags, (int)cb->nsp_flags, 
				(int)cb->src_port, (int)cb->dst_port, 
				(int)sk->lock.users);
		if (sk->lock.users == 0)
			ret = dn_nsp_backlog_rcv(sk, skb);
		else
			sk_add_backlog(sk, skb);
		bh_unlock_sock(sk);
		sock_put(sk);

		return ret;
	}

	return dn_nsp_no_socket(skb, reason);

free_out:
	kfree_skb(skb);
	return NET_RX_DROP;
}
示例#2
0
static int dn_nsp_rx_packet(struct net *net, struct sock *sk2,
			    struct sk_buff *skb)
{
	struct dn_skb_cb *cb = DN_SKB_CB(skb);
	struct sock *sk = NULL;
	unsigned char *ptr = (unsigned char *)skb->data;
	unsigned short reason = NSP_REASON_NL;

	if (!pskb_may_pull(skb, 2))
		goto free_out;

	skb_reset_transport_header(skb);
	cb->nsp_flags = *ptr++;

	if (decnet_debug_level & 2)
		printk(KERN_DEBUG "dn_nsp_rx: Message type 0x%02x\n", (int)cb->nsp_flags);

	if (cb->nsp_flags & 0x83)
		goto free_out;

	/*
	 * Filter out conninits and useless packet types
	 */
	if ((cb->nsp_flags & 0x0c) == 0x08) {
		switch (cb->nsp_flags & 0x70) {
		case 0x00: /* NOP */
		case 0x70: /* Reserved */
		case 0x50: /* Reserved, Phase II node init */
			goto free_out;
		case 0x10:
		case 0x60:
			if (unlikely(cb->rt_flags & DN_RT_F_RTS))
				goto free_out;
			sk = dn_find_listener(skb, &reason);
			goto got_it;
		}
	}

	if (!pskb_may_pull(skb, 3))
		goto free_out;

	/*
	 * Grab the destination address.
	 */
	cb->dst_port = *(__le16 *)ptr;
	cb->src_port = 0;
	ptr += 2;

	/*
	 * If not a connack, grab the source address too.
	 */
	if (pskb_may_pull(skb, 5)) {
		cb->src_port = *(__le16 *)ptr;
		ptr += 2;
		skb_pull(skb, 5);
	}

	/*
	 * Returned packets...
	 * Swap src & dst and look up in the normal way.
	 */
	if (unlikely(cb->rt_flags & DN_RT_F_RTS)) {
		swap(cb->dst_port, cb->src_port);
		swap(cb->dst, cb->src);
	}

	/*
	 * Find the socket to which this skb is destined.
	 */
	sk = dn_find_by_skb(skb);
got_it:
	if (sk != NULL) {
		struct dn_scp *scp = DN_SK(sk);

		/* Reset backoff */
		scp->nsp_rxtshift = 0;

		/*
		 * We linearize everything except data segments here.
		 */
		if (cb->nsp_flags & ~0x60) {
			if (unlikely(skb_linearize(skb)))
				goto free_out;
		}

		return sk_receive_skb(sk, skb, 0);
	}

	return dn_nsp_no_socket(skb, reason);

free_out:
	kfree_skb(skb);
	return NET_RX_DROP;
}
示例#3
0
static int dn_nsp_rx_packet(struct sk_buff *skb)
{
	struct dn_skb_cb *cb = DN_SKB_CB(skb);
	struct sock *sk = NULL;
	unsigned char *ptr = (unsigned char *)skb->data;
	unsigned short reason = NSP_REASON_NL;

	if (!pskb_may_pull(skb, 2))
		goto free_out;

	skb_reset_transport_header(skb);
	cb->nsp_flags = *ptr++;

	if (decnet_debug_level & 2)
		printk(KERN_DEBUG "dn_nsp_rx: Message type 0x%02x\n", (int)cb->nsp_flags);

	if (cb->nsp_flags & 0x83)
		goto free_out;

	
	if ((cb->nsp_flags & 0x0c) == 0x08) {
		switch(cb->nsp_flags & 0x70) {
			case 0x00: 
			case 0x70: 
			case 0x50: 
				goto free_out;
			case 0x10:
			case 0x60:
				if (unlikely(cb->rt_flags & DN_RT_F_RTS))
					goto free_out;
				sk = dn_find_listener(skb, &reason);
				goto got_it;
		}
	}

	if (!pskb_may_pull(skb, 3))
		goto free_out;

	
	cb->dst_port = *(__le16 *)ptr;
	cb->src_port = 0;
	ptr += 2;

	
	if (pskb_may_pull(skb, 5)) {
		cb->src_port = *(__le16 *)ptr;
		ptr += 2;
		skb_pull(skb, 5);
	}

	
	if (unlikely(cb->rt_flags & DN_RT_F_RTS)) {
		__le16 tmp = cb->dst_port;
		cb->dst_port = cb->src_port;
		cb->src_port = tmp;
		tmp = cb->dst;
		cb->dst = cb->src;
		cb->src = tmp;
	}

	
	sk = dn_find_by_skb(skb);
got_it:
	if (sk != NULL) {
		struct dn_scp *scp = DN_SK(sk);

		
		scp->nsp_rxtshift = 0;

		
		if (cb->nsp_flags & ~0x60) {
			if (unlikely(skb_linearize(skb)))
				goto free_out;
		}

		return sk_receive_skb(sk, skb, 0);
	}

	return dn_nsp_no_socket(skb, reason);

free_out:
	kfree_skb(skb);
	return NET_RX_DROP;
}