| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
import struct,copy,socket |
|---|
| 7 |
from config import conf |
|---|
| 8 |
from volatile import * |
|---|
| 9 |
from data import * |
|---|
| 10 |
from utils import * |
|---|
| 11 |
from base_classes import BasePacket,Gen,Net |
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
class Field: |
|---|
| 19 |
"""For more informations on how this work, please refer to |
|---|
| 20 |
http://www.secdev.org/projects/scapy/files/scapydoc.pdf |
|---|
| 21 |
chapter ``Adding a New Field''""" |
|---|
| 22 |
islist=0 |
|---|
| 23 |
holds_packets=0 |
|---|
| 24 |
def __init__(self, name, default, fmt="H"): |
|---|
| 25 |
self.name = name |
|---|
| 26 |
if fmt[0] in "@=<>!": |
|---|
| 27 |
self.fmt = fmt |
|---|
| 28 |
else: |
|---|
| 29 |
self.fmt = "!"+fmt |
|---|
| 30 |
self.default = self.any2i(None,default) |
|---|
| 31 |
self.sz = struct.calcsize(self.fmt) |
|---|
| 32 |
self.owners = [] |
|---|
| 33 |
|
|---|
| 34 |
def register_owner(self, cls): |
|---|
| 35 |
self.owners.append(cls) |
|---|
| 36 |
|
|---|
| 37 |
def i2len(self, pkt, x): |
|---|
| 38 |
"""Convert internal value to a length usable by a FieldLenField""" |
|---|
| 39 |
return self.sz |
|---|
| 40 |
def i2count(self, pkt, x): |
|---|
| 41 |
"""Convert internal value to a number of elements usable by a FieldLenField. |
|---|
| 42 |
Always 1 except for list fields""" |
|---|
| 43 |
return 1 |
|---|
| 44 |
def h2i(self, pkt, x): |
|---|
| 45 |
"""Convert human value to internal value""" |
|---|
| 46 |
return x |
|---|
| 47 |
def i2h(self, pkt, x): |
|---|
| 48 |
"""Convert internal value to human value""" |
|---|
| 49 |
return x |
|---|
| 50 |
def m2i(self, pkt, x): |
|---|
| 51 |
"""Convert machine value to internal value""" |
|---|
| 52 |
return x |
|---|
| 53 |
def i2m(self, pkt, x): |
|---|
| 54 |
"""Convert internal value to machine value""" |
|---|
| 55 |
if x is None: |
|---|
| 56 |
x = 0 |
|---|
| 57 |
return x |
|---|
| 58 |
def any2i(self, pkt, x): |
|---|
| 59 |
"""Try to understand the most input values possible and make an internal value from them""" |
|---|
| 60 |
return self.h2i(pkt, x) |
|---|
| 61 |
def i2repr(self, pkt, x): |
|---|
| 62 |
"""Convert internal value to a nice representation""" |
|---|
| 63 |
return repr(self.i2h(pkt,x)) |
|---|
| 64 |
def addfield(self, pkt, s, val): |
|---|
| 65 |
"""Add an internal value to a string""" |
|---|
| 66 |
return s+struct.pack(self.fmt, self.i2m(pkt,val)) |
|---|
| 67 |
def getfield(self, pkt, s): |
|---|
| 68 |
"""Extract an internal value from a string""" |
|---|
| 69 |
return s[self.sz:], self.m2i(pkt, struct.unpack(self.fmt, s[:self.sz])[0]) |
|---|
| 70 |
def do_copy(self, x): |
|---|
| 71 |
if hasattr(x, "copy"): |
|---|
| 72 |
return x.copy() |
|---|
| 73 |
if type(x) is list: |
|---|
| 74 |
x = x[:] |
|---|
| 75 |
for i in xrange(len(x)): |
|---|
| 76 |
if isinstance(x[i], BasePacket): |
|---|
| 77 |
x[i] = x[i].copy() |
|---|
| 78 |
return x |
|---|
| 79 |
def __repr__(self): |
|---|
| 80 |
return "<Field (%s).%s>" % (",".join(x.__name__ for x in self.owners),self.name) |
|---|
| 81 |
def copy(self): |
|---|
| 82 |
return copy.deepcopy(self) |
|---|
| 83 |
def randval(self): |
|---|
| 84 |
"""Return a volatile object whose value is both random and suitable for this field""" |
|---|
| 85 |
fmtt = self.fmt[-1] |
|---|
| 86 |
if fmtt in "BHIQ": |
|---|
| 87 |
return {"B":RandByte,"H":RandShort,"I":RandInt, "Q":RandLong}[fmtt]() |
|---|
| 88 |
elif fmtt == "s": |
|---|
| 89 |
if self.fmt[0] in "0123456789": |
|---|
| 90 |
l = int(self.fmt[:-1]) |
|---|
| 91 |
else: |
|---|
| 92 |
l = int(self.fmt[1:-1]) |
|---|
| 93 |
return RandBin(l) |
|---|
| 94 |
else: |
|---|
| 95 |
warning("no random class for [%s] (fmt=%s)." % (self.name, self.fmt)) |
|---|
| 96 |
|
|---|
| 97 |
|
|---|
| 98 |
|
|---|
| 99 |
|
|---|
| 100 |
class Emph: |
|---|
| 101 |
fld = "" |
|---|
| 102 |
def __init__(self, fld): |
|---|
| 103 |
self.fld = fld |
|---|
| 104 |
def __getattr__(self, attr): |
|---|
| 105 |
return getattr(self.fld,attr) |
|---|
| 106 |
def __hash__(self): |
|---|
| 107 |
return hash(self.fld) |
|---|
| 108 |
def __eq__(self, other): |
|---|
| 109 |
return self.fld == other |
|---|
| 110 |
|
|---|
| 111 |
|
|---|
| 112 |
class ActionField: |
|---|
| 113 |
_fld = None |
|---|
| 114 |
def __init__(self, fld, action_method, **kargs): |
|---|
| 115 |
self._fld = fld |
|---|
| 116 |
self._action_method = action_method |
|---|
| 117 |
self._privdata = kargs |
|---|
| 118 |
def any2i(self, pkt, val): |
|---|
| 119 |
getattr(pkt, self._action_method)(val, self._fld, **self._privdata) |
|---|
| 120 |
return getattr(self._fld, "any2i")(pkt, val) |
|---|
| 121 |
def __getattr__(self, attr): |
|---|
| 122 |
return getattr(self._fld,attr) |
|---|
| 123 |
|
|---|
| 124 |
|
|---|
| 125 |
class ConditionalField: |
|---|
| 126 |
fld = None |
|---|
| 127 |
def __init__(self, fld, cond): |
|---|
| 128 |
self.fld = fld |
|---|
| 129 |
self.cond = cond |
|---|
| 130 |
def _evalcond(self,pkt): |
|---|
| 131 |
return self.cond(pkt) |
|---|
| 132 |
|
|---|
| 133 |
def getfield(self, pkt, s): |
|---|
| 134 |
if self._evalcond(pkt): |
|---|
| 135 |
return self.fld.getfield(pkt,s) |
|---|
| 136 |
else: |
|---|
| 137 |
return s,None |
|---|
| 138 |
|
|---|
| 139 |
def addfield(self, pkt, s, val): |
|---|
| 140 |
if self._evalcond(pkt): |
|---|
| 141 |
return self.fld.addfield(pkt,s,val) |
|---|
| 142 |
else: |
|---|
| 143 |
return s |
|---|
| 144 |
def __getattr__(self, attr): |
|---|
| 145 |
return getattr(self.fld,attr) |
|---|
| 146 |
|
|---|
| 147 |
|
|---|
| 148 |
class PadField: |
|---|
| 149 |
"""Add bytes after the proxified field so that it ends at the specified |
|---|
| 150 |
alignment from its begining""" |
|---|
| 151 |
_fld = None |
|---|
| 152 |
def __init__(self, fld, align, padwith=None): |
|---|
| 153 |
self._fld = fld |
|---|
| 154 |
self._align = align |
|---|
| 155 |
self._padwith = padwith or "" |
|---|
| 156 |
|
|---|
| 157 |
def addfield(self, pkt, s, val): |
|---|
| 158 |
sval = self._fld.addfield(pkt, "", val) |
|---|
| 159 |
return s+sval+struct.pack("%is" % (-len(sval)%self._align), self._padwith) |
|---|
| 160 |
|
|---|
| 161 |
def __getattr__(self, attr): |
|---|
| 162 |
return getattr(self._fld,attr) |
|---|
| 163 |
|
|---|
| 164 |
|
|---|
| 165 |
class MACField(Field): |
|---|
| 166 |
def __init__(self, name, default): |
|---|
| 167 |
Field.__init__(self, name, default, "6s") |
|---|
| 168 |
def i2m(self, pkt, x): |
|---|
| 169 |
if x is None: |
|---|
| 170 |
return "\0\0\0\0\0\0" |
|---|
| 171 |
return mac2str(x) |
|---|
| 172 |
def m2i(self, pkt, x): |
|---|
| 173 |
return str2mac(x) |
|---|
| 174 |
def any2i(self, pkt, x): |
|---|
| 175 |
if type(x) is str and len(x) is 6: |
|---|
| 176 |
x = self.m2i(pkt, x) |
|---|
| 177 |
return x |
|---|
| 178 |
def i2repr(self, pkt, x): |
|---|
| 179 |
x = self.i2h(pkt, x) |
|---|
| 180 |
if self in conf.resolve: |
|---|
| 181 |
x = conf.manufdb._resolve_MAC(x) |
|---|
| 182 |
return x |
|---|
| 183 |
def randval(self): |
|---|
| 184 |
return RandMAC() |
|---|
| 185 |
|
|---|
| 186 |
|
|---|
| 187 |
class IPField(Field): |
|---|
| 188 |
def __init__(self, name, default): |
|---|
| 189 |
Field.__init__(self, name, default, "4s") |
|---|
| 190 |
def h2i(self, pkt, x): |
|---|
| 191 |
if type(x) is str: |
|---|
| 192 |
try: |
|---|
| 193 |
inet_aton(x) |
|---|
| 194 |
except socket.error: |
|---|
| 195 |
x = Net(x) |
|---|
| 196 |
elif type(x) is list: |
|---|
| 197 |
x = [self.h2i(pkt, n) for n in x] |
|---|
| 198 |
return x |
|---|
| 199 |
def resolve(self, x): |
|---|
| 200 |
if self in conf.resolve: |
|---|
| 201 |
try: |
|---|
| 202 |
ret = socket.gethostbyaddr(x)[0] |
|---|
| 203 |
except: |
|---|
| 204 |
pass |
|---|
| 205 |
else: |
|---|
| 206 |
if ret: |
|---|
| 207 |
return ret |
|---|
| 208 |
return x |
|---|
| 209 |
def i2m(self, pkt, x): |
|---|
| 210 |
return inet_aton(x) |
|---|
| 211 |
def m2i(self, pkt, x): |
|---|
| 212 |
return inet_ntoa(x) |
|---|
| 213 |
def any2i(self, pkt, x): |
|---|
| 214 |
return self.h2i(pkt,x) |
|---|
| 215 |
def i2repr(self, pkt, x): |
|---|
| 216 |
return self.resolve(self.i2h(pkt, x)) |
|---|
| 217 |
def randval(self): |
|---|
| 218 |
return RandIP() |
|---|
| 219 |
|
|---|
| 220 |
class SourceIPField(IPField): |
|---|
| 221 |
def __init__(self, name, dstname): |
|---|
| 222 |
IPField.__init__(self, name, None) |
|---|
| 223 |
self.dstname = dstname |
|---|
| 224 |
def i2m(self, pkt, x): |
|---|
| 225 |
if x is None: |
|---|
| 226 |
iff,x,gw = pkt.route() |
|---|
| 227 |
if x is None: |
|---|
| 228 |
x = "0.0.0.0" |
|---|
| 229 |
return IPField.i2m(self, pkt, x) |
|---|
| 230 |
def i2h(self, pkt, x): |
|---|
| 231 |
if x is None: |
|---|
| 232 |
dst=getattr(pkt,self.dstname) |
|---|
| 233 |
if isinstance(dst,Gen): |
|---|
| 234 |
r = map(conf.route.route, dst) |
|---|
| 235 |
r.sort() |
|---|
| 236 |
if r[0] != r[-1]: |
|---|
| 237 |
warning("More than one possible route for %s"%repr(dst)) |
|---|
| 238 |
iff,x,gw = r[0] |
|---|
| 239 |
else: |
|---|
| 240 |
iff,x,gw = conf.route.route(dst) |
|---|
| 241 |
return IPField.i2h(self, pkt, x) |
|---|
| 242 |
|
|---|
| 243 |
|
|---|
| 244 |
|
|---|
| 245 |
|
|---|
| 246 |
class ByteField(Field): |
|---|
| 247 |
def __init__(self, name, default): |
|---|
| 248 |
Field.__init__(self, name, default, "B") |
|---|
| 249 |
|
|---|
| 250 |
class XByteField(ByteField): |
|---|
| 251 |
def i2repr(self, pkt, x): |
|---|
| 252 |
if x is None: |
|---|
| 253 |
x = 0 |
|---|
| 254 |
return lhex(self.i2h(pkt, x)) |
|---|
| 255 |
|
|---|
| 256 |
class X3BytesField(XByteField): |
|---|
| 257 |
def __init__(self, name, default): |
|---|
| 258 |
Field.__init__(self, name, default, "!I") |
|---|
| 259 |
def addfield(self, pkt, s, val): |
|---|
| 260 |
return s+struct.pack(self.fmt, self.i2m(pkt,val))[1:4] |
|---|
| 261 |
def getfield(self, pkt, s): |
|---|
| 262 |
return s[3:], self.m2i(pkt, struct.unpack(self.fmt, "\x00"+s[:3])[0]) |
|---|
| 263 |
|
|---|
| 264 |
|
|---|
| 265 |
class ShortField(Field): |
|---|
| 266 |
def __init__(self, name, default): |
|---|
| 267 |
Field.__init__(self, name, default, "H") |
|---|
| 268 |
|
|---|
| 269 |
class LEShortField(Field): |
|---|
| 270 |
def __init__(self, name, default): |
|---|
| 271 |
Field.__init__(self, name, default, "<H") |
|---|
| 272 |
|
|---|
| 273 |
class XShortField(ShortField): |
|---|
| 274 |
def i2repr(self, pkt, x): |
|---|
| 275 |
if x is None: |
|---|
| 276 |
x = 0 |
|---|
| 277 |
return lhex(self.i2h(pkt, x)) |
|---|
| 278 |
|
|---|
| 279 |
|
|---|
| 280 |
class IntField(Field): |
|---|
| 281 |
def __init__(self, name, default): |
|---|
| 282 |
Field.__init__(self, name, default, "I") |
|---|
| 283 |
|
|---|
| 284 |
class SignedIntField(Field): |
|---|
| 285 |
def __init__(self, name, default): |
|---|
| 286 |
Field.__init__(self, name, default, "i") |
|---|
| 287 |
def randval(self): |
|---|
| 288 |
return RandSInt() |
|---|
| 289 |
|
|---|
| 290 |
class LEIntField(Field): |
|---|
| 291 |
def __init__(self, name, default): |
|---|
| 292 |
Field.__init__(self, name, default, "<I") |
|---|
| 293 |
|
|---|
| 294 |
class LESignedIntField(Field): |
|---|
| 295 |
def __init__(self, name, default): |
|---|
| 296 |
Field.__init__(self, name, default, "<i") |
|---|
| 297 |
def randval(self): |
|---|
| 298 |
return RandSInt() |
|---|
| 299 |
|
|---|
| 300 |
class XIntField(IntField): |
|---|
| 301 |
def i2repr(self, pkt, x): |
|---|
| 302 |
if x is None: |
|---|
| 303 |
x = 0 |
|---|
| 304 |
return lhex(self.i2h(pkt, x)) |
|---|
| 305 |
|
|---|
| 306 |
|
|---|
| 307 |
class LongField(Field): |
|---|
| 308 |
def __init__(self, name, default): |
|---|
| 309 |
Field.__init__(self, name, default, "Q") |
|---|
| 310 |
|
|---|
| 311 |
class XLongField(LongField): |
|---|
| 312 |
def i2repr(self, pkt, x): |
|---|
| 313 |
if x is None: |
|---|
| 314 |
x = 0 |
|---|
| 315 |
return lhex(self.i2h(pkt, x)) |
|---|
| 316 |
|
|---|
| 317 |
class IEEEFloatField(Field): |
|---|
| 318 |
def __init__(self, name, default): |
|---|
| 319 |
Field.__init__(self, name, default, "f") |
|---|
| 320 |
|
|---|
| 321 |
class IEEEDoubleField(Field): |
|---|
| 322 |
def __init__(self, name, default): |
|---|
| 323 |
Field.__init__(self, name, default, "d") |
|---|
| 324 |
|
|---|
| 325 |
|
|---|
| 326 |
class StrField(Field): |
|---|
| 327 |
def __init__(self, name, default, fmt="H", remain=0): |
|---|
| 328 |
Field.__init__(self,name,default,fmt) |
|---|
| 329 |
self.remain = remain |
|---|
| 330 |
def i2len(self, pkt, i): |
|---|
| 331 |
return len(i) |
|---|
| 332 |
def i2m(self, pkt, x): |
|---|
| 333 |
if x is None: |
|---|
| 334 |
x = "" |
|---|
| 335 |
elif type(x) is not str: |
|---|
| 336 |
x=str(x) |
|---|
| 337 |
return x |
|---|
| 338 |
def addfield(self, pkt, s, val): |
|---|
| 339 |
return s+self.i2m(pkt, val) |
|---|
| 340 |
def getfield(self, pkt, s): |
|---|
| 341 |
if self.remain == 0: |
|---|
| 342 |
return "",self.m2i(pkt, s) |
|---|
| 343 |
else: |
|---|
| 344 |
return s[-self.remain:],self.m2i(pkt, s[:-self.remain]) |
|---|
| 345 |
def randval(self): |
|---|
| 346 |
return RandBin(RandNum(0,1200)) |
|---|
| 347 |
|
|---|
| 348 |
class PacketField(StrField): |
|---|
| 349 |
holds_packets=1 |
|---|
| 350 |
def __init__(self, name, default, cls, remain=0): |
|---|
| 351 |
StrField.__init__(self, name, default, remain=remain) |
|---|
| 352 |
self.cls = cls |
|---|
| 353 |
def i2m(self, pkt, i): |
|---|
| 354 |
return str(i) |
|---|
| 355 |
def m2i(self, pkt, m): |
|---|
| 356 |
return self.cls(m) |
|---|
| 357 |
def getfield(self, pkt, s): |
|---|
| 358 |
i = self.m2i(pkt, s) |
|---|
| 359 |
remain = "" |
|---|
| 360 |
if 'Padding' in i: |
|---|
| 361 |
r = i['Padding'] |
|---|
| 362 |
del(r.underlayer.payload) |
|---|
| 363 |
remain = r.load |
|---|
| 364 |
return remain,i |
|---|
| 365 |
|
|---|
| 366 |
class PacketLenField(PacketField): |
|---|
| 367 |
holds_packets=1 |
|---|
| 368 |
def __init__(self, name, default, cls, length_from=None): |
|---|
| 369 |
PacketField.__init__(self, name, default, cls) |
|---|
| 370 |
self.length_from = length_from |
|---|
| 371 |
def getfield(self, pkt, s): |
|---|
| 372 |
l = self.length_from(pkt) |
|---|
| 373 |
i = self.m2i(pkt, s[:l]) |
|---|
| 374 |
return s[l:],i |
|---|
| 375 |
|
|---|
| 376 |
|
|---|
| 377 |
class PacketListField(PacketField): |
|---|
| 378 |
islist = 1 |
|---|
| 379 |
holds_packets=1 |
|---|
| 380 |
def __init__(self, name, default, cls, count_from=None, length_from=None): |
|---|
| 381 |
if default is None: |
|---|
| 382 |
default = [] |
|---|
| 383 |
PacketField.__init__(self, name, default, cls) |
|---|
| 384 |
self.count_from = count_from |
|---|
| 385 |
self.length_from = length_from |
|---|
| 386 |
|
|---|
| 387 |
|
|---|
| 388 |
def any2i(self, pkt, x): |
|---|
| 389 |
if type(x) is not list: |
|---|
| 390 |
return [x] |
|---|
| 391 |
else: |
|---|
| 392 |
return x |
|---|
| 393 |
def i2count(self, pkt, val): |
|---|
| 394 |
if type(val) is list: |
|---|
| 395 |
return len(val) |
|---|
| 396 |
return 1 |
|---|
| 397 |
def i2len(self, pkt, val): |
|---|
| 398 |
return sum( len(p) for p in val ) |
|---|
| 399 |
def do_copy(self, x): |
|---|
| 400 |
return map(lambda p:p.copy(), x) |
|---|
| 401 |
def getfield(self, pkt, s): |
|---|
| 402 |
c = l = None |
|---|
| 403 |
if self.length_from is not None: |
|---|
| 404 |
l = self.length_from(pkt) |
|---|
| 405 |
elif self.count_from is not None: |
|---|
| 406 |
c = self.count_from(pkt) |
|---|
| 407 |
|
|---|
| 408 |
lst = [] |
|---|
| 409 |
ret = "" |
|---|
| 410 |
remain = s |
|---|
| 411 |
if l is not None: |
|---|
| 412 |
remain,ret = s[:l],s[l:] |
|---|
| 413 |
while remain: |
|---|
| 414 |
if c is not None: |
|---|
| 415 |
if c <= 0: |
|---|
| 416 |
break |
|---|
| 417 |
c -= 1 |
|---|
| 418 |
p = self.m2i(pkt,remain) |
|---|
| 419 |
if 'Padding' in p: |
|---|
| 420 |
pad = p['Padding'] |
|---|
| 421 |
remain = pad.load |
|---|
| 422 |
del(pad.underlayer.payload) |
|---|
| 423 |
else: |
|---|
| 424 |
remain = "" |
|---|
| 425 |
lst.append(p) |
|---|
| 426 |
return remain+ret,lst |
|---|
| 427 |
def addfield(self, pkt, s, val): |
|---|
| 428 |
return s+"".join(map(str, val)) |
|---|
| 429 |
|
|---|
| 430 |
|
|---|
| 431 |
class StrFixedLenField(StrField): |
|---|
| 432 |
def __init__(self, name, default, length=None, length_from=None): |
|---|
| 433 |
StrField.__init__(self, name, default) |
|---|
| 434 |
self.length_from = length_from |
|---|
| 435 |
if length is not None: |
|---|
| 436 |
self.length_from = lambda pkt,length=length: length |
|---|
| 437 |
def i2repr(self, pkt, v): |
|---|
| 438 |
if type(v) is str: |
|---|
| 439 |
v = v.rstrip("\0") |
|---|
| 440 |
return repr(v) |
|---|
| 441 |
def getfield(self, pkt, s): |
|---|
| 442 |
l = self.length_from(pkt) |
|---|
| 443 |
return s[l:], self.m2i(pkt,s[:l]) |
|---|
| 444 |
def addfield(self, pkt, s, val): |
|---|
| 445 |
l = self.length_from(pkt) |
|---|
| 446 |
return s+struct.pack("%is"%l,self.i2m(pkt, val)) |
|---|
| 447 |
def randval(self): |
|---|
| 448 |
try: |
|---|
| 449 |
l = self.length_from(None) |
|---|
| 450 |
except: |
|---|
| 451 |
l = RandNum(0,200) |
|---|
| 452 |
return RandBin(l) |
|---|
| 453 |
|
|---|
| 454 |
class NetBIOSNameField(StrFixedLenField): |
|---|
| 455 |
def __init__(self, name, default, length=31): |
|---|
| 456 |
StrFixedLenField.__init__(self, name, default, length) |
|---|
| 457 |
def i2m(self, pkt, x): |
|---|
| 458 |
l = self.length_from(pkt)/2 |
|---|
| 459 |
if x is None: |
|---|
| 460 |
x = "" |
|---|
| 461 |
x += " "*(l) |
|---|
| 462 |
x = x[:l] |
|---|
| 463 |
x = "".join(map(lambda x: chr(0x41+(ord(x)>>4))+chr(0x41+(ord(x)&0xf)), x)) |
|---|
| 464 |
x = " "+x |
|---|
| 465 |
return x |
|---|
| 466 |
def m2i(self, pkt, x): |
|---|
| 467 |
x = x.strip("\x00").strip(" ") |
|---|
| 468 |
return "".join(map(lambda x,y: chr((((ord(x)-1)&0xf)<<4)+((ord(y)-1)&0xf)), x[::2],x[1::2])) |
|---|
| 469 |
|
|---|
| 470 |
class StrLenField(StrField): |
|---|
| 471 |
def __init__(self, name, default, fld=None, length_from=None): |
|---|
| 472 |
StrField.__init__(self, name, default) |
|---|
| 473 |
self.length_from = length_from |
|---|
| 474 |
def getfield(self, pkt, s): |
|---|
| 475 |
l = self.length_from(pkt) |
|---|
| 476 |
return s[l:], self.m2i(pkt,s[:l]) |
|---|
| 477 |
|
|---|
| 478 |
class FieldListField(Field): |
|---|
| 479 |
islist=1 |
|---|
| 480 |
def __init__(self, name, default, field, length_from=None, count_from=None): |
|---|
| 481 |
if default is None: |
|---|
| 482 |
default = [] |
|---|
| 483 |
Field.__init__(self, name, default) |
|---|
| 484 |
self.count_from = count_from |
|---|
| 485 |
self.length_from = length_from |
|---|
| 486 |
self.field = field |
|---|
| 487 |
|
|---|
| 488 |
def i2count(self, pkt, val): |
|---|
| 489 |
if type(val) is list: |
|---|
| 490 |
return len(val) |
|---|
| 491 |
return 1 |
|---|
| 492 |
def i2len(self, pkt, val): |
|---|
| 493 |
return sum( self.field.i2len(pkt,v) for v in val ) |
|---|
| 494 |
|
|---|
| 495 |
def i2m(self, pkt, val): |
|---|
| 496 |
if val is None: |
|---|
| 497 |
val = [] |
|---|
| 498 |
return val |
|---|
| 499 |
def any2i(self, pkt, x): |
|---|
| 500 |
if type(x) is not list: |
|---|
| 501 |
return [x] |
|---|
| 502 |
else: |
|---|
| 503 |
return x |
|---|
| 504 |
def addfield(self, pkt, s, val): |
|---|
| 505 |
val = self.i2m(pkt, val) |
|---|
| 506 |
for v in val: |
|---|
| 507 |
s = self.field.addfield(pkt, s, v) |
|---|
| 508 |
return s |
|---|
| 509 |
def getfield(self, pkt, s): |
|---|
| 510 |
c = l = None |
|---|
| 511 |
if self.length_from is not None: |
|---|
| 512 |
l = self.length_from(pkt) |
|---|
| 513 |
elif self.count_from is not None: |
|---|
| 514 |
c = self.count_from(pkt) |
|---|
| 515 |
|
|---|
| 516 |
val = [] |
|---|
| 517 |
ret="" |
|---|
| 518 |
if l is not None: |
|---|
| 519 |
s,ret = s[:l],s[l:] |
|---|
| 520 |
|
|---|
| 521 |
while s: |
|---|
| 522 |
if c is not None: |
|---|
| 523 |
if c <= 0: |
|---|
| 524 |
break |
|---|
| 525 |
c -= 1 |
|---|
| 526 |
s,v = self.field.getfield(pkt, s) |
|---|
| 527 |
val.append(v) |
|---|
| 528 |
return s+ret, val |
|---|
| 529 |
|
|---|
| 530 |
class FieldLenField(Field): |
|---|
| 531 |
def __init__(self, name, default, length_of=None, fmt = "H", count_of=None, adjust=lambda pkt,x:x, fld=None): |
|---|
| 532 |
Field.__init__(self, name, default, fmt) |
|---|
| 533 |
self.length_of=length_of |
|---|
| 534 |
self.count_of=count_of |
|---|
| 535 |
self.adjust=adjust |
|---|
| 536 |
if fld is not None: |
|---|
| 537 |
FIELD_LENGTH_MANAGEMENT_DEPRECATION(self.__class__.__name__) |
|---|
| 538 |
self.length_of = fld |
|---|
| 539 |
def i2m(self, pkt, x): |
|---|
| 540 |
if x is None: |
|---|
| 541 |
if self.length_of is not None: |
|---|
| 542 |
fld,fval = pkt.getfield_and_val(self.length_of) |
|---|
| 543 |
f = fld.i2len(pkt, fval) |
|---|
| 544 |
else: |
|---|
| 545 |
fld,fval = pkt.getfield_and_val(self.count_of) |
|---|
| 546 |
f = fld.i2count(pkt, fval) |
|---|
| 547 |
x = self.adjust(pkt,f) |
|---|
| 548 |
return x |
|---|
| 549 |
|
|---|
| 550 |
class StrNullField(StrField): |
|---|
| 551 |
def addfield(self, pkt, s, val): |
|---|
| 552 |
return s+self.i2m(pkt, val)+"\x00" |
|---|
| 553 |
def getfield(self, pkt, s): |
|---|
| 554 |
l = s.find("\x00") |
|---|
| 555 |
if l < 0: |
|---|
| 556 |
|
|---|
| 557 |
return "",s |
|---|
| 558 |
return s[l+1:],self.m2i(pkt, s[:l]) |
|---|
| 559 |
def randval(self): |
|---|
| 560 |
return RandTermString(RandNum(0,1200),"\x00") |
|---|
| 561 |
|
|---|
| 562 |
class StrStopField(StrField): |
|---|
| 563 |
def __init__(self, name, default, stop, additionnal=0): |
|---|
| 564 |
Field.__init__(self, name, default) |
|---|
| 565 |
self.stop=stop |
|---|
| 566 |
self.additionnal=additionnal |
|---|
| 567 |
def getfield(self, pkt, s): |
|---|
| 568 |
l = s.find(self.stop) |
|---|
| 569 |
if l < 0: |
|---|
| 570 |
return "",s |
|---|
| 571 |
|
|---|
| 572 |
l += len(self.stop)+self.additionnal |
|---|
| 573 |
return s[l:],s[:l] |
|---|
| 574 |
def randval(self): |
|---|
| 575 |
return RandTermString(RandNum(0,1200),self.stop) |
|---|
| 576 |
|
|---|
| 577 |
class LenField(Field): |
|---|
| 578 |
def i2m(self, pkt, x): |
|---|
| 579 |
if x is None: |
|---|
| 580 |
x = len(pkt.payload) |
|---|
| 581 |
return x |
|---|
| 582 |
|
|---|
| 583 |
class BCDFloatField(Field): |
|---|
| 584 |
def i2m(self, pkt, x): |
|---|
| 585 |
return int(256*x) |
|---|
| 586 |
def m2i(self, pkt, x): |
|---|
| 587 |
return x/256.0 |
|---|
| 588 |
|
|---|
| 589 |
class BitField(Field): |
|---|
| 590 |
def __init__(self, name, default, size): |
|---|
| 591 |
Field.__init__(self, name, default) |
|---|
| 592 |
self.rev = size < 0 |
|---|
| 593 |
self.size = abs(size) |
|---|
| 594 |
def reverse(self, val): |
|---|
| 595 |
if self.size == 16: |
|---|
| 596 |
val = socket.ntohs(val) |
|---|
| 597 |
elif self.size == 32: |
|---|
| 598 |
val = socket.ntohl(val) |
|---|
| 599 |
return val |
|---|
| 600 |
|
|---|
| 601 |
def addfield(self, pkt, s, val): |
|---|
| 602 |
val = self.i2m(pkt, val) |
|---|
| 603 |
if type(s) is tuple: |
|---|
| 604 |
s,bitsdone,v = s |
|---|
| 605 |
else: |
|---|
| 606 |
bitsdone = 0 |
|---|
| 607 |
v = 0 |
|---|
| 608 |
if self.rev: |
|---|
| 609 |
val = self.reverse(val) |
|---|
| 610 |
v <<= self.size |
|---|
| 611 |
v |= val & ((1L<<self.size) - 1) |
|---|
| 612 |
bitsdone += self.size |
|---|
| 613 |
while bitsdone >= 8: |
|---|
| 614 |
bitsdone -= 8 |
|---|
| 615 |
s = s+struct.pack("!B", v >> bitsdone) |
|---|
| 616 |
v &= (1L<<bitsdone)-1 |
|---|
| 617 |
if bitsdone: |
|---|
| 618 |
return s,bitsdone,v |
|---|
| 619 |
else: |
|---|
| 620 |
return s |
|---|
| 621 |
def getfield(self, pkt, s): |
|---|
| 622 |
if type(s) is tuple: |
|---|
| 623 |
s,bn = s |
|---|
| 624 |
else: |
|---|
| 625 |
bn = 0 |
|---|
| 626 |
|
|---|
| 627 |
nb_bytes = (self.size+bn-1)/8 + 1 |
|---|
| 628 |
w = s[:nb_bytes] |
|---|
| 629 |
|
|---|
| 630 |
|
|---|
| 631 |
bytes = struct.unpack('!%dB' % nb_bytes , w) |
|---|
| 632 |
|
|---|
| 633 |
b = 0L |
|---|
| 634 |
for c in range(nb_bytes): |
|---|
| 635 |
b |= long(bytes[c]) << (nb_bytes-c-1)*8 |
|---|
| 636 |
|
|---|
| 637 |
|
|---|
| 638 |
b &= (1L << (nb_bytes*8-bn)) - 1 |
|---|
| 639 |
|
|---|
| 640 |
|
|---|
| 641 |
b = b >> (nb_bytes*8 - self.size - bn) |
|---|
| 642 |
|
|---|
| 643 |
if self.rev: |
|---|
| 644 |
b = self.reverse(b) |
|---|
| 645 |
|
|---|
| 646 |
bn += self.size |
|---|
| 647 |
s = s[bn/8:] |
|---|
| 648 |
bn = bn%8 |
|---|
| 649 |
b = self.m2i(pkt, b) |
|---|
| 650 |
if bn: |
|---|
| 651 |
return (s,bn),b |
|---|
| 652 |
else: |
|---|
| 653 |
return s,b |
|---|
| 654 |
def randval(self): |
|---|
| 655 |
return RandNum(0,2**self.size-1) |
|---|
| 656 |
|
|---|
| 657 |
|
|---|
| 658 |
class BitFieldLenField(BitField): |
|---|
| 659 |
def __init__(self, name, default, size, length_of=None, count_of=None, adjust=lambda pkt,x:x): |
|---|
| 660 |
BitField.__init__(self, name, default, size) |
|---|
| 661 |
self.length_of=length_of |
|---|
| 662 |
self.count_of=count_of |
|---|
| 663 |
self.adjust=adjust |
|---|
| 664 |
def i2m(self, pkt, x): |
|---|
| 665 |
return FieldLenField.i2m.im_func(self, pkt, x) |
|---|
| 666 |
|
|---|
| 667 |
|
|---|
| 668 |
class XBitField(BitField): |
|---|
| 669 |
def i2repr(self, pkt, x): |
|---|
| 670 |
return lhex(self.i2h(pkt,x)) |
|---|
| 671 |
|
|---|
| 672 |
|
|---|
| 673 |
class EnumField(Field): |
|---|
| 674 |
def __init__(self, name, default, enum, fmt = "H"): |
|---|
| 675 |
i2s = self.i2s = {} |
|---|
| 676 |
s2i = self.s2i = {} |
|---|
| 677 |
if type(enum) is list: |
|---|
| 678 |
keys = xrange(len(enum)) |
|---|
| 679 |
else: |
|---|
| 680 |
keys = enum.keys() |
|---|
| 681 |
if filter(lambda x: type(x) is str, keys): |
|---|
| 682 |
i2s,s2i = s2i,i2s |
|---|
| 683 |
for k in keys: |
|---|
| 684 |
i2s[k] = enum[k] |
|---|
| 685 |
s2i[enum[k]] = k |
|---|
| 686 |
Field.__init__(self, name, default, fmt) |
|---|
| 687 |
def any2i_one(self, pkt, x): |
|---|
| 688 |
if type(x) is str: |
|---|
| 689 |
x = self.s2i[x] |
|---|
| 690 |
return x |
|---|
| 691 |
def i2repr_one(self, pkt, x): |
|---|
| 692 |
if self not in conf.noenum and not isinstance(x,VolatileValue) and x in self.i2s: |
|---|
| 693 |
return self.i2s[x] |
|---|
| 694 |
return repr(x) |
|---|
| 695 |
|
|---|
| 696 |
def any2i(self, pkt, x): |
|---|
| 697 |
if type(x) is list: |
|---|
| 698 |
return map(lambda z,pkt=pkt:self.any2i_one(pkt,z), x) |
|---|
| 699 |
else: |
|---|
| 700 |
return self.any2i_one(pkt,x) |
|---|
| 701 |
def i2repr(self, pkt, x): |
|---|
| 702 |
if type(x) is list: |
|---|
| 703 |
return map(lambda z,pkt=pkt:self.i2repr_one(pkt,z), x) |
|---|
| 704 |
else: |
|---|
| 705 |
return self.i2repr_one(pkt,x) |
|---|
| 706 |
|
|---|
| 707 |
class CharEnumField(EnumField): |
|---|
| 708 |
def __init__(self, name, default, enum, fmt = "1s"): |
|---|
| 709 |
EnumField.__init__(self, name, default, enum, fmt) |
|---|
| 710 |
k = self.i2s.keys() |
|---|
| 711 |
if k and len(k[0]) != 1: |
|---|
| 712 |
self.i2s,self.s2i = self.s2i,self.i2s |
|---|
| 713 |
def any2i_one(self, pkt, x): |
|---|
| 714 |
if len(x) != 1: |
|---|
| 715 |
x = self.s2i[x] |
|---|
| 716 |
return x |
|---|
| 717 |
|
|---|
| 718 |
class BitEnumField(BitField,EnumField): |
|---|
| 719 |
def __init__(self, name, default, size, enum): |
|---|
| 720 |
EnumField.__init__(self, name, default, enum) |
|---|
| 721 |
self.rev = size < 0 |
|---|
| 722 |
self.size = abs(size) |
|---|
| 723 |
def any2i(self, pkt, x): |
|---|
| 724 |
return EnumField.any2i(self, pkt, x) |
|---|
| 725 |
def i2repr(self, pkt, x): |
|---|
| 726 |
return EnumField.i2repr(self, pkt, x) |
|---|
| 727 |
|
|---|
| 728 |
class ShortEnumField(EnumField): |
|---|
| 729 |
def __init__(self, name, default, enum): |
|---|
| 730 |
EnumField.__init__(self, name, default, enum, "H") |
|---|
| 731 |
|
|---|
| 732 |
class LEShortEnumField(EnumField): |
|---|
| 733 |
def __init__(self, name, default, enum): |
|---|
| 734 |
EnumField.__init__(self, name, default, enum, "<H") |
|---|
| 735 |
|
|---|
| 736 |
class ByteEnumField(EnumField): |
|---|
| 737 |
def __init__(self, name, default, enum): |
|---|
| 738 |
EnumField.__init__(self, name, default, enum, "B") |
|---|
| 739 |
|
|---|
| 740 |
class IntEnumField(EnumField): |
|---|
| 741 |
def __init__(self, name, default, enum): |
|---|
| 742 |
EnumField.__init__(self, name, default, enum, "I") |
|---|
| 743 |
|
|---|
| 744 |
class SignedIntEnumField(EnumField): |
|---|
| 745 |
def __init__(self, name, default, enum): |
|---|
| 746 |
EnumField.__init__(self, name, default, enum, "i") |
|---|
| 747 |
def randval(self): |
|---|
| 748 |
return RandSInt() |
|---|
| 749 |
|
|---|
| 750 |
class LEIntEnumField(EnumField): |
|---|
| 751 |
def __init__(self, name, default, enum): |
|---|
| 752 |
EnumField.__init__(self, name, default, enum, "<I") |
|---|
| 753 |
|
|---|
| 754 |
class XShortEnumField(ShortEnumField): |
|---|
| 755 |
def i2repr_one(self, pkt, x): |
|---|
| 756 |
if self not in conf.noenum and not isinstance(x,VolatileValue) and x in self.i2s: |
|---|
| 757 |
return self.i2s[x] |
|---|
| 758 |
return lhex(x) |
|---|
| 759 |
|
|---|
| 760 |
|
|---|
| 761 |
class LELongField(Field): |
|---|
| 762 |
def __init__(self, name, default): |
|---|
| 763 |
Field.__init__(self, name, default, "<Q") |
|---|
| 764 |
|
|---|
| 765 |
|
|---|
| 766 |
class LEFieldLenField(FieldLenField): |
|---|
| 767 |
def __init__(self, name, default, length_of=None, fmt = "<H", count_of=None, adjust=lambda pkt,x:x, fld=None): |
|---|
| 768 |
FieldLenField.__init__(self, name, default, length_of=length_of, fmt=fmt, fld=fld, adjust=adjust) |
|---|
| 769 |
|
|---|
| 770 |
|
|---|
| 771 |
class FlagsField(BitField): |
|---|
| 772 |
def __init__(self, name, default, size, names): |
|---|
| 773 |
BitField.__init__(self, name, default, size) |
|---|
| 774 |
self.multi = type(names) is list |
|---|
| 775 |
if self.multi: |
|---|
| 776 |
self.names = map(lambda x:[x], names) |
|---|
| 777 |
else: |
|---|
| 778 |
self.names = names |
|---|
| 779 |
def any2i(self, pkt, x): |
|---|
| 780 |
if type(x) is str: |
|---|
| 781 |
if self.multi: |
|---|
| 782 |
x = map(lambda y:[y], x.split("+")) |
|---|
| 783 |
y = 0 |
|---|
| 784 |
for i in x: |
|---|
| 785 |
y |= 1 << self.names.index(i) |
|---|
| 786 |
x = y |
|---|
| 787 |
return x |
|---|
| 788 |
def i2repr(self, pkt, x): |
|---|
| 789 |
if type(x) is list or type(x) is tuple: |
|---|
| 790 |
return repr(x) |
|---|
| 791 |
if self.multi: |
|---|
| 792 |
r = [] |
|---|
| 793 |
else: |
|---|
| 794 |
r = "" |
|---|
| 795 |
i=0 |
|---|
| 796 |
while x: |
|---|
| 797 |
if x & 1: |
|---|
| 798 |
r += self.names[i] |
|---|
| 799 |
i += 1 |
|---|
| 800 |
x >>= 1 |
|---|
| 801 |
if self.multi: |
|---|
| 802 |
r = "+".join(r) |
|---|
| 803 |
return r |
|---|
| 804 |
|
|---|
| 805 |
|
|---|
| 806 |
|
|---|
| 807 |
|
|---|
| 808 |
class FixedPointField(BitField): |
|---|
| 809 |
def __init__(self, name, default, size, frac_bits=16): |
|---|
| 810 |
self.frac_bits = frac_bits |
|---|
| 811 |
BitField.__init__(self, name, default, size) |
|---|
| 812 |
|
|---|
| 813 |
def any2i(self, pkt, val): |
|---|
| 814 |
if val is None: |
|---|
| 815 |
return val |
|---|
| 816 |
ival = int(val) |
|---|
| 817 |
fract = int( (val-ival) * 2**self.frac_bits ) |
|---|
| 818 |
return (ival << self.frac_bits) | fract |
|---|
| 819 |
|
|---|
| 820 |
def i2h(self, pkt, val): |
|---|
| 821 |
int_part = val >> self.frac_bits |
|---|
| 822 |
frac_part = val & (1L << self.frac_bits) - 1 |
|---|
| 823 |
frac_part /= 2.0**self.frac_bits |
|---|
| 824 |
return int_part+frac_part |
|---|
| 825 |
def i2repr(self, pkt, val): |
|---|
| 826 |
return self.i2h(pkt, val) |
|---|