def test_default_args(self): la = icmpv6.nd_option_sla() buf = la.serialize() res = struct.unpack(icmpv6.nd_option_sla._PACK_STR, str(buf)) eq_(res[0], icmpv6.ND_OPTION_SLA) eq_(res[1], len(icmpv6.nd_option_sla()) / 8) eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00')) # with nd_neighbor prev = ipv6(nxt=inet.IPPROTO_ICMPV6) ic = icmpv6.icmpv6( type_=icmpv6.ND_NEIGHBOR_ADVERT, data=icmpv6.nd_neighbor( option=icmpv6.nd_option_tla())) prev.serialize(ic, None) buf = ic.serialize(bytearray(), prev) res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) eq_(res[0], icmpv6.ND_NEIGHBOR_ADVERT) eq_(res[1], 0) eq_(res[2], icmpv6_csum(prev, buf)) res = struct.unpack(icmpv6.nd_neighbor._PACK_STR, str(buf[4:24])) eq_(res[0], 0) eq_(res[1], addrconv.ipv6.text_to_bin('::')) res = struct.unpack(icmpv6.nd_option_tla._PACK_STR, str(buf[24:])) eq_(res[0], icmpv6.ND_OPTION_TLA) eq_(res[1], len(icmpv6.nd_option_tla()) / 8) eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00')) # with nd_router_solicit prev = ipv6(nxt=inet.IPPROTO_ICMPV6) ic = icmpv6.icmpv6( type_=icmpv6.ND_ROUTER_SOLICIT, data=icmpv6.nd_router_solicit( option=icmpv6.nd_option_sla())) prev.serialize(ic, None) buf = ic.serialize(bytearray(), prev) res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) eq_(res[0], icmpv6.ND_ROUTER_SOLICIT) eq_(res[1], 0) eq_(res[2], icmpv6_csum(prev, buf)) res = struct.unpack(icmpv6.nd_router_solicit._PACK_STR, str(buf[4:8])) eq_(res[0], 0) res = struct.unpack(icmpv6.nd_option_sla._PACK_STR, str(buf[8:])) eq_(res[0], icmpv6.ND_OPTION_SLA) eq_(res[1], len(icmpv6.nd_option_sla()) / 8) eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00'))
def test_default_args(self): la = icmpv6.nd_option_sla() buf = la.serialize() res = struct.unpack(icmpv6.nd_option_sla._PACK_STR, str(buf)) eq_(res[0], icmpv6.ND_OPTION_SLA) eq_(res[1], len(icmpv6.nd_option_sla()) / 8) eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00')) # with nd_neighbor prev = ipv6(nxt=inet.IPPROTO_ICMPV6) ic = icmpv6.icmpv6( type_=icmpv6.ND_NEIGHBOR_ADVERT, data=icmpv6.nd_neighbor(option=icmpv6.nd_option_tla())) prev.serialize(ic, None) buf = ic.serialize(bytearray(), prev) res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) eq_(res[0], icmpv6.ND_NEIGHBOR_ADVERT) eq_(res[1], 0) eq_(res[2], icmpv6_csum(prev, buf)) res = struct.unpack(icmpv6.nd_neighbor._PACK_STR, str(buf[4:24])) eq_(res[0], 0) eq_(res[1], addrconv.ipv6.text_to_bin('::')) res = struct.unpack(icmpv6.nd_option_tla._PACK_STR, str(buf[24:])) eq_(res[0], icmpv6.ND_OPTION_TLA) eq_(res[1], len(icmpv6.nd_option_tla()) / 8) eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00')) # with nd_router_solicit prev = ipv6(nxt=inet.IPPROTO_ICMPV6) ic = icmpv6.icmpv6( type_=icmpv6.ND_ROUTER_SOLICIT, data=icmpv6.nd_router_solicit(option=icmpv6.nd_option_sla())) prev.serialize(ic, None) buf = ic.serialize(bytearray(), prev) res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) eq_(res[0], icmpv6.ND_ROUTER_SOLICIT) eq_(res[1], 0) eq_(res[2], icmpv6_csum(prev, buf)) res = struct.unpack(icmpv6.nd_router_solicit._PACK_STR, str(buf[4:8])) eq_(res[0], 0) res = struct.unpack(icmpv6.nd_option_sla._PACK_STR, str(buf[8:])) eq_(res[0], icmpv6.ND_OPTION_SLA) eq_(res[1], len(icmpv6.nd_option_sla()) / 8) eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00'))
def __init__(self, mac_src, mac_dst, ipv6_src, ipv6_dst, ipv6_tgt): """ ================ ========================================================= Input Parameter Description ================ ========================================================= mac_src String instance mac_dst String instance ipv6_src String instance ipv6_dst String instance ipv6_tgt String instance ================ ========================================================= ================ ========================================================= Attribute Description ================ ========================================================= pkt The Neighbor Solicitation generated packet ================ ========================================================= """ self.pkt = packet.Packet() e = ethernet.ethernet(mac_dst, mac_src, ether.ETH_TYPE_IPV6) i6 = ipv6.ipv6(src = ipv6_src, dst = ipv6_dst, nxt = inet.IPPROTO_ICMPV6) ic = icmpv6.icmpv6(type_ = icmpv6.ND_NEIGHBOR_SOLICIT, data = icmpv6.nd_neighbor(dst = ipv6_tgt, option = icmpv6.nd_option_sla(hw_src = mac_src))) self.pkt.add_protocol(e) self.pkt.add_protocol(i6) self.pkt.add_protocol(ic)
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 __init__(self, mac_src, mac_dst, ipv6_src, ipv6_dst, ipv6_tgt): """ ================ ========================================================= Input Parameter Description ================ ========================================================= mac_src String instance mac_dst String instance ipv6_src String instance ipv6_dst String instance ipv6_tgt String instance ================ ========================================================= ================ ========================================================= Attribute Description ================ ========================================================= pkt The Neighbor Solicitation generated packet ================ ========================================================= """ self.pkt = packet.Packet() e = ethernet.ethernet(mac_dst, mac_src, ether.ETH_TYPE_IPV6) i6 = ipv6.ipv6(src=ipv6_src, dst=ipv6_dst, nxt=inet.IPPROTO_ICMPV6) ic = icmpv6.icmpv6( type_=icmpv6.ND_NEIGHBOR_SOLICIT, data=icmpv6.nd_neighbor(dst=ipv6_tgt, option=icmpv6.nd_option_sla(hw_src=mac_src)), ) self.pkt.add_protocol(e) self.pkt.add_protocol(i6) self.pkt.add_protocol(ic)
def nd_request(eth_src, vid, src_ip, dst_ip): """Return IPv6 neighbor discovery request packet. Args: eth_src (str): source Ethernet MAC address. vid (int or None): VLAN VID to use (or None). src_ip (ipaddr.IPv6Address): source IPv6 address. dst_ip (ipaddr.IPv6Address): requested IPv6 address. Returns: ryu.lib.packet.ethernet: Serialized IPv6 neighbor discovery packet. """ nd_mac = ipv6_link_eth_mcast(dst_ip) ip_gw_mcast = ipv6_solicited_node_from_ucast(dst_ip) pkt = build_pkt_header(eth_src, nd_mac, vid, ether.ETH_TYPE_IPV6) ipv6_pkt = ipv6.ipv6( src=str(src_ip), dst=ip_gw_mcast, nxt=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 test_to_string(self): nd_opt = icmpv6.nd_option_sla(self.nd_length, self.nd_hw_src) rs = icmpv6.nd_router_solicit(self.res, nd_opt) ic = icmpv6.icmpv6(self.type_, self.code, self.csum, rs) nd_opt_values = {'length': self.nd_length, 'hw_src': self.nd_hw_src, 'data': None} _nd_opt_str = ','.join(['%s=%s' % (k, repr(nd_opt_values[k])) for k, v in inspect.getmembers(nd_opt) if k in nd_opt_values]) nd_opt_str = '%s(%s)' % (icmpv6.nd_option_sla.__name__, _nd_opt_str) rs_values = {'res': repr(rs.res), 'option': nd_opt_str} _rs_str = ','.join(['%s=%s' % (k, rs_values[k]) for k, v in inspect.getmembers(rs) if k in rs_values]) rs_str = '%s(%s)' % (icmpv6.nd_router_solicit.__name__, _rs_str) icmp_values = {'type_': repr(self.type_), 'code': repr(self.code), 'csum': repr(self.csum), 'data': rs_str} _ic_str = ','.join(['%s=%s' % (k, icmp_values[k]) for k, v in inspect.getmembers(ic) if k in icmp_values]) ic_str = '%s(%s)' % (icmpv6.icmpv6.__name__, _ic_str) eq_(str(ic), ic_str) eq_(repr(ic), ic_str)
def test_to_string(self): nd_opt = icmpv6.nd_option_sla(self.nd_length, self.nd_hw_src) nd = icmpv6.nd_neighbor(self.res, self.dst, nd_opt) ic = icmpv6.icmpv6(self.type_, self.code, self.csum, nd) nd_opt_values = {'length': self.nd_length, 'hw_src': self.nd_hw_src, 'data': None} _nd_opt_str = ','.join(['%s=%s' % (k, repr(nd_opt_values[k])) for k, v in inspect.getmembers(nd_opt) if k in nd_opt_values]) nd_opt_str = '%s(%s)' % (icmpv6.nd_option_sla.__name__, _nd_opt_str) nd_values = {'res': repr(nd.res), 'dst': repr(self.dst), 'option': nd_opt_str} _nd_str = ','.join(['%s=%s' % (k, nd_values[k]) for k, v in inspect.getmembers(nd) if k in nd_values]) nd_str = '%s(%s)' % (icmpv6.nd_neighbor.__name__, _nd_str) icmp_values = {'type_': repr(self.type_), 'code': repr(self.code), 'csum': repr(self.csum), 'data': nd_str} _ic_str = ','.join(['%s=%s' % (k, icmp_values[k]) for k, v in inspect.getmembers(ic) if k in icmp_values]) ic_str = '%s(%s)' % (icmpv6.icmpv6.__name__, _ic_str) eq_(str(ic), ic_str) eq_(repr(ic), ic_str)
def _send_icmp_NS(self, datapath, outport_no, dst_ip): src_mac_addr = \ str(self.dpid_to_switch[datapath.id].ports[outport_no].hw_addr) src_ip = \ str(self.dpid_to_switch[datapath.id].ports[outport_no].gateway.gw_ipv6) p = packet.Packet() dst_mac, dst_ip_multicast = self._generate_dst_for_NS(dst_ip) dst_mac = str(dst_mac) dst_ip_multicast = str(dst_ip_multicast) dst_ip = str(dst_ip) e = ethernet.ethernet(dst = dst_mac, src = src_mac_addr, ethertype = ether.ETH_TYPE_IPV6) ip6 = ipv6.ipv6(version = 6, traffic_class = 0, flow_label = 0, # 4byte ICMP header, 4byte reserved, 16byte target address, # 8byte "source link-layer address" option # next header value for ICMPv6 is 58 payload_length = 32, nxt = 58, hop_limit = 255, src = src_ip, dst = dst_ip_multicast) # source link-layer address sla_addr = icmpv6.nd_option_sla(hw_src = src_mac_addr) # ns for neighbor solicit; res for reserved, but actually is a flag, # see comments on "nd_option_tla" above ns = icmpv6.nd_neighbor(res = 4, dst = dst_ip, data = sla_addr) ic6 = icmpv6.icmpv6(type_ = icmpv6.ND_NEIGHBOR_SOLICIT, code = 0, # checksum = 0 then ryu calculate for you csum = 0, data = ns) p.add_protocol(e) p.add_protocol(ip6) p.add_protocol(ic6) p.serialize() datapath.send_packet_out(in_port = ofproto_v1_0.OFPP_NONE, actions = [datapath.ofproto_parser.OFPActionOutput(outport_no)], data = p.data)
def _send_router_advertisement(self, ipv6_src: str, tun_id: int, tun_ipv4_dst: str, output_port): """ Generates the Router Advertisement response packet """ ofproto, parser = self._datapath.ofproto, self._datapath.ofproto_parser if not tun_id or not tun_ipv4_dst: self.logger.error("Packet missing tunnel information, can't reply") return prefix = self.get_custom_prefix(ipv6_src) if not prefix: self.logger.debug("Can't reply to RS for UE ip %s", ipv6_src) return pkt = packet.Packet() pkt.add_protocol( ethernet.ethernet( dst=self.MAC_MULTICAST, src=self.config.ll_addr, ethertype=ether_types.ETH_TYPE_IPV6, )) pkt.add_protocol( ipv6.ipv6( dst=self.DEVICE_MULTICAST, src=self.config.ipv6_src, nxt=in_proto.IPPROTO_ICMPV6, )) pkt.add_protocol( icmpv6.icmpv6( type_=icmpv6.ND_ROUTER_ADVERT, data=icmpv6.nd_router_advert(options=[ icmpv6.nd_option_sla(hw_src=self.config.ll_addr, ), icmpv6.nd_option_pi( pl=self.config.prefix_len, prefix=prefix, ) ]), )) pkt.serialize() actions_out = [ parser.NXActionSetTunnel(tun_id=tun_id), parser.NXActionRegLoad2(dst='tun_ipv4_dst', value=tun_ipv4_dst), parser.OFPActionOutput(port=output_port) ] out = parser.OFPPacketOut(datapath=self._datapath, buffer_id=ofproto.OFP_NO_BUFFER, in_port=ofproto.OFPP_CONTROLLER, actions=actions_out, data=pkt.data) ret = self._datapath.send_msg(out) if not ret: self.logger.error("Datapath disconnected, couldn't send RA")
def build_pkt(pkt): """Build and return a packet and eth type from a dict.""" layers = [] assert 'eth_dst' in pkt and 'eth_src' in pkt ethertype = None if 'arp_source_ip' in pkt and 'arp_target_ip' in pkt: ethertype = ether.ETH_TYPE_ARP layers.append( arp.arp(src_ip=pkt['arp_source_ip'], dst_ip=pkt['arp_target_ip'])) elif 'ipv6_src' in pkt and 'ipv6_dst' in pkt: ethertype = ether.ETH_TYPE_IPV6 if 'neighbor_solicit_ip' in pkt: layers.append( icmpv6.icmpv6( type_=icmpv6.ND_NEIGHBOR_SOLICIT, data=icmpv6.nd_neighbor( dst=pkt['neighbor_solicit_ip'], option=icmpv6.nd_option_sla(hw_src=pkt['eth_src'])))) elif 'echo_request_data' in pkt: layers.append( icmpv6.icmpv6(type_=icmpv6.ICMPV6_ECHO_REQUEST, data=icmpv6.echo(id_=1, seq=1, data=pkt['echo_request_data']))) layers.append( ipv6.ipv6(src=pkt['ipv6_src'], dst=pkt['ipv6_dst'], nxt=inet.IPPROTO_ICMPV6)) elif 'ipv4_src' in pkt and 'ipv4_dst' in pkt: ethertype = ether.ETH_TYPE_IP proto = inet.IPPROTO_IP if 'echo_request_data' in pkt: echo = icmp.echo(id_=1, seq=1, data=pkt['echo_request_data']) layers.append(icmp.icmp(type_=icmp.ICMP_ECHO_REQUEST, data=echo)) proto = inet.IPPROTO_ICMP net = ipv4.ipv4(src=pkt['ipv4_src'], dst=pkt['ipv4_dst'], proto=proto) layers.append(net) assert ethertype is not None, pkt if 'vid' in pkt: tpid = ether.ETH_TYPE_8021Q layers.append(vlan.vlan(vid=pkt['vid'], ethertype=ethertype)) else: tpid = ethertype eth = ethernet.ethernet(dst=pkt['eth_dst'], src=pkt['eth_src'], ethertype=tpid) layers.append(eth) layers = [layer for layer in reversed(layers)] result = packet.Packet() for layer in layers: result.add_protocol(layer) result.serialize() return (result, ethertype)
def generate_ra_pkt(self, datapath, in_port): nd_option_sla = icmpv6.nd_option_sla(hw_src=self.port_mac_dic[datapath.id][in_port]) nd_option_pi = icmpv6.nd_option_pi( pl=64, res1=6, val_l=2592000, pre_l=604800, prefix=setting.Prefix_dic[datapath.id][in_port]) ra_data = icmpv6.nd_router_advert(ch_l=64, res=0, rou_l=1800, rea_t=0, ret_t=0, options=[nd_option_sla, nd_option_pi]) ra_pkt = packet.Packet() ra_pkt.add_protocol(ethernet.ethernet(ethertype=0x86DD, dst='33:33:00:00:00:01', src=self.port_mac_dic[datapath.id][in_port])) ra_pkt.add_protocol(ipv6.ipv6(dst='ff02::1', src=setting.Port_link_dic[datapath.id][in_port], nxt=58)) ra_pkt.add_protocol(icmpv6.icmpv6(type_=134, code=0, data=ra_data)) return ra_pkt
def router_advert(vid, eth_src, eth_dst, src_ip, dst_ip, vips, hop_limit=255, pi_flags=0x6): """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): dest Ethernet MAC address. src_ip (ipaddress.IPv6Address): source IPv6 address. vips (list): prefixes (ipaddress.IPv6Address) to advertise. hop_limit (int): IPv6 hop limit. 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, ether.ETH_TYPE_IPV6) ipv6_pkt = ipv6.ipv6(src=src_ip, dst=dst_ip, nxt=inet.IPPROTO_ICMPV6, hop_limit=hop_limit) 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=hop_limit, options=options)) pkt.add_protocol(icmpv6_ra_pkt) pkt.serialize() return pkt
def _send_icmp_NS(self, datapath, outport_no, dst_ip): src_mac_addr = \ str(self.dpid_to_switch[datapath.id].ports[outport_no].hw_addr) src_ip = \ str(self.dpid_to_switch[datapath.id].ports[outport_no].gateway.gw_ipv6) p = packet.Packet() dst_mac, dst_ip_multicast = self._generate_dst_for_NS(dst_ip) dst_mac = str(dst_mac) dst_ip_multicast = str(dst_ip_multicast) dst_ip = str(dst_ip) e = ethernet.ethernet(dst=dst_mac, src=src_mac_addr, ethertype=ether.ETH_TYPE_IPV6) ip6 = ipv6.ipv6( version=6, traffic_class=0, flow_label=0, # 4byte ICMP header, 4byte reserved, 16byte target address, # 8byte "source link-layer address" option # next header value for ICMPv6 is 58 payload_length=32, nxt=58, hop_limit=255, src=src_ip, dst=dst_ip_multicast) # source link-layer address sla_addr = icmpv6.nd_option_sla(hw_src=src_mac_addr) # ns for neighbor solicit; res for reserved, but actually is a flag, # see comments on "nd_option_tla" above ns = icmpv6.nd_neighbor(res=4, dst=dst_ip, data=sla_addr) ic6 = icmpv6.icmpv6( type_=icmpv6.ND_NEIGHBOR_SOLICIT, code=0, # checksum = 0 then ryu calculate for you csum=0, data=ns) p.add_protocol(e) p.add_protocol(ip6) p.add_protocol(ic6) p.serialize() datapath.send_packet_out( in_port=ofproto_v1_0.OFPP_NONE, actions=[datapath.ofproto_parser.OFPActionOutput(outport_no)], data=p.data)
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_to_string(self): nd_opt = icmpv6.nd_option_sla(self.nd_length, self.nd_hw_src) nd = icmpv6.nd_neighbor(self.res, self.dst, nd_opt) ic = icmpv6.icmpv6(self.type_, self.code, self.csum, nd) nd_opt_values = { 'length': self.nd_length, 'hw_src': self.nd_hw_src, 'data': None } _nd_opt_str = ','.join([ '%s=%s' % (k, repr(nd_opt_values[k])) for k, v in inspect.getmembers(nd_opt) if k in nd_opt_values ]) nd_opt_str = '%s(%s)' % (icmpv6.nd_option_sla.__name__, _nd_opt_str) nd_values = { 'res': repr(nd.res), 'dst': repr(self.dst), 'option': nd_opt_str } _nd_str = ','.join([ '%s=%s' % (k, nd_values[k]) for k, v in inspect.getmembers(nd) if k in nd_values ]) nd_str = '%s(%s)' % (icmpv6.nd_neighbor.__name__, _nd_str) icmp_values = { 'type_': repr(self.type_), 'code': repr(self.code), 'csum': repr(self.csum), 'data': nd_str } _ic_str = ','.join([ '%s=%s' % (k, icmp_values[k]) for k, v in inspect.getmembers(ic) if k in icmp_values ]) ic_str = '%s(%s)' % (icmpv6.icmpv6.__name__, _ic_str) eq_(str(ic), ic_str) eq_(repr(ic), ic_str)
def test_serialize_with_data(self): nd_opt = icmpv6.nd_option_sla(self.nd_length, self.nd_hw_src) rs = icmpv6.nd_router_solicit(self.res, nd_opt) prev = ipv6(6, 0, 0, 16, 64, 255, self.src_ipv6, self.dst_ipv6) rs_csum = icmpv6_csum(prev, self.buf + self.data) icmp = icmpv6.icmpv6(self.type_, self.code, 0, rs) buf = buffer(icmp.serialize(bytearray(), prev)) (type_, code, csum) = struct.unpack_from(icmp._PACK_STR, buf, 0) res = struct.unpack_from(rs._PACK_STR, buf, icmp._MIN_LEN) (nd_type, nd_length, nd_hw_src) = struct.unpack_from( nd_opt._PACK_STR, buf, icmp._MIN_LEN + rs._MIN_LEN) data = buf[(icmp._MIN_LEN + rs._MIN_LEN + 8):] eq_(type_, self.type_) eq_(code, self.code) eq_(csum, rs_csum) eq_(res[0], self.res) eq_(nd_type, self.nd_type) eq_(nd_length, self.nd_length) eq_(nd_hw_src, addrconv.mac.text_to_bin(self.nd_hw_src))
def nd_solicit_ip_gw(self, ip_gw, controller_ip, vlan, ports): flowmods = [] if ports: self.logger.info('Resolving %s', ip_gw) nd_mac = self.ipv6_link_eth_mcast(ip_gw) ip_gw_mcast = self.ipv6_link_mcast_from_ucast(ip_gw) port_num = ports[0].number pkt = self.build_ethernet_pkt( nd_mac, port_num, vlan, ether.ETH_TYPE_IPV6) ipv6_pkt = ipv6.ipv6( src=controller_ip.ip, dst=ip_gw_mcast, nxt=inet.IPPROTO_ICMPV6) icmpv6_pkt = icmpv6.icmpv6( type_=icmpv6.ND_NEIGHBOR_SOLICIT, data=icmpv6.nd_neighbor( dst=ip_gw, option=icmpv6.nd_option_sla(hw_src=self.FAUCET_MAC))) pkt.add_protocol(ipv6_pkt) pkt.add_protocol(icmpv6_pkt) pkt.serialize() for port in ports: flowmods.append(self.valve_packetout(port.number, pkt.data)) return flowmods
def test_serialize_with_data(self): nd_opt = icmpv6.nd_option_sla(self.nd_length, self.nd_hw_src) rs = icmpv6.nd_router_solicit(self.res, nd_opt) prev = ipv6(6, 0, 0, 16, 64, 255, self.src_ipv6, self.dst_ipv6) rs_csum = icmpv6_csum(prev, self.buf + self.data) icmp = icmpv6.icmpv6(self.type_, self.code, 0, rs) buf = buffer(icmp.serialize(bytearray(), prev)) (type_, code, csum) = struct.unpack_from(icmp._PACK_STR, buf, 0) res = struct.unpack_from(rs._PACK_STR, buf, icmp._MIN_LEN) (nd_type, nd_length, nd_hw_src) = struct.unpack_from(nd_opt._PACK_STR, buf, icmp._MIN_LEN + rs._MIN_LEN) data = buf[(icmp._MIN_LEN + rs._MIN_LEN + 8):] eq_(type_, self.type_) eq_(code, self.code) eq_(csum, rs_csum) eq_(res[0], self.res) eq_(nd_type, self.nd_type) eq_(nd_length, self.nd_length) eq_(nd_hw_src, addrconv.mac.text_to_bin(self.nd_hw_src))
def test_serialize_with_data(self): nd_opt = icmpv6.nd_option_sla(self.nd_length, self.nd_hw_src) nd = icmpv6.nd_neighbor(self.res, self.dst, nd_opt) prev = ipv6(6, 0, 0, 32, 64, 255, self.src_ipv6, self.dst_ipv6) nd_csum = icmpv6_csum(prev, self.buf + self.data) icmp = icmpv6.icmpv6(self.type_, self.code, 0, nd) buf = buffer(icmp.serialize(bytearray(), prev)) (type_, code, csum) = struct.unpack_from(icmp._PACK_STR, buf, 0) (res, dst) = struct.unpack_from(nd._PACK_STR, buf, icmp._MIN_LEN) (nd_type, nd_length, nd_hw_src) = struct.unpack_from( nd_opt._PACK_STR, buf, icmp._MIN_LEN + nd._MIN_LEN) data = buf[(icmp._MIN_LEN + nd._MIN_LEN + 8):] eq_(type_, self.type_) eq_(code, self.code) eq_(csum, nd_csum) eq_(res >> 29, self.res) eq_(dst, addrconv.ipv6.text_to_bin(self.dst)) eq_(nd_type, self.nd_type) eq_(nd_length, self.nd_length) eq_(nd_hw_src, addrconv.mac.text_to_bin(self.nd_hw_src))
def test_to_string(self): nd_opt = icmpv6.nd_option_sla(self.nd_length, self.nd_hw_src) rs = icmpv6.nd_router_solicit(self.res, nd_opt) ic = icmpv6.icmpv6(self.type_, self.code, self.csum, rs) nd_opt_values = { 'length': self.nd_length, 'hw_src': self.nd_hw_src, 'data': None } _nd_opt_str = ','.join([ '%s=%s' % (k, repr(nd_opt_values[k])) for k, v in inspect.getmembers(nd_opt) if k in nd_opt_values ]) nd_opt_str = '%s(%s)' % (icmpv6.nd_option_sla.__name__, _nd_opt_str) rs_values = {'res': repr(rs.res), 'option': nd_opt_str} _rs_str = ','.join([ '%s=%s' % (k, rs_values[k]) for k, v in inspect.getmembers(rs) if k in rs_values ]) rs_str = '%s(%s)' % (icmpv6.nd_router_solicit.__name__, _rs_str) icmp_values = { 'type_': repr(self.type_), 'code': repr(self.code), 'csum': repr(self.csum), 'data': rs_str } _ic_str = ','.join([ '%s=%s' % (k, icmp_values[k]) for k, v in inspect.getmembers(ic) if k in icmp_values ]) ic_str = '%s(%s)' % (icmpv6.icmpv6.__name__, _ic_str) eq_(str(ic), ic_str) eq_(repr(ic), ic_str)
def __init__(self, mac_src, mac_dst, ipv6_src, ipv6_dst, rou_l, ipv6_options): """ ================ ========================================================= Input Parameter Description ================ ========================================================= mac_src String instance mac_dst String instance ipv6_src String instance ipv6_dst String instance rou_l Int instance ipv6_options Tuple instance: (prefix, prefix_length, valid_lft, preferred_lft) ================ ========================================================= ================ ========================================================= Attribute Description ================ ========================================================= pkt The Neighbor Solicitation generated packet ================ ========================================================= """ self.pkt = packet.Packet() e = ethernet.ethernet(mac_dst, mac_src, ether.ETH_TYPE_IPV6) i6 = ipv6.ipv6(src=ipv6_src, dst=ipv6_dst, nxt=inet.IPPROTO_ICMPV6) # ipv6_options element structure: (prefix, prefix_length, valid_lft, preferred_lft) options = [] for ipv6_opt in ipv6_options: options.append( icmpv6.nd_option_pi(prefix=ipv6_opt[0], pl=ipv6_opt[1], val_l=ipv6_opt[2], pre_l=ipv6_opt[3], res1=2) ) options.append(icmpv6.nd_option_sla(hw_src=mac_src)) ic = icmpv6.icmpv6(type_=icmpv6.ND_ROUTER_ADVERT, data=icmpv6.nd_router_advert(rou_l=rou_l, options=options)) self.pkt.add_protocol(e) self.pkt.add_protocol(i6) self.pkt.add_protocol(ic)
def test_serialize_with_data(self): nd_opt = icmpv6.nd_option_sla(self.nd_length, self.nd_hw_src) nd = icmpv6.nd_neighbor(self.res, self.dst, nd_opt) prev = ipv6(6, 0, 0, 32, 64, 255, self.src_ipv6, self.dst_ipv6) nd_csum = icmpv6_csum(prev, self.buf + self.data) icmp = icmpv6.icmpv6(self.type_, self.code, 0, nd) buf = buffer(icmp.serialize(bytearray(), prev)) (type_, code, csum) = struct.unpack_from(icmp._PACK_STR, buf, 0) (res, dst) = struct.unpack_from(nd._PACK_STR, buf, icmp._MIN_LEN) (nd_type, nd_length, nd_hw_src) = struct.unpack_from(nd_opt._PACK_STR, buf, icmp._MIN_LEN + nd._MIN_LEN) data = buf[(icmp._MIN_LEN + nd._MIN_LEN + 8):] eq_(type_, self.type_) eq_(code, self.code) eq_(csum, nd_csum) eq_(res >> 29, self.res) eq_(dst, addrconv.ipv6.text_to_bin(self.dst)) eq_(nd_type, self.nd_type) eq_(nd_length, self.nd_length) eq_(nd_hw_src, addrconv.mac.text_to_bin(self.nd_hw_src))
def __init__(self, mac_src, mac_dst, ipv6_src, ipv6_dst, rou_l, ipv6_options): """ ================ ========================================================= Input Parameter Description ================ ========================================================= mac_src String instance mac_dst String instance ipv6_src String instance ipv6_dst String instance rou_l Int instance ipv6_options Tuple instance: (prefix, prefix_length, valid_lft, preferred_lft) ================ ========================================================= ================ ========================================================= Attribute Description ================ ========================================================= pkt The Neighbor Solicitation generated packet ================ ========================================================= """ self.pkt = packet.Packet() e = ethernet.ethernet(mac_dst, mac_src, ether.ETH_TYPE_IPV6) i6 = ipv6.ipv6(src = ipv6_src, dst = ipv6_dst, nxt = inet.IPPROTO_ICMPV6) # ipv6_options element structure: (prefix, prefix_length, valid_lft, preferred_lft) options = [] for ipv6_opt in ipv6_options: options.append(icmpv6.nd_option_pi(prefix = ipv6_opt[0], pl = ipv6_opt[1], val_l = ipv6_opt[2], pre_l = ipv6_opt[3], res1 = 2)) options.append(icmpv6.nd_option_sla(hw_src = mac_src)) ic = icmpv6.icmpv6(type_ = icmpv6.ND_ROUTER_ADVERT, data = icmpv6.nd_router_advert(rou_l = rou_l, options = options)) self.pkt.add_protocol(e) self.pkt.add_protocol(i6) self.pkt.add_protocol(ic)
def _send_router_advertisement( self, ipv6_src: str, tun_id: int, output_port, ): """ Generates the Router Advertisement response packet """ ofproto, parser = self._datapath.ofproto, self._datapath.ofproto_parser if not tun_id: self.logger.debug( "Packet missing tunnel-id information, can't reply") return prefix = self.get_custom_prefix(ipv6_src) if not prefix: self.logger.debug("Can't reply to RS for UE ip %s", ipv6_src) return pkt = packet.Packet() pkt.add_protocol( ethernet.ethernet( dst=self.MAC_MULTICAST, src=self.config.ll_addr, ethertype=ether_types.ETH_TYPE_IPV6, ), ) pkt.add_protocol( ipv6.ipv6( dst=ipv6_src, src=self.config.ipv6_src, nxt=in_proto.IPPROTO_ICMPV6, ), ) pkt.add_protocol( icmpv6.icmpv6( type_=icmpv6.ND_ROUTER_ADVERT, data=icmpv6.nd_router_advert( ch_l=MAX_HOP_LIMIT, rou_l=MAX_ROUTE_ADVT_LIFE_TIME, options=[ icmpv6.nd_option_sla(hw_src=self.config.ll_addr, ), icmpv6.nd_option_pi( pl=self.config.prefix_len, prefix=prefix, val_l=MAX_ROUTE_LIFE_TIME, pre_l=MAX_ROUTE_LIFE_TIME, res1=int( hex(ROUTE_PREFIX_HDR_FLAG_L | ROUTE_PREFIX_HDR_FLAG_A), 16), ), ], ), ), ) self.logger.debug("RA pkt response ->") for p in pkt.protocols: self.logger.debug(p) pkt.serialize() actions_out = [ parser.NXActionSetTunnel(tun_id=tun_id), parser.OFPActionOutput(port=output_port), ] out = parser.OFPPacketOut( datapath=self._datapath, buffer_id=ofproto.OFP_NO_BUFFER, in_port=ofproto.OFPP_CONTROLLER, actions=actions_out, data=pkt.data, ) ret = self._datapath.send_msg(out) if not ret: self.logger.error("Datapath disconnected, couldn't send RA")
def test_default_args(self): prev = ipv6(nxt=inet.IPPROTO_ICMPV6) ic = icmpv6.icmpv6(type_=icmpv6.ND_ROUTER_ADVERT, data=icmpv6.nd_router_advert()) prev.serialize(ic, None) buf = ic.serialize(bytearray(), prev) res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) eq_(res[0], icmpv6.ND_ROUTER_ADVERT) eq_(res[1], 0) eq_(res[2], icmpv6_csum(prev, buf)) res = struct.unpack(icmpv6.nd_router_advert._PACK_STR, str(buf[4:])) eq_(res[0], 0) eq_(res[1], 0) eq_(res[2], 0) eq_(res[3], 0) eq_(res[4], 0) # with nd_option_sla prev = ipv6(nxt=inet.IPPROTO_ICMPV6) ic = icmpv6.icmpv6( type_=icmpv6.ND_ROUTER_ADVERT, data=icmpv6.nd_router_advert(options=[icmpv6.nd_option_sla()])) prev.serialize(ic, None) buf = ic.serialize(bytearray(), prev) res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) eq_(res[0], icmpv6.ND_ROUTER_ADVERT) eq_(res[1], 0) eq_(res[2], icmpv6_csum(prev, buf)) res = struct.unpack(icmpv6.nd_router_advert._PACK_STR, str(buf[4:16])) eq_(res[0], 0) eq_(res[1], 0) eq_(res[2], 0) eq_(res[3], 0) eq_(res[4], 0) res = struct.unpack(icmpv6.nd_option_sla._PACK_STR, str(buf[16:])) eq_(res[0], icmpv6.ND_OPTION_SLA) eq_(res[1], len(icmpv6.nd_option_sla()) / 8) eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00')) # with nd_option_pi prev = ipv6(nxt=inet.IPPROTO_ICMPV6) ic = icmpv6.icmpv6( type_=icmpv6.ND_ROUTER_ADVERT, data=icmpv6.nd_router_advert(options=[icmpv6.nd_option_pi()])) prev.serialize(ic, None) buf = ic.serialize(bytearray(), prev) res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) eq_(res[0], icmpv6.ND_ROUTER_ADVERT) eq_(res[1], 0) eq_(res[2], icmpv6_csum(prev, buf)) res = struct.unpack(icmpv6.nd_router_advert._PACK_STR, str(buf[4:16])) eq_(res[0], 0) eq_(res[1], 0) eq_(res[2], 0) eq_(res[3], 0) eq_(res[4], 0) res = struct.unpack(icmpv6.nd_option_pi._PACK_STR, str(buf[16:])) eq_(res[0], icmpv6.ND_OPTION_PI) eq_(res[1], 4) eq_(res[2], 0) eq_(res[3], 0) eq_(res[4], 0) eq_(res[5], 0) eq_(res[6], 0) eq_(res[7], addrconv.ipv6.text_to_bin('::')) # with nd_option_sla and nd_option_pi prev = ipv6(nxt=inet.IPPROTO_ICMPV6) ic = icmpv6.icmpv6( type_=icmpv6.ND_ROUTER_ADVERT, data=icmpv6.nd_router_advert( options=[icmpv6.nd_option_sla(), icmpv6.nd_option_pi()])) prev.serialize(ic, None) buf = ic.serialize(bytearray(), prev) res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) eq_(res[0], icmpv6.ND_ROUTER_ADVERT) eq_(res[1], 0) eq_(res[2], icmpv6_csum(prev, buf)) res = struct.unpack(icmpv6.nd_router_advert._PACK_STR, str(buf[4:16])) eq_(res[0], 0) eq_(res[1], 0) eq_(res[2], 0) eq_(res[3], 0) eq_(res[4], 0) res = struct.unpack(icmpv6.nd_option_sla._PACK_STR, str(buf[16:24])) eq_(res[0], icmpv6.ND_OPTION_SLA) eq_(res[1], len(icmpv6.nd_option_sla()) / 8) eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00')) res = struct.unpack(icmpv6.nd_option_pi._PACK_STR, str(buf[24:])) eq_(res[0], icmpv6.ND_OPTION_PI) eq_(res[1], len(icmpv6.nd_option_pi()) / 8) eq_(res[2], 0) eq_(res[3], 0) eq_(res[4], 0) eq_(res[5], 0) eq_(res[6], 0) eq_(res[7], addrconv.ipv6.text_to_bin('::'))
def test_default_args(self): prev = ipv6(nxt=inet.IPPROTO_ICMPV6) ic = icmpv6.icmpv6( type_=icmpv6.ND_ROUTER_ADVERT, data=icmpv6.nd_router_advert()) prev.serialize(ic, None) buf = ic.serialize(bytearray(), prev) res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) eq_(res[0], icmpv6.ND_ROUTER_ADVERT) eq_(res[1], 0) eq_(res[2], icmpv6_csum(prev, buf)) res = struct.unpack(icmpv6.nd_router_advert._PACK_STR, str(buf[4:])) eq_(res[0], 0) eq_(res[1], 0) eq_(res[2], 0) eq_(res[3], 0) eq_(res[4], 0) # with nd_option_sla prev = ipv6(nxt=inet.IPPROTO_ICMPV6) ic = icmpv6.icmpv6( type_=icmpv6.ND_ROUTER_ADVERT, data=icmpv6.nd_router_advert( options=[icmpv6.nd_option_sla()])) prev.serialize(ic, None) buf = ic.serialize(bytearray(), prev) res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) eq_(res[0], icmpv6.ND_ROUTER_ADVERT) eq_(res[1], 0) eq_(res[2], icmpv6_csum(prev, buf)) res = struct.unpack(icmpv6.nd_router_advert._PACK_STR, str(buf[4:16])) eq_(res[0], 0) eq_(res[1], 0) eq_(res[2], 0) eq_(res[3], 0) eq_(res[4], 0) res = struct.unpack(icmpv6.nd_option_sla._PACK_STR, str(buf[16:])) eq_(res[0], icmpv6.ND_OPTION_SLA) eq_(res[1], len(icmpv6.nd_option_sla()) / 8) eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00')) # with nd_option_pi prev = ipv6(nxt=inet.IPPROTO_ICMPV6) ic = icmpv6.icmpv6( type_=icmpv6.ND_ROUTER_ADVERT, data=icmpv6.nd_router_advert( options=[icmpv6.nd_option_pi()])) prev.serialize(ic, None) buf = ic.serialize(bytearray(), prev) res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) eq_(res[0], icmpv6.ND_ROUTER_ADVERT) eq_(res[1], 0) eq_(res[2], icmpv6_csum(prev, buf)) res = struct.unpack(icmpv6.nd_router_advert._PACK_STR, str(buf[4:16])) eq_(res[0], 0) eq_(res[1], 0) eq_(res[2], 0) eq_(res[3], 0) eq_(res[4], 0) res = struct.unpack(icmpv6.nd_option_pi._PACK_STR, str(buf[16:])) eq_(res[0], icmpv6.ND_OPTION_PI) eq_(res[1], 4) eq_(res[2], 0) eq_(res[3], 0) eq_(res[4], 0) eq_(res[5], 0) eq_(res[6], 0) eq_(res[7], addrconv.ipv6.text_to_bin('::')) # with nd_option_sla and nd_option_pi prev = ipv6(nxt=inet.IPPROTO_ICMPV6) ic = icmpv6.icmpv6( type_=icmpv6.ND_ROUTER_ADVERT, data=icmpv6.nd_router_advert( options=[icmpv6.nd_option_sla(), icmpv6.nd_option_pi()])) prev.serialize(ic, None) buf = ic.serialize(bytearray(), prev) res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) eq_(res[0], icmpv6.ND_ROUTER_ADVERT) eq_(res[1], 0) eq_(res[2], icmpv6_csum(prev, buf)) res = struct.unpack(icmpv6.nd_router_advert._PACK_STR, str(buf[4:16])) eq_(res[0], 0) eq_(res[1], 0) eq_(res[2], 0) eq_(res[3], 0) eq_(res[4], 0) res = struct.unpack(icmpv6.nd_option_sla._PACK_STR, str(buf[16:24])) eq_(res[0], icmpv6.ND_OPTION_SLA) eq_(res[1], len(icmpv6.nd_option_sla()) / 8) eq_(res[2], addrconv.mac.text_to_bin('00:00:00:00:00:00')) res = struct.unpack(icmpv6.nd_option_pi._PACK_STR, str(buf[24:])) eq_(res[0], icmpv6.ND_OPTION_PI) eq_(res[1], len(icmpv6.nd_option_pi()) / 8) eq_(res[2], 0) eq_(res[3], 0) eq_(res[4], 0) eq_(res[5], 0) eq_(res[6], 0) eq_(res[7], addrconv.ipv6.text_to_bin('::'))