1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1991 by Sun Microsystems, Inc.
24  */
25 
26 #ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <fcntl.h>
29 #include <arpa/tftp.h>
30 #include "snoop.h"
31 
32 extern char *dlc_header;
33 char *tftperror();
34 char *show_type();
35 
36 interpret_tftp(flags, tftp, fraglen)
37 	int flags;
38 	struct tftphdr *tftp;
39 	int fraglen;
40 {
41 	char *name, *mode;
42 	extern int src_port, dst_port;
43 	int blocksize = fraglen - 4;
44 
45 	switch (ntohs(tftp->th_opcode)) {
46 	case RRQ:
47 	case WRQ:
48 		add_transient(src_port, interpret_tftp);
49 		break;
50 	case ERROR:
51 		del_transient(src_port);
52 		break;
53 	}
54 
55 	if (flags & F_SUM) {
56 		switch (ntohs(tftp->th_opcode)) {
57 		case RRQ:
58 			name = (char *) &tftp->th_stuff;
59 			mode = name + (strlen(name) + 1);
60 			(void) sprintf(get_sum_line(),
61 				"TFTP Read \"%s\" (%s)", name, mode);
62 			break;
63 		case WRQ:
64 			name = (char *) &tftp->th_stuff;
65 			mode = name + (strlen(name) + 1);
66 			(void) sprintf(get_sum_line(),
67 				"TFTP Write \"%s\" (%s)", name, mode);
68 			break;
69 		case DATA:
70 			(void) sprintf(get_sum_line(),
71 				"TFTP Data block %d (%d bytes)%s",
72 				ntohs(tftp->th_block),
73 				blocksize,
74 				blocksize < 512 ? " (last block)":"");
75 			break;
76 		case ACK:
77 			(void) sprintf(get_sum_line(),
78 				"TFTP Ack  block %d",
79 				ntohs(tftp->th_block));
80 			break;
81 		case ERROR:
82 			(void) sprintf(get_sum_line(),
83 				"TFTP Error: %s",
84 				tftperror(ntohs(tftp->th_code)));
85 			break;
86 		}
87 	}
88 
89 	if (flags & F_DTAIL) {
90 
91 	show_header("TFTP:  ", "Trivial File Transfer Protocol", fraglen);
92 	show_space();
93 	(void) sprintf(get_line((char *)tftp->th_opcode - dlc_header, 2),
94 		"Opcode = %d (%s)",
95 		ntohs(tftp->th_opcode),
96 		show_type(ntohs(tftp->th_opcode)));
97 
98 	switch (ntohs(tftp->th_opcode)) {
99 	case RRQ:
100 	case WRQ:
101 		name = (char *) &tftp->th_stuff;
102 		mode = name + (strlen(name) + 1);
103 		(void) sprintf(
104 			get_line(name - dlc_header, strlen(name) + 1),
105 			"File name = \"%s\"",
106 			name);
107 		(void) sprintf(
108 			get_line(mode - dlc_header, strlen(mode) + 1),
109 			"Transfer mode = %s",
110 			mode);
111 		break;
112 
113 	case DATA:
114 		(void) sprintf(
115 			get_line((char *)tftp->th_block - dlc_header, 2),
116 			"Data block = %d%s",
117 			ntohs(tftp->th_block),
118 			blocksize < 512 ? " (last block)":"");
119 		(void) sprintf(
120 			get_line((char *)tftp->th_data - dlc_header, blocksize),
121 			"[ %d bytes of data ]",
122 			blocksize);
123 		break;
124 
125 	case ACK:
126 		(void) sprintf(
127 			get_line((char *)tftp->th_block - dlc_header, 2),
128 			"Acknowledge block = %d",
129 			ntohs(tftp->th_block));
130 		break;
131 
132 	case ERROR:
133 		(void) sprintf(
134 			get_line((char *)tftp->th_code - dlc_header, 2),
135 			"Error = %d (%s)",
136 			ntohs(tftp->th_code),
137 			tftperror(ntohs(tftp->th_code)));
138 		(void) sprintf(
139 			get_line((char *)tftp->th_data - dlc_header,
140 				strlen(tftp->th_data) + 1),
141 			"Error string = \"%s\"",
142 				tftp->th_data);
143 	}
144 	}
145 
146 	return (fraglen);
147 }
148 
149 char *
150 show_type(t)
151 	int t;
152 {
153 	switch (t) {
154 	case RRQ:	return ("read request");
155 	case WRQ:	return ("write request");
156 	case DATA:	return ("data packet");
157 	case ACK:	return ("acknowledgement");
158 	case ERROR:	return ("error");
159 	}
160 	return ("?");
161 }
162 
163 char *
164 tftperror(code)
165     unsigned short code;
166 {
167 	static char buf[128];
168 
169 	switch (code) {
170 	case EUNDEF:	return ("not defined");
171 	case ENOTFOUND:	return ("file not found");
172 	case EACCESS:	return ("access violation");
173 	case ENOSPACE:	return ("disk full or allocation exceeded");
174 	case EBADOP:	return ("illegal TFTP operation");
175 	case EBADID:	return ("unknown transfer ID");
176 	case EEXISTS:	return ("file already exists");
177 	case ENOUSER:	return ("no such user");
178 	}
179 	(void) sprintf(buf, "%d", code);
180 
181 	return (buf);
182 }
183