From 898975ee8b892cadd04322dc884b3bb8d491c8f8 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sat, 22 May 2010 12:40:34 +0100 Subject: [PATCH] server/tun-slip.c, server/tripe-admin.5.in: Handle write errors. The error handling here is a little delicate. SLIP pipes are marked nonblocking, so that a slow driver won't hold up the server. We ignore EWOULDBLOCK/EAGAIN on the grounds that a dropped packet isn't particularly disastrous and SLIP is pretty good at resynchronizing. Other errors break the tunnel; we issue a warning and stop bothering to write packets at all until the interface is released and reassigned. Obviously dynamic interfaces will be discarded completely; static ones might be left broken, but at least we'll retry. Also, add the new warning to the documentation, since write errors weren't previously something we worried about. --- server/tripe-admin.5.in | 3 +++ server/tun-slip.c | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/server/tripe-admin.5.in b/server/tripe-admin.5.in index e921cfcf..21426747 100644 --- a/server/tripe-admin.5.in +++ b/server/tripe-admin.5.in @@ -1436,6 +1436,9 @@ Configuring the Linux TUN/TAP interface failed. .BI "TUN " ifname " " tun-name " read-error " ecode " " message Reading from the tunnel device failed. .SP +.BI "TUN " ifname " " tun-name " write-error " ecode " " message +Writing from the tunnel device failed. +.SP .BI "TUN " ifname " slip bad-escape" The SLIP driver encountered a escaped byte it wasn't expecting to see. The erroneous packet will be ignored. diff --git a/server/tun-slip.c b/server/tun-slip.c index 993aca9d..e807662a 100644 --- a/server/tun-slip.c +++ b/server/tun-slip.c @@ -52,6 +52,7 @@ struct tunnel { # 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 */ }; @@ -245,6 +246,29 @@ whine: 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 @@ -342,7 +366,8 @@ found: 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); @@ -394,6 +419,10 @@ static void t_inject(tunnel *t, buf *b) 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++) { @@ -408,7 +437,8 @@ static void t_inject(tunnel *t, buf *b) 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@ --- * -- 2.11.0