示例#1
0
    def __init__(self, bytes=None, timestamp=None, **kv):
        # XXX: TLV fields can't contain multiple values yet, so we
        # kludge by making the first TLV fields exposed here.
        it = pcs.Field("info_type", 8)
        il = pcs.Field("info_len", 8)
        port = pcs.Field("port", 16)
        system = pcs.StringField("system", 6 * 8)
        xid = pcs.Field("xid", 32)
        pad = pcs.Field("pad", 16)
        tt = pcs.Field("term_type", 8)
        tl = pcs.Field("term_len", 8)
        resv = pcs.StringField("resv", 90 * 8)

        pcs.Packet.__init__(self, [ it, il, port, system, xid, pad, \
                                    tt, tl, resv ], bytes = bytes, **kv)
        self.description = "IEEE 802.3ad Slow Protocols -- Marker"

        if timestamp is None:
            self.timestamp = time.time()
        else:
            self.timestamp = timestamp

        if bytes is not None:
            self.data = payload(bytes[self.sizeof():len(bytes)],
                                timestamp=timestamp)
        else:
            self.data = None
示例#2
0
    def __init__(self, bytes = None, timestamp = None, **kv):
        # XXX: TLV fields can't contain multiple values yet, so we
        # kludge by making the first TLV fields exposed here.
        it = pcs.Field("info_type", 8)
        il = pcs.Field("info_len", 8)
        port = pcs.Field("port", 16)
        system = pcs.StringField("system", 6*8)
        xid = pcs.Field("xid", 32)
        pad = pcs.Field("pad", 16)
        tt = pcs.Field("term_type", 8)
        tl = pcs.Field("term_len", 8)
        resv = pcs.StringField("resv", 90 * 8)

        pcs.Packet.__init__(self, [ it, il, port, system, xid, pad, \
                                    tt, tl, resv ], bytes = bytes, **kv)
        self.description = "IEEE 802.3ad Slow Protocols -- Marker"

        if timestamp is None:
            self.timestamp = time.time()
        else:
            self.timestamp = timestamp

        if bytes is not None:
            self.data = payload(bytes[self.sizeof():len(bytes)],
                                timestamp = timestamp)
        else:
            self.data = None
def ICMPv6_pack_message(iface, pkt_type):
	
	#procedure to get iface address
	#iface = 'wlan2' #interface
	addrs = netifaces.ifaddresses(iface)
	ll_src_addr = addrs[netifaces.AF_INET6][1]['addr']
	ll_src_addr = ll_src_addr[:ll_src_addr.find('%')]
	
	gl_src_addr = addrs[netifaces.AF_INET6][0]['addr']
	#gl_src_addr = gl_src_addr[:gl_src_addr.find('%')]
	
	#print gl_src_addr
	#print ll_src_addr
	# building ethernet header
	e = ethernet()
	mac = netifaces.ifaddresses(iface)[netifaces.AF_LINK][0]['addr'] #geting mac addr
	e.src = ether_atob(mac)
	e.dst = ether_atob('ff:ff:ff:ff:ff:ff')
	e.type = 0x86dd #ETHERTYPE_IPV6
	
	#building ipv6 packet basic info
	ip6 = ipv6()
	ip6.version = 6
	#cs = icmp6.cksum(ip6) & 0xffff
	# building ipv6 header
	ip6.traffic_class = 0x0a
	ip6.flow = 0
	ip6.length = 50
	ip6.next_header = 58#IPPROTO_ICMPV6
	ip6.hop = 255
	ip6.src = pcs.inet_pton(AF_INET6, ll_src_addr)
	ip6.dst = pcs.inet_pton(AF_INET6, 'ff02::1')
	
	# building icmpv6
	icmp6 = icmpv6(ICMP6_ECHO_REQUEST) #ICMP6_ECHO_REPLY
	icmp6.code = 0
	icmp6.seq  = 0
	icmp6.id = 0x03e8
	icmp6.checksum = 0x0 #kt.calc_checksums()
	
	data = payload(payload = gl_src_addr) #message data
	ip6.length = len(icmp6.getbytes()) + len(data) #recalculation of packet length
	if(pkt_type == 0):
		icmp6.cheksum = 0xf220
		ip6.traffic_class = 0x0a
		pkt = pcs.Chain([e, ip6, icmp6, data]) #appendin packet
	else:
		icmp6.checksum = 0xe91b
		ip6.traffic_class = 0x0f
		pkt = pcs.Chain([e, ip6, icmp6]) #appendin packet
	#icmp6.checksum = pkt.calc_checksums()
	pkt.encode()
	#print pkt
	return pkt
示例#4
0
    def test20045executeTriggerStatusCodeNegative(self):
        self.type = 'reset'
        self.value = 1
        self.action = Trigger.Trigger.STOP
        self.payload = 'Bad Payload'

        # Negative Test
        self.tr = TcpTrigger.TcpTrigger(self.type, self.value, self.action)
        p = payload(self.payload)
        chain = None

        # IPv4
        pkt = self.createIpv4Pkt(0x06, p, None)
        try:
            chain = self.tr.executeTrigger(pkt)
        except Exception, e:
            self.assertEquals(
                e.errCode, Trigger.ERR_PCAPR_TRIGGER_INVALID,
                'Execute trigger failed: false trigger mishandled')
示例#5
0
    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
示例#6
0
    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
示例#7
0
    def test20025executeTriggerStatusCodeNegative(self):
        self.type = 'statusCode'
        self.value = '404'
        self.action = Trigger.Trigger.STOP
        self.payload = 'Bad Payload'

        # Negative Test
        self.tr = HttpTrigger.HttpTrigger(self.type, self.value, self.action)
        t = pcs.packets.tcp.tcp()
        t.sport = 23
        t.dport = 22
        t.offset = 5
        p = payload(self.payload)
        chain = None

        # IPv4
        pkt = self.createIpv4Pkt(0x06, t, p)
        try:
            chain = self.tr.executeTrigger(pkt)
        except Exception, e:
            self.assertEquals(
                e.errCode, Trigger.ERR_PCAPR_TRIGGER_INVALID,
                'Execute trigger failed: false trigger mishandled')
示例#8
0
文件: icmpv4.py 项目: JahanviB/PCS
    def __init__(self, bytes = None, timestamp = None, **kv):
        """initialize a ICMPv4 packet"""
        type = pcs.Field("type", 8, discriminator=True)
        code = pcs.Field("code", 8)
        cksum = pcs.Field("checksum", 16)
        pcs.Packet.__init__(self, [type, code, cksum], bytes, **kv)
        self.description = "ICMPv4"

        if timestamp is None:
            self.timestamp = time.time()
        else:
            self.timestamp = timestamp

        if bytes is not None:
            offset = self.sizeof()
            # 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:
                from pcs.packets.payload import payload
                self.data = payload(bytes[offset:len(bytes)])
        else:
            self.data = None
示例#9
0
    def __init__(self, bytes=None, timestamp=None, **kv):
        """initialize a ICMPv4 packet"""
        type = pcs.Field("type", 8, discriminator=True)
        code = pcs.Field("code", 8)
        cksum = pcs.Field("checksum", 16)
        pcs.Packet.__init__(self, [type, code, cksum], bytes, **kv)
        self.description = "ICMPv4"

        if timestamp is None:
            self.timestamp = time.time()
        else:
            self.timestamp = timestamp

        if bytes is not None:
            offset = self.sizeof()
            # 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:
                from pcs.packets.payload import payload
                self.data = payload(bytes[offset:len(bytes)])
        else:
            self.data = None
示例#10
0
文件: ping.py 项目: jeamland/PCS
def main():

    from optparse import OptionParser
    
    parser = OptionParser()
    parser.add_option("-c", "--count",
                      dest="count", default=1,
                      help="Stop after sending (and recieving) count ECHO_RESPONSE packets..")
    
    parser.add_option("-D", "--dont_fragment",
                      dest="df", default=False,
                      help="Set the Don't Fragment bit.")

    parser.add_option("-s", "--ip_source",
                      dest="ip_source", default=None,
                      help="The IP source address.")

    parser.add_option("-d", "--ip_dest",
                      dest="ip_dest", default=None,
                      help="The IP destination address.")

    parser.add_option("-I", "--ether_iface",
                      dest="ether_iface", default=None,
                      help="The name of the source interface.")

    parser.add_option("-e", "--ether_source",
                      dest="ether_source", default=None,
                      help="The host Ethernet source address.")

    parser.add_option("-g", "--ether_dest",
                      dest="ether_dest", default=None,
                      help="The gateway Ethernet destination address.")

    (options, args) = parser.parse_args()
 
    c = ethernet(src=ether_atob(options.ether_source),  \
                 dst=ether_atob(options.ether_dest)) /  \
        ipv4(ttl=64, src=inet_atol(options.ip_source),  \
                     dst=inet_atol(options.ip_dest)) / \
        icmpv4(type=8) / icmpv4echo(id=12345) / payload(payload="foobar")

    c.calc_lengths()

    #
    # Increment ICMP echo sequence number with each iteration.
    #
    output = PcapConnector(options.ether_iface)
    ip = c.packets[1]
    echo = c.packets[3]
    count = int(options.count)
    while (count > 0):
        c.calc_checksums()
        c.encode()

        out = output.write(c.bytes, len(c.bytes))
#        packet = input.read()
#        print packet
        sleep(1)
        count -= 1
        ip.id += 1
        echo.sequence += 1
示例#11
0
文件: tcp.py 项目: jeamland/PCS
    def __init__(self, bytes = None, timestamp = None, **kv):
        """initialize a TCP packet"""
        sport = pcs.Field("sport", 16)
        dport = pcs.Field("dport", 16)
        seq = pcs.Field("sequence", 32)
        acknum = pcs.Field("ack_number", 32)
        off = pcs.Field("offset", 4)
        reserved = pcs.Field("reserved", 6)
        urg = pcs.Field("urgent", 1)
        ack = pcs.Field("ack", 1)
        psh = pcs.Field("push", 1)
        rst = pcs.Field("reset", 1)
        syn = pcs.Field("syn", 1)
        fin = pcs.Field("fin", 1)
        window = pcs.Field("window", 16)
        checksum = pcs.Field("checksum", 16)
        urgp = pcs.Field("urg_pointer",16)
        options = pcs.OptionListField("options")
        pcs.Packet.__init__(self, [sport, dport, seq, acknum, off, reserved,
                                   urg, ack, psh, rst, syn, fin, window,
                                   checksum, urgp, 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
示例#12
0
文件: ping6rt.py 项目: victorlawn/PCS
def main():

    from optparse import OptionParser
    
    parser = OptionParser()
    parser.add_option("-c", "--count",
                      dest="count", default=1,
                      help="Stop after sending (and recieving) count ECHO_RESPONSE packets..")
    
    parser.add_option("-D", "--dont_fragment",
                      dest="df", default=False,
                      help="Set the Don't Fragment bit.")

    parser.add_option("-s", "--ip_source",
                      dest="ip_source", default=None,
                      help="The IP source address.")

    parser.add_option("-d", "--ip_dest",
                      dest="ip_dest", default=None,
                      help="The IP destination address.")

    parser.add_option("-I", "--ether_iface",
                      dest="ether_iface", default=None,
                      help="The name of the source interface.")

    parser.add_option("-e", "--ether_source",
                      dest="ether_source", default=None,
                      help="The host Ethernet source address.")

    parser.add_option("-g", "--ether_dest",
                      dest="ether_dest", default=None,
                      help="The gateway Ethernet destination address.")

    parser.add_option("-r", "--rt_hop",
                      dest="hop", default="::",
                      help="The intermediate router address.")

    (options, args) = parser.parse_args()
 
    rtcount = 1
    # plen is 8 + rtcount * 16 for rt hdr, 8 for ICMP, 6 for foobar
    plen = 8 + rtcount * 16 + 8 + 6
    c = ethernet(src=ether_atob(options.ether_source),  \
                 dst=ether_atob(options.ether_dest)) /  \
        ipv6(hop=64, next_header = 43, length = plen, \
                     src=inet_pton(AF_INET6, options.ip_source),  \
                     dst=inet_pton(AF_INET6, options.ip_dest)) / \
        ipv6ext.rt_ext(next_header = 58, \
		       addr1 = inet_pton(AF_INET6, options.hop)) / \
        icmpv6(type=ICMP6_ECHO_REQUEST, id=12345) / \
        payload(payload="foobar")

    c.calc_lengths()

    #
    # Increment ICMP echo sequence number with each iteration.
    #
    output = PcapConnector(options.ether_iface)
    ip = c.packets[1]
    icmpecho = c.packets[3]
    count = int(options.count)
    while (count > 0):
        # c.calc_checksums()
        # icmpecho.cksum = icmpv6.cksum(icmpecho, ip)
        # icmpecho.calc_checksum()
        c.encode()

        out = output.write(c.bytes, len(c.bytes))
#        packet = input.read()
#        print packet
        sleep(1)
        count -= 1
        icmpecho.sequence += 1
示例#13
0
文件: ping6rt.py 项目: JahanviB/PCS
def main():

    from optparse import OptionParser
    
    parser = OptionParser()
    parser.add_option("-c", "--count",
                      dest="count", default=1,
                      help="Stop after sending (and recieving) count ECHO_RESPONSE packets..")
    
    parser.add_option("-D", "--dont_fragment",
                      dest="df", default=False,
                      help="Set the Don't Fragment bit.")

    parser.add_option("-s", "--ip_source",
                      dest="ip_source", default=None,
                      help="The IP source address.")

    parser.add_option("-d", "--ip_dest",
                      dest="ip_dest", default=None,
                      help="The IP destination address.")

    parser.add_option("-I", "--ether_iface",
                      dest="ether_iface", default=None,
                      help="The name of the source interface.")

    parser.add_option("-e", "--ether_source",
                      dest="ether_source", default=None,
                      help="The host Ethernet source address.")

    parser.add_option("-g", "--ether_dest",
                      dest="ether_dest", default=None,
                      help="The gateway Ethernet destination address.")

    parser.add_option("-r", "--rt_hop",
                      dest="hop", default="::",
                      help="The intermediate router address.")

    (options, args) = parser.parse_args()
 
    rtcount = 1
    # plen is 8 + rtcount * 16 for rt hdr, 8 for ICMP, 6 for foobar
    plen = 8 + rtcount * 16 + 8 + 6
    c = ethernet(src=ether_atob(options.ether_source),  \
                 dst=ether_atob(options.ether_dest)) /  \
        ipv6(hop=64, next_header = 43, length = plen, \
                     src=inet_pton(AF_INET6, options.ip_source),  \
                     dst=inet_pton(AF_INET6, options.ip_dest)) / \
        ipv6ext.rt_ext(next_header = 58, \
		       addr1 = inet_pton(AF_INET6, options.hop)) / \
        icmpv6(type=ICMP6_ECHO_REQUEST, id=12345) / \
        payload(payload="foobar")

    c.calc_lengths()

    #
    # Increment ICMP echo sequence number with each iteration.
    #
    output = PcapConnector(options.ether_iface)
    ip = c.packets[1]
    icmpecho = c.packets[3]
    count = int(options.count)
    while (count > 0):
        # c.calc_checksums()
        # icmpecho.cksum = icmpv6.cksum(icmpecho, ip)
        # icmpecho.calc_checksum()
        c.encode()

        out = output.write(c.bytes, len(c.bytes))
#        packet = input.read()
#        print packet
        sleep(1)
        count -= 1
        icmpecho.sequence += 1
示例#14
0
文件: tcp.py 项目: victorlawn/PCS
    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