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 static 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, "Artificial 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, "Artificial 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 91 if (error == 0) 92 return ("success"); 93 for (pe = errmsgs; pe->e_code >= 0; pe++) 94 if (pe->e_code == error) 95 return (pe->e_msg); 96 snprintf(ebuf, sizeof(ebuf), "error %d", error); 97 return (ebuf); 98 } 99 100 static int 101 send_packet(int peer, uint16_t block, char *pkt, int size) 102 { 103 int i; 104 int t = 1; 105 106 for (i = 0; i < 12 ; i++) { 107 DROPPACKETn("send_packet", 0); 108 109 if (sendto(peer, pkt, size, 0, (struct sockaddr *)&peer_sock, 110 peer_sock.ss_len) == size) { 111 if (i) 112 tftp_log(LOG_ERR, 113 "%s block %d, attempt %d successful", 114 packettype(ntohs(((struct tftphdr *) 115 (pkt))->th_opcode)), block, i); 116 return (0); 117 } 118 tftp_log(LOG_ERR, 119 "%s block %d, attempt %d failed (Error %d: %s)", 120 packettype(ntohs(((struct tftphdr *)(pkt))->th_opcode)), 121 block, i, errno, strerror(errno)); 122 sleep(t); 123 if (t < 32) 124 t <<= 1; 125 } 126 tftp_log(LOG_ERR, "send_packet: %s", strerror(errno)); 127 return (1); 128 } 129 130 /* 131 * Send an ERROR packet (error message). 132 * Error code passed in is one of the 133 * standard TFTP codes, or a UNIX errno 134 * offset by 100. 135 */ 136 void 137 send_error(int peer, int error) 138 { 139 struct tftphdr *tp; 140 int length; 141 struct errmsg *pe; 142 char buf[MAXPKTSIZE]; 143 144 if (debug&DEBUG_PACKETS) 145 tftp_log(LOG_DEBUG, "Sending ERROR %d", error); 146 147 DROPPACKET("send_error"); 148 149 tp = (struct tftphdr *)buf; 150 tp->th_opcode = htons((u_short)ERROR); 151 tp->th_code = htons((u_short)error); 152 for (pe = errmsgs; pe->e_code >= 0; pe++) 153 if (pe->e_code == error) 154 break; 155 if (pe->e_code < 0) { 156 pe->e_msg = strerror(error - 100); 157 tp->th_code = EUNDEF; /* set 'undef' errorcode */ 158 } 159 strcpy(tp->th_msg, pe->e_msg); 160 length = strlen(pe->e_msg); 161 tp->th_msg[length] = '\0'; 162 length += 5; 163 164 if (debug&DEBUG_PACKETS) 165 tftp_log(LOG_DEBUG, "Sending ERROR %d: %s", error, tp->th_msg); 166 167 if (sendto(peer, buf, length, 0, 168 (struct sockaddr *)&peer_sock, peer_sock.ss_len) != length) 169 tftp_log(LOG_ERR, "send_error: %s", strerror(errno)); 170 } 171 172 /* 173 * Send an WRQ packet (write request). 174 */ 175 int 176 send_wrq(int peer, char *filename, char *mode) 177 { 178 int n; 179 struct tftphdr *tp; 180 char *bp; 181 char buf[MAXPKTSIZE]; 182 int size; 183 184 if (debug&DEBUG_PACKETS) 185 tftp_log(LOG_DEBUG, "Sending WRQ: filename: '%s', mode '%s'", 186 filename, mode 187 ); 188 189 DROPPACKETn("send_wrq", 1); 190 191 tp = (struct tftphdr *)buf; 192 tp->th_opcode = htons((u_short)WRQ); 193 size = 2; 194 195 bp = tp->th_stuff; 196 strcpy(bp, filename); 197 bp += strlen(filename); 198 *bp = 0; 199 bp++; 200 size += strlen(filename) + 1; 201 202 strcpy(bp, mode); 203 bp += strlen(mode); 204 *bp = 0; 205 bp++; 206 size += strlen(mode) + 1; 207 208 if (options_rfc_enabled) 209 size += make_options(peer, bp, sizeof(buf) - size); 210 211 n = sendto(peer, buf, size, 0, 212 (struct sockaddr *)&peer_sock, peer_sock.ss_len); 213 if (n != size) { 214 tftp_log(LOG_ERR, "send_wrq: %s", strerror(errno)); 215 return (1); 216 } 217 return (0); 218 } 219 220 /* 221 * Send an RRQ packet (write request). 222 */ 223 int 224 send_rrq(int peer, char *filename, char *mode) 225 { 226 int n; 227 struct tftphdr *tp; 228 char *bp; 229 char buf[MAXPKTSIZE]; 230 int size; 231 232 if (debug&DEBUG_PACKETS) 233 tftp_log(LOG_DEBUG, "Sending RRQ: filename: '%s', mode '%s'", 234 filename, mode 235 ); 236 237 DROPPACKETn("send_rrq", 1); 238 239 tp = (struct tftphdr *)buf; 240 tp->th_opcode = htons((u_short)RRQ); 241 size = 2; 242 243 bp = tp->th_stuff; 244 strcpy(bp, filename); 245 bp += strlen(filename); 246 *bp = 0; 247 bp++; 248 size += strlen(filename) + 1; 249 250 strcpy(bp, mode); 251 bp += strlen(mode); 252 *bp = 0; 253 bp++; 254 size += strlen(mode) + 1; 255 256 if (options_rfc_enabled) { 257 options[OPT_TSIZE].o_request = strdup("0"); 258 size += make_options(peer, bp, sizeof(buf) - size); 259 } 260 261 n = sendto(peer, buf, size, 0, 262 (struct sockaddr *)&peer_sock, peer_sock.ss_len); 263 if (n != size) { 264 tftp_log(LOG_ERR, "send_rrq: %d %s", n, strerror(errno)); 265 return (1); 266 } 267 return (0); 268 } 269 270 /* 271 * Send an OACK packet (option acknowledgement). 272 */ 273 int 274 send_oack(int peer) 275 { 276 struct tftphdr *tp; 277 int size, i, n; 278 char *bp; 279 char buf[MAXPKTSIZE]; 280 281 if (debug&DEBUG_PACKETS) 282 tftp_log(LOG_DEBUG, "Sending OACK"); 283 284 DROPPACKETn("send_oack", 0); 285 286 /* 287 * Send back an options acknowledgement (only the ones with 288 * a reply for) 289 */ 290 tp = (struct tftphdr *)buf; 291 bp = buf + 2; 292 size = sizeof(buf) - 2; 293 tp->th_opcode = htons((u_short)OACK); 294 for (i = 0; options[i].o_type != NULL; i++) { 295 if (options[i].o_reply != NULL) { 296 n = snprintf(bp, size, "%s%c%s", options[i].o_type, 297 0, options[i].o_reply); 298 bp += n+1; 299 size -= n+1; 300 if (size < 0) { 301 tftp_log(LOG_ERR, "oack: buffer overflow"); 302 exit(1); 303 } 304 } 305 } 306 size = bp - buf; 307 308 if (sendto(peer, buf, size, 0, 309 (struct sockaddr *)&peer_sock, peer_sock.ss_len) != size) { 310 tftp_log(LOG_INFO, "send_oack: %s", strerror(errno)); 311 return (1); 312 } 313 314 return (0); 315 } 316 317 /* 318 * Send an ACK packet (acknowledgement). 319 */ 320 int 321 send_ack(int fp, uint16_t block) 322 { 323 struct tftphdr *tp; 324 int size; 325 char buf[MAXPKTSIZE]; 326 327 if (debug&DEBUG_PACKETS) 328 tftp_log(LOG_DEBUG, "Sending ACK for block %d", block); 329 330 DROPPACKETn("send_ack", 0); 331 332 tp = (struct tftphdr *)buf; 333 size = sizeof(buf) - 2; 334 tp->th_opcode = htons((u_short)ACK); 335 tp->th_block = htons((u_short)block); 336 size = 4; 337 338 if (sendto(fp, buf, size, 0, 339 (struct sockaddr *)&peer_sock, peer_sock.ss_len) != size) { 340 tftp_log(LOG_INFO, "send_ack: %s", strerror(errno)); 341 return (1); 342 } 343 344 return (0); 345 } 346 347 /* 348 * Send a DATA packet 349 */ 350 int 351 send_data(int peer, uint16_t block, char *data, int size) 352 { 353 char buf[MAXPKTSIZE]; 354 struct tftphdr *pkt; 355 int n; 356 357 if (debug&DEBUG_PACKETS) 358 tftp_log(LOG_DEBUG, "Sending DATA packet %d of %d bytes", 359 block, size); 360 361 DROPPACKETn("send_data", 0); 362 363 pkt = (struct tftphdr *)buf; 364 365 pkt->th_opcode = htons((u_short)DATA); 366 pkt->th_block = htons((u_short)block); 367 memcpy(pkt->th_data, data, size); 368 369 n = send_packet(peer, block, (char *)pkt, size + 4); 370 return (n); 371 } 372 373 374 /* 375 * Receive a packet 376 */ 377 static jmp_buf timeoutbuf; 378 379 static void 380 timeout(int sig __unused) 381 { 382 383 /* tftp_log(LOG_DEBUG, "Timeout\n"); Inside a signal handler... */ 384 longjmp(timeoutbuf, 1); 385 } 386 387 int 388 receive_packet(int peer, char *data, int size, struct sockaddr_storage *from, 389 int thistimeout) 390 { 391 struct tftphdr *pkt; 392 struct sockaddr_storage from_local; 393 struct sockaddr_storage *pfrom; 394 socklen_t fromlen; 395 int n; 396 static int waiting; 397 398 if (debug&DEBUG_PACKETS) 399 tftp_log(LOG_DEBUG, 400 "Waiting %d seconds for packet", timeoutpacket); 401 402 pkt = (struct tftphdr *)data; 403 404 waiting = 0; 405 signal(SIGALRM, timeout); 406 setjmp(timeoutbuf); 407 alarm(thistimeout); 408 409 if (waiting > 0) { 410 alarm(0); 411 return (RP_TIMEOUT); 412 } 413 414 if (waiting > 0) { 415 tftp_log(LOG_ERR, "receive_packet: timeout"); 416 alarm(0); 417 return (RP_TIMEOUT); 418 } 419 420 waiting++; 421 pfrom = (from == NULL) ? &from_local : from; 422 fromlen = sizeof(*pfrom); 423 n = recvfrom(peer, data, size, 0, (struct sockaddr *)pfrom, &fromlen); 424 425 alarm(0); 426 427 DROPPACKETn("receive_packet", RP_TIMEOUT); 428 429 if (n < 0) { 430 tftp_log(LOG_ERR, "receive_packet: timeout"); 431 return (RP_TIMEOUT); 432 } 433 434 alarm(0); 435 436 if (n < 0) { 437 /* No idea what could have happened if it isn't a timeout */ 438 tftp_log(LOG_ERR, "receive_packet: %s", strerror(errno)); 439 return (RP_RECVFROM); 440 } 441 if (n < 4) { 442 tftp_log(LOG_ERR, 443 "receive_packet: packet too small (%d bytes)", n); 444 return (RP_TOOSMALL); 445 } 446 447 pkt->th_opcode = ntohs((u_short)pkt->th_opcode); 448 if (pkt->th_opcode == DATA || 449 pkt->th_opcode == ACK) 450 pkt->th_block = ntohs((u_short)pkt->th_block); 451 452 if (pkt->th_opcode == DATA && n > pktsize) { 453 tftp_log(LOG_ERR, "receive_packet: packet too big"); 454 return (RP_TOOBIG); 455 } 456 457 if (((struct sockaddr_in *)(pfrom))->sin_addr.s_addr != 458 ((struct sockaddr_in *)(&peer_sock))->sin_addr.s_addr) { 459 tftp_log(LOG_ERR, 460 "receive_packet: received packet from wrong source"); 461 return (RP_WRONGSOURCE); 462 } 463 464 if (pkt->th_opcode == ERROR) { 465 tftp_log(pkt->th_code == EUNDEF ? LOG_DEBUG : LOG_ERR, 466 "Got ERROR packet: %s", pkt->th_msg); 467 return (RP_ERROR); 468 } 469 470 if (debug&DEBUG_PACKETS) 471 tftp_log(LOG_DEBUG, "Received %d bytes in a %s packet", 472 n, packettype(pkt->th_opcode)); 473 474 return n - 4; 475 } 476