2011-02-24 17:17:19

by Andre Dieb Martins

[permalink] [raw]
Subject: [PATCH] Fix HCI LE advertising report dump

LE advertising report event has only one data block for each report. Thus, we
can't reuse ext_inquiry_response_dump(), which loops over successive data blocks
until reaches a zero-length one.

This commit introduces ext_inquiry_data_dump(), which dumps a frame containing
data formatted according to [Vol 3] Part C, Section 8. This function is reused
by ext_inquiry_response_dump().

Also adds RSSI parsing to each advertising report.
---
parser/hci.c | 136 ++++++++++++++++++++++++++++++++-------------------------
1 files changed, 76 insertions(+), 60 deletions(-)

diff --git a/parser/hci.c b/parser/hci.c
index 183fa66..dc27a27 100644
--- a/parser/hci.c
+++ b/parser/hci.c
@@ -757,67 +757,83 @@ static char *filterpolicy2str(uint8_t policy)
}
}

-static inline void ext_inquiry_response_dump(int level, struct frame *frm)
+static inline void ext_inquiry_data_dump(int level, struct frame *frm,
+ uint8_t *data)
{
- void *ptr = frm->ptr;
- uint32_t len = frm->len;
- uint8_t type, length;
+ uint8_t len = data[0];
+ uint8_t type;
char *str;
int i;

- length = get_u8(frm);
+ if (len == 0)
+ return;

- while (length > 0) {
- type = get_u8(frm);
- length--;
+ type = data[1];
+ data += 2;
+ len -= 1;

- switch (type) {
- case 0x01:
- p_indent(level, frm);
- printf("Flags:");
- for (i = 0; i < length; i++)
- printf(" 0x%2.2x", *((uint8_t *) (frm->ptr + i)));
- printf("\n");
- break;
+ switch (type) {
+ case 0x01:
+ p_indent(level, frm);
+ printf("Flags:");
+ for (i = 0; i < len; i++)
+ printf(" 0x%2.2x", data[i]);
+ printf("\n");
+ break;

- case 0x02:
- case 0x03:
- p_indent(level, frm);
- printf("%s service classes:",
- type == 0x02 ? "Shortened" : "Complete");
- for (i = 0; i < length / 2; i++) {
- uint16_t val = btohs(bt_get_unaligned((uint16_t *) (frm->ptr + (i * 2))));
- printf(" 0x%4.4x", val);
- }
- printf("\n");
- break;
+ case 0x02:
+ case 0x03:
+ p_indent(level, frm);
+ printf("%s service classes:",
+ type == 0x02 ? "Shortened" : "Complete");

- case 0x08:
- case 0x09:
- str = malloc(length + 1);
- if (str) {
- snprintf(str, length + 1, "%s", (char *) frm->ptr);
- for (i = 0; i < length; i++)
- if (!isprint(str[i]))
- str[i] = '.';
- p_indent(level, frm);
- printf("%s local name: \'%s\'\n",
- type == 0x08 ? "Shortened" : "Complete", str);
- free(str);
- }
- break;
+ for (i = 0; i < len / 2; i++) {
+ uint16_t val;

- case 0x0a:
- p_indent(level, frm);
- printf("TX power level: %d\n", *((uint8_t *) frm->ptr));
- break;
+ val = btohs(bt_get_unaligned(((uint16_t *) (data + i * 2))));
+ printf(" 0x%4.4x", val);
+ }
+ printf("\n");
+ break;

- default:
+ case 0x08:
+ case 0x09:
+ str = malloc(len + 1);
+ if (str) {
+ snprintf(str, len + 1, "%s", (char *) data);
+ for (i = 0; i < len; i++)
+ if (!isprint(str[i]))
+ str[i] = '.';
p_indent(level, frm);
- printf("Unknown type 0x%02x with %d bytes data\n",
- type, length);
- break;
+ printf("%s local name: \'%s\'\n",
+ type == 0x08 ? "Shortened" : "Complete", str);
+ free(str);
}
+ break;
+
+ case 0x0a:
+ p_indent(level, frm);
+ printf("TX power level: %d\n", *((uint8_t *) data));
+ break;
+
+ default:
+ p_indent(level, frm);
+ printf("Unknown type 0x%02x with %d bytes data\n",
+ type, len);
+ break;
+ }
+}
+
+static inline void ext_inquiry_response_dump(int level, struct frame *frm)
+{
+ void *ptr = frm->ptr;
+ uint32_t len = frm->len;
+ uint8_t length;
+
+ length = get_u8(frm);
+
+ while (length > 0) {
+ ext_inquiry_data_dump(level, frm, frm->ptr);

frm->ptr += length;
frm->len -= length;
@@ -3504,14 +3520,12 @@ static inline void evt_le_conn_complete_dump(int level, struct frame *frm)

static inline void evt_le_advertising_report_dump(int level, struct frame *frm)
{
- uint8_t num = get_u8(frm);
- char addr[18];
- int i;
+ uint8_t num_reports = get_u8(frm);
+ const uint8_t RSSI_SIZE = 1;

- for (i = 0; i < num; i++) {
+ while (num_reports--) {
+ char addr[18];
le_advertising_info *info = frm->ptr;
- void *ptr = frm->ptr;
- uint32_t len = frm->len;

p_ba2str(&info->bdaddr, addr);

@@ -3522,13 +3536,15 @@ static inline void evt_le_advertising_report_dump(int level, struct frame *frm)
printf("bdaddr %s (%s)\n", addr,
bdaddrtype2str(info->bdaddr_type));

- frm->ptr += LE_ADVERTISING_INFO_SIZE;
- frm->len -= LE_ADVERTISING_INFO_SIZE;
+ if (info->length > 0) {
+ ext_inquiry_data_dump(level, frm, &info->length + 1);
+ }

- ext_inquiry_response_dump(level, frm);
+ frm->ptr += LE_ADVERTISING_INFO_SIZE + info->length + RSSI_SIZE;
+ frm->len -= LE_ADVERTISING_INFO_SIZE + info->length + RSSI_SIZE;

- frm->ptr = ptr + 1;
- frm->len = len - 1;
+ p_indent(level, frm);
+ printf("RSSI: %d\n", ((int8_t *) frm->ptr)[frm->len - 1]);
}
}

--
1.7.1



2011-02-24 17:40:10

by Claudio Takahasi

[permalink] [raw]
Subject: Re: [PATCH] Fix HCI LE advertising report dump

SGkgQW5kcmUsCgpPbiBUaHUsIEZlYiAyNCwgMjAxMSBhdCA1OjE3IFBNLCBBbmRyZSBEaWViIE1h
cnRpbnMKPGFuZHJlLmRpZWJAc2lnbm92ZS5jb20+IHdyb3RlOgo+IExFIGFkdmVydGlzaW5nIHJl
cG9ydCBldmVudCBoYXMgb25seSBvbmUgZGF0YSBibG9jayBmb3IgZWFjaCByZXBvcnQuIFRodXMs
IHdlCj4gY2FuJ3QgcmV1c2UgZXh0X2lucXVpcnlfcmVzcG9uc2VfZHVtcCgpLCB3aGljaCBsb29w
cyBvdmVyIHN1Y2Nlc3NpdmUgZGF0YSBibG9ja3MKPiB1bnRpbCByZWFjaGVzIGEgemVyby1sZW5n
dGggb25lLgo+Cj4gVGhpcyBjb21taXQgaW50cm9kdWNlcyBleHRfaW5xdWlyeV9kYXRhX2R1bXAo
KSwgd2hpY2ggZHVtcHMgYSBmcmFtZSBjb250YWluaW5nCj4gZGF0YSBmb3JtYXR0ZWQgYWNjb3Jk
aW5nIHRvIFtWb2wgM10gUGFydCBDLCBTZWN0aW9uIDguIFRoaXMgZnVuY3Rpb24gaXMgcmV1c2Vk
Cj4gYnkgZXh0X2lucXVpcnlfcmVzcG9uc2VfZHVtcCgpLgo+Cj4gQWxzbyBhZGRzIFJTU0kgcGFy
c2luZyB0byBlYWNoIGFkdmVydGlzaW5nIHJlcG9ydC4KPiAtLS0KPiDCoHBhcnNlci9oY2kuYyB8
IMKgMTM2ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLQo+IMKgMSBmaWxlcyBjaGFuZ2VkLCA3NiBpbnNlcnRpb25zKCspLCA2MCBkZWxldGlv
bnMoLSkKPgo+IGRpZmYgLS1naXQgYS9wYXJzZXIvaGNpLmMgYi9wYXJzZXIvaGNpLmMKPiBpbmRl
eCAxODNmYTY2Li5kYzI3YTI3IDEwMDY0NAo+IC0tLSBhL3BhcnNlci9oY2kuYwo+ICsrKyBiL3Bh
cnNlci9oY2kuYwo+IEBAIC03NTcsNjcgKzc1Nyw4MyBAQCBzdGF0aWMgY2hhciAqZmlsdGVycG9s
aWN5MnN0cih1aW50OF90IHBvbGljeSkKPiDCoCDCoCDCoCDCoH0KPiDCoH0KPgo+IC1zdGF0aWMg
aW5saW5lIHZvaWQgZXh0X2lucXVpcnlfcmVzcG9uc2VfZHVtcChpbnQgbGV2ZWwsIHN0cnVjdCBm
cmFtZSAqZnJtKQo+ICtzdGF0aWMgaW5saW5lIHZvaWQgZXh0X2lucXVpcnlfZGF0YV9kdW1wKGlu
dCBsZXZlbCwgc3RydWN0IGZyYW1lICpmcm0sCj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB1aW50OF90ICpkYXRh
KQo+IMKgewo+IC0gwqAgwqAgwqAgdm9pZCAqcHRyID0gZnJtLT5wdHI7Cj4gLSDCoCDCoCDCoCB1
aW50MzJfdCBsZW4gPSBmcm0tPmxlbjsKPiAtIMKgIMKgIMKgIHVpbnQ4X3QgdHlwZSwgbGVuZ3Ro
Owo+ICsgwqAgwqAgwqAgdWludDhfdCBsZW4gPSBkYXRhWzBdOwo+ICsgwqAgwqAgwqAgdWludDhf
dCB0eXBlOwo+IMKgIMKgIMKgIMKgY2hhciAqc3RyOwo+IMKgIMKgIMKgIMKgaW50IGk7Cj4KPiAt
IMKgIMKgIMKgIGxlbmd0aCA9IGdldF91OChmcm0pOwo+ICsgwqAgwqAgwqAgaWYgKGxlbiA9PSAw
KQo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgcmV0dXJuOwo+Cj4gLSDCoCDCoCDCoCB3aGlsZSAo
bGVuZ3RoID4gMCkgewo+IC0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgdHlwZSA9IGdldF91OChmcm0p
Owo+IC0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgbGVuZ3RoLS07Cj4gKyDCoCDCoCDCoCB0eXBlID0g
ZGF0YVsxXTsKPiArIMKgIMKgIMKgIGRhdGEgKz0gMjsKPiArIMKgIMKgIMKgIGxlbiAtPSAxOwo+
Cj4gLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzd2l0Y2ggKHR5cGUpIHsKPiAtIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIGNhc2UgMHgwMToKPiAtIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IHBfaW5kZW50KGxldmVsLCBmcm0pOwo+IC0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgcHJpbnRmKCJGbGFnczoiKTsKPiAtIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykKPiAtIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIHByaW50ZigiIDB4JTIuMngiLCAqKCh1aW50OF90ICopIChm
cm0tPnB0ciArIGkpKSk7Cj4gLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBwcmlu
dGYoIlxuIik7Cj4gLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBicmVhazsKPiAr
IMKgIMKgIMKgIHN3aXRjaCAodHlwZSkgewo+ICsgwqAgwqAgwqAgY2FzZSAweDAxOgo+ICsgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgcF9pbmRlbnQobGV2ZWwsIGZybSk7Cj4gKyDCoCDCoCDCoCDCoCDC
oCDCoCDCoCBwcmludGYoIkZsYWdzOiIpOwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZm9yIChp
ID0gMDsgaSA8IGxlbjsgaSsrKQo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
cHJpbnRmKCIgMHglMi4yeCIsIGRhdGFbaV0pOwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgcHJp
bnRmKCJcbiIpOwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgYnJlYWs7Cj4KPiAtIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIGNhc2UgMHgwMjoKPiAtIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGNhc2UgMHgw
MzoKPiAtIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHBfaW5kZW50KGxldmVsLCBm
cm0pOwo+IC0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgcHJpbnRmKCIlcyBzZXJ2
aWNlIGNsYXNzZXM6IiwKPiAtIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIHR5cGUgPT0gMHgwMiA/ICJTaG9ydGVuZWQiIDogIkNvbXBsZXRl
Iik7Cj4gLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBmb3IgKGkgPSAwOyBpIDwg
bGVuZ3RoIC8gMjsgaSsrKSB7Cj4gLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoCB1aW50MTZfdCB2YWwgPSBidG9ocyhidF9nZXRfdW5hbGlnbmVkKCh1aW50MTZf
dCAqKSAoZnJtLT5wdHIgKyAoaSAqIDIpKSkpOwo+IC0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgcHJpbnRmKCIgMHglNC40eCIsIHZhbCk7Cj4gLSDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB9Cj4gLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCBwcmludGYoIlxuIik7Cj4gLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCBicmVhazsKPiArIMKgIMKgIMKgIGNhc2UgMHgwMjoKPiArIMKgIMKgIMKgIGNhc2UgMHgwMzoK
PiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHBfaW5kZW50KGxldmVsLCBmcm0pOwo+ICsgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgcHJpbnRmKCIlcyBzZXJ2aWNlIGNsYXNzZXM6IiwKPiArIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHR5cGUgPT0gMHgwMiA/ICJTaG9y
dGVuZWQiIDogIkNvbXBsZXRlIik7Cj4KPiAtIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGNhc2UgMHgw
ODoKPiAtIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGNhc2UgMHgwOToKPiAtIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIHN0ciA9IG1hbGxvYyhsZW5ndGggKyAxKTsKPiAtIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIChzdHIpIHsKPiAtIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHNucHJpbnRmKHN0ciwgbGVuZ3RoICsgMSwgIiVz
IiwgKGNoYXIgKikgZnJtLT5wdHIpOwo+IC0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKQo+IC0gwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKCFpc3By
aW50KHN0cltpXSkpCj4gLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzdHJbaV0gPSAnLic7Cj4gLSDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBwX2luZGVudChsZXZlbCwgZnJtKTsK
PiAtIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHByaW50Zigi
JXMgbG9jYWwgbmFtZTogXCclc1wnXG4iLAo+IC0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgdHlwZSA9PSAweDA4ID8gIlNob3J0ZW5lZCIg
OiAiQ29tcGxldGUiLCBzdHIpOwo+IC0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgZnJlZShzdHIpOwo+IC0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgfQo+IC0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgYnJlYWs7Cj4gKyDCoCDC
oCDCoCDCoCDCoCDCoCDCoCBmb3IgKGkgPSAwOyBpIDwgbGVuIC8gMjsgaSsrKSB7Cj4gKyDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB1aW50MTZfdCB2YWw7Cj4KPiAtIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIGNhc2UgMHgwYToKPiAtIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIHBfaW5kZW50KGxldmVsLCBmcm0pOwo+IC0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgcHJpbnRmKCJUWCBwb3dlciBsZXZlbDogJWRcbiIsICooKHVpbnQ4X3QgKikgZnJtLT5w
dHIpKTsKPiAtIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGJyZWFrOwo+ICsgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgdmFsID0gYnRvaHMoYnRfZ2V0X3VuYWxpZ25l
ZCgoKHVpbnQxNl90ICopIChkYXRhICsgaSAqIDIpKSkpOwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgcHJpbnRmKCIgMHglNC40eCIsIHZhbCk7Cj4gKyDCoCDCoCDCoCDCoCDC
oCDCoCDCoCB9Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCBwcmludGYoIlxuIik7Cj4gKyDCoCDC
oCDCoCDCoCDCoCDCoCDCoCBicmVhazsKPgo+IC0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgZGVmYXVs
dDoKPiArIMKgIMKgIMKgIGNhc2UgMHgwODoKPiArIMKgIMKgIMKgIGNhc2UgMHgwOToKPiArIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIHN0ciA9IG1hbGxvYyhsZW4gKyAxKTsKPiArIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIGlmIChzdHIpIHsKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IHNucHJpbnRmKHN0ciwgbGVuICsgMSwgIiVzIiwgKGNoYXIgKikgZGF0YSk7Cj4gKyDCoCDCoCDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspCj4gKyDC
oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpZiAoIWlzcHJpbnQo
c3RyW2ldKSkKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIHN0cltpXSA9ICcuJzsKPiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC
oCDCoCDCoHBfaW5kZW50KGxldmVsLCBmcm0pOwo+IC0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgcHJpbnRmKCJVbmtub3duIHR5cGUgMHglMDJ4IHdpdGggJWQgYnl0ZXMgZGF0YVxu
IiwKPiAtIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHR5cGUsIGxlbmd0aCk7
Cj4gLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBicmVhazsKPiArIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHByaW50ZigiJXMgbG9jYWwgbmFtZTogXCclc1wnXG4i
LAo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgdHlwZSA9
PSAweDA4ID8gIlNob3J0ZW5lZCIgOiAiQ29tcGxldGUiLCBzdHIpOwo+ICsgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgZnJlZShzdHIpOwo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
fQo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgYnJlYWs7Cj4gKwo+ICsgwqAgwqAgwqAgY2FzZSAw
eDBhOgo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgcF9pbmRlbnQobGV2ZWwsIGZybSk7Cj4gKyDC
oCDCoCDCoCDCoCDCoCDCoCDCoCBwcmludGYoIlRYIHBvd2VyIGxldmVsOiAlZFxuIiwgKigodWlu
dDhfdCAqKSBkYXRhKSk7Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCBicmVhazsKPiArCj4gKyDC
oCDCoCDCoCBkZWZhdWx0Ogo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgcF9pbmRlbnQobGV2ZWws
IGZybSk7Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCBwcmludGYoIlVua25vd24gdHlwZSAweCUw
Mnggd2l0aCAlZCBieXRlcyBkYXRhXG4iLAo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgdHlw
ZSwgbGVuKTsKPiArIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGJyZWFrOwo+ICsgwqAgwqAgwqAgfQo+
ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5lIHZvaWQgZXh0X2lucXVpcnlfcmVzcG9uc2VfZHVtcChp
bnQgbGV2ZWwsIHN0cnVjdCBmcmFtZSAqZnJtKQo+ICt7Cj4gKyDCoCDCoCDCoCB2b2lkICpwdHIg
PSBmcm0tPnB0cjsKPiArIMKgIMKgIMKgIHVpbnQzMl90IGxlbiA9IGZybS0+bGVuOwo+ICsgwqAg
wqAgwqAgdWludDhfdCBsZW5ndGg7Cj4gKwo+ICsgwqAgwqAgwqAgbGVuZ3RoID0gZ2V0X3U4KGZy
bSk7Cj4gKwo+ICsgwqAgwqAgwqAgd2hpbGUgKGxlbmd0aCA+IDApIHsKPiArIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIGV4dF9pbnF1aXJ5X2RhdGFfZHVtcChsZXZlbCwgZnJtLCBmcm0tPnB0cik7Cj4K
PiDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGZybS0+cHRyICs9IGxlbmd0aDsKPiDCoCDCoCDCoCDC
oCDCoCDCoCDCoCDCoGZybS0+bGVuIC09IGxlbmd0aDsKPiBAQCAtMzUwNCwxNCArMzUyMCwxMiBA
QCBzdGF0aWMgaW5saW5lIHZvaWQgZXZ0X2xlX2Nvbm5fY29tcGxldGVfZHVtcChpbnQgbGV2ZWws
IHN0cnVjdCBmcmFtZSAqZnJtKQo+Cj4gwqBzdGF0aWMgaW5saW5lIHZvaWQgZXZ0X2xlX2FkdmVy
dGlzaW5nX3JlcG9ydF9kdW1wKGludCBsZXZlbCwgc3RydWN0IGZyYW1lICpmcm0pCj4gwqB7Cj4g
LSDCoCDCoCDCoCB1aW50OF90IG51bSA9IGdldF91OChmcm0pOwo+IC0gwqAgwqAgwqAgY2hhciBh
ZGRyWzE4XTsKPiAtIMKgIMKgIMKgIGludCBpOwo+ICsgwqAgwqAgwqAgdWludDhfdCBudW1fcmVw
b3J0cyA9IGdldF91OChmcm0pOwo+ICsgwqAgwqAgwqAgY29uc3QgdWludDhfdCBSU1NJX1NJWkUg
PSAxOwo+Cj4gLSDCoCDCoCDCoCBmb3IgKGkgPSAwOyBpIDwgbnVtOyBpKyspIHsKPiArIMKgIMKg
IMKgIHdoaWxlIChudW1fcmVwb3J0cy0tKSB7Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCBjaGFy
IGFkZHJbMThdOwo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgbGVfYWR2ZXJ0aXNpbmdfaW5mbyAq
aW5mbyA9IGZybS0+cHRyOwo+IC0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgdm9pZCAqcHRyID0gZnJt
LT5wdHI7Cj4gLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCB1aW50MzJfdCBsZW4gPSBmcm0tPmxlbjsK
Pgo+IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgcF9iYTJzdHIoJmluZm8tPmJkYWRkciwgYWRkcik7
Cj4KPiBAQCAtMzUyMiwxMyArMzUzNiwxNSBAQCBzdGF0aWMgaW5saW5lIHZvaWQgZXZ0X2xlX2Fk
dmVydGlzaW5nX3JlcG9ydF9kdW1wKGludCBsZXZlbCwgc3RydWN0IGZyYW1lICpmcm0pCj4gwqAg
wqAgwqAgwqAgwqAgwqAgwqAgwqBwcmludGYoImJkYWRkciAlcyAoJXMpXG4iLCBhZGRyLAo+IMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
YmRhZGRydHlwZTJzdHIoaW5mby0+YmRhZGRyX3R5cGUpKTsKPgo+IC0gwqAgwqAgwqAgwqAgwqAg
wqAgwqAgZnJtLT5wdHIgKz0gTEVfQURWRVJUSVNJTkdfSU5GT19TSVpFOwo+IC0gwqAgwqAgwqAg
wqAgwqAgwqAgwqAgZnJtLT5sZW4gLT0gTEVfQURWRVJUSVNJTkdfSU5GT19TSVpFOwo+ICsgwqAg
wqAgwqAgwqAgwqAgwqAgwqAgaWYgKGluZm8tPmxlbmd0aCA+IDApIHsKPiArIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIGV4dF9pbnF1aXJ5X2RhdGFfZHVtcChsZXZlbCwgZnJtLCAm
aW5mby0+bGVuZ3RoICsgMSk7Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCB9Cj4KPiAtIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIGV4dF9pbnF1aXJ5X3Jlc3BvbnNlX2R1bXAobGV2ZWwsIGZybSk7Cj4g
KyDCoCDCoCDCoCDCoCDCoCDCoCDCoCBmcm0tPnB0ciArPSBMRV9BRFZFUlRJU0lOR19JTkZPX1NJ
WkUgKyBpbmZvLT5sZW5ndGggKyBSU1NJX1NJWkU7Cj4gKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCBm
cm0tPmxlbiAtPSBMRV9BRFZFUlRJU0lOR19JTkZPX1NJWkUgKyBpbmZvLT5sZW5ndGggKyBSU1NJ
X1NJWkU7Cj4KPiAtIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGZybS0+cHRyID0gcHRyICsgMTsKPiAt
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIGZybS0+bGVuID0gbGVuIC0gMTsKPiArIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIHBfaW5kZW50KGxldmVsLCBmcm0pOwo+ICsgwqAgwqAgwqAgwqAgwqAgwqAgwqAg
cHJpbnRmKCJSU1NJOiAlZFxuIiwgKChpbnQ4X3QgKikgZnJtLT5wdHIpW2ZybS0+bGVuIC0gMV0p
Owo+IMKgIMKgIMKgIMKgfQo+IMKgfQo+Cj4gLS0KPiAxLjcuMQo+Cj4gLS0KPiBUbyB1bnN1YnNj
cmliZSBmcm9tIHRoaXMgbGlzdDogc2VuZCB0aGUgbGluZSAidW5zdWJzY3JpYmUgbGludXgtYmx1
ZXRvb3RoIiBpbgo+IHRoZSBib2R5IG9mIGEgbWVzc2FnZSB0byBtYWpvcmRvbW9Admdlci5rZXJu
ZWwub3JnCj4gTW9yZSBtYWpvcmRvbW8gaW5mbyBhdCDCoGh0dHA6Ly92Z2VyLmtlcm5lbC5vcmcv
bWFqb3Jkb21vLWluZm8uaHRtbAo+CgpoY2lkdW1wIGlzIGNyYXNoaW5nLiBJIGdvbm5hIHNlbmQg
YSBwcml2YXRlIGUtbWFpbCB3aXRoIHRoZSBoY2lkdW1wCmxvZyB0byByZXByb2R1Y2UgdGhlIHBy
b2JsZW0uCgpDbGF1ZGlvLgo=