pypacker.py 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017
  1. """
  2. Simple packet creation and parsing logic.
  3. """
  4. import copy
  5. import logging
  6. import random
  7. import re
  8. from struct import Struct
  9. from pypacker.pypacker_meta import MetaPacket
  10. logging.basicConfig(format="%(levelname)s (%(funcName)s): %(message)s")
  11. logger = logging.getLogger("pypacker")
  12. logger.setLevel(logging.WARNING)
  13. # logger.setLevel(logging.INFO)
  14. # logger.setLevel(logging.DEBUG)
  15. PROG_VISIBLE_CHARS = re.compile(b"[^\x20-\x7e]")
  16. HEADER_TYPES_SIMPLE = set([int, bytes])
  17. DIR_SAME = 1
  18. DIR_REV = 2
  19. DIR_UNKNOWN = 4
  20. DIR_NOT_IMPLEMENTED = 255
  21. class Packet(object, metaclass=MetaPacket):
  22. """
  23. Base packet class, with metaclass magic to generate members from self.__hdr__ field.
  24. This class can be instatiated via:
  25. Packet(byte_string)
  26. Packet(key1=val1, key2=val2, ...)
  27. Every packet got a header and a body. Body-data can be raw byte string OR a packet itself
  28. (the body handler) which itself stores a packet etc. This continues until a packet only
  29. contains raw bytes (highest layer). The following schema illustrates the Packet-structure:
  30. Packet structure
  31. ================
  32. [Packet:
  33. headerfield_1
  34. headerfield_2
  35. ...
  36. headerfield_N
  37. [Body -> Packet:
  38. headerfield_1
  39. ...
  40. headerfield_N
  41. [Body: -> Packet:
  42. headerfields
  43. ...
  44. [Body: b"some_bytes"]
  45. ]]]
  46. A header definition like __hdr__ = (("name", "12s", b"defaultvalue"),) will define a header field
  47. having the name "name", format "12s" and default value b"defaultvalue" as bytestring. Fields will
  48. be added in order of definition. The static variable __byte_order__ can be set to override the
  49. default value '>'. Extending classes should overwrite the "_dissect"-method in order to dissect given data.
  50. Requirements
  51. ============
  52. - Auto-decoding of headers via given format-patterns (defined via __hdr__)
  53. - Auto-decoding of body-handlers (like IP -> parse IP-data -> add TCP-handler to IP -> parse TCP-data..)
  54. - Access of higher layers via layer1.layer2.layerX or "layer1[layerX]" notation
  55. - There are three types of headers:
  56. 1) Simple constant fields (constant format)
  57. Format for __hdr__: ("name", "format", value)
  58. 2) Simple dynamic fields (byte string which changes in length)
  59. Format for __hdr__: ("name", None, b"bytestring")
  60. Such types MUST get initiated in _dissect() because there is no way in guessing
  61. the correct format when unpacking values!
  62. 3) TriggerList (List containing Packets, bytes or whatever implemented)
  63. Format for __hdr__: ("name", None, TriggerList)
  64. - Convenient access for standard types (MAC, IP address) using string-representations
  65. This is done by appending "_s" to the attributename:
  66. ip.src_s = "127.0.0.1"
  67. ip_src_bytes = ip.src
  68. Implementation info:
  69. Convenient access should be set via varname_s = pypacker.Packet.get_property_XXX("varname")
  70. - Concatination via "layer1 + layer2 + layerX"
  71. - Header-values with length < 1 Byte should be set by using properties
  72. - Activate/deactivate non-TriggerList header fields by setting values (None=deactive, value=active)
  73. - Checksums (static auto fields in general) are auto-recalculated when calling bin(update_auto_fields=True) (default)
  74. - Ability to check direction to other Packets via "[is_]direction()"
  75. - Access to next lower/upper layer
  76. - No correction of given raw packet-data eg checksums when creating a packet from it
  77. If the packet can't be parsed without correct data -> raise exception.
  78. The internal state will only be updated on changes to headers or data later on
  79. - General rule: less changes to headers/body-data = more performance
  80. Call-flows
  81. ==========
  82. pypacker(bytes)
  83. -> _dissect(): has to be overwritten, get to know/verify the real header-structure
  84. -> (optional): call _init_handler() initiating a handler representing an upper-layer
  85. -> (optional): call _init_triggerlist(name, b"bytes", dissect_callback) to initiate a TriggerList field
  86. -> (optional) on access to simple headers: _unpack() sets all header values
  87. -> (optional) on access to TriggerList headers: lazy parsing gets triggered
  88. -> (optional) on access to body handler next upper layer gets initiated
  89. pypacker(keyword1=value, ...)
  90. -> (optional) set headers
  91. pypacker()
  92. -> sets standard values for simple headers
  93. """
  94. """Dict for saving body handler globaly: { class_name : {id : handler_class} }"""
  95. _handler = {}
  96. """Constants for Packet-directions"""
  97. DIR_SAME = DIR_SAME
  98. DIR_REV = DIR_REV
  99. DIR_UNKNOWN = DIR_UNKNOWN
  100. DIR_NOT_IMPLEMENTED = DIR_NOT_IMPLEMENTED
  101. def __init__(self, *args, **kwargs):
  102. """
  103. Packet constructors:
  104. Packet(bytestring, target_class)
  105. Note: target_class is only meant for internal usage
  106. Packet(keyword1=val1, keyword2=val2, ...)
  107. bytestring -- packet bytes to build packet from, nonempty values are NOT allowed
  108. target_class -- For internal usage only: unpack until this class (meant eg for __getitem__(...))
  109. keywords -- keyword arguments correspond to header fields to be set
  110. """
  111. if args:
  112. if len(args) > 1:
  113. # assume packet, target class given until which we unpack
  114. self._target_unpack_clz = args[1]._target_unpack_clz
  115. try:
  116. # logger.debug("dissecting: %r" % self.__class__.__name__)
  117. header_len = self._dissect(args[0])
  118. # logger.debug("init header (+ body bytes): %r" % self.__class__.__name__)
  119. self._header_len = header_len
  120. self._header_cached = args[0][:header_len]
  121. if not self._body_changed:
  122. # _dissect(...) didn't change body: set raw data.
  123. self._body_bytes = args[0][header_len:]
  124. # reset the changed-flags: original unpacked value = no changes
  125. except Exception as e:
  126. # TODO: remove to continue parsing
  127. # raise Exception("%r" % e)
  128. self._dissect_error = True
  129. logger.exception("could not dissect or unpack: %r" % e)
  130. self._reset_changed()
  131. self._unpacked = False
  132. elif len(kwargs) > 0:
  133. # overwrite default parameters
  134. # logger.debug("new packet with keyword args (%s)" % self.__class__.__name__)
  135. # _unpack is set to None: nothing to unpack until now
  136. for k, v in kwargs.items():
  137. # logger.debug("setting: %s=%s" % (k, v))
  138. setattr(self, k, v)
  139. # no reset: directly assigned = changed
  140. # keyword args means: allready unpacked (nothing to unpack)
  141. self._unpacked = True
  142. else:
  143. self._unpacked = True
  144. def _dissect(self, buf):
  145. """
  146. Dissect packet bytes by doing some (or nothing) of the following:
  147. - call self._init_triggerlist(...) to initiate TriggerLists
  148. - call self._init_handler(...) to initiate upper layer handler
  149. - activate/deactivate non-TriggerList fields by setting values/None to fields
  150. buf -- bytestring to be dissected
  151. return -- header length
  152. """
  153. # _dissect(...) was not overwritten: no changes to header, return original header length
  154. return self._header_len
  155. def __len__(self):
  156. """Return total length (= header + all upper layer data) in bytes."""
  157. if self._body_bytes is not None:
  158. # logger.debug("returning length from raw bytes in %s" % self.__class__.__name__)
  159. return self.header_len + len(self._body_bytes)
  160. else:
  161. try:
  162. # lazy data present: avoid unneeded parsing
  163. # logger.debug("returning length from cached lazy handler in %s" % self.__class__.__name__)
  164. return self.header_len + len(self._lazy_handler_data[2])
  165. except TypeError:
  166. # logger.debug("returning length from present handler in %s, handler is: %s"\
  167. # % (self.__class__.__name__, self._bodytypename))
  168. return self.header_len + len(self.__getattribute__(self._bodytypename))
  169. #
  170. # public access to header length: keep it uptodate
  171. #
  172. def _get_header_len(self):
  173. if self._header_changed and self._header_format_changed:
  174. # header has NOT changed if __init__ just finished -> avoid unneeded re-formating
  175. # update format to get the real length
  176. self._update_header_format()
  177. return self._header_len
  178. # update format if needed and return actual header size
  179. header_len = property(_get_header_len)
  180. def _get_dissect_error(self):
  181. return self._dissect_error
  182. dissect_error = property(_get_dissect_error)
  183. def _get_bodybytes(self):
  184. """
  185. Return raw data bytes or handler bytes (including all upper layers) if present.
  186. This is the same as calling bin() but excluding this header and without resetting changed-status.
  187. """
  188. if self._lazy_handler_data is not None:
  189. # no need to parse: raw bytes for all upper layers
  190. return self._lazy_handler_data[2]
  191. elif self._bodytypename is not None:
  192. # some handler was set
  193. hndl = self.__getattribute__(self._bodytypename)
  194. return hndl._pack_header() + hndl._get_bodybytes()
  195. # return raw bytes
  196. else:
  197. return self._body_bytes
  198. def _set_body_bytes(self, value):
  199. """
  200. Set body bytes to value (bytestring). This will reset any handler.
  201. value -- a byte string (do NOT set to None)
  202. """
  203. if self._bodytypename is not None:
  204. # reset all handler data
  205. self._set_bodyhandler(None)
  206. # logger.debug("setting new raw data: %s" % value)
  207. self._body_bytes = value
  208. self._body_changed = True
  209. self._lazy_handler_data = None
  210. self._notify_changelistener()
  211. # return body data as raw bytes (deprecated)
  212. data = property(_get_bodybytes, _set_body_bytes)
  213. # get and set bytes for body
  214. body_bytes = property(_get_bodybytes, _set_body_bytes)
  215. def _get_bodyhandler(self):
  216. """
  217. return -- handler object or None if not present.
  218. """
  219. if self._lazy_handler_data is not None:
  220. # parse lazy handler data on the next layer
  221. return self.__getattr__(self._lazy_handler_data[0])
  222. elif self._bodytypename is not None:
  223. # body handler already parsed
  224. return self.__getattribute__(self._bodytypename)
  225. else:
  226. # nope, chuck testa
  227. # logger.debug("returning None")
  228. return None
  229. def _set_bodyhandler(self, hndl):
  230. """
  231. Set body handler for this packet and make it accessible via layername.addedtype
  232. like ethernet.ip. This will take the lowercase classname of the given handler eg "ip"
  233. and make the handler accessible by this name. If handler is None any handler will
  234. be reset and data will be set to an empty byte string.
  235. hndl -- the handler to be set (None or a Packet instance)
  236. """
  237. if self._bodytypename is not None and self._lazy_handler_data is None:
  238. # clear old linked data if body handler is already parsed
  239. # logger.debug("removing old data handler connections")
  240. current_handl = self.__getattribute__(self._bodytypename)
  241. current_handl._lower_layer = None
  242. if hndl is None:
  243. # switch (handler=obj, body_bytes=None) to (handler=None, body_bytes=b'')
  244. self._bodytypename = None
  245. # avoid (body_bytes=None, handler=None)
  246. self._body_bytes = b""
  247. else:
  248. # set a new body handler
  249. # associate ip, arp etc with handler-instance to call "ether.ip", "ip.tcp" etc
  250. self._bodytypename = hndl.__class__.__name__.lower()
  251. self._body_bytes = None
  252. # upper layer (self) to lower layer (hndl) eg TCP -access to-> IP
  253. hndl._lower_layer = self
  254. setattr(self, self._bodytypename, hndl)
  255. # logger.debug("finished setting handler: %s" % self._bodytypename)
  256. self._body_changed = True
  257. self._lazy_handler_data = None
  258. self._notify_changelistener()
  259. # get/set body handler or None. Note: this will force lazy dissecting when reading
  260. body_handler = property(_get_bodyhandler, _set_bodyhandler)
  261. # get/set body handler or None. Note: this will force lazy dissecting when reading
  262. upper_layer = property(_get_bodyhandler, _set_bodyhandler)
  263. # get next lower body handler or None (lowest layer reached)
  264. lower_layer = property(lambda v: v._lower_layer)
  265. def _lowest_layer(self):
  266. current = self
  267. while current._lower_layer is not None:
  268. current = current._lower_layer
  269. return current
  270. def _highest_layer(self):
  271. current = self
  272. while current.body_handler is not None:
  273. current = current.body_handler
  274. return current
  275. # get lowest layer
  276. lowest_layer = property(_lowest_layer)
  277. # get top layer
  278. highest_layer = property(_highest_layer)
  279. def __getattr__(self, varname):
  280. """
  281. Gets called if there are no fields matching the name 'varname'. Check if we got
  282. lazy handler data set which must get initiated now.
  283. """
  284. try:
  285. # This should be the best way lazy initiating body handler as body handler names/types
  286. # are not known a priori.
  287. if self._lazy_handler_data[0] == varname:
  288. # lazy handler data was set, parse lazy handler data now!
  289. # logger.debug("lazy dissecting handler: %s" % varname)
  290. handler_data = self._lazy_handler_data
  291. try:
  292. # instantiate handler class using lazy data buffer
  293. # See _init_handler() for 2nd place where handler instantation takes place
  294. # logger.debug("lazy parsing using: %r" % handler_data)
  295. type_instance = handler_data[1](handler_data[2], self)
  296. self._set_bodyhandler(type_instance)
  297. self._lazy_handler_data = None
  298. # this was a lazy init: same as direct dissecting -> no body change
  299. self._body_changed = False
  300. return type_instance
  301. except:
  302. # error on lazy dissecting: set raw bytes
  303. # logger.debug("Exception on dissecting lazy handler")
  304. logger.exception("could not lazy-parse handler: %r, there could be 2 reasons for this: " % handler_data +
  305. "1) packet was malformed 2) dissecting-code is buggy" )
  306. self._bodytypename = None
  307. self._body_bytes = handler_data[2]
  308. self._lazy_handler_data = None
  309. # TODO: remove this to ignore parse errors (set raw bytes after all)
  310. # raise Exception("2>>>>>>>>>>> %r (lazy dissecting)" % e)
  311. return None
  312. # logger.debug("searching for dynamic field: %s/%r" % (varname,self._header_fields_dyn_dict))
  313. except TypeError:
  314. # logger.warning("unable to find: %s" % varname)
  315. pass
  316. # nope not found...
  317. raise AttributeError("Can't find Attribute %s in %r, body type: %s" % (varname, self.__class__, self._bodytypename))
  318. def __getitem__(self, packet_type):
  319. """
  320. Check every layer upwards (inclusive this layer) for the given Packet class
  321. and return the first matched instance or None if nothing was found.
  322. packet_type -- Packet class to search for like Ethernet, IP, TCP etc.
  323. return -- first finding of packet_type or None if nothing was found
  324. """
  325. p_instance = self
  326. # set most top layer to be unpacked, __getattr__() could be called unpacking lazy data
  327. self._target_unpack_clz = packet_type
  328. while not type(p_instance) is packet_type:
  329. # this will auto-parse lazy handler data via _get_bodyhandler()
  330. p_instance = p_instance._get_bodyhandler()
  331. if p_instance is None:
  332. break
  333. # logger.debug("returning found packet-handler: %s->%s" % (type(self), type(p_instance)))
  334. return p_instance
  335. def __iter__(self):
  336. """
  337. Iterate over every layer starting with this ending at last/highest one
  338. """
  339. p_instance = self._get_bodyhandler()
  340. # assume string class never gets found
  341. self._target_unpack_clz = str.__class__
  342. while p_instance is not None:
  343. yield p_instance
  344. # this will auto-parse lazy handler data via _get_bodyhandler()
  345. p_instance = p_instance._get_bodyhandler()
  346. if p_instance is None:
  347. break
  348. def __reassemble(self, packets, fragmentation_protocol=None):
  349. """
  350. TODO: to be implemented
  351. Trys to reassemble the given packets to this packet. This is intended e.g. for TCP fragmented
  352. application Data like HTTP or SSL. This will only work on packets which set the "_fragmented" flag
  353. an are capable of calling "_dissect(...)" multiple times without cousing trouble (additional data gets
  354. added, old data is preserved). This will stop reassembling until "_fragmented" is False.
  355. packets -- list of packets to be assembled to THIS packet
  356. fragmentation_protocol -- protocol which was used for fragmentation (only TCP is supported until now)
  357. if self.fragmented and self.is_direction(other_packets, DIR_SAME):
  358. if transport_protocol == tcp.TCP:
  359. tcp_this = self[tcp.TCP]
  360. tcp_other = other_packets[tcp.TCP]
  361. if tcp_this.seq + tcp_this.dlen == tcp_other.seq:
  362. pass
  363. # TODO: check if data regarding transport_protocol from this packet relates to other_packets
  364. # -> check for non-empty body -> take data -> add data from other packet -> save to bts ...
  365. self._dissect(bts)
  366. """
  367. pass
  368. def dissect_full(self):
  369. """
  370. Recursive unpack ALL data inlcuding lazy header etc up to highest layer inlcuding danymic fields.
  371. """
  372. for name in self._header_field_names:
  373. self.__getattribute__(name)
  374. try:
  375. self._get_bodyhandler().dissect_full()
  376. except AttributeError:
  377. # no handler present
  378. pass
  379. def __add__(self, packet_to_add):
  380. """
  381. Handle concatination of layers like "Ethernet + IP + TCP" and make them accessible
  382. via "ethernet.ip.tcp" (class names as lowercase). Every "A + B" operation will return A
  383. after setting B as the handler (of the deepest handler) of A.
  384. NOTE: changes to A, B... after creating a Packet like "A+B+C+..." will affect the new created Packet itself.
  385. Create a deep copy to avoid this behaviour.
  386. packet_to_add -- the packet to be added as new highest layer for this packet
  387. """
  388. # get highest layer from this packet
  389. highest_layer = self
  390. # unpack all layer, assuming string class will be never found
  391. self._target_unpack_clz = str.__class__
  392. while highest_layer is not None:
  393. if highest_layer._bodytypename is not None:
  394. # this will dissect any lazy data
  395. highest_layer = highest_layer._get_bodyhandler()
  396. else:
  397. break
  398. highest_layer._set_bodyhandler(packet_to_add)
  399. return self
  400. def _summarize(self, verbose=False):
  401. """
  402. verbose -- If False just include this layer, otherweise include all up to highest layer
  403. """
  404. # recalculate fields like checksums, lengths etc
  405. if self._header_changed or self._body_changed:
  406. # logger.debug("header/body changed: need to reparse")
  407. self.bin()
  408. if not self._unpacked:
  409. self._unpack()
  410. # create key=value descriptions
  411. # show all header even deactivated ones
  412. l = ["%s=%r" % (name[1:], getattr(self, name[1:])) for name in self._header_field_names]
  413. if self._bodytypename is None:
  414. # no bodyhandler present
  415. l.append("bytes=%r" % self.body_bytes)
  416. else:
  417. # assume bodyhandler is set
  418. l.append("handler=%s" % self._bodytypename)
  419. layer_sums = ["%s(%s)" % (self.__class__.__name__, ", ".join(l))]
  420. if verbose and self._bodytypename is not None:
  421. layer_sums.append("%r" % self._get_bodyhandler())
  422. return "\n".join(layer_sums)
  423. def __str__(self):
  424. return self._summarize()
  425. def __repr__(self):
  426. return self._summarize(verbose=True)
  427. def _unpack(self):
  428. """
  429. Unpack a full layer (set field values) unpacked (extracted) from cached header bytes.
  430. This will use the current value of _header_cached to set all field values.
  431. NOTE:
  432. - This is only called by the Packet class itself
  433. - This is called prior to changing ANY header values
  434. """
  435. # Needed to set here (and not at the end) to avoid recursive calls
  436. self._unpacked = True
  437. # logger.debug("%r" % self._header_field_names)
  438. # we need the whole format when:
  439. # format changed or some TriggestLists are non-empty (not yet dissected)
  440. if self._header_format_changed:
  441. self._update_header_format()
  442. self_setattr = self.__setattr__
  443. self_getattr = self.__getattribute__
  444. """
  445. logger.debug(">=================\nunpacking 1: %r, %r,\n%s,\n(format via xxx_format) %r,\n%r,\n%s\nformat.size %d\ncached size: %d\n=====================<" %
  446. (self.__class__,
  447. self._header_field_names,
  448. self._header_format.format,
  449. [self_getattr(name + "_format") for name in self._header_field_names],
  450. [self_getattr(name + "_active") for name in self._header_field_names],
  451. self._header_cached,
  452. self._header_format.size,
  453. len(self._header_cached)))
  454. """
  455. # logger.debug([self_getattr(name) for name in self._header_field_names])
  456. header_unpacked = self._header_format.unpack(self._header_cached)
  457. # logger.debug("unpacking via format: %r -> %r" % (self._header_format.format, header_unpacked))
  458. cnt = 0
  459. """
  460. logger.debug("unpacking 2: %r, %r -> %r,\n%r,\n %r\n" % (self.__class__, header_unpacked, self._header_field_names,
  461. [self_getattr(name + "_format") for name in self._header_field_names],
  462. [self_getattr(name + "_active") for name in self._header_field_names]))
  463. """
  464. for name in self._header_field_names:
  465. # only set values if active simple field
  466. if self_getattr(name + "_format") is not None and self_getattr(name + "_active"):
  467. # logger.debug("unpacking value: %s -> %s" % (name_bytes[0], name_bytes[1]))
  468. self_setattr(name, header_unpacked[cnt])
  469. cnt += 1
  470. def reverse_address(self):
  471. """
  472. Reverse source <-> destination address of THIS packet. This is at minimum defined for: Ethernet, IP, TCP, UDP
  473. """
  474. pass
  475. def reverse_all_address(self):
  476. """
  477. Reverse source <-> destination address of EVERY packet upwards including this one
  478. (reverse_address has to be implemented).
  479. """
  480. current_hndl = self
  481. while current_hndl is not None:
  482. current_hndl.reverse_address()
  483. current_hndl = current_hndl._get_bodyhandler()
  484. def _init_handler(self, hndl_type, buffer):
  485. """
  486. Called by overwritten "_dissect()":
  487. Initiate the handler-parser using the given buffer and set it using _set_bodyhandler() later on (lazy
  488. init). This will use the calling class and given handler type to retrieve the resulting handler.
  489. On any error this will set raw bytes given for body data.
  490. hndl_type -- A value to place the handler in the handler-dict like
  491. dict[Class.__name__][hndl_type] (eg type-id, port-number)
  492. buffer -- The buffer to be used to create the handler
  493. """
  494. # empty buffer must lead to empty body
  495. # initiating packets using empty buffer would lead to wrong (default) values
  496. if len(buffer) == 0:
  497. # logger.debug("empty buffer given for _init_handler()!")
  498. return
  499. try:
  500. if self._target_unpack_clz is None or self._target_unpack_clz is self.__class__:
  501. # set lazy handler data, __getattr__() will be called on access to handler (field not yet initiated)
  502. clz = Packet._handler[self.__class__.__name__][hndl_type]
  503. clz_name = clz.__name__.lower()
  504. # logger.debug("setting handler name: %s -> %s" % (self.__class__.__name__, clz_name))
  505. self._lazy_handler_data = [clz_name, clz, buffer]
  506. # set name although we don't set a handler (needed for direction() et al)
  507. self._bodytypename = clz_name
  508. self._body_bytes = None
  509. # avoid setting body_bytes by _unpack()
  510. self._body_changed = True
  511. else:
  512. # continue parsing layers, happens on "__getitem__()": avoid unneeded lazy-data handling
  513. # if specific class must be found
  514. # logger.debug("--------> direct unpacking in: %s" % (self.__class__.__name__))
  515. type_instance = Packet._handler[self.__class__.__name__][hndl_type](buffer, self)
  516. self._set_bodyhandler(type_instance)
  517. except KeyError:
  518. logger.info("unknown type for %s: %d, feel free to implement" % (self.__class__, hndl_type))
  519. self.body_bytes = buffer
  520. # TODO: comment in
  521. # raise Exception("1a>>>>>>>>>>> (key unknown)")
  522. except Exception:
  523. logger.exception("can't set handler data, type/lazy: %s/%s:" %
  524. (str(hndl_type), self._target_unpack_clz is None or self._target_unpack_clz is self.__class__))
  525. # set raw bytes as data (eg handler class not found)
  526. self.body_bytes = buffer
  527. # TODO: comment in
  528. # raise Exception("1b>>>>>>>>>>> %r" % e)
  529. def _init_triggerlist(self, name, bts, dissect_callback):
  530. """
  531. Inititiate a TriggerList field. It will be dissected ondemand.
  532. name -- name of the dynamic filed to be initiated
  533. bts -- bts to be dissected
  534. dissect_callback -- callback to be used to dissect, signature: callback(bytes) -> returns list of bytes, packets, ...
  535. """
  536. self.__setattr__("_%s" % name, [bts, dissect_callback])
  537. self._header_format_changed = True
  538. def direction_all(self, other_packet):
  539. """
  540. Check for direction on ALL layers from this one upwards.
  541. This continues upwards until no body handler can be found anymore.
  542. The extending class can overwrite direction() to implement an individual check,
  543. signature: direction(self, other_packet) return [same as direction_all]
  544. other_packet -- Packet to be compared with this Packet
  545. return -- Bitwise AND-concatination of all directions of ALL layers starting from
  546. this one upwards. Directions are: [DIR_SAME | DIR_REV | DIR_UNKNOWN].
  547. This can be checked via eg "direction_found & DIR_SAME"
  548. """
  549. dir_ext = self.direction(other_packet)
  550. logger.debug("direction of %r: %d" % (self.__class__, dir_ext))
  551. try:
  552. # check upper layers and combine current result
  553. logger.debug("direction? checking next layer")
  554. dir_upper = self._get_bodyhandler().direction_all(other_packet._get_bodyhandler())
  555. return dir_ext & dir_upper
  556. except AttributeError:
  557. # one of both _bodytypename was None
  558. # Example: TCP ACK (last step of handshake, no payload) <-> TCP ACK + Telnet
  559. logger.debug("AttributeError, direction: %d" % dir_ext)
  560. # logger.debug(e)
  561. return dir_ext
  562. def direction(self, other):
  563. """
  564. Check if this layer got a specific direction.
  565. Can be overwritten.
  566. return -- [DIR_SAME | DIR_REV | DIR_UNKNOWN | DIR_NOT_IMPLEMENTED]
  567. """
  568. return Packet.DIR_NOT_IMPLEMENTED
  569. def is_direction(self, packet2, direction):
  570. """
  571. Same as "direction_all()" but using explicit direction to be checked.
  572. As direction_all can be DIR_SAME and DIR_REV at the same time, this call
  573. is more clearly.
  574. packet2 -- packet to be compared to this packet
  575. direction -- check for this direction (DIR_...)
  576. return -- True if direction is found in this packet, False otherwise.
  577. """
  578. logger.debug("direction_all & direction = %d & %d" % (self.direction_all(packet2), direction))
  579. return self.direction_all(packet2) & direction == direction
  580. def bin(self, update_auto_fields=True):
  581. """
  582. Return this header and body (including all upper layers) as byte string
  583. and reset changed-status.
  584. update_auto_fields -- if True auto-update fields like checksums, else leave them be
  585. """
  586. # logger.debug("bin for: %s" % self.__class__.__name__)
  587. # preserve change status until we got all data of all sub-handlers
  588. # needed for eg IP (changed) -> TCP (check changed for sum).
  589. if self._lazy_handler_data is not None:
  590. # no need to parse, just take lazy handler data bytes
  591. body_tmp = self._lazy_handler_data[2]
  592. elif self._bodytypename is not None:
  593. # handler allready parsed
  594. body_tmp = self._get_bodyhandler().bin(update_auto_fields=update_auto_fields)
  595. else:
  596. # raw bytes
  597. body_tmp = self._body_bytes
  598. header_tmp = self._pack_header()
  599. # now every layer got informed about our status, reset it
  600. self._reset_changed()
  601. return header_tmp + body_tmp
  602. def _update_header_format(self):
  603. """
  604. Update format of non-static fields and update _header_format
  605. """
  606. header_format = [self._header_format_order]
  607. self_getattr = self.__getattribute__
  608. for name in self._header_field_names:
  609. if not self_getattr(name + "_active"):
  610. continue
  611. val = self.__getattribute__(name)
  612. if val.__class__ in HEADER_TYPES_SIMPLE: # assume bytes/int/float
  613. header_format.append(self_getattr(name + "_format"))
  614. # logger.debug("adding format for (simple): %r, %s, val: %s" % (self.__class__, name, self_getattr(name)))
  615. else: # assume TriggerList
  616. if val.__class__ == list:
  617. # TriggerList not yet initiated: take cached value
  618. header_format.append("%ds" % len(val[0]))
  619. # logger.debug("adding format for: %r, %s, val: %s" % (self.__class__, name, val[0]))
  620. else:
  621. header_format.append("%ds" % len(val.bin()))
  622. # logger.debug("adding format for: %r, %s, val: %s" % (self.__class__, name, val.bin()))
  623. self._header_format = Struct("".join(header_format))
  624. self._header_len = self._header_format.size
  625. self._header_format_changed = False
  626. def _pack_header(self):
  627. """
  628. Return header as byte string.
  629. """
  630. if not self._header_changed:
  631. # return cached data if nothing changed
  632. # logger.warning("returning cached header (hdr changed=%s): %s->%s" %\
  633. # (self._header_changed, self.__class__.__name__, self._header_cached))
  634. return self._header_cached
  635. if not self._unpacked:
  636. # this happens on: Packet(b"bytes") -> only changes to TriggerList. We need to unpack buffer values
  637. # to re-read them for header packing
  638. self._unpack()
  639. elif self._header_format_changed:
  640. # _unpack will call _update_header_format() if needed
  641. # real format needed for correct packing
  642. self._update_header_format()
  643. header_values = []
  644. self_getattr = self.__getattribute__
  645. for name in self._header_field_names:
  646. if not self_getattr(name + "_active"):
  647. continue
  648. val = self_getattr(name)
  649. # two options:
  650. # - simple type (int, bytes, ...) -> add given value
  651. # - TriggerList (found via format None) -> call bin()
  652. if val.__class__ in HEADER_TYPES_SIMPLE: # assume bytes/int/float
  653. header_values.append(val)
  654. else: # assume TriggerList
  655. if val.__class__ == list:
  656. header_values.append(val[0])
  657. else:
  658. header_values.append(val.bin())
  659. # logger.debug("header bytes for %s: %s = %s" % (self.__class__.__name__, self._header_format.format, header_bytes))
  660. # info: individual unpacking is about 4 times slower than cumulative
  661. try:
  662. self._header_cached = self._header_format.pack(*header_values)
  663. except Exception as e:
  664. logger.warning("Could not pack header data. Did some header value exceed specified format?"
  665. " (e.g. 500 -> 'B'): %r" % e)
  666. return None
  667. # logger.debug(">>> cached header: %s (%d)" % (self._header_cached, len(self._header_cached)))
  668. self._header_changed = False
  669. return self._header_cached
  670. # readonly access to header
  671. header_bytes = property(_pack_header)
  672. def _changed(self):
  673. """
  674. Check if this or any upper layer changed in header or body
  675. return -- True if header or body changed, else False
  676. """
  677. changed = False
  678. p_instance = self
  679. while p_instance is not None:
  680. if p_instance._header_changed or p_instance._body_changed:
  681. changed = True
  682. break
  683. elif p_instance._lazy_handler_data is None:
  684. # one layer up, stop if next layer is not yet initiated which means: no change
  685. p_instance = p_instance._get_bodyhandler()
  686. else:
  687. # nothing changed upwards: lazy handler data still present/nothing got parsed
  688. break
  689. return changed
  690. def _reset_changed(self):
  691. """Set the header/body changed-flag to False. This won't clear caches."""
  692. self._header_changed = False
  693. self._body_changed = False
  694. def _add_change_listener(self, listener_cb):
  695. """
  696. Add a new callback to be called on changes to header or body.
  697. The only argument is this packet itself.
  698. listener_cb -- the change listener to be added as callback-function
  699. """
  700. if len(self._changelistener) == 0:
  701. # copy list (shared)
  702. self._changelistener = []
  703. self._changelistener.append(listener_cb)
  704. def _remove_change_listener(self, listener_cb, remove_all=False):
  705. """
  706. Remove callback from the list of listeners.
  707. listener_cb -- the change listener to be removed
  708. remove_all -- remove all listener at once
  709. """
  710. if not remove_all:
  711. self._changelistener.remove(listener_cb)
  712. else:
  713. del self._changelistener[:]
  714. def _notify_changelistener(self):
  715. """
  716. Notify listener about changes in header or body using signature callback(self).
  717. This is primarily meant for triggerlist to react
  718. on changes in packets like Triggerlist[packet1, packet2, ...].
  719. """
  720. for listener_cb in self._changelistener:
  721. try:
  722. listener_cb()
  723. except Exception as e:
  724. logger.exception("error when informing listener: %r" % e)
  725. @classmethod
  726. def load_handler(cls, clz_add, handler):
  727. """
  728. Load Packet handler using a shared dictionary.
  729. clz_add -- class for which handler has to be added
  730. handler -- dict of handlers to be set like { id : class }, id can be a tuple of values
  731. """
  732. clz_name = clz_add.__name__
  733. if clz_name in Packet._handler:
  734. logger.debug("handler already loaded: %r" % clz_name)
  735. return
  736. # logger.debug("adding classes as handler: [%r] = %r" % (clz_add, handler))
  737. Packet._handler[clz_name] = {}
  738. for handler_id, packetclass in handler.items():
  739. # pypacker.Packet.load_handler(IP, { ID : class } )
  740. if type(handler_id) is not tuple:
  741. Packet._handler[clz_name][handler_id] = packetclass
  742. else:
  743. # pypacker.Packet.load_handler(IP, { (ID1, ID2, ...) : class } )
  744. for id_x in handler_id:
  745. Packet._handler[clz_name][id_x] = packetclass
  746. def hexdump(self, length=16, only_header=False):
  747. """
  748. length -- amount of bytes per line
  749. only_header -- if True: just dump header, else header + body (default)
  750. return -- hexdump output string for this packet (header or header + body).
  751. """
  752. bytepos = 0
  753. res = []
  754. if only_header:
  755. buf = self._pack_header()
  756. else:
  757. buf = self.bin()
  758. buflen = len(buf)
  759. while bytepos < buflen:
  760. line = buf[bytepos: bytepos + length]
  761. hexa = " ".join(["%02x" % x for x in line])
  762. # line = line.translate(__vis_filter)
  763. line = re.sub(PROG_VISIBLE_CHARS, b".", line)
  764. res.append(" %04d: %-*s %s" % (bytepos, length * 3, hexa, line))
  765. bytepos += length
  766. return "\n".join(res)
  767. #
  768. # utility functions
  769. # These could be put into separate modules but this would lead to recursive import problems.
  770. #
  771. # avoid unneeded references for performance reasons
  772. pack_ipv4 = Struct("BBBB").pack
  773. unpack_ipv4 = Struct("BBBB").unpack
  774. pack_mac = Struct("BBBBBB").pack
  775. unpack_mac = Struct("BBBBBB").unpack
  776. randint = random.randint
  777. def byte2hex(buf):
  778. """Convert a bytestring to a hex-represenation:
  779. b'1234' -> '\x31\x32\x33\x34'"""
  780. return "\\x" + "\\x".join(["%02X" % x for x in buf])
  781. # MAC address
  782. def mac_str_to_bytes(mac_str):
  783. """Convert mac address AA:BB:CC:DD:EE:FF to byte representation."""
  784. return b"".join([bytes.fromhex(x) for x in mac_str.split(":")])
  785. def mac_bytes_to_str(mac_bytes):
  786. """Convert mac address from byte representation to AA:BB:CC:DD:EE:FF."""
  787. return "%02X:%02X:%02X:%02X:%02X:%02X" % unpack_mac(mac_bytes)
  788. def get_rnd_mac():
  789. """Create random mac address as bytestring"""
  790. return pack_mac(randint(0, 255), randint(0, 255), randint(0, 255),
  791. randint(0, 255), randint(0, 255), randint(0, 255))
  792. def get_property_mac(varname):
  793. """Create a get/set-property for a MAC address as string-representation."""
  794. # logger.debug("--------------------- returning property")
  795. return property(
  796. lambda obj: mac_bytes_to_str(obj.__getattribute__(varname)),
  797. lambda obj, val: obj.__setattr__(varname, mac_str_to_bytes(val))
  798. )
  799. # IPv4 address
  800. def ip4_str_to_bytes(ip_str):
  801. """Convert ip address 127.0.0.1 to byte representation."""
  802. ips = [int(x) for x in ip_str.split(".")]
  803. return pack_ipv4(ips[0], ips[1], ips[2], ips[3])
  804. def ip4_bytes_to_str(ip_bytes):
  805. """Convert ip address from byte representation to 127.0.0.1."""
  806. return "%d.%d.%d.%d" % unpack_ipv4(ip_bytes)
  807. def get_rnd_ipv4():
  808. """Create random ipv4 adress as bytestring"""
  809. return pack_ipv4(randint(0, 255), randint(0, 255), randint(0, 255), randint(0, 255))
  810. def get_property_ip4(var):
  811. """Create a get/set-property for an IP4 address as string-representation."""
  812. return property(
  813. lambda obj: ip4_bytes_to_str(obj.__getattribute__(var)),
  814. lambda obj, val: obj.__setattr__(var, ip4_str_to_bytes(val))
  815. )
  816. # DNS names
  817. def dns_name_decode(name):
  818. """
  819. DNS domain name decoder (bytes to string)
  820. name -- example: b"\x03www\x07example\x03com\x00"
  821. return -- example: "www.example.com."
  822. """
  823. # ["www", "example", "com"]
  824. name_decoded = []
  825. off = 1
  826. while off < len(name):
  827. # b"xxx" -> "xxx"
  828. name_decoded.append(name[off: off + name[off - 1]].decode())
  829. off += name[off - 1] + 1
  830. return ".".join(name_decoded) + "."
  831. def dns_name_encode(name):
  832. """
  833. DNS domain name encoder (string to bytes)
  834. name -- example: "www.example.com"
  835. return -- example: b'\x03www\x07example\x03com\x00'
  836. """
  837. name_encoded = [b""]
  838. # "www" -> b"www"
  839. labels = [part.encode() for part in name.split(".") if len(part) != 0]
  840. for label in labels:
  841. # b"www" -> "\x03www"
  842. name_encoded.append(chr(len(label)).encode() + label)
  843. return b"".join(name_encoded) + b"\x00"
  844. def get_property_dnsname(var):
  845. """Create a get/set-property for a DNS name."""
  846. return property(
  847. lambda obj: dns_name_decode(obj.__getattribute__(var)),
  848. lambda obj, val: obj.__setattr__(var, dns_name_encode(val))
  849. )