Sigh. Brown paper bag re-submit, to cover an "off-by-one." When using the icmp.dest_unreach and icmp.TimeExceeded classes, we should ensure that it is in compliance with RFC 4884. As such, the data_len parameter passed to the constructor of each should be interpreted in 32 bit units. Furthermore - any data that is passed in must be zero padded to a 32 bit boundary.
The only sample application known to use either of these types is rest_router. This patch corrects its use of these classes. Signed-off-by: Victor J. Orlikowski <v...@duke.edu> diff --git a/ryu/app/rest_router.py b/ryu/app/rest_router.py index 30812a7..a0132c1 100644 --- a/ryu/app/rest_router.py +++ b/ryu/app/rest_router.py @@ -1523,18 +1523,37 @@ class OfCtl(object): eth = protocol_list[ETHERNET] e = ethernet.ethernet(eth.src, eth.dst, ether_proto) + ip = protocol_list[IPV4] + if icmp_data is None and msg_data is not None: - ip_datagram = msg_data[offset:] + # RFC 4884 says that we should send "at least 128 octets" + # if we are using the ICMP Extension Structure. + # We're not using the extension structure, but let's send + # up to 128 bytes of the original msg_data. + # + # RFC 4884 also states that the length field is interpreted in + # 32 bit units, so the length calculated in bytes needs to first + # be divided by 4, then increased by 1 if the modulus is non-zero. + # + # Finally, RFC 4884 says, if we're specifying the length, we MUST + # zero pad to the next 32 bit boundary. + end_of_data = offset + len(ip) + 128 + ip_datagram = bytearray() + ip_datagram += msg_data[offset:end_of_data] + data_len = int(len(ip_datagram) / 4) + length_modulus = int(len(ip_datagram) % 4) + if length_modulus: + data_len += 1 + ip_datagram += bytearray([0]*(4 - length_modulus)) if icmp_type == icmp.ICMP_DEST_UNREACH: - icmp_data = icmp.dest_unreach(data_len=len(ip_datagram), + icmp_data = icmp.dest_unreach(data_len=data_len, data=ip_datagram) elif icmp_type == icmp.ICMP_TIME_EXCEEDED: - icmp_data = icmp.TimeExceeded(data_len=len(ip_datagram), + icmp_data = icmp.TimeExceeded(data_len=data_len, data=ip_datagram) ic = icmp.icmp(icmp_type, icmp_code, csum, data=icmp_data) - ip = protocol_list[IPV4] if src_ip is None: src_ip = ip.dst ip_total_length = ip.header_length * 4 + ic._MIN_LEN Best, Victor -- Victor J. Orlikowski <> vjo@[cs.]duke.edu ------------------------------------------------------------------------------ Site24x7 APM Insight: Get Deep Visibility into Application Performance APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month Monitor end-to-end web transactions and take corrective actions now Troubleshoot faster and improve end-user experience. Signup Now! http://pubads.g.doubleclick.net/gampad/clk?id=267308311&iu=/4140 _______________________________________________ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel