diff options
| author | David S. Miller <davem@nuts.ninka.net> | 2002-07-15 23:46:58 -0700 |
|---|---|---|
| committer | David S. Miller <davem@nuts.ninka.net> | 2002-07-15 23:46:58 -0700 |
| commit | bf54f8a23402f313fc1ea3845d77811b688ccc21 (patch) | |
| tree | ab88f6b2836e96ad89759028c371bea1880404cc | |
| parent | 7fde4915a17dec953900e02252a013abcd37cdab (diff) | |
| parent | 33185cc3f558ae2a430f338d801f499eaeb3c6d2 (diff) | |
Merge master.kernel.org:/home/acme/BK/tcpv6-shared-port/
into nuts.ninka.net:/home/davem/src/BK/net-2.5
| -rw-r--r-- | include/net/tcp.h | 3 | ||||
| -rw-r--r-- | net/ipv4/tcp_ipv4.c | 4 | ||||
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 93 | ||||
| -rw-r--r-- | net/netsyms.c | 1 |
4 files changed, 49 insertions, 52 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h index ae3b35eb282e..07102180d2fa 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -153,6 +153,9 @@ static __inline__ int tcp_bhashfn(__u16 lport) return (lport & (tcp_bhash_size - 1)); } +extern void tcp_bind_hash(struct sock *sk, struct tcp_bind_bucket *tb, + unsigned short snum); + /* This is a TIME_WAIT bucket. It works around the memory consumption * problems of sockets in such a state on heavily loaded servers, but * without violating the protocol specification. diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 53c06caf141f..b3065b9707a0 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -158,8 +158,8 @@ __inline__ void tcp_inherit_port(struct sock *sk, struct sock *child) local_bh_enable(); } -static inline void tcp_bind_hash(struct sock *sk, struct tcp_bind_bucket *tb, - unsigned short snum) +void tcp_bind_hash(struct sock *sk, struct tcp_bind_bucket *tb, + unsigned short snum) { inet_sk(sk)->num = snum; if ((sk->bind_next = tb->owners) != NULL) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 64cb4aa69bd2..897d106fbd34 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -85,6 +85,37 @@ static __inline__ int tcp_v6_sk_hashfn(struct sock *sk) return tcp_v6_hashfn(laddr, lport, faddr, fport); } +static inline int ipv6_rcv_saddr_equal(struct sock *sk, struct sock *sk2) +{ + struct ipv6_pinfo *np = inet6_sk(sk); + int addr_type = ipv6_addr_type(&np->rcv_saddr); + + return !inet_sk(sk2)->rcv_saddr || addr_type == IPV6_ADDR_ANY || + (sk2->family == AF_INET6 && + !ipv6_addr_cmp(&np->rcv_saddr, + sk2->state != TCP_TIME_WAIT ? + &inet6_sk(sk2)->rcv_saddr : + &((struct tcp_tw_bucket *)sk)->v6_rcv_saddr)) || + (addr_type == IPV6_ADDR_MAPPED && sk2->family == AF_INET && + inet_sk(sk)->rcv_saddr == inet_sk(sk2)->rcv_saddr); +} + +static inline int tcp_v6_bind_conflict(struct sock *sk, + struct tcp_bind_bucket *tb) +{ + struct sock *sk2 = tb->owners; + + /* We must walk the whole port owner list in this case. -DaveM */ + for (; sk2; sk2 = sk2->bind_next) + if (sk != sk2 && sk->bound_dev_if == sk2->bound_dev_if && + (!sk->reuse || !sk2->reuse || + sk2->state == TCP_LISTEN) && + ipv6_rcv_saddr_equal(sk, sk2)) + break; + + return sk2 != NULL; +} + /* Grrr, addr_type already calculated by caller, but I don't want * to add some silly "cookie" argument to this method just for that. * But it doesn't matter, the recalculation is in the rarest path @@ -139,44 +170,15 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum) if (tb->fastreuse > 0 && sk->reuse != 0 && sk->state != TCP_LISTEN) { goto success; } else { - struct ipv6_pinfo *np = inet6_sk(sk); - struct sock *sk2 = tb->owners; - int sk_reuse = sk->reuse; - int addr_type = ipv6_addr_type(&np->rcv_saddr); - - /* We must walk the whole port owner list in this case. -DaveM */ - for( ; sk2 != NULL; sk2 = sk2->bind_next) { - struct ipv6_pinfo *np2 = inet6_sk(sk2); - - if (sk != sk2 && - sk->bound_dev_if == sk2->bound_dev_if) { - if (!sk_reuse || - !sk2->reuse || - sk2->state == TCP_LISTEN) { - /* NOTE: IPv6 tw bucket have different format */ - if (!inet_sk(sk2)->rcv_saddr || - addr_type == IPV6_ADDR_ANY || - !ipv6_addr_cmp(&np->rcv_saddr, - sk2->state != TCP_TIME_WAIT ? - &np2->rcv_saddr : - &((struct tcp_tw_bucket*)sk)->v6_rcv_saddr) || - (addr_type==IPV6_ADDR_MAPPED && sk2->family==AF_INET && - inet_sk(sk)->rcv_saddr == - inet_sk(sk2)->rcv_saddr)) - break; - } - } - } - /* If we found a conflict, fail. */ ret = 1; - if (sk2 != NULL) + if (tcp_v6_bind_conflict(sk, tb)) goto fail_unlock; } } ret = 1; if (tb == NULL && (tb = tcp_bucket_create(head, snum)) == NULL) - goto fail_unlock; + goto fail_unlock; if (tb->owners == NULL) { if (sk->reuse && sk->state != TCP_LISTEN) tb->fastreuse = 1; @@ -187,16 +189,9 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum) tb->fastreuse = 0; success: - inet_sk(sk)->num = snum; - if (sk->prev == NULL) { - if ((sk->bind_next = tb->owners) != NULL) - tb->owners->bind_pprev = &sk->bind_next; - tb->owners = sk; - sk->bind_pprev = &tb->owners; - sk->prev = (struct sock *) tb; - } else { - BUG_TRAP(sk->prev == (struct sock *) tb); - } + if (!sk->prev) + tcp_bind_hash(sk, tb, snum); + BUG_TRAP(sk->prev == (struct sock *)tb); ret = 0; fail_unlock: @@ -413,7 +408,7 @@ static __inline__ u16 tcp_v6_check(struct tcphdr *th, int len, static __u32 tcp_v6_init_sequence(struct sock *sk, struct sk_buff *skb) { - if (skb->protocol == __constant_htons(ETH_P_IPV6)) { + if (skb->protocol == htons(ETH_P_IPV6)) { return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32, skb->nh.ipv6h->saddr.s6_addr32, skb->h.th->dest, @@ -1051,10 +1046,8 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 if (ts) { u32 *ptr = (u32*)(t1 + 1); - *ptr++ = __constant_htonl((TCPOPT_NOP << 24) | - (TCPOPT_NOP << 16) | - (TCPOPT_TIMESTAMP << 8) | - TCPOLEN_TIMESTAMP); + *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | + (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); *ptr++ = htonl(tcp_time_stamp); *ptr = htonl(ts); } @@ -1166,7 +1159,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) struct open_request *req = NULL; __u32 isn = TCP_SKB_CB(skb)->when; - if (skb->protocol == __constant_htons(ETH_P_IP)) + if (skb->protocol == htons(ETH_P_IP)) return tcp_v4_conn_request(sk, skb); /* FIXME: do the same check for anycast */ @@ -1247,7 +1240,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, struct sock *newsk; struct ipv6_txoptions *opt; - if (skb->protocol == __constant_htons(ETH_P_IP)) { + if (skb->protocol == htons(ETH_P_IP)) { /* * v6 mapped */ @@ -1463,7 +1456,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) tcp_v6_hnd_req and tcp_v6_send_reset(). --ANK */ - if (skb->protocol == __constant_htons(ETH_P_IP)) + if (skb->protocol == htons(ETH_P_IP)) return tcp_v4_do_rcv(sk, skb); #ifdef CONFIG_FILTER @@ -1784,7 +1777,7 @@ static void v6_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr) struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) uaddr; sin6->sin6_family = AF_INET6; - memcpy(&sin6->sin6_addr, &np->daddr, sizeof(struct in6_addr)); + ipv6_addr_copy(&sin6->sin6_addr, &np->daddr); sin6->sin6_port = inet_sk(sk)->dport; /* We do not store received flowlabel for TCP */ sin6->sin6_flowinfo = 0; diff --git a/net/netsyms.c b/net/netsyms.c index c75c1bd1c0d4..260cc9309b68 100644 --- a/net/netsyms.c +++ b/net/netsyms.c @@ -320,6 +320,7 @@ EXPORT_SYMBOL(udp_ioctl); EXPORT_SYMBOL(udp_connect); EXPORT_SYMBOL(udp_disconnect); EXPORT_SYMBOL(udp_sendmsg); +EXPORT_SYMBOL(tcp_bind_hash); EXPORT_SYMBOL(tcp_close); EXPORT_SYMBOL(tcp_disconnect); EXPORT_SYMBOL(tcp_accept); |
