14edb46e9SPaul Traina /* 24644f044SBill Fenner * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 34edb46e9SPaul Traina * The Regents of the University of California. All rights reserved. 44edb46e9SPaul Traina * 54edb46e9SPaul Traina * Redistribution and use in source and binary forms, with or without 64edb46e9SPaul Traina * modification, are permitted provided that: (1) source code distributions 74edb46e9SPaul Traina * retain the above copyright notice and this paragraph in its entirety, (2) 84edb46e9SPaul Traina * distributions including binary code include the above copyright notice and 94edb46e9SPaul Traina * this paragraph in its entirety in the documentation or other materials 104edb46e9SPaul Traina * provided with the distribution, and (3) all advertising materials mentioning 114edb46e9SPaul Traina * features or use of this software display the following acknowledgement: 124edb46e9SPaul Traina * ``This product includes software developed by the University of California, 134edb46e9SPaul Traina * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 144edb46e9SPaul Traina * the University nor the names of its contributors may be used to endorse 154edb46e9SPaul Traina * or promote products derived from this software without specific prior 164edb46e9SPaul Traina * written permission. 174edb46e9SPaul Traina * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 184edb46e9SPaul Traina * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 194edb46e9SPaul Traina * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 204edb46e9SPaul Traina * 214edb46e9SPaul Traina * Format and print trivial file transfer protocol packets. 224edb46e9SPaul Traina */ 234edb46e9SPaul Traina 24*3c602fabSXin LI #define NETDISSECT_REWORKED 25b0453382SBill Fenner #ifdef HAVE_CONFIG_H 26b0453382SBill Fenner #include "config.h" 274edb46e9SPaul Traina #endif 284edb46e9SPaul Traina 295b0fe478SBruce M Simpson #include <tcpdump-stdinc.h> 304edb46e9SPaul Traina 314edb46e9SPaul Traina #include <string.h> 324edb46e9SPaul Traina 334edb46e9SPaul Traina #include "interface.h" 345b0fe478SBruce M Simpson #include "extract.h" 35*3c602fabSXin LI 36*3c602fabSXin LI /* 37*3c602fabSXin LI * Trivial File Transfer Protocol (IEN-133) 38*3c602fabSXin LI */ 39*3c602fabSXin LI 40*3c602fabSXin LI /* 41*3c602fabSXin LI * Packet types. 42*3c602fabSXin LI */ 43*3c602fabSXin LI #define RRQ 01 /* read request */ 44*3c602fabSXin LI #define WRQ 02 /* write request */ 45*3c602fabSXin LI #define DATA 03 /* data packet */ 46*3c602fabSXin LI #define ACK 04 /* acknowledgement */ 47*3c602fabSXin LI #define TFTP_ERROR 05 /* error code */ 48*3c602fabSXin LI #define OACK 06 /* option acknowledgement */ 49*3c602fabSXin LI 50*3c602fabSXin LI struct tftphdr { 51*3c602fabSXin LI unsigned short th_opcode; /* packet type */ 52*3c602fabSXin LI union { 53*3c602fabSXin LI unsigned short tu_block; /* block # */ 54*3c602fabSXin LI unsigned short tu_code; /* error code */ 55*3c602fabSXin LI char tu_stuff[1]; /* request packet stuff */ 56*3c602fabSXin LI } th_u; 57*3c602fabSXin LI char th_data[1]; /* data or error string */ 58*3c602fabSXin LI }; 59*3c602fabSXin LI 60*3c602fabSXin LI #define th_block th_u.tu_block 61*3c602fabSXin LI #define th_code th_u.tu_code 62*3c602fabSXin LI #define th_stuff th_u.tu_stuff 63*3c602fabSXin LI #define th_msg th_data 64*3c602fabSXin LI 65*3c602fabSXin LI /* 66*3c602fabSXin LI * Error codes. 67*3c602fabSXin LI */ 68*3c602fabSXin LI #define EUNDEF 0 /* not defined */ 69*3c602fabSXin LI #define ENOTFOUND 1 /* file not found */ 70*3c602fabSXin LI #define EACCESS 2 /* access violation */ 71*3c602fabSXin LI #define ENOSPACE 3 /* disk full or allocation exceeded */ 72*3c602fabSXin LI #define EBADOP 4 /* illegal TFTP operation */ 73*3c602fabSXin LI #define EBADID 5 /* unknown transfer ID */ 74*3c602fabSXin LI #define EEXISTS 6 /* file already exists */ 75*3c602fabSXin LI #define ENOUSER 7 /* no such user */ 76*3c602fabSXin LI 77*3c602fabSXin LI static const char tstr[] = " [|tftp]"; 784edb46e9SPaul Traina 794edb46e9SPaul Traina /* op code to string mapping */ 80*3c602fabSXin LI static const struct tok op2str[] = { 814edb46e9SPaul Traina { RRQ, "RRQ" }, /* read request */ 824edb46e9SPaul Traina { WRQ, "WRQ" }, /* write request */ 834edb46e9SPaul Traina { DATA, "DATA" }, /* data packet */ 844edb46e9SPaul Traina { ACK, "ACK" }, /* acknowledgement */ 85a5779b6eSRui Paulo { TFTP_ERROR, "ERROR" }, /* error code */ 86b5bfcb5dSMax Laier { OACK, "OACK" }, /* option acknowledgement */ 874edb46e9SPaul Traina { 0, NULL } 884edb46e9SPaul Traina }; 894edb46e9SPaul Traina 904edb46e9SPaul Traina /* error code to string mapping */ 91*3c602fabSXin LI static const struct tok err2str[] = { 924edb46e9SPaul Traina { EUNDEF, "EUNDEF" }, /* not defined */ 934edb46e9SPaul Traina { ENOTFOUND, "ENOTFOUND" }, /* file not found */ 944edb46e9SPaul Traina { EACCESS, "EACCESS" }, /* access violation */ 954edb46e9SPaul Traina { ENOSPACE, "ENOSPACE" }, /* disk full or allocation exceeded */ 964edb46e9SPaul Traina { EBADOP, "EBADOP" }, /* illegal TFTP operation */ 974edb46e9SPaul Traina { EBADID, "EBADID" }, /* unknown transfer ID */ 984edb46e9SPaul Traina { EEXISTS, "EEXISTS" }, /* file already exists */ 994edb46e9SPaul Traina { ENOUSER, "ENOUSER" }, /* no such user */ 1004edb46e9SPaul Traina { 0, NULL } 1014edb46e9SPaul Traina }; 1024edb46e9SPaul Traina 1034edb46e9SPaul Traina /* 1044edb46e9SPaul Traina * Print trivial file transfer program requests 1054edb46e9SPaul Traina */ 1064edb46e9SPaul Traina void 107*3c602fabSXin LI tftp_print(netdissect_options *ndo, 108*3c602fabSXin LI register const u_char *bp, u_int length) 1094edb46e9SPaul Traina { 1104edb46e9SPaul Traina register const struct tftphdr *tp; 1114edb46e9SPaul Traina register const char *cp; 1124edb46e9SPaul Traina register const u_char *p; 1134edb46e9SPaul Traina register int opcode, i; 1144edb46e9SPaul Traina 1154edb46e9SPaul Traina tp = (const struct tftphdr *)bp; 1164edb46e9SPaul Traina 1174edb46e9SPaul Traina /* Print length */ 118*3c602fabSXin LI ND_PRINT((ndo, " %d", length)); 1194edb46e9SPaul Traina 1204edb46e9SPaul Traina /* Print tftp request type */ 121*3c602fabSXin LI ND_TCHECK(tp->th_opcode); 1225b0fe478SBruce M Simpson opcode = EXTRACT_16BITS(&tp->th_opcode); 1234edb46e9SPaul Traina cp = tok2str(op2str, "tftp-#%d", opcode); 124*3c602fabSXin LI ND_PRINT((ndo, " %s", cp)); 1254edb46e9SPaul Traina /* Bail if bogus opcode */ 1264edb46e9SPaul Traina if (*cp == 't') 1274edb46e9SPaul Traina return; 1284edb46e9SPaul Traina 1294edb46e9SPaul Traina switch (opcode) { 1304edb46e9SPaul Traina 1314edb46e9SPaul Traina case RRQ: 1324edb46e9SPaul Traina case WRQ: 133b5bfcb5dSMax Laier case OACK: 1344edb46e9SPaul Traina p = (u_char *)tp->th_stuff; 135*3c602fabSXin LI ND_PRINT((ndo, " ")); 136b5bfcb5dSMax Laier /* Print filename or first option */ 137b5bfcb5dSMax Laier if (opcode != OACK) 138*3c602fabSXin LI ND_PRINT((ndo, "\"")); 139*3c602fabSXin LI i = fn_print(ndo, p, ndo->ndo_snapend); 140b5bfcb5dSMax Laier if (opcode != OACK) 141*3c602fabSXin LI ND_PRINT((ndo, "\"")); 1425b0fe478SBruce M Simpson 143b5bfcb5dSMax Laier /* Print the mode (RRQ and WRQ only) and any options */ 1445b0fe478SBruce M Simpson while ((p = (const u_char *)strchr((const char *)p, '\0')) != NULL) { 1455b0fe478SBruce M Simpson if (length <= (u_int)(p - (const u_char *)&tp->th_block)) 1465b0fe478SBruce M Simpson break; 1475b0fe478SBruce M Simpson p++; 1485b0fe478SBruce M Simpson if (*p != '\0') { 149*3c602fabSXin LI ND_PRINT((ndo, " ")); 150*3c602fabSXin LI fn_print(ndo, p, ndo->ndo_snapend); 1515b0fe478SBruce M Simpson } 1525b0fe478SBruce M Simpson } 1535b0fe478SBruce M Simpson 1544edb46e9SPaul Traina if (i) 1554edb46e9SPaul Traina goto trunc; 1564edb46e9SPaul Traina break; 1574edb46e9SPaul Traina 1584edb46e9SPaul Traina case ACK: 1594edb46e9SPaul Traina case DATA: 160*3c602fabSXin LI ND_TCHECK(tp->th_block); 161*3c602fabSXin LI ND_PRINT((ndo, " block %d", EXTRACT_16BITS(&tp->th_block))); 1624edb46e9SPaul Traina break; 1634edb46e9SPaul Traina 164a5779b6eSRui Paulo case TFTP_ERROR: 1654edb46e9SPaul Traina /* Print error code string */ 166*3c602fabSXin LI ND_TCHECK(tp->th_code); 167*3c602fabSXin LI ND_PRINT((ndo, " %s \"", tok2str(err2str, "tftp-err-#%d \"", 168*3c602fabSXin LI EXTRACT_16BITS(&tp->th_code)))); 1694edb46e9SPaul Traina /* Print error message string */ 170*3c602fabSXin LI i = fn_print(ndo, (const u_char *)tp->th_data, ndo->ndo_snapend); 171*3c602fabSXin LI ND_PRINT((ndo, "\"")); 1724edb46e9SPaul Traina if (i) 1734edb46e9SPaul Traina goto trunc; 1744edb46e9SPaul Traina break; 1754edb46e9SPaul Traina 1764edb46e9SPaul Traina default: 1774edb46e9SPaul Traina /* We shouldn't get here */ 178*3c602fabSXin LI ND_PRINT((ndo, "(unknown #%d)", opcode)); 1794edb46e9SPaul Traina break; 1804edb46e9SPaul Traina } 1814edb46e9SPaul Traina return; 1824edb46e9SPaul Traina trunc: 183*3c602fabSXin LI ND_PRINT((ndo, "%s", tstr)); 1844edb46e9SPaul Traina return; 1854edb46e9SPaul Traina } 186