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; }
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; }
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; }