Home | History | Annotate | Line # | Download | only in dist
print-tftp.c revision 1.7
      1  1.1  christos /*
      2  1.1  christos  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
      3  1.1  christos  *	The Regents of the University of California.  All rights reserved.
      4  1.1  christos  *
      5  1.1  christos  * Redistribution and use in source and binary forms, with or without
      6  1.1  christos  * modification, are permitted provided that: (1) source code distributions
      7  1.1  christos  * retain the above copyright notice and this paragraph in its entirety, (2)
      8  1.1  christos  * distributions including binary code include the above copyright notice and
      9  1.1  christos  * this paragraph in its entirety in the documentation or other materials
     10  1.1  christos  * provided with the distribution, and (3) all advertising materials mentioning
     11  1.1  christos  * features or use of this software display the following acknowledgement:
     12  1.1  christos  * ``This product includes software developed by the University of California,
     13  1.1  christos  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
     14  1.1  christos  * the University nor the names of its contributors may be used to endorse
     15  1.1  christos  * or promote products derived from this software without specific prior
     16  1.1  christos  * written permission.
     17  1.1  christos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
     18  1.1  christos  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
     19  1.1  christos  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     20  1.1  christos  */
     21  1.1  christos 
     22  1.7       spz /* \summary: Trivial File Transfer Protocol (TFTP) printer */
     23  1.7       spz 
     24  1.2  christos #include <sys/cdefs.h>
     25  1.1  christos #ifndef lint
     26  1.7       spz __RCSID("$NetBSD: print-tftp.c,v 1.7 2017/02/05 04:05:05 spz Exp $");
     27  1.1  christos #endif
     28  1.1  christos 
     29  1.1  christos #ifdef HAVE_CONFIG_H
     30  1.1  christos #include "config.h"
     31  1.1  christos #endif
     32  1.1  christos 
     33  1.6  christos #include <netdissect-stdinc.h>
     34  1.1  christos 
     35  1.1  christos #include <string.h>
     36  1.1  christos 
     37  1.6  christos #include "netdissect.h"
     38  1.1  christos #include "extract.h"
     39  1.5  christos 
     40  1.5  christos /*
     41  1.5  christos  * Trivial File Transfer Protocol (IEN-133)
     42  1.5  christos  */
     43  1.5  christos 
     44  1.5  christos /*
     45  1.5  christos  * Packet types.
     46  1.5  christos  */
     47  1.5  christos #define	RRQ	01			/* read request */
     48  1.5  christos #define	WRQ	02			/* write request */
     49  1.5  christos #define	DATA	03			/* data packet */
     50  1.5  christos #define	ACK	04			/* acknowledgement */
     51  1.5  christos #define	TFTP_ERROR	05			/* error code */
     52  1.5  christos #define OACK	06			/* option acknowledgement */
     53  1.5  christos 
     54  1.5  christos struct	tftphdr {
     55  1.5  christos 	unsigned short	th_opcode;		/* packet type */
     56  1.5  christos 	union {
     57  1.5  christos 		unsigned short	tu_block;	/* block # */
     58  1.5  christos 		unsigned short	tu_code;	/* error code */
     59  1.5  christos 		char	tu_stuff[1];	/* request packet stuff */
     60  1.5  christos 	} th_u;
     61  1.5  christos 	char	th_data[1];		/* data or error string */
     62  1.5  christos };
     63  1.5  christos 
     64  1.5  christos #define	th_block	th_u.tu_block
     65  1.5  christos #define	th_code		th_u.tu_code
     66  1.5  christos #define	th_stuff	th_u.tu_stuff
     67  1.5  christos #define	th_msg		th_data
     68  1.5  christos 
     69  1.5  christos /*
     70  1.5  christos  * Error codes.
     71  1.5  christos  */
     72  1.5  christos #define	EUNDEF		0		/* not defined */
     73  1.5  christos #define	ENOTFOUND	1		/* file not found */
     74  1.5  christos #define	EACCESS		2		/* access violation */
     75  1.5  christos #define	ENOSPACE	3		/* disk full or allocation exceeded */
     76  1.5  christos #define	EBADOP		4		/* illegal TFTP operation */
     77  1.5  christos #define	EBADID		5		/* unknown transfer ID */
     78  1.5  christos #define	EEXISTS		6		/* file already exists */
     79  1.5  christos #define	ENOUSER		7		/* no such user */
     80  1.5  christos 
     81  1.5  christos static const char tstr[] = " [|tftp]";
     82  1.1  christos 
     83  1.1  christos /* op code to string mapping */
     84  1.4  christos static const struct tok op2str[] = {
     85  1.1  christos 	{ RRQ,		"RRQ" },	/* read request */
     86  1.1  christos 	{ WRQ,		"WRQ" },	/* write request */
     87  1.1  christos 	{ DATA,		"DATA" },	/* data packet */
     88  1.1  christos 	{ ACK,		"ACK" },	/* acknowledgement */
     89  1.1  christos 	{ TFTP_ERROR,	"ERROR" },	/* error code */
     90  1.1  christos 	{ OACK,		"OACK" },	/* option acknowledgement */
     91  1.1  christos 	{ 0,		NULL }
     92  1.1  christos };
     93  1.1  christos 
     94  1.1  christos /* error code to string mapping */
     95  1.4  christos static const struct tok err2str[] = {
     96  1.1  christos 	{ EUNDEF,	"EUNDEF" },	/* not defined */
     97  1.1  christos 	{ ENOTFOUND,	"ENOTFOUND" },	/* file not found */
     98  1.1  christos 	{ EACCESS,	"EACCESS" },	/* access violation */
     99  1.1  christos 	{ ENOSPACE,	"ENOSPACE" },	/* disk full or allocation exceeded */
    100  1.1  christos 	{ EBADOP,	"EBADOP" },	/* illegal TFTP operation */
    101  1.1  christos 	{ EBADID,	"EBADID" },	/* unknown transfer ID */
    102  1.1  christos 	{ EEXISTS,	"EEXISTS" },	/* file already exists */
    103  1.1  christos 	{ ENOUSER,	"ENOUSER" },	/* no such user */
    104  1.1  christos 	{ 0,		NULL }
    105  1.1  christos };
    106  1.1  christos 
    107  1.1  christos /*
    108  1.1  christos  * Print trivial file transfer program requests
    109  1.1  christos  */
    110  1.1  christos void
    111  1.5  christos tftp_print(netdissect_options *ndo,
    112  1.5  christos            register const u_char *bp, u_int length)
    113  1.1  christos {
    114  1.1  christos 	register const struct tftphdr *tp;
    115  1.1  christos 	register const char *cp;
    116  1.1  christos 	register const u_char *p;
    117  1.7       spz 	register int opcode;
    118  1.7       spz 	u_int ui;
    119  1.1  christos 
    120  1.1  christos 	tp = (const struct tftphdr *)bp;
    121  1.1  christos 
    122  1.1  christos 	/* Print length */
    123  1.5  christos 	ND_PRINT((ndo, " %d", length));
    124  1.1  christos 
    125  1.1  christos 	/* Print tftp request type */
    126  1.7       spz 	if (length < 2)
    127  1.7       spz 		goto trunc;
    128  1.5  christos 	ND_TCHECK(tp->th_opcode);
    129  1.1  christos 	opcode = EXTRACT_16BITS(&tp->th_opcode);
    130  1.1  christos 	cp = tok2str(op2str, "tftp-#%d", opcode);
    131  1.7       spz 	length -= 2;
    132  1.5  christos 	ND_PRINT((ndo, " %s", cp));
    133  1.1  christos 	/* Bail if bogus opcode */
    134  1.1  christos 	if (*cp == 't')
    135  1.1  christos 		return;
    136  1.1  christos 
    137  1.1  christos 	switch (opcode) {
    138  1.1  christos 
    139  1.1  christos 	case RRQ:
    140  1.1  christos 	case WRQ:
    141  1.6  christos 		p = (const u_char *)tp->th_stuff;
    142  1.7       spz 		if (length == 0)
    143  1.7       spz 			goto trunc;
    144  1.7       spz 		ND_PRINT((ndo, " "));
    145  1.7       spz 		/* Print filename */
    146  1.7       spz 		ND_PRINT((ndo, "\""));
    147  1.7       spz 		ui = fn_printztn(ndo, p, length, ndo->ndo_snapend);
    148  1.7       spz 		ND_PRINT((ndo, "\""));
    149  1.7       spz 		if (ui == 0)
    150  1.7       spz 			goto trunc;
    151  1.7       spz 		p += ui;
    152  1.7       spz 		length -= ui;
    153  1.7       spz 
    154  1.7       spz 		/* Print the mode - RRQ and WRQ only */
    155  1.7       spz 		if (length == 0)
    156  1.7       spz 			goto trunc;	/* no mode */
    157  1.5  christos 		ND_PRINT((ndo, " "));
    158  1.7       spz 		ui = fn_printztn(ndo, p, length, ndo->ndo_snapend);
    159  1.7       spz 		if (ui == 0)
    160  1.7       spz 			goto trunc;
    161  1.7       spz 		p += ui;
    162  1.7       spz 		length -= ui;
    163  1.7       spz 
    164  1.7       spz 		/* Print options, if any */
    165  1.7       spz 		while (length != 0) {
    166  1.7       spz 			ND_TCHECK(*p);
    167  1.7       spz 			if (*p != '\0')
    168  1.5  christos 				ND_PRINT((ndo, " "));
    169  1.7       spz 			ui = fn_printztn(ndo, p, length, ndo->ndo_snapend);
    170  1.7       spz 			if (ui == 0)
    171  1.7       spz 				goto trunc;
    172  1.7       spz 			p += ui;
    173  1.7       spz 			length -= ui;
    174  1.1  christos 		}
    175  1.7       spz 		break;
    176  1.5  christos 
    177  1.7       spz 	case OACK:
    178  1.7       spz 		p = (const u_char *)tp->th_stuff;
    179  1.7       spz 		/* Print options */
    180  1.7       spz 		while (length != 0) {
    181  1.7       spz 			ND_TCHECK(*p);
    182  1.7       spz 			if (*p != '\0')
    183  1.7       spz 				ND_PRINT((ndo, " "));
    184  1.7       spz 			ui = fn_printztn(ndo, p, length, ndo->ndo_snapend);
    185  1.7       spz 			if (ui == 0)
    186  1.7       spz 				goto trunc;
    187  1.7       spz 			p += ui;
    188  1.7       spz 			length -= ui;
    189  1.7       spz 		}
    190  1.1  christos 		break;
    191  1.1  christos 
    192  1.1  christos 	case ACK:
    193  1.1  christos 	case DATA:
    194  1.7       spz 		if (length < 2)
    195  1.7       spz 			goto trunc;	/* no block number */
    196  1.5  christos 		ND_TCHECK(tp->th_block);
    197  1.5  christos 		ND_PRINT((ndo, " block %d", EXTRACT_16BITS(&tp->th_block)));
    198  1.1  christos 		break;
    199  1.1  christos 
    200  1.1  christos 	case TFTP_ERROR:
    201  1.1  christos 		/* Print error code string */
    202  1.7       spz 		if (length < 2)
    203  1.7       spz 			goto trunc;	/* no error code */
    204  1.5  christos 		ND_TCHECK(tp->th_code);
    205  1.7       spz 		ND_PRINT((ndo, " %s", tok2str(err2str, "tftp-err-#%d \"",
    206  1.5  christos 				       EXTRACT_16BITS(&tp->th_code))));
    207  1.7       spz 		length -= 2;
    208  1.1  christos 		/* Print error message string */
    209  1.7       spz 		if (length == 0)
    210  1.7       spz 			goto trunc;	/* no error message */
    211  1.7       spz 		ND_PRINT((ndo, " \""));
    212  1.7       spz 		ui = fn_printztn(ndo, (const u_char *)tp->th_data, length, ndo->ndo_snapend);
    213  1.5  christos 		ND_PRINT((ndo, "\""));
    214  1.7       spz 		if (ui == 0)
    215  1.1  christos 			goto trunc;
    216  1.1  christos 		break;
    217  1.1  christos 
    218  1.1  christos 	default:
    219  1.1  christos 		/* We shouldn't get here */
    220  1.5  christos 		ND_PRINT((ndo, "(unknown #%d)", opcode));
    221  1.1  christos 		break;
    222  1.1  christos 	}
    223  1.1  christos 	return;
    224  1.1  christos trunc:
    225  1.5  christos 	ND_PRINT((ndo, "%s", tstr));
    226  1.1  christos 	return;
    227  1.1  christos }
    228