class IP6(pypacker.Packet): __hdr__ = ( ("v_fc_flow", "I", 0x60000000), ("dlen", "H", 0), # payload length (not including standard header) ("nxt", "B", 0), # next header protocol ("hlim", "B", 0), # hop limit ("src", "16s", b"\x00" * 16), ("dst", "16s", b"\x00" * 16), ("opts", None, triggerlist.TriggerList)) def __get_v(self): return self.v_fc_flow >> 28 def __set_v(self, v): self.v_fc_flow = (self.v_fc_flow & ~0xf0000000) | (v << 28) v = property(__get_v, __set_v) def __get_fc(self): return (self.v_fc_flow >> 20) & 0xff def __set_fc(self, v): self.v_fc_flow = (self.v_fc_flow & ~0xff00000) | (v << 20) fc = property(__get_fc, __set_fc) def __get_flow(self): return self.v_fc_flow & 0xfffff def __set_flow(self, v): self.v_fc_flow = (self.v_fc_flow & ~0xfffff) | (v & 0xfffff) flow = property(__get_flow, __set_flow) # Convenient access for: src[_s], dst[_s] src_s = pypacker.get_property_ip6("src") dst_s = pypacker.get_property_ip6("dst") __handler__ = { IP_PROTO_ICMP6: icmp6.ICMP6, IP_PROTO_IGMP: igmp.IGMP, IP_PROTO_TCP: tcp.TCP, IP_PROTO_UDP: udp.UDP, IP_PROTO_ESP: esp.ESP, IP_PROTO_PIM: pim.PIM, IP_PROTO_IPXIP: ipx.IPX, IP_PROTO_SCTP: sctp.SCTP, IP_PROTO_OSPF: ospf.OSPF } def _dissect(self, buf): type_nxt = buf[6] off = 40 opts = [] # logger.debug("type: %d buflen: %d" % (type_nxt, len(buf))) # logger.debug("parsing opts from bytes (dst: %s): (len: %d) %s" % # (buf[24:40], self.hdr_len, buf[off:])) # parse options until type is an upper layer one while type_nxt in ext_hdrs: length = 8 + buf[off + 1] * 8 # logger.debug("next type is: %s, len: %d, %r" % (type_nxt, length, buf[off:off + length])) opt = ext_hdrs_cls[type_nxt](buf[off:off + length]) opts.append(opt) type_nxt = buf[off] off += length # TODO: lazy dissect possible? self.opts.extend(opts) # IPv6 and IPv4 share same handler # TODO: extract real data length: # There are some cases where padding can not be identified on ethernet -> do it here (eg VSS shit trailer) self._init_handler(type_nxt, buf[off:]) return off def direction(self, other): # logger.debug("checking direction: %s<->%s" % (self, next)) if self.src == other.src and self.dst == other.dst: # consider packet to itself: can be DIR_REV return pypacker.Packet.DIR_SAME | pypacker.Packet.DIR_REV if self.src == other.dst and self.dst == other.src: return pypacker.Packet.DIR_REV return pypacker.Packet.DIR_UNKNOWN def reverse_address(self): self.src, self.dst = self.dst, self.src
class IP6(pypacker.Packet): __hdr__ = ( ("v_fc_flow", "I", 0x60000000), ("dlen", "H", 0, FIELD_FLAG_AUTOUPDATE ), # length of extension header (opts header) + body # body handler type OR type of first extension hedader (opts header) ("nxt", "B", 0), ("hlim", "B", 0), # hop limit ("src", "16s", b"\x00" * 16), ("dst", "16s", b"\x00" * 16), ("opts", None, triggerlist.TriggerList)) def __get_v(self): return self.v_fc_flow >> 28 def __set_v(self, v): self.v_fc_flow = (self.v_fc_flow & ~0xf0000000) | (v << 28) v = property(__get_v, __set_v) def __get_fc(self): return (self.v_fc_flow >> 20) & 0xff def __set_fc(self, v): self.v_fc_flow = (self.v_fc_flow & ~0xff00000) | (v << 20) fc = property(__get_fc, __set_fc) def __get_flow(self): return self.v_fc_flow & 0xfffff def __set_flow(self, v): self.v_fc_flow = (self.v_fc_flow & ~0xfffff) | (v & 0xfffff) flow = property(__get_flow, __set_flow) # Convenient access for: src[_s], dst[_s] src_s = pypacker.get_property_ip6("src") dst_s = pypacker.get_property_ip6("dst") __handler__ = { IP_PROTO_ICMP6: icmp6.ICMP6, IP_PROTO_IGMP: igmp.IGMP, IP_PROTO_TCP: tcp.TCP, IP_PROTO_UDP: udp.UDP, IP_PROTO_ESP: esp.ESP, IP_PROTO_PIM: pim.PIM, IP_PROTO_IPXIP: ipx.IPX, IP_PROTO_SCTP: sctp.SCTP, IP_PROTO_OSPF: ospf.OSPF } def _dissect(self, buf): type_nxt = buf[6] off = 40 opts = [] # logger.debug("type: %d buflen: %d" % (type_nxt, len(buf))) # logger.debug("parsing opts from bytes (dst: %s): (len: %d) %s" % # (buf[24:40], self.hdr_len, buf[off:])) # parse options until type is an upper layer one while type_nxt in ext_hdrs: length = 8 + buf[off + 1] * 8 # logger.debug("next type is: %s, len: %d, %r" % (type_nxt, length, buf[off:off + length])) opt = ext_hdrs_cls[type_nxt](buf[off:off + length]) opts.append(opt) type_nxt = buf[off] off += length # TODO: lazy dissect possible? self.opts.extend(opts) # IPv6 and IPv4 share same handler # TODO: extract real data length: # There are some cases where padding can not be identified on ethernet -> do it here (eg VSS shit trailer) self._init_handler(type_nxt, buf[off:]) return off def _update_fields(self): if self.dlen_au_active: self.dlen = len(self.opts.bin()) + len(self.body_bytes) # Set type value in nxt OR in last opts element (if present) # Updating is a bit more complicated so we can't use FIELD_FLAG_IS_TYPEFIELD # idval is None if body handler is None # logger.debug("handler %r -> %r", self.__class__, self.body_handler.__class__) idval = pypacker.Packet.get_id_for_handlerclass( self.__class__, self.body_handler.__class__) #logger.debug("nxt will be %r", idval) if idval is not None: if len(self.opts) == 0: self.nxt = idval else: # no problem if nxt is not a header field name self.opts[-1].nxt = idval def direction(self, other): # logger.debug("checking direction: %s<->%s" % (self, next)) if self.src == other.src and self.dst == other.dst: # consider packet to itself: can be DIR_REV return pypacker.Packet.DIR_SAME | pypacker.Packet.DIR_REV if self.src == other.dst and self.dst == other.src: return pypacker.Packet.DIR_REV return pypacker.Packet.DIR_UNKNOWN def reverse_address(self): self.src, self.dst = self.dst, self.src
class IP6(pypacker.Packet): __hdr__ = ( ("v_fc_flow", "I", 0x60000000), ("dlen", "H", 0), # payload length (not including standard header) ("nxt", "B", 0), # next header protocol ("hlim", "B", 0), # hop limit ("src", "16s", b"\x00" * 16), ("dst", "16s", b"\x00" * 16), ("opts", None, triggerlist.TriggerList)) def __get_v(self): return self.v_fc_flow >> 28 def __set_v(self, v): self.v_fc_flow = (self.v_fc_flow & ~0xf0000000) | (v << 28) v = property(__get_v, __set_v) def __get_fc(self): return (self.v_fc_flow >> 20) & 0xff def __set_fc(self, v): self.v_fc_flow = (self.v_fc_flow & ~0xff00000) | (v << 20) fc = property(__get_fc, __set_fc) def __get_flow(self): return self.v_fc_flow & 0xfffff def __set_flow(self, v): self.v_fc_flow = (self.v_fc_flow & ~0xfffff) | (v & 0xfffff) flow = property(__get_flow, __set_flow) # Convenient access for: src[_s], dst[_s] src_s = pypacker.get_property_ip6("src") dst_s = pypacker.get_property_ip6("dst") def _dissect(self, buf): type_nxt = buf[6] off = 40 opts = [] # logger.debug("parsing opts from bytes (dst: %s): (len: %d) %s" % (buf[24:40], self.hdr_len, buf[off:])) # parse options until type is an upper layer one while type_nxt in ext_hdrs: length = 8 + buf[off + 1] * 8 # logger.debug("next type is: %s, len: %d, %r" % (type_nxt, length, buf[off:off + length])) opt = ext_hdrs_cls[type_nxt](buf[off:off + length]) opts.append(opt) type_nxt = buf[off] off += length # TODO: lazy dissect possible? self.opts.extend(opts) # IPv6 and IPv4 share same handler self._init_handler(type_nxt, buf[off:]) # TODO: return length without parsing everything return off def direction(self, other): # logger.debug("checking direction: %s<->%s" % (self, next)) if self.src == other.src and self.dst == other.dst: # consider packet to itself: can be DIR_REV return pypacker.Packet.DIR_SAME | pypacker.Packet.DIR_REV elif self.src == other.dst and self.dst == other.src: return pypacker.Packet.DIR_REV else: return pypacker.Packet.DIR_UNKNOWN def reverse_address(self): self.src, self.dst = self.dst, self.src