print-tftp.c revision 1.2
1/*
2 * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 * Format and print trivial file transfer protocol packets.
22 */
23
24#include <sys/cdefs.h>
25#ifndef lint
26#if 0
27static const char rcsid[] _U_ =
28    "@(#) Header: /tcpdump/master/tcpdump/print-tftp.c,v 1.39 2008-04-11 16:47:38 gianluca Exp (LBL)";
29#else
30__RCSID("$NetBSD: print-tftp.c,v 1.2 2010/12/05 05:11:31 christos Exp $");
31#endif
32#endif
33
34#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37
38#include <tcpdump-stdinc.h>
39
40#ifdef SEGSIZE
41#undef SEGSIZE					/* SINIX sucks */
42#endif
43
44#include <stdio.h>
45#include <string.h>
46
47#include "interface.h"
48#include "addrtoname.h"
49#include "extract.h"
50#include "tftp.h"
51
52/* op code to string mapping */
53static struct tok op2str[] = {
54	{ RRQ,		"RRQ" },	/* read request */
55	{ WRQ,		"WRQ" },	/* write request */
56	{ DATA,		"DATA" },	/* data packet */
57	{ ACK,		"ACK" },	/* acknowledgement */
58	{ TFTP_ERROR,	"ERROR" },	/* error code */
59	{ OACK,		"OACK" },	/* option acknowledgement */
60	{ 0,		NULL }
61};
62
63/* error code to string mapping */
64static struct tok err2str[] = {
65	{ EUNDEF,	"EUNDEF" },	/* not defined */
66	{ ENOTFOUND,	"ENOTFOUND" },	/* file not found */
67	{ EACCESS,	"EACCESS" },	/* access violation */
68	{ ENOSPACE,	"ENOSPACE" },	/* disk full or allocation exceeded */
69	{ EBADOP,	"EBADOP" },	/* illegal TFTP operation */
70	{ EBADID,	"EBADID" },	/* unknown transfer ID */
71	{ EEXISTS,	"EEXISTS" },	/* file already exists */
72	{ ENOUSER,	"ENOUSER" },	/* no such user */
73	{ 0,		NULL }
74};
75
76/*
77 * Print trivial file transfer program requests
78 */
79void
80tftp_print(register const u_char *bp, u_int length)
81{
82	register const struct tftphdr *tp;
83	register const char *cp;
84	register const u_char *p;
85	register int opcode, i;
86	static char tstr[] = " [|tftp]";
87
88	tp = (const struct tftphdr *)bp;
89
90	/* Print length */
91	printf(" %d", length);
92
93	/* Print tftp request type */
94	TCHECK(tp->th_opcode);
95	opcode = EXTRACT_16BITS(&tp->th_opcode);
96	cp = tok2str(op2str, "tftp-#%d", opcode);
97	printf(" %s", cp);
98	/* Bail if bogus opcode */
99	if (*cp == 't')
100		return;
101
102	switch (opcode) {
103
104	case RRQ:
105	case WRQ:
106	case OACK:
107		/*
108		 * XXX Not all arpa/tftp.h's specify th_stuff as any
109		 * array; use address of th_block instead
110		 */
111#ifdef notdef
112		p = (u_char *)tp->th_stuff;
113#else
114		p = (u_char *)&tp->th_block;
115#endif
116		putchar(' ');
117		/* Print filename or first option */
118		if (opcode != OACK)
119			putchar('"');
120		i = fn_print(p, snapend);
121		if (opcode != OACK)
122			putchar('"');
123
124		/* Print the mode (RRQ and WRQ only) and any options */
125		while ((p = (const u_char *)strchr((const char *)p, '\0')) != NULL) {
126			if (length <= (u_int)(p - (const u_char *)&tp->th_block))
127				break;
128			p++;
129			if (*p != '\0') {
130				putchar(' ');
131				fn_print(p, snapend);
132			}
133		}
134
135		if (i)
136			goto trunc;
137		break;
138
139	case ACK:
140	case DATA:
141		TCHECK(tp->th_block);
142		printf(" block %d", EXTRACT_16BITS(&tp->th_block));
143		break;
144
145	case TFTP_ERROR:
146		/* Print error code string */
147		TCHECK(tp->th_code);
148		printf(" %s \"", tok2str(err2str, "tftp-err-#%d \"",
149				       EXTRACT_16BITS(&tp->th_code)));
150		/* Print error message string */
151		i = fn_print((const u_char *)tp->th_data, snapend);
152		putchar('"');
153		if (i)
154			goto trunc;
155		break;
156
157	default:
158		/* We shouldn't get here */
159		printf("(unknown #%d)", opcode);
160		break;
161	}
162	return;
163trunc:
164	fputs(tstr, stdout);
165	return;
166}
167