diff --git a/scapy/arch/__init__.py b/scapy/arch/__init__.py
index d13db5244a4cdca5d757dbfd9e8ad3fcf838c850..23e1cb7ce655df563bbe01bbfe596d850d942d9c 100644
--- a/scapy/arch/__init__.py
+++ b/scapy/arch/__init__.py
@@ -82,15 +82,26 @@ if scapy.config.conf.iface is None:
     scapy.config.conf.iface = LOOPBACK_NAME
 
 
+def get_if_addr6(iff):
+    """
+    Returns the main global unicast address associated with provided 
+    interface, in human readable form. If no global address is found,
+    None is returned. 
+    """
+    for x in in6_getifaddr():
+        if x[2] == iff and x[1] == IPV6_ADDR_GLOBAL:
+            return x[0]
+        
+    return None
+
 def get_if_raw_addr6(iff):
     """
     Returns the main global unicast address associated with provided 
     interface, in network format. If no global address is found, None 
     is returned. 
     """
-    r = filter(lambda x: x[2] == iff and x[1] == IPV6_ADDR_GLOBAL, in6_getifaddr())
-    if len(r) == 0:
-        return None
-    else:
-        r = r[0][0] 
-    return inet_pton(socket.AF_INET6, r)
+    ip6= get_if_addr6(iff)
+    if ip6 is not None:
+        return inet_pton(socket.AF_INET6, ip6)
+    
+    return None
diff --git a/scapy/automaton.py b/scapy/automaton.py
index 7502ac51d8a8243df303d892adf08bcf2f67008b..69651c50b68a741d177a070eb55854f794a10359 100644
--- a/scapy/automaton.py
+++ b/scapy/automaton.py
@@ -8,7 +8,7 @@ Automata with states, transitions and actions.
 """
 
 from __future__ import with_statement
-import types,itertools,time,os,sys,socket
+import types,itertools,time,os,sys,socket,traceback
 from select import select
 from collections import deque
 import thread
@@ -429,13 +429,16 @@ class Automaton:
                 raise self.AutomatonError("INTERCEPT: unkown verdict: %r" % cmd.type)
         self.my_send(pkt)
         self.debug(3,"SENT : %s" % pkt.summary())
-        self.packets.append(pkt.copy())
+        
+        if self.store_packets:
+            self.packets.append(pkt.copy())
 
 
     ## Internals
     def __init__(self, *args, **kargs):
         external_fd = kargs.pop("external_fd",{})
         self.send_sock_class = kargs.pop("ll", conf.L3socket)
+        self.recv_sock_class = kargs.pop("recvsock", conf.L2listen)
         self.started = thread.allocate_lock()
         self.threadid = None
         self.breakpointed = None
@@ -493,7 +496,8 @@ class Automaton:
         except ATMT.NewStateRequested, state_req:
             self.debug(2, "%s [%s] taken to state [%s]" % (cond.atmt_type, cond.atmt_condname, state_req.state))
             if cond.atmt_type == ATMT.RECV:
-                self.packets.append(args[0])
+                if self.store_packets:
+                    self.packets.append(args[0])
             for action in self.actions[cond.atmt_condname]:
                 self.debug(2, "   + Running action [%s]" % action.func_name)
                 action(self, *state_req.action_args, **state_req.action_kargs)
@@ -522,7 +526,7 @@ class Automaton:
             # Start the automaton
             self.state=self.initial_states[0](self)
             self.send_sock = self.send_sock_class()
-            self.listen_sock = conf.L2listen(**self.socket_kargs)
+            self.listen_sock = self.recv_sock_class(**self.socket_kargs)
             self.packets = PacketList(name="session[%s]"%self.__class__.__name__)
 
             singlestep = True
@@ -556,8 +560,9 @@ class Automaton:
                 c = Message(type=_ATMT_Command.END, result=e.args[0])
                 self.cmdout.send(c)
             except Exception,e:
-                self.debug(3, "Transfering exception [%s] from tid=%i"% (e,self.threadid))
-                m = Message(type = _ATMT_Command.EXCEPTION, exception=e, exc_info=sys.exc_info())
+                exc_info = sys.exc_info()
+                self.debug(3, "Transfering exception from tid=%i:\n%s"% (self.threadid, traceback.format_exc(exc_info)))
+                m = Message(type=_ATMT_Command.EXCEPTION, exception=e, exc_info=exc_info)
                 self.cmdout.send(m)        
             self.debug(3, "Stopping control thread (tid=%i)"%self.threadid)
             self.threadid = None
diff --git a/scapy/contrib/isis.py b/scapy/contrib/isis.py
new file mode 100644
index 0000000000000000000000000000000000000000..1fb5dde6c0c1a2435d4d3ca4d4d5fe46bdc569b6
--- /dev/null
+++ b/scapy/contrib/isis.py
@@ -0,0 +1,726 @@
+# scapy.contrib.description = ISIS
+# scapy.contrib.status = loads
+
+"""
+    IS-IS Scapy Extension
+    ~~~~~~~~~~~~~~~~~~~~~
+
+    :copyright: 2014 BENOCS GmbH, Berlin (Germany)
+    :author:    Marcel Patzlaff, mpatzlaff@benocs.com
+    :license:   GPLv2
+
+        This module is free software; you can redistribute it and/or
+        modify it under the terms of the GNU General Public License
+        as published by the Free Software Foundation; either version 2
+        of the License, or (at your option) any later version.
+
+        This module is distributed in the hope that it will be useful,
+        but WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+        GNU General Public License for more details.
+
+    :description:
+
+        This module provides Scapy layers for the Intermediate System
+        to Intermediate System routing protocol as defined in RFC 1195.
+        
+        Currently it (partially) supports the packaging/encoding
+        requirements of the following RFCs:
+         * RFC 1195 (only the TCP/IP related part)
+         * RFC 3358 (optional checksums)
+         * RFC 5301 (dynamic hostname extension)
+         * RFC 5302 (domain-wide prefix destribution)
+         * RFC 5303 (three-way handshake)
+         * RFC 5304 (cryptographic authentication)
+         * RFC 5308 (routing IPv6 with IS-IS)
+                
+    :TODO:
+
+        - packet relations (requests, responses)
+        - support for recent RFCs:
+          * RFC 5305 (traffic engineering)
+          * RFC 5307 (support for G-MPLS)
+          * RFC 5310 (generic cryptographic authentication)
+          * RFC 5316 (inter-AS MPLS and G-MPLS TE)
+
+"""
+
+import struct
+
+from scapy.config import conf
+from scapy.fields import Field, FlagsField, ByteField, ByteEnumField, \
+    FieldLenField, ShortField, PacketListField, XIntField, \
+    XShortField, ConditionalField, X3BytesField, IntField, BitField, IPField, \
+    FieldListField, MACField, BitFieldLenField, IPPrefixField, IP6PrefixField,\
+    BoundStrLenField
+from scapy.layers.clns import network_layer_protocol_ids, register_cln_protocol
+from scapy.layers.inet6 import IP6ListField
+from scapy.packet import Packet, bind_layers
+from scapy.utils import fletcher16_checkbytes
+from scapy.volatile import RandString, RandByte
+import random
+
+
+EXT_VERSION = "v0.0.1"
+
+conf.debug_dissector= True
+
+#######################################################################
+##  ISIS Utilities + Fields                                          ##
+#######################################################################
+
+def isis_area2str(area):
+    return "".join(x.decode("hex") for x in area.split("."))
+
+def isis_str2area(s):
+    if len(s) == 0:
+        return ""
+    
+    numbytes= len(s[1:])
+    fmt= "%02X" + (".%02X%02X" * (numbytes / 2)) + ("" if (numbytes % 2) == 0 else ".%02X")
+    return fmt % tuple(map(ord,s))
+
+def isis_sysid2str(sysid):
+    return "".join(x.decode("hex") for x in sysid.split("."))
+
+def isis_str2sysid(s):
+    return ("%02X%02X."*3)[:-1] % tuple(map(ord, s))
+
+def isis_nodeid2str(nodeid):
+    return "%s%s" % (isis_sysid2str(nodeid[:-3]), nodeid[-2:].decode("hex"))
+    
+def isis_str2nodeid(s):
+    return "%s.%02X" % (isis_str2sysid(s[:-1]), ord(s[-1]))
+
+def isis_lspid2str(lspid):
+    return "%s%s" % (isis_nodeid2str(lspid[:-3]), lspid[-2:].decode("hex"))
+    
+def isis_str2lspid(s):
+    return "%s-%02X" % (isis_str2nodeid(s[:-1]), ord(s[-1]))
+
+
+class _ISIS_IdFieldBase(Field):
+    def __init__(self, name, default, length, to_str, to_id):
+        self.to_str= to_str
+        self.to_id= to_id
+        self.length= length
+        Field.__init__(self, name, default, "%is" %length)
+
+    def i2m(self, pkt, x):
+        if x is None:
+            return "\0"*self.length
+        
+        return self.to_str(x)
+
+    def m2i(self, pkt, x):
+        return self.to_id(x)
+
+    def any2i(self, pkt, x):
+        if type(x) is str and len(x) == self.length:
+            return self.m2i(pkt, x)
+
+        return x
+
+
+class _ISIS_RandId(RandString):
+    def __init__(self, template):
+        self.bytecount= template.count("*")
+        self.format=template.replace("*","%02X")
+    
+    def _fix(self):
+        if self.bytecount == 0:
+            return ""
+        
+        val=()
+        
+        for _ in range(self.bytecount):
+            val+= (RandByte(),)
+        
+        return self.format % val
+
+class _ISIS_RandAreaId(_ISIS_RandId):
+    def __init__(self, bytecount= None):
+        self.bytecount= random.randint(1,13) if bytecount is None else bytecount
+        self.format= "%02X" + (".%02X%02X" * ((self.bytecount-1) / 2)) + ("" if ((self.bytecount-1) % 2) == 0 else ".%02X")
+
+
+class ISIS_AreaIdField(Field):
+    def __init__(self, name, default, length_from):
+        Field.__init__(self, name, default)
+        self.length_from= length_from
+        
+    def i2m(self, pkt, x):
+        return isis_area2str(x)
+    
+    def m2i(self, pkt, x):
+        return isis_str2area(x)
+    
+    def i2len(self, pkt, x):
+        if x is None:
+            return 0
+        l= len(x)
+        # l/5 is the number of dots in the Area ID
+        return (l - (l / 5)) / 2
+        
+    def addfield(self, pkt, s, val):
+        sval= self.i2m(pkt, val)
+        return s+struct.pack("!%is" % len(sval), sval)
+    
+    def getfield(self, pkt, s):
+        numbytes= self.length_from(pkt)
+        return s[numbytes:], self.m2i(pkt, struct.unpack("!%is" % numbytes, s[:numbytes])[0])
+    
+    def randval(self):
+        return _ISIS_RandAreaId()
+
+
+class ISIS_SystemIdField(_ISIS_IdFieldBase):
+    def __init__(self, name, default):
+        _ISIS_IdFieldBase.__init__(self, name, default, 6, isis_sysid2str, isis_str2sysid)
+        
+    def randval(self):
+        return _ISIS_RandId("**.**.**")
+
+
+class ISIS_NodeIdField(_ISIS_IdFieldBase):
+    def __init__(self, name, default):
+        _ISIS_IdFieldBase.__init__(self, name, default, 7, isis_nodeid2str, isis_str2nodeid)
+        
+    def randval(self):
+        return _ISIS_RandId("**.**.**.*")
+
+
+class ISIS_LspIdField(_ISIS_IdFieldBase):
+    def __init__(self, name, default):
+        _ISIS_IdFieldBase.__init__(self, name, default, 8, isis_lspid2str, isis_str2lspid)
+        
+    def randval(self):
+        return _ISIS_RandId("**.**.**.*-*")
+
+
+class ISIS_CircuitTypeField(FlagsField):
+    def __init__(self, name="circuittype", default=2, size=8, names=["L1", "L2", "r0", "r1", "r2", "r3", "r4", "r5"]):
+        FlagsField.__init__(self, name, default, size, names)
+
+
+#######################################################################
+##  ISIS TLVs                                                        ##
+#######################################################################
+
+_isis_tlv_classes= { 
+           1: "ISIS_AreaTlv",
+           2: "ISIS_IsReachabilityTlv",
+           6: "ISIS_IsNeighbourTlv",
+           8: "ISIS_PaddingTlv",
+           9: "ISIS_LspEntryTlv",
+          10: "ISIS_AuthenticationTlv",
+          12: "ISIS_ChecksumTlv", 
+          14: "ISIS_BufferSizeTlv",
+          22: "ISIS_ExtendedIsReachabilityTlv",
+         128: "ISIS_InternalIpReachabilityTlv",
+         129: "ISIS_ProtocolsSupportedTlv",
+         130: "ISIS_ExternalIpReachabilityTlv",
+         132: "ISIS_IpInterfaceAddressTlv",
+         135: "ISIS_ExtendedIpReachabilityTlv",
+         137: "ISIS_DynamicHostnameTlv",
+         232: "ISIS_Ipv6InterfaceAddressTlv",
+         236: "ISIS_Ipv6ReachabilityTlv",
+         240: "ISIS_P2PAdjacencyStateTlv"
+}
+
+_isis_tlv_names= { 
+           1: "Area TLV",
+           2: "IS Reachability TLV",
+           6: "IS Neighbour TLV",
+           7: "Instance Identifier TLV",
+           8: "Padding TLV",
+           9: "LSP Entries TLV",
+          10: "Authentication TLV",
+          12: "Optional Checksum TLV",
+          13: "Purge Originator Identification TLV", 
+          14: "LSP Buffer Size TLV",
+          22: "Extended IS-Reachability TLV",
+          23: "IS Neighbour Attribute TLV",
+          24: "IS Alias ID",
+         128: "IP Internal Reachability TLV",
+         129: "Protocols Supported TLV",
+         130: "IP External Reachability TLV",
+         131: "Inter-Domain Routing Protocol Information TLV",
+         132: "IP Interface Address TLV",
+         134: "Traffic Engineering Router ID TLV",
+         135: "Extended IP Reachability TLV",
+         137: "Dynamic Hostname TLV",
+         138: "GMPLS Shared Risk Link Group TLV",
+         139: "IPv6 Shared Risk Link Group TLV",
+         140: "IPv6 Traffic Engineering Router ID TLV",
+         141: "Inter-AS Reachability Information TLV",
+         142: "Group Address TLV",
+         143: "Multi-Topology-Aware Port Capability TLV",
+         144: "Multi-Topology Capability TLV",
+         145: "TRILL Neighbour TLV",
+         147: "MAC-Reachability TLV",
+         148: "BFD-Enabled TLV",
+         211: "Restart TLV",
+         222: "Multi-Topology Intermediate Systems TLV",
+         223: "Multi-Topology IS Neighbour Attributes TLV",
+         229: "Multi-Topology TLV",
+         232: "IPv6 Interface Address TLV",
+         233: "IPv6 Global Interface Address TLV",
+         235: "Multi-Topology IPv4 Reachability TLV",
+         236: "IPv6 Reachability TLV",
+         237: "Multi-Topology IPv6 Reachability TLV",
+         240: "Point-to-Point Three-Way Adjacency TLV",
+         242: "IS-IS Router Capability TLV",
+         251: "Generic Information TLV"
+}
+
+
+
+def _ISIS_GuessTlvClass(p, **kargs):
+    cls = conf.raw_layer
+    if len(p) >= 2:
+        tlvtype = struct.unpack("!B", p[0])[0]
+        clsname = _isis_tlv_classes.get(tlvtype, "ISIS_GenericTlv")
+        cls = globals()[clsname]
+
+    return cls(p, **kargs)
+
+
+class ISIS_GenericTlv(Packet):
+    name = "ISIS Generic TLV"
+    fields_desc = [ByteEnumField("type", 0, _isis_tlv_names),
+                   FieldLenField("len", None, length_of="val", fmt="B"),
+                   BoundStrLenField("val", "", length_from=lambda pkt: pkt.len)]
+
+    def guess_payload_class(self, p):
+        return conf.padding_layer
+
+
+class ISIS_AreaEntry(Packet):
+    name = "ISIS Area Entry"
+    fields_desc = [FieldLenField("arealen", None, length_of="areaid", fmt="B"),
+                   ISIS_AreaIdField("areaid", "49", length_from=lambda pkt: pkt.arealen)]
+    
+    def extract_padding(self, s):
+        return "", s
+
+
+class ISIS_AreaTlv(ISIS_GenericTlv):
+    name = "ISIS Area TLV"
+    fields_desc = [ByteEnumField("type", 1, _isis_tlv_names),
+                   FieldLenField("len", None, length_of= "areas", fmt="B"),
+                   PacketListField("areas", [], ISIS_AreaEntry, length_from=lambda x: x.len)]
+
+
+class ISIS_AuthenticationTlv(ISIS_GenericTlv):
+    name = "ISIS Authentication TLV"
+    fields_desc = [ByteEnumField("type", 10, _isis_tlv_names),
+                   FieldLenField("len", None, length_of= "password", adjust=lambda pkt,x: x + 1, fmt="B"),
+                   ByteEnumField("authtype", 1, {1: "Plain", 17: "HMAC-MD5"}),
+                   BoundStrLenField("password", "", maxlen= 254, length_from=lambda pkt: pkt.len - 1)]
+
+
+class ISIS_BufferSizeTlv(ISIS_GenericTlv):
+    name = "ISIS Buffer Size TLV"
+    fields_desc = [ByteEnumField("type", 14, _isis_tlv_names),
+                   ByteField("len", 2),
+                   ShortField("lspbuffersize", 1497)]
+    
+
+
+class ISIS_ChecksumTlv(ISIS_GenericTlv):
+    name = "ISIS Optional Checksum TLV"
+    fields_desc = [ByteEnumField("type", 12, _isis_tlv_names),
+                   ByteField("len", 2),
+                   XShortField("checksum", None)]
+
+    
+class ISIS_DynamicHostnameTlv(ISIS_GenericTlv):
+    name = "ISIS Dynamic Hostname TLV"
+    fields_desc = [ByteEnumField("type", 137, _isis_tlv_names),
+                   FieldLenField("len", None, length_of= "hostname", fmt="B"),
+                   BoundStrLenField("hostname", "", length_from=lambda pkt: pkt.len)]
+
+
+
+class ISIS_GenericSubTlv(Packet):
+    name = "ISIS Generic Sub-TLV"
+    fields_desc = [ByteField("type", 0),
+                   FieldLenField("len", None, length_of="val", fmt="B"),
+                   BoundStrLenField("val", "", length_from=lambda pkt: pkt.len)]
+
+    def guess_payload_class(self, p):
+        return conf.padding_layer
+
+def _isis_guess_subtlv_cls(p, **kargs):
+    return ISIS_GenericSubTlv(p, **kargs)
+
+
+class ISIS_ExtendedIpPrefix(Packet):
+    name = "ISIS Extended IP Prefix"
+    fields_desc = [IntField("metric", 1),
+                   BitField("updown", 0, 1),
+                   BitField("subtlvindicator", 0, 1),
+                   BitFieldLenField("pfxlen", None, 6, length_of="pfx"),
+                   IPPrefixField("pfx", None, wordbytes=1, length_from= lambda x: x.pfxlen),
+                   ConditionalField(FieldLenField("subtlvslen", None, length_of=lambda x: x.subtlvs, fmt= "B"), lambda pkt: pkt.subtlvindicator == 1), 
+                   ConditionalField(PacketListField("subtlvs", [], _isis_guess_subtlv_cls, length_from=lambda x: x.subtlvslen), lambda pkt: pkt.subtlvindicator == 1)]
+    
+    def extract_padding(self, s):
+        return "", s
+ 
+class ISIS_ExtendedIpReachabilityTlv(ISIS_GenericTlv):
+    name = "ISIS Extended IP Reachability TLV"
+    fields_desc = [ByteEnumField("type", 135, _isis_tlv_names),
+                   FieldLenField("len", None, length_of="pfxs", fmt="B"),
+                   PacketListField("pfxs", [], ISIS_ExtendedIpPrefix, length_from= lambda pkt: pkt.len)]
+
+
+class ISIS_ExtendedIsNeighbourEntry(Packet):
+    name = "ISIS Extended IS Neighbour Entry"
+    fields_desc = [ISIS_NodeIdField("neighbourid", "0102.0304.0506.07"),
+                   X3BytesField("metric", 1),
+                   FieldLenField("subtlvslen", None, length_of="subtlvs", fmt= "B"),
+                   ConditionalField(PacketListField("subtlvs", [], _isis_guess_subtlv_cls, length_from=lambda x: x.subtlvslen), lambda pkt: pkt.subtlvslen > 0)]
+    
+    def extract_padding(self, s):
+        return "", s
+    
+class ISIS_ExtendedIsReachabilityTlv(ISIS_GenericTlv):
+    name = "ISIS Extended IS Reachability TLV"
+    fields_desc = [ByteEnumField("type", 22, _isis_tlv_names),
+                   FieldLenField("len", None, length_of="neighbours", fmt="B"),
+                   PacketListField("neighbours", [], ISIS_ExtendedIsNeighbourEntry, length_from=lambda x: x.len)]
+
+
+class ISIS_IpInterfaceAddressTlv(ISIS_GenericTlv):
+    name = "ISIS IP Interface Address TLV"
+    fields_desc = [ByteEnumField("type", 132, _isis_tlv_names),
+                   FieldLenField("len", None, length_of= "addresses", fmt="B"),
+                   FieldListField("addresses", [], IPField("", "0.0.0.0"), count_from= lambda pkt: pkt.len / 4)]
+    
+
+class ISIS_Ipv6InterfaceAddressTlv(ISIS_GenericTlv):
+    name = "ISIS IPv6 Interface Address TLV"
+    fields_desc = [ByteEnumField("type", 232, _isis_tlv_names),
+                   FieldLenField("len", None, length_of= "addresses", fmt="B"),
+                   IP6ListField("addresses", [], count_from= lambda pkt: pkt.len / 16)]
+
+
+
+class ISIS_Ipv6Prefix(Packet):
+    name = "ISIS IPv6 Prefix"
+    fields_desc = [IntField("metric", 1),
+               BitField("updown", 0, 1),
+               BitField("external", 0, 1),
+               BitField("subtlvindicator", 0, 1),
+               BitField("reserved", 0, 5),
+               FieldLenField("pfxlen", None, length_of="pfx", fmt="B"),
+               IP6PrefixField("pfx", None, wordbytes=1, length_from= lambda x: x.pfxlen),
+               ConditionalField(FieldLenField("subtlvslen", None, length_of=lambda x: x.subtlvs, fmt= "B"), lambda pkt: pkt.subtlvindicator == 1), 
+               ConditionalField(PacketListField("subtlvs", [], _isis_guess_subtlv_cls, length_from=lambda x: x.subtlvslen), lambda pkt: pkt.subtlvindicator == 1)]
+    
+    def extract_padding(self, s):
+        return "", s
+
+class ISIS_Ipv6ReachabilityTlv(ISIS_GenericTlv):
+    name= "ISIS IPv6 Reachability TLV"
+    fields_desc = [ByteEnumField("type", 236, _isis_tlv_names),
+                   FieldLenField("len", None, length_of= "pfxs", fmt="B"),
+                   PacketListField("pfxs", [], ISIS_Ipv6Prefix, length_from= lambda pkt: pkt.len)]
+
+class ISIS_IsNeighbourTlv(ISIS_GenericTlv):
+    name = "ISIS IS Neighbour TLV"
+    fields_desc = [ByteEnumField("type", 6, _isis_tlv_names),
+                   FieldLenField("len", None, length_of= "neighbours", fmt="B"),
+                   FieldListField("neighbours", [], MACField("", "00.00.00.00.00.00"), count_from= lambda pkt: pkt.len / 6)]
+    
+
+class ISIS_LspEntry(Packet):
+    name = "ISIS LSP Entry"
+    fields_desc = [ShortField("lifetime", 1200),
+                   ISIS_LspIdField("lspid", "0102.0304.0506.07-08"),
+                   XIntField("seqnum", 0x00000001),
+                   XShortField("checksum", None)]
+    
+    def extract_padding(self, s):
+        return "", s
+
+
+class ISIS_LspEntryTlv(ISIS_GenericTlv):
+    name = "ISIS LSP Entry TLV"
+    fields_desc = [ByteEnumField("type", 9, _isis_tlv_names),
+               FieldLenField("len", None, length_of= "entries", fmt="B"),
+               PacketListField("entries", [], ISIS_LspEntry, count_from= lambda pkt: pkt.len / 16)]
+
+
+class _AdjacencyStateTlvLenField(Field):
+    def i2m(self, pkt, x):
+        if pkt.neighbourextlocalcircuitid is not None:
+            return 15
+        
+        if pkt.neighboursystemid is not None:
+            return 11
+        
+        if pkt.extlocalcircuitid is not None:
+            return 5
+
+        return 1
+
+class ISIS_P2PAdjacencyStateTlv(ISIS_GenericTlv):
+    name = "ISIS P2P Adjacency State TLV"
+    fields_desc = [ByteEnumField("type", 240, _isis_tlv_names),
+               _AdjacencyStateTlvLenField("len", None, fmt="B"),
+               ByteEnumField("state", "Down", {0x2 : "Down", 0x1 : "Initialising", 0x0 : "Up"}),
+               ConditionalField(IntField("extlocalcircuitid", None), lambda pkt: pkt.len >= 5),
+               ConditionalField(ISIS_SystemIdField("neighboursystemid", None), lambda pkt: pkt.len >= 11),
+               ConditionalField(IntField("neighbourextlocalcircuitid", None), lambda pkt: pkt.len == 15)]
+
+# TODO dynamically allocate sufficient size
+class ISIS_PaddingTlv(ISIS_GenericTlv):
+    name = "ISIS Padding TLV"
+    fields_desc = [ByteEnumField("type", 8, _isis_tlv_names),
+               FieldLenField("len", None, length_of= "padding", fmt="B"),
+               BoundStrLenField("padding", "", length_from=lambda pkt: pkt.len)]
+    
+
+class ISIS_ProtocolsSupportedTlv(ISIS_GenericTlv):
+    name = "ISIS Protocols Supported TLV"
+    fields_desc = [ByteEnumField("type", 129, _isis_tlv_names),
+                   FieldLenField("len", None, count_of= "nlpids", fmt="B"),
+                   FieldListField("nlpids", [], ByteEnumField("", "IPv4", network_layer_protocol_ids), count_from= lambda pkt: pkt.len)]
+
+
+#######################################################################
+##  ISIS Old-Style TLVs                                              ##
+#######################################################################
+
+class ISIS_IpReachabilityEntry(Packet):
+    name = "ISIS IP Reachability"
+    fields_desc = [ByteField("defmetric", 1),
+                   ByteField("delmetric", 0x80),
+                   ByteField("expmetric", 0x80),
+                   ByteField("errmetric", 0x80),
+                   IPField("ipaddress", "0.0.0.0"),
+                   IPField("subnetmask", "255.255.255.255")]
+    
+    def extract_padding(self, s):
+        return "", s
+
+class ISIS_InternalIpReachabilityTlv(ISIS_GenericTlv):
+    name = "ISIS Internal IP Reachability TLV"
+    fields_desc = [ByteEnumField("type", 128, _isis_tlv_names),
+                   FieldLenField("len", None, length_of= "entries", fmt="B"),
+                   PacketListField("entries", [], ISIS_IpReachabilityEntry, count_from= lambda x: x.len / 12)]
+
+class ISIS_ExternalIpReachabilityTLV(ISIS_GenericTlv):
+    name = "ISIS External IP Reachability TLV"
+    fields_desc = [ByteEnumField("type", 130, _isis_tlv_names),
+                   FieldLenField("len", None, length_of= "entries", fmt="B"),
+                   PacketListField("entries", [], ISIS_IpReachabilityEntry, count_from= lambda x: x.len / 12)]
+
+
+class ISIS_IsReachabilityEntry(Packet):
+    name = "ISIS IS Reachability"
+    fields_desc = [ByteField("defmetric", 1),
+                   ByteField("delmetric", 0x80),
+                   ByteField("expmetric", 0x80),
+                   ByteField("errmetric", 0x80),
+                   ISIS_NodeIdField("neighbourid", "0102.0304.0506.07")]
+
+    def extract_padding(self, s):
+        return "", s
+
+class ISIS_IsReachabilityTlv(ISIS_GenericTlv):
+    name = "ISIS IS Reachability TLV"
+    fields_desc = [ByteEnumField("type", 2, _isis_tlv_names),
+                   FieldLenField("len", None, fmt="B", length_of= "neighbours", adjust= lambda pkt,x: x+1),
+                   ByteField("virtual", 0),
+                   PacketListField("neighbours", [], ISIS_IsReachabilityEntry, count_from= lambda x: (x.len - 1) / 11)]
+
+
+#######################################################################
+##  ISIS PDU Packets                                                 ##
+#######################################################################
+_isis_pdu_names = {
+        15: "L1 LAN Hello",
+        16: "L2 LAN Hello",
+        17: "P2P Hello",
+        18: "L1 LSP",
+        20: "L2 LSP",
+        24: "L1 CSNP",
+        25: "L2 CSNP",
+        26: "L1 PSNP",
+        27: "L2 PSNP"
+}
+
+class ISIS_CommonHdr(Packet):
+    name= "ISIS Common Header"
+    fields_desc= [
+        ByteEnumField("nlpid", 0x83, network_layer_protocol_ids),
+        ByteField("hdrlen", None),
+        ByteField("version", 1),
+        ByteField("idlen", 0),
+        ByteEnumField("pdutype", None, _isis_pdu_names),
+        ByteField("pduversion", 1),
+        ByteField("hdrreserved", 0),
+        ByteField("maxareaaddr", 0)
+    ]
+
+    def post_build(self, pkt, pay):
+        # calculating checksum if requested
+        pdu= pkt + pay
+        checksumInfo= self[1].checksum_info(self.hdrlen)
+        
+        if checksumInfo is not None:
+            (cbegin, cpos) = checksumInfo
+            checkbytes= fletcher16_checkbytes(pdu[cbegin:], (cpos - cbegin))
+            pdu = pdu[:cpos] + checkbytes + pdu[cpos+2:]
+        
+        return pdu
+
+
+class _ISIS_PduBase(Packet):
+    def checksum_info(self, hdrlen):
+        checksumPosition= hdrlen
+        for tlv in self.tlvs:
+            if isinstance(tlv, ISIS_ChecksumTlv):
+                checksumPosition+= 2
+                return (0, checksumPosition)
+            else:
+                checksumPosition+= len(tlv)
+            
+        return None
+    
+    def guess_payload_class(self, p):
+        return conf.padding_layer
+
+
+class _ISIS_PduLengthField(FieldLenField):
+    def __init__(self):
+        FieldLenField.__init__(self, "pdulength", None, length_of= "tlvs", adjust= lambda pkt,x: x + pkt.underlayer.hdrlen)
+        
+
+class _ISIS_TlvListField(PacketListField):
+    def __init__(self):
+        PacketListField.__init__(self, "tlvs", [], _ISIS_GuessTlvClass, count_from= None, length_from= lambda pkt: pkt.pdulength - pkt.underlayer.hdrlen)
+
+class _ISIS_LAN_HelloBase(_ISIS_PduBase):
+    fields_desc= [
+        ISIS_CircuitTypeField(),
+        ISIS_SystemIdField("sourceid", "0102.0304.0506"),
+        ShortField("holdingtime", 30),
+        _ISIS_PduLengthField(),
+        ByteField("priority", 1),
+        ISIS_NodeIdField("lanid", "0000.0000.0000.00"),
+        _ISIS_TlvListField()
+    ]
+
+class ISIS_L1_LAN_Hello(_ISIS_LAN_HelloBase):
+    name= "ISIS L1 LAN Hello PDU"
+
+class ISIS_L2_LAN_Hello(_ISIS_LAN_HelloBase):
+    name= "ISIS L2 LAN Hello PDU"
+
+
+class ISIS_P2P_Hello(_ISIS_PduBase):
+    name= "ISIS Point-to-Point Hello PDU"
+    
+    fields_desc= [
+        ISIS_CircuitTypeField(),
+        ISIS_SystemIdField("sourceid", "0102.0304.0506"),
+        ShortField("holdingtime", 30),
+        _ISIS_PduLengthField(),
+        ByteField("localcircuitid", 0),
+        _ISIS_TlvListField()
+    ]
+
+
+class _ISIS_LSP_Base(_ISIS_PduBase):
+    fields_desc= [
+        _ISIS_PduLengthField(),
+        ShortField("lifetime", 1199),
+        ISIS_LspIdField("lspid", "0102.0304.0506.00-00"),
+        XIntField("seqnum", 0x00000001),
+        XShortField("checksum", None),
+        FlagsField("typeblock", 0x03, 8, ["L1", "L2", "OL", "ADef", "ADel", "AExp", "AErr", "P"]),
+        _ISIS_TlvListField()
+    ]
+    
+    def checksum_info(self, hdrlen):
+        if self.checksum is not None:
+            return None
+        
+        return (12, 24)
+
+def _lsp_answers(lsp, other, clsname):
+    # TODO
+    return 0
+
+class ISIS_L1_LSP(_ISIS_LSP_Base):
+    name= "ISIS L1 Link State PDU"
+    
+    def answers(self, other):
+        return _lsp_answers(self, other, "ISIS_L1_PSNP")
+
+class ISIS_L2_LSP(_ISIS_LSP_Base):
+    name= "ISIS L2 Link State PDU"
+    
+    def answers(self, other):
+        return _lsp_answers(self, other, "ISIS_L2_PSNP")
+
+
+class _ISIS_CSNP_Base(_ISIS_PduBase):
+    fields_desc= [
+        _ISIS_PduLengthField(),
+        ISIS_NodeIdField("sourceid", "0102.0304.0506.00"),
+        ISIS_LspIdField("startlspid", "0000.0000.0000.00-00"),
+        ISIS_LspIdField("endlspid", "FFFF.FFFF.FFFF.FF-FF"),
+        _ISIS_TlvListField()
+    ]
+
+def _snp_answers(snp, other, clsname):
+    # TODO
+    return 0
+
+class ISIS_L1_CSNP(_ISIS_CSNP_Base):
+    name= "ISIS L1 Complete Sequence Number Packet"
+    
+    def answers(self, other):
+        return _snp_answers(self, other, "ISIS_L1_LSP")
+
+class ISIS_L2_CSNP(_ISIS_CSNP_Base):
+    name= "ISIS L2 Complete Sequence Number Packet"
+
+    def answers(self, other):
+        return _snp_answers(self, other, "ISIS_L2_LSP")
+
+class _ISIS_PSNP_Base(_ISIS_PduBase):
+    fields_desc= [
+        _ISIS_PduLengthField(),
+        ISIS_NodeIdField("sourceid", "0102.0304.0506.00"),
+        _ISIS_TlvListField()
+    ]
+
+class ISIS_L1_PSNP(_ISIS_PSNP_Base):
+    name= "ISIS L1 Partial Sequence Number Packet"
+    
+    def answers(self, other):
+        return _snp_answers(self, other, "ISIS_L1_LSP")
+
+class ISIS_L2_PSNP(_ISIS_PSNP_Base):
+    name= "ISIS L2 Partial Sequence Number Packet"
+    
+    def answers(self, other):
+        return _snp_answers(self, other, "ISIS_L2_LSP")
+
+register_cln_protocol(0x83, ISIS_CommonHdr)
+bind_layers(ISIS_CommonHdr, ISIS_L1_LAN_Hello, hdrlen= 27, pdutype= 15)
+bind_layers(ISIS_CommonHdr, ISIS_L2_LAN_Hello, hdrlen= 27, pdutype= 16)
+bind_layers(ISIS_CommonHdr, ISIS_P2P_Hello, hdrlen= 20, pdutype= 17)
+bind_layers(ISIS_CommonHdr, ISIS_L1_LSP, hdrlen= 27, pdutype= 18)
+bind_layers(ISIS_CommonHdr, ISIS_L2_LSP, hdrlen= 27, pdutype= 20)
+bind_layers(ISIS_CommonHdr, ISIS_L1_CSNP, hdrlen= 33, pdutype= 24)
+bind_layers(ISIS_CommonHdr, ISIS_L2_CSNP, hdrlen= 33, pdutype= 25)
+bind_layers(ISIS_CommonHdr, ISIS_L1_PSNP, hdrlen= 17, pdutype= 26)
+bind_layers(ISIS_CommonHdr, ISIS_L2_PSNP, hdrlen= 17, pdutype= 27)
\ No newline at end of file
diff --git a/scapy/contrib/ospf.py b/scapy/contrib/ospf.py
index a6422bd8bcaae7f8a291394eadd7c5af1ff2599e..362e467edb51469e340f071306d5c25b56b055d6 100644
--- a/scapy/contrib/ospf.py
+++ b/scapy/contrib/ospf.py
@@ -206,40 +206,7 @@ _OSPF_LSclasses = {1: "OSPF_Router_LSA",
 
 
 def ospf_lsa_checksum(lsa):
-    """ Fletcher checksum for OSPF LSAs, returned as a 2 byte string.
-
-    Give the whole LSA packet as argument.
-    For details on the algorithm, see RFC 2328 chapter 12.1.7 and RFC 905 Annex B.
-    """
-    # This is based on the GPLed C implementation in Zebra <http://www.zebra.org/>
-
-    CHKSUM_OFFSET = 16
-
-    if len(lsa) < CHKSUM_OFFSET:
-        raise Exception("LSA Packet too short (%s bytes)" % len(lsa))
-
-    c0 = c1 = 0
-    # Calculation is done with checksum set to zero
-    lsa = lsa[:CHKSUM_OFFSET] + "\x00\x00" + lsa[CHKSUM_OFFSET + 2:]
-    for char in lsa[2:]:  #  leave out age
-        c0 += ord(char)
-        c1 += c0
-
-    c0 %= 255
-    c1 %= 255
-
-    x = ((len(lsa) - CHKSUM_OFFSET - 1) * c0 - c1) % 255
-
-    if (x <= 0):
-        x += 255
-
-    y = 510 - c0 - x
-
-    if (y > 255):
-        y -= 255
-    #checksum = (x << 8) + y
-
-    return chr(x) + chr(y)
+    return fletcher16_checkbytes("\x00\x00" + lsa[2:], 16) # leave out age
 
 
 class OSPF_LSA_Hdr(Packet):
@@ -456,69 +423,6 @@ class OSPF_LSAck(Packet):
 #------------------------------------------------------------------------------
 # OSPFv3
 #------------------------------------------------------------------------------
-# TODO: Add length_from / adjust functionality to IP6Field and remove this class
-class OspfIP6Field(StrField, IP6Field):
-    """
-    Special IP6Field for prefix fields in OSPFv3 LSAs
-    """
-
-    def __init__(self, name, default, length=None, length_from=None):
-        StrField.__init__(self, name, default)
-        self.length_from = length_from
-        if length is not None:
-            self.length_from = lambda pkt, length = length: length
-
-    def any2i(self, pkt, x):
-        return IP6Field.any2i(self, pkt, x)
-
-    def i2repr(self, pkt, x):
-        return IP6Field.i2repr(self, pkt, x)
-
-    def h2i(self, pkt, x):
-        return IP6Field.h2i(self, pkt, x)
-
-    def i2m(self, pkt, x):
-        x = inet_pton(socket.AF_INET6, x)
-        l = self.length_from(pkt)
-        l = self.prefixlen_to_bytelen(l)
-
-        return x[:l]
-
-    def m2i(self, pkt, x):
-        l = self.length_from(pkt)
-
-        prefixlen = self.prefixlen_to_bytelen(l)
-        if l > 128:
-            warning("OspfIP6Field: Prefix length is > 128. Dissection of this packet will fail")
-        else:
-            pad = "\x00" * (16 - prefixlen)
-            x += pad
-
-        return inet_ntop(socket.AF_INET6, x)
-
-    def prefixlen_to_bytelen(self, l):
-        if l <= 32:
-            return 4
-        elif l <= 64:
-            return 8
-        elif l <= 96:
-            return 12
-        else:
-            return 16
-
-    def i2len(self, pkt, x):
-        l = self.length_from(pkt)
-        l = self.prefixlen_to_bytelen(l)
-
-        return l
-
-    def getfield(self, pkt, s):
-        l = self.length_from(pkt)
-        l = self.prefixlen_to_bytelen(l)
-
-        return s[l:], self.m2i(pkt, s[:l])
-
-
 class OSPFv3_Hdr(Packet):
     name = "OSPFv3 Header"
     fields_desc = [ByteField("version", 3),
@@ -678,10 +582,10 @@ class OSPFv3_Inter_Area_Prefix_LSA(OSPF_BaseLSA):
                    ShortField("len", None),
                    ByteField("reserved", 0),
                    X3BytesField("metric", 10),
-                   ByteField("prefixlen", 64),
+                   FieldLenField("prefixlen", None, length_of="prefix", fmt="B"),
                    OSPFv3PrefixOptionsField(),
                    ShortField("reserved2", 0),
-                   OspfIP6Field("prefix", "2001:db8:0:42::", length_from=lambda pkt: pkt.prefixlen)]
+                   IP6PrefixField("prefix", "2001:db8:0:42::/64", wordbytes=4, length_from=lambda pkt: pkt.prefixlen)]
 
 
 class OSPFv3_Inter_Area_Router_LSA(OSPF_BaseLSA):
@@ -694,6 +598,8 @@ class OSPFv3_Inter_Area_Router_LSA(OSPF_BaseLSA):
                    XShortField("chksum", None),
                    ShortField("len", None),
                    ByteField("reserved", 0),
+                   OSPFv3OptionsField(),
+                   ByteField("reserved2", 0),
                    X3BytesField("metric", 1),
                    IPField("router", "2.2.2.2")]
 
@@ -709,10 +615,10 @@ class OSPFv3_AS_External_LSA(OSPF_BaseLSA):
                    ShortField("len", None),
                    FlagsField("flags", 0, 8, ["T", "F", "E"]),
                    X3BytesField("metric", 20),
-                   ByteField("prefixlen", 64),
+                   FieldLenField("prefixlen", None, length_of="prefix", fmt="B"),
                    OSPFv3PrefixOptionsField(),
                    ShortEnumField("reflstype", 0, _OSPFv3_LStypes),
-                   OspfIP6Field("prefix", "2001:db8:0:42::", length_from=lambda pkt: pkt.prefixlen),
+                   IP6PrefixField("prefix", "2001:db8:0:42::/64", wordbytes=4, length_from=lambda pkt: pkt.prefixlen),
                    ConditionalField(IP6Field("fwaddr", "::"), lambda pkt: pkt.flags & 0x02 == 0x02),
                    ConditionalField(IntField("tag", 0), lambda pkt: pkt.flags & 0x01 == 0x01),
                    ConditionalField(IPField("reflsid", 0), lambda pkt: pkt.reflstype != 0)]
@@ -725,10 +631,10 @@ class OSPFv3_Type_7_LSA(OSPFv3_AS_External_LSA):
 
 class OSPFv3_Prefix_Item(Packet):
     name = "OSPFv3 Link Prefix Item"
-    fields_desc = [ByteField("prefixlen", 64),
+    fields_desc = [FieldLenField("prefixlen", None, length_of="prefix", fmt="B"),
                    OSPFv3PrefixOptionsField(),
                    ShortField("metric", 10),
-                   OspfIP6Field("prefix", "2001:db8:0:42::", length_from=lambda pkt: pkt.prefixlen)]
+                   IP6PrefixField("prefix", "2001:db8:0:42::/64", wordbytes=4, length_from=lambda pkt: pkt.prefixlen)]
 
     def extract_padding(self, s):
         return "", s
@@ -746,7 +652,7 @@ class OSPFv3_Link_LSA(OSPF_BaseLSA):
                    ByteField("prio", 1),
                    OSPFv3OptionsField(),
                    IP6Field("lladdr", "fe80::"),
-                   IntField("prefixes", 0),
+                   FieldLenField("prefixes", None, count_of="prefixlist", fmt="I"),
                    PacketListField("prefixlist", None, OSPFv3_Prefix_Item,
                                   count_from = lambda pkt: pkt.prefixes)]
 
@@ -760,7 +666,7 @@ class OSPFv3_Intra_Area_Prefix_LSA(OSPF_BaseLSA):
                    XIntField("seq", 0x80000001),
                    XShortField("chksum", None),
                    ShortField("len", None),
-                   ShortField("prefixes", 0),
+                   FieldLenField("prefixes", None, count_of="prefixlist", fmt="H"),
                    ShortEnumField("reflstype", 0, _OSPFv3_LStypes),
                    IPField("reflsid", "0.0.0.0"),
                    IPField("refadrouter", "0.0.0.0"),
diff --git a/scapy/fields.py b/scapy/fields.py
index b4b69aac6a4ead1086a36f15bbaff0b41e1592c1..50eebd0da51063855fa1bea252ff4c405944c543 100644
--- a/scapy/fields.py
+++ b/scapy/fields.py
@@ -412,7 +412,10 @@ class PacketListField(PacketField):
     def i2len(self, pkt, val):
         return sum( len(p) for p in val )
     def do_copy(self, x):
-        return map(lambda p:p.copy(), x)
+        if x is None:
+            return None
+        else:
+            return map(lambda p:p.copy(), x)
     def getfield(self, pkt, s):
         c = l = None
         if self.length_from is not None:
@@ -509,16 +512,25 @@ class StrLenField(StrField):
     def getfield(self, pkt, s):
         l = self.length_from(pkt)
         return s[l:], self.m2i(pkt,s[:l])
+    
+class BoundStrLenField(StrLenField):
+    def __init__(self,name, default, minlen= 0, maxlen= 255, fld=None, length_from=None):
+        StrLenField.__init__(self, name, default, fld, length_from)
+        self.minlen= minlen
+        self.maxlen= maxlen
+    
+    def randval(self):
+        return RandBin(RandNum(self.minlen, self.maxlen))
 
 class FieldListField(Field):
     islist=1
     def __init__(self, name, default, field, length_from=None, count_from=None):
         if default is None:
             default = []  # Create a new list for each instance
+        self.field = field
         Field.__init__(self, name, default)
         self.count_from = count_from
         self.length_from = length_from
-        self.field = field            
             
     def i2count(self, pkt, val):
         if type(val) is list:
@@ -533,9 +545,11 @@ class FieldListField(Field):
         return val
     def any2i(self, pkt, x):
         if type(x) is not list:
-            return [x]
+            return [self.field.any2i(pkt, x)]
         else:
-            return x
+            return map(lambda e, pkt=pkt: self.field.any2i(pkt, e), x)
+    def i2repr(self, pkt, x):
+        return map(lambda e, pkt=pkt: self.field.i2repr(pkt,e), x)
     def addfield(self, pkt, s, val):
         val = self.i2m(pkt, val)
         for v in val:
@@ -916,3 +930,76 @@ class FixedPointField(BitField):
         return int_part+frac_part
     def i2repr(self, pkt, val):
         return self.i2h(pkt, val)
+
+
+# Base class for IPv4 and IPv6 Prefixes inspired by IPField and IP6Field.
+# Machine values are encoded in a multiple of wordbytes bytes.
+class _IPPrefixFieldBase(Field):
+    def __init__(self, name, default, wordbytes, maxbytes, aton, ntoa, length_from):
+        self.wordbytes= wordbytes
+        self.maxbytes= maxbytes
+        self.aton= aton
+        self.ntoa= ntoa
+        Field.__init__(self, name, default, "%is" % self.maxbytes)
+        self.length_from= length_from
+    
+    def _numbytes(self, pfxlen):
+        wbits= self.wordbytes * 8
+        return ((pfxlen + (wbits - 1)) / wbits) * self.wordbytes
+    
+    def h2i(self, pkt, x):
+        # "fc00:1::1/64" -> ("fc00:1::1", 64)
+        [pfx,pfxlen]= x.split('/')
+        self.aton(pfx) # check for validity
+        return (pfx, int(pfxlen))
+
+
+    def i2h(self, pkt, x):
+        # ("fc00:1::1", 64) -> "fc00:1::1/64"
+        (pfx,pfxlen)= x
+        return "%s/%i" % (pfx,pfxlen)
+
+    def i2m(self, pkt, x):
+        # ("fc00:1::1", 64) -> ("\xfc\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 64)
+        (pfx,pfxlen)= x
+        s= self.aton(pfx);
+        return (s[:self._numbytes(pfxlen)], pfxlen)
+    
+    def m2i(self, pkt, x):
+        # ("\xfc\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 64) -> ("fc00:1::1", 64)
+        (s,pfxlen)= x
+        
+        if len(s) < self.maxbytes:
+            s= s + ("\0" * (self.maxbytes - len(s)))
+        return (self.ntoa(s), pfxlen)
+    
+    def any2i(self, pkt, x):
+        if x is None:
+            return (self.ntoa("\0"*self.maxbytes), 1)
+        
+        return self.h2i(pkt,x)
+    
+    def i2len(self, pkt, x):
+        (_,pfxlen)= x
+        return pfxlen
+        
+    def addfield(self, pkt, s, val):
+        (rawpfx,pfxlen)= self.i2m(pkt,val)
+        fmt= "!%is" % self._numbytes(pfxlen)
+        return s+struct.pack(fmt, rawpfx)
+    
+    def getfield(self, pkt, s):
+        pfxlen= self.length_from(pkt)
+        numbytes= self._numbytes(pfxlen)
+        fmt= "!%is" % numbytes
+        return s[numbytes:], self.m2i(pkt, (struct.unpack(fmt, s[:numbytes])[0], pfxlen))
+
+
+class IPPrefixField(_IPPrefixFieldBase):
+    def __init__(self, name, default, wordbytes=1, length_from= None):
+        _IPPrefixFieldBase.__init__(self, name, default, wordbytes, 4, inet_aton, inet_ntoa, length_from)
+
+
+class IP6PrefixField(_IPPrefixFieldBase):
+    def __init__(self, name, default, wordbytes= 1, length_from= None):
+        _IPPrefixFieldBase.__init__(self, name, default, wordbytes, 16, lambda a: inet_pton(socket.AF_INET6, a), lambda n: inet_ntop(socket.AF_INET6, n), length_from)
\ No newline at end of file
diff --git a/scapy/layers/clns.py b/scapy/layers/clns.py
new file mode 100644
index 0000000000000000000000000000000000000000..37a2f51748d2f6f608416fb7b66c1d4a1c008603
--- /dev/null
+++ b/scapy/layers/clns.py
@@ -0,0 +1,86 @@
+"""
+    CLNS Extension
+    ~~~~~~~~~~~~~~~~~~~~~
+
+    :copyright: 2014 BENOCS GmbH, Berlin (Germany)
+    :author:    Marcel Patzlaff, mpatzlaff@benocs.com
+    :license:   GPLv2
+
+        This module is free software; you can redistribute it and/or
+        modify it under the terms of the GNU General Public License
+        as published by the Free Software Foundation; either version 2
+        of the License, or (at your option) any later version.
+
+        This module is distributed in the hope that it will be useful,
+        but WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+        GNU General Public License for more details.
+
+    :description:
+
+        This module provides a layer and registration function for
+        OSI Connectionless-mode Network Services (such as IS-IS).
+                
+    :TODO:
+
+        - rework this if a better way is found/implemented to bind
+          protocols such as IS-IS (or if IS-IS remains the sole CLN
+          protocol)
+
+"""
+import struct
+
+from scapy.config import conf
+from scapy.fields import ByteEnumField, PacketField
+from scapy.layers.l2 import LLC
+from scapy.packet import Packet, bind_layers
+
+
+network_layer_protocol_ids= {
+    0x00 : "Null",
+    0x08 : "Q.933",
+    0x80 : "IEEE SNAP",
+    0x81 : "ISO 8438 CLNP",
+    0x82 : "ISO 9542 ES-IS",
+    0x83 : "ISO 10589 IS-IS",
+    0x8E : "IPv6",
+    0xB0 : "FRF.9",
+    0xB1 : "FRF.12",
+    0xC0 : "TRILL",
+    0xC1 : "IEEE 802.aq",
+    0xCC : "IPv4",
+    0xCF : "PPP"
+}
+
+
+_cln_protocols= {}
+
+class _GenericClnsPdu(Packet):
+    name= "Generic CLNS PDU"
+    fields_desc= [
+        ByteEnumField("nlpid", 0x00, network_layer_protocol_ids),
+        PacketField("rawdata", None, conf.raw_layer)
+    ]
+    
+
+class ConnectionlessNetworkService(Packet):
+    name= "Connectionless-mode Network Service"
+    
+    def guess_payload_class(self, p):
+        cls= conf.raw_layer
+         
+        if len(p) >= 1:
+            nlpid = struct.unpack("!B", p[0])[0]
+            cls= _cln_protocols.get(nlpid, _GenericClnsPdu)
+             
+        return cls
+
+@conf.commands.register
+def register_cln_protocol(nlpid, cln_protocol_class):
+    if nlpid is None or cln_protocol_class is None:
+        return
+    
+    _cln_protocols[nlpid]= cln_protocol_class
+
+
+bind_layers(LLC, ConnectionlessNetworkService, dsap=0xfe, ssap=0xfe, ctrl=3)
\ No newline at end of file
diff --git a/scapy/utils.py b/scapy/utils.py
index 07b00ab4e877f86c1693e3de390af24632300510..e4613094b8949e1054c785dc3ab56987c8c915c5 100644
--- a/scapy/utils.py
+++ b/scapy/utils.py
@@ -237,6 +237,60 @@ else:
         s = ~s
         return (((s>>8)&0xff)|s<<8) & 0xffff
 
+
+def _fletcher16(charbuf):
+    # This is based on the GPLed C implementation in Zebra <http://www.zebra.org/>
+    c0 = c1 = 0
+    for char in charbuf:
+        c0 += ord(char)
+        c1 += c0
+
+    c0 %= 255
+    c1 %= 255
+    return (c0,c1)
+
+@conf.commands.register
+def fletcher16_checksum(binbuf):
+    """ Calculates Fletcher-16 checksum of the given buffer.
+        
+        Note:
+        If the buffer contains the two checkbytes derived from the Fletcher-16 checksum
+        the result of this function has to be 0. Otherwise the buffer has been corrupted.
+    """
+    (c0,c1)= _fletcher16(binbuf)
+    return (c1 << 8) | c0
+
+
+@conf.commands.register
+def fletcher16_checkbytes(binbuf, offset):
+    """ Calculates the Fletcher-16 checkbytes returned as 2 byte binary-string.
+    
+        Including the bytes into the buffer (at the position marked by offset) the
+        global Fletcher-16 checksum of the buffer will be 0. Thus it is easy to verify
+        the integrity of the buffer on the receiver side.
+        
+        For details on the algorithm, see RFC 2328 chapter 12.1.7 and RFC 905 Annex B.
+    """
+    
+    # This is based on the GPLed C implementation in Zebra <http://www.zebra.org/>
+    if len(binbuf) < offset:
+        raise Exception("Packet too short for checkbytes %d" % len(binbuf))
+
+    binbuf = binbuf[:offset] + "\x00\x00" + binbuf[offset + 2:]
+    (c0,c1)= _fletcher16(binbuf)
+
+    x = ((len(binbuf) - offset - 1) * c0 - c1) % 255
+
+    if (x <= 0):
+        x += 255
+
+    y = 510 - c0 - x
+
+    if (y > 255):
+        y -= 255
+    return chr(x) + chr(y)
+
+
 def warning(x):
     log_runtime.warning(x)