1 /* 2 * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 * 21 * Format and print trivial file transfer protocol packets. 22 */ 23 24 #ifndef lint 25 static const char rcsid[] _U_ = 26 "@(#) $Header: /tcpdump/master/tcpdump/print-tftp.c,v 1.37 2003/11/16 09:36:40 guy Exp $ (LBL)"; 27 #endif 28 29 #ifdef HAVE_CONFIG_H 30 #include "config.h" 31 #endif 32 33 #include <tcpdump-stdinc.h> 34 35 #ifdef SEGSIZE 36 #undef SEGSIZE /* SINIX sucks */ 37 #endif 38 #include <arpa/tftp.h> 39 40 #include <stdio.h> 41 #include <string.h> 42 43 #include "interface.h" 44 #include "addrtoname.h" 45 #include "extract.h" 46 47 /* op code to string mapping */ 48 static struct tok op2str[] = { 49 { RRQ, "RRQ" }, /* read request */ 50 { WRQ, "WRQ" }, /* write request */ 51 { DATA, "DATA" }, /* data packet */ 52 { ACK, "ACK" }, /* acknowledgement */ 53 { ERROR, "ERROR" }, /* error code */ 54 { 0, NULL } 55 }; 56 57 /* error code to string mapping */ 58 static struct tok err2str[] = { 59 { EUNDEF, "EUNDEF" }, /* not defined */ 60 { ENOTFOUND, "ENOTFOUND" }, /* file not found */ 61 { EACCESS, "EACCESS" }, /* access violation */ 62 { ENOSPACE, "ENOSPACE" }, /* disk full or allocation exceeded */ 63 { EBADOP, "EBADOP" }, /* illegal TFTP operation */ 64 { EBADID, "EBADID" }, /* unknown transfer ID */ 65 { EEXISTS, "EEXISTS" }, /* file already exists */ 66 { ENOUSER, "ENOUSER" }, /* no such user */ 67 { 0, NULL } 68 }; 69 70 /* 71 * Print trivial file transfer program requests 72 */ 73 void 74 tftp_print(register const u_char *bp, u_int length) 75 { 76 register const struct tftphdr *tp; 77 register const char *cp; 78 register const u_char *p; 79 register int opcode, i; 80 static char tstr[] = " [|tftp]"; 81 82 tp = (const struct tftphdr *)bp; 83 84 /* Print length */ 85 printf(" %d", length); 86 87 /* Print tftp request type */ 88 TCHECK(tp->th_opcode); 89 opcode = EXTRACT_16BITS(&tp->th_opcode); 90 cp = tok2str(op2str, "tftp-#%d", opcode); 91 printf(" %s", cp); 92 /* Bail if bogus opcode */ 93 if (*cp == 't') 94 return; 95 96 switch (opcode) { 97 98 case RRQ: 99 case WRQ: 100 /* 101 * XXX Not all arpa/tftp.h's specify th_stuff as any 102 * array; use address of th_block instead 103 */ 104 #ifdef notdef 105 p = (u_char *)tp->th_stuff; 106 #else 107 p = (u_char *)&tp->th_block; 108 #endif 109 fputs(" \"", stdout); 110 i = fn_print(p, snapend); 111 putchar('"'); 112 113 /* Print the mode and any options */ 114 while ((p = (const u_char *)strchr((const char *)p, '\0')) != NULL) { 115 if (length <= (u_int)(p - (const u_char *)&tp->th_block)) 116 break; 117 p++; 118 if (*p != '\0') { 119 putchar(' '); 120 fn_print(p, snapend); 121 } 122 } 123 124 if (i) 125 goto trunc; 126 break; 127 128 case ACK: 129 case DATA: 130 TCHECK(tp->th_block); 131 printf(" block %d", EXTRACT_16BITS(&tp->th_block)); 132 break; 133 134 case ERROR: 135 /* Print error code string */ 136 TCHECK(tp->th_code); 137 printf(" %s ", tok2str(err2str, "tftp-err-#%d \"", 138 EXTRACT_16BITS(&tp->th_code))); 139 /* Print error message string */ 140 i = fn_print((const u_char *)tp->th_data, snapend); 141 putchar('"'); 142 if (i) 143 goto trunc; 144 break; 145 146 default: 147 /* We shouldn't get here */ 148 printf("(unknown #%d)", opcode); 149 break; 150 } 151 return; 152 trunc: 153 fputs(tstr, stdout); 154 return; 155 } 156