From: phk Date: Tue, 3 Mar 2009 12:23:11 +0000 (+0000) Subject: Add minimal facility for dealing with TELNET option negotiation X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e8023ae4e077fa0439c14ff1630641491842634f;p=varnish Add minimal facility for dealing with TELNET option negotiation in a way that telnet clients don't get confused about: Return WONT on to all DO or DONT and ignore everything else. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@3866 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/varnish-cache/bin/varnishd/mgt_cli.c b/varnish-cache/bin/varnishd/mgt_cli.c index 3068395e..d2682655 100644 --- a/varnish-cache/bin/varnishd/mgt_cli.c +++ b/varnish-cache/bin/varnishd/mgt_cli.c @@ -501,6 +501,10 @@ mgt_cli_setup(int fdi, int fdo, int verbose, const char *ident) XXXAN(cp->cli->sb); cp->cli->priv = cp; + /* Deal with TELNET options */ + if (cp->fdi != 0) + VLU_SetTelnet(cp->vlu, cp->fdo); + /* * If we have a secret file authenticate all CLI connections * except the stdin/stdout debug port. diff --git a/varnish-cache/include/vlu.h b/varnish-cache/include/vlu.h index 3dd7eeab..60cfa179 100644 --- a/varnish-cache/include/vlu.h +++ b/varnish-cache/include/vlu.h @@ -38,5 +38,6 @@ int VLU_Fd(int fd, struct vlu *l); int VLU_File(FILE *f, struct vlu *l); int VLU_Data(const void *ptr, int len, struct vlu *l); void VLU_Destroy(struct vlu *l); +void VLU_SetTelnet(struct vlu *l, int fd); #endif diff --git a/varnish-cache/lib/libvarnish/vlu.c b/varnish-cache/lib/libvarnish/vlu.c index c728749d..3aec5879 100644 --- a/varnish-cache/lib/libvarnish/vlu.c +++ b/varnish-cache/lib/libvarnish/vlu.c @@ -46,6 +46,7 @@ struct vlu { unsigned bufl; unsigned bufp; void *priv; + int telnet; vlu_f *func; }; @@ -66,10 +67,19 @@ VLU_New(void *priv, vlu_f *func, unsigned bufsize) FREE_OBJ(l); l = NULL; } + l->telnet = -1; } return (l); } +void +VLU_SetTelnet(struct vlu *l, int fd) +{ + CHECK_OBJ_NOTNULL(l, LINEUP_MAGIC); + assert(fd >= 0); + l->telnet = fd; +} + void VLU_Destroy(struct vlu *l) { @@ -79,6 +89,51 @@ VLU_Destroy(struct vlu *l) FREE_OBJ(l); } +static int +vlu_dotelnet(struct vlu *l, char *p) +{ + char *e; + char tno[3]; + int i; + + e = l->buf + l->bufp; + assert(p >= l->buf && p < e); + assert(*p == (char)255); + + /* We need at least two characters */ + if (p == e - 1) + return (1); + + /* And three for will/wont/do/dont */ + if (p[1] >= (char)251 && p[1] <= (char)254 && p == e - 2) + return (1); + + switch (p[1]) { + case (char)251: /* WILL */ + case (char)252: /* WONT */ + /* Ignore these */ + i = 3; + break; + case (char)253: /* DO */ + case (char)254: /* DONT */ + /* Return WONT for these */ + memcpy(tno, p, 3); + tno[1] = (char)252; + write(l->telnet, tno, 3); + i = 3; + break; + default: + /* Ignore the rest */ + /* XXX: only p[1] >= 240 ? */ + i = 2; + } + + /* Remove telnet sequence from buffer */ + memmove(p, p + i, 1 + e - (p + i)); + l->bufp -= i; + return (0); +} + static int LineUpProcess(struct vlu *l) { @@ -88,9 +143,13 @@ LineUpProcess(struct vlu *l) l->buf[l->bufp] = '\0'; for (p = l->buf; *p != '\0'; p = q) { /* Find first CR or NL */ - for (q = p; *q != '\0'; q++) + for (q = p; *q != '\0'; q++) { + while (l->telnet >= 0 && *q == (char)255) + if (vlu_dotelnet(l, q)) + return (0); if (*q == '\n' || *q == '\r') break; + } if (*q == '\0') break; *q++ = '\0';