vserver 1.9.3
[linux-2.6.git] / net / ipv4 / tcp_ipv4.c
index 514090f..6886042 100644 (file)
@@ -180,62 +180,6 @@ void tcp_bind_hash(struct sock *sk, struct tcp_bind_bucket *tb,
        tcp_sk(sk)->bind_hash = tb;
 }
 
-/*
-       Return 1 if addr match the socket IP list
-       or the socket is INADDR_ANY
-*/
-static inline int tcp_in_list(struct sock *sk, u32 addr)
-{
-       struct nx_info *nxi = sk->sk_nx_info;
-
-       vxdprintk(VXD_CBIT(net, 2), "tcp_in_list(%p) %p,%p;%lx",
-               sk, nxi, sk->sk_socket,
-               (sk->sk_socket?sk->sk_socket->flags:0));
-
-       if (nxi) {
-               int n = nxi->nbipv4;
-               int i;
-
-               for (i=0; i<n; i++)
-                       if (nxi->ipv4[i] == addr)
-                               return 1;
-       }
-       else if (!tcp_v4_rcv_saddr(sk) || tcp_v4_rcv_saddr(sk) == addr)
-               return 1;
-       return 0;
-}
-       
-/*
-       Check if the addresses in sk1 conflict with those in sk2
-*/
-int tcp_ipv4_addr_conflict(struct sock *sk1, struct sock *sk2)
-{
-       if (sk1 && sk2)
-       vxdprintk(VXD_CBIT(net, 5),
-               "tcp_ipv4_addr_conflict(%p,%p) %p,%p;%lx %p,%p;%lx",
-               sk1, sk2,
-               sk1->sk_nx_info, sk1->sk_socket,
-               (sk1->sk_socket?sk1->sk_socket->flags:0),
-               sk2->sk_nx_info, sk2->sk_socket,
-               (sk2->sk_socket?sk2->sk_socket->flags:0));
-
-       if (tcp_v4_rcv_saddr(sk1)) {
-               /* Bind to one address only */
-               return tcp_in_list (sk2, tcp_v4_rcv_saddr(sk1));
-       } else if (sk1->sk_nx_info) {
-               /* A restricted bind(any) */
-               struct nx_info *nxi = sk1->sk_nx_info;
-               int n = nxi->nbipv4;
-               int i;
-
-               for (i=0; i<n; i++)
-                       if (tcp_in_list (sk2, nxi->ipv4[i]))
-                               return 1;
-       } else  /* A bind(any) do not allow other bind on the same port */
-               return 1;
-       return 0;
-}
-
 static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb)
 {
        struct sock *sk2;
@@ -250,7 +194,8 @@ static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb)
                     sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {
                        if (!reuse || !sk2->sk_reuse ||
                            sk2->sk_state == TCP_LISTEN) {
-                               if (tcp_ipv4_addr_conflict(sk, sk2))
+                               if (nx_addr_conflict(sk->sk_nx_info,
+                                       tcp_v4_rcv_saddr(sk), sk2))
                                        break;
                        }
                }
@@ -459,34 +404,26 @@ void tcp_unhash(struct sock *sk)
                wake_up(&tcp_lhash_wait);
 }
 
+
 /*
-       Check if an address is in the list
-*/
-static inline int tcp_addr_in_list(
-       u32 rcv_saddr,
-       u32 daddr,
-       struct nx_info *nx_info)
-{
-       if (rcv_saddr == daddr)
+ *      Check if a given address matches for a tcp socket
+ *
+ *      nxi:   the socket's nx_info if any
+ *      addr:  to be verified address
+ *      saddr: socket addresses
+ */
+static inline int tcp_addr_match (
+       struct nx_info *nxi,
+       uint32_t addr,
+       uint32_t saddr)
+{
+       if (addr && (saddr == addr))
                return 1;
-       else if (rcv_saddr == 0) {
-               /* Accept any address or check the list */
-               if (!nx_info)
-                       return 1;
-               else {
-                       int n = nx_info->nbipv4;
-                       int i;
-
-                       for (i=0; i<n; i++)
-                               if (nx_info->ipv4[i] == daddr)
-                                       return 1;
-               }
-       }
+       if (!saddr)
+               return addr_in_nx_info(nxi, addr);
        return 0;
 }
 
-
-
 /* Don't inline this cruft.  Here are some nice properties to
  * exploit here.  The BSD API does not allow a listening TCP
  * to specify the remote port nor the remote address for the
@@ -508,7 +445,7 @@ static struct sock *__tcp_v4_lookup_listener(struct hlist_head *head, u32 daddr,
                        __u32 rcv_saddr = inet->rcv_saddr;
 
                        score = (sk->sk_family == PF_INET ? 1 : 0);
-                       if (tcp_addr_in_list(rcv_saddr, daddr, sk->sk_nx_info))
+                       if (tcp_addr_match(sk->sk_nx_info, daddr, rcv_saddr))
                                score+=2;
                        else
                                continue;
@@ -542,7 +479,7 @@ inline struct sock *tcp_v4_lookup_listener(u32 daddr, unsigned short hnum,
 
                if (inet->num == hnum && !sk->sk_node.next &&
                    (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) &&
-                   tcp_addr_in_list(inet->rcv_saddr, daddr, sk->sk_nx_info) &&
+                   tcp_addr_match(sk->sk_nx_info, daddr, inet->rcv_saddr) &&
                    !sk->sk_bound_dev_if)
                        goto sherry_cache;
                sk = __tcp_v4_lookup_listener(head, daddr, hnum, dif);
@@ -1114,11 +1051,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
 
        switch (type) {
        case ICMP_SOURCE_QUENCH:
-               /* This is deprecated, but if someone generated it,
-                * we have no reasons to ignore it.
-                */
-               if (!sock_owned_by_user(sk))
-                       tcp_enter_cwr(tp);
+               /* Just silently ignore these. */
                goto out;
        case ICMP_PARAMETERPROB:
                err = EPROTO;
@@ -2156,7 +2089,7 @@ static int tcp_v4_init_sock(struct sock *sk)
         */
        tp->snd_ssthresh = 0x7fffffff;  /* Infinity */
        tp->snd_cwnd_clamp = ~0;
-       tp->mss_cache = 536;
+       tp->mss_cache_std = tp->mss_cache = 536;
 
        tp->reordering = sysctl_tcp_reordering;
 
@@ -2247,9 +2180,10 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
                while (1) {
                        while (req) {
                                vxdprintk(VXD_CBIT(net, 6),
-                                       "sk,req: %p [#%d] (from %d)",
-                                       req->sk, req->sk->sk_xid, current->xid);
-                               if (!vx_check(req->sk->sk_xid, VX_IDENT|VX_WATCH))
+                                       "sk,req: %p [#%d] (from %d)", req->sk,
+                                       (req->sk)?req->sk->sk_xid:0, current->xid);
+                               if (req->sk &&
+                                       !vx_check(req->sk->sk_xid, VX_IDENT|VX_WATCH))
                                        continue;
                                if (req->class->family == st->family) {
                                        cur = req;
@@ -2265,8 +2199,14 @@ get_req:
                sk        = sk_next(st->syn_wait_sk);
                st->state = TCP_SEQ_STATE_LISTENING;
                read_unlock_bh(&tp->syn_wait_lock);
-       } else
+       } else {
+               tp = tcp_sk(sk);
+               read_lock_bh(&tp->syn_wait_lock);
+               if (tp->listen_opt && tp->listen_opt->qlen)
+                       goto start_req;
+               read_unlock_bh(&tp->syn_wait_lock);
                sk = sk_next(sk);
+       }
 get_sk:
        sk_for_each_from(sk, node) {
                vxdprintk(VXD_CBIT(net, 6), "sk: %p [#%d] (from %d)",
@@ -2280,6 +2220,7 @@ get_sk:
                tp = tcp_sk(sk);
                read_lock_bh(&tp->syn_wait_lock);
                if (tp->listen_opt && tp->listen_opt->qlen) {
+start_req:
                        st->uid         = sock_i_uid(sk);
                        st->syn_wait_sk = sk;
                        st->state       = TCP_SEQ_STATE_OPENREQ;
@@ -2721,6 +2662,7 @@ struct proto tcp_prot = {
        .sysctl_wmem            = sysctl_tcp_wmem,
        .sysctl_rmem            = sysctl_tcp_rmem,
        .max_header             = MAX_TCP_HEADER,
+       .slab_obj_size          = sizeof(struct tcp_sock),
 };