def generate_config(cls, node: CoreNode, filename: str) -> str: """ Generate a startpcap.sh traffic logging script. """ cfg = """ #!/bin/sh # set tcpdump options here (see 'man tcpdump' for help) # (-s snap length, -C limit pcap file length, -n disable name resolution) DUMPOPTS="-s 12288 -C 10 -n" if [ "x$1" = "xstart" ]; then """ for iface in node.get_ifaces(): if hasattr(iface, "control") and iface.control is True: cfg += "# " redir = "< /dev/null" cfg += "tcpdump ${DUMPOPTS} -w %s.%s.pcap -i %s %s &\n" % ( node.name, iface.name, iface.name, redir, ) cfg += """ elif [ "x$1" = "xstop" ]; then mkdir -p ${SESSION_DIR}/pcap mv *.pcap ${SESSION_DIR}/pcap fi; """ return cfg
def generate_config(cls, node: CoreNode, filename: str) -> str: """ Generate a RADVD router advertisement daemon config file using the network address of each interface. """ cfg = "# auto-generated by RADVD service (utility.py)\n" for iface in node.get_ifaces(control=False): prefixes = list(map(cls.subnetentry, iface.ips())) if len(prefixes) < 1: continue cfg += ("""\ interface %s { AdvSendAdvert on; MinRtrAdvInterval 3; MaxRtrAdvInterval 10; AdvDefaultPreference low; AdvHomeAgentFlag off; """ % iface.name) for prefix in prefixes: if prefix == "": continue cfg += ("""\ prefix %s { AdvOnLink on; AdvAutonomous on; AdvRouterAddr on; }; """ % prefix) cfg += "};\n" return cfg
def generate_frr_config(cls, node: CoreNode) -> str: cfg = "router ospf6\n" rtrid = cls.router_id(node) cfg += " router-id %s\n" % rtrid for iface in node.get_ifaces(control=False): cfg += " interface %s area 0.0.0.0\n" % iface.name cfg += "!\n" return cfg
def router_id(node: CoreNode) -> str: """ Helper to return the first IPv4 address of a node as its router ID. """ for iface in node.get_ifaces(control=False): ip4 = iface.get_ip4() if ip4: return str(ip4.ip) return "0.0.0.0"
def generate_config(cls, node: CoreNode, filename: str) -> str: cfg = "#!/bin/sh\n" cfg += "# auto-generated by StaticRoute service (utility.py)\n#\n" cfg += "# NOTE: this service must be customized to be of any use\n" cfg += "# Below are samples that you can uncomment and edit.\n#\n" for iface in node.get_ifaces(control=False): cfg += "\n".join(map(cls.routestr, iface.ips())) cfg += "\n" return cfg
def generate_frr_config(cls, node: CoreNode) -> str: cfg = "router ospf\n" rtrid = cls.router_id(node) cfg += " router-id %s\n" % rtrid # network 10.0.0.0/24 area 0 for iface in node.get_ifaces(control=False): for ip4 in iface.ip4s: cfg += f" network {ip4} area 0\n" cfg += "!\n" return cfg
def generate_bird_iface_config(cls, node: CoreNode) -> str: """ Use only bare interfaces descriptions in generated protocol configurations. This has the slight advantage of being the same everywhere. """ cfg = "" for iface in node.get_ifaces(control=False): cfg += ' interface "%s";\n' % iface.name return cfg
def generate_quagga_conf(cls, node: CoreNode) -> str: """ Returns configuration file text. Other services that depend on zebra will have hooks that are invoked here. """ # we could verify here that filename == Quagga.conf cfg = "" for iface in node.get_ifaces(): cfg += "interface %s\n" % iface.name # include control interfaces in addressing but not routing daemons if iface.control: cfg += " " cfg += "\n ".join(map(cls.addrstr, iface.ips())) cfg += "\n" continue cfgv4 = "" cfgv6 = "" want_ipv4 = False want_ipv6 = False for s in node.services: if cls.name not in s.dependencies: continue if not (isinstance(s, QuaggaService) or issubclass(s, QuaggaService)): continue iface_config = s.generate_quagga_iface_config(node, iface) if s.ipv4_routing: want_ipv4 = True if s.ipv6_routing: want_ipv6 = True cfgv6 += iface_config else: cfgv4 += iface_config if want_ipv4: cfg += " " cfg += "\n ".join(map(cls.addrstr, iface.ip4s)) cfg += "\n" cfg += cfgv4 if want_ipv6: cfg += " " cfg += "\n ".join(map(cls.addrstr, iface.ip6s)) cfg += "\n" cfg += cfgv6 cfg += "!\n" for s in node.services: if cls.name not in s.dependencies: continue if not (isinstance(s, QuaggaService) or issubclass(s, QuaggaService)): continue cfg += s.generate_quagga_config(node) return cfg
def generate_config(cls, node: CoreNode, filename: str) -> str: cfg = "#!/bin/sh\n" cfg += "# auto-generated by DefaultMulticastRoute service (utility.py)\n" cfg += "# the first interface is chosen below; please change it " cfg += "as needed\n" for iface in node.get_ifaces(control=False): rtcmd = "ip route add 224.0.0.0/4 dev" cfg += "%s %s\n" % (rtcmd, iface.name) cfg += "\n" break return cfg
def firstipv4prefix(node: CoreNode, prefixlen: int = 24) -> str: """ Similar to QuaggaService.routerid(). Helper to return the first IPv4 prefix of a node, using the supplied prefix length. This ignores the interface's prefix length, so e.g. '/32' can turn into '/24'. """ for iface in node.get_ifaces(control=False): ip4 = iface.get_ip4() if ip4: return f"{ip4.ip}/{prefixlen}" return "0.0.0.0/%s" % prefixlen
def get_startup(cls, node: CoreNode) -> Tuple[str, ...]: """ Generate the appropriate command-line based on node interfaces. """ cmd = cls.startup[0] ifaces = node.get_ifaces(control=False) if len(ifaces) > 0: iface_names = map(lambda x: x.name, ifaces) cmd += " -i " cmd += " -i ".join(iface_names) return (cmd, )
def generatehtml(cls, node: CoreNode, filename: str) -> str: body = ("""\ <!-- generated by utility.py:HttpService --> <h1>%s web server</h1> <p>This is the default web page for this server.</p> <p>The web server software is running but no content has been added, yet.</p> """ % node.name) for iface in node.get_ifaces(control=False): body += "<li>%s - %s</li>\n" % (iface.name, [str(x) for x in iface.ips()]) return "<html><body>%s</body></html>" % body
def generate_config(cls, node: CoreNode, filename: str) -> str: emane_manager = node.session.emane cfg = "" for iface in node.get_ifaces(): if not isinstance(iface.net, EmaneNet): continue emane_net = iface.net config = emane_manager.get_iface_config(emane_net, iface) if emanexml.is_external(config): nem_id = emane_manager.get_nem_id(iface) cfg += f"emanegentransportxml {iface.name}-platform.xml\n" cfg += f"emanetransportd -r -l 0 -d transportdaemon{nem_id}.xml\n" return cfg
def generate_frr_config(cls, node: CoreNode) -> str: ifname = "eth0" for iface in node.get_ifaces(): if iface.name != "lo": ifname = iface.name break cfg = "router mfea\n!\n" cfg += "router igmp\n!\n" cfg += "router pim\n" cfg += " !ip pim rp-address 10.0.0.1\n" cfg += " ip pim bsr-candidate %s\n" % ifname cfg += " ip pim rp-candidate %s\n" % ifname cfg += " !ip pim spt-threshold interval 10 bytes 80000\n" return cfg
def generate_config(cls, node: CoreNode, filename: str) -> str: routes = [] ifaces = node.get_ifaces() if ifaces: iface = ifaces[0] for ip in iface.ips(): net = ip.cidr if net.size > 1: router = net[1] routes.append(str(router)) cfg = "#!/bin/sh\n" cfg += "# auto-generated by DefaultRoute service (utility.py)\n" for route in routes: cfg += f"ip route add default via {route}\n" return cfg
def generate_config(cls, node: CoreNode, filename: str) -> str: """ Generate a script to invoke dhclient on all interfaces. """ cfg = "#!/bin/sh\n" cfg += "# auto-generated by DHCPClient service (utility.py)\n" cfg += "# uncomment this mkdir line and symlink line to enable client-" cfg += "side DNS\n# resolution based on the DHCP server response.\n" cfg += "#mkdir -p /var/run/resolvconf/interface\n" for iface in node.get_ifaces(control=False): cfg += "#ln -s /var/run/resolvconf/interface/%s.dhclient" % iface.name cfg += " /var/run/resolvconf/resolv.conf\n" cfg += "/sbin/dhclient -nw -pf /var/run/dhclient-%s.pid" % iface.name cfg += " -lf /var/run/dhclient-%s.lease %s\n" % (iface.name, iface.name) return cfg
def generate_config(cls, node: CoreNode, filename: str) -> str: """ Generate a startup script for MgenActor. Because mgenActor does not daemonize, it can cause problems in some situations when launched directly using vcmd. """ cfg = "#!/bin/sh\n" cfg += "# auto-generated by nrl.py:MgenActor.generateconfig()\n" comments = "" cmd = "mgenBasicActor.py -n %s -a 0.0.0.0" % node.name ifaces = node.get_ifaces(control=False) if len(ifaces) == 0: return "" cfg += comments + cmd + " < /dev/null > /dev/null 2>&1 &\n\n" return cfg
def generate_xorp_config(cls, node: CoreNode) -> str: cfg = cls.fea("unicast-forwarding6") rtrid = cls.router_id(node) cfg += "\nprotocols {\n" cfg += " ospf6 0 { /* Instance ID 0 */\n" cfg += "\trouter-id: %s\n" % rtrid cfg += "\tarea 0.0.0.0 {\n" for iface in node.get_ifaces(control=False): cfg += "\t interface %s {\n" % iface.name cfg += "\t\tvif %s {\n" % iface.name cfg += "\t\t}\n" cfg += "\t }\n" cfg += "\t}\n" cfg += " }\n" cfg += "}\n" return cfg
def generate_xorp_config(cls, node: CoreNode) -> str: cfg = cls.fea("unicast-forwarding6") cfg += cls.policyexportconnected() cfg += "\nprotocols {\n" cfg += " ripng {\n" cfg += '\texport: "export-connected"\n' for iface in node.get_ifaces(control=False): cfg += "\tinterface %s {\n" % iface.name cfg += "\t vif %s {\n" % iface.name cfg += "\t\taddress %s {\n" % iface.mac.eui64() cfg += "\t\t disable: false\n" cfg += "\t\t}\n" cfg += "\t }\n" cfg += "\t}\n" cfg += " }\n" cfg += "}\n" return cfg
def generate_xorp_config(cls, node: CoreNode) -> str: cfg = cls.fea("unicast-forwarding4") rtrid = cls.router_id(node) cfg += "\nprotocols {\n" cfg += " olsr4 {\n" cfg += "\tmain-address: %s\n" % rtrid for iface in node.get_ifaces(control=False): cfg += "\tinterface %s {\n" % iface.name cfg += "\t vif %s {\n" % iface.name for ip4 in iface.ip4s: cfg += "\t\taddress %s {\n" % ip4.ip cfg += "\t\t}\n" cfg += "\t }\n" cfg += "\t}\n" cfg += " }\n" cfg += "}\n" return cfg
def generate_config(cls, node: CoreNode, filename: str) -> str: """ NAT out the first interface """ cfg = "#!/bin/sh\n" cfg += "# generated by security.py\n" cfg += "# NAT out the first interface by default\n" have_nat = False for iface in node.get_ifaces(control=False): if have_nat: cfg += cls.generate_iface_nat_rule(iface, prefix="#") else: have_nat = True cfg += "# NAT out the " + iface.name + " interface\n" cfg += cls.generate_iface_nat_rule(iface) cfg += "\n" return cfg
def get_startup(cls, node: CoreNode) -> Tuple[str, ...]: """ Generate the appropriate command-line based on node interfaces. """ cmd = cls.startup[0] cmd += " -l /var/log/nrlnhdp.log" cmd += " -rpipe %s_nhdp" % node.name servicenames = map(lambda x: x.name, node.services) if "SMF" in servicenames: cmd += " -flooding ecds" cmd += " -smfClient %s_smf" % node.name ifaces = node.get_ifaces(control=False) if len(ifaces) > 0: iface_names = map(lambda x: x.name, ifaces) cmd += " -i " cmd += " -i ".join(iface_names) return (cmd, )
def generate_config(cls, node: CoreNode, filename: str) -> str: """ Returns a string representation for a file, given the node the service is starting on the config filename that this information will be used for. This must be defined, if "configs" are defined. :param node: core node that the service is being ran on :param filename: configuration file to generate :return: configuration file content """ cfg = "#!/bin/sh\n" if filename == cls.configs[0]: cfg += "# auto-generated by MyService (sample.py)\n" for iface in node.get_ifaces(): cfg += f'echo "Node {node.name} has interface {iface.name}"\n' elif filename == cls.configs[1]: cfg += "echo hello" return cfg
def generate_xorp_config(cls, node: CoreNode) -> str: cfg = cls.mfea("mfea6", node) cfg += "\nprotocols {\n" cfg += " mld {\n" names = [] for iface in node.get_ifaces(control=False): names.append(iface.name) cfg += "\tinterface %s {\n" % iface.name cfg += "\t vif %s {\n" % iface.name cfg += "\t\tdisable: false\n" cfg += "\t }\n" cfg += "\t}\n" cfg += " }\n" cfg += "}\n" cfg += "\nprotocols {\n" cfg += " pimsm6 {\n" names.append("register_vif") for name in names: cfg += "\tinterface %s {\n" % name cfg += "\t vif %s {\n" % name cfg += "\t\tdr-priority: 1\n" cfg += "\t }\n" cfg += "\t}\n" cfg += "\tbootstrap {\n" cfg += "\t cand-bsr {\n" cfg += "\t\tscope-zone ff00::/8 {\n" cfg += '\t\t cand-bsr-by-vif-name: "%s"\n' % names[0] cfg += "\t\t}\n" cfg += "\t }\n" cfg += "\t cand-rp {\n" cfg += "\t\tgroup-prefix ff00::/8 {\n" cfg += '\t\t cand-rp-by-vif-name: "%s"\n' % names[0] cfg += "\t\t}\n" cfg += "\t }\n" cfg += "\t}\n" cfg += " }\n" cfg += "}\n" cfg += "\nprotocols {\n" cfg += " fib2mrib {\n" cfg += "\tdisable: false\n" cfg += " }\n" cfg += "}\n" return cfg
def mfea(forwarding, node: CoreNode) -> str: """ Helper to add a multicast forwarding engine entry to the config file. """ names = [] for iface in node.get_ifaces(control=False): names.append(iface.name) names.append("register_vif") cfg = "plumbing {\n" cfg += " %s {\n" % forwarding for name in names: cfg += "\tinterface %s {\n" % name cfg += "\t vif %s {\n" % name cfg += "\t\tdisable: false\n" cfg += "\t }\n" cfg += "\t}\n" cfg += " }\n" cfg += "}\n" return cfg
def get_startup(cls, node: CoreNode) -> Tuple[str, ...]: """ Generate the appropriate command-line based on node interfaces. """ cmd = cls.startup[0] # are multiple interfaces supported? No. ifaces = node.get_ifaces() if len(ifaces) > 0: iface = ifaces[0] cmd += " -i %s" % iface.name cmd += " -l /var/log/nrlolsrd.log" cmd += " -rpipe %s_olsr" % node.name servicenames = map(lambda x: x.name, node.services) if "SMF" in servicenames and "NHDP" not in servicenames: cmd += " -flooding s-mpr" cmd += " -smfClient %s_smf" % node.name if "zebra" in servicenames: cmd += " -z" return (cmd, )
def generateconfiglinux(cls, node: CoreNode, filename: str) -> str: cfg = """\ #!/bin/sh # auto-generated by IPForward service (utility.py) %(sysctl)s -w net.ipv4.conf.all.forwarding=1 %(sysctl)s -w net.ipv4.conf.default.forwarding=1 %(sysctl)s -w net.ipv6.conf.all.forwarding=1 %(sysctl)s -w net.ipv6.conf.default.forwarding=1 %(sysctl)s -w net.ipv4.conf.all.send_redirects=0 %(sysctl)s -w net.ipv4.conf.default.send_redirects=0 %(sysctl)s -w net.ipv4.conf.all.rp_filter=0 %(sysctl)s -w net.ipv4.conf.default.rp_filter=0 """ % { "sysctl": SYSCTL } for iface in node.get_ifaces(): name = utils.sysctl_devname(iface.name) cfg += "%s -w net.ipv4.conf.%s.forwarding=1\n" % (SYSCTL, name) cfg += "%s -w net.ipv4.conf.%s.send_redirects=0\n" % (SYSCTL, name) cfg += "%s -w net.ipv4.conf.%s.rp_filter=0\n" % (SYSCTL, name) return cfg
def generate_config(cls, node: CoreNode, filename: str) -> str: """ Generate a dhcpd config file using the network address of each interface. """ cfg = """\ # auto-generated by DHCP service (utility.py) # NOTE: move these option lines into the desired pool { } block(s) below #option domain-name "test.com"; #option domain-name-servers 10.0.0.1; #option routers 10.0.0.1; log-facility local6; default-lease-time 600; max-lease-time 7200; ddns-update-style none; """ for iface in node.get_ifaces(control=False): cfg += "\n".join(map(cls.subnetentry, iface.ips())) cfg += "\n" return cfg
def generate_config(cls, node: CoreNode, filename: str) -> str: """ Returns config.boot configuration file text. Other services that depend on this will have generatexorpconfig() hooks that are invoked here. Filename currently ignored. """ cfg = "interfaces {\n" for iface in node.get_ifaces(): cfg += " interface %s {\n" % iface.name cfg += "\tvif %s {\n" % iface.name cfg += "".join(map(cls.addrstr, iface.ips())) cfg += cls.lladdrstr(iface) cfg += "\t}\n" cfg += " }\n" cfg += "}\n\n" for s in node.services: if cls.name not in s.dependencies: continue if not (isinstance(s, XorpService) or issubclass(s, XorpService)): continue cfg += s.generate_xorp_config(node) return cfg
def generate_config(cls, node: CoreNode, filename: str) -> str: """ Generate a startup script for SMF. Because nrlsmf does not daemonize, it can cause problems in some situations when launched directly using vcmd. """ cfg = "#!/bin/sh\n" cfg += "# auto-generated by nrl.py:NrlSmf.generateconfig()\n" comments = "" cmd = "nrlsmf instance %s_smf" % node.name servicenames = map(lambda x: x.name, node.services) ifaces = node.get_ifaces(control=False) if len(ifaces) == 0: return "" if "arouted" in servicenames: comments += "# arouted service is enabled\n" cmd += " tap %s_tap" % (node.name, ) cmd += " unicast %s" % cls.firstipv4prefix(node, 24) cmd += " push lo,%s resequence on" % ifaces[0].name if len(ifaces) > 0: if "NHDP" in servicenames: comments += "# NHDP service is enabled\n" cmd += " ecds " elif "OLSR" in servicenames: comments += "# OLSR service is enabled\n" cmd += " smpr " else: cmd += " cf " iface_names = map(lambda x: x.name, ifaces) cmd += ",".join(iface_names) cmd += " hash MD5" cmd += " log /var/log/nrlsmf.log" cfg += comments + cmd + " < /dev/null > /dev/null 2>&1 &\n\n" return cfg