aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-06-13 23:52:39 -0400
committerDavid S. Miller <davem@davemloft.net>2008-06-13 23:52:39 -0400
commit4ae127d1b6c71f9240dd4245f240e6dd8fc98014 (patch)
treeb7aa27b3e0c655f4613fe2146cb57d7f69e421f6 /net/ipv4
parent875ec4333b99144e2589e900a0bcd2c25c757b27 (diff)
parent7775c9753b94fe429dc4323360d6502c95e0dd6e (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts: drivers/net/smc911x.c
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/fib_semantics.c5
-rw-r--r--net/ipv4/inet_connection_sock.c11
-rw-r--r--net/ipv4/netfilter/nf_nat_snmp_basic.c14
-rw-r--r--net/ipv4/syncookies.c3
-rw-r--r--net/ipv4/tcp.c18
-rw-r--r--net/ipv4/tcp_input.c45
-rw-r--r--net/ipv4/tcp_ipv4.c10
-rw-r--r--net/ipv4/tcp_minisocks.c32
-rw-r--r--net/ipv4/tcp_timer.c5
9 files changed, 51 insertions, 92 deletions
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 9335eba683c3..ded2ae34eab1 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -958,7 +958,10 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
958 rtm->rtm_dst_len = dst_len; 958 rtm->rtm_dst_len = dst_len;
959 rtm->rtm_src_len = 0; 959 rtm->rtm_src_len = 0;
960 rtm->rtm_tos = tos; 960 rtm->rtm_tos = tos;
961 rtm->rtm_table = tb_id; 961 if (tb_id < 256)
962 rtm->rtm_table = tb_id;
963 else
964 rtm->rtm_table = RT_TABLE_COMPAT;
962 NLA_PUT_U32(skb, RTA_TABLE, tb_id); 965 NLA_PUT_U32(skb, RTA_TABLE, tb_id);
963 rtm->rtm_type = type; 966 rtm->rtm_type = type;
964 rtm->rtm_flags = fi->fib_flags; 967 rtm->rtm_flags = fi->fib_flags;
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 828ea211ff21..045e799d3e1d 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -419,7 +419,8 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,
419 struct inet_connection_sock *icsk = inet_csk(parent); 419 struct inet_connection_sock *icsk = inet_csk(parent);
420 struct request_sock_queue *queue = &icsk->icsk_accept_queue; 420 struct request_sock_queue *queue = &icsk->icsk_accept_queue;
421 struct listen_sock *lopt = queue->listen_opt; 421 struct listen_sock *lopt = queue->listen_opt;
422 int thresh = icsk->icsk_syn_retries ? : sysctl_tcp_synack_retries; 422 int max_retries = icsk->icsk_syn_retries ? : sysctl_tcp_synack_retries;
423 int thresh = max_retries;
423 unsigned long now = jiffies; 424 unsigned long now = jiffies;
424 struct request_sock **reqp, *req; 425 struct request_sock **reqp, *req;
425 int i, budget; 426 int i, budget;
@@ -455,6 +456,9 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,
455 } 456 }
456 } 457 }
457 458
459 if (queue->rskq_defer_accept)
460 max_retries = queue->rskq_defer_accept;
461
458 budget = 2 * (lopt->nr_table_entries / (timeout / interval)); 462 budget = 2 * (lopt->nr_table_entries / (timeout / interval));
459 i = lopt->clock_hand; 463 i = lopt->clock_hand;
460 464
@@ -462,8 +466,9 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,
462 reqp=&lopt->syn_table[i]; 466 reqp=&lopt->syn_table[i];
463 while ((req = *reqp) != NULL) { 467 while ((req = *reqp) != NULL) {
464 if (time_after_eq(now, req->expires)) { 468 if (time_after_eq(now, req->expires)) {
465 if (req->retrans < thresh && 469 if ((req->retrans < (inet_rsk(req)->acked ? max_retries : thresh)) &&
466 !req->rsk_ops->rtx_syn_ack(parent, req)) { 470 (inet_rsk(req)->acked ||
471 !req->rsk_ops->rtx_syn_ack(parent, req))) {
467 unsigned long timeo; 472 unsigned long timeo;
468 473
469 if (req->retrans++ == 0) 474 if (req->retrans++ == 0)
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
index 5daefad3d193..7750c97fde7b 100644
--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
@@ -232,6 +232,11 @@ static unsigned char asn1_length_decode(struct asn1_ctx *ctx,
232 } 232 }
233 } 233 }
234 } 234 }
235
236 /* don't trust len bigger than ctx buffer */
237 if (*len > ctx->end - ctx->pointer)
238 return 0;
239
235 return 1; 240 return 1;
236} 241}
237 242
@@ -250,6 +255,10 @@ static unsigned char asn1_header_decode(struct asn1_ctx *ctx,
250 if (!asn1_length_decode(ctx, &def, &len)) 255 if (!asn1_length_decode(ctx, &def, &len))
251 return 0; 256 return 0;
252 257
258 /* primitive shall be definite, indefinite shall be constructed */
259 if (*con == ASN1_PRI && !def)
260 return 0;
261
253 if (def) 262 if (def)
254 *eoc = ctx->pointer + len; 263 *eoc = ctx->pointer + len;
255 else 264 else
@@ -434,6 +443,11 @@ static unsigned char asn1_oid_decode(struct asn1_ctx *ctx,
434 unsigned long *optr; 443 unsigned long *optr;
435 444
436 size = eoc - ctx->pointer + 1; 445 size = eoc - ctx->pointer + 1;
446
447 /* first subid actually encodes first two subids */
448 if (size < 2 || size > ULONG_MAX/sizeof(unsigned long))
449 return 0;
450
437 *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC); 451 *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
438 if (*oid == NULL) { 452 if (*oid == NULL) {
439 if (net_ratelimit()) 453 if (net_ratelimit())
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 6317d3c8dc0d..fdde2ae07e24 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -283,7 +283,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
283 cookie_check_timestamp(&tcp_opt); 283 cookie_check_timestamp(&tcp_opt);
284 284
285 ret = NULL; 285 ret = NULL;
286 req = reqsk_alloc(&tcp_request_sock_ops); /* for safety */ 286 req = inet_reqsk_alloc(&tcp_request_sock_ops); /* for safety */
287 if (!req) 287 if (!req)
288 goto out; 288 goto out;
289 289
@@ -299,7 +299,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
299 ireq->rmt_port = th->source; 299 ireq->rmt_port = th->source;
300 ireq->loc_addr = ip_hdr(skb)->daddr; 300 ireq->loc_addr = ip_hdr(skb)->daddr;
301 ireq->rmt_addr = ip_hdr(skb)->saddr; 301 ireq->rmt_addr = ip_hdr(skb)->saddr;
302 ireq->opt = NULL;
303 ireq->snd_wscale = tcp_opt.snd_wscale; 302 ireq->snd_wscale = tcp_opt.snd_wscale;
304 ireq->rcv_wscale = tcp_opt.rcv_wscale; 303 ireq->rcv_wscale = tcp_opt.rcv_wscale;
305 ireq->sack_ok = tcp_opt.sack_ok; 304 ireq->sack_ok = tcp_opt.sack_ok;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 6d30ca559c64..cf0850c068f5 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2110,12 +2110,15 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
2110 break; 2110 break;
2111 2111
2112 case TCP_DEFER_ACCEPT: 2112 case TCP_DEFER_ACCEPT:
2113 if (val < 0) { 2113 icsk->icsk_accept_queue.rskq_defer_accept = 0;
2114 err = -EINVAL; 2114 if (val > 0) {
2115 } else { 2115 /* Translate value in seconds to number of
2116 if (val > MAX_TCP_ACCEPT_DEFERRED) 2116 * retransmits */
2117 val = MAX_TCP_ACCEPT_DEFERRED; 2117 while (icsk->icsk_accept_queue.rskq_defer_accept < 32 &&
2118 icsk->icsk_accept_queue.rskq_defer_accept = val; 2118 val > ((TCP_TIMEOUT_INIT / HZ) <<
2119 icsk->icsk_accept_queue.rskq_defer_accept))
2120 icsk->icsk_accept_queue.rskq_defer_accept++;
2121 icsk->icsk_accept_queue.rskq_defer_accept++;
2119 } 2122 }
2120 break; 2123 break;
2121 2124
@@ -2297,7 +2300,8 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
2297 val = (val ? : sysctl_tcp_fin_timeout) / HZ; 2300 val = (val ? : sysctl_tcp_fin_timeout) / HZ;
2298 break; 2301 break;
2299 case TCP_DEFER_ACCEPT: 2302 case TCP_DEFER_ACCEPT:
2300 val = icsk->icsk_accept_queue.rskq_defer_accept; 2303 val = !icsk->icsk_accept_queue.rskq_defer_accept ? 0 :
2304 ((TCP_TIMEOUT_INIT / HZ) << (icsk->icsk_accept_queue.rskq_defer_accept - 1));
2301 break; 2305 break;
2302 case TCP_WINDOW_CLAMP: 2306 case TCP_WINDOW_CLAMP:
2303 val = tp->window_clamp; 2307 val = tp->window_clamp;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index bc7f62e2792b..de30e70ff256 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4576,49 +4576,6 @@ static void tcp_urg(struct sock *sk, struct sk_buff *skb, struct tcphdr *th)
4576 } 4576 }
4577} 4577}
4578 4578
4579static int tcp_defer_accept_check(struct sock *sk)
4580{
4581 struct tcp_sock *tp = tcp_sk(sk);
4582
4583 if (tp->defer_tcp_accept.request) {
4584 int queued_data = tp->rcv_nxt - tp->copied_seq;
4585 int hasfin = !skb_queue_empty(&sk->sk_receive_queue) ?
4586 tcp_hdr((struct sk_buff *)
4587 sk->sk_receive_queue.prev)->fin : 0;
4588
4589 if (queued_data && hasfin)
4590 queued_data--;
4591
4592 if (queued_data &&
4593 tp->defer_tcp_accept.listen_sk->sk_state == TCP_LISTEN) {
4594 if (sock_flag(sk, SOCK_KEEPOPEN)) {
4595 inet_csk_reset_keepalive_timer(sk,
4596 keepalive_time_when(tp));
4597 } else {
4598 inet_csk_delete_keepalive_timer(sk);
4599 }
4600
4601 inet_csk_reqsk_queue_add(
4602 tp->defer_tcp_accept.listen_sk,
4603 tp->defer_tcp_accept.request,
4604 sk);
4605
4606 tp->defer_tcp_accept.listen_sk->sk_data_ready(
4607 tp->defer_tcp_accept.listen_sk, 0);
4608
4609 sock_put(tp->defer_tcp_accept.listen_sk);
4610 sock_put(sk);
4611 tp->defer_tcp_accept.listen_sk = NULL;
4612 tp->defer_tcp_accept.request = NULL;
4613 } else if (hasfin ||
4614 tp->defer_tcp_accept.listen_sk->sk_state != TCP_LISTEN) {
4615 tcp_reset(sk);
4616 return -1;
4617 }
4618 }
4619 return 0;
4620}
4621
4622static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen) 4579static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen)
4623{ 4580{
4624 struct tcp_sock *tp = tcp_sk(sk); 4581 struct tcp_sock *tp = tcp_sk(sk);
@@ -4979,8 +4936,6 @@ step5:
4979 4936
4980 tcp_data_snd_check(sk); 4937 tcp_data_snd_check(sk);
4981 tcp_ack_snd_check(sk); 4938 tcp_ack_snd_check(sk);
4982
4983 tcp_defer_accept_check(sk);
4984 return 0; 4939 return 0;
4985 4940
4986csum_error: 4941csum_error:
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 9088d709725e..b219a7a7cd08 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1185,7 +1185,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
1185 if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) 1185 if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
1186 goto drop; 1186 goto drop;
1187 1187
1188 req = reqsk_alloc(&tcp_request_sock_ops); 1188 req = inet_reqsk_alloc(&tcp_request_sock_ops);
1189 if (!req) 1189 if (!req)
1190 goto drop; 1190 goto drop;
1191 1191
@@ -1818,14 +1818,6 @@ int tcp_v4_destroy_sock(struct sock *sk)
1818 sk->sk_sndmsg_page = NULL; 1818 sk->sk_sndmsg_page = NULL;
1819 } 1819 }
1820 1820
1821 if (tp->defer_tcp_accept.request) {
1822 reqsk_free(tp->defer_tcp_accept.request);
1823 sock_put(tp->defer_tcp_accept.listen_sk);
1824 sock_put(sk);
1825 tp->defer_tcp_accept.listen_sk = NULL;
1826 tp->defer_tcp_accept.request = NULL;
1827 }
1828
1829 atomic_dec(&tcp_sockets_allocated); 1821 atomic_dec(&tcp_sockets_allocated);
1830 1822
1831 return 0; 1823 return 0;
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 1276cab85e3e..ea68a478fad6 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -569,8 +569,10 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
569 does sequence test, SYN is truncated, and thus we consider 569 does sequence test, SYN is truncated, and thus we consider
570 it a bare ACK. 570 it a bare ACK.
571 571
572 Both ends (listening sockets) accept the new incoming 572 If icsk->icsk_accept_queue.rskq_defer_accept, we silently drop this
573 connection and try to talk to each other. 8-) 573 bare ACK. Otherwise, we create an established connection. Both
574 ends (listening sockets) accept the new incoming connection and try
575 to talk to each other. 8-)
574 576
575 Note: This case is both harmless, and rare. Possibility is about the 577 Note: This case is both harmless, and rare. Possibility is about the
576 same as us discovering intelligent life on another plant tomorrow. 578 same as us discovering intelligent life on another plant tomorrow.
@@ -638,6 +640,13 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
638 if (!(flg & TCP_FLAG_ACK)) 640 if (!(flg & TCP_FLAG_ACK))
639 return NULL; 641 return NULL;
640 642
643 /* If TCP_DEFER_ACCEPT is set, drop bare ACK. */
644 if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
645 TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
646 inet_rsk(req)->acked = 1;
647 return NULL;
648 }
649
641 /* OK, ACK is valid, create big socket and 650 /* OK, ACK is valid, create big socket and
642 * feed this segment to it. It will repeat all 651 * feed this segment to it. It will repeat all
643 * the tests. THIS SEGMENT MUST MOVE SOCKET TO 652 * the tests. THIS SEGMENT MUST MOVE SOCKET TO
@@ -676,24 +685,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
676 inet_csk_reqsk_queue_unlink(sk, req, prev); 685 inet_csk_reqsk_queue_unlink(sk, req, prev);
677 inet_csk_reqsk_queue_removed(sk, req); 686 inet_csk_reqsk_queue_removed(sk, req);
678 687
679 if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && 688 inet_csk_reqsk_queue_add(sk, req, child);
680 TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
681
682 /* the accept queue handling is done is est recv slow
683 * path so lets make sure to start there
684 */
685 tcp_sk(child)->pred_flags = 0;
686 sock_hold(sk);
687 sock_hold(child);
688 tcp_sk(child)->defer_tcp_accept.listen_sk = sk;
689 tcp_sk(child)->defer_tcp_accept.request = req;
690
691 inet_csk_reset_keepalive_timer(child,
692 inet_csk(sk)->icsk_accept_queue.rskq_defer_accept * HZ);
693 } else {
694 inet_csk_reqsk_queue_add(sk, req, child);
695 }
696
697 return child; 689 return child;
698 690
699 listen_overflow: 691 listen_overflow:
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index e77e7ae0bf2c..3e358cbb1247 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -487,11 +487,6 @@ static void tcp_keepalive_timer (unsigned long data)
487 goto death; 487 goto death;
488 } 488 }
489 489
490 if (tp->defer_tcp_accept.request && sk->sk_state == TCP_ESTABLISHED) {
491 tcp_send_active_reset(sk, GFP_ATOMIC);
492 goto death;
493 }
494
495 if (!sock_flag(sk, SOCK_KEEPOPEN) || sk->sk_state == TCP_CLOSE) 490 if (!sock_flag(sk, SOCK_KEEPOPEN) || sk->sk_state == TCP_CLOSE)
496 goto out; 491 goto out;
497 492