+
+ /* --- If no dynamic interfaces are available, give up --- */
+
+ if (!slipcmd) {
+ a_warn("TUN %s slip no-slip-interfaces", p_name(p));
+ goto fail;
+ }
+
+ /* --- Fork off a child process to create a dynamic SLIP interface --- */
+
+ if (pipe(pin) || pipe(pout)) {
+ a_warn("TUN %s slip pipe-error -- %s", p_name(p), strerror(errno));
+ goto fail;
+ }
+ if ((kid = fork()) < 0) {
+ a_warn("TUN %s slip fork-error -- %s", p_name(p), strerror(errno));
+ goto fail;
+ }
+ if (!kid) {
+ close(pin[1]);
+ close(pout[0]);
+ dup2(pin[0], STDIN_FILENO);
+ dup2(pout[1], STDOUT_FILENO);
+ execlp(slipcmd, slipcmd, p_name(p), (char *)0);
+ _exit(127);
+ }
+
+ /* --- Read the interface name --- */
+
+ sl = CREATE(slipif);
+ close(pin[0]); pin[0] = -1;
+ close(pout[1]); pout[1] = -1;
+ for (;;) {
+ errno = EIO;
+ if (read(pout[0], &ch, 1) != 1 || ch == SL_END) {
+ a_warn("TUN %s slip read-ifname-failed -- %s",
+ p_name(p), strerror(errno));
+ goto fail;
+ }
+ if (ch == '\n')
+ break;
+ DPUTC(&d, (char)ch);
+ }
+ DPUTZ(&d);
+ sl->name = xstrdup(d.buf);
+ sl->ifd = pout[0];
+ sl->ofd = pin[1];
+ sl->kid = kid;
+ sl->next = 0;
+ sl->f = SLIPIFF_DYNAMIC;
+ T( trace(T_TUNNEL, "tunnel: %s using dynamic slipif %s",
+ p_name(p), sl->name); )
+ fdflags(pout[0], O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
+ fdflags(pin[1], O_NONBLOCK, 0, FD_CLOEXEC, FD_CLOEXEC);
+
+ /* --- Set up the new tunnel --- */