print-tftp.c revision 276788
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 * Format and print trivial file transfer protocol packets. 2217680Spst */ 2317680Spst 24276788Sdelphij#define NETDISSECT_REWORKED 2556893Sfenner#ifdef HAVE_CONFIG_H 2656893Sfenner#include "config.h" 2756893Sfenner#endif 2856893Sfenner 29127668Sbms#include <tcpdump-stdinc.h> 3017680Spst 3117680Spst#include <string.h> 3217680Spst 3317680Spst#include "interface.h" 34127668Sbms#include "extract.h" 3517680Spst 36276788Sdelphij/* 37276788Sdelphij * Trivial File Transfer Protocol (IEN-133) 38276788Sdelphij */ 39276788Sdelphij 40276788Sdelphij/* 41276788Sdelphij * Packet types. 42276788Sdelphij */ 43276788Sdelphij#define RRQ 01 /* read request */ 44276788Sdelphij#define WRQ 02 /* write request */ 45276788Sdelphij#define DATA 03 /* data packet */ 46276788Sdelphij#define ACK 04 /* acknowledgement */ 47276788Sdelphij#define TFTP_ERROR 05 /* error code */ 48276788Sdelphij#define OACK 06 /* option acknowledgement */ 49276788Sdelphij 50276788Sdelphijstruct tftphdr { 51276788Sdelphij unsigned short th_opcode; /* packet type */ 52276788Sdelphij union { 53276788Sdelphij unsigned short tu_block; /* block # */ 54276788Sdelphij unsigned short tu_code; /* error code */ 55276788Sdelphij char tu_stuff[1]; /* request packet stuff */ 56276788Sdelphij } th_u; 57276788Sdelphij char th_data[1]; /* data or error string */ 58276788Sdelphij}; 59276788Sdelphij 60276788Sdelphij#define th_block th_u.tu_block 61276788Sdelphij#define th_code th_u.tu_code 62276788Sdelphij#define th_stuff th_u.tu_stuff 63276788Sdelphij#define th_msg th_data 64276788Sdelphij 65276788Sdelphij/* 66276788Sdelphij * Error codes. 67276788Sdelphij */ 68276788Sdelphij#define EUNDEF 0 /* not defined */ 69276788Sdelphij#define ENOTFOUND 1 /* file not found */ 70276788Sdelphij#define EACCESS 2 /* access violation */ 71276788Sdelphij#define ENOSPACE 3 /* disk full or allocation exceeded */ 72276788Sdelphij#define EBADOP 4 /* illegal TFTP operation */ 73276788Sdelphij#define EBADID 5 /* unknown transfer ID */ 74276788Sdelphij#define EEXISTS 6 /* file already exists */ 75276788Sdelphij#define ENOUSER 7 /* no such user */ 76276788Sdelphij 77276788Sdelphijstatic const char tstr[] = " [|tftp]"; 78276788Sdelphij 7917680Spst/* op code to string mapping */ 80276788Sdelphijstatic const struct tok op2str[] = { 8117680Spst { RRQ, "RRQ" }, /* read request */ 8217680Spst { WRQ, "WRQ" }, /* write request */ 8317680Spst { DATA, "DATA" }, /* data packet */ 8417680Spst { ACK, "ACK" }, /* acknowledgement */ 85190207Srpaulo { TFTP_ERROR, "ERROR" }, /* error code */ 86172683Smlaier { OACK, "OACK" }, /* option acknowledgement */ 8717680Spst { 0, NULL } 8817680Spst}; 8917680Spst 9017680Spst/* error code to string mapping */ 91276788Sdelphijstatic const struct tok err2str[] = { 9217680Spst { EUNDEF, "EUNDEF" }, /* not defined */ 9317680Spst { ENOTFOUND, "ENOTFOUND" }, /* file not found */ 9417680Spst { EACCESS, "EACCESS" }, /* access violation */ 9517680Spst { ENOSPACE, "ENOSPACE" }, /* disk full or allocation exceeded */ 9617680Spst { EBADOP, "EBADOP" }, /* illegal TFTP operation */ 9717680Spst { EBADID, "EBADID" }, /* unknown transfer ID */ 9817680Spst { EEXISTS, "EEXISTS" }, /* file already exists */ 9917680Spst { ENOUSER, "ENOUSER" }, /* no such user */ 10017680Spst { 0, NULL } 10117680Spst}; 10217680Spst 10317680Spst/* 10417680Spst * Print trivial file transfer program requests 10517680Spst */ 10617680Spstvoid 107276788Sdelphijtftp_print(netdissect_options *ndo, 108276788Sdelphij register const u_char *bp, u_int length) 10917680Spst{ 11017680Spst register const struct tftphdr *tp; 11117680Spst register const char *cp; 11217680Spst register const u_char *p; 11317680Spst register int opcode, i; 11417680Spst 11517680Spst tp = (const struct tftphdr *)bp; 11617680Spst 11717680Spst /* Print length */ 118276788Sdelphij ND_PRINT((ndo, " %d", length)); 11917680Spst 12017680Spst /* Print tftp request type */ 121276788Sdelphij ND_TCHECK(tp->th_opcode); 122127668Sbms opcode = EXTRACT_16BITS(&tp->th_opcode); 12317680Spst cp = tok2str(op2str, "tftp-#%d", opcode); 124276788Sdelphij ND_PRINT((ndo, " %s", cp)); 12517680Spst /* Bail if bogus opcode */ 12617680Spst if (*cp == 't') 12717680Spst return; 12817680Spst 12917680Spst switch (opcode) { 13017680Spst 13117680Spst case RRQ: 13217680Spst case WRQ: 133172683Smlaier case OACK: 13417680Spst p = (u_char *)tp->th_stuff; 135276788Sdelphij ND_PRINT((ndo, " ")); 136172683Smlaier /* Print filename or first option */ 137172683Smlaier if (opcode != OACK) 138276788Sdelphij ND_PRINT((ndo, "\"")); 139276788Sdelphij i = fn_print(ndo, p, ndo->ndo_snapend); 140172683Smlaier if (opcode != OACK) 141276788Sdelphij ND_PRINT((ndo, "\"")); 142127668Sbms 143172683Smlaier /* Print the mode (RRQ and WRQ only) and any options */ 144127668Sbms while ((p = (const u_char *)strchr((const char *)p, '\0')) != NULL) { 145127668Sbms if (length <= (u_int)(p - (const u_char *)&tp->th_block)) 146127668Sbms break; 147127668Sbms p++; 148127668Sbms if (*p != '\0') { 149276788Sdelphij ND_PRINT((ndo, " ")); 150276788Sdelphij fn_print(ndo, p, ndo->ndo_snapend); 151127668Sbms } 152127668Sbms } 153276788Sdelphij 15417680Spst if (i) 15517680Spst goto trunc; 15617680Spst break; 15717680Spst 15817680Spst case ACK: 15917680Spst case DATA: 160276788Sdelphij ND_TCHECK(tp->th_block); 161276788Sdelphij ND_PRINT((ndo, " block %d", EXTRACT_16BITS(&tp->th_block))); 16217680Spst break; 16317680Spst 164190207Srpaulo case TFTP_ERROR: 16517680Spst /* Print error code string */ 166276788Sdelphij ND_TCHECK(tp->th_code); 167276788Sdelphij ND_PRINT((ndo, " %s \"", tok2str(err2str, "tftp-err-#%d \"", 168276788Sdelphij EXTRACT_16BITS(&tp->th_code)))); 16917680Spst /* Print error message string */ 170276788Sdelphij i = fn_print(ndo, (const u_char *)tp->th_data, ndo->ndo_snapend); 171276788Sdelphij ND_PRINT((ndo, "\"")); 17217680Spst if (i) 17317680Spst goto trunc; 17417680Spst break; 17517680Spst 17617680Spst default: 17717680Spst /* We shouldn't get here */ 178276788Sdelphij ND_PRINT((ndo, "(unknown #%d)", opcode)); 17917680Spst break; 18017680Spst } 18117680Spst return; 18217680Spsttrunc: 183276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 18417680Spst return; 18517680Spst} 186