10f74e101Schristos /* 20f74e101Schristos * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 30f74e101Schristos * The Regents of the University of California. All rights reserved. 40f74e101Schristos * 50f74e101Schristos * Redistribution and use in source and binary forms, with or without 60f74e101Schristos * modification, are permitted provided that: (1) source code distributions 70f74e101Schristos * retain the above copyright notice and this paragraph in its entirety, (2) 80f74e101Schristos * distributions including binary code include the above copyright notice and 90f74e101Schristos * this paragraph in its entirety in the documentation or other materials 100f74e101Schristos * provided with the distribution, and (3) all advertising materials mentioning 110f74e101Schristos * features or use of this software display the following acknowledgement: 120f74e101Schristos * ``This product includes software developed by the University of California, 130f74e101Schristos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 140f74e101Schristos * the University nor the names of its contributors may be used to endorse 150f74e101Schristos * or promote products derived from this software without specific prior 160f74e101Schristos * written permission. 170f74e101Schristos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 180f74e101Schristos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 190f74e101Schristos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 200f74e101Schristos */ 210f74e101Schristos 22dc860a36Sspz /* \summary: Trivial File Transfer Protocol (TFTP) printer */ 23dc860a36Sspz 2411b3aaa1Schristos #include <sys/cdefs.h> 250f74e101Schristos #ifndef lint 26*26ba0b50Schristos __RCSID("$NetBSD: print-tftp.c,v 1.10 2024/09/02 16:15:33 christos Exp $"); 270f74e101Schristos #endif 280f74e101Schristos 29c74ad251Schristos #include <config.h> 300f74e101Schristos 31c74ad251Schristos #include "netdissect-stdinc.h" 320f74e101Schristos 33fdccd7e4Schristos #include "netdissect.h" 340f74e101Schristos #include "extract.h" 35b3a00663Schristos 36b3a00663Schristos /* 37b3a00663Schristos * Trivial File Transfer Protocol (IEN-133) 38b3a00663Schristos */ 39b3a00663Schristos 40b3a00663Schristos /* 41b3a00663Schristos * Packet types. 42b3a00663Schristos */ 43b3a00663Schristos #define RRQ 01 /* read request */ 44b3a00663Schristos #define WRQ 02 /* write request */ 45b3a00663Schristos #define DATA 03 /* data packet */ 46b3a00663Schristos #define ACK 04 /* acknowledgement */ 47b3a00663Schristos #define TFTP_ERROR 05 /* error code */ 48b3a00663Schristos #define OACK 06 /* option acknowledgement */ 49b3a00663Schristos 50b3a00663Schristos /* 51b3a00663Schristos * Error codes. 52b3a00663Schristos */ 53b3a00663Schristos #define EUNDEF 0 /* not defined */ 54b3a00663Schristos #define ENOTFOUND 1 /* file not found */ 55b3a00663Schristos #define EACCESS 2 /* access violation */ 56b3a00663Schristos #define ENOSPACE 3 /* disk full or allocation exceeded */ 57b3a00663Schristos #define EBADOP 4 /* illegal TFTP operation */ 58b3a00663Schristos #define EBADID 5 /* unknown transfer ID */ 59b3a00663Schristos #define EEXISTS 6 /* file already exists */ 60b3a00663Schristos #define ENOUSER 7 /* no such user */ 61b3a00663Schristos 620f74e101Schristos 630f74e101Schristos /* op code to string mapping */ 64870189d2Schristos static const struct tok op2str[] = { 650f74e101Schristos { RRQ, "RRQ" }, /* read request */ 660f74e101Schristos { WRQ, "WRQ" }, /* write request */ 670f74e101Schristos { DATA, "DATA" }, /* data packet */ 680f74e101Schristos { ACK, "ACK" }, /* acknowledgement */ 690f74e101Schristos { TFTP_ERROR, "ERROR" }, /* error code */ 700f74e101Schristos { OACK, "OACK" }, /* option acknowledgement */ 710f74e101Schristos { 0, NULL } 720f74e101Schristos }; 730f74e101Schristos 740f74e101Schristos /* error code to string mapping */ 75870189d2Schristos static const struct tok err2str[] = { 760f74e101Schristos { EUNDEF, "EUNDEF" }, /* not defined */ 770f74e101Schristos { ENOTFOUND, "ENOTFOUND" }, /* file not found */ 780f74e101Schristos { EACCESS, "EACCESS" }, /* access violation */ 790f74e101Schristos { ENOSPACE, "ENOSPACE" }, /* disk full or allocation exceeded */ 800f74e101Schristos { EBADOP, "EBADOP" }, /* illegal TFTP operation */ 810f74e101Schristos { EBADID, "EBADID" }, /* unknown transfer ID */ 820f74e101Schristos { EEXISTS, "EEXISTS" }, /* file already exists */ 830f74e101Schristos { ENOUSER, "ENOUSER" }, /* no such user */ 840f74e101Schristos { 0, NULL } 850f74e101Schristos }; 860f74e101Schristos 870f74e101Schristos /* 880f74e101Schristos * Print trivial file transfer program requests 890f74e101Schristos */ 900f74e101Schristos void 91b3a00663Schristos tftp_print(netdissect_options *ndo, 92c74ad251Schristos const u_char *bp, u_int length) 930f74e101Schristos { 94c74ad251Schristos const char *cp; 95c74ad251Schristos u_int opcode; 96dc860a36Sspz u_int ui; 970f74e101Schristos 98c74ad251Schristos ndo->ndo_protocol = "tftp"; 99c74ad251Schristos 100c74ad251Schristos /* Print protocol */ 101c74ad251Schristos nd_print_protocol_caps(ndo); 1020f74e101Schristos /* Print length */ 103c74ad251Schristos ND_PRINT(", length %u", length); 1040f74e101Schristos 1050f74e101Schristos /* Print tftp request type */ 106dc860a36Sspz if (length < 2) 107dc860a36Sspz goto trunc; 108c74ad251Schristos opcode = GET_BE_U_2(bp); 109c74ad251Schristos cp = tok2str(op2str, "tftp-#%u", opcode); 110c74ad251Schristos ND_PRINT(", %s", cp); 1110f74e101Schristos /* Bail if bogus opcode */ 1120f74e101Schristos if (*cp == 't') 1130f74e101Schristos return; 11472c96ff3Schristos bp += 2; 11572c96ff3Schristos length -= 2; 1160f74e101Schristos 1170f74e101Schristos switch (opcode) { 1180f74e101Schristos 1190f74e101Schristos case RRQ: 1200f74e101Schristos case WRQ: 121dc860a36Sspz if (length == 0) 122dc860a36Sspz goto trunc; 123c74ad251Schristos ND_PRINT(" "); 124dc860a36Sspz /* Print filename */ 125c74ad251Schristos ND_PRINT("\""); 126c74ad251Schristos ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend); 127c74ad251Schristos ND_PRINT("\""); 128dc860a36Sspz if (ui == 0) 129dc860a36Sspz goto trunc; 13072c96ff3Schristos bp += ui; 131dc860a36Sspz length -= ui; 132dc860a36Sspz 133dc860a36Sspz /* Print the mode - RRQ and WRQ only */ 134dc860a36Sspz if (length == 0) 135dc860a36Sspz goto trunc; /* no mode */ 136c74ad251Schristos ND_PRINT(" "); 137c74ad251Schristos ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend); 138dc860a36Sspz if (ui == 0) 139dc860a36Sspz goto trunc; 14072c96ff3Schristos bp += ui; 141dc860a36Sspz length -= ui; 142dc860a36Sspz 143dc860a36Sspz /* Print options, if any */ 144dc860a36Sspz while (length != 0) { 145c74ad251Schristos if (GET_U_1(bp) != '\0') 146c74ad251Schristos ND_PRINT(" "); 147c74ad251Schristos ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend); 148dc860a36Sspz if (ui == 0) 149dc860a36Sspz goto trunc; 15072c96ff3Schristos bp += ui; 151dc860a36Sspz length -= ui; 152dc860a36Sspz } 153dc860a36Sspz break; 154dc860a36Sspz 1550f74e101Schristos case OACK: 156dc860a36Sspz /* Print options */ 157dc860a36Sspz while (length != 0) { 158c74ad251Schristos if (GET_U_1(bp) != '\0') 159c74ad251Schristos ND_PRINT(" "); 160c74ad251Schristos ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend); 161dc860a36Sspz if (ui == 0) 1620f74e101Schristos goto trunc; 16372c96ff3Schristos bp += ui; 164dc860a36Sspz length -= ui; 165dc860a36Sspz } 1660f74e101Schristos break; 1670f74e101Schristos 1680f74e101Schristos case ACK: 1690f74e101Schristos case DATA: 170dc860a36Sspz if (length < 2) 171dc860a36Sspz goto trunc; /* no block number */ 172c74ad251Schristos ND_PRINT(" block %u", GET_BE_U_2(bp)); 1730f74e101Schristos break; 1740f74e101Schristos 1750f74e101Schristos case TFTP_ERROR: 1760f74e101Schristos /* Print error code string */ 177dc860a36Sspz if (length < 2) 178dc860a36Sspz goto trunc; /* no error code */ 179c74ad251Schristos ND_PRINT(" %s", tok2str(err2str, "tftp-err-#%u \"", 180c74ad251Schristos GET_BE_U_2(bp))); 18172c96ff3Schristos bp += 2; 182dc860a36Sspz length -= 2; 1830f74e101Schristos /* Print error message string */ 184dc860a36Sspz if (length == 0) 185dc860a36Sspz goto trunc; /* no error message */ 186c74ad251Schristos ND_PRINT(" \""); 187c74ad251Schristos ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend); 188c74ad251Schristos ND_PRINT("\""); 189dc860a36Sspz if (ui == 0) 1900f74e101Schristos goto trunc; 1910f74e101Schristos break; 1920f74e101Schristos 1930f74e101Schristos default: 1940f74e101Schristos /* We shouldn't get here */ 195c74ad251Schristos ND_PRINT("(unknown #%u)", opcode); 1960f74e101Schristos break; 1970f74e101Schristos } 1980f74e101Schristos return; 1990f74e101Schristos trunc: 200c74ad251Schristos nd_print_trunc(ndo); 2010f74e101Schristos } 202