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(&current_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