ip6.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. """
  2. Internet Protocol version 6..for whoever needs it (:
  3. RFC 2460
  4. """
  5. from pypacker import pypacker, triggerlist
  6. from pypacker.layer3.ip_shared import *
  7. import logging
  8. logger = logging.getLogger("pypacker")
  9. # TODO: to be implemented
  10. # Encapsulation Security Payload Header = 50
  11. # IP_PROTO_MOBILITY = 135
  12. # IP_PROTO_NONEXT = 59
  13. ext_hdrs = set([
  14. IP_PROTO_HOPOPTS,
  15. IP_PROTO_ROUTING,
  16. IP_PROTO_FRAGMENT,
  17. IP_PROTO_AH,
  18. IP_PROTO_ESP,
  19. IP_PROTO_DSTOPTS,
  20. # TODO: to be implemented
  21. # IP_PROTO_MOBILITY
  22. # IP_PROTO_NONEXT
  23. ])
  24. class IP6(pypacker.Packet):
  25. __hdr__ = (
  26. ("v_fc_flow", "I", 0x60000000),
  27. ("dlen", "H", 0), # payload length (not including standard header)
  28. ("nxt", "B", 0), # next header protocol
  29. ("hlim", "B", 0), # hop limit
  30. ("src", "16s", b"\x00" * 16),
  31. ("dst", "16s", b"\x00" * 16),
  32. ("opts", None, triggerlist.TriggerList)
  33. )
  34. def __get_v(self):
  35. return self.v_fc_flow >> 28
  36. def __set_v(self, v):
  37. self.v_fc_flow = (self.v_fc_flow & ~0xf0000000) | (v << 28)
  38. v = property(__get_v, __set_v)
  39. def __get_fc(self):
  40. return (self.v_fc_flow >> 20) & 0xff
  41. def __set_fc(self, v):
  42. self.v_fc_flow = (self.v_fc_flow & ~0xff00000) | (v << 20)
  43. fc = property(__get_fc, __set_fc)
  44. def __get_flow(self):
  45. return self.v_fc_flow & 0xfffff
  46. def __set_flow(self, v):
  47. self.v_fc_flow = (self.v_fc_flow & ~0xfffff) | (v & 0xfffff)
  48. flow = property(__get_flow, __set_flow)
  49. def _dissect(self, buf):
  50. type_nxt = buf[6]
  51. off = 40
  52. opts = []
  53. # logger.debug("parsing opts from bytes (dst: %s): (len: %d) %s" % (buf[24:40], self.hdr_len, buf[off:]))
  54. # parse options until type is an upper layer one
  55. while type_nxt in ext_hdrs:
  56. length = 8 + buf[off + 1] * 8
  57. # logger.debug("next type is: %s, len: %d, %r" % (type_nxt, length, buf[off:off + length]))
  58. opt = ext_hdrs_cls[type_nxt](buf[off:off + length])
  59. opts.append(opt)
  60. type_nxt = buf[off]
  61. off += length
  62. # TODO: lazy dissect possible?
  63. self.opts.extend(opts)
  64. # IPv6 and IPv4 share same handler
  65. self._init_handler(type_nxt, buf[off:])
  66. # TODO: return length without parsing everything
  67. return off
  68. def direction(self, other):
  69. # logger.debug("checking direction: %s<->%s" % (self, next))
  70. if self.src == other.src and self.dst == other.dst:
  71. # consider packet to itself: can be DIR_REV
  72. return pypacker.Packet.DIR_SAME | pypacker.Packet.DIR_REV
  73. elif self.src == other.dst and self.dst == other.src:
  74. return pypacker.Packet.DIR_REV
  75. else:
  76. return pypacker.Packet.DIR_UNKNOWN
  77. def reverse_address(self):
  78. self.src, self.dst = self.dst, self.src
  79. #
  80. # Basic shared option classes
  81. #
  82. class IP6OptsHeader(pypacker.Packet):
  83. __hdr__ = (
  84. ("nxt", "B", 0), # next extension header protocol
  85. ("len", "B", 0), # option data length in 8 octect units (ignoring first 8 octets) so, len 0 == 64bit header
  86. ("opts", None, triggerlist.TriggerList)
  87. )
  88. def _dissect(self, buf):
  89. length = 8 + buf[1] * 8
  90. options = []
  91. off = 2
  92. # TODO: check https://code.google.com/p/pypacker/issues/attachmentText?id=72
  93. while off < length:
  94. opt_type = buf[off]
  95. # logger.debug("IP6OptsHeader: type: %d" % opt_type)
  96. # http://tools.ietf.org/html/rfc2460#section-4.2
  97. # PAD1 option: no length or data field
  98. if opt_type == 0:
  99. opt = IP6OptionPad(type=opt_type)
  100. # logger.debug("next ip6 bytes 1: %r" % (buf[off:off + 2]))
  101. off += 1
  102. else:
  103. opt_len = buf[off + 1]
  104. opt = IP6Option(type=opt_type, len=opt_len, body_bytes=buf[off + 2: off + 2 + opt_len])
  105. # logger.debug("next ip6 bytes 2: %r" % (buf[off + 2: off + 2 + opt_len]))
  106. off += 2 + opt_len
  107. options.append(opt)
  108. self.opts.extend(options)
  109. return off
  110. class IP6Option(pypacker.Packet):
  111. __hdr__ = (
  112. ("type", "B", 0),
  113. ("len", "B", 0)
  114. )
  115. class IP6OptionPad(pypacker.Packet):
  116. __hdr__ = (
  117. ("type", "B", 0),
  118. )
  119. class IP6HopOptsHeader(IP6OptsHeader):
  120. def _dissect(self, buf):
  121. # logger.debug("IP6HopOptsHeader parsing")
  122. return IP6OptsHeader._dissect(self, buf)
  123. class IP6RoutingHeader(pypacker.Packet):
  124. __hdr__ = (
  125. ("nxt", "B", 0), # next extension header protocol
  126. ("len", "B", 0), # extension data length in 8 octect units (ignoring first 8 octets) (<= 46 for type 0)
  127. ("type", "B", 0), # routing type (currently, only 0 is used)
  128. ("segs_left", "B", 0), # remaining segments in route, until destination (<= 23)
  129. ("rsvd_sl_bits", "I", 0), # reserved (1 byte), strict/loose bitmap for addresses
  130. ("addresses", None, triggerlist.TriggerList)
  131. )
  132. def __get_sl_bits(self):
  133. return self.rsvd_sl_bits & 0xffffff
  134. def __set_sl_bits(self, v):
  135. self.rsvd_sl_bits = (self.rsvd_sl_bits & ~0xfffff) | (v & 0xfffff)
  136. sl_bits = property(__get_sl_bits, __set_sl_bits)
  137. def _dissect(self, buf):
  138. hdr_size = 8
  139. addr_size = 16
  140. addresses = []
  141. num_addresses = self.buf[1] / 2
  142. buf = buf[hdr_size:hdr_size + num_addresses * addr_size]
  143. # logger.debug("IP6RoutingHeader: parsing addresses")
  144. for i in range(num_addresses):
  145. addresses.append(buf[i * addr_size: i * addr_size + addr_size])
  146. self.addresses.extend(addresses)
  147. return len(num_addresses) * addr_size + addr_size
  148. # setattr(self, "addresses", addresses)
  149. # setattr(self, "length", self.len * 8 + 8)
  150. class IP6FragmentHeader(pypacker.Packet):
  151. __hdr__ = (
  152. ("nxt", "B", 0), # next extension header protocol
  153. ("resv", "B", 0), # reserved, set to 0
  154. ("frag_off_resv_m", "H", 0), # frag offset (13 bits), reserved zero (2 bits), More frags flag
  155. ("id", "I", 0) # fragments id
  156. )
  157. def __get_frag_off(self):
  158. return self.frag_off_resv_m >> 3
  159. def __set_frag_off(self, v):
  160. self.frag_off_resv_m = (self.frag_off_resv_m & ~0xfff8) | (v << 3)
  161. frag_off = property(__get_frag_off, __set_frag_off)
  162. def __get_m_flag(self):
  163. return self.frag_off_resv_m & 1
  164. def __set_m_flag(self, v):
  165. self.frag_off_resv_m = (self.frag_off_resv_m & ~0xfffe) | v
  166. m_flag = property(__get_m_flag, __set_m_flag)
  167. class IP6AHHeader(pypacker.Packet):
  168. __hdr__ = (
  169. ("nxt", "B", 0), # next extension header protocol
  170. ("len", "B", 0), # length of header in 4 octet units (ignoring first 2 units)
  171. ("resv", "H", 0), # reserved, 2 bytes of 0
  172. ("spi", "I", 0), # SPI security parameter index
  173. ("seq", "I", 0) # sequence no.
  174. )
  175. class IP6ESPHeader(pypacker.Packet):
  176. def _dissect(self, buf):
  177. raise NotImplementedError("ESP extension headers are not supported.")
  178. class IP6DstOptsHeader(IP6OptsHeader):
  179. def _dissect(self, buf):
  180. # logger.debug("IP6DstOptsHeader parsing")
  181. IP6OptsHeader._dissect(self, buf)
  182. ext_hdrs_cls = {
  183. IP_PROTO_HOPOPTS: IP6HopOptsHeader,
  184. IP_PROTO_ROUTING: IP6RoutingHeader,
  185. IP_PROTO_FRAGMENT: IP6FragmentHeader,
  186. IP_PROTO_ESP: IP6ESPHeader,
  187. IP_PROTO_AH: IP6AHHeader,
  188. IP_PROTO_DSTOPTS: IP6DstOptsHeader
  189. # IP_PROTO_MOBILITY:
  190. # IP_PROTO_NONEXT:
  191. }
  192. # load handler
  193. from pypacker.layer3 import esp, icmp6, igmp, ipx, ospf, pim
  194. from pypacker.layer4 import tcp, udp, sctp
  195. pypacker.Packet.load_handler(IP6,
  196. {
  197. IP_PROTO_ICMP6: icmp6.ICMP6,
  198. IP_PROTO_IGMP: igmp.IGMP,
  199. IP_PROTO_TCP: tcp.TCP,
  200. IP_PROTO_UDP: udp.UDP,
  201. IP_PROTO_IP6: IP6,
  202. IP_PROTO_ESP: esp.ESP,
  203. IP_PROTO_PIM: pim.PIM,
  204. IP_PROTO_IPXIP: ipx.IPX,
  205. IP_PROTO_SCTP: sctp.SCTP,
  206. IP_PROTO_OSPF: ospf.OSPF
  207. }
  208. )