Skip to content

Commit

Permalink
fix TLV encoding
Browse files Browse the repository at this point in the history
by adding the current TLV header, which was missing in the
previous commit.

Also clean up the code and use extend_option() where the data
is more than 255 bytes.

We try to avoid splitting data across multiple options.  The result
is that the encoder may output multiple options of the same number,
BUT where the lengths are smaller than 255.  This means that any
decoder can just decode the data in-place most of the time.

We split data across multiple options ONLY when the encoded data
is more than 255 bytes.  And even then, we try to start that
encoding on a new option.
  • Loading branch information
alandekok committed Apr 6, 2019
1 parent 129aed0 commit c62b5d1
Showing 1 changed file with 31 additions and 28 deletions.
59 changes: 31 additions & 28 deletions src/protocols/dhcpv4/encode.c
Expand Up @@ -303,8 +303,7 @@ static ssize_t encode_rfc_hdr(uint8_t *out, ssize_t outlen,
out = extend_option(out, end, p, len);
if (!out) break;

p = out + 2;
p += out[1];
p = out + 2 + out[1];
}

next = fr_cursor_current(cursor);
Expand Down Expand Up @@ -367,6 +366,7 @@ static ssize_t encode_tlv_hdr(uint8_t *out, ssize_t outlen,
if (len < 0) return len;
if (len == 0) break; /* Insufficient space */


/*
* If the newly added data fits within the
* current option, then update the header, and go
Expand All @@ -377,41 +377,44 @@ static ssize_t encode_tlv_hdr(uint8_t *out, ssize_t outlen,
p += len;

} else {
p += len;
/*
* The data doesn't fit within the
* current option. Start a new option.
*/

/*
* The encoder added more data than fits
* into the current option. Wind the
* pointers to the end of the encoded
* data.
* Not enough space for the 2 byte
* header.
*/
while ((out + out[1]) < p) {
out += out[1]; /* should be 255 */
}
if ((p + 2 + len) >= end) break;

/*
* The current option ends at p, which is
* what we want. However, if the current
* option ALSO is full, then we need to
* add a new option header.
* Move the data up and start a new
* option.
*/
if (out[1] == 255) {
out += out[1];
memmove(p + 2, p, len);
p[0] = start[0];
p[1] = 0;
out = p;
p = out + 2;

/*
* The data fits entirely within the new
* option. Just use that.
*/
if (len <= 255) {
out[1] = len;
p += len;

} else {
/*
* Don't add in an option header.
* Rely on the caller to check
* that there's no more room in
* the buffer.
* The data has to be split
* across multiple options.
*/
if ((end - out) < 3) {
p = out;
break;
}

out[0] = start[0];
out[1] = 0;
p = out + 2;
out = extend_option(out, end, p, len);
if (!out) break;

p = out + 2 + out[1];
}
}

Expand Down

0 comments on commit c62b5d1

Please sign in to comment.