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.c227
1 files changed, 93 insertions, 134 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 345e24928fa6..1d5fd82c5c08 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -90,16 +90,8 @@ EXPORT_SYMBOL(sysctl_tcp_low_latency);
90 90
91 91
92#ifdef CONFIG_TCP_MD5SIG 92#ifdef CONFIG_TCP_MD5SIG
93static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, 93static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
94 __be32 addr);
95static int tcp_v4_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key,
96 __be32 daddr, __be32 saddr, const struct tcphdr *th); 94 __be32 daddr, __be32 saddr, const struct tcphdr *th);
97#else
98static inline
99struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr)
100{
101 return NULL;
102}
103#endif 95#endif
104 96
105struct inet_hashinfo tcp_hashinfo; 97struct inet_hashinfo tcp_hashinfo;
@@ -631,7 +623,9 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
631 arg.iov[0].iov_len = sizeof(rep.th); 623 arg.iov[0].iov_len = sizeof(rep.th);
632 624
633#ifdef CONFIG_TCP_MD5SIG 625#ifdef CONFIG_TCP_MD5SIG
634 key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->saddr) : NULL; 626 key = sk ? tcp_md5_do_lookup(sk,
627 (union tcp_md5_addr *)&ip_hdr(skb)->saddr,
628 AF_INET) : NULL;
635 if (key) { 629 if (key) {
636 rep.opt[0] = htonl((TCPOPT_NOP << 24) | 630 rep.opt[0] = htonl((TCPOPT_NOP << 24) |
637 (TCPOPT_NOP << 16) | 631 (TCPOPT_NOP << 16) |
@@ -759,7 +753,8 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
759 tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, 753 tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd,
760 req->ts_recent, 754 req->ts_recent,
761 0, 755 0,
762 tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr), 756 tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&ip_hdr(skb)->daddr,
757 AF_INET),
763 inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0, 758 inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0,
764 ip_hdr(skb)->tos); 759 ip_hdr(skb)->tos);
765} 760}
@@ -876,146 +871,124 @@ static struct ip_options_rcu *tcp_v4_save_options(struct sock *sk,
876 */ 871 */
877 872
878/* Find the Key structure for an address. */ 873/* Find the Key structure for an address. */
879static struct tcp_md5sig_key * 874struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk,
880 tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr) 875 const union tcp_md5_addr *addr,
876 int family)
881{ 877{
882 struct tcp_sock *tp = tcp_sk(sk); 878 struct tcp_sock *tp = tcp_sk(sk);
883 int i; 879 struct tcp_md5sig_key *key;
880 struct hlist_node *pos;
881 unsigned int size = sizeof(struct in_addr);
884 882
885 if (!tp->md5sig_info || !tp->md5sig_info->entries4) 883 if (!tp->md5sig_info)
886 return NULL; 884 return NULL;
887 for (i = 0; i < tp->md5sig_info->entries4; i++) { 885#if IS_ENABLED(CONFIG_IPV6)
888 if (tp->md5sig_info->keys4[i].addr == addr) 886 if (family == AF_INET6)
889 return &tp->md5sig_info->keys4[i].base; 887 size = sizeof(struct in6_addr);
888#endif
889 hlist_for_each_entry_rcu(key, pos, &tp->md5sig_info->head, node) {
890 if (key->family != family)
891 continue;
892 if (!memcmp(&key->addr, addr, size))
893 return key;
890 } 894 }
891 return NULL; 895 return NULL;
892} 896}
897EXPORT_SYMBOL(tcp_md5_do_lookup);
893 898
894struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk, 899struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk,
895 struct sock *addr_sk) 900 struct sock *addr_sk)
896{ 901{
897 return tcp_v4_md5_do_lookup(sk, inet_sk(addr_sk)->inet_daddr); 902 union tcp_md5_addr *addr;
903
904 addr = (union tcp_md5_addr *)&inet_sk(addr_sk)->inet_daddr;
905 return tcp_md5_do_lookup(sk, addr, AF_INET);
898} 906}
899EXPORT_SYMBOL(tcp_v4_md5_lookup); 907EXPORT_SYMBOL(tcp_v4_md5_lookup);
900 908
901static struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk, 909static struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk,
902 struct request_sock *req) 910 struct request_sock *req)
903{ 911{
904 return tcp_v4_md5_do_lookup(sk, inet_rsk(req)->rmt_addr); 912 union tcp_md5_addr *addr;
913
914 addr = (union tcp_md5_addr *)&inet_rsk(req)->rmt_addr;
915 return tcp_md5_do_lookup(sk, addr, AF_INET);
905} 916}
906 917
907/* This can be called on a newly created socket, from other files */ 918/* This can be called on a newly created socket, from other files */
908int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, 919int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
909 u8 *newkey, u8 newkeylen) 920 int family, const u8 *newkey, u8 newkeylen, gfp_t gfp)
910{ 921{
911 /* Add Key to the list */ 922 /* Add Key to the list */
912 struct tcp_md5sig_key *key; 923 struct tcp_md5sig_key *key;
913 struct tcp_sock *tp = tcp_sk(sk); 924 struct tcp_sock *tp = tcp_sk(sk);
914 struct tcp4_md5sig_key *keys; 925 struct tcp_md5sig_info *md5sig;
915 926
916 key = tcp_v4_md5_do_lookup(sk, addr); 927 key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET);
917 if (key) { 928 if (key) {
918 /* Pre-existing entry - just update that one. */ 929 /* Pre-existing entry - just update that one. */
919 kfree(key->key); 930 memcpy(key->key, newkey, newkeylen);
920 key->key = newkey;
921 key->keylen = newkeylen; 931 key->keylen = newkeylen;
922 } else { 932 return 0;
923 struct tcp_md5sig_info *md5sig; 933 }
924
925 if (!tp->md5sig_info) {
926 tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info),
927 GFP_ATOMIC);
928 if (!tp->md5sig_info) {
929 kfree(newkey);
930 return -ENOMEM;
931 }
932 sk_nocaps_add(sk, NETIF_F_GSO_MASK);
933 }
934 934
935 md5sig = tp->md5sig_info; 935 md5sig = tp->md5sig_info;
936 if (md5sig->entries4 == 0 && 936 if (!md5sig) {
937 tcp_alloc_md5sig_pool(sk) == NULL) { 937 md5sig = kmalloc(sizeof(*md5sig), gfp);
938 kfree(newkey); 938 if (!md5sig)
939 return -ENOMEM; 939 return -ENOMEM;
940 }
941
942 if (md5sig->alloced4 == md5sig->entries4) {
943 keys = kmalloc((sizeof(*keys) *
944 (md5sig->entries4 + 1)), GFP_ATOMIC);
945 if (!keys) {
946 kfree(newkey);
947 if (md5sig->entries4 == 0)
948 tcp_free_md5sig_pool();
949 return -ENOMEM;
950 }
951 940
952 if (md5sig->entries4) 941 sk_nocaps_add(sk, NETIF_F_GSO_MASK);
953 memcpy(keys, md5sig->keys4, 942 INIT_HLIST_HEAD(&md5sig->head);
954 sizeof(*keys) * md5sig->entries4); 943 tp->md5sig_info = md5sig;
944 }
955 945
956 /* Free old key list, and reference new one */ 946 key = kmalloc(sizeof(*key), gfp);
957 kfree(md5sig->keys4); 947 if (!key)
958 md5sig->keys4 = keys; 948 return -ENOMEM;
959 md5sig->alloced4++; 949 if (hlist_empty(&md5sig->head) && !tcp_alloc_md5sig_pool(sk)) {
960 } 950 kfree(key);
961 md5sig->entries4++; 951 return -ENOMEM;
962 md5sig->keys4[md5sig->entries4 - 1].addr = addr;
963 md5sig->keys4[md5sig->entries4 - 1].base.key = newkey;
964 md5sig->keys4[md5sig->entries4 - 1].base.keylen = newkeylen;
965 } 952 }
953
954 memcpy(key->key, newkey, newkeylen);
955 key->keylen = newkeylen;
956 key->family = family;
957 memcpy(&key->addr, addr,
958 (family == AF_INET6) ? sizeof(struct in6_addr) :
959 sizeof(struct in_addr));
960 hlist_add_head_rcu(&key->node, &md5sig->head);
966 return 0; 961 return 0;
967} 962}
968EXPORT_SYMBOL(tcp_v4_md5_do_add); 963EXPORT_SYMBOL(tcp_md5_do_add);
969 964
970int tcp_v4_md5_do_del(struct sock *sk, __be32 addr) 965int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family)
971{ 966{
972 struct tcp_sock *tp = tcp_sk(sk); 967 struct tcp_sock *tp = tcp_sk(sk);
973 int i; 968 struct tcp_md5sig_key *key;
974 969
975 for (i = 0; i < tp->md5sig_info->entries4; i++) { 970 key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET);
976 if (tp->md5sig_info->keys4[i].addr == addr) { 971 if (!key)
977 /* Free the key */ 972 return -ENOENT;
978 kfree(tp->md5sig_info->keys4[i].base.key); 973 hlist_del_rcu(&key->node);
979 tp->md5sig_info->entries4--; 974 kfree_rcu(key, rcu);
980 975 if (hlist_empty(&tp->md5sig_info->head))
981 if (tp->md5sig_info->entries4 == 0) { 976 tcp_free_md5sig_pool();
982 kfree(tp->md5sig_info->keys4); 977 return 0;
983 tp->md5sig_info->keys4 = NULL;
984 tp->md5sig_info->alloced4 = 0;
985 tcp_free_md5sig_pool();
986 } else if (tp->md5sig_info->entries4 != i) {
987 /* Need to do some manipulation */
988 memmove(&tp->md5sig_info->keys4[i],
989 &tp->md5sig_info->keys4[i+1],
990 (tp->md5sig_info->entries4 - i) *
991 sizeof(struct tcp4_md5sig_key));
992 }
993 return 0;
994 }
995 }
996 return -ENOENT;
997} 978}
998EXPORT_SYMBOL(tcp_v4_md5_do_del); 979EXPORT_SYMBOL(tcp_md5_do_del);
999 980
1000static void tcp_v4_clear_md5_list(struct sock *sk) 981void tcp_clear_md5_list(struct sock *sk)
1001{ 982{
1002 struct tcp_sock *tp = tcp_sk(sk); 983 struct tcp_sock *tp = tcp_sk(sk);
984 struct tcp_md5sig_key *key;
985 struct hlist_node *pos, *n;
1003 986
1004 /* Free each key, then the set of key keys, 987 if (!hlist_empty(&tp->md5sig_info->head))
1005 * the crypto element, and then decrement our
1006 * hold on the last resort crypto.
1007 */
1008 if (tp->md5sig_info->entries4) {
1009 int i;
1010 for (i = 0; i < tp->md5sig_info->entries4; i++)
1011 kfree(tp->md5sig_info->keys4[i].base.key);
1012 tp->md5sig_info->entries4 = 0;
1013 tcp_free_md5sig_pool(); 988 tcp_free_md5sig_pool();
1014 } 989 hlist_for_each_entry_safe(key, pos, n, &tp->md5sig_info->head, node) {
1015 if (tp->md5sig_info->keys4) { 990 hlist_del_rcu(&key->node);
1016 kfree(tp->md5sig_info->keys4); 991 kfree_rcu(key, rcu);
1017 tp->md5sig_info->keys4 = NULL;
1018 tp->md5sig_info->alloced4 = 0;
1019 } 992 }
1020} 993}
1021 994
@@ -1024,7 +997,6 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval,
1024{ 997{
1025 struct tcp_md5sig cmd; 998 struct tcp_md5sig cmd;
1026 struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr; 999 struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr;
1027 u8 *newkey;
1028 1000
1029 if (optlen < sizeof(cmd)) 1001 if (optlen < sizeof(cmd))
1030 return -EINVAL; 1002 return -EINVAL;
@@ -1038,29 +1010,16 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval,
1038 if (!cmd.tcpm_key || !cmd.tcpm_keylen) { 1010 if (!cmd.tcpm_key || !cmd.tcpm_keylen) {
1039 if (!tcp_sk(sk)->md5sig_info) 1011 if (!tcp_sk(sk)->md5sig_info)
1040 return -ENOENT; 1012 return -ENOENT;
1041 return tcp_v4_md5_do_del(sk, sin->sin_addr.s_addr); 1013 return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr,
1014 AF_INET);
1042 } 1015 }
1043 1016
1044 if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN) 1017 if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
1045 return -EINVAL; 1018 return -EINVAL;
1046 1019
1047 if (!tcp_sk(sk)->md5sig_info) { 1020 return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr,
1048 struct tcp_sock *tp = tcp_sk(sk); 1021 AF_INET, cmd.tcpm_key, cmd.tcpm_keylen,
1049 struct tcp_md5sig_info *p; 1022 GFP_KERNEL);
1050
1051 p = kzalloc(sizeof(*p), sk->sk_allocation);
1052 if (!p)
1053 return -EINVAL;
1054
1055 tp->md5sig_info = p;
1056 sk_nocaps_add(sk, NETIF_F_GSO_MASK);
1057 }
1058
1059 newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, sk->sk_allocation);
1060 if (!newkey)
1061 return -ENOMEM;
1062 return tcp_v4_md5_do_add(sk, sin->sin_addr.s_addr,
1063 newkey, cmd.tcpm_keylen);
1064} 1023}
1065 1024
1066static int tcp_v4_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, 1025static int tcp_v4_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp,
@@ -1086,7 +1045,7 @@ static int tcp_v4_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp,
1086 return crypto_hash_update(&hp->md5_desc, &sg, sizeof(*bp)); 1045 return crypto_hash_update(&hp->md5_desc, &sg, sizeof(*bp));
1087} 1046}
1088 1047
1089static int tcp_v4_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key, 1048static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
1090 __be32 daddr, __be32 saddr, const struct tcphdr *th) 1049 __be32 daddr, __be32 saddr, const struct tcphdr *th)
1091{ 1050{
1092 struct tcp_md5sig_pool *hp; 1051 struct tcp_md5sig_pool *hp;
@@ -1186,7 +1145,8 @@ static int tcp_v4_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb)
1186 int genhash; 1145 int genhash;
1187 unsigned char newhash[16]; 1146 unsigned char newhash[16];
1188 1147
1189 hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr); 1148 hash_expected = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&iph->saddr,
1149 AF_INET);
1190 hash_location = tcp_parse_md5sig_option(th); 1150 hash_location = tcp_parse_md5sig_option(th);
1191 1151
1192 /* We've parsed the options - do we have a hash? */ 1152 /* We've parsed the options - do we have a hash? */
@@ -1474,7 +1434,8 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1474 1434
1475#ifdef CONFIG_TCP_MD5SIG 1435#ifdef CONFIG_TCP_MD5SIG
1476 /* Copy over the MD5 key from the original socket */ 1436 /* Copy over the MD5 key from the original socket */
1477 key = tcp_v4_md5_do_lookup(sk, newinet->inet_daddr); 1437 key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&newinet->inet_daddr,
1438 AF_INET);
1478 if (key != NULL) { 1439 if (key != NULL) {
1479 /* 1440 /*
1480 * We're using one, so create a matching key 1441 * We're using one, so create a matching key
@@ -1482,10 +1443,8 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1482 * memory, then we end up not copying the key 1443 * memory, then we end up not copying the key
1483 * across. Shucks. 1444 * across. Shucks.
1484 */ 1445 */
1485 char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); 1446 tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newinet->inet_daddr,
1486 if (newkey != NULL) 1447 AF_INET, key->key, key->keylen, GFP_ATOMIC);
1487 tcp_v4_md5_do_add(newsk, newinet->inet_daddr,
1488 newkey, key->keylen);
1489 sk_nocaps_add(newsk, NETIF_F_GSO_MASK); 1448 sk_nocaps_add(newsk, NETIF_F_GSO_MASK);
1490 } 1449 }
1491#endif 1450#endif
@@ -1934,7 +1893,7 @@ void tcp_v4_destroy_sock(struct sock *sk)
1934#ifdef CONFIG_TCP_MD5SIG 1893#ifdef CONFIG_TCP_MD5SIG
1935 /* Clean up the MD5 key list, if any */ 1894 /* Clean up the MD5 key list, if any */
1936 if (tp->md5sig_info) { 1895 if (tp->md5sig_info) {
1937 tcp_v4_clear_md5_list(sk); 1896 tcp_clear_md5_list(sk);
1938 kfree(tp->md5sig_info); 1897 kfree(tp->md5sig_info);
1939 tp->md5sig_info = NULL; 1898 tp->md5sig_info = NULL;
1940 } 1899 }