def __init__(self, bytes=None, timestamp=None, **kv): u = pcs.Field("u", 1) type = pcs.Field("exp", 15) length = pcs.Field("length", 16) id = pcs.Field("id", 32) mparams = pcs.OptionListField("") oparams = pcs.OptionListField("") pcs.Packet.__init__(self, [ u, type, length, id, mparams, oparams ], \ bytes = bytes, **kv) self.description = "RFC 3036 LDP message header " if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if bytes is not None: offset = self.sizeof() curr = offset remaining = len(bytes) - offset self.data = payload.payload(bytes[curr:remaining], \ timestamp = timestamp) else: self.data = None
def __init__(self, bytes=None, timestamp=None, **kv): """initialize a header very similar to that of IGMPv1/v2""" reserved00 = pcs.Field("reserved00", 8) capabilities = pcs.Field("capabilities", 8) minor = pcs.Field("minor", 8) major = pcs.Field("major", 8) options = pcs.OptionListField("options") pcs.Packet.__init__(self, [reserved00, capabilities, minor, major, options], bytes, **kv) self.description = "initialize a header very similar to that of IGMPv1/v2" if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp # XXX optional bytes not processed yet. if bytes is not None: offset = self.sizeof() self.data = payload.payload(bytes[offset:len(bytes)]) else: self.data = None
def __init__(self, name, **kv): self.packet = None self.name = name self.len = pcs.Field("len", 16) self.flags = pcs.Field("flags", 8) self.hops = pcs.Field("hops", 8) self.ifindex = pcs.Field("ifindex", 32) self.tlvs = pcs.OptionListField("tlvs") # XXX I actually have variable width when I am being encoded, # OptionList deals with this. self.width = self.len.width + self.flags.width + \ self.hops.width + self.ifindex.width + \ self.tlvs.width # If keyword initializers are present, deal with the syntactic sugar. # TODO: Figure out how to initialize the TLVs inside our TLV... if kv is not None: for kw in kv.iteritems(): if kw[0] in self.__dict__: if kw[0] == 'tlvs': if not isinstance(kw[1], list): if __debug__: print "argument is not a list" continue #for src in kw[1]: # if not isinstance(src, int): # if __debug__: # print "source is not an IPv4 address" # continue # self.sources.append(pcs.Field("", 32, default=src)) else: self.__dict__[kw[0]].value = kw[1]
def __init__(self, bytes=None, timestamp=None, **kv): ntpts = pcs.Field("ntpts", 64) rtpts = pcs.Field("rtpts", 32) spkts = pcs.Field("spkts", 32) sbytes = pcs.Field("sbytes", 32) opt = pcs.OptionListField("opt") pcs.Packet.__init__(self, [ntpts, rtpts, spkts, sbytes, opt], bytes=bytes, **kv) self.description = "RFC 3550 Real Time Control Protocol sender message portion" if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if bytes is not None: offset = self.sizeof() curr = offset remaining = len(bytes) - offset # XXX TODO decapsulate all the report counts. # to do this, we need to see the parent RC. self.data = payload.payload(bytes[curr:remaining], \ timestamp = timestamp) else: self.data = None
def __init__(self, bytes=None, timestamp=None, **kv): """initialize an IGMPv3 query""" group = pcs.Field("group", 32) reserved00 = pcs.Field("reserved00", 4) sbit = pcs.Field("sbit", 1) qrv = pcs.Field("qrv", 3) qqic = pcs.Field("qqic", 8) nsrc = pcs.Field("nsrc", 16) srcs = pcs.OptionListField("sources") # If keyword initializers are present, deal with the syntactic sugar. # query's constructor accepts a list of IP addresses. These need # to be turned into Fields for encoding to work, as they are going # to be stashed into the "sources" OptionListField defined above. if kv is not None: for kw in kv.iteritems(): if kw[0] == 'sources': assert isinstance(kw[1], list) for src in kw[1]: assert isinstance(src, int) srcs.append(pcs.Field("", 32, default=src)) kv.pop('sources') pcs.Packet.__init__(self, [group, reserved00, sbit, qrv, qqic, nsrc, srcs], bytes=bytes, **kv) self.description = "initialize an IGMPv3 query" if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp # Decode source list if provided. if bytes is not None: sources_len = self.nsrc * 4 query_len = self.sizeof() + sources_len if query_len > len(bytes): raise UnpackError, \ "IGMPv3 query is larger than input (%d > %d)" % \ (query_len, len(bytes)) rem = sources_len curr = self.sizeof() while rem >= 4: src = struct.unpack('I', bytes[curr:curr + 4])[0] sources.append(pcs.Field("", 32, default=src)) curr += 4 rem -= 4 if rem > 0: print "WARNING: %d trailing bytes in query." % rem # IGMPv3 queries SHOULD NOT contain ancillary data. If we # do find any, we'll append it to the data member. self.data = payload.payload(bytes[query_len:len(bytes)]) else: self.data = None
def __init__(self, bytes=None, timestamp=None, **kv): """initialize an IGMPv3 report header""" reserved00 = pcs.Field("reserved00", 16) nrecords = pcs.Field("nrecords", 16) records = pcs.OptionListField("records") pcs.Packet.__init__(self, [reserved00, nrecords, records], bytes, **kv) self.description = "initialize an IGMPv3 report header" if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp # Decode additional bytes into group records, if provided. # Group records are variable length structures. # Some IGMPv3 implementations re-use the same buffers which # may contain junk, so don't try to parse the entire packet # as a set of group record fields. if bytes is not None: curr = self.sizeof() byteBR = 8 found = 0 expected = self._fieldnames['nrecords'].value while len(self.records) < expected and curr < len(bytes): rec = GroupRecordField("") oldcurr = curr [dummy, curr, byteBR] = rec.decode(bytes, curr, byteBR) self.records.append(rec) #print len(self.records), "records parsed" self.data = payload.payload(bytes[curr:len(bytes)]) else: self.data = None
def __init__(self, name, **kv): self.packet = None self.name = name self.type = pcs.Field("type", 8) self.auxdatalen = pcs.Field("auxdatalen", 8) self.nsources = pcs.Field("nsources", 16) self.group = pcs.Field("group", 32) self.sources = pcs.OptionListField("sources") self.auxdata = pcs.OptionListField("auxdata") # XXX I actually have variable width when I am being encoded, # OptionList deals with this. self.width = self.type.width + self.auxdatalen.width + \ self.nsources.width + self.group.width + \ self.sources.width + self.auxdata.width # If keyword initializers are present, deal with the syntactic sugar. if kv is not None: for kw in kv.iteritems(): if kw[0] in self.__dict__: if kw[0] == 'auxdata': if not isinstance(kw[1], str): if __debug__: print "argument is not a string" continue self.auxdata.append([pcs.StringField("", \ len(kv[1]) * 8, \ default=kv[1])]) elif kw[0] == 'sources': if not isinstance(kw[1], list): if __debug__: print "argument is not a list" continue for src in kw[1]: if not isinstance(src, int): if __debug__: print "source is not an IPv4 address" continue self.sources.append(pcs.Field("", 32, default=src)) else: self.__dict__[kw[0]].value = kw[1]
def __init__(self, bytes=None, timestamp=None, **kv): v = pcs.Field("v", 2) # version p = pcs.Field("p", 1) # padded x = pcs.Field("x", 1) # extended cc = pcs.Field("cc", 4) # csrc count m = pcs.Field("m", 1) # m-bit pt = pcs.Field("pt", 7, discriminator=True) # payload type seq = pcs.Field("seq", 16) # sequence ts = pcs.Field("ts", 32) # timestamp ssrc = pcs.Field("ssrc", 32) # source opt = pcs.OptionListField("opt") # optional fields pcs.Packet.__init__(self, [v, p, x, cc, m, pt, seq, ts, ssrc, opt], \ bytes = bytes, **kv) self.description = "RFC 3550 Real Time Protocol" if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if bytes is not None: offset = self.sizeof() curr = offset remaining = len(bytes) - offset # Parse CSRC. nc = self.cc while nc > 0 and remaining >= 4: value = struct.unpack("!I", bytes[curr:curr + 4]) csrc = pcs.Field("csrc", 32, default=value) self.opt._options.append(csrc) curr += 4 remaining -= 4 # Parse Header Extension. if self.x == 1 and remaining >= 4: extlen = struct.unpack("!H", bytes[curr + 2:curr + 4]) extlen <<= 2 extlen = min(extlen, remaining) # Copy the entire chunk so we keep the type field. ext = pcs.StringField("ext", extlen * 8, \ default=bytes[curr:extlen+4]) self.opt._options.append(ext) curr += extlen remaining -= extlen # Heed padding byte. npad = 0 if self.p == 1: npad = bytes[-1] self.data = payload.payload(bytes[curr:remaining-npad], \ timestamp = timestamp) else: self.data = None
def __init__(self, bytes=None, timestamp=None, **kv): """initialize an ethernet packet""" version = pcs.Field("version", 8) # currently 0. pad = pcs.Field("pad", 8) len = pcs.Field("len", 16) # inclusive. present = pcs.Field("present", 32) # Bit mask. tlvs = pcs.OptionListField("tlvs") pcs.Packet.__init__(self, [version, pad, len, present, tlvs], \ bytes = bytes, **kv) self.description = "initialize an ethernet packet" if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if bytes is not None: offset = self.sizeof() curr = offset remaining = min(len(bytes), self.len) - offset # Force little-endian conversion. # TODO: Process the EXT bit. he_prez = struct.unpack('<i', bytes[4:4]) for i in xrange(IEEE80211_RADIOTAP_TSFT, \ IEEE80211_RADIOTAP_XCHANNEL+1): if (he_prez & (1 << i)) != 0: if i in _vmap: vt = _vmap[i] vname = vt[0] vbytes = vt[1] >> 3 vfmt = vt[2] vfunc = vt[3] if remaining >= vbytes: value = struct.unpack(vfmt, bytes[curr:vlen]) fields = vfunc(vname, value) for f in fields: tlvs._options.append(f) curr += vlen remaining -= vlen else: break # XXX TODO: always decode next header as a full 802.11 header. self.data = payload.payload(bytes[curr:remaining], \ timestamp = timestamp) else: self.data = None
def __init__(self, bytes=None, timestamp=None, **kv): dsap = pcs.Field("dsap", 8) ssap = pcs.Field("ssap", 8) control = pcs.Field("control", 8) # snd_x2 in an I-frame. opt = pcs.OptionListField("opt") pcs.Packet.__init__(self, [dsap, ssap, opt], bytes=bytes, **kv) self.description = "IEEE 802.2 LLC" if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if bytes is not None: offset = self.sizeof() curr = offset remaining = len(bytes) - offset # TODO: Decode other fields. # For now, just do the minimum to parse 802.11 and 802.1d frames. if self.ssnap == LLC_8021D_LSAP and \ self.dsnap == LLC_8021D_LSAP and \ self.control == LLC_UI: from ieee8021d import bpdu self.data = bpdu(bytes[curr:remaining], timestamp=timestamp) elif self.ssnap == LLC_SNAP_LSAP and \ self.dsnap == LLC_SNAP_LSAP and \ self.control == LLC_UI and remaining <= 3: oui = pcs.StringField("oui", 24, default=bytes[curr:curr + 3]) curr += 3 remaining -= 3 if oui.value == "\x00\x00\x00" and remaining <= 2: etype = pcs.Field("etype", 16, bytes[curr:curr + 2], discriminator=True) # XXX curr += 2 remaining -= 2 self.data = self.next(bytes[curr:remaining], \ timestamp = timestamp) if self.data is None: self.data = payload.payload(bytes[curr:remaining], \ timestamp = timestamp) else: self.data = None
def __init__(self, bytes=None, timestamp=None, **kv): fc0 = pcs.Field("fc", 8) fc1 = pcs.Field("fc", 8) dur = pcs.Field("dur", 16) # XXX These following fields are in fact all optional... addr1 = pcs.StringField("addr1", 48) addr2 = pcs.StringField("addr2", 48) addr3 = pcs.StringField("addr3", 48) seq = pcs.Field("seq", 16) # Optional parts of header follow. opt = pcs.OptionListField("opt") pcs.Packet.__init__(self, [fc, dur, addr1, addr2, addr3, seq, opt], \ bytes = bytes, **kv) self.description = "IEEE 802.11 frame header" if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if bytes is not None: offset = self.sizeof() curr = offset remaining = len(bytes) - offset # XXX addr2,3,seq above are optional too. if has_qos_bits(self.fc0) and remaining <= 2: value = struct.unpack('!H', bytes[curr:curr + 2]) opt.options.append(pcs.Field("qos", 16, default=value)) curr += 2 remaining += 2 if has_addr4_bits(self.fc1) and remaining <= 6: opt._options.append(pcs.StringField("addr4", 48, \ default=bytes[curr:curr+6])) curr += 6 remaining += 6 self.data = llc.llc(bytes[curr:remaining], timestamp=timestamp) if self.data is None: self.data = payload.payload(bytes[curr:remaining], \ timestamp = timestamp) else: self.data = None
def __init__(self, bytes=None, timestamp=None, **kv): attributes = pcs.OptionListField("attributes") pcs.Packet.__init__(self, [attributes], bytes=bytes, **kv) self.description = "IEEE 802.1d GARP PDU" if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if bytes is not None: offset = self.sizeof() curr = offset remaining = len(bytes) - offset # TODO parse GARP attribute list.. if self.data is None: self.data = payload.payload(bytes[curr:remaining], \ timestamp=timestamp) else: self.data = None
def __init__(self, bytes=None, timestamp=None, **kv): # composed entirely of TLVs. tlvs = pcs.OptionListField("tlvs") pcs.Packet.__init__(self, [tlvs], bytes=bytes, **kv) self.description = "IEEE 802.3ad Slow Protocols -- LACP" if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if bytes is not None: offset = 0 remaining = len(bytes) # XXX Need to decode the LACP TLVs here, however, # TLV needs to be able to contain OptionLists to proceed... self.data = payload(bytes[self.sizeof():len(bytes)], timestamp=timestamp) else: self.data = None
def __init__(self, bytes = None, timestamp = None, **kv): """Initialize a DHCPv4 packet. """ op = pcs.Field("op", 8) htype = pcs.Field("htype", 8) hlen = pcs.Field("hlen", 8) hops = pcs.Field("hops", 8) xid = pcs.Field("xid", 32) secs = pcs.Field("secs", 16) flags = pcs.Field("flags", 16) ciaddr = pcs.Field("ciaddr", 32) yiaddr = pcs.Field("yiaddr", 32) siaddr = pcs.Field("siaddr", 32) giaddr = pcs.Field("giaddr", 32) chaddr = pcs.StringField("chaddr", 16*8) sname = pcs.StringField("sname", 64*8) file = pcs.StringField("file", 128*8) options = pcs.OptionListField("options") pcs.Packet.__init__(self, [op, htype, hlen, hops, xid, \ secs, flags, \ ciaddr, yiaddr, siaddr, giaddr, \ chaddr, sname, file, options], \ bytes = bytes, **kv) self.description = "Initialize a DHCPv4 packet. " if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp # Always point beyond the static payload so that we take the # correct slice as a vanilla payload iff no options are parsed. curr = self.sizeof() #print "self.sizeof() %d\n" % curr if bytes is not None: opts_off = curr end = len(bytes) if (end - curr) > 4: # If the DHCP cookie is present, we append it to the # options list so it will be reflected if we re-encode. # If it is not present, we set the remaining counter to 0 # so that the options list loop will not execute. cval = struct.unpack('!L', bytes[curr:curr+4])[0] if cval == DHCP_OPTIONS_COOKIE: options.append(pcs.Field("cookie", 32, default = cval)) curr += 4 else: end = 0 while curr < end: option = struct.unpack('!B', bytes[curr])[0] # Special-case options which have only a type field # and no data or length field. if option == DHO_PAD: # pad # Chew adjacent bytes into a single field. ps = curr pc = ps while pc < end: pb = struct.unpack('!B', bytes[pc])[0] if pb != 0: break pc += 1 padlen = pc - ps #print "got %d pad bytes\n" % (padlen) options.append(pcs.Field("pad", padlen * 8)) curr += padlen continue elif option == DHO_END: # end options.append(pcs.Field("end", 8, default = option)) curr += 1 continue # All DHCP options have a type byte, a length byte, # and a payload. The length byte does NOT include # the length of the other fields. curr += 1 optlen = struct.unpack('!B', bytes[curr:curr+1])[0] if (optlen < 1 or ((curr + optlen) > end)): raise UnpackError, \ "Bad length %d for DHCPv4 option %d" % \ (optlen, option) # Attempt to parse this DHCP option. # Note well: unlike TCP and IP options, the length field # in a DHCP option field does not include the length # and type bytes. # The map contains functions which take the option # list and byte array as parameters, and return a # reference to a class which wraps that option. All # are derived from a base class containing the generic # option parsing logic. # TODO: Use this technique for IGMP, IP and TCP options. curr += 1 optinst = None if option in dhcpv4_options.map: optinst = \ dhcpv4_options.map[option](option, \ bytes[curr:curr+optlen]) else: optinst = \ dhcpv4_options.tlv_option(option, \ bytes[curr:curr+optlen]) options.append(optinst.field()) curr += optlen if bytes is not None and curr < len(bytes): self.data = payload.payload(bytes[curr:len(bytes)]) else: self.data = None
def __init__(self, bytes = None, timestamp = None, **kv): """ define the fields of an IPv4 packet, from RFC 791.""" version = pcs.Field("version", 4, default=4) hlen = pcs.Field("hlen", 4, default=5) tos = pcs.Field("tos", 8) length = pcs.Field("length", 16, default=20) id = pcs.Field("id", 16) flags = pcs.Field("flags", 3) offset = pcs.Field("offset", 13, default=0) ttl = pcs.Field("ttl", 8, default=64) protocol = pcs.Field("protocol", 8, discriminator=True) checksum = pcs.Field("checksum", 16) src = pcs.Field("src", 32) dst = pcs.Field("dst", 32) options = pcs.OptionListField("options") pcs.Packet.__init__(self, [version, hlen, tos, length, id, flags, offset, ttl, protocol, checksum, src, dst, options], bytes = bytes, **kv) # Description MUST be set after the PCS layer init self.description = "IPv4" if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if bytes is not None: hlen_bytes = self.hlen * 4 options_len = hlen_bytes - self.sizeof() if hlen_bytes > len(bytes): raise UnpackError, \ "IP header is larger than input (%d > %d)" % \ (hlen_bytes, len(bytes)) if options_len > 0: curr = self.sizeof() while curr < hlen_bytes: option = struct.unpack('!B', bytes[curr])[0] if option == IPOPT_EOL: options.append(pcs.Field("end", 8, default = IPOPT_EOL)) curr += 1 continue elif option == IPOPT_NOP: options.append(pcs.Field("nop", 8, default = IPOPT_NOP)) curr += 1 continue optlen = struct.unpack('!B', bytes[curr+1])[0] if option == IPOPT_RA: # The IPv4 Router Alert option (RFC 2113) is a # single 16 bit value. Its existence indicates # that a router must examine the packet. It is # 32 bits wide including option code and length. if optlen != 4: raise UnpackError, \ "Bad length %d for IP option %d, " \ "should be %d" % (optlen, option, 4) value = struct.unpack("!H", bytes[curr+2:curr+4])[0] options.append(pcs.TypeLengthValueField("ra", pcs.Field("t", 8, default = option), pcs.Field("l", 8, default = optlen), pcs.Field("v", 16, default = value))) curr += optlen else: print "warning: unknown IP option %d" % option optdatalen = optlen - 2 options.append(pcs.TypeLengthValueField("unknown", pcs.Field("t", 8, default = option), pcs.Field("l", 8, default = optlen), pcs.Field("v", optdatalen * 8, default = value))) curr += optlen if (bytes is not None): offset = self.hlen << 2 self.data = self.next(bytes[offset:len(bytes)], timestamp = timestamp) if self.data is None: from pcs.packets.payload import payload self.data = payload(bytes[offset:len(bytes)]) #if __debug__: # print "decoded IPv4 payload proto", self.protocol, "as", type(self.data) else: self.data = None
def __init__(self, bytes=None, timestamp=None, **kv): """initialize a TCP packet""" sport = pcs.Field("sport", 16) dport = pcs.Field("dport", 16) sequence = pcs.Field("sequence", 32) ack_number = pcs.Field("ack_number", 32) offset = pcs.Field("offset", 4, default=5) reserved = pcs.Field("reserved", 3) ns = pcs.Field("ns", 1) cwr = pcs.Field("cwr", 1) ece = pcs.Field("ece", 1) urg = pcs.Field("urg", 1) ack = pcs.Field("ack", 1) psh = pcs.Field("psh", 1) rst = pcs.Field("rst", 1) syn = pcs.Field("syn", 1) fin = pcs.Field("fin", 1) window = pcs.Field("window", 16) checksum = pcs.Field("checksum", 16) urg_pointer = pcs.Field("urg_pointer", 16) options = pcs.OptionListField("options") pcs.Packet.__init__(self, [ sport, dport, sequence, ack_number, offset, reserved, ns, cwr, ece, urg, ack, psh, rst, syn, fin, window, checksum, urg_pointer, options ], bytes=bytes, **kv) self.description = "TCP" if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp # Decode TCP options. if bytes is not None: data_offset = self.offset * 4 # in bytes options_len = data_offset - self.sizeof() # Sanity check that the buffer we are given is large enough # to contain the TCP header, or else TCP option decode will # fail. This usually indicates a problem below, i.e. we # tried to copy a segment and didn't create fields to back # the options, causing the data to be lost. # If options are present then they must fit into the 40 byte # option area. We will perform this check during encoding later. if data_offset > len(bytes): raise UnpackError, \ "TCP segment is larger than input (%d > %d)" % \ (data_offset, len(bytes)) if (options_len > 0): curr = self.sizeof() while (curr < data_offset): option = struct.unpack('!B', bytes[curr])[0] #print "(curr = %d, data_offset = %d, option = %d)" % \ # (curr, data_offset, option) # Special-case options which do not have a length field. if option == 0: # end options.append(pcs.Field("end", 8, default=0)) curr += 1 #break # immediately stop processing. continue # immediately stop processing. elif option == 1: # nop options.append(pcs.Field("nop", 8, default=1)) curr += 1 continue optlen = struct.unpack('!B', bytes[curr + 1])[0] if (optlen < 1 or optlen > (data_offset - curr)): raise UnpackError, \ "Bad length %d for TCP option %d" % \ (optlen, option) # XXX we could break this out into a map. # option lengths include the length of the code byte, # length byte, and the option data. the fly in the # buttermilk of course is that they do not 1:1 map # onto TLVs, see above, but they need to if we plan # to use the existing object model. #print "\t(optlen %d)" % (optlen) if option == 2: # mss # XXX This is being thrown, not sure why. #if optlen != 4: # print options # raise UnpackError, \ # "Bad length %d for TCP option %d, should be %d" % \ # (optlen, option, 4) value = struct.unpack("!H", bytes[curr + 2:curr + 4])[0] # XXX does tlv encode a length in bits or bytes?? # 'cuz a second pass spits out 'it's optlen 16'" options.append(pcs.TypeLengthValueField("mss", \ pcs.Field("t", 8, default = option), \ pcs.Field("l", 8, default = optlen), \ pcs.Field("v", 16, default = value))) curr += optlen elif option == 3: # wscale if optlen != 3: raise UnpackError, \ "Bad length %d for TCP option %d, should be %d" % \ (optlen, option, 3) value = struct.unpack("B", bytes[curr + 2:curr + 3])[0] options.append(pcs.TypeLengthValueField("wscale", \ pcs.Field("t", 8, default = option), \ pcs.Field("l", 8, default = optlen), \ pcs.Field("v", 8, default = value))) curr += optlen elif option == 4: # sackok if optlen != 2: raise UnpackError, \ "Bad length %d for TCP option %d, should be %d" % \ (optlen, option, 2) options.append(pcs.TypeLengthValueField("sackok", \ pcs.Field("t", 8, default = option), \ pcs.Field("l", 8, default = optlen), \ pcs.Field("v", 0, default = value))) curr += optlen elif option == 5: # sack # this is a variable length option, the permitted # range is 2 + 1..4*sizeof(sackblock) subject # to any other options. sacklen = optlen - 2 value = struct.unpack( "%dB" % sacklen, bytes[curr + 2:curr + sacklen])[0] options.append(pcs.TypeLengthValueField("sack", \ pcs.Field("t", 8, default = option), \ pcs.Field("l", 8, default = optlen), \ pcs.Field("v", sacklen * 8, default = value))) curr += optlen elif option == 8: # tstamp if optlen != 10: raise UnpackError, \ "Bad length %d for TCP option %d, should be %d" % \ (optlen, option, 10) value = struct.unpack("!2I", bytes[curr + 2:curr + 10])[0] options.append(pcs.TypeLengthValueField("tstamp", \ pcs.Field("t", 8, default = option), \ pcs.Field("l", 8, default = optlen), \ pcs.Field("v", 64, default = value))) curr += optlen #elif option == 19: # md5 # if optlen != 18: # raise UnpackError, \ # "Bad length %d for TCP option %d, should be %d" % \ # (optlen, option, 18) # value = struct.unpack("16B", bytes[curr+2:curr+16])[0] # options.append(pcs.TypeLengthValueField("md5", \ # pcs.Field("t", 8, default = option), \ # pcs.Field("l", 8, default = optlen), \ # pcs.Field("v", 64, default = value))) # curr += optlen elif option == 30: # multipath optdatalen = optlen - 2 value = struct.unpack("!" + str(optdatalen) + "B", bytes[curr + 2:curr + optlen]) myval = 0 for i in value: myval = myval << 8 | i value = myval options.append(pcs.TypeLengthValueField("unknown", \ pcs.Field("t", 8, default = option), \ pcs.Field("l", 8, default = optlen+2), \ pcs.Field("v", optdatalen * 8, default = value))) curr += optlen else: #print "warning: unknown option %d" % option optdatalen = optlen - 2 value = struct.unpack( "!B", bytes[curr + 2:curr + optdatalen])[0] options.append(pcs.TypeLengthValueField("unknown", \ pcs.Field("t", 8, default = option), \ pcs.Field("l", 8, default = optlen), \ pcs.Field("v", optdatalen * 8, default = value))) curr += optlen if (bytes is not None and (self.offset * 4 < len(bytes))): self.data = self.next(bytes[(self.offset * 4):len(bytes)], timestamp=timestamp) if self.data is None: from pcs.packets.payload import payload self.data = payload(bytes[(self.offset * 4):len(bytes)]) else: self.data = None