1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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/types.h> 32 #include <sys/socket.h> 33 #include <sys/stat.h> 34 35 #include <netinet/in.h> 36 #include <arpa/inet.h> 37 #include <arpa/tftp.h> 38 39 #include <assert.h> 40 #include <errno.h> 41 #include <poll.h> 42 #include <stddef.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <syslog.h> 47 #include <unistd.h> 48 49 #include "tftp-file.h" 50 #include "tftp-io.h" 51 #include "tftp-utils.h" 52 #include "tftp-options.h" 53 54 struct sockaddr_storage peer_sock; 55 struct sockaddr_storage me_sock; 56 57 static int send_packet(int peer, uint16_t block, char *pkt, int size); 58 59 static struct errmsg { 60 int e_code; 61 const char *e_msg; 62 } errmsgs[] = { 63 { EUNDEF, "Undefined error code" }, 64 { ENOTFOUND, "File not found" }, 65 { EACCESS, "Access violation" }, 66 { ENOSPACE, "Disk full or allocation exceeded" }, 67 { EBADOP, "Illegal TFTP operation" }, 68 { EBADID, "Unknown transfer ID" }, 69 { EEXISTS, "File already exists" }, 70 { ENOUSER, "No such user" }, 71 { EOPTNEG, "Option negotiation" }, 72 { -1, NULL } 73 }; 74 75 #define DROPPACKET(s) \ 76 if (packetdroppercentage != 0 && \ 77 random()%100 < packetdroppercentage) { \ 78 tftp_log(LOG_DEBUG, "Artificial packet drop in %s", s); \ 79 return; \ 80 } 81 #define DROPPACKETn(s,n) \ 82 if (packetdroppercentage != 0 && \ 83 random()%100 < packetdroppercentage) { \ 84 tftp_log(LOG_DEBUG, "Artificial packet drop in %s", s); \ 85 return (n); \ 86 } 87 88 const char * 89 errtomsg(int error) 90 { 91 static char ebuf[40]; 92 struct errmsg *pe; 93 94 if (error == 0) 95 return ("success"); 96 for (pe = errmsgs; pe->e_code >= 0; pe++) 97 if (pe->e_code == error) 98 return (pe->e_msg); 99 snprintf(ebuf, sizeof(ebuf), "error %d", error); 100 return (ebuf); 101 } 102 103 static int 104 send_packet(int peer, uint16_t block, char *pkt, int size) 105 { 106 int i; 107 int t = 1; 108 109 for (i = 0; i < 12 ; i++) { 110 DROPPACKETn("send_packet", 0); 111 112 if (sendto(peer, pkt, size, 0, (struct sockaddr *)&peer_sock, 113 peer_sock.ss_len) == size) { 114 if (i) 115 tftp_log(LOG_ERR, 116 "%s block %d, attempt %d successful", 117 packettype(ntohs(((struct tftphdr *) 118 (pkt))->th_opcode)), block, i); 119 return (0); 120 } 121 tftp_log(LOG_ERR, 122 "%s block %d, attempt %d failed (Error %d: %s)", 123 packettype(ntohs(((struct tftphdr *)(pkt))->th_opcode)), 124 block, i, errno, strerror(errno)); 125 sleep(t); 126 if (t < 32) 127 t <<= 1; 128 } 129 tftp_log(LOG_ERR, "send_packet: %s", strerror(errno)); 130 return (1); 131 } 132 133 /* 134 * Send an ERROR packet (error message). 135 * Error code passed in is one of the 136 * standard TFTP codes, or a UNIX errno 137 * offset by 100. 138 */ 139 void 140 send_error(int peer, int error) 141 { 142 struct tftphdr *tp; 143 int length; 144 struct errmsg *pe; 145 char buf[MAXPKTSIZE]; 146 147 if (debug & DEBUG_PACKETS) 148 tftp_log(LOG_DEBUG, "Sending ERROR %d", error); 149 150 DROPPACKET("send_error"); 151 152 tp = (struct tftphdr *)buf; 153 tp->th_opcode = htons((u_short)ERROR); 154 tp->th_code = htons((u_short)error); 155 for (pe = errmsgs; pe->e_code >= 0; pe++) 156 if (pe->e_code == error) 157 break; 158 if (pe->e_code < 0) { 159 pe->e_msg = strerror(error - 100); 160 tp->th_code = EUNDEF; /* set 'undef' errorcode */ 161 } 162 strcpy(tp->th_msg, pe->e_msg); 163 length = strlen(pe->e_msg); 164 tp->th_msg[length] = '\0'; 165 length += 5; 166 167 if (debug & DEBUG_PACKETS) 168 tftp_log(LOG_DEBUG, "Sending ERROR %d: %s", error, tp->th_msg); 169 170 if (sendto(peer, buf, length, 0, 171 (struct sockaddr *)&peer_sock, peer_sock.ss_len) != length) 172 tftp_log(LOG_ERR, "send_error: %s", strerror(errno)); 173 } 174 175 /* 176 * Send an WRQ packet (write request). 177 */ 178 int 179 send_wrq(int peer, char *filename, char *mode) 180 { 181 int n; 182 struct tftphdr *tp; 183 char *bp; 184 char buf[MAXPKTSIZE]; 185 int size; 186 187 if (debug & DEBUG_PACKETS) 188 tftp_log(LOG_DEBUG, "Sending WRQ: filename: '%s', mode '%s'", 189 filename, mode 190 ); 191 192 DROPPACKETn("send_wrq", 0); 193 194 tp = (struct tftphdr *)buf; 195 tp->th_opcode = htons((u_short)WRQ); 196 size = offsetof(struct tftphdr, th_stuff); 197 198 bp = tp->th_stuff; 199 strlcpy(bp, filename, sizeof(buf) - size); 200 bp += strlen(filename); 201 *bp = 0; 202 bp++; 203 size += strlen(filename) + 1; 204 205 strlcpy(bp, mode, sizeof(buf) - size); 206 bp += strlen(mode); 207 *bp = 0; 208 bp++; 209 size += strlen(mode) + 1; 210 211 if (options_rfc_enabled) 212 size += make_options(peer, bp, sizeof(buf) - size); 213 214 n = sendto(peer, buf, size, 0, 215 (struct sockaddr *)&peer_sock, peer_sock.ss_len); 216 if (n != size) { 217 tftp_log(LOG_ERR, "send_wrq: %s", strerror(errno)); 218 return (1); 219 } 220 return (0); 221 } 222 223 /* 224 * Send an RRQ packet (write request). 225 */ 226 int 227 send_rrq(int peer, char *filename, char *mode) 228 { 229 int n; 230 struct tftphdr *tp; 231 char *bp; 232 char buf[MAXPKTSIZE]; 233 int size; 234 235 if (debug & DEBUG_PACKETS) 236 tftp_log(LOG_DEBUG, "Sending RRQ: filename: '%s', mode '%s'", 237 filename, mode 238 ); 239 240 DROPPACKETn("send_rrq", 0); 241 242 tp = (struct tftphdr *)buf; 243 tp->th_opcode = htons((u_short)RRQ); 244 size = offsetof(struct tftphdr, th_stuff); 245 246 bp = tp->th_stuff; 247 strlcpy(bp, filename, sizeof(buf) - size); 248 bp += strlen(filename); 249 *bp = 0; 250 bp++; 251 size += strlen(filename) + 1; 252 253 strlcpy(bp, mode, sizeof(buf) - size); 254 bp += strlen(mode); 255 *bp = 0; 256 bp++; 257 size += strlen(mode) + 1; 258 259 if (options_rfc_enabled) { 260 options_set_request(OPT_TSIZE, "0"); 261 size += make_options(peer, bp, sizeof(buf) - size); 262 } 263 264 n = sendto(peer, buf, size, 0, 265 (struct sockaddr *)&peer_sock, peer_sock.ss_len); 266 if (n != size) { 267 tftp_log(LOG_ERR, "send_rrq: %d %s", n, strerror(errno)); 268 return (1); 269 } 270 return (0); 271 } 272 273 /* 274 * Send an OACK packet (option acknowledgement). 275 */ 276 int 277 send_oack(int peer) 278 { 279 struct tftphdr *tp; 280 int size, i, n; 281 char *bp; 282 char buf[MAXPKTSIZE]; 283 284 if (debug & DEBUG_PACKETS) 285 tftp_log(LOG_DEBUG, "Sending OACK"); 286 287 DROPPACKETn("send_oack", 0); 288 289 /* 290 * Send back an options acknowledgement (only the ones with 291 * a reply for) 292 */ 293 tp = (struct tftphdr *)buf; 294 bp = buf + 2; 295 size = sizeof(buf) - 2; 296 tp->th_opcode = htons((u_short)OACK); 297 for (i = 0; options[i].o_type != NULL; i++) { 298 if (options[i].o_reply != NULL) { 299 n = snprintf(bp, size, "%s%c%s", options[i].o_type, 300 0, options[i].o_reply); 301 bp += n+1; 302 size -= n+1; 303 if (size < 0) { 304 tftp_log(LOG_ERR, "oack: buffer overflow"); 305 exit(1); 306 } 307 } 308 } 309 size = bp - buf; 310 311 if (sendto(peer, buf, size, 0, 312 (struct sockaddr *)&peer_sock, peer_sock.ss_len) != size) { 313 tftp_log(LOG_INFO, "send_oack: %s", strerror(errno)); 314 return (1); 315 } 316 317 return (0); 318 } 319 320 /* 321 * Send an ACK packet (acknowledgement). 322 */ 323 int 324 send_ack(int fp, uint16_t block) 325 { 326 struct tftphdr *tp; 327 int size; 328 char buf[MAXPKTSIZE]; 329 330 if (debug & DEBUG_PACKETS) 331 tftp_log(LOG_DEBUG, "Sending ACK for block %d", block); 332 333 DROPPACKETn("send_ack", 0); 334 335 tp = (struct tftphdr *)buf; 336 size = sizeof(buf) - 2; 337 tp->th_opcode = htons((u_short)ACK); 338 tp->th_block = htons((u_short)block); 339 size = 4; 340 341 if (sendto(fp, buf, size, 0, 342 (struct sockaddr *)&peer_sock, peer_sock.ss_len) != size) { 343 tftp_log(LOG_INFO, "send_ack: %s", strerror(errno)); 344 return (1); 345 } 346 347 return (0); 348 } 349 350 /* 351 * Send a DATA packet 352 */ 353 int 354 send_data(int peer, uint16_t block, char *data, int size) 355 { 356 char buf[MAXPKTSIZE]; 357 struct tftphdr *pkt; 358 int n; 359 360 if (debug & DEBUG_PACKETS) 361 tftp_log(LOG_DEBUG, "Sending DATA packet %d of %d bytes", 362 block, size); 363 364 DROPPACKETn("send_data", 0); 365 366 pkt = (struct tftphdr *)buf; 367 368 pkt->th_opcode = htons((u_short)DATA); 369 pkt->th_block = htons((u_short)block); 370 memcpy(pkt->th_data, data, size); 371 372 n = send_packet(peer, block, (char *)pkt, size + 4); 373 return (n); 374 } 375 376 377 /* 378 * Receive a packet 379 * 380 * If timeout is negative, no error will be logged on timeout. 381 */ 382 int 383 receive_packet(int peer, char *data, int size, struct sockaddr_storage *from, 384 int timeout) 385 { 386 struct pollfd pfd; 387 struct tftphdr *pkt; 388 struct sockaddr_storage from_local; 389 struct sockaddr_storage *pfrom; 390 socklen_t fromlen; 391 int n; 392 393 if (debug & DEBUG_PACKETS) 394 tftp_log(LOG_DEBUG, 395 "Waiting %d seconds for packet", timeoutpacket); 396 397 pkt = (struct tftphdr *)data; 398 399 pfd.fd = peer; 400 pfd.events = POLLIN; 401 if (poll(&pfd, 1, 1000 * (timeout < 0 ? -timeout : timeout)) < 1) { 402 if (timeout > 0) 403 tftp_log(LOG_ERR, "receive_packet: timeout"); 404 return (RP_TIMEOUT); 405 } 406 407 pfrom = (from == NULL) ? &from_local : from; 408 fromlen = sizeof(*pfrom); 409 n = recvfrom(peer, data, size, 0, (struct sockaddr *)pfrom, &fromlen); 410 411 DROPPACKETn("receive_packet", RP_TIMEOUT); 412 413 if (n < 0) { 414 /* No idea what could have happened if it isn't a timeout */ 415 tftp_log(LOG_ERR, "receive_packet: %s", strerror(errno)); 416 return (RP_RECVFROM); 417 } 418 if (n < 4) { 419 tftp_log(LOG_ERR, 420 "receive_packet: packet too small (%d bytes)", n); 421 return (RP_TOOSMALL); 422 } 423 424 pkt->th_opcode = ntohs((u_short)pkt->th_opcode); 425 if (pkt->th_opcode == DATA || 426 pkt->th_opcode == ACK) 427 pkt->th_block = ntohs((u_short)pkt->th_block); 428 429 if (pkt->th_opcode == DATA && n > pktsize) { 430 tftp_log(LOG_ERR, "receive_packet: packet too big"); 431 return (RP_TOOBIG); 432 } 433 434 if (((struct sockaddr_in *)(pfrom))->sin_addr.s_addr != 435 ((struct sockaddr_in *)(&peer_sock))->sin_addr.s_addr) { 436 tftp_log(LOG_ERR, 437 "receive_packet: received packet from wrong source"); 438 return (RP_WRONGSOURCE); 439 } 440 441 if (pkt->th_opcode == ERROR) { 442 tftp_log(pkt->th_code == EUNDEF ? LOG_DEBUG : LOG_ERR, 443 "Got ERROR packet: %s", pkt->th_msg); 444 return (RP_ERROR); 445 } 446 447 if (debug & DEBUG_PACKETS) 448 tftp_log(LOG_DEBUG, "Received %d bytes in a %s packet", 449 n, packettype(pkt->th_opcode)); 450 451 return n - 4; 452 } 453