139213Sgibbs/* 239213Sgibbs * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 371752Sken * The Regents of the University of California. All rights reserved. 439213Sgibbs * 539213Sgibbs * Redistribution and use in source and binary forms, with or without 639213Sgibbs * modification, are permitted provided that: (1) source code distributions 739213Sgibbs * retain the above copyright notice and this paragraph in its entirety, (2) 839213Sgibbs * distributions including binary code include the above copyright notice and 939213Sgibbs * this paragraph in its entirety in the documentation or other materials 1039213Sgibbs * provided with the distribution, and (3) all advertising materials mentioning 1139213Sgibbs * features or use of this software display the following acknowledgement: 1239213Sgibbs * ``This product includes software developed by the University of California, 1339213Sgibbs * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1439213Sgibbs * the University nor the names of its contributors may be used to endorse 1539213Sgibbs * or promote products derived from this software without specific prior 1639213Sgibbs * written permission. 1739213Sgibbs * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1839213Sgibbs * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1939213Sgibbs * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2039213Sgibbs */ 2139213Sgibbs 2239213Sgibbs/* \summary: Trivial File Transfer Protocol (TFTP) printer */ 2339213Sgibbs 2439213Sgibbs#include <sys/cdefs.h> 2539213Sgibbs#ifndef lint 2639213Sgibbs__RCSID("$NetBSD: print-tftp.c,v 1.9 2023/08/17 20:19:40 christos Exp $"); 2750477Speter#endif 2839213Sgibbs 2939213Sgibbs#ifdef HAVE_CONFIG_H 3039213Sgibbs#include <config.h> 3139213Sgibbs#endif 3239213Sgibbs 3339213Sgibbs#include "netdissect-stdinc.h" 3439213Sgibbs 3539213Sgibbs#include "netdissect.h" 3639213Sgibbs#include "extract.h" 3739213Sgibbs 3839213Sgibbs/* 3939213Sgibbs * Trivial File Transfer Protocol (IEN-133) 4039213Sgibbs */ 4139213Sgibbs 4239213Sgibbs/* 4339213Sgibbs * Packet types. 4439213Sgibbs */ 4539213Sgibbs#define RRQ 01 /* read request */ 4639213Sgibbs#define WRQ 02 /* write request */ 4739213Sgibbs#define DATA 03 /* data packet */ 4839213Sgibbs#define ACK 04 /* acknowledgement */ 4940020Sken#define TFTP_ERROR 05 /* error code */ 5039213Sgibbs#define OACK 06 /* option acknowledgement */ 5139213Sgibbs 5239213Sgibbs/* 5339213Sgibbs * Error codes. 5460041Sphk */ 5551836Sphk#define EUNDEF 0 /* not defined */ 5651836Sphk#define ENOTFOUND 1 /* file not found */ 5739213Sgibbs#define EACCESS 2 /* access violation */ 5839213Sgibbs#define ENOSPACE 3 /* disk full or allocation exceeded */ 59105421Snjl#define EBADOP 4 /* illegal TFTP operation */ 6060422Sken#define EBADID 5 /* unknown transfer ID */ 6139213Sgibbs#define EEXISTS 6 /* file already exists */ 6239213Sgibbs#define ENOUSER 7 /* no such user */ 6339213Sgibbs 6439213Sgibbs 6539213Sgibbs/* op code to string mapping */ 6639213Sgibbsstatic const struct tok op2str[] = { 6739213Sgibbs { RRQ, "RRQ" }, /* read request */ 6839213Sgibbs { WRQ, "WRQ" }, /* write request */ 6939213Sgibbs { DATA, "DATA" }, /* data packet */ 7039213Sgibbs { ACK, "ACK" }, /* acknowledgement */ 7139213Sgibbs { TFTP_ERROR, "ERROR" }, /* error code */ 7239213Sgibbs { OACK, "OACK" }, /* option acknowledgement */ 7339213Sgibbs { 0, NULL } 7439213Sgibbs}; 7539213Sgibbs 7639213Sgibbs/* error code to string mapping */ 7739213Sgibbsstatic const struct tok err2str[] = { 7839213Sgibbs { EUNDEF, "EUNDEF" }, /* not defined */ 7939213Sgibbs { ENOTFOUND, "ENOTFOUND" }, /* file not found */ 8039213Sgibbs { EACCESS, "EACCESS" }, /* access violation */ 8139213Sgibbs { ENOSPACE, "ENOSPACE" }, /* disk full or allocation exceeded */ 8239213Sgibbs { EBADOP, "EBADOP" }, /* illegal TFTP operation */ 8339213Sgibbs { EBADID, "EBADID" }, /* unknown transfer ID */ 8439213Sgibbs { EEXISTS, "EEXISTS" }, /* file already exists */ 8539213Sgibbs { ENOUSER, "ENOUSER" }, /* no such user */ 8639213Sgibbs { 0, NULL } 8739213Sgibbs}; 8839213Sgibbs 8939213Sgibbs/* 9039213Sgibbs * Print trivial file transfer program requests 9139213Sgibbs */ 9239213Sgibbsvoid 9339213Sgibbstftp_print(netdissect_options *ndo, 9439213Sgibbs const u_char *bp, u_int length) 9539213Sgibbs{ 9639213Sgibbs const char *cp; 9739213Sgibbs u_int opcode; 9839213Sgibbs u_int ui; 9939213Sgibbs 10039213Sgibbs ndo->ndo_protocol = "tftp"; 10139213Sgibbs 10239213Sgibbs /* Print protocol */ 10339213Sgibbs nd_print_protocol_caps(ndo); 10439213Sgibbs /* Print length */ 10539213Sgibbs ND_PRINT(", length %u", length); 10639213Sgibbs 10739213Sgibbs /* Print tftp request type */ 10839213Sgibbs if (length < 2) 10939213Sgibbs goto trunc; 11039213Sgibbs opcode = GET_BE_U_2(bp); 11139213Sgibbs cp = tok2str(op2str, "tftp-#%u", opcode); 11239213Sgibbs ND_PRINT(", %s", cp); 11339213Sgibbs /* Bail if bogus opcode */ 11439213Sgibbs if (*cp == 't') 11539213Sgibbs return; 11639213Sgibbs bp += 2; 11739213Sgibbs length -= 2; 11839213Sgibbs 11939213Sgibbs switch (opcode) { 12039213Sgibbs 12139213Sgibbs case RRQ: 12239213Sgibbs case WRQ: 12339213Sgibbs if (length == 0) 12439213Sgibbs goto trunc; 12539213Sgibbs ND_PRINT(" "); 12639213Sgibbs /* Print filename */ 12746581Sken ND_PRINT("\""); 12859249Sphk ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend); 12960938Sjake ND_PRINT("\""); 13039213Sgibbs if (ui == 0) 13139213Sgibbs goto trunc; 13239213Sgibbs bp += ui; 13339213Sgibbs length -= ui; 13460938Sjake 13539213Sgibbs /* Print the mode - RRQ and WRQ only */ 13639213Sgibbs if (length == 0) 13739213Sgibbs goto trunc; /* no mode */ 138104456Sphk ND_PRINT(" "); 139104880Sphk ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend); 14039213Sgibbs if (ui == 0) 14139213Sgibbs goto trunc; 14239213Sgibbs bp += ui; 14339213Sgibbs length -= ui; 14439213Sgibbs 14539213Sgibbs /* Print options, if any */ 14639213Sgibbs while (length != 0) { 14739213Sgibbs if (GET_U_1(bp) != '\0') 14839213Sgibbs ND_PRINT(" "); 14939213Sgibbs ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend); 15039213Sgibbs if (ui == 0) 15139213Sgibbs goto trunc; 15239213Sgibbs bp += ui; 15339213Sgibbs length -= ui; 15439213Sgibbs } 15539213Sgibbs break; 15639213Sgibbs 15739213Sgibbs case OACK: 15839213Sgibbs /* Print options */ 15939213Sgibbs while (length != 0) { 16039213Sgibbs if (GET_U_1(bp) != '\0') 16139213Sgibbs ND_PRINT(" "); 16254451Sken ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend); 16339213Sgibbs if (ui == 0) 16440262Sken goto trunc; 16540262Sken bp += ui; 16667752Sken length -= ui; 16767752Sken } 16867752Sken break; 16967752Sken 17040262Sken case ACK: 17140262Sken case DATA: 17239213Sgibbs if (length < 2) 17339213Sgibbs goto trunc; /* no block number */ 17439213Sgibbs ND_PRINT(" block %u", GET_BE_U_2(bp)); 17539213Sgibbs break; 17639213Sgibbs 17739213Sgibbs case TFTP_ERROR: 17839213Sgibbs /* Print error code string */ 17939213Sgibbs if (length < 2) 18039213Sgibbs goto trunc; /* no error code */ 18139213Sgibbs ND_PRINT(" %s", tok2str(err2str, "tftp-err-#%u \"", 18239213Sgibbs GET_BE_U_2(bp))); 18339213Sgibbs bp += 2; 18439213Sgibbs length -= 2; 18539213Sgibbs /* Print error message string */ 18639213Sgibbs if (length == 0) 18739213Sgibbs goto trunc; /* no error message */ 18839213Sgibbs ND_PRINT(" \""); 18939213Sgibbs ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend); 19040603Sken ND_PRINT("\""); 19139213Sgibbs if (ui == 0) 19239213Sgibbs goto trunc; 19339213Sgibbs break; 19439213Sgibbs 19539213Sgibbs default: 19639213Sgibbs /* We shouldn't get here */ 19739213Sgibbs ND_PRINT("(unknown #%u)", opcode); 19839213Sgibbs break; 19939213Sgibbs } 20039213Sgibbs return; 20139213Sgibbstrunc: 20242531Seivind nd_print_trunc(ndo); 20339213Sgibbs} 20439213Sgibbs