print-fddi.c \
print-forces.c \
print-fr.c \
+ print-ftp.c \
print-geonet.c \
print-gre.c \
print-hsrp.c \
+ print-http.c \
print-icmp.c \
print-igmp.c \
print-igrp.c \
print-rpki-rtr.c \
print-rrcp.c \
print-rsvp.c \
+ print-rtsp.c \
print-rx.c \
print-sctp.c \
print-sflow.c \
print-sl.c \
print-sll.c \
print-slow.c \
+ print-smtp.c \
print-snmp.c \
print-stp.c \
print-sunatm.c \
extern int fn_printzp(netdissect_options *, const u_char *, u_int, const u_char *);
extern const char *tok2str(const struct tok *, const char *, int);
+#define RESP_CODE_SECOND_TOKEN 0x00000001
+
+extern void txtproto_print(netdissect_options *, const u_char *, u_int,
+ const char *, const char **, u_int);
+
#if 0
extern char *read_infile(netdissect_options *, char *);
extern char *copy_argv(netdissect_options *, char **);
extern void timed_print(netdissect_options *, const u_char *);
extern void m3ua_print(netdissect_options *, const u_char *, const u_int);
extern void aoe_print(netdissect_options *, const u_char *, const u_int);
+extern void ftp_print(netdissect_options *, const u_char *, u_int);
+extern void http_print(netdissect_options *, const u_char *, u_int);
+extern void rtsp_print(netdissect_options *, const u_char *, u_int);
+extern void smtp_print(netdissect_options *, const u_char *, u_int);
/* stuff that has not yet been rototiled */
--- /dev/null
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+ "@(#) $Header$";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "netdissect.h"
+#include "extract.h"
+
+void
+ftp_print(netdissect_options *ndo, const u_char *pptr, u_int len)
+{
+ txtproto_print(ndo, pptr, len, "ftp", NULL, 0);
+}
--- /dev/null
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+ "@(#) $Header$";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "interface.h"
+#include "extract.h"
+
+/*
+ * Includes WebDAV requests.
+ */
+static const char *httpcmds[] = {
+ "GET",
+ "PUT",
+ "COPY",
+ "HEAD",
+ "LOCK",
+ "MOVE",
+ "POLL",
+ "POST",
+ "BCOPY",
+ "BMOVE",
+ "MKCOL",
+ "TRACE",
+ "LABEL",
+ "MERGE",
+ "DELETE",
+ "SEARCH",
+ "UNLOCK",
+ "REPORT",
+ "UPDATE",
+ "NOTIFY",
+ "BDELETE",
+ "CONNECT",
+ "OPTIONS",
+ "CHECKIN",
+ "PROPFIND",
+ "CHECKOUT",
+ "CCM_POST",
+ "SUBSCRIBE",
+ "PROPPATCH",
+ "BPROPFIND",
+ "BPROPPATCH",
+ "UNCHECKOUT",
+ "MKACTIVITY",
+ "MKWORKSPACE",
+ "UNSUBSCRIBE",
+ "RPC_CONNECT",
+ "VERSION-CONTROL",
+ "BASELINE-CONTROL",
+ NULL
+};
+
+void
+http_print(netdissect_options *ndo, const u_char *pptr, u_int len)
+{
+ txtproto_print(ndo, pptr, len, "http", httpcmds, RESP_CODE_SECOND_TOKEN);
+}
--- /dev/null
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+ "@(#) $Header$";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "interface.h"
+#include "extract.h"
+
+static const char *rtspcmds[] = {
+ "DESCRIBE",
+ "ANNOUNCE",
+ "GET_PARAMETER",
+ "OPTIONS",
+ "PAUSE",
+ "PLAY",
+ "RECORD",
+ "REDIRECT",
+ "SETUP",
+ "SET_PARAMETER",
+ "TEARDOWN",
+ NULL
+};
+
+void
+rtsp_print(netdissect_options *ndo, const u_char *pptr, u_int len)
+{
+ txtproto_print(ndo, pptr, len, "rtsp", rtspcmds, RESP_CODE_SECOND_TOKEN);
+}
* FOR A PARTICULAR PURPOSE.
*
+ * Turned into common "text protocol" code, which this uses, by
+ * Guy Harris.
*/
#define NETDISSECT_REWORKED
#include "interface.h"
#include "extract.h"
+static const char *sipcmds[] = {
+ "ACK",
+ "BYE",
+ "CANCEL",
+ "DO",
+ "INFO",
+ "INVITE",
+ "MESSAGE",
+ "NOTIFY",
+ "OPTIONS",
+ "PRACK",
+ "QAUTH",
+ "REFER",
+ "REGISTER",
+ "SPRACK",
+ "SUBSCRIBE",
+ "UPDATE",
+ "PUBLISH",
+ NULL
+};
+
void
-sip_print(netdissect_options *ndo,
- register const u_char *pptr, register u_int len)
+sip_print(netdissect_options *ndo, const u_char *pptr, u_int len)
{
- u_int idx;
-
- ND_PRINT((ndo, "SIP, length: %u%s", len, ndo->ndo_vflag ? "\n\t" : ""));
-
- /* in non-verbose mode just lets print the protocol and length */
- if (ndo->ndo_vflag < 1)
- return;
-
- for (idx = 0; idx < len; idx++) {
- ND_TCHECK2(*(pptr+idx), 2);
- if (EXTRACT_16BITS(pptr+idx) != 0x0d0a) { /* linefeed ? */
- safeputchar(ndo, *(pptr + idx));
- } else {
- ND_PRINT((ndo, "\n\t"));
- idx+=1;
- }
- }
-
- /* do we want to see an additionally hexdump ? */
- if (ndo->ndo_vflag > 1)
- print_unknown_data(ndo, pptr, "\n\t", len);
-
- return;
-
-trunc:
- ND_PRINT((ndo, "[|sip]"));
+ txtproto_print(ndo, pptr, len, "sip", sipcmds, RESP_CODE_SECOND_TOKEN);
}
--- /dev/null
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "netdissect.h"
+#include "extract.h"
+
+void
+smtp_print(netdissect_options *ndo, const u_char *pptr, u_int len)
+{
+ txtproto_print(ndo, pptr, len, "smtp", NULL, 0);
+}
if (sport == TELNET_PORT || dport == TELNET_PORT) {
if (!ndo->ndo_qflag && ndo->ndo_vflag)
telnet_print(ndo, bp, length);
+ } else if (sport == SMTP_PORT || dport == SMTP_PORT) {
+ ND_PRINT((ndo, ": "));
+ smtp_print(ndo, bp, length);
} else if (sport == BGP_PORT || dport == BGP_PORT)
bgp_print(ndo, bp, length);
else if (sport == PPTP_PORT || dport == PPTP_PORT)
else if (sport == OPENFLOW_PORT_OLD || dport == OPENFLOW_PORT_OLD ||
sport == OPENFLOW_PORT_IANA || dport == OPENFLOW_PORT_IANA)
openflow_print(ndo, bp, length);
- else if (length > 2 &&
+ else if (sport == FTP_PORT || dport == FTP_PORT) {
+ ND_PRINT((ndo, ": "));
+ ftp_print(ndo, bp, length);
+ } else if (sport == HTTP_PORT || dport == HTTP_PORT ||
+ sport == HTTP_PORT_ALT || dport == HTTP_PORT_ALT) {
+ ND_PRINT((ndo, ": "));
+ http_print(ndo, bp, length);
+ } else if (sport == RTSP_PORT || dport == RTSP_PORT ||
+ sport == RTSP_PORT_ALT || dport == RTSP_PORT_ALT) {
+ ND_PRINT((ndo, ": "));
+ rtsp_print(ndo, bp, length);
+ } else if (length > 2 &&
(sport == NAMESERVER_PORT || dport == NAMESERVER_PORT ||
sport == MULTICASTDNS_PORT || dport == MULTICASTDNS_PORT)) {
/*
#ifndef TELNET_PORT
#define TELNET_PORT 23
#endif
+#ifndef SMTP_PORT
+#define SMTP_PORT 25
+#endif
#ifndef BGP_PORT
#define BGP_PORT 179
#endif
#ifndef SMB_PORT
#define SMB_PORT 445
#endif
+#ifndef HTTP_PORT
+#define HTTP_PORT 80
+#endif
+#ifndef HTTP_PORT_ALT
+#define HTTP_PORT_ALT 8080
+#endif
+#ifndef RTSP_PORT
+#define RTSP_PORT 554
+#endif
+#ifndef RTSP_PORT_ALT
+#define RTSP_PORT_ALT 8554
+#endif
+#ifndef FTP_PORT
+#define FTP_PORT 21
+#endif
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
+/*
+ * txtproto_print() derived from original code by Hannes Gredler
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ */
+
#define NETDISSECT_REWORKED
#ifdef HAVE_CONFIG_H
#include "config.h"
}
#endif /* INET6 */
+/*
+ * Routine to print out information for text-based protocols such as FTP,
+ * HTTP, SMTP, RTSP, SIP, ....
+ */
+#define MAX_TOKEN 128
+
+/*
+ * Fetch a token from a packet, starting at the specified index,
+ * and return the length of the token.
+ *
+ * Returns 0 on error; yes, this is indistinguishable from an empty
+ * token, but an "empty token" isn't a valid token - it just means
+ * either a space character at the beginning of the line (this
+ * includes a blank line) or no more tokens remaining on the line.
+ */
+static int
+fetch_token(netdissect_options *ndo, const u_char *pptr, u_int idx, u_int len,
+ u_char *tbuf, size_t tbuflen)
+{
+ size_t toklen = 0;
+
+ for (; idx < len; idx++) {
+ if (!ND_TTEST(*(pptr + idx))) {
+ /* ran past end of captured data */
+ return (0);
+ }
+ if (!isascii(*(pptr + idx))) {
+ /* not an ASCII character */
+ return (0);
+ }
+ if (isspace(*(pptr + idx))) {
+ /* end of token */
+ break;
+ }
+ if (!isprint(*(pptr + idx))) {
+ /* not part of a command token or response code */
+ return (0);
+ }
+ if (toklen + 2 > tbuflen) {
+ /* no room for this character and terminating '\0' */
+ return (0);
+ }
+ tbuf[toklen] = *(pptr + idx);
+ toklen++;
+ }
+ if (toklen == 0) {
+ /* no token */
+ return (0);
+ }
+ tbuf[toklen] = '\0';
+
+ /*
+ * Skip past any white space after the token, until we see
+ * an end-of-line (CR or LF).
+ */
+ for (; idx < len; idx++) {
+ if (!ND_TTEST(*(pptr + idx))) {
+ /* ran past end of captured data */
+ break;
+ }
+ if (*(pptr + idx) == '\r' || *(pptr + idx) == '\n') {
+ /* end of line */
+ break;
+ }
+ if (!isascii(*(pptr + idx)) || !isprint(*(pptr + idx))) {
+ /* not a printable ASCII character */
+ break;
+ }
+ if (!isspace(*(pptr + idx))) {
+ /* beginning of next token */
+ break;
+ }
+ }
+ return (idx);
+}
+
+/*
+ * Scan a buffer looking for a line ending - LF or CR-LF.
+ * Return the index of the character after the line ending or 0 if
+ * we encounter a non-ASCII or non-printable character or don't find
+ * the line ending.
+ */
+static u_int
+print_txt_line(netdissect_options *ndo, const char *protoname,
+ const char *prefix, const u_char *pptr, u_int idx, u_int len)
+{
+ u_int startidx;
+ u_int linelen;
+
+ startidx = idx;
+ while (idx < len) {
+ ND_TCHECK(*(pptr+idx));
+ if (*(pptr+idx) == '\n') {
+ /*
+ * LF without CR; end of line.
+ * Skip the LF and print the line, with the
+ * exception of the LF.
+ */
+ linelen = idx - startidx;
+ idx++;
+ goto print;
+ } else if (*(pptr+idx) == '\r') {
+ /* CR - any LF? */
+ if ((idx+1) >= len) {
+ /* not in this packet */
+ return (0);
+ }
+ ND_TCHECK(*(pptr+idx+1));
+ if (*(pptr+idx+1) == '\n') {
+ /*
+ * CR-LF; end of line.
+ * Skip the CR-LF and print the line, with
+ * the exception of the CR-LF.
+ */
+ linelen = idx - startidx;
+ idx += 2;
+ goto print;
+ }
+
+ /*
+ * CR followed by something else; treat this
+ * as if it were binary data, and don't print
+ * it.
+ */
+ return (0);
+ } else if (!isascii(*(pptr+idx)) ||
+ (!isprint(*(pptr+idx)) && *(pptr+idx) != '\t')) {
+ /*
+ * Not a printable ASCII character and not a tab;
+ * treat this as if it were binary data, and
+ * don't print it.
+ */
+ return (0);
+ }
+ idx++;
+ }
+
+ /*
+ * All printable ASCII, but no line ending after that point
+ * in the buffer; treat this as if it were truncated.
+ */
+trunc:
+ ND_PRINT((ndo, "%s%.*s[!%s]", prefix, (int)linelen, pptr + startidx,
+ protoname));
+ return (0);
+
+print:
+ ND_PRINT((ndo, "%s%.*s", prefix, (int)linelen, pptr + startidx));
+ return (idx);
+}
+
+void
+txtproto_print(netdissect_options *ndo, const u_char *pptr, u_int len,
+ const char *protoname, const char **cmds, u_int flags)
+{
+ u_int idx, eol;
+ u_char token[MAX_TOKEN+1];
+ const char *cmd;
+ int is_reqresp = 0;
+ const char *pnp;
+
+ if (cmds != NULL) {
+ /*
+ * This protocol has more than just request and
+ * response lines; see whether this looks like a
+ * request or response.
+ */
+ idx = fetch_token(ndo, pptr, 0, len, token, sizeof(token));
+ if (idx != 0) {
+ /* Is this a valid request name? */
+ while ((cmd = *cmds++) != NULL) {
+ if (strcasecmp((const char *)token, cmd) == 0) {
+ /* Yes. */
+ is_reqresp = 1;
+ break;
+ }
+ }
+
+ /*
+ * No - is this a valid response code (3 digits)?
+ *
+ * Is this token the response code, or is the next
+ * token the response code?
+ */
+ if (flags & RESP_CODE_SECOND_TOKEN) {
+ /*
+ * Next token - get it.
+ */
+ idx = fetch_token(ndo, pptr, idx, len, token,
+ sizeof(token));
+ }
+ if (idx != 0) {
+ if (isdigit(token[0]) && isdigit(token[1]) &&
+ isdigit(token[2]) && token[3] == '\0') {
+ /* Yes. */
+ is_reqresp = 1;
+ }
+ }
+ }
+ } else {
+ /*
+ * This protocol has only request and response lines
+ * (e.g., FTP, where all the data goes over a
+ * different connection); assume the payload is
+ * a request or response.
+ */
+ is_reqresp = 1;
+ }
+
+ /* Capitalize the protocol name */
+ for (pnp = protoname; *pnp != '\0'; pnp++)
+ ND_PRINT((ndo, "%c", toupper(*pnp)));
+
+ if (is_reqresp) {
+ /*
+ * In non-verbose mode, just print the protocol, followed
+ * by the first line as the request or response info.
+ *
+ * In verbose mode, print lines as text until we run out
+ * of characters or see something that's not a
+ * printable-ASCII line.
+ */
+ if (ndo->ndo_vflag) {
+ /*
+ * We're going to print all the text lines in the
+ * request or response; just print the length
+ * on the first line of the output.
+ */
+ ND_PRINT((ndo, ", length: %u", len));
+ for (idx = 0;
+ idx < len && (eol = print_txt_line(ndo, protoname, "\n\t", pptr, idx, len)) != 0;
+ idx = eol)
+ ;
+ } else {
+ /*
+ * Just print the first text line.
+ */
+ print_txt_line(ndo, protoname, ": ", pptr, 0, len);
+ }
+ }
+}
+
/* VARARGS */
void
error(const char *fmt, ...)