Lines Matching +full:async +full:- +full:prefix

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * INET An implementation of the TCP Authentication Option (TCP-AO).
28 if (crypto_ahash_setkey(crypto_ahash_reqtfm(hp->req), in tcp_ao_calc_traffic_key()
29 mkt->key, mkt->keylen)) in tcp_ao_calc_traffic_key()
32 ret = crypto_ahash_init(hp->req); in tcp_ao_calc_traffic_key()
37 ahash_request_set_crypt(hp->req, &sg, key, len); in tcp_ao_calc_traffic_key()
38 crypto_ahash_update(hp->req); in tcp_ao_calc_traffic_key()
40 ret = crypto_ahash_final(hp->req); in tcp_ao_calc_traffic_key()
59 * >> A TCP-AO implementation MUST default to ignore incoming ICMPv4 in tcp_ao_ignore_icmp()
60 * messages of Type 3 (destination unreachable), Codes 2-4 (protocol in tcp_ao_ignore_icmp()
61 * unreachable, port unreachable, and fragmentation needed -- ’hard in tcp_ao_ignore_icmp()
64 * for connections in synchronized states (ESTABLISHED, FIN-WAIT-1, FIN- in tcp_ao_ignore_icmp()
65 * WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK, TIME-WAIT) that match MKTs. in tcp_ao_ignore_icmp()
80 switch (sk->sk_state) { in tcp_ao_ignore_icmp()
82 ao = rcu_dereference(tcp_twsk(sk)->ao_info); in tcp_ao_ignore_icmp()
94 ao = rcu_dereference(tcp_sk(sk)->ao_info); in tcp_ao_ignore_icmp()
97 if (ao && !ao->accept_icmps) { in tcp_ao_ignore_icmp()
100 atomic64_inc(&ao->counters.dropped_icmp); in tcp_ao_ignore_icmp()
116 hlist_for_each_entry_rcu(key, &ao->head, node) { in tcp_ao_established_key()
117 if ((sndid >= 0 && key->sndid != sndid) || in tcp_ao_established_key()
118 (rcvid >= 0 && key->rcvid != rcvid)) in tcp_ao_established_key()
131 __be32 a1 = addr1->s_addr & mask; in ipv4_prefix_cmp()
132 __be32 a2 = addr2->s_addr & mask; in ipv4_prefix_cmp()
143 if (sndid >= 0 && key->sndid != sndid) in __tcp_ao_key_cmp()
144 return (key->sndid > sndid) ? 1 : -1; in __tcp_ao_key_cmp()
145 if (rcvid >= 0 && key->rcvid != rcvid) in __tcp_ao_key_cmp()
146 return (key->rcvid > rcvid) ? 1 : -1; in __tcp_ao_key_cmp()
147 if (l3index >= 0 && (key->keyflags & TCP_AO_KEYF_IFINDEX)) { in __tcp_ao_key_cmp()
148 if (key->l3index != l3index) in __tcp_ao_key_cmp()
149 return (key->l3index > l3index) ? 1 : -1; in __tcp_ao_key_cmp()
154 if (key->family != family) in __tcp_ao_key_cmp()
155 return (key->family > family) ? 1 : -1; in __tcp_ao_key_cmp()
158 if (ntohl(key->addr.a4.s_addr) == INADDR_ANY) in __tcp_ao_key_cmp()
160 if (ntohl(addr->a4.s_addr) == INADDR_ANY) in __tcp_ao_key_cmp()
162 return ipv4_prefix_cmp(&key->addr.a4, &addr->a4, prefixlen); in __tcp_ao_key_cmp()
165 if (ipv6_addr_any(&key->addr.a6) || ipv6_addr_any(&addr->a6)) in __tcp_ao_key_cmp()
167 if (ipv6_prefix_equal(&key->addr.a6, &addr->a6, prefixlen)) in __tcp_ao_key_cmp()
169 return memcmp(&key->addr.a6, &addr->a6, sizeof(addr->a6)); in __tcp_ao_key_cmp()
172 return -1; in __tcp_ao_key_cmp()
180 if (family == AF_INET6 && ipv6_addr_v4mapped(&addr->a6)) { in tcp_ao_key_cmp()
181 __be32 addr4 = addr->a6.s6_addr32[3]; in tcp_ao_key_cmp()
193 const union tcp_ao_addr *addr, int family, u8 prefix, in __tcp_ao_do_lookup() argument
202 ao = rcu_dereference_check(tcp_sk(sk)->ao_info, in __tcp_ao_do_lookup()
207 hlist_for_each_entry_rcu(key, &ao->head, node) { in __tcp_ao_do_lookup()
208 u8 prefixlen = min(prefix, key->prefixlen); in __tcp_ao_do_lookup()
231 INIT_HLIST_HEAD(&ao->head); in tcp_ao_alloc_info()
232 refcount_set(&ao->refcnt, 1); in tcp_ao_alloc_info()
239 hlist_add_head_rcu(&mkt->node, &ao->head); in tcp_ao_link_mkt()
253 INIT_HLIST_NODE(&new_key->node); in tcp_ao_copy_key()
254 tcp_sigpool_get(new_key->tcp_sigpool_id); in tcp_ao_copy_key()
255 atomic64_set(&new_key->pkt_good, 0); in tcp_ao_copy_key()
256 atomic64_set(&new_key->pkt_bad, 0); in tcp_ao_copy_key()
265 tcp_sigpool_release(key->tcp_sigpool_id); in tcp_ao_key_free_rcu()
276 ao = rcu_dereference_protected(tcp_twsk(sk)->ao_info, 1); in tcp_ao_destroy_sock()
277 tcp_twsk(sk)->ao_info = NULL; in tcp_ao_destroy_sock()
279 ao = rcu_dereference_protected(tcp_sk(sk)->ao_info, 1); in tcp_ao_destroy_sock()
280 tcp_sk(sk)->ao_info = NULL; in tcp_ao_destroy_sock()
283 if (!ao || !refcount_dec_and_test(&ao->refcnt)) in tcp_ao_destroy_sock()
286 hlist_for_each_entry_safe(key, n, &ao->head, node) { in tcp_ao_destroy_sock()
287 hlist_del_rcu(&key->node); in tcp_ao_destroy_sock()
289 atomic_sub(tcp_ao_sizeof_key(key), &sk->sk_omem_alloc); in tcp_ao_destroy_sock()
290 call_rcu(&key->rcu, tcp_ao_key_free_rcu); in tcp_ao_destroy_sock()
299 struct tcp_ao_info *ao_info = rcu_dereference_protected(tp->ao_info, 1); in tcp_ao_time_wait()
306 hlist_for_each_entry_safe(key, n, &ao_info->head, node) { in tcp_ao_time_wait()
310 refcount_inc(&ao_info->refcnt); in tcp_ao_time_wait()
311 atomic_sub(omem, &(((struct sock *)tp)->sk_omem_alloc)); in tcp_ao_time_wait()
312 rcu_assign_pointer(tcptw->ao_info, ao_info); in tcp_ao_time_wait()
314 tcptw->ao_info = NULL; in tcp_ao_time_wait()
334 err = tcp_sigpool_start(mkt->tcp_sigpool_id, &hp); in tcp_v4_ao_calc_key()
339 tmp->counter = 1; in tcp_v4_ao_calc_key()
340 memcpy(tmp->label, "TCP-AO", 6); in tcp_v4_ao_calc_key()
341 tmp->ctx.saddr = saddr; in tcp_v4_ao_calc_key()
342 tmp->ctx.daddr = daddr; in tcp_v4_ao_calc_key()
343 tmp->ctx.sport = sport; in tcp_v4_ao_calc_key()
344 tmp->ctx.dport = dport; in tcp_v4_ao_calc_key()
345 tmp->ctx.sisn = sisn; in tcp_v4_ao_calc_key()
346 tmp->ctx.disn = disn; in tcp_v4_ao_calc_key()
347 tmp->outlen = htons(tcp_ao_digest_size(mkt) * 8); /* in bits */ in tcp_v4_ao_calc_key()
360 return tcp_v4_ao_calc_key(mkt, key, sk->sk_rcv_saddr, in tcp_v4_ao_calc_key_sk()
361 sk->sk_daddr, htons(sk->sk_num), in tcp_v4_ao_calc_key_sk()
362 sk->sk_dport, sisn, disn); in tcp_v4_ao_calc_key_sk()
364 return tcp_v4_ao_calc_key(mkt, key, sk->sk_daddr, in tcp_v4_ao_calc_key_sk()
365 sk->sk_rcv_saddr, sk->sk_dport, in tcp_v4_ao_calc_key_sk()
366 htons(sk->sk_num), disn, sisn); in tcp_v4_ao_calc_key_sk()
373 if (mkt->family == AF_INET) in tcp_ao_calc_key_sk()
376 else if (mkt->family == AF_INET6) in tcp_ao_calc_key_sk()
380 return -EOPNOTSUPP; in tcp_ao_calc_key_sk()
389 ireq->ir_loc_addr, ireq->ir_rmt_addr, in tcp_v4_ao_calc_key_rsk()
390 htons(ireq->ir_num), ireq->ir_rmt_port, in tcp_v4_ao_calc_key_rsk()
391 htonl(tcp_rsk(req)->snt_isn), in tcp_v4_ao_calc_key_rsk()
392 htonl(tcp_rsk(req)->rcv_isn)); in tcp_v4_ao_calc_key_rsk()
402 return tcp_v4_ao_calc_key(mkt, key, iph->saddr, iph->daddr, in tcp_v4_ao_calc_key_skb()
403 th->source, th->dest, sisn, disn); in tcp_v4_ao_calc_key_skb()
416 return -EAFNOSUPPORT; in tcp_ao_calc_key_skb()
426 bp = hp->scratch; in tcp_v4_ao_hash_pseudoheader()
427 bp->saddr = saddr; in tcp_v4_ao_hash_pseudoheader()
428 bp->daddr = daddr; in tcp_v4_ao_hash_pseudoheader()
429 bp->pad = 0; in tcp_v4_ao_hash_pseudoheader()
430 bp->protocol = IPPROTO_TCP; in tcp_v4_ao_hash_pseudoheader()
431 bp->len = cpu_to_be16(nbytes); in tcp_v4_ao_hash_pseudoheader()
434 ahash_request_set_crypt(hp->req, &sg, NULL, sizeof(*bp)); in tcp_v4_ao_hash_pseudoheader()
435 return crypto_ahash_update(hp->req); in tcp_v4_ao_hash_pseudoheader()
446 if (!th->check) { in tcp_ao_hash_pseudoheader()
448 return tcp_v4_ao_hash_pseudoheader(hp, sk->sk_daddr, in tcp_ao_hash_pseudoheader()
449 sk->sk_rcv_saddr, skb->len); in tcp_ao_hash_pseudoheader()
452 return tcp_v6_ao_hash_pseudoheader(hp, &sk->sk_v6_daddr, in tcp_ao_hash_pseudoheader()
453 &sk->sk_v6_rcv_saddr, skb->len); in tcp_ao_hash_pseudoheader()
456 return -EAFNOSUPPORT; in tcp_ao_hash_pseudoheader()
462 return tcp_v4_ao_hash_pseudoheader(hp, iph->daddr, in tcp_ao_hash_pseudoheader()
463 iph->saddr, skb->len); in tcp_ao_hash_pseudoheader()
468 return tcp_v6_ao_hash_pseudoheader(hp, &iph->daddr, in tcp_ao_hash_pseudoheader()
469 &iph->saddr, skb->len); in tcp_ao_hash_pseudoheader()
472 return -EAFNOSUPPORT; in tcp_ao_hash_pseudoheader()
481 sne--; in tcp_ao_compute_sne()
491 * @hp - used for hashing
492 * @sne - sne value
499 bp = (__be32 *)hp->scratch; in tcp_ao_hash_sne()
503 ahash_request_set_crypt(hp->req, &sg, NULL, sizeof(*bp)); in tcp_ao_hash_sne()
504 return crypto_ahash_update(hp->req); in tcp_ao_hash_sne()
512 int err, len = th->doff << 2; in tcp_ao_hash_header()
514 u8 *hdr = hp->scratch; in tcp_ao_hash_header()
521 (u8 *)th + hash_offset - sizeof(struct tcp_ao_hdr), in tcp_ao_hash_header()
525 ((struct tcphdr *)hdr)->check = 0; in tcp_ao_hash_header()
527 len = th->doff << 2; in tcp_ao_hash_header()
529 /* zero out tcp-ao hash */ in tcp_ao_hash_header()
530 ((struct tcphdr *)hdr)->check = 0; in tcp_ao_hash_header()
535 ahash_request_set_crypt(hp->req, &sg, NULL, len); in tcp_ao_hash_header()
536 err = crypto_ahash_update(hp->req); in tcp_ao_hash_header()
548 int hash_offset = ao_hash - (char *)th; in tcp_ao_hash_hdr()
556 if (tcp_sigpool_start(key->tcp_sigpool_id, &hp)) in tcp_ao_hash_hdr()
568 if (tcp_v4_ao_hash_pseudoheader(&hp, daddr->a4.s_addr, in tcp_ao_hash_hdr()
569 saddr->a4.s_addr, th->doff * 4)) in tcp_ao_hash_hdr()
573 if (tcp_v6_ao_hash_pseudoheader(&hp, &daddr->a6, in tcp_ao_hash_hdr()
574 &saddr->a6, th->doff * 4)) in tcp_ao_hash_hdr()
582 !!(key->keyflags & TCP_AO_KEYF_EXCLUDE_OPT), in tcp_ao_hash_hdr()
616 if (tcp_sigpool_start(key->tcp_sigpool_id, &hp)) in tcp_ao_hash_skb()
628 if (tcp_ao_hash_pseudoheader(family, sk, skb, &hp, skb->len)) in tcp_ao_hash_skb()
631 !!(key->keyflags & TCP_AO_KEYF_EXCLUDE_OPT), in tcp_ao_hash_skb()
634 if (tcp_sigpool_hash_skb_data(&hp, skb, th->doff << 2)) in tcp_ao_hash_skb()
670 return -ENOMEM; in tcp_v4_ao_synack_hash()
688 union tcp_ao_addr *addr = (union tcp_ao_addr *)&ireq->ir_rmt_addr; in tcp_v4_ao_lookup_rsk()
691 l3index = l3mdev_master_ifindex_by_index(sock_net(sk), ireq->ir_iif); in tcp_v4_ao_lookup_rsk()
699 addr_sk->sk_bound_dev_if); in tcp_v4_ao_lookup()
700 union tcp_ao_addr *addr = (union tcp_ao_addr *)&addr_sk->sk_daddr; in tcp_v4_ao_lookup()
714 /* If there's no socket - than initial sisn/disn are unknown. in tcp_ao_prepare_reset()
718 * Linux TCP-AO support provides TCP_AO_ADD_KEY and TCP_AO_REPAIR in tcp_ao_prepare_reset()
719 * options to restore a socket post-reboot. in tcp_ao_prepare_reset()
722 return -ENOTCONN; in tcp_ao_prepare_reset()
724 if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_NEW_SYN_RECV)) { in tcp_ao_prepare_reset()
725 unsigned int family = READ_ONCE(sk->sk_family); in tcp_ao_prepare_reset()
729 if (sk->sk_state == TCP_NEW_SYN_RECV) { in tcp_ao_prepare_reset()
732 sisn = htonl(tcp_rsk(req)->rcv_isn); in tcp_ao_prepare_reset()
733 disn = htonl(tcp_rsk(req)->snt_isn); in tcp_ao_prepare_reset()
734 *sne = tcp_ao_compute_sne(0, tcp_rsk(req)->snt_isn, seq); in tcp_ao_prepare_reset()
736 sisn = th->seq; in tcp_ao_prepare_reset()
740 addr = (union tcp_md5_addr *)&ipv6_hdr(skb)->saddr; in tcp_ao_prepare_reset()
742 addr = (union tcp_md5_addr *)&ip_hdr(skb)->saddr; in tcp_ao_prepare_reset()
744 if (family == AF_INET6 && ipv6_addr_v4mapped(&sk->sk_v6_daddr)) in tcp_ao_prepare_reset()
749 ao_info = rcu_dereference(tcp_sk(sk)->ao_info); in tcp_ao_prepare_reset()
751 return -ENOENT; in tcp_ao_prepare_reset()
753 -1, aoh->rnext_keyid); in tcp_ao_prepare_reset()
755 return -ENOENT; in tcp_ao_prepare_reset()
758 return -ENOMEM; in tcp_ao_prepare_reset()
762 return -1; in tcp_ao_prepare_reset()
763 *keyid = (*key)->rcvid; in tcp_ao_prepare_reset()
768 if (sk->sk_state == TCP_TIME_WAIT) { in tcp_ao_prepare_reset()
769 ao_info = rcu_dereference(tcp_twsk(sk)->ao_info); in tcp_ao_prepare_reset()
770 snd_basis = tcp_twsk(sk)->tw_snd_nxt; in tcp_ao_prepare_reset()
772 ao_info = rcu_dereference(tcp_sk(sk)->ao_info); in tcp_ao_prepare_reset()
773 snd_basis = tcp_sk(sk)->snd_una; in tcp_ao_prepare_reset()
776 return -ENOENT; in tcp_ao_prepare_reset()
778 *key = tcp_ao_established_key(ao_info, aoh->rnext_keyid, -1); in tcp_ao_prepare_reset()
780 return -ENOENT; in tcp_ao_prepare_reset()
782 rnext_key = READ_ONCE(ao_info->rnext_key); in tcp_ao_prepare_reset()
783 *keyid = rnext_key->rcvid; in tcp_ao_prepare_reset()
784 *sne = tcp_ao_compute_sne(READ_ONCE(ao_info->snd_sne), in tcp_ao_prepare_reset()
801 ao = rcu_dereference_protected(tcp_sk(sk)->ao_info, in tcp_ao_transmit_skb()
804 if (unlikely(tcb->tcp_flags & TCPHDR_SYN)) { in tcp_ao_transmit_skb()
807 if (!(tcb->tcp_flags & TCPHDR_ACK)) { in tcp_ao_transmit_skb()
811 return -ENOMEM; in tcp_ao_transmit_skb()
814 disn = ao->risn; in tcp_ao_transmit_skb()
816 tp->af_specific->ao_calc_key_sk(key, traffic_key, in tcp_ao_transmit_skb()
817 sk, ao->lisn, disn, true); in tcp_ao_transmit_skb()
819 sne = tcp_ao_compute_sne(READ_ONCE(ao->snd_sne), READ_ONCE(tp->snd_una), in tcp_ao_transmit_skb()
820 ntohl(th->seq)); in tcp_ao_transmit_skb()
821 tp->af_specific->calc_ao_hash(hash_location, key, sk, skb, traffic_key, in tcp_ao_transmit_skb()
822 hash_location - (u8 *)th, sne); in tcp_ao_transmit_skb()
835 (union tcp_ao_addr *)&iph->saddr, in tcp_ao_inbound_lookup()
841 (union tcp_ao_addr *)&iph->saddr, in tcp_ao_inbound_lookup()
855 /* treq->af_specific is used to perform TCP_AO lookup in tcp_ao_syncookie()
860 treq->af_specific = &tcp_request_sock_ipv6_ops; in tcp_ao_syncookie()
863 treq->af_specific = &tcp_request_sock_ipv4_ops; in tcp_ao_syncookie()
865 treq->used_tcp_ao = false; in tcp_ao_syncookie()
870 l3index = l3mdev_master_ifindex_by_index(sock_net(sk), inet_rsk(req)->ir_iif); in tcp_ao_syncookie()
871 key = tcp_ao_inbound_lookup(family, sk, skb, -1, aoh->keyid, l3index); in tcp_ao_syncookie()
873 /* Key not found, continue without TCP-AO */ in tcp_ao_syncookie()
876 treq->ao_rcv_next = aoh->keyid; in tcp_ao_syncookie()
877 treq->ao_keyid = aoh->rnext_keyid; in tcp_ao_syncookie()
878 treq->used_tcp_ao = true; in tcp_ao_syncookie()
887 u8 maclen = aoh->length - sizeof(struct tcp_ao_hdr); in tcp_ao_verify_hash()
893 atomic64_inc(&info->counters.pkt_bad); in tcp_ao_verify_hash()
894 atomic64_inc(&key->pkt_bad); in tcp_ao_verify_hash()
905 /* XXX: make it per-AF callback? */ in tcp_ao_verify_hash()
907 (phash - (u8 *)th), sne); in tcp_ao_verify_hash()
910 atomic64_inc(&info->counters.pkt_bad); in tcp_ao_verify_hash()
911 atomic64_inc(&key->pkt_bad); in tcp_ao_verify_hash()
918 atomic64_inc(&info->counters.pkt_good); in tcp_ao_verify_hash()
919 atomic64_inc(&key->pkt_good); in tcp_ao_verify_hash()
938 info = rcu_dereference(tcp_sk(sk)->ao_info); in tcp_inbound_ao_hash()
942 "keyid: %u L3index: %d", aoh->keyid, l3index); in tcp_inbound_ao_hash()
946 if (unlikely(th->syn)) { in tcp_inbound_ao_hash()
947 sisn = th->seq; in tcp_inbound_ao_hash()
951 /* Fast-path */ in tcp_inbound_ao_hash()
952 if (likely((1 << sk->sk_state) & TCP_AO_ESTABLISHED)) { in tcp_inbound_ao_hash()
960 key = READ_ONCE(info->rnext_key); in tcp_inbound_ao_hash()
961 if (key->rcvid != aoh->keyid) { in tcp_inbound_ao_hash()
962 key = tcp_ao_established_key(info, -1, aoh->keyid); in tcp_inbound_ao_hash()
968 if (unlikely(th->syn && !th->ack)) in tcp_inbound_ao_hash()
971 sne = tcp_ao_compute_sne(info->rcv_sne, tcp_sk(sk)->rcv_nxt, in tcp_inbound_ao_hash()
972 ntohl(th->seq)); in tcp_inbound_ao_hash()
979 current_key = READ_ONCE(info->current_key); in tcp_inbound_ao_hash()
981 if (unlikely(aoh->rnext_keyid != current_key->sndid)) { in tcp_inbound_ao_hash()
983 key = tcp_ao_established_key(info, aoh->rnext_keyid, -1); in tcp_inbound_ao_hash()
986 WRITE_ONCE(info->current_key, key); in tcp_inbound_ao_hash()
994 * - request sockets would race on those key pointers in tcp_inbound_ao_hash()
995 * - tcp_ao_del_cmd() allows async key removal in tcp_inbound_ao_hash()
997 key = tcp_ao_inbound_lookup(family, sk, skb, -1, aoh->keyid, l3index); in tcp_inbound_ao_hash()
1001 if (th->syn && !th->ack) in tcp_inbound_ao_hash()
1004 if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_NEW_SYN_RECV)) { in tcp_inbound_ao_hash()
1007 sne = tcp_ao_compute_sne(0, tcp_rsk(req)->rcv_isn, in tcp_inbound_ao_hash()
1008 ntohl(th->seq)); in tcp_inbound_ao_hash()
1009 sisn = htonl(tcp_rsk(req)->rcv_isn); in tcp_inbound_ao_hash()
1010 disn = htonl(tcp_rsk(req)->snt_isn); in tcp_inbound_ao_hash()
1011 } else if (unlikely(th->ack && !th->syn)) { in tcp_inbound_ao_hash()
1013 sisn = htonl(ntohl(th->seq) - 1); in tcp_inbound_ao_hash()
1014 disn = htonl(ntohl(th->ack_seq) - 1); in tcp_inbound_ao_hash()
1016 ntohl(th->seq)); in tcp_inbound_ao_hash()
1017 } else if (unlikely(!th->syn)) { in tcp_inbound_ao_hash()
1018 /* no way to figure out initial sisn/disn - drop */ in tcp_inbound_ao_hash()
1021 } else if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { in tcp_inbound_ao_hash()
1022 disn = info->lisn; in tcp_inbound_ao_hash()
1023 if (th->syn || th->rst) in tcp_inbound_ao_hash()
1024 sisn = th->seq; in tcp_inbound_ao_hash()
1026 sisn = info->risn; in tcp_inbound_ao_hash()
1028 WARN_ONCE(1, "TCP-AO: Unexpected sk_state %d", sk->sk_state); in tcp_inbound_ao_hash()
1043 atomic64_inc(&info->counters.key_not_found); in tcp_inbound_ao_hash()
1057 ao->lisn, ao->risn, true); in tcp_ao_cache_traffic_keys()
1063 ao->lisn, ao->risn, false); in tcp_ao_cache_traffic_keys()
1075 ao_info = rcu_dereference_protected(tp->ao_info, in tcp_ao_connect_init()
1081 family = sk->sk_family; in tcp_ao_connect_init()
1083 addr = (union tcp_ao_addr *)&sk->sk_daddr; in tcp_ao_connect_init()
1086 addr = (union tcp_ao_addr *)&sk->sk_v6_daddr; in tcp_ao_connect_init()
1091 sk->sk_bound_dev_if); in tcp_ao_connect_init()
1093 hlist_for_each_entry_rcu(key, &ao_info->head, node) { in tcp_ao_connect_init()
1094 if (!tcp_ao_key_cmp(key, l3index, addr, key->prefixlen, family, -1, -1)) in tcp_ao_connect_init()
1097 if (key == ao_info->current_key) in tcp_ao_connect_init()
1098 ao_info->current_key = NULL; in tcp_ao_connect_init()
1099 if (key == ao_info->rnext_key) in tcp_ao_connect_init()
1100 ao_info->rnext_key = NULL; in tcp_ao_connect_init()
1101 hlist_del_rcu(&key->node); in tcp_ao_connect_init()
1102 atomic_sub(tcp_ao_sizeof_key(key), &sk->sk_omem_alloc); in tcp_ao_connect_init()
1103 call_rcu(&key->rcu, tcp_ao_key_free_rcu); in tcp_ao_connect_init()
1106 key = tp->af_specific->ao_lookup(sk, sk, -1, -1); in tcp_ao_connect_init()
1111 if (!ao_info->current_key) in tcp_ao_connect_init()
1112 ao_info->current_key = key; in tcp_ao_connect_init()
1113 if (!ao_info->rnext_key) in tcp_ao_connect_init()
1114 ao_info->rnext_key = key; in tcp_ao_connect_init()
1115 tp->tcp_header_len += tcp_ao_len_aligned(key); in tcp_ao_connect_init()
1117 ao_info->lisn = htonl(tp->write_seq); in tcp_ao_connect_init()
1118 ao_info->snd_sne = 0; in tcp_ao_connect_init()
1121 * at least one tcp-ao key that matches the remote peer. in tcp_ao_connect_init()
1124 rcu_assign_pointer(tp->ao_info, NULL); in tcp_ao_connect_init()
1134 ao = rcu_dereference_protected(tcp_sk(sk)->ao_info, in tcp_ao_established()
1139 hlist_for_each_entry_rcu(key, &ao->head, node) in tcp_ao_established()
1148 ao = rcu_dereference_protected(tcp_sk(sk)->ao_info, in tcp_ao_finish_connect()
1153 WRITE_ONCE(ao->risn, tcp_hdr(skb)->seq); in tcp_ao_finish_connect()
1154 ao->rcv_sne = 0; in tcp_ao_finish_connect()
1156 hlist_for_each_entry_rcu(key, &ao->head, node) in tcp_ao_finish_connect()
1167 int l3index, ret = -ENOMEM; in tcp_ao_copy_all_matching()
1171 ao = rcu_dereference(tcp_sk(sk)->ao_info); in tcp_ao_copy_all_matching()
1175 /* New socket without TCP-AO on it */ in tcp_ao_copy_all_matching()
1181 return -ENOMEM; in tcp_ao_copy_all_matching()
1182 new_ao->lisn = htonl(tcp_rsk(req)->snt_isn); in tcp_ao_copy_all_matching()
1183 new_ao->risn = htonl(tcp_rsk(req)->rcv_isn); in tcp_ao_copy_all_matching()
1184 new_ao->ao_required = ao->ao_required; in tcp_ao_copy_all_matching()
1185 new_ao->accept_icmps = ao->accept_icmps; in tcp_ao_copy_all_matching()
1188 addr = (union tcp_ao_addr *)&newsk->sk_daddr; in tcp_ao_copy_all_matching()
1191 addr = (union tcp_ao_addr *)&newsk->sk_v6_daddr; in tcp_ao_copy_all_matching()
1194 ret = -EAFNOSUPPORT; in tcp_ao_copy_all_matching()
1198 newsk->sk_bound_dev_if); in tcp_ao_copy_all_matching()
1200 hlist_for_each_entry_rcu(key, &ao->head, node) { in tcp_ao_copy_all_matching()
1201 if (tcp_ao_key_cmp(key, l3index, addr, key->prefixlen, family, -1, -1)) in tcp_ao_copy_all_matching()
1214 /* RFC5925 (7.4.1) specifies that the TCP-AO status in tcp_ao_copy_all_matching()
1216 * At this point the connection was TCP-AO enabled, so in tcp_ao_copy_all_matching()
1220 ret = -EKEYREJECTED; in tcp_ao_copy_all_matching()
1225 ret = -EUSERS; in tcp_ao_copy_all_matching()
1229 key_head = rcu_dereference(hlist_first_rcu(&new_ao->head)); in tcp_ao_copy_all_matching()
1232 key = tcp_ao_established_key(new_ao, tcp_rsk(req)->ao_keyid, -1); in tcp_ao_copy_all_matching()
1234 new_ao->current_key = key; in tcp_ao_copy_all_matching()
1236 new_ao->current_key = first_key; in tcp_ao_copy_all_matching()
1239 key = tcp_ao_established_key(new_ao, -1, tcp_rsk(req)->ao_rcv_next); in tcp_ao_copy_all_matching()
1241 new_ao->rnext_key = key; in tcp_ao_copy_all_matching()
1243 new_ao->rnext_key = first_key; in tcp_ao_copy_all_matching()
1246 rcu_assign_pointer(tcp_sk(newsk)->ao_info, new_ao); in tcp_ao_copy_all_matching()
1251 hlist_for_each_entry_safe(key, key_head, &new_ao->head, node) { in tcp_ao_copy_all_matching()
1252 hlist_del(&key->node); in tcp_ao_copy_all_matching()
1253 tcp_sigpool_release(key->tcp_sigpool_id); in tcp_ao_copy_all_matching()
1254 atomic_sub(tcp_ao_sizeof_key(key), &newsk->sk_omem_alloc); in tcp_ao_copy_all_matching()
1265 if (sk->sk_state == TCP_LISTEN) in tcp_ao_can_set_current_rnext()
1273 struct sockaddr_in *sin = (struct sockaddr_in *)&cmd->addr; in tcp_ao_verify_ipv4()
1276 if (sin->sin_family != AF_INET) in tcp_ao_verify_ipv4()
1277 return -EINVAL; in tcp_ao_verify_ipv4()
1280 if (sin->sin_port != 0) in tcp_ao_verify_ipv4()
1281 return -EINVAL; in tcp_ao_verify_ipv4()
1283 /* Check prefix and trailing 0's in addr */ in tcp_ao_verify_ipv4()
1284 if (cmd->prefix != 0) { in tcp_ao_verify_ipv4()
1287 if (ntohl(sin->sin_addr.s_addr) == INADDR_ANY) in tcp_ao_verify_ipv4()
1288 return -EINVAL; in tcp_ao_verify_ipv4()
1289 if (cmd->prefix > 32) in tcp_ao_verify_ipv4()
1290 return -EINVAL; in tcp_ao_verify_ipv4()
1292 mask = inet_make_mask(cmd->prefix); in tcp_ao_verify_ipv4()
1293 if (sin->sin_addr.s_addr & ~mask) in tcp_ao_verify_ipv4()
1294 return -EINVAL; in tcp_ao_verify_ipv4()
1297 if (ntohl(inet->inet_daddr) != INADDR_ANY && in tcp_ao_verify_ipv4()
1298 (inet->inet_daddr & mask) != sin->sin_addr.s_addr) in tcp_ao_verify_ipv4()
1299 return -EINVAL; in tcp_ao_verify_ipv4()
1301 if (ntohl(sin->sin_addr.s_addr) != INADDR_ANY) in tcp_ao_verify_ipv4()
1302 return -EINVAL; in tcp_ao_verify_ipv4()
1305 *addr = (union tcp_ao_addr *)&sin->sin_addr; in tcp_ao_verify_ipv4()
1319 if (!strcmp("cmac(aes128)", cmd->alg_name)) { in tcp_ao_parse_crypto()
1320 strscpy(cmd->alg_name, "cmac(aes)", sizeof(cmd->alg_name)); in tcp_ao_parse_crypto()
1321 is_kdf_aes_128_cmac = (cmd->keylen != 16); in tcp_ao_parse_crypto()
1322 tmp_key = kmalloc(cmd->keylen, GFP_KERNEL); in tcp_ao_parse_crypto()
1324 return -ENOMEM; in tcp_ao_parse_crypto()
1327 key->maclen = cmd->maclen ?: 12; /* 12 is the default in RFC5925 */ in tcp_ao_parse_crypto()
1329 /* Check: maclen + tcp-ao header <= (MAX_TCP_OPTION_SPACE - mss in tcp_ao_parse_crypto()
1330 * - tstamp (including sackperm) in tcp_ao_parse_crypto()
1331 * - wscale), in tcp_ao_parse_crypto()
1334 * In order to allow D-SACK with TCP-AO, the header size should be: in tcp_ao_parse_crypto()
1335 * (MAX_TCP_OPTION_SPACE - TCPOLEN_TSTAMP_ALIGNED in tcp_ao_parse_crypto()
1336 * - TCPOLEN_SACK_BASE_ALIGNED in tcp_ao_parse_crypto()
1337 * - 2 * TCPOLEN_SACK_PERBLOCK) = 8 (maclen = 4), in tcp_ao_parse_crypto()
1341 * Typical MACs are 96-128 bits (12-16 bytes), but any length in tcp_ao_parse_crypto()
1346 * TCP-AO continues to consume 16 bytes in non-SYN segments, in tcp_ao_parse_crypto()
1350 * such as to handle D-SACK, a smaller TCP-AO MAC would be required in tcp_ao_parse_crypto()
1352 * bytes for the D-SACK variant of the SACK option) [RFC2883]. in tcp_ao_parse_crypto()
1353 * Note that D-SACK is not supportable in TCP MD5 in the presence in tcp_ao_parse_crypto()
1358 syn_tcp_option_space -= TCPOLEN_MSS_ALIGNED; in tcp_ao_parse_crypto()
1359 syn_tcp_option_space -= TCPOLEN_TSTAMP_ALIGNED; in tcp_ao_parse_crypto()
1360 syn_tcp_option_space -= TCPOLEN_WSCALE_ALIGNED; in tcp_ao_parse_crypto()
1362 err = -EMSGSIZE; in tcp_ao_parse_crypto()
1366 key->keylen = cmd->keylen; in tcp_ao_parse_crypto()
1367 memcpy(key->key, cmd->key, cmd->keylen); in tcp_ao_parse_crypto()
1369 err = tcp_sigpool_start(key->tcp_sigpool_id, &hp); in tcp_ao_parse_crypto()
1378 memcpy(tmp_key, cmd->key, cmd->keylen); in tcp_ao_parse_crypto()
1379 sg_init_one(&sg, tmp_key, cmd->keylen); in tcp_ao_parse_crypto()
1381 /* Using zero-key of 16 bytes as described in RFC5926 */ in tcp_ao_parse_crypto()
1391 ahash_request_set_crypt(hp.req, &sg, key->key, cmd->keylen); in tcp_ao_parse_crypto()
1399 key->keylen = 16; in tcp_ao_parse_crypto()
1402 err = crypto_ahash_setkey(tfm, key->key, key->keylen); in tcp_ao_parse_crypto()
1409 if (tcp_ao_maclen(key) > key->digest_size) in tcp_ao_parse_crypto()
1410 return -EINVAL; in tcp_ao_parse_crypto()
1426 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd->addr; in tcp_ao_verify_ipv6()
1427 struct in6_addr *addr = &sin6->sin6_addr; in tcp_ao_verify_ipv6()
1428 u8 prefix = cmd->prefix; in tcp_ao_verify_ipv6() local
1430 if (sin6->sin6_family != AF_INET6) in tcp_ao_verify_ipv6()
1431 return -EINVAL; in tcp_ao_verify_ipv6()
1434 if (sin6->sin6_port != 0) in tcp_ao_verify_ipv6()
1435 return -EINVAL; in tcp_ao_verify_ipv6()
1437 /* Check prefix and trailing 0's in addr */ in tcp_ao_verify_ipv6()
1438 if (cmd->prefix != 0 && ipv6_addr_v4mapped(addr)) { in tcp_ao_verify_ipv6()
1439 __be32 addr4 = addr->s6_addr32[3]; in tcp_ao_verify_ipv6()
1442 if (prefix > 32 || ntohl(addr4) == INADDR_ANY) in tcp_ao_verify_ipv6()
1443 return -EINVAL; in tcp_ao_verify_ipv6()
1445 mask = inet_make_mask(prefix); in tcp_ao_verify_ipv6()
1447 return -EINVAL; in tcp_ao_verify_ipv6()
1450 if (!ipv6_addr_any(&sk->sk_v6_daddr)) { in tcp_ao_verify_ipv6()
1451 __be32 daddr4 = sk->sk_v6_daddr.s6_addr32[3]; in tcp_ao_verify_ipv6()
1453 if (!ipv6_addr_v4mapped(&sk->sk_v6_daddr)) in tcp_ao_verify_ipv6()
1454 return -EINVAL; in tcp_ao_verify_ipv6()
1456 return -EINVAL; in tcp_ao_verify_ipv6()
1459 *paddr = (union tcp_ao_addr *)&addr->s6_addr32[3]; in tcp_ao_verify_ipv6()
1462 } else if (cmd->prefix != 0) { in tcp_ao_verify_ipv6()
1465 if (ipv6_addr_any(addr) || prefix > 128) in tcp_ao_verify_ipv6()
1466 return -EINVAL; in tcp_ao_verify_ipv6()
1468 ipv6_addr_prefix(&pfx, addr, prefix); in tcp_ao_verify_ipv6()
1470 return -EINVAL; in tcp_ao_verify_ipv6()
1473 if (!ipv6_addr_any(&sk->sk_v6_daddr) && in tcp_ao_verify_ipv6()
1474 !ipv6_prefix_equal(&sk->sk_v6_daddr, addr, prefix)) in tcp_ao_verify_ipv6()
1476 return -EINVAL; in tcp_ao_verify_ipv6()
1479 return -EINVAL; in tcp_ao_verify_ipv6()
1490 return -EOPNOTSUPP; in tcp_ao_verify_ipv6()
1497 return rcu_dereference_protected(tcp_sk(sk)->ao_info, in setsockopt_ao_info()
1499 } else if (sk->sk_state == TCP_TIME_WAIT) { in setsockopt_ao_info()
1500 return rcu_dereference_protected(tcp_twsk(sk)->ao_info, in setsockopt_ao_info()
1503 return ERR_PTR(-ESOCKTNOSUPPORT); in setsockopt_ao_info()
1509 return rcu_dereference(tcp_sk(sk)->ao_info); in getsockopt_ao_info()
1510 else if (sk->sk_state == TCP_TIME_WAIT) in getsockopt_ao_info()
1511 return rcu_dereference(tcp_twsk(sk)->ao_info); in getsockopt_ao_info()
1513 return ERR_PTR(-ESOCKTNOSUPPORT); in getsockopt_ao_info()
1522 const char *algo = cmd->alg_name; in tcp_ao_key_alloc()
1530 /* Force null-termination of alg_name */ in tcp_ao_key_alloc()
1531 cmd->alg_name[ARRAY_SIZE(cmd->alg_name) - 1] = '\0'; in tcp_ao_key_alloc()
1537 /* Full TCP header (th->doff << 2) should fit into scratch area, in tcp_ao_key_alloc()
1555 err = -ENOMEM; in tcp_ao_key_alloc()
1559 key->tcp_sigpool_id = pool_id; in tcp_ao_key_alloc()
1560 key->digest_size = digest_size; in tcp_ao_key_alloc()
1579 return -EINVAL; in tcp_ao_add_cmd()
1586 return -EINVAL; in tcp_ao_add_cmd()
1589 return -EINVAL; in tcp_ao_add_cmd()
1599 return -EINVAL; in tcp_ao_add_cmd()
1603 return -EINVAL; in tcp_ao_add_cmd()
1607 return -EINVAL; in tcp_ao_add_cmd()
1611 int bound_dev_if = READ_ONCE(sk->sk_bound_dev_if); in tcp_ao_add_cmd()
1617 l3index = dev->ifindex; in tcp_ao_add_cmd()
1621 return -EINVAL; in tcp_ao_add_cmd()
1625 * non peer-matching key on an established TCP-AO in tcp_ao_add_cmd()
1628 if (!((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) in tcp_ao_add_cmd()
1629 return -EINVAL; in tcp_ao_add_cmd()
1633 * re-bind to a different dev (with CAP_NET_RAW). in tcp_ao_add_cmd()
1642 /* Don't allow keys for peers that have a matching TCP-MD5 key */ in tcp_ao_add_cmd()
1644 /* Non-_exact version of tcp_md5_do_lookup() will in tcp_ao_add_cmd()
1650 return -EKEYREJECTED; in tcp_ao_add_cmd()
1653 return -EKEYREJECTED; in tcp_ao_add_cmd()
1663 return -ENOMEM; in tcp_ao_add_cmd()
1671 if (__tcp_ao_do_lookup(sk, l3index, addr, family, cmd.prefix, -1, cmd.rcvid)) in tcp_ao_add_cmd()
1672 return -EEXIST; in tcp_ao_add_cmd()
1674 cmd.prefix, cmd.sndid, -1)) in tcp_ao_add_cmd()
1675 return -EEXIST; in tcp_ao_add_cmd()
1684 INIT_HLIST_NODE(&key->node); in tcp_ao_add_cmd()
1685 memcpy(&key->addr, addr, (family == AF_INET) ? sizeof(struct in_addr) : in tcp_ao_add_cmd()
1687 key->prefixlen = cmd.prefix; in tcp_ao_add_cmd()
1688 key->family = family; in tcp_ao_add_cmd()
1689 key->keyflags = cmd.keyflags; in tcp_ao_add_cmd()
1690 key->sndid = cmd.sndid; in tcp_ao_add_cmd()
1691 key->rcvid = cmd.rcvid; in tcp_ao_add_cmd()
1692 key->l3index = l3index; in tcp_ao_add_cmd()
1693 atomic64_set(&key->pkt_good, 0); in tcp_ao_add_cmd()
1694 atomic64_set(&key->pkt_bad, 0); in tcp_ao_add_cmd()
1700 if (!((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) { in tcp_ao_add_cmd()
1703 ao_info->current_key = key; in tcp_ao_add_cmd()
1704 ao_info->rnext_key = key; in tcp_ao_add_cmd()
1711 ret = -EUSERS; in tcp_ao_add_cmd()
1715 rcu_assign_pointer(tcp_sk(sk)->ao_info, ao_info); in tcp_ao_add_cmd()
1719 WRITE_ONCE(ao_info->current_key, key); in tcp_ao_add_cmd()
1721 WRITE_ONCE(ao_info->rnext_key, key); in tcp_ao_add_cmd()
1725 atomic_sub(tcp_ao_sizeof_key(key), &sk->sk_omem_alloc); in tcp_ao_add_cmd()
1726 tcp_sigpool_release(key->tcp_sigpool_id); in tcp_ao_add_cmd()
1741 hlist_del_rcu(&key->node); in tcp_ao_delete_key()
1743 /* Support for async delete on listening sockets: as they don't in tcp_ao_delete_key()
1748 atomic_sub(tcp_ao_sizeof_key(key), &sk->sk_omem_alloc); in tcp_ao_delete_key()
1749 call_rcu(&key->rcu, tcp_ao_key_free_rcu); in tcp_ao_delete_key()
1755 * after which the key is off-list and can't be looked up again; in tcp_ao_delete_key()
1760 * changed it in forced-delete). in tcp_ao_delete_key()
1764 WRITE_ONCE(ao_info->current_key, new_current); in tcp_ao_delete_key()
1766 WRITE_ONCE(ao_info->rnext_key, new_rnext); in tcp_ao_delete_key()
1768 if (unlikely(READ_ONCE(ao_info->current_key) == key || in tcp_ao_delete_key()
1769 READ_ONCE(ao_info->rnext_key) == key)) { in tcp_ao_delete_key()
1770 err = -EBUSY; in tcp_ao_delete_key()
1774 atomic_sub(tcp_ao_sizeof_key(key), &sk->sk_omem_alloc); in tcp_ao_delete_key()
1775 call_rcu(&key->rcu, tcp_ao_key_free_rcu); in tcp_ao_delete_key()
1779 hlist_add_head_rcu(&key->node, &ao_info->head); in tcp_ao_delete_key()
1792 __u8 prefix; in tcp_ao_del_cmd() local
1796 return -EINVAL; in tcp_ao_del_cmd()
1803 return -EINVAL; in tcp_ao_del_cmd()
1807 return -EINVAL; in tcp_ao_del_cmd()
1811 return -EINVAL; in tcp_ao_del_cmd()
1819 return -EINVAL; in tcp_ao_del_cmd()
1825 return -ENOENT; in tcp_ao_del_cmd()
1833 new_current = tcp_ao_established_key(ao_info, cmd.current_key, -1); in tcp_ao_del_cmd()
1835 return -ENOENT; in tcp_ao_del_cmd()
1838 new_rnext = tcp_ao_established_key(ao_info, -1, cmd.rnext); in tcp_ao_del_cmd()
1840 return -ENOENT; in tcp_ao_del_cmd()
1842 if (cmd.del_async && sk->sk_state != TCP_LISTEN) in tcp_ao_del_cmd()
1843 return -EINVAL; in tcp_ao_del_cmd()
1848 addr = (union tcp_ao_addr *)&sin->sin_addr; in tcp_ao_del_cmd()
1850 port = ntohs(sin->sin_port); in tcp_ao_del_cmd()
1853 struct in6_addr *addr6 = &sin6->sin6_addr; in tcp_ao_del_cmd()
1856 addr = (union tcp_ao_addr *)&addr6->s6_addr32[3]; in tcp_ao_del_cmd()
1863 port = ntohs(sin6->sin6_port); in tcp_ao_del_cmd()
1865 prefix = cmd.prefix; in tcp_ao_del_cmd()
1869 return -EINVAL; in tcp_ao_del_cmd()
1874 * specify how-to coordinate key removal, but says: in tcp_ao_del_cmd()
1878 hlist_for_each_entry_rcu(key, &ao_info->head, node) { in tcp_ao_del_cmd()
1879 if (cmd.sndid != key->sndid || in tcp_ao_del_cmd()
1880 cmd.rcvid != key->rcvid) in tcp_ao_del_cmd()
1883 if (family != key->family || in tcp_ao_del_cmd()
1884 prefix != key->prefixlen || in tcp_ao_del_cmd()
1885 memcmp(addr, &key->addr, addr_len)) in tcp_ao_del_cmd()
1889 (key->keyflags & TCP_AO_KEYF_IFINDEX)) in tcp_ao_del_cmd()
1892 if (key->l3index != l3index) in tcp_ao_del_cmd()
1901 return -ENOENT; in tcp_ao_del_cmd()
1904 /* cmd.ao_required makes a socket TCP-AO only.
1907 * ao_info->ao_required on inbound tcp segment fast-path.
1917 md5sig = rcu_dereference_check(tcp_sk(sk)->md5sig_info, in tcp_ao_required_verify()
1922 if (rcu_dereference_check(hlist_first_rcu(&md5sig->head), in tcp_ao_required_verify()
1939 return -EINVAL; in tcp_ao_info_cmd()
1947 return -EINVAL; in tcp_ao_info_cmd()
1951 return -EINVAL; in tcp_ao_info_cmd()
1957 if (!((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) in tcp_ao_info_cmd()
1958 return -EINVAL; in tcp_ao_info_cmd()
1961 return -ENOMEM; in tcp_ao_info_cmd()
1966 return -EKEYREJECTED; in tcp_ao_info_cmd()
1974 new_current = tcp_ao_established_key(ao_info, cmd.current_key, -1); in tcp_ao_info_cmd()
1976 err = -ENOENT; in tcp_ao_info_cmd()
1981 new_rnext = tcp_ao_established_key(ao_info, -1, cmd.rnext); in tcp_ao_info_cmd()
1983 err = -ENOENT; in tcp_ao_info_cmd()
1988 atomic64_set(&ao_info->counters.pkt_good, cmd.pkt_good); in tcp_ao_info_cmd()
1989 atomic64_set(&ao_info->counters.pkt_bad, cmd.pkt_bad); in tcp_ao_info_cmd()
1990 atomic64_set(&ao_info->counters.key_not_found, cmd.pkt_key_not_found); in tcp_ao_info_cmd()
1991 atomic64_set(&ao_info->counters.ao_required, cmd.pkt_ao_required); in tcp_ao_info_cmd()
1992 atomic64_set(&ao_info->counters.dropped_icmp, cmd.pkt_dropped_icmp); in tcp_ao_info_cmd()
1995 ao_info->ao_required = cmd.ao_required; in tcp_ao_info_cmd()
1996 ao_info->accept_icmps = cmd.accept_icmps; in tcp_ao_info_cmd()
1998 WRITE_ONCE(ao_info->current_key, new_current); in tcp_ao_info_cmd()
2000 WRITE_ONCE(ao_info->rnext_key, new_rnext); in tcp_ao_info_cmd()
2003 err = -EUSERS; in tcp_ao_info_cmd()
2007 rcu_assign_pointer(tcp_sk(sk)->ao_info, ao_info); in tcp_ao_info_cmd()
2020 return -EAFNOSUPPORT; in tcp_parse_ao()
2031 return -EINVAL; in tcp_parse_ao()
2057 * returned, otherwise only keys matching <addr, prefix, sndid, rcvid>
2067 * (ksize - usize) are interpreted as 0 by the kernel.
2069 * older kernel. The trailing bytes unknown to the kernel (usize - ksize)
2070 * are checked to ensure they are zeroed, otherwise -E2BIG is returned.
2091 return -EFAULT; in tcp_ao_copy_mkts_to_user()
2094 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2103 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2105 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2107 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2110 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2113 l3index = (opt_in.keyflags & TCP_AO_KEYF_IFINDEX) ? opt_in.ifindex : -1; in tcp_ao_copy_mkts_to_user()
2117 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2127 port = sin->sin_port; in tcp_ao_copy_mkts_to_user()
2128 addr = (union tcp_ao_addr *)&sin->sin_addr; in tcp_ao_copy_mkts_to_user()
2130 if (opt_in.prefix > 32) in tcp_ao_copy_mkts_to_user()
2131 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2133 if (ntohl(sin->sin_addr.s_addr) == INADDR_ANY && in tcp_ao_copy_mkts_to_user()
2134 opt_in.prefix != 0) in tcp_ao_copy_mkts_to_user()
2135 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2137 mask = inet_make_mask(opt_in.prefix); in tcp_ao_copy_mkts_to_user()
2138 if (sin->sin_addr.s_addr & ~mask) in tcp_ao_copy_mkts_to_user()
2139 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2148 addr = (union tcp_ao_addr *)&sin6->sin6_addr; in tcp_ao_copy_mkts_to_user()
2149 addr6 = &sin6->sin6_addr; in tcp_ao_copy_mkts_to_user()
2150 port = sin6->sin6_port; in tcp_ao_copy_mkts_to_user()
2156 if (opt_in.prefix != 0) { in tcp_ao_copy_mkts_to_user()
2158 __be32 mask, addr4 = addr6->s6_addr32[3]; in tcp_ao_copy_mkts_to_user()
2160 if (opt_in.prefix > 32 || in tcp_ao_copy_mkts_to_user()
2162 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2163 mask = inet_make_mask(opt_in.prefix); in tcp_ao_copy_mkts_to_user()
2165 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2170 opt_in.prefix > 128) in tcp_ao_copy_mkts_to_user()
2171 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2173 ipv6_addr_prefix(&pfx, addr6, opt_in.prefix); in tcp_ao_copy_mkts_to_user()
2175 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2178 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2187 return -EAFNOSUPPORT; in tcp_ao_copy_mkts_to_user()
2193 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2194 if (opt_in.prefix || opt_in.sndid || opt_in.rcvid) in tcp_ao_copy_mkts_to_user()
2195 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2200 /* May change in RX, while we're dumping, pre-fetch it */ in tcp_ao_copy_mkts_to_user()
2201 current_key = READ_ONCE(ao_info->current_key); in tcp_ao_copy_mkts_to_user()
2203 hlist_for_each_entry_rcu(key, &ao_info->head, node) { in tcp_ao_copy_mkts_to_user()
2210 if (opt_in.is_rnext && key == ao_info->rnext_key) in tcp_ao_copy_mkts_to_user()
2215 if (tcp_ao_key_cmp(key, l3index, addr, opt_in.prefix, in tcp_ao_copy_mkts_to_user()
2226 if (key->family == AF_INET) { in tcp_ao_copy_mkts_to_user()
2229 sin_out->sin_family = key->family; in tcp_ao_copy_mkts_to_user()
2230 sin_out->sin_port = 0; in tcp_ao_copy_mkts_to_user()
2231 memcpy(&sin_out->sin_addr, &key->addr, sizeof(struct in_addr)); in tcp_ao_copy_mkts_to_user()
2235 sin6_out->sin6_family = key->family; in tcp_ao_copy_mkts_to_user()
2236 sin6_out->sin6_port = 0; in tcp_ao_copy_mkts_to_user()
2237 memcpy(&sin6_out->sin6_addr, &key->addr, sizeof(struct in6_addr)); in tcp_ao_copy_mkts_to_user()
2239 opt_out.sndid = key->sndid; in tcp_ao_copy_mkts_to_user()
2240 opt_out.rcvid = key->rcvid; in tcp_ao_copy_mkts_to_user()
2241 opt_out.prefix = key->prefixlen; in tcp_ao_copy_mkts_to_user()
2242 opt_out.keyflags = key->keyflags; in tcp_ao_copy_mkts_to_user()
2244 opt_out.is_rnext = (key == ao_info->rnext_key); in tcp_ao_copy_mkts_to_user()
2246 opt_out.maclen = key->maclen; in tcp_ao_copy_mkts_to_user()
2247 opt_out.keylen = key->keylen; in tcp_ao_copy_mkts_to_user()
2248 opt_out.ifindex = key->l3index; in tcp_ao_copy_mkts_to_user()
2249 opt_out.pkt_good = atomic64_read(&key->pkt_good); in tcp_ao_copy_mkts_to_user()
2250 opt_out.pkt_bad = atomic64_read(&key->pkt_bad); in tcp_ao_copy_mkts_to_user()
2251 memcpy(&opt_out.key, key->key, key->keylen); in tcp_ao_copy_mkts_to_user()
2252 tcp_sigpool_algo(key->tcp_sigpool_id, opt_out.alg_name, 64); in tcp_ao_copy_mkts_to_user()
2257 return -EFAULT; in tcp_ao_copy_mkts_to_user()
2263 return -EFAULT; in tcp_ao_copy_mkts_to_user()
2268 return -EFAULT; in tcp_ao_copy_mkts_to_user()
2281 return -ENOENT; in tcp_ao_get_mkts()
2294 return -EFAULT; in tcp_ao_get_sock_info()
2297 return -EINVAL; in tcp_ao_get_sock_info()
2308 return -EINVAL; in tcp_ao_get_sock_info()
2314 return -ENOENT; in tcp_ao_get_sock_info()
2317 out.ao_required = ao->ao_required; in tcp_ao_get_sock_info()
2318 out.accept_icmps = ao->accept_icmps; in tcp_ao_get_sock_info()
2319 out.pkt_good = atomic64_read(&ao->counters.pkt_good); in tcp_ao_get_sock_info()
2320 out.pkt_bad = atomic64_read(&ao->counters.pkt_bad); in tcp_ao_get_sock_info()
2321 out.pkt_key_not_found = atomic64_read(&ao->counters.key_not_found); in tcp_ao_get_sock_info()
2322 out.pkt_ao_required = atomic64_read(&ao->counters.ao_required); in tcp_ao_get_sock_info()
2323 out.pkt_dropped_icmp = atomic64_read(&ao->counters.dropped_icmp); in tcp_ao_get_sock_info()
2325 current_key = READ_ONCE(ao->current_key); in tcp_ao_get_sock_info()
2328 out.current_key = current_key->sndid; in tcp_ao_get_sock_info()
2330 if (ao->rnext_key) { in tcp_ao_get_sock_info()
2332 out.rnext = ao->rnext_key->rcvid; in tcp_ao_get_sock_info()
2336 return -EFAULT; in tcp_ao_get_sock_info()
2350 return -EINVAL; in tcp_ao_set_repair()
2356 if (!tp->repair) in tcp_ao_set_repair()
2357 return -EPERM; in tcp_ao_set_repair()
2363 return -ENOENT; in tcp_ao_set_repair()
2365 WRITE_ONCE(ao->lisn, cmd.snt_isn); in tcp_ao_set_repair()
2366 WRITE_ONCE(ao->risn, cmd.rcv_isn); in tcp_ao_set_repair()
2367 WRITE_ONCE(ao->snd_sne, cmd.snd_sne); in tcp_ao_set_repair()
2368 WRITE_ONCE(ao->rcv_sne, cmd.rcv_sne); in tcp_ao_set_repair()
2370 hlist_for_each_entry_rcu(key, &ao->head, node) in tcp_ao_set_repair()
2384 return -EFAULT; in tcp_ao_get_repair()
2387 return -EINVAL; in tcp_ao_get_repair()
2389 if (!tp->repair) in tcp_ao_get_repair()
2390 return -EPERM; in tcp_ao_get_repair()
2396 return ao ? PTR_ERR(ao) : -ENOENT; in tcp_ao_get_repair()
2399 opt.snt_isn = ao->lisn; in tcp_ao_get_repair()
2400 opt.rcv_isn = ao->risn; in tcp_ao_get_repair()
2401 opt.snd_sne = READ_ONCE(ao->snd_sne); in tcp_ao_get_repair()
2402 opt.rcv_sne = READ_ONCE(ao->rcv_sne); in tcp_ao_get_repair()
2406 return -EFAULT; in tcp_ao_get_repair()