xref: /illumos-gate/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_tftp.c (revision 8cd45542f2a452ca0dab13d8b2d5cfa876ccbebc)
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 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <fcntl.h>
30 #include <arpa/tftp.h>
31 #include "snoop.h"
32 
33 extern char *dlc_header;
34 char *tftperror();
35 char *show_type();
36 
37 int
38 interpret_tftp(int flags, struct tftphdr *tftp, int fraglen)
39 {
40 	char *name, *mode;
41 	extern int src_port, dst_port;
42 	int blocksize = fraglen - 4;
43 
44 	switch (ntohs(tftp->th_opcode)) {
45 	case RRQ:
46 	case WRQ:
47 		add_transient(src_port, interpret_tftp);
48 		break;
49 	case ERROR:
50 		del_transient(src_port);
51 		break;
52 	}
53 
54 	if (flags & F_SUM) {
55 		switch (ntohs(tftp->th_opcode)) {
56 		case RRQ:
57 			name = (char *)&tftp->th_stuff;
58 			mode = name + (strlen(name) + 1);
59 			(void) sprintf(get_sum_line(),
60 				"TFTP Read \"%s\" (%s)", name, mode);
61 			break;
62 		case WRQ:
63 			name = (char *)&tftp->th_stuff;
64 			mode = name + (strlen(name) + 1);
65 			(void) sprintf(get_sum_line(),
66 				"TFTP Write \"%s\" (%s)", name, mode);
67 			break;
68 		case DATA:
69 			(void) sprintf(get_sum_line(),
70 				"TFTP Data block %d (%d bytes)%s",
71 				ntohs(tftp->th_block),
72 				blocksize,
73 				blocksize < 512 ? " (last block)":"");
74 			break;
75 		case ACK:
76 			(void) sprintf(get_sum_line(),
77 				"TFTP Ack  block %d",
78 				ntohs(tftp->th_block));
79 			break;
80 		case ERROR:
81 			(void) sprintf(get_sum_line(),
82 				"TFTP Error: %s",
83 				tftperror(ntohs(tftp->th_code)));
84 			break;
85 		}
86 	}
87 
88 	if (flags & F_DTAIL) {
89 
90 	show_header("TFTP:  ", "Trivial File Transfer Protocol", fraglen);
91 	show_space();
92 	(void) sprintf(get_line((char *)(uintptr_t)tftp->th_opcode -
93 		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 *)(uintptr_t)tftp->th_block -
116 			dlc_header, 2),	"Data block = %d%s",
117 			ntohs(tftp->th_block),
118 			blocksize < 512 ? " (last block)":"");
119 		(void) sprintf(get_line((char *)(uintptr_t)tftp->th_data -
120 			dlc_header, blocksize),
121 			"[ %d bytes of data ]",
122 			blocksize);
123 		break;
124 
125 	case ACK:
126 		(void) sprintf(get_line((char *)(uintptr_t)tftp->th_block -
127 			dlc_header, 2),	"Acknowledge block = %d",
128 			ntohs(tftp->th_block));
129 		break;
130 
131 	case ERROR:
132 		(void) sprintf(get_line((char *)(uintptr_t)tftp->th_code -
133 			dlc_header, 2),	"Error = %d (%s)",
134 			ntohs(tftp->th_code),
135 			tftperror(ntohs(tftp->th_code)));
136 		(void) sprintf(get_line((char *)(uintptr_t)tftp->th_data -
137 			dlc_header, strlen(tftp->th_data) + 1),
138 			"Error string = \"%s\"", tftp->th_data);
139 	}
140 	}
141 
142 	return (fraglen);
143 }
144 
145 char *
146 show_type(t)
147 	int t;
148 {
149 	switch (t) {
150 	case RRQ:	return ("read request");
151 	case WRQ:	return ("write request");
152 	case DATA:	return ("data packet");
153 	case ACK:	return ("acknowledgement");
154 	case ERROR:	return ("error");
155 	}
156 	return ("?");
157 }
158 
159 char *
160 tftperror(code)
161     unsigned short code;
162 {
163 	static char buf[128];
164 
165 	switch (code) {
166 	case EUNDEF:	return ("not defined");
167 	case ENOTFOUND:	return ("file not found");
168 	case EACCESS:	return ("access violation");
169 	case ENOSPACE:	return ("disk full or allocation exceeded");
170 	case EBADOP:	return ("illegal TFTP operation");
171 	case EBADID:	return ("unknown transfer ID");
172 	case EEXISTS:	return ("file already exists");
173 	case ENOUSER:	return ("no such user");
174 	}
175 	(void) sprintf(buf, "%d", code);
176 
177 	return (buf);
178 }
179