initial pass at removing bsd and code related to using bsd nodes

This commit is contained in:
Blake J. Harnden 2018-03-07 12:54:19 -08:00
parent 4858151d7c
commit bc1e3e70c9
62 changed files with 720 additions and 18008 deletions

View file

@ -1,89 +0,0 @@
"""
netgraph.py: Netgraph helper functions; for now these are wrappers around
ngctl commands.
"""
import subprocess
from core import constants
from core.misc import utils
utils.check_executables([constants.NGCTL_BIN])
def createngnode(node_type, hookstr, name=None):
"""
Create a new Netgraph node of type and optionally assign name. The
hook string hookstr should contain two names. This is a string so
other commands may be inserted after the two names.
Return the name and netgraph ID of the new node.
:param node_type: node type to create
:param hookstr: hook string
:param name: name
:return: name and id
:rtype: tuple
"""
hook1 = hookstr.split()[0]
ngcmd = "mkpeer %s %s \n show .%s" % (node_type, hookstr, hook1)
cmd = [constants.NGCTL_BIN, "-f", "-"]
cmdid = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
# err will always be None
result, err = cmdid.communicate(input=ngcmd)
status = cmdid.wait()
if status > 0:
raise Exception("error creating Netgraph node %s (%s): %s" % (node_type, ngcmd, result))
results = result.split()
ngname = results[1]
ngid = results[5]
if name:
subprocess.check_call([constants.NGCTL_BIN, "name", "[0x%s]:" % ngid, name])
return ngname, ngid
def destroyngnode(name):
"""
Shutdown a Netgraph node having the given name.
:param str name: node name
:return: nothing
"""
subprocess.check_call([constants.NGCTL_BIN, "shutdown", "%s:" % name])
def connectngnodes(name1, name2, hook1, hook2):
"""
Connect two hooks of two Netgraph nodes given by their names.
:param str name1: name one
:param str name2: name two
:param str hook1: hook one
:param str hook2: hook two
:return: nothing
"""
node1 = "%s:" % name1
node2 = "%s:" % name2
subprocess.check_call([constants.NGCTL_BIN, "connect", node1, node2, hook1, hook2])
def ngmessage(name, msg):
"""
Send a Netgraph message to the node named name.
:param str name: node name
:param list msg: message
:return: nothing
"""
cmd = [constants.NGCTL_BIN, "msg", "%s:" % name] + msg
subprocess.check_call(cmd)
def ngloadkernelmodule(name):
"""
Load a kernel module by invoking kldstat. This is needed for the
ng_ether module which automatically creates Netgraph nodes when loaded.
:param str name: module name
:return: nothing
"""
utils.check_cmd(["kldload", name])

View file

@ -1,212 +0,0 @@
"""
nodes.py: definition of CoreNode classes and other node classes that inherit
from the CoreNode, implementing specific node types.
"""
import socket
import subprocess
from core import constants
from core import logger
from core.api import coreapi
from core.bsd.netgraph import connectngnodes
from core.bsd.netgraph import ngloadkernelmodule
from core.bsd.vnet import NetgraphNet
from core.bsd.vnet import NetgraphPipeNet
from core.bsd.vnode import JailNode
from core.enumerations import LinkTlvs
from core.enumerations import LinkTypes
from core.enumerations import NodeTypes
from core.enumerations import RegisterTlvs
from core.misc import ipaddress
from core.misc import utils
utils.check_executables([constants.IFCONFIG_BIN])
class CoreNode(JailNode):
apitype = NodeTypes.DEFAULT.value
class PtpNet(NetgraphPipeNet):
def tonodemsg(self, flags):
"""
Do not generate a Node Message for point-to-point links. They are
built using a link message instead.
"""
pass
def tolinkmsgs(self, flags):
"""
Build CORE API TLVs for a point-to-point link. One Link message
describes this network.
"""
tlvdata = ""
if len(self._netif) != 2:
return tlvdata
(if1, if2) = self._netif.items()
if1 = if1[1]
if2 = if2[1]
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.N1_NUMBER.value, if1.node.objid)
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.N2_NUMBER.value, if2.node.objid)
delay = if1.getparam("delay")
bw = if1.getparam("bw")
loss = if1.getparam("loss")
duplicate = if1.getparam("duplicate")
jitter = if1.getparam("jitter")
if delay is not None:
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.DELAY.value, delay)
if bw is not None:
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.BANDWIDTH.value, bw)
if loss is not None:
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.PER.value, str(loss))
if duplicate is not None:
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.DUP.value, str(duplicate))
if jitter is not None:
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.JITTER.value, jitter)
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.TYPE.value, self.linktype)
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE1_NUMBER.value, if1.node.getifindex(if1))
if if1.hwaddr:
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE1_MAC.value, if1.hwaddr)
for addr in if1.addrlist:
ip, sep, mask = addr.partition("/")
mask = int(mask)
if ipaddress.is_ipv4_address(ip):
family = socket.AF_INET
tlvtypeip = LinkTlvs.INTERFACE1_IP4.value
tlvtypemask = LinkTlvs.INTERFACE1_IP4_MASK
else:
family = socket.AF_INET6
tlvtypeip = LinkTlvs.INTERFACE1_IP6.value
tlvtypemask = LinkTlvs.INTERFACE1_IP6_MASK.value
ipl = socket.inet_pton(family, ip)
tlvdata += coreapi.CoreLinkTlv.pack(tlvtypeip, ipaddress.IpAddress(af=family, address=ipl))
tlvdata += coreapi.CoreLinkTlv.pack(tlvtypemask, mask)
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE2_NUMBER.value, if2.node.getifindex(if2))
if if2.hwaddr:
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE2_MAC.value, if2.hwaddr)
for addr in if2.addrlist:
ip, sep, mask = addr.partition("/")
mask = int(mask)
if ipaddress.is_ipv4_address(ip):
family = socket.AF_INET
tlvtypeip = LinkTlvs.INTERFACE2_IP4.value
tlvtypemask = LinkTlvs.INTERFACE2_IP4_MASK
else:
family = socket.AF_INET6
tlvtypeip = LinkTlvs.INTERFACE2_IP6.value
tlvtypemask = LinkTlvs.INTERFACE2_IP6_MASK.value
ipl = socket.inet_pton(family, ip)
tlvdata += coreapi.CoreLinkTlv.pack(tlvtypeip, ipaddress.IpAddress(af=family, address=ipl))
tlvdata += coreapi.CoreLinkTlv.pack(tlvtypemask, mask)
msg = coreapi.CoreLinkMessage.pack(flags, tlvdata)
return [msg, ]
class SwitchNode(NetgraphNet):
ngtype = "bridge"
nghooks = "link0 link0\nmsg .link0 setpersistent"
apitype = NodeTypes.SWITCH.value
policy = "ACCEPT"
class HubNode(NetgraphNet):
ngtype = "hub"
nghooks = "link0 link0\nmsg .link0 setpersistent"
apitype = NodeTypes.HUB.value
policy = "ACCEPT"
class WlanNode(NetgraphNet):
ngtype = "wlan"
nghooks = "anchor anchor"
apitype = NodeTypes.WIRELESS_LAN.value
linktype = LinkTypes.WIRELESS.value
policy = "DROP"
def __init__(self, session, objid=None, name=None, start=True, policy=None):
NetgraphNet.__init__(self, session, objid, name, start, policy)
# wireless model such as basic range
self.model = None
# mobility model such as scripted
self.mobility = None
def attach(self, netif):
NetgraphNet.attach(self, netif)
if self.model:
netif.poshook = self.model.position_callback
if netif.node is None:
return
x, y, z = netif.node.position.get()
netif.poshook(netif, x, y, z)
def setmodel(self, model, config):
"""
Mobility and wireless model.
:param core.mobility.WirelessModel.cls model: model to set
:param dict config: configuration for model
:return:
"""
logger.info("adding model %s" % model.name)
if model.config_type == RegisterTlvs.WIRELESS.value:
self.model = model(session=self.session, objid=self.objid, values=config)
if self.model.position_callback:
for netif in self.netifs():
netif.poshook = self.model.position_callback
if netif.node is not None:
x, y, z = netif.node.position.get()
netif.poshook(netif, x, y, z)
self.model.setlinkparams()
elif model.config_type == RegisterTlvs.MOBILITY.value:
self.mobility = model(session=self.session, objid=self.objid, values=config)
class RJ45Node(NetgraphPipeNet):
apitype = NodeTypes.RJ45.value
policy = "ACCEPT"
def __init__(self, session, objid, name, start=True):
if start:
ngloadkernelmodule("ng_ether")
NetgraphPipeNet.__init__(self, session, objid, name, start)
if start:
self.setpromisc(True)
def shutdown(self):
self.setpromisc(False)
NetgraphPipeNet.shutdown(self)
def setpromisc(self, promisc):
p = "promisc"
if not promisc:
p = "-" + p
subprocess.check_call([constants.IFCONFIG_BIN, self.name, "up", p])
def attach(self, netif):
if len(self._netif) > 0:
raise ValueError("RJ45 networks support at most 1 network interface")
NetgraphPipeNet.attach(self, netif)
connectngnodes(self.ngname, self.name, self.gethook(), "lower")
class TunnelNode(NetgraphNet):
ngtype = "pipe"
nghooks = "upper lower"
apitype = NodeTypes.TUNNEL.value
policy = "ACCEPT"
BSD_NODES = {
NodeTypes.DEFAULT: CoreNode,
NodeTypes.SWITCH: SwitchNode,
NodeTypes.HUB: HubNode,
NodeTypes.WIRELESS_LAN: WlanNode,
NodeTypes.RJ45: RJ45Node,
NodeTypes.TUNNEL: TunnelNode,
NodeTypes.PEER_TO_PEER: PtpNet,
NodeTypes.CONTROL_NET: None
}

View file

@ -1,206 +0,0 @@
"""
vnet.py: NetgraphNet and NetgraphPipeNet classes that implement virtual networks
using the FreeBSD Netgraph subsystem.
"""
from core import logger
from core.bsd.netgraph import connectngnodes
from core.bsd.netgraph import createngnode
from core.bsd.netgraph import destroyngnode
from core.bsd.netgraph import ngmessage
from core.coreobj import PyCoreNet
class NetgraphNet(PyCoreNet):
ngtype = None
nghooks = ()
def __init__(self, session, objid=None, name=None, start=True, policy=None):
PyCoreNet.__init__(self, session, objid, name)
if name is None:
name = str(self.objid)
if policy is not None:
self.policy = policy
self.name = name
self.ngname = "n_%s_%s" % (str(self.objid), self.session.session_id)
self.ngid = None
self._netif = {}
self._linked = {}
self.up = False
if start:
self.startup()
def startup(self):
tmp, self.ngid = createngnode(node_type=self.ngtype, hookstr=self.nghooks, name=self.ngname)
self.up = True
def shutdown(self):
if not self.up:
return
self.up = False
while self._netif:
k, netif = self._netif.popitem()
if netif.pipe:
pipe = netif.pipe
netif.pipe = None
pipe.shutdown()
else:
netif.shutdown()
self._netif.clear()
self._linked.clear()
del self.session
destroyngnode(self.ngname)
def attach(self, netif):
"""
Attach an interface to this netgraph node. Create a pipe between
the interface and the hub/switch/wlan node.
(Note that the PtpNet subclass overrides this method.)
"""
if self.up:
pipe = self.session.addobj(cls=NetgraphPipeNet, start=True)
pipe.attach(netif)
hook = "link%d" % len(self._netif)
pipe.attachnet(self, hook)
PyCoreNet.attach(self, netif)
def detach(self, netif):
PyCoreNet.detach(self, netif)
def linked(self, netif1, netif2):
# check if the network interfaces are attached to this network
if self._netif[netif1] != netif1:
raise ValueError("inconsistency for netif %s" % netif1.name)
if self._netif[netif2] != netif2:
raise ValueError("inconsistency for netif %s" % netif2.name)
try:
linked = self._linked[netif1][netif2]
except KeyError:
linked = False
self._linked[netif1][netif2] = linked
return linked
def unlink(self, netif1, netif2):
if not self.linked(netif1, netif2):
return
msg = ["unlink", "{", "node1=0x%s" % netif1.pipe.ngid]
msg += ["node2=0x%s" % netif2.pipe.ngid, "}"]
ngmessage(self.ngname, msg)
self._linked[netif1][netif2] = False
def link(self, netif1, netif2):
if self.linked(netif1, netif2):
return
msg = ["link", "{", "node1=0x%s" % netif1.pipe.ngid]
msg += ["node2=0x%s" % netif2.pipe.ngid, "}"]
ngmessage(self.ngname, msg)
self._linked[netif1][netif2] = True
def linknet(self, net):
"""
Link this bridge with another by creating a veth pair and installing
each device into each bridge.
"""
raise NotImplementedError
def linkconfig(self, netif, bw=None, delay=None,
loss=None, duplicate=None, jitter=None, netif2=None):
"""
Set link effects by modifying the pipe connected to an interface.
"""
if not netif.pipe:
logger.warn("linkconfig for %s but interface %s has no pipe", self.name, netif.name)
return
return netif.pipe.linkconfig(netif, bw, delay, loss, duplicate, jitter, netif2)
class NetgraphPipeNet(NetgraphNet):
ngtype = "pipe"
nghooks = "upper lower"
def __init__(self, session, objid=None, name=None, start=True, policy=None):
NetgraphNet.__init__(self, session, objid, name, start, policy)
if start:
# account for Ethernet header
ngmessage(self.ngname, ["setcfg", "{", "header_offset=14", "}"])
def attach(self, netif):
"""
Attach an interface to this pipe node.
The first interface is connected to the "upper" hook, the second
connected to the "lower" hook.
"""
if len(self._netif) > 1:
raise ValueError("Netgraph pipes support at most 2 network interfaces")
if self.up:
hook = self.gethook()
connectngnodes(self.ngname, netif.localname, hook, netif.hook)
if netif.pipe:
raise ValueError("Interface %s already attached to pipe %s" % (netif.name, netif.pipe.name))
netif.pipe = self
self._netif[netif] = netif
self._linked[netif] = {}
def attachnet(self, net, hook):
"""
Attach another NetgraphNet to this pipe node.
"""
localhook = self.gethook()
connectngnodes(self.ngname, net.ngname, localhook, hook)
def gethook(self):
"""
Returns the first hook (e.g. "upper") then the second hook
(e.g. "lower") based on the number of connections.
"""
hooks = self.nghooks.split()
if len(self._netif) == 0:
return hooks[0]
else:
return hooks[1]
def linkconfig(self, netif, bw=None, delay=None,
loss=None, duplicate=None, jitter=None, netif2=None):
"""
Set link effects by sending a Netgraph setcfg message to the pipe.
"""
netif.setparam("bw", bw)
netif.setparam("delay", delay)
netif.setparam("loss", loss)
netif.setparam("duplicate", duplicate)
netif.setparam("jitter", jitter)
if not self.up:
return
params = []
upstream = []
downstream = []
if bw is not None:
if str(bw) == "0":
bw = "-1"
params += ["bandwidth=%s" % bw, ]
if delay is not None:
if str(delay) == "0":
delay = "-1"
params += ["delay=%s" % delay, ]
if loss is not None:
if str(loss) == "0":
loss = "-1"
upstream += ["BER=%s" % loss, ]
downstream += ["BER=%s" % loss, ]
if duplicate is not None:
if str(duplicate) == "0":
duplicate = "-1"
upstream += ["duplicate=%s" % duplicate, ]
downstream += ["duplicate=%s" % duplicate, ]
if jitter:
logger.warn("jitter parameter ignored for link %s", self.name)
if len(params) > 0 or len(upstream) > 0 or len(downstream) > 0:
setcfg = ["setcfg", "{", ] + params
if len(upstream) > 0:
setcfg += ["upstream={", ] + upstream + ["}", ]
if len(downstream) > 0:
setcfg += ["downstream={", ] + downstream + ["}", ]
setcfg += ["}", ]
ngmessage(self.ngname, setcfg)

View file

@ -1,386 +0,0 @@
"""
vnode.py: SimpleJailNode and JailNode classes that implement the FreeBSD
jail-based virtual node.
"""
import os
import subprocess
import threading
from core import constants
from core import logger
from core.bsd.netgraph import createngnode
from core.bsd.netgraph import destroyngnode
from core.coreobj import PyCoreNetIf
from core.coreobj import PyCoreNode
from core.misc import utils
utils.check_executables([constants.IFCONFIG_BIN, constants.VIMAGE_BIN])
class VEth(PyCoreNetIf):
def __init__(self, node, name, localname, mtu=1500, net=None,
start=True):
PyCoreNetIf.__init__(self, node=node, name=name, mtu=mtu)
# name is the device name (e.g. ngeth0, ngeth1, etc.) before it is
# installed in a node; the Netgraph name is renamed to localname
# e.g. before install: name = ngeth0 localname = n0_0_123
# after install: name = eth0 localname = n0_0_123
self.localname = localname
self.ngid = None
self.net = None
self.pipe = None
self.addrlist = []
self.hwaddr = None
self.up = False
self.hook = "ether"
if start:
self.startup()
def startup(self):
hookstr = "%s %s" % (self.hook, self.hook)
ngname, ngid = createngnode(node_type="eiface", hookstr=hookstr, name=self.localname)
self.name = ngname
self.ngid = ngid
subprocess.check_call([constants.IFCONFIG_BIN, ngname, "up"])
self.up = True
def shutdown(self):
if not self.up:
return
destroyngnode(self.localname)
self.up = False
def attachnet(self, net):
if self.net:
self.detachnet()
self.net = None
net.attach(self)
self.net = net
def detachnet(self):
if self.net is not None:
self.net.detach(self)
def addaddr(self, addr):
self.addrlist.append(addr)
def deladdr(self, addr):
self.addrlist.remove(addr)
def sethwaddr(self, addr):
self.hwaddr = addr
class TunTap(PyCoreNetIf):
"""
TUN/TAP virtual device in TAP mode
"""
def __init__(self, node, name, localname, mtu=None, net=None, start=True):
raise NotImplementedError
class SimpleJailNode(PyCoreNode):
def __init__(self, session, objid=None, name=None, nodedir=None):
PyCoreNode.__init__(self, session, objid, name)
self.nodedir = nodedir
self.pid = None
self.up = False
self.lock = threading.RLock()
self._mounts = []
def startup(self):
if self.up:
raise Exception("already up")
vimg = [constants.VIMAGE_BIN, "-c", self.name]
try:
os.spawnlp(os.P_WAIT, constants.VIMAGE_BIN, *vimg)
except OSError:
raise Exception("vimage command not found while running: %s" % vimg)
logger.info("bringing up loopback interface")
self.cmd([constants.IFCONFIG_BIN, "lo0", "127.0.0.1"])
logger.info("setting hostname: %s", self.name)
self.cmd(["hostname", self.name])
self.cmd([constants.SYSCTL_BIN, "vfs.morphing_symlinks=1"])
self.up = True
def shutdown(self):
if not self.up:
return
for netif in self.netifs():
netif.shutdown()
self._netif.clear()
del self.session
vimg = [constants.VIMAGE_BIN, "-d", self.name]
try:
os.spawnlp(os.P_WAIT, constants.VIMAGE_BIN, *vimg)
except OSError:
raise Exception("vimage command not found while running: %s" % vimg)
self.up = False
def cmd(self, args, wait=True):
if wait:
mode = os.P_WAIT
else:
mode = os.P_NOWAIT
tmp = subprocess.call([constants.VIMAGE_BIN, self.name] + args, cwd=self.nodedir)
if not wait:
tmp = None
if tmp:
logger.warn("cmd exited with status %s: %s", tmp, str(args))
return tmp
def cmdresult(self, args, wait=True):
cmdid, cmdin, cmdout, cmderr = self.popen(args)
result = cmdout.read()
result += cmderr.read()
cmdin.close()
cmdout.close()
cmderr.close()
if wait:
status = cmdid.wait()
else:
status = 0
return status, result
def popen(self, args):
cmd = [constants.VIMAGE_BIN, self.name]
cmd.extend(args)
tmp = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE, cwd=self.nodedir)
return tmp, tmp.stdin, tmp.stdout, tmp.stderr
def icmd(self, args):
return os.spawnlp(os.P_WAIT, constants.VIMAGE_BIN, constants.VIMAGE_BIN, self.name, *args)
def term(self, sh="/bin/sh"):
return os.spawnlp(os.P_WAIT, "xterm", "xterm", "-ut",
"-title", self.name, "-e", constants.VIMAGE_BIN, self.name, sh)
def termcmdstring(self, sh="/bin/sh"):
"""
We add "sudo" to the command string because the GUI runs as a
normal user.
"""
return "cd %s && sudo %s %s %s" % (self.nodedir, constants.VIMAGE_BIN, self.name, sh)
def shcmd(self, cmdstr, sh="/bin/sh"):
return self.cmd([sh, "-c", cmdstr])
def boot(self):
pass
def mount(self, source, target):
source = os.path.abspath(source)
logger.info("mounting %s at %s", source, target)
self.addsymlink(path=target, file=None)
def umount(self, target):
logger.info("unmounting %s", target)
def newveth(self, ifindex=None, ifname=None, net=None):
self.lock.acquire()
try:
if ifindex is None:
ifindex = self.newifindex()
if ifname is None:
ifname = "eth%d" % ifindex
sessionid = self.session.short_session_id()
name = "n%s_%s_%s" % (self.objid, ifindex, sessionid)
localname = name
ifclass = VEth
veth = ifclass(node=self, name=name, localname=localname,
mtu=1500, net=net, start=self.up)
if self.up:
# install into jail
subprocess.check_call([constants.IFCONFIG_BIN, veth.name, "vnet", self.name])
# rename from "ngeth0" to "eth0"
self.cmd([constants.IFCONFIG_BIN, veth.name, "name", ifname])
veth.name = ifname
try:
self.addnetif(veth, ifindex)
except:
veth.shutdown()
del veth
raise
return ifindex
finally:
self.lock.release()
def sethwaddr(self, ifindex, addr):
self._netif[ifindex].sethwaddr(addr)
if self.up:
self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), "link", str(addr)])
def addaddr(self, ifindex, addr):
if self.up:
if ":" in addr:
family = "inet6"
else:
family = "inet"
self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), family, "alias", str(addr)])
self._netif[ifindex].addaddr(addr)
def deladdr(self, ifindex, addr):
try:
self._netif[ifindex].deladdr(addr)
except ValueError:
logger.warn("trying to delete unknown address: %s", addr)
if self.up:
if ":" in addr:
family = "inet6"
else:
family = "inet"
self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), family, "-alias",
str(addr)])
valid_deladdrtype = ("inet", "inet6", "inet6link")
def delalladdr(self, ifindex, addrtypes=valid_deladdrtype):
addr = self.getaddr(self.ifname(ifindex), rescan=True)
for t in addrtypes:
if t not in self.valid_deladdrtype:
raise ValueError("addr type must be in: " + " ".join(self.valid_deladdrtype))
for a in addr[t]:
self.deladdr(ifindex, a)
# update cached information
self.getaddr(self.ifname(ifindex), rescan=True)
def ifup(self, ifindex):
if self.up:
self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), "up"])
def newnetif(self, net=None, addrlist=[], hwaddr=None,
ifindex=None, ifname=None):
self.lock.acquire()
try:
ifindex = self.newveth(ifindex=ifindex, ifname=ifname, net=net)
if net is not None:
self.attachnet(ifindex, net)
if hwaddr:
self.sethwaddr(ifindex, hwaddr)
for addr in utils.make_tuple(addrlist):
self.addaddr(ifindex, addr)
self.ifup(ifindex)
return ifindex
finally:
self.lock.release()
def attachnet(self, ifindex, net):
self._netif[ifindex].attachnet(net)
def detachnet(self, ifindex):
self._netif[ifindex].detachnet()
def addfile(self, srcname, filename):
shcmd = 'mkdir -p $(dirname "%s") && mv "%s" "%s" && sync' % (filename, srcname, filename)
self.shcmd(shcmd)
def getaddr(self, ifname, rescan=False):
return None
def addsymlink(self, path, file):
"""
Create a symbolic link from /path/name/file ->
/tmp/pycore.nnnnn/@.conf/path.name/file
"""
dirname = path
if dirname and dirname[0] == "/":
dirname = dirname[1:]
dirname = dirname.replace("/", ".")
if file:
pathname = os.path.join(path, file)
sym = os.path.join(self.session.session_dir, "@.conf", dirname, file)
else:
pathname = path
sym = os.path.join(self.session.session_dir, "@.conf", dirname)
if os.path.islink(pathname):
if os.readlink(pathname) == sym:
# this link already exists - silently return
return
os.unlink(pathname)
else:
if os.path.exists(pathname):
logger.warn("did not create symlink for %s since path exists on host", pathname)
return
logger.info("creating symlink %s -> %s", pathname, sym)
os.symlink(sym, pathname)
class JailNode(SimpleJailNode):
def __init__(self, session, objid=None, name=None, nodedir=None, bootsh="boot.sh", start=True):
super(JailNode, self).__init__(session=session, objid=objid, name=name, nodedir=nodedir)
self.bootsh = bootsh
if not start:
return
# below here is considered node startup/instantiation code
self.makenodedir()
self.startup()
def boot(self):
self.session.services.bootnodeservices(self)
def validate(self):
self.session.services.validatenodeservices(self)
def startup(self):
self.lock.acquire()
try:
super(JailNode, self).startup()
# self.privatedir("/var/run")
# self.privatedir("/var/log")
finally:
self.lock.release()
def shutdown(self):
if not self.up:
return
self.lock.acquire()
# services are instead stopped when session enters datacollect state
# self.session.services.stopnodeservices(self)
try:
super(JailNode, self).shutdown()
finally:
self.rmnodedir()
self.lock.release()
def privatedir(self, path):
if path[0] != "/":
raise ValueError, "path not fully qualified: " + path
hostpath = os.path.join(
self.nodedir,
os.path.normpath(path).strip("/").replace("/", ".")
)
try:
os.mkdir(hostpath)
except OSError:
pass
except Exception, e:
raise Exception, e
self.mount(hostpath, path)
def opennodefile(self, filename, mode="w"):
dirname, basename = os.path.split(filename)
# self.addsymlink(path=dirname, file=basename)
if not basename:
raise ValueError("no basename for filename: %s" % filename)
if dirname and dirname[0] == "/":
dirname = dirname[1:]
dirname = dirname.replace("/", ".")
dirname = os.path.join(self.nodedir, dirname)
if not os.path.isdir(dirname):
os.makedirs(dirname, mode=0755)
hostfilename = os.path.join(dirname, basename)
return open(hostfilename, mode)
def nodefile(self, filename, contents, mode=0644):
f = self.opennodefile(filename, "w")
f.write(contents)
os.chmod(f.name, mode)
f.close()
logger.info("created nodefile: %s; mode: 0%o", f.name, mode)

View file

@ -87,9 +87,7 @@ class CoreServices(ConfigurableManager):
name = "services"
config_type = RegisterTlvs.UTILITY.value
_invalid_custom_names = (
'core', 'api', 'bsd', 'emane', 'misc', 'netns', 'phys', 'services', 'xen'
)
_invalid_custom_names = ('core', 'api', 'emane', 'misc', 'netns', 'phys', 'services', 'xen')
def __init__(self, session):
"""
@ -763,7 +761,7 @@ class CoreServices(ConfigurableManager):
cfg = self.getservicefiledata(s, filename)
if cfg is None:
cfg = s.generateconfig(node, filename, services)
node.nodefile(filename, cfg)
fail_data = ""

View file

@ -298,8 +298,7 @@ class OlsrOrg(NrlService):
#######################################
### Linux specific OLSRd extensions ###
#######################################
# these parameters are only working on linux at the moment, but might become
# useful on BSD in the future
# these parameters are only working on linux at the moment
# SrcIpRoutes tells OLSRd to set the Src flag of host routes to the originator-ip
# of the node. In addition to this an additional localhost device is created
@ -516,7 +515,7 @@ LinkQualityFishEye 0
# - /lib, followed by /usr/lib
#
# the examples in this list are for linux, so check if the plugin is
# available if you use windows/BSD.
# available if you use windows.
# each plugin should have a README file in it's lib subfolder
# LoadPlugin "olsrd_txtinfo.dll"

View file

@ -40,10 +40,8 @@ class IPForwardService(UtilService):
def generateconfig(cls, node, filename, services):
if os.uname()[0] == "Linux":
return cls.generateconfiglinux(node, filename, services)
elif os.uname()[0] == "FreeBSD":
return cls.generateconfigbsd(node, filename, services)
else:
raise Exception, "unknown platform"
raise Exception("unknown platform")
@classmethod
def generateconfiglinux(cls, node, filename, services):
@ -67,17 +65,6 @@ class IPForwardService(UtilService):
cfg += "%s -w net.ipv4.conf.%s.rp_filter=0\n" % (constants.SYSCTL_BIN, name)
return cfg
@classmethod
def generateconfigbsd(cls, node, filename, services):
return """\
#!/bin/sh
# auto-generated by IPForward service (utility.py)
%s -w net.inet.ip.forwarding=1
%s -w net.inet6.ip6.forwarding=1
%s -w net.inet.icmp.bmcastecho=1
%s -w net.inet.icmp.icmplim=0
""" % (constants.SYSCTL_BIN, constants.SYSCTL_BIN, constants.SYSCTL_BIN, constants.SYSCTL_BIN)
class DefaultRouteService(UtilService):
_name = "DefaultRoute"
@ -108,10 +95,8 @@ class DefaultRouteService(UtilService):
else:
if os.uname()[0] == "Linux":
rtcmd = "ip route add default via"
elif os.uname()[0] == "FreeBSD":
rtcmd = "route add -%s" % fam
else:
raise Exception, "unknown platform"
raise Exception("unknown platform")
return "%s %s" % (rtcmd, net.min_addr())
@ -132,10 +117,8 @@ class DefaultMulticastRouteService(UtilService):
continue
if os.uname()[0] == "Linux":
rtcmd = "ip route add 224.0.0.0/4 dev"
elif os.uname()[0] == "FreeBSD":
rtcmd = "route add 224.0.0.0/4 -iface"
else:
raise Exception, "unknown platform"
raise Exception("unknown platform")
cfg += "%s %s\n" % (rtcmd, ifc.name)
cfg += "\n"
break
@ -176,21 +159,15 @@ class StaticRouteService(UtilService):
else:
if os.uname()[0] == "Linux":
rtcmd = "#/sbin/ip route add %s via" % dst
elif os.uname()[0] == "FreeBSD":
rtcmd = "#/sbin/route add -%s %s" % (fam, dst)
else:
raise Exception, "unknown platform"
raise Exception("unknown platform")
return "%s %s" % (rtcmd, net.min_addr())
class SshService(UtilService):
_name = "SSH"
if os.uname()[0] == "FreeBSD":
_configs = ("startsshd.sh", "sshd_config",)
_dirs = ()
else:
_configs = ("startsshd.sh", "/etc/ssh/sshd_config",)
_dirs = ("/etc/ssh", "/var/run/sshd",)
_configs = ("startsshd.sh", "/etc/ssh/sshd_config",)
_dirs = ("/etc/ssh", "/var/run/sshd",)
_startup = ("sh startsshd.sh",)
_shutdown = ("killall sshd",)
_validate = ()
@ -201,14 +178,9 @@ class SshService(UtilService):
Use a startup script for launching sshd in order to wait for host
key generation.
"""
if os.uname()[0] == "FreeBSD":
sshcfgdir = node.nodedir
sshstatedir = node.nodedir
sshlibdir = "/usr/libexec"
else:
sshcfgdir = cls._dirs[0]
sshstatedir = cls._dirs[1]
sshlibdir = "/usr/lib/openssh"
sshcfgdir = cls._dirs[0]
sshstatedir = cls._dirs[1]
sshlibdir = "/usr/lib/openssh"
if filename == "startsshd.sh":
return """\
#!/bin/sh

View file

@ -933,7 +933,7 @@ class Session(object):
"""
with self._objects_lock:
for obj in self.objects.itervalues():
# TODO: PyCoreNode is not the type to check, but there are two types, due to bsd and netns
# TODO: PyCoreNode is not the type to check
if isinstance(obj, nodes.PyCoreNode) and not nodeutils.is_node(obj, NodeTypes.RJ45):
# add a control interface if configured
logger.info("booting node: %s - %s", obj.objid, obj.name)