Loading include/net/tcp.h +2 −0 Original line number Diff line number Diff line Loading @@ -399,6 +399,8 @@ extern void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx, int estab); extern u8 *tcp_parse_md5sig_option(struct tcphdr *th); /* * TCP v4 functions exported for the inet6 API */ Loading net/ipv4/tcp_input.c +40 −0 Original line number Diff line number Diff line Loading @@ -3450,6 +3450,43 @@ static int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr *th, return 1; } #ifdef CONFIG_TCP_MD5SIG /* * Parse MD5 Signature option */ u8 *tcp_parse_md5sig_option(struct tcphdr *th) { int length = (th->doff << 2) - sizeof (*th); u8 *ptr = (u8*)(th + 1); /* If the TCP option is too short, we can short cut */ if (length < TCPOLEN_MD5SIG) return NULL; while (length > 0) { int opcode = *ptr++; int opsize; switch(opcode) { case TCPOPT_EOL: return NULL; case TCPOPT_NOP: length--; continue; default: opsize = *ptr++; if (opsize < 2 || opsize > length) return NULL; if (opcode == TCPOPT_MD5SIG) return ptr; } ptr += opsize - 2; length -= opsize; } return NULL; } #endif static inline void tcp_store_ts_recent(struct tcp_sock *tp) { tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval; Loading Loading @@ -5467,6 +5504,9 @@ EXPORT_SYMBOL(sysctl_tcp_ecn); EXPORT_SYMBOL(sysctl_tcp_reordering); EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); EXPORT_SYMBOL(tcp_parse_options); #ifdef CONFIG_TCP_MD5SIG EXPORT_SYMBOL(tcp_parse_md5sig_option); #endif EXPORT_SYMBOL(tcp_rcv_established); EXPORT_SYMBOL(tcp_rcv_state_process); EXPORT_SYMBOL(tcp_initialize_rcv_mss); net/ipv4/tcp_ipv4.c +1 −41 Original line number Diff line number Diff line Loading @@ -1134,52 +1134,12 @@ static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb) struct tcp_md5sig_key *hash_expected; const struct iphdr *iph = ip_hdr(skb); struct tcphdr *th = tcp_hdr(skb); int length = (th->doff << 2) - sizeof(struct tcphdr); int genhash; unsigned char *ptr; unsigned char newhash[16]; hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr); hash_location = tcp_parse_md5sig_option(th); /* * If the TCP option length is less than the TCP_MD5SIG * option length, then we can shortcut */ if (length < TCPOLEN_MD5SIG) { if (hash_expected) return 1; else return 0; } /* Okay, we can't shortcut - we have to grub through the options */ ptr = (unsigned char *)(th + 1); while (length > 0) { int opcode = *ptr++; int opsize; switch (opcode) { case TCPOPT_EOL: goto done_opts; case TCPOPT_NOP: length--; continue; default: opsize = *ptr++; if (opsize < 2) goto done_opts; if (opsize > length) goto done_opts; if (opcode == TCPOPT_MD5SIG) { hash_location = ptr; goto done_opts; } } ptr += opsize-2; length -= opsize; } done_opts: /* We've parsed the options - do we have a hash? */ if (!hash_expected && !hash_location) return 0; Loading net/ipv6/tcp_ipv6.c +1 −32 Original line number Diff line number Diff line Loading @@ -844,43 +844,12 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) struct tcp_md5sig_key *hash_expected; struct ipv6hdr *ip6h = ipv6_hdr(skb); struct tcphdr *th = tcp_hdr(skb); int length = (th->doff << 2) - sizeof (*th); int genhash; u8 *ptr; u8 newhash[16]; hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr); hash_location = tcp_parse_md5sig_option(th); /* If the TCP option is too short, we can short cut */ if (length < TCPOLEN_MD5SIG) return hash_expected ? 1 : 0; /* parse options */ ptr = (u8*)(th + 1); while (length > 0) { int opcode = *ptr++; int opsize; switch(opcode) { case TCPOPT_EOL: goto done_opts; case TCPOPT_NOP: length--; continue; default: opsize = *ptr++; if (opsize < 2 || opsize > length) goto done_opts; if (opcode == TCPOPT_MD5SIG) { hash_location = ptr; goto done_opts; } } ptr += opsize - 2; length -= opsize; } done_opts: /* do we have a hash as expected? */ if (!hash_expected) { if (!hash_location) Loading Loading
include/net/tcp.h +2 −0 Original line number Diff line number Diff line Loading @@ -399,6 +399,8 @@ extern void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx, int estab); extern u8 *tcp_parse_md5sig_option(struct tcphdr *th); /* * TCP v4 functions exported for the inet6 API */ Loading
net/ipv4/tcp_input.c +40 −0 Original line number Diff line number Diff line Loading @@ -3450,6 +3450,43 @@ static int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr *th, return 1; } #ifdef CONFIG_TCP_MD5SIG /* * Parse MD5 Signature option */ u8 *tcp_parse_md5sig_option(struct tcphdr *th) { int length = (th->doff << 2) - sizeof (*th); u8 *ptr = (u8*)(th + 1); /* If the TCP option is too short, we can short cut */ if (length < TCPOLEN_MD5SIG) return NULL; while (length > 0) { int opcode = *ptr++; int opsize; switch(opcode) { case TCPOPT_EOL: return NULL; case TCPOPT_NOP: length--; continue; default: opsize = *ptr++; if (opsize < 2 || opsize > length) return NULL; if (opcode == TCPOPT_MD5SIG) return ptr; } ptr += opsize - 2; length -= opsize; } return NULL; } #endif static inline void tcp_store_ts_recent(struct tcp_sock *tp) { tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval; Loading Loading @@ -5467,6 +5504,9 @@ EXPORT_SYMBOL(sysctl_tcp_ecn); EXPORT_SYMBOL(sysctl_tcp_reordering); EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); EXPORT_SYMBOL(tcp_parse_options); #ifdef CONFIG_TCP_MD5SIG EXPORT_SYMBOL(tcp_parse_md5sig_option); #endif EXPORT_SYMBOL(tcp_rcv_established); EXPORT_SYMBOL(tcp_rcv_state_process); EXPORT_SYMBOL(tcp_initialize_rcv_mss);
net/ipv4/tcp_ipv4.c +1 −41 Original line number Diff line number Diff line Loading @@ -1134,52 +1134,12 @@ static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb) struct tcp_md5sig_key *hash_expected; const struct iphdr *iph = ip_hdr(skb); struct tcphdr *th = tcp_hdr(skb); int length = (th->doff << 2) - sizeof(struct tcphdr); int genhash; unsigned char *ptr; unsigned char newhash[16]; hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr); hash_location = tcp_parse_md5sig_option(th); /* * If the TCP option length is less than the TCP_MD5SIG * option length, then we can shortcut */ if (length < TCPOLEN_MD5SIG) { if (hash_expected) return 1; else return 0; } /* Okay, we can't shortcut - we have to grub through the options */ ptr = (unsigned char *)(th + 1); while (length > 0) { int opcode = *ptr++; int opsize; switch (opcode) { case TCPOPT_EOL: goto done_opts; case TCPOPT_NOP: length--; continue; default: opsize = *ptr++; if (opsize < 2) goto done_opts; if (opsize > length) goto done_opts; if (opcode == TCPOPT_MD5SIG) { hash_location = ptr; goto done_opts; } } ptr += opsize-2; length -= opsize; } done_opts: /* We've parsed the options - do we have a hash? */ if (!hash_expected && !hash_location) return 0; Loading
net/ipv6/tcp_ipv6.c +1 −32 Original line number Diff line number Diff line Loading @@ -844,43 +844,12 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) struct tcp_md5sig_key *hash_expected; struct ipv6hdr *ip6h = ipv6_hdr(skb); struct tcphdr *th = tcp_hdr(skb); int length = (th->doff << 2) - sizeof (*th); int genhash; u8 *ptr; u8 newhash[16]; hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr); hash_location = tcp_parse_md5sig_option(th); /* If the TCP option is too short, we can short cut */ if (length < TCPOLEN_MD5SIG) return hash_expected ? 1 : 0; /* parse options */ ptr = (u8*)(th + 1); while (length > 0) { int opcode = *ptr++; int opsize; switch(opcode) { case TCPOPT_EOL: goto done_opts; case TCPOPT_NOP: length--; continue; default: opsize = *ptr++; if (opsize < 2 || opsize > length) goto done_opts; if (opcode == TCPOPT_MD5SIG) { hash_location = ptr; goto done_opts; } } ptr += opsize - 2; length -= opsize; } done_opts: /* do we have a hash as expected? */ if (!hash_expected) { if (!hash_location) Loading