Exemple #1
0
 def alias_to_addr(self, alias):
     addr = netif.InterfaceAddress()
     ip = ipaddress.ip_interface('{}/{}'.format(alias['address'], alias['netmask']))
     addr.af = getattr(netif.AddressFamily, 'INET6' if ':' in alias['address'] else 'INET')
     addr.address = ip.ip
     addr.netmask = ip.netmask
     addr.broadcast = ip.network.broadcast_address
     if 'vhid' in alias:
         addr.vhid = alias['vhid']
     return addr
Exemple #2
0
def convert_aliases(entity):
    for i in entity.get('aliases', []):
        addr = netif.InterfaceAddress()
        iface = ipaddress.ip_interface('{0}/{1}'.format(i['address'], i['netmask']))
        addr.af = getattr(netif.AddressFamily, i.get('type', 'INET'))
        addr.address = ipaddress.ip_address(i['address'])
        addr.netmask = iface.netmask
        addr.broadcast = iface.network.broadcast_address

        if i.get('broadcast'):
            addr.broadcast = ipaddress.ip_address(i['broadcast'])

        if i.get('dest-address'):
            addr.dest_address = ipaddress.ip_address(i['dest-address'])

        yield addr
Exemple #3
0
    def up(self):
        # Destroy old bridge (if exists)
        try:
            netif.destroy_interface(self.ifname)
        except OSError as err:
            if err.errno != errno.ENXIO:
                raise RuntimeError('Cannot destroy {0}: {1}'.format(self.ifname, str(err)))

        # Setup bridge
        self.bridge_if = netif.get_interface(netif.create_interface('bridge'))
        self.bridge_if.rename(self.ifname)
        self.bridge_if.description = 'containerd management network'
        self.bridge_if.add_address(netif.InterfaceAddress(
            netif.AddressFamily.INET,
            self.subnet
        ))
        self.bridge_if.up()

        self.dhcp_server.server_name = 'FreeNAS'
        self.dhcp_server.on_request = self.dhcp_request
        self.dhcp_server.start(self.ifname, self.subnet.ip)
        self.dhcp_server_thread = gevent.spawn(self.dhcp_worker)
    def run(self):
        vpn_state = self.dispatcher.call_sync('service.query', [('name', '=', 'openvpn')], {'single': True})
        node = ConfigNode('service.openvpn', self.configstore).__getstate__()

        if vpn_state['state'] != 'RUNNING':
            raise TaskException(errno.EPERM, 'For bridging VPN capabilities openvpn needs to be running.')

        if node['mode'] == 'psk':
            raise TaskException(errno.EPERM, 'Bridging VPN capabilities only in pki mode.')

        # This feels like a not so good solution - feel free to change
        tap_interfaces = netif.get_ifgroup('tap')

        for vpn_interface_name in tap_interfaces:
            tap_pids = system('/usr/bin/fuser', '/dev/' + vpn_interface_name)[0].split()
            if vpn_state['pid'] in tap_pids:
                    break

        try:
            vpn_interface = netif.get_interface(vpn_interface_name)

        except KeyError:
            raise TaskException(
                errno.EINVAL,
                '{0} interface does not exist - Verify OpenVPN status'.format(vpn_interface_name)
            )
        else:
            vpn_interface.up()

        default_interface = self.dispatcher.call_sync('networkd.configuration.get_default_interface')
        if not default_interface:
            raise TaskException(errno.EINVAL, 'No default interface configured. Verify network setup.')

        # Heavily inspired by containterd
        available_bridges = list(b for b in netif.list_interfaces().keys()
                                 if isinstance(netif.get_interface(b), netif.BridgeInterface))

        for b in available_bridges:
            bridge_interface = netif.get_interface(b, bridge=True)
            if default_interface in bridge_interface.members:
                try:
                    bridge_interface.add_member(vpn_interface_name)
                except FileExistsError:
                    pass

                break

        else:
            bridge_interface = netif.get_interface(netif.create_interface('bridge'))
            bridge_interface.rename('brg{0}'.format(len(available_bridges)))
            bridge_interface.description = 'OpenVPN bridge interface'
            bridge_interface.up()
            bridge_interface.add_member(default_interface)
            bridge_interface.add_member(vpn_interface_name)

        if node['server_bridge_extended']:
            subnet = ipaddress.ip_interface('{0}/{1}'.format(node['server_bridge_ip'],
                                                             node['server_bridge_netmask']))
            bridge_interface.add_address(netif.InterfaceAddress(
                netif.AddressFamily.INET,
                subnet
            ))
Exemple #5
0
        def bind(old_lease, lease):
            self.logger.info('{0} DHCP lease on {1} from {2}, valid for {3} seconds'.format(
                'Renewed' if old_lease else 'Acquired',
                interface,
                client.server_address,
                lease.lifetime,
                interface
            ))

            if old_lease is None or lease.client_ip != old_lease.client_ip:
                self.logger.info('Assigning IP address {0} to interface {1}'.format(lease.client_ip, interface))
                alias = lease.client_interface
                iface = netif.get_interface(interface)

                if old_lease:
                    try:
                        addr = first_or_default(lambda a: a.address == old_lease.client_ip, iface.addresses)
                        if addr:
                            iface.remove_address(addr)
                    except OSError as err:
                        self.logger.error('Cannot remove alias {0}: {1}'.format(old_lease.client_ip, err.strerror))

                try:
                    iface.add_address(netif.InterfaceAddress(netif.AddressFamily.INET, alias))
                except OSError as err:
                    self.logger.error('Cannot add alias to {0}: {1}'.format(interface, err.strerror))

            if lease.router and self.configstore.get('network.dhcp.assign_gateway'):
                try:
                    rtable = netif.RoutingTable()
                    newroute = default_route(lease.router)
                    if rtable.default_route_ipv4 != newroute:
                        if rtable.default_route_ipv4:
                            self.logger.info('DHCP default route changed from {0} to {1}'.format(
                                rtable.default_route_ipv4,
                                newroute
                            ))
                            rtable.delete(rtable.default_route_ipv4)
                            rtable.add(default_route(lease.router))
                        else:
                            self.logger.info('Adding default route via {0}'.format(lease.router))
                            rtable.add(default_route(lease.router))
                except OSError as err:
                    self.logger.error('Cannot configure default route: {0}'.format(err.strerror))

            if lease.dns_addresses and self.configstore.get('network.dhcp.assign_dns'):
                inp = []
                addrs = []
                proc = subprocess.Popen(
                    ['/sbin/resolvconf', '-a', interface],
                    stdout=subprocess.PIPE,
                    stdin=subprocess.PIPE
                )

                for i in lease.dns_addresses:
                    # Filter out bogus DNS server addresses
                    if str(i) in ('127.0.0.1', '0.0.0.0', '255.255.255.255'):
                        continue

                    inp.append('nameserver {0}'.format(i))
                    addrs.append(i)

                if lease.domain_name:
                    inp.append('search {0}'.format(lease.domain_name))

                proc.communicate('\n'.join(inp).encode('ascii'))
                proc.wait()
                self.client.emit_event('network.dns.configured', {
                    'addresses': addrs,
                })
                self.logger.info('Updated DNS configuration')
            else:
                subprocess.call(['/sbin/resolvconf', '-d', interface])
                self.client.emit_event('network.dns.configured', {
                    'addresses': [],
                })
                self.logger.info('Deleted DNS configuration')
Exemple #6
0
    def run(self):
        rtsock = netif.RoutingSocket()
        rtsock.open()

        self.build_cache()

        while True:
            message = rtsock.read_message()

            if type(message) is netif.InterfaceAnnounceMessage:
                args = {'name': message.interface}

                if message.type == netif.InterfaceAnnounceType.ARRIVAL:
                    self.context.interface_attached(message.interface)
                    self.client.emit_event('network.interface.attached', args)

                if message.type == netif.InterfaceAnnounceType.DEPARTURE:
                    self.context.interface_detached(message.interface)
                    self.client.emit_event('network.interface.detached', args)

                self.build_cache()

            if type(message) is netif.InterfaceInfoMessage:
                ifname = message.interface
                if self.mtu_cache[ifname] != message.mtu:
                    self.client.emit_event('network.interface.mtu_changed', {
                        'interface': ifname,
                        'old_mtu': self.mtu_cache[ifname],
                        'new_mtu': message.mtu
                    })

                if self.link_state_cache[ifname] != message.link_state:
                    if message.link_state == netif.InterfaceLinkState.LINK_STATE_DOWN:
                        self.context.logger.warn('Link down on interface {0}'.format(ifname))
                        self.client.emit_event('network.interface.link_down', {
                            'interface': ifname,
                        })

                    if message.link_state == netif.InterfaceLinkState.LINK_STATE_UP:
                        self.context.logger.warn('Link up on interface {0}'.format(ifname))
                        self.client.emit_event('network.interface.link_up', {
                            'interface': ifname,
                        })

                if self.flags_cache[ifname] != message.flags:
                    if (netif.InterfaceFlags.UP in self.flags_cache) and (netif.InterfaceFlags.UP not in message.flags):
                        self.client.emit_event('network.interface.down', {
                            'interface': ifname,
                        })

                    if (netif.InterfaceFlags.UP not in self.flags_cache) and (netif.InterfaceFlags.UP in message.flags):
                        self.client.emit_event('network.interface.up', {
                            'interface': ifname,
                        })

                    self.client.emit_event('network.interface.flags_changed', {
                        'interface': ifname,
                        'old_flags': [f.name for f in self.flags_cache[ifname]],
                        'new_flags': [f.name for f in message.flags]
                    })

                self.client.emit_event('network.interface.changed', {
                    'operation': 'update',
                    'ids': [ifname]
                })

                self.build_cache()

            if type(message) is netif.InterfaceAddrMessage:
                entity = self.context.datastore.get_by_id('network.interfaces', message.interface)
                if entity is None:
                    continue

                # Skip messagess with empty address
                if not message.address:
                    continue

                # Skip 0.0.0.0 aliases
                if message.address == ipaddress.IPv4Address('0.0.0.0'):
                    continue

                addr = netif.InterfaceAddress()
                addr.af = netif.AddressFamily.INET
                addr.address = message.address
                addr.netmask = message.netmask
                addr.broadcast = message.dest_address

                if message.type == netif.RoutingMessageType.NEWADDR:
                    self.context.logger.warn('New alias added to interface {0} externally: {1}/{2}'.format(
                        message.interface,
                        message.address,
                        message.netmask
                    ))

                if message.type == netif.RoutingMessageType.DELADDR:
                    self.context.logger.warn('Alias removed from interface {0} externally: {1}/{2}'.format(
                        message.interface,
                        message.address,
                        message.netmask
                    ))

                self.client.emit_event('network.interface.changed', {
                    'operation': 'update',
                    'ids': [entity['id']]
                })

            if type(message) is netif.RoutingMessage:
                if message.errno != 0:
                    continue

                if message.type == netif.RoutingMessageType.ADD:
                    self.context.logger.info('Route to {0} added'.format(describe_route(message.route)))
                    self.client.emit_event('network.route.added', message.__getstate__())
                    with self.context.cv:
                        if str(message.route.network) == '0.0.0.0':
                            self.context.default_interface = message.route.interface
                            self.context.cv.notify_all()

                if message.type == netif.RoutingMessageType.DELETE:
                    self.context.logger.info('Route to {0} deleted'.format(describe_route(message.route)))
                    self.client.emit_event('network.route.deleted', message.__getstate__())

        rtsock.close()