1 /* 2 * Copyright (c) 1983, 1993 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 the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #if 0 35 #ifndef lint 36 static char sccsid[] = "@(#)tftp.c 8.1 (Berkeley) 6/6/93"; 37 #endif /* not lint */ 38 #endif 39 40 #include <sys/cdefs.h> 41 __FBSDID("$FreeBSD$"); 42 43 /* Many bug fixes are from Jim Guyton <guyton@rand-unix> */ 44 45 /* 46 * TFTP User Program -- Protocol Machines 47 */ 48 #include <sys/socket.h> 49 #include <sys/stat.h> 50 51 #include <netinet/in.h> 52 53 #include <arpa/tftp.h> 54 55 #include <err.h> 56 #include <netdb.h> 57 #include <stdio.h> 58 #include <stdlib.h> 59 #include <string.h> 60 #include <syslog.h> 61 62 #include "tftp.h" 63 #include "tftp-file.h" 64 #include "tftp-utils.h" 65 #include "tftp-io.h" 66 #include "tftp-transfer.h" 67 #include "tftp-options.h" 68 69 /* 70 * Send the requested file. 71 */ 72 void 73 xmitfile(int peer, char *port, int fd, char *name, char *mode) 74 { 75 struct tftphdr *rp; 76 int n, i; 77 uint16_t block; 78 struct sockaddr_storage serv; /* valid server port number */ 79 char recvbuffer[MAXPKTSIZE]; 80 struct tftp_stats tftp_stats; 81 82 stats_init(&tftp_stats); 83 84 memset(&serv, 0, sizeof(serv)); 85 rp = (struct tftphdr *)recvbuffer; 86 87 if (port == NULL) { 88 struct servent *se; 89 se = getservbyname("tftp", "udp"); 90 ((struct sockaddr_in *)&peer_sock)->sin_port = se->s_port; 91 } else 92 ((struct sockaddr_in *)&peer_sock)->sin_port = 93 htons(atoi(port)); 94 95 for (i = 0; i < 12; i++) { 96 struct sockaddr_storage from; 97 98 /* Tell the other side what we want to do */ 99 if (debug&DEBUG_SIMPLE) 100 printf("Sending %s\n", name); 101 102 n = send_wrq(peer, name, mode); 103 if (n > 0) { 104 printf("Cannot send WRQ packet\n"); 105 return; 106 } 107 108 /* 109 * The first packet we receive has the new destination port 110 * we have to send the next packets to. 111 */ 112 n = receive_packet(peer, recvbuffer, 113 MAXPKTSIZE, &from, timeoutpacket); 114 115 /* We got some data! */ 116 if (n >= 0) { 117 ((struct sockaddr_in *)&peer_sock)->sin_port = 118 ((struct sockaddr_in *)&from)->sin_port; 119 break; 120 } 121 122 /* This should be retried */ 123 if (n == RP_TIMEOUT) { 124 printf("Try %d, didn't receive answer from remote.\n", 125 i + 1); 126 continue; 127 } 128 129 /* Everything else is fatal */ 130 break; 131 } 132 if (i == 12) { 133 printf("Transfer timed out.\n"); 134 return; 135 } 136 if (rp->th_opcode == ERROR) { 137 printf("Got ERROR, aborted\n"); 138 return; 139 } 140 141 /* 142 * If the first packet is an OACK instead of an ACK packet, 143 * handle it different. 144 */ 145 if (rp->th_opcode == OACK) { 146 if (!options_rfc_enabled) { 147 printf("Got OACK while options are not enabled!\n"); 148 send_error(peer, EBADOP); 149 return; 150 } 151 152 parse_options(peer, rp->th_stuff, n + 2); 153 } 154 155 if (read_init(fd, NULL, mode) < 0) { 156 warn("read_init()"); 157 return; 158 } 159 160 block = 1; 161 tftp_send(peer, &block, &tftp_stats); 162 163 read_close(); 164 if (tftp_stats.amount > 0) 165 printstats("Sent", verbose, &tftp_stats); 166 167 txrx_error = 1; 168 } 169 170 /* 171 * Receive a file. 172 */ 173 void 174 recvfile(int peer, char *port, int fd, char *name, char *mode) 175 { 176 struct tftphdr *rp; 177 uint16_t block; 178 char recvbuffer[MAXPKTSIZE]; 179 int n, i; 180 struct tftp_stats tftp_stats; 181 182 stats_init(&tftp_stats); 183 184 rp = (struct tftphdr *)recvbuffer; 185 186 if (port == NULL) { 187 struct servent *se; 188 se = getservbyname("tftp", "udp"); 189 ((struct sockaddr_in *)&peer_sock)->sin_port = se->s_port; 190 } else 191 ((struct sockaddr_in *)&peer_sock)->sin_port = 192 htons(atoi(port)); 193 194 for (i = 0; i < 12; i++) { 195 struct sockaddr_storage from; 196 197 /* Tell the other side what we want to do */ 198 if (debug&DEBUG_SIMPLE) 199 printf("Requesting %s\n", name); 200 201 n = send_rrq(peer, name, mode); 202 if (n > 0) { 203 printf("Cannot send RRQ packet\n"); 204 return; 205 } 206 207 /* 208 * The first packet we receive has the new destination port 209 * we have to send the next packets to. 210 */ 211 n = receive_packet(peer, recvbuffer, 212 MAXPKTSIZE, &from, timeoutpacket); 213 214 /* We got something useful! */ 215 if (n >= 0) { 216 ((struct sockaddr_in *)&peer_sock)->sin_port = 217 ((struct sockaddr_in *)&from)->sin_port; 218 break; 219 } 220 221 /* We should retry if this happens */ 222 if (n == RP_TIMEOUT) { 223 printf("Try %d, didn't receive answer from remote.\n", 224 i + 1); 225 continue; 226 } 227 228 /* Otherwise it is a fatal error */ 229 break; 230 } 231 if (i == 12) { 232 printf("Transfer timed out.\n"); 233 return; 234 } 235 if (rp->th_opcode == ERROR) { 236 tftp_log(LOG_ERR, "Error code %d: %s", rp->th_code, rp->th_msg); 237 return; 238 } 239 240 if (write_init(fd, NULL, mode) < 0) { 241 warn("write_init"); 242 return; 243 } 244 245 /* 246 * If the first packet is an OACK packet instead of an DATA packet, 247 * handle it different. 248 */ 249 if (rp->th_opcode == OACK) { 250 if (!options_rfc_enabled) { 251 printf("Got OACK while options are not enabled!\n"); 252 send_error(peer, EBADOP); 253 return; 254 } 255 256 parse_options(peer, rp->th_stuff, n + 2); 257 258 n = send_ack(peer, 0); 259 if (n > 0) { 260 printf("Cannot send ACK on OACK.\n"); 261 return; 262 } 263 block = 0; 264 tftp_receive(peer, &block, &tftp_stats, NULL, 0); 265 } else { 266 block = 1; 267 tftp_receive(peer, &block, &tftp_stats, rp, n); 268 } 269 270 write_close(); 271 if (tftp_stats.amount > 0) 272 printstats("Received", verbose, &tftp_stats); 273 return; 274 } 275