def get_config(): conf = Config() mroute = {'old_mroute': {}, 'mroute': {}} base_path = "protocols static multicast" if not (conf.exists(base_path) or conf.exists_effective(base_path)): return None conf.set_level(base_path) # Get multicast effective routes for route in conf.list_effective_nodes('route'): mroute['old_mroute'][route] = {} for next_hop in conf.list_effective_nodes( 'route {0} next-hop'.format(route)): mroute['old_mroute'][route].update({ next_hop: conf.return_value('route {0} next-hop {1} distance'.format( route, next_hop)) }) # Get multicast effective interface-routes for route in conf.list_effective_nodes('interface-route'): if not route in mroute['old_mroute']: mroute['old_mroute'][route] = {} for next_hop in conf.list_effective_nodes( 'interface-route {0} next-hop-interface'.format(route)): mroute['old_mroute'][route].update({ next_hop: conf.return_value( 'interface-route {0} next-hop-interface {1} distance'. format(route, next_hop)) }) # Get multicast routes for route in conf.list_nodes('route'): mroute['mroute'][route] = {} for next_hop in conf.list_nodes('route {0} next-hop'.format(route)): mroute['mroute'][route].update({ next_hop: conf.return_value('route {0} next-hop {1} distance'.format( route, next_hop)) }) # Get multicast interface-routes for route in conf.list_nodes('interface-route'): if not route in mroute['mroute']: mroute['mroute'][route] = {} for next_hop in conf.list_nodes( 'interface-route {0} next-hop-interface'.format(route)): mroute['mroute'][route].update({ next_hop: conf.return_value( 'interface-route {0} next-hop-interface {1} distance'. format(route, next_hop)) }) return mroute
def get_config(): conf = Config() igmp_conf = {'igmp_conf': False, 'old_ifaces': {}, 'ifaces': {}} if not (conf.exists('protocols igmp') or conf.exists_effective('protocols igmp')): return None if conf.exists('protocols igmp'): igmp_conf['igmp_conf'] = True conf.set_level('protocols igmp') # # Get interfaces for iface in conf.list_effective_nodes('interface'): igmp_conf['old_ifaces'].update({ iface: { 'version': conf.return_effective_value( 'interface {0} version'.format(iface)), 'query_interval': conf.return_effective_value( 'interface {0} query-interval'.format(iface)), 'query_max_resp_time': conf.return_effective_value( 'interface {0} query-max-response-time'.format(iface)), 'gr_join': {} } }) for gr_join in conf.list_effective_nodes( 'interface {0} join'.format(iface)): igmp_conf['old_ifaces'][iface]['gr_join'][ gr_join] = conf.return_effective_values( 'interface {0} join {1} source'.format(iface, gr_join)) for iface in conf.list_nodes('interface'): igmp_conf['ifaces'].update({ iface: { 'version': conf.return_value('interface {0} version'.format(iface)), 'query_interval': conf.return_value( 'interface {0} query-interval'.format(iface)), 'query_max_resp_time': conf.return_value( 'interface {0} query-max-response-time'.format(iface)), 'gr_join': {} } }) for gr_join in conf.list_nodes('interface {0} join'.format(iface)): igmp_conf['ifaces'][iface]['gr_join'][ gr_join] = conf.return_values( 'interface {0} join {1} source'.format(iface, gr_join)) return igmp_conf
def verify(bridge): if bridge['dhcpv6_prm_only'] and bridge['dhcpv6_temporary']: raise ConfigError( 'DHCPv6 temporary and parameters-only options are mutually exclusive!' ) vrf_name = bridge['vrf'] if vrf_name and vrf_name not in interfaces(): raise ConfigError(f'VRF "{vrf_name}" does not exist') conf = Config() for intf in bridge['member']: # the interface must exist prior adding it to a bridge if intf['name'] not in interfaces(): raise ConfigError( (f'Cannot add nonexistent interface "{intf["name"]}" ' f'to bridge "{bridge["intf"]}"')) if intf['name'] == 'lo': raise ConfigError( 'Loopback interface "lo" can not be added to a bridge') # bridge members aren't allowed to be members of another bridge for br in conf.list_nodes('interfaces bridge'): # it makes no sense to verify ourself in this case if br == bridge['intf']: continue tmp = conf.list_nodes(f'interfaces bridge {br} member interface') if intf['name'] in tmp: raise ConfigError(( f'Cannot add interface "{intf["name"]}" to bridge ' f'"{bridge["intf"]}", it is already a member of bridge "{br}"!' )) # bridge members are not allowed to be bond members tmp = is_member(conf, intf['name'], 'bonding') if tmp: raise ConfigError( (f'Cannot add interface "{intf["name"]}" to bridge ' f'"{bridge["intf"]}", it is already a member of bond "{tmp}"!' )) # bridge members must not have an assigned address if has_address_configured(conf, intf['name']): raise ConfigError( (f'Cannot add interface "{intf["name"]}" to bridge ' f'"{bridge["intf"]}", it has an address assigned!')) return None
def get_config(): conf = Config() conf.set_level("service broadcast-relay id") relay_id = conf.list_nodes("") relays = [] for id in relay_id: interface_list = [] address = conf.return_value("{0} address".format(id)) description = conf.return_value("{0} description".format(id)) port = conf.return_value("{0} port".format(id)) # split the interface name listing and form a list if conf.exists("{0} interface".format(id)): intfs_names = conf.return_values("{0} interface".format(id)) intfs_names = intfs_names.replace("'", "") intfs_names = intfs_names.split() for name in intfs_names: interface_list.append(name) relay = { "id": id, "address": address, "description": description, "interfaces": interface_list, "port": port } relays.append(relay) return relays
def verify(bridge): if bridge['dhcpv6_prm_only'] and bridge['dhcpv6_temporary']: raise ConfigError( 'DHCPv6 temporary and parameters-only options are mutually exclusive!' ) vrf_name = bridge['vrf'] if vrf_name and vrf_name not in interfaces(): raise ConfigError(f'VRF "{vrf_name}" does not exist') conf = Config() for br in conf.list_nodes('interfaces bridge'): # it makes no sense to verify ourself in this case if br == bridge['intf']: continue for intf in bridge['member']: tmp = conf.list_nodes( 'interfaces bridge {} member interface'.format(br)) if intf['name'] in tmp: raise ConfigError( 'Interface "{}" belongs to bridge "{}" and can not be enslaved.' .format(intf['name'], bridge['intf'])) # the interface must exist prior adding it to a bridge for intf in bridge['member']: if intf['name'] not in interfaces(): raise ConfigError( 'Can not add non existing interface "{}" to bridge "{}"'. format(intf['name'], bridge['intf'])) if intf['name'] == 'lo': raise ConfigError( 'Loopback interface "lo" can not be added to a bridge') # bridge members are not allowed to be bond members, too for intf in bridge['member']: for bond in conf.list_nodes('interfaces bonding'): if conf.exists('interfaces bonding ' + bond + ' member interface'): if intf['name'] in conf.return_values('interfaces bonding ' + bond + ' member interface'): raise ConfigError( 'Interface {} belongs to bond {}, can not add it to {}' .format(intf['name'], bond, bridge['intf'])) return None
def get_config(): c = Config() if not c.exists('protocols static arp'): return None c.set_level('protocols static') config_data = {} for ip_addr in c.list_nodes('arp'): config_data.update( {ip_addr: c.return_value('arp ' + ip_addr + ' hwaddr')}) return config_data
def get_config(): relay = deepcopy(default_config_data) conf = Config() base = ['service', 'broadcast-relay'] if not conf.exists(base): return None else: conf.set_level(base) # Service can be disabled by user if conf.exists('disable'): relay['disabled'] = True return relay # Parse configuration of each individual instance if conf.exists('id'): for id in conf.list_nodes('id'): conf.set_level(base + ['id', id]) config = { 'id': id, 'disabled': False, 'address': '', 'description': '', 'interfaces': [], 'port': '' } # Check if individual broadcast relay service is disabled if conf.exists(['disable']): config['disabled'] = True # Source IP of forwarded packets, if empty original senders address is used if conf.exists(['address']): config['address'] = conf.return_value(['address']) # A description for each individual broadcast relay service if conf.exists(['description']): config['description'] = conf.return_value(['description']) # UDP port to listen on for broadcast frames if conf.exists(['port']): config['port'] = conf.return_value(['port']) # Network interfaces to listen on for broadcast frames to be relayed if conf.exists(['interface']): config['interfaces'] = conf.return_values(['interface']) relay['instances'].append(config) return relay
def get_config(): relay = deepcopy(default_config_data) conf = Config() if not conf.exists('service dhcpv6-relay'): return None else: conf.set_level('service dhcpv6-relay') # Network interfaces/address to listen on for DHCPv6 query(s) if conf.exists('listen-interface'): interfaces = conf.list_nodes('listen-interface') for intf in interfaces: if conf.exists('listen-interface {0} address'.format(intf)): addr = conf.return_value( 'listen-interface {0} address'.format(intf)) listen = addr + '%' + intf relay['listen_addr'].append(listen) # Upstream interface/address for remote DHCPv6 server if conf.exists('upstream-interface'): interfaces = conf.list_nodes('upstream-interface') for intf in interfaces: addresses = conf.return_values( 'upstream-interface {0} address'.format(intf)) for addr in addresses: server = addr + '%' + intf relay['upstream_addr'].append(server) # Maximum hop count. When forwarding packets, dhcrelay discards packets # which have reached a hop count of COUNT. Default is 10. Maximum is 255. if conf.exists('max-hop-count'): count = '-c ' + conf.return_value('max-hop-count') relay['options'].append(count) if conf.exists('use-interface-id-option'): relay['options'].append('-I') return relay
def get_config(): bfd = deepcopy(default_config_data) conf = Config() if not (conf.exists('protocols bfd') or conf.exists_effective('protocols bfd')): return None else: conf.set_level('protocols bfd') # as we have to use vtysh to talk to FRR we also need to know # which peers are gone due to a config removal - thus we read in # all peers (active or to delete) for peer in conf.list_effective_nodes('peer'): bfd['old_peers'].append(get_bfd_peer_config(peer, "effective")) for peer in conf.list_nodes('peer'): bfd['new_peers'].append(get_bfd_peer_config(peer)) # find deleted peers set_new_peers = set(conf.list_nodes('peer')) set_old_peers = set(conf.list_effective_nodes('peer')) bfd['deleted_peers'] = set_old_peers - set_new_peers return bfd
def get_config(): opts = copy.deepcopy(default_config_data) conf = Config() if not conf.exists('firewall options'): # bail out early return opts else: conf.set_level('firewall options') # Parse configuration of each individual instance if conf.exists('interface'): for intf in conf.list_nodes('interface'): conf.set_level('firewall options interface {0}'.format(intf)) config = { 'intf': intf, 'disabled': False, 'mss4': '', 'mss6': '' } # Check if individual option is disabled if conf.exists('disable'): config['disabled'] = True # # Get MSS value IPv4 # if conf.exists('adjust-mss'): config['mss4'] = conf.return_value('adjust-mss') # We need a marker that a new iptables chain needs to be generated if not opts['new_chain4']: opts['new_chain4'] = True # # Get MSS value IPv6 # if conf.exists('adjust-mss6'): config['mss6'] = conf.return_value('adjust-mss6') # We need a marker that a new ip6tables chain needs to be generated if not opts['new_chain6']: opts['new_chain6'] = True # Append interface options to global list opts['intf_opts'].append(config) return opts
def get_config(): igmp_proxy = deepcopy(default_config_data) conf = Config() base = ['protocols', 'igmp-proxy'] if not conf.exists(base): return None else: conf.set_level(base) # Network interfaces to listen on if conf.exists(['disable']): igmp_proxy['disable'] = True # Option to disable "quickleave" if conf.exists(['disable-quickleave']): igmp_proxy['disable_quickleave'] = True for intf in conf.list_nodes(['interface']): conf.set_level(base + ['interface', intf]) interface = { 'name': intf, 'alt_subnet': [], 'role': 'downstream', 'threshold': '1', 'whitelist': [] } if conf.exists(['alt-subnet']): interface['alt_subnet'] = conf.return_values(['alt-subnet']) if conf.exists(['role']): interface['role'] = conf.return_value(['role']) if conf.exists(['threshold']): interface['threshold'] = conf.return_value(['threshold']) if conf.exists(['whitelist']): interface['whitelist'] = conf.return_values(['whitelist']) # Append interface configuration to global configuration list igmp_proxy['interfaces'].append(interface) return igmp_proxy
def get_config(): ntp = deepcopy(default_config_data) conf = Config() if not conf.exists('system ntp'): return None else: conf.set_level('system ntp') if conf.exists('allow-clients address'): networks = conf.return_values('allow-clients address') for n in networks: addr = ip_network(n) net = { "network" : n, "address" : addr.network_address, "netmask" : addr.netmask } ntp['allowed_networks'].append(net) if conf.exists('listen-address'): ntp['listen_address'] = conf.return_values('listen-address') if conf.exists('server'): for node in conf.list_nodes('server'): options = [] server = { "name": node, "options": [] } if conf.exists('server {0} noselect'.format(node)): options.append('noselect') if conf.exists('server {0} preempt'.format(node)): options.append('preempt') if conf.exists('server {0} prefer'.format(node)): options.append('prefer') server['options'] = options ntp['servers'].append(server) return ntp
def verify(eth): if eth['deleted']: return None if eth['intf'] not in interfaces(): raise ConfigError(f"Interface ethernet {eth['intf']} does not exist") if eth['speed'] == 'auto': if eth['duplex'] != 'auto': raise ConfigError( 'If speed is hardcoded, duplex must be hardcoded, too') if eth['duplex'] == 'auto': if eth['speed'] != 'auto': raise ConfigError( 'If duplex is hardcoded, speed must be hardcoded, too') if eth['dhcpv6_prm_only'] and eth['dhcpv6_temporary']: raise ConfigError( 'DHCPv6 temporary and parameters-only options are mutually exclusive!' ) vrf_name = eth['vrf'] if vrf_name and vrf_name not in interfaces(): raise ConfigError(f'VRF "{vrf_name}" does not exist') conf = Config() # some options can not be changed when interface is enslaved to a bond for bond in conf.list_nodes('interfaces bonding'): if conf.exists('interfaces bonding ' + bond + ' member interface'): bond_member = conf.return_values('interfaces bonding ' + bond + ' member interface') if eth['intf'] in bond_member: if eth['address']: raise ConfigError( f"Can not assign address to interface {eth['intf']} which is a member of {bond}" ) # use common function to verify VLAN configuration verify_vlan_config(eth) return None
def get_config(): conf = Config() conf.set_level("system task-scheduler task") task_names = conf.list_nodes("") tasks = [] for name in task_names: interval = conf.return_value("{0} interval".format(name)) spec = conf.return_value("{0} crontab-spec".format(name)) executable = conf.return_value("{0} executable path".format(name)) args = conf.return_value("{0} executable arguments".format(name)) task = { "name": name, "interval": interval, "spec": spec, "executable": executable, "args": args } tasks.append(task) return tasks
def get_config(): http_api = deepcopy(vyos.defaults.api_data) x = http_api.get('api_keys') if x is None: default_key = None else: default_key = x[0] keys_added = False conf = Config() if not conf.exists('service https api'): return None else: conf.set_level('service https api') if conf.exists('strict'): http_api['strict'] = 'true' if conf.exists('debug'): http_api['debug'] = 'true' if conf.exists('port'): port = conf.return_value('port') http_api['port'] = port if conf.exists('keys'): for name in conf.list_nodes('keys id'): if conf.exists('keys id {0} key'.format(name)): key = conf.return_value('keys id {0} key'.format(name)) new_key = {'id': name, 'key': key} http_api['api_keys'].append(new_key) keys_added = True if keys_added and default_key: if default_key in http_api['api_keys']: http_api['api_keys'].remove(default_key) return http_api
def get_config(): conf = Config() hosts = copy.deepcopy(default_config_data) if conf.exists("system host-name"): hosts['hostname'] = conf.return_value("system host-name") # This may happen if the config is not loaded yet, # e.g. if run by cloud-init if not hosts['hostname']: hosts['hostname'] = default_config_data['hostname'] if conf.exists("system domain-name"): hosts['domain_name'] = conf.return_value("system domain-name") hosts['domain_search'].append(hosts['domain_name']) for search in conf.return_values("system domain-search domain"): hosts['domain_search'].append(search) if conf.exists("system name-server"): hosts['nameserver'] = conf.return_values("system name-server") if conf.exists("system disable-dhcp-nameservers"): hosts['no_dhcp_ns'] = True # system static-host-mapping hosts['static_host_mapping'] = [] if conf.exists('system static-host-mapping host-name'): for hn in conf.list_nodes('system static-host-mapping host-name'): mapping = {} mapping['host'] = hn mapping['address'] = conf.return_value( 'system static-host-mapping host-name {0} inet'.format(hn)) mapping['aliases'] = conf.return_values( 'system static-host-mapping host-name {0} alias'.format(hn)) hosts['static_host_mapping'].append(mapping) return hosts
def get_config(): vc = Config() vc.set_level('') # Convert the VyOS config to an abstract internal representation flow_config = { 'flow-accounting-configured': vc.exists('system flow-accounting'), 'buffer-size': vc.return_value('system flow-accounting buffer-size'), 'disable-imt': _node_exists('system flow-accounting disable-imt'), 'syslog-facility': vc.return_value('system flow-accounting syslog-facility'), 'interfaces': None, 'sflow': { 'configured': vc.exists('system flow-accounting sflow'), 'agent-address': vc.return_value('system flow-accounting sflow agent-address'), 'sampling-rate': vc.return_value('system flow-accounting sflow sampling-rate'), 'servers': None }, 'netflow': { 'configured': vc.exists('system flow-accounting netflow'), 'engine-id': vc.return_value('system flow-accounting netflow engine-id'), 'max-flows': vc.return_value('system flow-accounting netflow max-flows'), 'sampling-rate': vc.return_value('system flow-accounting netflow sampling-rate'), 'source-ip': vc.return_value('system flow-accounting netflow source-ip'), 'version': vc.return_value('system flow-accounting netflow version'), 'timeout': { 'expint': vc.return_value( 'system flow-accounting netflow timeout expiry-interval'), 'general': vc.return_value( 'system flow-accounting netflow timeout flow-generic'), 'icmp': vc.return_value('system flow-accounting netflow timeout icmp'), 'maxlife': vc.return_value( 'system flow-accounting netflow timeout max-active-life'), 'tcp.fin': vc.return_value( 'system flow-accounting netflow timeout tcp-fin'), 'tcp': vc.return_value( 'system flow-accounting netflow timeout tcp-generic'), 'tcp.rst': vc.return_value( 'system flow-accounting netflow timeout tcp-rst'), 'udp': vc.return_value('system flow-accounting netflow timeout udp') }, 'servers': None } } # get interfaces list if vc.exists('system flow-accounting interface'): flow_config['interfaces'] = vc.return_values( 'system flow-accounting interface') # get sFlow collectors list if vc.exists('system flow-accounting sflow server'): flow_config['sflow']['servers'] = [] sflow_collectors = vc.list_nodes('system flow-accounting sflow server') for collector in sflow_collectors: port = default_sflow_server_port if vc.return_value( "system flow-accounting sflow server {} port".format( collector)): port = vc.return_value( "system flow-accounting sflow server {} port".format( collector)) flow_config['sflow']['servers'].append({ 'address': collector, 'port': port }) # get NetFlow collectors list if vc.exists('system flow-accounting netflow server'): flow_config['netflow']['servers'] = [] netflow_collectors = vc.list_nodes( 'system flow-accounting netflow server') for collector in netflow_collectors: port = default_netflow_server_port if vc.return_value( "system flow-accounting netflow server {} port".format( collector)): port = vc.return_value( "system flow-accounting netflow server {} port".format( collector)) flow_config['netflow']['servers'].append({ 'address': collector, 'port': port }) # get sflow agent-id if flow_config['sflow']['agent-address'] == None or flow_config['sflow'][ 'agent-address'] == 'auto': flow_config['sflow']['agent-address'] = _sflow_default_agentip(vc) # get NetFlow version if not flow_config['netflow']['version']: flow_config['netflow']['version'] = default_netflow_version # convert NetFlow engine-id format, if this is necessary if flow_config['netflow']['engine-id'] and flow_config['netflow'][ 'version'] == '5': regex_filter = re.compile('^\d+$') if regex_filter.search(flow_config['netflow']['engine-id']): flow_config['netflow']['engine-id'] = "{}:0".format( flow_config['netflow']['engine-id']) # return dict with flow-accounting configuration return flow_config
def get_config(): openvpn = deepcopy(default_config_data) conf = Config() # determine tagNode instance if 'VYOS_TAGNODE_VALUE' not in os.environ: raise ConfigError('Interface (VYOS_TAGNODE_VALUE) not specified') openvpn['intf'] = os.environ['VYOS_TAGNODE_VALUE'] # Check if interface instance has been removed if not conf.exists('interfaces openvpn ' + openvpn['intf']): openvpn['deleted'] = True return openvpn # Check if we belong to any bridge interface for bridge in conf.list_nodes('interfaces bridge'): for intf in conf.list_nodes( 'interfaces bridge {} member interface'.format(bridge)): if intf == openvpn['intf']: openvpn['bridge_member'].append(intf) # set configuration level conf.set_level('interfaces openvpn ' + openvpn['intf']) # retrieve authentication options - username if conf.exists('authentication username'): openvpn['auth_user'] = conf.return_value('authentication username') openvpn['auth'] = True # retrieve authentication options - username if conf.exists('authentication password'): openvpn['auth_pass'] = conf.return_value('authentication password') openvpn['auth'] = True # retrieve interface description if conf.exists('description'): openvpn['description'] = conf.return_value('description') # interface device-type if conf.exists('device-type'): openvpn['type'] = conf.return_value('device-type') # disable interface if conf.exists('disable'): openvpn['disable'] = True # data encryption algorithm cipher if conf.exists('encryption cipher'): openvpn['encryption'] = conf.return_value('encryption cipher') # disable ncp-ciphers support if conf.exists('encryption disable-ncp'): openvpn['disable_ncp'] = True # data encryption algorithm ncp-list if conf.exists('encryption ncp-ciphers'): _ncp_ciphers = [] for enc in conf.return_values('encryption ncp-ciphers'): if enc == 'des': _ncp_ciphers.append('des-cbc') _ncp_ciphers.append('DES-CBC') elif enc == '3des': _ncp_ciphers.append('des-ede3-cbc') _ncp_ciphers.append('DES-EDE3-CBC') elif enc == 'aes128': _ncp_ciphers.append('aes-128-cbc') _ncp_ciphers.append('AES-128-CBC') elif enc == 'aes128gcm': _ncp_ciphers.append('aes-128-gcm') _ncp_ciphers.append('AES-128-GCM') elif enc == 'aes192': _ncp_ciphers.append('aes-192-cbc') _ncp_ciphers.append('AES-192-CBC') elif enc == 'aes192gcm': _ncp_ciphers.append('aes-192-gcm') _ncp_ciphers.append('AES-192-GCM') elif enc == 'aes256': _ncp_ciphers.append('aes-256-cbc') _ncp_ciphers.append('AES-256-CBC') elif enc == 'aes256gcm': _ncp_ciphers.append('aes-256-gcm') _ncp_ciphers.append('AES-256-GCM') openvpn['ncp_ciphers'] = ':'.join(_ncp_ciphers) # hash algorithm if conf.exists('hash'): openvpn['hash'] = conf.return_value('hash') # Maximum number of keepalive packet failures if conf.exists('keep-alive failure-count') and conf.exists( 'keep-alive interval'): fail_count = conf.return_value('keep-alive failure-count') interval = conf.return_value('keep-alive interval') openvpn['ping_interval'] = interval openvpn['ping_restart'] = int(interval) * int(fail_count) # Local IP address of tunnel - even as it is a tag node - we can only work # on the first address if conf.exists('local-address'): openvpn['local_address'] = conf.list_nodes('local-address')[0] if conf.exists('local-address {} subnet-mask'.format( openvpn['local_address'])): openvpn['local_address_subnet'] = conf.return_value( 'local-address {} subnet-mask'.format( openvpn['local_address'])) # Local IP address to accept connections if conf.exists('local-host'): openvpn['local_host'] = conf.return_value('local-host') # Local port number to accept connections if conf.exists('local-port'): openvpn['local_port'] = conf.return_value('local-port') # Enable acquisition of IPv6 address using stateless autoconfig (SLAAC) if conf.exists('ipv6 address autoconf'): openvpn['ipv6_autoconf'] = 1 # Get prefix for IPv6 addressing based on MAC address (EUI-64) if conf.exists('ipv6 address eui64'): openvpn['ipv6_eui64_prefix'] = conf.return_value('ipv6 address eui64') # Disable IPv6 forwarding on this interface if conf.exists('ipv6 disable-forwarding'): openvpn['ipv6_forwarding'] = 0 # IPv6 Duplicate Address Detection (DAD) tries if conf.exists('ipv6 dup-addr-detect-transmits'): openvpn['ipv6_dup_addr_detect'] = int( conf.return_value('ipv6 dup-addr-detect-transmits')) # OpenVPN operation mode if conf.exists('mode'): openvpn['mode'] = conf.return_value('mode') # Additional OpenVPN options if conf.exists('openvpn-option'): openvpn['options'] = conf.return_values('openvpn-option') # Do not close and reopen interface if conf.exists('persistent-tunnel'): openvpn['persistent_tunnel'] = True # Communication protocol if conf.exists('protocol'): openvpn['protocol'] = conf.return_value('protocol') # IP address of remote end of tunnel if conf.exists('remote-address'): openvpn['remote_address'] = conf.return_value('remote-address') # Remote host to connect to (dynamic if not set) if conf.exists('remote-host'): openvpn['remote_host'] = conf.return_values('remote-host') # Remote port number to connect to if conf.exists('remote-port'): openvpn['remote_port'] = conf.return_value('remote-port') # OpenVPN tunnel to be used as the default route # see https://openvpn.net/community-resources/reference-manual-for-openvpn-2-4/ # redirect-gateway flags if conf.exists('replace-default-route'): openvpn['redirect_gateway'] = 'def1' if conf.exists('replace-default-route local'): openvpn['redirect_gateway'] = 'local def1' # Topology for clients if conf.exists('server topology'): openvpn['server_topology'] = conf.return_value('server topology') # Server-mode subnet (from which client IPs are allocated) if conf.exists('server subnet'): network = conf.return_value('server subnet') tmp = IPv4Interface(network).with_netmask # convert the network in format: "192.0.2.0 255.255.255.0" for later use in template openvpn['server_subnet'] = tmp.replace(r'/', ' ') # Client-specific settings for client in conf.list_nodes('server client'): # set configuration level conf.set_level('interfaces openvpn ' + openvpn['intf'] + ' server client ' + client) data = { 'name': client, 'disable': False, 'ip': '', 'push_route': [], 'subnet': [], 'remote_netmask': '' } # note: with "topology subnet", this is "<ip> <netmask>". # with "topology p2p", this is "<ip> <our_ip>". if openvpn['server_topology'] == 'subnet': # we are only interested in the netmask portion of server_subnet data['remote_netmask'] = openvpn['server_subnet'].split(' ')[1] else: # we need the server subnet in format 192.0.2.0/255.255.255.0 subnet = openvpn['server_subnet'].replace(' ', r'/') # get iterator over the usable hosts in the network tmp = ip_network(subnet).hosts() # OpenVPN always uses the subnets first available IP address data['remote_netmask'] = list(tmp)[0] # Option to disable client connection if conf.exists('disable'): data['disable'] = True # IP address of the client if conf.exists('ip'): data['ip'] = conf.return_value('ip') # Route to be pushed to the client for network in conf.return_values('push-route'): tmp = IPv4Interface(network).with_netmask data['push_route'].append(tmp.replace(r'/', ' ')) # Subnet belonging to the client for network in conf.return_values('subnet'): tmp = IPv4Interface(network).with_netmask data['subnet'].append(tmp.replace(r'/', ' ')) # Append to global client list openvpn['client'].append(data) # re-set configuration level conf.set_level('interfaces openvpn ' + openvpn['intf']) # DNS suffix to be pushed to all clients if conf.exists('server domain-name'): openvpn['server_domain'] = conf.return_value('server domain-name') # Number of maximum client connections if conf.exists('server max-connections'): openvpn['server_max_conn'] = conf.return_value( 'server max-connections') # Domain Name Server (DNS) if conf.exists('server name-server'): openvpn['server_dns_nameserver'] = conf.return_values( 'server name-server') # Route to be pushed to all clients if conf.exists('server push-route'): for network in conf.return_values('server push-route'): tmp = IPv4Interface(network).with_netmask openvpn['server_push_route'].append(tmp.replace(r'/', ' ')) # Reject connections from clients that are not explicitly configured if conf.exists('server reject-unconfigured-clients'): openvpn['server_reject_unconfigured'] = True # File containing TLS auth static key if conf.exists('tls auth-file'): openvpn['tls_auth'] = conf.return_value('tls auth-file') openvpn['tls'] = True # File containing certificate for Certificate Authority (CA) if conf.exists('tls ca-cert-file'): openvpn['tls_ca_cert'] = conf.return_value('tls ca-cert-file') openvpn['tls'] = True # File containing certificate for this host if conf.exists('tls cert-file'): openvpn['tls_cert'] = conf.return_value('tls cert-file') openvpn['tls'] = True # File containing certificate revocation list (CRL) for this host if conf.exists('tls crl-file'): openvpn['tls_crl'] = conf.return_value('tls crl-file') openvpn['tls'] = True # File containing Diffie Hellman parameters (server only) if conf.exists('tls dh-file'): openvpn['tls_dh'] = conf.return_value('tls dh-file') openvpn['tls'] = True # File containing this host's private key if conf.exists('tls key-file'): openvpn['tls_key'] = conf.return_value('tls key-file') openvpn['tls'] = True # File containing key to encrypt control channel packets if conf.exists('tls crypt-file'): openvpn['tls_crypt'] = conf.return_value('tls crypt-file') openvpn['tls'] = True # Role in TLS negotiation if conf.exists('tls role'): openvpn['tls_role'] = conf.return_value('tls role') openvpn['tls'] = True # Minimum required TLS version if conf.exists('tls tls-version-min'): openvpn['tls_version_min'] = conf.return_value('tls tls-version-min') openvpn['tls'] = True if conf.exists('shared-secret-key-file'): openvpn['shared_secret_file'] = conf.return_value( 'shared-secret-key-file') if conf.exists('use-lzo-compression'): openvpn['compress_lzo'] = True # Special case when using EC certificates: # if key-file is EC and dh-file is unset, set tls_dh to 'none' if not openvpn['tls_dh'] and openvpn['tls_key'] and checkCertHeader( '-----BEGIN EC PRIVATE KEY-----', openvpn['tls_key']): openvpn['tls_dh'] = 'none' return openvpn
def get_config(): conf = Config() vrf_config = deepcopy(default_config_data) cfg_base = ['vrf'] if not conf.exists(cfg_base): # get all currently effetive VRFs and mark them for deletion vrf_config['vrf_remove'] = conf.list_effective_nodes(cfg_base + ['name']) else: # set configuration level base conf.set_level(cfg_base) # Should services be allowed to bind to all VRFs? if conf.exists(['bind-to-all']): vrf_config['bind_to_all'] = '1' # Determine vrf interfaces (currently effective) - to determine which # vrf interface is no longer present and needs to be removed eff_vrf = conf.list_effective_nodes(['name']) act_vrf = conf.list_nodes(['name']) vrf_config['vrf_remove'] = list_diff(eff_vrf, act_vrf) # read in individual VRF definition and build up # configuration for name in conf.list_nodes(['name']): vrf_inst = { 'description': '', 'members': [], 'name': name, 'table': '', 'table_mod': False } conf.set_level(cfg_base + ['name', name]) if conf.exists(['table']): # VRF table can't be changed on demand, thus we need to read in the # current and the effective routing table number act_table = conf.return_value(['table']) eff_table = conf.return_effective_value(['table']) vrf_inst['table'] = act_table if eff_table and eff_table != act_table: vrf_inst['table_mod'] = True if conf.exists(['description']): vrf_inst['description'] = conf.return_value(['description']) # append individual VRF configuration to global configuration list vrf_config['vrf_add'].append(vrf_inst) # set configuration level base conf.set_level(cfg_base) # check VRFs which need to be removed as they are not allowed to have # interfaces attached tmp = [] for name in vrf_config['vrf_remove']: vrf_inst = {'interfaces': [], 'name': name, 'routes': []} # find member interfaces of this particulat VRF vrf_inst['interfaces'] = vrf_interfaces(conf, name) # find routing protocols used by this VRF vrf_inst['routes'] = vrf_routing(conf, name) # append individual VRF configuration to temporary configuration list tmp.append(vrf_inst) # replace values in vrf_remove with list of dictionaries # as we need it in verify() - we can't delete a VRF with members attached vrf_config['vrf_remove'] = tmp return vrf_config
def get_config(): conf = Config() pim_conf = { 'pim_conf': False, 'old_pim': { 'ifaces': {}, 'rp': {} }, 'pim': { 'ifaces': {}, 'rp': {} } } if not (conf.exists('protocols pim') or conf.exists_effective('protocols pim')): return None if conf.exists('protocols pim'): pim_conf['pim_conf'] = True conf.set_level('protocols pim') # Get interfaces for iface in conf.list_effective_nodes('interface'): pim_conf['old_pim']['ifaces'].update({ iface: { 'hello': conf.return_effective_value( 'interface {0} hello'.format(iface)), 'dr_prio': conf.return_effective_value( 'interface {0} dr-priority'.format(iface)) } }) for iface in conf.list_nodes('interface'): pim_conf['pim']['ifaces'].update({ iface: { 'hello': conf.return_value('interface {0} hello'.format(iface)), 'dr_prio': conf.return_value('interface {0} dr-priority'.format(iface)), } }) conf.set_level('protocols pim rp') # Get RPs addresses for rp_addr in conf.list_effective_nodes('address'): pim_conf['old_pim']['rp'][rp_addr] = conf.return_effective_values( 'address {0} group'.format(rp_addr)) for rp_addr in conf.list_nodes('address'): pim_conf['pim']['rp'][rp_addr] = conf.return_values( 'address {0} group'.format(rp_addr)) # Get RP keep-alive-timer if conf.exists_effective('rp keep-alive-timer'): pim_conf['old_pim']['rp_keep_alive'] = conf.return_effective_value( 'rp keep-alive-timer') if conf.exists('rp keep-alive-timer'): pim_conf['pim']['rp_keep_alive'] = conf.return_value( 'rp keep-alive-timer') return pim_conf
def get_config(): server_block_list = [] conf = Config() if not conf.exists('service https'): return None else: conf.set_level('service https') if not conf.exists('virtual-host'): server_block_list.append(default_server_block) else: for vhost in conf.list_nodes('virtual-host'): server_block = deepcopy(default_server_block) server_block['id'] = vhost if conf.exists(f'virtual-host {vhost} listen-address'): addr = conf.return_value( f'virtual-host {vhost} listen-address') server_block['address'] = addr if conf.exists(f'virtual-host {vhost} listen-port'): port = conf.return_value(f'virtual-host {vhost} listen-port') server_block['port'] = port if conf.exists(f'virtual-host {vhost} server-name'): names = conf.return_values(f'virtual-host {vhost} server-name') server_block['name'] = names[:] server_block_list.append(server_block) vyos_cert_data = {} if conf.exists('certificates system-generated-certificate'): vyos_cert_data = vyos.defaults.vyos_cert_data if vyos_cert_data: for block in server_block_list: block['vyos_cert'] = vyos_cert_data certbot = False certbot_domains = [] if conf.exists('certificates certbot domain-name'): certbot_domains = conf.return_values( 'certificates certbot domain-name') if certbot_domains: certbot = True for domain in certbot_domains: sub_list = vyos.certbot_util.choose_server_block( server_block_list, domain) if sub_list: for sb in sub_list: sb['certbot'] = True # certbot organizes certificates by first domain sb['certbot_dir'] = certbot_domains[0] api_somewhere = False api_data = {} if conf.exists('api'): api_somewhere = True api_data = vyos.defaults.api_data if conf.exists('api port'): port = conf.return_value('api port') api_data['port'] = port if conf.exists('api-restrict virtual-host'): vhosts = conf.return_values('api-restrict virtual-host') api_data['vhost'] = vhosts[:] if api_data: # we do not want to include 'vhost' key as part of # vyos.defaults.api_data, so check for key existence vhost_list = api_data.get('vhost') if vhost_list is None: for block in server_block_list: block['api'] = api_data else: for block in server_block_list: if block['id'] in vhost_list: block['api'] = api_data https = { 'server_block_list': server_block_list, 'api_somewhere': api_somewhere, 'certbot': certbot } return https
def get_config(): dyndns = deepcopy(default_config_data) conf = Config() base_level = ['service', 'dns', 'dynamic'] if not conf.exists(base_level): dyndns['deleted'] = True return dyndns for interface in conf.list_nodes(base_level + ['interface']): node = { 'interface': interface, 'rfc2136': [], 'service': [], 'web_skip': '', 'web_url': '' } # set config level to e.g. "service dns dynamic interface eth0" conf.set_level(base_level + ['interface', interface]) # Handle RFC2136 - Dynamic Updates in the Domain Name System for rfc2136 in conf.list_nodes(['rfc2136']): rfc = { 'name': rfc2136, 'keyfile': '', 'record': [], 'server': '', 'ttl': '600', 'zone': '' } # set config level conf.set_level(base_level + ['interface', interface, 'rfc2136', rfc2136]) if conf.exists(['key']): rfc['keyfile'] = conf.return_value(['key']) if conf.exists(['record']): rfc['record'] = conf.return_values(['record']) if conf.exists(['server']): rfc['server'] = conf.return_value(['server']) if conf.exists(['ttl']): rfc['ttl'] = conf.return_value(['ttl']) if conf.exists(['zone']): rfc['zone'] = conf.return_value(['zone']) node['rfc2136'].append(rfc) # set config level to e.g. "service dns dynamic interface eth0" conf.set_level(base_level + ['interface', interface]) # Handle DynDNS service providers for service in conf.list_nodes(['service']): srv = { 'provider': service, 'host': [], 'login': '', 'password': '', 'protocol': '', 'server': '', 'custom' : False, 'zone' : '' } # set config level conf.set_level(base_level + ['interface', interface, 'service', service]) # preload protocol from default service mapping if service in default_service_protocol.keys(): srv['protocol'] = default_service_protocol[service] else: srv['custom'] = True if conf.exists(['login']): srv['login'] = conf.return_value(['login']) if conf.exists(['host-name']): srv['host'] = conf.return_values(['host-name']) if conf.exists(['protocol']): srv['protocol'] = conf.return_value(['protocol']) if conf.exists(['password']): srv['password'] = conf.return_value(['password']) if conf.exists(['server']): srv['server'] = conf.return_value(['server']) if conf.exists(['zone']): srv['zone'] = conf.return_value(['zone']) elif srv['provider'] == 'cloudflare': # default populate zone entry with bar.tld if # host-name is foo.bar.tld srv['zone'] = srv['host'][0].split('.',1)[1] node['service'].append(srv) # Set config back to appropriate level for these options conf.set_level(base_level + ['interface', interface]) # Additional settings in CLI if conf.exists(['use-web', 'skip']): node['web_skip'] = conf.return_value(['use-web', 'skip']) if conf.exists(['use-web', 'url']): node['web_url'] = conf.return_value(['use-web', 'url']) # set config level back to top level conf.set_level(base_level) dyndns['interfaces'].append(node) return dyndns
def get_config(): c = Config() if not c.exists(['vpn', 'pptp', 'remote-access']): return None c.set_level(['vpn', 'pptp', 'remote-access']) config_data = { 'authentication': { 'mode': 'local', 'local-users': {}, 'radiussrv': {}, 'auth_proto': 'auth_mschap_v2', 'mppe': 'require' }, 'outside_addr': '', 'dns': [], 'wins': [], 'client_ip_pool': '', 'mtu': '1436', } ### general options ### if c.exists(['dns-servers', 'server-1']): config_data['dns'].append(c.return_value(['dns-servers', 'server-1'])) if c.exists(['dns-servers', 'server-2']): config_data['dns'].append(c.return_value(['dns-servers', 'server-2'])) if c.exists(['wins-servers', 'server-1']): config_data['wins'].append(c.return_value(['wins-servers', 'server-1'])) if c.exists(['wins-servers', 'server-2']): config_data['wins'].append(c.return_value(['wins-servers', 'server-2'])) if c.exists(['outside-address']): config_data['outside_addr'] = c.return_value(['outside-address']) # auth local if c.exists(['authentication', 'mode', 'local']): if c.exists(['authentication', 'local-users', 'username']): for usr in c.list_nodes( ['authentication', 'local-users', 'username']): config_data['authentication']['local-users'].update( {usr: { 'passwd': '', 'state': 'enabled', 'ip': '' }}) if c.exists([ 'authentication', 'local-users', 'username', usr, 'password' ]): config_data['authentication']['local-users'][usr][ 'passwd'] = c.return_value([ 'authentication', 'local-users', 'username', usr, 'password' ]) if c.exists([ 'authentication', 'local-users', 'username', usr, 'disable' ]): config_data['authentication']['local-users'][usr][ 'state'] = 'disable' if c.exists([ 'authentication', 'local-users', 'username', usr, 'static-ip' ]): config_data['authentication']['local-users'][usr][ 'ip'] = c.return_value([ 'authentication', 'local-users', 'username', usr, 'static-ip' ]) # authentication mode radius servers and settings if c.exists(['authentication', 'mode', 'radius']): config_data['authentication']['mode'] = 'radius' rsrvs = c.list_nodes(['authentication', 'radius', 'server']) for rsrv in rsrvs: if not c.return_value( ['authentication', 'radius', 'server', rsrv, 'fail-time']): ftime = '0' else: ftime = c.return_value( ['authentication', 'radius', 'server', rsrv, 'fail-time']) if not c.return_value( ['authentication', 'radius-server', rsrv, 'req-limit']): reql = '0' else: reql = c.return_value( ['authentication', 'radius', 'server', rsrv, 'req-limit']) config_data['authentication']['radiussrv'].update({ rsrv: { 'secret': c.return_value( ['authentication', 'radius', 'server', rsrv, 'key']), 'fail-time': ftime, 'req-limit': reql } }) if c.exists(['client-ip-pool']): if c.exists(['client-ip-pool', 'start']): config_data['client_ip_pool'] = c.return_value( ['client-ip-pool', 'start']) if c.exists(['client-ip-pool', 'stop']): config_data['client_ip_pool'] += '-' + \ re.search( '[0-9]+$', c.return_value(['client-ip-pool', 'stop'])).group(0) if c.exists(['mtu']): config_data['mtu'] = c.return_value(['mtu']) # gateway address if c.exists(['gateway-address']): config_data['gw_ip'] = c.return_value(['gateway-address']) else: config_data['gw_ip'] = re.sub('[0-9]+$', '1', config_data['client_ip_pool']) if c.exists(['authentication', 'require']): if c.return_value(['authentication', 'require']) == 'pap': config_data['authentication']['auth_proto'] = 'auth_pap' if c.return_value(['authentication', 'require']) == 'chap': config_data['authentication']['auth_proto'] = 'auth_chap_md5' if c.return_value(['authentication', 'require']) == 'mschap': config_data['authentication']['auth_proto'] = 'auth_mschap_v1' if c.return_value(['authentication', 'require']) == 'mschap-v2': config_data['authentication']['auth_proto'] = 'auth_mschap_v2' if c.exists(['authentication', 'mppe']): config_data['authentication']['mppe'] = c.return_value( ['authentication', 'mppe']) return config_data
def get_config(): sstp = deepcopy(default_config_data) base_path = ['vpn', 'sstp'] conf = Config() if not conf.exists(base_path): return None conf.set_level(base_path) cpu = os.cpu_count() if cpu > 1: sstp['thread_cnt'] = int(cpu/2) if conf.exists(['authentication', 'mode']): sstp['auth_mode'] = conf.return_value(['authentication', 'mode']) # # local auth if conf.exists(['authentication', 'local-users']): for username in conf.list_nodes(['authentication', 'local-users', 'username']): user = { 'name' : username, 'password' : '', 'state' : 'enabled', 'ip' : '*', 'upload' : None, 'download' : None } conf.set_level(base_path + ['authentication', 'local-users', 'username', username]) if conf.exists(['password']): user['password'] = conf.return_value(['password']) if conf.exists(['disable']): user['state'] = 'disable' if conf.exists(['static-ip']): user['ip'] = conf.return_value(['static-ip']) if conf.exists(['rate-limit', 'download']): user['download'] = conf.return_value(['rate-limit', 'download']) if conf.exists(['rate-limit', 'upload']): user['upload'] = conf.return_value(['rate-limit', 'upload']) sstp['local_users'].append(user) # # RADIUS auth and settings conf.set_level(base_path + ['authentication', 'radius']) if conf.exists(['server']): for server in conf.list_nodes(['server']): radius = { 'server' : server, 'key' : '', 'fail_time' : 0, 'port' : '1812' } conf.set_level(base_path + ['authentication', 'radius', 'server', server]) if conf.exists(['fail-time']): radius['fail-time'] = conf.return_value(['fail-time']) if conf.exists(['port']): radius['port'] = conf.return_value(['port']) if conf.exists(['key']): radius['key'] = conf.return_value(['key']) if not conf.exists(['disable']): sstp['radius_server'].append(radius) # # advanced radius-setting conf.set_level(base_path + ['authentication', 'radius']) if conf.exists(['acct-timeout']): sstp['radius_acct_tmo'] = conf.return_value(['acct-timeout']) if conf.exists(['max-try']): sstp['radius_max_try'] = conf.return_value(['max-try']) if conf.exists(['timeout']): sstp['radius_timeout'] = conf.return_value(['timeout']) if conf.exists(['nas-identifier']): sstp['radius_nas_id'] = conf.return_value(['nas-identifier']) if conf.exists(['nas-ip-address']): sstp['radius_nas_ip'] = conf.return_value(['nas-ip-address']) if conf.exists(['source-address']): sstp['radius_source_address'] = conf.return_value(['source-address']) # Dynamic Authorization Extensions (DOA)/Change Of Authentication (COA) if conf.exists(['dynamic-author']): dae = { 'port' : '', 'server' : '', 'key' : '' } if conf.exists(['dynamic-author', 'server']): dae['server'] = conf.return_value(['dynamic-author', 'server']) if conf.exists(['dynamic-author', 'port']): dae['port'] = conf.return_value(['dynamic-author', 'port']) if conf.exists(['dynamic-author', 'key']): dae['key'] = conf.return_value(['dynamic-author', 'key']) sstp['radius_dynamic_author'] = dae if conf.exists(['rate-limit', 'enable']): sstp['radius_shaper_attr'] = 'Filter-Id' c_attr = ['rate-limit', 'enable', 'attribute'] if conf.exists(c_attr): sstp['radius_shaper_attr'] = conf.return_value(c_attr) c_vendor = ['rate-limit', 'enable', 'vendor'] if conf.exists(c_vendor): sstp['radius_shaper_vendor'] = conf.return_value(c_vendor) # # authentication protocols conf.set_level(base_path + ['authentication']) if conf.exists(['protocols']): auth_mods = { 'pap': 'auth_pap', 'chap': 'auth_chap_md5', 'mschap': 'auth_mschap_v1', 'mschap-v2': 'auth_mschap_v2' } for proto in conf.return_values(['protocols']): sstp['auth_proto'].append(auth_mods[proto]) # # read in SSL certs conf.set_level(base_path + ['ssl']) if conf.exists(['ca-cert-file']): sstp['ssl_ca'] = conf.return_value(['ca-cert-file']) if conf.exists(['cert-file']): sstp['ssl_cert'] = conf.return_value(['cert-file']) if conf.exists(['key-file']): sstp['ssl_key'] = conf.return_value(['key-file']) # # read in client ip pool settings conf.set_level(base_path + ['network-settings', 'client-ip-settings']) if conf.exists(['subnet']): sstp['client_ip_pool'] = conf.return_values(['subnet']) if conf.exists(['gateway-address']): sstp['client_gateway'] = conf.return_value(['gateway-address']) # # read in network settings conf.set_level(base_path + ['network-settings']) if conf.exists(['name-server']): sstp['dnsv4'] = conf.return_values(['name-server']) if conf.exists(['mtu']): sstp['mtu'] = conf.return_value(['mtu']) # # read in PPP stuff conf.set_level(base_path + ['ppp-settings']) if conf.exists('mppe'): sstp['ppp_mppe'] = conf.return_value(['ppp-settings', 'mppe']) if conf.exists(['lcp-echo-failure']): sstp['ppp_echo_failure'] = conf.return_value(['lcp-echo-failure']) if conf.exists(['lcp-echo-interval']): sstp['ppp_echo_interval'] = conf.return_value(['lcp-echo-interval']) if conf.exists(['lcp-echo-timeout']): sstp['ppp_echo_timeout'] = conf.return_value(['lcp-echo-timeout']) return sstp
def verify(bfd): if bfd is None: return None # some variables to use later conf = Config() for peer in bfd['new_peers']: # IPv6 link local peers require an explicit local address/interface if is_ipv6_link_local(peer['remote']): if not (peer['src_if'] and peer['src_addr']): raise ConfigError( 'BFD IPv6 link-local peers require explicit local address and interface setting' ) # IPv6 peers require an explicit local address if is_ipv6(peer['remote']): if not peer['src_addr']: raise ConfigError( 'BFD IPv6 peers require explicit local address setting') # multihop require source address if peer['multihop'] and not peer['src_addr']: raise ConfigError('Multihop require source address') # multihop and echo-mode cannot be used together if peer['multihop'] and peer['echo_mode']: raise ConfigError('Multihop and echo-mode cannot be used together') # multihop doesn't accept interface names if peer['multihop'] and peer['src_if']: raise ConfigError( 'Multihop and source interface cannot be used together') # echo interval can be configured only with enabled echo-mode if peer['echo_interval'] != '' and not peer['echo_mode']: raise ConfigError( 'echo-interval can be configured only with enabled echo-mode') # check if we deleted peers are not used in configuration if conf.exists('protocols bgp'): bgp_as = conf.list_nodes('protocols bgp')[0] # check BGP neighbors for peer in bfd['deleted_peers']: if conf.exists('protocols bgp {0} neighbor {1} bfd'.format( bgp_as, peer)): raise ConfigError( 'Cannot delete BFD peer {0}: it is used in BGP configuration' .format(peer)) if conf.exists('protocols bgp {0} neighbor {1} peer-group'.format( bgp_as, peer)): peer_group = conf.return_value( 'protocols bgp {0} neighbor {1} peer-group'.format( bgp_as, peer)) if conf.exists('protocols bgp {0} peer-group {1} bfd'.format( bgp_as, peer_group)): raise ConfigError( 'Cannot delete BFD peer {0}: it belongs to BGP peer-group {1} with enabled BFD' .format(peer, peer_group)) return None
def get_config(): snmp = default_config_data conf = Config() if not conf.exists('service snmp'): return None else: conf.set_level('service snmp') version_data = vyos.version.get_version_data() snmp['version'] = version_data['version'] # create an internal snmpv3 user of the form 'vyattaxxxxxxxxxxxxxxxx' # os.urandom(8) returns 8 bytes of random data snmp['vyos_user'] = '******' + binascii.hexlify( os.urandom(8)).decode('utf-8') snmp['vyos_user_pass'] = binascii.hexlify(os.urandom(16)).decode('utf-8') if conf.exists('community'): for name in conf.list_nodes('community'): community = {'name': name, 'authorization': 'ro', 'network': []} if conf.exists('community {0} authorization'.format(name)): community['authorization'] = conf.return_value( 'community {0} authorization'.format(name)) if conf.exists('community {0} network'.format(name)): community['network'] = conf.return_values( 'community {0} network'.format(name)) snmp['communities'].append(community) if conf.exists('contact'): snmp['contact'] = conf.return_value('contact') if conf.exists('description'): snmp['description'] = conf.return_value('description') if conf.exists('listen-address'): for addr in conf.list_nodes('listen-address'): listen = '' port = '161' if conf.exists('listen-address {0} port'.format(addr)): port = conf.return_value( 'listen-address {0} port'.format(addr)) if ipaddress.ip_address(addr).version == 4: # udp:127.0.0.1:161 listen = 'udp:' + addr + ':' + port elif ipaddress.ip_address(addr).version == 6: # udp6:[::1]:161 listen = 'udp6:' + '[' + addr + ']' + ':' + port else: raise ConfigError('Invalid IP address version') snmp['listen_on'].append(listen) if conf.exists('location'): snmp['location'] = conf.return_value('location') if conf.exists('smux-peer'): snmp['smux_peers'] = conf.return_values('smux-peer') if conf.exists('trap-source'): snmp['trap_source'] = conf.return_value('trap-source') if conf.exists('trap-target'): for target in conf.list_nodes('trap-target'): trap_tgt = {'target': target, 'community': '', 'port': ''} if conf.exists('trap-target {0} community'.format(target)): trap_tgt['community'] = conf.return_value( 'trap-target {0} community'.format(target)) if conf.exists('trap-target {0} port'.format(target)): trap_tgt['port'] = conf.return_value( 'trap-target {0} port'.format(target)) snmp['trap_targets'].append(trap_tgt) ######################################################################### # ____ _ _ __ __ ____ _____ # # / ___|| \ | | \/ | _ \ __ _|___ / # # \___ \| \| | |\/| | |_) | \ \ / / |_ \ # # ___) | |\ | | | | __/ \ V / ___) | # # |____/|_| \_|_| |_|_| \_/ |____/ # # # # now take care about the fancy SNMP v3 stuff, or bail out eraly # ######################################################################### if not conf.exists('v3'): return snmp else: snmp['v3_enabled'] = True # # 'set service snmp v3 engineid' # if conf.exists('v3 engineid'): snmp['v3_engineid'] = conf.return_value('v3 engineid') # # 'set service snmp v3 group' # if conf.exists('v3 group'): for group in conf.list_nodes('v3 group'): v3_group = { 'name': group, 'mode': 'ro', 'seclevel': 'auth', 'view': '' } if conf.exists('v3 group {0} mode'.format(group)): v3_group['mode'] = conf.return_value( 'v3 group {0} mode'.format(group)) if conf.exists('v3 group {0} seclevel'.format(group)): v3_group['seclevel'] = conf.return_value( 'v3 group {0} seclevel'.format(group)) if conf.exists('v3 group {0} view'.format(group)): v3_group['view'] = conf.return_value( 'v3 group {0} view'.format(group)) snmp['v3_groups'].append(v3_group) # # 'set service snmp v3 trap-target' # if conf.exists('v3 trap-target'): for trap in conf.list_nodes('v3 trap-target'): trap_cfg = { 'ipAddr': trap, 'engineID': '', 'secName': '', 'authProtocol': 'md5', 'authPassword': '', 'authMasterKey': '', 'privProtocol': 'des', 'privPassword': '', 'privMasterKey': '', 'ipProto': 'udp', 'ipPort': '162', 'type': '', 'secLevel': 'noAuthNoPriv' } if conf.exists('v3 trap-target {0} engineid'.format(trap)): # Set the context engineID used for SNMPv3 REQUEST messages scopedPdu. # If not specified, this will default to the authoritative engineID. trap_cfg['engineID'] = conf.return_value( 'v3 trap-target {0} engineid'.format(trap)) if conf.exists('v3 trap-target {0} user'.format(trap)): # Set the securityName used for authenticated SNMPv3 messages. trap_cfg['secName'] = conf.return_value( 'v3 trap-target {0} user'.format(trap)) if conf.exists('v3 trap-target {0} auth type'.format(trap)): # Set the authentication protocol (MD5 or SHA) used for authenticated SNMPv3 messages # cmdline option '-a' trap_cfg['authProtocol'] = conf.return_value( 'v3 trap-target {0} auth type'.format(trap)) if conf.exists( 'v3 trap-target {0} auth plaintext-key'.format(trap)): # Set the authentication pass phrase used for authenticated SNMPv3 messages. # cmdline option '-A' trap_cfg['authPassword'] = conf.return_value( 'v3 trap-target {0} auth plaintext-key'.format(trap)) if conf.exists( 'v3 trap-target {0} auth encrypted-key'.format(trap)): # Sets the keys to be used for SNMPv3 transactions. These options allow you to set the master authentication keys. # cmdline option '-3m' trap_cfg['authMasterKey'] = conf.return_value( 'v3 trap-target {0} auth encrypted-key'.format(trap)) if conf.exists('v3 trap-target {0} privacy type'.format(trap)): # Set the privacy protocol (DES or AES) used for encrypted SNMPv3 messages. # cmdline option '-x' trap_cfg['privProtocol'] = conf.return_value( 'v3 trap-target {0} privacy type'.format(trap)) if conf.exists( 'v3 trap-target {0} privacy plaintext-key'.format(trap)): # Set the privacy pass phrase used for encrypted SNMPv3 messages. # cmdline option '-X' trap_cfg['privPassword'] = conf.return_value( 'v3 trap-target {0} privacy plaintext-key'.format(trap)) if conf.exists( 'v3 trap-target {0} privacy encrypted-key'.format(trap)): # Sets the keys to be used for SNMPv3 transactions. These options allow you to set the master encryption keys. # cmdline option '-3M' trap_cfg['privMasterKey'] = conf.return_value( 'v3 trap-target {0} privacy encrypted-key'.format(trap)) if conf.exists('v3 trap-target {0} protocol'.format(trap)): trap_cfg['ipProto'] = conf.return_value( 'v3 trap-target {0} protocol'.format(trap)) if conf.exists('v3 trap-target {0} port'.format(trap)): trap_cfg['ipPort'] = conf.return_value( 'v3 trap-target {0} port'.format(trap)) if conf.exists('v3 trap-target {0} type'.format(trap)): trap_cfg['type'] = conf.return_value( 'v3 trap-target {0} type'.format(trap)) # Determine securityLevel used for SNMPv3 messages (noAuthNoPriv|authNoPriv|authPriv). # Appropriate pass phrase(s) must provided when using any level higher than noAuthNoPriv. if trap_cfg['authPassword'] or trap_cfg['authMasterKey']: if trap_cfg['privProtocol'] or trap_cfg['privPassword']: trap_cfg['secLevel'] = 'authPriv' else: trap_cfg['secLevel'] = 'authNoPriv' snmp['v3_traps'].append(trap_cfg) # # 'set service snmp v3 tsm' # if conf.exists('v3 tsm'): if conf.exists('v3 tsm local-key'): snmp['v3_tsm_key'] = conf.return_value('v3 tsm local-key') if conf.exists('v3 tsm port'): snmp['v3_tsm_port'] = conf.return_value('v3 tsm port') # # 'set service snmp v3 user' # if conf.exists('v3 user'): for user in conf.list_nodes('v3 user'): user_cfg = { 'name': user, 'authMasterKey': '', 'authPassword': '', 'authProtocol': '', 'authOID': '', 'engineID': '', 'group': '', 'mode': 'ro', 'privMasterKey': '', 'privPassword': '', 'privOID': '', 'privTsmKey': '', 'privProtocol': '' } # # v3 user {0} auth # if conf.exists('v3 user {0} auth encrypted-key'.format(user)): user_cfg['authMasterKey'] = conf.return_value( 'v3 user {0} auth encrypted-key'.format(user)) if conf.exists('v3 user {0} auth plaintext-key'.format(user)): user_cfg['authPassword'] = conf.return_value( 'v3 user {0} auth plaintext-key'.format(user)) if conf.exists('v3 user {0} auth type'.format(user)): type = conf.return_value('v3 user {0} auth type'.format(user)) user_cfg['authProtocol'] = type user_cfg['authOID'] = OIDs[type] # # v3 user {0} engineid # if conf.exists('v3 user {0} engineid'.format(user)): user_cfg['engineID'] = conf.return_value( 'v3 user {0} engineid'.format(user)) # # v3 user {0} group # if conf.exists('v3 user {0} group'.format(user)): user_cfg['group'] = conf.return_value( 'v3 user {0} group'.format(user)) # # v3 user {0} mode # if conf.exists('v3 user {0} mode'.format(user)): user_cfg['mode'] = conf.return_value( 'v3 user {0} mode'.format(user)) # # v3 user {0} privacy # if conf.exists('v3 user {0} privacy encrypted-key'.format(user)): user_cfg['privMasterKey'] = conf.return_value( 'v3 user {0} privacy encrypted-key'.format(user)) if conf.exists('v3 user {0} privacy plaintext-key'.format(user)): user_cfg['privPassword'] = conf.return_value( 'v3 user {0} privacy plaintext-key'.format(user)) if conf.exists('v3 user {0} privacy tsm-key'.format(user)): user_cfg['privTsmKey'] = conf.return_value( 'v3 user {0} privacy tsm-key'.format(user)) if conf.exists('v3 user {0} privacy type'.format(user)): type = conf.return_value( 'v3 user {0} privacy type'.format(user)) user_cfg['privProtocol'] = type user_cfg['privOID'] = OIDs[type] snmp['v3_users'].append(user_cfg) # # 'set service snmp v3 view' # if conf.exists('v3 view'): for view in conf.list_nodes('v3 view'): view_cfg = {'name': view, 'oids': []} if conf.exists('v3 view {0} oid'.format(view)): for oid in conf.list_nodes('v3 view {0} oid'.format(view)): oid_cfg = {'oid': oid} view_cfg['oids'].append(oid_cfg) snmp['v3_views'].append(view_cfg) return snmp
from vyos.config import Config from vyos.util import cmd, run if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument( '-i', '--interface', action='store', help= 'Interface name which should be added to bridge it is configured for', required=True) args, unknownargs = parser.parse_known_args() conf = Config() if not conf.list_nodes('interfaces bridge'): # no bridge interfaces exist .. bail out early exit(0) else: for bridge in conf.list_nodes('interfaces bridge'): for member_if in conf.list_nodes( 'interfaces bridge {} member interface'.format(bridge)): if args.interface == member_if: command = 'brctl addif "{}" "{}"'.format( bridge, args.interface) # let interfaces etc. settle - especially required for OpenVPN bridged interfaces sleep(4) # XXX: This is ignoring any issue, should be cmd but kept as it # XXX: during the migration to not cause any regression run(command)
def get_config(arguments): dns = deepcopy(default_config_data) conf = Config() base = ['service', 'dns', 'forwarding'] if arguments.dhclient: conf.exists = conf.exists_effective conf.return_value = conf.return_effective_value conf.return_values = conf.return_effective_values if not conf.exists(base): return None conf.set_level(base) if conf.exists(['allow-from']): dns['allow_from'] = conf.return_values(['allow-from']) if conf.exists(['cache-size']): cache_size = conf.return_value(['cache-size']) dns['cache_size'] = cache_size if conf.exists('negative-ttl'): negative_ttl = conf.return_value(['negative-ttl']) dns['negative_ttl'] = negative_ttl if conf.exists(['domain']): for node in conf.list_nodes(['domain']): servers = conf.return_values(['domain', node, 'server']) domain = {"name": node, "servers": bracketize_ipv6_addrs(servers)} dns['domains'].append(domain) if conf.exists(['ignore-hosts-file']): dns['export_hosts_file'] = "no" if conf.exists(['name-server']): name_servers = conf.return_values(['name-server']) dns['name_servers'] = dns['name_servers'] + name_servers if conf.exists(['system']): conf.set_level(['system']) system_name_servers = [] system_name_servers = conf.return_values(['name-server']) if not system_name_servers: print( "DNS forwarding warning: No name-servers set under 'system name-server'\n" ) else: dns['name_servers'] = dns['name_servers'] + system_name_servers conf.set_level(base) dns['name_servers'] = bracketize_ipv6_addrs(dns['name_servers']) if conf.exists(['listen-address']): dns['listen_on'] = conf.return_values(['listen-address']) if conf.exists(['dnssec']): dns['dnssec'] = conf.return_value(['dnssec']) # Add name servers received from DHCP if conf.exists(['dhcp']): interfaces = [] interfaces = conf.return_values(['dhcp']) hc = hostsd_client() for interface in interfaces: dhcp_resolvers = hc.get_name_servers(f'dhcp-{interface}') dhcpv6_resolvers = hc.get_name_servers(f'dhcpv6-{interface}') if dhcp_resolvers: dns['name_servers'] = dns['name_servers'] + dhcp_resolvers if dhcpv6_resolvers: dns['name_servers'] = dns['name_servers'] + dhcpv6_resolvers return dns
def get_config(): c = Config() if not c.exists('service pppoe-server'): return None config_data = { 'concentrator': 'vyos-ac', 'authentication': { 'local-users': {}, 'mode': 'local', 'radiussrv': {}, 'radiusopt': {} }, 'client_ip_pool': '', 'client_ip_subnets': [], 'client_ipv6_pool': {}, 'interface': {}, 'ppp_gw': '', 'svc_name': [], 'dns': [], 'dnsv6': [], 'wins': [], 'mtu': '1492', 'ppp_options': {}, 'limits': {}, 'snmp': 'disable', 'sesscrtl': 'replace', 'pado_delay': '' } c.set_level(['service', 'pppoe-server']) # general options if c.exists(['access-concentrator']): config_data['concentrator'] = c.return_value(['access-concentrator']) if c.exists(['service-name']): config_data['svc_name'] = c.return_values(['service-name']) if c.exists(['interface']): for intfc in c.list_nodes(['interface']): config_data['interface'][intfc] = {'vlans': []} if c.exists(['interface', intfc, 'vlan-id']): config_data['interface'][intfc]['vlans'] += c.return_values( ['interface', intfc, 'vlan-id']) if c.exists(['interface', intfc, 'vlan-range']): config_data['interface'][intfc]['vlans'] += c.return_values( ['interface', intfc, 'vlan-range']) if c.exists(['local-ip']): config_data['ppp_gw'] = c.return_value(['local-ip']) if c.exists(['dns-servers']): if c.return_value(['dns-servers', 'server-1']): config_data['dns'].append( c.return_value(['dns-servers', 'server-1'])) if c.return_value(['dns-servers', 'server-2']): config_data['dns'].append( c.return_value(['dns-servers', 'server-2'])) if c.exists(['dnsv6-servers']): if c.return_value(['dnsv6-servers', 'server-1']): config_data['dnsv6'].append( c.return_value(['dnsv6-servers', 'server-1'])) if c.return_value(['dnsv6-servers', 'server-2']): config_data['dnsv6'].append( c.return_value(['dnsv6-servers', 'server-2'])) if c.return_value(['dnsv6-servers', 'server-3']): config_data['dnsv6'].append( c.return_value(['dnsv6-servers', 'server-3'])) if c.exists(['wins-servers']): if c.return_value(['wins-servers', 'server-1']): config_data['wins'].append( c.return_value(['wins-servers', 'server-1'])) if c.return_value(['wins-servers', 'server-2']): config_data['wins'].append( c.return_value(['wins-servers', 'server-2'])) if c.exists(['client-ip-pool']): if c.exists(['client-ip-pool', 'start']): config_data['client_ip_pool'] = c.return_value( ['client-ip-pool start']) if c.exists(['client-ip-pool stop']): config_data['client_ip_pool'] += '-' + re.search( '[0-9]+$', c.return_value(['client-ip-pool', 'stop' ])).group(0) else: raise ConfigError('client ip pool stop required') if c.exists(['client-ip-pool', 'subnet']): config_data['client_ip_subnets'] = c.return_values( ['client-ip-pool', 'subnet']) if c.exists(['client-ipv6-pool', 'prefix']): config_data['client_ipv6_pool']['prefix'] = c.return_values( ['client-ipv6-pool', 'prefix']) if c.exists(['client-ipv6-pool', 'delegate-prefix']): config_data['client_ipv6_pool'][ 'delegate-prefix'] = c.return_values( ['client-ipv6-pool', 'delegate-prefix']) if c.exists(['limits']): if c.exists(['limits', 'burst']): config_data['limits']['burst'] = str( c.return_value(['limits', 'burst'])) if c.exists(['limits', 'timeout']): config_data['limits']['timeout'] = str( c.return_value(['limits', 'timeout'])) if c.exists(['limits', 'connection-limit']): config_data['limits']['conn-limit'] = str( c.return_value(['limits', 'connection-limit'])) if c.exists(['snmp']): config_data['snmp'] = 'enable' if c.exists(['snmp', 'master-agent']): config_data['snmp'] = 'enable-ma' # authentication mode local if not c.exists(['authentication', 'mode']): raise ConfigError('pppoe-server authentication mode required') if c.exists(['authentication', 'mode', 'local']): if c.exists(['authentication', 'local-users', 'username']): for usr in c.list_nodes( ['authentication', 'local-users', 'username']): config_data['authentication']['local-users'].update({ usr: { 'passwd': None, 'state': 'enabled', 'ip': '*', 'upload': None, 'download': None } }) if c.exists([ 'authentication', 'local-users', 'username', usr, 'password' ]): config_data['authentication']['local-users'][usr][ 'passwd'] = c.return_value([ 'authentication', 'local-users', 'username', usr, 'password' ]) if c.exists([ 'authentication', 'local-users', 'username', usr, 'disable' ]): config_data['authentication']['local-users'][usr][ 'state'] = 'disable' if c.exists([ 'authentication', 'local-users', 'username', usr, 'static-ip' ]): config_data['authentication']['local-users'][usr][ 'ip'] = c.return_value([ 'authentication', 'local-users', 'username', usr, 'static-ip' ]) if c.exists([ 'authentication', 'local-users', 'username', usr, 'rate-limit', 'download' ]): config_data['authentication']['local-users'][usr][ 'download'] = c.return_value([ 'authentication', 'local-users', 'username', usr, 'rate-limit', 'download' ]) if c.exists([ 'authentication', 'local-users', 'username', usr, 'rate-limit', 'upload' ]): config_data['authentication']['local-users'][usr][ 'upload'] = c.return_value([ 'authentication', 'local-users', 'username', usr, 'rate-limit', 'upload' ]) # authentication mode radius servers and settings if c.exists(['authentication', 'mode', 'radius']): config_data['authentication']['mode'] = 'radius' rsrvs = c.list_nodes(['authentication', 'radius-server']) for rsrv in rsrvs: if c.return_value( ['authentication', 'radius-server', rsrv, 'fail-time']) == None: ftime = '0' else: ftime = str( c.return_value( ['authentication', 'radius-server', rsrv, 'fail-time'])) if c.return_value( ['authentication', 'radius-server', rsrv, 'req-limit']) == None: reql = '0' else: reql = str( c.return_value( ['authentication', 'radius-server', rsrv, 'req-limit'])) config_data['authentication']['radiussrv'].update({ rsrv: { 'secret': c.return_value( ['authentication', 'radius-server', rsrv, 'secret']), 'fail-time': ftime, 'req-limit': reql } }) # advanced radius-setting if c.exists(['authentication', 'radius-settings']): if c.exists(['authentication', 'radius-settings', 'acct-timeout']): config_data['authentication']['radiusopt'][ 'acct-timeout'] = c.return_value( ['authentication', 'radius-settings', 'acct-timeout']) if c.exists(['authentication', 'radius-settings', 'max-try']): config_data['authentication']['radiusopt'][ 'max-try'] = c.return_value( ['authentication', 'radius-settings', 'max-try']) if c.exists(['authentication', 'radius-settings', 'timeout']): config_data['authentication']['radiusopt'][ 'timeout'] = c.return_value( ['authentication', 'radius-settings', 'timeout']) if c.exists( ['authentication', 'radius-settings', 'nas-identifier']): config_data['authentication']['radiusopt'][ 'nas-id'] = c.return_value([ 'authentication', 'radius-settings', 'nas-identifier' ]) if c.exists( ['authentication', 'radius-settings', 'nas-ip-address']): config_data['authentication']['radiusopt'][ 'nas-ip'] = c.return_value([ 'authentication', 'radius-settings', 'nas-ip-address' ]) if c.exists(['authentication', 'radius-settings', 'dae-server']): config_data['authentication']['radiusopt'].update({ 'dae-srv': { 'ip-addr': c.return_value([ 'authentication', 'radius-settings', 'dae-server', 'ip-address' ]), 'port': c.return_value([ 'authentication', 'radius-settings', 'dae-server', 'port' ]), 'secret': str( c.return_value([ 'authentication', 'radius-settings', 'dae-server', 'secret' ])) } }) # filter-id is the internal accel default if attribute is empty # set here as default for visibility which may change in the future if c.exists( ['authentication', 'radius-settings', 'rate-limit', 'enable']): if not c.exists([ 'authentication', 'radius-settings', 'rate-limit', 'attribute' ]): config_data['authentication']['radiusopt']['shaper'] = { 'attr': 'Filter-Id' } else: config_data['authentication']['radiusopt']['shaper'] = { 'attr': c.return_value([ 'authentication', 'radius-settings', 'rate-limit', 'attribute' ]) } if c.exists([ 'authentication', 'radius-settings', 'rate-limit', 'vendor' ]): config_data['authentication']['radiusopt']['shaper'][ 'vendor'] = c.return_value([ 'authentication', 'radius-settings', 'rate-limit', 'vendor' ]) if c.exists(['mtu']): config_data['mtu'] = c.return_value(['mtu']) # ppp_options ppp_options = {} if c.exists(['ppp-options']): if c.exists(['ppp-options', 'ccp']): ppp_options['ccp'] = c.return_value(['ppp-options', 'ccp']) if c.exists(['ppp-options', 'min-mtu']): ppp_options['min-mtu'] = c.return_value(['ppp-options', 'min-mtu']) if c.exists(['ppp-options', 'mru']): ppp_options['mru'] = c.return_value(['ppp-options', 'mru']) if c.exists(['ppp-options', 'mppe deny']): ppp_options['mppe'] = 'deny' if c.exists(['ppp-options', 'mppe', 'require']): ppp_options['mppe'] = 'require' if c.exists(['ppp-options', 'mppe', 'prefer']): ppp_options['mppe'] = 'prefer' if c.exists(['ppp-options', 'lcp-echo-failure']): ppp_options['lcp-echo-failure'] = c.return_value( ['ppp-options', 'lcp-echo-failure']) if c.exists(['ppp-options', 'lcp-echo-interval']): ppp_options['lcp-echo-interval'] = c.return_value( ['ppp-options', 'lcp-echo-interval']) if c.exists(['ppp-options', 'ipv4']): ppp_options['ipv4'] = c.return_value(['ppp-options', 'ipv4']) if c.exists(['ppp-options', 'ipv6']): ppp_options['ipv6'] = c.return_value(['ppp-options', 'ipv6']) if c.exists(['ppp-options', 'ipv6-accept-peer-intf-id']): ppp_options['ipv6-accept-peer-intf-id'] = 1 if c.exists(['ppp-options', 'ipv6-intf-id']): ppp_options['ipv6-intf-id'] = c.return_value( ['ppp-options', 'ipv6-intf-id']) if c.exists(['ppp-options', 'ipv6-peer-intf-id']): ppp_options['ipv6-peer-intf-id'] = c.return_value( ['ppp-options', 'ipv6-peer-intf-id']) if c.exists(['ppp-options', 'lcp-echo-timeout']): ppp_options['lcp-echo-timeout'] = c.return_value( ['ppp-options', 'lcp-echo-timeout']) if len(ppp_options) != 0: config_data['ppp_options'] = ppp_options if c.exists(['session-control']): config_data['sesscrtl'] = c.return_value(['session-control']) if c.exists(['pado-delay']): config_data['pado_delay'] = '0' a = {} for id in c.list_nodes(['pado-delay']): if not c.return_value(['pado-delay', id, 'sessions']): a[id] = 0 else: a[id] = c.return_value(['pado-delay', id, 'sessions']) for k in sorted(a.keys()): if k != sorted(a.keys())[-1]: config_data['pado_delay'] += ",{0}:{1}".format(k, a[k]) else: config_data['pado_delay'] += ",{0}:{1}".format('-1', a[k]) return config_data
def get_config(): dhcpv6 = deepcopy(default_config_data) conf = Config() if not conf.exists('service dhcpv6-server'): return None else: conf.set_level('service dhcpv6-server') # Check for global disable of DHCPv6 service if conf.exists('disable'): dhcpv6['disabled'] = True return dhcpv6 # Preference of this DHCPv6 server compared with others if conf.exists('preference'): dhcpv6['preference'] = conf.return_value('preference') # check for multiple, shared networks served with DHCPv6 addresses if conf.exists('shared-network-name'): for network in conf.list_nodes('shared-network-name'): conf.set_level( 'service dhcpv6-server shared-network-name {0}'.format( network)) config = {'name': network, 'disabled': False, 'subnet': []} # If disabled, the shared-network configuration becomes inactive if conf.exists('disable'): config['disabled'] = True # check for multiple subnet configurations in a shared network if conf.exists('subnet'): for net in conf.list_nodes('subnet'): conf.set_level( 'service dhcpv6-server shared-network-name {0} subnet {1}' .format(network, net)) subnet = { 'network': net, 'range6_prefix': [], 'range6': [], 'default_router': '', 'dns_server': [], 'domain_name': '', 'domain_search': [], 'lease_def': '', 'lease_min': '', 'lease_max': '', 'nis_domain': '', 'nis_server': [], 'nisp_domain': '', 'nisp_server': [], 'sip_address': [], 'sip_hostname': [], 'sntp_server': [], 'static_mapping': [] } # For any subnet on which addresses will be assigned dynamically, there must be at # least one address range statement. The range statement gives the lowest and highest # IP addresses in a range. All IP addresses in the range should be in the subnet in # which the range statement is declared. if conf.exists('address-range prefix'): for prefix in conf.list_nodes('address-range prefix'): range = {'prefix': prefix, 'temporary': False} # Address range will be used for temporary addresses if conf.exists( 'address-range prefix {0} temporary'. format(range['prefix'])): range['temporary'] = True # Append to subnet temporary range6 list subnet['range6_prefix'].append(range) if conf.exists('address-range start'): for range in conf.list_nodes('address-range start'): range = { 'start': range, 'stop': conf.return_value( 'address-range start {0} stop'.format( range)) } # Append to subnet range6 list subnet['range6'].append(range) # The domain-search option specifies a 'search list' of Domain Names to be used # by the client to locate not-fully-qualified domain names. if conf.exists('domain-search'): for domain in conf.return_values('domain-search'): subnet['domain_search'].append('"' + domain + '"') # IPv6 address valid lifetime # (at the end the address is no longer usable by the client) # (set to 30 days, the usual IPv6 default) if conf.exists('lease-time default'): subnet['lease_def'] = conf.return_value( 'lease-time default') # Time should be the maximum length in seconds that will be assigned to a lease. # The only exception to this is that Dynamic BOOTP lease lengths, which are not # specified by the client, are not limited by this maximum. if conf.exists('lease-time maximum'): subnet['lease_max'] = conf.return_value( 'lease-time maximum') # Time should be the minimum length in seconds that will be assigned to a lease if conf.exists('lease-time minimum'): subnet['lease_min'] = conf.return_value( 'lease-time minimum') # Specifies a list of Domain Name System name servers available to the client. # Servers should be listed in order of preference. if conf.exists('name-server'): subnet['dns_server'] = conf.return_values( 'name-server') # Ancient NIS (Network Information Service) domain name if conf.exists('nis-domain'): subnet['nis_domain'] = conf.return_value('nis-domain') # Ancient NIS (Network Information Service) servers if conf.exists('nis-server'): subnet['nis_server'] = conf.return_values('nis-server') # Ancient NIS+ (Network Information Service) domain name if conf.exists('nisplus-domain'): subnet['nisp_domain'] = conf.return_value( 'nisplus-domain') # Ancient NIS+ (Network Information Service) servers if conf.exists('nisplus-server'): subnet['nisp_server'] = conf.return_values( 'nisplus-server') # Prefix Delegation (RFC 3633) if conf.exists('prefix-delegation'): print( 'TODO: This option is actually not implemented right now!' ) # Local SIP server that is to be used for all outbound SIP requests - IPv6 address if conf.exists('sip-server-address'): subnet['sip_address'] = conf.return_values( 'sip-server-address') # Local SIP server that is to be used for all outbound SIP requests - hostname if conf.exists('sip-server-name'): for hostname in conf.return_values('sip-server-name'): subnet['sip_hostname'].append('"' + hostname + '"') # List of local SNTP servers available for the client to synchronize their clocks if conf.exists('sntp-server'): subnet['sntp_server'] = conf.return_values( 'sntp-server') # # Static DHCP v6 leases # if conf.exists('static-mapping'): for mapping in conf.list_nodes('static-mapping'): conf.set_level( 'service dhcpv6-server shared-network-name {0} subnet {1} static-mapping {2}' .format(network, net, mapping)) mapping = { 'name': mapping, 'disabled': False, 'ipv6_address': '', 'client_identifier': '', } # This static lease is disabled if conf.exists('disable'): mapping['disabled'] = True # IPv6 address used for this DHCP client if conf.exists('ipv6-address'): mapping['ipv6_address'] = conf.return_value( 'ipv6-address') # This option specifies the client’s DUID identifier. DUIDs are similar but different from DHCPv4 client identifiers if conf.exists('identifier'): mapping[ 'client_identifier'] = conf.return_value( 'identifier') # append static mapping configuration tu subnet list subnet['static_mapping'].append(mapping) # append subnet configuration to shared network subnet list config['subnet'].append(subnet) # append shared network configuration to config dictionary dhcpv6['shared_network'].append(config) return dhcpv6