1234285Sdim/* 2234285Sdim * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 3234285Sdim * The Regents of the University of California. All rights reserved. 4234285Sdim * 5234285Sdim * Redistribution and use in source and binary forms, with or without 6234285Sdim * modification, are permitted provided that: (1) source code distributions 7234285Sdim * retain the above copyright notice and this paragraph in its entirety, (2) 8234285Sdim * distributions including binary code include the above copyright notice and 9234285Sdim * this paragraph in its entirety in the documentation or other materials 10234285Sdim * provided with the distribution, and (3) all advertising materials mentioning 11234285Sdim * features or use of this software display the following acknowledgement: 12234285Sdim * ``This product includes software developed by the University of California, 13234285Sdim * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14234285Sdim * the University nor the names of its contributors may be used to endorse 15234285Sdim * or promote products derived from this software without specific prior 16234285Sdim * written permission. 17234285Sdim * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18234285Sdim * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19234285Sdim * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20234285Sdim * 21249423Sdim * Format and print trivial file transfer protocol packets. 22234285Sdim */ 23234285Sdim 24249423Sdim#ifndef lint 25234285Sdimstatic const char rcsid[] _U_ = 26234285Sdim "@(#) $Header: /tcpdump/master/tcpdump/print-tftp.c,v 1.39 2008-04-11 16:47:38 gianluca Exp $ (LBL)"; 27234285Sdim#endif 28234285Sdim 29234285Sdim#ifdef HAVE_CONFIG_H 30234285Sdim#include "config.h" 31234285Sdim#endif 32234285Sdim 33234285Sdim#include <tcpdump-stdinc.h> 34234285Sdim 35234285Sdim#ifdef SEGSIZE 36234285Sdim#undef SEGSIZE /* SINIX sucks */ 37234285Sdim#endif 38234285Sdim 39234285Sdim#include <stdio.h> 40234285Sdim#include <string.h> 41234285Sdim 42234285Sdim#include "interface.h" 43234285Sdim#include "addrtoname.h" 44234285Sdim#include "extract.h" 45234285Sdim#include "tftp.h" 46234285Sdim 47234285Sdim/* op code to string mapping */ 48234285Sdimstatic struct tok op2str[] = { 49234285Sdim { RRQ, "RRQ" }, /* read request */ 50234285Sdim { WRQ, "WRQ" }, /* write request */ 51234285Sdim { DATA, "DATA" }, /* data packet */ 52234285Sdim { ACK, "ACK" }, /* acknowledgement */ 53239462Sdim { TFTP_ERROR, "ERROR" }, /* error code */ 54239462Sdim { OACK, "OACK" }, /* option acknowledgement */ 55239462Sdim { 0, NULL } 56234285Sdim}; 57234285Sdim 58234285Sdim/* error code to string mapping */ 59234285Sdimstatic struct tok err2str[] = { 60239462Sdim { EUNDEF, "EUNDEF" }, /* not defined */ 61234285Sdim { ENOTFOUND, "ENOTFOUND" }, /* file not found */ 62234285Sdim { EACCESS, "EACCESS" }, /* access violation */ 63234285Sdim { ENOSPACE, "ENOSPACE" }, /* disk full or allocation exceeded */ 64234285Sdim { EBADOP, "EBADOP" }, /* illegal TFTP operation */ 65234285Sdim { EBADID, "EBADID" }, /* unknown transfer ID */ 66234285Sdim { EEXISTS, "EEXISTS" }, /* file already exists */ 67234285Sdim { ENOUSER, "ENOUSER" }, /* no such user */ 68234285Sdim { 0, NULL } 69234285Sdim}; 70239462Sdim 71239462Sdim/* 72239462Sdim * Print trivial file transfer program requests 73239462Sdim */ 74239462Sdimvoid 75234285Sdimtftp_print(register const u_char *bp, u_int length) 76234285Sdim{ 77234285Sdim register const struct tftphdr *tp; 78234285Sdim register const char *cp; 79234285Sdim register const u_char *p; 80234285Sdim register int opcode, i; 81234285Sdim static char tstr[] = " [|tftp]"; 82234285Sdim 83234285Sdim tp = (const struct tftphdr *)bp; 84234285Sdim 85234285Sdim /* Print length */ 86234285Sdim printf(" %d", length); 87234285Sdim 88234285Sdim /* Print tftp request type */ 89234285Sdim TCHECK(tp->th_opcode); 90234285Sdim opcode = EXTRACT_16BITS(&tp->th_opcode); 91234285Sdim cp = tok2str(op2str, "tftp-#%d", opcode); 92234285Sdim printf(" %s", cp); 93234285Sdim /* Bail if bogus opcode */ 94234285Sdim if (*cp == 't') 95239462Sdim return; 96234285Sdim 97234285Sdim switch (opcode) { 98234285Sdim 99234285Sdim case RRQ: 100234285Sdim case WRQ: 101234285Sdim case OACK: 102239462Sdim p = (u_char *)tp->th_stuff; 103234285Sdim putchar(' '); 104234285Sdim /* Print filename or first option */ 105234285Sdim if (opcode != OACK) 106234285Sdim putchar('"'); 107234285Sdim i = fn_print(p, snapend); 108234285Sdim if (opcode != OACK) 109234285Sdim putchar('"'); 110234285Sdim 111234285Sdim /* Print the mode (RRQ and WRQ only) and any options */ 112234285Sdim while ((p = (const u_char *)strchr((const char *)p, '\0')) != NULL) { 113234285Sdim if (length <= (u_int)(p - (const u_char *)&tp->th_block)) 114234285Sdim break; 115234285Sdim p++; 116234285Sdim if (*p != '\0') { 117234285Sdim putchar(' '); 118234285Sdim fn_print(p, snapend); 119234285Sdim } 120234285Sdim } 121234285Sdim 122234285Sdim if (i) 123234285Sdim goto trunc; 124234285Sdim break; 125234285Sdim 126234285Sdim case ACK: 127239462Sdim case DATA: 128234285Sdim TCHECK(tp->th_block); 129234285Sdim printf(" block %d", EXTRACT_16BITS(&tp->th_block)); 130234285Sdim break; 131234285Sdim 132234285Sdim case TFTP_ERROR: 133234285Sdim /* Print error code string */ 134234285Sdim TCHECK(tp->th_code); 135234285Sdim printf(" %s \"", tok2str(err2str, "tftp-err-#%d \"", 136234285Sdim EXTRACT_16BITS(&tp->th_code))); 137234285Sdim /* Print error message string */ 138234285Sdim i = fn_print((const u_char *)tp->th_data, snapend); 139234285Sdim putchar('"'); 140234285Sdim if (i) 141234285Sdim goto trunc; 142234285Sdim break; 143234285Sdim 144234285Sdim default: 145234285Sdim /* We shouldn't get here */ 146 printf("(unknown #%d)", opcode); 147 break; 148 } 149 return; 150trunc: 151 fputs(tstr, stdout); 152 return; 153} 154