Commit ad262aa5 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Implement mandatory bits in all TLVs.

parent afdc3e1b
...@@ -165,7 +165,10 @@ parse_update_subtlv(struct interface *ifp, int metric, ...@@ -165,7 +165,10 @@ parse_update_subtlv(struct interface *ifp, int metric,
memcpy(channels, a + i + 2, MIN(len, *channels_len_return)); memcpy(channels, a + i + 2, MIN(len, *channels_len_return));
channels_len = MIN(len, *channels_len_return); channels_len = MIN(len, *channels_len_return);
} else { } else {
debugf("Received unknown update sub-TLV %d.\n", type); debugf("Received unknown%s Update sub-TLV %d.\n",
(type & 0x80) != 0 ? " mandatory" : "", type);
if((type & 0x80) != 0)
return -1;
} }
i += len + 2; i += len + 2;
...@@ -210,7 +213,10 @@ parse_hello_subtlv(const unsigned char *a, int alen, ...@@ -210,7 +213,10 @@ parse_hello_subtlv(const unsigned char *a, int alen,
/* But don't break. */ /* But don't break. */
} }
} else { } else {
debugf("Received unknown Hello sub-TLV type %d.\n", type); debugf("Received unknown%s Hello sub-TLV %d.\n",
(type & 0x80) != 0 ? " mandatory" : "", type);
if((type & 0x80) != 0)
return -1;
} }
i += len + 2; i += len + 2;
...@@ -262,7 +268,10 @@ parse_ihu_subtlv(const unsigned char *a, int alen, ...@@ -262,7 +268,10 @@ parse_ihu_subtlv(const unsigned char *a, int alen,
/* But don't break. */ /* But don't break. */
} }
} else { } else {
debugf("Received unknown IHU sub-TLV type %d.\n", type); debugf("Received unknown%s IHU sub-TLV %d.\n",
(type & 0x80) != 0 ? " mandatory" : "", type);
if((type & 0x80) != 0)
return -1;
} }
i += len + 2; i += len + 2;
...@@ -277,6 +286,38 @@ parse_ihu_subtlv(const unsigned char *a, int alen, ...@@ -277,6 +286,38 @@ parse_ihu_subtlv(const unsigned char *a, int alen,
return 1; return 1;
} }
static int
parse_other_subtlv(const unsigned char *a, int alen)
{
int type, len, i = 0;
while(i < alen) {
type = a[0];
if(type == SUBTLV_PAD1) {
i++;
continue;
}
if(i + 1 > alen) {
fprintf(stderr, "Received truncated sub-TLV on IHU.\n");
return -1;
}
len = a[i + 1];
if(i + len > alen) {
fprintf(stderr, "Received truncated sub-TLV on IHU.\n");
return -1;
}
if((type & 0x80) != 0) {
debugf("Received unknown mandatory sub-TLV %d.\n", type);
return -1;
}
i += len + 2;
}
return 1;
}
static int static int
network_address(int ae, const unsigned char *a, unsigned int len, network_address(int ae, const unsigned char *a, unsigned int len,
unsigned char *a_r) unsigned char *a_r)
...@@ -364,19 +405,27 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -364,19 +405,27 @@ parse_packet(const unsigned char *from, struct interface *ifp,
len, format_address(from), ifp->name); len, format_address(from), ifp->name);
} else if(type == MESSAGE_ACK_REQ) { } else if(type == MESSAGE_ACK_REQ) {
unsigned short nonce, interval; unsigned short nonce, interval;
int rc;
if(len < 6) goto fail; if(len < 6) goto fail;
DO_NTOHS(nonce, message + 4); DO_NTOHS(nonce, message + 4);
DO_NTOHS(interval, message + 6); DO_NTOHS(interval, message + 6);
debugf("Received ack-req (%04X %d) from %s on %s.\n", debugf("Received ack-req (%04X %d) from %s on %s.\n",
nonce, interval, format_address(from), ifp->name); nonce, interval, format_address(from), ifp->name);
rc = parse_other_subtlv(message + 8, len - 6);
if(rc < 0)
goto done;
send_ack(neigh, nonce, interval); send_ack(neigh, nonce, interval);
} else if(type == MESSAGE_ACK) { } else if(type == MESSAGE_ACK) {
int rc;
debugf("Received ack from %s on %s.\n", debugf("Received ack from %s on %s.\n",
format_address(from), ifp->name); format_address(from), ifp->name);
rc = parse_other_subtlv(message + 4, len - 2);
if(rc < 0)
goto done;
/* Nothing right now */ /* Nothing right now */
} else if(type == MESSAGE_HELLO) { } else if(type == MESSAGE_HELLO) {
unsigned short seqno, interval; unsigned short seqno, interval;
int changed, have_timestamp; int changed, have_timestamp, rc;
unsigned int timestamp; unsigned int timestamp;
if(len < 6) goto fail; if(len < 6) goto fail;
DO_NTOHS(seqno, message + 4); DO_NTOHS(seqno, message + 4);
...@@ -390,16 +439,15 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -390,16 +439,15 @@ parse_packet(const unsigned char *from, struct interface *ifp,
/* Multiply by 3/2 to allow hellos to expire. */ /* Multiply by 3/2 to allow hellos to expire. */
schedule_neighbours_check(interval * 15, 0); schedule_neighbours_check(interval * 15, 0);
/* Sub-TLV handling. */ /* Sub-TLV handling. */
if(len > 8) {
int rc;
rc = parse_hello_subtlv(message + 8, len - 6, rc = parse_hello_subtlv(message + 8, len - 6,
&timestamp, &have_timestamp); &timestamp, &have_timestamp);
if(rc >= 0 && have_timestamp) { if(rc < 0)
goto done;
if(have_timestamp) {
neigh->hello_send_us = timestamp; neigh->hello_send_us = timestamp;
neigh->hello_rtt_receive_time = now; neigh->hello_rtt_receive_time = now;
have_hello_rtt = 1; have_hello_rtt = 1;
} }
}
} else if(type == MESSAGE_IHU) { } else if(type == MESSAGE_IHU) {
unsigned short txcost, interval; unsigned short txcost, interval;
unsigned char address[16]; unsigned char address[16];
...@@ -414,7 +462,13 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -414,7 +462,13 @@ parse_packet(const unsigned char *from, struct interface *ifp,
format_address(from), ifp->name, format_address(from), ifp->name,
format_address(address)); format_address(address));
if(message[2] == 0 || interface_ll_address(ifp, address)) { if(message[2] == 0 || interface_ll_address(ifp, address)) {
int changed = txcost != neigh->txcost; int changed;
rc = parse_ihu_subtlv(message + 8 + rc, len - 6 - rc,
&hello_send_us, &hello_rtt_receive_time,
NULL);
if(rc < 0)
goto done;
changed = txcost != neigh->txcost;
neigh->txcost = txcost; neigh->txcost = txcost;
neigh->ihu_time = now; neigh->ihu_time = now;
neigh->ihu_interval = interval; neigh->ihu_interval = interval;
...@@ -422,17 +476,16 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -422,17 +476,16 @@ parse_packet(const unsigned char *from, struct interface *ifp,
if(interval > 0) if(interval > 0)
/* Multiply by 3/2 to allow neighbours to expire. */ /* Multiply by 3/2 to allow neighbours to expire. */
schedule_neighbours_check(interval * 45, 0); schedule_neighbours_check(interval * 45, 0);
/* RTT sub-TLV. */
if(len > 10 + rc)
parse_ihu_subtlv(message + 8 + rc, len - 6 - rc,
&hello_send_us, &hello_rtt_receive_time,
NULL);
} }
} else if(type == MESSAGE_ROUTER_ID) { } else if(type == MESSAGE_ROUTER_ID) {
int rc;
if(len < 10) { if(len < 10) {
have_router_id = 0; have_router_id = 0;
goto fail; goto fail;
} }
rc = parse_other_subtlv(message + 12, len - 10);
if(rc < 0)
goto done;
memcpy(router_id, message + 4, 8); memcpy(router_id, message + 4, 8);
have_router_id = 1; have_router_id = 1;
debugf("Received router-id %s from %s on %s.\n", debugf("Received router-id %s from %s on %s.\n",
...@@ -455,6 +508,9 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -455,6 +508,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
debugf("Received nh %s (%d) from %s on %s.\n", debugf("Received nh %s (%d) from %s on %s.\n",
format_address(nh), message[2], format_address(nh), message[2],
format_address(from), ifp->name); format_address(from), ifp->name);
rc = parse_other_subtlv(message + 4 + rc, len - 2 - rc);
if(rc < 0)
goto done;
if(message[2] == 1) { if(message[2] == 1) {
memcpy(v4_nh, nh, 16); memcpy(v4_nh, nh, 16);
have_v4_nh = 1; have_v4_nh = 1;
...@@ -535,6 +591,9 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -535,6 +591,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
"Received wildcard update with finite metric.\n"); "Received wildcard update with finite metric.\n");
goto done; goto done;
} }
rc = parse_other_subtlv(message + 12, len - 8);
if(rc < 0)
goto done;
retract_neighbour_routes(neigh); retract_neighbour_routes(neigh);
goto done; goto done;
} else if(message[2] == 1) { } else if(message[2] == 1) {
...@@ -568,7 +627,13 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -568,7 +627,13 @@ parse_packet(const unsigned char *from, struct interface *ifp,
debugf("Received request for %s from %s on %s.\n", debugf("Received request for %s from %s on %s.\n",
message[2] == 0 ? "any" : format_prefix(prefix, plen), message[2] == 0 ? "any" : format_prefix(prefix, plen),
format_address(from), ifp->name); format_address(from), ifp->name);
rc = parse_other_subtlv(message + 4 + rc, len - 2 - rc);
if(rc < 0)
goto done;
if(message[2] == 0) { if(message[2] == 0) {
rc = parse_other_subtlv(message + 4, len - 2);
if(rc < 0)
goto done;
/* If a neighbour is requesting a full route dump from us, /* If a neighbour is requesting a full route dump from us,
we might as well send it an IHU. */ we might as well send it an IHU. */
send_ihu(neigh, NULL); send_ihu(neigh, NULL);
...@@ -598,6 +663,9 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -598,6 +663,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
rc = network_prefix(message[2], message[3], 0, rc = network_prefix(message[2], message[3], 0,
message + 16, NULL, len - 14, prefix); message + 16, NULL, len - 14, prefix);
if(rc < 0) goto fail; if(rc < 0) goto fail;
rc = parse_other_subtlv(message + 8 + rc, len - 6 - rc);
if(rc < 0)
goto done;
plen = message[3] + (message[2] == 1 ? 96 : 0); plen = message[3] + (message[2] == 1 ? 96 : 0);
if(message[2] == 1) { if(message[2] == 1) {
v4tov6(src_prefix, zeroes); v4tov6(src_prefix, zeroes);
...@@ -680,8 +748,10 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -680,8 +748,10 @@ parse_packet(const unsigned char *from, struct interface *ifp,
goto done; goto done;
} }
parse_update_subtlv(ifp, metric, message + 2 + parsed_len, rc = parse_update_subtlv(ifp, metric, message + 2 + parsed_len,
len - parsed_len, channels, &channels_len); len - parsed_len, channels, &channels_len);
if(rc < 0)
goto done;
update_route(router_id, prefix, plen, src_prefix, src_plen, update_route(router_id, prefix, plen, src_prefix, src_plen,
seqno, metric, interval, neigh, nh, seqno, metric, interval, neigh, nh,
channels, channels_len); channels, channels_len);
...@@ -704,6 +774,9 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -704,6 +774,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
if(ae == 1) if(ae == 1)
src_plen += 96; src_plen += 96;
parsed += rc; parsed += rc;
rc = parse_other_subtlv(message + parsed, len - parsed - 2);
if(rc < 0)
goto done;
if(ae == 0) { if(ae == 0) {
debugf("Received request for any source-specific " debugf("Received request for any source-specific "
"from %s on %s.\n", "from %s on %s.\n",
...@@ -741,6 +814,10 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -741,6 +814,10 @@ parse_packet(const unsigned char *from, struct interface *ifp,
rc = network_prefix(ae, src_plen, 0, message + parsed, rc = network_prefix(ae, src_plen, 0, message + parsed,
NULL, len + 2 - parsed, src_prefix); NULL, len + 2 - parsed, src_prefix);
if(rc < 0) goto fail; if(rc < 0) goto fail;
parsed += rc;
rc = parse_other_subtlv(message + parsed, len - parsed - 2);
if(rc < 0)
goto done;
if(ae == 1) if(ae == 1)
src_plen += 96; src_plen += 96;
debugf("Received request (%d) for (%s, %s)" debugf("Received request (%d) for (%s, %s)"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment