print-tftp.c revision 276788
117680Spst/*
239297Sfenner * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
317680Spst *	The Regents of the University of California.  All rights reserved.
417680Spst *
517680Spst * Redistribution and use in source and binary forms, with or without
617680Spst * modification, are permitted provided that: (1) source code distributions
717680Spst * retain the above copyright notice and this paragraph in its entirety, (2)
817680Spst * distributions including binary code include the above copyright notice and
917680Spst * this paragraph in its entirety in the documentation or other materials
1017680Spst * provided with the distribution, and (3) all advertising materials mentioning
1117680Spst * features or use of this software display the following acknowledgement:
1217680Spst * ``This product includes software developed by the University of California,
1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1417680Spst * the University nor the names of its contributors may be used to endorse
1517680Spst * or promote products derived from this software without specific prior
1617680Spst * written permission.
1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2017680Spst *
2117680Spst * Format and print trivial file transfer protocol packets.
2217680Spst */
2317680Spst
24276788Sdelphij#define NETDISSECT_REWORKED
2556893Sfenner#ifdef HAVE_CONFIG_H
2656893Sfenner#include "config.h"
2756893Sfenner#endif
2856893Sfenner
29127668Sbms#include <tcpdump-stdinc.h>
3017680Spst
3117680Spst#include <string.h>
3217680Spst
3317680Spst#include "interface.h"
34127668Sbms#include "extract.h"
3517680Spst
36276788Sdelphij/*
37276788Sdelphij * Trivial File Transfer Protocol (IEN-133)
38276788Sdelphij */
39276788Sdelphij
40276788Sdelphij/*
41276788Sdelphij * Packet types.
42276788Sdelphij */
43276788Sdelphij#define	RRQ	01			/* read request */
44276788Sdelphij#define	WRQ	02			/* write request */
45276788Sdelphij#define	DATA	03			/* data packet */
46276788Sdelphij#define	ACK	04			/* acknowledgement */
47276788Sdelphij#define	TFTP_ERROR	05			/* error code */
48276788Sdelphij#define OACK	06			/* option acknowledgement */
49276788Sdelphij
50276788Sdelphijstruct	tftphdr {
51276788Sdelphij	unsigned short	th_opcode;		/* packet type */
52276788Sdelphij	union {
53276788Sdelphij		unsigned short	tu_block;	/* block # */
54276788Sdelphij		unsigned short	tu_code;	/* error code */
55276788Sdelphij		char	tu_stuff[1];	/* request packet stuff */
56276788Sdelphij	} th_u;
57276788Sdelphij	char	th_data[1];		/* data or error string */
58276788Sdelphij};
59276788Sdelphij
60276788Sdelphij#define	th_block	th_u.tu_block
61276788Sdelphij#define	th_code		th_u.tu_code
62276788Sdelphij#define	th_stuff	th_u.tu_stuff
63276788Sdelphij#define	th_msg		th_data
64276788Sdelphij
65276788Sdelphij/*
66276788Sdelphij * Error codes.
67276788Sdelphij */
68276788Sdelphij#define	EUNDEF		0		/* not defined */
69276788Sdelphij#define	ENOTFOUND	1		/* file not found */
70276788Sdelphij#define	EACCESS		2		/* access violation */
71276788Sdelphij#define	ENOSPACE	3		/* disk full or allocation exceeded */
72276788Sdelphij#define	EBADOP		4		/* illegal TFTP operation */
73276788Sdelphij#define	EBADID		5		/* unknown transfer ID */
74276788Sdelphij#define	EEXISTS		6		/* file already exists */
75276788Sdelphij#define	ENOUSER		7		/* no such user */
76276788Sdelphij
77276788Sdelphijstatic const char tstr[] = " [|tftp]";
78276788Sdelphij
7917680Spst/* op code to string mapping */
80276788Sdelphijstatic const struct tok op2str[] = {
8117680Spst	{ RRQ,		"RRQ" },	/* read request */
8217680Spst	{ WRQ,		"WRQ" },	/* write request */
8317680Spst	{ DATA,		"DATA" },	/* data packet */
8417680Spst	{ ACK,		"ACK" },	/* acknowledgement */
85190207Srpaulo	{ TFTP_ERROR,	"ERROR" },	/* error code */
86172683Smlaier	{ OACK,		"OACK" },	/* option acknowledgement */
8717680Spst	{ 0,		NULL }
8817680Spst};
8917680Spst
9017680Spst/* error code to string mapping */
91276788Sdelphijstatic const struct tok err2str[] = {
9217680Spst	{ EUNDEF,	"EUNDEF" },	/* not defined */
9317680Spst	{ ENOTFOUND,	"ENOTFOUND" },	/* file not found */
9417680Spst	{ EACCESS,	"EACCESS" },	/* access violation */
9517680Spst	{ ENOSPACE,	"ENOSPACE" },	/* disk full or allocation exceeded */
9617680Spst	{ EBADOP,	"EBADOP" },	/* illegal TFTP operation */
9717680Spst	{ EBADID,	"EBADID" },	/* unknown transfer ID */
9817680Spst	{ EEXISTS,	"EEXISTS" },	/* file already exists */
9917680Spst	{ ENOUSER,	"ENOUSER" },	/* no such user */
10017680Spst	{ 0,		NULL }
10117680Spst};
10217680Spst
10317680Spst/*
10417680Spst * Print trivial file transfer program requests
10517680Spst */
10617680Spstvoid
107276788Sdelphijtftp_print(netdissect_options *ndo,
108276788Sdelphij           register const u_char *bp, u_int length)
10917680Spst{
11017680Spst	register const struct tftphdr *tp;
11117680Spst	register const char *cp;
11217680Spst	register const u_char *p;
11317680Spst	register int opcode, i;
11417680Spst
11517680Spst	tp = (const struct tftphdr *)bp;
11617680Spst
11717680Spst	/* Print length */
118276788Sdelphij	ND_PRINT((ndo, " %d", length));
11917680Spst
12017680Spst	/* Print tftp request type */
121276788Sdelphij	ND_TCHECK(tp->th_opcode);
122127668Sbms	opcode = EXTRACT_16BITS(&tp->th_opcode);
12317680Spst	cp = tok2str(op2str, "tftp-#%d", opcode);
124276788Sdelphij	ND_PRINT((ndo, " %s", cp));
12517680Spst	/* Bail if bogus opcode */
12617680Spst	if (*cp == 't')
12717680Spst		return;
12817680Spst
12917680Spst	switch (opcode) {
13017680Spst
13117680Spst	case RRQ:
13217680Spst	case WRQ:
133172683Smlaier	case OACK:
13417680Spst		p = (u_char *)tp->th_stuff;
135276788Sdelphij		ND_PRINT((ndo, " "));
136172683Smlaier		/* Print filename or first option */
137172683Smlaier		if (opcode != OACK)
138276788Sdelphij			ND_PRINT((ndo, "\""));
139276788Sdelphij		i = fn_print(ndo, p, ndo->ndo_snapend);
140172683Smlaier		if (opcode != OACK)
141276788Sdelphij			ND_PRINT((ndo, "\""));
142127668Sbms
143172683Smlaier		/* Print the mode (RRQ and WRQ only) and any options */
144127668Sbms		while ((p = (const u_char *)strchr((const char *)p, '\0')) != NULL) {
145127668Sbms			if (length <= (u_int)(p - (const u_char *)&tp->th_block))
146127668Sbms				break;
147127668Sbms			p++;
148127668Sbms			if (*p != '\0') {
149276788Sdelphij				ND_PRINT((ndo, " "));
150276788Sdelphij				fn_print(ndo, p, ndo->ndo_snapend);
151127668Sbms			}
152127668Sbms		}
153276788Sdelphij
15417680Spst		if (i)
15517680Spst			goto trunc;
15617680Spst		break;
15717680Spst
15817680Spst	case ACK:
15917680Spst	case DATA:
160276788Sdelphij		ND_TCHECK(tp->th_block);
161276788Sdelphij		ND_PRINT((ndo, " block %d", EXTRACT_16BITS(&tp->th_block)));
16217680Spst		break;
16317680Spst
164190207Srpaulo	case TFTP_ERROR:
16517680Spst		/* Print error code string */
166276788Sdelphij		ND_TCHECK(tp->th_code);
167276788Sdelphij		ND_PRINT((ndo, " %s \"", tok2str(err2str, "tftp-err-#%d \"",
168276788Sdelphij				       EXTRACT_16BITS(&tp->th_code))));
16917680Spst		/* Print error message string */
170276788Sdelphij		i = fn_print(ndo, (const u_char *)tp->th_data, ndo->ndo_snapend);
171276788Sdelphij		ND_PRINT((ndo, "\""));
17217680Spst		if (i)
17317680Spst			goto trunc;
17417680Spst		break;
17517680Spst
17617680Spst	default:
17717680Spst		/* We shouldn't get here */
178276788Sdelphij		ND_PRINT((ndo, "(unknown #%d)", opcode));
17917680Spst		break;
18017680Spst	}
18117680Spst	return;
18217680Spsttrunc:
183276788Sdelphij	ND_PRINT((ndo, "%s", tstr));
18417680Spst	return;
18517680Spst}
186