Initial import
[ldd.git] / ldd / filters.py
CommitLineData
769e7ed9 1# ldd - DNS implementation in Python
2# Copyright (C) 2006 Fredrik Tolf <fredrik@dolda2000.com>
3#
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 2 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program; if not, write to the Free Software
16# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
18import socket
19import time
20import fcntl
21import struct
22
23import server
24
25def linuxifip4hack(ifname):
26 req = ifname + ("\0" * (32 - len(ifname)))
27 sk = socket.socket()
28 res = fcntl.ioctl(sk.fileno(), 0x8915, req)
29 sk.close()
30 sockaddr = res[16:]
31 return sockaddr[4:8]
32
33class valuecache:
34 def __init__(self, func, expire):
35 self.func = func
36 self.expire = expire
37 self.last = 0
38
39 def __call__(self, *args):
40 now = int(time.time())
41 if self.last == 0 or now - self.last > self.expire:
42 self.val = self.func(*(args))
43 self.last = now
44 return self.val
45
46class prefix6to4(server.handler):
47 def __init__(self, next, v4addr):
48 self.next = next
49 if callable(v4addr):
50 self.packed = v4addr
51 elif len(v4addr) == 4:
52 self.packed = v4addr
53 else:
54 self.packed = socket.inet_pton(socket.AF_INET, v4addr)
55
56 def handle(self, *args):
57 resp = self.next.handle(*args)
58 if resp is None:
59 return None
60 for rr in resp.allrrs():
61 if rr.head.istype("AAAA"):
62 addr = rr.data["address"]
63 if addr[0:6] == "\x20\x02\x00\x00\x00\x00":
64 packed = self.packed
65 if callable(packed):
66 packed = packed()
67 addr = addr[0:2] + packed + addr[6:]
68 rr.data["address"] = addr
69 return resp
70
71class addrfilter(server.handler):
72 def __init__(self, default = None, matchers = []):
73 self.matchers = matchers
74 self.default = default
75
76 def setdefault(self, handler):
77 self.default = handler
78
79 def addmatcher(self, af, prefix, preflen, handler):
80 self.matchers += [(af, socket.inet_pton(af, prefix), preflen, handler)]
81
82 def handle(self, query, pkt, origin):
83 matchlen = -1
84 match = self.default
85 if pkt.addr is not None:
86 for af, prefix, preflen, handler in self.matchers:
87 if pkt.addr[0] == af:
88 addr = socket.inet_pton(af, pkt.addr[1])
89 bytes = preflen >> 3
90 restmask = 255 ^ ((1 << (8 - (preflen & 7))) - 1)
91 if prefix[0:bytes] == addr[0:bytes] and \
92 (ord(prefix[bytes]) & restmask) == (ord(addr[bytes]) & restmask):
93 if preflen > matchlen:
94 matchlen = preflen
95 match = handler
96 if match is not None:
97 return match.handle(query, pkt, origin)
98 return None