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 #include <sys/cdefs.h> 25 #ifndef lint 26 __RCSID("$NetBSD: print-tftp.c,v 1.5 2014/11/20 03:05:03 christos Exp $"); 27 #endif 28 29 #define NETDISSECT_REWORKED 30 #ifdef HAVE_CONFIG_H 31 #include "config.h" 32 #endif 33 34 #include <tcpdump-stdinc.h> 35 36 #include <string.h> 37 38 #include "interface.h" 39 #include "extract.h" 40 41 /* 42 * Trivial File Transfer Protocol (IEN-133) 43 */ 44 45 /* 46 * Packet types. 47 */ 48 #define RRQ 01 /* read request */ 49 #define WRQ 02 /* write request */ 50 #define DATA 03 /* data packet */ 51 #define ACK 04 /* acknowledgement */ 52 #define TFTP_ERROR 05 /* error code */ 53 #define OACK 06 /* option acknowledgement */ 54 55 struct tftphdr { 56 unsigned short th_opcode; /* packet type */ 57 union { 58 unsigned short tu_block; /* block # */ 59 unsigned short tu_code; /* error code */ 60 char tu_stuff[1]; /* request packet stuff */ 61 } th_u; 62 char th_data[1]; /* data or error string */ 63 }; 64 65 #define th_block th_u.tu_block 66 #define th_code th_u.tu_code 67 #define th_stuff th_u.tu_stuff 68 #define th_msg th_data 69 70 /* 71 * Error codes. 72 */ 73 #define EUNDEF 0 /* not defined */ 74 #define ENOTFOUND 1 /* file not found */ 75 #define EACCESS 2 /* access violation */ 76 #define ENOSPACE 3 /* disk full or allocation exceeded */ 77 #define EBADOP 4 /* illegal TFTP operation */ 78 #define EBADID 5 /* unknown transfer ID */ 79 #define EEXISTS 6 /* file already exists */ 80 #define ENOUSER 7 /* no such user */ 81 82 static const char tstr[] = " [|tftp]"; 83 84 /* op code to string mapping */ 85 static const struct tok op2str[] = { 86 { RRQ, "RRQ" }, /* read request */ 87 { WRQ, "WRQ" }, /* write request */ 88 { DATA, "DATA" }, /* data packet */ 89 { ACK, "ACK" }, /* acknowledgement */ 90 { TFTP_ERROR, "ERROR" }, /* error code */ 91 { OACK, "OACK" }, /* option acknowledgement */ 92 { 0, NULL } 93 }; 94 95 /* error code to string mapping */ 96 static const struct tok err2str[] = { 97 { EUNDEF, "EUNDEF" }, /* not defined */ 98 { ENOTFOUND, "ENOTFOUND" }, /* file not found */ 99 { EACCESS, "EACCESS" }, /* access violation */ 100 { ENOSPACE, "ENOSPACE" }, /* disk full or allocation exceeded */ 101 { EBADOP, "EBADOP" }, /* illegal TFTP operation */ 102 { EBADID, "EBADID" }, /* unknown transfer ID */ 103 { EEXISTS, "EEXISTS" }, /* file already exists */ 104 { ENOUSER, "ENOUSER" }, /* no such user */ 105 { 0, NULL } 106 }; 107 108 /* 109 * Print trivial file transfer program requests 110 */ 111 void 112 tftp_print(netdissect_options *ndo, 113 register const u_char *bp, u_int length) 114 { 115 register const struct tftphdr *tp; 116 register const char *cp; 117 register const u_char *p; 118 register int opcode, i; 119 120 tp = (const struct tftphdr *)bp; 121 122 /* Print length */ 123 ND_PRINT((ndo, " %d", length)); 124 125 /* Print tftp request type */ 126 ND_TCHECK(tp->th_opcode); 127 opcode = EXTRACT_16BITS(&tp->th_opcode); 128 cp = tok2str(op2str, "tftp-#%d", opcode); 129 ND_PRINT((ndo, " %s", cp)); 130 /* Bail if bogus opcode */ 131 if (*cp == 't') 132 return; 133 134 switch (opcode) { 135 136 case RRQ: 137 case WRQ: 138 case OACK: 139 p = (u_char *)tp->th_stuff; 140 ND_PRINT((ndo, " ")); 141 /* Print filename or first option */ 142 if (opcode != OACK) 143 ND_PRINT((ndo, "\"")); 144 i = fn_print(ndo, p, ndo->ndo_snapend); 145 if (opcode != OACK) 146 ND_PRINT((ndo, "\"")); 147 148 /* Print the mode (RRQ and WRQ only) and any options */ 149 while ((p = (const u_char *)strchr((const char *)p, '\0')) != NULL) { 150 if (length <= (u_int)(p - (const u_char *)&tp->th_block)) 151 break; 152 p++; 153 if (*p != '\0') { 154 ND_PRINT((ndo, " ")); 155 fn_print(ndo, p, ndo->ndo_snapend); 156 } 157 } 158 159 if (i) 160 goto trunc; 161 break; 162 163 case ACK: 164 case DATA: 165 ND_TCHECK(tp->th_block); 166 ND_PRINT((ndo, " block %d", EXTRACT_16BITS(&tp->th_block))); 167 break; 168 169 case TFTP_ERROR: 170 /* Print error code string */ 171 ND_TCHECK(tp->th_code); 172 ND_PRINT((ndo, " %s \"", tok2str(err2str, "tftp-err-#%d \"", 173 EXTRACT_16BITS(&tp->th_code)))); 174 /* Print error message string */ 175 i = fn_print(ndo, (const u_char *)tp->th_data, ndo->ndo_snapend); 176 ND_PRINT((ndo, "\"")); 177 if (i) 178 goto trunc; 179 break; 180 181 default: 182 /* We shouldn't get here */ 183 ND_PRINT((ndo, "(unknown #%d)", opcode)); 184 break; 185 } 186 return; 187 trunc: 188 ND_PRINT((ndo, "%s", tstr)); 189 return; 190 } 191