def icmpv6_echo_reply(vid, eth_src, eth_dst, src_ip, dst_ip, hop_limit, id_, seq, data): r"""Return IPv6 ICMP echo reply packet. Args: vid (int or None): VLAN VID to use (or None). eth_src (str): source Ethernet MAC address. eth_dst (str): destination Ethernet MAC address. src_ip (ipaddress.IPv6Address): source IPv6 address. dst_ip (ipaddress.IPv6Address): destination IPv6 address. hop_limit (int): IPv6 hop limit. id_ (int): identifier for echo reply. seq (int): sequence number for echo reply. data (str): payload for echo reply. Returns: ryu.lib.packet.ethernet: Serialized IPv6 ICMP echo reply packet. """ pkt = build_pkt_header(vid, eth_src, eth_dst, valve_of.ether.ETH_TYPE_IPV6) ipv6_reply = ipv6.ipv6(src=src_ip, dst=dst_ip, nxt=valve_of.inet.IPPROTO_ICMPV6, hop_limit=hop_limit) pkt.add_protocol(ipv6_reply) icmpv6_reply = icmpv6.icmpv6(type_=icmpv6.ICMPV6_ECHO_REPLY, data=icmpv6.echo(id_=id_, seq=seq, data=data)) pkt.add_protocol(icmpv6_reply) pkt.serialize() return pkt
def nd_advert(vid, eth_src, eth_dst, src_ip, dst_ip): """Return IPv6 neighbor avertisement packet. Args: vid (int or None): VLAN VID to use (or None). eth_src (str): source Ethernet MAC address. eth_dst (str): destination Ethernet MAC address. src_ip (ipaddress.IPv6Address): source IPv6 address. dst_ip (ipaddress.IPv6Address): destination IPv6 address. Returns: ryu.lib.packet.ethernet: Serialized IPv6 neighbor discovery packet. """ pkt = build_pkt_header(vid, eth_src, eth_dst, valve_of.ether.ETH_TYPE_IPV6) ipv6_icmp6 = ipv6.ipv6(src=src_ip, dst=dst_ip, nxt=valve_of.inet.IPPROTO_ICMPV6, hop_limit=IPV6_MAX_HOP_LIM) pkt.add_protocol(ipv6_icmp6) icmpv6_nd_advert = icmpv6.icmpv6( type_=icmpv6.ND_NEIGHBOR_ADVERT, data=icmpv6.nd_neighbor(dst=src_ip, option=icmpv6.nd_option_tla(hw_src=eth_src), res=7)) pkt.add_protocol(icmpv6_nd_advert) pkt.serialize() return pkt
def nd_request(vid, eth_src, eth_dst, src_ip, dst_ip): """Return IPv6 neighbor discovery request packet. Args: vid (int or None): VLAN VID to use (or None). eth_src (str): source Ethernet MAC address. eth_dst (str): Ethernet destination address. src_ip (ipaddress.IPv6Address): source IPv6 address. dst_ip (ipaddress.IPv6Address): requested IPv6 address. Returns: ryu.lib.packet.ethernet: Serialized IPv6 neighbor discovery packet. """ if mac_addr_is_unicast(eth_dst): nd_mac = eth_dst nd_ip = dst_ip else: nd_mac = ipv6_link_eth_mcast(dst_ip) nd_ip = ipv6_solicited_node_from_ucast(dst_ip) pkt = build_pkt_header(vid, eth_src, nd_mac, valve_of.ether.ETH_TYPE_IPV6) ipv6_pkt = ipv6.ipv6(src=str(src_ip), dst=nd_ip, nxt=valve_of.inet.IPPROTO_ICMPV6) pkt.add_protocol(ipv6_pkt) icmpv6_pkt = icmpv6.icmpv6( type_=icmpv6.ND_NEIGHBOR_SOLICIT, data=icmpv6.nd_neighbor(dst=dst_ip, option=icmpv6.nd_option_sla(hw_src=eth_src))) pkt.add_protocol(icmpv6_pkt) pkt.serialize() return pkt
def packet_in_handler(self, event): if event.msg.match['in_port'] != FAKEPORT: return pkt = packet.Packet(event.msg.data) eth_protocol = pkt.get_protocol(ethernet.ethernet) vlan_protocol = pkt.get_protocol(vlan.vlan) ipv6_protocol = pkt.get_protocol(ipv6.ipv6) icmpv6_protocol = pkt.get_protocol(icmpv6.icmpv6) if not (eth_protocol and vlan_protocol and ipv6_protocol and icmpv6_protocol): return if icmpv6_protocol.type_ != icmpv6.ND_NEIGHBOR_SOLICIT: return if int(ipaddress.ip_address(ipv6_protocol.src)) == 0: return src_ip = ipaddress.ip_address(icmpv6_protocol.data.dst) if src_ip.is_reserved: return eth_dst = eth_protocol.src dst_ip = ipv6_protocol.src eth_src = FAKECLIENTMAC vid = vlan_protocol.vid reply = packet.Packet() for protocol in (ethernet.ethernet(eth_dst, eth_src, ether.ETH_TYPE_8021Q), vlan.vlan(vid=vid, ethertype=ether.ETH_TYPE_IPV6), ipv6.ipv6(src=src_ip, dst=dst_ip, nxt=socket.IPPROTO_ICMPV6, hop_limit=255), icmpv6.icmpv6( type_=icmpv6.ND_NEIGHBOR_ADVERT, data=icmpv6.nd_neighbor( dst=src_ip, option=icmpv6.nd_option_tla(hw_src=eth_src), res=7))): reply.add_protocol(protocol) reply.serialize() out = parser.OFPPacketOut(datapath=event.msg.datapath, buffer_id=ofp.OFP_NO_BUFFER, in_port=ofp.OFPP_CONTROLLER, actions=[parser.OFPActionOutput(FAKEPORT)], data=reply.data) self.send_mods(event.msg.datapath, [out])
def test_smoke_packet_in(self): nd_solicit = packet.Packet() eth_src = '01:02:03:04:05:06' eth_dst = 'ff:ff:ff:ff:ff:ff' src_ip = 'fc00::1' dst_ip = 'fc00::2' vid = 2 for protocol in (ethernet.ethernet(eth_dst, eth_src, ether.ETH_TYPE_8021Q), vlan.vlan(vid=vid, ethertype=ether.ETH_TYPE_IPV6), ipv6.ipv6(src=src_ip, dst=dst_ip, nxt=socket.IPPROTO_ICMPV6, hop_limit=255), icmpv6.icmpv6( type_=icmpv6.ND_NEIGHBOR_SOLICIT, data=icmpv6.nd_neighbor( dst=src_ip, option=icmpv6.nd_option_tla(hw_src=eth_src), res=7))): nd_solicit.add_protocol(protocol) nd_solicit.serialize() fake_dp = FakeDP() fake_pipette = Pipette(dpset={}) class FakeMsg: def __init__(self): self.datapath = fake_dp self.match = {'in_port': FAKEPORT} self.data = nd_solicit.data class FakePiEv: def __init__(self): self.msg = FakeMsg() fake_pipette = Pipette(dpset={}) fake_pipette.packet_in_handler(FakePiEv()) assert fake_dp.msgs
def router_advert(vid, eth_src, eth_dst, src_ip, dst_ip, vips, pi_flags=0x6): """Return IPv6 ICMP Router Advert. Args: vid (int or None): VLAN VID to use (or None). eth_src (str): source Ethernet MAC address. eth_dst (str): dest Ethernet MAC address. src_ip (ipaddress.IPv6Address): source IPv6 address. vips (list): prefixes (ipaddress.IPv6Address) to advertise. pi_flags (int): flags to set in prefix information field (default set A and L) Returns: ryu.lib.packet.ethernet: Serialized IPv6 ICMP RA packet. """ pkt = build_pkt_header(vid, eth_src, eth_dst, valve_of.ether.ETH_TYPE_IPV6) ipv6_pkt = ipv6.ipv6(src=src_ip, dst=dst_ip, nxt=valve_of.inet.IPPROTO_ICMPV6, hop_limit=IPV6_MAX_HOP_LIM) pkt.add_protocol(ipv6_pkt) options = [] for vip in vips: options.append( icmpv6.nd_option_pi( prefix=vip.network.network_address, pl=vip.network.prefixlen, res1=pi_flags, val_l=86400, pre_l=14400, )) options.append(icmpv6.nd_option_sla(hw_src=eth_src)) # https://tools.ietf.org/html/rfc4861#section-4.6.2 icmpv6_ra_pkt = icmpv6.icmpv6(type_=icmpv6.ND_ROUTER_ADVERT, data=icmpv6.nd_router_advert( rou_l=1800, ch_l=IPV6_RA_HOP_LIM, options=options)) pkt.add_protocol(icmpv6_ra_pkt) pkt.serialize() return pkt