def _create_test_dhcp6_packet(self, zero_time=False): ret_pkt = packet.Packet() ret_pkt.add_protocol( ethernet.ethernet( ethertype=ether_types.ETH_TYPE_IPV6, dst='33:33:00:01:00:02', src=self.port_info['mac_address'])) ret_pkt.add_protocol( ipv6.ipv6( src='fe80::f816:3eff:fe60:714b', dst='ff02::1:2', nxt=inet.IPPROTO_UDP)) ret_pkt.add_protocol( udp.udp( src_port=constants.DHCPV6_RESPONSE_PORT, dst_port=constants.DHCPV6_CLIENT_PORT)) options = [dhcp6.option( code=1, data=b"\x00\x01\x00\x01", length=4)] if zero_time: options.append(dhcp6.option( code=3, data=b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", length=12)) else: options.append(dhcp6.option( code=3, data=b"\x01\x02\x03\x04\x05\x06\x07\x08\x0a\x0b\x0c\x0d", length=12)) ret_pkt.add_protocol(dhcp6.dhcp6( dhcp6.DHCPV6_REQUEST, dhcp6.options(option_list=options))) return ret_pkt
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 create_packet(self, primary_ip_address, vlan_id=None): """Prepare a VRRP packet. Returns a newly created os_ken.lib.packet.packet.Packet object with appropriate protocol header objects added by add_protocol(). It's caller's responsibility to serialize(). The serialized packet would looks like the ones described in the following sections. * RFC 3768 5.1. VRRP Packet Format * RFC 5798 5.1. VRRP Packet Format ================== ==================== Argument Description ================== ==================== primary_ip_address Source IP address vlan_id VLAN ID. None for no VLAN. ================== ==================== """ if self.is_ipv6: traffic_class = 0xc0 # set tos to internetwork control flow_label = 0 payload_length = ipv6.ipv6._MIN_LEN + len(self) # XXX _MIN_LEN e = ethernet.ethernet(VRRP_IPV6_DST_MAC_ADDRESS, vrrp_ipv6_src_mac_address(self.vrid), ether.ETH_TYPE_IPV6) ip = ipv6.ipv6(6, traffic_class, flow_label, payload_length, inet.IPPROTO_VRRP, VRRP_IPV6_HOP_LIMIT, primary_ip_address, VRRP_IPV6_DST_ADDRESS) else: header_length = ipv4.ipv4._MIN_LEN // 4 # XXX _MIN_LEN total_length = 0 tos = 0xc0 # set tos to internetwork control identification = self.get_identification() e = ethernet.ethernet(VRRP_IPV4_DST_MAC_ADDRESS, vrrp_ipv4_src_mac_address(self.vrid), ether.ETH_TYPE_IP) ip = ipv4.ipv4(4, header_length, tos, total_length, identification, 0, 0, VRRP_IPV4_TTL, inet.IPPROTO_VRRP, 0, primary_ip_address, VRRP_IPV4_DST_ADDRESS) p = packet.Packet() p.add_protocol(e) if vlan_id is not None: vlan_ = vlan.vlan(0, 0, vlan_id, e.ethertype) e.ethertype = ether.ETH_TYPE_8021Q p.add_protocol(vlan_) p.add_protocol(ip) p.add_protocol(self) return p
def get_ret_packet(self, packet_in, port_info, req_type): ip_info = self.get_port_ip(port_info, ip_version=constants.IP_VERSION_6) if not ip_info: return gateway_ip = ip_info['gateway_ip'] mac = port_info['mac_address'] header_eth = packet_in.get_protocol(ethernet.ethernet) header_ipv6 = packet_in.get_protocol(ipv6.ipv6) header_dhcp = packet_in.get_protocol(dhcp6.dhcp6) if req_type == 'CONFIRM': options = self.get_reply_dhcp_options( mac, message="all addresses still on link", req_options=header_dhcp.options.option_list) if req_type == 'RELEASE': options = self.get_reply_dhcp_options( mac, message="release received", req_options=header_dhcp.options.option_list) else: options = self.get_dhcp_options(mac, ip_info, header_dhcp.options.option_list, req_type) ret_pkt = packet.Packet() ret_pkt.add_protocol( ethernet.ethernet(ethertype=header_eth.ethertype, dst=header_eth.src, src=self.hw_addr)) ret_pkt.add_protocol( ipv6.ipv6(src=gateway_ip, dst=header_ipv6.src, nxt=inet.IPPROTO_UDP)) ret_pkt.add_protocol( udp.udp(src_port=constants.DHCPV6_RESPONSE_PORT, dst_port=constants.DHCPV6_CLIENT_PORT)) ret_type = self.get_ret_type(req_type) ret_pkt.add_protocol( dhcp6.dhcp6(ret_type, options, transaction_id=header_dhcp.transaction_id)) return ret_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 decode(nfa): """This function analyses nflog packet by using os-ken packet library.""" prefix = ffi.string(libnflog.nflog_get_prefix(nfa)) packet_hdr = libnflog.nflog_get_msg_packet_hdr(nfa) hw_proto = socket.ntohs(packet_hdr.hw_protocol) msg = '' msg_packet_hwhdr = libnflog.nflog_get_msg_packet_hwhdr(nfa) if msg_packet_hwhdr != ffi.NULL: packet_hwhdr = ffi.string(msg_packet_hwhdr) if len(packet_hwhdr) >= 12: dst, src = struct.unpack_from('!6s6s', packet_hwhdr) # Dump ethernet packet to get mac addresses eth = ethernet.ethernet(addrconv.mac.bin_to_text(dst), addrconv.mac.bin_to_text(src), ethertype=hw_proto) msg = str(eth) # Dump IP packet pkt = _payload(nfa) if hw_proto == ether_types.ETH_TYPE_IP: ip_pkt, proto, data = ipv4.ipv4().parser(pkt) msg += str(ip_pkt) proto_pkt, a, b = proto.parser(data) msg += str(proto_pkt) elif hw_proto == ether_types.ETH_TYPE_IPV6: ip_pkt, proto, data = ipv6.ipv6().parser(pkt) proto_pkt, a, b = proto.parser(data) msg += str(proto_pkt) elif hw_proto == ether_types.ETH_TYPE_ARP: ip_pkt, proto, data = arp.arp().parser(pkt) msg += str(ip_pkt) else: msg += "Does not support hw_proto: " + str(hw_proto) return { 'prefix': encodeutils.safe_decode(prefix), 'msg': encodeutils.safe_decode(msg) }
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
def test_serialize(self): src_ip = '2001:db8:2000::1' dst_ip = vrrp.VRRP_IPV6_DST_ADDRESS prev = ipv6.ipv6(6, 0, 0, 0, inet.IPPROTO_VRRP, vrrp.VRRP_IPV6_HOP_LIMIT, src_ip, dst_ip) type_ = vrrp.VRRP_TYPE_ADVERTISEMENT vrid = 5 priority = 10 max_adver_int = 30 ip_address = '2001:db8:2000::2' ip_addresses = [ip_address] vrrp_ = vrrp.vrrpv3.create(type_, vrid, priority, max_adver_int, ip_addresses) buf = vrrp_.serialize(bytearray(), prev) print(len(buf), type(buf), buf) pack_str = vrrp.vrrpv3._PACK_STR + '16s' pack_len = struct.calcsize(pack_str) res = struct.unpack(pack_str, six.binary_type(buf)) eq_(res[0], vrrp.vrrp_to_version_type(vrrp.VRRP_VERSION_V3, type_)) eq_(res[1], vrid) eq_(res[2], priority) eq_(res[3], len(ip_addresses)) eq_(res[4], max_adver_int) # res[5] is checksum eq_(res[6], addrconv.ipv6.text_to_bin(ip_address)) eq_(len(buf), pack_len) print(res) # checksum ph = struct.pack('!16s16sI3xB', addrconv.ipv6.text_to_bin(src_ip), addrconv.ipv6.text_to_bin(dst_ip), pack_len, inet.IPPROTO_VRRP) s = packet_utils.checksum(ph + buf) eq_(0, s)
def _gen_ipv6(self, nxt, src=None, dst=None): return ipv6.ipv6( src=(src or SRC_IPV6_1), dst=(dst or DST_IPV6_1), nxt=nxt, )