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 25*ee67461eSJoseph Mingrone #include <config.h> 264edb46e9SPaul Traina #endif 274edb46e9SPaul Traina 28*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h" 294edb46e9SPaul Traina 303340d773SGleb Smirnoff #include "netdissect.h" 315b0fe478SBruce M Simpson #include "extract.h" 323c602fabSXin LI 333c602fabSXin LI /* 343c602fabSXin LI * Trivial File Transfer Protocol (IEN-133) 353c602fabSXin LI */ 363c602fabSXin LI 373c602fabSXin LI /* 383c602fabSXin LI * Packet types. 393c602fabSXin LI */ 403c602fabSXin LI #define RRQ 01 /* read request */ 413c602fabSXin LI #define WRQ 02 /* write request */ 423c602fabSXin LI #define DATA 03 /* data packet */ 433c602fabSXin LI #define ACK 04 /* acknowledgement */ 443c602fabSXin LI #define TFTP_ERROR 05 /* error code */ 453c602fabSXin LI #define OACK 06 /* option acknowledgement */ 463c602fabSXin LI 473c602fabSXin LI /* 483c602fabSXin LI * Error codes. 493c602fabSXin LI */ 503c602fabSXin LI #define EUNDEF 0 /* not defined */ 513c602fabSXin LI #define ENOTFOUND 1 /* file not found */ 523c602fabSXin LI #define EACCESS 2 /* access violation */ 533c602fabSXin LI #define ENOSPACE 3 /* disk full or allocation exceeded */ 543c602fabSXin LI #define EBADOP 4 /* illegal TFTP operation */ 553c602fabSXin LI #define EBADID 5 /* unknown transfer ID */ 563c602fabSXin LI #define EEXISTS 6 /* file already exists */ 573c602fabSXin LI #define ENOUSER 7 /* no such user */ 583c602fabSXin LI 594edb46e9SPaul Traina 604edb46e9SPaul Traina /* op code to string mapping */ 613c602fabSXin LI static const struct tok op2str[] = { 624edb46e9SPaul Traina { RRQ, "RRQ" }, /* read request */ 634edb46e9SPaul Traina { WRQ, "WRQ" }, /* write request */ 644edb46e9SPaul Traina { DATA, "DATA" }, /* data packet */ 654edb46e9SPaul Traina { ACK, "ACK" }, /* acknowledgement */ 66a5779b6eSRui Paulo { TFTP_ERROR, "ERROR" }, /* error code */ 67b5bfcb5dSMax Laier { OACK, "OACK" }, /* option acknowledgement */ 684edb46e9SPaul Traina { 0, NULL } 694edb46e9SPaul Traina }; 704edb46e9SPaul Traina 714edb46e9SPaul Traina /* error code to string mapping */ 723c602fabSXin LI static const struct tok err2str[] = { 734edb46e9SPaul Traina { EUNDEF, "EUNDEF" }, /* not defined */ 744edb46e9SPaul Traina { ENOTFOUND, "ENOTFOUND" }, /* file not found */ 754edb46e9SPaul Traina { EACCESS, "EACCESS" }, /* access violation */ 764edb46e9SPaul Traina { ENOSPACE, "ENOSPACE" }, /* disk full or allocation exceeded */ 774edb46e9SPaul Traina { EBADOP, "EBADOP" }, /* illegal TFTP operation */ 784edb46e9SPaul Traina { EBADID, "EBADID" }, /* unknown transfer ID */ 794edb46e9SPaul Traina { EEXISTS, "EEXISTS" }, /* file already exists */ 804edb46e9SPaul Traina { ENOUSER, "ENOUSER" }, /* no such user */ 814edb46e9SPaul Traina { 0, NULL } 824edb46e9SPaul Traina }; 834edb46e9SPaul Traina 844edb46e9SPaul Traina /* 854edb46e9SPaul Traina * Print trivial file transfer program requests 864edb46e9SPaul Traina */ 874edb46e9SPaul Traina void 883c602fabSXin LI tftp_print(netdissect_options *ndo, 89*ee67461eSJoseph Mingrone const u_char *bp, u_int length) 904edb46e9SPaul Traina { 91*ee67461eSJoseph Mingrone const char *cp; 92*ee67461eSJoseph Mingrone u_int opcode; 933340d773SGleb Smirnoff u_int ui; 944edb46e9SPaul Traina 95*ee67461eSJoseph Mingrone ndo->ndo_protocol = "tftp"; 96*ee67461eSJoseph Mingrone 97*ee67461eSJoseph Mingrone /* Print protocol */ 98*ee67461eSJoseph Mingrone nd_print_protocol_caps(ndo); 994edb46e9SPaul Traina /* Print length */ 100*ee67461eSJoseph Mingrone ND_PRINT(", length %u", length); 1014edb46e9SPaul Traina 1024edb46e9SPaul Traina /* Print tftp request type */ 1033340d773SGleb Smirnoff if (length < 2) 1043340d773SGleb Smirnoff goto trunc; 105*ee67461eSJoseph Mingrone opcode = GET_BE_U_2(bp); 106*ee67461eSJoseph Mingrone cp = tok2str(op2str, "tftp-#%u", opcode); 107*ee67461eSJoseph Mingrone ND_PRINT(", %s", cp); 1084edb46e9SPaul Traina /* Bail if bogus opcode */ 1094edb46e9SPaul Traina if (*cp == 't') 1104edb46e9SPaul Traina return; 1110bff6a5aSEd Maste bp += 2; 1120bff6a5aSEd 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; 120*ee67461eSJoseph Mingrone ND_PRINT(" "); 1213340d773SGleb Smirnoff /* Print filename */ 122*ee67461eSJoseph Mingrone ND_PRINT("\""); 123*ee67461eSJoseph Mingrone ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend); 124*ee67461eSJoseph Mingrone ND_PRINT("\""); 1253340d773SGleb Smirnoff if (ui == 0) 1263340d773SGleb Smirnoff goto trunc; 1270bff6a5aSEd 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 */ 133*ee67461eSJoseph Mingrone ND_PRINT(" "); 134*ee67461eSJoseph Mingrone ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend); 1353340d773SGleb Smirnoff if (ui == 0) 1363340d773SGleb Smirnoff goto trunc; 1370bff6a5aSEd Maste bp += ui; 1383340d773SGleb Smirnoff length -= ui; 1393340d773SGleb Smirnoff 1403340d773SGleb Smirnoff /* Print options, if any */ 1413340d773SGleb Smirnoff while (length != 0) { 142*ee67461eSJoseph Mingrone if (GET_U_1(bp) != '\0') 143*ee67461eSJoseph Mingrone ND_PRINT(" "); 144*ee67461eSJoseph Mingrone ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend); 1453340d773SGleb Smirnoff if (ui == 0) 1463340d773SGleb Smirnoff goto trunc; 1470bff6a5aSEd Maste bp += ui; 1483340d773SGleb Smirnoff length -= ui; 1493340d773SGleb Smirnoff } 1503340d773SGleb Smirnoff break; 1513340d773SGleb Smirnoff 1523340d773SGleb Smirnoff case OACK: 1533340d773SGleb Smirnoff /* Print options */ 1543340d773SGleb Smirnoff while (length != 0) { 155*ee67461eSJoseph Mingrone if (GET_U_1(bp) != '\0') 156*ee67461eSJoseph Mingrone ND_PRINT(" "); 157*ee67461eSJoseph Mingrone ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend); 1583340d773SGleb Smirnoff if (ui == 0) 1593340d773SGleb Smirnoff goto trunc; 1600bff6a5aSEd Maste bp += ui; 1613340d773SGleb Smirnoff length -= ui; 1623340d773SGleb Smirnoff } 1634edb46e9SPaul Traina break; 1644edb46e9SPaul Traina 1654edb46e9SPaul Traina case ACK: 1664edb46e9SPaul Traina case DATA: 1673340d773SGleb Smirnoff if (length < 2) 1683340d773SGleb Smirnoff goto trunc; /* no block number */ 169*ee67461eSJoseph Mingrone ND_PRINT(" block %u", GET_BE_U_2(bp)); 1704edb46e9SPaul Traina break; 1714edb46e9SPaul Traina 172a5779b6eSRui Paulo case TFTP_ERROR: 1734edb46e9SPaul Traina /* Print error code string */ 1743340d773SGleb Smirnoff if (length < 2) 1753340d773SGleb Smirnoff goto trunc; /* no error code */ 176*ee67461eSJoseph Mingrone ND_PRINT(" %s", tok2str(err2str, "tftp-err-#%u \"", 177*ee67461eSJoseph Mingrone GET_BE_U_2(bp))); 1780bff6a5aSEd Maste bp += 2; 1793340d773SGleb Smirnoff length -= 2; 1804edb46e9SPaul Traina /* Print error message string */ 1813340d773SGleb Smirnoff if (length == 0) 1823340d773SGleb Smirnoff goto trunc; /* no error message */ 183*ee67461eSJoseph Mingrone ND_PRINT(" \""); 184*ee67461eSJoseph Mingrone ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend); 185*ee67461eSJoseph Mingrone ND_PRINT("\""); 1863340d773SGleb Smirnoff if (ui == 0) 1874edb46e9SPaul Traina goto trunc; 1884edb46e9SPaul Traina break; 1894edb46e9SPaul Traina 1904edb46e9SPaul Traina default: 1914edb46e9SPaul Traina /* We shouldn't get here */ 192*ee67461eSJoseph Mingrone ND_PRINT("(unknown #%u)", opcode); 1934edb46e9SPaul Traina break; 1944edb46e9SPaul Traina } 1954edb46e9SPaul Traina return; 1964edb46e9SPaul Traina trunc: 197*ee67461eSJoseph Mingrone nd_print_trunc(ndo); 1984edb46e9SPaul Traina } 199