diff options
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 713 |
1 files changed, 647 insertions, 66 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 22ef8bd26620..a1222d6968c4 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -78,6 +78,9 @@ | |||
78 | #include <linux/proc_fs.h> | 78 | #include <linux/proc_fs.h> |
79 | #include <linux/seq_file.h> | 79 | #include <linux/seq_file.h> |
80 | 80 | ||
81 | #include <linux/crypto.h> | ||
82 | #include <linux/scatterlist.h> | ||
83 | |||
81 | int sysctl_tcp_tw_reuse __read_mostly; | 84 | int sysctl_tcp_tw_reuse __read_mostly; |
82 | int sysctl_tcp_low_latency __read_mostly; | 85 | int sysctl_tcp_low_latency __read_mostly; |
83 | 86 | ||
@@ -89,10 +92,19 @@ static struct socket *tcp_socket; | |||
89 | 92 | ||
90 | void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb); | 93 | void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb); |
91 | 94 | ||
95 | #ifdef CONFIG_TCP_MD5SIG | ||
96 | static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, | ||
97 | __be32 addr); | ||
98 | static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | ||
99 | __be32 saddr, __be32 daddr, | ||
100 | struct tcphdr *th, int protocol, | ||
101 | int tcplen); | ||
102 | #endif | ||
103 | |||
92 | struct inet_hashinfo __cacheline_aligned tcp_hashinfo = { | 104 | struct inet_hashinfo __cacheline_aligned tcp_hashinfo = { |
93 | .lhash_lock = __RW_LOCK_UNLOCKED(tcp_hashinfo.lhash_lock), | 105 | .lhash_lock = __RW_LOCK_UNLOCKED(tcp_hashinfo.lhash_lock), |
94 | .lhash_users = ATOMIC_INIT(0), | 106 | .lhash_users = ATOMIC_INIT(0), |
95 | .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait), | 107 | .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait), |
96 | }; | 108 | }; |
97 | 109 | ||
98 | static int tcp_v4_get_port(struct sock *sk, unsigned short snum) | 110 | static int tcp_v4_get_port(struct sock *sk, unsigned short snum) |
@@ -111,7 +123,7 @@ void tcp_unhash(struct sock *sk) | |||
111 | inet_unhash(&tcp_hashinfo, sk); | 123 | inet_unhash(&tcp_hashinfo, sk); |
112 | } | 124 | } |
113 | 125 | ||
114 | static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb) | 126 | static inline __u32 tcp_v4_init_sequence(struct sk_buff *skb) |
115 | { | 127 | { |
116 | return secure_tcp_sequence_number(skb->nh.iph->daddr, | 128 | return secure_tcp_sequence_number(skb->nh.iph->daddr, |
117 | skb->nh.iph->saddr, | 129 | skb->nh.iph->saddr, |
@@ -205,13 +217,14 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
205 | if (tcp_death_row.sysctl_tw_recycle && | 217 | if (tcp_death_row.sysctl_tw_recycle && |
206 | !tp->rx_opt.ts_recent_stamp && rt->rt_dst == daddr) { | 218 | !tp->rx_opt.ts_recent_stamp && rt->rt_dst == daddr) { |
207 | struct inet_peer *peer = rt_get_peer(rt); | 219 | struct inet_peer *peer = rt_get_peer(rt); |
208 | 220 | /* | |
209 | /* VJ's idea. We save last timestamp seen from | 221 | * VJ's idea. We save last timestamp seen from |
210 | * the destination in peer table, when entering state TIME-WAIT | 222 | * the destination in peer table, when entering state |
211 | * and initialize rx_opt.ts_recent from it, when trying new connection. | 223 | * TIME-WAIT * and initialize rx_opt.ts_recent from it, |
224 | * when trying new connection. | ||
212 | */ | 225 | */ |
213 | 226 | if (peer != NULL && | |
214 | if (peer && peer->tcp_ts_stamp + TCP_PAWS_MSL >= xtime.tv_sec) { | 227 | peer->tcp_ts_stamp + TCP_PAWS_MSL >= xtime.tv_sec) { |
215 | tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp; | 228 | tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp; |
216 | tp->rx_opt.ts_recent = peer->tcp_ts; | 229 | tp->rx_opt.ts_recent = peer->tcp_ts; |
217 | } | 230 | } |
@@ -236,7 +249,8 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
236 | if (err) | 249 | if (err) |
237 | goto failure; | 250 | goto failure; |
238 | 251 | ||
239 | err = ip_route_newports(&rt, IPPROTO_TCP, inet->sport, inet->dport, sk); | 252 | err = ip_route_newports(&rt, IPPROTO_TCP, |
253 | inet->sport, inet->dport, sk); | ||
240 | if (err) | 254 | if (err) |
241 | goto failure; | 255 | goto failure; |
242 | 256 | ||
@@ -260,7 +274,10 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
260 | return 0; | 274 | return 0; |
261 | 275 | ||
262 | failure: | 276 | failure: |
263 | /* This unhashes the socket and releases the local port, if necessary. */ | 277 | /* |
278 | * This unhashes the socket and releases the local port, | ||
279 | * if necessary. | ||
280 | */ | ||
264 | tcp_set_state(sk, TCP_CLOSE); | 281 | tcp_set_state(sk, TCP_CLOSE); |
265 | ip_rt_put(rt); | 282 | ip_rt_put(rt); |
266 | sk->sk_route_caps = 0; | 283 | sk->sk_route_caps = 0; |
@@ -485,8 +502,9 @@ void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb) | |||
485 | struct tcphdr *th = skb->h.th; | 502 | struct tcphdr *th = skb->h.th; |
486 | 503 | ||
487 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 504 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
488 | th->check = ~tcp_v4_check(th, len, inet->saddr, inet->daddr, 0); | 505 | th->check = ~tcp_v4_check(th, len, |
489 | skb->csum = offsetof(struct tcphdr, check); | 506 | inet->saddr, inet->daddr, 0); |
507 | skb->csum_offset = offsetof(struct tcphdr, check); | ||
490 | } else { | 508 | } else { |
491 | th->check = tcp_v4_check(th, len, inet->saddr, inet->daddr, | 509 | th->check = tcp_v4_check(th, len, inet->saddr, inet->daddr, |
492 | csum_partial((char *)th, | 510 | csum_partial((char *)th, |
@@ -508,7 +526,7 @@ int tcp_v4_gso_send_check(struct sk_buff *skb) | |||
508 | 526 | ||
509 | th->check = 0; | 527 | th->check = 0; |
510 | th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0); | 528 | th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0); |
511 | skb->csum = offsetof(struct tcphdr, check); | 529 | skb->csum_offset = offsetof(struct tcphdr, check); |
512 | skb->ip_summed = CHECKSUM_PARTIAL; | 530 | skb->ip_summed = CHECKSUM_PARTIAL; |
513 | return 0; | 531 | return 0; |
514 | } | 532 | } |
@@ -526,11 +544,19 @@ int tcp_v4_gso_send_check(struct sk_buff *skb) | |||
526 | * Exception: precedence violation. We do not implement it in any case. | 544 | * Exception: precedence violation. We do not implement it in any case. |
527 | */ | 545 | */ |
528 | 546 | ||
529 | static void tcp_v4_send_reset(struct sk_buff *skb) | 547 | static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) |
530 | { | 548 | { |
531 | struct tcphdr *th = skb->h.th; | 549 | struct tcphdr *th = skb->h.th; |
532 | struct tcphdr rth; | 550 | struct { |
551 | struct tcphdr th; | ||
552 | #ifdef CONFIG_TCP_MD5SIG | ||
553 | __be32 opt[(TCPOLEN_MD5SIG_ALIGNED >> 2)]; | ||
554 | #endif | ||
555 | } rep; | ||
533 | struct ip_reply_arg arg; | 556 | struct ip_reply_arg arg; |
557 | #ifdef CONFIG_TCP_MD5SIG | ||
558 | struct tcp_md5sig_key *key; | ||
559 | #endif | ||
534 | 560 | ||
535 | /* Never send a reset in response to a reset. */ | 561 | /* Never send a reset in response to a reset. */ |
536 | if (th->rst) | 562 | if (th->rst) |
@@ -540,29 +566,49 @@ static void tcp_v4_send_reset(struct sk_buff *skb) | |||
540 | return; | 566 | return; |
541 | 567 | ||
542 | /* Swap the send and the receive. */ | 568 | /* Swap the send and the receive. */ |
543 | memset(&rth, 0, sizeof(struct tcphdr)); | 569 | memset(&rep, 0, sizeof(rep)); |
544 | rth.dest = th->source; | 570 | rep.th.dest = th->source; |
545 | rth.source = th->dest; | 571 | rep.th.source = th->dest; |
546 | rth.doff = sizeof(struct tcphdr) / 4; | 572 | rep.th.doff = sizeof(struct tcphdr) / 4; |
547 | rth.rst = 1; | 573 | rep.th.rst = 1; |
548 | 574 | ||
549 | if (th->ack) { | 575 | if (th->ack) { |
550 | rth.seq = th->ack_seq; | 576 | rep.th.seq = th->ack_seq; |
551 | } else { | 577 | } else { |
552 | rth.ack = 1; | 578 | rep.th.ack = 1; |
553 | rth.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin + | 579 | rep.th.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin + |
554 | skb->len - (th->doff << 2)); | 580 | skb->len - (th->doff << 2)); |
555 | } | 581 | } |
556 | 582 | ||
557 | memset(&arg, 0, sizeof arg); | 583 | memset(&arg, 0, sizeof(arg)); |
558 | arg.iov[0].iov_base = (unsigned char *)&rth; | 584 | arg.iov[0].iov_base = (unsigned char *)&rep; |
559 | arg.iov[0].iov_len = sizeof rth; | 585 | arg.iov[0].iov_len = sizeof(rep.th); |
586 | |||
587 | #ifdef CONFIG_TCP_MD5SIG | ||
588 | key = sk ? tcp_v4_md5_do_lookup(sk, skb->nh.iph->daddr) : NULL; | ||
589 | if (key) { | ||
590 | rep.opt[0] = htonl((TCPOPT_NOP << 24) | | ||
591 | (TCPOPT_NOP << 16) | | ||
592 | (TCPOPT_MD5SIG << 8) | | ||
593 | TCPOLEN_MD5SIG); | ||
594 | /* Update length and the length the header thinks exists */ | ||
595 | arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED; | ||
596 | rep.th.doff = arg.iov[0].iov_len / 4; | ||
597 | |||
598 | tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[1], | ||
599 | key, | ||
600 | skb->nh.iph->daddr, | ||
601 | skb->nh.iph->saddr, | ||
602 | &rep.th, IPPROTO_TCP, | ||
603 | arg.iov[0].iov_len); | ||
604 | } | ||
605 | #endif | ||
560 | arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr, | 606 | arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr, |
561 | skb->nh.iph->saddr, /*XXX*/ | 607 | skb->nh.iph->saddr, /* XXX */ |
562 | sizeof(struct tcphdr), IPPROTO_TCP, 0); | 608 | sizeof(struct tcphdr), IPPROTO_TCP, 0); |
563 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; | 609 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; |
564 | 610 | ||
565 | ip_send_reply(tcp_socket->sk, skb, &arg, sizeof rth); | 611 | ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len); |
566 | 612 | ||
567 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); | 613 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); |
568 | TCP_INC_STATS_BH(TCP_MIB_OUTRSTS); | 614 | TCP_INC_STATS_BH(TCP_MIB_OUTRSTS); |
@@ -572,28 +618,37 @@ static void tcp_v4_send_reset(struct sk_buff *skb) | |||
572 | outside socket context is ugly, certainly. What can I do? | 618 | outside socket context is ugly, certainly. What can I do? |
573 | */ | 619 | */ |
574 | 620 | ||
575 | static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | 621 | static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, |
622 | struct sk_buff *skb, u32 seq, u32 ack, | ||
576 | u32 win, u32 ts) | 623 | u32 win, u32 ts) |
577 | { | 624 | { |
578 | struct tcphdr *th = skb->h.th; | 625 | struct tcphdr *th = skb->h.th; |
579 | struct { | 626 | struct { |
580 | struct tcphdr th; | 627 | struct tcphdr th; |
581 | u32 tsopt[TCPOLEN_TSTAMP_ALIGNED >> 2]; | 628 | __be32 opt[(TCPOLEN_TSTAMP_ALIGNED >> 2) |
629 | #ifdef CONFIG_TCP_MD5SIG | ||
630 | + (TCPOLEN_MD5SIG_ALIGNED >> 2) | ||
631 | #endif | ||
632 | ]; | ||
582 | } rep; | 633 | } rep; |
583 | struct ip_reply_arg arg; | 634 | struct ip_reply_arg arg; |
635 | #ifdef CONFIG_TCP_MD5SIG | ||
636 | struct tcp_md5sig_key *key; | ||
637 | struct tcp_md5sig_key tw_key; | ||
638 | #endif | ||
584 | 639 | ||
585 | memset(&rep.th, 0, sizeof(struct tcphdr)); | 640 | memset(&rep.th, 0, sizeof(struct tcphdr)); |
586 | memset(&arg, 0, sizeof arg); | 641 | memset(&arg, 0, sizeof(arg)); |
587 | 642 | ||
588 | arg.iov[0].iov_base = (unsigned char *)&rep; | 643 | arg.iov[0].iov_base = (unsigned char *)&rep; |
589 | arg.iov[0].iov_len = sizeof(rep.th); | 644 | arg.iov[0].iov_len = sizeof(rep.th); |
590 | if (ts) { | 645 | if (ts) { |
591 | rep.tsopt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | | 646 | rep.opt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | |
592 | (TCPOPT_TIMESTAMP << 8) | | 647 | (TCPOPT_TIMESTAMP << 8) | |
593 | TCPOLEN_TIMESTAMP); | 648 | TCPOLEN_TIMESTAMP); |
594 | rep.tsopt[1] = htonl(tcp_time_stamp); | 649 | rep.opt[1] = htonl(tcp_time_stamp); |
595 | rep.tsopt[2] = htonl(ts); | 650 | rep.opt[2] = htonl(ts); |
596 | arg.iov[0].iov_len = sizeof(rep); | 651 | arg.iov[0].iov_len = TCPOLEN_TSTAMP_ALIGNED; |
597 | } | 652 | } |
598 | 653 | ||
599 | /* Swap the send and the receive. */ | 654 | /* Swap the send and the receive. */ |
@@ -605,8 +660,44 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
605 | rep.th.ack = 1; | 660 | rep.th.ack = 1; |
606 | rep.th.window = htons(win); | 661 | rep.th.window = htons(win); |
607 | 662 | ||
663 | #ifdef CONFIG_TCP_MD5SIG | ||
664 | /* | ||
665 | * The SKB holds an imcoming packet, but may not have a valid ->sk | ||
666 | * pointer. This is especially the case when we're dealing with a | ||
667 | * TIME_WAIT ack, because the sk structure is long gone, and only | ||
668 | * the tcp_timewait_sock remains. So the md5 key is stashed in that | ||
669 | * structure, and we use it in preference. I believe that (twsk || | ||
670 | * skb->sk) holds true, but we program defensively. | ||
671 | */ | ||
672 | if (!twsk && skb->sk) { | ||
673 | key = tcp_v4_md5_do_lookup(skb->sk, skb->nh.iph->daddr); | ||
674 | } else if (twsk && twsk->tw_md5_keylen) { | ||
675 | tw_key.key = twsk->tw_md5_key; | ||
676 | tw_key.keylen = twsk->tw_md5_keylen; | ||
677 | key = &tw_key; | ||
678 | } else | ||
679 | key = NULL; | ||
680 | |||
681 | if (key) { | ||
682 | int offset = (ts) ? 3 : 0; | ||
683 | |||
684 | rep.opt[offset++] = htonl((TCPOPT_NOP << 24) | | ||
685 | (TCPOPT_NOP << 16) | | ||
686 | (TCPOPT_MD5SIG << 8) | | ||
687 | TCPOLEN_MD5SIG); | ||
688 | arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED; | ||
689 | rep.th.doff = arg.iov[0].iov_len/4; | ||
690 | |||
691 | tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[offset], | ||
692 | key, | ||
693 | skb->nh.iph->daddr, | ||
694 | skb->nh.iph->saddr, | ||
695 | &rep.th, IPPROTO_TCP, | ||
696 | arg.iov[0].iov_len); | ||
697 | } | ||
698 | #endif | ||
608 | arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr, | 699 | arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr, |
609 | skb->nh.iph->saddr, /*XXX*/ | 700 | skb->nh.iph->saddr, /* XXX */ |
610 | arg.iov[0].iov_len, IPPROTO_TCP, 0); | 701 | arg.iov[0].iov_len, IPPROTO_TCP, 0); |
611 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; | 702 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; |
612 | 703 | ||
@@ -618,17 +709,20 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
618 | static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) | 709 | static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) |
619 | { | 710 | { |
620 | struct inet_timewait_sock *tw = inet_twsk(sk); | 711 | struct inet_timewait_sock *tw = inet_twsk(sk); |
621 | const struct tcp_timewait_sock *tcptw = tcp_twsk(sk); | 712 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); |
622 | 713 | ||
623 | tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | 714 | tcp_v4_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, |
624 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, tcptw->tw_ts_recent); | 715 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
716 | tcptw->tw_ts_recent); | ||
625 | 717 | ||
626 | inet_twsk_put(tw); | 718 | inet_twsk_put(tw); |
627 | } | 719 | } |
628 | 720 | ||
629 | static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) | 721 | static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, |
722 | struct request_sock *req) | ||
630 | { | 723 | { |
631 | tcp_v4_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, | 724 | tcp_v4_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1, |
725 | tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, | ||
632 | req->ts_recent); | 726 | req->ts_recent); |
633 | } | 727 | } |
634 | 728 | ||
@@ -662,8 +756,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req, | |||
662 | err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, | 756 | err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, |
663 | ireq->rmt_addr, | 757 | ireq->rmt_addr, |
664 | ireq->opt); | 758 | ireq->opt); |
665 | if (err == NET_XMIT_CN) | 759 | err = net_xmit_eval(err); |
666 | err = 0; | ||
667 | } | 760 | } |
668 | 761 | ||
669 | out: | 762 | out: |
@@ -715,7 +808,423 @@ static struct ip_options *tcp_v4_save_options(struct sock *sk, | |||
715 | return dopt; | 808 | return dopt; |
716 | } | 809 | } |
717 | 810 | ||
718 | struct request_sock_ops tcp_request_sock_ops = { | 811 | #ifdef CONFIG_TCP_MD5SIG |
812 | /* | ||
813 | * RFC2385 MD5 checksumming requires a mapping of | ||
814 | * IP address->MD5 Key. | ||
815 | * We need to maintain these in the sk structure. | ||
816 | */ | ||
817 | |||
818 | /* Find the Key structure for an address. */ | ||
819 | static struct tcp_md5sig_key * | ||
820 | tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr) | ||
821 | { | ||
822 | struct tcp_sock *tp = tcp_sk(sk); | ||
823 | int i; | ||
824 | |||
825 | if (!tp->md5sig_info || !tp->md5sig_info->entries4) | ||
826 | return NULL; | ||
827 | for (i = 0; i < tp->md5sig_info->entries4; i++) { | ||
828 | if (tp->md5sig_info->keys4[i].addr == addr) | ||
829 | return (struct tcp_md5sig_key *) | ||
830 | &tp->md5sig_info->keys4[i]; | ||
831 | } | ||
832 | return NULL; | ||
833 | } | ||
834 | |||
835 | struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk, | ||
836 | struct sock *addr_sk) | ||
837 | { | ||
838 | return tcp_v4_md5_do_lookup(sk, inet_sk(addr_sk)->daddr); | ||
839 | } | ||
840 | |||
841 | EXPORT_SYMBOL(tcp_v4_md5_lookup); | ||
842 | |||
843 | static struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk, | ||
844 | struct request_sock *req) | ||
845 | { | ||
846 | return tcp_v4_md5_do_lookup(sk, inet_rsk(req)->rmt_addr); | ||
847 | } | ||
848 | |||
849 | /* This can be called on a newly created socket, from other files */ | ||
850 | int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, | ||
851 | u8 *newkey, u8 newkeylen) | ||
852 | { | ||
853 | /* Add Key to the list */ | ||
854 | struct tcp4_md5sig_key *key; | ||
855 | struct tcp_sock *tp = tcp_sk(sk); | ||
856 | struct tcp4_md5sig_key *keys; | ||
857 | |||
858 | key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr); | ||
859 | if (key) { | ||
860 | /* Pre-existing entry - just update that one. */ | ||
861 | kfree(key->key); | ||
862 | key->key = newkey; | ||
863 | key->keylen = newkeylen; | ||
864 | } else { | ||
865 | struct tcp_md5sig_info *md5sig; | ||
866 | |||
867 | if (!tp->md5sig_info) { | ||
868 | tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info), | ||
869 | GFP_ATOMIC); | ||
870 | if (!tp->md5sig_info) { | ||
871 | kfree(newkey); | ||
872 | return -ENOMEM; | ||
873 | } | ||
874 | } | ||
875 | if (tcp_alloc_md5sig_pool() == NULL) { | ||
876 | kfree(newkey); | ||
877 | return -ENOMEM; | ||
878 | } | ||
879 | md5sig = tp->md5sig_info; | ||
880 | |||
881 | if (md5sig->alloced4 == md5sig->entries4) { | ||
882 | keys = kmalloc((sizeof(*keys) * | ||
883 | (md5sig->entries4 + 1)), GFP_ATOMIC); | ||
884 | if (!keys) { | ||
885 | kfree(newkey); | ||
886 | tcp_free_md5sig_pool(); | ||
887 | return -ENOMEM; | ||
888 | } | ||
889 | |||
890 | if (md5sig->entries4) | ||
891 | memcpy(keys, md5sig->keys4, | ||
892 | sizeof(*keys) * md5sig->entries4); | ||
893 | |||
894 | /* Free old key list, and reference new one */ | ||
895 | if (md5sig->keys4) | ||
896 | kfree(md5sig->keys4); | ||
897 | md5sig->keys4 = keys; | ||
898 | md5sig->alloced4++; | ||
899 | } | ||
900 | md5sig->entries4++; | ||
901 | md5sig->keys4[md5sig->entries4 - 1].addr = addr; | ||
902 | md5sig->keys4[md5sig->entries4 - 1].key = newkey; | ||
903 | md5sig->keys4[md5sig->entries4 - 1].keylen = newkeylen; | ||
904 | } | ||
905 | return 0; | ||
906 | } | ||
907 | |||
908 | EXPORT_SYMBOL(tcp_v4_md5_do_add); | ||
909 | |||
910 | static int tcp_v4_md5_add_func(struct sock *sk, struct sock *addr_sk, | ||
911 | u8 *newkey, u8 newkeylen) | ||
912 | { | ||
913 | return tcp_v4_md5_do_add(sk, inet_sk(addr_sk)->daddr, | ||
914 | newkey, newkeylen); | ||
915 | } | ||
916 | |||
917 | int tcp_v4_md5_do_del(struct sock *sk, __be32 addr) | ||
918 | { | ||
919 | struct tcp_sock *tp = tcp_sk(sk); | ||
920 | int i; | ||
921 | |||
922 | for (i = 0; i < tp->md5sig_info->entries4; i++) { | ||
923 | if (tp->md5sig_info->keys4[i].addr == addr) { | ||
924 | /* Free the key */ | ||
925 | kfree(tp->md5sig_info->keys4[i].key); | ||
926 | tp->md5sig_info->entries4--; | ||
927 | |||
928 | if (tp->md5sig_info->entries4 == 0) { | ||
929 | kfree(tp->md5sig_info->keys4); | ||
930 | tp->md5sig_info->keys4 = NULL; | ||
931 | } else if (tp->md5sig_info->entries4 != i) { | ||
932 | /* Need to do some manipulation */ | ||
933 | memcpy(&tp->md5sig_info->keys4[i], | ||
934 | &tp->md5sig_info->keys4[i+1], | ||
935 | (tp->md5sig_info->entries4 - i) * | ||
936 | sizeof(struct tcp4_md5sig_key)); | ||
937 | } | ||
938 | tcp_free_md5sig_pool(); | ||
939 | return 0; | ||
940 | } | ||
941 | } | ||
942 | return -ENOENT; | ||
943 | } | ||
944 | |||
945 | EXPORT_SYMBOL(tcp_v4_md5_do_del); | ||
946 | |||
947 | static void tcp_v4_clear_md5_list(struct sock *sk) | ||
948 | { | ||
949 | struct tcp_sock *tp = tcp_sk(sk); | ||
950 | |||
951 | /* Free each key, then the set of key keys, | ||
952 | * the crypto element, and then decrement our | ||
953 | * hold on the last resort crypto. | ||
954 | */ | ||
955 | if (tp->md5sig_info->entries4) { | ||
956 | int i; | ||
957 | for (i = 0; i < tp->md5sig_info->entries4; i++) | ||
958 | kfree(tp->md5sig_info->keys4[i].key); | ||
959 | tp->md5sig_info->entries4 = 0; | ||
960 | tcp_free_md5sig_pool(); | ||
961 | } | ||
962 | if (tp->md5sig_info->keys4) { | ||
963 | kfree(tp->md5sig_info->keys4); | ||
964 | tp->md5sig_info->keys4 = NULL; | ||
965 | tp->md5sig_info->alloced4 = 0; | ||
966 | } | ||
967 | } | ||
968 | |||
969 | static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval, | ||
970 | int optlen) | ||
971 | { | ||
972 | struct tcp_md5sig cmd; | ||
973 | struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr; | ||
974 | u8 *newkey; | ||
975 | |||
976 | if (optlen < sizeof(cmd)) | ||
977 | return -EINVAL; | ||
978 | |||
979 | if (copy_from_user(&cmd, optval, sizeof(cmd))) | ||
980 | return -EFAULT; | ||
981 | |||
982 | if (sin->sin_family != AF_INET) | ||
983 | return -EINVAL; | ||
984 | |||
985 | if (!cmd.tcpm_key || !cmd.tcpm_keylen) { | ||
986 | if (!tcp_sk(sk)->md5sig_info) | ||
987 | return -ENOENT; | ||
988 | return tcp_v4_md5_do_del(sk, sin->sin_addr.s_addr); | ||
989 | } | ||
990 | |||
991 | if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN) | ||
992 | return -EINVAL; | ||
993 | |||
994 | if (!tcp_sk(sk)->md5sig_info) { | ||
995 | struct tcp_sock *tp = tcp_sk(sk); | ||
996 | struct tcp_md5sig_info *p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
997 | |||
998 | if (!p) | ||
999 | return -EINVAL; | ||
1000 | |||
1001 | tp->md5sig_info = p; | ||
1002 | |||
1003 | } | ||
1004 | |||
1005 | newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); | ||
1006 | if (!newkey) | ||
1007 | return -ENOMEM; | ||
1008 | return tcp_v4_md5_do_add(sk, sin->sin_addr.s_addr, | ||
1009 | newkey, cmd.tcpm_keylen); | ||
1010 | } | ||
1011 | |||
1012 | static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | ||
1013 | __be32 saddr, __be32 daddr, | ||
1014 | struct tcphdr *th, int protocol, | ||
1015 | int tcplen) | ||
1016 | { | ||
1017 | struct scatterlist sg[4]; | ||
1018 | __u16 data_len; | ||
1019 | int block = 0; | ||
1020 | __sum16 old_checksum; | ||
1021 | struct tcp_md5sig_pool *hp; | ||
1022 | struct tcp4_pseudohdr *bp; | ||
1023 | struct hash_desc *desc; | ||
1024 | int err; | ||
1025 | unsigned int nbytes = 0; | ||
1026 | |||
1027 | /* | ||
1028 | * Okay, so RFC2385 is turned on for this connection, | ||
1029 | * so we need to generate the MD5 hash for the packet now. | ||
1030 | */ | ||
1031 | |||
1032 | hp = tcp_get_md5sig_pool(); | ||
1033 | if (!hp) | ||
1034 | goto clear_hash_noput; | ||
1035 | |||
1036 | bp = &hp->md5_blk.ip4; | ||
1037 | desc = &hp->md5_desc; | ||
1038 | |||
1039 | /* | ||
1040 | * 1. the TCP pseudo-header (in the order: source IP address, | ||
1041 | * destination IP address, zero-padded protocol number, and | ||
1042 | * segment length) | ||
1043 | */ | ||
1044 | bp->saddr = saddr; | ||
1045 | bp->daddr = daddr; | ||
1046 | bp->pad = 0; | ||
1047 | bp->protocol = protocol; | ||
1048 | bp->len = htons(tcplen); | ||
1049 | sg_set_buf(&sg[block++], bp, sizeof(*bp)); | ||
1050 | nbytes += sizeof(*bp); | ||
1051 | |||
1052 | /* 2. the TCP header, excluding options, and assuming a | ||
1053 | * checksum of zero/ | ||
1054 | */ | ||
1055 | old_checksum = th->check; | ||
1056 | th->check = 0; | ||
1057 | sg_set_buf(&sg[block++], th, sizeof(struct tcphdr)); | ||
1058 | nbytes += sizeof(struct tcphdr); | ||
1059 | |||
1060 | /* 3. the TCP segment data (if any) */ | ||
1061 | data_len = tcplen - (th->doff << 2); | ||
1062 | if (data_len > 0) { | ||
1063 | unsigned char *data = (unsigned char *)th + (th->doff << 2); | ||
1064 | sg_set_buf(&sg[block++], data, data_len); | ||
1065 | nbytes += data_len; | ||
1066 | } | ||
1067 | |||
1068 | /* 4. an independently-specified key or password, known to both | ||
1069 | * TCPs and presumably connection-specific | ||
1070 | */ | ||
1071 | sg_set_buf(&sg[block++], key->key, key->keylen); | ||
1072 | nbytes += key->keylen; | ||
1073 | |||
1074 | /* Now store the Hash into the packet */ | ||
1075 | err = crypto_hash_init(desc); | ||
1076 | if (err) | ||
1077 | goto clear_hash; | ||
1078 | err = crypto_hash_update(desc, sg, nbytes); | ||
1079 | if (err) | ||
1080 | goto clear_hash; | ||
1081 | err = crypto_hash_final(desc, md5_hash); | ||
1082 | if (err) | ||
1083 | goto clear_hash; | ||
1084 | |||
1085 | /* Reset header, and free up the crypto */ | ||
1086 | tcp_put_md5sig_pool(); | ||
1087 | th->check = old_checksum; | ||
1088 | |||
1089 | out: | ||
1090 | return 0; | ||
1091 | clear_hash: | ||
1092 | tcp_put_md5sig_pool(); | ||
1093 | clear_hash_noput: | ||
1094 | memset(md5_hash, 0, 16); | ||
1095 | goto out; | ||
1096 | } | ||
1097 | |||
1098 | int tcp_v4_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | ||
1099 | struct sock *sk, | ||
1100 | struct dst_entry *dst, | ||
1101 | struct request_sock *req, | ||
1102 | struct tcphdr *th, int protocol, | ||
1103 | int tcplen) | ||
1104 | { | ||
1105 | __be32 saddr, daddr; | ||
1106 | |||
1107 | if (sk) { | ||
1108 | saddr = inet_sk(sk)->saddr; | ||
1109 | daddr = inet_sk(sk)->daddr; | ||
1110 | } else { | ||
1111 | struct rtable *rt = (struct rtable *)dst; | ||
1112 | BUG_ON(!rt); | ||
1113 | saddr = rt->rt_src; | ||
1114 | daddr = rt->rt_dst; | ||
1115 | } | ||
1116 | return tcp_v4_do_calc_md5_hash(md5_hash, key, | ||
1117 | saddr, daddr, | ||
1118 | th, protocol, tcplen); | ||
1119 | } | ||
1120 | |||
1121 | EXPORT_SYMBOL(tcp_v4_calc_md5_hash); | ||
1122 | |||
1123 | static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb) | ||
1124 | { | ||
1125 | /* | ||
1126 | * This gets called for each TCP segment that arrives | ||
1127 | * so we want to be efficient. | ||
1128 | * We have 3 drop cases: | ||
1129 | * o No MD5 hash and one expected. | ||
1130 | * o MD5 hash and we're not expecting one. | ||
1131 | * o MD5 hash and its wrong. | ||
1132 | */ | ||
1133 | __u8 *hash_location = NULL; | ||
1134 | struct tcp_md5sig_key *hash_expected; | ||
1135 | struct iphdr *iph = skb->nh.iph; | ||
1136 | struct tcphdr *th = skb->h.th; | ||
1137 | int length = (th->doff << 2) - sizeof(struct tcphdr); | ||
1138 | int genhash; | ||
1139 | unsigned char *ptr; | ||
1140 | unsigned char newhash[16]; | ||
1141 | |||
1142 | hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr); | ||
1143 | |||
1144 | /* | ||
1145 | * If the TCP option length is less than the TCP_MD5SIG | ||
1146 | * option length, then we can shortcut | ||
1147 | */ | ||
1148 | if (length < TCPOLEN_MD5SIG) { | ||
1149 | if (hash_expected) | ||
1150 | return 1; | ||
1151 | else | ||
1152 | return 0; | ||
1153 | } | ||
1154 | |||
1155 | /* Okay, we can't shortcut - we have to grub through the options */ | ||
1156 | ptr = (unsigned char *)(th + 1); | ||
1157 | while (length > 0) { | ||
1158 | int opcode = *ptr++; | ||
1159 | int opsize; | ||
1160 | |||
1161 | switch (opcode) { | ||
1162 | case TCPOPT_EOL: | ||
1163 | goto done_opts; | ||
1164 | case TCPOPT_NOP: | ||
1165 | length--; | ||
1166 | continue; | ||
1167 | default: | ||
1168 | opsize = *ptr++; | ||
1169 | if (opsize < 2) | ||
1170 | goto done_opts; | ||
1171 | if (opsize > length) | ||
1172 | goto done_opts; | ||
1173 | |||
1174 | if (opcode == TCPOPT_MD5SIG) { | ||
1175 | hash_location = ptr; | ||
1176 | goto done_opts; | ||
1177 | } | ||
1178 | } | ||
1179 | ptr += opsize-2; | ||
1180 | length -= opsize; | ||
1181 | } | ||
1182 | done_opts: | ||
1183 | /* We've parsed the options - do we have a hash? */ | ||
1184 | if (!hash_expected && !hash_location) | ||
1185 | return 0; | ||
1186 | |||
1187 | if (hash_expected && !hash_location) { | ||
1188 | LIMIT_NETDEBUG(KERN_INFO "MD5 Hash NOT expected but found " | ||
1189 | "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n", | ||
1190 | NIPQUAD(iph->saddr), ntohs(th->source), | ||
1191 | NIPQUAD(iph->daddr), ntohs(th->dest)); | ||
1192 | return 1; | ||
1193 | } | ||
1194 | |||
1195 | if (!hash_expected && hash_location) { | ||
1196 | LIMIT_NETDEBUG(KERN_INFO "MD5 Hash NOT expected but found " | ||
1197 | "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n", | ||
1198 | NIPQUAD(iph->saddr), ntohs(th->source), | ||
1199 | NIPQUAD(iph->daddr), ntohs(th->dest)); | ||
1200 | return 1; | ||
1201 | } | ||
1202 | |||
1203 | /* Okay, so this is hash_expected and hash_location - | ||
1204 | * so we need to calculate the checksum. | ||
1205 | */ | ||
1206 | genhash = tcp_v4_do_calc_md5_hash(newhash, | ||
1207 | hash_expected, | ||
1208 | iph->saddr, iph->daddr, | ||
1209 | th, sk->sk_protocol, | ||
1210 | skb->len); | ||
1211 | |||
1212 | if (genhash || memcmp(hash_location, newhash, 16) != 0) { | ||
1213 | if (net_ratelimit()) { | ||
1214 | printk(KERN_INFO "MD5 Hash failed for " | ||
1215 | "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)%s\n", | ||
1216 | NIPQUAD(iph->saddr), ntohs(th->source), | ||
1217 | NIPQUAD(iph->daddr), ntohs(th->dest), | ||
1218 | genhash ? " tcp_v4_calc_md5_hash failed" : ""); | ||
1219 | } | ||
1220 | return 1; | ||
1221 | } | ||
1222 | return 0; | ||
1223 | } | ||
1224 | |||
1225 | #endif | ||
1226 | |||
1227 | struct request_sock_ops tcp_request_sock_ops __read_mostly = { | ||
719 | .family = PF_INET, | 1228 | .family = PF_INET, |
720 | .obj_size = sizeof(struct tcp_request_sock), | 1229 | .obj_size = sizeof(struct tcp_request_sock), |
721 | .rtx_syn_ack = tcp_v4_send_synack, | 1230 | .rtx_syn_ack = tcp_v4_send_synack, |
@@ -724,9 +1233,16 @@ struct request_sock_ops tcp_request_sock_ops = { | |||
724 | .send_reset = tcp_v4_send_reset, | 1233 | .send_reset = tcp_v4_send_reset, |
725 | }; | 1234 | }; |
726 | 1235 | ||
1236 | #ifdef CONFIG_TCP_MD5SIG | ||
1237 | static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { | ||
1238 | .md5_lookup = tcp_v4_reqsk_md5_lookup, | ||
1239 | }; | ||
1240 | #endif | ||
1241 | |||
727 | static struct timewait_sock_ops tcp_timewait_sock_ops = { | 1242 | static struct timewait_sock_ops tcp_timewait_sock_ops = { |
728 | .twsk_obj_size = sizeof(struct tcp_timewait_sock), | 1243 | .twsk_obj_size = sizeof(struct tcp_timewait_sock), |
729 | .twsk_unique = tcp_twsk_unique, | 1244 | .twsk_unique = tcp_twsk_unique, |
1245 | .twsk_destructor= tcp_twsk_destructor, | ||
730 | }; | 1246 | }; |
731 | 1247 | ||
732 | int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | 1248 | int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) |
@@ -774,6 +1290,10 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
774 | if (!req) | 1290 | if (!req) |
775 | goto drop; | 1291 | goto drop; |
776 | 1292 | ||
1293 | #ifdef CONFIG_TCP_MD5SIG | ||
1294 | tcp_rsk(req)->af_specific = &tcp_request_sock_ipv4_ops; | ||
1295 | #endif | ||
1296 | |||
777 | tcp_clear_options(&tmp_opt); | 1297 | tcp_clear_options(&tmp_opt); |
778 | tmp_opt.mss_clamp = 536; | 1298 | tmp_opt.mss_clamp = 536; |
779 | tmp_opt.user_mss = tcp_sk(sk)->rx_opt.user_mss; | 1299 | tmp_opt.user_mss = tcp_sk(sk)->rx_opt.user_mss; |
@@ -859,7 +1379,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
859 | goto drop_and_free; | 1379 | goto drop_and_free; |
860 | } | 1380 | } |
861 | 1381 | ||
862 | isn = tcp_v4_init_sequence(sk, skb); | 1382 | isn = tcp_v4_init_sequence(skb); |
863 | } | 1383 | } |
864 | tcp_rsk(req)->snt_isn = isn; | 1384 | tcp_rsk(req)->snt_isn = isn; |
865 | 1385 | ||
@@ -892,6 +1412,9 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
892 | struct inet_sock *newinet; | 1412 | struct inet_sock *newinet; |
893 | struct tcp_sock *newtp; | 1413 | struct tcp_sock *newtp; |
894 | struct sock *newsk; | 1414 | struct sock *newsk; |
1415 | #ifdef CONFIG_TCP_MD5SIG | ||
1416 | struct tcp_md5sig_key *key; | ||
1417 | #endif | ||
895 | 1418 | ||
896 | if (sk_acceptq_is_full(sk)) | 1419 | if (sk_acceptq_is_full(sk)) |
897 | goto exit_overflow; | 1420 | goto exit_overflow; |
@@ -926,6 +1449,22 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
926 | newtp->advmss = dst_metric(dst, RTAX_ADVMSS); | 1449 | newtp->advmss = dst_metric(dst, RTAX_ADVMSS); |
927 | tcp_initialize_rcv_mss(newsk); | 1450 | tcp_initialize_rcv_mss(newsk); |
928 | 1451 | ||
1452 | #ifdef CONFIG_TCP_MD5SIG | ||
1453 | /* Copy over the MD5 key from the original socket */ | ||
1454 | if ((key = tcp_v4_md5_do_lookup(sk, newinet->daddr)) != NULL) { | ||
1455 | /* | ||
1456 | * We're using one, so create a matching key | ||
1457 | * on the newsk structure. If we fail to get | ||
1458 | * memory, then we end up not copying the key | ||
1459 | * across. Shucks. | ||
1460 | */ | ||
1461 | char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); | ||
1462 | if (newkey != NULL) | ||
1463 | tcp_v4_md5_do_add(newsk, inet_sk(sk)->daddr, | ||
1464 | newkey, key->keylen); | ||
1465 | } | ||
1466 | #endif | ||
1467 | |||
929 | __inet_hash(&tcp_hashinfo, newsk, 0); | 1468 | __inet_hash(&tcp_hashinfo, newsk, 0); |
930 | __inet_inherit_port(&tcp_hashinfo, sk, newsk); | 1469 | __inet_inherit_port(&tcp_hashinfo, sk, newsk); |
931 | 1470 | ||
@@ -971,7 +1510,7 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
971 | return sk; | 1510 | return sk; |
972 | } | 1511 | } |
973 | 1512 | ||
974 | static int tcp_v4_checksum_init(struct sk_buff *skb) | 1513 | static __sum16 tcp_v4_checksum_init(struct sk_buff *skb) |
975 | { | 1514 | { |
976 | if (skb->ip_summed == CHECKSUM_COMPLETE) { | 1515 | if (skb->ip_summed == CHECKSUM_COMPLETE) { |
977 | if (!tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr, | 1516 | if (!tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr, |
@@ -1001,10 +1540,24 @@ static int tcp_v4_checksum_init(struct sk_buff *skb) | |||
1001 | */ | 1540 | */ |
1002 | int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) | 1541 | int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) |
1003 | { | 1542 | { |
1543 | struct sock *rsk; | ||
1544 | #ifdef CONFIG_TCP_MD5SIG | ||
1545 | /* | ||
1546 | * We really want to reject the packet as early as possible | ||
1547 | * if: | ||
1548 | * o We're expecting an MD5'd packet and this is no MD5 tcp option | ||
1549 | * o There is an MD5 option and we're not expecting one | ||
1550 | */ | ||
1551 | if (tcp_v4_inbound_md5_hash(sk, skb)) | ||
1552 | goto discard; | ||
1553 | #endif | ||
1554 | |||
1004 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ | 1555 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ |
1005 | TCP_CHECK_TIMER(sk); | 1556 | TCP_CHECK_TIMER(sk); |
1006 | if (tcp_rcv_established(sk, skb, skb->h.th, skb->len)) | 1557 | if (tcp_rcv_established(sk, skb, skb->h.th, skb->len)) { |
1558 | rsk = sk; | ||
1007 | goto reset; | 1559 | goto reset; |
1560 | } | ||
1008 | TCP_CHECK_TIMER(sk); | 1561 | TCP_CHECK_TIMER(sk); |
1009 | return 0; | 1562 | return 0; |
1010 | } | 1563 | } |
@@ -1018,20 +1571,24 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1018 | goto discard; | 1571 | goto discard; |
1019 | 1572 | ||
1020 | if (nsk != sk) { | 1573 | if (nsk != sk) { |
1021 | if (tcp_child_process(sk, nsk, skb)) | 1574 | if (tcp_child_process(sk, nsk, skb)) { |
1575 | rsk = nsk; | ||
1022 | goto reset; | 1576 | goto reset; |
1577 | } | ||
1023 | return 0; | 1578 | return 0; |
1024 | } | 1579 | } |
1025 | } | 1580 | } |
1026 | 1581 | ||
1027 | TCP_CHECK_TIMER(sk); | 1582 | TCP_CHECK_TIMER(sk); |
1028 | if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len)) | 1583 | if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len)) { |
1584 | rsk = sk; | ||
1029 | goto reset; | 1585 | goto reset; |
1586 | } | ||
1030 | TCP_CHECK_TIMER(sk); | 1587 | TCP_CHECK_TIMER(sk); |
1031 | return 0; | 1588 | return 0; |
1032 | 1589 | ||
1033 | reset: | 1590 | reset: |
1034 | tcp_v4_send_reset(skb); | 1591 | tcp_v4_send_reset(rsk, skb); |
1035 | discard: | 1592 | discard: |
1036 | kfree_skb(skb); | 1593 | kfree_skb(skb); |
1037 | /* Be careful here. If this function gets more complicated and | 1594 | /* Be careful here. If this function gets more complicated and |
@@ -1140,7 +1697,7 @@ no_tcp_socket: | |||
1140 | bad_packet: | 1697 | bad_packet: |
1141 | TCP_INC_STATS_BH(TCP_MIB_INERRS); | 1698 | TCP_INC_STATS_BH(TCP_MIB_INERRS); |
1142 | } else { | 1699 | } else { |
1143 | tcp_v4_send_reset(skb); | 1700 | tcp_v4_send_reset(NULL, skb); |
1144 | } | 1701 | } |
1145 | 1702 | ||
1146 | discard_it: | 1703 | discard_it: |
@@ -1263,6 +1820,15 @@ struct inet_connection_sock_af_ops ipv4_specific = { | |||
1263 | #endif | 1820 | #endif |
1264 | }; | 1821 | }; |
1265 | 1822 | ||
1823 | #ifdef CONFIG_TCP_MD5SIG | ||
1824 | static struct tcp_sock_af_ops tcp_sock_ipv4_specific = { | ||
1825 | .md5_lookup = tcp_v4_md5_lookup, | ||
1826 | .calc_md5_hash = tcp_v4_calc_md5_hash, | ||
1827 | .md5_add = tcp_v4_md5_add_func, | ||
1828 | .md5_parse = tcp_v4_parse_md5_keys, | ||
1829 | }; | ||
1830 | #endif | ||
1831 | |||
1266 | /* NOTE: A lot of things set to zero explicitly by call to | 1832 | /* NOTE: A lot of things set to zero explicitly by call to |
1267 | * sk_alloc() so need not be done here. | 1833 | * sk_alloc() so need not be done here. |
1268 | */ | 1834 | */ |
@@ -1302,6 +1868,9 @@ static int tcp_v4_init_sock(struct sock *sk) | |||
1302 | 1868 | ||
1303 | icsk->icsk_af_ops = &ipv4_specific; | 1869 | icsk->icsk_af_ops = &ipv4_specific; |
1304 | icsk->icsk_sync_mss = tcp_sync_mss; | 1870 | icsk->icsk_sync_mss = tcp_sync_mss; |
1871 | #ifdef CONFIG_TCP_MD5SIG | ||
1872 | tp->af_specific = &tcp_sock_ipv4_specific; | ||
1873 | #endif | ||
1305 | 1874 | ||
1306 | sk->sk_sndbuf = sysctl_tcp_wmem[1]; | 1875 | sk->sk_sndbuf = sysctl_tcp_wmem[1]; |
1307 | sk->sk_rcvbuf = sysctl_tcp_rmem[1]; | 1876 | sk->sk_rcvbuf = sysctl_tcp_rmem[1]; |
@@ -1325,6 +1894,15 @@ int tcp_v4_destroy_sock(struct sock *sk) | |||
1325 | /* Cleans up our, hopefully empty, out_of_order_queue. */ | 1894 | /* Cleans up our, hopefully empty, out_of_order_queue. */ |
1326 | __skb_queue_purge(&tp->out_of_order_queue); | 1895 | __skb_queue_purge(&tp->out_of_order_queue); |
1327 | 1896 | ||
1897 | #ifdef CONFIG_TCP_MD5SIG | ||
1898 | /* Clean up the MD5 key list, if any */ | ||
1899 | if (tp->md5sig_info) { | ||
1900 | tcp_v4_clear_md5_list(sk); | ||
1901 | kfree(tp->md5sig_info); | ||
1902 | tp->md5sig_info = NULL; | ||
1903 | } | ||
1904 | #endif | ||
1905 | |||
1328 | #ifdef CONFIG_NET_DMA | 1906 | #ifdef CONFIG_NET_DMA |
1329 | /* Cleans up our sk_async_wait_queue */ | 1907 | /* Cleans up our sk_async_wait_queue */ |
1330 | __skb_queue_purge(&sk->sk_async_wait_queue); | 1908 | __skb_queue_purge(&sk->sk_async_wait_queue); |
@@ -1385,7 +1963,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur) | |||
1385 | if (st->state == TCP_SEQ_STATE_OPENREQ) { | 1963 | if (st->state == TCP_SEQ_STATE_OPENREQ) { |
1386 | struct request_sock *req = cur; | 1964 | struct request_sock *req = cur; |
1387 | 1965 | ||
1388 | icsk = inet_csk(st->syn_wait_sk); | 1966 | icsk = inet_csk(st->syn_wait_sk); |
1389 | req = req->dl_next; | 1967 | req = req->dl_next; |
1390 | while (1) { | 1968 | while (1) { |
1391 | while (req) { | 1969 | while (req) { |
@@ -1395,7 +1973,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur) | |||
1395 | } | 1973 | } |
1396 | req = req->dl_next; | 1974 | req = req->dl_next; |
1397 | } | 1975 | } |
1398 | if (++st->sbucket >= TCP_SYNQ_HSIZE) | 1976 | if (++st->sbucket >= icsk->icsk_accept_queue.listen_opt->nr_table_entries) |
1399 | break; | 1977 | break; |
1400 | get_req: | 1978 | get_req: |
1401 | req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket]; | 1979 | req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket]; |
@@ -1543,7 +2121,7 @@ static void *established_get_idx(struct seq_file *seq, loff_t pos) | |||
1543 | while (rc && pos) { | 2121 | while (rc && pos) { |
1544 | rc = established_get_next(seq, rc); | 2122 | rc = established_get_next(seq, rc); |
1545 | --pos; | 2123 | --pos; |
1546 | } | 2124 | } |
1547 | return rc; | 2125 | return rc; |
1548 | } | 2126 | } |
1549 | 2127 | ||
@@ -1672,7 +2250,7 @@ int tcp_proc_register(struct tcp_seq_afinfo *afinfo) | |||
1672 | afinfo->seq_fops->read = seq_read; | 2250 | afinfo->seq_fops->read = seq_read; |
1673 | afinfo->seq_fops->llseek = seq_lseek; | 2251 | afinfo->seq_fops->llseek = seq_lseek; |
1674 | afinfo->seq_fops->release = seq_release_private; | 2252 | afinfo->seq_fops->release = seq_release_private; |
1675 | 2253 | ||
1676 | p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops); | 2254 | p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops); |
1677 | if (p) | 2255 | if (p) |
1678 | p->data = afinfo; | 2256 | p->data = afinfo; |
@@ -1686,7 +2264,7 @@ void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo) | |||
1686 | if (!afinfo) | 2264 | if (!afinfo) |
1687 | return; | 2265 | return; |
1688 | proc_net_remove(afinfo->name); | 2266 | proc_net_remove(afinfo->name); |
1689 | memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops)); | 2267 | memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops)); |
1690 | } | 2268 | } |
1691 | 2269 | ||
1692 | static void get_openreq4(struct sock *sk, struct request_sock *req, | 2270 | static void get_openreq4(struct sock *sk, struct request_sock *req, |
@@ -1721,8 +2299,8 @@ static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i) | |||
1721 | struct tcp_sock *tp = tcp_sk(sp); | 2299 | struct tcp_sock *tp = tcp_sk(sp); |
1722 | const struct inet_connection_sock *icsk = inet_csk(sp); | 2300 | const struct inet_connection_sock *icsk = inet_csk(sp); |
1723 | struct inet_sock *inet = inet_sk(sp); | 2301 | struct inet_sock *inet = inet_sk(sp); |
1724 | unsigned int dest = inet->daddr; | 2302 | __be32 dest = inet->daddr; |
1725 | unsigned int src = inet->rcv_saddr; | 2303 | __be32 src = inet->rcv_saddr; |
1726 | __u16 destp = ntohs(inet->dport); | 2304 | __u16 destp = ntohs(inet->dport); |
1727 | __u16 srcp = ntohs(inet->sport); | 2305 | __u16 srcp = ntohs(inet->sport); |
1728 | 2306 | ||
@@ -1744,7 +2322,8 @@ static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i) | |||
1744 | "%08X %5d %8d %lu %d %p %u %u %u %u %d", | 2322 | "%08X %5d %8d %lu %d %p %u %u %u %u %d", |
1745 | i, src, srcp, dest, destp, sp->sk_state, | 2323 | i, src, srcp, dest, destp, sp->sk_state, |
1746 | tp->write_seq - tp->snd_una, | 2324 | tp->write_seq - tp->snd_una, |
1747 | (sp->sk_state == TCP_LISTEN) ? sp->sk_ack_backlog : (tp->rcv_nxt - tp->copied_seq), | 2325 | sp->sk_state == TCP_LISTEN ? sp->sk_ack_backlog : |
2326 | (tp->rcv_nxt - tp->copied_seq), | ||
1748 | timer_active, | 2327 | timer_active, |
1749 | jiffies_to_clock_t(timer_expires - jiffies), | 2328 | jiffies_to_clock_t(timer_expires - jiffies), |
1750 | icsk->icsk_retransmits, | 2329 | icsk->icsk_retransmits, |
@@ -1759,7 +2338,8 @@ static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i) | |||
1759 | tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh); | 2338 | tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh); |
1760 | } | 2339 | } |
1761 | 2340 | ||
1762 | static void get_timewait4_sock(struct inet_timewait_sock *tw, char *tmpbuf, int i) | 2341 | static void get_timewait4_sock(struct inet_timewait_sock *tw, |
2342 | char *tmpbuf, int i) | ||
1763 | { | 2343 | { |
1764 | __be32 dest, src; | 2344 | __be32 dest, src; |
1765 | __u16 destp, srcp; | 2345 | __u16 destp, srcp; |
@@ -1872,7 +2452,8 @@ struct proto tcp_prot = { | |||
1872 | 2452 | ||
1873 | void __init tcp_v4_init(struct net_proto_family *ops) | 2453 | void __init tcp_v4_init(struct net_proto_family *ops) |
1874 | { | 2454 | { |
1875 | if (inet_csk_ctl_sock_create(&tcp_socket, PF_INET, SOCK_RAW, IPPROTO_TCP) < 0) | 2455 | if (inet_csk_ctl_sock_create(&tcp_socket, PF_INET, SOCK_RAW, |
2456 | IPPROTO_TCP) < 0) | ||
1876 | panic("Failed to create the TCP control socket.\n"); | 2457 | panic("Failed to create the TCP control socket.\n"); |
1877 | } | 2458 | } |
1878 | 2459 | ||