def routerid(node): ''' Helper to return the first IPv4 address of a node as its router ID. ''' # Use IPv4 loopback address of this node as the routerID. # Don't get v4-loopback-addr directly from node as the node might has # IPv4 disabled. Instead, directly query the central 'database' for the # IPv4 address that would be the nodes IPv4 loopback. return str(Loopback.getLoopbackIPv4(node))
def getAndGeneratePTRZonesASAuthServer(cls, node): """ returns a list of all reverse zones a root dns server serves """ # find dns as authoritative servers # (server_name, server_addr, zone) as_auth_servers = [] service_helpers.nodewalker(node, node, as_auth_servers, cls.nodewalker_root_dns_find_all_auth_servers_callback) as_auth_servers = [('%s.%s' % (server_name, zone), server_addr, zone) \ for server_name, server_addr, zone in as_auth_servers] # zone = "AS%s.virtual." % str(netid) zonenames = [] if hasattr(node, 'netid') and not node.netid is None: netid = node.netid else: # TODO: netid 0 is invalid netid = 0 asn = netid for ipversion in node.getIPversions(): # collect loopback address space loopback_net = Loopback.getLoopbackNet_per_net(\ node.session.sessionid, netid, ipversion) print(('[DEBUG] loopback_net IPv%d: %s' % (ipversion, loopback_net))) # collect interface address space interface_net = Interface.getInterfaceNet_per_net(\ node.session.sessionid, netid, ipversion) print(('[DEBUG] interface_net IPv%d: %s' % (ipversion, interface_net))) if ipversion == 4: auth_servers = [(server_name, server_addr) \ for server_name, server_addr, zone in as_auth_servers \ if zone == "AS%s.virtual." % str(netid) and \ isIPv4Address(server_addr)] elif ipversion == 6: auth_servers = [(server_name, server_addr) \ for server_name, server_addr, zone in as_auth_servers \ if zone == "AS%s.virtual." % str(netid) and \ isIPv6Address(server_addr)] else: raise ValueError for asn_net in loopback_net, interface_net: zonename = cls.getPTRZoneNameFromPrefix(cls, asn_net) print(('[DEBUG] zonename: %s' % zonename)) ORIGINHeader = '$ORIGIN %s\n' % zonename print(('[DEBUG] ORIGINHeader: %s' % ORIGINHeader)) SOAHeader = cls.generateSOAHeader(cls, auth_servers, zonename) print(('[DEBUG] SOAHeader:\n%s' % SOAHeader)) zoneentries = [] # get host list of this AS # TODO: iterating over all nodes for interface and # loopback address space is expensive. and we are only talking # about IPv4 or IPv6 at the moment. # is there a better way of doing this? hosts = [] service_helpers.nodewalker(node, node, hosts, cls.nodewalker_asroot_dns_find_hosts_in_as_callback) for hostname, asn_addr, zone in hosts: if ipversion == 4 and not isIPv4Address(asn_addr): continue if ipversion == 6 and not isIPv6Address(asn_addr): continue if ipversion == 4: asn_addr = IPv4Addr(asn_addr) elif ipversion == 6: asn_addr = IPv6Addr(asn_addr) else: raise ValueError if asn_addr < asn_net.minaddr() or \ asn_addr > asn_net.maxaddr(): continue # set prefix length. just to be sure asn_addr.set_prefixlen(asn_net.prefixlen) asn_ptr_name = cls.getPTR_CNAME_FromAddr(cls, asn_addr) print(('[DEBUG] ASN PTR addr (IPv%d): %s' % (ipversion, str(asn_addr)))) print(('[DEBUG] adding: "%s IN PTR %s.AS%s.virtual.' % (asn_ptr_name, hostname, str(netid)))) zoneentries.append(('%s IN PTR %s.AS%s.virtual.' % (asn_ptr_name, hostname, str(netid)))) print(('[DEBUG] PTR records: %s' % (zoneentries))) zonecontents = '%s\n%s\n%s\n' % (ORIGINHeader, SOAHeader, '\n'.join(zoneentries)) cls.writeZoneFile(cls, node, zonename, zonecontents) print(('[DEBUG] adding ptrzone: %s' % zonename)) zonenames.append(zonename) return zonenames
def getAndGeneratePTRZonesRootServer(cls, node): """ returns a list of all reverse zones a root dns server serves """ # find dns root servers # (server_name, server_addr) rootservers = [] service_helpers.nodewalker(node, node, rootservers, cls.nodewalker_find_root_dns_callback) rootservers = [('%s.' % server_name, server_addr) \ for server_name, server_addr in rootservers] # find dns as authoritative servers # (server_name, server_addr, zone) as_auth_servers = [] service_helpers.nodewalker(node, node, as_auth_servers, cls.nodewalker_root_dns_find_all_auth_servers_callback) as_auth_servers = [('%s.%s' % (server_name, zone), server_addr, zone) \ for server_name, server_addr, zone in as_auth_servers] zonenames = [] SOAHeader = cls.generateSOAHeader(cls, rootservers, '.') print(('[DEBUG] SOAHeader:\n%s' % SOAHeader)) for ipversion in node.getIPversions(): # collect loopback address space loopback_net = Loopback.getLoopbackNet(ipversion) print(('[DEBUG] loopback_net IPv%d: %s' % (ipversion, loopback_net))) # collect interface address space interface_net = Interface.getInterfaceNet(ipversion) print(('[DEBUG] interface_net IPv%d: %s' % (ipversion, interface_net))) # get all deployed ASN's asns = list(NetIDNodeMap.mapping[node.session.sessionid].keys()) print(('[DEBUG] deployed ASN\'s: %s' % asns)) for net in loopback_net, interface_net: zonename = cls.getPTRZoneNameFromPrefix(cls, net) net_prefixlen = net.prefixlen print(('[DEBUG] zonename: %s' % zonename)) ORIGINHeader = '$ORIGIN %s\n' % zonename print(('[DEBUG] ORIGINHeader: %s' % ORIGINHeader)) zoneentries = [] for asn in asns: # get AS address space if net == loopback_net: asn_net = Loopback.getLoopbackNet_per_net(\ node.session.sessionid, asn, ipversion) elif net == interface_net: asn_net = Interface.getInterfaceNet_per_net(\ node.session.sessionid, asn, ipversion) # find authoritative AS dns servers # zone == "AS%s.virtual." % str(netid) for server_name, server_addr, zone in as_auth_servers: server_asn = zone.lstrip('AS') server_asn = int(server_asn[:server_asn.find('.')]) # not the correct asn if not asn == server_asn: continue # not our IP version if ipversion == 4 and not isIPv4Address(server_addr): continue if ipversion == 6 and not isIPv6Address(server_addr): continue print(('[DEBUG] server_name: %s, server_addr: %s, zone: %s' % (server_name, server_addr, zone))) if ipversion == 4: # get host list of this AS # TODO: iterating over all nodes for each AS for interface and # loopback address space is expensive. and we are only talking # about IPv4 at the moment. is there a better way of doing this? hosts = [] # TODO: tmp. setting another netid of a node is a dirty hack tmpnetid = node.netid node.netid = server_asn service_helpers.nodewalker(node, node, hosts, cls.nodewalker_asroot_dns_find_hosts_in_as_callback) node.netid = tmpnetid for hostname, asn_addr, zone in hosts: if not isIPv4Address(asn_addr): continue asn_addr = IPv4Addr(asn_addr) print(('[DEBUG] asn_addr(%s) in asn_net(%s)' % (str(asn_addr), str(asn_net)))) if asn_addr < asn_net.minaddr() or \ asn_addr > asn_net.maxaddr(): continue # set prefix length of the supernet asn_addr.set_prefixlen(net_prefixlen) asn_ptr_name = cls.getPTR_CNAME_FromAddr(cls, asn_addr) #print(('[DEBUG] deployed ASN network (IPv%d): %s' % # (ipversion, str(asn_net)))) print(('[DEBUG] ASN PTR addr (IPv%d): %s' % (ipversion, str(asn_addr)))) print(('[DEBUG] adding: "%s IN NS %s"' % (asn_ptr_name, server_name))) zoneentries.append(('%s IN NS %s' % (asn_ptr_name, server_name))) elif ipversion == 6: asn_ptr_name = cls.getPTRZoneNameFromPrefix(cls, asn_net) print(('[DEBUG] adding: "%s IN NS %s"' % (asn_ptr_name, server_name))) zoneentries.append(('%s IN NS %s' % (asn_ptr_name, server_name))) print(('[DEBUG] subnet name servers: %s' % (zoneentries))) zonecontents = '%s\n%s\n%s\n' % (ORIGINHeader, SOAHeader, '\n'.join(zoneentries)) cls.writeZoneFile(cls, node, zonename, zonecontents) print(('[DEBUG] adding ptrzone to zonenames: %s' % zonename)) zonenames.append(zonename) return zonenames
def generatequaggaconfig(cls, node): v6cfg = [] v6prefixes = [] if not node.enable_ipv4 and not node.enable_ipv6: return '' cfg = '!\n! BGP configuration\n!\n' cfg += 'log file /tmp/quagga-bgp-%s.log\n' % node.name cfg += 'router bgp %s\n' % node.netid cfg += ' bgp router-id %s\n' % cls.routerid(node) cfg += ' redistribute kernel\n' cfg += ' redistribute static\n' cfg += '!\n' if hasattr(node, 'netid') and not node.netid is None: netid = node.netid else: # TODO: netid 0 is invalid netid = 0 # configure EBGP connections: if service_flags.EGP in node.services: tmpcfg, tmpv6cfg = cls.configure_EGP(node) cfg += tmpcfg v6cfg.extend(tmpv6cfg) # configure IBGP connections confstr_list = [cfg] # full mesh service_helpers.nodewalker(node, node, confstr_list, cls.nodewalker_ibgp_find_neighbors_callback) cfg = ''.join(confstr_list) if node.enable_ipv4 and service_flags.EGP in node.services: interface_net = Interface.getInterfaceNet_per_net(\ node.session.sessionid, netid, 4) loopback_net = Loopback.getLoopbackNet_per_net(\ node.session.sessionid, netid, 4) cfg += ' network %s\n' % str(loopback_net) cfg += ' network %s\n' % str(interface_net) cfg += ' aggregate-address %s summary-only\n' % str(loopback_net) cfg += ' aggregate-address %s summary-only\n' % str(interface_net) if node.enable_ipv6: v6_ibgp_neighbor_list = [] service_helpers.nodewalker(node, node, v6_ibgp_neighbor_list, cls.nodewalker_ibgp_find_neighbor_addrs_v6_callback) cfg += ' address-family ipv6\n' # activate IBGP neighbors cfg += ''.join([(' neighbor %s activate\n') % \ (str(remote_addr).split('/')[0]) \ for local_addr, remote_addr in v6_ibgp_neighbor_list]) # activate EBGP neighbors cfg += ''.join(v6cfg) if service_flags.EGP in node.services: # announce networks interface_net = Interface.getInterfaceNet_per_net(\ node.session.sessionid, netid, 6) loopback_net = Loopback.getLoopbackNet_per_net(\ node.session.sessionid, netid, 6) cfg += ' network %s\n' % str(loopback_net) cfg += ' network %s\n' % str(interface_net) cfg += ' aggregate-address %s summary-only\n' % str(loopback_net) cfg += ' aggregate-address %s summary-only\n' % str(interface_net) adj_addrs = cls.collect_adjacent_loopback_addrs_v6(cls, node) for adj_addr in adj_addrs: cfg += ' network %s/128\n' % str(adj_addr) cfg += '\n exit-address-family\n' return cfg
def routerid(node): ''' Helper to return the first IPv4 address of a node as its router ID. ''' return str(Loopback.getLoopbackIPv4(node))