print-tftp.c revision 1.3
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.3 2013/04/06 19:33:08 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		p = (u_char *)tp->th_stuff;
108		putchar(' ');
109		/* Print filename or first option */
110		if (opcode != OACK)
111			putchar('"');
112		i = fn_print(p, snapend);
113		if (opcode != OACK)
114			putchar('"');
115
116		/* Print the mode (RRQ and WRQ only) and any options */
117		while ((p = (const u_char *)strchr((const char *)p, '\0')) != NULL) {
118			if (length <= (u_int)(p - (const u_char *)&tp->th_block))
119				break;
120			p++;
121			if (*p != '\0') {
122				putchar(' ');
123				fn_print(p, snapend);
124			}
125		}
126
127		if (i)
128			goto trunc;
129		break;
130
131	case ACK:
132	case DATA:
133		TCHECK(tp->th_block);
134		printf(" block %d", EXTRACT_16BITS(&tp->th_block));
135		break;
136
137	case TFTP_ERROR:
138		/* Print error code string */
139		TCHECK(tp->th_code);
140		printf(" %s \"", tok2str(err2str, "tftp-err-#%d \"",
141				       EXTRACT_16BITS(&tp->th_code)));
142		/* Print error message string */
143		i = fn_print((const u_char *)tp->th_data, snapend);
144		putchar('"');
145		if (i)
146			goto trunc;
147		break;
148
149	default:
150		/* We shouldn't get here */
151		printf("(unknown #%d)", opcode);
152		break;
153	}
154	return;
155trunc:
156	fputs(tstr, stdout);
157	return;
158}
159