]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-telnet.c
Fix the pointer tests in the non-ndoified TTEST2() macro as well.
[tcpdump] / print-telnet.c
index 505369c56f487b3876b29e54d9aa810ca434f108..4911e5caf2385375daae78d32a592216342f8c7c 100644 (file)
  */
 /*
  *      @(#)Copyright (c) 1994, Simon J. Gerraty.
- *      
+ *
  *      This is free software.  It comes with NO WARRANTY.
- *      Permission to use, modify and distribute this source code 
+ *      Permission to use, modify and distribute this source code
  *      is granted subject to the following conditions.
- *      1/ that the above copyright notice and this notice 
+ *      1/ that the above copyright notice and this notice
  *      are preserved in all copies.
  */
 
 #include "config.h"
 #endif
 
-#include <sys/cdefs.h>
-#if 0
 #ifndef lint
-__RCSID("$NetBSD: print-telnet.c,v 1.2 1999/10/11 12:40:12 sjg Exp $");
-#endif
+static const char rcsid[] _U_ =
+     "@(#) $Header: /tcpdump/master/tcpdump/print-telnet.c,v 1.24 2003-12-29 11:05:10 hannes Exp $";
 #endif
 
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/types.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/ip_var.h>
-#include <netinet/tcp.h>
-#include <netinet/tcpip.h>
-
-#define TELCMDS
-#define TELOPTS
-#include <arpa/telnet.h>
+#include <tcpdump-stdinc.h>
 
 #include <stdio.h>
-#ifdef __STDC__
 #include <stdlib.h>
-#endif
-#include <unistd.h>
 #include <string.h>
 
 #include "interface.h"
 #include "addrtoname.h"
 
+#define TELCMDS
+#define TELOPTS
+#include "telnet.h"
 
-#ifndef TELCMD_FIRST
-# define TELCMD_FIRST SE
-#endif
+/* normal */
+static const char *cmds[] = {
+       "IS", "SEND", "INFO",
+};
 
-void
-telnet_print(register const u_char *sp, u_int length)
+/* 37: Authentication */
+static const char *authcmd[] = {
+       "IS", "SEND", "REPLY", "NAME",
+};
+static const char *authtype[] = {
+       "NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK",
+       "SRP", "RSA", "SSL", NULL, NULL,
+       "LOKI", "SSA", "KEA_SJ", "KEA_SJ_INTEG", "DSS",
+       "NTLM",
+};
+
+/* 38: Encryption */
+static const char *enccmd[] = {
+       "IS", "SUPPORT", "REPLY", "START", "END",
+       "REQUEST-START", "REQUEST-END", "END_KEYID", "DEC_KEYID",
+};
+static const char *enctype[] = {
+       "NULL", "DES_CFB64", "DES_OFB64", "DES3_CFB64", "DES3_OFB64",
+       NULL, "CAST5_40_CFB64", "CAST5_40_OFB64", "CAST128_CFB64", "CAST128_OFB64",
+};
+
+#define STR_OR_ID(x, tab) \
+       (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
+
+static char *
+numstr(int x)
 {
-       static char tnet[128];
-       register int i, c, x;
-       register u_char *rcp;
-       int off, first = 1;
-       u_char  *osp;
-
-       off = 0;
-       x = 0;
-       
-       while (length > 0 && *sp == IAC) {
-               osp = (u_char *) sp;
-               tnet[0] = '\0';
-               
-               c = *sp++;
-               length--;
-               switch (*sp) {
-               case IAC:                       /* <IAC><IAC>! */
-                       if (length > 1 && sp[1] == IAC) {
-                               (void)strcpy(tnet, "IAC IAC");
-                       } else {
-                               length = 0;
-                               continue;
-                       }
+       static char buf[20];
+
+       snprintf(buf, sizeof(buf), "%#x", x);
+       return buf;
+}
+
+/* sp points to IAC byte */
+static int
+telnet_parse(const u_char *sp, u_int length, int print)
+{
+       int i, x;
+       u_int c;
+       const u_char *osp, *p;
+#define FETCH(c, sp, length) \
+       do { \
+               if (length < 1) \
+                       goto pktend; \
+               TCHECK(*sp); \
+               c = *sp++; \
+               length--; \
+       } while (0)
+
+       osp = sp;
+
+       FETCH(c, sp, length);
+       if (c != IAC)
+               goto pktend;
+       FETCH(c, sp, length);
+       if (c == IAC) {         /* <IAC><IAC>! */
+               if (print)
+                       printf("IAC IAC");
+               goto done;
+       }
+
+       i = c - TELCMD_FIRST;
+       if (i < 0 || i > IAC - TELCMD_FIRST)
+               goto pktend;
+
+       switch (c) {
+       case DONT:
+       case DO:
+       case WONT:
+       case WILL:
+       case SB:
+               /* DONT/DO/WONT/WILL x */
+               FETCH(x, sp, length);
+               if (x >= 0 && x < NTELOPTS) {
+                       if (print)
+                               (void)printf("%s %s", telcmds[i], telopts[x]);
+               } else {
+                       if (print)
+                               (void)printf("%s %#x", telcmds[i], x);
+               }
+               if (c != SB)
+                       break;
+               /* IAC SB .... IAC SE */
+               p = sp;
+               while (length > (u_int)(p + 1 - sp)) {
+                       if (p[0] == IAC && p[1] == SE)
+                               break;
+                       p++;
+               }
+               if (*p != IAC)
+                       goto pktend;
+
+               switch (x) {
+               case TELOPT_AUTHENTICATION:
+                       if (p <= sp)
+                               break;
+                       FETCH(c, sp, length);
+                       if (print)
+                               (void)printf(" %s", STR_OR_ID(c, authcmd));
+                       if (p <= sp)
+                               break;
+                       FETCH(c, sp, length);
+                       if (print)
+                               (void)printf(" %s", STR_OR_ID(c, authtype));
+                       break;
+               case TELOPT_ENCRYPT:
+                       if (p <= sp)
+                               break;
+                       FETCH(c, sp, length);
+                       if (print)
+                               (void)printf(" %s", STR_OR_ID(c, enccmd));
+                       if (p <= sp)
+                               break;
+                       FETCH(c, sp, length);
+                       if (print)
+                               (void)printf(" %s", STR_OR_ID(c, enctype));
                        break;
                default:
-                       c = *sp++;
-                       length--;
-                       if ((i = c - TELCMD_FIRST) < 0
-                           || i > IAC - TELCMD_FIRST) {
-                               (void)printf("unknown: ff%02x\n", c);
-                               return;
-                       }
-                       switch (c) {
-                       case DONT:
-                       case DO:
-                       case WONT:
-                       case WILL:
-                       case SB:
-                               x = *sp++; /* option */
-                               length--;
-                               if (x >= 0 && x < NTELOPTS) {
-                                       (void)sprintf(tnet, "%s %s",
-                                                     telcmds[i], telopts[x]);
-                               } else {
-                                       (void)sprintf(tnet, "%s %#x",
-                                                     telcmds[i], x);
-                               }
+                       if (p <= sp)
                                break;
-                       default:
-                               (void)strcpy(tnet, telcmds[i]);
-                       }
-                       if (c == SB) {
-                               c = *sp++;
-                               length--;
-                               (void)strcat(tnet, c ? " SEND" : " IS '");
-                               rcp = (u_char *) sp;
-                               i = strlen(tnet);
-                               while (length > 0 && (x = *sp++) != IAC)
-                                       --length;
-                               if (x == IAC) {
-                                       if (2 < vflag
-                                           && i + 16 + sp - rcp < sizeof(tnet)) {
-                                               (void)strncpy(&tnet[i], rcp, sp - rcp);
-                                               i += (sp - rcp) - 1;
-                                               tnet[i] = '\0';
-                                       } else if (i + 8 < sizeof(tnet)) {
-                                               (void)strcat(&tnet[i], "...");
-                                       }
-                                       if (*sp++ == SE
-                                           && i + 4 < sizeof(tnet))
-                                               (void)strcat(tnet, c ? " SE" : "' SE");
-                               } else if (i + 16 < sizeof(tnet)) {
-                                       (void)strcat(tnet, " truncated!");
-                               }
-                       }
+                       FETCH(c, sp, length);
+                       if (print)
+                               (void)printf(" %s", STR_OR_ID(c, cmds));
                        break;
                }
+               while (p > sp) {
+                       FETCH(x, sp, length);
+                       if (print)
+                               (void)printf(" %#x", x);
+               }
+               /* terminating IAC SE */
+               if (print)
+                       (void)printf(" SE");
+               sp += 2;
+               length -= 2;
+               break;
+       default:
+               if (print)
+                       (void)printf("%s", telcmds[i]);
+               goto done;
+       }
+
+done:
+       return sp - osp;
+
+trunc:
+       (void)printf("[|telnet]");
+pktend:
+       return -1;
+#undef FETCH
+}
+
+void
+telnet_print(const u_char *sp, u_int length)
+{
+       int first = 1;
+       const u_char *osp;
+       int l;
+
+       osp = sp;
+
+       while (length > 0 && *sp == IAC) {
+               l = telnet_parse(sp, length, 0);
+               if (l < 0)
+                       break;
+
                /*
                 * now print it
                 */
                if (Xflag && 2 < vflag) {
                        if (first)
-                               printf("\nTelnet:\n");
-                       i = sp - osp;
-                       hex_print_with_offset(osp, i, off);
-                       off += i;
-                       if (i > 8)
-                               printf("\n\t\t\t\t%s", tnet);
+                               printf("\nTelnet:");
+                       hex_print_with_offset("\n", sp, l, sp - osp);
+                       if (l > 8)
+                               printf("\n\t\t\t\t");
                        else
-                               printf("%*s\t%s", (8 - i) * 3, "", tnet);
-               } else {
-                       printf("%s%s", (first) ? " [telnet " : ", ", tnet);
-               }
+                               printf("%*s\t", (8 - l) * 3, "");
+               } else
+                       printf("%s", (first) ? " [telnet " : ", ");
+
+               (void)telnet_parse(sp, length, 1);
                first = 0;
+
+               sp += l;
+               length -= l;
        }
        if (!first) {
                if (Xflag && 2 < vflag)