Beispiel #1
0
    def pass_stream(self, num, fd):
        self.send({'type': 'pass-stream', 'num': num})
        passfd.sendfd(self.sock, fd)

        resp = self.file.read(3)
        if resp != 'ok\n':
            raise IOError('bad response to pass-stream')
Beispiel #2
0
    def pass_stream(self, num, fd):
        self.send({'type': 'pass-stream', 'num': num})
        passfd.sendfd(self.sock, fd)

        resp = self.file.read(3)
        if resp != 'ok\n':
            raise IOError('bad response to pass-stream')
Beispiel #3
0
 def send_fd(self, fd):
     import passfd
     import socket
     
     address = self.simulation.invoke(self.uuid, "recvFD")
     sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
     sock.connect(address)
     passfd.sendfd(sock, fd, '0')
Beispiel #4
0
    def send_fd(self, fd):
        import passfd
        import socket

        address = self.simulation.invoke(self.uuid, "recvFD")
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
        sock.connect(address)
        passfd.sendfd(sock, fd, '0')
Beispiel #5
0
def connect_fd(testbed_instance, tap_guid, cross_data):
    import passfd
    import socket
    tap = testbed_instance._elements[tap_guid]
    address = cross_data["tun_addr"]
    sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
    sock.connect(address)
    passfd.sendfd(sock, tap.fd, '0')
Beispiel #6
0
def passfd_action(fd, args):
    """ Sends the file descriptor associated to the TAP device 
    to another process through a unix socket.
    """
    address = args.pop(0)
    print address
    sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
    sock.connect(address)
    passfd.sendfd(sock, fd, '0')
    return "PASSFD-ACK"
Beispiel #7
0
 def _send_fd(self, name, fd):
     "Pass a file descriptor"
     self._send_cmd("PROC", name)
     self._read_and_check_reply(3)
     try:
         passfd.sendfd(self._wfd, fd, "PROC " + name)
     except:
         # need to fill the buffer on the other side, nevertheless
         self._wfd.write("=" * (len(name) + 5) + "\n")
         # And also read the expected error
         self._read_and_check_reply(5)
         raise
     self._read_and_check_reply()
Beispiel #8
0
def _rpc_write_bson(sock, doc):
    fds = doc.get('fds', [])
    doc['fds'] = len(fds)

    sock.sendall(struct.pack('!I', len(fds)))
    for fd in fds:
        if not isinstance(fd, FD):
            raise TypeError('fds need to be instances of FD (not %r)' % fd)
        passfd.sendfd(sock, fd.fileno(), 'whatever')

    msg = _bson.BSON.encode(doc)
    sock.sendall(struct.pack('!I', len(msg)))
    sock.sendall(msg)
Beispiel #9
0
 def _send_fd(self, name, fd):
     "Pass a file descriptor"
     self._send_cmd("PROC", name)
     self._read_and_check_reply(3)
     try:
         passfd.sendfd(self._wfd, fd, "PROC " + name)
     except:
         # need to fill the buffer on the other side, nevertheless
         self._wfd.write("=" * (len(name) + 5) + "\n")
         # And also read the expected error
         self._read_and_check_reply(5)
         raise
     self._read_and_check_reply()
Beispiel #10
0
 def do_X11_SOCK(self, cmdname):
     if not self._xsock:
         self.reply(500, "X forwarding not set up.")
         return
     # Needs to be a separate command to handle synch & buffering issues
     try:
         passfd.sendfd(self._wfd, self._xsock.fileno(), "1")
     except:
         # need to fill the buffer on the other side, nevertheless
         self._wfd.write("1")
         self.reply(500, "Error sending file descriptor.")
         return
     self._xsock = None
     self.reply(200, "Will set up X forwarding.")
Beispiel #11
0
 def do_X11_SOCK(self, cmdname):
     if not self._xsock:
         self.reply(500, "X forwarding not set up.")
         return
     # Needs to be a separate command to handle synch & buffering issues
     try:
         passfd.sendfd(self._wfd, self._xsock.fileno(), "1")
     except:
         # need to fill the buffer on the other side, nevertheless
         self._wfd.write("1")
         self.reply(500, "Error sending file descriptor.")
         return
     self._xsock = None
     self.reply(200, "Will set up X forwarding.")
    def test_sanity_checks(self):
        self.assertRaises(TypeError, recvfd, "foo")
        s = socket.socket(socket.AF_INET)
        self.assertRaises(ValueError, recvfd, s)

        (s0, s1) = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM, 0)
        f = file("/dev/zero")
        sendfd(s0, f)
        recvfd(s1)

        # Using integers
        sendfd(s0.fileno(), f.fileno())
        recvfd(s1.fileno())

        self.assertRaises(TypeError, sendfd, s0, "foo")
        # Assuming fd 255 is not valid
        self.assertRaises(OSError, sendfd, s0, 255)
Beispiel #13
0
    def test_sanity_checks(self):
        self.assertRaises(TypeError, recvfd, "foo")
        s = socket.socket(socket.AF_INET)
        self.assertRaises(ValueError, recvfd, s)

        (s0, s1) = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM, 0)
        f = file("/dev/zero")
        sendfd(s0, f)
        recvfd(s1)

        # Using integers
        sendfd(s0.fileno(), f.fileno())
        recvfd(s1.fileno())

        self.assertRaises(TypeError, sendfd, s0, "foo")
        # Assuming fd 255 is not valid
        self.assertRaises(OSError, sendfd, s0, 255)
Beispiel #14
0
    def _start_accepting(self, sock):
        '''
                    server1                 server2
                       |                dial   |
                       |<----------------------|
                       | accept                |
                       |                       |
                       | listener fd           |
                       |---------------------->|
                       |                       |
                       | num of worker fds     |
                       |---------------------->|
                       |                       |
                       | worker fd 1by1        |
                       |---------------------->|
                       |                       |
        '''
        # at this time, self.server.serve_forever() must be called
        # so that self.server.socket is not empty
        c, addr = sock.accept()
        print >>sys.stderr, time.ctime(), 'accepted from', c

        os.unlink(self._workernpath)

        # send listener fd and then close the listener right now
        print >>sys.stderr, time.ctime(), 'sending listener', self.server.socket
        passfd.sendfd(c, self.server.socket)

        # close my listener, so that my accepted workers will be snapshotted
        self.server.socket.close() 

        self._notify_worker_fds_num(len(self.accepted))

        # pass fd of worker one by one
        for s in self.accepted:
            print >>sys.stderr, time.ctime(), 'sending client fd', s
            passfd.sendfd(c, s)

        print >>sys.stderr, time.ctime(), 'waiting for worker to finish after %d seconds...' % self.LAME_DUCK_PERIOD_SECOND
        gevent.sleep(self.LAME_DUCK_PERIOD_SECOND)
        self.server.stop()
        print >>sys.stderr, time.ctime(), 'bye!'
Beispiel #15
0
def pass_to_daemon(conn, cmd='start-tls'):
    #print "Sending fd"
    s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    s.connect("/tmp/tlsd.sock")

    ret = passfd.sendfd(s, conn.fileno(), cmd)
    #print "Send %s bytes" % ret
    #print "Receiving fd..."
    fd, msg = passfd.recvfd(s)

    #print "  fd: %s" % fd
    #print "  message: %s" % msg

    if (msg.split()[0] == 'ERR'):
        conn.close()
        s.close()
        return conn, s, msg.split()[1], msg.split()[2]
    if (msg.split()[0] == 'OK'):
        sock = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)
        return sock, s, 0, msg.split()[1]
Beispiel #16
0
def pass_to_daemon(conn, cmd="start-tls"):
    # print "Sending fd"
    s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    s.connect("/tmp/tlsd.sock")

    ret = passfd.sendfd(s, conn.fileno(), cmd)
    # print "Send %s bytes" % ret
    # print "Receiving fd..."
    fd, msg = passfd.recvfd(s)

    # print "  fd: %s" % fd
    # print "  message: %s" % msg

    if msg.split()[0] == "ERR":
        conn.close()
        s.close()
        return conn, s, msg.split()[1], msg.split()[2]
    if msg.split()[0] == "OK":
        sock = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)
        return sock, s, 0, msg.split()[1]
Beispiel #17
0
 def child_tests(self, s, dgram = False):
     f = file("/dev/zero")
     assert sendfd(s, f, "") == 0
     s.recv(1)
     assert sendfd(s, f, "a") == 1
     s.recv(1)
     assert sendfd(s, f, "\0") == 1
     s.recv(1)
     assert sendfd(s, f, "foobar") == 6
     s.recv(1)
     assert sendfd(s, f, "long string is long") == 19
     # The other side will recv() instead of recvmsg(), this fd would be
     # lost. I couldn't find any specification on this semantic
     s.recv(1)
     assert sendfd(s, f, "foobar") == 6
     s.recv(1)
     assert s.send("barbaz") == 6
     # Try to write!
     s.recv(1)
     assert sendfd(s, f, "writing") == 7
     s.recv(1)
     f = file("/dev/null", "w")
     assert sendfd(s, f, "writing") == 7
     s.recv(1)
 def child_tests(self, s, dgram=False):
     f = file("/dev/zero")
     assert sendfd(s, f, "") == 0
     s.recv(1)
     assert sendfd(s, f, "a") == 1
     s.recv(1)
     assert sendfd(s, f, "\0") == 1
     s.recv(1)
     assert sendfd(s, f, "foobar") == 6
     s.recv(1)
     assert sendfd(s, f, "long string is long") == 19
     # The other side will recv() instead of recvmsg(), this fd would be
     # lost. I couldn't find any specification on this semantic
     s.recv(1)
     assert sendfd(s, f, "foobar") == 6
     s.recv(1)
     assert s.send("barbaz") == 6
     # Try to write!
     s.recv(1)
     assert sendfd(s, f, "writing") == 7
     s.recv(1)
     f = file("/dev/null", "w")
     assert sendfd(s, f, "writing") == 7
     s.recv(1)
Beispiel #19
0
def send_fd(f):
  fd = f.fileno()
  passfd.sendfd(KCHAN, fd)
Beispiel #20
0
    msg = msg[0:len(msg) - 1]
    print "K]]received msg:[" + msg + "]"
    flds = string.split(msg, ":")
    hostname = flds[0]
    port = int(flds[1])
    family = int(flds[2])
    stype = int(flds[3])
    protocol = int(flds[4])

    print "K]]a socket is created in the kernel"
    print "K]]hostname:" + str(hostname)
    print "K]]port:" + str(port)
    print "K]]family:" + str(family)
    print "K]]stype:" + str(stype)
    print "K]]protocol:" + str(protocol)

    s = socket.socket(family, stype)
    s.connect((hostname, port))

    sP.send("ResultSocket\0")
    passfd.sendfd(sP, s.fileno(), message="\x00")
    tab_waiting = False
  except:
    print "KERNEL]socket creation failed"
    if tab_waiting :
      sP.send("ResultSocket\0")
      passfd.sendfd(sP, 0 , message="\x00")


    
Beispiel #21
0
    family = socket.AF_INET
elif nfamily == 10:
    family = socket.AF_INET6

nsocktype = int(socket_descs[3])
socktype = socket.SOCK_SEQPACKET
if nsocktype == 1:
    socktype = socket.SOCK_STREAM
elif nsocktype == 2:
    socktype = socket.SOCK_DGRAM
elif nsocktype == 3:
    socktype = socket.SOCK_RAW

s = None
for res in socket.getaddrinfo(host, port, family, socktype):
    af, socktype, proto, canonname, sa = res
    try:
        s = socket.socket(af, socktype, proto)
    except socket.error as msg:
        s = None
        continue
    try:
        s.connect(sa)
    except socket.error as msg:
        s.close()
        s = None
        continue
    break

passfd.sendfd(message_handler.KCHAN, s.fileno(), "C")
Beispiel #22
0
    def run(self):
        logger.debug("Starting %s", self.name)
        
        logger.debug("Waiting for fd")
        fd, msg = passfd.recvfd(self.clnt_cmd)

        logger.debug("Received fd: %s; message: %s", fd, msg)

        # Find out type of socket
        temp_s = socket.fromfd(fd, socket.AF_UNIX, socket.SOCK_STREAM)
        styp = temp_s.getsockopt(socket.SOL_SOCKET, socket.SO_TYPE)
        # IPv6 or IPv4?
        if ':' in temp_s.getsockname()[0]:
            sfam = socket.AF_INET6
        else:
            sfam = socket.AF_INET
        del temp_s

        logger.debug("Creating socket from fd %s with family %d and type %d", fd, sfam, styp)
        self.connection = socket.fromfd(fd, sfam, styp)
        self.remote_port = self.connection.getpeername()[1]

        clnt_fd = 0
        ret_msg = "OK"
        try:
            msg_split = msg.split()
            if msg_split[0] == 'start-tls':
                #format of msg is: start-tls [server_name [flags]]
                if len(msg_split) > 1:
                    logger.debug("SNI: %s", msg_split[1])
                    self.server_name = msg_split[1]
                if len(msg_split) > 2:
                    validator.parse_flags(msg_split[2])
                clnt_fd = self.start_tls()
            elif msg_split[0] == "recv-tls":
                #format of msg is: recv-tls [flags]
                if len(msg_split) > 1:
                    validator.parse_flags(msg_split[1])
                clnt_fd = self.recv_tls()
            else:
                raise Exception('Unknown Command')
        except libtlsd.validation.InsecureLookupException:
            ret_msg = "ERR 1 InsecureLookupException"
        except libtlsd.validation.LDAPUserNotFound:
            ret_msg = "ERR 2 LDAPUserNotFound"
        except libtlsd.validation.DaneError:
            ret_msg = "ERR 3 DaneError"
        except:
            logger.debug('Unspecified error: %s', sys.exc_info()[0])
            traceback.print_exc()
            ret_msg = "ERR 99 Unspecified"

        if validator.validated_identity:
            ret_msg += ' %s' % (validator.validated_identity)
        logger.debug("Sending substitute fd: %s", clnt_fd)
        passfd.sendfd(self.clnt_cmd, clnt_fd, ret_msg)

        if clnt_fd == 0:
            return 0

        # Create list of all sockets in correct order to always read the session socket first
        inputs = []
        inputs.append(self.session)
        inputs.append(self.clnt_data)
        inputs.append(self.clnt_cmd)
        
        logger.info("Connection setup done forwarding all traffic...")
        while(not self.stop):
            inputready, outputready, exceptready = select.select(inputs, [], [])

            for s in inputready:
                data = s.recv(BUF_SIZE)
                
                if data:
                    if s is self.clnt_cmd:
                        self.process_cmd(data)
                    elif s is self.clnt_data:
                        self.session.send(data)
                    elif s is self.session:
                        self.clnt_data.send(data)
                else:
                    # Interpret empty result as closed connection and close all
                    # Ignore termination of cmd socket
                    if s is self.clnt_cmd:
                        logger.info('Client cmd socket was closed')
                        inputs.remove(self.clnt_cmd)
                    else:
                        self.close_connections()

        logger.debug("Terminating %s", self.name)
Beispiel #23
0
 def send_fd(self, f):
     fd = f.fileno()
     passfd.sendfd(self.KCHAN, fd, "C")
Beispiel #24
0
while True : 
  try :
    family = struct.unpack("i", sP.recv(4))[0]
    tab_waiting = True

    stype = struct.unpack("i", sP.recv(4))[0]
    protocol = struct.unpack("i", sP.recv(4))[0]
    port = struct.unpack("i", sP.recv(4))[0]
    hostname = sP.recv(4096)

    print "K]]a socket is created in the kernel"
    print "K]]family:" + str(family)
    print "K]]stype:" + str(stype)
    print "K]]protocol:" + str(protocol)
    print "K]]port:" + str(port)
    print "K]]hostname:" + str(hostname)

    s = socket.socket(family, stype)
    s.connect((hostname, port))
    passfd.sendfd(sP, s.fileno(), message="\x00")
    tab_waiting = False
  except:
    #raise
    print "KERNEL]socket creation failed"
    if tab_waiting :
        passfd.sendfd(sP, 0 , message="\x00")


    
Beispiel #25
0
def write_message_len(m, soc):
    soc.sendall(len_encoding(m))
    if m.type == mtypes.RES_SOCKET:
        passfd.sendfd(soc, m.socfd, message="\x00")
Beispiel #26
0
     sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
     retrydelay = 1.0
     for i in xrange(30):
         if TERMINATE:
             raise OSError, "Killed"
         try:
             sock.connect(options.pass_fd)
             break
         except socket.error:
             # wait a while, retry
             print >>sys.stderr, "%s: Could not connect. Retrying in a sec..." % (time.strftime('%c'),)
             time.sleep(min(30.0,retrydelay))
             retrydelay *= 1.1
     else:
         sock.connect(options.pass_fd)
     passfd.sendfd(sock, tun.fileno(), '0')
     
     # just wait forever
     def tun_fwd(tun, remote, **kw):
         global TERMINATE
         TERM = TERMINATE
         while not TERM:
             time.sleep(1)
     remote = None
 elif options.protocol == "gre":
     if accept_packet or filter_init:
         raise NotImplementedError, "--mode %s and --filter are not compatible" % (options.mode,)
     
     # just wait forever
     def tun_fwd(tun, remote, **kw):
         global TERMINATE
Beispiel #27
0
        retrydelay = 1.0
        for i in xrange(30):
            if TERMINATE:
                raise OSError, "Killed"
            try:
                sock.connect(options.pass_fd)
                break
            except socket.error:
                # wait a while, retry
                print >> sys.stderr, "%s: Could not connect. Retrying in a sec..." % (
                    time.strftime('%c'), )
                time.sleep(min(30.0, retrydelay))
                retrydelay *= 1.1
        else:
            sock.connect(options.pass_fd)
        passfd.sendfd(sock, tun.fileno(), '0')

        # just wait forever
        def tun_fwd(tun, remote, **kw):
            global TERMINATE
            TERM = TERMINATE
            while not TERM:
                time.sleep(1)

        remote = None
    elif options.protocol == "gre":
        if accept_packet or filter_init:
            raise NotImplementedError, "--mode %s and --filter are not compatible" % (
                options.mode, )

        # just wait forever
Beispiel #28
0
    def run(self):
        logger.debug("Starting %s", self.name)

        logger.debug("Waiting for fd")
        fd, msg = passfd.recvfd(self.clnt_cmd)

        logger.debug("Received fd: %s; message: %s", fd, msg)

        # Find out type of socket
        temp_s = socket.fromfd(fd, socket.AF_UNIX, socket.SOCK_STREAM)
        styp = temp_s.getsockopt(socket.SOL_SOCKET, socket.SO_TYPE)
        # IPv6 or IPv4?
        if ':' in temp_s.getsockname()[0]:
            sfam = socket.AF_INET6
        else:
            sfam = socket.AF_INET
        del temp_s

        logger.debug("Creating socket from fd %s with family %d and type %d",
                     fd, sfam, styp)
        self.connection = socket.fromfd(fd, sfam, styp)
        self.remote_port = self.connection.getpeername()[1]

        clnt_fd = 0
        ret_msg = "OK"
        try:
            msg_split = msg.split()
            if msg_split[0] == 'start-tls':
                #format of msg is: start-tls [server_name [flags]]
                if len(msg_split) > 1:
                    logger.debug("SNI: %s", msg_split[1])
                    self.server_name = msg_split[1]
                if len(msg_split) > 2:
                    validator.parse_flags(msg_split[2])
                clnt_fd = self.start_tls()
            elif msg_split[0] == "recv-tls":
                #format of msg is: recv-tls [flags]
                if len(msg_split) > 1:
                    validator.parse_flags(msg_split[1])
                clnt_fd = self.recv_tls()
            else:
                raise Exception('Unknown Command')
        except libtlsd.validation.InsecureLookupException:
            ret_msg = "ERR 1 InsecureLookupException"
        except libtlsd.validation.LDAPUserNotFound:
            ret_msg = "ERR 2 LDAPUserNotFound"
        except libtlsd.validation.DaneError:
            ret_msg = "ERR 3 DaneError"
        except:
            logger.debug('Unspecified error: %s', sys.exc_info()[0])
            traceback.print_exc()
            ret_msg = "ERR 99 Unspecified"

        if validator.validated_identity:
            ret_msg += ' %s' % (validator.validated_identity)
        logger.debug("Sending substitute fd: %s", clnt_fd)
        passfd.sendfd(self.clnt_cmd, clnt_fd, ret_msg)

        if clnt_fd == 0:
            return 0

        # Create list of all sockets in correct order to always read the session socket first
        inputs = []
        inputs.append(self.session)
        inputs.append(self.clnt_data)
        inputs.append(self.clnt_cmd)

        logger.info("Connection setup done forwarding all traffic...")
        while (not self.stop):
            inputready, outputready, exceptready = select.select(
                inputs, [], [])

            for s in inputready:
                data = s.recv(BUF_SIZE)

                if data:
                    if s is self.clnt_cmd:
                        self.process_cmd(data)
                    elif s is self.clnt_data:
                        self.session.send(data)
                    elif s is self.session:
                        self.clnt_data.send(data)
                else:
                    # Interpret empty result as closed connection and close all
                    # Ignore termination of cmd socket
                    if s is self.clnt_cmd:
                        logger.info('Client cmd socket was closed')
                        inputs.remove(self.clnt_cmd)
                    else:
                        self.close_connections()

        logger.debug("Terminating %s", self.name)
Beispiel #29
0
def send_fd(f):
    fd = f.fileno()
    passfd.sendfd(KCHAN, fd)
Beispiel #30
0
def write_message_len(m, soc):
    soc.sendall(len_encoding(m))
    if m.type == mtypes.RES_SOCKET:
        passfd.sendfd(soc, m.socfd, message="\x00")
Beispiel #31
0
#
# fork() off!
#

pid = os.fork()

if pid != 0:
    # We're in the parent.

    # ioctl() will only pass raw filedescriptors. Find fd of fileObj.
    fd = fileObj.fileno()

    # Send to the child
    os.write(wfd, "x")
    passfd.sendfd(wfd, fd)

    # Wait for child to terminate, then exit.
    os.waitpid(pid, 0)
    fileObj.close()
    sys.exit(0)

else:
    # We're in the child.

    fileObj.close()

    print os.read(rfd, 1)
    fd = passfd.recvfd(rfd)

    # Reopen the filedescriptor as a Python File-object.
Beispiel #32
0
    family = socket.AF_INET
elif nfamily == 10 :
    family = socket.AF_INET6

nsocktype = int(socket_descs[3])
socktype = socket.SOCK_SEQPACKET
if nsocktype == 1  :
    socktype = socket.SOCK_STREAM
elif nsocktype == 2 :
    socktype = socket.SOCK_DGRAM
elif nsocktype == 3 :
    socktype = socket.SOCK_RAW

s = None
for res in socket.getaddrinfo(host, port, family, socktype) :
    af, socktype, proto, canonname, sa = res
    try:
        s = socket.socket(af, socktype, proto)
    except socket.error as msg:
        s = None
        continue
    try:
        s.connect(sa)
    except socket.error as msg:
        s.close()
        s = None
        continue
    break

passfd.sendfd(message_handler.KCHAN, s.fileno(), "C")
Beispiel #33
0
#
# fork() off!
#

pid = os.fork()

if pid != 0:
    # We're in the parent.

    # ioctl() will only pass raw filedescriptors. Find fd of fileObj.
    fd = fileObj.fileno()

    # Send to the child
    os.write(wfd, "x")
    passfd.sendfd(wfd, fd)

    # Wait for child to terminate, then exit.
    os.waitpid(pid, 0)
    fileObj.close()
    sys.exit(0)

else:
    # We're in the child.

    fileObj.close()
    
    print os.read(rfd, 1)
    fd = passfd.recvfd(rfd)

    # Reopen the filedescriptor as a Python File-object.
Beispiel #34
0
 def attach_async(self, cmd, wait_pipe, stdin=0, stdout=1, stderr=2):
     self._wait_for_init()
     passfd.sendfd(self._initout, stdin, '\0'.join(cmd))
     passfd.sendfd(self._initout, stdout, 'nic')
     passfd.sendfd(self._initout, stderr, 'nic')
     passfd.sendfd(self._initout, wait_pipe, 'nic')