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 22*3340d773SGleb Smirnoff /* \summary: Trivial File Transfer Protocol (TFTP) printer */ 23*3340d773SGleb Smirnoff 24b0453382SBill Fenner #ifdef HAVE_CONFIG_H 25b0453382SBill Fenner #include "config.h" 264edb46e9SPaul Traina #endif 274edb46e9SPaul Traina 28*3340d773SGleb Smirnoff #include <netdissect-stdinc.h> 294edb46e9SPaul Traina 304edb46e9SPaul Traina #include <string.h> 314edb46e9SPaul Traina 32*3340d773SGleb 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 struct tftphdr { 503c602fabSXin LI unsigned short th_opcode; /* packet type */ 513c602fabSXin LI union { 523c602fabSXin LI unsigned short tu_block; /* block # */ 533c602fabSXin LI unsigned short tu_code; /* error code */ 543c602fabSXin LI char tu_stuff[1]; /* request packet stuff */ 553c602fabSXin LI } th_u; 563c602fabSXin LI char th_data[1]; /* data or error string */ 573c602fabSXin LI }; 583c602fabSXin LI 593c602fabSXin LI #define th_block th_u.tu_block 603c602fabSXin LI #define th_code th_u.tu_code 613c602fabSXin LI #define th_stuff th_u.tu_stuff 623c602fabSXin LI #define th_msg th_data 633c602fabSXin LI 643c602fabSXin LI /* 653c602fabSXin LI * Error codes. 663c602fabSXin LI */ 673c602fabSXin LI #define EUNDEF 0 /* not defined */ 683c602fabSXin LI #define ENOTFOUND 1 /* file not found */ 693c602fabSXin LI #define EACCESS 2 /* access violation */ 703c602fabSXin LI #define ENOSPACE 3 /* disk full or allocation exceeded */ 713c602fabSXin LI #define EBADOP 4 /* illegal TFTP operation */ 723c602fabSXin LI #define EBADID 5 /* unknown transfer ID */ 733c602fabSXin LI #define EEXISTS 6 /* file already exists */ 743c602fabSXin LI #define ENOUSER 7 /* no such user */ 753c602fabSXin LI 763c602fabSXin LI static const char tstr[] = " [|tftp]"; 774edb46e9SPaul Traina 784edb46e9SPaul Traina /* op code to string mapping */ 793c602fabSXin LI static const struct tok op2str[] = { 804edb46e9SPaul Traina { RRQ, "RRQ" }, /* read request */ 814edb46e9SPaul Traina { WRQ, "WRQ" }, /* write request */ 824edb46e9SPaul Traina { DATA, "DATA" }, /* data packet */ 834edb46e9SPaul Traina { ACK, "ACK" }, /* acknowledgement */ 84a5779b6eSRui Paulo { TFTP_ERROR, "ERROR" }, /* error code */ 85b5bfcb5dSMax Laier { OACK, "OACK" }, /* option acknowledgement */ 864edb46e9SPaul Traina { 0, NULL } 874edb46e9SPaul Traina }; 884edb46e9SPaul Traina 894edb46e9SPaul Traina /* error code to string mapping */ 903c602fabSXin LI static const struct tok err2str[] = { 914edb46e9SPaul Traina { EUNDEF, "EUNDEF" }, /* not defined */ 924edb46e9SPaul Traina { ENOTFOUND, "ENOTFOUND" }, /* file not found */ 934edb46e9SPaul Traina { EACCESS, "EACCESS" }, /* access violation */ 944edb46e9SPaul Traina { ENOSPACE, "ENOSPACE" }, /* disk full or allocation exceeded */ 954edb46e9SPaul Traina { EBADOP, "EBADOP" }, /* illegal TFTP operation */ 964edb46e9SPaul Traina { EBADID, "EBADID" }, /* unknown transfer ID */ 974edb46e9SPaul Traina { EEXISTS, "EEXISTS" }, /* file already exists */ 984edb46e9SPaul Traina { ENOUSER, "ENOUSER" }, /* no such user */ 994edb46e9SPaul Traina { 0, NULL } 1004edb46e9SPaul Traina }; 1014edb46e9SPaul Traina 1024edb46e9SPaul Traina /* 1034edb46e9SPaul Traina * Print trivial file transfer program requests 1044edb46e9SPaul Traina */ 1054edb46e9SPaul Traina void 1063c602fabSXin LI tftp_print(netdissect_options *ndo, 1073c602fabSXin LI register const u_char *bp, u_int length) 1084edb46e9SPaul Traina { 1094edb46e9SPaul Traina register const struct tftphdr *tp; 1104edb46e9SPaul Traina register const char *cp; 1114edb46e9SPaul Traina register const u_char *p; 112*3340d773SGleb Smirnoff register int opcode; 113*3340d773SGleb Smirnoff u_int ui; 1144edb46e9SPaul Traina 1154edb46e9SPaul Traina tp = (const struct tftphdr *)bp; 1164edb46e9SPaul Traina 1174edb46e9SPaul Traina /* Print length */ 1183c602fabSXin LI ND_PRINT((ndo, " %d", length)); 1194edb46e9SPaul Traina 1204edb46e9SPaul Traina /* Print tftp request type */ 121*3340d773SGleb Smirnoff if (length < 2) 122*3340d773SGleb Smirnoff goto trunc; 1233c602fabSXin LI ND_TCHECK(tp->th_opcode); 1245b0fe478SBruce M Simpson opcode = EXTRACT_16BITS(&tp->th_opcode); 1254edb46e9SPaul Traina cp = tok2str(op2str, "tftp-#%d", opcode); 126*3340d773SGleb Smirnoff length -= 2; 1273c602fabSXin LI ND_PRINT((ndo, " %s", cp)); 1284edb46e9SPaul Traina /* Bail if bogus opcode */ 1294edb46e9SPaul Traina if (*cp == 't') 1304edb46e9SPaul Traina return; 1314edb46e9SPaul Traina 1324edb46e9SPaul Traina switch (opcode) { 1334edb46e9SPaul Traina 1344edb46e9SPaul Traina case RRQ: 1354edb46e9SPaul Traina case WRQ: 136*3340d773SGleb Smirnoff p = (const u_char *)tp->th_stuff; 137*3340d773SGleb Smirnoff if (length == 0) 1384edb46e9SPaul Traina goto trunc; 139*3340d773SGleb Smirnoff ND_PRINT((ndo, " ")); 140*3340d773SGleb Smirnoff /* Print filename */ 141*3340d773SGleb Smirnoff ND_PRINT((ndo, "\"")); 142*3340d773SGleb Smirnoff ui = fn_printztn(ndo, p, length, ndo->ndo_snapend); 143*3340d773SGleb Smirnoff ND_PRINT((ndo, "\"")); 144*3340d773SGleb Smirnoff if (ui == 0) 145*3340d773SGleb Smirnoff goto trunc; 146*3340d773SGleb Smirnoff p += ui; 147*3340d773SGleb Smirnoff length -= ui; 148*3340d773SGleb Smirnoff 149*3340d773SGleb Smirnoff /* Print the mode - RRQ and WRQ only */ 150*3340d773SGleb Smirnoff if (length == 0) 151*3340d773SGleb Smirnoff goto trunc; /* no mode */ 152*3340d773SGleb Smirnoff ND_PRINT((ndo, " ")); 153*3340d773SGleb Smirnoff ui = fn_printztn(ndo, p, length, ndo->ndo_snapend); 154*3340d773SGleb Smirnoff if (ui == 0) 155*3340d773SGleb Smirnoff goto trunc; 156*3340d773SGleb Smirnoff p += ui; 157*3340d773SGleb Smirnoff length -= ui; 158*3340d773SGleb Smirnoff 159*3340d773SGleb Smirnoff /* Print options, if any */ 160*3340d773SGleb Smirnoff while (length != 0) { 161*3340d773SGleb Smirnoff ND_TCHECK(*p); 162*3340d773SGleb Smirnoff if (*p != '\0') 163*3340d773SGleb Smirnoff ND_PRINT((ndo, " ")); 164*3340d773SGleb Smirnoff ui = fn_printztn(ndo, p, length, ndo->ndo_snapend); 165*3340d773SGleb Smirnoff if (ui == 0) 166*3340d773SGleb Smirnoff goto trunc; 167*3340d773SGleb Smirnoff p += ui; 168*3340d773SGleb Smirnoff length -= ui; 169*3340d773SGleb Smirnoff } 170*3340d773SGleb Smirnoff break; 171*3340d773SGleb Smirnoff 172*3340d773SGleb Smirnoff case OACK: 173*3340d773SGleb Smirnoff p = (const u_char *)tp->th_stuff; 174*3340d773SGleb Smirnoff /* Print options */ 175*3340d773SGleb Smirnoff while (length != 0) { 176*3340d773SGleb Smirnoff ND_TCHECK(*p); 177*3340d773SGleb Smirnoff if (*p != '\0') 178*3340d773SGleb Smirnoff ND_PRINT((ndo, " ")); 179*3340d773SGleb Smirnoff ui = fn_printztn(ndo, p, length, ndo->ndo_snapend); 180*3340d773SGleb Smirnoff if (ui == 0) 181*3340d773SGleb Smirnoff goto trunc; 182*3340d773SGleb Smirnoff p += ui; 183*3340d773SGleb Smirnoff length -= ui; 184*3340d773SGleb Smirnoff } 1854edb46e9SPaul Traina break; 1864edb46e9SPaul Traina 1874edb46e9SPaul Traina case ACK: 1884edb46e9SPaul Traina case DATA: 189*3340d773SGleb Smirnoff if (length < 2) 190*3340d773SGleb Smirnoff goto trunc; /* no block number */ 1913c602fabSXin LI ND_TCHECK(tp->th_block); 1923c602fabSXin LI ND_PRINT((ndo, " block %d", EXTRACT_16BITS(&tp->th_block))); 1934edb46e9SPaul Traina break; 1944edb46e9SPaul Traina 195a5779b6eSRui Paulo case TFTP_ERROR: 1964edb46e9SPaul Traina /* Print error code string */ 197*3340d773SGleb Smirnoff if (length < 2) 198*3340d773SGleb Smirnoff goto trunc; /* no error code */ 1993c602fabSXin LI ND_TCHECK(tp->th_code); 200*3340d773SGleb Smirnoff ND_PRINT((ndo, " %s", tok2str(err2str, "tftp-err-#%d \"", 2013c602fabSXin LI EXTRACT_16BITS(&tp->th_code)))); 202*3340d773SGleb Smirnoff length -= 2; 2034edb46e9SPaul Traina /* Print error message string */ 204*3340d773SGleb Smirnoff if (length == 0) 205*3340d773SGleb Smirnoff goto trunc; /* no error message */ 2063c602fabSXin LI ND_PRINT((ndo, " \"")); 207*3340d773SGleb Smirnoff ui = fn_printztn(ndo, (const u_char *)tp->th_data, length, ndo->ndo_snapend); 208*3340d773SGleb Smirnoff ND_PRINT((ndo, "\"")); 209*3340d773SGleb Smirnoff if (ui == 0) 2104edb46e9SPaul Traina goto trunc; 2114edb46e9SPaul Traina break; 2124edb46e9SPaul Traina 2134edb46e9SPaul Traina default: 2144edb46e9SPaul Traina /* We shouldn't get here */ 2153c602fabSXin LI ND_PRINT((ndo, "(unknown #%d)", opcode)); 2164edb46e9SPaul Traina break; 2174edb46e9SPaul Traina } 2184edb46e9SPaul Traina return; 2194edb46e9SPaul Traina trunc: 2203c602fabSXin LI ND_PRINT((ndo, "%s", tstr)); 2214edb46e9SPaul Traina return; 2224edb46e9SPaul Traina } 223