diff --git a/confluent_server/confluent/discovery/protocols/pxe.py b/confluent_server/confluent/discovery/protocols/pxe.py
index f682d4f4..f49f1822 100644
--- a/confluent_server/confluent/discovery/protocols/pxe.py
+++ b/confluent_server/confluent/discovery/protocols/pxe.py
@@ -27,6 +27,7 @@ import confluent.collective.manager as collective
 import confluent.noderange as noderange
 import confluent.log as log
 import confluent.netutil as netutil
+import confluent.util as util
 import ctypes
 import ctypes.util
 import eventlet
@@ -45,6 +46,9 @@ udphdr = b'\x00\x43\x00\x44\x00\x00\x00\x00'
 ignoremacs = {}
 ignoredisco = {}
 
+mcastv6addr = 'ff02::1:2'
+
+
 def _ipsum(data):
     currsum = 0
     if len(data) % 2:
@@ -189,6 +193,26 @@ def _decode_ocp_vivso(rq, idx, size):
         idx += rq[idx + 1] + 2
     return '', None, vivso
 
+def v6opts_to_dict(rq):
+    optidx = 0
+    reqdict = {}
+    disco = {'uuid':None, 'arch': None, 'vivso': None}
+    try:
+        while optidx < len(rq):
+            optnum, optlen = struct.unpack('!HH', rq[optidx:optidx+4])
+            reqdict[optnum] = rq[optidx + 4:optidx + 4 + optlen]
+            optidx += optlen + 4
+    except IndexError:
+        pass
+    if 1 in reqdict:
+        duid = reqdict[1]
+        if struct.unpack('!H', duid[:2])[0] == 4:
+            disco['uuid'] = decode_uuid(duid[2:])
+    if 61 in reqdict:
+        arch = bytes(rq[optidx+4:optidx+4+optlen])
+        disco['arch'] = pxearchs.get(bytes(reqdict[61]), None)
+    return reqdict, disco
+
 def opts_to_dict(rq, optidx, expectype=1):
     reqdict = {}
     disco = {'uuid':None, 'arch': None, 'vivso': None}
@@ -317,95 +341,117 @@ def snoop(handler, protocol=None, nodeguess=None):
     net4.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
     net4.setsockopt(socket.IPPROTO_IP, IP_PKTINFO, 1)
     net4.bind(('', 67))
+    v6addr = socket.inet_pton(socket.AF_INET6, mcastv6addr)
+    net6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
+    net6.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+    for ifidx in util.list_interface_indexes():
+        v6grp = v6addr + struct.pack('=I', ifidx)
+        net6.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, v6grp)
+    net6.bind(('', 547))
+    clientaddr = sockaddr_in()
+    rawbuffer = bytearray(2048)
+    data = pkttype.from_buffer(rawbuffer)
+    msg = msghdr()
+    cmsgarr = bytearray(cmsgsize)
+    cmsg = cmsgtype.from_buffer(cmsgarr)
+    iov = iovec()
+    iov.iov_base = ctypes.addressof(data)
+    iov.iov_len = 2048
+    msg.msg_iov = ctypes.pointer(iov)
+    msg.msg_iovlen = 1
+    msg.msg_control = ctypes.addressof(cmsg)
+    msg.msg_controllen = ctypes.sizeof(cmsg)
+    msg.msg_name = ctypes.addressof(clientaddr)
+    msg.msg_namelen = ctypes.sizeof(clientaddr)
+    # We'll leave name and namelen blank for now
     while True:
         try:
             # Just need some delay, picked a prime number so that overlap with other
             # timers might be reduced, though it really is probably nothing
-            ready = select.select([net4], [], [], None)
+            ready = select.select([net4, net6], [], [], None)
             if not ready or not ready[0]:
                 continue
-            clientaddr = sockaddr_in()
-            rawbuffer = bytearray(2048)
-            data = pkttype.from_buffer(rawbuffer)
-            msg = msghdr()
-            cmsgarr = bytearray(cmsgsize)
-            cmsg = cmsgtype.from_buffer(cmsgarr)
-            iov = iovec()
-            iov.iov_base = ctypes.addressof(data)
-            iov.iov_len = 2048
-            msg.msg_iov = ctypes.pointer(iov)
-            msg.msg_iovlen = 1
-            msg.msg_control = ctypes.addressof(cmsg)
-            msg.msg_controllen = ctypes.sizeof(cmsg)
-            msg.msg_name = ctypes.addressof(clientaddr)
-            msg.msg_namelen = ctypes.sizeof(clientaddr)
-            # We'll leave name and namelen blank for now
-            i = recvmsg(net4.fileno(), ctypes.pointer(msg), 0)
-            # if we have a small packet, just skip, it can't possible hold enough
-            # data and avoids some downstream IndexErrors that would be messy
-            # with try/except
-            if i < 64:
-                continue
-            #peer = ipfromint(clientaddr.sin_addr.s_addr)
-            # We don't need peer yet, generally it's 0.0.0.0
-            _, level, typ = struct.unpack('QII', cmsgarr[:16])
-            if level == socket.IPPROTO_IP and typ == IP_PKTINFO:
-                idx, recv, targ = struct.unpack('III', cmsgarr[16:28])
-                recv = ipfromint(recv)
-                targ = ipfromint(targ)
-            # peer is the source ip (in dhcpdiscover, 0.0.0.0)
-            # recv is the 'ip' that recevied the packet, regardless of target
-            # targ is the ip in the destination ip of the header.
-            # idx is the ip link number of the receiving nic
-            # For example, a DHCPDISCOVER will probably have:
-            # peer of 0.0.0.0
-            # targ of 255.255.255.255
-            # recv of <actual ip address that could reply>
-            # idx correlated to the nic
-            rqv = memoryview(rawbuffer)
-            rq = bytearray(rqv[:i])
-            if rq[0] == 1:  # Boot request
-                addrlen = rq[2]
-                if addrlen > 16 or addrlen == 0:
-                    continue
-                rawnetaddr = rq[28:28+addrlen]
-                netaddr = ':'.join(['{0:02x}'.format(x) for x in rawnetaddr])
-                optidx = 0
-                try:
-                    optidx = rq.index(b'\x63\x82\x53\x63') + 4
-                except ValueError:
-                    continue
-                txid = rq[4:8] # struct.unpack('!I', rq[4:8])[0]
-                rqinfo, disco = opts_to_dict(rq, optidx)
-                vivso = disco.get('vivso', None)
-                if vivso:
-                    # info['modelnumber'] = info['attributes']['enclosure-machinetype-model'][0]
-                    info = {'hwaddr': netaddr, 'uuid': disco['uuid'],
-                            'architecture': vivso.get('arch', ''),
-                            'services': (vivso['service-type'],),
-                            'netinfo': {'ifidx': idx, 'recvip': recv, 'txid': txid},
-                            'attributes': {'enclosure-machinetype-model': [vivso.get('machine', '')]}}
-                    if time.time() > ignoredisco.get(netaddr, 0) + 90:
-                        ignoredisco[netaddr] = time.time()
-                        handler(info)
-                    #consider_discover(info, rqinfo, net4, cfg, rqv)
-                    continue
-                # We will fill out service to have something to byte into,
-                # but the nature of the beast is that we do not have peers,
-                # so that will not be present for a pxe snoop
-                info = {'hwaddr': netaddr, 'uuid': disco['uuid'],
-                        'architecture': disco['arch'],
-                        'netinfo': {'ifidx': idx, 'recvip': recv, 'txid': txid},
-                        'services': ('pxe-client',)}
-                if (disco['uuid']
-                        and time.time() > ignoredisco.get(netaddr, 0) + 90):
-                    ignoredisco[netaddr] = time.time()
-                    handler(info)
-                consider_discover(info, rqinfo, net4, cfg, rqv, nodeguess)
+            for netc in ready[0]:
+                idx = None
+                if netc == net4:
+                    i = recvmsg(netc.fileno(), ctypes.pointer(msg), 0)
+                    # if we have a small packet, just skip, it can't possible hold enough
+                    # data and avoids some downstream IndexErrors that would be messy
+                    # with try/except
+                    if i < 64:
+                        continue
+                    _, level, typ = struct.unpack('QII', cmsgarr[:16])
+                    if level == socket.IPPROTO_IP and typ == IP_PKTINFO:
+                        idx, recv = struct.unpack('II', cmsgarr[16:24])
+                        recv = ipfromint(recv)
+                    rqv = memoryview(rawbuffer)
+                    if rawbuffer[0] == 1:  # Boot request
+                        process_dhcp4req(handler, nodeguess, cfg, net4, idx, recv, rqv)
+                elif netc == net6:
+                    recv = 'ff02::1:2'
+                    pkt, addr = netc.recvfrom(2048)
+                    idx = addr[-1]
+                    i = len(pkt)
+                    if i < 64:
+                        continue
+                    rqv = memoryview(pkt)
+                    rq = bytearray(rqv[:2])
+                    if rq[0] == 1: # dhcpv6 solicit
+                        process_dhcp6req(rqv, addr[0])
+
         except Exception as e:
             tracelog.log(traceback.format_exc(), ltype=log.DataTypes.event,
                             event=log.Events.stacktrace)
 
+def process_dhcp6req(rqv, addr):
+    txid = rqv[1:4]
+    req, disco = v6opts_to_dict(bytearray(rqv[4:]))
+    if 'uuid' not in disco:
+        return
+    print(addr)
+    print(repr(disco))
+
+
+def process_dhcp4req(handler, nodeguess, cfg, net4, idx, recv, rqv):
+    rq = bytearray(rqv)
+    addrlen = rq[2]
+    if addrlen > 16 or addrlen == 0:
+        return
+    rawnetaddr = rq[28:28+addrlen]
+    netaddr = ':'.join(['{0:02x}'.format(x) for x in rawnetaddr])
+    optidx = 0
+    try:
+        optidx = rq.index(b'\x63\x82\x53\x63') + 4
+    except ValueError:
+        return
+    txid = rq[4:8] # struct.unpack('!I', rq[4:8])[0]
+    rqinfo, disco = opts_to_dict(rq, optidx)
+    vivso = disco.get('vivso', None)
+    if vivso:
+                        # info['modelnumber'] = info['attributes']['enclosure-machinetype-model'][0]
+        info = {'hwaddr': netaddr, 'uuid': disco['uuid'],
+                                'architecture': vivso.get('arch', ''),
+                                'services': (vivso['service-type'],),
+                                'netinfo': {'ifidx': idx, 'recvip': recv, 'txid': txid},
+                                'attributes': {'enclosure-machinetype-model': [vivso.get('machine', '')]}}
+        if time.time() > ignoredisco.get(netaddr, 0) + 90:
+            ignoredisco[netaddr] = time.time()
+            handler(info)
+                        #consider_discover(info, rqinfo, net4, cfg, rqv)
+        return
+                    # We will fill out service to have something to byte into,
+                    # but the nature of the beast is that we do not have peers,
+                    # so that will not be present for a pxe snoop
+    info = {'hwaddr': netaddr, 'uuid': disco['uuid'],
+                            'architecture': disco['arch'],
+                            'netinfo': {'ifidx': idx, 'recvip': recv, 'txid': txid},
+                            'services': ('pxe-client',)}
+    if (disco['uuid']
+                            and time.time() > ignoredisco.get(netaddr, 0) + 90):
+        ignoredisco[netaddr] = time.time()
+        handler(info)
+    consider_discover(info, rqinfo, net4, cfg, rqv, nodeguess)
+
 
 
 def clear_nodes(nodes):