aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_ipv4.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r--net/ipv4/tcp_ipv4.c170
1 files changed, 34 insertions, 136 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 12695be2c255..0db9b75c1fa2 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -5,8 +5,6 @@
5 * 5 *
6 * Implementation of the Transmission Control Protocol(TCP). 6 * Implementation of the Transmission Control Protocol(TCP).
7 * 7 *
8 * Version: $Id: tcp_ipv4.c,v 1.240 2002/02/01 22:01:04 davem Exp $
9 *
10 * IPv4 specific functions 8 * IPv4 specific functions
11 * 9 *
12 * 10 *
@@ -91,8 +89,13 @@ static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk,
91 __be32 addr); 89 __be32 addr);
92static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, 90static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
93 __be32 saddr, __be32 daddr, 91 __be32 saddr, __be32 daddr,
94 struct tcphdr *th, int protocol, 92 struct tcphdr *th, unsigned int tcplen);
95 unsigned int tcplen); 93#else
94static inline
95struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr)
96{
97 return NULL;
98}
96#endif 99#endif
97 100
98struct inet_hashinfo __cacheline_aligned tcp_hashinfo = { 101struct inet_hashinfo __cacheline_aligned tcp_hashinfo = {
@@ -582,8 +585,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
582 key, 585 key,
583 ip_hdr(skb)->daddr, 586 ip_hdr(skb)->daddr,
584 ip_hdr(skb)->saddr, 587 ip_hdr(skb)->saddr,
585 &rep.th, IPPROTO_TCP, 588 &rep.th, arg.iov[0].iov_len);
586 arg.iov[0].iov_len);
587 } 589 }
588#endif 590#endif
589 arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, 591 arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
@@ -602,9 +604,9 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
602 outside socket context is ugly, certainly. What can I do? 604 outside socket context is ugly, certainly. What can I do?
603 */ 605 */
604 606
605static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, 607static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
606 struct sk_buff *skb, u32 seq, u32 ack, 608 u32 win, u32 ts, int oif,
607 u32 win, u32 ts) 609 struct tcp_md5sig_key *key)
608{ 610{
609 struct tcphdr *th = tcp_hdr(skb); 611 struct tcphdr *th = tcp_hdr(skb);
610 struct { 612 struct {
@@ -616,10 +618,6 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
616 ]; 618 ];
617 } rep; 619 } rep;
618 struct ip_reply_arg arg; 620 struct ip_reply_arg arg;
619#ifdef CONFIG_TCP_MD5SIG
620 struct tcp_md5sig_key *key;
621 struct tcp_md5sig_key tw_key;
622#endif
623 621
624 memset(&rep.th, 0, sizeof(struct tcphdr)); 622 memset(&rep.th, 0, sizeof(struct tcphdr));
625 memset(&arg, 0, sizeof(arg)); 623 memset(&arg, 0, sizeof(arg));
@@ -645,23 +643,6 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
645 rep.th.window = htons(win); 643 rep.th.window = htons(win);
646 644
647#ifdef CONFIG_TCP_MD5SIG 645#ifdef CONFIG_TCP_MD5SIG
648 /*
649 * The SKB holds an imcoming packet, but may not have a valid ->sk
650 * pointer. This is especially the case when we're dealing with a
651 * TIME_WAIT ack, because the sk structure is long gone, and only
652 * the tcp_timewait_sock remains. So the md5 key is stashed in that
653 * structure, and we use it in preference. I believe that (twsk ||
654 * skb->sk) holds true, but we program defensively.
655 */
656 if (!twsk && skb->sk) {
657 key = tcp_v4_md5_do_lookup(skb->sk, ip_hdr(skb)->daddr);
658 } else if (twsk && twsk->tw_md5_keylen) {
659 tw_key.key = twsk->tw_md5_key;
660 tw_key.keylen = twsk->tw_md5_keylen;
661 key = &tw_key;
662 } else
663 key = NULL;
664
665 if (key) { 646 if (key) {
666 int offset = (ts) ? 3 : 0; 647 int offset = (ts) ? 3 : 0;
667 648
@@ -676,16 +657,15 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
676 key, 657 key,
677 ip_hdr(skb)->daddr, 658 ip_hdr(skb)->daddr,
678 ip_hdr(skb)->saddr, 659 ip_hdr(skb)->saddr,
679 &rep.th, IPPROTO_TCP, 660 &rep.th, arg.iov[0].iov_len);
680 arg.iov[0].iov_len);
681 } 661 }
682#endif 662#endif
683 arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, 663 arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
684 ip_hdr(skb)->saddr, /* XXX */ 664 ip_hdr(skb)->saddr, /* XXX */
685 arg.iov[0].iov_len, IPPROTO_TCP, 0); 665 arg.iov[0].iov_len, IPPROTO_TCP, 0);
686 arg.csumoffset = offsetof(struct tcphdr, check) / 2; 666 arg.csumoffset = offsetof(struct tcphdr, check) / 2;
687 if (twsk) 667 if (oif)
688 arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if; 668 arg.bound_dev_if = oif;
689 669
690 ip_send_reply(dev_net(skb->dev)->ipv4.tcp_sock, skb, 670 ip_send_reply(dev_net(skb->dev)->ipv4.tcp_sock, skb,
691 &arg, arg.iov[0].iov_len); 671 &arg, arg.iov[0].iov_len);
@@ -698,9 +678,12 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
698 struct inet_timewait_sock *tw = inet_twsk(sk); 678 struct inet_timewait_sock *tw = inet_twsk(sk);
699 struct tcp_timewait_sock *tcptw = tcp_twsk(sk); 679 struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
700 680
701 tcp_v4_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, 681 tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
702 tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, 682 tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
703 tcptw->tw_ts_recent); 683 tcptw->tw_ts_recent,
684 tw->tw_bound_dev_if,
685 tcp_twsk_md5_key(tcptw)
686 );
704 687
705 inet_twsk_put(tw); 688 inet_twsk_put(tw);
706} 689}
@@ -708,9 +691,11 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
708static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, 691static void tcp_v4_reqsk_send_ack(struct sk_buff *skb,
709 struct request_sock *req) 692 struct request_sock *req)
710{ 693{
711 tcp_v4_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1, 694 tcp_v4_send_ack(skb, tcp_rsk(req)->snt_isn + 1,
712 tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, 695 tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd,
713 req->ts_recent); 696 req->ts_recent,
697 0,
698 tcp_v4_md5_do_lookup(skb->sk, ip_hdr(skb)->daddr));
714} 699}
715 700
716/* 701/*
@@ -1002,18 +987,12 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval,
1002 987
1003static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, 988static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
1004 __be32 saddr, __be32 daddr, 989 __be32 saddr, __be32 daddr,
1005 struct tcphdr *th, int protocol, 990 struct tcphdr *th,
1006 unsigned int tcplen) 991 unsigned int tcplen)
1007{ 992{
1008 struct scatterlist sg[4];
1009 __u16 data_len;
1010 int block = 0;
1011 __sum16 old_checksum;
1012 struct tcp_md5sig_pool *hp; 993 struct tcp_md5sig_pool *hp;
1013 struct tcp4_pseudohdr *bp; 994 struct tcp4_pseudohdr *bp;
1014 struct hash_desc *desc;
1015 int err; 995 int err;
1016 unsigned int nbytes = 0;
1017 996
1018 /* 997 /*
1019 * Okay, so RFC2385 is turned on for this connection, 998 * Okay, so RFC2385 is turned on for this connection,
@@ -1025,63 +1004,25 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
1025 goto clear_hash_noput; 1004 goto clear_hash_noput;
1026 1005
1027 bp = &hp->md5_blk.ip4; 1006 bp = &hp->md5_blk.ip4;
1028 desc = &hp->md5_desc;
1029 1007
1030 /* 1008 /*
1031 * 1. the TCP pseudo-header (in the order: source IP address, 1009 * The TCP pseudo-header (in the order: source IP address,
1032 * destination IP address, zero-padded protocol number, and 1010 * destination IP address, zero-padded protocol number, and
1033 * segment length) 1011 * segment length)
1034 */ 1012 */
1035 bp->saddr = saddr; 1013 bp->saddr = saddr;
1036 bp->daddr = daddr; 1014 bp->daddr = daddr;
1037 bp->pad = 0; 1015 bp->pad = 0;
1038 bp->protocol = protocol; 1016 bp->protocol = IPPROTO_TCP;
1039 bp->len = htons(tcplen); 1017 bp->len = htons(tcplen);
1040 1018
1041 sg_init_table(sg, 4); 1019 err = tcp_calc_md5_hash(md5_hash, key, sizeof(*bp),
1042 1020 th, tcplen, hp);
1043 sg_set_buf(&sg[block++], bp, sizeof(*bp));
1044 nbytes += sizeof(*bp);
1045
1046 /* 2. the TCP header, excluding options, and assuming a
1047 * checksum of zero/
1048 */
1049 old_checksum = th->check;
1050 th->check = 0;
1051 sg_set_buf(&sg[block++], th, sizeof(struct tcphdr));
1052 nbytes += sizeof(struct tcphdr);
1053
1054 /* 3. the TCP segment data (if any) */
1055 data_len = tcplen - (th->doff << 2);
1056 if (data_len > 0) {
1057 unsigned char *data = (unsigned char *)th + (th->doff << 2);
1058 sg_set_buf(&sg[block++], data, data_len);
1059 nbytes += data_len;
1060 }
1061
1062 /* 4. an independently-specified key or password, known to both
1063 * TCPs and presumably connection-specific
1064 */
1065 sg_set_buf(&sg[block++], key->key, key->keylen);
1066 nbytes += key->keylen;
1067
1068 sg_mark_end(&sg[block - 1]);
1069
1070 /* Now store the Hash into the packet */
1071 err = crypto_hash_init(desc);
1072 if (err)
1073 goto clear_hash;
1074 err = crypto_hash_update(desc, sg, nbytes);
1075 if (err)
1076 goto clear_hash;
1077 err = crypto_hash_final(desc, md5_hash);
1078 if (err) 1021 if (err)
1079 goto clear_hash; 1022 goto clear_hash;
1080 1023
1081 /* Reset header, and free up the crypto */ 1024 /* Free up the crypto pool */
1082 tcp_put_md5sig_pool(); 1025 tcp_put_md5sig_pool();
1083 th->check = old_checksum;
1084
1085out: 1026out:
1086 return 0; 1027 return 0;
1087clear_hash: 1028clear_hash:
@@ -1095,7 +1036,7 @@ int tcp_v4_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
1095 struct sock *sk, 1036 struct sock *sk,
1096 struct dst_entry *dst, 1037 struct dst_entry *dst,
1097 struct request_sock *req, 1038 struct request_sock *req,
1098 struct tcphdr *th, int protocol, 1039 struct tcphdr *th,
1099 unsigned int tcplen) 1040 unsigned int tcplen)
1100{ 1041{
1101 __be32 saddr, daddr; 1042 __be32 saddr, daddr;
@@ -1111,7 +1052,7 @@ int tcp_v4_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
1111 } 1052 }
1112 return tcp_v4_do_calc_md5_hash(md5_hash, key, 1053 return tcp_v4_do_calc_md5_hash(md5_hash, key,
1113 saddr, daddr, 1054 saddr, daddr,
1114 th, protocol, tcplen); 1055 th, tcplen);
1115} 1056}
1116 1057
1117EXPORT_SYMBOL(tcp_v4_calc_md5_hash); 1058EXPORT_SYMBOL(tcp_v4_calc_md5_hash);
@@ -1130,52 +1071,12 @@ static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb)
1130 struct tcp_md5sig_key *hash_expected; 1071 struct tcp_md5sig_key *hash_expected;
1131 const struct iphdr *iph = ip_hdr(skb); 1072 const struct iphdr *iph = ip_hdr(skb);
1132 struct tcphdr *th = tcp_hdr(skb); 1073 struct tcphdr *th = tcp_hdr(skb);
1133 int length = (th->doff << 2) - sizeof(struct tcphdr);
1134 int genhash; 1074 int genhash;
1135 unsigned char *ptr;
1136 unsigned char newhash[16]; 1075 unsigned char newhash[16];
1137 1076
1138 hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr); 1077 hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr);
1078 hash_location = tcp_parse_md5sig_option(th);
1139 1079
1140 /*
1141 * If the TCP option length is less than the TCP_MD5SIG
1142 * option length, then we can shortcut
1143 */
1144 if (length < TCPOLEN_MD5SIG) {
1145 if (hash_expected)
1146 return 1;
1147 else
1148 return 0;
1149 }
1150
1151 /* Okay, we can't shortcut - we have to grub through the options */
1152 ptr = (unsigned char *)(th + 1);
1153 while (length > 0) {
1154 int opcode = *ptr++;
1155 int opsize;
1156
1157 switch (opcode) {
1158 case TCPOPT_EOL:
1159 goto done_opts;
1160 case TCPOPT_NOP:
1161 length--;
1162 continue;
1163 default:
1164 opsize = *ptr++;
1165 if (opsize < 2)
1166 goto done_opts;
1167 if (opsize > length)
1168 goto done_opts;
1169
1170 if (opcode == TCPOPT_MD5SIG) {
1171 hash_location = ptr;
1172 goto done_opts;
1173 }
1174 }
1175 ptr += opsize-2;
1176 length -= opsize;
1177 }
1178done_opts:
1179 /* We've parsed the options - do we have a hash? */ 1080 /* We've parsed the options - do we have a hash? */
1180 if (!hash_expected && !hash_location) 1081 if (!hash_expected && !hash_location)
1181 return 0; 1082 return 0;
@@ -1202,8 +1103,7 @@ done_opts:
1202 genhash = tcp_v4_do_calc_md5_hash(newhash, 1103 genhash = tcp_v4_do_calc_md5_hash(newhash,
1203 hash_expected, 1104 hash_expected,
1204 iph->saddr, iph->daddr, 1105 iph->saddr, iph->daddr,
1205 th, sk->sk_protocol, 1106 th, skb->len);
1206 skb->len);
1207 1107
1208 if (genhash || memcmp(hash_location, newhash, 16) != 0) { 1108 if (genhash || memcmp(hash_location, newhash, 16) != 0) {
1209 if (net_ratelimit()) { 1109 if (net_ratelimit()) {
@@ -1871,7 +1771,7 @@ static int tcp_v4_init_sock(struct sock *sk)
1871 return 0; 1771 return 0;
1872} 1772}
1873 1773
1874int tcp_v4_destroy_sock(struct sock *sk) 1774void tcp_v4_destroy_sock(struct sock *sk)
1875{ 1775{
1876 struct tcp_sock *tp = tcp_sk(sk); 1776 struct tcp_sock *tp = tcp_sk(sk);
1877 1777
@@ -1915,8 +1815,6 @@ int tcp_v4_destroy_sock(struct sock *sk)
1915 } 1815 }
1916 1816
1917 atomic_dec(&tcp_sockets_allocated); 1817 atomic_dec(&tcp_sockets_allocated);
1918
1919 return 0;
1920} 1818}
1921 1819
1922EXPORT_SYMBOL(tcp_v4_destroy_sock); 1820EXPORT_SYMBOL(tcp_v4_destroy_sock);