diff --git a/scapy/asn1/asn1.py b/scapy/asn1/asn1.py
index c8c42f72d40ffe74382809d30bdf1f7a630b3549..5e1866da5aae6d0152f6b42acfac575baf50b350 100644
--- a/scapy/asn1/asn1.py
+++ b/scapy/asn1/asn1.py
@@ -161,7 +161,9 @@ class ASN1_Class_UNIVERSAL(ASN1_Class):
     BMP_STRING = 30
     IPADDRESS = 0x40
     COUNTER32 = 0x41
+    GAUGE32 = 0x42
     TIME_TICKS = 0x43
+    SEP = 0x80
 
 class ASN1_Object_metaclass(type):
     def __new__(cls, name, bases, dct):
@@ -246,15 +248,27 @@ class ASN1_IPADDRESS(ASN1_STRING):
 class ASN1_UTC_TIME(ASN1_STRING):
     tag = ASN1_Class_UNIVERSAL.UTC_TIME
 
+class ASN1_GENERALIZED_TIME(ASN1_STRING):
+    tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME
+
 class ASN1_TIME_TICKS(ASN1_INTEGER):
     tag = ASN1_Class_UNIVERSAL.TIME_TICKS
 
 class ASN1_BOOLEAN(ASN1_INTEGER):
     tag = ASN1_Class_UNIVERSAL.BOOLEAN
+
+class ASN1_ENUMERATED(ASN1_INTEGER):
+    tag = ASN1_Class_UNIVERSAL.ENUMERATED
     
 class ASN1_NULL(ASN1_INTEGER):
     tag = ASN1_Class_UNIVERSAL.NULL
 
+class ASN1_SEP(ASN1_NULL):
+    tag = ASN1_Class_UNIVERSAL.SEP
+
+class ASN1_GAUGE32(ASN1_INTEGER):
+    tag = ASN1_Class_UNIVERSAL.GAUGE32
+    
 class ASN1_COUNTER32(ASN1_INTEGER):
     tag = ASN1_Class_UNIVERSAL.COUNTER32
     
@@ -276,6 +290,8 @@ class ASN1_OID(ASN1_Object):
         ASN1_Object.__init__(self, val)
     def __repr__(self):
         return "<%s[%r]>" % (self.__dict__.get("name", self.__class__.__name__), conf.mib._oidname(self.val))
+    def __oidname__(self):
+        return '%s'%conf.mib._oidname(self.val)
     
 
 
diff --git a/scapy/asn1/ber.py b/scapy/asn1/ber.py
index 25c913dd63388d44329b4fca4159df82b260d56a..371274bf66950de660f393b0f5ddf7094c5507c0 100644
--- a/scapy/asn1/ber.py
+++ b/scapy/asn1/ber.py
@@ -223,6 +223,9 @@ class BERcodec_INTEGER(BERcodec_Object):
 class BERcodec_BOOLEAN(BERcodec_INTEGER):
     tag = ASN1_Class_UNIVERSAL.BOOLEAN
 
+class BERcodec_ENUMERATED(BERcodec_INTEGER):
+    tag = ASN1_Class_UNIVERSAL.ENUMERATED
+
 class BERcodec_NULL(BERcodec_INTEGER):
     tag = ASN1_Class_UNIVERSAL.NULL
     @classmethod
@@ -232,6 +235,9 @@ class BERcodec_NULL(BERcodec_INTEGER):
         else:
             return super(cls,cls).enc(i)
 
+class BERcodec_SEP(BERcodec_NULL):
+    tag = ASN1_Class_UNIVERSAL.SEP
+
 class BERcodec_STRING(BERcodec_Object):
     tag = ASN1_Class_UNIVERSAL.STRING
     @classmethod
@@ -277,9 +283,15 @@ class BERcodec_IPADDRESS(BERcodec_STRING):
 class BERcodec_UTC_TIME(BERcodec_STRING):
     tag = ASN1_Class_UNIVERSAL.UTC_TIME
 
+class BERcodec_GENERALIZED_TIME(BERcodec_STRING):
+    tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME
+
 class BERcodec_TIME_TICKS(BERcodec_INTEGER):
     tag = ASN1_Class_UNIVERSAL.TIME_TICKS
 
+class BERcodec_GAUGE32(BERcodec_INTEGER):
+    tag = ASN1_Class_UNIVERSAL.GAUGE32
+
 class BERcodec_COUNTER32(BERcodec_INTEGER):
     tag = ASN1_Class_UNIVERSAL.COUNTER32
 
diff --git a/scapy/asn1fields.py b/scapy/asn1fields.py
index 83722125e8b6298d606d83cfc6e7c1d6d0ac4ec0..c32fbe31b6bcb86fa6116478d217ec48a05e63d2 100644
--- a/scapy/asn1fields.py
+++ b/scapy/asn1fields.py
@@ -123,6 +123,9 @@ class ASN1F_BOOLEAN(ASN1F_field):
 class ASN1F_NULL(ASN1F_INTEGER):
     ASN1_tag= ASN1_Class_UNIVERSAL.NULL
 
+class ASN1F_SEP(ASN1F_NULL):
+    ASN1_tag= ASN1_Class_UNIVERSAL.SEP
+
 class ASN1F_enum_INTEGER(ASN1F_INTEGER):
     def __init__(self, name, default, enum):
         ASN1F_INTEGER.__init__(self, name, default)
@@ -155,6 +158,9 @@ class ASN1F_enum_INTEGER(ASN1F_INTEGER):
         else:
             return self.i2repr_one(pkt,x)
 
+class ASN1F_ENUMERATED(ASN1F_enum_INTEGER):
+    ASN1_tag = ASN1_Class_UNIVERSAL.ENUMERATED
+
 class ASN1F_STRING(ASN1F_field):
     ASN1_tag = ASN1_Class_UNIVERSAL.STRING
     def randval(self):
@@ -175,6 +181,9 @@ class ASN1F_TIME_TICKS(ASN1F_INTEGER):
 class ASN1F_UTC_TIME(ASN1F_STRING):
     ASN1_tag = ASN1_Class_UNIVERSAL.UTC_TIME
 
+class ASN1F_GENERALIZED_TIME(ASN1F_STRING):
+    ASN1_tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME
+
 class ASN1F_OID(ASN1F_field):
     ASN1_tag = ASN1_Class_UNIVERSAL.OID
     def randval(self):
diff --git a/scapy/base_classes.py b/scapy/base_classes.py
index 6d36053c021c16386dc593b9037da18273863ae6..c2fa4b73aa9611f6ddd6a296d1092b988047770c 100644
--- a/scapy/base_classes.py
+++ b/scapy/base_classes.py
@@ -46,28 +46,34 @@ class Net(Gen):
     """Generate a list of IPs from a network address or a name"""
     name = "ip"
     ipaddress = re.compile(r"^(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)\.(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)\.(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)\.(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)(/[0-3]?[0-9])?$")
-    def __init__(self, net):
-        self.repr=net
 
+    @staticmethod
+    def _parse_digit(a,netmask):
+        netmask = min(8,max(netmask,0))
+        if a == "*":
+            a = (0,256)
+        elif a.find("-") >= 0:
+            x,y = map(int,a.split("-"))
+            if x > y:
+                y = x
+            a = (x &  (0xffL<<netmask) , max(y, (x | (0xffL>>(8-netmask))))+1)
+        else:
+            a = (int(a) & (0xffL<<netmask),(int(a) | (0xffL>>(8-netmask)))+1)
+        return a
+
+    @classmethod
+    def _parse_net(cls, net):
         tmp=net.split('/')+["32"]
-        if not self.ipaddress.match(net):
+        if not cls.ipaddress.match(net):
             tmp[0]=socket.gethostbyname(tmp[0])
         netmask = int(tmp[1])
+        return map(lambda x,y: cls._parse_digit(x,y), tmp[0].split("."), map(lambda x,nm=netmask: x-nm, (8,16,24,32))),netmask
+
+    def __init__(self, net):
+        self.repr=net
+        self.parsed,self.netmask = self._parse_net(net)
 
-        def parse_digit(a,netmask):
-            netmask = min(8,max(netmask,0))
-            if a == "*":
-                a = (0,256)
-            elif a.find("-") >= 0:
-                x,y = map(int,a.split("-"))
-                if x > y:
-                    y = x
-                a = (x &  (0xffL<<netmask) , max(y, (x | (0xffL>>(8-netmask))))+1)
-            else:
-                a = (int(a) & (0xffL<<netmask),(int(a) | (0xffL>>(8-netmask)))+1)
-            return a
 
-        self.parsed = map(lambda x,y: parse_digit(x,y), tmp[0].split("."), map(lambda x,nm=netmask: x-nm, (8,16,24,32)))
                                                                                                
     def __iter__(self):
         for d in xrange(*self.parsed[3]):
@@ -83,6 +89,24 @@ class Net(Gen):
                           
     def __repr__(self):
         return "Net(%r)" % self.repr
+    def __eq__(self, other):
+        if hasattr(other, "parsed"):
+            p2 = other.parsed
+        else:
+            p2,nm2 = self._parse_net(other)
+        return self.parsed == p2
+    def __contains__(self, other):
+        if hasattr(other, "parsed"):
+            p2 = other.parsed
+        else:
+            p2,nm2 = self._parse_net(other)
+        for (a1,b1),(a2,b2) in zip(self.parsed,p2):
+            if a1 > a2 or b1 < b2:
+                return False
+        return True
+    def __rcontains__(self, other):        
+        return self in self.__class__(other)
+        
 
 class OID(Gen):
     name = "OID"
diff --git a/scapy/layers/inet6.py b/scapy/layers/inet6.py
index 5466e985721c3bae2c465fd2c57beaf0338057f2..5f5314d2b9bf3254ae12ae98d4adcb8a159b4345 100644
--- a/scapy/layers/inet6.py
+++ b/scapy/layers/inet6.py
@@ -206,6 +206,8 @@ class IP6Field(Field):
                 vaddr = in6_6to4ExtractAddr(x)
                 return "%s [6to4 GW: %s]" % (self.i2h(pkt, x), vaddr)
         return self.i2h(pkt, x)       # No specific information to return
+    def randval(self):
+        return RandIP6()
 
 class SourceIP6Field(IP6Field):
     def __init__(self, name, dstname):
diff --git a/scapy/layers/isakmp.py b/scapy/layers/isakmp.py
index 8dd60ad8c069cad0a25764cb9c4fe19f05337473..ccbad10deb2a29906499abfb01122d423b20dc95 100644
--- a/scapy/layers/isakmp.py
+++ b/scapy/layers/isakmp.py
@@ -7,7 +7,8 @@ import struct
 from scapy.packet import *
 from scapy.fields import *
 from scapy.ansmachine import *
-from scapy.layers.inet import UDP
+from scapy.layers.inet import IP,UDP
+from scapy.sendrecv import sr
 
 
 # see http://www.iana.org/assignments/ipsec-registry for details
diff --git a/scapy/modules/p0f.py b/scapy/modules/p0f.py
index 28542edfa6f578048e882a24ccb42e2e662e12ed..ebcf68d05940be09298b95365ccd5d3692906b78 100644
--- a/scapy/modules/p0f.py
+++ b/scapy/modules/p0f.py
@@ -5,8 +5,13 @@
 
 from scapy.data import KnowledgeBase
 from scapy.config import conf
+from scapy.layers.inet import IP, TCP, TCPOptions
+from scapy.packet import NoPayload
 
 conf.p0f_base ="/etc/p0f/p0f.fp"
+conf.p0fa_base ="/etc/p0f/p0fa.fp"
+conf.p0fr_base ="/etc/p0f/p0fr.fp"
+conf.p0fo_base ="/etc/p0f/p0fo.fp"
 
 
 ###############
@@ -26,8 +31,6 @@ conf.p0f_base ="/etc/p0f/p0f.fp"
 # OS      - OS genre
 # details - OS description
 
-
-
 class p0fKnowledgeBase(KnowledgeBase):
     def __init__(self, filename):
         KnowledgeBase.__init__(self, filename)
@@ -46,7 +49,11 @@ class p0fKnowledgeBase(KnowledgeBase):
                 l = tuple(l.split(":"))
                 if len(l) < 8:
                     continue
-                li = map(int,l[1:4])
+                def a2i(x):
+                    if x.isdigit():
+                        return int(x)
+                    return x
+                li = map(a2i, l[1:4])
                 #if li[0] not in self.ttl_range:
                 #    self.ttl_range.append(li[0])
                 #    self.ttl_range.sort()
@@ -57,38 +64,70 @@ class p0fKnowledgeBase(KnowledgeBase):
         f.close()
 
 p0f_kdb = p0fKnowledgeBase(conf.p0f_base)
+p0fa_kdb = p0fKnowledgeBase(conf.p0fa_base)
+p0fr_kdb = p0fKnowledgeBase(conf.p0fr_base)
+p0fo_kdb = p0fKnowledgeBase(conf.p0fo_base)
 
+def p0f_selectdb(flags):
+    # tested flags: S, R, A
+    if flags & 0x16 == 0x2:
+        # SYN
+        return p0f_kdb
+    elif flags & 0x16 == 0x12:
+        # SYN/ACK
+        return p0fa_kdb
+    elif flags & 0x16 in [ 0x4, 0x14 ]:
+        # RST RST/ACK
+        return p0fr_kdb
+    elif flags & 0x16 == 0x10:
+        # ACK
+        return p0fo_kdb
+    else:
+        return None
 
 def packet2p0f(pkt):
+    pkt = pkt.copy()
+    pkt = pkt.__class__(str(pkt))
     while pkt.haslayer(IP) and pkt.haslayer(TCP):
         pkt = pkt.getlayer(IP)
         if isinstance(pkt.payload, TCP):
             break
         pkt = pkt.payload
-
+    
     if not isinstance(pkt, IP) or not isinstance(pkt.payload, TCP):
         raise TypeError("Not a TCP/IP packet")
-    if pkt.payload.flags & 0x13 != 0x02: #S,!A,!F
-        raise TypeError("Not a syn packet")
+    #if pkt.payload.flags & 0x7 != 0x02: #S,!F,!R
+    #    raise TypeError("Not a SYN or SYN/ACK packet")
+    
+    db = p0f_selectdb(pkt.payload.flags)
     
     #t = p0f_kdb.ttl_range[:]
     #t += [pkt.ttl]
     #t.sort()
     #ttl=t[t.index(pkt.ttl)+1]
     ttl = pkt.ttl
-
+    
     df = (pkt.flags & 2) / 2
     ss = len(pkt)
     # from p0f/config.h : PACKET_BIG = 100
     if ss > 100:
-        ss = 0
-
+        if db == p0fr_kdb:
+            # p0fr.fp: "Packet size may be wildcarded. The meaning of
+            #           wildcard is, however, hardcoded as 'size >
+            #           PACKET_BIG'"
+            ss = '*'
+        else:
+            ss = 0
+    if db == p0fo_kdb:
+        # p0fo.fp: "Packet size MUST be wildcarded."
+        ss = '*'
+    
     ooo = ""
     mss = -1
     qqT = False
     qqP = False
     #qqBroken = False
-    ilen = (pkt[TCP].dataofs << 2) - 20 # from p0f.c
+    ilen = (pkt.payload.dataofs << 2) - 20 # from p0f.c
     for option in pkt.payload.options:
         ilen -= 1
         if option[0] == "MSS":
@@ -118,60 +157,85 @@ def packet2p0f(pkt):
             if ilen > 0:
                 qqP = True
         else:
-            ooo += "?,"
+            if type(option[0]) is str:
+                ooo += "?%i," % TCPOptions[1][option[0]]
+            else:
+                ooo += "?%i," % option[0]
             # FIXME: ilen
     ooo = ooo[:-1]
     if ooo == "": ooo = "."
-
+    
     win = pkt.payload.window
     if mss != -1:
-        if win % mss == 0:
+        if mss != 0 and win % mss == 0:
             win = "S" + str(win/mss)
         elif win % (mss + 40) == 0:
             win = "T" + str(win/(mss+40))
-        win = str(win)
-
+    win = str(win)
+    
     qq = ""
-
+    
+    if db == p0fr_kdb:
+        if pkt.payload.flags & 0x10 == 0x10:
+            # p0fr.fp: "A new quirk, 'K', is introduced to denote
+            #           RST+ACK packets"
+            qq += "K"
+    # The two next cases should also be only for p0f*r*, but although
+    # it's not documented (or I have not noticed), p0f seems to
+    # support the '0' and 'Q' quirks on any databases (or at the least
+    # "classical" p0f.fp).
+    if pkt.payload.seq == pkt.payload.ack:
+        # p0fr.fp: "A new quirk, 'Q', is used to denote SEQ number
+        #           equal to ACK number."
+        qq += "Q"
+    if pkt.payload.seq == 0:
+        # p0fr.fp: "A new quirk, '0', is used to denote packets
+        #           with SEQ number set to 0."
+        qq += "0"
     if qqP:
         qq += "P"
-    if pkt[IP].id == 0:
+    if pkt.id == 0:
         qq += "Z"
-    if pkt[IP].options != '':
+    if pkt.options != []:
         qq += "I"
-    if pkt[TCP].urgptr != 0:
+    if pkt.payload.urgptr != 0:
         qq += "U"
-    if pkt[TCP].reserved != 0:
+    if pkt.payload.reserved != 0:
         qq += "X"
-    if pkt[TCP].ack != 0:
+    if pkt.payload.ack != 0:
         qq += "A"
     if qqT:
         qq += "T"
-    if pkt[TCP].flags & 40 != 0:
-        # U or P
-        qq += "F"
-    if not isinstance(pkt[TCP].payload, NoPayload):
+    if db == p0fo_kdb:
+        if pkt.payload.flags & 0x20 != 0:
+            # U
+            # p0fo.fp: "PUSH flag is excluded from 'F' quirk checks"
+            qq += "F"
+    else:
+        if pkt.payload.flags & 0x28 != 0:
+            # U or P
+            qq += "F"
+    if db != p0fo_kdb and not isinstance(pkt.payload.payload, NoPayload):
+        # p0fo.fp: "'D' quirk is not checked for."
         qq += "D"
-    # FIXME : "!" - broken options segment
+    # FIXME : "!" - broken options segment: not handled yet
 
     if qq == "":
         qq = "."
 
-    return (win,
-            ttl,
-            df,
-            ss,
-            ooo,
-            qq)
+    return (db, (win, ttl, df, ss, ooo, qq))
 
 def p0f_correl(x,y):
     d = 0
-    # wwww can be "*" or "%nn"
+    # wwww can be "*" or "%nn". "Tnn" and "Snn" should work fine with
+    # the x[0] == y[0] test.
     d += (x[0] == y[0] or y[0] == "*" or (y[0][0] == "%" and x[0].isdigit() and (int(x[0]) % int(y[0][1:])) == 0))
     # ttl
     d += (y[1] >= x[1] and y[1] - x[1] < 32)
-    for i in [2, 3, 5]:
-        d += (x[i] == y[i])
+    for i in [2, 5]:
+        d += (x[i] == y[i] or y[i] == '*')
+    # '*' has a special meaning for ss
+    d += x[3] == y[3]
     xopt = x[4].split(",")
     yopt = y[4].split(",")
     if len(xopt) == len(yopt):
@@ -192,31 +256,34 @@ def p0f_correl(x,y):
 
 @conf.commands.register
 def p0f(pkt):
-    """Passive OS fingerprinting: which OS emitted this TCP SYN ?
+    """Passive OS fingerprinting: which OS emitted this TCP packet ?
 p0f(packet) -> accuracy, [list of guesses]
 """
-    pb = p0f_kdb.get_base()
+    db, sig = packet2p0f(pkt)
+    if db:
+        pb = db.get_base()
+    else:
+        pb = []
     if not pb:
         warning("p0f base empty.")
         return []
-    s = len(pb[0][0])
+    #s = len(pb[0][0])
     r = []
-    sig = packet2p0f(pkt)
     max = len(sig[4].split(",")) + 5
     for b in pb:
         d = p0f_correl(sig,b)
         if d == max:
             r.append((b[6], b[7], b[1] - pkt[IP].ttl))
     return r
-            
 
 def prnp0f(pkt):
+    # we should print which DB we use
     try:
         r = p0f(pkt)
     except:
         return
     if r == []:
-        r = ("UNKNOWN", "[" + ":".join(map(str, packet2p0f(pkt))) + ":?:?]", None)
+        r = ("UNKNOWN", "[" + ":".join(map(str, packet2p0f(pkt)[1])) + ":?:?]", None)
     else:
         r = r[0]
     uptime = None
@@ -228,16 +295,16 @@ def prnp0f(pkt):
         uptime = None
     res = pkt.sprintf("%IP.src%:%TCP.sport% - " + r[0] + " " + r[1])
     if uptime is not None:
-        res += pkt.sprintf(" (up: " + str(uptime/3600) + " hrs)\n  -> %IP.dst%:%TCP.dport%")
+        res += pkt.sprintf(" (up: " + str(uptime/3600) + " hrs)\n  -> %IP.dst%:%TCP.dport% (%TCP.flags%)")
     else:
-        res += pkt.sprintf("\n  -> %IP.dst%:%TCP.dport%")
+        res += pkt.sprintf("\n  -> %IP.dst%:%TCP.dport% (%TCP.flags%)")
     if r[2] is not None:
         res += " (distance " + str(r[2]) + ")"
     print res
 
 @conf.commands.register
 def pkt2uptime(pkt, HZ=100):
-    """Calculate the date the machine which emitted the packet booted using TCP timestamp
+    """Calculate the date the machine which emitted the packet booted using TCP timestamp 
 pkt2uptime(pkt, [HZ=100])"""
     if not isinstance(pkt, Packet):
         raise TypeError("Not a TCP packet")
@@ -253,4 +320,219 @@ pkt2uptime(pkt, [HZ=100])"""
             return t
     raise TypeError("No timestamp option")
 
+def p0f_impersonate(pkt, osgenre=None, osdetails=None, signature=None,
+                    extrahops=0, mtu=1500, uptime=None):
+    """Modifies pkt so that p0f will think it has been sent by a
+specific OS.  If osdetails is None, then we randomly pick up a
+personality matching osgenre. If osgenre and signature are also None,
+we use a local signature (using p0f_getlocalsigs). If signature is
+specified (as a tuple), we use the signature.
+
+For now, only TCP Syn packets are supported.
+Some specifications of the p0f.fp file are not (yet) implemented."""
+    pkt = pkt.copy()
+    #pkt = pkt.__class__(str(pkt))
+    while pkt.haslayer(IP) and pkt.haslayer(TCP):
+        pkt = pkt.getlayer(IP)
+        if isinstance(pkt.payload, TCP):
+            break
+        pkt = pkt.payload
+    
+    if not isinstance(pkt, IP) or not isinstance(pkt.payload, TCP):
+        raise TypeError("Not a TCP/IP packet")
+    
+    if uptime is None:
+        uptime = random.randint(120,100*60*60*24*365)
+    
+    db = p0f_selectdb(pkt.payload.flags)
+    if osgenre:
+        pb = db.get_base()
+        if pb is None:
+            pb = []
+        pb = filter(lambda x: x[6] == osgenre, pb)
+        if osdetails:
+            pb = filter(lambda x: x[7] == osdetails, pb)
+    elif signature:
+        pb = [signature]
+    else:
+        pb = p0f_getlocalsigs()[db]
+    if db == p0fr_kdb:
+        # 'K' quirk <=> RST+ACK
+        if pkt.payload.flags & 0x4 == 0x4:
+            pb = filter(lambda x: 'K' in x[5], pb)
+        else:
+            pb = filter(lambda x: 'K' not in x[5], pb)
+    if not pb:
+        raise Scapy_Exception("No match in the p0f database")
+    pers = pb[random.randint(0, len(pb) - 1)]
+    
+    # options (we start with options because of MSS)
+    ## TODO: let the options already set if they are valid
+    options = []
+    if pers[4] != '.':
+        for opt in pers[4].split(','):
+            if opt[0] == 'M':
+                # MSS might have a maximum size because of window size
+                # specification
+                if pers[0][0] == 'S':
+                    maxmss = (2L**16-1) / int(pers[0][1:])
+                else:
+                    maxmss = (2L**16-1)
+                # If we have to randomly pick up a value, we cannot use
+                # scapy RandXXX() functions, because the value has to be
+                # set in case we need it for the window size value. That's
+                # why we use random.randint()
+                if opt[1:] == '*':
+                    options.append(('MSS', random.randint(1,maxmss)))
+                elif opt[1] == '%':
+                    coef = int(opt[2:])
+                    options.append(('MSS', coef*random.randint(1,maxmss/coef)))
+                else:
+                    options.append(('MSS', int(opt[1:])))
+            elif opt[0] == 'W':
+                if opt[1:] == '*':
+                    options.append(('WScale', RandByte()))
+                elif opt[1] == '%':
+                    coef = int(opt[2:])
+                    options.append(('WScale', coef*RandNum(min=1,
+                                                           max=(2L**8-1)/coef)))
+                else:
+                    options.append(('WScale', int(opt[1:])))
+            elif opt == 'T0':
+                options.append(('Timestamp', (0, 0)))
+            elif opt == 'T':
+                if 'T' in pers[5]:
+                    # FIXME: RandInt() here does not work (bug (?) in
+                    # TCPOptionsField.m2i often raises "OverflowError:
+                    # long int too large to convert to int" in:
+                    #    oval = struct.pack(ofmt, *oval)"
+                    # Actually, this is enough to often raise the error:
+                    #    struct.pack('I', RandInt())
+                    options.append(('Timestamp', (uptime, random.randint(1,2**32-1))))
+                else:
+                    options.append(('Timestamp', (uptime, 0)))
+            elif opt == 'S':
+                options.append(('SAckOK', ''))
+            elif opt == 'N':
+                options.append(('NOP', None))
+            elif opt == 'E':
+                options.append(('EOL', None))
+            elif opt[0] == '?':
+                if int(opt[1:]) in TCPOptions[0]:
+                    optname = TCPOptions[0][int(opt[1:])][0]
+                    optstruct = TCPOptions[0][int(opt[1:])][1]
+                    options.append((optname,
+                                    struct.unpack(optstruct,
+                                                  RandString(struct.calcsize(optstruct))._fix())))
+                else:
+                    options.append((int(opt[1:]), ''))
+            ## FIXME: qqP not handled
+            else:
+                warning("unhandled TCP option " + opt)
+            pkt.payload.options = options
+    
+    # window size
+    if pers[0] == '*':
+        pkt.payload.window = RandShort()
+    elif pers[0].isdigit():
+        pkt.payload.window = int(pers[0])
+    elif pers[0][0] == '%':
+        coef = int(pers[0][1:])
+        pkt.payload.window = coef * RandNum(min=1,max=(2L**16-1)/coef)
+    elif pers[0][0] == 'T':
+        pkt.payload.window = mtu * int(pers[0][1:])
+    elif pers[0][0] == 'S':
+        ## needs MSS set
+        MSS = filter(lambda x: x[0] == 'MSS', options)
+        if not filter(lambda x: x[0] == 'MSS', options):
+            raise Scapy_Exception("TCP window value requires MSS, and MSS option not set")
+        pkt.payload.window = filter(lambda x: x[0] == 'MSS', options)[0][1] * int(pers[0][1:])
+    else:
+        raise Scapy_Exception('Unhandled window size specification')
+    
+    # ttl
+    pkt.ttl = pers[1]-extrahops
+    # DF flag
+    pkt.flags |= (2 * pers[2])
+    ## FIXME: ss (packet size) not handled (how ? may be with D quirk
+    ## if present)
+    # Quirks
+    if pers[5] != '.':
+        for qq in pers[5]:
+            ## FIXME: not handled: P, I, X, !
+            # T handled with the Timestamp option
+            if qq == 'Z': pkt.id = 0
+            elif qq == 'U': pkt.payload.urgptr = RandShort()
+            elif qq == 'A': pkt.payload.ack = RandInt()
+            elif qq == 'F':
+                if db == p0fo_kdb:
+                    pkt.payload.flags |= 0x20 # U
+                else:
+                    pkt.payload.flags |= RandChoice(8, 32, 40) #P / U / PU
+            elif qq == 'D' and db != p0fo_kdb:
+                pkt /= Raw(load=RandString(random.randint(1, 10))) # XXX p0fo.fp
+            elif qq == 'Q': pkt.payload.seq = pkt.payload.ack
+            #elif qq == '0': pkt.payload.seq = 0
+        #if db == p0fr_kdb:
+        # '0' quirk is actually not only for p0fr.fp (see
+        # packet2p0f())
+    if '0' in pers[5]:
+        pkt.payload.seq = 0
+    elif pkt.payload.seq == 0:
+        pkt.payload.seq = RandInt()
+    
+    while pkt.underlayer:
+        pkt = pkt.underlayer
+    return pkt
+
+def p0f_getlocalsigs():
+    """This function returns a dictionary of signatures indexed by p0f
+db (e.g., p0f_kdb, p0fa_kdb, ...) for the local TCP/IP stack.
+
+You need to have your firewall at least accepting the TCP packets
+from/to a high port (30000 <= x <= 40000) on your loopback interface.
+
+Please note that the generated signatures come from the loopback
+interface and may (are likely to) be different than those generated on
+"normal" interfaces."""
+    pid = os.fork()
+    port = random.randint(30000, 40000)
+    if pid > 0:
+        # parent: sniff
+        result = {}
+        def addresult(res):
+            # TODO: wildcard window size in some cases? and maybe some
+            # other values?
+            if res[0] not in result:
+                result[res[0]] = [res[1]]
+            else:
+                if res[1] not in result[res[0]]:
+                    result[res[0]].append(res[1])
+        # XXX could we try with a "normal" interface using other hosts
+        iface = conf.route.route('127.0.0.1')[0]
+        # each packet is seen twice: S + RA, S + SA + A + FA + A
+        # XXX are the packets also seen twice on non Linux systems ?
+        count=14
+        pl = sniff(iface=iface, filter='tcp and port ' + str(port), count = count, timeout=3)
+        map(addresult, map(packet2p0f, pl))
+        os.waitpid(pid,0)
+    elif pid < 0:
+        log_runtime.error("fork error")
+    else:
+        # child: send
+        # XXX erk
+        time.sleep(1)
+        s1 = socket.socket(socket.AF_INET, type = socket.SOCK_STREAM)
+        # S & RA
+        try:
+            s1.connect(('127.0.0.1', port))
+        except socket.error:
+            pass
+        # S, SA, A, FA, A
+        s1.bind(('127.0.0.1', port))
+        s1.connect(('127.0.0.1', port))
+        # howto: get an RST w/o ACK packet
+        s1.close()
+        os._exit(0)
+    return result
 
diff --git a/scapy/plist.py b/scapy/plist.py
index afed77fc3efad348ce9ec474fba419b4cd83a915..716727a04ac71183584bf89791d332707199f3f0 100644
--- a/scapy/plist.py
+++ b/scapy/plist.py
@@ -411,6 +411,7 @@ lfilter: truth function to apply to each packet to decide whether it will be dis
     def sessions(self, session_extractor=None):
         if session_extractor is None:
             def session_extractor(p):
+                sess = "Other"
                 if 'Ether' in p:
                     if 'IP' in p:
                         if 'TCP' in p:
diff --git a/scapy/sendrecv.py b/scapy/sendrecv.py
index b0432686d306b1c28c10c3cc10825d9791c09c28..587b8396c80e19468806afb16153c73786136a58 100644
--- a/scapy/sendrecv.py
+++ b/scapy/sendrecv.py
@@ -203,7 +203,7 @@ def sndrcv(pks, pkt, timeout = None, inter = 0, verbose=None, chainCC=0, retry=0
     return plist.SndRcvList(ans),plist.PacketList(remain,"Unanswered")
 
 
-def __gen_send(s, x, inter=0, loop=0, count=None, verbose=None, *args, **kargs):
+def __gen_send(s, x, inter=0, loop=0, count=None, verbose=None, realtime=None, *args, **kargs):
     if type(x) is str:
         x = Raw(load=x)
     if not isinstance(x, Gen):
@@ -215,9 +215,18 @@ def __gen_send(s, x, inter=0, loop=0, count=None, verbose=None, *args, **kargs):
         loop = -count
     elif not loop:
         loop=-1
+    dt0 = None
     try:
         while loop:
             for p in x:
+                if realtime:
+                    ct = time.time()
+                    if dt0:
+                        st = dt0+p.time-ct
+                        if st > 0:
+                            time.sleep(st)
+                    else:
+                        dt0 = ct-p.time 
                 s.send(p)
                 n += 1
                 if verbose:
@@ -232,18 +241,18 @@ def __gen_send(s, x, inter=0, loop=0, count=None, verbose=None, *args, **kargs):
         print "\nSent %i packets." % n
         
 @conf.commands.register
-def send(x, inter=0, loop=0, count=None, verbose=None, *args, **kargs):
+def send(x, inter=0, loop=0, count=None, verbose=None, realtime=None, *args, **kargs):
     """Send packets at layer 3
 send(packets, [inter=0], [loop=0], [verbose=conf.verb]) -> None"""
-    __gen_send(conf.L3socket(*args, **kargs), x, inter=inter, loop=loop, count=count,verbose=verbose)
+    __gen_send(conf.L3socket(*args, **kargs), x, inter=inter, loop=loop, count=count,verbose=verbose, realtime=realtime)
 
 @conf.commands.register
-def sendp(x, inter=0, loop=0, iface=None, iface_hint=None, count=None, verbose=None, *args, **kargs):
+def sendp(x, inter=0, loop=0, iface=None, iface_hint=None, count=None, verbose=None, realtime=None, *args, **kargs):
     """Send packets at layer 2
 sendp(packets, [inter=0], [loop=0], [verbose=conf.verb]) -> None"""
     if iface is None and iface_hint is not None:
         iface = conf.route.route(iface_hint)[0]
-    __gen_send(conf.L2socket(iface=iface, *args, **kargs), x, inter=inter, loop=loop, count=count, verbose=verbose)
+    __gen_send(conf.L2socket(iface=iface, *args, **kargs), x, inter=inter, loop=loop, count=count, verbose=verbose, realtime=realtime)
 
 @conf.commands.register
 def sendpfast(x, pps=None, mbps=None, realtime=None, loop=0, iface=None):
diff --git a/scapy/utils6.py b/scapy/utils6.py
index 4f9b096734d6c48a59d0b8a96ade79ba37ae3841..fd9a39a9471f93662d2863814bd99284bdde40d6 100644
--- a/scapy/utils6.py
+++ b/scapy/utils6.py
@@ -26,7 +26,7 @@ def construct_source_candidate_set(addr, plen, laddr, loname):
     """
 
     cset = []
-    if in6_isgladdr(addr):
+    if in6_isgladdr(addr) or in6_isuladdr(addr):
 	cset = filter(lambda x: x[1] == IPV6_ADDR_GLOBAL, laddr)
     elif in6_islladdr(addr):
 	cset = filter(lambda x: x[1] == IPV6_ADDR_LINKLOCAL, laddr)
@@ -600,7 +600,7 @@ def in6_isuladdr(str):
     Returns True if provided address in printable format belongs to
     Unique local address space (fc00::/7).
     """
-    return in6_isincluded(str, 'fc::', 7)
+    return in6_isincluded(str, 'fc00::', 7)
 
 # TODO : we should see the status of Unique Local addresses against
 #        global address space.
diff --git a/scapy/volatile.py b/scapy/volatile.py
index d1f72c7bbbc043e1d03f4240bae096409f812080..bbe61e7f01d7e2652f4c300fd5bfe03af4a79ff7 100644
--- a/scapy/volatile.py
+++ b/scapy/volatile.py
@@ -66,6 +66,13 @@ class VolatileValue:
     def __getattr__(self, attr):
         if attr == "__setstate__":
             raise AttributeError(attr)
+        elif attr == "__cmp__":
+            x = self._fix()
+            def cmp2(y,x=x):
+                if type(x) != type(y):
+                    return -1
+                return x.__cmp__(y)
+            return cmp2
         return getattr(self._fix(),attr)
     def _fix(self):
         return None
@@ -226,13 +233,58 @@ class RandMAC(RandString):
                 v = RandByte()
             elif "-" in template[i]:
                 x,y = template[i].split("-")
-                v = RandSeq(int(x,16), int(y,16))
+                v = RandNum(int(x,16), int(y,16))
             else:
                 v = int(template[i],16)
             self.mac += (v,)
     def _fix(self):
         return "%02x:%02x:%02x:%02x:%02x:%02x" % self.mac
     
+class RandIP6(RandString):
+    def __init__(self, ip6template="**"):
+        self.tmpl = ip6template
+        self.sp = self.tmpl.split(":")
+        for i,v in enumerate(self.sp):
+            if not v or v == "**":
+                continue
+            if "-" in v:
+                a,b = v.split("-")
+            elif v == "*":
+                a=b=""
+            else:
+                a=b=v
+
+            if not a:
+                a = "0"
+            if not b:
+                b = "ffff"
+            if a==b:
+                self.sp[i] = int(a,16)
+            else:
+                self.sp[i] = RandNum(int(a,16), int(b,16))
+        self.variable = "" in self.sp
+        self.multi = self.sp.count("**")
+    def _fix(self):
+        done = 0
+        nbm = self.multi
+        ip = []
+        for i,n in enumerate(self.sp):
+            if n == "**":
+                nbm -= 1
+                remain = 8-(len(self.sp)-i-1)-len(ip)+nbm
+                if "" in self.sp:
+                    remain += 1
+                if nbm or self.variable:
+                    remain = random.randint(0,remain)
+                for j in range(remain):
+                    ip.append("%04x" % random.randint(0,65535))
+            elif not n:
+                ip.append("")
+            else:
+                ip.append("%04x" % n)
+        if len(ip) == 9:
+            ip.remove("")
+        return ":".join(ip)
 
 class RandOID(RandString):
     def __init__(self, fmt=None, depth=RandNumExpo(0.1), idnum=RandNumExpo(0.01)):
@@ -267,8 +319,6 @@ class RandOID(RandString):
             return ".".join(oid)
             
 
-from pprint import pprint
-        
 class RandRegExp(RandField):
     def __init__(self, regexp, lambda_=0.3,):
         self._regexp = regexp