1238438Sdteske/*
2238438Sdteske * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3238438Sdteske *	The Regents of the University of California.  All rights reserved.
4238438Sdteske *
5238438Sdteske * Redistribution and use in source and binary forms, with or without
6238438Sdteske * modification, are permitted provided that: (1) source code distributions
7238438Sdteske * retain the above copyright notice and this paragraph in its entirety, (2)
8238438Sdteske * distributions including binary code include the above copyright notice and
9238438Sdteske * this paragraph in its entirety in the documentation or other materials
10238438Sdteske * provided with the distribution, and (3) all advertising materials mentioning
11238438Sdteske * features or use of this software display the following acknowledgement:
12238438Sdteske * ``This product includes software developed by the University of California,
13238438Sdteske * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14238438Sdteske * the University nor the names of its contributors may be used to endorse
15238438Sdteske * or promote products derived from this software without specific prior
16238438Sdteske * written permission.
17238438Sdteske * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18238438Sdteske * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19238438Sdteske * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20238438Sdteske *
21238438Sdteske * Format and print trivial file transfer protocol packets.
22238438Sdteske */
23238438Sdteske
24238438Sdteske#ifndef lint
25238438Sdteskestatic const char rcsid[] _U_ =
26238438Sdteske    "@(#) $Header: /tcpdump/master/tcpdump/print-tftp.c,v 1.39 2008-04-11 16:47:38 gianluca Exp $ (LBL)";
27238438Sdteske#endif
28238438Sdteske
29238438Sdteske#ifdef HAVE_CONFIG_H
30238438Sdteske#include "config.h"
31238438Sdteske#endif
32238438Sdteske
33238438Sdteske#include <tcpdump-stdinc.h>
34238438Sdteske
35238438Sdteske#ifdef SEGSIZE
36238438Sdteske#undef SEGSIZE					/* SINIX sucks */
37238438Sdteske#endif
38238438Sdteske
39238438Sdteske#include <stdio.h>
40238438Sdteske#include <string.h>
41238438Sdteske
42238438Sdteske#include "interface.h"
43238438Sdteske#include "addrtoname.h"
44238438Sdteske#include "extract.h"
45238438Sdteske#include "tftp.h"
46238438Sdteske
47238438Sdteske/* op code to string mapping */
48238438Sdteskestatic struct tok op2str[] = {
49238438Sdteske	{ RRQ,		"RRQ" },	/* read request */
50238438Sdteske	{ WRQ,		"WRQ" },	/* write request */
51238438Sdteske	{ DATA,		"DATA" },	/* data packet */
52238438Sdteske	{ ACK,		"ACK" },	/* acknowledgement */
53238438Sdteske	{ TFTP_ERROR,	"ERROR" },	/* error code */
54238438Sdteske	{ OACK,		"OACK" },	/* option acknowledgement */
55238438Sdteske	{ 0,		NULL }
56238438Sdteske};
57238438Sdteske
58238438Sdteske/* error code to string mapping */
59238438Sdteskestatic struct tok err2str[] = {
60238438Sdteske	{ EUNDEF,	"EUNDEF" },	/* not defined */
61238438Sdteske	{ ENOTFOUND,	"ENOTFOUND" },	/* file not found */
62238438Sdteske	{ EACCESS,	"EACCESS" },	/* access violation */
63238438Sdteske	{ ENOSPACE,	"ENOSPACE" },	/* disk full or allocation exceeded */
64238438Sdteske	{ EBADOP,	"EBADOP" },	/* illegal TFTP operation */
65238438Sdteske	{ EBADID,	"EBADID" },	/* unknown transfer ID */
66238438Sdteske	{ EEXISTS,	"EEXISTS" },	/* file already exists */
67238438Sdteske	{ ENOUSER,	"ENOUSER" },	/* no such user */
68238438Sdteske	{ 0,		NULL }
69238438Sdteske};
70238438Sdteske
71238438Sdteske/*
72238438Sdteske * Print trivial file transfer program requests
73238438Sdteske */
74238438Sdteskevoid
75238438Sdtesketftp_print(register const u_char *bp, u_int length)
76238438Sdteske{
77238438Sdteske	register const struct tftphdr *tp;
78238438Sdteske	register const char *cp;
79238438Sdteske	register const u_char *p;
80238438Sdteske	register int opcode, i;
81238438Sdteske	static char tstr[] = " [|tftp]";
82238438Sdteske
83238438Sdteske	tp = (const struct tftphdr *)bp;
84238438Sdteske
85238438Sdteske	/* Print length */
86238438Sdteske	printf(" %d", length);
87238438Sdteske
88238438Sdteske	/* Print tftp request type */
89238438Sdteske	TCHECK(tp->th_opcode);
90238438Sdteske	opcode = EXTRACT_16BITS(&tp->th_opcode);
91238438Sdteske	cp = tok2str(op2str, "tftp-#%d", opcode);
92238438Sdteske	printf(" %s", cp);
93238438Sdteske	/* Bail if bogus opcode */
94238438Sdteske	if (*cp == 't')
95238438Sdteske		return;
96238438Sdteske
97238438Sdteske	switch (opcode) {
98238438Sdteske
99238438Sdteske	case RRQ:
100238438Sdteske	case WRQ:
101238438Sdteske	case OACK:
102238438Sdteske		p = (u_char *)tp->th_stuff;
103238438Sdteske		putchar(' ');
104238438Sdteske		/* Print filename or first option */
105238438Sdteske		if (opcode != OACK)
106238438Sdteske			putchar('"');
107238438Sdteske		i = fn_print(p, snapend);
108238438Sdteske		if (opcode != OACK)
109238438Sdteske			putchar('"');
110238438Sdteske
111238438Sdteske		/* Print the mode (RRQ and WRQ only) and any options */
112238438Sdteske		while ((p = (const u_char *)strchr((const char *)p, '\0')) != NULL) {
113238438Sdteske			if (length <= (u_int)(p - (const u_char *)&tp->th_block))
114238438Sdteske				break;
115238438Sdteske			p++;
116238438Sdteske			if (*p != '\0') {
117238438Sdteske				putchar(' ');
118238438Sdteske				fn_print(p, snapend);
119238438Sdteske			}
120238438Sdteske		}
121238438Sdteske
122238438Sdteske		if (i)
123238438Sdteske			goto trunc;
124238438Sdteske		break;
125238438Sdteske
126238438Sdteske	case ACK:
127238438Sdteske	case DATA:
128238438Sdteske		TCHECK(tp->th_block);
129238438Sdteske		printf(" block %d", EXTRACT_16BITS(&tp->th_block));
130238438Sdteske		break;
131238438Sdteske
132238438Sdteske	case TFTP_ERROR:
133238438Sdteske		/* Print error code string */
134238438Sdteske		TCHECK(tp->th_code);
135238438Sdteske		printf(" %s \"", tok2str(err2str, "tftp-err-#%d \"",
136238438Sdteske				       EXTRACT_16BITS(&tp->th_code)));
137238438Sdteske		/* Print error message string */
138238438Sdteske		i = fn_print((const u_char *)tp->th_data, snapend);
139238438Sdteske		putchar('"');
140238438Sdteske		if (i)
141238438Sdteske			goto trunc;
142238438Sdteske		break;
143
144	default:
145		/* We shouldn't get here */
146		printf("(unknown #%d)", opcode);
147		break;
148	}
149	return;
150trunc:
151	fputs(tstr, stdout);
152	return;
153}
154