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 223340d773SGleb Smirnoff /* \summary: Trivial File Transfer Protocol (TFTP) printer */ 233340d773SGleb Smirnoff 24b0453382SBill Fenner #ifdef HAVE_CONFIG_H 25b0453382SBill Fenner #include "config.h" 264edb46e9SPaul Traina #endif 274edb46e9SPaul Traina 283340d773SGleb Smirnoff #include <netdissect-stdinc.h> 294edb46e9SPaul Traina 304edb46e9SPaul Traina #include <string.h> 314edb46e9SPaul Traina 323340d773SGleb Smirnoff #include "netdissect.h" 335b0fe478SBruce M Simpson #include "extract.h" 343c602fabSXin LI 353c602fabSXin LI /* 363c602fabSXin LI * Trivial File Transfer Protocol (IEN-133) 373c602fabSXin LI */ 383c602fabSXin LI 393c602fabSXin LI /* 403c602fabSXin LI * Packet types. 413c602fabSXin LI */ 423c602fabSXin LI #define RRQ 01 /* read request */ 433c602fabSXin LI #define WRQ 02 /* write request */ 443c602fabSXin LI #define DATA 03 /* data packet */ 453c602fabSXin LI #define ACK 04 /* acknowledgement */ 463c602fabSXin LI #define TFTP_ERROR 05 /* error code */ 473c602fabSXin LI #define OACK 06 /* option acknowledgement */ 483c602fabSXin LI 493c602fabSXin LI /* 503c602fabSXin LI * Error codes. 513c602fabSXin LI */ 523c602fabSXin LI #define EUNDEF 0 /* not defined */ 533c602fabSXin LI #define ENOTFOUND 1 /* file not found */ 543c602fabSXin LI #define EACCESS 2 /* access violation */ 553c602fabSXin LI #define ENOSPACE 3 /* disk full or allocation exceeded */ 563c602fabSXin LI #define EBADOP 4 /* illegal TFTP operation */ 573c602fabSXin LI #define EBADID 5 /* unknown transfer ID */ 583c602fabSXin LI #define EEXISTS 6 /* file already exists */ 593c602fabSXin LI #define ENOUSER 7 /* no such user */ 603c602fabSXin LI 613c602fabSXin LI static const char tstr[] = " [|tftp]"; 624edb46e9SPaul Traina 634edb46e9SPaul Traina /* op code to string mapping */ 643c602fabSXin LI static const struct tok op2str[] = { 654edb46e9SPaul Traina { RRQ, "RRQ" }, /* read request */ 664edb46e9SPaul Traina { WRQ, "WRQ" }, /* write request */ 674edb46e9SPaul Traina { DATA, "DATA" }, /* data packet */ 684edb46e9SPaul Traina { ACK, "ACK" }, /* acknowledgement */ 69a5779b6eSRui Paulo { TFTP_ERROR, "ERROR" }, /* error code */ 70b5bfcb5dSMax Laier { OACK, "OACK" }, /* option acknowledgement */ 714edb46e9SPaul Traina { 0, NULL } 724edb46e9SPaul Traina }; 734edb46e9SPaul Traina 744edb46e9SPaul Traina /* error code to string mapping */ 753c602fabSXin LI static const struct tok err2str[] = { 764edb46e9SPaul Traina { EUNDEF, "EUNDEF" }, /* not defined */ 774edb46e9SPaul Traina { ENOTFOUND, "ENOTFOUND" }, /* file not found */ 784edb46e9SPaul Traina { EACCESS, "EACCESS" }, /* access violation */ 794edb46e9SPaul Traina { ENOSPACE, "ENOSPACE" }, /* disk full or allocation exceeded */ 804edb46e9SPaul Traina { EBADOP, "EBADOP" }, /* illegal TFTP operation */ 814edb46e9SPaul Traina { EBADID, "EBADID" }, /* unknown transfer ID */ 824edb46e9SPaul Traina { EEXISTS, "EEXISTS" }, /* file already exists */ 834edb46e9SPaul Traina { ENOUSER, "ENOUSER" }, /* no such user */ 844edb46e9SPaul Traina { 0, NULL } 854edb46e9SPaul Traina }; 864edb46e9SPaul Traina 874edb46e9SPaul Traina /* 884edb46e9SPaul Traina * Print trivial file transfer program requests 894edb46e9SPaul Traina */ 904edb46e9SPaul Traina void 913c602fabSXin LI tftp_print(netdissect_options *ndo, 923c602fabSXin LI register const u_char *bp, u_int length) 934edb46e9SPaul Traina { 944edb46e9SPaul Traina register const char *cp; 953340d773SGleb Smirnoff register int opcode; 963340d773SGleb Smirnoff u_int ui; 974edb46e9SPaul Traina 984edb46e9SPaul Traina /* Print length */ 993c602fabSXin LI ND_PRINT((ndo, " %d", length)); 1004edb46e9SPaul Traina 1014edb46e9SPaul Traina /* Print tftp request type */ 1023340d773SGleb Smirnoff if (length < 2) 1033340d773SGleb Smirnoff goto trunc; 104*0bff6a5aSEd Maste ND_TCHECK_16BITS(bp); 105*0bff6a5aSEd Maste opcode = EXTRACT_16BITS(bp); 1064edb46e9SPaul Traina cp = tok2str(op2str, "tftp-#%d", opcode); 1073c602fabSXin LI ND_PRINT((ndo, " %s", cp)); 1084edb46e9SPaul Traina /* Bail if bogus opcode */ 1094edb46e9SPaul Traina if (*cp == 't') 1104edb46e9SPaul Traina return; 111*0bff6a5aSEd Maste bp += 2; 112*0bff6a5aSEd Maste length -= 2; 1134edb46e9SPaul Traina 1144edb46e9SPaul Traina switch (opcode) { 1154edb46e9SPaul Traina 1164edb46e9SPaul Traina case RRQ: 1174edb46e9SPaul Traina case WRQ: 1183340d773SGleb Smirnoff if (length == 0) 1194edb46e9SPaul Traina goto trunc; 1203340d773SGleb Smirnoff ND_PRINT((ndo, " ")); 1213340d773SGleb Smirnoff /* Print filename */ 1223340d773SGleb Smirnoff ND_PRINT((ndo, "\"")); 123*0bff6a5aSEd Maste ui = fn_printztn(ndo, bp, length, ndo->ndo_snapend); 1243340d773SGleb Smirnoff ND_PRINT((ndo, "\"")); 1253340d773SGleb Smirnoff if (ui == 0) 1263340d773SGleb Smirnoff goto trunc; 127*0bff6a5aSEd Maste bp += ui; 1283340d773SGleb Smirnoff length -= ui; 1293340d773SGleb Smirnoff 1303340d773SGleb Smirnoff /* Print the mode - RRQ and WRQ only */ 1313340d773SGleb Smirnoff if (length == 0) 1323340d773SGleb Smirnoff goto trunc; /* no mode */ 1333340d773SGleb Smirnoff ND_PRINT((ndo, " ")); 134*0bff6a5aSEd Maste ui = fn_printztn(ndo, bp, length, ndo->ndo_snapend); 1353340d773SGleb Smirnoff if (ui == 0) 1363340d773SGleb Smirnoff goto trunc; 137*0bff6a5aSEd Maste bp += ui; 1383340d773SGleb Smirnoff length -= ui; 1393340d773SGleb Smirnoff 1403340d773SGleb Smirnoff /* Print options, if any */ 1413340d773SGleb Smirnoff while (length != 0) { 142*0bff6a5aSEd Maste ND_TCHECK(*bp); 143*0bff6a5aSEd Maste if (*bp != '\0') 1443340d773SGleb Smirnoff ND_PRINT((ndo, " ")); 145*0bff6a5aSEd Maste ui = fn_printztn(ndo, bp, length, ndo->ndo_snapend); 1463340d773SGleb Smirnoff if (ui == 0) 1473340d773SGleb Smirnoff goto trunc; 148*0bff6a5aSEd Maste bp += ui; 1493340d773SGleb Smirnoff length -= ui; 1503340d773SGleb Smirnoff } 1513340d773SGleb Smirnoff break; 1523340d773SGleb Smirnoff 1533340d773SGleb Smirnoff case OACK: 1543340d773SGleb Smirnoff /* Print options */ 1553340d773SGleb Smirnoff while (length != 0) { 156*0bff6a5aSEd Maste ND_TCHECK(*bp); 157*0bff6a5aSEd Maste if (*bp != '\0') 1583340d773SGleb Smirnoff ND_PRINT((ndo, " ")); 159*0bff6a5aSEd Maste ui = fn_printztn(ndo, bp, length, ndo->ndo_snapend); 1603340d773SGleb Smirnoff if (ui == 0) 1613340d773SGleb Smirnoff goto trunc; 162*0bff6a5aSEd Maste bp += ui; 1633340d773SGleb Smirnoff length -= ui; 1643340d773SGleb Smirnoff } 1654edb46e9SPaul Traina break; 1664edb46e9SPaul Traina 1674edb46e9SPaul Traina case ACK: 1684edb46e9SPaul Traina case DATA: 1693340d773SGleb Smirnoff if (length < 2) 1703340d773SGleb Smirnoff goto trunc; /* no block number */ 171*0bff6a5aSEd Maste ND_TCHECK_16BITS(bp); 172*0bff6a5aSEd Maste ND_PRINT((ndo, " block %d", EXTRACT_16BITS(bp))); 1734edb46e9SPaul Traina break; 1744edb46e9SPaul Traina 175a5779b6eSRui Paulo case TFTP_ERROR: 1764edb46e9SPaul Traina /* Print error code string */ 1773340d773SGleb Smirnoff if (length < 2) 1783340d773SGleb Smirnoff goto trunc; /* no error code */ 179*0bff6a5aSEd Maste ND_TCHECK_16BITS(bp); 1803340d773SGleb Smirnoff ND_PRINT((ndo, " %s", tok2str(err2str, "tftp-err-#%d \"", 181*0bff6a5aSEd Maste EXTRACT_16BITS(bp)))); 182*0bff6a5aSEd Maste bp += 2; 1833340d773SGleb Smirnoff length -= 2; 1844edb46e9SPaul Traina /* Print error message string */ 1853340d773SGleb Smirnoff if (length == 0) 1863340d773SGleb Smirnoff goto trunc; /* no error message */ 1873c602fabSXin LI ND_PRINT((ndo, " \"")); 188*0bff6a5aSEd Maste ui = fn_printztn(ndo, bp, length, ndo->ndo_snapend); 1893340d773SGleb Smirnoff ND_PRINT((ndo, "\"")); 1903340d773SGleb Smirnoff if (ui == 0) 1914edb46e9SPaul Traina goto trunc; 1924edb46e9SPaul Traina break; 1934edb46e9SPaul Traina 1944edb46e9SPaul Traina default: 1954edb46e9SPaul Traina /* We shouldn't get here */ 1963c602fabSXin LI ND_PRINT((ndo, "(unknown #%d)", opcode)); 1974edb46e9SPaul Traina break; 1984edb46e9SPaul Traina } 1994edb46e9SPaul Traina return; 2004edb46e9SPaul Traina trunc: 2013c602fabSXin LI ND_PRINT((ndo, "%s", tstr)); 2024edb46e9SPaul Traina return; 2034edb46e9SPaul Traina } 204