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