1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (C) 2008 Edwin Groothuis. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include <sys/stat.h> 32 #include <sys/types.h> 33 #include <sys/socket.h> 34 35 #include <netinet/in.h> 36 #include <arpa/tftp.h> 37 #include <arpa/inet.h> 38 39 #include <assert.h> 40 #include <errno.h> 41 #include <setjmp.h> 42 #include <signal.h> 43 #include <stddef.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <syslog.h> 48 #include <unistd.h> 49 50 #include "tftp-file.h" 51 #include "tftp-io.h" 52 #include "tftp-utils.h" 53 #include "tftp-options.h" 54 55 struct sockaddr_storage peer_sock; 56 struct sockaddr_storage me_sock; 57 58 static int send_packet(int peer, uint16_t block, char *pkt, int size); 59 60 static struct errmsg { 61 int e_code; 62 const char *e_msg; 63 } errmsgs[] = { 64 { EUNDEF, "Undefined error code" }, 65 { ENOTFOUND, "File not found" }, 66 { EACCESS, "Access violation" }, 67 { ENOSPACE, "Disk full or allocation exceeded" }, 68 { EBADOP, "Illegal TFTP operation" }, 69 { EBADID, "Unknown transfer ID" }, 70 { EEXISTS, "File already exists" }, 71 { ENOUSER, "No such user" }, 72 { EOPTNEG, "Option negotiation" }, 73 { -1, NULL } 74 }; 75 76 #define DROPPACKET(s) \ 77 if (packetdroppercentage != 0 && \ 78 random()%100 < packetdroppercentage) { \ 79 tftp_log(LOG_DEBUG, "Artificial packet drop in %s", s); \ 80 return; \ 81 } 82 #define DROPPACKETn(s,n) \ 83 if (packetdroppercentage != 0 && \ 84 random()%100 < packetdroppercentage) { \ 85 tftp_log(LOG_DEBUG, "Artificial packet drop in %s", s); \ 86 return (n); \ 87 } 88 89 const char * 90 errtomsg(int error) 91 { 92 static char ebuf[40]; 93 struct errmsg *pe; 94 95 if (error == 0) 96 return ("success"); 97 for (pe = errmsgs; pe->e_code >= 0; pe++) 98 if (pe->e_code == error) 99 return (pe->e_msg); 100 snprintf(ebuf, sizeof(ebuf), "error %d", error); 101 return (ebuf); 102 } 103 104 static int 105 send_packet(int peer, uint16_t block, char *pkt, int size) 106 { 107 int i; 108 int t = 1; 109 110 for (i = 0; i < 12 ; i++) { 111 DROPPACKETn("send_packet", 0); 112 113 if (sendto(peer, pkt, size, 0, (struct sockaddr *)&peer_sock, 114 peer_sock.ss_len) == size) { 115 if (i) 116 tftp_log(LOG_ERR, 117 "%s block %d, attempt %d successful", 118 packettype(ntohs(((struct tftphdr *) 119 (pkt))->th_opcode)), block, i); 120 return (0); 121 } 122 tftp_log(LOG_ERR, 123 "%s block %d, attempt %d failed (Error %d: %s)", 124 packettype(ntohs(((struct tftphdr *)(pkt))->th_opcode)), 125 block, i, errno, strerror(errno)); 126 sleep(t); 127 if (t < 32) 128 t <<= 1; 129 } 130 tftp_log(LOG_ERR, "send_packet: %s", strerror(errno)); 131 return (1); 132 } 133 134 /* 135 * Send an ERROR packet (error message). 136 * Error code passed in is one of the 137 * standard TFTP codes, or a UNIX errno 138 * offset by 100. 139 */ 140 void 141 send_error(int peer, int error) 142 { 143 struct tftphdr *tp; 144 int length; 145 struct errmsg *pe; 146 char buf[MAXPKTSIZE]; 147 148 if (debug&DEBUG_PACKETS) 149 tftp_log(LOG_DEBUG, "Sending ERROR %d", error); 150 151 DROPPACKET("send_error"); 152 153 tp = (struct tftphdr *)buf; 154 tp->th_opcode = htons((u_short)ERROR); 155 tp->th_code = htons((u_short)error); 156 for (pe = errmsgs; pe->e_code >= 0; pe++) 157 if (pe->e_code == error) 158 break; 159 if (pe->e_code < 0) { 160 pe->e_msg = strerror(error - 100); 161 tp->th_code = EUNDEF; /* set 'undef' errorcode */ 162 } 163 strcpy(tp->th_msg, pe->e_msg); 164 length = strlen(pe->e_msg); 165 tp->th_msg[length] = '\0'; 166 length += 5; 167 168 if (debug&DEBUG_PACKETS) 169 tftp_log(LOG_DEBUG, "Sending ERROR %d: %s", error, tp->th_msg); 170 171 if (sendto(peer, buf, length, 0, 172 (struct sockaddr *)&peer_sock, peer_sock.ss_len) != length) 173 tftp_log(LOG_ERR, "send_error: %s", strerror(errno)); 174 } 175 176 /* 177 * Send an WRQ packet (write request). 178 */ 179 int 180 send_wrq(int peer, char *filename, char *mode) 181 { 182 int n; 183 struct tftphdr *tp; 184 char *bp; 185 char buf[MAXPKTSIZE]; 186 int size; 187 188 if (debug&DEBUG_PACKETS) 189 tftp_log(LOG_DEBUG, "Sending WRQ: filename: '%s', mode '%s'", 190 filename, mode 191 ); 192 193 DROPPACKETn("send_wrq", 0); 194 195 tp = (struct tftphdr *)buf; 196 tp->th_opcode = htons((u_short)WRQ); 197 size = offsetof(struct tftphdr, th_stuff); 198 199 bp = tp->th_stuff; 200 strlcpy(bp, filename, sizeof(buf) - size); 201 bp += strlen(filename); 202 *bp = 0; 203 bp++; 204 size += strlen(filename) + 1; 205 206 strlcpy(bp, mode, sizeof(buf) - size); 207 bp += strlen(mode); 208 *bp = 0; 209 bp++; 210 size += strlen(mode) + 1; 211 212 if (options_rfc_enabled) 213 size += make_options(peer, bp, sizeof(buf) - size); 214 215 n = sendto(peer, buf, size, 0, 216 (struct sockaddr *)&peer_sock, peer_sock.ss_len); 217 if (n != size) { 218 tftp_log(LOG_ERR, "send_wrq: %s", strerror(errno)); 219 return (1); 220 } 221 return (0); 222 } 223 224 /* 225 * Send an RRQ packet (write request). 226 */ 227 int 228 send_rrq(int peer, char *filename, char *mode) 229 { 230 int n; 231 struct tftphdr *tp; 232 char *bp; 233 char buf[MAXPKTSIZE]; 234 int size; 235 236 if (debug&DEBUG_PACKETS) 237 tftp_log(LOG_DEBUG, "Sending RRQ: filename: '%s', mode '%s'", 238 filename, mode 239 ); 240 241 DROPPACKETn("send_rrq", 0); 242 243 tp = (struct tftphdr *)buf; 244 tp->th_opcode = htons((u_short)RRQ); 245 size = offsetof(struct tftphdr, th_stuff); 246 247 bp = tp->th_stuff; 248 strlcpy(bp, filename, sizeof(buf) - size); 249 bp += strlen(filename); 250 *bp = 0; 251 bp++; 252 size += strlen(filename) + 1; 253 254 strlcpy(bp, mode, sizeof(buf) - size); 255 bp += strlen(mode); 256 *bp = 0; 257 bp++; 258 size += strlen(mode) + 1; 259 260 if (options_rfc_enabled) { 261 options[OPT_TSIZE].o_request = strdup("0"); 262 size += make_options(peer, bp, sizeof(buf) - size); 263 } 264 265 n = sendto(peer, buf, size, 0, 266 (struct sockaddr *)&peer_sock, peer_sock.ss_len); 267 if (n != size) { 268 tftp_log(LOG_ERR, "send_rrq: %d %s", n, strerror(errno)); 269 return (1); 270 } 271 return (0); 272 } 273 274 /* 275 * Send an OACK packet (option acknowledgement). 276 */ 277 int 278 send_oack(int peer) 279 { 280 struct tftphdr *tp; 281 int size, i, n; 282 char *bp; 283 char buf[MAXPKTSIZE]; 284 285 if (debug&DEBUG_PACKETS) 286 tftp_log(LOG_DEBUG, "Sending OACK"); 287 288 DROPPACKETn("send_oack", 0); 289 290 /* 291 * Send back an options acknowledgement (only the ones with 292 * a reply for) 293 */ 294 tp = (struct tftphdr *)buf; 295 bp = buf + 2; 296 size = sizeof(buf) - 2; 297 tp->th_opcode = htons((u_short)OACK); 298 for (i = 0; options[i].o_type != NULL; i++) { 299 if (options[i].o_reply != NULL) { 300 n = snprintf(bp, size, "%s%c%s", options[i].o_type, 301 0, options[i].o_reply); 302 bp += n+1; 303 size -= n+1; 304 if (size < 0) { 305 tftp_log(LOG_ERR, "oack: buffer overflow"); 306 exit(1); 307 } 308 } 309 } 310 size = bp - buf; 311 312 if (sendto(peer, buf, size, 0, 313 (struct sockaddr *)&peer_sock, peer_sock.ss_len) != size) { 314 tftp_log(LOG_INFO, "send_oack: %s", strerror(errno)); 315 return (1); 316 } 317 318 return (0); 319 } 320 321 /* 322 * Send an ACK packet (acknowledgement). 323 */ 324 int 325 send_ack(int fp, uint16_t block) 326 { 327 struct tftphdr *tp; 328 int size; 329 char buf[MAXPKTSIZE]; 330 331 if (debug&DEBUG_PACKETS) 332 tftp_log(LOG_DEBUG, "Sending ACK for block %d", block); 333 334 DROPPACKETn("send_ack", 0); 335 336 tp = (struct tftphdr *)buf; 337 size = sizeof(buf) - 2; 338 tp->th_opcode = htons((u_short)ACK); 339 tp->th_block = htons((u_short)block); 340 size = 4; 341 342 if (sendto(fp, buf, size, 0, 343 (struct sockaddr *)&peer_sock, peer_sock.ss_len) != size) { 344 tftp_log(LOG_INFO, "send_ack: %s", strerror(errno)); 345 return (1); 346 } 347 348 return (0); 349 } 350 351 /* 352 * Send a DATA packet 353 */ 354 int 355 send_data(int peer, uint16_t block, char *data, int size) 356 { 357 char buf[MAXPKTSIZE]; 358 struct tftphdr *pkt; 359 int n; 360 361 if (debug&DEBUG_PACKETS) 362 tftp_log(LOG_DEBUG, "Sending DATA packet %d of %d bytes", 363 block, size); 364 365 DROPPACKETn("send_data", 0); 366 367 pkt = (struct tftphdr *)buf; 368 369 pkt->th_opcode = htons((u_short)DATA); 370 pkt->th_block = htons((u_short)block); 371 memcpy(pkt->th_data, data, size); 372 373 n = send_packet(peer, block, (char *)pkt, size + 4); 374 return (n); 375 } 376 377 378 /* 379 * Receive a packet 380 */ 381 static jmp_buf timeoutbuf; 382 383 static void 384 timeout(int sig __unused) 385 { 386 387 /* tftp_log(LOG_DEBUG, "Timeout\n"); Inside a signal handler... */ 388 longjmp(timeoutbuf, 1); 389 } 390 391 int 392 receive_packet(int peer, char *data, int size, struct sockaddr_storage *from, 393 int thistimeout) 394 { 395 struct tftphdr *pkt; 396 struct sockaddr_storage from_local; 397 struct sockaddr_storage *pfrom; 398 socklen_t fromlen; 399 int n; 400 static int timed_out; 401 402 if (debug&DEBUG_PACKETS) 403 tftp_log(LOG_DEBUG, 404 "Waiting %d seconds for packet", timeoutpacket); 405 406 pkt = (struct tftphdr *)data; 407 408 signal(SIGALRM, timeout); 409 timed_out = setjmp(timeoutbuf); 410 alarm(thistimeout); 411 412 if (timed_out != 0) { 413 tftp_log(LOG_ERR, "receive_packet: timeout"); 414 alarm(0); 415 return (RP_TIMEOUT); 416 } 417 418 pfrom = (from == NULL) ? &from_local : from; 419 fromlen = sizeof(*pfrom); 420 n = recvfrom(peer, data, size, 0, (struct sockaddr *)pfrom, &fromlen); 421 422 alarm(0); 423 424 DROPPACKETn("receive_packet", RP_TIMEOUT); 425 426 if (n < 0) { 427 tftp_log(LOG_ERR, "receive_packet: timeout"); 428 return (RP_TIMEOUT); 429 } 430 431 if (n < 0) { 432 /* No idea what could have happened if it isn't a timeout */ 433 tftp_log(LOG_ERR, "receive_packet: %s", strerror(errno)); 434 return (RP_RECVFROM); 435 } 436 if (n < 4) { 437 tftp_log(LOG_ERR, 438 "receive_packet: packet too small (%d bytes)", n); 439 return (RP_TOOSMALL); 440 } 441 442 pkt->th_opcode = ntohs((u_short)pkt->th_opcode); 443 if (pkt->th_opcode == DATA || 444 pkt->th_opcode == ACK) 445 pkt->th_block = ntohs((u_short)pkt->th_block); 446 447 if (pkt->th_opcode == DATA && n > pktsize) { 448 tftp_log(LOG_ERR, "receive_packet: packet too big"); 449 return (RP_TOOBIG); 450 } 451 452 if (((struct sockaddr_in *)(pfrom))->sin_addr.s_addr != 453 ((struct sockaddr_in *)(&peer_sock))->sin_addr.s_addr) { 454 tftp_log(LOG_ERR, 455 "receive_packet: received packet from wrong source"); 456 return (RP_WRONGSOURCE); 457 } 458 459 if (pkt->th_opcode == ERROR) { 460 tftp_log(pkt->th_code == EUNDEF ? LOG_DEBUG : LOG_ERR, 461 "Got ERROR packet: %s", pkt->th_msg); 462 return (RP_ERROR); 463 } 464 465 if (debug&DEBUG_PACKETS) 466 tftp_log(LOG_DEBUG, "Received %d bytes in a %s packet", 467 n, packettype(pkt->th_opcode)); 468 469 return n - 4; 470 } 471