print-tftp.c revision 1.7
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 22/* \summary: Trivial File Transfer Protocol (TFTP) printer */ 23 24#include <sys/cdefs.h> 25#ifndef lint 26__RCSID("$NetBSD: print-tftp.c,v 1.7 2017/02/05 04:05:05 spz Exp $"); 27#endif 28 29#ifdef HAVE_CONFIG_H 30#include "config.h" 31#endif 32 33#include <netdissect-stdinc.h> 34 35#include <string.h> 36 37#include "netdissect.h" 38#include "extract.h" 39 40/* 41 * Trivial File Transfer Protocol (IEN-133) 42 */ 43 44/* 45 * Packet types. 46 */ 47#define RRQ 01 /* read request */ 48#define WRQ 02 /* write request */ 49#define DATA 03 /* data packet */ 50#define ACK 04 /* acknowledgement */ 51#define TFTP_ERROR 05 /* error code */ 52#define OACK 06 /* option acknowledgement */ 53 54struct tftphdr { 55 unsigned short th_opcode; /* packet type */ 56 union { 57 unsigned short tu_block; /* block # */ 58 unsigned short tu_code; /* error code */ 59 char tu_stuff[1]; /* request packet stuff */ 60 } th_u; 61 char th_data[1]; /* data or error string */ 62}; 63 64#define th_block th_u.tu_block 65#define th_code th_u.tu_code 66#define th_stuff th_u.tu_stuff 67#define th_msg th_data 68 69/* 70 * Error codes. 71 */ 72#define EUNDEF 0 /* not defined */ 73#define ENOTFOUND 1 /* file not found */ 74#define EACCESS 2 /* access violation */ 75#define ENOSPACE 3 /* disk full or allocation exceeded */ 76#define EBADOP 4 /* illegal TFTP operation */ 77#define EBADID 5 /* unknown transfer ID */ 78#define EEXISTS 6 /* file already exists */ 79#define ENOUSER 7 /* no such user */ 80 81static const char tstr[] = " [|tftp]"; 82 83/* op code to string mapping */ 84static const struct tok op2str[] = { 85 { RRQ, "RRQ" }, /* read request */ 86 { WRQ, "WRQ" }, /* write request */ 87 { DATA, "DATA" }, /* data packet */ 88 { ACK, "ACK" }, /* acknowledgement */ 89 { TFTP_ERROR, "ERROR" }, /* error code */ 90 { OACK, "OACK" }, /* option acknowledgement */ 91 { 0, NULL } 92}; 93 94/* error code to string mapping */ 95static const struct tok err2str[] = { 96 { EUNDEF, "EUNDEF" }, /* not defined */ 97 { ENOTFOUND, "ENOTFOUND" }, /* file not found */ 98 { EACCESS, "EACCESS" }, /* access violation */ 99 { ENOSPACE, "ENOSPACE" }, /* disk full or allocation exceeded */ 100 { EBADOP, "EBADOP" }, /* illegal TFTP operation */ 101 { EBADID, "EBADID" }, /* unknown transfer ID */ 102 { EEXISTS, "EEXISTS" }, /* file already exists */ 103 { ENOUSER, "ENOUSER" }, /* no such user */ 104 { 0, NULL } 105}; 106 107/* 108 * Print trivial file transfer program requests 109 */ 110void 111tftp_print(netdissect_options *ndo, 112 register const u_char *bp, u_int length) 113{ 114 register const struct tftphdr *tp; 115 register const char *cp; 116 register const u_char *p; 117 register int opcode; 118 u_int ui; 119 120 tp = (const struct tftphdr *)bp; 121 122 /* Print length */ 123 ND_PRINT((ndo, " %d", length)); 124 125 /* Print tftp request type */ 126 if (length < 2) 127 goto trunc; 128 ND_TCHECK(tp->th_opcode); 129 opcode = EXTRACT_16BITS(&tp->th_opcode); 130 cp = tok2str(op2str, "tftp-#%d", opcode); 131 length -= 2; 132 ND_PRINT((ndo, " %s", cp)); 133 /* Bail if bogus opcode */ 134 if (*cp == 't') 135 return; 136 137 switch (opcode) { 138 139 case RRQ: 140 case WRQ: 141 p = (const u_char *)tp->th_stuff; 142 if (length == 0) 143 goto trunc; 144 ND_PRINT((ndo, " ")); 145 /* Print filename */ 146 ND_PRINT((ndo, "\"")); 147 ui = fn_printztn(ndo, p, length, ndo->ndo_snapend); 148 ND_PRINT((ndo, "\"")); 149 if (ui == 0) 150 goto trunc; 151 p += ui; 152 length -= ui; 153 154 /* Print the mode - RRQ and WRQ only */ 155 if (length == 0) 156 goto trunc; /* no mode */ 157 ND_PRINT((ndo, " ")); 158 ui = fn_printztn(ndo, p, length, ndo->ndo_snapend); 159 if (ui == 0) 160 goto trunc; 161 p += ui; 162 length -= ui; 163 164 /* Print options, if any */ 165 while (length != 0) { 166 ND_TCHECK(*p); 167 if (*p != '\0') 168 ND_PRINT((ndo, " ")); 169 ui = fn_printztn(ndo, p, length, ndo->ndo_snapend); 170 if (ui == 0) 171 goto trunc; 172 p += ui; 173 length -= ui; 174 } 175 break; 176 177 case OACK: 178 p = (const u_char *)tp->th_stuff; 179 /* Print options */ 180 while (length != 0) { 181 ND_TCHECK(*p); 182 if (*p != '\0') 183 ND_PRINT((ndo, " ")); 184 ui = fn_printztn(ndo, p, length, ndo->ndo_snapend); 185 if (ui == 0) 186 goto trunc; 187 p += ui; 188 length -= ui; 189 } 190 break; 191 192 case ACK: 193 case DATA: 194 if (length < 2) 195 goto trunc; /* no block number */ 196 ND_TCHECK(tp->th_block); 197 ND_PRINT((ndo, " block %d", EXTRACT_16BITS(&tp->th_block))); 198 break; 199 200 case TFTP_ERROR: 201 /* Print error code string */ 202 if (length < 2) 203 goto trunc; /* no error code */ 204 ND_TCHECK(tp->th_code); 205 ND_PRINT((ndo, " %s", tok2str(err2str, "tftp-err-#%d \"", 206 EXTRACT_16BITS(&tp->th_code)))); 207 length -= 2; 208 /* Print error message string */ 209 if (length == 0) 210 goto trunc; /* no error message */ 211 ND_PRINT((ndo, " \"")); 212 ui = fn_printztn(ndo, (const u_char *)tp->th_data, length, ndo->ndo_snapend); 213 ND_PRINT((ndo, "\"")); 214 if (ui == 0) 215 goto trunc; 216 break; 217 218 default: 219 /* We shouldn't get here */ 220 ND_PRINT((ndo, "(unknown #%d)", opcode)); 221 break; 222 } 223 return; 224trunc: 225 ND_PRINT((ndo, "%s", tstr)); 226 return; 227} 228