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).
29 if (crypto_ahash_setkey(crypto_ahash_reqtfm(hp->req), in tcp_ao_calc_traffic_key()
30 mkt->key, mkt->keylen)) in tcp_ao_calc_traffic_key()
33 ret = crypto_ahash_init(hp->req); in tcp_ao_calc_traffic_key()
38 ahash_request_set_crypt(hp->req, &sg, key, len); in tcp_ao_calc_traffic_key()
39 crypto_ahash_update(hp->req); in tcp_ao_calc_traffic_key()
41 ret = crypto_ahash_final(hp->req); in tcp_ao_calc_traffic_key()
60 * >> A TCP-AO implementation MUST default to ignore incoming ICMPv4 in tcp_ao_ignore_icmp()
61 * messages of Type 3 (destination unreachable), Codes 2-4 (protocol in tcp_ao_ignore_icmp()
62 * unreachable, port unreachable, and fragmentation needed -- ’hard in tcp_ao_ignore_icmp()
65 * for connections in synchronized states (ESTABLISHED, FIN-WAIT-1, FIN- in tcp_ao_ignore_icmp()
66 * WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK, TIME-WAIT) that match MKTs. in tcp_ao_ignore_icmp()
81 switch (sk->sk_state) { in tcp_ao_ignore_icmp()
83 ao = rcu_dereference(tcp_twsk(sk)->ao_info); in tcp_ao_ignore_icmp()
95 ao = rcu_dereference(tcp_sk(sk)->ao_info); in tcp_ao_ignore_icmp()
98 if (ao && !ao->accept_icmps) { in tcp_ao_ignore_icmp()
101 atomic64_inc(&ao->counters.dropped_icmp); in tcp_ao_ignore_icmp()
117 hlist_for_each_entry_rcu(key, &ao->head, node) { in tcp_ao_established_key()
118 if ((sndid >= 0 && key->sndid != sndid) || in tcp_ao_established_key()
119 (rcvid >= 0 && key->rcvid != rcvid)) in tcp_ao_established_key()
132 __be32 a1 = addr1->s_addr & mask; in ipv4_prefix_cmp()
133 __be32 a2 = addr2->s_addr & mask; in ipv4_prefix_cmp()
144 if (sndid >= 0 && key->sndid != sndid) in __tcp_ao_key_cmp()
145 return (key->sndid > sndid) ? 1 : -1; in __tcp_ao_key_cmp()
146 if (rcvid >= 0 && key->rcvid != rcvid) in __tcp_ao_key_cmp()
147 return (key->rcvid > rcvid) ? 1 : -1; in __tcp_ao_key_cmp()
148 if (l3index >= 0 && (key->keyflags & TCP_AO_KEYF_IFINDEX)) { in __tcp_ao_key_cmp()
149 if (key->l3index != l3index) in __tcp_ao_key_cmp()
150 return (key->l3index > l3index) ? 1 : -1; in __tcp_ao_key_cmp()
155 if (key->family != family) in __tcp_ao_key_cmp()
156 return (key->family > family) ? 1 : -1; in __tcp_ao_key_cmp()
159 if (ntohl(key->addr.a4.s_addr) == INADDR_ANY) in __tcp_ao_key_cmp()
161 if (ntohl(addr->a4.s_addr) == INADDR_ANY) in __tcp_ao_key_cmp()
163 return ipv4_prefix_cmp(&key->addr.a4, &addr->a4, prefixlen); in __tcp_ao_key_cmp()
166 if (ipv6_addr_any(&key->addr.a6) || ipv6_addr_any(&addr->a6)) in __tcp_ao_key_cmp()
168 if (ipv6_prefix_equal(&key->addr.a6, &addr->a6, prefixlen)) in __tcp_ao_key_cmp()
170 return memcmp(&key->addr.a6, &addr->a6, sizeof(addr->a6)); in __tcp_ao_key_cmp()
173 return -1; in __tcp_ao_key_cmp()
181 if (family == AF_INET6 && ipv6_addr_v4mapped(&addr->a6)) { in tcp_ao_key_cmp()
182 __be32 addr4 = addr->a6.s6_addr32[3]; in tcp_ao_key_cmp()
194 const union tcp_ao_addr *addr, int family, u8 prefix, in __tcp_ao_do_lookup() argument
203 ao = rcu_dereference_check(tcp_sk(sk)->ao_info, in __tcp_ao_do_lookup()
208 hlist_for_each_entry_rcu(key, &ao->head, node) { in __tcp_ao_do_lookup()
209 u8 prefixlen = min(prefix, key->prefixlen); in __tcp_ao_do_lookup()
232 INIT_HLIST_HEAD(&ao->head); in tcp_ao_alloc_info()
233 refcount_set(&ao->refcnt, 1); in tcp_ao_alloc_info()
240 hlist_add_head_rcu(&mkt->node, &ao->head); in tcp_ao_link_mkt()
254 INIT_HLIST_NODE(&new_key->node); in tcp_ao_copy_key()
255 tcp_sigpool_get(new_key->tcp_sigpool_id); in tcp_ao_copy_key()
256 atomic64_set(&new_key->pkt_good, 0); in tcp_ao_copy_key()
257 atomic64_set(&new_key->pkt_bad, 0); in tcp_ao_copy_key()
266 tcp_sigpool_release(key->tcp_sigpool_id); in tcp_ao_key_free_rcu()
276 hlist_for_each_entry_safe(key, n, &ao->head, node) { in tcp_ao_info_free_rcu()
277 hlist_del(&key->node); in tcp_ao_info_free_rcu()
278 tcp_sigpool_release(key->tcp_sigpool_id); in tcp_ao_info_free_rcu()
290 hlist_for_each_entry(key, &ao->head, node) in tcp_ao_sk_omem_free()
292 atomic_sub(total_ao_sk_mem, &sk->sk_omem_alloc); in tcp_ao_sk_omem_free()
300 ao = rcu_dereference_protected(tcp_twsk(sk)->ao_info, 1); in tcp_ao_destroy_sock()
301 rcu_assign_pointer(tcp_twsk(sk)->ao_info, NULL); in tcp_ao_destroy_sock()
303 ao = rcu_dereference_protected(tcp_sk(sk)->ao_info, 1); in tcp_ao_destroy_sock()
304 rcu_assign_pointer(tcp_sk(sk)->ao_info, NULL); in tcp_ao_destroy_sock()
307 if (!ao || !refcount_dec_and_test(&ao->refcnt)) in tcp_ao_destroy_sock()
312 call_rcu(&ao->rcu, tcp_ao_info_free_rcu); in tcp_ao_destroy_sock()
317 struct tcp_ao_info *ao_info = rcu_dereference_protected(tp->ao_info, 1); in tcp_ao_time_wait()
324 hlist_for_each_entry_safe(key, n, &ao_info->head, node) { in tcp_ao_time_wait()
328 refcount_inc(&ao_info->refcnt); in tcp_ao_time_wait()
329 atomic_sub(omem, &(((struct sock *)tp)->sk_omem_alloc)); in tcp_ao_time_wait()
330 rcu_assign_pointer(tcptw->ao_info, ao_info); in tcp_ao_time_wait()
332 tcptw->ao_info = NULL; in tcp_ao_time_wait()
352 err = tcp_sigpool_start(mkt->tcp_sigpool_id, &hp); in tcp_v4_ao_calc_key()
357 tmp->counter = 1; in tcp_v4_ao_calc_key()
358 memcpy(tmp->label, "TCP-AO", 6); in tcp_v4_ao_calc_key()
359 tmp->ctx.saddr = saddr; in tcp_v4_ao_calc_key()
360 tmp->ctx.daddr = daddr; in tcp_v4_ao_calc_key()
361 tmp->ctx.sport = sport; in tcp_v4_ao_calc_key()
362 tmp->ctx.dport = dport; in tcp_v4_ao_calc_key()
363 tmp->ctx.sisn = sisn; in tcp_v4_ao_calc_key()
364 tmp->ctx.disn = disn; in tcp_v4_ao_calc_key()
365 tmp->outlen = htons(tcp_ao_digest_size(mkt) * 8); /* in bits */ in tcp_v4_ao_calc_key()
378 return tcp_v4_ao_calc_key(mkt, key, sk->sk_rcv_saddr, in tcp_v4_ao_calc_key_sk()
379 sk->sk_daddr, htons(sk->sk_num), in tcp_v4_ao_calc_key_sk()
380 sk->sk_dport, sisn, disn); in tcp_v4_ao_calc_key_sk()
382 return tcp_v4_ao_calc_key(mkt, key, sk->sk_daddr, in tcp_v4_ao_calc_key_sk()
383 sk->sk_rcv_saddr, sk->sk_dport, in tcp_v4_ao_calc_key_sk()
384 htons(sk->sk_num), disn, sisn); in tcp_v4_ao_calc_key_sk()
391 if (mkt->family == AF_INET) in tcp_ao_calc_key_sk()
394 else if (mkt->family == AF_INET6) in tcp_ao_calc_key_sk()
398 return -EOPNOTSUPP; in tcp_ao_calc_key_sk()
407 ireq->ir_loc_addr, ireq->ir_rmt_addr, in tcp_v4_ao_calc_key_rsk()
408 htons(ireq->ir_num), ireq->ir_rmt_port, in tcp_v4_ao_calc_key_rsk()
409 htonl(tcp_rsk(req)->snt_isn), in tcp_v4_ao_calc_key_rsk()
410 htonl(tcp_rsk(req)->rcv_isn)); in tcp_v4_ao_calc_key_rsk()
420 return tcp_v4_ao_calc_key(mkt, key, iph->saddr, iph->daddr, in tcp_v4_ao_calc_key_skb()
421 th->source, th->dest, sisn, disn); in tcp_v4_ao_calc_key_skb()
434 return -EAFNOSUPPORT; in tcp_ao_calc_key_skb()
444 bp = hp->scratch; in tcp_v4_ao_hash_pseudoheader()
445 bp->saddr = saddr; in tcp_v4_ao_hash_pseudoheader()
446 bp->daddr = daddr; in tcp_v4_ao_hash_pseudoheader()
447 bp->pad = 0; in tcp_v4_ao_hash_pseudoheader()
448 bp->protocol = IPPROTO_TCP; in tcp_v4_ao_hash_pseudoheader()
449 bp->len = cpu_to_be16(nbytes); in tcp_v4_ao_hash_pseudoheader()
452 ahash_request_set_crypt(hp->req, &sg, NULL, sizeof(*bp)); in tcp_v4_ao_hash_pseudoheader()
453 return crypto_ahash_update(hp->req); in tcp_v4_ao_hash_pseudoheader()
464 if (!th->check) { in tcp_ao_hash_pseudoheader()
466 return tcp_v4_ao_hash_pseudoheader(hp, sk->sk_daddr, in tcp_ao_hash_pseudoheader()
467 sk->sk_rcv_saddr, skb->len); in tcp_ao_hash_pseudoheader()
470 return tcp_v6_ao_hash_pseudoheader(hp, &sk->sk_v6_daddr, in tcp_ao_hash_pseudoheader()
471 &sk->sk_v6_rcv_saddr, skb->len); in tcp_ao_hash_pseudoheader()
474 return -EAFNOSUPPORT; in tcp_ao_hash_pseudoheader()
480 return tcp_v4_ao_hash_pseudoheader(hp, iph->daddr, in tcp_ao_hash_pseudoheader()
481 iph->saddr, skb->len); in tcp_ao_hash_pseudoheader()
486 return tcp_v6_ao_hash_pseudoheader(hp, &iph->daddr, in tcp_ao_hash_pseudoheader()
487 &iph->saddr, skb->len); in tcp_ao_hash_pseudoheader()
490 return -EAFNOSUPPORT; in tcp_ao_hash_pseudoheader()
499 sne--; in tcp_ao_compute_sne()
509 * @hp - used for hashing
510 * @sne - sne value
517 bp = (__be32 *)hp->scratch; in tcp_ao_hash_sne()
521 ahash_request_set_crypt(hp->req, &sg, NULL, sizeof(*bp)); in tcp_ao_hash_sne()
522 return crypto_ahash_update(hp->req); in tcp_ao_hash_sne()
531 u8 *hdr = hp->scratch; in tcp_ao_hash_header()
539 (u8 *)th + hash_offset - sizeof(struct tcp_ao_hdr), in tcp_ao_hash_header()
543 ((struct tcphdr *)hdr)->check = 0; in tcp_ao_hash_header()
545 len = th->doff << 2; in tcp_ao_hash_header()
547 /* zero out tcp-ao hash */ in tcp_ao_hash_header()
548 ((struct tcphdr *)hdr)->check = 0; in tcp_ao_hash_header()
553 ahash_request_set_crypt(hp->req, &sg, NULL, len); in tcp_ao_hash_header()
554 err = crypto_ahash_update(hp->req); in tcp_ao_hash_header()
566 int hash_offset = ao_hash - (char *)th; in tcp_ao_hash_hdr()
574 if (tcp_sigpool_start(key->tcp_sigpool_id, &hp)) in tcp_ao_hash_hdr()
586 if (tcp_v4_ao_hash_pseudoheader(&hp, daddr->a4.s_addr, in tcp_ao_hash_hdr()
587 saddr->a4.s_addr, th->doff * 4)) in tcp_ao_hash_hdr()
591 if (tcp_v6_ao_hash_pseudoheader(&hp, &daddr->a6, in tcp_ao_hash_hdr()
592 &saddr->a6, th->doff * 4)) in tcp_ao_hash_hdr()
600 !!(key->keyflags & TCP_AO_KEYF_EXCLUDE_OPT), in tcp_ao_hash_hdr()
634 if (tcp_sigpool_start(key->tcp_sigpool_id, &hp)) in tcp_ao_hash_skb()
646 if (tcp_ao_hash_pseudoheader(family, sk, skb, &hp, skb->len)) in tcp_ao_hash_skb()
649 !!(key->keyflags & TCP_AO_KEYF_EXCLUDE_OPT), in tcp_ao_hash_skb()
652 if (tcp_sigpool_hash_skb_data(&hp, skb, th->doff << 2)) in tcp_ao_hash_skb()
688 return -ENOMEM; in tcp_v4_ao_synack_hash()
706 union tcp_ao_addr *addr = (union tcp_ao_addr *)&ireq->ir_rmt_addr; in tcp_v4_ao_lookup_rsk()
709 l3index = l3mdev_master_ifindex_by_index(sock_net(sk), ireq->ir_iif); in tcp_v4_ao_lookup_rsk()
717 addr_sk->sk_bound_dev_if); in tcp_v4_ao_lookup()
718 union tcp_ao_addr *addr = (union tcp_ao_addr *)&addr_sk->sk_daddr; in tcp_v4_ao_lookup()
732 /* If there's no socket - than initial sisn/disn are unknown. in tcp_ao_prepare_reset()
736 * Linux TCP-AO support provides TCP_AO_ADD_KEY and TCP_AO_REPAIR in tcp_ao_prepare_reset()
737 * options to restore a socket post-reboot. in tcp_ao_prepare_reset()
740 return -ENOTCONN; in tcp_ao_prepare_reset()
742 if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_NEW_SYN_RECV)) { in tcp_ao_prepare_reset()
743 unsigned int family = READ_ONCE(sk->sk_family); in tcp_ao_prepare_reset()
747 if (sk->sk_state == TCP_NEW_SYN_RECV) { in tcp_ao_prepare_reset()
750 sisn = htonl(tcp_rsk(req)->rcv_isn); in tcp_ao_prepare_reset()
751 disn = htonl(tcp_rsk(req)->snt_isn); in tcp_ao_prepare_reset()
752 *sne = tcp_ao_compute_sne(0, tcp_rsk(req)->snt_isn, seq); in tcp_ao_prepare_reset()
754 sisn = th->seq; in tcp_ao_prepare_reset()
758 addr = (union tcp_md5_addr *)&ipv6_hdr(skb)->saddr; in tcp_ao_prepare_reset()
760 addr = (union tcp_md5_addr *)&ip_hdr(skb)->saddr; in tcp_ao_prepare_reset()
762 if (family == AF_INET6 && ipv6_addr_v4mapped(&sk->sk_v6_daddr)) in tcp_ao_prepare_reset()
767 ao_info = rcu_dereference(tcp_sk(sk)->ao_info); in tcp_ao_prepare_reset()
769 return -ENOENT; in tcp_ao_prepare_reset()
771 -1, aoh->rnext_keyid); in tcp_ao_prepare_reset()
773 return -ENOENT; in tcp_ao_prepare_reset()
776 return -ENOMEM; in tcp_ao_prepare_reset()
780 return -1; in tcp_ao_prepare_reset()
781 *keyid = (*key)->rcvid; in tcp_ao_prepare_reset()
786 if (sk->sk_state == TCP_TIME_WAIT) { in tcp_ao_prepare_reset()
787 ao_info = rcu_dereference(tcp_twsk(sk)->ao_info); in tcp_ao_prepare_reset()
788 snd_basis = tcp_twsk(sk)->tw_snd_nxt; in tcp_ao_prepare_reset()
790 ao_info = rcu_dereference(tcp_sk(sk)->ao_info); in tcp_ao_prepare_reset()
791 snd_basis = tcp_sk(sk)->snd_una; in tcp_ao_prepare_reset()
794 return -ENOENT; in tcp_ao_prepare_reset()
796 *key = tcp_ao_established_key(ao_info, aoh->rnext_keyid, -1); in tcp_ao_prepare_reset()
798 return -ENOENT; in tcp_ao_prepare_reset()
800 rnext_key = READ_ONCE(ao_info->rnext_key); in tcp_ao_prepare_reset()
801 *keyid = rnext_key->rcvid; in tcp_ao_prepare_reset()
802 *sne = tcp_ao_compute_sne(READ_ONCE(ao_info->snd_sne), in tcp_ao_prepare_reset()
819 ao = rcu_dereference_protected(tcp_sk(sk)->ao_info, in tcp_ao_transmit_skb()
822 if (unlikely(tcb->tcp_flags & TCPHDR_SYN)) { in tcp_ao_transmit_skb()
825 if (!(tcb->tcp_flags & TCPHDR_ACK)) { in tcp_ao_transmit_skb()
829 return -ENOMEM; in tcp_ao_transmit_skb()
832 disn = ao->risn; in tcp_ao_transmit_skb()
834 tp->af_specific->ao_calc_key_sk(key, traffic_key, in tcp_ao_transmit_skb()
835 sk, ao->lisn, disn, true); in tcp_ao_transmit_skb()
837 sne = tcp_ao_compute_sne(READ_ONCE(ao->snd_sne), READ_ONCE(tp->snd_una), in tcp_ao_transmit_skb()
838 ntohl(th->seq)); in tcp_ao_transmit_skb()
839 tp->af_specific->calc_ao_hash(hash_location, key, sk, skb, traffic_key, in tcp_ao_transmit_skb()
840 hash_location - (u8 *)th, sne); in tcp_ao_transmit_skb()
853 (union tcp_ao_addr *)&iph->saddr, in tcp_ao_inbound_lookup()
859 (union tcp_ao_addr *)&iph->saddr, in tcp_ao_inbound_lookup()
873 /* treq->af_specific is used to perform TCP_AO lookup in tcp_ao_syncookie()
878 treq->af_specific = &tcp_request_sock_ipv6_ops; in tcp_ao_syncookie()
881 treq->af_specific = &tcp_request_sock_ipv4_ops; in tcp_ao_syncookie()
883 treq->used_tcp_ao = false; in tcp_ao_syncookie()
888 l3index = l3mdev_master_ifindex_by_index(sock_net(sk), inet_rsk(req)->ir_iif); in tcp_ao_syncookie()
889 key = tcp_ao_inbound_lookup(family, sk, skb, -1, aoh->keyid, l3index); in tcp_ao_syncookie()
891 /* Key not found, continue without TCP-AO */ in tcp_ao_syncookie()
894 treq->ao_rcv_next = aoh->keyid; in tcp_ao_syncookie()
895 treq->ao_keyid = aoh->rnext_keyid; in tcp_ao_syncookie()
896 treq->used_tcp_ao = true; in tcp_ao_syncookie()
911 atomic64_inc(&info->counters.pkt_bad); in tcp_ao_verify_hash()
912 atomic64_inc(&key->pkt_bad); in tcp_ao_verify_hash()
913 trace_tcp_ao_wrong_maclen(sk, skb, aoh->keyid, in tcp_ao_verify_hash()
914 aoh->rnext_keyid, maclen); in tcp_ao_verify_hash()
922 /* XXX: make it per-AF callback? */ in tcp_ao_verify_hash()
924 (phash - (u8 *)th), sne); in tcp_ao_verify_hash()
927 atomic64_inc(&info->counters.pkt_bad); in tcp_ao_verify_hash()
928 atomic64_inc(&key->pkt_bad); in tcp_ao_verify_hash()
929 trace_tcp_ao_mismatch(sk, skb, aoh->keyid, in tcp_ao_verify_hash()
930 aoh->rnext_keyid, maclen); in tcp_ao_verify_hash()
935 atomic64_inc(&info->counters.pkt_good); in tcp_ao_verify_hash()
936 atomic64_inc(&key->pkt_good); in tcp_ao_verify_hash()
957 info = rcu_dereference(tcp_sk(sk)->ao_info); in tcp_inbound_ao_hash()
960 trace_tcp_ao_key_not_found(sk, skb, aoh->keyid, in tcp_inbound_ao_hash()
961 aoh->rnext_keyid, maclen); in tcp_inbound_ao_hash()
965 if (unlikely(th->syn)) { in tcp_inbound_ao_hash()
966 sisn = th->seq; in tcp_inbound_ao_hash()
970 state = READ_ONCE(sk->sk_state); in tcp_inbound_ao_hash()
971 /* Fast-path */ in tcp_inbound_ao_hash()
980 key = READ_ONCE(info->rnext_key); in tcp_inbound_ao_hash()
981 if (key->rcvid != aoh->keyid) { in tcp_inbound_ao_hash()
982 key = tcp_ao_established_key(info, -1, aoh->keyid); in tcp_inbound_ao_hash()
988 if (unlikely(th->syn && !th->ack)) in tcp_inbound_ao_hash()
991 sne = tcp_ao_compute_sne(info->rcv_sne, tcp_sk(sk)->rcv_nxt, in tcp_inbound_ao_hash()
992 ntohl(th->seq)); in tcp_inbound_ao_hash()
999 current_key = READ_ONCE(info->current_key); in tcp_inbound_ao_hash()
1001 if (unlikely(aoh->rnext_keyid != current_key->sndid)) { in tcp_inbound_ao_hash()
1002 trace_tcp_ao_rnext_request(sk, skb, current_key->sndid, in tcp_inbound_ao_hash()
1003 aoh->rnext_keyid, in tcp_inbound_ao_hash()
1006 key = tcp_ao_established_key(info, aoh->rnext_keyid, -1); in tcp_inbound_ao_hash()
1009 WRITE_ONCE(info->current_key, key); in tcp_inbound_ao_hash()
1020 * - request sockets would race on those key pointers in tcp_inbound_ao_hash()
1021 * - tcp_ao_del_cmd() allows async key removal in tcp_inbound_ao_hash()
1023 key = tcp_ao_inbound_lookup(family, sk, skb, -1, aoh->keyid, l3index); in tcp_inbound_ao_hash()
1027 if (th->syn && !th->ack) in tcp_inbound_ao_hash()
1033 sne = tcp_ao_compute_sne(0, tcp_rsk(req)->rcv_isn, in tcp_inbound_ao_hash()
1034 ntohl(th->seq)); in tcp_inbound_ao_hash()
1035 sisn = htonl(tcp_rsk(req)->rcv_isn); in tcp_inbound_ao_hash()
1036 disn = htonl(tcp_rsk(req)->snt_isn); in tcp_inbound_ao_hash()
1037 } else if (unlikely(th->ack && !th->syn)) { in tcp_inbound_ao_hash()
1039 sisn = htonl(ntohl(th->seq) - 1); in tcp_inbound_ao_hash()
1040 disn = htonl(ntohl(th->ack_seq) - 1); in tcp_inbound_ao_hash()
1042 ntohl(th->seq)); in tcp_inbound_ao_hash()
1043 } else if (unlikely(!th->syn)) { in tcp_inbound_ao_hash()
1044 /* no way to figure out initial sisn/disn - drop */ in tcp_inbound_ao_hash()
1048 disn = info->lisn; in tcp_inbound_ao_hash()
1049 if (th->syn || th->rst) in tcp_inbound_ao_hash()
1050 sisn = th->seq; in tcp_inbound_ao_hash()
1052 sisn = info->risn; in tcp_inbound_ao_hash()
1054 WARN_ONCE(1, "TCP-AO: Unexpected sk_state %d", state); in tcp_inbound_ao_hash()
1069 atomic64_inc(&info->counters.key_not_found); in tcp_inbound_ao_hash()
1070 trace_tcp_ao_key_not_found(sk, skb, aoh->keyid, in tcp_inbound_ao_hash()
1071 aoh->rnext_keyid, maclen); in tcp_inbound_ao_hash()
1083 ao->lisn, ao->risn, true); in tcp_ao_cache_traffic_keys()
1089 ao->lisn, ao->risn, false); in tcp_ao_cache_traffic_keys()
1102 ao_info = rcu_dereference_protected(tp->ao_info, in tcp_ao_connect_init()
1108 family = sk->sk_family; in tcp_ao_connect_init()
1110 addr = (union tcp_ao_addr *)&sk->sk_daddr; in tcp_ao_connect_init()
1113 addr = (union tcp_ao_addr *)&sk->sk_v6_daddr; in tcp_ao_connect_init()
1118 sk->sk_bound_dev_if); in tcp_ao_connect_init()
1120 hlist_for_each_entry_safe(key, next, &ao_info->head, node) { in tcp_ao_connect_init()
1121 if (!tcp_ao_key_cmp(key, l3index, addr, key->prefixlen, family, -1, -1)) in tcp_ao_connect_init()
1124 if (key == ao_info->current_key) in tcp_ao_connect_init()
1125 ao_info->current_key = NULL; in tcp_ao_connect_init()
1126 if (key == ao_info->rnext_key) in tcp_ao_connect_init()
1127 ao_info->rnext_key = NULL; in tcp_ao_connect_init()
1128 hlist_del_rcu(&key->node); in tcp_ao_connect_init()
1129 atomic_sub(tcp_ao_sizeof_key(key), &sk->sk_omem_alloc); in tcp_ao_connect_init()
1130 call_rcu(&key->rcu, tcp_ao_key_free_rcu); in tcp_ao_connect_init()
1133 key = tp->af_specific->ao_lookup(sk, sk, -1, -1); in tcp_ao_connect_init()
1138 if (!ao_info->current_key) in tcp_ao_connect_init()
1139 ao_info->current_key = key; in tcp_ao_connect_init()
1140 if (!ao_info->rnext_key) in tcp_ao_connect_init()
1141 ao_info->rnext_key = key; in tcp_ao_connect_init()
1142 tp->tcp_header_len += tcp_ao_len_aligned(key); in tcp_ao_connect_init()
1144 ao_info->lisn = htonl(tp->write_seq); in tcp_ao_connect_init()
1145 ao_info->snd_sne = 0; in tcp_ao_connect_init()
1148 * at least one tcp-ao key that matches the remote peer. in tcp_ao_connect_init()
1151 rcu_assign_pointer(tp->ao_info, NULL); in tcp_ao_connect_init()
1161 ao = rcu_dereference_protected(tcp_sk(sk)->ao_info, in tcp_ao_established()
1166 hlist_for_each_entry_rcu(key, &ao->head, node) in tcp_ao_established()
1175 ao = rcu_dereference_protected(tcp_sk(sk)->ao_info, in tcp_ao_finish_connect()
1180 WRITE_ONCE(ao->risn, tcp_hdr(skb)->seq); in tcp_ao_finish_connect()
1181 ao->rcv_sne = 0; in tcp_ao_finish_connect()
1183 hlist_for_each_entry_rcu(key, &ao->head, node) in tcp_ao_finish_connect()
1194 int l3index, ret = -ENOMEM; in tcp_ao_copy_all_matching()
1198 ao = rcu_dereference(tcp_sk(sk)->ao_info); in tcp_ao_copy_all_matching()
1202 /* New socket without TCP-AO on it */ in tcp_ao_copy_all_matching()
1208 return -ENOMEM; in tcp_ao_copy_all_matching()
1209 new_ao->lisn = htonl(tcp_rsk(req)->snt_isn); in tcp_ao_copy_all_matching()
1210 new_ao->risn = htonl(tcp_rsk(req)->rcv_isn); in tcp_ao_copy_all_matching()
1211 new_ao->ao_required = ao->ao_required; in tcp_ao_copy_all_matching()
1212 new_ao->accept_icmps = ao->accept_icmps; in tcp_ao_copy_all_matching()
1215 addr = (union tcp_ao_addr *)&newsk->sk_daddr; in tcp_ao_copy_all_matching()
1218 addr = (union tcp_ao_addr *)&newsk->sk_v6_daddr; in tcp_ao_copy_all_matching()
1221 ret = -EAFNOSUPPORT; in tcp_ao_copy_all_matching()
1225 newsk->sk_bound_dev_if); in tcp_ao_copy_all_matching()
1227 hlist_for_each_entry_rcu(key, &ao->head, node) { in tcp_ao_copy_all_matching()
1228 if (tcp_ao_key_cmp(key, l3index, addr, key->prefixlen, family, -1, -1)) in tcp_ao_copy_all_matching()
1241 /* RFC5925 (7.4.1) specifies that the TCP-AO status in tcp_ao_copy_all_matching()
1243 * At this point the connection was TCP-AO enabled, so in tcp_ao_copy_all_matching()
1247 ret = -EKEYREJECTED; in tcp_ao_copy_all_matching()
1252 ret = -EUSERS; in tcp_ao_copy_all_matching()
1256 key_head = rcu_dereference(hlist_first_rcu(&new_ao->head)); in tcp_ao_copy_all_matching()
1259 key = tcp_ao_established_key(new_ao, tcp_rsk(req)->ao_keyid, -1); in tcp_ao_copy_all_matching()
1261 new_ao->current_key = key; in tcp_ao_copy_all_matching()
1263 new_ao->current_key = first_key; in tcp_ao_copy_all_matching()
1266 key = tcp_ao_established_key(new_ao, -1, tcp_rsk(req)->ao_rcv_next); in tcp_ao_copy_all_matching()
1268 new_ao->rnext_key = key; in tcp_ao_copy_all_matching()
1270 new_ao->rnext_key = first_key; in tcp_ao_copy_all_matching()
1273 rcu_assign_pointer(tcp_sk(newsk)->ao_info, new_ao); in tcp_ao_copy_all_matching()
1278 hlist_for_each_entry_safe(key, key_head, &new_ao->head, node) { in tcp_ao_copy_all_matching()
1279 hlist_del(&key->node); in tcp_ao_copy_all_matching()
1280 tcp_sigpool_release(key->tcp_sigpool_id); in tcp_ao_copy_all_matching()
1281 atomic_sub(tcp_ao_sizeof_key(key), &newsk->sk_omem_alloc); in tcp_ao_copy_all_matching()
1292 if (sk->sk_state == TCP_LISTEN) in tcp_ao_can_set_current_rnext()
1300 struct sockaddr_in *sin = (struct sockaddr_in *)&cmd->addr; in tcp_ao_verify_ipv4()
1303 if (sin->sin_family != AF_INET) in tcp_ao_verify_ipv4()
1304 return -EINVAL; in tcp_ao_verify_ipv4()
1307 if (sin->sin_port != 0) in tcp_ao_verify_ipv4()
1308 return -EINVAL; in tcp_ao_verify_ipv4()
1310 /* Check prefix and trailing 0's in addr */ in tcp_ao_verify_ipv4()
1311 if (cmd->prefix != 0) { in tcp_ao_verify_ipv4()
1314 if (ntohl(sin->sin_addr.s_addr) == INADDR_ANY) in tcp_ao_verify_ipv4()
1315 return -EINVAL; in tcp_ao_verify_ipv4()
1316 if (cmd->prefix > 32) in tcp_ao_verify_ipv4()
1317 return -EINVAL; in tcp_ao_verify_ipv4()
1319 mask = inet_make_mask(cmd->prefix); in tcp_ao_verify_ipv4()
1320 if (sin->sin_addr.s_addr & ~mask) in tcp_ao_verify_ipv4()
1321 return -EINVAL; in tcp_ao_verify_ipv4()
1324 if (ntohl(inet->inet_daddr) != INADDR_ANY && in tcp_ao_verify_ipv4()
1325 (inet->inet_daddr & mask) != sin->sin_addr.s_addr) in tcp_ao_verify_ipv4()
1326 return -EINVAL; in tcp_ao_verify_ipv4()
1328 if (ntohl(sin->sin_addr.s_addr) != INADDR_ANY) in tcp_ao_verify_ipv4()
1329 return -EINVAL; in tcp_ao_verify_ipv4()
1332 *addr = (union tcp_ao_addr *)&sin->sin_addr; in tcp_ao_verify_ipv4()
1346 if (!strcmp("cmac(aes128)", cmd->alg_name)) { in tcp_ao_parse_crypto()
1347 strscpy(cmd->alg_name, "cmac(aes)", sizeof(cmd->alg_name)); in tcp_ao_parse_crypto()
1348 is_kdf_aes_128_cmac = (cmd->keylen != 16); in tcp_ao_parse_crypto()
1349 tmp_key = kmalloc(cmd->keylen, GFP_KERNEL); in tcp_ao_parse_crypto()
1351 return -ENOMEM; in tcp_ao_parse_crypto()
1354 key->maclen = cmd->maclen ?: 12; /* 12 is the default in RFC5925 */ in tcp_ao_parse_crypto()
1356 /* Check: maclen + tcp-ao header <= (MAX_TCP_OPTION_SPACE - mss in tcp_ao_parse_crypto()
1357 * - tstamp (including sackperm) in tcp_ao_parse_crypto()
1358 * - wscale), in tcp_ao_parse_crypto()
1361 * In order to allow D-SACK with TCP-AO, the header size should be: in tcp_ao_parse_crypto()
1362 * (MAX_TCP_OPTION_SPACE - TCPOLEN_TSTAMP_ALIGNED in tcp_ao_parse_crypto()
1363 * - TCPOLEN_SACK_BASE_ALIGNED in tcp_ao_parse_crypto()
1364 * - 2 * TCPOLEN_SACK_PERBLOCK) = 8 (maclen = 4), in tcp_ao_parse_crypto()
1368 * Typical MACs are 96-128 bits (12-16 bytes), but any length in tcp_ao_parse_crypto()
1373 * TCP-AO continues to consume 16 bytes in non-SYN segments, in tcp_ao_parse_crypto()
1377 * such as to handle D-SACK, a smaller TCP-AO MAC would be required in tcp_ao_parse_crypto()
1379 * bytes for the D-SACK variant of the SACK option) [RFC2883]. in tcp_ao_parse_crypto()
1380 * Note that D-SACK is not supportable in TCP MD5 in the presence in tcp_ao_parse_crypto()
1385 syn_tcp_option_space -= TCPOLEN_MSS_ALIGNED; in tcp_ao_parse_crypto()
1386 syn_tcp_option_space -= TCPOLEN_TSTAMP_ALIGNED; in tcp_ao_parse_crypto()
1387 syn_tcp_option_space -= TCPOLEN_WSCALE_ALIGNED; in tcp_ao_parse_crypto()
1389 err = -EMSGSIZE; in tcp_ao_parse_crypto()
1393 key->keylen = cmd->keylen; in tcp_ao_parse_crypto()
1394 memcpy(key->key, cmd->key, cmd->keylen); in tcp_ao_parse_crypto()
1396 err = tcp_sigpool_start(key->tcp_sigpool_id, &hp); in tcp_ao_parse_crypto()
1405 memcpy(tmp_key, cmd->key, cmd->keylen); in tcp_ao_parse_crypto()
1406 sg_init_one(&sg, tmp_key, cmd->keylen); in tcp_ao_parse_crypto()
1408 /* Using zero-key of 16 bytes as described in RFC5926 */ in tcp_ao_parse_crypto()
1418 ahash_request_set_crypt(hp.req, &sg, key->key, cmd->keylen); in tcp_ao_parse_crypto()
1426 key->keylen = 16; in tcp_ao_parse_crypto()
1429 err = crypto_ahash_setkey(tfm, key->key, key->keylen); in tcp_ao_parse_crypto()
1436 if (tcp_ao_maclen(key) > key->digest_size) in tcp_ao_parse_crypto()
1437 return -EINVAL; in tcp_ao_parse_crypto()
1453 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd->addr; in tcp_ao_verify_ipv6()
1454 struct in6_addr *addr = &sin6->sin6_addr; in tcp_ao_verify_ipv6()
1455 u8 prefix = cmd->prefix; in tcp_ao_verify_ipv6() local
1457 if (sin6->sin6_family != AF_INET6) in tcp_ao_verify_ipv6()
1458 return -EINVAL; in tcp_ao_verify_ipv6()
1461 if (sin6->sin6_port != 0) in tcp_ao_verify_ipv6()
1462 return -EINVAL; in tcp_ao_verify_ipv6()
1464 /* Check prefix and trailing 0's in addr */ in tcp_ao_verify_ipv6()
1465 if (cmd->prefix != 0 && ipv6_addr_v4mapped(addr)) { in tcp_ao_verify_ipv6()
1466 __be32 addr4 = addr->s6_addr32[3]; in tcp_ao_verify_ipv6()
1469 if (prefix > 32 || ntohl(addr4) == INADDR_ANY) in tcp_ao_verify_ipv6()
1470 return -EINVAL; in tcp_ao_verify_ipv6()
1472 mask = inet_make_mask(prefix); in tcp_ao_verify_ipv6()
1474 return -EINVAL; in tcp_ao_verify_ipv6()
1477 if (!ipv6_addr_any(&sk->sk_v6_daddr)) { in tcp_ao_verify_ipv6()
1478 __be32 daddr4 = sk->sk_v6_daddr.s6_addr32[3]; in tcp_ao_verify_ipv6()
1480 if (!ipv6_addr_v4mapped(&sk->sk_v6_daddr)) in tcp_ao_verify_ipv6()
1481 return -EINVAL; in tcp_ao_verify_ipv6()
1483 return -EINVAL; in tcp_ao_verify_ipv6()
1486 *paddr = (union tcp_ao_addr *)&addr->s6_addr32[3]; in tcp_ao_verify_ipv6()
1489 } else if (cmd->prefix != 0) { in tcp_ao_verify_ipv6()
1492 if (ipv6_addr_any(addr) || prefix > 128) in tcp_ao_verify_ipv6()
1493 return -EINVAL; in tcp_ao_verify_ipv6()
1495 ipv6_addr_prefix(&pfx, addr, prefix); in tcp_ao_verify_ipv6()
1497 return -EINVAL; in tcp_ao_verify_ipv6()
1500 if (!ipv6_addr_any(&sk->sk_v6_daddr) && in tcp_ao_verify_ipv6()
1501 !ipv6_prefix_equal(&sk->sk_v6_daddr, addr, prefix)) in tcp_ao_verify_ipv6()
1503 return -EINVAL; in tcp_ao_verify_ipv6()
1506 return -EINVAL; in tcp_ao_verify_ipv6()
1517 return -EOPNOTSUPP; in tcp_ao_verify_ipv6()
1524 return rcu_dereference_protected(tcp_sk(sk)->ao_info, in setsockopt_ao_info()
1526 } else if (sk->sk_state == TCP_TIME_WAIT) { in setsockopt_ao_info()
1527 return rcu_dereference_protected(tcp_twsk(sk)->ao_info, in setsockopt_ao_info()
1530 return ERR_PTR(-ESOCKTNOSUPPORT); in setsockopt_ao_info()
1536 return rcu_dereference(tcp_sk(sk)->ao_info); in getsockopt_ao_info()
1537 else if (sk->sk_state == TCP_TIME_WAIT) in getsockopt_ao_info()
1538 return rcu_dereference(tcp_twsk(sk)->ao_info); in getsockopt_ao_info()
1540 return ERR_PTR(-ESOCKTNOSUPPORT); in getsockopt_ao_info()
1549 const char *algo = cmd->alg_name; in tcp_ao_key_alloc()
1557 /* Force null-termination of alg_name */ in tcp_ao_key_alloc()
1558 cmd->alg_name[ARRAY_SIZE(cmd->alg_name) - 1] = '\0'; in tcp_ao_key_alloc()
1564 /* Full TCP header (th->doff << 2) should fit into scratch area, in tcp_ao_key_alloc()
1582 err = -ENOMEM; in tcp_ao_key_alloc()
1586 key->tcp_sigpool_id = pool_id; in tcp_ao_key_alloc()
1587 key->digest_size = digest_size; in tcp_ao_key_alloc()
1606 return -EINVAL; in tcp_ao_add_cmd()
1613 return -EINVAL; in tcp_ao_add_cmd()
1616 return -EINVAL; in tcp_ao_add_cmd()
1626 return -EINVAL; in tcp_ao_add_cmd()
1630 return -EINVAL; in tcp_ao_add_cmd()
1634 return -EINVAL; in tcp_ao_add_cmd()
1638 int bound_dev_if = READ_ONCE(sk->sk_bound_dev_if); in tcp_ao_add_cmd()
1644 l3index = dev->ifindex; in tcp_ao_add_cmd()
1648 return -EINVAL; in tcp_ao_add_cmd()
1652 * non peer-matching key on an established TCP-AO in tcp_ao_add_cmd()
1655 if (!((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) in tcp_ao_add_cmd()
1656 return -EINVAL; in tcp_ao_add_cmd()
1660 * re-bind to a different dev (with CAP_NET_RAW). in tcp_ao_add_cmd()
1669 /* Don't allow keys for peers that have a matching TCP-MD5 key */ in tcp_ao_add_cmd()
1671 /* Non-_exact version of tcp_md5_do_lookup() will in tcp_ao_add_cmd()
1677 return -EKEYREJECTED; in tcp_ao_add_cmd()
1680 return -EKEYREJECTED; in tcp_ao_add_cmd()
1690 return -ENOMEM; in tcp_ao_add_cmd()
1698 if (__tcp_ao_do_lookup(sk, l3index, addr, family, cmd.prefix, -1, cmd.rcvid)) in tcp_ao_add_cmd()
1699 return -EEXIST; in tcp_ao_add_cmd()
1701 cmd.prefix, cmd.sndid, -1)) in tcp_ao_add_cmd()
1702 return -EEXIST; in tcp_ao_add_cmd()
1711 INIT_HLIST_NODE(&key->node); in tcp_ao_add_cmd()
1712 memcpy(&key->addr, addr, (family == AF_INET) ? sizeof(struct in_addr) : in tcp_ao_add_cmd()
1714 key->prefixlen = cmd.prefix; in tcp_ao_add_cmd()
1715 key->family = family; in tcp_ao_add_cmd()
1716 key->keyflags = cmd.keyflags; in tcp_ao_add_cmd()
1717 key->sndid = cmd.sndid; in tcp_ao_add_cmd()
1718 key->rcvid = cmd.rcvid; in tcp_ao_add_cmd()
1719 key->l3index = l3index; in tcp_ao_add_cmd()
1720 atomic64_set(&key->pkt_good, 0); in tcp_ao_add_cmd()
1721 atomic64_set(&key->pkt_bad, 0); in tcp_ao_add_cmd()
1727 if (!((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) { in tcp_ao_add_cmd()
1730 ao_info->current_key = key; in tcp_ao_add_cmd()
1731 ao_info->rnext_key = key; in tcp_ao_add_cmd()
1738 ret = -EUSERS; in tcp_ao_add_cmd()
1742 rcu_assign_pointer(tcp_sk(sk)->ao_info, ao_info); in tcp_ao_add_cmd()
1746 WRITE_ONCE(ao_info->current_key, key); in tcp_ao_add_cmd()
1748 WRITE_ONCE(ao_info->rnext_key, key); in tcp_ao_add_cmd()
1752 atomic_sub(tcp_ao_sizeof_key(key), &sk->sk_omem_alloc); in tcp_ao_add_cmd()
1753 tcp_sigpool_release(key->tcp_sigpool_id); in tcp_ao_add_cmd()
1768 hlist_del_rcu(&key->node); in tcp_ao_delete_key()
1770 /* Support for async delete on listening sockets: as they don't in tcp_ao_delete_key()
1775 atomic_sub(tcp_ao_sizeof_key(key), &sk->sk_omem_alloc); in tcp_ao_delete_key()
1776 call_rcu(&key->rcu, tcp_ao_key_free_rcu); in tcp_ao_delete_key()
1782 * after which the key is off-list and can't be looked up again; in tcp_ao_delete_key()
1787 * changed it in forced-delete). in tcp_ao_delete_key()
1791 WRITE_ONCE(ao_info->current_key, new_current); in tcp_ao_delete_key()
1793 WRITE_ONCE(ao_info->rnext_key, new_rnext); in tcp_ao_delete_key()
1795 if (unlikely(READ_ONCE(ao_info->current_key) == key || in tcp_ao_delete_key()
1796 READ_ONCE(ao_info->rnext_key) == key)) { in tcp_ao_delete_key()
1797 err = -EBUSY; in tcp_ao_delete_key()
1801 atomic_sub(tcp_ao_sizeof_key(key), &sk->sk_omem_alloc); in tcp_ao_delete_key()
1802 call_rcu(&key->rcu, tcp_ao_key_free_rcu); in tcp_ao_delete_key()
1806 hlist_add_head_rcu(&key->node, &ao_info->head); in tcp_ao_delete_key()
1819 __u8 prefix; in tcp_ao_del_cmd() local
1823 return -EINVAL; in tcp_ao_del_cmd()
1830 return -EINVAL; in tcp_ao_del_cmd()
1834 return -EINVAL; in tcp_ao_del_cmd()
1838 return -EINVAL; in tcp_ao_del_cmd()
1846 return -EINVAL; in tcp_ao_del_cmd()
1852 return -ENOENT; in tcp_ao_del_cmd()
1860 new_current = tcp_ao_established_key(ao_info, cmd.current_key, -1); in tcp_ao_del_cmd()
1862 return -ENOENT; in tcp_ao_del_cmd()
1865 new_rnext = tcp_ao_established_key(ao_info, -1, cmd.rnext); in tcp_ao_del_cmd()
1867 return -ENOENT; in tcp_ao_del_cmd()
1869 if (cmd.del_async && sk->sk_state != TCP_LISTEN) in tcp_ao_del_cmd()
1870 return -EINVAL; in tcp_ao_del_cmd()
1875 addr = (union tcp_ao_addr *)&sin->sin_addr; in tcp_ao_del_cmd()
1877 port = ntohs(sin->sin_port); in tcp_ao_del_cmd()
1880 struct in6_addr *addr6 = &sin6->sin6_addr; in tcp_ao_del_cmd()
1883 addr = (union tcp_ao_addr *)&addr6->s6_addr32[3]; in tcp_ao_del_cmd()
1890 port = ntohs(sin6->sin6_port); in tcp_ao_del_cmd()
1892 prefix = cmd.prefix; in tcp_ao_del_cmd()
1896 return -EINVAL; in tcp_ao_del_cmd()
1901 * specify how-to coordinate key removal, but says: in tcp_ao_del_cmd()
1905 hlist_for_each_entry_rcu(key, &ao_info->head, node) { in tcp_ao_del_cmd()
1906 if (cmd.sndid != key->sndid || in tcp_ao_del_cmd()
1907 cmd.rcvid != key->rcvid) in tcp_ao_del_cmd()
1910 if (family != key->family || in tcp_ao_del_cmd()
1911 prefix != key->prefixlen || in tcp_ao_del_cmd()
1912 memcmp(addr, &key->addr, addr_len)) in tcp_ao_del_cmd()
1916 (key->keyflags & TCP_AO_KEYF_IFINDEX)) in tcp_ao_del_cmd()
1919 if (key->l3index != l3index) in tcp_ao_del_cmd()
1928 return -ENOENT; in tcp_ao_del_cmd()
1931 /* cmd.ao_required makes a socket TCP-AO only.
1934 * ao_info->ao_required on inbound tcp segment fast-path.
1944 md5sig = rcu_dereference_check(tcp_sk(sk)->md5sig_info, in tcp_ao_required_verify()
1949 if (rcu_dereference_check(hlist_first_rcu(&md5sig->head), in tcp_ao_required_verify()
1966 return -EINVAL; in tcp_ao_info_cmd()
1974 return -EINVAL; in tcp_ao_info_cmd()
1978 return -EINVAL; in tcp_ao_info_cmd()
1984 if (!((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) in tcp_ao_info_cmd()
1985 return -EINVAL; in tcp_ao_info_cmd()
1988 return -ENOMEM; in tcp_ao_info_cmd()
1993 err = -EKEYREJECTED; in tcp_ao_info_cmd()
2003 new_current = tcp_ao_established_key(ao_info, cmd.current_key, -1); in tcp_ao_info_cmd()
2005 err = -ENOENT; in tcp_ao_info_cmd()
2010 new_rnext = tcp_ao_established_key(ao_info, -1, cmd.rnext); in tcp_ao_info_cmd()
2012 err = -ENOENT; in tcp_ao_info_cmd()
2017 atomic64_set(&ao_info->counters.pkt_good, cmd.pkt_good); in tcp_ao_info_cmd()
2018 atomic64_set(&ao_info->counters.pkt_bad, cmd.pkt_bad); in tcp_ao_info_cmd()
2019 atomic64_set(&ao_info->counters.key_not_found, cmd.pkt_key_not_found); in tcp_ao_info_cmd()
2020 atomic64_set(&ao_info->counters.ao_required, cmd.pkt_ao_required); in tcp_ao_info_cmd()
2021 atomic64_set(&ao_info->counters.dropped_icmp, cmd.pkt_dropped_icmp); in tcp_ao_info_cmd()
2024 ao_info->ao_required = cmd.ao_required; in tcp_ao_info_cmd()
2025 ao_info->accept_icmps = cmd.accept_icmps; in tcp_ao_info_cmd()
2027 WRITE_ONCE(ao_info->current_key, new_current); in tcp_ao_info_cmd()
2029 WRITE_ONCE(ao_info->rnext_key, new_rnext); in tcp_ao_info_cmd()
2032 err = -EUSERS; in tcp_ao_info_cmd()
2036 rcu_assign_pointer(tcp_sk(sk)->ao_info, ao_info); in tcp_ao_info_cmd()
2049 return -EAFNOSUPPORT; in tcp_parse_ao()
2060 return -EINVAL; in tcp_parse_ao()
2086 * returned, otherwise only keys matching <addr, prefix, sndid, rcvid>
2096 * (ksize - usize) are interpreted as 0 by the kernel.
2098 * older kernel. The trailing bytes unknown to the kernel (usize - ksize)
2099 * are checked to ensure they are zeroed, otherwise -E2BIG is returned.
2120 return -EFAULT; in tcp_ao_copy_mkts_to_user()
2123 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2132 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2134 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2136 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2139 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2142 l3index = (opt_in.keyflags & TCP_AO_KEYF_IFINDEX) ? opt_in.ifindex : -1; in tcp_ao_copy_mkts_to_user()
2146 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2156 port = sin->sin_port; in tcp_ao_copy_mkts_to_user()
2157 addr = (union tcp_ao_addr *)&sin->sin_addr; in tcp_ao_copy_mkts_to_user()
2159 if (opt_in.prefix > 32) in tcp_ao_copy_mkts_to_user()
2160 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2162 if (ntohl(sin->sin_addr.s_addr) == INADDR_ANY && in tcp_ao_copy_mkts_to_user()
2163 opt_in.prefix != 0) in tcp_ao_copy_mkts_to_user()
2164 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2166 mask = inet_make_mask(opt_in.prefix); in tcp_ao_copy_mkts_to_user()
2167 if (sin->sin_addr.s_addr & ~mask) in tcp_ao_copy_mkts_to_user()
2168 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2177 addr = (union tcp_ao_addr *)&sin6->sin6_addr; in tcp_ao_copy_mkts_to_user()
2178 addr6 = &sin6->sin6_addr; in tcp_ao_copy_mkts_to_user()
2179 port = sin6->sin6_port; in tcp_ao_copy_mkts_to_user()
2185 if (opt_in.prefix != 0) { in tcp_ao_copy_mkts_to_user()
2187 __be32 mask, addr4 = addr6->s6_addr32[3]; in tcp_ao_copy_mkts_to_user()
2189 if (opt_in.prefix > 32 || in tcp_ao_copy_mkts_to_user()
2191 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2192 mask = inet_make_mask(opt_in.prefix); in tcp_ao_copy_mkts_to_user()
2194 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2199 opt_in.prefix > 128) in tcp_ao_copy_mkts_to_user()
2200 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2202 ipv6_addr_prefix(&pfx, addr6, opt_in.prefix); in tcp_ao_copy_mkts_to_user()
2204 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2207 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2216 return -EAFNOSUPPORT; in tcp_ao_copy_mkts_to_user()
2222 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2223 if (opt_in.prefix || opt_in.sndid || opt_in.rcvid) in tcp_ao_copy_mkts_to_user()
2224 return -EINVAL; in tcp_ao_copy_mkts_to_user()
2229 /* May change in RX, while we're dumping, pre-fetch it */ in tcp_ao_copy_mkts_to_user()
2230 current_key = READ_ONCE(ao_info->current_key); in tcp_ao_copy_mkts_to_user()
2232 hlist_for_each_entry_rcu(key, &ao_info->head, node) { in tcp_ao_copy_mkts_to_user()
2239 if (opt_in.is_rnext && key == ao_info->rnext_key) in tcp_ao_copy_mkts_to_user()
2244 if (tcp_ao_key_cmp(key, l3index, addr, opt_in.prefix, in tcp_ao_copy_mkts_to_user()
2255 if (key->family == AF_INET) { in tcp_ao_copy_mkts_to_user()
2258 sin_out->sin_family = key->family; in tcp_ao_copy_mkts_to_user()
2259 sin_out->sin_port = 0; in tcp_ao_copy_mkts_to_user()
2260 memcpy(&sin_out->sin_addr, &key->addr, sizeof(struct in_addr)); in tcp_ao_copy_mkts_to_user()
2264 sin6_out->sin6_family = key->family; in tcp_ao_copy_mkts_to_user()
2265 sin6_out->sin6_port = 0; in tcp_ao_copy_mkts_to_user()
2266 memcpy(&sin6_out->sin6_addr, &key->addr, sizeof(struct in6_addr)); in tcp_ao_copy_mkts_to_user()
2268 opt_out.sndid = key->sndid; in tcp_ao_copy_mkts_to_user()
2269 opt_out.rcvid = key->rcvid; in tcp_ao_copy_mkts_to_user()
2270 opt_out.prefix = key->prefixlen; in tcp_ao_copy_mkts_to_user()
2271 opt_out.keyflags = key->keyflags; in tcp_ao_copy_mkts_to_user()
2273 opt_out.is_rnext = (key == ao_info->rnext_key); in tcp_ao_copy_mkts_to_user()
2275 opt_out.maclen = key->maclen; in tcp_ao_copy_mkts_to_user()
2276 opt_out.keylen = key->keylen; in tcp_ao_copy_mkts_to_user()
2277 opt_out.ifindex = key->l3index; in tcp_ao_copy_mkts_to_user()
2278 opt_out.pkt_good = atomic64_read(&key->pkt_good); in tcp_ao_copy_mkts_to_user()
2279 opt_out.pkt_bad = atomic64_read(&key->pkt_bad); in tcp_ao_copy_mkts_to_user()
2280 memcpy(&opt_out.key, key->key, key->keylen); in tcp_ao_copy_mkts_to_user()
2281 tcp_sigpool_algo(key->tcp_sigpool_id, opt_out.alg_name, 64); in tcp_ao_copy_mkts_to_user()
2286 return -EFAULT; in tcp_ao_copy_mkts_to_user()
2292 return -EFAULT; in tcp_ao_copy_mkts_to_user()
2297 return -EFAULT; in tcp_ao_copy_mkts_to_user()
2310 return -ENOENT; in tcp_ao_get_mkts()
2323 return -EFAULT; in tcp_ao_get_sock_info()
2326 return -EINVAL; in tcp_ao_get_sock_info()
2337 return -EINVAL; in tcp_ao_get_sock_info()
2343 return -ENOENT; in tcp_ao_get_sock_info()
2346 out.ao_required = ao->ao_required; in tcp_ao_get_sock_info()
2347 out.accept_icmps = ao->accept_icmps; in tcp_ao_get_sock_info()
2348 out.pkt_good = atomic64_read(&ao->counters.pkt_good); in tcp_ao_get_sock_info()
2349 out.pkt_bad = atomic64_read(&ao->counters.pkt_bad); in tcp_ao_get_sock_info()
2350 out.pkt_key_not_found = atomic64_read(&ao->counters.key_not_found); in tcp_ao_get_sock_info()
2351 out.pkt_ao_required = atomic64_read(&ao->counters.ao_required); in tcp_ao_get_sock_info()
2352 out.pkt_dropped_icmp = atomic64_read(&ao->counters.dropped_icmp); in tcp_ao_get_sock_info()
2354 current_key = READ_ONCE(ao->current_key); in tcp_ao_get_sock_info()
2357 out.current_key = current_key->sndid; in tcp_ao_get_sock_info()
2359 if (ao->rnext_key) { in tcp_ao_get_sock_info()
2361 out.rnext = ao->rnext_key->rcvid; in tcp_ao_get_sock_info()
2365 return -EFAULT; in tcp_ao_get_sock_info()
2379 return -EINVAL; in tcp_ao_set_repair()
2385 if (!tp->repair) in tcp_ao_set_repair()
2386 return -EPERM; in tcp_ao_set_repair()
2392 return -ENOENT; in tcp_ao_set_repair()
2394 WRITE_ONCE(ao->lisn, cmd.snt_isn); in tcp_ao_set_repair()
2395 WRITE_ONCE(ao->risn, cmd.rcv_isn); in tcp_ao_set_repair()
2396 WRITE_ONCE(ao->snd_sne, cmd.snd_sne); in tcp_ao_set_repair()
2397 WRITE_ONCE(ao->rcv_sne, cmd.rcv_sne); in tcp_ao_set_repair()
2399 hlist_for_each_entry_rcu(key, &ao->head, node) in tcp_ao_set_repair()
2413 return -EFAULT; in tcp_ao_get_repair()
2416 return -EINVAL; in tcp_ao_get_repair()
2418 if (!tp->repair) in tcp_ao_get_repair()
2419 return -EPERM; in tcp_ao_get_repair()
2425 return ao ? PTR_ERR(ao) : -ENOENT; in tcp_ao_get_repair()
2428 opt.snt_isn = ao->lisn; in tcp_ao_get_repair()
2429 opt.rcv_isn = ao->risn; in tcp_ao_get_repair()
2430 opt.snd_sne = READ_ONCE(ao->snd_sne); in tcp_ao_get_repair()
2431 opt.rcv_sne = READ_ONCE(ao->rcv_sne); in tcp_ao_get_repair()
2435 return -EFAULT; in tcp_ao_get_repair()