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,
memcpy(channels, a + i + 2, MIN(len, *channels_len_return));
channels_len = MIN(len, *channels_len_return);
} 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;
......@@ -210,7 +213,10 @@ parse_hello_subtlv(const unsigned char *a, int alen,
/* But don't break. */
}
} 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;
......@@ -262,7 +268,10 @@ parse_ihu_subtlv(const unsigned char *a, int alen,
/* But don't break. */
}
} 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;
......@@ -277,6 +286,38 @@ parse_ihu_subtlv(const unsigned char *a, int alen,
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
network_address(int ae, const unsigned char *a, unsigned int len,
unsigned char *a_r)
......@@ -364,19 +405,27 @@ parse_packet(const unsigned char *from, struct interface *ifp,
len, format_address(from), ifp->name);
} else if(type == MESSAGE_ACK_REQ) {
unsigned short nonce, interval;
int rc;
if(len < 6) goto fail;
DO_NTOHS(nonce, message + 4);
DO_NTOHS(interval, message + 6);
debugf("Received ack-req (%04X %d) from %s on %s.\n",
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);
} else if(type == MESSAGE_ACK) {
int rc;
debugf("Received ack from %s on %s.\n",
format_address(from), ifp->name);
rc = parse_other_subtlv(message + 4, len - 2);
if(rc < 0)
goto done;
/* Nothing right now */
} else if(type == MESSAGE_HELLO) {
unsigned short seqno, interval;
int changed, have_timestamp;
int changed, have_timestamp, rc;
unsigned int timestamp;
if(len < 6) goto fail;
DO_NTOHS(seqno, message + 4);
......@@ -390,16 +439,15 @@ parse_packet(const unsigned char *from, struct interface *ifp,
/* Multiply by 3/2 to allow hellos to expire. */
schedule_neighbours_check(interval * 15, 0);
/* Sub-TLV handling. */
if(len > 8) {
int rc;
rc = parse_hello_subtlv(message + 8, len - 6,
&timestamp, &have_timestamp);
if(rc >= 0 && have_timestamp) {
if(rc < 0)
goto done;
if(have_timestamp) {
neigh->hello_send_us = timestamp;
neigh->hello_rtt_receive_time = now;
have_hello_rtt = 1;
}
}
} else if(type == MESSAGE_IHU) {
unsigned short txcost, interval;
unsigned char address[16];
......@@ -414,7 +462,13 @@ parse_packet(const unsigned char *from, struct interface *ifp,
format_address(from), ifp->name,
format_address(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->ihu_time = now;
neigh->ihu_interval = interval;
......@@ -422,17 +476,16 @@ parse_packet(const unsigned char *from, struct interface *ifp,
if(interval > 0)
/* Multiply by 3/2 to allow neighbours to expire. */
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) {
int rc;
if(len < 10) {
have_router_id = 0;
goto fail;
}
rc = parse_other_subtlv(message + 12, len - 10);
if(rc < 0)
goto done;
memcpy(router_id, message + 4, 8);
have_router_id = 1;
debugf("Received router-id %s from %s on %s.\n",
......@@ -455,6 +508,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
debugf("Received nh %s (%d) from %s on %s.\n",
format_address(nh), message[2],
format_address(from), ifp->name);
rc = parse_other_subtlv(message + 4 + rc, len - 2 - rc);
if(rc < 0)
goto done;
if(message[2] == 1) {
memcpy(v4_nh, nh, 16);
have_v4_nh = 1;
......@@ -535,6 +591,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
"Received wildcard update with finite metric.\n");
goto done;
}
rc = parse_other_subtlv(message + 12, len - 8);
if(rc < 0)
goto done;
retract_neighbour_routes(neigh);
goto done;
} else if(message[2] == 1) {
......@@ -568,7 +627,13 @@ parse_packet(const unsigned char *from, struct interface *ifp,
debugf("Received request for %s from %s on %s.\n",
message[2] == 0 ? "any" : format_prefix(prefix, plen),
format_address(from), ifp->name);
rc = parse_other_subtlv(message + 4 + rc, len - 2 - rc);
if(rc < 0)
goto done;
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,
we might as well send it an IHU. */
send_ihu(neigh, NULL);
......@@ -598,6 +663,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
rc = network_prefix(message[2], message[3], 0,
message + 16, NULL, len - 14, prefix);
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);
if(message[2] == 1) {
v4tov6(src_prefix, zeroes);
......@@ -680,8 +748,10 @@ parse_packet(const unsigned char *from, struct interface *ifp,
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);
if(rc < 0)
goto done;
update_route(router_id, prefix, plen, src_prefix, src_plen,
seqno, metric, interval, neigh, nh,
channels, channels_len);
......@@ -704,6 +774,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
if(ae == 1)
src_plen += 96;
parsed += rc;
rc = parse_other_subtlv(message + parsed, len - parsed - 2);
if(rc < 0)
goto done;
if(ae == 0) {
debugf("Received request for any source-specific "
"from %s on %s.\n",
......@@ -741,6 +814,10 @@ parse_packet(const unsigned char *from, struct interface *ifp,
rc = network_prefix(ae, src_plen, 0, message + parsed,
NULL, len + 2 - parsed, src_prefix);
if(rc < 0) goto fail;
parsed += rc;
rc = parse_other_subtlv(message + parsed, len - parsed - 2);
if(rc < 0)
goto done;
if(ae == 1)
src_plen += 96;
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