forked from mirrors/linux
		
	[SCTP] Support SO_BINDTODEVICE socket option on incoming packets.
Signed-off-by: Neil Horman <nhorman@redhat.com> Signed-off-by: Sridhar Samudrala <sri@us.ibm.com Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									4243cac1e7
								
							
						
					
					
						commit
						0fd9a65a76
					
				
					 1 changed files with 34 additions and 15 deletions
				
			
		| 
						 | 
				
			
			@ -178,6 +178,37 @@ int sctp_rcv(struct sk_buff *skb)
 | 
			
		|||
 | 
			
		||||
	asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
 | 
			
		||||
 | 
			
		||||
	if (!asoc)
 | 
			
		||||
		ep = __sctp_rcv_lookup_endpoint(&dest);
 | 
			
		||||
 | 
			
		||||
	/* Retrieve the common input handling substructure. */
 | 
			
		||||
	rcvr = asoc ? &asoc->base : &ep->base;
 | 
			
		||||
	sk = rcvr->sk;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If a frame arrives on an interface and the receiving socket is
 | 
			
		||||
	 * bound to another interface, via SO_BINDTODEVICE, treat it as OOTB
 | 
			
		||||
	 */
 | 
			
		||||
	if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb)))
 | 
			
		||||
	{
 | 
			
		||||
		sock_put(sk);
 | 
			
		||||
		if (asoc) {
 | 
			
		||||
			sctp_association_put(asoc);
 | 
			
		||||
			asoc = NULL;
 | 
			
		||||
		} else {
 | 
			
		||||
			sctp_endpoint_put(ep);
 | 
			
		||||
			ep = NULL;
 | 
			
		||||
		}
 | 
			
		||||
		sk = sctp_get_ctl_sock();
 | 
			
		||||
		ep = sctp_sk(sk)->ep;
 | 
			
		||||
		sctp_endpoint_hold(ep);
 | 
			
		||||
		sock_hold(sk);
 | 
			
		||||
		rcvr = &ep->base;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
 | 
			
		||||
		goto discard_release;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * RFC 2960, 8.4 - Handle "Out of the blue" Packets.
 | 
			
		||||
	 * An SCTP packet is called an "out of the blue" (OOTB)
 | 
			
		||||
| 
						 | 
				
			
			@ -187,22 +218,12 @@ int sctp_rcv(struct sk_buff *skb)
 | 
			
		|||
	 * packet belongs.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!asoc) {
 | 
			
		||||
		ep = __sctp_rcv_lookup_endpoint(&dest);
 | 
			
		||||
		if (sctp_rcv_ootb(skb)) {
 | 
			
		||||
			SCTP_INC_STATS_BH(SCTP_MIB_OUTOFBLUES);
 | 
			
		||||
			goto discard_release;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Retrieve the common input handling substructure. */
 | 
			
		||||
	rcvr = asoc ? &asoc->base : &ep->base;
 | 
			
		||||
	sk = rcvr->sk;
 | 
			
		||||
 | 
			
		||||
	if ((sk) && (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)) {
 | 
			
		||||
		goto discard_release;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	/* SCTP seems to always need a timestamp right now (FIXME) */
 | 
			
		||||
	if (skb->stamp.tv_sec == 0) {
 | 
			
		||||
		do_gettimeofday(&skb->stamp);
 | 
			
		||||
| 
						 | 
				
			
			@ -265,13 +286,11 @@ int sctp_rcv(struct sk_buff *skb)
 | 
			
		|||
 | 
			
		||||
discard_release:
 | 
			
		||||
	/* Release any structures we may be holding. */
 | 
			
		||||
	if (asoc) {
 | 
			
		||||
		sock_put(asoc->base.sk);
 | 
			
		||||
	sock_put(sk);
 | 
			
		||||
	if (asoc)
 | 
			
		||||
		sctp_association_put(asoc);
 | 
			
		||||
	} else {
 | 
			
		||||
		sock_put(ep->base.sk);
 | 
			
		||||
	else
 | 
			
		||||
		sctp_endpoint_put(ep);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	goto discard_it;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue