aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2008-04-16 23:29:53 -0400
committerYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2008-06-11 13:38:18 -0400
commit7d5d5525bd88313e6fd90c0659665aee5114bc2d (patch)
tree41517e753220261c8cc46d975977cfd711892f6c
parent81b302a321a0d99ff172b8cb2a8de17bff2f9499 (diff)
tcp md5sig: Share MD5 Signature option parser between IPv4 and IPv6.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
-rw-r--r--include/net/tcp.h2
-rw-r--r--net/ipv4/tcp_input.c40
-rw-r--r--net/ipv4/tcp_ipv4.c42
-rw-r--r--net/ipv6/tcp_ipv6.c33
4 files changed, 44 insertions, 73 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 633147cb6bbc..b1c4b78f1cb8 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -399,6 +399,8 @@ extern void tcp_parse_options(struct sk_buff *skb,
399 struct tcp_options_received *opt_rx, 399 struct tcp_options_received *opt_rx,
400 int estab); 400 int estab);
401 401
402extern u8 *tcp_parse_md5sig_option(struct tcphdr *th);
403
402/* 404/*
403 * TCP v4 functions exported for the inet6 API 405 * TCP v4 functions exported for the inet6 API
404 */ 406 */
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index eba873e9b560..f331e67f2328 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3450,6 +3450,43 @@ static int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr *th,
3450 return 1; 3450 return 1;
3451} 3451}
3452 3452
3453#ifdef CONFIG_TCP_MD5SIG
3454/*
3455 * Parse MD5 Signature option
3456 */
3457u8 *tcp_parse_md5sig_option(struct tcphdr *th)
3458{
3459 int length = (th->doff << 2) - sizeof (*th);
3460 u8 *ptr = (u8*)(th + 1);
3461
3462 /* If the TCP option is too short, we can short cut */
3463 if (length < TCPOLEN_MD5SIG)
3464 return NULL;
3465
3466 while (length > 0) {
3467 int opcode = *ptr++;
3468 int opsize;
3469
3470 switch(opcode) {
3471 case TCPOPT_EOL:
3472 return NULL;
3473 case TCPOPT_NOP:
3474 length--;
3475 continue;
3476 default:
3477 opsize = *ptr++;
3478 if (opsize < 2 || opsize > length)
3479 return NULL;
3480 if (opcode == TCPOPT_MD5SIG)
3481 return ptr;
3482 }
3483 ptr += opsize - 2;
3484 length -= opsize;
3485 }
3486 return NULL;
3487}
3488#endif
3489
3453static inline void tcp_store_ts_recent(struct tcp_sock *tp) 3490static inline void tcp_store_ts_recent(struct tcp_sock *tp)
3454{ 3491{
3455 tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval; 3492 tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval;
@@ -5467,6 +5504,9 @@ EXPORT_SYMBOL(sysctl_tcp_ecn);
5467EXPORT_SYMBOL(sysctl_tcp_reordering); 5504EXPORT_SYMBOL(sysctl_tcp_reordering);
5468EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); 5505EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
5469EXPORT_SYMBOL(tcp_parse_options); 5506EXPORT_SYMBOL(tcp_parse_options);
5507#ifdef CONFIG_TCP_MD5SIG
5508EXPORT_SYMBOL(tcp_parse_md5sig_option);
5509#endif
5470EXPORT_SYMBOL(tcp_rcv_established); 5510EXPORT_SYMBOL(tcp_rcv_established);
5471EXPORT_SYMBOL(tcp_rcv_state_process); 5511EXPORT_SYMBOL(tcp_rcv_state_process);
5472EXPORT_SYMBOL(tcp_initialize_rcv_mss); 5512EXPORT_SYMBOL(tcp_initialize_rcv_mss);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index cd601a866c2f..56f550933644 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1134,52 +1134,12 @@ static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb)
1134 struct tcp_md5sig_key *hash_expected; 1134 struct tcp_md5sig_key *hash_expected;
1135 const struct iphdr *iph = ip_hdr(skb); 1135 const struct iphdr *iph = ip_hdr(skb);
1136 struct tcphdr *th = tcp_hdr(skb); 1136 struct tcphdr *th = tcp_hdr(skb);
1137 int length = (th->doff << 2) - sizeof(struct tcphdr);
1138 int genhash; 1137 int genhash;
1139 unsigned char *ptr;
1140 unsigned char newhash[16]; 1138 unsigned char newhash[16];
1141 1139
1142 hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr); 1140 hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr);
1141 hash_location = tcp_parse_md5sig_option(th);
1143 1142
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 }
1182done_opts:
1183 /* We've parsed the options - do we have a hash? */ 1143 /* We've parsed the options - do we have a hash? */
1184 if (!hash_expected && !hash_location) 1144 if (!hash_expected && !hash_location)
1185 return 0; 1145 return 0;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 715965f0fac0..dd4ddb30a3a9 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -844,43 +844,12 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb)
844 struct tcp_md5sig_key *hash_expected; 844 struct tcp_md5sig_key *hash_expected;
845 struct ipv6hdr *ip6h = ipv6_hdr(skb); 845 struct ipv6hdr *ip6h = ipv6_hdr(skb);
846 struct tcphdr *th = tcp_hdr(skb); 846 struct tcphdr *th = tcp_hdr(skb);
847 int length = (th->doff << 2) - sizeof (*th);
848 int genhash; 847 int genhash;
849 u8 *ptr;
850 u8 newhash[16]; 848 u8 newhash[16];
851 849
852 hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr); 850 hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr);
851 hash_location = tcp_parse_md5sig_option(th);
853 852
854 /* If the TCP option is too short, we can short cut */
855 if (length < TCPOLEN_MD5SIG)
856 return hash_expected ? 1 : 0;
857
858 /* parse options */
859 ptr = (u8*)(th + 1);
860 while (length > 0) {
861 int opcode = *ptr++;
862 int opsize;
863
864 switch(opcode) {
865 case TCPOPT_EOL:
866 goto done_opts;
867 case TCPOPT_NOP:
868 length--;
869 continue;
870 default:
871 opsize = *ptr++;
872 if (opsize < 2 || opsize > length)
873 goto done_opts;
874 if (opcode == TCPOPT_MD5SIG) {
875 hash_location = ptr;
876 goto done_opts;
877 }
878 }
879 ptr += opsize - 2;
880 length -= opsize;
881 }
882
883done_opts:
884 /* do we have a hash as expected? */ 853 /* do we have a hash as expected? */
885 if (!hash_expected) { 854 if (!hash_expected) {
886 if (!hash_location) 855 if (!hash_location)