Beispiel #1
0
def test_customer_bogon_routes(bf, customer_list):
    """Check that no BOGON routes are accepted from customers"""
    bf.asserts.current_assertion = 'Assert no BOGON prefixes accepted from customers'

    df = bf.q.routes(
        rib='bgp').answer().frame()  #retrieve BGP RIB for all devices
    bogons = []

    for customer in customer_list:
        for _, row in df.iterrows():
            if (row['Node'] == customer['Node']) & (
                    row['Next_Hop_IP'] == customer['Remote_IP']
            ):  #found routes learnt from customer
                z = IPNetwork(row['Network'])
                if (z.is_reserved() or z.is_private() or z.is_loopback()
                        or z.is_link_local() or z.is_multicast()):
                    bogons.append(
                        f"Prefix {row['Network']} from {customer['Remote_IP']} on {customer['Node']} should not be accepted"
                    )

    test = (len(bogons) == 0)
    pass_message = "No BOGON prefixes accepted from customers\n"
    fail_message = f"List of BOGON prefixes accepted from customers\n\n{bogons}"

    record_results(bf, test, pass_message, fail_message)
Beispiel #2
0
def _verify_network(name, network):
    """
    Verifies syntax of a specific network.

    :param str name: Name of network
    :param dict network: the network
    :return: Number of errors, Number of warnings
    :rtype: tuple(int, int)
    """
    num_warnings = 0
    num_errors = 0

    for key, value in network.items():
        # Subnet verification
        if "subnet" not in value:
            logging.warning("No subnet specified for %s %s", name, key)
            num_warnings += 1
        else:
            try:
                subnet = IPNetwork(value["subnet"])
            except AddrFormatError:
                logging.error("Invalid format for subnet '%s'",
                              str(value["subnet"]))
                num_errors += 1
            else:
                if subnet.is_reserved() \
                        or subnet.is_multicast() \
                        or subnet.is_loopback():
                    logging.error("%s %s is in a invalid IP address space",
                                  name, key)
                    num_errors += 1
                elif not subnet.is_private():
                    logging.warning("Non-private subnet used for %s %s", name,
                                    key)
                    num_warnings += 1

        # VLAN verification
        if "vlan" in value:
            if name == "unique-networks" and int(value["vlan"]) >= 2000:
                logging.error("VLAN must be less than 2000 for network %s",
                              key)
                num_errors += 1
            elif name == "generic-networks":
                logging.error(
                    "VLAN specification is not allowed "
                    "for network %s", key)
                num_errors += 1

        # Increment verification
        if "increment" in value:
            if name == "unique-networks":
                logging.error("Increment cannot be used for network %s", key)
                num_errors += 1
            elif not isinstance(value["increment"], bool):
                logging.error("Increment must be a boolean for network %s",
                              key)
                num_errors += 1
    return num_errors, num_warnings
Beispiel #3
0
def validate_network_str(network_str,
                         minimum_size,
                         existing_networks=None,
                         multicast=False):
    """Determine whether a network is valid."""
    try:
        network = IPNetwork(network_str)
        if network.ip != network.network:
            raise ValidateFail("Invalid network address")
        elif network.size < minimum_size:
            raise ValidateFail("Subnet too small - must have at least %d "
                               "addresses" % minimum_size)
        elif network.version == 6 and network.prefixlen < 64:
            raise ValidateFail("IPv6 minimum prefix length is 64")
        elif existing_networks:
            if any(network.ip in subnet for subnet in existing_networks):
                raise ValidateFail("Subnet overlaps with another "
                                   "configured subnet")
        elif multicast and not network.is_multicast():
            raise ValidateFail("Invalid subnet - must be multicast")
        return network
    except AddrFormatError:
        raise ValidateFail("Invalid subnet - not a valid IP subnet")
Beispiel #4
0
def get_ipcalc_network(query, netmask=""):
    """
    IP calculator tool: supports IPv6 and IPv4 networks. For list of values see below.

    IP list is optional since it will return many IPs for some subnets,
    if you need to show ip list you will have to append ``?iplist`` to your get request.

    **PLEASE NOTE:** iplist will print only 65536 addresses which is /16 in IPv4 subnetting or /112 in IPv6 subnetting.
    If you try to get more you will get an error.

    :param query: IP address or hostname
    :param netmask: (Optional) If you want the whole range of hosts

    **Example:**

        When getting single host

        $ GET ``/api/ipcalc/199.16.156.102/30``

        ::


            {
              "results": {
                "broadcast": "199.16.156.103",
                "cidr": "199.16.156.100/30",
                "first_host": "199.16.156.101",
                "hostmask": "0.0.0.3",
                "ip_bits": "11000111.00010000.10011100.01100110",
                "ip_version": 4,
                "is_linklocal": false,
                "is_loopback": false,
                "is_multicast": false,
                "is_private": false,
                "is_public": true,
                "is_reserved": false,
                "is_unicast": true,
                "last_host": "199.16.156.102",
                "netmask": "255.255.255.252",
                "netmask_bits": "11111111.11111111.11111111.11111100",
                "network": "199.16.156.100",
                "network_bits": "11000111.00010000.10011100.01100100",
                "num_addresses": 4,
                "prefixlen": 30,
                "supernet": [
                  "0.0.0.0/0",
                  "128.0.0.0/1",
                  "192.0.0.0/2",
                  "192.0.0.0/3",
                  "192.0.0.0/4",
                  "192.0.0.0/5",
                  "196.0.0.0/6",
                  "198.0.0.0/7",
                  "199.0.0.0/8",
                  "199.0.0.0/9",
                  "199.0.0.0/10",
                  "199.0.0.0/11",
                  "199.16.0.0/12",
                  "199.16.0.0/13",
                  "199.16.0.0/14",
                  "199.16.0.0/15",
                  "199.16.0.0/16",
                  "199.16.128.0/17",
                  "199.16.128.0/18",
                  "199.16.128.0/19",
                  "199.16.144.0/20",
                  "199.16.152.0/21",
                  "199.16.156.0/22",
                  "199.16.156.0/23",
                  "199.16.156.0/24",
                  "199.16.156.0/25",
                  "199.16.156.64/26",
                  "199.16.156.96/27",
                  "199.16.156.96/28",
                  "199.16.156.96/29"
                ],
                "to_ipv6": "::ffff:199.16.156.102/126"
              },
              "status": "ok"
            }

    """

    if netmask is not "":
        ip = query + '/' + netmask
    else:
        ip = query

    try:
        net = IPNetwork(ip)
    except AddrFormatError:
        abort(400)

    results = dict()
    results['broadcast'] = str(net.broadcast)
    results['network'] = str(net.network)
    results['netmask'] = str(net.netmask)
    results['cidr'] = str(net.cidr)
    results['num_addresses'] = net.size
    results['hostmask'] = str(net.hostmask)
    results['is_loopback'] = net.is_loopback()
    results['is_unicast'] = net.is_unicast()
    results['is_multicast'] = net.is_multicast()
    results['is_private'] = net.is_private()
    results['is_reserved'] = net.is_reserved()
    results['is_linklocal'] = net.is_link_local()
    results['is_public'] = net.is_unicast() and not net.is_private()
    results['prefixlen'] = net.prefixlen
    results['ip_version'] = net.version
    results['ip_bits'] = net.ip.bits()
    results['network_bits'] = net.network.bits()
    results['netmask_bits'] = net.netmask.bits()
    results['supernet'] = [str(supernet) for supernet in net.supernet()]

    if net.version == 4:
        results['to_ipv6'] = str(net.ipv6())

        if request.query_string == 'iplist':
            if net.size <= 65536:
                results['ip_list'] = [str(ip) for ip in list(net)]
            else:
                return error_response("Too many IPs to list (limit is 65536), "
                                      "use smaller subnet or remove '?iplist' from query.", 400)

        if net.broadcast is not None:
            results['first_host'] = str(net.network + 1)
            results['last_host'] = str(net.broadcast - 1)
        else:
            results['first_host'] = str(net.ip)
            results['last_host'] = str(net.ip)

    elif net.version == 6:
        try:
            results['to_ipv4'] = str(net.ipv4())
        except AddrConversionError:
            results['to_ipv4'] = None

        if request.query_string == 'iplist':
            if net.size <= 65536:
                results['ip_list'] = [str(ip) for ip in list(net)]
            else:
                return error_response("Too many IPs to list (limit is 65536), "
                                      "use smaller subnet or remove '?iplist' from query.", 400)

    return jsonify({'status': "ok",
                    'results': results})