Esempio n. 1
0
    def test_default_args(self):
        du = icmp.dest_unreach()
        buf = du.serialize()
        res = struct.unpack(icmp.dest_unreach._PACK_STR, six.binary_type(buf))

        eq_(res[0], 0)
        eq_(res[1], 0)
Esempio n. 2
0
    def test_default_args(self):
        du = icmp.dest_unreach()
        buf = du.serialize()
        res = struct.unpack(icmp.dest_unreach._PACK_STR, six.binary_type(buf))

        eq_(res[0], 0)
        eq_(res[1], 0)
Esempio n. 3
0
 def setUp(self):
     self.mtu = 10
     self.data = b"abc"
     self.data_len = len(self.data)
     self.dest_unreach = icmp.dest_unreach(data_len=self.data_len, mtu=self.mtu, data=self.data)
     self.buf = struct.pack("!xBH", self.data_len, self.mtu)
     self.buf += self.data
Esempio n. 4
0
 def setUp(self):
     self.mtu = 10
     self.data = 'abc'
     self.data_len = len(self.data)
     self.dest_unreach = icmp.dest_unreach(
         data_len=self.data_len, mtu=self.mtu, data=self.data)
     self.buf = struct.pack('!xBH', self.data_len, self.mtu)
     self.buf += self.data
 def setUp(self):
     self.mtu = 10
     self.data = 'abc'
     self.data_len = len(self.data)
     self.dest_unreach = icmp.dest_unreach(
         data_len=self.data_len, mtu=self.mtu, data=self.data)
     self.buf = struct.pack('!xBH', self.data_len, self.mtu)
     self.buf += self.data
def _create_icmp_data(icmp_type, data_len, data):
    if icmp_type == icmp.ICMP_DEST_UNREACH:
        icmp_data = icmp.dest_unreach(data_len=data_len, data=data)
    elif icmp_type == icmp.ICMP_TIME_EXCEEDED:
        icmp_data = icmp.TimeExceeded(data_len=data_len, data=data)
    else:
        icmp_data = None

    return icmp_data
Esempio n. 7
0
    def send_icmp(self, datapath, dst_ip, src_mac, icmp_type, icmp_code,
                  ip_ihl, icmp_data):
        self.logger.debug("Sending ICMP")
        proto = datapath.ofproto
        parser = datapath.ofproto_parser
        dpid = dpid_to_str(datapath.id)

        pkt = packet.Packet()

        out_port, hop_ip = self.get_route(dpid, dst_ip)
        out_mac = self.mac_from_port(dpid, out_port)
        dst_mac = src_mac
        self.logger.debug(
            "Router {} sending ICMP to {} with target MAC {} (from port {} hopping to {})"
            .format(dpid, dst_ip, dst_mac, out_port, hop_ip))

        for interface in self.interface_table.get(dpid):
            if interface.get("port") == out_port:
                src_ip = interface.get("ip")

        offset = 14 + 8 + (ip_ihl * 4)
        payload = icmp_data[14:offset]

        if icmp_type == 3:
            self.logger.debug("TYPE 3 ICMP")
            payload = icmp.dest_unreach(data=payload)

        if icmp_type == 11:
            self.logger.debug("TYPE 11 ICMP")
            payload = icmp.TimeExceeded(data=payload)

        ## pkt.add_protocol(...)
        ## https://ryu.readthedocs.io/en/latest/library_packet_ref/packet_icmp.html

        pkt.add_protocol(
            ethernet.ethernet(dst=dst_mac,
                              src=out_mac,
                              ethertype=ethernet.ether.ETH_TYPE_IP))
        pkt.add_protocol(
            ipv4.ipv4(dst=dst_ip,
                      src=src_ip,
                      ttl=64,
                      proto=ipv4.inet.IPPROTO_ICMP))
        pkt.add_protocol(
            icmp.icmp(type_=icmp_type, code=icmp_code, data=payload))

        pkt.serialize()
        data = pkt.data
        actions = [datapath.ofproto_parser.OFPActionOutput(port=out_port)]
        out = datapath.ofproto_parser.OFPPacketOut(
            datapath=datapath,
            buffer_id=proto.OFP_NO_BUFFER,
            in_port=proto.OFPP_ANY,
            actions=actions,
            data=data)
        datapath.send_msg(out)
Esempio n. 8
0
    def send_icmp(self,
                  in_port,
                  icmp_type,
                  icmp_code,
                  datapath,
                  ipv4_header=None,
                  ethernet_header=None,
                  icmp_data=None,
                  msg_data=None,
                  src_ip=None):
        # Generate ICMP reply packet
        csum = 0
        offset = ethernet.ethernet._MIN_LEN

        ether_proto = ether.ETH_TYPE_IP

        eth = ethernet_header
        e = ethernet.ethernet(eth.src, eth.dst, ether_proto)

        if icmp_data is None and msg_data is not None:
            ip_datagram = msg_data[offset:]
            if icmp_type == icmp.ICMP_DEST_UNREACH:
                icmp_data = icmp.dest_unreach(data_len=len(ip_datagram),
                                              data=ip_datagram)
            elif icmp_type == icmp.ICMP_TIME_EXCEEDED:
                icmp_data = icmp.TimeExceeded(data_len=len(ip_datagram),
                                              data=ip_datagram)

        ic = icmp.icmp(icmp_type, icmp_code, csum, data=icmp_data)

        ip = ipv4_header
        if src_ip is None:
            src_ip = ip.dst
        ip_total_length = ip.header_length * 4 + ic._MIN_LEN
        if ic.data is not None:
            ip_total_length += ic.data._MIN_LEN
            if ic.data.data is not None:
                ip_total_length += +len(ic.data.data)
        i = ipv4.ipv4(ip.version, ip.header_length, ip.tos, ip_total_length,
                      ip.identification, ip.flags, ip.offset, DEFAULT_TTL,
                      inet.IPPROTO_ICMP, csum, src_ip, ip.src)

        pkt = packet.Packet()
        pkt.add_protocol(e)

        pkt.add_protocol(i)
        pkt.add_protocol(ic)
        pkt.serialize()

        # Send packet out
        self.send_packet_out(datapath,
                             in_port,
                             datapath.ofproto.OFPP_IN_PORT,
                             pkt.data,
                             data_str=str(pkt))
Esempio n. 9
0
    def setUp_with_dest_unreach(self):
        self.unreach_mtu = 10
        self.unreach_data = b"abc"
        self.unreach_data_len = len(self.unreach_data)
        self.data = icmp.dest_unreach(data_len=self.unreach_data_len, mtu=self.unreach_mtu, data=self.unreach_data)

        self.type_ = icmp.ICMP_DEST_UNREACH
        self.code = icmp.ICMP_HOST_UNREACH_CODE
        self.ic = icmp.icmp(self.type_, self.code, self.csum, self.data)

        self.buf = bytearray(struct.pack(icmp.icmp._PACK_STR, self.type_, self.code, self.csum))
        self.buf += self.data.serialize()
        self.csum_calc = packet_utils.checksum(self.buf)
        struct.pack_into("!H", self.buf, 2, self.csum_calc)
Esempio n. 10
0
class Test_icmp_dest_unreach(unittest.TestCase):

    type_ = icmp.ICMP_DEST_UNREACH
    code = icmp.ICMP_HOST_UNREACH_CODE
    csum = 0

    mtu = 10
    data = 'abc'
    data_len = len(data)
    dst_unreach = icmp.dest_unreach(data_len=data_len, mtu=mtu, data=data)

    ic = icmp.icmp(type_, code, csum, data=dst_unreach)

    def setUp(self):
        pass

    def tearDown(self):
        pass

    def test_to_string(self):
        data_values = {
            'data': self.data,
            'data_len': self.data_len,
            'mtu': self.mtu
        }
        _data_str = ','.join([
            '%s=%s' % (k, repr(data_values[k]))
            for k, v in inspect.getmembers(self.dst_unreach)
            if k in data_values
        ])
        data_str = '%s(%s)' % (icmp.dest_unreach.__name__, _data_str)

        icmp_values = {
            'type': repr(self.type_),
            'code': repr(self.code),
            'csum': repr(self.csum),
            'data': data_str
        }
        _ic_str = ','.join([
            '%s=%s' % (k, icmp_values[k])
            for k, v in inspect.getmembers(self.ic) if k in icmp_values
        ])
        ic_str = '%s(%s)' % (icmp.icmp.__name__, _ic_str)

        eq_(str(self.ic), ic_str)
        eq_(repr(self.ic), ic_str)
Esempio n. 11
0
    def test_default_args(self):
        ic = icmp.icmp()
        buf = ic.serialize(bytearray(), None)
        res = struct.unpack(icmp.icmp._PACK_STR, six.binary_type(buf[:4]))

        eq_(res[0], 8)
        eq_(res[1], 0)
        eq_(buf[4:], b'\x00\x00\x00\x00')

        # with data
        ic = icmp.icmp(type_=icmp.ICMP_DEST_UNREACH, data=icmp.dest_unreach())
        buf = ic.serialize(bytearray(), None)
        res = struct.unpack(icmp.icmp._PACK_STR, six.binary_type(buf[:4]))

        eq_(res[0], 3)
        eq_(res[1], 0)
        eq_(buf[4:], b'\x00\x00\x00\x00')
Esempio n. 12
0
    def setUp_with_dest_unreach(self):
        self.unreach_mtu = 10
        self.unreach_data = 'abc'
        self.unreach_data_len = len(self.unreach_data)
        self.data = icmp.dest_unreach(data_len=self.unreach_data_len,
                                      mtu=self.unreach_mtu,
                                      data=self.unreach_data)

        self.type_ = icmp.ICMP_DEST_UNREACH
        self.code = icmp.ICMP_HOST_UNREACH_CODE
        self.ic = icmp.icmp(self.type_, self.code, self.csum, self.data)

        self.buf = struct.pack(icmp.icmp._PACK_STR, self.type_, self.code,
                               self.csum)
        self.buf += self.data.serialize()
        self.csum_calc = packet_utils.checksum(str(self.buf))
        struct.pack_into('!H', self.buf, 2, self.csum_calc)
Esempio n. 13
0
    def test_default_args(self):
        ic = icmp.icmp()
        buf = ic.serialize(bytearray(), None)
        res = struct.unpack(icmp.icmp._PACK_STR, six.binary_type(buf[:4]))

        eq_(res[0], 8)
        eq_(res[1], 0)
        eq_(buf[4:], b'\x00\x00\x00\x00')

        # with data
        ic = icmp.icmp(type_=icmp.ICMP_DEST_UNREACH, data=icmp.dest_unreach())
        buf = ic.serialize(bytearray(), None)
        res = struct.unpack(icmp.icmp._PACK_STR, six.binary_type(buf[:4]))

        eq_(res[0], 3)
        eq_(res[1], 0)
        eq_(buf[4:], b'\x00\x00\x00\x00')
Esempio n. 14
0
    def create_icmp_unrachalbe_packet(self, pkt, ipv4_pkt):

        eth_pkt = pkt.get_protocol(ethernet.ethernet)
        pkt = packet.Packet()
        pkt.add_protocol(
            ethernet.ethernet(dst=eth_pkt.src, ethertype=eth_pkt.ethertype)
        )  #src hardware addr is default = '00.00.00.00.00.00.00.00'
        pkt.add_protocol(
            ipv4.ipv4(src=ipv4_pkt.dst, dst=ipv4_pkt.src,
                      proto=ipv4_pkt.proto))

        pkt_payload = icmp.dest_unreach()
        pkt.add_protocol(
            icmp.icmp(type_=icmp.ICMP_DEST_UNREACH,
                      code=icmp.ICMP_HOST_UNREACH_CODE,
                      csum=0,
                      data=pkt_payload))

        pkt.serialize()
        return pkt.data
Esempio n. 15
0
    def send_icmp_port_unreachable(self, datapath, old_pkt, output):

        pkt = packet.Packet()
        datapkt = packet.Packet()

        dst_ip = None

        for protocol in old_pkt:
            if not hasattr(protocol, 'protocol_name'):
                datapkt.add_protocol(protocol)
            elif protocol.protocol_name == 'ethernet':
                e = ethernet.ethernet(src=protocol.dst, dst=protocol.src, ethertype=ether_types.ETH_TYPE_IP)
                pkt.add_protocol(e)
            elif protocol.protocol_name == 'ipv4':
                ip = ipv4.ipv4(dst=protocol.src, src=protocol.dst, proto=in_proto.IPPROTO_ICMP)
                dst_ip = protocol.src
                pkt.add_protocol(ip)
                datapkt.add_protocol(protocol)
            else:
                datapkt.add_protocol(protocol)

        datapkt.serialize()
        icm_data = icmp.dest_unreach(data=datapkt.data)
        icm = icmp.icmp(type_=icmp.ICMP_DEST_UNREACH, code=icmp.ICMP_PORT_UNREACH_CODE, csum=0, data=icm_data)

        pkt.add_protocol(icm)

        pkt.serialize()

        actions = [datapath.ofproto_parser.OFPActionOutput(output, 0)]

        ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        res = ofp_parser.OFPPacketOut(datapath=datapath, buffer_id=ofp.OFP_NO_BUFFER,
                                      in_port=datapath.ofproto.OFPP_CONTROLLER, actions=actions, data=pkt.data)

        LOG.info('Sending ICMP Port unreachable message for %s', dst_ip)
        datapath.send_msg(res)
Esempio n. 16
0
    def send_icmp(self,
                  in_port,
                  protocol_list,
                  vlan_id,
                  icmp_type,
                  icmp_code,
                  icmp_data=None,
                  msg_data=None,
                  src_ip=None):
        # Generate ICMP reply packet
        csum = 0
        offset = ethernet.ethernet._MIN_LEN

        if vlan_id != VLANID_NONE:
            ether_proto = ether.ETH_TYPE_8021Q
            pcp = 0
            cfi = 0
            vlan_ether = ether.ETH_TYPE_IP
            v = vlan.vlan(pcp, cfi, vlan_id, vlan_ether)
            offset += vlan.vlan._MIN_LEN
        else:
            ether_proto = ether.ETH_TYPE_IP

        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:
            # 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=data_len,
                                              data=ip_datagram)
            elif icmp_type == icmp.ICMP_TIME_EXCEEDED:
                icmp_data = icmp.TimeExceeded(data_len=data_len,
                                              data=ip_datagram)

        ic = icmp.icmp(icmp_type, icmp_code, csum, data=icmp_data)

        if src_ip is None:
            src_ip = ip.dst
        ip_total_length = ip.header_length * 4 + ic._MIN_LEN
        if ic.data is not None:
            ip_total_length += ic.data._MIN_LEN
            if ic.data.data is not None:
                ip_total_length += +len(ic.data.data)
        i = ipv4.ipv4(ip.version, ip.header_length, ip.tos, ip_total_length,
                      ip.identification, ip.flags, ip.offset, DEFAULT_TTL,
                      inet.IPPROTO_ICMP, csum, src_ip, ip.src)

        pkt = packet.Packet()
        pkt.add_protocol(e)
        if vlan_id != VLANID_NONE:
            pkt.add_protocol(v)
        pkt.add_protocol(i)
        pkt.add_protocol(ic)
        pkt.serialize()

        # Send packet out
        self.send_packet_out(in_port,
                             self.dp.ofproto.OFPP_IN_PORT,
                             pkt.data,
                             data_str=str(pkt))
Esempio n. 17
0
    def send_icmp(self,
                  in_port,
                  protocol_list,
                  vlan_id,
                  icmp_type,
                  icmp_code,
                  icmp_data=None,
                  msg_data=None,
                  src_ip=None):
        # Generate ICMP reply packet
        csum = 0
        offset = ethernet.ethernet._MIN_LEN

        if vlan_id != VLANID_NONE:
            ether_proto = ether.ETH_TYPE_8021Q
            pcp = 0
            cfi = 0
            vlan_ether = ether.ETH_TYPE_IP
            v = vlan.vlan(pcp, cfi, vlan_id, vlan_ether)
            offset += vlan.vlan._MIN_LEN
        else:
            ether_proto = ether.ETH_TYPE_IP

        eth = protocol_list[ETHERNET]
        e = ethernet.ethernet(eth.src, eth.dst, ether_proto)

        if icmp_data is None and msg_data is not None:
            ip_datagram = msg_data[offset:]
            if icmp_type == icmp.ICMP_DEST_UNREACH:
                icmp_data = icmp.dest_unreach(data_len=len(ip_datagram),
                                              data=ip_datagram)
            elif icmp_type == icmp.ICMP_TIME_EXCEEDED:
                icmp_data = icmp.TimeExceeded(data_len=len(ip_datagram),
                                              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
        if ic.data is not None:
            ip_total_length += ic.data._MIN_LEN
            if ic.data.data is not None:
                ip_total_length += +len(ic.data.data)
        i = ipv4.ipv4(ip.version, ip.header_length, ip.tos, ip_total_length,
                      ip.identification, ip.flags, ip.offset, DEFAULT_TTL,
                      inet.IPPROTO_ICMP, csum, src_ip, ip.src)

        pkt = packet.Packet()
        pkt.add_protocol(e)
        if vlan_id != VLANID_NONE:
            pkt.add_protocol(v)
        pkt.add_protocol(i)
        pkt.add_protocol(ic)
        pkt.serialize()

        # Send packet out
        self.send_packet_out(in_port,
                             self.dp.ofproto.OFPP_IN_PORT,
                             pkt.data,
                             data_str=str(pkt))
Esempio n. 18
0
    def generate_icmp_datagram(self, dpid, iface_port, msg, pkt, icmp_type, code) -> packet.Packet():
        eth_hdr = pkt.protocols[0]  # Link-Layer header
        ip_hdr = original_ip_hdr = pkt.protocols[1]  # Network-Layer header

        iface_mac = self.interfaces[dpid][iface_port]['mac']  # The MAC address of this i/face
        iface_ip = self.interfaces[dpid][iface_port]['ip']  # The IP address of this i/face
        msg_data = msg.data  # The data from the original datagram (received)

        # Configure Link-Layer header
        eth_hdr.dst = eth_hdr.src  # The source mac address, will now be the recipient (destination mac)
        eth_hdr.src = iface_mac  # This router's i/face mac address will be the sender (source mac)

        # Configure Network-Layer header
        ip_hdr.total_length = 0  # 0 means calculate automatically while encoding
        ip_hdr.dst = ip_hdr.src  # Same as Link-Layer changes, but with IP address instead of MAC address
        ip_hdr.src = iface_ip  # Same as Link-Layer changes, but with IP address instead of MAC address
        ip_hdr.proto = inet.IPPROTO_ICMP  # proto could've been udp or tcp

        # Generate new ICMP header of type "destination unreachable"
        # Logic for construction of TTL EXCEEDED icmp header and network layer header bytes, taken from
        # https://github.com/osrg/ryu/blob/master/ryu/app/rest_router.py  (see function send_icmp())
        offset = ethernet.ethernet._MIN_LEN  # Get the header offset
        end_of_data = offset + len(original_ip_hdr) + 128
        ip_hdr_bytes = bytearray(msg_data[offset:end_of_data])  # Get IP header data of original pkt
        data_len = int(len(ip_hdr_bytes) / 4)  # Get the length of the data
        length_mod = int(len(ip_hdr_bytes) % 4)
        if length_mod:
            data_len += 1  # add 1 more, if there is remainder to avoid sending less data and therefore invalid
            ip_hdr_bytes += bytearray([0] * (4 - length_mod))  # finally get ip header bytes

        # instantiate the icmp header based on type of icmp
        if icmp_type == icmp.ICMP_DEST_UNREACH:
            icmp_hdr = icmp.icmp(
                type_=icmp_type, code=code, csum=0, data=icmp.dest_unreach(data_len=data_len, data=ip_hdr_bytes)
            )
        elif icmp_type == icmp.ICMP_ECHO_REPLY:
            original_icmp_hdr = pkt.protocols[2]
            icmp_hdr = icmp.icmp(type_=icmp_type, code=code, csum=0, data=original_icmp_hdr.data)

        elif icmp_type == icmp.ICMP_TIME_EXCEEDED:
            default_ttl = 64
            icmp_hdr = icmp.icmp(
                type_=icmp_type, code=code, csum=0, data=icmp.TimeExceeded(data_len=data_len, data=ip_hdr_bytes)
            )
            ip_total_length = ip_hdr.header_length * 4 + icmp_hdr._MIN_LEN
            ip_total_length += icmp_hdr.data._MIN_LEN
            ip_total_length += + len(icmp_hdr.data.data)

            # Generate new Network Layer header
            new_ip_hdr = ipv4.ipv4(
                header_length=ip_hdr.header_length, total_length=0, src=ip_hdr.src, dst=ip_hdr.dst, proto=ip_hdr.proto,
                tos=original_ip_hdr.tos, identification=original_ip_hdr.identification, flags=original_ip_hdr.flags,
                offset=original_ip_hdr.offset, ttl=default_ttl
            )
            p = packet.Packet()
            p.add_protocol(eth_hdr)
            p.add_protocol(new_ip_hdr)
            p.add_protocol(icmp_hdr)
            return p

        else:
            return None  # Return null for unsupported icmp packets destined to router

        # Replace headers in the packet
        pkt.protocols[0] = eth_hdr
        pkt.protocols[1] = ip_hdr
        pkt.protocols[2] = icmp_hdr

        # Return the packet containing the router's response to packet_in handler for forwarding
        return pkt