228 lines
7.0 KiB
Python
228 lines
7.0 KiB
Python
import os
|
|
import re
|
|
|
|
import netaddr
|
|
|
|
|
|
class Interface(object):
|
|
"""
|
|
"""
|
|
def __init__(self, ifname=None, addresses=[], groups=None, flags=None,
|
|
lladdr=None, mtu=1500, media=None, description=None,
|
|
**extra_params):
|
|
self.ifname = ifname
|
|
self.description = description
|
|
self.addresses = addresses
|
|
self.groups = groups or []
|
|
self.flags = flags or []
|
|
self.lladdr = lladdr
|
|
self.mtu = mtu
|
|
self.media = media
|
|
self.extra_params = extra_params
|
|
|
|
def __repr__(self):
|
|
return '<Interface: %s %s>' % (self.ifname,
|
|
[str(a) for a in self.addresses])
|
|
|
|
@property
|
|
def description(self):
|
|
return self._description
|
|
|
|
@description.setter
|
|
def description(self, value):
|
|
if not value:
|
|
self._description = ''
|
|
elif re.match('\w*$', value):
|
|
self._description = value
|
|
else:
|
|
raise ValueError('Description must be chars from [a-zA-Z0-9_]')
|
|
|
|
@property
|
|
def addresses(self):
|
|
return self._addresses
|
|
|
|
@addresses.setter
|
|
def addresses(self, value):
|
|
self._addresses = [netaddr.IPNetwork(a) for a in value]
|
|
|
|
@property
|
|
def is_up(self):
|
|
if ('state' in self.extra_params
|
|
and self.extra_params['state'].lower() == 'up'):
|
|
return 'UP'
|
|
return 'UP' in self.flags
|
|
|
|
@classmethod
|
|
def from_dict(cls, d):
|
|
return Interface(**d)
|
|
|
|
def to_dict(self, extended=False):
|
|
include = ['ifname', 'groups', 'mtu', 'lladdr', 'media']
|
|
if extended:
|
|
include.extend(['flags', 'extra_params'])
|
|
retval = dict(
|
|
[(k, v) for k, v in vars(self).iteritems() if k in include])
|
|
retval['description'] = self.description
|
|
retval['addresses'] = self.addresses
|
|
retval['state'] = (self.is_up and 'up') or 'down'
|
|
return retval
|
|
|
|
|
|
class FilterRule(object):
|
|
"""
|
|
"""
|
|
def __init__(self, action=None, interface=None, family=None,
|
|
protocol=None, source=None, source_port=None,
|
|
destination_interface=None,
|
|
destination=None, destination_port=None,
|
|
redirect=None, redirect_port=None):
|
|
|
|
self.action = action
|
|
self.interface = interface
|
|
self.family = family
|
|
self.protocol = protocol
|
|
self.source = source
|
|
self.source_port = source_port
|
|
self.destination_interface = destination_interface
|
|
self.destination = destination
|
|
self.destination_port = destination_port
|
|
self.redirect = redirect
|
|
self.redirect_port = redirect_port
|
|
|
|
def __setattr__(self, name, value):
|
|
if name != 'action' and not value:
|
|
pass
|
|
elif name == 'action':
|
|
if value not in ('pass', 'block'):
|
|
raise ValueError("Action must be 'pass' or 'block' not '%s'" %
|
|
value)
|
|
elif name in ('source', 'destination'):
|
|
if '/' in value:
|
|
value = netaddr.IPNetwork(value)
|
|
elif name == 'redirect':
|
|
value = netaddr.IPAddress(value)
|
|
elif name.endswith('_port'):
|
|
value = int(value)
|
|
elif name == 'family':
|
|
if value not in ('inet', 'inet6'):
|
|
raise ValueError("Family must be 'inet', 'inet6', None and not"
|
|
" %s" % value)
|
|
elif name == 'protocol':
|
|
if value not in ('tcp', 'udp', 'imcp'):
|
|
raise ValueError("Protocol must be tcp|udp|imcp not '%s'." %
|
|
value)
|
|
|
|
super(FilterRule, self).__setattr__(name, value)
|
|
|
|
@property
|
|
def pf_rule(self):
|
|
retval = [self.action]
|
|
if self.interface:
|
|
retval.append('on %s' % self.interface)
|
|
if self.family:
|
|
retval.append(self.family)
|
|
if self.protocol:
|
|
retval.append('proto %s' % self.protocol)
|
|
if self.source or self.source_port:
|
|
retval.append('from')
|
|
if self.source:
|
|
retval.append(str(self.source))
|
|
if self.source_port:
|
|
retval.append('port %s' % self.source_port)
|
|
if (self.destination_interface
|
|
or self.destination
|
|
or self.destination_port):
|
|
retval.append('to')
|
|
if self.destination_interface:
|
|
retval.append(self.destination_interface)
|
|
if self.destination:
|
|
retval.append(str(self.destination))
|
|
if self.destination_port:
|
|
retval.append('port %s' % self.destination_port)
|
|
if self.redirect or self.redirect_port:
|
|
retval.append('rdr-to')
|
|
if self.redirect:
|
|
retval.append(str(self.redirect))
|
|
if self.redirect_port:
|
|
retval.append('port %s' % self.redirect_port)
|
|
return ' '.join(retval)
|
|
|
|
@classmethod
|
|
def from_dict(cls, d):
|
|
return FilterRule(**d)
|
|
|
|
def to_dict(self):
|
|
return vars(self)
|
|
|
|
|
|
class Anchor(object):
|
|
def __init__(self, name, rules=[]):
|
|
self.name = name
|
|
self.rules = rules
|
|
|
|
@property
|
|
def pf_rule(self):
|
|
pf_rules = '\n\t'.join([r.pf_rule for r in self.rules])
|
|
return "anchor %s {\n%s\n}\n" % (self.name, pf_rules)
|
|
|
|
def external_pf_rule(self, base_dir):
|
|
path = os.path.abspath(os.path.join(base_dir, self.name))
|
|
return 'anchor %s\nload anchor %s from %s' % (self.name,
|
|
self.name,
|
|
path)
|
|
|
|
|
|
class AddressBookEntry(object):
|
|
def __init__(self, name, cidrs=[]):
|
|
self.name = name
|
|
self.cidrs = cidrs
|
|
|
|
@property
|
|
def cidrs(self):
|
|
return self._cidrs
|
|
|
|
@cidrs.setter
|
|
def cidrs(self, values):
|
|
self._cidrs = [netaddr.IPNetwork(a) for a in values]
|
|
|
|
@property
|
|
def pf_rule(self):
|
|
return 'table <%s> {%s}' % (self.name, ', '.join(map(str, self.cidrs)))
|
|
|
|
def external_pf_rule(self, base_dir):
|
|
path = os.path.abspath(os.path.join(base_dir, self.name))
|
|
return 'table %s\npersist file "%s"' % (self.name,
|
|
path)
|
|
|
|
def external_table_data(self):
|
|
return '\n'.join(map(str, self.cidrs))
|
|
|
|
|
|
class Allocation(object):
|
|
def __init__(self, lladdr, hostname, ip_address):
|
|
self.lladdr = lladdr
|
|
self.hostname = hostname
|
|
self.ip_address = ip_address
|
|
|
|
|
|
class StaticRoute(object):
|
|
def __init__(self, destination, next_hop):
|
|
self.destination = destination
|
|
self.next_hop = next_hop
|
|
|
|
@property
|
|
def destination(self):
|
|
return self._destination
|
|
|
|
@destination.setter
|
|
def destination(self, value):
|
|
self._destination = netaddr.IPNetwork(value)
|
|
|
|
@property
|
|
def next_hop(self):
|
|
return self._next_hop
|
|
|
|
@next_hop.setter
|
|
def next_hop(self, value):
|
|
self._next_hop = netaddr.IPAddress(value)
|