summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ryu/app/rest_router.py27
1 files changed, 23 insertions, 4 deletions
diff --git a/ryu/app/rest_router.py b/ryu/app/rest_router.py
index 30812a74..100d565e 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