unsigned st; /* Current parser state */
# define ST_ESC 1u /* Last saw an escape character */
# define ST_BAD 2u /* This packet is malformed */
+# define ST_MASK 3u /* Mask for the above bits */
# define ST_EOF 4u /* File descriptor reported EOF */
+# define ST_BROKEN 8u /* Sending side is broken */
size_t n; /* Number of bytes used in buffer */
octet buf[PKBUFSZ]; /* Buffer for incoming data */
};
#endif
errno == EAGAIN)
return;
- a_warn("TUN", "%s", p_ifname(t->p), "read-error", "?ERRNO", A_END);
+ a_warn("TUN", "%s", p_ifname(t->p), "slip",
+ "read-error", "?ERRNO", A_END);
return;
}
if (!n) {
a_warn("TUN", "%s", p_ifname(t->p), "slip", "eof", A_END);
- t->st = ST_EOF;
+ t->st = (t->st & ~ST_MASK) | ST_EOF;
sel_rmfile(&t->f);
return;
}
case SL_END:
if (st & ST_BAD)
;
- else if (st & ST_ESC)
+ else if (st & ST_ESC) {
a_warn("TUN", "%s", p_ifname(t->p), "slip", "escape-end", A_END);
- else if (q == t->buf) {
+ st |= ST_BAD;
+ } else if (q == t->buf) {
T( trace(T_TUNNEL, "tun-slip: empty packet"); )
} else {
IF_TRACING(T_TUNNEL, {
p_tun(t->p, &b);
}
q = t->buf;
- st &= ~(ST_ESC | ST_BAD);
+ st &= ~ST_MASK;
break;
case SL_ESC:
if ((st & ST_ESC) && !(st & ST_BAD)) {
moan("bad slip interface list");
}
+/* --- @t_broken@ --- *
+ *
+ * Arguments: @tunnel *t@ = pointer to the tunnel
+ *
+ * Returns: ---
+ *
+ * Use: Marks the tunnel as broken and reports an error.
+ */
+
+static void t_broken(tunnel *t)
+{
+ if (errno == EINTR ||
+#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
+ errno == EWOULDBLOCK ||
+#endif
+ errno == EAGAIN)
+ return;
+ a_warn("TUN", "%s", p_ifname(t->p), "slip",
+ "write-error", "?ERRNO", A_END);
+ T( trace(T_TUNNEL, "tun-slip: marking tunnel broken"); )
+ t->st |= ST_BROKEN;
+}
+
/* --- @t_create@ --- *
*
* Arguments: @peer *p@ = pointer to peer block
{
slipif *sl = 0;
int pin[2] = { -1, -1 }, pout[2] = { -1, -1 };
+ mdup_fd md[2];
pid_t kid = -1;
dstr d = DSTR_INIT;
unsigned char ch;
tunnel *t;
- static const char end[] = { SL_END, SL_END };
+ static const octet end[] = { SL_END, SL_END };
/* --- Try to find a spare static interface --- */
goto fail;
}
if (!kid) {
- close(pin[1]);
- close(pout[0]);
- dup2(pin[0], STDIN_FILENO);
- dup2(pout[1], STDOUT_FILENO);
+ close(pin[1]); close(pout[0]);
+ md[0].cur = pin[0]; md[0].want = STDIN_FILENO;
+ md[1].cur = pout[1]; md[1].want = STDOUT_FILENO;
+ mdup(md, 2);
execlp(slipcmd, slipcmd, p_name(p), (char *)0);
_exit(127);
}
sl->f |= F_INUSE;
sel_initfile(&sel, &t->f, sl->ifd, SEL_READ, t_read, t);
sel_addfile(&t->f);
- write(sl->ofd, end, sizeof(end));
+ if (write(sl->ofd, end, sizeof(end)) < 0)
+ t_broken(t);
*ifn = xstrdup(sl->name);
dstr_destroy(&d);
return (t);
trace_block(T_PACKET, "tun-slip: packet contents", BBASE(b), BLEN(b));
})
+ if (t-> st & ST_BROKEN) {
+ T( trace(T_TUNNEL, "tun-slip: tunnel broken; discarding"); )
+ return;
+ }
q = buf;
*q++ = SL_END;
for (p = BBASE(b), l = BCUR(b); p < l; p++) {
trace_block(T_PACKET, "tun-slip: SLIP-encapsulated contents",
buf, q - buf);
})
- write(t->sl->ofd, buf, q - buf);
+ if (write(t->sl->ofd, buf, q - buf) < 0)
+ t_broken(t);
}
/* --- @t_destroy@ --- *