diff --git a/scapy/config.py b/scapy/config.py
index 6c99582b4e97c6b06bd38f927f4dfec96edcca24..bb8d1d01e167767f507cd37e16931ae8be5c5e4d 100644
--- a/scapy/config.py
+++ b/scapy/config.py
@@ -312,7 +312,7 @@ extensions_paths: path or list of paths where extensions are to be looked for
     stats_dot11_protocols = []
     temp_files = []
     netcache = NetCache()
-    load_layers = ["l2", "inet", "dhcp", "dns", "dot11", "gprs", "hsrp", "ip6", "ir", "isakmp", "l2tp",
+    load_layers = ["l2", "inet", "dhcp", "dns", "dot11", "gprs", "hsrp", "inet6", "ir", "isakmp", "l2tp",
                    "mgcp", "mobileip", "netbios", "netflow", "ntp", "ppp", "radius", "rip", "rtp",
                    "sebek", "skinny", "smb", "snmp", "tftp", "x509", "bluetooth" ]
     
diff --git a/scapy/layers/inet.py b/scapy/layers/inet.py
index 34a9a9956e721ef9eeebf4d8adf58efb43ceb026..f90a329170d73aadbe76cffc332f6bfa28ae0a0e 100644
--- a/scapy/layers/inet.py
+++ b/scapy/layers/inet.py
@@ -277,7 +277,7 @@ class TCP(Packet):
                                      ln)
                 ck=checksum(psdhdr+p)
                 p = p[:16]+struct.pack("!H", ck)+p[18:]
-            elif isinstance(self.underlayer, IPv6) or isinstance(self.underlayer, _IPv6OptionHeader):
+            elif isinstance(self.underlayer, inet6.IPv6) or isinstance(self.underlayer, inet6._IPv6ExtHdr):
                 ck = in6_chksum(socket.IPPROTO_TCP, self.underlayer, p)
                 p = p[:16]+struct.pack("!H", ck)+p[18:]
             else:
@@ -301,7 +301,7 @@ class TCP(Packet):
     def mysummary(self):
         if isinstance(self.underlayer, IP):
             return self.underlayer.sprintf("TCP %IP.src%:%TCP.sport% > %IP.dst%:%TCP.dport% %TCP.flags%")
-        elif isinstance(self.underlayer, IPv6):
+        elif isinstance(self.underlayer, inet6.IPv6):
             return self.underlayer.sprintf("TCP %IPv6.src%:%TCP.sport% > %IPv6.dst%:%TCP.dport% %TCP.flags%")
         else:
             return self.sprintf("TCP %TCP.sport% > %TCP.dport% %TCP.flags%")
@@ -331,7 +331,7 @@ class UDP(Packet):
                                      ln)
                 ck=checksum(psdhdr+p)
                 p = p[:6]+struct.pack("!H", ck)+p[8:]
-            elif isinstance(self.underlayer, IPv6) or isinstance(self.underlayer, _IPv6OptionHeader):
+            elif isinstance(self.underlayer, inet6.IPv6) or isinstance(self.underlayer, inet6._IPv6ExtHdr):
                 ck = in6_chksum(socket.IPPROTO_UDP, self.underlayer, p)
                 p = p[:6]+struct.pack("!H", ck)+p[8:]
             else:
@@ -352,7 +352,7 @@ class UDP(Packet):
     def mysummary(self):
         if isinstance(self.underlayer, IP):
             return self.underlayer.sprintf("UDP %IP.src%:%UDP.sport% > %IP.dst%:%UDP.dport%")
-        elif isinstance(self.underlayer, IPv6):
+        elif isinstance(self.underlayer, inet6.IPv6):
             return self.underlayer.sprintf("UDP %IPv6.src%:%UDP.sport% > %IPv6.dst%:%UDP.dport%")
         else:
             return self.sprintf("UDP %UDP.sport% > %UDP.dport%")    
@@ -925,8 +925,8 @@ class TracerouteResult(SndRcvList):
         ports = {}
         ports_done = {}
         for s,r in self.res:
-            r = r[IP] or r[IPv6] or r
-            s = s[IP] or s[IPv6] or s
+            r = r[IP] or r[inet6.IPv6] or r
+            s = s[IP] or s[inet6.IPv6] or s
             ips[r.src] = None
             if TCP in s:
                 trace_id = (s.src,s.dst,6,s.dport)
@@ -937,8 +937,8 @@ class TracerouteResult(SndRcvList):
             else:
                 trace_id = (s.src,s.dst,s.proto,0)
             trace = rt.get(trace_id,{})
-            ttl = IPv6 in s and s.hlim or s.ttl
-            if not (ICMP in r and r[ICMP].type == 11) and not (IPv6 in r and ICMPv6TimeExceeded in r):
+            ttl = inet6.IPv6 in s and s.hlim or s.ttl
+            if not (ICMP in r and r[ICMP].type == 11) and not (inet6.IPv6 in r and ICMPv6TimeExceeded in r):
                 if trace_id in ports_done:
                     continue
                 ports_done[trace_id] = None
@@ -1221,3 +1221,5 @@ def fragleak2(target, timeout=0.4, onlyasc=0):
 
 conf.stats_classic_protocols += [TCP,UDP,ICMP]
 conf.stats_dot11_protocols += [TCP,UDP,ICMP]
+
+from scapy.layers import inet6
diff --git a/scapy/layers/inet6.py b/scapy/layers/inet6.py
index aa0c8c3924053fd67656f3e5bc3a2a4a724d97eb..dbbed2080f20e795bb0c15ff960de236173c069e 100644
--- a/scapy/layers/inet6.py
+++ b/scapy/layers/inet6.py
@@ -1,16 +1,16 @@
 #! /usr/bin/env python
 #############################################################################
 ##                                                                         ##
-## scapy6.py --- IPv6 support for Scapy                                    ##
-##               see http://namabiiru.hongo.wide.ad.jp/scapy6/             ##
-##               for more informations                                     ##
+## inet6.py --- IPv6 support for Scapy                                     ##
+##              see http://natisbad.org/IPv6/                              ##
+##              for more informations                                      ##
 ##                                                                         ##
 ## Copyright (C) 2005  Guillaume Valadon <guedou@hongo.wide.ad.jp>         ##
 ##                     Arnaud Ebalard <arnaud.ebalard@eads.net>            ##
 ##                                                                         ##
 ## This program is free software; you can redistribute it and/or modify it ##
 ## under the terms of the GNU General Public License version 2 as          ##
-## published by the Free Software Foundation; version 2.                   ##
+## published by the Free Software Foundation.                              ##
 ##                                                                         ##
 ## This program is distributed in the hope that it will be useful, but     ##
 ## WITHOUT ANY WARRANTY; without even the implied warranty of              ##
@@ -19,8 +19,18 @@
 ##                                                                         ##
 #############################################################################
 
-from scapy import *
-import __builtin__
+
+from scapy.layers.l2 import *
+from scapy.layers.inet import *
+from scapy.layers.dns import *
+from scapy.fields import *
+from scapy.packet import *
+from scapy.volatile import *
+from scapy.config import conf
+from scapy.sendrecv import sr,sr1,srp1
+from scapy.as_resolvers import AS_resolver_riswhois
+from scapy.supersocket import SuperSocket,L3RawSocket
+from scapy.arch import *
 
 
 #############################################################################
@@ -28,7 +38,7 @@ import __builtin__
 #############################################################################
 
 def get_cls(name, fallback_cls):
-    return __builtin__.__dict__.get(name, fallback_cls)
+    return globals().get(name, fallback_cls)
 
 
 #############################################################################
@@ -42,10 +52,6 @@ NETBSD = sys.platform.startswith("netbsd")
 DARWIN=sys.platform.startswith("darwin")
 WINDOWS = sys.platform.startswith("win")
 
-if OPENBSD or FREEBSD or NETBSD or DARWIN:
-        loname = "lo0"
-else:
-        loname = "lo"
 
 # From net/ipv6.h on Linux (+ Additions)
 IPV6_ADDR_UNICAST     = 0x01
@@ -90,7 +96,7 @@ def construct_source_candidate_set(addr, plen, laddr):
         cset = filter(lambda x: x[1] == IPV6_ADDR_SITELOCAL, laddr)
     elif in6_ismaddr(addr):
         if in6_ismnladdr(addr):
-            cset = [('::1', 16, loname)]
+            cset = [('::1', 16, LOOPBACK_NAME)]
         elif in6_ismgladdr(addr):
             cset = filter(lambda x: x[1] == IPV6_ADDR_GLOBAL, laddr)
         elif in6_ismlladdr(addr):
@@ -321,7 +327,7 @@ class Route6:
                 
         if not pathes:
             warning("No route found for IPv6 destination %s (no default route?)" % dst)
-            return (loname, "::", "::") # XXX Linux specific
+            return (LOOPBACK_NAME, "::", "::") # XXX Linux specific
 
         pathes.sort()
         pathes.reverse()
@@ -341,7 +347,7 @@ class Route6:
         #  - dst is unicast global. Check if it is 6to4 and we have a source 
         #    6to4 address in those available
         #  - dst is link local (unicast or multicast) and multiple output
-        #    interfaces are available. Take main one (conf.iface)
+        #    interfaces are available. Take main one (conf.iface6)
         #  - if none of the previous or ambiguity persists, be lazy and keep
         #    first one
         #  XXX TODO : in a _near_ future, include metric in the game
@@ -354,7 +360,7 @@ class Route6:
                 tmp = filter(lambda x: in6_isaddr6to4(x[1][1]), res)
             elif in6_ismaddr(dst) or in6_islladdr(dst):
                 # TODO : I'm sure we are not covering all addresses. Check that
-                tmp = filter(lambda x: x[1][0] == conf.iface, res)
+                tmp = filter(lambda x: x[1][0] == conf.iface6, res)
 
             if tmp:
                 res = tmp
@@ -441,7 +447,7 @@ if LINUX:
             nh = proc2r(nh)
 
             cset = [] # candidate set (possible source addresses)
-            if dev == loname:
+            if dev == LOOPBACK_NAME:
                 if d == '::':
                     continue
                 cset = ['::1']
@@ -468,7 +474,7 @@ elif WINDOWS:
         # Just some dummy values for now
         xx = "::1"
         scope = 128
-        ifname = loname
+        ifname = LOOPBACK_NAME
         ret.append(xx, scope, ifname)
         return ret
 
@@ -478,7 +484,7 @@ elif WINDOWS:
         d = '::'
         dp = 0
         nh = '::'
-        dev = loname
+        dev = LOOPBACK_NAME
         cset = ['::1']
         routes.append((d, dp, nh, dev, cset))
         return routes
@@ -550,7 +556,7 @@ else:
                 d,dev = d.split('%')
             if '%' in nh:
                 nh,dev = nh.split('%')
-            if loname in dev:
+            if LOOPBACK_NAME in dev:
                 cset = ['::1']
                 nh = '::'
             else:
@@ -603,7 +609,7 @@ class neighborCache:
     #       fork is done and the updated cache returned at the end.
     
     def __init__(self):
-        self.neighcache = arp_cache
+        self.neighcache = {}
 
     def flush(self, statictoo=True):
         self.neighcache = {}
@@ -685,9 +691,9 @@ class neighborCache:
             mac = in6_getnsmac(inet_pton(socket.AF_INET6, ip6))
             return mac
     
-        iff,a,nh = conf.route6.route(ip6, dev=conf.iface)
+        iff,a,nh = conf.route6.route(ip6, dev=conf.iface6)
 
-        if iff == loname:
+        if iff == LOOPBACK_NAME:
             return "ff:ff:ff:ff:ff:ff"
 
         if nh != '::': 
@@ -1024,7 +1030,7 @@ def in6_getLocalUniquePrefix():
     j = int((tod - i)*(2**32))
     tod = struct.pack("!II", i,j)
     # TODO: Add some check regarding system address gathering
-    rawmac = get_if_raw_hwaddr(conf.iface)[1]
+    rawmac = get_if_raw_hwaddr(conf.iface6)[1]
     mac = ":".join(map(lambda x: "%.02x" % ord(x), list(rawmac)))
     # construct modified EUI-64 ID
     eui64 = inet_pton(socket.AF_INET6, '::' + in6_mactoifaceid(mac))[8:] 
@@ -1564,6 +1570,13 @@ class IPv6(_IPv6GuessPayload, Packet, IPTools):
                     ByteField("hlim", 64),
                     SourceIP6Field("src", "dst"), # dst is for src @ selection
                     IP6Field("dst", "::1") ]
+
+    def route(self):
+        dst = self.dst
+        if isinstance(dst,Gen):
+            dst = iter(dst).next()
+        return conf.route6.route(dst)
+
     def mysummary(self):
         return "%s > %s (%i)" % (self.src,self.dst, self.nh)
 
@@ -1673,8 +1686,9 @@ class IPv6(_IPv6GuessPayload, Packet, IPTools):
                 return False
             return self.payload.answers(other.payload)
 
-import scapy 
-scapy.IPv6 = IPv6
+
+conf.neighbor.register_l3(Ether, IPv6, lambda l2,l3: getmacbyip6(l3.dst))
+
 
 class IPerror6(IPv6):
     name = "IPv6 in ICMPv6"
@@ -1833,8 +1847,6 @@ class _IPv6ExtHdr(_IPv6GuessPayload, Packet):
     name = 'Abstract IPV6 Option Header'
     aliastypes = [IPv6, IPerror6] # TODO ...
 
-scapy._IPv6OptionHeader = _IPv6ExtHdr
-
 
 #################### IPv6 options for Extension Headers #####################
 
@@ -4695,7 +4707,7 @@ class DHCPv6_am(AnsweringMachine):
     def usage(self):
         msg = """
 dhcp6d( dns="2001:500::1035", domain="localdomain, local", duid=None)
-        iface=conf.iface, advpref=255, sntpservers=None, 
+        iface=conf.iface6, advpref=255, sntpservers=None, 
         sipdomains=None, sipservers=None, 
         nisdomain=None, nisservers=None, 
         nispdomain=None, nispservers=None,
@@ -4709,7 +4721,7 @@ dhcp6d( dns="2001:500::1035", domain="localdomain, local", duid=None)
             answering machine. 
   
    iface : the interface to listen/reply on if you do not want to use 
-           conf.iface.
+           conf.iface6.
 
    advpref : Value in [0,255] given to Advertise preference field.
              By default, 255 is used. Be aware that this specific
@@ -4763,7 +4775,7 @@ dhcp6d( dns="2001:500::1035", domain="localdomain, local", duid=None)
                       sntpservers=None, sipdomains=None, sipservers=None, 
                       nisdomain=None, nisservers=None, nispdomain=None,
                       nispservers=None, bcmcsservers=None, bcmcsdomains=None,
-                      iface=conf.iface, debug=0, advpref=255):
+                      iface=None, debug=0, advpref=255):
         def norm_list(val, param_name):
             if val is None:
                 return None
@@ -4777,6 +4789,9 @@ dhcp6d( dns="2001:500::1035", domain="localdomain, local", duid=None)
                 self.usage()
                 return -1
 
+        if iface is None:
+            iface = conf.iface6
+        
         self.debug = debug
 
         # Dictionary of provided DHCPv6 options, keyed by option type
@@ -5930,9 +5945,8 @@ class _IPv6inIP(SuperSocket):
 #############################################################################
 #############################################################################
 
-L3Types[ETH_P_IPV6] =  IPv6
-LLTypes[31] = IPv6
-LLNumTypes[IPv6] = 31
+conf.l3types.register(ETH_P_IPV6, IPv6)
+conf.l2types.register(31, IPv6)
 
 bind_layers(Ether,     IPv6,     type = 0x86dd )
 bind_layers(IPerror6,  TCPerror, nh = socket.IPPROTO_TCP )
@@ -5948,7 +5962,7 @@ bind_layers(IPv6,      IPv6,     nh = socket.IPPROTO_IPV6 )
 
 def get_working_if6():
     """
-    try to guess the best interface for conf.iface by looking for the 
+    try to guess the best interface for conf.iface6 by looking for the 
     one used by default route if any.
     """
     res = conf.route6.route("::/0")
@@ -5958,7 +5972,7 @@ def get_working_if6():
     return get_working_if()
 
 conf.route6 = Route6()
-conf.iface = get_working_if6()
+conf.iface6 = get_working_if6()
 
 if __name__ == '__main__':
     interact(mydict=globals(), mybanner="IPv6 enabled")
diff --git a/scapy/layers/ip6.py b/scapy/layers/ip6.py
deleted file mode 100644
index b789f387509eb91664885a0566418733db91ce99..0000000000000000000000000000000000000000
--- a/scapy/layers/ip6.py
+++ /dev/null
@@ -1,27 +0,0 @@
-## This file is part of Scapy
-## See http://www.secdev.org/projects/scapy for more informations
-## Copyright (C) Philippe Biondi <phil@secdev.org>
-## This program is published under a GPLv2 license
-
-from scapy.error import log_interactive
-from scapy.packet import *
-from scapy.fields import *
-
-
-class IPv6(Packet):
-    """See http://namabiiru.hongo.wide.ad.jp/scapy6"""
-    name = "IPv6 not implemented here." 
-    def __init__(self, *args, **kargs):
-        log_interactive.error(self.name)
-    def __repr__(self):
-        return "<IPv6: ERROR not implemented>"
-    
-class _IPv6OptionHeader(Packet):
-    """See http://namabiiru.hongo.wide.ad.jp/scapy6"""
-    name = "IPv6 not implemented here."
-    def __init__(self, *args, **kargs):
-        log_interactive.error(self.name)
-    def __repr__(self):
-        return "<IPv6: ERROR not implemented>"
-
-