mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-23 07:12:09 +00:00
tcp: Add l3index to tcp_md5sig_key and md5 functions
Add l3index to tcp_md5sig_key to represent the L3 domain of a key, and add l3index to tcp_md5_do_add and tcp_md5_do_del to fill in the key. With the key now based on an l3index, add the new parameter to the lookup functions and consider the l3index when looking for a match. The l3index comes from the skb when processing ingress packets leveraging the helpers created for socket lookups, tcp_v4_sdif and inet_iif (and the v6 variants). When the sdif index is set it means the packet ingressed a device that is part of an L3 domain and inet_iif points to the VRF device. For egress, the L3 domain is determined from the socket binding and sk_bound_dev_if. Signed-off-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
534322ca3d
commit
dea53bb80e
3 changed files with 113 additions and 51 deletions
|
@ -81,7 +81,8 @@ static const struct tcp_sock_af_ops tcp_sock_ipv6_specific;
|
|||
static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific;
|
||||
#else
|
||||
static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(const struct sock *sk,
|
||||
const struct in6_addr *addr)
|
||||
const struct in6_addr *addr,
|
||||
int l3index)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@ -532,15 +533,22 @@ static void tcp_v6_reqsk_destructor(struct request_sock *req)
|
|||
|
||||
#ifdef CONFIG_TCP_MD5SIG
|
||||
static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(const struct sock *sk,
|
||||
const struct in6_addr *addr)
|
||||
const struct in6_addr *addr,
|
||||
int l3index)
|
||||
{
|
||||
return tcp_md5_do_lookup(sk, (union tcp_md5_addr *)addr, AF_INET6);
|
||||
return tcp_md5_do_lookup(sk, l3index,
|
||||
(union tcp_md5_addr *)addr, AF_INET6);
|
||||
}
|
||||
|
||||
static struct tcp_md5sig_key *tcp_v6_md5_lookup(const struct sock *sk,
|
||||
const struct sock *addr_sk)
|
||||
{
|
||||
return tcp_v6_md5_do_lookup(sk, &addr_sk->sk_v6_daddr);
|
||||
int l3index;
|
||||
|
||||
l3index = l3mdev_master_ifindex_by_index(sock_net(sk),
|
||||
addr_sk->sk_bound_dev_if);
|
||||
return tcp_v6_md5_do_lookup(sk, &addr_sk->sk_v6_daddr,
|
||||
l3index);
|
||||
}
|
||||
|
||||
static int tcp_v6_parse_md5_keys(struct sock *sk, int optname,
|
||||
|
@ -548,6 +556,7 @@ static int tcp_v6_parse_md5_keys(struct sock *sk, int optname,
|
|||
{
|
||||
struct tcp_md5sig cmd;
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr;
|
||||
int l3index = 0;
|
||||
u8 prefixlen;
|
||||
|
||||
if (optlen < sizeof(cmd))
|
||||
|
@ -572,9 +581,9 @@ static int tcp_v6_parse_md5_keys(struct sock *sk, int optname,
|
|||
if (!cmd.tcpm_keylen) {
|
||||
if (ipv6_addr_v4mapped(&sin6->sin6_addr))
|
||||
return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3],
|
||||
AF_INET, prefixlen);
|
||||
AF_INET, prefixlen, l3index);
|
||||
return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr,
|
||||
AF_INET6, prefixlen);
|
||||
AF_INET6, prefixlen, l3index);
|
||||
}
|
||||
|
||||
if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
|
||||
|
@ -582,12 +591,13 @@ static int tcp_v6_parse_md5_keys(struct sock *sk, int optname,
|
|||
|
||||
if (ipv6_addr_v4mapped(&sin6->sin6_addr))
|
||||
return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3],
|
||||
AF_INET, prefixlen, cmd.tcpm_key,
|
||||
cmd.tcpm_keylen, GFP_KERNEL);
|
||||
AF_INET, prefixlen, l3index,
|
||||
cmd.tcpm_key, cmd.tcpm_keylen,
|
||||
GFP_KERNEL);
|
||||
|
||||
return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr,
|
||||
AF_INET6, prefixlen, cmd.tcpm_key,
|
||||
cmd.tcpm_keylen, GFP_KERNEL);
|
||||
AF_INET6, prefixlen, l3index,
|
||||
cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
|
||||
}
|
||||
|
||||
static int tcp_v6_md5_hash_headers(struct tcp_md5sig_pool *hp,
|
||||
|
@ -706,10 +716,15 @@ static bool tcp_v6_inbound_md5_hash(const struct sock *sk,
|
|||
struct tcp_md5sig_key *hash_expected;
|
||||
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
|
||||
const struct tcphdr *th = tcp_hdr(skb);
|
||||
int genhash;
|
||||
int genhash, l3index;
|
||||
u8 newhash[16];
|
||||
|
||||
hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr);
|
||||
/* sdif set, means packet ingressed via a device
|
||||
* in an L3 domain and dif is set to the l3mdev
|
||||
*/
|
||||
l3index = sdif ? dif : 0;
|
||||
|
||||
hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr, l3index);
|
||||
hash_location = tcp_parse_md5sig_option(th);
|
||||
|
||||
/* We've parsed the options - do we have a hash? */
|
||||
|
@ -733,10 +748,10 @@ static bool tcp_v6_inbound_md5_hash(const struct sock *sk,
|
|||
|
||||
if (genhash || memcmp(hash_location, newhash, 16) != 0) {
|
||||
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5FAILURE);
|
||||
net_info_ratelimited("MD5 Hash %s for [%pI6c]:%u->[%pI6c]:%u\n",
|
||||
net_info_ratelimited("MD5 Hash %s for [%pI6c]:%u->[%pI6c]:%u L3 index %d\n",
|
||||
genhash ? "failed" : "mismatch",
|
||||
&ip6h->saddr, ntohs(th->source),
|
||||
&ip6h->daddr, ntohs(th->dest));
|
||||
&ip6h->daddr, ntohs(th->dest), l3index);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -952,10 +967,17 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
|
|||
rcu_read_lock();
|
||||
hash_location = tcp_parse_md5sig_option(th);
|
||||
if (sk && sk_fullsock(sk)) {
|
||||
key = tcp_v6_md5_do_lookup(sk, &ipv6h->saddr);
|
||||
int l3index;
|
||||
|
||||
/* sdif set, means packet ingressed via a device
|
||||
* in an L3 domain and inet_iif is set to it.
|
||||
*/
|
||||
l3index = tcp_v6_sdif(skb) ? tcp_v6_iif_l3_slave(skb) : 0;
|
||||
key = tcp_v6_md5_do_lookup(sk, &ipv6h->saddr, l3index);
|
||||
} else if (hash_location) {
|
||||
int dif = tcp_v6_iif_l3_slave(skb);
|
||||
int sdif = tcp_v6_sdif(skb);
|
||||
int l3index;
|
||||
|
||||
/*
|
||||
* active side is lost. Try to find listening socket through
|
||||
|
@ -972,7 +994,12 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
|
|||
if (!sk1)
|
||||
goto out;
|
||||
|
||||
key = tcp_v6_md5_do_lookup(sk1, &ipv6h->saddr);
|
||||
/* sdif set, means packet ingressed via a device
|
||||
* in an L3 domain and dif is set to it.
|
||||
*/
|
||||
l3index = tcp_v6_sdif(skb) ? dif : 0;
|
||||
|
||||
key = tcp_v6_md5_do_lookup(sk1, &ipv6h->saddr, l3index);
|
||||
if (!key)
|
||||
goto out;
|
||||
|
||||
|
@ -1042,6 +1069,10 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
|
|||
static void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
|
||||
struct request_sock *req)
|
||||
{
|
||||
int l3index;
|
||||
|
||||
l3index = tcp_v6_sdif(skb) ? tcp_v6_iif_l3_slave(skb) : 0;
|
||||
|
||||
/* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV
|
||||
* sk->sk_state == TCP_SYN_RECV -> for Fast Open.
|
||||
*/
|
||||
|
@ -1056,7 +1087,7 @@ static void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
|
|||
req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale,
|
||||
tcp_time_stamp_raw() + tcp_rsk(req)->ts_off,
|
||||
req->ts_recent, sk->sk_bound_dev_if,
|
||||
tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr),
|
||||
tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr, l3index),
|
||||
0, 0, sk->sk_priority);
|
||||
}
|
||||
|
||||
|
@ -1128,6 +1159,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
|
|||
struct sock *newsk;
|
||||
#ifdef CONFIG_TCP_MD5SIG
|
||||
struct tcp_md5sig_key *key;
|
||||
int l3index;
|
||||
#endif
|
||||
struct flowi6 fl6;
|
||||
|
||||
|
@ -1271,8 +1303,10 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
|
|||
newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
|
||||
|
||||
#ifdef CONFIG_TCP_MD5SIG
|
||||
l3index = l3mdev_master_ifindex_by_index(sock_net(sk), ireq->ir_iif);
|
||||
|
||||
/* Copy over the MD5 key from the original socket */
|
||||
key = tcp_v6_md5_do_lookup(sk, &newsk->sk_v6_daddr);
|
||||
key = tcp_v6_md5_do_lookup(sk, &newsk->sk_v6_daddr, l3index);
|
||||
if (key) {
|
||||
/* We're using one, so create a matching key
|
||||
* on the newsk structure. If we fail to get
|
||||
|
@ -1280,7 +1314,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
|
|||
* across. Shucks.
|
||||
*/
|
||||
tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newsk->sk_v6_daddr,
|
||||
AF_INET6, 128, key->key, key->keylen,
|
||||
AF_INET6, 128, l3index, key->key, key->keylen,
|
||||
sk_gfp_mask(sk, GFP_ATOMIC));
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue