10
10
import gnutls.connection
 
11
11
import gnutls.errors
 
12
12
import ConfigParser
 
16
14
class Client(object):
 
17
 
    def __init__(self, name=None, options=None, dn=None,
 
18
 
                 password=None, passfile=None, fqdn=None,
 
19
 
                 timeout=None, interval=-1):
 
 
15
    def __init__(self, name=None, dn=None, password=None,
 
 
16
                 passfile=None, fqdn=None, timeout=None,
 
 
28
26
            # raise RuntimeError XXX
 
29
27
            self.password = "gazonk"
 
31
 
        self.created = datetime.datetime.now()
 
32
30
        self.last_seen = None
 
33
31
        if timeout is None:
 
34
 
            timeout = options.timeout
 
 
32
            timeout = self.server.options.timeout
 
35
33
        self.timeout = timeout
 
37
 
            interval = options.interval
 
 
35
            interval = self.server.options.interval
 
38
36
        self.interval = interval
 
39
 
        self.next_check = datetime.datetime.now()
 
42
 
class server_metaclass(type):
 
43
 
    "Common behavior for the UDP and TCP server classes"
 
44
 
    def __new__(cls, name, bases, attrs):
 
45
 
        attrs["address_family"] = socket.AF_INET6
 
46
 
        attrs["allow_reuse_address"] = True
 
47
 
        def server_bind(self):
 
48
 
            if self.options.interface:
 
49
 
                if not hasattr(socket, "SO_BINDTODEVICE"):
 
50
 
                    # From /usr/include/asm-i486/socket.h
 
51
 
                    socket.SO_BINDTODEVICE = 25
 
53
 
                    self.socket.setsockopt(socket.SOL_SOCKET,
 
54
 
                                           socket.SO_BINDTODEVICE,
 
55
 
                                           self.options.interface)
 
56
 
                except socket.error, error:
 
57
 
                    if error[0] == errno.EPERM:
 
58
 
                        print "Warning: No permission to bind to interface", \
 
59
 
                              self.options.interface
 
62
 
            return super(type(self), self).server_bind()
 
63
 
        attrs["server_bind"] = server_bind
 
64
 
        def init(self, *args, **kwargs):
 
65
 
            if "options" in kwargs:
 
66
 
                self.options = kwargs["options"]
 
68
 
            if "clients" in kwargs:
 
69
 
                self.clients = kwargs["clients"]
 
71
 
            if "credentials" in kwargs:
 
72
 
                self.credentials = kwargs["credentials"]
 
73
 
                del kwargs["credentials"]
 
74
 
            return super(type(self), self).__init__(*args, **kwargs)
 
75
 
        attrs["__init__"] = init
 
76
 
        return type.__new__(cls, name, bases, attrs)
 
 
38
def server_bind(self):
 
 
39
    if self.options.interface:
 
 
40
        if not hasattr(socket, "SO_BINDTODEVICE"):
 
 
41
            # From /usr/include/asm-i486/socket.h
 
 
42
            socket.SO_BINDTODEVICE = 25
 
 
44
            self.socket.setsockopt(socket.SOL_SOCKET,
 
 
45
                                   socket.SO_BINDTODEVICE,
 
 
46
                                   self.options.interface)
 
 
47
        except socket.error, error:
 
 
48
            if error[0] == errno.EPERM:
 
 
49
                print "Warning: Denied permission to bind to interface", \
 
 
50
                      self.options.interface
 
 
53
    return super(type(self), self).server_bind()
 
 
56
def init_with_options(self, *args, **kwargs):
 
 
57
    if "options" in kwargs:
 
 
58
        self.options = kwargs["options"]
 
 
60
    if "clients" in kwargs:
 
 
61
        self.clients = kwargs["clients"]
 
 
63
    if "credentials" in kwargs:
 
 
64
        self.credentials = kwargs["credentials"]
 
 
65
        del kwargs["credentials"]
 
 
66
    return super(type(self), self).__init__(*args, **kwargs)
 
79
69
class udp_handler(SocketServer.DatagramRequestHandler, object):
 
 
85
75
class IPv6_UDPServer(SocketServer.UDPServer, object):
 
86
 
    __metaclass__ = server_metaclass
 
 
76
    __init__ = init_with_options
 
 
77
    address_family = socket.AF_INET6
 
 
78
    allow_reuse_address = True
 
 
79
    server_bind = server_bind
 
87
80
    def verify_request(self, request, client_address):
 
88
81
        print "UDP request came"
 
89
82
        return request[0] == "Marco"
 
 
119
111
class IPv6_TCPServer(SocketServer.ForkingTCPServer, object):
 
120
 
    __metaclass__ = server_metaclass
 
 
112
    __init__ = init_with_options
 
 
113
    address_family = socket.AF_INET6
 
 
114
    allow_reuse_address = True
 
121
115
    request_queue_size = 1024
 
 
116
    server_bind = server_bind
 
124
119
in6addr_any = "::"
 
128
 
def string_to_delta(interval):
 
129
 
    """Parse a string and return a datetime.timedelta
 
131
 
    >>> string_to_delta('7d')
 
132
 
    datetime.timedelta(7)
 
133
 
    >>> string_to_delta('60s')
 
134
 
    datetime.timedelta(0, 60)
 
135
 
    >>> string_to_delta('60m')
 
136
 
    datetime.timedelta(0, 3600)
 
137
 
    >>> string_to_delta('24h')
 
138
 
    datetime.timedelta(1)
 
139
 
    >>> string_to_delta(u'1w')
 
140
 
    datetime.timedelta(7)
 
143
 
        suffix=unicode(interval[-1])
 
144
 
        value=int(interval[:-1])
 
146
 
            delta = datetime.timedelta(value)
 
148
 
            delta = datetime.timedelta(0, value)
 
150
 
            delta = datetime.timedelta(0, 0, 0, 0, value)
 
152
 
            delta = datetime.timedelta(0, 0, 0, 0, 0, value)
 
154
 
            delta = datetime.timedelta(0, 0, 0, 0, 0, 0, value)
 
157
 
    except (ValueError, IndexError):
 
162
124
    parser = OptionParser()
 
163
125
    parser.add_option("-i", "--interface", type="string",
 
 
182
144
    parser.add_option("-t", "--timeout", type="string", # Parsed later
 
184
146
                      help="Amount of downtime allowed for clients")
 
185
 
    parser.add_option("--interval", type="string", # Parsed later
 
187
 
                      help="How often to check that a client is up")
 
188
 
    parser.add_option("--check", action="store_true", default=False,
 
189
 
                      help="Run self-test")
 
190
147
    (options, args) = parser.parse_args()
 
197
 
    # Parse the time arguments
 
 
149
    # Parse the time argument
 
199
 
        options.timeout = string_to_delta(options.timeout)
 
 
151
        suffix=options.timeout[-1]
 
 
152
        value=int(options.timeout[:-1])
 
 
154
            options.timeout = datetime.timedelta(value)
 
 
156
            options.timeout = datetime.timedelta(0, value)
 
 
158
            options.timeout = datetime.timedelta(0, 0, 0, 0, value)
 
 
160
            options.timeout = datetime.timedelta(0, 0, 0, 0, 0, value)
 
 
162
            options.timeout = datetime.timedelta(0, 0, 0, 0, 0, 0,
 
 
166
    except (ValueError, IndexError):
 
201
167
        parser.error("option --timeout: Unparseable time")
 
204
 
        options.interval = string_to_delta(options.interval)
 
206
 
        parser.error("option --interval: Unparseable time")
 
208
169
    cert = gnutls.crypto.X509Certificate(open(options.cert).read())
 
209
170
    key = gnutls.crypto.X509PrivateKey(open(options.key).read())
 
210
171
    ca = gnutls.crypto.X509Certificate(open(options.ca).read())