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): """common header initialization""" type = pcs.Field("type", 8, default=0) reserved = pcs.Field("reserved", 5) unordered = pcs.Field("unordered", 1) beginning = pcs.Field("beginning", 1) ending = pcs.Field("ending", 1) length = pcs.Field("length", 16) tsn = pcs.Field("tsn", 32) stream_id = pcs.Field("stream_id", 16) stream_seq = pcs.Field("stream_seq", 16) ppi = pcs.Field("ppi", 32) pcs.Packet.__init__(self, [ type, reserved, unordered, beginning, ending, length, tsn, stream_im, stream_seq, ppi ], bytes=bytes, **kv) self.description = "SCTP payload chunk class" if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if (bytes is not None): self.data = self.next(bytes[0:len(bytes)], timestamp=timestamp) else: self.data = None
def __init__(self, bytes=None, timestamp=None, **kv): family = pcs.Field("family", 8) prefixlen = pcs.Field("pad00", 8) flags = pcs.Field("flags", 8) scope = pcs.Field("scope", 8) index = pcs.Field("index", 32) #tlvs = pcs.OptionListField("tlvs") pcs.Packet.__init__(self, [family, prefixlen, flags, scope, index],\ bytes = bytes, **kv) self.description = "RFC 3549 interface address message." if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if bytes is not None: offset = self.sizeof() remaining = len(bytes) - offset # TODO demux TLVs. if self.data is None: self.data = payload.payload(bytes[offset:remaining], \ timestamp=timestamp) 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, bytes=None): """IPv6 routing extension header from RFC 2460""" next = pcs.Field("next_header", 8) len = pcs.Field("length", 8) type = pcs.Field("type", 8) segments_left = pcs.Field("segments_left", 8) pcs.Packet.__init__(self, [next, len, type, segments_left], bytes)
def __init__(self, bytes=None, timestamp=None, **kv): """Followup Header """ preciseOriginTimestampSeconds = pcs.Field( "preciseOriginTimestampSeconds", 48) preciseOriginTimestampNanoSeconds = pcs.Field( "preciseOriginTimestampNanoSeconds", 32) pcs.Packet.__init__( self, [preciseOriginTimestampSeconds, preciseOriginTimestampNanoSeconds], bytes=bytes, **kv) self.description = "Followup" if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if (bytes is not None): self.data = self.next(bytes[self.sizeof():len(bytes)], 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, bytes = None, timestamp = None, **kv): """initialize the common header """ versionPTP = pcs.Field("versionPTP", 16) versionNetwork = pcs.Field("versionNetwork", 16) subdomain = pcs.StringField("subdomain", PTP_SUBDOMAIN_NAME_LENGTH * 8) messageType = pcs.Field("messageType", 8) sourceCommunicationTechnology = pcs.Field("sourceCommunicationTechnology", 8) sourceUuid = pcs.StringField("sourceUuid", PTP_UUID_LENGTH * 8) sourcePortId = pcs.Field("sourcePortId", 16) sequenceId = pcs.Field("sequenceId", 16) control = pcs.Field("control", 8, discriminator = True) zero1 = pcs.Field("zero1", 8, default = 0) flags = pcs.Field("flags", 16) zero2 = pcs.Field("zero2", 32, default = 0) pcs.Packet.__init__(self, [versionPTP, versionNetwork, subdomain, messageType, sourceCommunicationTechnology, sourceUuid, sourcePortId, sequenceId, control, zero1, flags, zero2], bytes = bytes, **kv) self.description = "initialize the common header " if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if (bytes is not None): self.data = self.next(bytes[self.sizeof():len(bytes)], timestamp = timestamp) else: self.data = None
def __init__(self, bytes=None, timestamp=None, **kv): """ Define the common IGMP encapsulation; see RFC 2236. """ type = pcs.Field("type", 8, discriminator=True) code = pcs.Field("code", 8) checksum = pcs.Field("checksum", 16) pcs.Packet.__init__(self, [type, code, checksum], bytes=bytes, **kv) self.description = "IGMP" if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if bytes is not None: offset = self.sizeof() if self.type == IGMP_HOST_MEMBERSHIP_QUERY and \ len(bytes) >= igmpv3.IGMP_V3_QUERY_MINLEN: self.data = igmpv3.query(bytes[offset:len(bytes)], timestamp=timestamp) else: # XXX Workaround Packet.next() -- it only returns something # if it can discriminate. self.data = self.next(bytes[offset:len(bytes)], timestamp=timestamp) if self.data is None: self.data = payload.payload(bytes[offset:len(bytes)]) else: self.data = None
def test_tcp_with_options(self): """Assert that a TCP with options is correctly encoded.""" packet = tcp() nop = pcs.Field("nop", 8) mss = pcs.TypeLengthValueField("mss", pcs.Field("t", 8, default=0x02), pcs.Field("l", 8), pcs.Field("v", 16)) end = pcs.Field("end", 8) nop.value = 1 mss.value.value = 1460 # Most common Internet MSS value. # Build a TCP option list which will be 32-bits aligned. packet.options.append(nop) packet.options.append(nop) packet.options.append(mss) packet.options.append(nop) packet.options.append(end) expected = "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x01\x01\x02\x04" \ "\x05\xb4\x01\x00" got = packet.bytes #packet.encode() #hd = hexdumper() #print hd.dump(expected) #print hd.dump(got) # XXX: Note well: just because you added an option list, # doesn't mean the TCP option length is correct. self.assertEqual(expected, got)
def __init__(self, bytes=None): """initialize a DNS query packet, which is a query for information""" type = pcs.Field("type", 16) qclass = pcs.Field("query_class", 16) pcs.Packet.__init__(self, [type, qclass], bytes=bytes) self.description = "DNS Query"
def __init__(self, bytes=None, timestamp=None, **kv): """Followup Header """ zero1 = pcs.Field("zero1", 16, default=0) associatedSequenceId = pcs.Field("associatedSequenceId", 16) preciseTimestampSeconds = pcs.Field("preciseTimestampSeconds", 32) preciseTimestampNanoseconds = pcs.Field("preciseTimestampNanoseconds", 32) pcs.Packet.__init__(self, [ zero1, associatedSequenceId, preciseTimestampSeconds, preciseTimestampNanoseconds ], bytes=bytes, **kv) self.description = "Followup Header " if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if (bytes is not None): self.data = self.next(bytes[self.sizeof():len(bytes)], timestamp=timestamp) else: self.data = None
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 test_copy_lengthvaluefield(self): """Test shallow copy of LengthValueField. It contains two other Fields, so a shallow copy should copy only those members.""" addr1 = inet_atol("192.0.2.1") lf1 = pcs.Field("", 8) vf1 = pcs.Field("", 32) lvf1 = LengthValueField("lvf1", lf1, vf1) self.assert_(isinstance(lvf1, pcs.LengthValueField)) self.assert_(isinstance(lvf1.length, pcs.Field)) self.assert_(isinstance(lvf1.value, pcs.Field)) self.assert_(id(lf1) == id(lvf1.length)) self.assert_(id(vf1) == id(lvf1.value)) vf1.value = addr1 self.assertEqual(lvf1.value.value, addr1, \ "lvf1's value-field value not set by assignment!") lvf2 = copy(lvf1) self.assertEqual(lvf2.packet, None, "lvf2.packet is not None!") self.assert_(isinstance(lvf2, pcs.LengthValueField)) self.assert_(isinstance(lvf2.length, pcs.Field)) self.assert_(isinstance(lvf2.value, pcs.Field)) # Must be a shallow copy self.assert_(id(lf1) == id(lvf2.length)) self.assert_(id(vf1) == id(lvf2.value)) self.assertEqual(lvf2.name, "lvf1", "lvf2's name not set by copy()!") # Paranoia self.assertEqual(lvf2.value.value, inet_atol("192.0.2.1"), \ "lvf2's value-field value differs!")
def __init__(self, bytes=None, timestamp=None, **kv): """ Define the common rtmsg header; see <net/route.h>. """ msglen = pcs.Field("msglen", 16) version = pcs.Field("version", 8, default=RTM_VERSION) type = pcs.Field("type", 8, discriminator=True) # XXX There's implicit padding all over the shop here. pad0 = pcs.Field("type", 16) pcs.Packet.__init__(self, [msglen, version, type, pad0], \ bytes = bytes, **kv) self.description = " Define the common rtmsg header; see <net/route.h>. " if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if bytes is not None: # XXX Workaround Packet.next() -- it only returns something # if it can discriminate. # XXX Should try rtmsg next, next. offset = self.sizeof() self.data = self.next(bytes[offset:len(bytes)], timestamp=timestamp) if self.data is None: self.data = payload.payload(bytes[offset:len(bytes)]) else: self.data = None
def __init__(self, bytes=None): """Initialize a UDP packet for IPv6""" sport = pcs.Field("sport", 16) dport = pcs.Field("dport", 16) length = pcs.Field("length", 16) checksum = pcs.Field("checksum", 16) pcs.Packet.__init__(self, [sport, dport, length, checksum], bytes)
def test_copy_typevaluefield(self): """Test shallow copy of TypeValueField.""" addr1 = inet_atol("192.0.2.1") tf1 = pcs.Field("", 8) vf1 = pcs.Field("", 32) tvf1 = TypeValueField("tvf1", tf1, vf1) self.assert_(isinstance(tvf1, pcs.TypeValueField)) self.assert_(isinstance(tvf1.type, pcs.Field)) self.assert_(isinstance(tvf1.value, pcs.Field)) self.assert_(id(tf1) == id(tvf1.type)) self.assert_(id(vf1) == id(tvf1.value)) tvf1.value.value = addr1 self.assertEqual(tvf1.value.value, addr1, \ "tvf1's value-field value not set by assignment!") tvf2 = copy(tvf1) self.assert_(id(tvf1) != id(tvf2)) self.assertEqual(tvf2.packet, None, "tvf2.packet is not None!") self.assert_(isinstance(tvf2, pcs.TypeValueField)) self.assert_(isinstance(tvf2.type, pcs.Field)) self.assert_(isinstance(tvf2.value, pcs.Field)) # Must be a shallow copy self.assert_(id(tf1) == id(tvf2.type)) self.assert_(id(vf1) == id(tvf2.value)) self.assertEqual(tvf2.name, "tvf1", \ "tvf2's name not set by copy()!") # Paranoia self.assertEqual(tvf2.value.value, inet_atol("192.0.2.1"), \ "tvf2's value-field value differs!")
def __init__(self, bytes=None, timestamp=None, **kv): """Delay Response""" receiveTimestampSeconds = pcs.Field("receiveTimestampSeconds", 48) receiveTimestampNanoSeconds = pcs.Field("receiveTimestampNanoSeconds", 32) requestingPortIdentity = pcs.Field("requestingPortIdentity", 80) pcs.Packet.__init__(self, [ receiveTimestampSeconds, receiveTimestampNanoSeconds, requestingPortIdentity ], bytes=bytes, **kv) self.description = "Delay Response " if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if (bytes is not None): self.data = self.next(bytes[self.sizeof():len(bytes)], timestamp=timestamp) else: self.data = None
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): """IPv6 destination options extension header from RFC 2460""" global op op = 0 next = pcs.Field("next_header", 8) len = pcs.Field("length", 8) type = pcs.Field("type", 8) pcs.Packet.__init__(self, [next, len, type], bytes)
def __init__(self, bytes=None, timestamp=None): """IPv6 pseudo header from RFC 2460""" src = pcs.StringField("src", 16 * 8) dst = pcs.StringField("dst", 16 * 8) length = pcs.Field("length", 32) zero = pcs.Field("zero", 24) nh = pcs.Field("next_header", 8) pcs.Packet.__init__(self, [src, dst, length, zero, nh], bytes)
def test_deepcopy_typelengthvaluefield(self): """Test deep copy of TypeLengthValueField. It contains three other Fields, so a deep copy should copy everything.""" addr1 = inet_atol("192.0.2.1") tf1 = pcs.Field("", 8) lf1 = pcs.Field("", 8) vf1 = pcs.Field("", 32) tlvf1 = TypeLengthValueField("tlvf1", tf1, lf1, vf1) self.assert_(isinstance(tlvf1, pcs.TypeLengthValueField)) self.assert_(isinstance(tlvf1.type, pcs.Field)) self.assert_(isinstance(tlvf1.length, pcs.Field)) self.assert_(isinstance(tlvf1.value, pcs.Field)) self.assert_(id(tf1) == id(tlvf1.type)) self.assert_(id(lf1) == id(tlvf1.length)) self.assert_(id(vf1) == id(tlvf1.value)) tlvf1.value.value = addr1 self.assertEqual(tlvf1.value.value, addr1, \ "tlvf1's value-field value not set by assignment!") addr2 = ether_atob("01:02:03:04:05:06") tlvf2 = deepcopy(tlvf1) self.assert_(id(tlvf1) != id(tlvf2)) self.assertEqual(tlvf2.packet, None, "tlvf2.packet is not None!") self.assert_(isinstance(tlvf2, pcs.TypeLengthValueField)) self.assert_(isinstance(tlvf2.type, pcs.Field)) self.assert_(isinstance(tlvf2.length, pcs.Field)) self.assert_(isinstance(tlvf2.value, pcs.Field)) # Must be a deep copy self.assert_(id(tf1) != id(tlvf2.type)) self.assert_(id(lf1) != id(tlvf2.length)) self.assert_(id(vf1) != id(tlvf2.value)) self.assertEqual(tlvf2.name, "tlvf1", \ "tlvf2's name not set by deepcopy()!") # Paranoia self.assertEqual(tlvf2.value.value, inet_atol("192.0.2.1"), \ "tlvf2's value-field value differs after deepcopy!") tlvf1.value.value = inet_atol("192.0.2.2") self.assertEqual(tlvf2.value.value, inet_atol("192.0.2.1"), \ "tlvf2's value-field value was changed by assignment to tvf1!") tlvf2.type.value = 123 self.assertNotEqual( tlvf1.type.value, tlvf2.type.value, "tlvf2's type-field value does not differ after assignment!") tlvf2.length.value = len(addr2) self.assertNotEqual( tlvf1.length.value, tlvf2.length.value, "tlvf2's length-field value does not differ after assignment!") tlvf2.value.value = addr2 self.assertNotEqual( tlvf1.type.value, tlvf2.type.value, "tvf2's type-field value does not differ after assignment!")
def _channel(n, x): """Given a tuple returned by struct.unpack(), produce a list of decoded fields for a CHANNEL TLV.""" assert isinstance(n, str) assert isinstance(x, tuple) ret = [] ret += pcs.Field("chan_mhz", 8, default=x[0]) ret += pcs.Field("chan_flags", 8, default=x[1]) return ret
def __init__(self, bytes=None, timestamp=None, **kv): """initialize a Neighbor Solicitaion header""" reserved = pcs.Field("reserved", 32) target = pcs.Field("target", 128) pcs.Packet.__init__(self, [reserved, target], bytes, **kv) self.description = "initialize a Neighbor Solicitaion header" if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp
def field(self): """ Return the complete field value as it should be appended to the DHCPv4 options payload. """ return pcs.TypeLengthValueField( \ self.fieldname(), \ pcs.Field("t", 8, default = self.optno), \ pcs.Field("l", 8, default = len(self.bytes)), \ self.datafield(), \ inclusive = False, \ bytewise = True)
def __init__(self, bytes=None, timestamp=None, **kv): version = pcs.Field("version", 8) type = pcs.Field("type", 8) flags = pcs.Field("flags", 8) root = pcs.StringField("root", 8 * 8) cost = pcs.Field("cost", 32) src = pcs.StringField("src", 8 * 8) pid = pcs.Field("pid", 16) age = pcs.Field("age", 16) maxage = pcs.Field("maxage", 16) interval = pcs.Field("interval", 16) delay = pcs.Field("delay", 16) #opt = pcs.OptionListField("opt") pcs.Packet.__init__(self, [ version, type, flags, root, \ cost, src, pid, age, maxage, interval, \ delay ], bytes = bytes, **kv) self.description = "IEEE 802.1d STP 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 # 802.1d shouldn't have any trailers. self.data = payload.payload(bytes[curr:remaining], \ timestamp = timestamp) else: self.data = None
def __init__(self, bytes=None, timestamp=None, **kv): """ Define the common RTNetlink message header.""" family = pcs.Field("family", 8) dst_len = pcs.Field("dst_len", 8) src_len = pcs.Field("src_len", 8) tos = pcs.Field("tos", 8) table = pcs.Field("table", 8) protocol = pcs.Field("protocol", 8) scope = pcs.Field("scope", 8) type = pcs.Field("type", 8) flags = pcs.Field("flags", 32) #tlvs = pcs.OptionListField("tlvs") pcs.Packet.__init__(self, [family, dst_len, src_len, tos, table, \ protocol, scope, type, flags], \ bytes = bytes, **kv) self.description = " Define the common RTNetlink message header." if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if bytes is not None: offset = self.sizeof() remaining = len(bytes) - offset # TODO demux TLVs. if self.data is None: self.data = payload.payload(bytes[offset:remaining], \ timestamp=timestamp) else: self.data = None
def __init__(self, bytes = None, timestamp = None, **kv): originTimestampSeconds = pcs.Field("originTimestampSeconds", 48) originTimestampNanoSeconds = pcs.Field("originTimestampNanoSeconds", 32) currentUTCOffset = pcs.Field("currentUTCOffset", 16) reserved0 = pcs.Field("reserved0", 8, default = 0) grandmasterPriority1 = pcs.Field("grandmasterPriority1", 8) grandmasterClockQuality = pcs.Field("grandmasterClockQuality", 32) grandmasterPriority2 = pcs.Field("grandmasterPriority2", 8) grandmasterClockIdentity = pcs.StringField("grandmasterClockIdentity", 8) stepsRemoved = pcs.Field("stepsRemoved", 16) timeSource = pcs.Field("timeSource", 8) pcs.Packet.__init__(self, [originTimestampSeconds, originTimestampNanoSeconds, currentUTCOffset, reserved0, grandmasterPriority1, grandmasterClockQuality, grandmasterPriority2, grandmasterClockIdentity, stepsRemoved, timeSource], bytes = bytes, **kv) self.description = "PTP Announce" if timestamp is None: self.timestamp = time.time() else: self.timestamp = timestamp if (bytes is not None): self.data = self.next(bytes[self.sizeof():len(bytes)], timestamp = timestamp) else: self.data = None
def option(self, len=0): """add option header to the destination extension header""" # XXX: pad0 option has not this header. global op op += 1 otype = pcs.Field("otype" + str(op), 8) olen = pcs.Field("olength" + str(op), 8, default=len / 8) if len != 0: odata = pcs.Field("odata" + str(op), len) pcs.Packet.__add__(self, [otype, olen, odata]) else: pcs.Packet.__add__(self, [otype, olen])
def __init__(self, bytes=None): """initialize a DNS resource record, which encodes data returned from a query""" name = pcs.LengthValueField("name", 8) type = pcs.Field("type", 16) qclass = pcs.Field("query_class", 16) ttl = pcs.Field("ttl", 16) rdata = pcs.LengthValueField("rdata", 16) pcs.Packet.__init__(self, [name, type, qclass, ttl, rdata], bytes=bytes) self.description = "DNS Resource Record"