~ubuntu-branches/ubuntu/jaunty/libdumbnet/jaunty

« back to all changes in this revision

Viewing changes to python/dnet.pyx

  • Committer: Bazaar Package Importer
  • Author(s): Javier Fernandez-Sanguino Pen~a
  • Date: 2005-01-11 16:13:41 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050111161341-0a1we1xe03mnd2a1
Tags: 1.8-1.3
Fixed SONAME problem by fixing the -version-info number in
src/Makefile.am (Closes: #289777)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# dnet.pyx
 
3
#
 
4
# dnet Python bindings.
 
5
#
 
6
# Copyright (c) 2003 Dug Song <dugsong@monkey.org>
 
7
#
 
8
# $Id: dnet.pyx,v 1.9 2004/05/14 04:29:27 dugsong Exp $
 
9
 
 
10
"""dumb networking library
 
11
 
 
12
This module provides a simplified interface to several low-level
 
13
networking routines, including network address manipulation, kernel
 
14
arp(4) cache and route(4) table lookup and manipulation, network
 
15
firewalling, network interface lookup and manipulation, and raw IP
 
16
packet and Ethernet frame transmission.
 
17
"""
 
18
 
 
19
cdef extern from "dnet.h":
 
20
    pass
 
21
 
 
22
cdef extern from "Python.h":
 
23
    object  PyString_FromStringAndSize(char *s, int len)
 
24
    int     PyString_Size(object o)
 
25
 
 
26
cdef extern from *:
 
27
    void   *memcpy(char *dst, char *src, int len)
 
28
    void   *memset(char *b, int c, int len)
 
29
    char   *strerror(int errnum)
 
30
    int     strlcpy(char *dst, char *src, int size)
 
31
 
 
32
cdef __memcpy(char *dst, object src, int n):
 
33
    if PyString_Size(src) != n:
 
34
        raise ValueError, "not a %d-byte binary string: %s" % (n, src)
 
35
    memcpy(dst, src, n)
 
36
 
 
37
cdef __oserror():
 
38
    cdef extern int errno
 
39
    return strerror(errno)
 
40
 
 
41
#
 
42
# eth.h
 
43
#
 
44
cdef extern from *:
 
45
    ctypedef struct eth_t:
 
46
        int __xxx
 
47
    ctypedef struct eth_addr_t:
 
48
        char data[6]
 
49
    
 
50
    eth_t *eth_open(char *device)
 
51
    int    eth_get(eth_t *eth, eth_addr_t *ea)
 
52
    int    eth_set(eth_t *eth, eth_addr_t *ea)
 
53
    int    eth_send(eth_t *eth, char *buf, int len)
 
54
    eth_t *eth_close(eth_t *eth)
 
55
 
 
56
    char  *__eth_ntoa "eth_ntoa" (eth_addr_t *buf)
 
57
    int    __eth_aton "eth_aton" (char *src, eth_addr_t *dst)
 
58
    void   __eth_pack_hdr "eth_pack_hdr" (char *h,
 
59
               eth_addr_t dst, eth_addr_t src, int type)
 
60
 
 
61
ETH_ADDR_LEN =  6
 
62
ETH_ADDR_BITS = 48
 
63
ETH_TYPE_LEN =  2
 
64
ETH_CRC_LEN =   4
 
65
ETH_HDR_LEN =   14
 
66
 
 
67
ETH_LEN_MIN =   64              # /* minimum frame length with CRC */
 
68
ETH_LEN_MAX =   1518            # /* maximum frame length with CRC */
 
69
 
 
70
ETH_MTU =       (ETH_LEN_MAX - ETH_HDR_LEN - ETH_CRC_LEN)
 
71
ETH_MIN =       (ETH_LEN_MIN - ETH_HDR_LEN - ETH_CRC_LEN)
 
72
 
 
73
ETH_TYPE_PUP =  0x0200          # /* PUP protocol */
 
74
ETH_TYPE_IP =   0x0800          # /* IP protocol */
 
75
ETH_TYPE_ARP =  0x0806          # /* address resolution protocol */
 
76
ETH_TYPE_REVARP=0x8035          # /* reverse addr resolution protocol */
 
77
ETH_TYPE_8021Q =0x8100          # /* IEEE 802.1Q VLAN tagging */
 
78
ETH_TYPE_IPV6 = 0x86DD          # /* IPv6 protocol */
 
79
ETH_TYPE_MPLS = 0x8847          # /* MPLS */
 
80
ETH_TYPE_MPLS_MCAST =   0x8848  # /* MPLS Multicast */
 
81
ETH_TYPE_PPPOEDISC =    0x8863  # /* PPP Over Ethernet Discovery Stage */
 
82
ETH_TYPE_PPPOE =        0x8864  # /* PPP Over Ethernet Session Stage */
 
83
ETH_TYPE_LOOPBACK =     0x9000  # /* used to test interfaces */
 
84
 
 
85
ETH_ADDR_UNSPEC =       PyString_FromStringAndSize("\x00\x00\x00\x00\x00\x00", 6)
 
86
ETH_ADDR_BROADCAST =    PyString_FromStringAndSize("\xff\xff\xff\xff\xff\xff", 6)
 
87
 
 
88
cdef class eth:
 
89
    """eth(device) -> Ethernet device object
 
90
 
 
91
    Open the specified Ethernet device for sending.
 
92
    """
 
93
    cdef eth_t *eth
 
94
    
 
95
    def __init__(self, device):
 
96
        self.eth = eth_open(device)
 
97
        if not self.eth:
 
98
            raise OSError, __oserror()
 
99
        
 
100
    def get(self):
 
101
        """Return the MAC address associated with the device as a
 
102
        binary string."""
 
103
        cdef eth_addr_t ea
 
104
        if eth_get(self.eth, &ea) < 0:
 
105
            raise OSError, __oserror()
 
106
        return PyString_FromStringAndSize(ea.data, 6)
 
107
 
 
108
    def set(self, value):
 
109
        """Set the MAC address for the device, returning 0 on success,
 
110
        -1 on failure.
 
111
        
 
112
        Arguments:
 
113
        eth_addr -- 6-byte binary string (e.g. '\\x00\\xde\\xad\\xbe\\xef\\x00')
 
114
        """
 
115
        cdef eth_addr_t ea
 
116
        __memcpy(ea.data, value, 6)
 
117
        if eth_set(self.eth, &ea) < 0:
 
118
            raise OSError, __oserror()
 
119
 
 
120
    def send(self, frame):
 
121
        """Send an Ethernet frame, returning the number of bytes sent
 
122
        or -1 on failure.
 
123
        
 
124
        Arguments:
 
125
        frame -- binary string representing an Ethernet frame
 
126
        """
 
127
        return eth_send(self.eth, frame, PyString_Size(frame))
 
128
    
 
129
    def __del__(self):
 
130
        eth_close(self.eth)
 
131
 
 
132
def eth_ntoa(buf):
 
133
    """Convert an Ethernet MAC address from 6-byte packed binary string to
 
134
    a printable string ('00:de:ad:be:ef:00')."""
 
135
    cdef eth_addr_t ea
 
136
    __memcpy(ea.data, buf, 6)
 
137
    return __eth_ntoa(&ea)
 
138
 
 
139
def eth_aton(buf):
 
140
    """Convert an Ethernet MAC address from a printable string to a
 
141
    packed binary string ('\\x00\\xde\\xad\\xbe\\xef\\x00')."""
 
142
    cdef eth_addr_t ea
 
143
    if __eth_aton(buf, &ea) < 0:
 
144
        raise ValueError, "invalid Ethernet address"
 
145
    return PyString_FromStringAndSize(ea.data, 6)
 
146
 
 
147
def eth_pack_hdr(dst=ETH_ADDR_BROADCAST, src=ETH_ADDR_BROADCAST,
 
148
                 type=ETH_TYPE_IP):
 
149
    """Return a packed binary string representing an Ethernet header.
 
150
        
 
151
    Keyword arguments:
 
152
    dst  -- destination address                 (6-byte binary string)
 
153
    src  -- source address                      (6-byte binary string)
 
154
    type -- Ethernet payload type (ETH_TYPE_*)  (16-bit integer)
 
155
    """
 
156
    cdef char hdr[14]
 
157
    cdef eth_addr_t s, d
 
158
    __memcpy(s.data, src, 6)
 
159
    __memcpy(d.data, dst, 6)
 
160
    __eth_pack_hdr(hdr, d, s, type)
 
161
    return PyString_FromStringAndSize(hdr, 14)
 
162
 
 
163
#
 
164
# ip.h
 
165
#
 
166
cdef extern from *:
 
167
    ctypedef struct ip_t:
 
168
        int __xxx
 
169
    ctypedef struct ip_addr_t:
 
170
        char data[4]
 
171
 
 
172
    ip_t *ip_open()
 
173
    int   ip_send(ip_t *ip, char *buf, int len)
 
174
    ip_t *ip_close(ip_t *ip)
 
175
 
 
176
    char *__ip_ntoa "ip_ntoa" (ip_addr_t *buf)
 
177
    int   __ip_aton "ip_aton" (char *src, ip_addr_t *dst)
 
178
    void  __ip_checksum "ip_checksum" (char *buf, int len)
 
179
    void  __ip_pack_hdr "ip_pack_hdr" (char *h, int tos, int len, int id,
 
180
              int off, int ttl, int p, ip_addr_t s, ip_addr_t d)
 
181
 
 
182
IP_ADDR_LEN =   4               # /* IP address length */
 
183
IP_ADDR_BITS =  32              # /* IP address bits */
 
184
 
 
185
IP_HDR_LEN =    20              # /* base IP header length */
 
186
IP_OPT_LEN =    2               # /* base IP option length */
 
187
IP_OPT_LEN_MAX =40
 
188
IP_HDR_LEN_MAX =(IP_HDR_LEN + IP_OPT_LEN_MAX)
 
189
 
 
190
IP_LEN_MAX =    65535
 
191
IP_LEN_MIN =    IP_HDR_LEN
 
192
 
 
193
IP_TOS_DEFAULT =0x00            # /* default */
 
194
 
 
195
IP_RF =         0x8000          # /* reserved */
 
196
IP_DF =         0x4000          # /* don't fragment */
 
197
IP_MF =         0x2000          # /* more fragments (not last frag) */
 
198
IP_OFFMASK =    0x1fff          # /* mask for fragment offset */
 
199
 
 
200
IP_TTL_DEFAULT =64              # /* default ttl, RFC 1122, RFC 1340 */
 
201
IP_TTL_MAX =    255             # /* maximum ttl */
 
202
 
 
203
IP_PROTO_IP =           0               # /* dummy for IP */
 
204
IP_PROTO_ICMP =         1               # /* ICMP */
 
205
IP_PROTO_IGMP =         2               # /* IGMP */
 
206
IP_PROTO_TCP =          6               # /* TCP */
 
207
IP_PROTO_UDP =          17              # /* UDP */
 
208
IP_PROTO_IPV6 =         41              # /* IPv6 */
 
209
IP_PROTO_GRE =          47              # /* General Routing Encap */
 
210
IP_PROTO_ESP =          50              # /* Encap Security Payload */
 
211
IP_PROTO_AH =           51              # /* Authentication Header */
 
212
IP_PROTO_ICMPV6 =       58              # /* ICMP for IPv6 */
 
213
IP_PROTO_RAW =          255             # /* Raw IP packets */
 
214
IP_PROTO_RESERVED =     IP_PROTO_RAW    # /* Reserved */
 
215
IP_PROTO_MAX =          255
 
216
 
 
217
IP_ADDR_ANY =           PyString_FromStringAndSize("\x00\x00\x00\x00", 4)
 
218
IP_ADDR_BROADCAST =     PyString_FromStringAndSize("\xff\xff\xff\xff", 4)
 
219
IP_ADDR_LOOPBACK =      PyString_FromStringAndSize("\x7f\x00\x00\x01", 4)
 
220
IP_ADDR_MCAST_ALL =     PyString_FromStringAndSize("\xe0\x00\x00\x01", 4)
 
221
IP_ADDR_MCAST_LOCAL =   PyString_FromStringAndSize("\xe0\x00\x00\xff", 4)
 
222
 
 
223
cdef class ip:
 
224
    """ip() -> Raw IP object
 
225
 
 
226
    Open a raw IP socket for sending.
 
227
    """
 
228
    cdef ip_t *ip
 
229
 
 
230
    def __init__(self):
 
231
        self.ip = ip_open()
 
232
        if not self.ip:
 
233
            raise OSError, __oserror()
 
234
 
 
235
    def send(self, pkt):
 
236
        """Send an IP packet, returning the number of bytes sent
 
237
        or -1 on failure.
 
238
 
 
239
        Arguments:
 
240
        pkt -- binary string representing an IP packet
 
241
        """
 
242
        return ip_send(self.ip, pkt, PyString_Size(pkt))
 
243
 
 
244
    def __del__(self):
 
245
        ip_close(self.ip)
 
246
 
 
247
def ip_ntoa(buf):
 
248
    """Convert an IP address from a 4-byte packed binary string to a
 
249
    printable string ('10.0.0.1')."""
 
250
    cdef ip_addr_t ia
 
251
    __memcpy(<char *>&ia, buf, 4)
 
252
    return __ip_ntoa(&ia)
 
253
 
 
254
def ip_aton(buf):
 
255
    """Convert an IP address from a printable string to a
 
256
    packed binary string ('\\x0a\\x00\\x00\\x01')."""
 
257
    cdef ip_addr_t ia
 
258
    if __ip_aton(buf, &ia) < 0:
 
259
        raise ValueError, "invalid IP address"
 
260
    return PyString_FromStringAndSize(<char *>&ia, 4)
 
261
 
 
262
def ip_checksum(buf):
 
263
    """Return a packed binary string representing an IP packet 
 
264
    with the IP and transport-layer checksums set.
 
265
 
 
266
    Arguments:
 
267
    pkt -- binary string representing an IP packet
 
268
    """
 
269
    __ip_checksum(buf, PyString_Size(buf))
 
270
    return buf
 
271
 
 
272
def ip_pack_hdr(tos=IP_TOS_DEFAULT, len=IP_HDR_LEN, id=0, off=0,
 
273
                ttl=IP_TTL_DEFAULT, p=IP_PROTO_IP,
 
274
                src=IP_ADDR_ANY, dst=IP_ADDR_ANY):
 
275
    """Return a packed binary string representing an IP header.
 
276
    
 
277
    Keyword arguments:
 
278
    tos  -- type of service                     (8-bit integer)
 
279
    len -- length (IP_HDR_LEN + payload)        (16-bit integer)
 
280
    id   -- packet ID                           (16-bit integer)
 
281
    off  -- fragmentation offset                (16-bit integer)
 
282
    ttl  -- time-to-live                        (8-bit integer)
 
283
    p    -- protocol (IP_PROTO_*)               (8-bit integer)
 
284
    src  -- source address                      (4-byte binary string)
 
285
    dst  -- destination address                 (4-byte binary string)
 
286
    """
 
287
    cdef char hdr[20]
 
288
    cdef ip_addr_t s, d
 
289
    __memcpy(<char *>&s, src, 4)
 
290
    __memcpy(<char *>&d, dst, 4)
 
291
    __ip_pack_hdr(hdr, tos, len, id, off, ttl, p, s, d)
 
292
    return PyString_FromStringAndSize(hdr, 20)
 
293
 
 
294
#
 
295
# ip6.h
 
296
#
 
297
cdef extern from *:
 
298
    ctypedef struct ip6_addr_t:
 
299
        char data[16]
 
300
 
 
301
    char *__ip6_ntoa "ip6_ntoa" (ip6_addr_t *buf)
 
302
    int   __ip6_aton "ip6_aton" (char *src, ip6_addr_t *dst)
 
303
    void  __ip6_checksum "ip6_checksum" (char *buf, int len)
 
304
    void  __ip6_pack_hdr "ip6_pack_hdr" (char *h, int fd, int fl, int plen,
 
305
              int nxt, int hlim, ip6_addr_t s, ip6_addr_t d)
 
306
 
 
307
IP6_ADDR_LEN =  16
 
308
IP6_ADDR_BITS = 128
 
309
 
 
310
IP6_HDR_LEN =   40              # /* IPv6 header length */
 
311
IP6_LEN_MIN =   IP6_HDR_LEN
 
312
IP6_LEN_MAX =   65535           # /* non-jumbo payload */
 
313
 
 
314
IP6_MTU_MIN =   1280            # /* minimum MTU (1024 + 256) */
 
315
 
 
316
IP6_HLIM_DEFAULT=64
 
317
IP6_HLIM_MAX =  255
 
318
 
 
319
IP6_ADDR_UNSPEC = PyString_FromStringAndSize("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)
 
320
IP6_ADDR_LOOPBACK = PyString_FromStringAndSize("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 16)
 
321
 
 
322
def ip6_ntoa(buf):
 
323
    """Convert an IPv6 address from a 16-byte packed binary string to a
 
324
    printable string ('10.0.0.1')."""
 
325
    cdef ip6_addr_t ia
 
326
    __memcpy(<char *>&ia, buf, 16)
 
327
    return __ip6_ntoa(&ia)
 
328
 
 
329
def ip6_aton(buf):
 
330
    """Convert an IPv6 address from a printable string to a
 
331
    packed binary string ('\\x0a\\x00\\x00\\x01')."""
 
332
    cdef ip6_addr_t ia
 
333
    if __ip6_aton(buf, &ia) < 0:
 
334
        raise ValueError, "invalid IPv6 address"
 
335
    return PyString_FromStringAndSize(<char *>&ia, 16)
 
336
 
 
337
def ip6_checksum(buf):
 
338
    """Return a packed binary string representing an IPv6 packet 
 
339
    with the IPv6 and transport-layer checksums set.
 
340
 
 
341
    Arguments:
 
342
    pkt -- binary string representing an IPv6 packet
 
343
    """
 
344
    __ip6_checksum(buf, PyString_Size(buf))
 
345
    return buf
 
346
 
 
347
def ip6_pack_hdr(fc=0, fl=0, plen=0, nxt=IP_PROTO_IPV6, hlim=IP6_HLIM_DEFAULT,
 
348
                 src=IP6_ADDR_UNSPEC, dst=IP6_ADDR_UNSPEC):
 
349
    """Return a packed binary string representing an IPv6 header.
 
350
    
 
351
    Keyword arguments:
 
352
    fc   -- flow class                  (8-bit integer)
 
353
    fl   -- flow label                  (20-bit integer)
 
354
    plen -- payload length              (16-bit integer)
 
355
    nxt  -- next header (IP_PROTO_*)    (8-bit integer)
 
356
    hlim -- hop limit                   (8-bit integer)
 
357
    src  -- source address              (16-byte binary string)
 
358
    dst  -- destination address         (16-byte binary string)
 
359
    """
 
360
    cdef char hdr[40]
 
361
    cdef ip6_addr_t s, d
 
362
    __memcpy(<char *>&s, src, 16)
 
363
    __memcpy(<char *>&d, dst, 16)
 
364
    __ip6_pack_hdr(hdr, fc, fl, plen, nxt, hlim, s, d)
 
365
    return PyString_FromStringAndSize(hdr, 40)
 
366
 
 
367
#
 
368
# addr.h
 
369
#
 
370
cdef extern from *:
 
371
    cdef struct addr_t "addr":
 
372
        unsigned short addr_type
 
373
        unsigned short addr_bits
 
374
        char           addr_data8[16]
 
375
 
 
376
    int   addr_cmp(addr_t *a, addr_t *b)
 
377
    int   addr_bcast(addr_t *a, addr_t *b)
 
378
    int   addr_net(addr_t *a, addr_t *b)
 
379
    char *addr_ntoa(addr_t *a)
 
380
    int   addr_aton(char *src, addr_t *dst)
 
381
 
 
382
ADDR_TYPE_NONE =        0
 
383
ADDR_TYPE_ETH =         1
 
384
ADDR_TYPE_IP =          2
 
385
ADDR_TYPE_IP6 =         3
 
386
 
 
387
cdef class addr:
 
388
    """addr(addrtxt=None) -> network address object
 
389
 
 
390
    Create a network address object (optionally from its human-readable
 
391
    representation). Ethernet, IP, and IPv6 address types are currently
 
392
    supported.
 
393
    """
 
394
    cdef addr_t _addr
 
395
    
 
396
    def __init__(self, addrtxt=None):
 
397
        if addrtxt != None and addr_aton(addrtxt, &self._addr) < 0:
 
398
            raise ValueError, "invalid network address"
 
399
    
 
400
    property type:
 
401
        """Address type (ADDR_TYPE_*) integer."""
 
402
        def __get__(self):
 
403
            return self._addr.addr_type
 
404
        def __set__(self, unsigned int value):
 
405
            if value > 0xffff: raise OverflowError
 
406
            self._addr.addr_type = value
 
407
    
 
408
    property bits:
 
409
        """Address bitlength integer."""
 
410
        def __get__(self):
 
411
            return self._addr.addr_bits
 
412
        def __set__(self, unsigned int value):
 
413
            if value > 0xffff: raise OverflowError
 
414
            self._addr.addr_bits = value
 
415
 
 
416
    property eth:
 
417
        """Ethernet MAC address as binary string."""
 
418
        def __get__(self):
 
419
            if self._addr.addr_type != ADDR_TYPE_ETH:
 
420
                raise ValueError, "non-Ethernet address"
 
421
            return PyString_FromStringAndSize(self._addr.addr_data8, 6)
 
422
        
 
423
        def __set__(self, value):
 
424
            if self._addr.addr_type != ADDR_TYPE_ETH:
 
425
                raise ValueError, "non-Ethernet address"
 
426
            __memcpy(self._addr.addr_data8, value, 6)
 
427
    
 
428
    property ip:
 
429
        """IPv4 address as binary string."""
 
430
        def __get__(self):
 
431
            if self._addr.addr_type != ADDR_TYPE_IP:
 
432
                raise ValueError, "non-IP address"
 
433
            return PyString_FromStringAndSize(self._addr.addr_data8, 4)
 
434
        
 
435
        def __set__(self, value):
 
436
            if self._addr.addr_type != ADDR_TYPE_IP:
 
437
                raise ValueError, "non-IP address"
 
438
            __memcpy(self._addr.addr_data8, value, 4)
 
439
    
 
440
    property ip6:
 
441
        """IPv6 address as binary string."""
 
442
        def __get__(self):
 
443
            if self._addr.addr_type != ADDR_TYPE_IP6:
 
444
                raise ValueError, "non-IPv6 address"
 
445
            return PyString_FromStringAndSize(self._addr.addr_data8, 16)
 
446
        
 
447
        def __set__(self, value):
 
448
            if self._addr.addr_type != ADDR_TYPE_IP6:
 
449
                raise ValueError, "non-IPv6 address"
 
450
            __memcpy(self._addr.addr_data8, value, 16)
 
451
 
 
452
    def bcast(self):
 
453
        """Return an addr object for our broadcast address."""
 
454
        bcast = addr()
 
455
        addr_bcast(&self._addr, &(<addr>bcast)._addr)
 
456
        return bcast
 
457
 
 
458
    def net(self):
 
459
        """Return an addr object for our network address."""
 
460
        net = addr()
 
461
        addr_net(&self._addr, &(<addr>net)._addr)
 
462
        return net
 
463
    
 
464
    def __copy__(self):
 
465
        a = addr()
 
466
        memcpy(<char *>&(<addr>a)._addr, <char *>&self._addr,
 
467
               sizeof(self._addr))
 
468
        return a
 
469
    
 
470
    def __cmp__(addr x, addr y):
 
471
        return addr_cmp(&x._addr, &y._addr)
 
472
 
 
473
    def __contains__(self, addr other):
 
474
        cdef addr_t s1, s2, o1, o2
 
475
        if addr_net(&self._addr, &s1) != 0 or \
 
476
           addr_bcast(&self._addr, &s2) != 0 or \
 
477
           addr_net(&other._addr, &o1) != 0 or \
 
478
           addr_bcast(&other._addr, &o2) != 0:
 
479
            return 0
 
480
        return addr_cmp(&o1, &s1) >= 0 and addr_cmp(&o2, &s2) <= 0
 
481
 
 
482
    def __str__(self):
 
483
        cdef char *p
 
484
        p = addr_ntoa(&self._addr)
 
485
        if not p:
 
486
            return '<invalid address>'
 
487
        return p
 
488
 
 
489
#
 
490
# arp.h
 
491
#
 
492
cdef extern from *:
 
493
    cdef struct arp_entry:
 
494
        addr_t arp_pa
 
495
        addr_t arp_ha
 
496
    ctypedef struct arp_t:
 
497
        int __xxx
 
498
    ctypedef int (*arp_handler)(arp_entry *entry, void *arg)
 
499
    
 
500
    arp_t *arp_open()
 
501
    int    arp_add(arp_t *arp, arp_entry *entry)
 
502
    int    arp_delete(arp_t *arp, arp_entry *entry)
 
503
    int    arp_get(arp_t *arp, arp_entry *entry)
 
504
    int    arp_loop(arp_t *arp, arp_handler callback, void *arg)
 
505
    arp_t *arp_close(arp_t *arp)
 
506
 
 
507
    void   __arp_pack_hdr_ethip "arp_pack_hdr_ethip" (char *buf,
 
508
               int op, eth_addr_t sha, ip_addr_t spa,
 
509
               eth_addr_t dha, ip_addr_t dpa)
 
510
 
 
511
ARP_HDR_LEN =   8       # /* base ARP header length */
 
512
ARP_ETHIP_LEN = 20      # /* base ARP message length */
 
513
 
 
514
ARP_HRD_ETH =   0x0001  # /* ethernet hardware */
 
515
ARP_HRD_IEEE802=0x0006  # /* IEEE 802 hardware */
 
516
 
 
517
ARP_PRO_IP =    0x0800  # /* IP protocol */
 
518
 
 
519
ARP_OP_REQUEST =        1       # /* request to resolve ha given pa */
 
520
ARP_OP_REPLY =          2       # /* response giving hardware address */
 
521
ARP_OP_REVREQUEST =     3       # /* request to resolve pa given ha */
 
522
ARP_OP_REVREPLY =       4       # /* response giving protocol address */
 
523
 
 
524
cdef int __arp_callback(arp_entry *entry, void *arg):
 
525
    f, a = <object>arg
 
526
    ret = f(addr(addr_ntoa(&entry.arp_pa)), addr(addr_ntoa(&entry.arp_ha)), a)
 
527
    if not ret:
 
528
        ret = 0
 
529
    return ret
 
530
 
 
531
cdef class arp:
 
532
    """arp() -> ARP table object
 
533
 
 
534
    Open a handle to the system ARP table.
 
535
    """
 
536
    cdef arp_t *arp
 
537
    
 
538
    def __init__(self):
 
539
        self.arp = arp_open()
 
540
        if not self.arp:
 
541
            raise OSError, __oserror()
 
542
 
 
543
    def add(self, addr pa, addr ha):
 
544
        """Add an entry to the system ARP table.
 
545
 
 
546
        Arguments:
 
547
        pa -- ADDR_TYPE_IP network address object
 
548
        ha -- ADDR_TYPE_ETH network address object
 
549
        """
 
550
        cdef arp_entry entry
 
551
        entry.arp_pa = pa._addr
 
552
        entry.arp_ha = ha._addr
 
553
        if arp_add(self.arp, &entry) < 0:
 
554
            raise OSError, __oserror()
 
555
 
 
556
    def delete(self, addr pa):
 
557
        """Delete an entry from the system ARP table.
 
558
 
 
559
        Arguments:
 
560
        pa -- ADDR_TYPE_IP network address object
 
561
        """
 
562
        cdef arp_entry entry
 
563
        entry.arp_pa = pa._addr
 
564
        if arp_delete(self.arp, &entry) < 0:
 
565
            raise OSError, __oserror()
 
566
    
 
567
    def get(self, addr pa):
 
568
        """Return the hardware address for a given protocol address
 
569
        in the system ARP table.
 
570
 
 
571
        Arguments:
 
572
        pa -- ADDR_TYPE_IP network address object
 
573
        """
 
574
        cdef arp_entry entry
 
575
        entry.arp_pa = pa._addr
 
576
        if arp_get(self.arp, &entry) == 0:
 
577
            return addr(addr_ntoa(&entry.arp_ha))
 
578
        return None
 
579
 
 
580
    def loop(self, callback, arg=None):
 
581
        """Iterate over the system ARP table, invoking a user callback
 
582
        with each entry, returning the status of the callback routine.
 
583
 
 
584
        Keyword arguments:
 
585
        callback -- callback function with (pa, ha, arg) prototype.
 
586
                    If this function returns a non-zero value, the loop
 
587
                    will break early.
 
588
        arg      -- optional callback argument
 
589
        """
 
590
        _arg = (callback, arg)
 
591
        return arp_loop(self.arp, __arp_callback, <void *>_arg)
 
592
    
 
593
    def __del__(self):
 
594
        arp_close(self.arp)
 
595
 
 
596
def arp_pack_hdr_ethip(op=ARP_OP_REQUEST,
 
597
                       sha=ETH_ADDR_UNSPEC, spa=IP_ADDR_ANY,
 
598
                       dha=ETH_ADDR_UNSPEC, dpa=IP_ADDR_ANY):
 
599
    """Return a packed binary string representing an Ethernet/IP ARP message.
 
600
    
 
601
    Keyword arguments:
 
602
    op  -- operation (ARP_OP_*)                 (16-bit integer)
 
603
    sha -- sender Ethernet address              (6-byte binary string)
 
604
    spa -- sender IP address                    (4-byte binary string)
 
605
    dha -- destination Ethernet address         (6-byte binary string)
 
606
    dpa -- destination IP address               (4-byte binary string)
 
607
    """
 
608
    cdef char buf[28]
 
609
    cdef eth_addr_t sh, dh
 
610
    cdef ip_addr_t sp, dp
 
611
    __memcpy(sh.data, sha, 6)
 
612
    __memcpy(dh.data, dha, 6)
 
613
    __memcpy(<char *>&sp, spa, 4)
 
614
    __memcpy(<char *>&dp, dpa, 4)
 
615
    __arp_pack_hdr_ethip(buf, op, sh, sp, dh, dp)
 
616
    return PyString_FromStringAndSize(buf, 28)
 
617
 
 
618
#
 
619
# icmp.h
 
620
#
 
621
cdef extern from *:
 
622
    void __icmp_pack_hdr "icmp_pack_hdr" (char *hdr, int type, int code)
 
623
    
 
624
def icmp_pack_hdr(type, code):
 
625
    """Return a packed binary string representing an ICMP header.
 
626
 
 
627
    Keyword arguments:
 
628
    type -- ICMP type           (8-bit integer)
 
629
    code -- ICMP code           (8-bit integer)
 
630
    """
 
631
    cdef char buf[4]
 
632
    __icmp_pack_hdr(buf, type, code)
 
633
    return PyString_FromStringAndSize(buf, sizeof(buf))
 
634
 
 
635
#
 
636
# tcp.h
 
637
#
 
638
cdef extern from *:
 
639
    void __tcp_pack_hdr "tcp_pack_hdr" (char *hdr,
 
640
        int sport, int dport, unsigned long seq, unsigned long ack, int flags, int win, int urp)
 
641
 
 
642
TCP_HDR_LEN =   20              # /* base TCP header length */
 
643
 
 
644
TH_FIN =        0x01            # /* end of data */
 
645
TH_SYN =        0x02            # /* synchronize sequence numbers */
 
646
TH_RST =        0x04            # /* reset connection */
 
647
TH_PUSH =       0x08            # /* push */
 
648
TH_ACK =        0x10            # /* acknowledgement number set */
 
649
TH_URG =        0x20            # /* urgent pointer set */
 
650
TH_ECE =        0x40            # /* ECN echo, RFC 3168 */
 
651
TH_CWR =        0x80            # /* congestion window reduced */
 
652
 
 
653
TCP_PORT_MAX =  65535           # /* maximum port */
 
654
TCP_WIN_MAX =   65535           # /* maximum (unscaled) window */
 
655
 
 
656
def tcp_pack_hdr(sport, dport, seq=1, ack=0, flags=TH_SYN,
 
657
                 win=TCP_WIN_MAX, urp=0):
 
658
    """Return a packed binary string representing a TCP header.
 
659
 
 
660
    Keyword arguments:
 
661
    sport -- source port                (16-bit integer)
 
662
    dport -- destination port           (16-bit integer)
 
663
    seq   -- sequence number            (32-bit integer)
 
664
    ack   -- acknowledgment number      (32-bit integer)
 
665
    flags -- control flags (TH_*)       (8-bit integer bitmask)
 
666
    win   -- window size                (16-bit integer)
 
667
    urp   -- urgent pointer             (16-bit integer)
 
668
    """
 
669
    cdef char buf[20]
 
670
    __tcp_pack_hdr(buf, sport, dport, seq, ack, flags, win, urp)
 
671
    return PyString_FromStringAndSize(buf, sizeof(buf))
 
672
 
 
673
#
 
674
# udp.h
 
675
#
 
676
cdef extern from *:
 
677
    void __udp_pack_hdr "udp_pack_hdr" (char *hdr, int sport, int dport, int ulen)
 
678
 
 
679
UDP_HDR_LEN =   8
 
680
UDP_PORT_MAX =  65535
 
681
 
 
682
def udp_pack_hdr(sport, dport, ulen=UDP_HDR_LEN):
 
683
    """Return a packed binary string representing a UDP header.
 
684
 
 
685
    Keyword arguments:
 
686
    sport -- source port                (16-bit integer)
 
687
    dport -- destination port           (16-bit integer)
 
688
    ulen  -- UDP header + data length   (16-bit integer)
 
689
    """
 
690
    cdef char buf[8]
 
691
    __udp_pack_hdr(buf, sport, dport, ulen)
 
692
    return PyString_FromStringAndSize(buf, sizeof(buf))
 
693
 
 
694
#
 
695
# intf.h
 
696
#
 
697
cdef extern from *:
 
698
    struct intf_entry:
 
699
        unsigned int    intf_len
 
700
        char            intf_name[16]
 
701
        unsigned short  intf_type
 
702
        unsigned short  intf_flags
 
703
        unsigned int    intf_mtu
 
704
        addr_t          intf_addr
 
705
        addr_t          intf_dst_addr
 
706
        addr_t          intf_link_addr
 
707
        unsigned int    intf_alias_num
 
708
        addr_t          intf_alias_addrs[8]     # XXX
 
709
    ctypedef struct intf_t:
 
710
        int __xxx
 
711
    ctypedef int (*intf_handler)(intf_entry *entry, void *arg)
 
712
    
 
713
    intf_t *intf_open()
 
714
    int     intf_get(intf_t *intf, intf_entry *entry)
 
715
    int     intf_get_src(intf_t *intf, intf_entry *entry, addr_t *src)
 
716
    int     intf_get_dst(intf_t *intf, intf_entry *entry, addr_t *dst)
 
717
    int     intf_set(intf_t *intf, intf_entry *entry)
 
718
    int     intf_loop(intf_t *intf, intf_handler callback, void *arg)
 
719
    intf_t *intf_close(intf_t *intf)
 
720
 
 
721
INTF_TYPE_OTHER =       1       # /* other */
 
722
INTF_TYPE_ETH =         6       # /* Ethernet */
 
723
INTF_TYPE_LOOPBACK =    24      # /* software loopback */
 
724
INTF_TYPE_TUN =         53      # /* proprietary virtual/internal */
 
725
 
 
726
INTF_FLAG_UP =          0x01    # /* enable interface */
 
727
INTF_FLAG_LOOPBACK =    0x02    # /* is a loopback net (r/o) */
 
728
INTF_FLAG_POINTOPOINT = 0x04    # /* point-to-point link (r/o) */
 
729
INTF_FLAG_NOARP =       0x08    # /* disable ARP */
 
730
INTF_FLAG_BROADCAST =   0x10    # /* supports broadcast (r/o) */
 
731
INTF_FLAG_MULTICAST =   0x20    # /* supports multicast (r/o) */
 
732
 
 
733
cdef object ifent_to_dict(intf_entry *entry):
 
734
    d = {}
 
735
    d['name'] = entry.intf_name
 
736
    d['type'] = entry.intf_type
 
737
    d['flags'] = entry.intf_flags
 
738
    d['mtu'] = entry.intf_mtu
 
739
    if entry.intf_addr.addr_type != ADDR_TYPE_NONE:
 
740
        d['addr'] = addr(addr_ntoa(&entry.intf_addr))
 
741
    if entry.intf_dst_addr.addr_type != ADDR_TYPE_NONE:
 
742
        d['dst_addr'] = addr(addr_ntoa(&entry.intf_dst_addr))
 
743
    if entry.intf_link_addr.addr_type != ADDR_TYPE_NONE:
 
744
        d['link_addr'] = addr(addr_ntoa(&entry.intf_link_addr))
 
745
    if entry.intf_alias_num > 0:
 
746
        l = []
 
747
        for i from 0 <= i < entry.intf_alias_num:
 
748
            l.append(addr(addr_ntoa(&entry.intf_alias_addrs[i])))
 
749
        d['alias_addrs'] = l
 
750
    return d
 
751
 
 
752
cdef dict_to_ifent(object d, intf_entry *entry):
 
753
    s = d['name']
 
754
    strlcpy(entry.intf_name, s, 16)
 
755
    if 'flags' in d:
 
756
        entry.intf_flags = d['flags']
 
757
    if 'mtu' in d:
 
758
        entry.intf_mtu = d['mtu']
 
759
    if 'addr' in d:
 
760
        entry.intf_addr = (<addr>d['addr'])._addr
 
761
    if 'dst_addr' in d:
 
762
        entry.intf_dst_addr = (<addr>d['dst_addr'])._addr
 
763
    if 'link_addr' in d:
 
764
        entry.intf_link_addr = (<addr>d['link_addr'])._addr
 
765
    if 'alias_addrs' in d:
 
766
        entry.intf_alias_num = len(d['alias_addrs'])
 
767
        for i from 0 <= i < entry.intf_alias_num:
 
768
            entry.intf_alias_addrs[i] = (<addr>d['alias_addrs'][i])._addr
 
769
 
 
770
cdef int __intf_callback(intf_entry *entry, void *arg):
 
771
    f, a = <object>arg
 
772
    ret = f(ifent_to_dict(entry), a)
 
773
    if not ret:
 
774
        ret = 0
 
775
    return ret
 
776
 
 
777
cdef class intf:
 
778
    """intf() -> Interface table object
 
779
 
 
780
    Open a handle to the system network interface table.
 
781
    """
 
782
    cdef intf_t *intf
 
783
 
 
784
    def __init__(self):
 
785
        self.intf = intf_open()
 
786
        if not self.intf:
 
787
            raise OSError, __oserror()
 
788
    
 
789
    def get(self, name):
 
790
        """Return the configuration for a network interface as a dict.
 
791
        """
 
792
        cdef intf_entry *ifent
 
793
        cdef char buf[1024]
 
794
        ifent = <intf_entry *>buf
 
795
        ifent.intf_len = 1024
 
796
        strlcpy(ifent.intf_name, name, 16)
 
797
        if intf_get(self.intf, ifent) < 0:
 
798
            raise OSError, __oserror()
 
799
        return ifent_to_dict(ifent)
 
800
 
 
801
    def get_src(self, addr src):
 
802
        """Return the configuration for the interface whose primary address
 
803
        matches the specified source address.
 
804
        """
 
805
        cdef intf_entry *ifent
 
806
        cdef char buf[1024]
 
807
        ifent = <intf_entry *>buf
 
808
        ifent.intf_len = 1024
 
809
        if intf_get_src(self.intf, ifent, &src._addr) < 0:
 
810
            raise OSError, __oserror()
 
811
        return ifent_to_dict(ifent)
 
812
        
 
813
    def get_dst(self, addr dst):
 
814
        """Return the configuration for the best interface with which to
 
815
        reach the specified dst address.
 
816
        """
 
817
        cdef intf_entry *ifent
 
818
        cdef char buf[1024]
 
819
        ifent = <intf_entry *>buf
 
820
        ifent.intf_len = 1024
 
821
        if intf_get_dst(self.intf, ifent, &dst._addr) < 0:
 
822
            raise OSError, __oserror()
 
823
        return ifent_to_dict(ifent)
 
824
    
 
825
    def set(self, d):
 
826
        """Set the configuration for an interface from a dict.
 
827
 
 
828
        Dict values:
 
829
        name        -- name of interface to set         (string)
 
830
        flags       -- interface flags (INTF_FLAG_*)    (integer bitmask)
 
831
        mtu         -- interface MTU                    (integer)
 
832
        addr        -- primary network address          (addr object)
 
833
        dst_addr    -- point-to-point dst address       (addr object)
 
834
        link_addr   -- link-layer address               (addr object)
 
835
        alias_addrs -- additional network addresses     (list of addr objects)
 
836
        """
 
837
        cdef intf_entry *ifent
 
838
        cdef char buf[1024]
 
839
        memset(buf, 0, sizeof(buf))
 
840
        ifent = <intf_entry *>buf
 
841
        ifent.intf_len = 1024
 
842
        dict_to_ifent(d, ifent)
 
843
        if intf_set(self.intf, ifent) < 0:
 
844
            raise OSError, __oserror()
 
845
    
 
846
    def loop(self, callback, arg=None):
 
847
        """Iterate over the system interface table, invoking a user callback
 
848
        with each entry, returning the status of the callback routine.
 
849
 
 
850
        Keyword arguments:
 
851
        callback -- callback function with (dict, arg) prototype.
 
852
                    If this function returns a non-zero value, the loop
 
853
                    will break early.
 
854
        arg      -- optional callback argument
 
855
        """
 
856
        _arg = (callback, arg)
 
857
        return intf_loop(self.intf, __intf_callback, <void *>_arg)
 
858
    
 
859
    def __del__(self):
 
860
        intf_close(self.intf)
 
861
 
 
862
#
 
863
# route.h
 
864
#
 
865
cdef extern from *:
 
866
    cdef struct route_entry:
 
867
        addr_t route_dst
 
868
        addr_t route_gw
 
869
    ctypedef struct route_t:
 
870
        int __xxx
 
871
    ctypedef int (*route_handler)(route_entry *entry, void *arg)
 
872
    
 
873
    route_t *route_open()
 
874
    int      route_add(route_t *route, route_entry *entry)
 
875
    int      route_delete(route_t *route, route_entry *entry)
 
876
    int      route_get(route_t *route, route_entry *entry)
 
877
    int      route_loop(route_t *route, route_handler callback, void *arg)
 
878
    route_t *route_close(route_t *route)
 
879
 
 
880
cdef int __route_callback(route_entry *entry, void *arg):
 
881
    f, a = <object>arg
 
882
    ret = f(addr(addr_ntoa(&entry.route_dst)),
 
883
            addr(addr_ntoa(&entry.route_gw)), a)
 
884
    if not ret:
 
885
        ret = 0
 
886
    return ret
 
887
 
 
888
cdef class route:
 
889
    """route() -> Routing table object
 
890
 
 
891
    Open a handle to the system routing table.
 
892
    """
 
893
    cdef route_t *route
 
894
    
 
895
    def __init__(self):
 
896
        self.route = route_open()
 
897
        if not self.route:
 
898
            raise OSError, __oserror()
 
899
 
 
900
    def add(self, addr dst, addr gw):
 
901
        """Add an entry to the system routing table.
 
902
 
 
903
        Arguments:
 
904
        dst -- ADDR_TYPE_IP network address object
 
905
        gw -- ADDR_TYPE_IP network address object
 
906
        """
 
907
        cdef route_entry entry
 
908
        entry.route_dst = dst._addr
 
909
        entry.route_gw = gw._addr
 
910
        if route_add(self.route, &entry) < 0:
 
911
            raise OSError, __oserror()
 
912
 
 
913
    def delete(self, addr dst):
 
914
        """Delete an entry from the system routing table.
 
915
 
 
916
        Arguments:
 
917
        dst -- ADDR_TYPE_IP network address object
 
918
        """
 
919
        cdef route_entry entry
 
920
        entry.route_dst = dst._addr
 
921
        if route_delete(self.route, &entry) < 0:
 
922
            raise OSError, __oserror()
 
923
    
 
924
    def get(self, addr dst):
 
925
        """Return the hardware address for a given protocol address
 
926
        in the system routing table.
 
927
 
 
928
        Arguments:
 
929
        dst -- ADDR_TYPE_IP network address object
 
930
        """
 
931
        cdef route_entry entry
 
932
        entry.route_dst = dst._addr
 
933
        if route_get(self.route, &entry) == 0:
 
934
            return addr(addr_ntoa(&entry.route_gw))
 
935
        return None
 
936
 
 
937
    def loop(self, callback, arg=None):
 
938
        """Iterate over the system routing table, invoking a user callback
 
939
        with each entry, returning the status of the callback routine.
 
940
 
 
941
        Keyword arguments:
 
942
        callback -- callback function with (dst, gw, arg) prototype.
 
943
                    If this function returns a non-zero value, the loop
 
944
                    will break early.
 
945
        arg      -- optional callback argument
 
946
        """
 
947
        _arg = (callback, arg)
 
948
        return route_loop(self.route, __route_callback, <void *>_arg)
 
949
    
 
950
    def __del__(self):
 
951
        route_close(self.route)
 
952
 
 
953
#
 
954
# fw.h
 
955
#
 
956
cdef extern from *:
 
957
    cdef struct fw_rule:
 
958
        char    fw_device[16]
 
959
        int     fw_op
 
960
        int     fw_dir
 
961
        int     fw_proto
 
962
        addr_t  fw_src
 
963
        addr_t  fw_dst
 
964
        int     fw_sport[2]
 
965
        int     fw_dport[2]
 
966
    
 
967
    ctypedef struct fw_t:
 
968
        int __xxx
 
969
    ctypedef int (*fw_handler)(fw_rule *rule, void *arg)
 
970
 
 
971
    fw_t *fw_open()
 
972
    int   fw_add(fw_t *f, fw_rule *rule)
 
973
    int   fw_delete(fw_t *f, fw_rule *rule)
 
974
    int   fw_loop(fw_t *f, fw_handler callback, void *arg)
 
975
    fw_t *fw_close(fw_t *f)
 
976
 
 
977
FW_OP_ALLOW =   1
 
978
FW_OP_BLOCK =   2
 
979
 
 
980
FW_DIR_IN =     1
 
981
FW_DIR_OUT =    2
 
982
 
 
983
cdef object rule_to_dict(fw_rule *rule):
 
984
    d = {}
 
985
    d['device'] = rule.fw_device
 
986
    d['op'] = rule.fw_op
 
987
    d['dir'] = rule.fw_dir
 
988
    if rule.fw_proto != 0:
 
989
        d['proto'] = rule.fw_proto
 
990
    if rule.fw_src.addr_type != ADDR_TYPE_NONE:
 
991
        d['src'] = addr(addr_ntoa(&rule.fw_src))
 
992
    if rule.fw_dst.addr_type != ADDR_TYPE_NONE:
 
993
        d['dst'] = addr(addr_ntoa(&rule.fw_dst))
 
994
    if not (rule.fw_sport[0] == 0 and rule.fw_sport[1] == 0):
 
995
        d['sport'] = [ rule.fw_sport[0], rule.fw_sport[1] ]
 
996
    if not (rule.fw_dport[0] == 0 and rule.fw_dport[1] == 0):
 
997
        d['dport'] = [ rule.fw_dport[0], rule.fw_dport[1] ]
 
998
    return d
 
999
 
 
1000
cdef dict_to_rule(object d, fw_rule *rule):
 
1001
    s = d['device']
 
1002
    strlcpy(rule.fw_device, s, 16)
 
1003
    rule.fw_op = d['op']
 
1004
    rule.fw_dir = d['dir']
 
1005
    if 'proto' in d:
 
1006
        rule.fw_proto = d['proto']
 
1007
        if rule.fw_proto == IP_PROTO_TCP or rule.fw_proto == IP_PROTO_UDP:
 
1008
            rule.fw_sport[1] = 65535
 
1009
            rule.fw_dport[1] = 65535
 
1010
    if 'src' in d:
 
1011
        rule.fw_src = (<addr>d['src'])._addr
 
1012
    if 'dst' in d:
 
1013
        rule.fw_dst = (<addr>d['dst'])._addr
 
1014
    if 'sport' in d:
 
1015
        rule.fw_sport[0] = d['sport'][0]
 
1016
        rule.fw_sport[1] = d['sport'][1]
 
1017
    if 'dport' in d:
 
1018
        rule.fw_dport[0] = d['dport'][0]
 
1019
        rule.fw_dport[1] = d['dport'][1]
 
1020
 
 
1021
cdef int __fw_callback(fw_rule *rule, void *arg):
 
1022
    f, a = <object>arg
 
1023
    ret = f(rule_to_dict(rule), a)
 
1024
    if not ret:
 
1025
        ret = 0
 
1026
    return ret
 
1027
 
 
1028
cdef class fw:
 
1029
    """fw() -> Firewall ruleset object
 
1030
    
 
1031
    Open a handle to the local network firewall configuration.
 
1032
    """
 
1033
    cdef fw_t *fw
 
1034
    
 
1035
    def __init__(self):
 
1036
        self.fw = fw_open()
 
1037
        if not self.fw:
 
1038
            raise OSError, __oserror()
 
1039
 
 
1040
    def add(self, d):
 
1041
        """Add a firewall rule specified as a dict.
 
1042
 
 
1043
        Dict values:
 
1044
        device -- interface name                        (string)
 
1045
        op     -- operation (FW_OP_*)                   (integer)
 
1046
        dir    -- direction (FW_DIR_*)                  (integer)
 
1047
        proto  -- IP protocol (IP_PROTO_*)              (integer)
 
1048
        src    -- source address / net                  (addr object)
 
1049
        dst    -- destination address / net             (addr object)
 
1050
        sport  -- source port range or ICMP type/mask   (list of 2 integers)
 
1051
        dport  -- dest port range or ICMP code/mask     (list of 2 integers)
 
1052
        """
 
1053
        cdef fw_rule rule
 
1054
        memset(<char *>&rule, 0, sizeof(rule))
 
1055
        dict_to_rule(d, &rule)
 
1056
        if fw_add(self.fw, &rule) < 0:
 
1057
            raise OSError, __oserror()
 
1058
 
 
1059
    def delete(self, d):
 
1060
        """Delete a firewall rule specified as a dict."""
 
1061
        cdef fw_rule rule
 
1062
        memset(<char *>&rule, 0, sizeof(rule))
 
1063
        dict_to_rule(d, &rule)
 
1064
        if fw_delete(self.fw, &rule) < 0:
 
1065
            raise OSError, __oserror()
 
1066
 
 
1067
    def loop(self, callback, arg=None):
 
1068
        """Iterate over the local firewall ruleset, invoking a user callback
 
1069
        with each entry, returning the status of the callback routine.
 
1070
 
 
1071
        Keyword arguments:
 
1072
        callback -- callback function with (dict, arg) prototype.
 
1073
                    If this function returns a non-zero value, the loop
 
1074
                    will break early.
 
1075
        arg      -- optional callback argument
 
1076
        """
 
1077
        _arg = (callback, arg)
 
1078
        return fw_loop(self.fw, __fw_callback, <void *>_arg)
 
1079
 
 
1080
    def __del__(self):
 
1081
        fw_close(self.fw)
 
1082
 
 
1083
#
 
1084
# rand.h
 
1085
#
 
1086
cdef extern from *:
 
1087
    ctypedef struct rand_t:
 
1088
        int __xxx
 
1089
    
 
1090
    rand_t *rand_open()
 
1091
    int     rand_get(rand_t *rand, char *buf, int len)
 
1092
    int     rand_set(rand_t *rand, char *seed, int len)
 
1093
    int     rand_add(rand_t *rand, char *buf, int len)
 
1094
    unsigned int     rand_uint8(rand_t *rand)
 
1095
    unsigned int     rand_uint16(rand_t *rand)
 
1096
    unsigned long     rand_uint32(rand_t *rand)
 
1097
    rand_t *rand_close(rand_t *rand)
 
1098
 
 
1099
cdef class rand:
 
1100
    """rand() -> Pseudo-random number generator
 
1101
 
 
1102
    Obtain a handle for fast, cryptographically strong pseudo-random
 
1103
    number generation. The starting seed is derived from the system
 
1104
    random data source device (if one exists), or from the current time
 
1105
    and random stack contents.
 
1106
    """
 
1107
    cdef rand_t *rand
 
1108
 
 
1109
    def __init__(self):
 
1110
        self.rand = rand_open()
 
1111
        if not self.rand:
 
1112
            raise OSError, __oserror()
 
1113
 
 
1114
    def get(self, len):
 
1115
        """Return a string of random bytes.
 
1116
        
 
1117
        Arguments:
 
1118
        len -- number of random bytes to generate
 
1119
        """
 
1120
        buf = ' ' * len
 
1121
        rand_get(self.rand, buf, len)
 
1122
        return buf
 
1123
    
 
1124
    def set(self, buf):
 
1125
        """Initialize the PRNG from a known seed.
 
1126
        
 
1127
        Arguments:
 
1128
        string -- binary string seed value
 
1129
        """
 
1130
        rand_set(self.rand, buf, PyString_Size(buf))
 
1131
        
 
1132
    def add(self, buf):
 
1133
        """Add additional entropy into the PRNG mix.
 
1134
 
 
1135
        Arguments:
 
1136
        string -- binary string
 
1137
        """
 
1138
        rand_add(self.rand, buf, PyString_Size(buf))
 
1139
 
 
1140
    def uint8(self):
 
1141
        """Return a random 8-bit integer."""
 
1142
        return rand_uint8(self.rand)
 
1143
    
 
1144
    def uint16(self):
 
1145
        """Return a random 16-bit integer."""
 
1146
        return rand_uint16(self.rand)
 
1147
    
 
1148
    def uint32(self):
 
1149
        """Return a random 32-bit integer."""
 
1150
        return rand_uint32(self.rand)
 
1151