]> err.no Git - varnish/commitdiff
Add minimal facility for dealing with TELNET option negotiation
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Tue, 3 Mar 2009 12:23:11 +0000 (12:23 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Tue, 3 Mar 2009 12:23:11 +0000 (12:23 +0000)
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

varnish-cache/bin/varnishd/mgt_cli.c
varnish-cache/include/vlu.h
varnish-cache/lib/libvarnish/vlu.c

index 3068395ebb5d55a13feadd228a4b3cc734c12592..d26826556a5803680bd47a62987f2e625485cd41 100644 (file)
@@ -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.
index 3dd7eeab47e331bf5253a3b51c3d61d2c895037d..60cfa179bd7a86ac747b667672f6e17e7f17d14e 100644 (file)
@@ -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
index c728749dce4435fc2cfc5501ddfe3e3edc3ae03e..3aec587950a9bb34499ecc2423979779d4900411 100644 (file)
@@ -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';