@@ -690,6 +690,76 @@ static int dccp_feat_update(struct sock *sk, u8 type, u8 feat, u8 val)
690
690
return 0 ;
691
691
}
692
692
693
+ /* Select the first entry in @servlist that also occurs in @clilist (6.3.1) */
694
+ static int dccp_feat_preflist_match (u8 * servlist , u8 slen , u8 * clilist , u8 clen )
695
+ {
696
+ u8 c , s ;
697
+
698
+ for (s = 0 ; s < slen ; s ++ )
699
+ for (c = 0 ; c < clen ; c ++ )
700
+ if (servlist [s ] == clilist [c ])
701
+ return servlist [s ];
702
+ return -1 ;
703
+ }
704
+
705
+ /**
706
+ * dccp_feat_prefer - Move preferred entry to the start of array
707
+ * Reorder the @array_len elements in @array so that @preferred_value comes
708
+ * first. Returns >0 to indicate that @preferred_value does occur in @array.
709
+ */
710
+ static u8 dccp_feat_prefer (u8 preferred_value , u8 * array , u8 array_len )
711
+ {
712
+ u8 i , does_occur = 0 ;
713
+
714
+ if (array != NULL ) {
715
+ for (i = 0 ; i < array_len ; i ++ )
716
+ if (array [i ] == preferred_value ) {
717
+ array [i ] = array [0 ];
718
+ does_occur ++ ;
719
+ }
720
+ if (does_occur )
721
+ array [0 ] = preferred_value ;
722
+ }
723
+ return does_occur ;
724
+ }
725
+
726
+ /**
727
+ * dccp_feat_reconcile - Reconcile SP preference lists
728
+ * @fval: SP list to reconcile into
729
+ * @arr: received SP preference list
730
+ * @len: length of @arr in bytes
731
+ * @is_server: whether this side is the server (and @fv is the server's list)
732
+ * @reorder: whether to reorder the list in @fv after reconciling with @arr
733
+ * When successful, > 0 is returned and the reconciled list is in @fval.
734
+ * A value of 0 means that negotiation failed (no shared entry).
735
+ */
736
+ static int dccp_feat_reconcile (dccp_feat_val * fv , u8 * arr , u8 len ,
737
+ bool is_server , bool reorder )
738
+ {
739
+ int rc ;
740
+
741
+ if (!fv -> sp .vec || !arr ) {
742
+ DCCP_CRIT ("NULL feature value or array" );
743
+ return 0 ;
744
+ }
745
+
746
+ if (is_server )
747
+ rc = dccp_feat_preflist_match (fv -> sp .vec , fv -> sp .len , arr , len );
748
+ else
749
+ rc = dccp_feat_preflist_match (arr , len , fv -> sp .vec , fv -> sp .len );
750
+
751
+ if (!reorder )
752
+ return rc ;
753
+ if (rc < 0 )
754
+ return 0 ;
755
+
756
+ /*
757
+ * Reorder list: used for activating features and in dccp_insert_fn_opt.
758
+ */
759
+ return dccp_feat_prefer (rc , fv -> sp .vec , fv -> sp .len );
760
+ }
761
+
762
+ #ifdef __this_is_the_old_framework_and_will_be_removed_later_in_a_subsequent_patch
693
763
static int dccp_feat_reconcile (struct sock * sk , struct dccp_opt_pend * opt ,
694
764
u8 * rpref , u8 rlen )
695
765
{
@@ -885,6 +955,7 @@ static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len)
885
955
886
956
return 0 ;
887
957
}
958
+ #endif /* (later) */
888
959
889
960
static void dccp_feat_empty_confirm (struct dccp_minisock * dmsk ,
890
961
u8 type , u8 feature )
@@ -960,12 +1031,14 @@ int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len)
960
1031
switch (feature ) {
961
1032
/* deal with SP features */
962
1033
case DCCPF_CCID :
963
- rc = dccp_feat_sp (sk , type , feature , val , len );
1034
+ /* XXX Obsoleted by next patch
1035
+ rc = dccp_feat_sp(sk, type, feature, val, len); */
964
1036
break ;
965
1037
966
1038
/* deal with NN features */
967
1039
case DCCPF_ACK_RATIO :
968
- rc = dccp_feat_nn (sk , type , feature , val , len );
1040
+ /* XXX Obsoleted by next patch
1041
+ rc = dccp_feat_nn(sk, type, feature, val, len); */
969
1042
break ;
970
1043
971
1044
/* XXX implement other features */
0 commit comments