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