1
2
3
4 """Simple packet creation and parsing."""
5
6 import copy, itertools, struct
7
8 -class Error(Exception): pass
12
25
27 """Base packet class, with metaclass magic to generate members from
28 self.__hdr__.
29
30 __hdr__ should be defined as a list of (name, structfmt, default) tuples
31 __byte_order__ can be set to override the default ('>')
32
33 Example::
34
35 >>> class Foo(Packet):
36 ... __hdr__ = (('foo', 'I', 1), ('bar', 'H', 2), ('baz', '4s', 'quux'))
37 ...
38 >>> foo = Foo(bar=3)
39 >>> foo
40 Foo(bar=3)
41 >>> str(foo)
42 '\x00\x00\x00\x01\x00\x03quux'
43 >>> foo.bar
44 3
45 >>> foo.baz
46 'quux'
47 >>> foo.foo = 7
48 >>> foo.baz = 'whee'
49 >>> foo
50 Foo(baz='whee', foo=7, bar=3)
51 >>> Foo('hello, world!')
52 Foo(baz=' wor', foo=1751477356L, bar=28460, data='ld!')
53 """
54 __metaclass__ = _MetaPacket
55
57 """Packet constructor with ([buf], [field=val,...]) prototype.
58
59 Arguments:
60
61 buf -- optional packet buffer to unpack
62
63 Optional keyword arguments correspond to members to set
64 (matching fields in self.__hdr__, or 'data').
65 """
66 self.data = ''
67 if args:
68 try:
69 self.unpack(args[0])
70 except struct.error:
71 if len(args[0]) < self.__hdr_len__:
72 raise NeedData
73 raise UnpackError('invalid %s: %r' %
74 (self.__class__.__name__, args[0]))
75 else:
76 for k in self.__hdr_fields__:
77 setattr(self, k, copy.copy(self.__hdr_defaults__[k]))
78 for k, v in kwargs.iteritems():
79 setattr(self, k, v)
80
83
85 try: return getattr(self, k)
86 except AttributeError: raise KeyError
87
89 l = [ '%s=%r' % (k, getattr(self, k))
90 for k in self.__hdr_defaults__
91 if getattr(self, k) != self.__hdr_defaults__[k] ]
92 if self.data:
93 l.append('data=%r' % self.data)
94 return '%s(%s)' % (self.__class__.__name__, ', '.join(l))
95
97 return self.pack_hdr() + str(self.data)
98
100 """Return packed header string."""
101 try:
102 return struct.pack(self.__hdr_fmt__,
103 *[ getattr(self, k) for k in self.__hdr_fields__ ])
104 except struct.error:
105 vals = []
106 for k in self.__hdr_fields__:
107 v = getattr(self, k)
108 if isinstance(v, tuple):
109 vals.extend(v)
110 else:
111 vals.append(v)
112 try:
113 return struct.pack(self.__hdr_fmt__, *vals)
114 except struct.error, e:
115 raise PackError(str(e))
116
118 """Return packed header + self.data string."""
119 return str(self)
120
127
128
129 __vis_filter = """................................ !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[.]^_`abcdefghijklmnopqrstuvwxyz{|}~................................................................................................................................."""
130
132 """Return a hexdump output string of the given buffer."""
133 n = 0
134 res = []
135 while buf:
136 line, buf = buf[:length], buf[length:]
137 hexa = ' '.join(['%02x' % ord(x) for x in line])
138 line = line.translate(__vis_filter)
139 res.append(' %04d: %-*s %s' % (n, length * 3, hexa, line))
140 n += length
141 return '\n'.join(res)
142
143 try:
144 import dnet, socket
146 return dnet.ip_cksum_add(buf, s)
148 return socket.ntohs(dnet.ip_cksum_carry(s)) & 0xffff
149 except ImportError:
150 import array
152 nleft = len(buf)
153 a = array.array('B', buf)
154 i = 0
155 while nleft > 1:
156 s += a[i] * 256 + a[i+1]
157 i += 2
158 nleft -= 2
159 if nleft:
160 s += a[i] * 256
161 return s
163 while (s >> 16):
164 s = (s >> 16) + (s & 0xffff)
165 return (~s & 0xffff)
166
170