xref: /netbsd-src/external/bsd/tcpdump/dist/print-tftp.c (revision ba65fde2d7fefa7d39838fa5fa855e62bd606b5e)
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
27 static 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 */
53 static 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 */
64 static 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  */
79 void
80 tftp_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;
163 trunc:
164 	fputs(tstr, stdout);
165 	return;
166 }
167