1/* hey emacs! -*- Mode: C; c-file-style: "k&r"; indent-tabs-mode: nil -*- */ 2/* 3 * tftpd.c 4 * main server file 5 * 6 * $Id: tftpd.c,v 1.61 2004/02/27 02:05:26 jp Exp $ 7 * 8 * Copyright (c) 2000 Jean-Pierre Lefebvre <helix@step.polymtl.ca> 9 * and Remi Lefebvre <remi@debian.org> 10 * 11 * atftp is free software; you can redistribute them and/or modify them 12 * under the terms of the GNU General Public License as published by the 13 * Free Software Foundation; either version 2 of the License, or (at your 14 * option) any later version. 15 * 16 */ 17 18#include "config.h" 19 20#include <stdio.h> 21#include <stdlib.h> 22#include <sys/time.h> 23#include <sys/types.h> 24#include <sys/socket.h> 25#include <netinet/in.h> 26#include <arpa/inet.h> 27#include <netdb.h> 28#include <getopt.h> 29#include <unistd.h> 30#include <errno.h> 31#include <signal.h> 32#include <pthread.h> 33#include <string.h> 34#include <pwd.h> 35#include <grp.h> 36#ifdef HAVE_WRAP 37#include <tcpd.h> 38#endif 39#include "tftpd.h" 40#include "tftp_io.h" 41#include "tftp_def.h" 42#include "logger.h" 43#include "options.h" 44#include "stats.h" 45#ifdef HAVE_PCRE 46#include "tftpd_pcre.h" 47#endif 48#ifdef HAVE_MTFTP 49#include "tftpd_mtftp.h" 50#endif 51 52#undef RATE_CONTROL 53 54/* 55 * Global variables set by main when starting. Read-only for threads 56 */ 57int tftpd_max_thread = 100; /* number of concurent thread allowed */ 58int tftpd_timeout = 300; /* number of second of inactivity 59 before exiting */ 60char directory[MAXLEN] = "/tftpboot/"; 61int retry_timeout = S_TIMEOUT; 62 63int tftpd_daemon = 0; /* By default we are started by inetd */ 64int tftpd_daemon_no_fork = 0; /* For who want a false daemon mode */ 65short tftpd_port = 0; /* Port atftpd listen to */ 66char tftpd_addr[MAXLEN] = ""; /* IP address atftpd binds to */ 67 68int tftpd_cancel = 0; /* When true, thread must exit. pthread 69 cancellation point are not used because 70 thread id are not tracked. */ 71char *pidfile = NULL; /* File to write own's pid */ 72 73pthread_t main_thread_id; 74 75/* 76 * Multicast related. These reflect option from command line 77 * argument --mcast-ttl, --mcast-port and --mcast-addr 78 */ 79int mcast_ttl = 1; 80char mcast_addr[MAXLEN] = "239.255.0.0-255"; 81char mcast_port[MAXLEN] = "1758"; 82 83/* 84 * "logging level" is the maximum error level that will get logged. 85 * This can be increased with the -v switch. 86 */ 87int logging_level = LOG_NOTICE; 88char *log_file = NULL; 89 90/* logging level as requested by libwrap */ 91#ifdef HAVE_WRAP 92int allow_severity = LOG_NOTICE; 93int deny_severity = LOG_NOTICE; 94#endif 95 96/* user ID and group ID when running as a daemon */ 97char user_name[MAXLEN] = "nobody"; 98char group_name[MAXLEN] = "nogroup"; 99 100/* For special uses, disable source port checking */ 101int source_port_checking = 1; 102 103/* Special feature to make the server switch to new client as soon as 104 the current client timeout in multicast mode */ 105int mcast_switch_client = 0; 106 107int trace = 0; 108 109#ifdef HAVE_PCRE 110/* Use for PCRE file name substitution */ 111tftpd_pcre_self_t *pcre_top = NULL; 112char *pcre_file; 113#endif 114 115#ifdef HAVE_MTFTP 116/* mtftp options */ 117struct mtftp_data *mtftp_data = NULL; 118char mtftp_file[MAXLEN] = ""; 119int mtftp_sport = 75; 120#endif 121 122#ifdef RATE_CONTROL 123int rate = 0; 124#endif 125 126/* 127 * We need a lock on stdin from the time we notice fresh data coming from 128 * stdin to the time the freshly created server thread as read it. 129 */ 130pthread_mutex_t stdin_mutex = PTHREAD_MUTEX_INITIALIZER; 131 132/* 133 * Function defined in this file 134 */ 135void *tftpd_receive_request(void *); 136void signal_handler(int signal); 137int tftpd_cmd_line_options(int argc, char **argv); 138void tftpd_log_options(void); 139int tftpd_pid_file(char *file, int action); 140void tftpd_usage(void); 141 142/* 143 * Main thread. Do required initialisation and then go through a loop 144 * listening for client requests. When a request arrives, we allocate 145 * memory for a thread data structure and start a thread to serve the 146 * new client. If theres no activity for more than 'tftpd_timeout' 147 * seconds, we exit and tftpd must be respawned by inetd. 148 */ 149int main(int argc, char **argv) 150{ 151 fd_set rfds; /* for select */ 152 struct timeval tv; /* for select */ 153 int run = 1; /* while (run) loop */ 154 struct thread_data *new; /* for allocation of new thread_data */ 155 int sockfd; /* used in daemon mode */ 156 struct sockaddr_in sa; /* used in daemon mode */ 157 struct servent *serv; 158 struct passwd *user; 159 struct group *group; 160 161#ifdef HAVE_MTFTP 162 pthread_t mtftp_thread; 163#endif 164 165#ifdef RATE_CONTROL 166 struct timeval current_time = {0, 0}; /* For rate control */ 167 long long current = 0L; 168 struct timeval previous_time = {0, 0}; 169 long long previous = 0L; 170 int rcvbuf; /* size of input socket buffer */ 171#endif 172 int one = 1; /* for setsockopt() */ 173 174 /* 175 * Parse command line options. We parse before verifying 176 * if we are running on a tty or not to make it possible to 177 * verify the command line arguments 178 */ 179 if (tftpd_cmd_line_options(argc, argv) == ERR) 180 exit(1); 181 182 /* 183 * Can't be started from the prompt without explicitely specifying 184 * the --daemon option. 185 */ 186 if (isatty(0) && !(tftpd_daemon)) 187 { 188 tftpd_usage(); 189 exit(1); 190 } 191 192 /* Using syslog facilties through a wrapper. This call divert logs 193 * to a file as specified or to syslog if no file specified. Specifying 194 * /dev/stderr or /dev/stdout will work if the server is started in 195 * daemon mode. 196 */ 197 open_logger("atftpd", log_file, logging_level); 198 logger(LOG_NOTICE, "Advanced Trivial FTP server started (%s)", VERSION); 199 200#ifdef HAVE_PCRE 201 /* */ 202 if (pcre_file) 203 { 204 if ((pcre_top = tftpd_pcre_open(pcre_file)) == NULL) 205 logger(LOG_WARNING, "Failed to initialise PCRE, continuing anyway."); 206 } 207#endif 208 209#ifdef RATE_CONTROL 210 /* Some tuning */ 211 rcvbuf = 128; 212 if (setsockopt(0, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) == 0) 213 { 214 logger(LOG_WARNING, "Failed to set socket option: %s", strerror(errno)); 215 } 216 logger(LOG_DEBUG, "Receive socket buffer set to %d bytes", rcvbuf); 217#endif 218 219 /* 220 * If tftpd is run in daemon mode ... 221 */ 222 if (tftpd_daemon) 223 { 224 /* daemonize here */ 225 if (!tftpd_daemon_no_fork) 226 { 227 if (daemon(0, 0) == -1) 228 exit(2); 229 } 230 231 /* find the port */ 232 if (tftpd_port == 0) 233 { 234 if ((serv = getservbyname("tftp", "udp")) == NULL) 235 { 236 logger(LOG_ERR, "atftpd: udp/tftp, unknown service"); 237 exit(1); 238 } 239 tftpd_port = ntohs(serv->s_port); 240 } 241 /* initialise sockaddr_in structure */ 242 memset(&sa, 0, sizeof(sa)); 243 sa.sin_family = AF_INET; 244 sa.sin_port = htons(tftpd_port); 245 if (strlen(tftpd_addr) > 0) 246 { 247 if (inet_aton(tftpd_addr, &(sa.sin_addr)) == 0) 248 { 249 logger(LOG_ERR, "atftpd: invalid IP address %s", tftpd_addr); 250 exit(1); 251 } 252 } 253 else 254 sa.sin_addr.s_addr = htonl(INADDR_ANY); 255 /* open the socket */ 256 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == 0) 257 { 258 logger(LOG_ERR, "atftpd: can't open socket"); 259 exit(1); 260 } 261 /* bind the socket to the desired address and port */ 262 if (bind(sockfd, (struct sockaddr*)&sa, sizeof(sa)) < 0) 263 { 264 logger(LOG_ERR, "atftpd: can't bind port %s:%d/udp", 265 tftpd_addr, tftpd_port); 266 exit(1); 267 } 268 /* 269 * dup sockfd on 0 only, not 1,2 like inetd do to allow 270 * logging to stderr in pseudo daemon mode (--daemon --no-fork) 271 */ 272 dup2(sockfd, 0); 273 close(sockfd); 274 275 /* release priviliedge */ 276 user = getpwnam(user_name); 277 group = getgrnam(group_name); 278 if (!user || !group) 279 { 280 logger(LOG_ERR, 281 "atftpd: can't change identity to %s.%s, exiting.", 282 user_name, group_name); 283 exit(1); 284 } 285 286 /* write our pid in the specified file before changing user*/ 287 if (pidfile) 288 { 289 if (tftpd_pid_file(pidfile, 1) != OK) 290 exit(1); 291 /* to be able to remove it later */ 292 chown(pidfile, user->pw_uid, group->gr_gid); 293 } 294 295 setgid(group->gr_gid); 296 setuid(user->pw_uid); 297 298 /* Reopen log file now that we changed user, and that we've 299 * open and dup2 the socket. */ 300 open_logger("atftpd", log_file, logging_level); 301 } 302 303 /* We need to retrieve some information from incomming packets */ 304#ifndef __HAIKU__ 305 if (setsockopt(0, SOL_IP, IP_PKTINFO, &one, sizeof(one)) != 0) 306#else 307 if (setsockopt(0, IPPROTO_IP, IP_RECVDSTADDR, &one, sizeof(one)) != 0) 308#endif 309 { 310 logger(LOG_WARNING, "Failed to set socket option: %s", strerror(errno)); 311 } 312 313 /* save main thread ID for proper signal handling */ 314 main_thread_id = pthread_self(); 315 316 /* Register signal handler. */ 317 signal(SIGINT, signal_handler); 318 signal(SIGTERM, signal_handler); 319 320 /* print summary of options */ 321 tftpd_log_options(); 322 323 /* start collecting stats */ 324 stats_start(); 325 326#ifdef HAVE_MTFTP 327 /* start mtftp server thread */ 328 if (strlen(mtftp_file) > 0) 329 { 330 if (!tftpd_daemon) 331 logger(LOG_ERR, "Can't start mtftp server, use --deamon"); 332 else 333 { 334 if ((mtftp_data = tftpd_mtftp_init(mtftp_file)) == NULL) 335 logger(LOG_ERR, "Failled initialise mtftp"); 336 else 337 { 338 mtftp_data->server_port = mtftp_sport; 339 mtftp_data->mcast_ttl = mcast_ttl; 340 mtftp_data->timeout = retry_timeout; 341 mtftp_data->checkport = source_port_checking; 342 mtftp_data->trace = trace; 343 /* Start server thread. */ 344 if (pthread_create(&mtftp_thread, NULL, tftpd_mtftp_server, 345 (void *)mtftp_data) != 0) 346 { 347 logger(LOG_ERR, "Failed to start mtftp server thread"); 348 tftpd_mtftp_clean(mtftp_data); 349 mtftp_data = NULL; 350 } 351 } 352 } 353 } 354#endif 355 356 /* Wait for read or write request and exit if timeout. */ 357 while (run) 358 { 359 /* 360 * inetd dups the socket file descriptor to 0, 1 and 2 so we can 361 * use any of those as the socket fd. We use 0. stdout and stderr 362 * may not be used to print messages. 363 */ 364 FD_ZERO(&rfds); 365 FD_SET(0, &rfds); 366 tv.tv_sec = tftpd_timeout; 367 tv.tv_usec = 0; 368 369 /* We need to lock stdin, and release it when the thread 370 is done reading the request. */ 371 pthread_mutex_lock(&stdin_mutex); 372 373#ifdef RATE_CONTROL 374 /* if we want to implement rate control, we sleep some time here 375 so we cannot exceed the allowed thread/sec. */ 376 if (rate > 0) 377 { 378 gettimeofday(¤t_time, NULL); 379 current = (long long)current_time.tv_sec*1000000L + current_time.tv_usec; 380 logger(LOG_DEBUG, "time from previous request: %Ld", current - previous); 381 if ((current - previous) < (60L*1000000L / (long long)rate)) 382 { 383 logger(LOG_DEBUG, "will sleep for rate control (%Ld)", 384 (60L*1000000L / (long long)rate) - (current - previous)); 385 usleep((60L*1000000L / (long long)rate) - (current - previous)); 386 } 387 } 388#endif 389 390 /* A timeout of 0 is interpreted as infinity. Wait for incomming 391 packets */ 392 if (!tftpd_cancel) 393 { 394 if ((tftpd_timeout == 0) || (tftpd_daemon)) 395 select(FD_SETSIZE, &rfds, NULL, NULL, NULL); 396 else 397 select(FD_SETSIZE, &rfds, NULL, NULL, &tv); 398 } 399 400#ifdef RATE_CONTROL 401 /* get the time we receive this packet */ 402 if (rate > 0) 403 { 404 gettimeofday(&previous_time, NULL); 405 previous = (long long)previous_time.tv_sec*1000000L + 406 previous_time.tv_usec; 407 } 408#endif 409 410 if (FD_ISSET(0, &rfds) && (!tftpd_cancel)) 411 { 412 /* Allocate memory for thread_data structure. */ 413 if ((new = calloc(1, sizeof(struct thread_data))) == NULL) 414 { 415 logger(LOG_ERR, "%s: %d: Memory allocation failed", 416 __FILE__, __LINE__); 417 exit(1); 418 } 419 420 /* 421 * Initialisation of thread_data structure. 422 */ 423 pthread_mutex_init(&new->client_mutex, NULL); 424 new->sockfd = 0; 425 426 /* Allocate data buffer for tftp transfer. */ 427 if ((new->data_buffer = malloc((size_t)SEGSIZE + 4)) == NULL) 428 { 429 logger(LOG_ERR, "%s: %d: Memory allocation failed", 430 __FILE__, __LINE__); 431 exit(1); 432 } 433 new->data_buffer_size = SEGSIZE + 4; 434 435 /* Allocate memory for tftp option structure. */ 436 if ((new->tftp_options = 437 malloc(sizeof(tftp_default_options))) == NULL) 438 { 439 logger(LOG_ERR, "%s: %d: Memory allocation failed", 440 __FILE__, __LINE__); 441 exit(1); 442 } 443 444 /* Copy default options. */ 445 memcpy(new->tftp_options, tftp_default_options, 446 sizeof(tftp_default_options)); 447 448 /* default timeout */ 449 new->timeout = retry_timeout; 450 451 /* wheter we check source port or not */ 452 new->checkport = source_port_checking; 453 454 /* other options */ 455 new->mcast_switch_client = mcast_switch_client; 456 new->trace = trace; 457 458 /* default ttl for multicast */ 459 new->mcast_ttl = mcast_ttl; 460 461 /* Allocate memory for a client structure. */ 462 if ((new->client_info = 463 calloc(1, sizeof(struct client_info))) == NULL) 464 { 465 logger(LOG_ERR, "%s: %d: Memory allocation failed", 466 __FILE__, __LINE__); 467 exit(1); 468 } 469 new->client_info->done = 0; 470 new->client_info->next = NULL; 471 472 /* Start a new server thread. */ 473 if (pthread_create(&new->tid, NULL, tftpd_receive_request, 474 (void *)new) != 0) 475 { 476 logger(LOG_ERR, "Failed to start new thread"); 477 free(new); 478 pthread_mutex_unlock(&stdin_mutex); 479 } 480 } 481 else 482 { 483 pthread_mutex_unlock(&stdin_mutex); 484 485 /* Either select return after timeout of we've been killed. In the first case 486 we wait for server thread to finish, in the other we kill them */ 487 if (tftpd_cancel) 488 tftpd_list_kill_threads(); 489 490 while (tftpd_list_num_of_thread() != 0) 491 sleep(1); 492 493 run = 0; 494 if (tftpd_daemon || (tftpd_timeout == 0)) 495 logger(LOG_NOTICE, "atftpd terminating"); 496 else 497 logger(LOG_NOTICE, 498 "atftpd terminating after %d seconds", 499 tftpd_timeout); 500 } 501 } 502 503 /* close all open file descriptors */ 504 close(0); 505 close(1); 506 close(2); 507 508#ifdef HAVE_MTFTP 509 /* stop the mtftp threads */ 510 if (mtftp_data) 511 { 512 /* kill mtftp serving thread */ 513 tftpd_mtftp_kill_threads(mtftp_data); 514 /* kill mtftp main thread */ 515 pthread_kill(mtftp_thread, SIGTERM); 516 pthread_join(mtftp_thread, NULL); 517 } 518#endif 519 520 /* stop collecting stats and print them*/ 521 stats_end(); 522 stats_print(); 523 524#ifdef HAVE_PCRE 525 /* remove allocated memory for tftpd_pcre */ 526 if (pcre_top) 527 tftpd_pcre_close(pcre_top); 528#endif 529 530 /* some cleaning */ 531 if (log_file) 532 free(log_file); 533#ifdef HAVE_PCRE 534 if (pcre_file) 535 free(pcre_file); 536#endif 537 538 /* remove PID file */ 539 if (pidfile) 540 tftpd_pid_file(pidfile, 0); 541 542 logger(LOG_NOTICE, "Main thread exiting"); 543 close_logger(); 544 exit(0); 545} 546 547/* 548 * This function handles the initial connection with a client. It reads 549 * the request from stdin and then release the stdin_mutex, so the main 550 * thread may listen for new clients. After that, we process options and 551 * call the sending or receiving function. 552 * 553 * arg is a thread_data structure pointer for that thread. 554 */ 555void *tftpd_receive_request(void *arg) 556{ 557 struct thread_data *data = (struct thread_data *)arg; 558 559 int retval; /* hold return value for testing */ 560 int data_size; /* returned size by recvfrom */ 561 char string[MAXLEN]; /* hold the string we pass to the logger */ 562 int num_of_threads; 563 int abort = 0; /* 1 if we need to abort because the maximum 564 number of threads have been reached*/ 565 struct sockaddr_in to; /* destination of client's packet */ 566 socklen_t len = sizeof(struct sockaddr); 567 568#ifdef HAVE_WRAP 569 char client_addr[16]; 570#endif 571 572 /* Detach ourself. That way the main thread does not have to 573 * wait for us with pthread_join. */ 574 pthread_detach(pthread_self()); 575 576 /* Read the first packet from stdin. */ 577 data_size = data->data_buffer_size; 578 retval = tftp_get_packet(0, -1, NULL, &data->client_info->client, NULL, 579 &to, data->timeout, &data_size, 580 data->data_buffer); 581 582 /* now unlock stdin */ 583 pthread_mutex_unlock(&stdin_mutex); 584 585 /* Verify the number of threads */ 586 if ((num_of_threads = tftpd_list_num_of_thread()) >= tftpd_max_thread) 587 { 588 logger(LOG_INFO, "Maximum number of threads reached: %d", 589 num_of_threads); 590 abort = 1; 591 } 592 593#ifdef HAVE_WRAP 594 if (!abort) 595 { 596 /* Verify the client has access. We don't look for the name but 597 rely only on the IP address for that. */ 598 inet_ntop(AF_INET, &data->client_info->client.sin_addr, 599 client_addr, sizeof(client_addr)); 600 if (hosts_ctl("in.tftpd", STRING_UNKNOWN, client_addr, 601 STRING_UNKNOWN) == 0) 602 { 603 logger(LOG_ERR, "Connection refused from %s", client_addr); 604 abort = 1; 605 } 606 } 607#endif 608 609 /* Add this new thread structure to the list. */ 610 if (!abort) 611 stats_new_thread(tftpd_list_add(data)); 612 613 /* if the maximum number of thread is reached, too bad we abort. */ 614 if (abort) 615 stats_abort_locked(); 616 else 617 { 618 /* open a socket for client communication */ 619 data->sockfd = socket(PF_INET, SOCK_DGRAM, 0); 620 to.sin_family = AF_INET; 621 to.sin_port = 0; 622 if (data->sockfd > 0) 623 { 624 /* bind the socket to the interface */ 625 if (bind(data->sockfd, (struct sockaddr *)&to, len) == -1) 626 { 627 logger(LOG_ERR, "bind: %s", strerror(errno)); 628 retval = ABORT; 629 } 630 /* read back assigned port */ 631 len = sizeof(struct sockaddr); 632 if (getsockname(data->sockfd, (struct sockaddr *)&to, &len) == -1) 633 { 634 logger(LOG_ERR, "getsockname: %s", strerror(errno)); 635 retval = ABORT; 636 } 637 /* connect the socket, faster for kernel operation */ 638 if (connect(data->sockfd, 639 (struct sockaddr *)&data->client_info->client, 640 sizeof(data->client_info->client)) == -1) 641 { 642 logger(LOG_ERR, "connect: %s", strerror(errno)); 643 retval = ABORT; 644 } 645 logger(LOG_DEBUG, "Creating new socket: %s:%d", 646 inet_ntoa(to.sin_addr), ntohs(to.sin_port)); 647 648 /* read options from request */ 649 opt_parse_request(data->data_buffer, data_size, 650 data->tftp_options); 651 opt_request_to_string(data->tftp_options, string, MAXLEN); 652 } 653 else 654 { 655 retval = ABORT; 656 } 657 658 /* Analyse the request. */ 659 switch (retval) 660 { 661 case GET_RRQ: 662 logger(LOG_NOTICE, "Serving %s to %s:%d", 663 data->tftp_options[OPT_FILENAME].value, 664 inet_ntoa(data->client_info->client.sin_addr), 665 ntohs(data->client_info->client.sin_port)); 666 if (data->trace) 667 logger(LOG_DEBUG, "received RRQ <%s>", string); 668 if (tftpd_send_file(data) == OK) 669 stats_send_locked(); 670 else 671 stats_err_locked(); 672 break; 673 case GET_WRQ: 674 logger(LOG_NOTICE, "Fetching from %s to %s", 675 inet_ntoa(data->client_info->client.sin_addr), 676 data->tftp_options[OPT_FILENAME].value); 677 if (data->trace) 678 logger(LOG_DEBUG, "received WRQ <%s>", string); 679 if (tftpd_receive_file(data) == OK) 680 stats_recv_locked(); 681 else 682 stats_err_locked(); 683 break; 684 case ERR: 685 logger(LOG_ERR, "Error from tftp_get_packet"); 686 tftp_send_error(data->sockfd, &data->client_info->client, 687 EUNDEF, data->data_buffer, data->data_buffer_size); 688 if (data->trace) 689 logger(LOG_DEBUG, "sent ERROR <code: %d, msg: %s>", EUNDEF, 690 tftp_errmsg[EUNDEF]); 691 stats_err_locked(); 692 break; 693 case ABORT: 694 if (data->trace) 695 logger(LOG_ERR, "thread aborting"); 696 stats_err_locked(); 697 break; 698 default: 699 logger(LOG_NOTICE, "Invalid request <%d> from %s", 700 retval, inet_ntoa(data->client_info->client.sin_addr)); 701 tftp_send_error(data->sockfd, &data->client_info->client, 702 EBADOP, data->data_buffer, data->data_buffer_size); 703 if (data->trace) 704 logger(LOG_DEBUG, "sent ERROR <code: %d, msg: %s>", EBADOP, 705 tftp_errmsg[EBADOP]); 706 stats_err_locked(); 707 } 708 } 709 710 /* make sure all data is sent to the network */ 711 if (data->sockfd) 712 { 713 fsync(data->sockfd); 714 close(data->sockfd); 715 } 716 717 /* update stats */ 718 stats_thread_usage_locked(); 719 720 /* Remove the thread_data structure from the list, if it as been 721 added. */ 722 if (!abort) 723 tftpd_list_remove(data); 724 725 /* Free memory. */ 726 if (data->data_buffer) 727 free(data->data_buffer); 728 729 free(data->tftp_options); 730 731 /* if the thread had reserverd a multicast IP/Port, deallocate it */ 732 if (data->mc_port != 0) 733 tftpd_mcast_free_tid(data->mc_addr, data->mc_port); 734 735 /* this function take care of freeing allocated memory by other threads */ 736 tftpd_clientlist_free(data); 737 738 /* free the thread structure */ 739 free(data); 740 741 logger(LOG_INFO, "Server thread exiting"); 742 pthread_exit(NULL); 743} 744 745/* 746 * If we receive signals, we must exit in a clean way. This means 747 * sending an ERROR packet to all clients to terminate the connection. 748 */ 749void signal_handler(int signal) 750{ 751 /* Any thread may receive the signal, always make sure the main thread receive it 752 and cancel other threads itself. However, if tftpd_cancel already set, just 753 ignore the signal since the master thread as already got the signal. */ 754 if (pthread_self() != main_thread_id) 755 { 756 if (tftpd_cancel == 0) 757 { 758 logger(LOG_ERR, "Forwarding signal to main thread"); 759 pthread_kill(main_thread_id, signal); 760 } 761 return; 762 } 763 764 /* Only signals for the main thread get there */ 765 switch (signal) 766 { 767 case SIGINT: 768 logger(LOG_ERR, "SIGINT received, stopping threads and exiting."); 769 tftpd_cancel = 1; 770 break; 771 case SIGTERM: 772 logger(LOG_ERR, "SIGTERM received, stopping threads and exiting."); 773 tftpd_cancel = 1; 774 break; 775 default: 776 logger(LOG_WARNING, "Signal %d received, ignoring.", signal); 777 break; 778 } 779} 780 781#define OPT_RATE 'R' 782#define OPT_MCAST_TTL '0' 783#define OPT_MCAST_ADDR '1' 784#define OPT_MCAST_PORT '2' 785#define OPT_PCRE '3' 786#define OPT_PCRE_TEST '4' 787#define OPT_PORT_CHECK '5' 788#define OPT_MCAST_SWITCH '6' 789#define OPT_MTFTP '7' 790#define OPT_MTFTP_PORT '8' 791#define OPT_TRACE '9' 792 793/* 794 * Parse the command line using the standard getopt function. 795 */ 796int tftpd_cmd_line_options(int argc, char **argv) 797{ 798 int c; 799 char *tmp; 800#ifdef HAVE_PCRE 801 char string[MAXLEN], out[MAXLEN]; 802#endif 803 static struct option options[] = { 804 { "tftpd-timeout", 1, NULL, 't' }, 805 { "retry-timeout", 1, NULL, 'r' }, 806 { "maxthread", 1, NULL, 'm' }, 807#ifdef RATE_CONTROL 808 { "rate", 1, NULL, OPT_RATE }, 809#endif 810 { "verbose", 2, NULL, 'v' }, 811 { "trace", 0, NULL, OPT_TRACE }, 812 { "no-timeout", 0, NULL, 'T' }, 813 { "no-tsize", 0, NULL, 'S' }, 814 { "no-blksize", 0, NULL, 'B' }, 815 { "no-multicast", 0, NULL, 'M' }, 816 { "logfile", 1, NULL, 'L' }, 817 { "pidfile", 1, NULL, 'I'}, 818 { "daemon", 0, NULL, 'D' }, 819 { "no-fork", 0, NULL, 'N'}, 820 { "user", 1, NULL, 'U'}, 821 { "group", 1, NULL, 'G'}, 822 { "port", 1, NULL, 'P' }, 823 { "bind-address", 1, NULL, 'A'}, 824 { "mcast-ttl", 1, NULL, OPT_MCAST_TTL }, 825 { "mcast_ttl", 1, NULL, OPT_MCAST_TTL }, 826 { "mcast-addr", 1, NULL, OPT_MCAST_ADDR }, 827 { "mcast_addr", 1, NULL, OPT_MCAST_ADDR }, 828 { "mcast-port", 1, NULL, OPT_MCAST_PORT }, 829 { "mcast_port", 1, NULL, OPT_MCAST_PORT }, 830#ifdef HAVE_PCRE 831 { "pcre", 1, NULL, OPT_PCRE }, 832 { "pcre-test", 1, NULL, OPT_PCRE_TEST }, 833#endif 834#ifdef HAVE_MTFTP 835 { "mtftp", 1, NULL, OPT_MTFTP }, 836 { "mtftp-port", 1, NULL, OPT_MTFTP_PORT }, 837#endif 838 { "no-source-port-checking", 0, NULL, OPT_PORT_CHECK }, 839 { "mcast-switch-client", 0, NULL, OPT_MCAST_SWITCH }, 840 { "version", 0, NULL, 'V' }, 841 { "help", 0, NULL, 'h' }, 842 { 0, 0, 0, 0 } 843 }; 844 845 while ((c = getopt_long(argc, argv, "t:r:m:v::Vh", 846 options, NULL)) != EOF) 847 { 848 switch (c) 849 { 850 case 't': 851 tftpd_timeout = atoi(optarg); 852 break; 853 case 'r': 854 retry_timeout = atoi(optarg); 855 break; 856 case 'm': 857 tftpd_max_thread = atoi(optarg); 858 break; 859#ifdef RATE_CONTROL 860 case OPT_RATE: 861 rate = atoi(optarg); 862 break; 863#endif 864 case 'v': 865 if (optarg) 866 logging_level = atoi(optarg); 867 else 868 logging_level++; 869#ifdef HAVE_WRAP 870 allow_severity = logging_level; 871 deny_severity = logging_level; 872#endif 873 break; 874 case OPT_TRACE: 875 trace = 1; 876 break; 877 case 'T': 878 tftp_default_options[OPT_TIMEOUT].enabled = 0; 879 break; 880 case 'S': 881 tftp_default_options[OPT_TSIZE].enabled = 0; 882 break; 883 case 'B': 884 tftp_default_options[OPT_BLKSIZE].enabled = 0; 885 break; 886 case 'M': 887 tftp_default_options[OPT_MULTICAST].enabled = 0; 888 break; 889 case 'L': 890 log_file = strdup(optarg); 891 break; 892 case 'I': 893 pidfile = strdup(optarg); 894 break; 895 case 'D': 896 tftpd_daemon = 1; 897 break; 898 case 'N': 899 tftpd_daemon_no_fork = 1; 900 break; 901 case 'U': 902 tmp = strtok(optarg, "."); 903 if (tmp != NULL) 904 Strncpy(user_name, tmp, MAXLEN); 905 tmp = strtok(NULL, ""); 906 if (tmp != NULL) 907 Strncpy(group_name, optarg, MAXLEN); 908 break; 909 case 'G': 910 Strncpy(group_name, optarg, MAXLEN); 911 break; 912 case 'P': 913 tftpd_port = (short)atoi(optarg); 914 break; 915 case 'A': 916 Strncpy(tftpd_addr, optarg, MAXLEN); 917 break; 918 case OPT_MCAST_TTL: 919 mcast_ttl = atoi(optarg); 920 break; 921 case OPT_MCAST_ADDR: 922 Strncpy(mcast_addr, optarg, MAXLEN); 923 break; 924 case '2': 925 Strncpy(mcast_port, optarg, MAXLEN); 926 break; 927#ifdef HAVE_PCRE 928 case OPT_PCRE: 929 pcre_file = strdup(optarg); 930 break; 931 case OPT_PCRE_TEST: 932 /* test the pattern file */ 933 if ((pcre_top = tftpd_pcre_open(optarg)) == NULL) 934 { 935 fprintf(stderr, "Failed to initialise PCRE with file %s", optarg); 936 exit(1); 937 } 938 /* run test */ 939 while (1) 940 { 941 if (isatty(0)) 942 printf("> "); 943 if (fgets(string, MAXLEN, stdin) == NULL) 944 { 945 tftpd_pcre_close(pcre_top); 946 exit(0); 947 } 948 /* exit on empty line */ 949 if (string[0] == '\n') 950 { 951 tftpd_pcre_close(pcre_top); 952 exit(0); 953 } 954 /* remove \n from input */ 955 string[strlen(string) - 1] = '\0'; 956 /* do the substitution */ 957 if (tftpd_pcre_sub(pcre_top, out, MAXLEN, string) < 0) 958 printf("Substitution: \"%s\" -> \"\"\n", string); 959 else 960 printf("Substitution: \"%s\" -> \"%s\"\n", string, out); 961 } 962#endif 963 case OPT_PORT_CHECK: 964 source_port_checking = 0; 965 break; 966 case OPT_MCAST_SWITCH: 967 mcast_switch_client = 1; 968 break; 969#ifdef HAVE_MTFTP 970 case OPT_MTFTP: 971 Strncpy(mtftp_file, optarg, MAXLEN); 972 break; 973 case OPT_MTFTP_PORT: 974 mtftp_sport = atoi(optarg); 975 break; 976#endif 977 case 'V': 978 printf("atftp-%s (server)\n", VERSION); 979 exit(0); 980 case 'h': 981 tftpd_usage(); 982 exit(0); 983 case '?': 984 exit(1); 985 break; 986 } 987 } 988 989 /* verify that only one arguement is left */ 990 if (optind < argc) 991 Strncpy(directory, argv[optind], MAXLEN); 992 /* make sure the last caracter is a / */ 993 if (directory[strlen(directory)] != '/') 994 strcat(directory, "/"); 995 /* build multicast address/port range */ 996 if (tftpd_mcast_parse_opt(mcast_addr, mcast_port) != OK) 997 exit(1); 998 return OK; 999} 1000 1001/* 1002 * Output option to the syslog. 1003 */ 1004void tftpd_log_options(void) 1005{ 1006 if (tftpd_daemon == 1) 1007 { 1008 logger(LOG_INFO, " running in daemon mode on port %d", tftpd_port); 1009 if (strlen(tftpd_addr) > 0) 1010 logger(LOG_INFO, " bound to IP address %s only", tftpd_addr); 1011 } 1012 else 1013 logger(LOG_INFO, " started by inetd"); 1014 logger(LOG_INFO, " logging level: %d", logging_level); 1015 if (trace) 1016 logger(LOG_INFO, " trace enabled"); 1017 logger(LOG_INFO, " directory: %s", directory); 1018 logger(LOG_INFO, " user: %s.%s", user_name, group_name); 1019 logger(LOG_INFO, " log file: %s", (log_file==NULL) ? "syslog":log_file); 1020 if (pidfile) 1021 logger(LOG_INFO, " pid file: %s", pidfile); 1022 if (tftpd_daemon == 1) 1023 logger(LOG_INFO, " server timeout: Not used"); 1024 else 1025 logger(LOG_INFO, " server timeout: %d", tftpd_timeout); 1026 logger(LOG_INFO, " tftp retry timeout: %d", retry_timeout); 1027 logger(LOG_INFO, " maximum number of thread: %d", tftpd_max_thread); 1028#ifdef RATE_CONTROL 1029 if (rate > 0) 1030 logger(LOG_INFO, " request per minute limit: %d", rate); 1031 else 1032 logger(LOG_INFO, " request per minute limit: ---"); 1033#endif 1034 logger(LOG_INFO, " option timeout: %s", 1035 tftp_default_options[OPT_TIMEOUT].enabled ? "enabled":"disabled"); 1036 logger(LOG_INFO, " option tzise: %s", 1037 tftp_default_options[OPT_TSIZE].enabled ? "enabled":"disabled"); 1038 logger(LOG_INFO, " option blksize: %s", 1039 tftp_default_options[OPT_BLKSIZE].enabled ? "enabled":"disabled"); 1040 logger(LOG_INFO, " option multicast: %s", 1041 tftp_default_options[OPT_MULTICAST].enabled ? "enabled":"disabled"); 1042 logger(LOG_INFO, " address range: %s", mcast_addr); 1043 logger(LOG_INFO, " port range: %s", mcast_port); 1044#ifdef HAVE_PCRE 1045 if (pcre_top) 1046 logger(LOG_INFO, " PCRE: using file: %s", pcre_file); 1047#endif 1048#ifdef HAVE_MTFTP 1049 if (strcmp(mtftp_file, "") != 0) 1050 { 1051 logger(LOG_INFO, " mtftp: using file: %s", mtftp_file); 1052 logger(LOG_INFO, " mtftp: listenning on port %d", mtftp_sport); 1053 } 1054#endif 1055 if (mcast_switch_client) 1056 logger(LOG_INFO, " --mcast-switch-client turned on"); 1057 if (!source_port_checking) 1058 logger(LOG_INFO, " --no-source-port-checking turned on"); 1059} 1060 1061/* 1062 * 1063 */ 1064int tftpd_pid_file(char *file, int action) 1065{ 1066 FILE *fp; 1067 pid_t pid; 1068 1069 if (action) 1070 { 1071 /* check if file exist */ 1072 if ((fp = fopen(file, "r")) != NULL) 1073 { 1074 logger(LOG_NOTICE, "pid file already exist, overwriting"); 1075 fclose(fp); 1076 } 1077 /* open file for writing */ 1078 if ((fp = fopen(file, "w")) == NULL) 1079 { 1080 logger(LOG_ERR, "error writing PID to file %s\n", file); 1081 return ERR; 1082 } 1083 /* write it */ 1084 pid = getpid(); 1085 fprintf(fp, "%d\n", pid); 1086 fclose(fp); 1087 return OK; 1088 } 1089 else 1090 { 1091 /* unlink the pid file */ 1092 if (unlink(file) == -1) 1093 logger(LOG_ERR, "unlink: %s", strerror(errno)); 1094 return OK; 1095 } 1096} 1097 1098/* 1099 * Show a nice usage... 1100 */ 1101void tftpd_usage(void) 1102{ 1103 printf("Usage: tftpd [options] [directory]\n" 1104 " [options] may be:\n" 1105 " -t, --tftpd-timeout <value>: number of second of inactivity" 1106 " before exiting\n" 1107 " -r, --retry-timeout <value>: time to wait a reply before" 1108 " retransmition\n" 1109 " -m, --maxthread <value> : number of concurrent thread" 1110 " allowed\n" 1111#ifdef RATE_CONTROL 1112 " --rate <value> : number of request per minute limit\n" 1113#endif 1114 " -v, --verbose [value] : increase or set the level of" 1115 " output messages\n" 1116 " --trace : log all sent and received packets\n" 1117 " --no-timeout : disable 'timeout' from RFC2349\n" 1118 " --no-tisize : disable 'tsize' from RFC2349\n" 1119 " --no-blksize : disable 'blksize' from RFC2348\n" 1120 " --no-multicast : disable 'multicast' from RFC2090\n" 1121 " --logfile <file> : logfile to log logs to ;-)\n" 1122 " --pidfile <file> : write PID to this file\n" 1123 " --daemon : run atftpd standalone (no inetd)\n" 1124 " --no-fork : run as a daemon, don't fork\n" 1125 " --user <user[.group]> : default is nobody\n" 1126 " --group <group> : default is nogroup\n" 1127 " --port <port> : port on which atftp listen\n" 1128 " --bind-address <IP> : local address atftpd listen to\n" 1129 " --mcast-ttl : ttl to used for multicast\n" 1130 " --mcast-addr <address list>: list/range of IP address to use\n" 1131 " --mcast-port <port range> : ports to use for multicast" 1132 " transfer\n" 1133#ifdef HAVE_PCRE 1134 " --pcre <file> : use this file for pattern replacement\n" 1135 " --pcre-test <file> : just test pattern file, not starting server\n" 1136#endif 1137#ifdef HAVE_MTFTP 1138 " --mtftp <file> : mtftp configuration file\n" 1139 " --mtftp-port <port> : port mtftp will listen\n" 1140#endif 1141 " --no-source-port-checking : violate RFC, see man page\n" 1142 " --mcast-switch-client : switch client on first timeout, see man page\n" 1143 " -V, --version : print version information\n" 1144 " -h, --help : print this help\n" 1145 "\n" 1146 " [directory] must be a world readable/writable directories.\n" 1147 " By default /tftpboot is assumed." 1148 "\n"); 1149} 1150