[Announce]: Test Tree Updated to Implement NN-Options of Fixed Size

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is an update regarding the test tree.

The code has been amended to enforce fixed sizes of non-negotiable feature options:

 * 2 bytes for Ack Ratio (RFC 4340, 11.3 and 6.6.8)
 * 6 bytes for Sequence Window (RFC 4340, 7.5.2).

Thanks to Wei Yongjun for pointing this out.


Details of the change:
======================
 * removed patch "dccp: Auxiliary function for smallest-fit option lengths"
 * updated several other patches, an annotated inter-diff of the tree is below
 * all changes have been uploaded to
   git://eden-feed.erg.abdn.ac.uk/dccp_exp 	(tree "dccp" or	"ccid4")


RFC compliance:
===============
The length of options leaving the stack conforms to the above.

With regard to incoming options, there is greater leniency: NN-options are 
value-checked, but not also length-checked.

I believe that this is the correct behaviour with regard to the RFC, due to:
 * section 6.3.2 says that the feature-remote must accept any valid value;
 * general robustness principle (3.6), input is more liberal than output.

If people also wanted to enforce length constraints on incoming NN options,
this would be possible with not much change.


Testing the changes:
====================
The following were confirmed against RFC 4340:

1) from section 6.5 (page 37):

    Change L(Sequence Window, 1024)  gives (hex) 20  09  03  00 00 00 00 04 00
    Confirm R(Sequence Window, 1024) gives (hex) 23  09  03  00 00 00 00 04 00

   Where 0x9 is the fixed length of the Sequence Window option (type 0x3).

2) Repeated the same example with a local/remote Sequence Window of 1000
   This looks almost identical, with the difference that 1000 in hex is 03 e8.
    

3) The other NN-option is Ack Ratio (type 0x5) which has a length of 2+3=0x5:
    Change L(Ack Ratio, 4)  gives (hex) 20  05  05  00 04
    Confirm R(Ack Ratio, 4) gives (hex) 23  05  05  00 04

4) Communicating with a host that uses non-standard option lengths
    I have tested this with Sequence Window only, expect Ack Ratio to be similar.
    (a) DCCP A sends 9-byte Change L with value 1000, accepts confirmation from
        DCCP B even when 1000 is wrapped in two instead of 6 bytes.
    (b) DCCP A accepts a 2-byte Change L(Sequence Window, 2048) but confirms
        (correctly) with a 6-byte representation of 2048.
    

                          ===========================
                          Inter-diff of the Test tree
                          ===========================

----------------------------------------------------------------------------------
    The first change involves using fixed option lengths for the NN-options
    It introduces a new function dccp_feat_valid_nn_length()
----------------------------------------------------------------------------------
--- b/net/dccp/feat.h
+++ b/net/dccp/feat.h
@@ -114,7 +114,7 @@
 extern int  dccp_feat_clone_list(struct list_head const *, struct list_head *);
 
 /*
- * Determining lengths of variable-length options.
+ * Encoding variable-length options and their maximum length.
  *
  * This affects NN options (SP options are all u8) and other variable-length
  * options (see table 3 in RFC 4340). The limit is currently given the Sequence
@@ -124,13 +124,6 @@
  * sure that you also update all code which refers to it.
  */
 #define DCCP_OPTVAL_MAXLEN	6
-/* Find smallest-fit for @value, but not more than 6 bytes (current maximum) */
-static inline u8 dccp_bytes_per_value(const u64 value)
-{
-	if (value > 0xFFFFFFFFull)
-		return DCCP_OPTVAL_MAXLEN;
-	return value > 0xFFFF ? 4 : (value > 0xFF ? 2 : 1);
-}
 
 extern void dccp_encode_value_var(const u64 value, u8 *to, const u8 len);
 extern u64  dccp_decode_value_var(const u8 *bf, const u8 len);
--- b/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -565,6 +565,20 @@
 	return -ENOMEM;
 }
 
+/**
+ * dccp_feat_valid_nn_length  -  Enforce length constraints on NN options
+ * Length is between 0 and %DCCP_OPTVAL_MAXLEN. Used for outgoing packets only,
+ * incoming options are accepted as long as their values are valid.
+ */
+static u8 dccp_feat_valid_nn_length(u8 feat_num)
+{
+	if (feat_num == DCCPF_ACK_RATIO)	/* RFC 4340, 11.3 and 6.6.8 */
+		return 2;
+	if (feat_num == DCCPF_SEQUENCE_WINDOW)	/* RFC 4340, 7.5.2 and 6.5  */
+		return 6;
+	return 0;
+}
+
 static u8 dccp_feat_is_valid_nn_val(u8 feat_num, u64 val)
 {
 	switch (feat_num) {
@@ -635,7 +649,7 @@
 				ptr = pos->val.sp.vec;
 				rpt = pos->needs_confirm;
 			} else if (type == FEAT_NN) {
-				len = dccp_bytes_per_value(pos->val.nn);
+				len = dccp_feat_valid_nn_length(pos->feat_num);
 				ptr = nn_in_nbo;
 				dccp_encode_value_var(pos->val.nn, ptr, len);
 			} else {

----------------------------------------------------------------------------------
   The second update involves the variable length NDP option (1..6 bytes).
----------------------------------------------------------------------------------
--- b/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -279,6 +279,13 @@
 		*to++ = (value & 0xFF);
 }
 
+static inline u8 dccp_ndp_len(const u64 ndp)
+{
+	if (likely(ndp <= 0xFF))
+		return 1;
+	return likely(ndp <= USHORT_MAX) ? 2 : ndp <= UINT_MAX ? 4 : 6;
+}
+
 int dccp_insert_option(struct sock *sk, struct sk_buff *skb,
 			const unsigned char option,
 			const void *value, const unsigned char len)
@@ -312,7 +319,7 @@
 
 	if (ndp > 0) {
 		unsigned char *ptr;
-		const int ndp_len = dccp_bytes_per_value(ndp);
+		const int ndp_len = dccp_ndp_len(ndp);
 		const int len = ndp_len + 2;
 
 		if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
--
To unsubscribe from this list: send the line "unsubscribe dccp" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel]     [IETF DCCP]     [Linux Networking]     [Git]     [Security]     [Linux Assembly]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]

  Powered by Linux