diff mbox series

[v8,18/26] tcp: authopt: Add v4mapped ipv6 address support

Message ID 2830d885ea3ab71db10a5ca7f28e1c5556e32d43.1662361354.git.cdleonard@gmail.com (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series tcp: Initial support for RFC5925 auth option | expand

Checks

Context Check Description
netdev/tree_selection success Guessed tree name to be net-next, async
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix warning Target tree name not specified in the subject
netdev/cover_letter success Series has a cover letter
netdev/patch_count fail Series longer than 15 patches (and no cover letter)
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 2 this patch: 2
netdev/cc_maintainers warning 1 maintainers not CCed: pabeni@redhat.com
netdev/build_clang success Errors and warnings before: 5 this patch: 5
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 2 this patch: 2
netdev/checkpatch warning WARNING: line length of 82 exceeds 80 columns WARNING: line length of 92 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Leonard Crestez Sept. 5, 2022, 7:05 a.m. UTC
Keys that are added with v4mapped ipv6 addresses will now be used for
ipv4 packets. This outward behavior is similar to how MD5 support
currently works.

The implementation is different - v4mapped keys are still stored with
ipv6 addresses.

Signed-off-by: Leonard Crestez <cdleonard@gmail.com>
---
 net/ipv4/tcp_authopt.c | 35 +++++++++++++++++++++++++----------
 1 file changed, 25 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/net/ipv4/tcp_authopt.c b/net/ipv4/tcp_authopt.c
index 6db06e1edcc7..28c10a916fb3 100644
--- a/net/ipv4/tcp_authopt.c
+++ b/net/ipv4/tcp_authopt.c
@@ -324,27 +324,30 @@  static bool tcp_authopt_key_match_skb_addr(struct tcp_authopt_key_info *key,
 		struct sockaddr_in6 *key_addr = (struct sockaddr_in6 *)&key->addr;
 
 		return ipv6_prefix_equal(&ip6h->saddr,
 					 &key_addr->sin6_addr,
 					 key->prefixlen);
+	} else if (keyaf == AF_INET6 && iph->version == 4) {
+		struct sockaddr_in6 *key_addr = (struct sockaddr_in6 *)&key->addr;
+
+		/* handle ipv6-mapped-ipv4-addresses */
+		if (ipv6_addr_v4mapped(&key_addr->sin6_addr)) {
+			__be32 mask = inet_make_mask(key->prefixlen);
+			__be32 ipv4 = key_addr->sin6_addr.s6_addr32[3];
+
+			return (ipv4 & mask) == ipv4;
+		}
 	}
 
-	/* This actually happens with ipv6-mapped-ipv4-addresses
-	 * IPv6 listen sockets will be asked to validate ipv4 packets.
-	 */
 	return false;
 }
 
 static bool tcp_authopt_key_match_sk_addr(struct tcp_authopt_key_info *key,
 					  const struct sock *addr_sk)
 {
 	u16 keyaf = key->addr.ss_family;
 
-	/* This probably can't happen even with ipv4-mapped-ipv6 */
-	if (keyaf != addr_sk->sk_family)
-		return false;
-
 	if (keyaf == AF_INET) {
 		struct sockaddr_in *key_addr = (struct sockaddr_in *)&key->addr;
 		__be32 mask = inet_make_mask(key->prefixlen);
 
 		return (addr_sk->sk_daddr & mask) == key_addr->sin_addr.s_addr;
@@ -353,10 +356,16 @@  static bool tcp_authopt_key_match_sk_addr(struct tcp_authopt_key_info *key,
 		struct sockaddr_in6 *key_addr = (struct sockaddr_in6 *)&key->addr;
 
 		return ipv6_prefix_equal(&addr_sk->sk_v6_daddr,
 					 &key_addr->sin6_addr,
 					 key->prefixlen);
+	} else if (keyaf == AF_INET6 && addr_sk->sk_family == AF_INET) {
+		struct sockaddr_in6 *key_addr = (struct sockaddr_in6 *)&key->addr;
+		__be32 mask = inet_make_mask(key->prefixlen);
+		__be32 ipv4 = key_addr->sin6_addr.s6_addr32[3];
+
+		return (addr_sk->sk_daddr & mask) == ipv4;
 #endif
 	}
 
 	return false;
 }
@@ -1475,14 +1484,20 @@  static int __tcp_authopt_calc_mac(struct sock *sk,
 				  char *macbuf)
 {
 	struct tcp_authopt_alg_pool *mac_pool;
 	u8 traffic_key[TCP_AUTHOPT_MAX_TRAFFIC_KEY_LEN];
 	int err;
-	bool ipv6 = (sk->sk_family != AF_INET);
+	bool ipv6;
 
-	if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6)
-		return -EINVAL;
+#if IS_ENABLED(CONFIG_IPV6)
+	if (input)
+		ipv6 = (skb->protocol == htons(ETH_P_IPV6));
+	else
+		ipv6 = (sk->sk_family == AF_INET6) && !ipv6_addr_v4mapped(&sk->sk_v6_daddr);
+#else
+	ipv6 = false;
+#endif
 
 	err = tcp_authopt_get_traffic_key(sk, skb, key, info, input, ipv6, traffic_key);
 	if (err)
 		return err;