3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-11-26 18:59:22 +01:00

ie: Handle Extended Element IDs

Make parsing TLVs using Extended Element IDs easier by returning the
extended tag value as listed in enum ie_type instead of just the 255
value, and not returning the pointer to the extended tag as the IE data
and instead the pointer to the next byte after the extended ID.
This commit is contained in:
Andrew Zaborowski 2017-09-22 05:06:26 +02:00 committed by Denis Kenzior
parent bc30c94044
commit 5d8cb6260f

View File

@ -63,6 +63,14 @@ bool ie_tlv_iter_next(struct ie_tlv_iter *iter)
tag = *tlv++; tag = *tlv++;
len = *tlv++; len = *tlv++;
if (tag == IE_TYPE_EXTENSION) {
if (iter->pos + 2 >= iter->max || len < 1)
return false;
tag = 256 + *tlv++;
len--;
}
if (tlv + len > end) if (tlv + len > end)
return false; return false;
@ -255,8 +263,14 @@ static void ie_tlv_builder_write_header(struct ie_tlv_builder *builder)
{ {
unsigned char *tlv = builder->tlv + builder->pos; unsigned char *tlv = builder->tlv + builder->pos;
tlv[0] = builder->tag; if (builder->tag < 256) {
tlv[1] = builder->len; tlv[0] = builder->tag;
tlv[1] = builder->len;
} else {
tlv[0] = IE_TYPE_EXTENSION;
tlv[1] = builder->len + 1;
tlv[2] = builder->tag - 256;
}
} }
bool ie_tlv_builder_set_length(struct ie_tlv_builder *builder, bool ie_tlv_builder_set_length(struct ie_tlv_builder *builder,
@ -264,6 +278,9 @@ bool ie_tlv_builder_set_length(struct ie_tlv_builder *builder,
{ {
unsigned int new_pos = builder->pos + TLV_HEADER_LEN + new_len; unsigned int new_pos = builder->pos + TLV_HEADER_LEN + new_len;
if (builder->tag >= 256)
new_pos += 1;
if (new_pos > builder->max) if (new_pos > builder->max)
return false; return false;
@ -277,25 +294,23 @@ bool ie_tlv_builder_set_length(struct ie_tlv_builder *builder,
bool ie_tlv_builder_next(struct ie_tlv_builder *builder, unsigned int new_tag) bool ie_tlv_builder_next(struct ie_tlv_builder *builder, unsigned int new_tag)
{ {
if (new_tag > 0xff) if (new_tag > 0x1ff)
return false; return false;
if (builder->tag != 0xffff) { if (builder->tag != 0xffff) {
ie_tlv_builder_write_header(builder); ie_tlv_builder_write_header(builder);
builder->pos += TLV_HEADER_LEN + builder->len; builder->pos += TLV_HEADER_LEN + builder->tlv[builder->pos + 1];
} }
if (!ie_tlv_builder_set_length(builder, 0))
return false;
builder->tag = new_tag; builder->tag = new_tag;
return true; return ie_tlv_builder_set_length(builder, 0);
} }
unsigned char *ie_tlv_builder_get_data(struct ie_tlv_builder *builder) unsigned char *ie_tlv_builder_get_data(struct ie_tlv_builder *builder)
{ {
return builder->tlv + TLV_HEADER_LEN + builder->pos; return builder->tlv + TLV_HEADER_LEN + builder->pos +
(builder->tag >= 256 ? 1 : 0);
} }
bool ie_tlv_builder_recurse(struct ie_tlv_builder *builder, bool ie_tlv_builder_recurse(struct ie_tlv_builder *builder,
@ -319,7 +334,7 @@ void ie_tlv_builder_finalize(struct ie_tlv_builder *builder,
ie_tlv_builder_write_header(builder); ie_tlv_builder_write_header(builder);
len = builder->pos + TLV_HEADER_LEN + builder->len; len = builder->pos + TLV_HEADER_LEN + builder->tlv[builder->pos + 1];
if (out_len) if (out_len)
*out_len = len; *out_len = len;