diff options
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 312 |
1 files changed, 157 insertions, 155 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index fd54c5f8a255..3a25cf743f8b 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -50,6 +50,7 @@ | |||
50 | * a single port at the same time. | 50 | * a single port at the same time. |
51 | */ | 51 | */ |
52 | 52 | ||
53 | #define pr_fmt(fmt) "TCP: " fmt | ||
53 | 54 | ||
54 | #include <linux/bottom_half.h> | 55 | #include <linux/bottom_half.h> |
55 | #include <linux/types.h> | 56 | #include <linux/types.h> |
@@ -90,16 +91,8 @@ EXPORT_SYMBOL(sysctl_tcp_low_latency); | |||
90 | 91 | ||
91 | 92 | ||
92 | #ifdef CONFIG_TCP_MD5SIG | 93 | #ifdef CONFIG_TCP_MD5SIG |
93 | static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, | 94 | static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key, |
94 | __be32 addr); | ||
95 | static int tcp_v4_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key, | ||
96 | __be32 daddr, __be32 saddr, const struct tcphdr *th); | 95 | __be32 daddr, __be32 saddr, const struct tcphdr *th); |
97 | #else | ||
98 | static inline | ||
99 | struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr) | ||
100 | { | ||
101 | return NULL; | ||
102 | } | ||
103 | #endif | 96 | #endif |
104 | 97 | ||
105 | struct inet_hashinfo tcp_hashinfo; | 98 | struct inet_hashinfo tcp_hashinfo; |
@@ -601,6 +594,10 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
601 | struct ip_reply_arg arg; | 594 | struct ip_reply_arg arg; |
602 | #ifdef CONFIG_TCP_MD5SIG | 595 | #ifdef CONFIG_TCP_MD5SIG |
603 | struct tcp_md5sig_key *key; | 596 | struct tcp_md5sig_key *key; |
597 | const __u8 *hash_location = NULL; | ||
598 | unsigned char newhash[16]; | ||
599 | int genhash; | ||
600 | struct sock *sk1 = NULL; | ||
604 | #endif | 601 | #endif |
605 | struct net *net; | 602 | struct net *net; |
606 | 603 | ||
@@ -631,7 +628,36 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
631 | arg.iov[0].iov_len = sizeof(rep.th); | 628 | arg.iov[0].iov_len = sizeof(rep.th); |
632 | 629 | ||
633 | #ifdef CONFIG_TCP_MD5SIG | 630 | #ifdef CONFIG_TCP_MD5SIG |
634 | key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->saddr) : NULL; | 631 | hash_location = tcp_parse_md5sig_option(th); |
632 | if (!sk && hash_location) { | ||
633 | /* | ||
634 | * active side is lost. Try to find listening socket through | ||
635 | * source port, and then find md5 key through listening socket. | ||
636 | * we are not loose security here: | ||
637 | * Incoming packet is checked with md5 hash with finding key, | ||
638 | * no RST generated if md5 hash doesn't match. | ||
639 | */ | ||
640 | sk1 = __inet_lookup_listener(dev_net(skb_dst(skb)->dev), | ||
641 | &tcp_hashinfo, ip_hdr(skb)->daddr, | ||
642 | ntohs(th->source), inet_iif(skb)); | ||
643 | /* don't send rst if it can't find key */ | ||
644 | if (!sk1) | ||
645 | return; | ||
646 | rcu_read_lock(); | ||
647 | key = tcp_md5_do_lookup(sk1, (union tcp_md5_addr *) | ||
648 | &ip_hdr(skb)->saddr, AF_INET); | ||
649 | if (!key) | ||
650 | goto release_sk1; | ||
651 | |||
652 | genhash = tcp_v4_md5_hash_skb(newhash, key, NULL, NULL, skb); | ||
653 | if (genhash || memcmp(hash_location, newhash, 16) != 0) | ||
654 | goto release_sk1; | ||
655 | } else { | ||
656 | key = sk ? tcp_md5_do_lookup(sk, (union tcp_md5_addr *) | ||
657 | &ip_hdr(skb)->saddr, | ||
658 | AF_INET) : NULL; | ||
659 | } | ||
660 | |||
635 | if (key) { | 661 | if (key) { |
636 | rep.opt[0] = htonl((TCPOPT_NOP << 24) | | 662 | rep.opt[0] = htonl((TCPOPT_NOP << 24) | |
637 | (TCPOPT_NOP << 16) | | 663 | (TCPOPT_NOP << 16) | |
@@ -664,6 +690,14 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
664 | 690 | ||
665 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); | 691 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); |
666 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); | 692 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); |
693 | |||
694 | #ifdef CONFIG_TCP_MD5SIG | ||
695 | release_sk1: | ||
696 | if (sk1) { | ||
697 | rcu_read_unlock(); | ||
698 | sock_put(sk1); | ||
699 | } | ||
700 | #endif | ||
667 | } | 701 | } |
668 | 702 | ||
669 | /* The code following below sending ACKs in SYN-RECV and TIME-WAIT states | 703 | /* The code following below sending ACKs in SYN-RECV and TIME-WAIT states |
@@ -764,7 +798,8 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | |||
764 | tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, | 798 | tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, |
765 | req->ts_recent, | 799 | req->ts_recent, |
766 | 0, | 800 | 0, |
767 | tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr), | 801 | tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&ip_hdr(skb)->daddr, |
802 | AF_INET), | ||
768 | inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0, | 803 | inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0, |
769 | ip_hdr(skb)->tos); | 804 | ip_hdr(skb)->tos); |
770 | } | 805 | } |
@@ -842,8 +877,7 @@ int tcp_syn_flood_action(struct sock *sk, | |||
842 | lopt = inet_csk(sk)->icsk_accept_queue.listen_opt; | 877 | lopt = inet_csk(sk)->icsk_accept_queue.listen_opt; |
843 | if (!lopt->synflood_warned) { | 878 | if (!lopt->synflood_warned) { |
844 | lopt->synflood_warned = 1; | 879 | lopt->synflood_warned = 1; |
845 | pr_info("%s: Possible SYN flooding on port %d. %s. " | 880 | pr_info("%s: Possible SYN flooding on port %d. %s. Check SNMP counters.\n", |
846 | " Check SNMP counters.\n", | ||
847 | proto, ntohs(tcp_hdr(skb)->dest), msg); | 881 | proto, ntohs(tcp_hdr(skb)->dest), msg); |
848 | } | 882 | } |
849 | return want_cookie; | 883 | return want_cookie; |
@@ -881,153 +915,138 @@ static struct ip_options_rcu *tcp_v4_save_options(struct sock *sk, | |||
881 | */ | 915 | */ |
882 | 916 | ||
883 | /* Find the Key structure for an address. */ | 917 | /* Find the Key structure for an address. */ |
884 | static struct tcp_md5sig_key * | 918 | struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk, |
885 | tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr) | 919 | const union tcp_md5_addr *addr, |
920 | int family) | ||
886 | { | 921 | { |
887 | struct tcp_sock *tp = tcp_sk(sk); | 922 | struct tcp_sock *tp = tcp_sk(sk); |
888 | int i; | 923 | struct tcp_md5sig_key *key; |
889 | 924 | struct hlist_node *pos; | |
890 | if (!tp->md5sig_info || !tp->md5sig_info->entries4) | 925 | unsigned int size = sizeof(struct in_addr); |
926 | struct tcp_md5sig_info *md5sig; | ||
927 | |||
928 | /* caller either holds rcu_read_lock() or socket lock */ | ||
929 | md5sig = rcu_dereference_check(tp->md5sig_info, | ||
930 | sock_owned_by_user(sk) || | ||
931 | lockdep_is_held(&sk->sk_lock.slock)); | ||
932 | if (!md5sig) | ||
891 | return NULL; | 933 | return NULL; |
892 | for (i = 0; i < tp->md5sig_info->entries4; i++) { | 934 | #if IS_ENABLED(CONFIG_IPV6) |
893 | if (tp->md5sig_info->keys4[i].addr == addr) | 935 | if (family == AF_INET6) |
894 | return &tp->md5sig_info->keys4[i].base; | 936 | size = sizeof(struct in6_addr); |
937 | #endif | ||
938 | hlist_for_each_entry_rcu(key, pos, &md5sig->head, node) { | ||
939 | if (key->family != family) | ||
940 | continue; | ||
941 | if (!memcmp(&key->addr, addr, size)) | ||
942 | return key; | ||
895 | } | 943 | } |
896 | return NULL; | 944 | return NULL; |
897 | } | 945 | } |
946 | EXPORT_SYMBOL(tcp_md5_do_lookup); | ||
898 | 947 | ||
899 | struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk, | 948 | struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk, |
900 | struct sock *addr_sk) | 949 | struct sock *addr_sk) |
901 | { | 950 | { |
902 | return tcp_v4_md5_do_lookup(sk, inet_sk(addr_sk)->inet_daddr); | 951 | union tcp_md5_addr *addr; |
952 | |||
953 | addr = (union tcp_md5_addr *)&inet_sk(addr_sk)->inet_daddr; | ||
954 | return tcp_md5_do_lookup(sk, addr, AF_INET); | ||
903 | } | 955 | } |
904 | EXPORT_SYMBOL(tcp_v4_md5_lookup); | 956 | EXPORT_SYMBOL(tcp_v4_md5_lookup); |
905 | 957 | ||
906 | static struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk, | 958 | static struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk, |
907 | struct request_sock *req) | 959 | struct request_sock *req) |
908 | { | 960 | { |
909 | return tcp_v4_md5_do_lookup(sk, inet_rsk(req)->rmt_addr); | 961 | union tcp_md5_addr *addr; |
962 | |||
963 | addr = (union tcp_md5_addr *)&inet_rsk(req)->rmt_addr; | ||
964 | return tcp_md5_do_lookup(sk, addr, AF_INET); | ||
910 | } | 965 | } |
911 | 966 | ||
912 | /* This can be called on a newly created socket, from other files */ | 967 | /* This can be called on a newly created socket, from other files */ |
913 | int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, | 968 | int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, |
914 | u8 *newkey, u8 newkeylen) | 969 | int family, const u8 *newkey, u8 newkeylen, gfp_t gfp) |
915 | { | 970 | { |
916 | /* Add Key to the list */ | 971 | /* Add Key to the list */ |
917 | struct tcp_md5sig_key *key; | 972 | struct tcp_md5sig_key *key; |
918 | struct tcp_sock *tp = tcp_sk(sk); | 973 | struct tcp_sock *tp = tcp_sk(sk); |
919 | struct tcp4_md5sig_key *keys; | 974 | struct tcp_md5sig_info *md5sig; |
920 | 975 | ||
921 | key = tcp_v4_md5_do_lookup(sk, addr); | 976 | key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET); |
922 | if (key) { | 977 | if (key) { |
923 | /* Pre-existing entry - just update that one. */ | 978 | /* Pre-existing entry - just update that one. */ |
924 | kfree(key->key); | 979 | memcpy(key->key, newkey, newkeylen); |
925 | key->key = newkey; | ||
926 | key->keylen = newkeylen; | 980 | key->keylen = newkeylen; |
927 | } else { | 981 | return 0; |
928 | struct tcp_md5sig_info *md5sig; | 982 | } |
929 | |||
930 | if (!tp->md5sig_info) { | ||
931 | tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info), | ||
932 | GFP_ATOMIC); | ||
933 | if (!tp->md5sig_info) { | ||
934 | kfree(newkey); | ||
935 | return -ENOMEM; | ||
936 | } | ||
937 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); | ||
938 | } | ||
939 | 983 | ||
940 | md5sig = tp->md5sig_info; | 984 | md5sig = rcu_dereference_protected(tp->md5sig_info, |
941 | if (md5sig->entries4 == 0 && | 985 | sock_owned_by_user(sk)); |
942 | tcp_alloc_md5sig_pool(sk) == NULL) { | 986 | if (!md5sig) { |
943 | kfree(newkey); | 987 | md5sig = kmalloc(sizeof(*md5sig), gfp); |
988 | if (!md5sig) | ||
944 | return -ENOMEM; | 989 | return -ENOMEM; |
945 | } | ||
946 | |||
947 | if (md5sig->alloced4 == md5sig->entries4) { | ||
948 | keys = kmalloc((sizeof(*keys) * | ||
949 | (md5sig->entries4 + 1)), GFP_ATOMIC); | ||
950 | if (!keys) { | ||
951 | kfree(newkey); | ||
952 | if (md5sig->entries4 == 0) | ||
953 | tcp_free_md5sig_pool(); | ||
954 | return -ENOMEM; | ||
955 | } | ||
956 | 990 | ||
957 | if (md5sig->entries4) | 991 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); |
958 | memcpy(keys, md5sig->keys4, | 992 | INIT_HLIST_HEAD(&md5sig->head); |
959 | sizeof(*keys) * md5sig->entries4); | 993 | rcu_assign_pointer(tp->md5sig_info, md5sig); |
994 | } | ||
960 | 995 | ||
961 | /* Free old key list, and reference new one */ | 996 | key = sock_kmalloc(sk, sizeof(*key), gfp); |
962 | kfree(md5sig->keys4); | 997 | if (!key) |
963 | md5sig->keys4 = keys; | 998 | return -ENOMEM; |
964 | md5sig->alloced4++; | 999 | if (hlist_empty(&md5sig->head) && !tcp_alloc_md5sig_pool(sk)) { |
965 | } | 1000 | sock_kfree_s(sk, key, sizeof(*key)); |
966 | md5sig->entries4++; | 1001 | return -ENOMEM; |
967 | md5sig->keys4[md5sig->entries4 - 1].addr = addr; | ||
968 | md5sig->keys4[md5sig->entries4 - 1].base.key = newkey; | ||
969 | md5sig->keys4[md5sig->entries4 - 1].base.keylen = newkeylen; | ||
970 | } | 1002 | } |
971 | return 0; | ||
972 | } | ||
973 | EXPORT_SYMBOL(tcp_v4_md5_do_add); | ||
974 | 1003 | ||
975 | static int tcp_v4_md5_add_func(struct sock *sk, struct sock *addr_sk, | 1004 | memcpy(key->key, newkey, newkeylen); |
976 | u8 *newkey, u8 newkeylen) | 1005 | key->keylen = newkeylen; |
977 | { | 1006 | key->family = family; |
978 | return tcp_v4_md5_do_add(sk, inet_sk(addr_sk)->inet_daddr, | 1007 | memcpy(&key->addr, addr, |
979 | newkey, newkeylen); | 1008 | (family == AF_INET6) ? sizeof(struct in6_addr) : |
1009 | sizeof(struct in_addr)); | ||
1010 | hlist_add_head_rcu(&key->node, &md5sig->head); | ||
1011 | return 0; | ||
980 | } | 1012 | } |
1013 | EXPORT_SYMBOL(tcp_md5_do_add); | ||
981 | 1014 | ||
982 | int tcp_v4_md5_do_del(struct sock *sk, __be32 addr) | 1015 | int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family) |
983 | { | 1016 | { |
984 | struct tcp_sock *tp = tcp_sk(sk); | 1017 | struct tcp_sock *tp = tcp_sk(sk); |
985 | int i; | 1018 | struct tcp_md5sig_key *key; |
986 | 1019 | struct tcp_md5sig_info *md5sig; | |
987 | for (i = 0; i < tp->md5sig_info->entries4; i++) { | 1020 | |
988 | if (tp->md5sig_info->keys4[i].addr == addr) { | 1021 | key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET); |
989 | /* Free the key */ | 1022 | if (!key) |
990 | kfree(tp->md5sig_info->keys4[i].base.key); | 1023 | return -ENOENT; |
991 | tp->md5sig_info->entries4--; | 1024 | hlist_del_rcu(&key->node); |
992 | 1025 | atomic_sub(sizeof(*key), &sk->sk_omem_alloc); | |
993 | if (tp->md5sig_info->entries4 == 0) { | 1026 | kfree_rcu(key, rcu); |
994 | kfree(tp->md5sig_info->keys4); | 1027 | md5sig = rcu_dereference_protected(tp->md5sig_info, |
995 | tp->md5sig_info->keys4 = NULL; | 1028 | sock_owned_by_user(sk)); |
996 | tp->md5sig_info->alloced4 = 0; | 1029 | if (hlist_empty(&md5sig->head)) |
997 | tcp_free_md5sig_pool(); | 1030 | tcp_free_md5sig_pool(); |
998 | } else if (tp->md5sig_info->entries4 != i) { | 1031 | return 0; |
999 | /* Need to do some manipulation */ | ||
1000 | memmove(&tp->md5sig_info->keys4[i], | ||
1001 | &tp->md5sig_info->keys4[i+1], | ||
1002 | (tp->md5sig_info->entries4 - i) * | ||
1003 | sizeof(struct tcp4_md5sig_key)); | ||
1004 | } | ||
1005 | return 0; | ||
1006 | } | ||
1007 | } | ||
1008 | return -ENOENT; | ||
1009 | } | 1032 | } |
1010 | EXPORT_SYMBOL(tcp_v4_md5_do_del); | 1033 | EXPORT_SYMBOL(tcp_md5_do_del); |
1011 | 1034 | ||
1012 | static void tcp_v4_clear_md5_list(struct sock *sk) | 1035 | void tcp_clear_md5_list(struct sock *sk) |
1013 | { | 1036 | { |
1014 | struct tcp_sock *tp = tcp_sk(sk); | 1037 | struct tcp_sock *tp = tcp_sk(sk); |
1038 | struct tcp_md5sig_key *key; | ||
1039 | struct hlist_node *pos, *n; | ||
1040 | struct tcp_md5sig_info *md5sig; | ||
1015 | 1041 | ||
1016 | /* Free each key, then the set of key keys, | 1042 | md5sig = rcu_dereference_protected(tp->md5sig_info, 1); |
1017 | * the crypto element, and then decrement our | 1043 | |
1018 | * hold on the last resort crypto. | 1044 | if (!hlist_empty(&md5sig->head)) |
1019 | */ | ||
1020 | if (tp->md5sig_info->entries4) { | ||
1021 | int i; | ||
1022 | for (i = 0; i < tp->md5sig_info->entries4; i++) | ||
1023 | kfree(tp->md5sig_info->keys4[i].base.key); | ||
1024 | tp->md5sig_info->entries4 = 0; | ||
1025 | tcp_free_md5sig_pool(); | 1045 | tcp_free_md5sig_pool(); |
1026 | } | 1046 | hlist_for_each_entry_safe(key, pos, n, &md5sig->head, node) { |
1027 | if (tp->md5sig_info->keys4) { | 1047 | hlist_del_rcu(&key->node); |
1028 | kfree(tp->md5sig_info->keys4); | 1048 | atomic_sub(sizeof(*key), &sk->sk_omem_alloc); |
1029 | tp->md5sig_info->keys4 = NULL; | 1049 | kfree_rcu(key, rcu); |
1030 | tp->md5sig_info->alloced4 = 0; | ||
1031 | } | 1050 | } |
1032 | } | 1051 | } |
1033 | 1052 | ||
@@ -1036,7 +1055,6 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval, | |||
1036 | { | 1055 | { |
1037 | struct tcp_md5sig cmd; | 1056 | struct tcp_md5sig cmd; |
1038 | struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr; | 1057 | struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr; |
1039 | u8 *newkey; | ||
1040 | 1058 | ||
1041 | if (optlen < sizeof(cmd)) | 1059 | if (optlen < sizeof(cmd)) |
1042 | return -EINVAL; | 1060 | return -EINVAL; |
@@ -1047,32 +1065,16 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval, | |||
1047 | if (sin->sin_family != AF_INET) | 1065 | if (sin->sin_family != AF_INET) |
1048 | return -EINVAL; | 1066 | return -EINVAL; |
1049 | 1067 | ||
1050 | if (!cmd.tcpm_key || !cmd.tcpm_keylen) { | 1068 | if (!cmd.tcpm_key || !cmd.tcpm_keylen) |
1051 | if (!tcp_sk(sk)->md5sig_info) | 1069 | return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr, |
1052 | return -ENOENT; | 1070 | AF_INET); |
1053 | return tcp_v4_md5_do_del(sk, sin->sin_addr.s_addr); | ||
1054 | } | ||
1055 | 1071 | ||
1056 | if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN) | 1072 | if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN) |
1057 | return -EINVAL; | 1073 | return -EINVAL; |
1058 | 1074 | ||
1059 | if (!tcp_sk(sk)->md5sig_info) { | 1075 | return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr, |
1060 | struct tcp_sock *tp = tcp_sk(sk); | 1076 | AF_INET, cmd.tcpm_key, cmd.tcpm_keylen, |
1061 | struct tcp_md5sig_info *p; | 1077 | GFP_KERNEL); |
1062 | |||
1063 | p = kzalloc(sizeof(*p), sk->sk_allocation); | ||
1064 | if (!p) | ||
1065 | return -EINVAL; | ||
1066 | |||
1067 | tp->md5sig_info = p; | ||
1068 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); | ||
1069 | } | ||
1070 | |||
1071 | newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, sk->sk_allocation); | ||
1072 | if (!newkey) | ||
1073 | return -ENOMEM; | ||
1074 | return tcp_v4_md5_do_add(sk, sin->sin_addr.s_addr, | ||
1075 | newkey, cmd.tcpm_keylen); | ||
1076 | } | 1078 | } |
1077 | 1079 | ||
1078 | static int tcp_v4_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, | 1080 | static int tcp_v4_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, |
@@ -1098,7 +1100,7 @@ static int tcp_v4_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, | |||
1098 | return crypto_hash_update(&hp->md5_desc, &sg, sizeof(*bp)); | 1100 | return crypto_hash_update(&hp->md5_desc, &sg, sizeof(*bp)); |
1099 | } | 1101 | } |
1100 | 1102 | ||
1101 | static int tcp_v4_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key, | 1103 | static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key, |
1102 | __be32 daddr, __be32 saddr, const struct tcphdr *th) | 1104 | __be32 daddr, __be32 saddr, const struct tcphdr *th) |
1103 | { | 1105 | { |
1104 | struct tcp_md5sig_pool *hp; | 1106 | struct tcp_md5sig_pool *hp; |
@@ -1198,7 +1200,8 @@ static int tcp_v4_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb) | |||
1198 | int genhash; | 1200 | int genhash; |
1199 | unsigned char newhash[16]; | 1201 | unsigned char newhash[16]; |
1200 | 1202 | ||
1201 | hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr); | 1203 | hash_expected = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&iph->saddr, |
1204 | AF_INET); | ||
1202 | hash_location = tcp_parse_md5sig_option(th); | 1205 | hash_location = tcp_parse_md5sig_option(th); |
1203 | 1206 | ||
1204 | /* We've parsed the options - do we have a hash? */ | 1207 | /* We've parsed the options - do we have a hash? */ |
@@ -1224,10 +1227,10 @@ static int tcp_v4_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb) | |||
1224 | 1227 | ||
1225 | if (genhash || memcmp(hash_location, newhash, 16) != 0) { | 1228 | if (genhash || memcmp(hash_location, newhash, 16) != 0) { |
1226 | if (net_ratelimit()) { | 1229 | if (net_ratelimit()) { |
1227 | printk(KERN_INFO "MD5 Hash failed for (%pI4, %d)->(%pI4, %d)%s\n", | 1230 | pr_info("MD5 Hash failed for (%pI4, %d)->(%pI4, %d)%s\n", |
1228 | &iph->saddr, ntohs(th->source), | 1231 | &iph->saddr, ntohs(th->source), |
1229 | &iph->daddr, ntohs(th->dest), | 1232 | &iph->daddr, ntohs(th->dest), |
1230 | genhash ? " tcp_v4_calc_md5_hash failed" : ""); | 1233 | genhash ? " tcp_v4_calc_md5_hash failed" : ""); |
1231 | } | 1234 | } |
1232 | return 1; | 1235 | return 1; |
1233 | } | 1236 | } |
@@ -1396,7 +1399,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1396 | * to destinations, already remembered | 1399 | * to destinations, already remembered |
1397 | * to the moment of synflood. | 1400 | * to the moment of synflood. |
1398 | */ | 1401 | */ |
1399 | LIMIT_NETDEBUG(KERN_DEBUG "TCP: drop open request from %pI4/%u\n", | 1402 | LIMIT_NETDEBUG(KERN_DEBUG pr_fmt("drop open request from %pI4/%u\n"), |
1400 | &saddr, ntohs(tcp_hdr(skb)->source)); | 1403 | &saddr, ntohs(tcp_hdr(skb)->source)); |
1401 | goto drop_and_release; | 1404 | goto drop_and_release; |
1402 | } | 1405 | } |
@@ -1461,6 +1464,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1461 | ireq->opt = NULL; | 1464 | ireq->opt = NULL; |
1462 | newinet->mc_index = inet_iif(skb); | 1465 | newinet->mc_index = inet_iif(skb); |
1463 | newinet->mc_ttl = ip_hdr(skb)->ttl; | 1466 | newinet->mc_ttl = ip_hdr(skb)->ttl; |
1467 | newinet->rcv_tos = ip_hdr(skb)->tos; | ||
1464 | inet_csk(newsk)->icsk_ext_hdr_len = 0; | 1468 | inet_csk(newsk)->icsk_ext_hdr_len = 0; |
1465 | if (inet_opt) | 1469 | if (inet_opt) |
1466 | inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen; | 1470 | inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen; |
@@ -1490,7 +1494,8 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1490 | 1494 | ||
1491 | #ifdef CONFIG_TCP_MD5SIG | 1495 | #ifdef CONFIG_TCP_MD5SIG |
1492 | /* Copy over the MD5 key from the original socket */ | 1496 | /* Copy over the MD5 key from the original socket */ |
1493 | key = tcp_v4_md5_do_lookup(sk, newinet->inet_daddr); | 1497 | key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&newinet->inet_daddr, |
1498 | AF_INET); | ||
1494 | if (key != NULL) { | 1499 | if (key != NULL) { |
1495 | /* | 1500 | /* |
1496 | * We're using one, so create a matching key | 1501 | * We're using one, so create a matching key |
@@ -1498,10 +1503,8 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1498 | * memory, then we end up not copying the key | 1503 | * memory, then we end up not copying the key |
1499 | * across. Shucks. | 1504 | * across. Shucks. |
1500 | */ | 1505 | */ |
1501 | char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); | 1506 | tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newinet->inet_daddr, |
1502 | if (newkey != NULL) | 1507 | AF_INET, key->key, key->keylen, GFP_ATOMIC); |
1503 | tcp_v4_md5_do_add(newsk, newinet->inet_daddr, | ||
1504 | newkey, key->keylen); | ||
1505 | sk_nocaps_add(newsk, NETIF_F_GSO_MASK); | 1508 | sk_nocaps_add(newsk, NETIF_F_GSO_MASK); |
1506 | } | 1509 | } |
1507 | #endif | 1510 | #endif |
@@ -1862,7 +1865,6 @@ EXPORT_SYMBOL(ipv4_specific); | |||
1862 | static const struct tcp_sock_af_ops tcp_sock_ipv4_specific = { | 1865 | static const struct tcp_sock_af_ops tcp_sock_ipv4_specific = { |
1863 | .md5_lookup = tcp_v4_md5_lookup, | 1866 | .md5_lookup = tcp_v4_md5_lookup, |
1864 | .calc_md5_hash = tcp_v4_md5_hash_skb, | 1867 | .calc_md5_hash = tcp_v4_md5_hash_skb, |
1865 | .md5_add = tcp_v4_md5_add_func, | ||
1866 | .md5_parse = tcp_v4_parse_md5_keys, | 1868 | .md5_parse = tcp_v4_parse_md5_keys, |
1867 | }; | 1869 | }; |
1868 | #endif | 1870 | #endif |
@@ -1951,8 +1953,8 @@ void tcp_v4_destroy_sock(struct sock *sk) | |||
1951 | #ifdef CONFIG_TCP_MD5SIG | 1953 | #ifdef CONFIG_TCP_MD5SIG |
1952 | /* Clean up the MD5 key list, if any */ | 1954 | /* Clean up the MD5 key list, if any */ |
1953 | if (tp->md5sig_info) { | 1955 | if (tp->md5sig_info) { |
1954 | tcp_v4_clear_md5_list(sk); | 1956 | tcp_clear_md5_list(sk); |
1955 | kfree(tp->md5sig_info); | 1957 | kfree_rcu(tp->md5sig_info, rcu); |
1956 | tp->md5sig_info = NULL; | 1958 | tp->md5sig_info = NULL; |
1957 | } | 1959 | } |
1958 | #endif | 1960 | #endif |