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 icmpv6_echo_reply(eth_src, eth_dst, vid, src_ip, dst_ip, hop_limit, id_, seq, data): """Return IPv6 ICMP echo reply packet. Args: eth_src (str): source Ethernet MAC address. eth_dst (str): destination Ethernet MAC address. vid (int or None): VLAN VID to use (or None). src_ip (ipaddr.IPv6Address): source IPv6 address. dst_ip (ipaddr.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( eth_src, eth_dst, vid, ether.ETH_TYPE_IPV6) ipv6_reply = ipv6.ipv6( src=src_ip, dst=dst_ip, nxt=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 test_to_string(self): ec = icmpv6.echo(self.id_, self.seq, self.data) ic = icmpv6.icmpv6(self.type_, self.code, self.csum, ec) echo_values = {'id': self.id_, 'seq': self.seq, 'data': self.data} _echo_str = ','.join([ '%s=%s' % (k, repr(echo_values[k])) for k, v in inspect.getmembers(ec) if k in echo_values ]) echo_str = '%s(%s)' % (icmpv6.echo.__name__, _echo_str) icmp_values = { 'type_': repr(self.type_), 'code': repr(self.code), 'csum': repr(self.csum), 'data': echo_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 control_plane_icmpv6_handler(self, in_port, vlan, eth_src, ipv6_pkt, icmpv6_pkt): flowmods = [] pkt = self.build_ethernet_pkt( eth_src, in_port, vlan, ether.ETH_TYPE_IPV6) if icmpv6_pkt.type_ == icmpv6.ND_NEIGHBOR_SOLICIT: dst = icmpv6_pkt.data.dst ipv6_reply = ipv6.ipv6( src=dst, dst=ipv6_pkt.src, nxt=inet.IPPROTO_ICMPV6, hop_limit=ipv6_pkt.hop_limit) pkt.add_protocol(ipv6_reply) icmpv6_reply = icmpv6.icmpv6( type_=icmpv6.ND_NEIGHBOR_ADVERT, data=icmpv6.nd_neighbor( dst=dst, option=icmpv6.nd_option_tla(hw_src=self.FAUCET_MAC), res=7)) pkt.add_protocol(icmpv6_reply) pkt.serialize() flowmods.extend([self.valve_packetout(in_port, pkt.data)]) elif icmpv6_pkt.type_ == icmpv6.ND_NEIGHBOR_ADVERT: resolved_ip_gw = ipaddr.IPv6Address(icmpv6_pkt.data.dst) self.logger.info('ND response %s for %s', eth_src, resolved_ip_gw) is_updated = None if resolved_ip_gw in vlan.nd_cache: cached_eth_dst = vlan.nd_cache[resolved_ip_gw].eth_src if cached_eth_dst != eth_src: is_updated = True else: is_updated = False for ip_dst, ip_gw in vlan.ipv6_routes.iteritems(): if ip_gw == resolved_ip_gw: flowmods.extend( self.add_resolved_route( ether.ETH_TYPE_IPV6, vlan, vlan.nd_cache, ip_gw, ip_dst, eth_src,is_updated)) elif icmpv6_pkt.type_ == icmpv6.ICMPV6_ECHO_REQUEST: dst = ipv6_pkt.dst ipv6_reply = ipv6.ipv6( src=dst, dst=ipv6_pkt.src, nxt=inet.IPPROTO_ICMPV6, hop_limit=ipv6_pkt.hop_limit) pkt.add_protocol(ipv6_reply) icmpv6_reply = icmpv6.icmpv6( type_=icmpv6.ICMPV6_ECHO_REPLY, data=icmpv6.echo( id_=icmpv6_pkt.data.id, seq=icmpv6_pkt.data.seq, data=icmpv6_pkt.data.data)) pkt.add_protocol(icmpv6_reply) pkt.serialize() flowmods.extend([self.valve_packetout(in_port, pkt.data)]) return flowmods
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 control_plane_icmpv6_handler(self, in_port, vlan, eth_src, ipv6_pkt, icmpv6_pkt): flowmods = [] pkt = self.build_ethernet_pkt( eth_src, in_port, vlan, ether.ETH_TYPE_IPV6) if icmpv6_pkt.type_ == icmpv6.ND_NEIGHBOR_SOLICIT: dst = icmpv6_pkt.data.dst ipv6_reply = ipv6.ipv6( src=dst, dst=ipv6_pkt.src, nxt=inet.IPPROTO_ICMPV6, hop_limit=ipv6_pkt.hop_limit) pkt.add_protocol(ipv6_reply) icmpv6_reply = icmpv6.icmpv6( type_=icmpv6.ND_NEIGHBOR_ADVERT, data=icmpv6.nd_neighbor( dst=dst, option=icmpv6.nd_option_tla(hw_src=self.FAUCET_MAC), res=7)) pkt.add_protocol(icmpv6_reply) pkt.serialize() flowmods.extend([self.valve_packetout(in_port, pkt.data)]) elif icmpv6_pkt.type_ == icmpv6.ND_NEIGHBOR_ADVERT: resolved_ip_gw = ipaddr.IPv6Address(icmpv6_pkt.data.dst) for ip_dst, ip_gw in vlan.ipv6_routes.iteritems(): if ip_gw == resolved_ip_gw: self.logger.info('ND response %s for %s', eth_src, resolved_ip_gw) flowmods.extend( self.add_resolved_route( ether.ETH_TYPE_IPV6, vlan, vlan.nd_cache, ip_gw, ip_dst, eth_src)) elif icmpv6_pkt.type_ == icmpv6.ICMPV6_ECHO_REQUEST: dst = ipv6_pkt.dst ipv6_reply = ipv6.ipv6( src=dst, dst=ipv6_pkt.src, nxt=inet.IPPROTO_ICMPV6, hop_limit=ipv6_pkt.hop_limit) pkt.add_protocol(ipv6_reply) icmpv6_reply = icmpv6.icmpv6( type_=icmpv6.ICMPV6_ECHO_REPLY, data=icmpv6.echo( id_=icmpv6_pkt.data.id, seq=icmpv6_pkt.data.seq, data=icmpv6_pkt.data.data)) pkt.add_protocol(icmpv6_reply) pkt.serialize() flowmods.extend([self.valve_packetout(in_port, pkt.data)]) return flowmods
def ping_connected_hosts(self, datapath, wan_port): """ This function will send an ICMPv6 ECHO REQUEST message to all the nodes of protected network. That will in turn, trigger a Neighbor Solicitation message to be received and the IPv6 destination address, will be the randomly generated LLU address of Janus. :param datapath: The datapath (represents the device used as a traffic normaliser (Janus)) :param wan_port: The port to send a message from. Use this as the in_port, to exclude from multicast """ # Construct L2 header src_mac = generate_random_mac( ) # Generated randomly (can be seen that it is not factory default) dst_mac = '33:33:ff:ff:ff:ff' # This is a multicast L2 address self.temporary_mac_id = "33:33:ff" + src_mac[-9:] layer2 = ethernet.ethernet(dst=dst_mac, src=src_mac, ethertype=ether_types.ETH_TYPE_IPV6) # Construct L3 header ip6_dst = 'ff02::1' # well known multicast L3 address, as defined by IANA ip6_src = generate_llu_ipv6(src_mac) # IPv6 Link Local Unicast address layer3 = ipv6.ipv6(nxt=inet.IPPROTO_ICMPV6, src=ip6_src, dst=ip6_dst) # Construct l4 header icmpv6_type = icmpv6.ICMPV6_ECHO_REQUEST layer4 = icmpv6.icmpv6(type_=icmpv6_type, code=0, csum=0, data=icmpv6.echo()) # Create packet pkt = packet.Packet() # layer 1 is automatically generated when packet.serialize() is called pkt.add_protocol(layer2) pkt.add_protocol(layer3) pkt.add_protocol(layer4) # Send packet to multicast addresses in protected network ofproto = datapath.ofproto parser = datapath.ofproto_parser pkt.serialize() data = pkt.data actions = [parser.OFPActionOutput(ofproto.OFPP_FLOOD)] out = parser.OFPPacketOut(datapath=datapath, buffer_id=ofproto.OFP_NO_BUFFER, actions=actions, data=data, in_port=wan_port) datapath.send_msg(out)
def test_default_args(self): prev = ipv6(nxt=inet.IPPROTO_ICMPV6) ic = icmpv6.icmpv6(type_=icmpv6.ICMPV6_ECHO_REPLY, data=icmpv6.echo()) prev.serialize(ic, None) buf = ic.serialize(bytearray(), prev) res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) eq_(res[0], icmpv6.ICMPV6_ECHO_REPLY) eq_(res[1], 0) eq_(res[2], icmpv6_csum(prev, buf)) res = struct.unpack(icmpv6.echo._PACK_STR, str(buf[4:])) eq_(res[0], 0) eq_(res[1], 0)
def test_default_args(self): prev = ipv6(nxt=inet.IPPROTO_ICMPV6) ic = icmpv6.icmpv6( type_=icmpv6.ICMPV6_ECHO_REPLY, data=icmpv6.echo()) prev.serialize(ic, None) buf = ic.serialize(bytearray(), prev) res = struct.unpack(icmpv6.icmpv6._PACK_STR, str(buf[:4])) eq_(res[0], icmpv6.ICMPV6_ECHO_REPLY) eq_(res[1], 0) eq_(res[2], icmpv6_csum(prev, buf)) res = struct.unpack(icmpv6.echo._PACK_STR, str(buf[4:])) eq_(res[0], 0) eq_(res[1], 0)
def _test_serialize(self, echo_data=None): buf = self.buf + str(echo_data or "") src_ipv6 = netaddr.IPAddress("3ffe:507:0:1:200:86ff:fe05:80da").packed dst_ipv6 = netaddr.IPAddress("3ffe:501:0:1001::2").packed prev = ipv6(6, 0, 0, len(buf), 64, 255, src_ipv6, dst_ipv6) echo_csum = icmpv6_csum(prev, buf) echo = icmpv6.echo(self.id_, self.seq, echo_data) icmp = icmpv6.icmpv6(self.type_, self.code, 0, echo) buf = buffer(icmp.serialize(bytearray(), prev)) (type_, code, csum) = struct.unpack_from(icmp._PACK_STR, buf, 0) (id_, seq) = struct.unpack_from(echo._PACK_STR, buf, icmp._MIN_LEN) data = buf[(icmp._MIN_LEN + echo._MIN_LEN) :] data = data if len(data) != 0 else None eq_(type_, self.type_) eq_(code, self.code) eq_(csum, echo_csum) eq_(id_, self.id_) eq_(seq, self.seq) eq_(data, echo_data)
def _test_serialize(self, echo_data=None): buf = self.buf + str(echo_data or '') src_ipv6 = netaddr.IPAddress('3ffe:507:0:1:200:86ff:fe05:80da').packed dst_ipv6 = netaddr.IPAddress('3ffe:501:0:1001::2').packed prev = ipv6(6, 0, 0, len(buf), 64, 255, src_ipv6, dst_ipv6) echo_csum = icmpv6_csum(prev, buf) echo = icmpv6.echo(self.id_, self.seq, echo_data) icmp = icmpv6.icmpv6(self.type_, self.code, 0, echo) buf = buffer(icmp.serialize(bytearray(), prev)) (type_, code, csum) = struct.unpack_from(icmp._PACK_STR, buf, 0) (id_, seq) = struct.unpack_from(echo._PACK_STR, buf, icmp._MIN_LEN) data = buf[(icmp._MIN_LEN + echo._MIN_LEN):] data = data if len(data) != 0 else None eq_(type_, self.type_) eq_(code, self.code) eq_(csum, echo_csum) eq_(id_, self.id_) eq_(seq, self.seq) eq_(data, echo_data)
def test_to_string(self): ec = icmpv6.echo(self.id_, self.seq, self.data) ic = icmpv6.icmpv6(self.type_, self.code, self.csum, ec) echo_values = {'id': self.id_, 'seq': self.seq, 'data': self.data} _echo_str = ','.join(['%s=%s' % (k, repr(echo_values[k])) for k, v in inspect.getmembers(ec) if k in echo_values]) echo_str = '%s(%s)' % (icmpv6.echo.__name__, _echo_str) icmp_values = {'type_': repr(self.type_), 'code': repr(self.code), 'csum': repr(self.csum), 'data': echo_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_init(self): echo = icmpv6.echo(0, 0) eq_(echo.id, 0) eq_(echo.seq, 0) eq_(echo.data, None)