xref: /freebsd/contrib/tcpdump/print-tftp.c (revision 3c602fabf9b894ff79f08a80cbb7ad3b1eb84e62)
14edb46e9SPaul Traina /*
24644f044SBill Fenner  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
34edb46e9SPaul Traina  *	The Regents of the University of California.  All rights reserved.
44edb46e9SPaul Traina  *
54edb46e9SPaul Traina  * Redistribution and use in source and binary forms, with or without
64edb46e9SPaul Traina  * modification, are permitted provided that: (1) source code distributions
74edb46e9SPaul Traina  * retain the above copyright notice and this paragraph in its entirety, (2)
84edb46e9SPaul Traina  * distributions including binary code include the above copyright notice and
94edb46e9SPaul Traina  * this paragraph in its entirety in the documentation or other materials
104edb46e9SPaul Traina  * provided with the distribution, and (3) all advertising materials mentioning
114edb46e9SPaul Traina  * features or use of this software display the following acknowledgement:
124edb46e9SPaul Traina  * ``This product includes software developed by the University of California,
134edb46e9SPaul Traina  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
144edb46e9SPaul Traina  * the University nor the names of its contributors may be used to endorse
154edb46e9SPaul Traina  * or promote products derived from this software without specific prior
164edb46e9SPaul Traina  * written permission.
174edb46e9SPaul Traina  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
184edb46e9SPaul Traina  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
194edb46e9SPaul Traina  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
204edb46e9SPaul Traina  *
214edb46e9SPaul Traina  * Format and print trivial file transfer protocol packets.
224edb46e9SPaul Traina  */
234edb46e9SPaul Traina 
24*3c602fabSXin LI #define NETDISSECT_REWORKED
25b0453382SBill Fenner #ifdef HAVE_CONFIG_H
26b0453382SBill Fenner #include "config.h"
274edb46e9SPaul Traina #endif
284edb46e9SPaul Traina 
295b0fe478SBruce M Simpson #include <tcpdump-stdinc.h>
304edb46e9SPaul Traina 
314edb46e9SPaul Traina #include <string.h>
324edb46e9SPaul Traina 
334edb46e9SPaul Traina #include "interface.h"
345b0fe478SBruce M Simpson #include "extract.h"
35*3c602fabSXin LI 
36*3c602fabSXin LI /*
37*3c602fabSXin LI  * Trivial File Transfer Protocol (IEN-133)
38*3c602fabSXin LI  */
39*3c602fabSXin LI 
40*3c602fabSXin LI /*
41*3c602fabSXin LI  * Packet types.
42*3c602fabSXin LI  */
43*3c602fabSXin LI #define	RRQ	01			/* read request */
44*3c602fabSXin LI #define	WRQ	02			/* write request */
45*3c602fabSXin LI #define	DATA	03			/* data packet */
46*3c602fabSXin LI #define	ACK	04			/* acknowledgement */
47*3c602fabSXin LI #define	TFTP_ERROR	05			/* error code */
48*3c602fabSXin LI #define OACK	06			/* option acknowledgement */
49*3c602fabSXin LI 
50*3c602fabSXin LI struct	tftphdr {
51*3c602fabSXin LI 	unsigned short	th_opcode;		/* packet type */
52*3c602fabSXin LI 	union {
53*3c602fabSXin LI 		unsigned short	tu_block;	/* block # */
54*3c602fabSXin LI 		unsigned short	tu_code;	/* error code */
55*3c602fabSXin LI 		char	tu_stuff[1];	/* request packet stuff */
56*3c602fabSXin LI 	} th_u;
57*3c602fabSXin LI 	char	th_data[1];		/* data or error string */
58*3c602fabSXin LI };
59*3c602fabSXin LI 
60*3c602fabSXin LI #define	th_block	th_u.tu_block
61*3c602fabSXin LI #define	th_code		th_u.tu_code
62*3c602fabSXin LI #define	th_stuff	th_u.tu_stuff
63*3c602fabSXin LI #define	th_msg		th_data
64*3c602fabSXin LI 
65*3c602fabSXin LI /*
66*3c602fabSXin LI  * Error codes.
67*3c602fabSXin LI  */
68*3c602fabSXin LI #define	EUNDEF		0		/* not defined */
69*3c602fabSXin LI #define	ENOTFOUND	1		/* file not found */
70*3c602fabSXin LI #define	EACCESS		2		/* access violation */
71*3c602fabSXin LI #define	ENOSPACE	3		/* disk full or allocation exceeded */
72*3c602fabSXin LI #define	EBADOP		4		/* illegal TFTP operation */
73*3c602fabSXin LI #define	EBADID		5		/* unknown transfer ID */
74*3c602fabSXin LI #define	EEXISTS		6		/* file already exists */
75*3c602fabSXin LI #define	ENOUSER		7		/* no such user */
76*3c602fabSXin LI 
77*3c602fabSXin LI static const char tstr[] = " [|tftp]";
784edb46e9SPaul Traina 
794edb46e9SPaul Traina /* op code to string mapping */
80*3c602fabSXin LI static const struct tok op2str[] = {
814edb46e9SPaul Traina 	{ RRQ,		"RRQ" },	/* read request */
824edb46e9SPaul Traina 	{ WRQ,		"WRQ" },	/* write request */
834edb46e9SPaul Traina 	{ DATA,		"DATA" },	/* data packet */
844edb46e9SPaul Traina 	{ ACK,		"ACK" },	/* acknowledgement */
85a5779b6eSRui Paulo 	{ TFTP_ERROR,	"ERROR" },	/* error code */
86b5bfcb5dSMax Laier 	{ OACK,		"OACK" },	/* option acknowledgement */
874edb46e9SPaul Traina 	{ 0,		NULL }
884edb46e9SPaul Traina };
894edb46e9SPaul Traina 
904edb46e9SPaul Traina /* error code to string mapping */
91*3c602fabSXin LI static const struct tok err2str[] = {
924edb46e9SPaul Traina 	{ EUNDEF,	"EUNDEF" },	/* not defined */
934edb46e9SPaul Traina 	{ ENOTFOUND,	"ENOTFOUND" },	/* file not found */
944edb46e9SPaul Traina 	{ EACCESS,	"EACCESS" },	/* access violation */
954edb46e9SPaul Traina 	{ ENOSPACE,	"ENOSPACE" },	/* disk full or allocation exceeded */
964edb46e9SPaul Traina 	{ EBADOP,	"EBADOP" },	/* illegal TFTP operation */
974edb46e9SPaul Traina 	{ EBADID,	"EBADID" },	/* unknown transfer ID */
984edb46e9SPaul Traina 	{ EEXISTS,	"EEXISTS" },	/* file already exists */
994edb46e9SPaul Traina 	{ ENOUSER,	"ENOUSER" },	/* no such user */
1004edb46e9SPaul Traina 	{ 0,		NULL }
1014edb46e9SPaul Traina };
1024edb46e9SPaul Traina 
1034edb46e9SPaul Traina /*
1044edb46e9SPaul Traina  * Print trivial file transfer program requests
1054edb46e9SPaul Traina  */
1064edb46e9SPaul Traina void
107*3c602fabSXin LI tftp_print(netdissect_options *ndo,
108*3c602fabSXin LI            register const u_char *bp, u_int length)
1094edb46e9SPaul Traina {
1104edb46e9SPaul Traina 	register const struct tftphdr *tp;
1114edb46e9SPaul Traina 	register const char *cp;
1124edb46e9SPaul Traina 	register const u_char *p;
1134edb46e9SPaul Traina 	register int opcode, i;
1144edb46e9SPaul Traina 
1154edb46e9SPaul Traina 	tp = (const struct tftphdr *)bp;
1164edb46e9SPaul Traina 
1174edb46e9SPaul Traina 	/* Print length */
118*3c602fabSXin LI 	ND_PRINT((ndo, " %d", length));
1194edb46e9SPaul Traina 
1204edb46e9SPaul Traina 	/* Print tftp request type */
121*3c602fabSXin LI 	ND_TCHECK(tp->th_opcode);
1225b0fe478SBruce M Simpson 	opcode = EXTRACT_16BITS(&tp->th_opcode);
1234edb46e9SPaul Traina 	cp = tok2str(op2str, "tftp-#%d", opcode);
124*3c602fabSXin LI 	ND_PRINT((ndo, " %s", cp));
1254edb46e9SPaul Traina 	/* Bail if bogus opcode */
1264edb46e9SPaul Traina 	if (*cp == 't')
1274edb46e9SPaul Traina 		return;
1284edb46e9SPaul Traina 
1294edb46e9SPaul Traina 	switch (opcode) {
1304edb46e9SPaul Traina 
1314edb46e9SPaul Traina 	case RRQ:
1324edb46e9SPaul Traina 	case WRQ:
133b5bfcb5dSMax Laier 	case OACK:
1344edb46e9SPaul Traina 		p = (u_char *)tp->th_stuff;
135*3c602fabSXin LI 		ND_PRINT((ndo, " "));
136b5bfcb5dSMax Laier 		/* Print filename or first option */
137b5bfcb5dSMax Laier 		if (opcode != OACK)
138*3c602fabSXin LI 			ND_PRINT((ndo, "\""));
139*3c602fabSXin LI 		i = fn_print(ndo, p, ndo->ndo_snapend);
140b5bfcb5dSMax Laier 		if (opcode != OACK)
141*3c602fabSXin LI 			ND_PRINT((ndo, "\""));
1425b0fe478SBruce M Simpson 
143b5bfcb5dSMax Laier 		/* Print the mode (RRQ and WRQ only) and any options */
1445b0fe478SBruce M Simpson 		while ((p = (const u_char *)strchr((const char *)p, '\0')) != NULL) {
1455b0fe478SBruce M Simpson 			if (length <= (u_int)(p - (const u_char *)&tp->th_block))
1465b0fe478SBruce M Simpson 				break;
1475b0fe478SBruce M Simpson 			p++;
1485b0fe478SBruce M Simpson 			if (*p != '\0') {
149*3c602fabSXin LI 				ND_PRINT((ndo, " "));
150*3c602fabSXin LI 				fn_print(ndo, p, ndo->ndo_snapend);
1515b0fe478SBruce M Simpson 			}
1525b0fe478SBruce M Simpson 		}
1535b0fe478SBruce M Simpson 
1544edb46e9SPaul Traina 		if (i)
1554edb46e9SPaul Traina 			goto trunc;
1564edb46e9SPaul Traina 		break;
1574edb46e9SPaul Traina 
1584edb46e9SPaul Traina 	case ACK:
1594edb46e9SPaul Traina 	case DATA:
160*3c602fabSXin LI 		ND_TCHECK(tp->th_block);
161*3c602fabSXin LI 		ND_PRINT((ndo, " block %d", EXTRACT_16BITS(&tp->th_block)));
1624edb46e9SPaul Traina 		break;
1634edb46e9SPaul Traina 
164a5779b6eSRui Paulo 	case TFTP_ERROR:
1654edb46e9SPaul Traina 		/* Print error code string */
166*3c602fabSXin LI 		ND_TCHECK(tp->th_code);
167*3c602fabSXin LI 		ND_PRINT((ndo, " %s \"", tok2str(err2str, "tftp-err-#%d \"",
168*3c602fabSXin LI 				       EXTRACT_16BITS(&tp->th_code))));
1694edb46e9SPaul Traina 		/* Print error message string */
170*3c602fabSXin LI 		i = fn_print(ndo, (const u_char *)tp->th_data, ndo->ndo_snapend);
171*3c602fabSXin LI 		ND_PRINT((ndo, "\""));
1724edb46e9SPaul Traina 		if (i)
1734edb46e9SPaul Traina 			goto trunc;
1744edb46e9SPaul Traina 		break;
1754edb46e9SPaul Traina 
1764edb46e9SPaul Traina 	default:
1774edb46e9SPaul Traina 		/* We shouldn't get here */
178*3c602fabSXin LI 		ND_PRINT((ndo, "(unknown #%d)", opcode));
1794edb46e9SPaul Traina 		break;
1804edb46e9SPaul Traina 	}
1814edb46e9SPaul Traina 	return;
1824edb46e9SPaul Traina trunc:
183*3c602fabSXin LI 	ND_PRINT((ndo, "%s", tstr));
1844edb46e9SPaul Traina 	return;
1854edb46e9SPaul Traina }
186