b517898b137213ccbe0873d3fdcfb6c175fa0fad
[dragonfly.git] / contrib / tcpdump-3.9 / print-tftp.c
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.2.1 2007/09/14 01:03:12 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
39 #include <stdio.h>
40 #include <string.h>
41
42 #include "interface.h"
43 #include "addrtoname.h"
44 #include "extract.h"
45 #include "tftp.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         { OACK,         "OACK" },       /* option acknowledgement */
55         { 0,            NULL }
56 };
57
58 /* error code to string mapping */
59 static struct tok err2str[] = {
60         { EUNDEF,       "EUNDEF" },     /* not defined */
61         { ENOTFOUND,    "ENOTFOUND" },  /* file not found */
62         { EACCESS,      "EACCESS" },    /* access violation */
63         { ENOSPACE,     "ENOSPACE" },   /* disk full or allocation exceeded */
64         { EBADOP,       "EBADOP" },     /* illegal TFTP operation */
65         { EBADID,       "EBADID" },     /* unknown transfer ID */
66         { EEXISTS,      "EEXISTS" },    /* file already exists */
67         { ENOUSER,      "ENOUSER" },    /* no such user */
68         { 0,            NULL }
69 };
70
71 /*
72  * Print trivial file transfer program requests
73  */
74 void
75 tftp_print(register const u_char *bp, u_int length)
76 {
77         register const struct tftphdr *tp;
78         register const char *cp;
79         register const u_char *p;
80         register int opcode, i;
81         static char tstr[] = " [|tftp]";
82
83         tp = (const struct tftphdr *)bp;
84
85         /* Print length */
86         printf(" %d", length);
87
88         /* Print tftp request type */
89         TCHECK(tp->th_opcode);
90         opcode = EXTRACT_16BITS(&tp->th_opcode);
91         cp = tok2str(op2str, "tftp-#%d", opcode);
92         printf(" %s", cp);
93         /* Bail if bogus opcode */
94         if (*cp == 't')
95                 return;
96
97         switch (opcode) {
98
99         case RRQ:
100         case WRQ:
101         case OACK:
102                 /*
103                  * XXX Not all arpa/tftp.h's specify th_stuff as any
104                  * array; use address of th_block instead
105                  */
106 #ifdef notdef
107                 p = (u_char *)tp->th_stuff;
108 #else
109                 p = (u_char *)&tp->th_block;
110 #endif
111                 putchar(' ');
112                 /* Print filename or first option */
113                 if (opcode != OACK)
114                         putchar('"');
115                 i = fn_print(p, snapend);
116                 if (opcode != OACK)
117                         putchar('"');
118
119                 /* Print the mode (RRQ and WRQ only) and any options */
120                 while ((p = (const u_char *)strchr((const char *)p, '\0')) != NULL) {
121                         if (length <= (u_int)(p - (const u_char *)&tp->th_block))
122                                 break;
123                         p++;
124                         if (*p != '\0') {
125                                 putchar(' ');
126                                 fn_print(p, snapend);
127                         }
128                 }
129                 
130                 if (i)
131                         goto trunc;
132                 break;
133
134         case ACK:
135         case DATA:
136                 TCHECK(tp->th_block);
137                 printf(" block %d", EXTRACT_16BITS(&tp->th_block));
138                 break;
139
140         case ERROR:
141                 /* Print error code string */
142                 TCHECK(tp->th_code);
143                 printf(" %s \"", tok2str(err2str, "tftp-err-#%d \"",
144                                        EXTRACT_16BITS(&tp->th_code)));
145                 /* Print error message string */
146                 i = fn_print((const u_char *)tp->th_data, snapend);
147                 putchar('"');
148                 if (i)
149                         goto trunc;
150                 break;
151
152         default:
153                 /* We shouldn't get here */
154                 printf("(unknown #%d)", opcode);
155                 break;
156         }
157         return;
158 trunc:
159         fputs(tstr, stdout);
160         return;
161 }