def create_and_verify_traffic(topology, tx_host, rx_host, src_ip, src_port,
                              dst_ip, dst_port, proto_str, filter_str,
                              tx_count, rx_expect):
    assert topology is not None
    assert tx_host is not None
    assert rx_host is not None
    assert isinstance(src_ip, str)
    assert isinstance(dst_ip, str)
    assert isinstance(src_port, str)
    assert isinstance(dst_port, str)
    assert isinstance(proto_str, str) and \
        proto_str in ('IP/UDP', 'IP/ICMP')

    # The filter_str is expected to be a string.  Below is an example for a
    # UDP packet:
    # filter_udp = "lambda p: UDP in p and p[UDP].dport == 48621 and " \
    #   "p[IP].src == '1.1.1.1' and p[IP].dst == '1.1.1.2'"
    assert isinstance(filter_str, str)
    assert isinstance(tx_count, int)
    assert isinstance(rx_expect, bool)

    ip_packet = tx_host.libs.scapy.ip("dst='%s', src='%s'" % (dst_ip, src_ip))

    if proto_str == 'IP/UDP':
        proto_packet = tx_host.libs.scapy.udp()
        if dst_port != '':
            proto_packet['dport'] = int(dst_port)
        if src_port != '':
            proto_packet['sport'] = int(src_port)
        result_index = 1
    elif proto_str == 'IP/ICMP':
        proto_packet = tx_host.libs.scapy.icmp()
        result_index = 2
    else:
        assert False

    list1 = [ip_packet, proto_packet]
    port_str = '1'
    timeout = 25

    txthread = ScapyThread(send_traffic, tx_host.identifier, topology,
                           proto_str, list1, '', tx_count, '', 0)

    rxthread = ScapyThread(sniff_traffic, rx_host.identifier, topology, '', [],
                           filter_str, tx_count, port_str, timeout)

    rxthread.start()
    txthread.start()

    txthread.join()
    rxthread.join()

    if rxthread.outresult():
        rest, sniffcnt = rxthread.outresult().split('<Sniffed:')
        list_result = findall(r'[0-9]+', sniffcnt)

        assert (rx_expect == (list_result[result_index] == str(tx_count)))
    else:
        assert False
def create_and_verify_traffic(
    topology, tx_host, rx_host, src_ip, src_port, dst_ip, dst_port, proto_str, filter_str, tx_count, rx_expect
):
    assert topology is not None
    assert tx_host is not None
    assert rx_host is not None
    assert isinstance(src_ip, str)
    assert isinstance(dst_ip, str)
    assert isinstance(src_port, str)
    assert isinstance(dst_port, str)
    assert isinstance(proto_str, str) and proto_str in ("IP/UDP", "IP/ICMP")

    # The filter_str is expected to be a string.  Below is an example for a
    # UDP packet:
    # filter_udp = "lambda p: UDP in p and p[UDP].dport == 48621 and " \
    #   "p[IP].src == '1.1.1.1' and p[IP].dst == '1.1.1.2'"
    assert isinstance(filter_str, str)
    assert isinstance(tx_count, int)
    assert isinstance(rx_expect, bool)

    ip_packet = tx_host.libs.scapy.ip("dst='%s', src='%s'" % (dst_ip, src_ip))

    if proto_str == "IP/UDP":
        proto_packet = tx_host.libs.scapy.udp()
        if dst_port != "":
            proto_packet["dport"] = int(dst_port)
        if src_port != "":
            proto_packet["sport"] = int(src_port)
        result_index = 1
    elif proto_str == "IP/ICMP":
        proto_packet = tx_host.libs.scapy.icmp()
        result_index = 2
    else:
        assert False

    list1 = [ip_packet, proto_packet]
    port_str = "1"
    timeout = 25

    txthread = ScapyThread(send_traffic, tx_host.identifier, topology, proto_str, list1, "", tx_count, "", 0)

    rxthread = ScapyThread(sniff_traffic, rx_host.identifier, topology, "", [], filter_str, tx_count, port_str, timeout)

    rxthread.start()
    txthread.start()

    txthread.join()
    rxthread.join()

    if rxthread.outresult():
        rest, sniffcnt = rxthread.outresult().split("<Sniffed:")
        list_result = findall(r"[0-9]+", sniffcnt)

        assert rx_expect == (list_result[result_index] == str(tx_count))
    else:
        assert False
def acl_permit_icmp_on_multiple_ports(ops1, hs1, hs2, topology, step):
    """
    This test sends ICMP traffic from hs1 to hs2 after applying a permit
    ACL to interface 1. After it verifies that hs2 receives 10 packets,
    it sends traffic in the reverse direction and verifies that traffic
    behavior complies with the applied permit ACL
    """
    with ops1.libs.vtysh.ConfigAccessListIpTestname('test12') as ctx:
        ctx.permit(
            '', '11', 'icmp', '10.0.10.1', '',
            '10.0.10.2', '')

    test1_result = ops1('show run')

    assert search(
       ''
       r'11\s+permit\s+icmp\s+10\.0\.10\.1'
       '\s+10\.0\.10\.2'.format(
                                         **locals()
                                       ), test1_result
    )

    with ops1.libs.vtysh.ConfigInterface('1') as ctx:
        ctx.apply_access_list_ip_in('test12')

    test1_result = ops1('show run')

    assert search(
        r'(access-list\s+ip\s+test12\s+\in)'.format(
                                          **locals()
                                        ), test1_result
    )

    with ops1.libs.vtysh.ConfigAccessListIpTestname('test12') as ctx:
        ctx.permit(
            '', '12', 'icmp', '10.0.10.2', '',
            '10.0.10.1', '')

    test1_result = ops1('show run')

    assert search(
       ''
       r'12\s+permit\s+icmp\s+10\.0\.10\.2'
       '\s+10\.0\.10\.1'.format(
                                         **locals()
                                       ), test1_result
    )

    with ops1.libs.vtysh.ConfigInterface('2') as ctx:
        ctx.apply_access_list_ip_in('test12')

    test1_result = ops1('show run')

    assert search(
        r'(access-list\s+ip\s+test12\s+\in)'.format(
                                          **locals()
                                        ), test1_result
    )

    step('Create packets')
    ip_packet = hs1.libs.scapy.ip("dst='10.0.10.2', src='10.0.10.1'")
    icmp_packet = hs1.libs.scapy.icmp()

    list1 = [ip_packet, icmp_packet]
    proto_str = 'IP/ICMP'
    filter_str = 'icmp and ip src 10.0.10.1 and ip dst 10.0.10.2'
    port_str = '1'
    timeout = 25
    count = 10

    txthread = ScapyThread(
                send_traffic,
                'hs1', topology, proto_str, list1, '', count, '', 0)

    rxthread = ScapyThread(
                sniff_traffic,
                'hs2', topology, '', [], filter_str, count, port_str, timeout)

    rxthread.start()
    txthread.start()

    txthread.join()
    rxthread.join()

    if rxthread.outresult():
        rest, sniffcnt = rxthread.outresult().split('<Sniffed:')
        list_result = findall(r'[0-9]+', sniffcnt)

        assert (list_result[2] == '10')

    step('Create packets')
    ip_packet = hs2.libs.scapy.ip("dst='10.0.10.1', src='10.0.10.2'")
    icmp_packet = hs2.libs.scapy.icmp()
    filter_str = 'icmp and ip src 10.0.10.2 and ip dst 10.0.10.1'

    list1 = [ip_packet, icmp_packet]
    proto_str = 'IP/ICMP'
    port_str = '1'
    timeout = 25
    count = 10

    txthread = ScapyThread(
                send_traffic,
                'hs2', topology, proto_str, list1, '', count, '', 0)

    rxthread = ScapyThread(
                sniff_traffic,
                'hs1', topology, '', [], filter_str, count, port_str, timeout)

    rxthread.start()
    txthread.start()

    txthread.join()
    rxthread.join()

    if rxthread.outresult():
        rest, sniffcnt = rxthread.outresult().split('<Sniffed:')
        list_result = findall(r'[0-9]+', sniffcnt)

        assert (list_result[2] == '10')

    with ops1.libs.vtysh.ConfigAccessListIpTestname('test12') as ctx:
        ctx.no('12')

    with ops1.libs.vtysh.ConfigAccessListIpTestname('test12') as ctx:
        ctx.no('11')

    with ops1.libs.vtysh.Configure() as ctx:
        ctx.no_access_list_ip('test12')

    test1_result = ops1('show run')

    assert search(
         r'(?!access-list\s+ip\s+test12\s+)'.format(
                                         **locals()
                                     ), test1_result
    )
def acl_deny_icmp_prefix_len_mask(ops1, hs1, hs2, topology, step):
    """
    This test adds a "10 deny icmp 10.0.10.0/30 10.0.10.0/30" rule
    on interface 1. It then passes 10 ICMP packets from hs1 to hs2
    and verifies that 10 ICMP packets are not received on hs2.
    """
    with ops1.libs.vtysh.ConfigAccessListIpTestname('test10') as ctx:
        ctx.deny(
            '', '10', 'icmp', '10.0.10.0/30', '',
            '10.0.10.0/30', '')

    test1_result = ops1('show run')

    assert search(
       ''
       r'10\s+deny\s+icmp\s+10\.0\.10\.0/255\.255\.255\.252'
       '\s+10\.0\.10\.0/255\.255\.255\.252'.format(
                                         **locals()
                                       ), test1_result
    )

    with ops1.libs.vtysh.ConfigInterface('1') as ctx:
        ctx.apply_access_list_ip_in('test10')

    test1_result = ops1('show run')

    assert search(
        r'(access-list\s+ip\s+test10\s+\in)'.format(
                                          **locals()
                                        ), test1_result
    )

    step('Create packets')
    ip_packet = hs1.libs.scapy.ip("dst='10.0.10.2', src='10.0.10.1'")
    icmp_packet = hs1.libs.scapy.icmp()

    list1 = [ip_packet, icmp_packet]
    proto_str = 'IP/ICMP'
    filter_str = 'icmp and ip src 10.0.10.1 and ip dst 10.0.10.2'
    port_str = '1'
    timeout = 25
    count = 10

    txthread = ScapyThread(
                send_traffic,
                'hs1', topology, proto_str, list1, '', count, '', 0)

    rxthread = ScapyThread(
                sniff_traffic,
                'hs2', topology, '', [], filter_str, count, port_str, timeout)

    rxthread.start()
    txthread.start()

    txthread.join()
    rxthread.join()

    if rxthread.outresult():
        rest, sniffcnt = rxthread.outresult().split('<Sniffed:')
        list_result = findall(r'[0-9]+', sniffcnt)

        assert (list_result[2] == '0')

        assert search(
                ''
                r'(?!ICMP\s+10\.0\.10\.1\s+\>\s+10\.0\.10\.2)'.format(
                                 **locals()
                               ), rxthread.outresult()
            )

    with ops1.libs.vtysh.ConfigAccessListIpTestname('test10') as ctx:
        ctx.no('10')

    with ops1.libs.vtysh.Configure() as ctx:
        ctx.no_access_list_ip('test10')

    test1_result = ops1('show run')

    assert search(
         r'(?!access-list\s+ip\s+test10\s+)'.format(
                                         **locals()
                                     ), test1_result
    )
def acl_permit_icmp_non_contiguous_mask_neg(ops1, hs1, hs2, topology, step):
    """
    This test adds a "8 permit icmp 10.0.10.0/255.0.255.252
    10.0.10.2" rule on interface 1.
    It then sends 10 ICMP packets from hs1, which lies outside
    the permitted network, to hs2 and verifies that
    10 ICMP packets are not received on hs2.
    """
    with ops1.libs.vtysh.ConfigAccessListIpTestname('test8') as ctx:
        ctx.permit(
            '', '8', 'icmp', '10.0.10.0/255.0.255.252', '',
            '10.0.10.2', '')

    test1_result = ops1('show run')

    assert search(
       ''
       r'8\s+permit\s+icmp\s+10\.0\.10\.0/255\.0\.255\.252'
       '\s+10\.0\.10\.2'.format(
                                         **locals()
                                       ), test1_result
    )

    with ops1.libs.vtysh.ConfigInterface('1') as ctx:
        ctx.apply_access_list_ip_in('test8')

    test1_result = ops1('show run')

    assert search(
        r'(access-list\s+ip\s+test8\s+\in)'.format(
                                          **locals()
                                        ), test1_result
    )

    step('Create packets')
    ip_packet = hs1.libs.scapy.ip("dst='10.0.10.2', src='10.0.10.5'")
    icmp_packet = hs1.libs.scapy.icmp()
    filter_str = 'icmp and ip src 10.0.10.5 and ip dst 10.0.10.2'

    list1 = [ip_packet, icmp_packet]
    proto_str = 'IP/ICMP'
    port_str = '1'
    timeout = 25
    count = 10

    txthread = ScapyThread(
                send_traffic,
                'hs1', topology, proto_str, list1, '', count, '', 0)

    rxthread = ScapyThread(
                sniff_traffic,
                'hs2', topology, '', [], filter_str, count, port_str, timeout)

    rxthread.start()
    txthread.start()

    txthread.join()
    rxthread.join()
    if rxthread.outresult():
        rest, sniffcnt = rxthread.outresult().split('<Sniffed:')
        list_result = findall(r'[0-9]+', sniffcnt)
        assert (list_result[2] == '0')

    with ops1.libs.vtysh.ConfigAccessListIpTestname('test8') as ctx:
        ctx.no('8')

    with ops1.libs.vtysh.Configure() as ctx:
        ctx.no_access_list_ip('test8')

    test1_result = ops1('show run')

    assert search(
         r'(?!access-list\s+ip\s+test8\s+)'.format(
                                         **locals()
                                     ), test1_result
    )
def acl_permit_proto_1_hs1_hs2(ops1, hs1, hs2, topology, step):
    """
    This test adds a "6 permit 1 any any" rule on interface 1.
    It then sends 10 ICMP packets from hs1 to hs2 and verifies that
    10 ICMP packets are received on hs2.
    """
    with ops1.libs.vtysh.ConfigAccessListIpTestname('test6') as ctx:
        ctx.permit('', '6', '1', 'any', '', 'any', '')

    test1_result = ops1('show run')

    assert search(
       ''
       r'6\s+permit\s+icmp\s+any'
       '\s+any'.format(
                                         **locals()
                                       ), test1_result
    )

    with ops1.libs.vtysh.ConfigInterface('1') as ctx:
        ctx.apply_access_list_ip_in('test6')

    test1_result = ops1('show run')

    assert search(
        r'(access-list\s+ip\s+test6\s+\in)'.format(
                                          **locals()
                                        ), test1_result
    )

    step('Create packets')
    ip_packet = hs1.libs.scapy.ip("dst='10.0.10.2', src='10.0.10.1'")
    icmp_packet = hs1.libs.scapy.icmp()
    filter_str = 'icmp and ip src 10.0.10.1 and ip dst 10.0.10.2'

    list1 = [ip_packet, icmp_packet]
    proto_str = 'IP/ICMP'
    port_str = '1'
    timeout = 25
    count = 10

    txthread = ScapyThread(
                send_traffic,
                'hs1', topology, proto_str, list1, '', count, '', 0)

    rxthread = ScapyThread(
                sniff_traffic,
                'hs2', topology, '', [], filter_str, count, port_str, timeout)

    rxthread.start()
    txthread.start()

    txthread.join()
    rxthread.join()

    if rxthread.outresult():
        rest, sniffcnt = rxthread.outresult().split('<Sniffed:')
        list_result = findall(r'[0-9]+', sniffcnt)
        assert (list_result[2] == '10')

    with ops1.libs.vtysh.ConfigAccessListIpTestname('test6') as ctx:
        ctx.no('6')

    with ops1.libs.vtysh.Configure() as ctx:
        ctx.no_access_list_ip('test6')

    test1_result = ops1('show run')

    assert search(
         r'(?!access-list\s+ip\s+test6\s+)'.format(
                                         **locals()
                                     ), test1_result
    )
def acl_permit_icmp_on_multiple_ports(ops1, hs1, hs2, topology, step):
    """
    This test sends ICMP traffic from hs1 to hs2 after applying a permit
    ACL to interface 1. After it verifies that hs2 receives 10 packets,
    it sends traffic in the reverse direction and verifies that traffic
    behavior complies with the applied permit ACL
    """
    with ops1.libs.vtysh.ConfigAccessListIpTestname('test12') as ctx:
        ctx.permit('', '11', 'icmp', '10.0.10.1', '', '10.0.10.2', '')

    test1_result = ops1('show run')

    assert search(
        ''
        r'11\s+permit\s+icmp\s+10\.0\.10\.1'
        '\s+10\.0\.10\.2'.format(**locals()), test1_result)

    with ops1.libs.vtysh.ConfigInterface('1') as ctx:
        ctx.apply_access_list_ip_in('test12')

    test1_result = ops1('show run')

    assert search(r'(access-list\s+ip\s+test12\s+\in)'.format(**locals()),
                  test1_result)

    with ops1.libs.vtysh.ConfigAccessListIpTestname('test12') as ctx:
        ctx.permit('', '12', 'icmp', '10.0.10.2', '', '10.0.10.1', '')

    test1_result = ops1('show run')

    assert search(
        ''
        r'12\s+permit\s+icmp\s+10\.0\.10\.2'
        '\s+10\.0\.10\.1'.format(**locals()), test1_result)

    with ops1.libs.vtysh.ConfigInterface('2') as ctx:
        ctx.apply_access_list_ip_in('test12')

    test1_result = ops1('show run')

    assert search(r'(access-list\s+ip\s+test12\s+\in)'.format(**locals()),
                  test1_result)

    step('Create packets')
    ip_packet = hs1.libs.scapy.ip("dst='10.0.10.2', src='10.0.10.1'")
    icmp_packet = hs1.libs.scapy.icmp()

    list1 = [ip_packet, icmp_packet]
    proto_str = 'IP/ICMP'
    filter_str = 'icmp and ip src 10.0.10.1 and ip dst 10.0.10.2'
    port_str = '1'
    timeout = 25
    count = 10

    txthread = ScapyThread(send_traffic, 'hs1', topology, proto_str, list1, '',
                           count, '', 0)

    rxthread = ScapyThread(sniff_traffic, 'hs2', topology, '', [], filter_str,
                           count, port_str, timeout)

    rxthread.start()
    txthread.start()

    txthread.join()
    rxthread.join()

    if rxthread.outresult():
        rest, sniffcnt = rxthread.outresult().split('<Sniffed:')
        list_result = findall(r'[0-9]+', sniffcnt)

        assert (list_result[2] == '10')

    step('Create packets')
    ip_packet = hs2.libs.scapy.ip("dst='10.0.10.1', src='10.0.10.2'")
    icmp_packet = hs2.libs.scapy.icmp()
    filter_str = 'icmp and ip src 10.0.10.2 and ip dst 10.0.10.1'

    list1 = [ip_packet, icmp_packet]
    proto_str = 'IP/ICMP'
    port_str = '1'
    timeout = 25
    count = 10

    txthread = ScapyThread(send_traffic, 'hs2', topology, proto_str, list1, '',
                           count, '', 0)

    rxthread = ScapyThread(sniff_traffic, 'hs1', topology, '', [], filter_str,
                           count, port_str, timeout)

    rxthread.start()
    txthread.start()

    txthread.join()
    rxthread.join()

    if rxthread.outresult():
        rest, sniffcnt = rxthread.outresult().split('<Sniffed:')
        list_result = findall(r'[0-9]+', sniffcnt)

        assert (list_result[2] == '10')

    with ops1.libs.vtysh.ConfigAccessListIpTestname('test12') as ctx:
        ctx.no('12')

    with ops1.libs.vtysh.ConfigAccessListIpTestname('test12') as ctx:
        ctx.no('11')

    with ops1.libs.vtysh.Configure() as ctx:
        ctx.no_access_list_ip('test12')

    test1_result = ops1('show run')

    assert search(r'(?!access-list\s+ip\s+test12\s+)'.format(**locals()),
                  test1_result)
def acl_permit_any_hs1_hs2(ops1, hs1, hs2, topology, step):
    """
    This test adds a "40 permit 10.0.10.1 10.0.10.2" rule on interface 1.
    It then sends 10 ICMP packets from hs1 to hs2 and verifies that
    10 ICMP packets are received on hs2
    """

    with ops1.libs.vtysh.ConfigAccessListIpTestname('test1') as ctx:
        ctx.permit('', '40', 'any', '10.0.10.1', '', '10.0.10.2', '')

    test1_result = ops1('show run')

    assert search(
        ''
        r'40\s+permit\s+any\s+10\.0\.10\.1'
        '\s+10\.0\.10\.2'.format(**locals()), test1_result)

    with ops1.libs.vtysh.ConfigInterface('1') as ctx:
        ctx.apply_access_list_ip_in('test1')

    test1_result = ops1('show run')

    assert search(r'(access-list\s+ip\s+test1\s+\in)'.format(**locals()),
                  test1_result)

    step('Create packets')
    ip_packet = hs1.libs.scapy.ip("dst='10.0.10.2', src='10.0.10.1'")
    icmp_packet = hs1.libs.scapy.icmp()

    list1 = [ip_packet, icmp_packet]
    proto_str = 'IP/ICMP'
    filter_str = 'icmp and ip src 10.0.10.1 and ip dst 10.0.10.2'
    port_str = '1'
    timeout = 25
    count = 10

    txthread = ScapyThread(send_traffic, 'hs1', topology, proto_str, list1, '',
                           count, '', 0)

    rxthread = ScapyThread(sniff_traffic, 'hs2', topology, '', [], filter_str,
                           count, port_str, timeout)

    rxthread.start()
    txthread.start()

    txthread.join()
    rxthread.join()

    if rxthread.outresult():
        rest, sniffcnt = rxthread.outresult().split('<Sniffed:')
        list_result = findall(r'[0-9]+', sniffcnt)

        assert (list_result[2] == '10')
        assert search(
            ''
            r'ICMP\s+10\.0\.10\.1\s+\>\s+10\.0\.10\.2\s+'
            'echo-request'.format(**locals()), rxthread.outresult())

    with ops1.libs.vtysh.ConfigAccessListIpTestname('test1') as ctx:
        ctx.no('40')

    with ops1.libs.vtysh.Configure() as ctx:
        ctx.no_access_list_ip('test1')

    test1_result = ops1('show run')

    assert search(r'(?!access-list\s+ip\s+test1\s+)'.format(**locals()),
                  test1_result)
def acl_permit_icmp_non_contiguous_mask_neg(ops1, hs1, hs2, topology, step):
    """
    This test adds a "8 permit icmp 10.0.10.0/255.0.255.252
    10.0.10.2" rule on interface 1.
    It then sends 10 ICMP packets from hs1, which lies outside
    the permitted network, to hs2 and verifies that
    10 ICMP packets are not received on hs2.
    """
    with ops1.libs.vtysh.ConfigAccessListIpTestname('test8') as ctx:
        ctx.permit('', '8', 'icmp', '10.0.10.0/255.0.255.252', '', '10.0.10.2',
                   '')

    test1_result = ops1('show run')

    assert search(
        ''
        r'8\s+permit\s+icmp\s+10\.0\.10\.0/255\.0\.255\.252'
        '\s+10\.0\.10\.2'.format(**locals()), test1_result)

    with ops1.libs.vtysh.ConfigInterface('1') as ctx:
        ctx.apply_access_list_ip_in('test8')

    test1_result = ops1('show run')

    assert search(r'(access-list\s+ip\s+test8\s+\in)'.format(**locals()),
                  test1_result)

    step('Create packets')
    ip_packet = hs1.libs.scapy.ip("dst='10.0.10.2', src='10.0.10.5'")
    icmp_packet = hs1.libs.scapy.icmp()
    filter_str = 'icmp and ip src 10.0.10.5 and ip dst 10.0.10.2'

    list1 = [ip_packet, icmp_packet]
    proto_str = 'IP/ICMP'
    port_str = '1'
    timeout = 25
    count = 10

    txthread = ScapyThread(send_traffic, 'hs1', topology, proto_str, list1, '',
                           count, '', 0)

    rxthread = ScapyThread(sniff_traffic, 'hs2', topology, '', [], filter_str,
                           count, port_str, timeout)

    rxthread.start()
    txthread.start()

    txthread.join()
    rxthread.join()
    if rxthread.outresult():
        rest, sniffcnt = rxthread.outresult().split('<Sniffed:')
        list_result = findall(r'[0-9]+', sniffcnt)
        assert (list_result[2] == '0')

    with ops1.libs.vtysh.ConfigAccessListIpTestname('test8') as ctx:
        ctx.no('8')

    with ops1.libs.vtysh.Configure() as ctx:
        ctx.no_access_list_ip('test8')

    test1_result = ops1('show run')

    assert search(r'(?!access-list\s+ip\s+test8\s+)'.format(**locals()),
                  test1_result)