/* $NetBSD: print-telnet.c,v 1.2 1999/10/11 12:40:12 sjg Exp $ */ /*- * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Simon J. Gerraty. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * @(#)Copyright (c) 1994, Simon J. Gerraty. * * This is free software. It comes with NO WARRANTY. * 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 * are preserved in all copies. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifndef lint static const char rcsid[] = "@(#) $Header: /tcpdump/master/tcpdump/print-telnet.c,v 1.18 2001/09/10 06:40:08 fenner Exp $"; #endif #include <sys/param.h> #include <sys/time.h> #include <sys/types.h> #include <ctype.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include "interface.h" #include "addrtoname.h" #define TELCMDS #define TELOPTS #include "telnet.h" /* normal */ static const char *cmds[] = { "IS", "SEND", "INFO", }; /* 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 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, c, x; 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 > 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: if (p <= sp) break; 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:"); hex_print_with_offset(sp, l, sp - osp); if (l > 8) printf("\n\t\t\t\t"); else 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) printf("\n"); else printf("]"); } }