Skip to content

Commit 7ef4775

Browse files
Fix for multicast ping forwarding before adding MPL header(ARMmbed#1883)
1 parent 654dd44 commit 7ef4775

File tree

2 files changed

+49
-31
lines changed

2 files changed

+49
-31
lines changed

source/Common_Protocols/ipv6.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,24 @@ buffer_t *ipv6_forwarding_down(buffer_t *buf)
583583
return icmpv6_error(buf, NULL, ICMPV6_TYPE_ERROR_DESTINATION_UNREACH, ICMPV6_CODE_DST_UNREACH_NO_ROUTE, 0);
584584
}
585585

586+
/* Consider multicast forwarding /before/ calling routing code to modify
587+
* extension headers - if that actually decides to tunnel it will
588+
* overwrite the buffer's src_sa and dst_sa, when we want to consider
589+
* forwarding the inner packet. This ordering works out for our only
590+
* header-modifying multicast case of MPL:
591+
* 1) We never want to forward packets with MPL headers, which means the
592+
* outer packet in a tunnel gets ignored anyway.
593+
* 2) This also means we don't have to worry that we're forwarding packets
594+
* with the extension header not filled in yet.
595+
* If we ever do have a multicast system where we are working with
596+
* extension headers and forwarding those across interfaces, ipv6_get_exthdrs
597+
* system will need a rework - probably split the "try MODIFY" call from the
598+
* subsequent "give me tunnel parameters" part.
599+
*/
600+
if (!buf->ip_routed_up && addr_is_ipv6_multicast(buf->dst_sa.address)) {
601+
buf = ipv6_consider_forwarding_multicast_packet(buf, buf->interface, true);
602+
}
603+
586604
/* Allow routing code to update extension headers */
587605
int16_t exthdr_result;
588606
buf = ipv6_get_exthdrs(buf, IPV6_EXTHDR_MODIFY, &exthdr_result);
@@ -593,10 +611,6 @@ buffer_t *ipv6_forwarding_down(buffer_t *buf)
593611
goto drop;
594612
}
595613

596-
if (!buf->ip_routed_up && addr_is_ipv6_multicast(buf->dst_sa.address)) {
597-
buf = ipv6_consider_forwarding_multicast_packet(buf, buf->interface, true);
598-
}
599-
600614
/* Routing code may say it needs to tunnel to add headers - loop back to IP layer if requested */
601615
if (exthdr_result == IPV6_EXTHDR_MODIFY_TUNNEL) {
602616
/* Avoid an infinite loop in the event of routing code failure - never

source/MPL/mpl.c

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,17 +1011,41 @@ void mpl_clear_realm_scope_seeds(protocol_interface_info_entry_t *cur)
10111011
static buffer_t *mpl_exthdr_provider(buffer_t *buf, ipv6_exthdr_stage_t stage, int16_t *result)
10121012
{
10131013
mpl_domain_t *domain = mpl_domain_lookup_with_realm_check(buf->interface, buf->dst_sa.address);
1014-
if (!domain) {
1015-
// We need to tunnel
10161014

1017-
if (stage != IPV6_EXTHDR_MODIFY) {
1018-
*result = 0;
1015+
/* Deal with simpler modify-already-created-header case first. Note that no error returns. */
1016+
if (stage == IPV6_EXTHDR_MODIFY) {
1017+
if (!domain) {
1018+
*result = IPV6_EXTHDR_MODIFY_TUNNEL;
1019+
memcpy(buf->dst_sa.address, ADDR_ALL_MPL_FORWARDERS, 16);
1020+
buf->src_sa.addr_type = ADDR_NONE; // force auto-selection
10191021
return buf;
10201022
}
10211023

1022-
*result = IPV6_EXTHDR_MODIFY_TUNNEL;
1023-
memcpy(buf->dst_sa.address, ADDR_ALL_MPL_FORWARDERS, 16);
1024-
buf->src_sa.addr_type = ADDR_NONE; // force auto-selection
1024+
if (buf->options.ip_extflags & IPEXT_HBH_MPL_UNFILLED) {
1025+
/* We assume we created this, therefore our option is in place
1026+
* in the expected place. Sequence is set now, AFTER
1027+
* fragmentation.
1028+
*/
1029+
uint8_t *iphdr = buffer_data_pointer(buf);
1030+
uint8_t *ext = iphdr + IPV6_HDRLEN;
1031+
if (iphdr[IPV6_HDROFF_NH] != IPV6_NH_HOP_BY_HOP || ext[2] != IPV6_OPTION_MPL) {
1032+
tr_err("modify");
1033+
return buffer_free(buf);
1034+
}
1035+
/* We don't bother setting the M flag on these initial packets. Setting to 0 is always acceptable. */
1036+
ext[5] = domain->sequence++;
1037+
buf->options.ip_extflags &=~ IPEXT_HBH_MPL_UNFILLED;
1038+
buf->mpl_option_data_offset = IPV6_HDRLEN + 4;
1039+
mpl_forwarder_process_message(buf, domain, true);
1040+
}
1041+
*result = 0;
1042+
return buf;
1043+
}
1044+
1045+
/* Rest of code deals with header insertion */
1046+
if (!domain) {
1047+
// We will need to tunnel - do nothing on the inner packet
1048+
*result = 0;
10251049
return buf;
10261050
}
10271051

@@ -1112,26 +1136,6 @@ static buffer_t *mpl_exthdr_provider(buffer_t *buf, ipv6_exthdr_stage_t stage, i
11121136
buf->options.ip_extflags |= IPEXT_HBH_MPL | IPEXT_HBH_MPL_UNFILLED;
11131137
return buf;
11141138
}
1115-
case IPV6_EXTHDR_MODIFY:
1116-
if (buf->options.ip_extflags & IPEXT_HBH_MPL_UNFILLED) {
1117-
/* We assume we created this, therefore our option is in place
1118-
* in the expected place. Sequence is set now, AFTER
1119-
* fragmentation.
1120-
*/
1121-
uint8_t *iphdr = buffer_data_pointer(buf);
1122-
uint8_t *ext = iphdr + IPV6_HDRLEN;
1123-
if (iphdr[IPV6_HDROFF_NH] != IPV6_NH_HOP_BY_HOP || ext[2] != IPV6_OPTION_MPL) {
1124-
tr_err("modify");
1125-
return buffer_free(buf);
1126-
}
1127-
/* We don't bother setting the M flag on these initial packets. Setting to 0 is always acceptable. */
1128-
ext[5] = domain->sequence++;
1129-
buf->options.ip_extflags &=~ IPEXT_HBH_MPL_UNFILLED;
1130-
buf->mpl_option_data_offset = IPV6_HDRLEN + 4;
1131-
mpl_forwarder_process_message(buf, domain, true);
1132-
}
1133-
*result = 0;
1134-
return buf;
11351139
default:
11361140
return buffer_free(buf);
11371141
}

0 commit comments

Comments
 (0)