@@ -886,16 +886,15 @@ static unsigned int tcp_synack_options(const struct sock *sk,
886886 struct request_sock * req ,
887887 unsigned int mss , struct sk_buff * skb ,
888888 struct tcp_out_options * opts ,
889- const struct tcp_md5sig_key * md5 ,
889+ const struct tcp_key * key ,
890890 struct tcp_fastopen_cookie * foc ,
891891 enum tcp_synack_type synack_type ,
892892 struct sk_buff * syn_skb )
893893{
894894 struct inet_request_sock * ireq = inet_rsk (req );
895895 unsigned int remaining = MAX_TCP_OPTION_SPACE ;
896896
897- #ifdef CONFIG_TCP_MD5SIG
898- if (md5 ) {
897+ if (tcp_key_is_md5 (key )) {
899898 opts -> options |= OPTION_MD5 ;
900899 remaining -= TCPOLEN_MD5SIG_ALIGNED ;
901900
@@ -906,8 +905,11 @@ static unsigned int tcp_synack_options(const struct sock *sk,
906905 */
907906 if (synack_type != TCP_SYNACK_COOKIE )
908907 ireq -> tstamp_ok &= !ireq -> sack_ok ;
908+ } else if (tcp_key_is_ao (key )) {
909+ opts -> options |= OPTION_AO ;
910+ remaining -= tcp_ao_len (key -> ao_key );
911+ ireq -> tstamp_ok &= !ireq -> sack_ok ;
909912 }
910- #endif
911913
912914 /* We always send an MSS option. */
913915 opts -> mss = mss ;
@@ -3653,7 +3655,6 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst,
36533655{
36543656 struct inet_request_sock * ireq = inet_rsk (req );
36553657 const struct tcp_sock * tp = tcp_sk (sk );
3656- struct tcp_md5sig_key * md5 = NULL ;
36573658 struct tcp_out_options opts ;
36583659 struct tcp_key key = {};
36593660 struct sk_buff * skb ;
@@ -3707,18 +3708,48 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst,
37073708 tcp_rsk (req )-> snt_synack = tcp_skb_timestamp_us (skb );
37083709 }
37093710
3710- #ifdef CONFIG_TCP_MD5SIG
3711+ #if defined( CONFIG_TCP_MD5SIG ) || defined( CONFIG_TCP_AO )
37113712 rcu_read_lock ();
3712- md5 = tcp_rsk (req )-> af_specific -> req_md5_lookup (sk , req_to_sk (req ));
3713- if (md5 )
3714- key .type = TCP_KEY_MD5 ;
37153713#endif
3714+ if (tcp_rsk_used_ao (req )) {
3715+ #ifdef CONFIG_TCP_AO
3716+ struct tcp_ao_key * ao_key = NULL ;
3717+ u8 maclen = tcp_rsk (req )-> maclen ;
3718+ u8 keyid = tcp_rsk (req )-> ao_keyid ;
3719+
3720+ ao_key = tcp_sk (sk )-> af_specific -> ao_lookup (sk , req_to_sk (req ),
3721+ keyid , -1 );
3722+ /* If there is no matching key - avoid sending anything,
3723+ * especially usigned segments. It could try harder and lookup
3724+ * for another peer-matching key, but the peer has requested
3725+ * ao_keyid (RFC5925 RNextKeyID), so let's keep it simple here.
3726+ */
3727+ if (unlikely (!ao_key || tcp_ao_maclen (ao_key ) != maclen )) {
3728+ u8 key_maclen = ao_key ? tcp_ao_maclen (ao_key ) : 0 ;
3729+
3730+ rcu_read_unlock ();
3731+ kfree_skb (skb );
3732+ net_warn_ratelimited ("TCP-AO: the keyid %u with maclen %u|%u from SYN packet is not present - not sending SYNACK\n" ,
3733+ keyid , maclen , key_maclen );
3734+ return NULL ;
3735+ }
3736+ key .ao_key = ao_key ;
3737+ key .type = TCP_KEY_AO ;
3738+ #endif
3739+ } else {
3740+ #ifdef CONFIG_TCP_MD5SIG
3741+ key .md5_key = tcp_rsk (req )-> af_specific -> req_md5_lookup (sk ,
3742+ req_to_sk (req ));
3743+ if (key .md5_key )
3744+ key .type = TCP_KEY_MD5 ;
3745+ #endif
3746+ }
37163747 skb_set_hash (skb , READ_ONCE (tcp_rsk (req )-> txhash ), PKT_HASH_TYPE_L4 );
37173748 /* bpf program will be interested in the tcp_flags */
37183749 TCP_SKB_CB (skb )-> tcp_flags = TCPHDR_SYN | TCPHDR_ACK ;
3719- tcp_header_size = tcp_synack_options (sk , req , mss , skb , & opts , md5 ,
3720- foc , synack_type ,
3721- syn_skb ) + sizeof (* th );
3750+ tcp_header_size = tcp_synack_options (sk , req , mss , skb , & opts ,
3751+ & key , foc , synack_type , syn_skb )
3752+ + sizeof (* th );
37223753
37233754 skb_push (skb , tcp_header_size );
37243755 skb_reset_transport_header (skb );
@@ -3738,15 +3769,24 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst,
37383769
37393770 /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */
37403771 th -> window = htons (min (req -> rsk_rcv_wnd , 65535U ));
3741- tcp_options_write (th , NULL , NULL , & opts , & key );
3772+ tcp_options_write (th , NULL , tcp_rsk ( req ) , & opts , & key );
37423773 th -> doff = (tcp_header_size >> 2 );
37433774 TCP_INC_STATS (sock_net (sk ), TCP_MIB_OUTSEGS );
37443775
3745- #ifdef CONFIG_TCP_MD5SIG
37463776 /* Okay, we have all we need - do the md5 hash if needed */
3747- if (md5 )
3777+ if (tcp_key_is_md5 (& key )) {
3778+ #ifdef CONFIG_TCP_MD5SIG
37483779 tcp_rsk (req )-> af_specific -> calc_md5_hash (opts .hash_location ,
3749- md5 , req_to_sk (req ), skb );
3780+ key .md5_key , req_to_sk (req ), skb );
3781+ #endif
3782+ } else if (tcp_key_is_ao (& key )) {
3783+ #ifdef CONFIG_TCP_AO
3784+ tcp_rsk (req )-> af_specific -> ao_synack_hash (opts .hash_location ,
3785+ key .ao_key , req , skb ,
3786+ opts .hash_location - (u8 * )th , 0 );
3787+ #endif
3788+ }
3789+ #if defined(CONFIG_TCP_MD5SIG ) || defined(CONFIG_TCP_AO )
37503790 rcu_read_unlock ();
37513791#endif
37523792
0 commit comments