xref: /netbsd-src/external/bsd/tcpdump/dist/print-tftp.c (revision 26ba0b503b498a5194a71ac319838b7f5497f3fe)
10f74e101Schristos /*
20f74e101Schristos  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
30f74e101Schristos  *	The Regents of the University of California.  All rights reserved.
40f74e101Schristos  *
50f74e101Schristos  * Redistribution and use in source and binary forms, with or without
60f74e101Schristos  * modification, are permitted provided that: (1) source code distributions
70f74e101Schristos  * retain the above copyright notice and this paragraph in its entirety, (2)
80f74e101Schristos  * distributions including binary code include the above copyright notice and
90f74e101Schristos  * this paragraph in its entirety in the documentation or other materials
100f74e101Schristos  * provided with the distribution, and (3) all advertising materials mentioning
110f74e101Schristos  * features or use of this software display the following acknowledgement:
120f74e101Schristos  * ``This product includes software developed by the University of California,
130f74e101Schristos  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
140f74e101Schristos  * the University nor the names of its contributors may be used to endorse
150f74e101Schristos  * or promote products derived from this software without specific prior
160f74e101Schristos  * written permission.
170f74e101Schristos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
180f74e101Schristos  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
190f74e101Schristos  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
200f74e101Schristos  */
210f74e101Schristos 
22dc860a36Sspz /* \summary: Trivial File Transfer Protocol (TFTP) printer */
23dc860a36Sspz 
2411b3aaa1Schristos #include <sys/cdefs.h>
250f74e101Schristos #ifndef lint
26*26ba0b50Schristos __RCSID("$NetBSD: print-tftp.c,v 1.10 2024/09/02 16:15:33 christos Exp $");
270f74e101Schristos #endif
280f74e101Schristos 
29c74ad251Schristos #include <config.h>
300f74e101Schristos 
31c74ad251Schristos #include "netdissect-stdinc.h"
320f74e101Schristos 
33fdccd7e4Schristos #include "netdissect.h"
340f74e101Schristos #include "extract.h"
35b3a00663Schristos 
36b3a00663Schristos /*
37b3a00663Schristos  * Trivial File Transfer Protocol (IEN-133)
38b3a00663Schristos  */
39b3a00663Schristos 
40b3a00663Schristos /*
41b3a00663Schristos  * Packet types.
42b3a00663Schristos  */
43b3a00663Schristos #define	RRQ	01			/* read request */
44b3a00663Schristos #define	WRQ	02			/* write request */
45b3a00663Schristos #define	DATA	03			/* data packet */
46b3a00663Schristos #define	ACK	04			/* acknowledgement */
47b3a00663Schristos #define	TFTP_ERROR	05			/* error code */
48b3a00663Schristos #define OACK	06			/* option acknowledgement */
49b3a00663Schristos 
50b3a00663Schristos /*
51b3a00663Schristos  * Error codes.
52b3a00663Schristos  */
53b3a00663Schristos #define	EUNDEF		0		/* not defined */
54b3a00663Schristos #define	ENOTFOUND	1		/* file not found */
55b3a00663Schristos #define	EACCESS		2		/* access violation */
56b3a00663Schristos #define	ENOSPACE	3		/* disk full or allocation exceeded */
57b3a00663Schristos #define	EBADOP		4		/* illegal TFTP operation */
58b3a00663Schristos #define	EBADID		5		/* unknown transfer ID */
59b3a00663Schristos #define	EEXISTS		6		/* file already exists */
60b3a00663Schristos #define	ENOUSER		7		/* no such user */
61b3a00663Schristos 
620f74e101Schristos 
630f74e101Schristos /* op code to string mapping */
64870189d2Schristos static const struct tok op2str[] = {
650f74e101Schristos 	{ RRQ,		"RRQ" },	/* read request */
660f74e101Schristos 	{ WRQ,		"WRQ" },	/* write request */
670f74e101Schristos 	{ DATA,		"DATA" },	/* data packet */
680f74e101Schristos 	{ ACK,		"ACK" },	/* acknowledgement */
690f74e101Schristos 	{ TFTP_ERROR,	"ERROR" },	/* error code */
700f74e101Schristos 	{ OACK,		"OACK" },	/* option acknowledgement */
710f74e101Schristos 	{ 0,		NULL }
720f74e101Schristos };
730f74e101Schristos 
740f74e101Schristos /* error code to string mapping */
75870189d2Schristos static const struct tok err2str[] = {
760f74e101Schristos 	{ EUNDEF,	"EUNDEF" },	/* not defined */
770f74e101Schristos 	{ ENOTFOUND,	"ENOTFOUND" },	/* file not found */
780f74e101Schristos 	{ EACCESS,	"EACCESS" },	/* access violation */
790f74e101Schristos 	{ ENOSPACE,	"ENOSPACE" },	/* disk full or allocation exceeded */
800f74e101Schristos 	{ EBADOP,	"EBADOP" },	/* illegal TFTP operation */
810f74e101Schristos 	{ EBADID,	"EBADID" },	/* unknown transfer ID */
820f74e101Schristos 	{ EEXISTS,	"EEXISTS" },	/* file already exists */
830f74e101Schristos 	{ ENOUSER,	"ENOUSER" },	/* no such user */
840f74e101Schristos 	{ 0,		NULL }
850f74e101Schristos };
860f74e101Schristos 
870f74e101Schristos /*
880f74e101Schristos  * Print trivial file transfer program requests
890f74e101Schristos  */
900f74e101Schristos void
91b3a00663Schristos tftp_print(netdissect_options *ndo,
92c74ad251Schristos            const u_char *bp, u_int length)
930f74e101Schristos {
94c74ad251Schristos 	const char *cp;
95c74ad251Schristos 	u_int opcode;
96dc860a36Sspz 	u_int ui;
970f74e101Schristos 
98c74ad251Schristos 	ndo->ndo_protocol = "tftp";
99c74ad251Schristos 
100c74ad251Schristos 	/* Print protocol */
101c74ad251Schristos 	nd_print_protocol_caps(ndo);
1020f74e101Schristos 	/* Print length */
103c74ad251Schristos 	ND_PRINT(", length %u", length);
1040f74e101Schristos 
1050f74e101Schristos 	/* Print tftp request type */
106dc860a36Sspz 	if (length < 2)
107dc860a36Sspz 		goto trunc;
108c74ad251Schristos 	opcode = GET_BE_U_2(bp);
109c74ad251Schristos 	cp = tok2str(op2str, "tftp-#%u", opcode);
110c74ad251Schristos 	ND_PRINT(", %s", cp);
1110f74e101Schristos 	/* Bail if bogus opcode */
1120f74e101Schristos 	if (*cp == 't')
1130f74e101Schristos 		return;
11472c96ff3Schristos 	bp += 2;
11572c96ff3Schristos 	length -= 2;
1160f74e101Schristos 
1170f74e101Schristos 	switch (opcode) {
1180f74e101Schristos 
1190f74e101Schristos 	case RRQ:
1200f74e101Schristos 	case WRQ:
121dc860a36Sspz 		if (length == 0)
122dc860a36Sspz 			goto trunc;
123c74ad251Schristos 		ND_PRINT(" ");
124dc860a36Sspz 		/* Print filename */
125c74ad251Schristos 		ND_PRINT("\"");
126c74ad251Schristos 		ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend);
127c74ad251Schristos 		ND_PRINT("\"");
128dc860a36Sspz 		if (ui == 0)
129dc860a36Sspz 			goto trunc;
13072c96ff3Schristos 		bp += ui;
131dc860a36Sspz 		length -= ui;
132dc860a36Sspz 
133dc860a36Sspz 		/* Print the mode - RRQ and WRQ only */
134dc860a36Sspz 		if (length == 0)
135dc860a36Sspz 			goto trunc;	/* no mode */
136c74ad251Schristos 		ND_PRINT(" ");
137c74ad251Schristos 		ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend);
138dc860a36Sspz 		if (ui == 0)
139dc860a36Sspz 			goto trunc;
14072c96ff3Schristos 		bp += ui;
141dc860a36Sspz 		length -= ui;
142dc860a36Sspz 
143dc860a36Sspz 		/* Print options, if any */
144dc860a36Sspz 		while (length != 0) {
145c74ad251Schristos 			if (GET_U_1(bp) != '\0')
146c74ad251Schristos 				ND_PRINT(" ");
147c74ad251Schristos 			ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend);
148dc860a36Sspz 			if (ui == 0)
149dc860a36Sspz 				goto trunc;
15072c96ff3Schristos 			bp += ui;
151dc860a36Sspz 			length -= ui;
152dc860a36Sspz 		}
153dc860a36Sspz 		break;
154dc860a36Sspz 
1550f74e101Schristos 	case OACK:
156dc860a36Sspz 		/* Print options */
157dc860a36Sspz 		while (length != 0) {
158c74ad251Schristos 			if (GET_U_1(bp) != '\0')
159c74ad251Schristos 				ND_PRINT(" ");
160c74ad251Schristos 			ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend);
161dc860a36Sspz 			if (ui == 0)
1620f74e101Schristos 				goto trunc;
16372c96ff3Schristos 			bp += ui;
164dc860a36Sspz 			length -= ui;
165dc860a36Sspz 		}
1660f74e101Schristos 		break;
1670f74e101Schristos 
1680f74e101Schristos 	case ACK:
1690f74e101Schristos 	case DATA:
170dc860a36Sspz 		if (length < 2)
171dc860a36Sspz 			goto trunc;	/* no block number */
172c74ad251Schristos 		ND_PRINT(" block %u", GET_BE_U_2(bp));
1730f74e101Schristos 		break;
1740f74e101Schristos 
1750f74e101Schristos 	case TFTP_ERROR:
1760f74e101Schristos 		/* Print error code string */
177dc860a36Sspz 		if (length < 2)
178dc860a36Sspz 			goto trunc;	/* no error code */
179c74ad251Schristos 		ND_PRINT(" %s", tok2str(err2str, "tftp-err-#%u \"",
180c74ad251Schristos 				       GET_BE_U_2(bp)));
18172c96ff3Schristos 		bp += 2;
182dc860a36Sspz 		length -= 2;
1830f74e101Schristos 		/* Print error message string */
184dc860a36Sspz 		if (length == 0)
185dc860a36Sspz 			goto trunc;	/* no error message */
186c74ad251Schristos 		ND_PRINT(" \"");
187c74ad251Schristos 		ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend);
188c74ad251Schristos 		ND_PRINT("\"");
189dc860a36Sspz 		if (ui == 0)
1900f74e101Schristos 			goto trunc;
1910f74e101Schristos 		break;
1920f74e101Schristos 
1930f74e101Schristos 	default:
1940f74e101Schristos 		/* We shouldn't get here */
195c74ad251Schristos 		ND_PRINT("(unknown #%u)", opcode);
1960f74e101Schristos 		break;
1970f74e101Schristos 	}
1980f74e101Schristos 	return;
1990f74e101Schristos trunc:
200c74ad251Schristos 	nd_print_trunc(ndo);
2010f74e101Schristos }
202