Thangavelu K S | ef6f0a5 | 2016-12-14 19:57:05 +0000 | [diff] [blame] | 1 | ## This file is part of Scapy |
| 2 | ## See http://www.secdev.org/projects/scapy for more informations |
| 3 | ## Copyright (C) Philippe Biondi <phil@secdev.org> |
| 4 | ## This program is published under a GPLv2 license |
| 5 | |
| 6 | """ |
| 7 | Fields: basic data structures that make up parts of packets. |
| 8 | """ |
| 9 | |
| 10 | import struct,copy,socket |
| 11 | from config import conf |
| 12 | from volatile import * |
| 13 | from data import * |
| 14 | from utils import * |
| 15 | from base_classes import BasePacket,Gen,Net |
| 16 | |
| 17 | |
| 18 | ############ |
| 19 | ## Fields ## |
| 20 | ############ |
| 21 | |
| 22 | class Field: |
| 23 | """For more informations on how this work, please refer to |
| 24 | http://www.secdev.org/projects/scapy/files/scapydoc.pdf |
| 25 | chapter ``Adding a New Field''""" |
| 26 | islist=0 |
| 27 | holds_packets=0 |
| 28 | def __init__(self, name, default, fmt="H"): |
| 29 | self.name = name |
| 30 | if fmt[0] in "@=<>!": |
| 31 | self.fmt = fmt |
| 32 | else: |
| 33 | self.fmt = "!"+fmt |
| 34 | self.default = self.any2i(None,default) |
| 35 | self.sz = struct.calcsize(self.fmt) |
| 36 | self.owners = [] |
| 37 | |
| 38 | def register_owner(self, cls): |
| 39 | self.owners.append(cls) |
| 40 | |
| 41 | def i2len(self, pkt, x): |
| 42 | """Convert internal value to a length usable by a FieldLenField""" |
| 43 | return self.sz |
| 44 | def i2count(self, pkt, x): |
| 45 | """Convert internal value to a number of elements usable by a FieldLenField. |
| 46 | Always 1 except for list fields""" |
| 47 | return 1 |
| 48 | def h2i(self, pkt, x): |
| 49 | """Convert human value to internal value""" |
| 50 | return x |
| 51 | def i2h(self, pkt, x): |
| 52 | """Convert internal value to human value""" |
| 53 | return x |
| 54 | def m2i(self, pkt, x): |
| 55 | """Convert machine value to internal value""" |
| 56 | return x |
| 57 | def i2m(self, pkt, x): |
| 58 | """Convert internal value to machine value""" |
| 59 | if x is None: |
| 60 | x = 0 |
| 61 | return x |
| 62 | def any2i(self, pkt, x): |
| 63 | """Try to understand the most input values possible and make an internal value from them""" |
| 64 | return self.h2i(pkt, x) |
| 65 | def i2repr(self, pkt, x): |
| 66 | """Convert internal value to a nice representation""" |
| 67 | return repr(self.i2h(pkt,x)) |
| 68 | def addfield(self, pkt, s, val): |
| 69 | """Add an internal value to a string""" |
| 70 | return s+struct.pack(self.fmt, self.i2m(pkt,val)) |
| 71 | def getfield(self, pkt, s): |
| 72 | """Extract an internal value from a string""" |
| 73 | return s[self.sz:], self.m2i(pkt, struct.unpack(self.fmt, s[:self.sz])[0]) |
| 74 | def do_copy(self, x): |
| 75 | if hasattr(x, "copy"): |
| 76 | return x.copy() |
| 77 | if type(x) is list: |
| 78 | x = x[:] |
| 79 | for i in xrange(len(x)): |
| 80 | if isinstance(x[i], BasePacket): |
| 81 | x[i] = x[i].copy() |
| 82 | return x |
| 83 | def __repr__(self): |
| 84 | return "<Field (%s).%s>" % (",".join(x.__name__ for x in self.owners),self.name) |
| 85 | def copy(self): |
| 86 | return copy.deepcopy(self) |
| 87 | def randval(self): |
| 88 | """Return a volatile object whose value is both random and suitable for this field""" |
| 89 | fmtt = self.fmt[-1] |
| 90 | if fmtt in "BHIQ": |
| 91 | return {"B":RandByte,"H":RandShort,"I":RandInt, "Q":RandLong}[fmtt]() |
| 92 | elif fmtt == "s": |
| 93 | if self.fmt[0] in "0123456789": |
| 94 | l = int(self.fmt[:-1]) |
| 95 | else: |
| 96 | l = int(self.fmt[1:-1]) |
| 97 | return RandBin(l) |
| 98 | else: |
| 99 | warning("no random class for [%s] (fmt=%s)." % (self.name, self.fmt)) |
| 100 | |
| 101 | |
| 102 | |
| 103 | |
| 104 | class Emph: |
| 105 | fld = "" |
| 106 | def __init__(self, fld): |
| 107 | self.fld = fld |
| 108 | def __getattr__(self, attr): |
| 109 | return getattr(self.fld,attr) |
| 110 | def __hash__(self): |
| 111 | return hash(self.fld) |
| 112 | def __eq__(self, other): |
| 113 | return self.fld == other |
| 114 | |
| 115 | |
| 116 | class ActionField: |
| 117 | _fld = None |
| 118 | def __init__(self, fld, action_method, **kargs): |
| 119 | self._fld = fld |
| 120 | self._action_method = action_method |
| 121 | self._privdata = kargs |
| 122 | def any2i(self, pkt, val): |
| 123 | getattr(pkt, self._action_method)(val, self._fld, **self._privdata) |
| 124 | return getattr(self._fld, "any2i")(pkt, val) |
| 125 | def __getattr__(self, attr): |
| 126 | return getattr(self._fld,attr) |
| 127 | |
| 128 | |
| 129 | class ConditionalField: |
| 130 | fld = None |
| 131 | def __init__(self, fld, cond): |
| 132 | self.fld = fld |
| 133 | self.cond = cond |
| 134 | def _evalcond(self,pkt): |
| 135 | return self.cond(pkt) |
| 136 | |
| 137 | def getfield(self, pkt, s): |
| 138 | if self._evalcond(pkt): |
| 139 | return self.fld.getfield(pkt,s) |
| 140 | else: |
| 141 | return s,None |
| 142 | |
| 143 | def addfield(self, pkt, s, val): |
| 144 | if self._evalcond(pkt): |
| 145 | return self.fld.addfield(pkt,s,val) |
| 146 | else: |
| 147 | return s |
| 148 | def __getattr__(self, attr): |
| 149 | return getattr(self.fld,attr) |
| 150 | |
| 151 | |
| 152 | class PadField: |
| 153 | """Add bytes after the proxified field so that it ends at the specified |
| 154 | alignment from its begining""" |
| 155 | _fld = None |
| 156 | def __init__(self, fld, align, padwith=None): |
| 157 | self._fld = fld |
| 158 | self._align = align |
| 159 | self._padwith = padwith or "" |
| 160 | |
| 161 | def padlen(self, flen): |
| 162 | return -flen%self._align |
| 163 | |
| 164 | def getfield(self, pkt, s): |
| 165 | remain,val = self._fld.getfield(pkt,s) |
| 166 | padlen = self.padlen(len(s)-len(remain)) |
| 167 | return remain[padlen:], val |
| 168 | |
| 169 | def addfield(self, pkt, s, val): |
| 170 | sval = self._fld.addfield(pkt, "", val) |
| 171 | return s+sval+struct.pack("%is" % (self.padlen(len(sval))), self._padwith) |
| 172 | |
| 173 | def __getattr__(self, attr): |
| 174 | return getattr(self._fld,attr) |
| 175 | |
| 176 | |
| 177 | class MACField(Field): |
| 178 | def __init__(self, name, default): |
| 179 | Field.__init__(self, name, default, "6s") |
| 180 | def i2m(self, pkt, x): |
| 181 | if x is None: |
| 182 | return "\0\0\0\0\0\0" |
| 183 | return mac2str(x) |
| 184 | def m2i(self, pkt, x): |
| 185 | return str2mac(x) |
| 186 | def any2i(self, pkt, x): |
| 187 | if type(x) is str and len(x) is 6: |
| 188 | x = self.m2i(pkt, x) |
| 189 | return x |
| 190 | def i2repr(self, pkt, x): |
| 191 | x = self.i2h(pkt, x) |
| 192 | if self in conf.resolve: |
| 193 | x = conf.manufdb._resolve_MAC(x) |
| 194 | return x |
| 195 | def randval(self): |
| 196 | return RandMAC() |
| 197 | |
| 198 | |
| 199 | class IPField(Field): |
| 200 | def __init__(self, name, default): |
| 201 | Field.__init__(self, name, default, "4s") |
| 202 | def h2i(self, pkt, x): |
| 203 | if type(x) is str: |
| 204 | try: |
| 205 | inet_aton(x) |
| 206 | except socket.error: |
| 207 | x = Net(x) |
| 208 | elif type(x) is list: |
| 209 | x = [self.h2i(pkt, n) for n in x] |
| 210 | return x |
| 211 | def resolve(self, x): |
| 212 | if self in conf.resolve: |
| 213 | try: |
| 214 | ret = socket.gethostbyaddr(x)[0] |
| 215 | except: |
| 216 | pass |
| 217 | else: |
| 218 | if ret: |
| 219 | return ret |
| 220 | return x |
| 221 | def i2m(self, pkt, x): |
| 222 | return inet_aton(x) |
| 223 | def m2i(self, pkt, x): |
| 224 | return inet_ntoa(x) |
| 225 | def any2i(self, pkt, x): |
| 226 | return self.h2i(pkt,x) |
| 227 | def i2repr(self, pkt, x): |
| 228 | return self.resolve(self.i2h(pkt, x)) |
| 229 | def randval(self): |
| 230 | return RandIP() |
| 231 | |
| 232 | class SourceIPField(IPField): |
| 233 | def __init__(self, name, dstname): |
| 234 | IPField.__init__(self, name, None) |
| 235 | self.dstname = dstname |
| 236 | def i2m(self, pkt, x): |
| 237 | if x is None: |
| 238 | iff,x,gw = pkt.route() |
| 239 | if x is None: |
| 240 | x = "0.0.0.0" |
| 241 | return IPField.i2m(self, pkt, x) |
| 242 | def i2h(self, pkt, x): |
| 243 | if x is None: |
| 244 | dst=getattr(pkt,self.dstname) |
| 245 | if isinstance(dst,Gen): |
| 246 | r = map(conf.route.route, dst) |
| 247 | r.sort() |
| 248 | if r[0] != r[-1]: |
| 249 | warning("More than one possible route for %s"%repr(dst)) |
| 250 | iff,x,gw = r[0] |
| 251 | else: |
| 252 | iff,x,gw = conf.route.route(dst) |
| 253 | return IPField.i2h(self, pkt, x) |
| 254 | |
| 255 | |
| 256 | |
| 257 | |
| 258 | class ByteField(Field): |
| 259 | def __init__(self, name, default): |
| 260 | Field.__init__(self, name, default, "B") |
| 261 | |
| 262 | class XByteField(ByteField): |
| 263 | def i2repr(self, pkt, x): |
| 264 | return lhex(self.i2h(pkt, x)) |
| 265 | |
| 266 | class OByteField(ByteField): |
| 267 | def i2repr(self, pkt, x): |
| 268 | return "%03o"%self.i2h(pkt, x) |
| 269 | |
| 270 | class X3BytesField(XByteField): |
| 271 | def __init__(self, name, default): |
| 272 | Field.__init__(self, name, default, "!I") |
| 273 | def addfield(self, pkt, s, val): |
| 274 | return s+struct.pack(self.fmt, self.i2m(pkt,val))[1:4] |
| 275 | def getfield(self, pkt, s): |
| 276 | return s[3:], self.m2i(pkt, struct.unpack(self.fmt, "\x00"+s[:3])[0]) |
| 277 | |
| 278 | class ThreeBytesField(X3BytesField, ByteField): |
| 279 | def i2repr(self, pkt, x): |
| 280 | return ByteField.i2repr(self, pkt, x) |
| 281 | |
| 282 | class ShortField(Field): |
| 283 | def __init__(self, name, default): |
| 284 | Field.__init__(self, name, default, "H") |
| 285 | |
| 286 | class SignedShortField(Field): |
| 287 | def __init__(self, name, default): |
| 288 | Field.__init__(self, name, default, "h") |
| 289 | |
| 290 | class LEShortField(Field): |
| 291 | def __init__(self, name, default): |
| 292 | Field.__init__(self, name, default, "<H") |
| 293 | |
| 294 | class XShortField(ShortField): |
| 295 | def i2repr(self, pkt, x): |
| 296 | return lhex(self.i2h(pkt, x)) |
| 297 | |
| 298 | |
| 299 | class IntField(Field): |
| 300 | def __init__(self, name, default): |
| 301 | Field.__init__(self, name, default, "I") |
| 302 | |
| 303 | class SignedIntField(Field): |
| 304 | def __init__(self, name, default): |
| 305 | Field.__init__(self, name, default, "i") |
| 306 | def randval(self): |
| 307 | return RandSInt() |
| 308 | |
| 309 | class LEIntField(Field): |
| 310 | def __init__(self, name, default): |
| 311 | Field.__init__(self, name, default, "<I") |
| 312 | |
| 313 | class LESignedIntField(Field): |
| 314 | def __init__(self, name, default): |
| 315 | Field.__init__(self, name, default, "<i") |
| 316 | def randval(self): |
| 317 | return RandSInt() |
| 318 | |
| 319 | class XIntField(IntField): |
| 320 | def i2repr(self, pkt, x): |
| 321 | return lhex(self.i2h(pkt, x)) |
| 322 | |
| 323 | |
| 324 | class LongField(Field): |
| 325 | def __init__(self, name, default): |
| 326 | Field.__init__(self, name, default, "Q") |
| 327 | |
| 328 | class XLongField(LongField): |
| 329 | def i2repr(self, pkt, x): |
| 330 | return lhex(self.i2h(pkt, x)) |
| 331 | |
| 332 | class IEEEFloatField(Field): |
| 333 | def __init__(self, name, default): |
| 334 | Field.__init__(self, name, default, "f") |
| 335 | |
| 336 | class IEEEDoubleField(Field): |
| 337 | def __init__(self, name, default): |
| 338 | Field.__init__(self, name, default, "d") |
| 339 | |
| 340 | |
| 341 | class StrField(Field): |
| 342 | def __init__(self, name, default, fmt="H", remain=0): |
| 343 | Field.__init__(self,name,default,fmt) |
| 344 | self.remain = remain |
| 345 | def i2len(self, pkt, i): |
| 346 | return len(i) |
| 347 | def i2m(self, pkt, x): |
| 348 | if x is None: |
| 349 | x = "" |
| 350 | elif type(x) is not str: |
| 351 | x=str(x) |
| 352 | return x |
| 353 | def addfield(self, pkt, s, val): |
| 354 | return s+self.i2m(pkt, val) |
| 355 | def getfield(self, pkt, s): |
| 356 | if self.remain == 0: |
| 357 | return "",self.m2i(pkt, s) |
| 358 | else: |
| 359 | return s[-self.remain:],self.m2i(pkt, s[:-self.remain]) |
| 360 | def randval(self): |
| 361 | return RandBin(RandNum(0,1200)) |
| 362 | |
| 363 | class PacketField(StrField): |
| 364 | holds_packets=1 |
| 365 | def __init__(self, name, default, cls, remain=0): |
| 366 | StrField.__init__(self, name, default, remain=remain) |
| 367 | self.cls = cls |
| 368 | def i2m(self, pkt, i): |
| 369 | return str(i) |
| 370 | def m2i(self, pkt, m): |
| 371 | return self.cls(m) |
| 372 | def getfield(self, pkt, s): |
| 373 | i = self.m2i(pkt, s) |
| 374 | remain = "" |
| 375 | if conf.padding_layer in i: |
| 376 | r = i[conf.padding_layer] |
| 377 | del(r.underlayer.payload) |
| 378 | remain = r.load |
| 379 | return remain,i |
| 380 | |
| 381 | class PacketLenField(PacketField): |
| 382 | def __init__(self, name, default, cls, length_from=None): |
| 383 | PacketField.__init__(self, name, default, cls) |
| 384 | self.length_from = length_from |
| 385 | def getfield(self, pkt, s): |
| 386 | l = self.length_from(pkt) |
| 387 | try: |
| 388 | i = self.m2i(pkt, s[:l]) |
| 389 | except Exception: |
| 390 | if conf.debug_dissector: |
| 391 | raise |
| 392 | i = conf.raw_layer(load=s[:l]) |
| 393 | return s[l:],i |
| 394 | |
| 395 | |
| 396 | class PacketListField(PacketField): |
| 397 | islist = 1 |
| 398 | def __init__(self, name, default, cls, count_from=None, length_from=None): |
| 399 | if default is None: |
| 400 | default = [] # Create a new list for each instance |
| 401 | PacketField.__init__(self, name, default, cls) |
| 402 | self.count_from = count_from |
| 403 | self.length_from = length_from |
| 404 | |
| 405 | |
| 406 | def any2i(self, pkt, x): |
| 407 | if type(x) is not list: |
| 408 | return [x] |
| 409 | else: |
| 410 | return x |
| 411 | def i2count(self, pkt, val): |
| 412 | if type(val) is list: |
| 413 | return len(val) |
| 414 | return 1 |
| 415 | def i2len(self, pkt, val): |
| 416 | return sum( len(p) for p in val ) |
| 417 | def do_copy(self, x): |
| 418 | if x is None: |
| 419 | return None |
| 420 | else: |
| 421 | return [p if isinstance(p, basestring) else p.copy() for p in x] |
| 422 | def getfield(self, pkt, s): |
| 423 | c = l = None |
| 424 | if self.length_from is not None: |
| 425 | l = self.length_from(pkt) |
| 426 | elif self.count_from is not None: |
| 427 | c = self.count_from(pkt) |
| 428 | |
| 429 | lst = [] |
| 430 | ret = "" |
| 431 | remain = s |
| 432 | if l is not None: |
| 433 | remain,ret = s[:l],s[l:] |
| 434 | while remain: |
| 435 | if c is not None: |
| 436 | if c <= 0: |
| 437 | break |
| 438 | c -= 1 |
| 439 | try: |
| 440 | p = self.m2i(pkt,remain) |
| 441 | except Exception: |
| 442 | if conf.debug_dissector: |
| 443 | raise |
| 444 | p = conf.raw_layer(load=remain) |
| 445 | remain = "" |
| 446 | else: |
| 447 | if conf.padding_layer in p: |
| 448 | pad = p[conf.padding_layer] |
| 449 | remain = pad.load |
| 450 | del(pad.underlayer.payload) |
| 451 | else: |
| 452 | remain = "" |
| 453 | lst.append(p) |
| 454 | return remain+ret,lst |
| 455 | def addfield(self, pkt, s, val): |
| 456 | return s+"".join(map(str, val)) |
| 457 | |
| 458 | |
| 459 | class StrFixedLenField(StrField): |
| 460 | def __init__(self, name, default, length=None, length_from=None): |
| 461 | StrField.__init__(self, name, default) |
| 462 | self.length_from = length_from |
| 463 | if length is not None: |
| 464 | self.length_from = lambda pkt,length=length: length |
| 465 | def i2repr(self, pkt, v): |
| 466 | if type(v) is str: |
| 467 | v = v.rstrip("\0") |
| 468 | return repr(v) |
| 469 | def getfield(self, pkt, s): |
| 470 | l = self.length_from(pkt) |
| 471 | return s[l:], self.m2i(pkt,s[:l]) |
| 472 | def addfield(self, pkt, s, val): |
| 473 | l = self.length_from(pkt) |
| 474 | return s+struct.pack("%is"%l,self.i2m(pkt, val)) |
| 475 | def randval(self): |
| 476 | try: |
| 477 | l = self.length_from(None) |
| 478 | except: |
| 479 | l = RandNum(0,200) |
| 480 | return RandBin(l) |
| 481 | |
| 482 | class StrFixedLenEnumField(StrFixedLenField): |
| 483 | def __init__(self, name, default, length=None, enum=None, length_from=None): |
| 484 | StrFixedLenField.__init__(self, name, default, length=length, length_from=length_from) |
| 485 | self.enum = enum |
| 486 | def i2repr(self, pkt, v): |
| 487 | r = v.rstrip("\0") |
| 488 | rr = repr(r) |
| 489 | if v in self.enum: |
| 490 | rr = "%s (%s)" % (rr, self.enum[v]) |
| 491 | elif r in self.enum: |
| 492 | rr = "%s (%s)" % (rr, self.enum[r]) |
| 493 | return rr |
| 494 | |
| 495 | class NetBIOSNameField(StrFixedLenField): |
| 496 | def __init__(self, name, default, length=31): |
| 497 | StrFixedLenField.__init__(self, name, default, length) |
| 498 | def i2m(self, pkt, x): |
| 499 | l = self.length_from(pkt)/2 |
| 500 | if x is None: |
| 501 | x = "" |
| 502 | x += " "*(l) |
| 503 | x = x[:l] |
| 504 | x = "".join(map(lambda x: chr(0x41+(ord(x)>>4))+chr(0x41+(ord(x)&0xf)), x)) |
| 505 | x = " "+x |
| 506 | return x |
| 507 | def m2i(self, pkt, x): |
| 508 | x = x.strip("\x00").strip(" ") |
| 509 | return "".join(map(lambda x,y: chr((((ord(x)-1)&0xf)<<4)+((ord(y)-1)&0xf)), x[::2],x[1::2])) |
| 510 | |
| 511 | class StrLenField(StrField): |
| 512 | def __init__(self, name, default, fld=None, length_from=None): |
| 513 | StrField.__init__(self, name, default) |
| 514 | self.length_from = length_from |
| 515 | def getfield(self, pkt, s): |
| 516 | l = self.length_from(pkt) |
| 517 | return s[l:], self.m2i(pkt,s[:l]) |
| 518 | |
| 519 | class BoundStrLenField(StrLenField): |
| 520 | def __init__(self,name, default, minlen= 0, maxlen= 255, fld=None, length_from=None): |
| 521 | StrLenField.__init__(self, name, default, fld, length_from) |
| 522 | self.minlen= minlen |
| 523 | self.maxlen= maxlen |
| 524 | |
| 525 | def randval(self): |
| 526 | return RandBin(RandNum(self.minlen, self.maxlen)) |
| 527 | |
| 528 | class FieldListField(Field): |
| 529 | islist=1 |
| 530 | def __init__(self, name, default, field, length_from=None, count_from=None): |
| 531 | if default is None: |
| 532 | default = [] # Create a new list for each instance |
| 533 | self.field = field |
| 534 | Field.__init__(self, name, default) |
| 535 | self.count_from = count_from |
| 536 | self.length_from = length_from |
| 537 | |
| 538 | def i2count(self, pkt, val): |
| 539 | if type(val) is list: |
| 540 | return len(val) |
| 541 | return 1 |
| 542 | def i2len(self, pkt, val): |
| 543 | return sum( self.field.i2len(pkt,v) for v in val ) |
| 544 | |
| 545 | def i2m(self, pkt, val): |
| 546 | if val is None: |
| 547 | val = [] |
| 548 | return val |
| 549 | def any2i(self, pkt, x): |
| 550 | if type(x) is not list: |
| 551 | return [self.field.any2i(pkt, x)] |
| 552 | else: |
| 553 | return map(lambda e, pkt=pkt: self.field.any2i(pkt, e), x) |
| 554 | def i2repr(self, pkt, x): |
| 555 | return map(lambda e, pkt=pkt: self.field.i2repr(pkt,e), x) |
| 556 | def addfield(self, pkt, s, val): |
| 557 | val = self.i2m(pkt, val) |
| 558 | for v in val: |
| 559 | s = self.field.addfield(pkt, s, v) |
| 560 | return s |
| 561 | def getfield(self, pkt, s): |
| 562 | c = l = None |
| 563 | if self.length_from is not None: |
| 564 | l = self.length_from(pkt) |
| 565 | elif self.count_from is not None: |
| 566 | c = self.count_from(pkt) |
| 567 | |
| 568 | val = [] |
| 569 | ret="" |
| 570 | if l is not None: |
| 571 | s,ret = s[:l],s[l:] |
| 572 | |
| 573 | while s: |
| 574 | if c is not None: |
| 575 | if c <= 0: |
| 576 | break |
| 577 | c -= 1 |
| 578 | s,v = self.field.getfield(pkt, s) |
| 579 | val.append(v) |
| 580 | return s+ret, val |
| 581 | |
| 582 | class FieldLenField(Field): |
| 583 | def __init__(self, name, default, length_of=None, fmt = "H", count_of=None, adjust=lambda pkt,x:x, fld=None): |
| 584 | Field.__init__(self, name, default, fmt) |
| 585 | self.length_of=length_of |
| 586 | self.count_of=count_of |
| 587 | self.adjust=adjust |
| 588 | if fld is not None: |
| 589 | FIELD_LENGTH_MANAGEMENT_DEPRECATION(self.__class__.__name__) |
| 590 | self.length_of = fld |
| 591 | def i2m(self, pkt, x): |
| 592 | if x is None: |
| 593 | if self.length_of is not None: |
| 594 | fld,fval = pkt.getfield_and_val(self.length_of) |
| 595 | f = fld.i2len(pkt, fval) |
| 596 | else: |
| 597 | fld,fval = pkt.getfield_and_val(self.count_of) |
| 598 | f = fld.i2count(pkt, fval) |
| 599 | x = self.adjust(pkt,f) |
| 600 | return x |
| 601 | |
| 602 | class StrNullField(StrField): |
| 603 | def addfield(self, pkt, s, val): |
| 604 | return s+self.i2m(pkt, val)+"\x00" |
| 605 | def getfield(self, pkt, s): |
| 606 | l = s.find("\x00") |
| 607 | if l < 0: |
| 608 | #XXX \x00 not found |
| 609 | return "",s |
| 610 | return s[l+1:],self.m2i(pkt, s[:l]) |
| 611 | def randval(self): |
| 612 | return RandTermString(RandNum(0,1200),"\x00") |
| 613 | |
| 614 | class StrStopField(StrField): |
| 615 | def __init__(self, name, default, stop, additionnal=0): |
| 616 | Field.__init__(self, name, default) |
| 617 | self.stop=stop |
| 618 | self.additionnal=additionnal |
| 619 | def getfield(self, pkt, s): |
| 620 | l = s.find(self.stop) |
| 621 | if l < 0: |
| 622 | return "",s |
| 623 | # raise Scapy_Exception,"StrStopField: stop value [%s] not found" %stop |
| 624 | l += len(self.stop)+self.additionnal |
| 625 | return s[l:],s[:l] |
| 626 | def randval(self): |
| 627 | return RandTermString(RandNum(0,1200),self.stop) |
| 628 | |
| 629 | class LenField(Field): |
| 630 | def i2m(self, pkt, x): |
| 631 | if x is None: |
| 632 | x = len(pkt.payload) |
| 633 | return x |
| 634 | |
| 635 | class BCDFloatField(Field): |
| 636 | def i2m(self, pkt, x): |
| 637 | return int(256*x) |
| 638 | def m2i(self, pkt, x): |
| 639 | return x/256.0 |
| 640 | |
| 641 | class BitField(Field): |
| 642 | def __init__(self, name, default, size): |
| 643 | Field.__init__(self, name, default) |
| 644 | self.rev = size < 0 |
| 645 | self.size = abs(size) |
| 646 | def reverse(self, val): |
| 647 | if self.size == 16: |
| 648 | val = socket.ntohs(val) |
| 649 | elif self.size == 32: |
| 650 | val = socket.ntohl(val) |
| 651 | return val |
| 652 | |
| 653 | def addfield(self, pkt, s, val): |
| 654 | val = self.i2m(pkt, val) |
| 655 | if type(s) is tuple: |
| 656 | s,bitsdone,v = s |
| 657 | else: |
| 658 | bitsdone = 0 |
| 659 | v = 0 |
| 660 | if self.rev: |
| 661 | val = self.reverse(val) |
| 662 | v <<= self.size |
| 663 | v |= val & ((1L<<self.size) - 1) |
| 664 | bitsdone += self.size |
| 665 | while bitsdone >= 8: |
| 666 | bitsdone -= 8 |
| 667 | s = s+struct.pack("!B", v >> bitsdone) |
| 668 | v &= (1L<<bitsdone)-1 |
| 669 | if bitsdone: |
| 670 | return s,bitsdone,v |
| 671 | else: |
| 672 | return s |
| 673 | def getfield(self, pkt, s): |
| 674 | if type(s) is tuple: |
| 675 | s,bn = s |
| 676 | else: |
| 677 | bn = 0 |
| 678 | # we don't want to process all the string |
| 679 | nb_bytes = (self.size+bn-1)/8 + 1 |
| 680 | w = s[:nb_bytes] |
| 681 | |
| 682 | # split the substring byte by byte |
| 683 | bytes = struct.unpack('!%dB' % nb_bytes , w) |
| 684 | |
| 685 | b = 0L |
| 686 | for c in range(nb_bytes): |
| 687 | b |= long(bytes[c]) << (nb_bytes-c-1)*8 |
| 688 | |
| 689 | # get rid of high order bits |
| 690 | b &= (1L << (nb_bytes*8-bn)) - 1 |
| 691 | |
| 692 | # remove low order bits |
| 693 | b = b >> (nb_bytes*8 - self.size - bn) |
| 694 | |
| 695 | if self.rev: |
| 696 | b = self.reverse(b) |
| 697 | |
| 698 | bn += self.size |
| 699 | s = s[bn/8:] |
| 700 | bn = bn%8 |
| 701 | b = self.m2i(pkt, b) |
| 702 | if bn: |
| 703 | return (s,bn),b |
| 704 | else: |
| 705 | return s,b |
| 706 | def randval(self): |
| 707 | return RandNum(0,2**self.size-1) |
| 708 | |
| 709 | |
| 710 | class BitFieldLenField(BitField): |
| 711 | def __init__(self, name, default, size, length_of=None, count_of=None, adjust=lambda pkt,x:x): |
| 712 | BitField.__init__(self, name, default, size) |
| 713 | self.length_of=length_of |
| 714 | self.count_of=count_of |
| 715 | self.adjust=adjust |
| 716 | def i2m(self, pkt, x): |
| 717 | return FieldLenField.i2m.im_func(self, pkt, x) |
| 718 | |
| 719 | |
| 720 | class XBitField(BitField): |
| 721 | def i2repr(self, pkt, x): |
| 722 | return lhex(self.i2h(pkt,x)) |
| 723 | |
| 724 | |
| 725 | class EnumField(Field): |
| 726 | def __init__(self, name, default, enum, fmt = "H"): |
| 727 | i2s = self.i2s = {} |
| 728 | s2i = self.s2i = {} |
| 729 | if type(enum) is list: |
| 730 | keys = xrange(len(enum)) |
| 731 | else: |
| 732 | keys = enum.keys() |
| 733 | if filter(lambda x: type(x) is str, keys): |
| 734 | i2s,s2i = s2i,i2s |
| 735 | for k in keys: |
| 736 | i2s[k] = enum[k] |
| 737 | s2i[enum[k]] = k |
| 738 | Field.__init__(self, name, default, fmt) |
| 739 | |
| 740 | def any2i_one(self, pkt, x): |
| 741 | if type(x) is str: |
| 742 | if (x == 'TLS_2_1') | (x == 'RSA_WITH_AES_512_CBC_SHA'): |
| 743 | x = 70 |
| 744 | else: |
| 745 | x = self.s2i[x] |
| 746 | return x |
| 747 | |
| 748 | def any2i_one_negative_case(self, pkt, x): |
| 749 | if type(x) is str: |
| 750 | x = 770 |
| 751 | return x |
| 752 | def i2repr_one(self, pkt, x): |
| 753 | if self not in conf.noenum and not isinstance(x,VolatileValue) and x in self.i2s: |
| 754 | return self.i2s[x] |
| 755 | return repr(x) |
| 756 | |
| 757 | def any2i(self, pkt, x): |
| 758 | if type(x) is list: |
| 759 | return map(lambda z,pkt=pkt:self.any2i_one(pkt,z), x) |
| 760 | else: |
| 761 | return self.any2i_one(pkt,x) |
| 762 | def i2repr(self, pkt, x): |
| 763 | if type(x) is list: |
| 764 | return map(lambda z,pkt=pkt:self.i2repr_one(pkt,z), x) |
| 765 | else: |
| 766 | return self.i2repr_one(pkt,x) |
| 767 | |
| 768 | #scapy_obj = EnumField() |
| 769 | #scapy_obj.any2i_one = scapy_obj.any2i_one_negative_case |
| 770 | |
| 771 | class CharEnumField(EnumField): |
| 772 | def __init__(self, name, default, enum, fmt = "1s"): |
| 773 | EnumField.__init__(self, name, default, enum, fmt) |
| 774 | k = self.i2s.keys() |
| 775 | if k and len(k[0]) != 1: |
| 776 | self.i2s,self.s2i = self.s2i,self.i2s |
| 777 | def any2i_one(self, pkt, x): |
| 778 | if len(x) != 1: |
| 779 | x = self.s2i[x] |
| 780 | return x |
| 781 | |
| 782 | class BitEnumField(BitField,EnumField): |
| 783 | def __init__(self, name, default, size, enum): |
| 784 | EnumField.__init__(self, name, default, enum) |
| 785 | self.rev = size < 0 |
| 786 | self.size = abs(size) |
| 787 | def any2i(self, pkt, x): |
| 788 | return EnumField.any2i(self, pkt, x) |
| 789 | def i2repr(self, pkt, x): |
| 790 | return EnumField.i2repr(self, pkt, x) |
| 791 | |
| 792 | class ShortEnumField(EnumField): |
| 793 | def __init__(self, name, default, enum): |
| 794 | EnumField.__init__(self, name, default, enum, "H") |
| 795 | |
| 796 | class LEShortEnumField(EnumField): |
| 797 | def __init__(self, name, default, enum): |
| 798 | EnumField.__init__(self, name, default, enum, "<H") |
| 799 | |
| 800 | class ByteEnumField(EnumField): |
| 801 | def __init__(self, name, default, enum): |
| 802 | EnumField.__init__(self, name, default, enum, "B") |
| 803 | |
| 804 | class IntEnumField(EnumField): |
| 805 | def __init__(self, name, default, enum): |
| 806 | EnumField.__init__(self, name, default, enum, "I") |
| 807 | |
| 808 | class SignedIntEnumField(EnumField): |
| 809 | def __init__(self, name, default, enum): |
| 810 | EnumField.__init__(self, name, default, enum, "i") |
| 811 | def randval(self): |
| 812 | return RandSInt() |
| 813 | |
| 814 | class LEIntEnumField(EnumField): |
| 815 | def __init__(self, name, default, enum): |
| 816 | EnumField.__init__(self, name, default, enum, "<I") |
| 817 | |
| 818 | class XShortEnumField(ShortEnumField): |
| 819 | def i2repr_one(self, pkt, x): |
| 820 | if self not in conf.noenum and not isinstance(x,VolatileValue) and x in self.i2s: |
| 821 | return self.i2s[x] |
| 822 | return lhex(x) |
| 823 | |
| 824 | class MultiEnumField(EnumField): |
| 825 | def __init__(self, name, default, enum, depends_on, fmt = "H"): |
| 826 | |
| 827 | self.depends_on = depends_on |
| 828 | self.i2s_multi = enum |
| 829 | self.s2i_multi = {} |
| 830 | self.s2i_all = {} |
| 831 | for m in enum: |
| 832 | self.s2i_multi[m] = s2i = {} |
| 833 | for k,v in enum[m].iteritems(): |
| 834 | s2i[v] = k |
| 835 | self.s2i_all[v] = k |
| 836 | Field.__init__(self, name, default, fmt) |
| 837 | def any2i_one(self, pkt, x): |
| 838 | if type (x) is str: |
| 839 | v = self.depends_on(pkt) |
| 840 | if v in self.s2i_multi: |
| 841 | s2i = self.s2i_multi[v] |
| 842 | if x in s2i: |
| 843 | return s2i[x] |
| 844 | return self.s2i_all[x] |
| 845 | return x |
| 846 | def i2repr_one(self, pkt, x): |
| 847 | v = self.depends_on(pkt) |
| 848 | if v in self.i2s_multi: |
| 849 | return self.i2s_multi[v].get(x,x) |
| 850 | return x |
| 851 | |
| 852 | class BitMultiEnumField(BitField,MultiEnumField): |
| 853 | def __init__(self, name, default, size, enum, depends_on): |
| 854 | MultiEnumField.__init__(self, name, default, enum) |
| 855 | self.rev = size < 0 |
| 856 | self.size = abs(size) |
| 857 | def any2i(self, pkt, x): |
| 858 | return MultiEnumField.any2i(self, pkt, x) |
| 859 | def i2repr(self, pkt, x): |
| 860 | return MultiEnumField.i2repr(self, pkt, x) |
| 861 | |
| 862 | |
| 863 | class ByteEnumKeysField(ByteEnumField): |
| 864 | """ByteEnumField that picks valid values when fuzzed. """ |
| 865 | def randval(self): |
| 866 | return RandEnumKeys(self.i2s) |
| 867 | |
| 868 | |
| 869 | class ShortEnumKeysField(ShortEnumField): |
| 870 | """ShortEnumField that picks valid values when fuzzed. """ |
| 871 | def randval(self): |
| 872 | return RandEnumKeys(self.i2s) |
| 873 | |
| 874 | |
| 875 | class IntEnumKeysField(IntEnumField): |
| 876 | """IntEnumField that picks valid values when fuzzed. """ |
| 877 | def randval(self): |
| 878 | return RandEnumKeys(self.i2s) |
| 879 | |
| 880 | |
| 881 | # Little endian long field |
| 882 | class LELongField(Field): |
| 883 | def __init__(self, name, default): |
| 884 | Field.__init__(self, name, default, "<Q") |
| 885 | |
| 886 | # Little endian fixed length field |
| 887 | class LEFieldLenField(FieldLenField): |
| 888 | def __init__(self, name, default, length_of=None, fmt = "<H", count_of=None, adjust=lambda pkt,x:x, fld=None): |
| 889 | FieldLenField.__init__(self, name, default, length_of=length_of, fmt=fmt, count_of=count_of, fld=fld, adjust=adjust) |
| 890 | |
| 891 | |
| 892 | class FlagsField(BitField): |
| 893 | def __init__(self, name, default, size, names): |
| 894 | self.multi = type(names) is list |
| 895 | if self.multi: |
| 896 | self.names = map(lambda x:[x], names) |
| 897 | else: |
| 898 | self.names = names |
| 899 | BitField.__init__(self, name, default, size) |
| 900 | def any2i(self, pkt, x): |
| 901 | if type(x) is str: |
| 902 | if self.multi: |
| 903 | x = map(lambda y:[y], x.split("+")) |
| 904 | y = 0 |
| 905 | for i in x: |
| 906 | y |= 1 << self.names.index(i) |
| 907 | x = y |
| 908 | return x |
| 909 | def i2repr(self, pkt, x): |
| 910 | if type(x) is list or type(x) is tuple: |
| 911 | return repr(x) |
| 912 | if self.multi: |
| 913 | r = [] |
| 914 | else: |
| 915 | r = "" |
| 916 | i=0 |
| 917 | while x: |
| 918 | if x & 1: |
| 919 | r += self.names[i] |
| 920 | i += 1 |
| 921 | x >>= 1 |
| 922 | if self.multi: |
| 923 | r = "+".join(r) |
| 924 | return r |
| 925 | |
| 926 | |
| 927 | |
| 928 | |
| 929 | class FixedPointField(BitField): |
| 930 | def __init__(self, name, default, size, frac_bits=16): |
| 931 | self.frac_bits = frac_bits |
| 932 | BitField.__init__(self, name, default, size) |
| 933 | |
| 934 | def any2i(self, pkt, val): |
| 935 | if val is None: |
| 936 | return val |
| 937 | ival = int(val) |
| 938 | fract = int( (val-ival) * 2**self.frac_bits ) |
| 939 | return (ival << self.frac_bits) | fract |
| 940 | |
| 941 | def i2h(self, pkt, val): |
| 942 | int_part = val >> self.frac_bits |
| 943 | frac_part = val & (1L << self.frac_bits) - 1 |
| 944 | frac_part /= 2.0**self.frac_bits |
| 945 | return int_part+frac_part |
| 946 | def i2repr(self, pkt, val): |
| 947 | return self.i2h(pkt, val) |
| 948 | |
| 949 | |
| 950 | # Base class for IPv4 and IPv6 Prefixes inspired by IPField and IP6Field. |
| 951 | # Machine values are encoded in a multiple of wordbytes bytes. |
| 952 | class _IPPrefixFieldBase(Field): |
| 953 | def __init__(self, name, default, wordbytes, maxbytes, aton, ntoa, length_from): |
| 954 | self.wordbytes= wordbytes |
| 955 | self.maxbytes= maxbytes |
| 956 | self.aton= aton |
| 957 | self.ntoa= ntoa |
| 958 | Field.__init__(self, name, default, "%is" % self.maxbytes) |
| 959 | self.length_from= length_from |
| 960 | |
| 961 | def _numbytes(self, pfxlen): |
| 962 | wbits= self.wordbytes * 8 |
| 963 | return ((pfxlen + (wbits - 1)) / wbits) * self.wordbytes |
| 964 | |
| 965 | def h2i(self, pkt, x): |
| 966 | # "fc00:1::1/64" -> ("fc00:1::1", 64) |
| 967 | [pfx,pfxlen]= x.split('/') |
| 968 | self.aton(pfx) # check for validity |
| 969 | return (pfx, int(pfxlen)) |
| 970 | |
| 971 | |
| 972 | def i2h(self, pkt, x): |
| 973 | # ("fc00:1::1", 64) -> "fc00:1::1/64" |
| 974 | (pfx,pfxlen)= x |
| 975 | return "%s/%i" % (pfx,pfxlen) |
| 976 | |
| 977 | def i2m(self, pkt, x): |
| 978 | # ("fc00:1::1", 64) -> ("\xfc\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 64) |
| 979 | (pfx,pfxlen)= x |
| 980 | s= self.aton(pfx); |
| 981 | return (s[:self._numbytes(pfxlen)], pfxlen) |
| 982 | |
| 983 | def m2i(self, pkt, x): |
| 984 | # ("\xfc\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 64) -> ("fc00:1::1", 64) |
| 985 | (s,pfxlen)= x |
| 986 | |
| 987 | if len(s) < self.maxbytes: |
| 988 | s= s + ("\0" * (self.maxbytes - len(s))) |
| 989 | return (self.ntoa(s), pfxlen) |
| 990 | |
| 991 | def any2i(self, pkt, x): |
| 992 | if x is None: |
| 993 | return (self.ntoa("\0"*self.maxbytes), 1) |
| 994 | |
| 995 | return self.h2i(pkt,x) |
| 996 | |
| 997 | def i2len(self, pkt, x): |
| 998 | (_,pfxlen)= x |
| 999 | return pfxlen |
| 1000 | |
| 1001 | def addfield(self, pkt, s, val): |
| 1002 | (rawpfx,pfxlen)= self.i2m(pkt,val) |
| 1003 | fmt= "!%is" % self._numbytes(pfxlen) |
| 1004 | return s+struct.pack(fmt, rawpfx) |
| 1005 | |
| 1006 | def getfield(self, pkt, s): |
| 1007 | pfxlen= self.length_from(pkt) |
| 1008 | numbytes= self._numbytes(pfxlen) |
| 1009 | fmt= "!%is" % numbytes |
| 1010 | return s[numbytes:], self.m2i(pkt, (struct.unpack(fmt, s[:numbytes])[0], pfxlen)) |
| 1011 | |
| 1012 | |
| 1013 | class IPPrefixField(_IPPrefixFieldBase): |
| 1014 | def __init__(self, name, default, wordbytes=1, length_from= None): |
| 1015 | _IPPrefixFieldBase.__init__(self, name, default, wordbytes, 4, inet_aton, inet_ntoa, length_from) |
| 1016 | |
| 1017 | |
| 1018 | class IP6PrefixField(_IPPrefixFieldBase): |
| 1019 | def __init__(self, name, default, wordbytes= 1, length_from= None): |
| 1020 | _IPPrefixFieldBase.__init__(self, name, default, wordbytes, 16, lambda a: inet_pton(socket.AF_INET6, a), lambda n: inet_ntop(socket.AF_INET6, n), length_from) |
| 1021 | |
| 1022 | #sriptpath_for_dynamic_import = /usr/local/lib/python2.7/dist-packages/scapy/fileds.py |
| 1023 | #sys.path.append(os.path.abspath(scriptpath)) |
| 1024 | #import fields * |
| 1025 | |
| 1026 | |