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 49276788Sdelphij/* 50276788Sdelphij * Error codes. 51276788Sdelphij */ 52276788Sdelphij#define EUNDEF 0 /* not defined */ 53276788Sdelphij#define ENOTFOUND 1 /* file not found */ 54276788Sdelphij#define EACCESS 2 /* access violation */ 55276788Sdelphij#define ENOSPACE 3 /* disk full or allocation exceeded */ 56276788Sdelphij#define EBADOP 4 /* illegal TFTP operation */ 57276788Sdelphij#define EBADID 5 /* unknown transfer ID */ 58276788Sdelphij#define EEXISTS 6 /* file already exists */ 59276788Sdelphij#define ENOUSER 7 /* no such user */ 60276788Sdelphij 61276788Sdelphijstatic const char tstr[] = " [|tftp]"; 62276788Sdelphij 6317680Spst/* op code to string mapping */ 64276788Sdelphijstatic const struct tok op2str[] = { 6517680Spst { RRQ, "RRQ" }, /* read request */ 6617680Spst { WRQ, "WRQ" }, /* write request */ 6717680Spst { DATA, "DATA" }, /* data packet */ 6817680Spst { ACK, "ACK" }, /* acknowledgement */ 69190207Srpaulo { TFTP_ERROR, "ERROR" }, /* error code */ 70172683Smlaier { OACK, "OACK" }, /* option acknowledgement */ 7117680Spst { 0, NULL } 7217680Spst}; 7317680Spst 7417680Spst/* error code to string mapping */ 75276788Sdelphijstatic const struct tok err2str[] = { 7617680Spst { EUNDEF, "EUNDEF" }, /* not defined */ 7717680Spst { ENOTFOUND, "ENOTFOUND" }, /* file not found */ 7817680Spst { EACCESS, "EACCESS" }, /* access violation */ 7917680Spst { ENOSPACE, "ENOSPACE" }, /* disk full or allocation exceeded */ 8017680Spst { EBADOP, "EBADOP" }, /* illegal TFTP operation */ 8117680Spst { EBADID, "EBADID" }, /* unknown transfer ID */ 8217680Spst { EEXISTS, "EEXISTS" }, /* file already exists */ 8317680Spst { ENOUSER, "ENOUSER" }, /* no such user */ 8417680Spst { 0, NULL } 8517680Spst}; 8617680Spst 8717680Spst/* 8817680Spst * Print trivial file transfer program requests 8917680Spst */ 9017680Spstvoid 91276788Sdelphijtftp_print(netdissect_options *ndo, 92276788Sdelphij register const u_char *bp, u_int length) 9317680Spst{ 9417680Spst register const char *cp; 95313537Sglebius register int opcode; 96313537Sglebius u_int ui; 9717680Spst 9817680Spst /* Print length */ 99276788Sdelphij ND_PRINT((ndo, " %d", length)); 10017680Spst 10117680Spst /* Print tftp request type */ 102313537Sglebius if (length < 2) 103313537Sglebius goto trunc; 104327234Semaste ND_TCHECK_16BITS(bp); 105327234Semaste opcode = EXTRACT_16BITS(bp); 10617680Spst cp = tok2str(op2str, "tftp-#%d", opcode); 107276788Sdelphij ND_PRINT((ndo, " %s", cp)); 10817680Spst /* Bail if bogus opcode */ 10917680Spst if (*cp == 't') 11017680Spst return; 111327234Semaste bp += 2; 112327234Semaste length -= 2; 11317680Spst 11417680Spst switch (opcode) { 11517680Spst 11617680Spst case RRQ: 11717680Spst case WRQ: 118313537Sglebius if (length == 0) 119313537Sglebius goto trunc; 120276788Sdelphij ND_PRINT((ndo, " ")); 121313537Sglebius /* Print filename */ 122313537Sglebius ND_PRINT((ndo, "\"")); 123327234Semaste ui = fn_printztn(ndo, bp, length, ndo->ndo_snapend); 124313537Sglebius ND_PRINT((ndo, "\"")); 125313537Sglebius if (ui == 0) 126313537Sglebius goto trunc; 127327234Semaste bp += ui; 128313537Sglebius length -= ui; 129127668Sbms 130313537Sglebius /* Print the mode - RRQ and WRQ only */ 131313537Sglebius if (length == 0) 132313537Sglebius goto trunc; /* no mode */ 133313537Sglebius ND_PRINT((ndo, " ")); 134327234Semaste ui = fn_printztn(ndo, bp, length, ndo->ndo_snapend); 135313537Sglebius if (ui == 0) 136313537Sglebius goto trunc; 137327234Semaste bp += ui; 138313537Sglebius length -= ui; 139313537Sglebius 140313537Sglebius /* Print options, if any */ 141313537Sglebius while (length != 0) { 142327234Semaste ND_TCHECK(*bp); 143327234Semaste if (*bp != '\0') 144276788Sdelphij ND_PRINT((ndo, " ")); 145327234Semaste ui = fn_printztn(ndo, bp, length, ndo->ndo_snapend); 146313537Sglebius if (ui == 0) 147313537Sglebius goto trunc; 148327234Semaste bp += ui; 149313537Sglebius length -= ui; 150127668Sbms } 151313537Sglebius break; 152276788Sdelphij 153313537Sglebius case OACK: 154313537Sglebius /* Print options */ 155313537Sglebius while (length != 0) { 156327234Semaste ND_TCHECK(*bp); 157327234Semaste if (*bp != '\0') 158313537Sglebius ND_PRINT((ndo, " ")); 159327234Semaste ui = fn_printztn(ndo, bp, length, ndo->ndo_snapend); 160313537Sglebius if (ui == 0) 161313537Sglebius goto trunc; 162327234Semaste bp += ui; 163313537Sglebius length -= ui; 164313537Sglebius } 16517680Spst break; 16617680Spst 16717680Spst case ACK: 16817680Spst case DATA: 169313537Sglebius if (length < 2) 170313537Sglebius goto trunc; /* no block number */ 171327234Semaste ND_TCHECK_16BITS(bp); 172327234Semaste ND_PRINT((ndo, " block %d", EXTRACT_16BITS(bp))); 17317680Spst break; 17417680Spst 175190207Srpaulo case TFTP_ERROR: 17617680Spst /* Print error code string */ 177313537Sglebius if (length < 2) 178313537Sglebius goto trunc; /* no error code */ 179327234Semaste ND_TCHECK_16BITS(bp); 180313537Sglebius ND_PRINT((ndo, " %s", tok2str(err2str, "tftp-err-#%d \"", 181327234Semaste EXTRACT_16BITS(bp)))); 182327234Semaste bp += 2; 183313537Sglebius length -= 2; 18417680Spst /* Print error message string */ 185313537Sglebius if (length == 0) 186313537Sglebius goto trunc; /* no error message */ 187313537Sglebius ND_PRINT((ndo, " \"")); 188327234Semaste ui = fn_printztn(ndo, bp, length, ndo->ndo_snapend); 189276788Sdelphij ND_PRINT((ndo, "\"")); 190313537Sglebius if (ui == 0) 19117680Spst goto trunc; 19217680Spst break; 19317680Spst 19417680Spst default: 19517680Spst /* We shouldn't get here */ 196276788Sdelphij ND_PRINT((ndo, "(unknown #%d)", opcode)); 19717680Spst break; 19817680Spst } 19917680Spst return; 20017680Spsttrunc: 201276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 20217680Spst return; 20317680Spst} 204