print-tftp.c revision 313537
117680Spst/* 239297Sfenner * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 317680Spst * The Regents of the University of California. All rights reserved. 417680Spst * 517680Spst * Redistribution and use in source and binary forms, with or without 617680Spst * modification, are permitted provided that: (1) source code distributions 717680Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817680Spst * distributions including binary code include the above copyright notice and 917680Spst * this paragraph in its entirety in the documentation or other materials 1017680Spst * provided with the distribution, and (3) all advertising materials mentioning 1117680Spst * features or use of this software display the following acknowledgement: 1217680Spst * ``This product includes software developed by the University of California, 1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417680Spst * the University nor the names of its contributors may be used to endorse 1517680Spst * or promote products derived from this software without specific prior 1617680Spst * written permission. 1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2017680Spst */ 2117680Spst 22313537Sglebius/* \summary: Trivial File Transfer Protocol (TFTP) printer */ 23313537Sglebius 2456893Sfenner#ifdef HAVE_CONFIG_H 2556893Sfenner#include "config.h" 2656893Sfenner#endif 2756893Sfenner 28313537Sglebius#include <netdissect-stdinc.h> 2917680Spst 3017680Spst#include <string.h> 3117680Spst 32313537Sglebius#include "netdissect.h" 33127668Sbms#include "extract.h" 3417680Spst 35276788Sdelphij/* 36276788Sdelphij * Trivial File Transfer Protocol (IEN-133) 37276788Sdelphij */ 38276788Sdelphij 39276788Sdelphij/* 40276788Sdelphij * Packet types. 41276788Sdelphij */ 42276788Sdelphij#define RRQ 01 /* read request */ 43276788Sdelphij#define WRQ 02 /* write request */ 44276788Sdelphij#define DATA 03 /* data packet */ 45276788Sdelphij#define ACK 04 /* acknowledgement */ 46276788Sdelphij#define TFTP_ERROR 05 /* error code */ 47276788Sdelphij#define OACK 06 /* option acknowledgement */ 48276788Sdelphij 49276788Sdelphijstruct tftphdr { 50276788Sdelphij unsigned short th_opcode; /* packet type */ 51276788Sdelphij union { 52276788Sdelphij unsigned short tu_block; /* block # */ 53276788Sdelphij unsigned short tu_code; /* error code */ 54276788Sdelphij char tu_stuff[1]; /* request packet stuff */ 55276788Sdelphij } th_u; 56276788Sdelphij char th_data[1]; /* data or error string */ 57276788Sdelphij}; 58276788Sdelphij 59276788Sdelphij#define th_block th_u.tu_block 60276788Sdelphij#define th_code th_u.tu_code 61276788Sdelphij#define th_stuff th_u.tu_stuff 62276788Sdelphij#define th_msg th_data 63276788Sdelphij 64276788Sdelphij/* 65276788Sdelphij * Error codes. 66276788Sdelphij */ 67276788Sdelphij#define EUNDEF 0 /* not defined */ 68276788Sdelphij#define ENOTFOUND 1 /* file not found */ 69276788Sdelphij#define EACCESS 2 /* access violation */ 70276788Sdelphij#define ENOSPACE 3 /* disk full or allocation exceeded */ 71276788Sdelphij#define EBADOP 4 /* illegal TFTP operation */ 72276788Sdelphij#define EBADID 5 /* unknown transfer ID */ 73276788Sdelphij#define EEXISTS 6 /* file already exists */ 74276788Sdelphij#define ENOUSER 7 /* no such user */ 75276788Sdelphij 76276788Sdelphijstatic const char tstr[] = " [|tftp]"; 77276788Sdelphij 7817680Spst/* op code to string mapping */ 79276788Sdelphijstatic const struct tok op2str[] = { 8017680Spst { RRQ, "RRQ" }, /* read request */ 8117680Spst { WRQ, "WRQ" }, /* write request */ 8217680Spst { DATA, "DATA" }, /* data packet */ 8317680Spst { ACK, "ACK" }, /* acknowledgement */ 84190207Srpaulo { TFTP_ERROR, "ERROR" }, /* error code */ 85172683Smlaier { OACK, "OACK" }, /* option acknowledgement */ 8617680Spst { 0, NULL } 8717680Spst}; 8817680Spst 8917680Spst/* error code to string mapping */ 90276788Sdelphijstatic const struct tok err2str[] = { 9117680Spst { EUNDEF, "EUNDEF" }, /* not defined */ 9217680Spst { ENOTFOUND, "ENOTFOUND" }, /* file not found */ 9317680Spst { EACCESS, "EACCESS" }, /* access violation */ 9417680Spst { ENOSPACE, "ENOSPACE" }, /* disk full or allocation exceeded */ 9517680Spst { EBADOP, "EBADOP" }, /* illegal TFTP operation */ 9617680Spst { EBADID, "EBADID" }, /* unknown transfer ID */ 9717680Spst { EEXISTS, "EEXISTS" }, /* file already exists */ 9817680Spst { ENOUSER, "ENOUSER" }, /* no such user */ 9917680Spst { 0, NULL } 10017680Spst}; 10117680Spst 10217680Spst/* 10317680Spst * Print trivial file transfer program requests 10417680Spst */ 10517680Spstvoid 106276788Sdelphijtftp_print(netdissect_options *ndo, 107276788Sdelphij register const u_char *bp, u_int length) 10817680Spst{ 10917680Spst register const struct tftphdr *tp; 11017680Spst register const char *cp; 11117680Spst register const u_char *p; 112313537Sglebius register int opcode; 113313537Sglebius u_int ui; 11417680Spst 11517680Spst tp = (const struct tftphdr *)bp; 11617680Spst 11717680Spst /* Print length */ 118276788Sdelphij ND_PRINT((ndo, " %d", length)); 11917680Spst 12017680Spst /* Print tftp request type */ 121313537Sglebius if (length < 2) 122313537Sglebius goto trunc; 123276788Sdelphij ND_TCHECK(tp->th_opcode); 124127668Sbms opcode = EXTRACT_16BITS(&tp->th_opcode); 12517680Spst cp = tok2str(op2str, "tftp-#%d", opcode); 126313537Sglebius length -= 2; 127276788Sdelphij ND_PRINT((ndo, " %s", cp)); 12817680Spst /* Bail if bogus opcode */ 12917680Spst if (*cp == 't') 13017680Spst return; 13117680Spst 13217680Spst switch (opcode) { 13317680Spst 13417680Spst case RRQ: 13517680Spst case WRQ: 136313537Sglebius p = (const u_char *)tp->th_stuff; 137313537Sglebius if (length == 0) 138313537Sglebius goto trunc; 139276788Sdelphij ND_PRINT((ndo, " ")); 140313537Sglebius /* Print filename */ 141313537Sglebius ND_PRINT((ndo, "\"")); 142313537Sglebius ui = fn_printztn(ndo, p, length, ndo->ndo_snapend); 143313537Sglebius ND_PRINT((ndo, "\"")); 144313537Sglebius if (ui == 0) 145313537Sglebius goto trunc; 146313537Sglebius p += ui; 147313537Sglebius length -= ui; 148127668Sbms 149313537Sglebius /* Print the mode - RRQ and WRQ only */ 150313537Sglebius if (length == 0) 151313537Sglebius goto trunc; /* no mode */ 152313537Sglebius ND_PRINT((ndo, " ")); 153313537Sglebius ui = fn_printztn(ndo, p, length, ndo->ndo_snapend); 154313537Sglebius if (ui == 0) 155313537Sglebius goto trunc; 156313537Sglebius p += ui; 157313537Sglebius length -= ui; 158313537Sglebius 159313537Sglebius /* Print options, if any */ 160313537Sglebius while (length != 0) { 161313537Sglebius ND_TCHECK(*p); 162313537Sglebius if (*p != '\0') 163276788Sdelphij ND_PRINT((ndo, " ")); 164313537Sglebius ui = fn_printztn(ndo, p, length, ndo->ndo_snapend); 165313537Sglebius if (ui == 0) 166313537Sglebius goto trunc; 167313537Sglebius p += ui; 168313537Sglebius length -= ui; 169127668Sbms } 170313537Sglebius break; 171276788Sdelphij 172313537Sglebius case OACK: 173313537Sglebius p = (const u_char *)tp->th_stuff; 174313537Sglebius /* Print options */ 175313537Sglebius while (length != 0) { 176313537Sglebius ND_TCHECK(*p); 177313537Sglebius if (*p != '\0') 178313537Sglebius ND_PRINT((ndo, " ")); 179313537Sglebius ui = fn_printztn(ndo, p, length, ndo->ndo_snapend); 180313537Sglebius if (ui == 0) 181313537Sglebius goto trunc; 182313537Sglebius p += ui; 183313537Sglebius length -= ui; 184313537Sglebius } 18517680Spst break; 18617680Spst 18717680Spst case ACK: 18817680Spst case DATA: 189313537Sglebius if (length < 2) 190313537Sglebius goto trunc; /* no block number */ 191276788Sdelphij ND_TCHECK(tp->th_block); 192276788Sdelphij ND_PRINT((ndo, " block %d", EXTRACT_16BITS(&tp->th_block))); 19317680Spst break; 19417680Spst 195190207Srpaulo case TFTP_ERROR: 19617680Spst /* Print error code string */ 197313537Sglebius if (length < 2) 198313537Sglebius goto trunc; /* no error code */ 199276788Sdelphij ND_TCHECK(tp->th_code); 200313537Sglebius ND_PRINT((ndo, " %s", tok2str(err2str, "tftp-err-#%d \"", 201276788Sdelphij EXTRACT_16BITS(&tp->th_code)))); 202313537Sglebius length -= 2; 20317680Spst /* Print error message string */ 204313537Sglebius if (length == 0) 205313537Sglebius goto trunc; /* no error message */ 206313537Sglebius ND_PRINT((ndo, " \"")); 207313537Sglebius ui = fn_printztn(ndo, (const u_char *)tp->th_data, length, ndo->ndo_snapend); 208276788Sdelphij ND_PRINT((ndo, "\"")); 209313537Sglebius if (ui == 0) 21017680Spst goto trunc; 21117680Spst break; 21217680Spst 21317680Spst default: 21417680Spst /* We shouldn't get here */ 215276788Sdelphij ND_PRINT((ndo, "(unknown #%d)", opcode)); 21617680Spst break; 21717680Spst } 21817680Spst return; 21917680Spsttrunc: 220276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 22117680Spst return; 22217680Spst} 223