Esempio n. 1
0
    def run(self) -> int:
        try:
            with IPRoute() as ipr:
                links = ipr.get_links("all")
                routes = ipr.get_default_routes(family=AF_INET6)
        except Exception as e:
            LOG.exception(f"Failed to get list of valid interfaces: {e}")
            return -1

        for link in links:
            if link.get_attr("IFLA_IFNAME") != self.interface:
                continue

            self.interface_id = link["index"]
            break
        if not self.interface_id:
            LOG.error(f"Unable to find {self.interface} index")
            return 1

        for route in routes:
            multi_routes = route.get_attr("RTA_MULTIPATH")
            for mr in multi_routes:
                if mr["oif"] == self.interface_id:
                    return 0

        return 2
    def initdb(self, nl=None):
        '''
        Restart IPRoute channel, and create all the DB
        from scratch. Can be used when sync is lost.
        '''
        self.nl = nl or IPRoute()
        self.nl.monitor = True
        self.nl.bind(async=True)

        # resolvers
        self.interfaces = Dotkeys()
        self.routes = RoutingTables(ipdb=self)
        self.by_name = Dotkeys()
        self.by_index = Dotkeys()

        # caches
        self.ipaddr = {}
        self.neighbors = {}

        # load information
        links = self.nl.get_links()
        for link in links:
            self.device_put(link, skip_slaves=True)
        for link in links:
            self.update_slaves(link)
        self.update_addr(self.nl.get_addr())
        self.update_neighbors(self.nl.get_neighbors())
        routes = self.nl.get_routes()
        self.update_routes(routes)
Esempio n. 3
0
    def run(self):
        nat = {}
        clients = []

        srv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        srv.bind((self.addr, self.port))
        ipr = IPRoute()
        ipr.bind()

        poll = select.poll()
        poll.register(ipr, select.POLLIN | select.POLLPRI)
        poll.register(srv, select.POLLIN | select.POLLPRI)

        while True:
            events = poll.poll()
            for (fd, event) in events:
                if fd == ipr.fileno():
                    bufsize = ipr.getsockopt(socket.SOL_SOCKET,
                                             socket.SO_RCVBUF) // 2
                    data = ipr.recv(bufsize)
                    cookie = struct.unpack('I', data[8:12])[0]
                    if cookie == 0:
                        for address in clients:
                            srv.sendto(data, address)
                    else:
                        srv.sendto(data, nat[cookie])
                else:
                    data, address = srv.recvfrom(16384)
                    if data is None:
                        clients.remove(address)
                        continue
                    cookie = struct.unpack('I', data[8:12])[0]
                    nat[cookie] = address
                    ipr.sendto(data, (0, 0))
Esempio n. 4
0
 def __init__(self, ns_info):
     self.__ns_info = ns_info
     self.name = ns_info['name']
     self.ip = IPRoute()
     self.__interfaces = {}
     self.__bridges = {}
     self.logger_topo = None
Esempio n. 5
0
 def __init__(self, vswitch_instance, ns_info):
     self.__ns_info = ns_info
     self.name = ns_info['name']
     self.ip = IPRoute()
     # self.ipdb = IPDB(nl=NetNS(self.name))
     self.main_ipdb = IPDB()
     self.__vswitch = vswitch_instance
Esempio n. 6
0
    def initdb(self):

        # flush all the DB objects
        with self.exclusive:

            # explicitly cleanup object references
            for event in tuple(self._event_map):
                del self._event_map[event]

            self._flush_db()

            # if the command socket is not provided, create it
            if self._nl_own:
                if self.nl is not None:
                    self.nl.close()
                self.nl = IPRoute(sndbuf=self._sndbuf,
                                  rcvbuf=self._rcvbuf,
                                  async_qsize=0)  # OBS: legacy design
            # setup monitoring socket
            if self.mnl is not None:
                self._flush_mnl()
                self.mnl.close()
            self.mnl = self.nl.clone()
            try:
                self.mnl.bind(groups=self.nl_bind_groups,
                              async_cache=self._nl_async)
            except:
                self.mnl.close()
                if self._nl_own is None:
                    self.nl.close()
                raise

            # explicitly cleanup references
            for key in tuple(self._deferred):
                del self._deferred[key]

            for module in self._plugins:
                if (module.groups & self.nl_bind_groups) != module.groups:
                    continue
                for plugin in module.spec:
                    self._deferred[plugin['name']] = module.spec
                    if plugin['name'] in self._loaded:
                        delattr(self, plugin['name'])
                        self._loaded.remove(plugin['name'])

            # start service threads
            for tspec in (('_mthread', '_serve_main', 'IPDB main event loop'),
                          ('_cthread', '_serve_cb', 'IPDB cb event loop')):
                tg = getattr(self, tspec[0], None)
                if not getattr(tg, 'is_alive', lambda: False)():
                    tx = threading.Thread(name=tspec[2],
                                          target=getattr(self, tspec[1]))
                    setattr(self, tspec[0], tx)
                    tx.setDaemon(True)
                    tx.start()
Esempio n. 7
0
def address_exists(cls, config, value):
    ip = IPRoute()
    if value.version == 4:
        family = socket.AF_INET
    elif value.version == 6:
        family = socket.AF_INET6
    else:
        raise AssertionError("Unknown version {}".format(value.version))
    if ip.get_addr(family=family, address=value.ip, prefixlen=value.prefixlen):
        raise OptionCheckError("No such address {}".format(value),
                               option=cls.__name__)
Esempio n. 8
0
def connection_down(parsed_args):
    ipsec_connection = load_ipsec_connection(parsed_args)
    connection_name = ipsec_connection['name']
    ip_route = IPRoute()
    if is_connection_up(ip_route, ipsec_connection):
        ipsec_result = ipsec('down', connection_name)
        if ipsec_result.status != 0:
            raise DockerIPSecError('Failed to disconnect VPN: {0}\n{1}'.format(
                connection_name, ipsec_result.output))

    filter_func = functools.partial(comment_matches_ipsec_connection,
                                    connection_name)
    remove_iptables_rules(filter_func)
Esempio n. 9
0
def add_docker_networks(parsed_args):
    ipsec_connection = load_ipsec_connection(parsed_args)
    connection_name = ipsec_connection['name']
    docker_networks = parsed_args.dockerNetworks

    docker_client = docker.DockerClient()
    docker_network_to_ip_network = functools.partial(
        ip_network_for_docker_network, docker_client)
    docker_ip_networks = tuple(
        map(docker_network_to_ip_network, docker_networks))
    ip_route = IPRoute()
    if not is_connection_up(ip_route, ipsec_connection):
        raise DockerIPSecError(
            'IPSec connection {0} is not connected!'.format(connection_name))

    add_ip_networks(ip_route, docker_ip_networks, connection_name)
Esempio n. 10
0
    def create_interface(self):
        ifname = self.__intf_info["ifname"]
        IP_ROUTE = IPRoute()
        if len(IP_ROUTE.link_lookup(ifname=ifname)) > 0:
            self.logger_topo.warning(
                "ip link {} exists so not create it.".format(ifname))
            IP_ROUTE.close()
            return

        if self.__peer:
            if len(IP_ROUTE.link_lookup(ifname=self.__peer)) > 0:
                self.logger_topo.warning(
                    "ip link {} exists so not create it.".format(ifname))
                IP_ROUTE.close()
                return
        else:
            # Close IP_ROUTE first anyway
            IP_ROUTE.close()
            ps_intf = r"^\d+: (?P<intf>[\w-]+): "
            p_intf = re.compile(ps_intf, re.MULTILINE)
            _, out, _ = exec_cmd_in_namespace(self.__namespace, ["ip", "link"])
            m_intf = p_intf.findall(out)
            if ifname in m_intf:
                self.logger_topo.warning(
                    "ip link {} exists in namespace {} so not create it.".
                    format(ifname, self.__namespace))
                return

        MAIN_IPDB = IPDB()
        MAIN_IPDB.create(ifname=ifname,
                         kind="veth" if self.__peer else "dummy",
                         peer=self.__peer).commit()
        with MAIN_IPDB.interfaces[ifname] as veth:
            try:
                veth.net_ns_fd = self.__namespace
            except netlink.exceptions.NetlinkError as e:
                MAIN_IPDB.release()
                if e.code == 17:  # "File exists"
                    pass
                else:
                    raise e

        MAIN_IPDB.release()
        self.logger_topo.info(
            "interface {} in namespace {} is created, peer: {}.".format(
                ifname, self.__namespace, self.__peer))
Esempio n. 11
0
    def initdb(self, nl=None):
        '''
        Restart IPRoute channel, and create all the DB
        from scratch. Can be used when sync is lost.
        '''
        self.nl = nl or IPRoute()

        # resolvers
        self.interfaces = Dotkeys()
        self.routes = RoutingTableSet(ipdb=self,
                                      ignore_rtables=self._ignore_rtables)
        self.by_name = View(src=self.interfaces,
                            constraint=lambda k, v: isinstance(k, basestring))
        self.by_index = View(src=self.interfaces,
                             constraint=lambda k, v: isinstance(k, int))

        # caches
        self.ipaddr = {}
        self.neighbours = {}

        try:
            self.nl.bind(async=self._nl_async)
            # load information
            links = self.nl.get_links()
            for link in links:
                self.device_put(link, skip_slaves=True)
            for link in links:
                self.update_slaves(link)
            # bridge info
            links = self.nl.get_vlans()
            for link in links:
                self.update_dev(link)
            #
            self.update_addr(self.nl.get_addr())
            self.update_neighbours(self.nl.get_neighbours())
            routes4 = self.nl.get_routes(family=AF_INET)
            routes6 = self.nl.get_routes(family=AF_INET6)
            self.update_routes(routes4)
            self.update_routes(routes6)
        except Exception as e:
            try:
                self.nl.close()
            except:
                pass
            raise e
Esempio n. 12
0
    def create(self):
        """
        Main function to build all infrasim virtual network referring to
        resolved topology
        """
        self.__load()

        self.logger_topo.info("[Define openvswitches]")
        for _, ovs in self.__openvswitch.items():
            ovs.add_vswitch()
            ovs.add_all_ports()
            # FIXME: substitute for below code
            # self.__vswitch_ex.set_interface("phy-br-ex", "int-br-ex")
            # self.__vswitch_int.set_interface("int-br-ex", "phy-br-ex")
            ovs.add_interface_d()

        self.logger_topo.info("[Define namespaces]")
        for _, ns in self.__namespace.items():
            ns.create_namespace()
            ns.create_all_interfaces(ref=self.__connection)

        self.logger_topo.info("[Set openvswitch ports up]")
        IP_ROUTE = IPRoute()
        for _, ovs in self.__openvswitch.items():
            idx = IP_ROUTE.link_lookup(ifname=ovs.name)[0]
            IP_ROUTE.link("set", index=idx, state="up")
            self.logger_topo.info("set openvswitch {} up.".format(ovs.name))

        for _, ovs_port in self.__connection.items():
            idx = IP_ROUTE.link_lookup(ifname=ovs_port)[0]
            IP_ROUTE.link("set", index=idx, state="up")
            self.logger_topo.info("set port {} up.".format(ovs_port))

        self.logger_topo.info("[Set namespace interfaces up]")
        for _, ns in self.__namespace.items():
            ns.create_interface_d()
            ns.link_up_all()
            ns.create_routes()

        self.logger_topo.info("[Setup portforward]")
        self.__port_forward.build()

        IP_ROUTE.close()
Esempio n. 13
0
def connection_up(parsed_args):
    ipsec_connection = load_ipsec_connection(parsed_args)
    connection_name = ipsec_connection['name']
    docker_networks = parsed_args.dockerNetworks
    if len(docker_networks) > 0:
        docker_client = docker.DockerClient()
        docker_network_to_ip_network = functools.partial(
            ip_network_for_docker_network, docker_client)
        docker_ip_networks = tuple(
            map(docker_network_to_ip_network, docker_networks))
    else:
        docker_ip_networks = tuple()

    ip_route = IPRoute()
    if not is_connection_up(ip_route, ipsec_connection):
        ipsec_result = ipsec('up', connection_name)
        if ipsec_result.status != 0:
            raise DockerIPSecError('Failed to connect VPN: {0}\n{1}'.format(
                connection_name, ipsec_result.output))

    add_ip_networks(ip_route, docker_ip_networks, connection_name)
Esempio n. 14
0
    def initdb(self):
        # common event map, empty by default, so all the
        # events aer just ignored
        self.release(complete=False)
        self._stop = False
        # explicitly cleanup object references
        for event in tuple(self._event_map):
            del self._event_map[event]

        # if the command socket is not provided, create it
        if self._nl_own:
            self.nl = IPRoute()
        # setup monitoring socket
        self.mnl = self.nl.clone()
        try:
            self.mnl.bind(groups=self.nl_bind_groups, async=self._nl_async)
        except:
            self.mnl.close()
            if self._nl_own is None:
                self.nl.close()
            raise

        # explicitly cleanup references
        for key in tuple(self._deferred):
            del self._deferred[key]

        for module in self._plugins:
            if (module.groups & self.nl_bind_groups) != module.groups:
                continue
            for plugin in module.spec:
                self._deferred[plugin['name']] = module.spec
                if plugin['name'] in self._loaded:
                    delattr(self, plugin['name'])
                    self._loaded.remove(plugin['name'])

        # start the monitoring thread
        self._mthread = threading.Thread(name="IPDB event loop",
                                         target=self.serve_forever)
        self._mthread.setDaemon(True)
        self._mthread.start()
Esempio n. 15
0
def enable_static_routes(static_routes):
    """
    启用默认路由
    :param static_routes: list 默认路由列表
    """
    with IPRoute() as route:
        for r in static_routes:
            if_id = route.link_lookup(
                ifname=r['interface'])[0] if 'interface' in r else None
            args = {
                'dst': r['net'],
                'oif': if_id,
                'gateway': r.get('gateway'),
                'metric': 1
            }
            args = {k: v for k, v in args.iteritems() if v}
            try:
                route.route('add', **args)
            except NetlinkError as e:
                if e.code == 17:
                    continue
                else:
                    raise
def main():
    """
    Program entry point when run interactively.
    """

    # prepare option parser
    parser = ArgumentParser(usage="usage: %(prog)s [options]",
                            description="Executes a UDP broadcast to test for "
                            "connectivity")
    parser.add_argument("-i",
                        "--interface",
                        dest="interface",
                        default="poprow0",
                        action="store",
                        metavar="ifname",
                        help="Interface to use [default: %(default)s]")
    parser.add_argument("-p",
                        "--port",
                        dest="port",
                        type=int,
                        default=12345,
                        action="store",
                        help="UDP port [default: %(default)s]",
                        metavar="PORT")
    parser.add_argument(
        "-n",
        "--count",
        dest="count",
        type=int,
        default=100,
        action="store",
        help="Number of packets to send [default: %(default)s]",
        metavar="COUNT")
    parser.add_argument("-t",
                        "--interval",
                        dest="interval",
                        type=float,
                        default=0.2,
                        action="store",
                        help="Packet interval [default: %(default)s]")
    parser.add_argument("-v", "--verbose", dest="verbose", action="store_true")

    # parse options
    args = parser.parse_args()

    # copy options
    interface = args.interface
    port = args.port
    count = args.count
    interval = args.interval
    verbose = args.verbose

    ip = IPRoute()
    if_index = ip.link_lookup(ifname=interface)

    if len(if_index) == 0:
        print >> sys.stderr, "Can't find interface %s" % interface
        sys.exit(1)

    # from the given interface find unicast and broadcast addresses
    if_info = ip.get_addr(index=if_index[0])[0]
    address = if_info.get_attr("IFA_ADDRESS")
    netmask = if_info["prefixlen"]
    network = ipaddr.IPv4Network("%s/%d" % (address, netmask))
    broadcast = str(network.broadcast)

    # get hostname as additional information to send in the packets
    hostname = socket.gethostname()

    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)

    i = 0
    run = True
    while i < count and run:
        try:
            payload = "POPROWPING %d %s" % (i, hostname)
            if verbose:
                print >> sys.stderr, "Sending packet #%d to %s:%d" % \
                      (i+1, broadcast, port)
            sock.sendto(payload, (broadcast, port))
            i += 1
            time.sleep(interval)
        except SystemExit:
            run = False
            if verbose:
                print >> sys.stderr, "Catching SystemExit. Quitting"
        except KeyboardInterrupt:
            run = False
            if verbose:
                print >> sys.stderr, "Keyboard Interrupt. Quitting"
        except:
            run = False
            if verbose:
                print >> sys.stderr, "Error while sending packet. Quitting"

    sock.close()
Esempio n. 17
0
def main():
    """
    Program entry point when run interactively.
    """

    # prepare option parser
    parser = ArgumentParser(usage="usage: %(prog)s [options]",
                            description="Listens to UDP broadcasts to test for "
                                        "connectivity")
    parser.add_argument("-i", "--interface", dest="interface",
                        default="poprow0", action="store", metavar="ifname",
                        help="Interface to use [default: %(default)s]")
    parser.add_argument("-p", "--port", dest="port", type=int, default=12345,
                        action="store", help="UDP port [default: %(default)s]",
                        metavar="PORT")
    parser.add_argument("-f", "--filename", dest="filename", default="",
                        action="store",
                        help="Output file where to store results [default: "
                             "stdout]", metavar="FILENAME")
    parser.add_argument("-v", "--verbose", dest="verbose", action="store_true")
    parser.add_argument("-d", "--daemon", dest="daemon", action="store_true",
                        help="Daemonize the process")


    # parse options
    args = parser.parse_args()

    # copy options
    interface = args.interface
    port = args.port
    filename = args.filename
    verbose = args.verbose
    daemon = args.daemon

    ip = IPRoute()
    if_index = ip.link_lookup(ifname=interface)

    if len(if_index) == 0:
        print >> sys.stderr, "Can't find interface %s" % interface
        sys.exit(1)

    # from the given interface find unicast and broadcast addresses
    if_info = ip.get_addr(index=if_index[0])[0]
    address = if_info.get_attr("IFA_ADDRESS")
    netmask = if_info["prefixlen"]
    network = ipaddr.IPv4Network("%s/%d" % (address, netmask))
    broadcast = str(network.broadcast)

    # get hostname as additional information for the log file
    hostname = socket.gethostname()

    if not daemon:
        signal.signal(signal.SIGTERM, signal_handler)
    else:
        daemonize()

    # setup output file
    if filename == "":
        outfile = sys.stdout
    else:
        outfile = open(filename, "w")

    if verbose:
        print >> sys.stderr, "Host with IP %s listening for packets on " \
                             "broadcast IP %s" % (address, broadcast)

    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind((broadcast, port))

    run = True
    while run:
        try:
            datagram = sock.recvfrom(1024)
            payload = datagram[0].split(' ')
            src = datagram[1][0]
            src_port = datagram[1][1]
            # check that this is really our app message
            if payload[0] != "POPROWPING":
                continue
            count = int(payload[1])
            remote_host = payload[2]
            if verbose:
                print >> sys.stderr, "Received packet #%d from %s:%d" % \
                      (count, src, src_port)
            outfile.write("%s,%s,%s,%s,%d\n" % (hostname, address, remote_host,
                                                src, count))
            outfile.flush()
        except SystemExit:
            run = False
            if verbose:
                print >> sys.stderr, "Catching SystemExit. Quitting"
        except KeyboardInterrupt:
            run = False
            if verbose:
                print >> sys.stderr, "Keyboard Interrupt. Quitting"
        except:
            run = False
            if verbose:
                print >> sys.stderr, "Error while receiving packet. Quitting"

    sock.close()
    outfile.flush()
    outfile.close()
Esempio n. 18
0
def NetNServer(netns, rcvch, cmdch, flags=os.O_CREAT):
    '''
    The netns server supposed to be started automatically by NetNS.
    It has two communication channels: one simplex to forward incoming
    netlink packets, `rcvch`, and other synchronous duplex to get
    commands and send back responses, `cmdch`.

    Channels should support standard socket API, should be compatible
    with poll/select and should be able to transparently pickle objects.
    NetNS uses `multiprocessing.Pipe` for this purpose, but it can be
    any other implementation with compatible API.

    The first parameter, `netns`, is a netns name. Depending on the
    `flags`, the netns can be created automatically. The `flags` semantics
    is exactly the same as for `open(2)` system call.

    ...

    The server workflow is simple. The startup sequence::

        1. Create or open a netns.

        2. Start `IPRoute` instance. It will be used only on the low level,
           the `IPRoute` will not parse any packet.

        3. Start poll/select loop on `cmdch` and `IPRoute`.

    On the startup, the server sends via `cmdch` the status packet. It can be
    `None` if all is OK, or some exception.

    Further data handling, depending on the channel, server side::

        1. `IPRoute`: read an incoming netlink packet and send it unmodified
           to the peer via `rcvch`. The peer, polling `rcvch`, can handle
           the packet on its side.

        2. `cmdch`: read tuple (cmd, argv, kwarg). If the `cmd` starts with
           "send", then take `argv[0]` as a packet buffer, treat it as one
           netlink packet and substitute PID field (offset 12, uint32) with
           its own. Strictly speaking, it is not mandatory for modern netlink
           implementations, but it is required by the protocol standard.

    '''
    signal.signal(signal.SIGINT, signal.SIG_IGN)
    try:
        nsfd = setns(netns, flags)
    except OSError as e:
        cmdch.send(e)
        return e.errno
    except Exception as e:
        cmdch.send(OSError(errno.ECOMM, str(e), netns))
        return 255

    #
    try:
        ipr = IPRoute()
        rcvch_lock = ipr._sproxy.lock
        ipr._s_channel = rcvch
        poll = select.poll()
        poll.register(ipr, select.POLLIN | select.POLLPRI)
        poll.register(cmdch, select.POLLIN | select.POLLPRI)
    except Exception as e:
        cmdch.send(e)
        return 255

    # all is OK so far
    cmdch.send(None)
    # 8<-------------------------------------------------------------
    while True:
        events = poll.poll()
        for (fd, event) in events:
            if fd == ipr.fileno():
                bufsize = ipr.getsockopt(SOL_SOCKET, SO_RCVBUF) // 2
                with rcvch_lock:
                    rcvch.send(ipr.recv(bufsize))
            elif fd == cmdch.fileno():
                try:
                    cmdline = cmdch.recv()
                    if cmdline is None:
                        poll.unregister(ipr)
                        poll.unregister(cmdch)
                        ipr.close()
                        os.close(nsfd)
                        return
                    (cmd, argv, kwarg) = cmdline
                    if cmd[:4] == 'send':
                        # Achtung
                        #
                        # It's a hack, but we just have to do it: one
                        # must use actual pid in netlink messages
                        #
                        # FIXME: there can be several messages in one
                        # call buffer; but right now we can ignore it
                        msg = argv[0][:12]
                        msg += struct.pack("I", os.getpid())
                        msg += argv[0][16:]
                        argv = list(argv)
                        argv[0] = msg
                    cmdch.send(getattr(ipr, cmd)(*argv, **kwarg))
                except Exception as e:
                    e.tb = traceback.format_exc()
                    cmdch.send(e)
Esempio n. 19
0
import os
import shutil
import json
import re
import subprocess
import yaml
from pyroute2 import netlink
from pyroute2 import IPDB
from pyroute2 import netns
from pyroute2.iproute import IPRoute

IP_ROUTE = IPRoute()
MAIN_IPDB = IPDB()


def start_process(args):
    """
    Shell command agent
    """
    try:
        p = subprocess.Popen(args,
                             stdin=subprocess.PIPE,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
        out, err = p.communicate()
        return (p.returncode, out, err)
    except OSError:
        return (-1, None, None)


def exec_cmd_in_namespace(ns, cmd):
Esempio n. 20
0
# -*- coding: utf-8 -*-

from __future__ import absolute_import, division, print_function, unicode_literals

import os
import ipaddress
import threading

#import pyroute2
# for pyinstaller
# again for nuitka
from pyroute2.iproute import IPRoute


IP = IPRoute()


def _transform_attrs_inplace(result):
    for item in result:
        item['attrs'] = dict(item['attrs'])
    return result


def is_physical_iface(iface):
    device_path = os.readlink(os.path.join('/sys/class/net', iface))
    return not device_path.startswith('../../devices/virtual/')


def get_physical_ifaces():
    ifaces = os.listdir('/sys/class/net')
    return [iface for iface in ifaces if is_physical_iface(iface)]