X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv4%2Ftcp_ipv4.c;h=68860426e0377c2b2b3dfa16a18825e8df7d0808;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=514090ffa0a04e4c66ce46dc4747ea6e94cc99cc;hpb=a2c21200f1c81b08cb55e417b68150bba439b646;p=linux-2.6.git diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 514090ffa..68860426e 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -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; iipv4[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; iipv4[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; iipv4[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), };