/[LeafOK_CVS]/lbbs/src/net_server.c
ViewVC logotype

Diff of /lbbs/src/net_server.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.7 by sysadm, Fri Oct 22 15:20:32 2004 UTC Revision 1.74 by sysadm, Sat Oct 25 03:11:11 2025 UTC
# Line 1  Line 1 
1  /***************************************************************************  /***************************************************************************
2                            net_server.c  -  description                                                    net_server.c  -  description
3                               -------------------                                                           -------------------
4      begin                : Mon Oct 11 2004          Copyright            : (C) 2004-2025 by Leaflet
5      copyright            : (C) 2004 by Leaflet          Email                : leaflet@leafok.com
     email                : leaflet@leafok.com  
6   ***************************************************************************/   ***************************************************************************/
7    
8  /***************************************************************************  /***************************************************************************
9   *                                                                         *   *                                                                         *
10   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
11   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
12   *   the Free Software Foundation; either version 2 of the License, or     *   *   the Free Software Foundation; either version 3 of the License, or     *
13   *   (at your option) any later version.                                   *   *   (at your option) any later version.                                   *
14   *                                                                         *   *                                                                         *
15   ***************************************************************************/   ***************************************************************************/
16    
17    #include "bbs.h"
18    #include "bbs_main.h"
19  #include "common.h"  #include "common.h"
20    #include "database.h"
21    #include "file_loader.h"
22  #include "io.h"  #include "io.h"
23  #include <sys/socket.h>  #include "init.h"
24    #include "log.h"
25    #include "login.h"
26    #include "menu.h"
27    #include "net_server.h"
28    #include "section_list.h"
29    #include "section_list_loader.h"
30    #include <errno.h>
31    #include <fcntl.h>
32    #include <pty.h>
33    #include <signal.h>
34    #include <stdlib.h>
35    #include <string.h>
36    #include <unistd.h>
37    #include <utmp.h>
38    #include <arpa/inet.h>
39    #include <libssh/callbacks.h>
40    #include <libssh/libssh.h>
41    #include <libssh/server.h>
42  #include <netinet/in.h>  #include <netinet/in.h>
43    #include <sys/epoll.h>
44    #include <sys/socket.h>
45    #include <sys/syscall.h>
46    #include <sys/types.h>
47    #include <sys/wait.h>
48    #include <systemd/sd-daemon.h>
49    
50    #define WAIT_CHILD_PROCESS_EXIT_TIMEOUT 5 // second
51    #define WAIT_CHILD_PROCESS_KILL_TIMEOUT 1 // second
52    
53    struct process_sockaddr_t
54    {
55            pid_t pid;
56            in_addr_t s_addr;
57    };
58    typedef struct process_sockaddr_t PROCESS_SOCKADDR;
59    
60    static PROCESS_SOCKADDR process_sockaddr_pool[MAX_CLIENT_LIMIT];
61    
62    #define SSH_AUTH_MAX_DURATION (60 * 1000) // milliseconds
63    
64    #define SFTP_SERVER_PATH "/usr/lib/sftp-server"
65    
66    /* A userdata struct for session. */
67    struct session_data_struct
68    {
69            int tries;
70            int error;
71    };
72    
73    /* A userdata struct for channel. */
74    struct channel_data_struct
75    {
76            /* pid of the child process the channel will spawn. */
77            pid_t pid;
78            /* For PTY allocation */
79            socket_t pty_master;
80            socket_t pty_slave;
81            /* For communication with the child process. */
82            socket_t child_stdin;
83            socket_t child_stdout;
84            /* Only used for subsystem and exec requests. */
85            socket_t child_stderr;
86            /* Event which is used to poll the above descriptors. */
87            ssh_event event;
88            /* Terminal size struct. */
89            struct winsize *winsize;
90    };
91    
92    static int auth_password(ssh_session session, const char *user,
93                                                     const char *password, void *userdata)
94    {
95            struct session_data_struct *sdata = (struct session_data_struct *)userdata;
96            int ret;
97    
98            if (strcmp(user, "guest") == 0)
99            {
100                    ret = load_guest_info();
101            }
102            else
103            {
104                    ret = check_user(user, password);
105            }
106    
107            if (ret == 0)
108            {
109                    return SSH_AUTH_SUCCESS;
110            }
111    
112            if ((++(sdata->tries)) >= BBS_login_retry_times)
113            {
114                    sdata->error = 1;
115            }
116    
117            return SSH_AUTH_DENIED;
118    }
119    
120    static int pty_request(ssh_session session, ssh_channel channel, const char *term,
121                                               int cols, int rows, int px, int py, void *userdata)
122    {
123            struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
124            int rc;
125    
126            (void)session;
127            (void)channel;
128            (void)term;
129    
130            cdata->winsize->ws_row = (unsigned short int)rows;
131            cdata->winsize->ws_col = (unsigned short int)cols;
132            cdata->winsize->ws_xpixel = (unsigned short int)px;
133            cdata->winsize->ws_ypixel = (unsigned short int)py;
134    
135            rc = openpty(&cdata->pty_master, &cdata->pty_slave, NULL, NULL, cdata->winsize);
136            if (rc != 0)
137            {
138                    log_error("Failed to open pty\n");
139                    return SSH_ERROR;
140            }
141    
142            return SSH_OK;
143    }
144    
145    static int pty_resize(ssh_session session, ssh_channel channel, int cols, int rows,
146                                              int py, int px, void *userdata)
147    {
148            struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
149    
150            (void)session;
151            (void)channel;
152    
153            cdata->winsize->ws_row = (unsigned short int)rows;
154            cdata->winsize->ws_col = (unsigned short int)cols;
155            cdata->winsize->ws_xpixel = (unsigned short int)px;
156            cdata->winsize->ws_ypixel = (unsigned short int)py;
157    
158            if (cdata->pty_master != -1)
159            {
160                    return ioctl(cdata->pty_master, TIOCSWINSZ, cdata->winsize);
161            }
162    
163            return SSH_ERROR;
164    }
165    
166    static int exec_pty(const char *mode, const char *command, struct channel_data_struct *cdata)
167    {
168            (void)cdata;
169    
170            if (command != NULL)
171            {
172                    log_error("Forbid exec /bin/sh %s %s)\n", mode, command);
173            }
174    
175            return SSH_OK;
176    }
177    
178  int  static int exec_nopty(const char *command, struct channel_data_struct *cdata)
 net_server (const char *hostaddr, unsigned int port)  
179  {  {
180    int namelen, seq, netint;          (void)cdata;
181    struct sockaddr_in sin;  
182    char temp[256];          if (command != NULL)
183            {
184    socket_server = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);                  log_error("Forbid exec /bin/sh -c %s)\n", command);
185            }
186    if (socket_server < 0)  
187      {          return SSH_OK;
188        log_error ("Create socket failed\n");  }
189        exit (1);  
190      }  static int exec_request(ssh_session session, ssh_channel channel, const char *command, void *userdata)
191    {
192    sin.sin_family = AF_INET;          struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
193    sin.sin_addr.s_addr =  
194      (strlen (hostaddr) > 0 ? inet_addr (hostaddr) : INADDR_ANY);          (void)session;
195    sin.sin_port = htons (port);          (void)channel;
196    
197    if (bind (socket_server, (struct sockaddr *)&sin, sizeof(sin)) < 0)          if (cdata->pid > 0)
198      {          {
199        log_error ("Bind address %s:%u failed\n",                  return SSH_ERROR;
200          inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));          }
201        exit (2);  
202      }          if (cdata->pty_master != -1 && cdata->pty_slave != -1)
203            {
204    if (listen (socket_server, 10) < 0)                  return exec_pty("-c", command, cdata);
205      {          }
206        log_error ("Socket listen failed\n");          return exec_nopty(command, cdata);
207        exit (3);  }
208      }  
209    static int shell_request(ssh_session session, ssh_channel channel, void *userdata)
210    strcpy(hostaddr_server,(const char *)inet_ntoa(sin.sin_addr));  {
211    port_server = ntohs(sin.sin_port);          struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
212      
213  //  log_std ("Listening at %s:%d\n", hostaddr_server, port_server);          (void)session;
214    log_std ("Listening at %s:%d\n", "0.0.0.0", 2323);          (void)channel;
215    
216    namelen = sizeof (sin);          if (cdata->pid > 0)
217    while(1)          {
218      {                  return SSH_ERROR;
219        if ((socket_client = accept (socket_server, (struct sockaddr *) &sin, &namelen)) < 0)          }
220          {  
221            log_error ("Accept connection error\n");          if (cdata->pty_master != -1 && cdata->pty_slave != -1)
222            continue;          {
223          }                  return exec_pty("-l", NULL, cdata);
224            }
225        strcpy (hostaddr_client, (const char *)inet_ntoa(sin.sin_addr));          /* Client requested a shell without a pty, let's pretend we allow that */
226        port_client = ntohs(sin.sin_port);          return SSH_OK;
227    }
228        log_std ("Accept connection from %s:%d\n", hostaddr_client, port_client);  
229          static int subsystem_request(ssh_session session, ssh_channel channel, const char *subsystem, void *userdata)
230        if (fork_server()<0)  {
231          {          (void)session;
232            log_error ("Fork error\n");          (void)channel;
233          }  
234                  log_error("subsystem_request(subsystem=%s)\n", subsystem);
235        if (close(socket_client) == -1)  
236          {          /* subsystem requests behave similarly to exec requests. */
237            log_error("Close client socket failed\n");          if (strcmp(subsystem, "sftp") == 0)
238          }          {
239      }                  return exec_request(session, channel, SFTP_SERVER_PATH, userdata);
240            }
241    if (close(socket_server) == -1)          return SSH_ERROR;
242      {  }
243        log_error("Close server socket failed\n");  
244      }  static ssh_channel channel_open(ssh_session session, void *userdata)
245    {
246            (void)userdata;
247    
248            if (SSH_channel != NULL)
249            {
250                    return NULL;
251            }
252    
253            SSH_channel = ssh_channel_new(session);
254    
255            return SSH_channel;
256    }
257    
258    static int fork_server(void)
259    {
260            ssh_event event;
261            long int ssh_timeout = 0;
262            int pid;
263            int i;
264            int ret;
265    
266            /* Structure for storing the pty size. */
267            struct winsize wsize = {
268                    .ws_row = 0,
269                    .ws_col = 0,
270                    .ws_xpixel = 0,
271                    .ws_ypixel = 0};
272    
273            /* Our struct holding information about the channel. */
274            struct channel_data_struct cdata = {
275                    .pid = 0,
276                    .pty_master = -1,
277                    .pty_slave = -1,
278                    .child_stdin = -1,
279                    .child_stdout = -1,
280                    .child_stderr = -1,
281                    .event = NULL,
282                    .winsize = &wsize};
283    
284            struct session_data_struct cb_data = {
285                    .tries = 0,
286                    .error = 0,
287            };
288    
289            struct ssh_channel_callbacks_struct channel_cb = {
290                    .userdata = &cdata,
291                    .channel_pty_request_function = pty_request,
292                    .channel_pty_window_change_function = pty_resize,
293                    .channel_shell_request_function = shell_request,
294                    .channel_exec_request_function = exec_request,
295                    .channel_subsystem_request_function = subsystem_request};
296    
297            struct ssh_server_callbacks_struct server_cb = {
298                    .userdata = &cb_data,
299                    .auth_password_function = auth_password,
300                    .channel_open_request_session_function = channel_open,
301            };
302    
303            pid = fork();
304    
305            if (pid > 0) // Parent process
306            {
307                    SYS_child_process_count++;
308                    log_common("Child process (%d) start\n", pid);
309                    return pid;
310            }
311            else if (pid < 0) // Error
312            {
313                    log_error("fork() error (%d)\n", errno);
314                    return -1;
315            }
316    
317            // Child process
318    
319            if (close(socket_server[0]) == -1 || close(socket_server[1]) == -1)
320            {
321                    log_error("Close server socket failed\n");
322            }
323    
324            SSH_session = ssh_new();
325    
326            if (SSH_v2)
327            {
328                    if (ssh_bind_accept_fd(sshbind, SSH_session, socket_client) != SSH_OK)
329                    {
330                            log_error("ssh_bind_accept_fd() error: %s\n", ssh_get_error(SSH_session));
331                            goto cleanup;
332                    }
333    
334                    ssh_bind_free(sshbind);
335    
336                    ssh_callbacks_init(&channel_cb);
337                    ssh_callbacks_init(&server_cb);
338    
339                    ssh_set_server_callbacks(SSH_session, &server_cb);
340    
341                    ssh_timeout = 60; // second
342                    if (ssh_options_set(SSH_session, SSH_OPTIONS_TIMEOUT, &ssh_timeout) < 0)
343                    {
344                            log_error("Error setting SSH options: %s\n", ssh_get_error(SSH_session));
345                            goto cleanup;
346                    }
347    
348                    if (ssh_handle_key_exchange(SSH_session))
349                    {
350                            log_error("ssh_handle_key_exchange() error: %s\n", ssh_get_error(SSH_session));
351                            goto cleanup;
352                    }
353                    ssh_set_auth_methods(SSH_session, SSH_AUTH_METHOD_PASSWORD);
354    
355                    event = ssh_event_new();
356                    ssh_event_add_session(event, SSH_session);
357    
358                    for (i = 0; i < SSH_AUTH_MAX_DURATION && !SYS_server_exit && !cb_data.error && SSH_channel == NULL; i += 100)
359                    {
360                            ret = ssh_event_dopoll(event, 100); // 0.1 second
361                            if (ret == SSH_ERROR)
362                            {
363    #ifdef _DEBUG
364                                    log_error("ssh_event_dopoll() error: %s\n", ssh_get_error(SSH_session));
365    #endif
366                                    goto cleanup;
367                            }
368                    }
369    
370                    if (cb_data.error)
371                    {
372                            log_error("SSH auth error, tried %d times\n", cb_data.tries);
373                            goto cleanup;
374                    }
375    
376                    ssh_set_channel_callbacks(SSH_channel, &channel_cb);
377    
378                    ssh_timeout = 0;
379                    if (ssh_options_set(SSH_session, SSH_OPTIONS_TIMEOUT, &ssh_timeout) < 0)
380                    {
381                            log_error("Error setting SSH options: %s\n", ssh_get_error(SSH_session));
382                            goto cleanup;
383                    }
384            }
385    
386            // Redirect Input
387            close(STDIN_FILENO);
388            if (dup2(socket_client, STDIN_FILENO) == -1)
389            {
390                    log_error("Redirect stdin to client socket failed\n");
391                    goto cleanup;
392            }
393    
394            // Redirect Output
395            close(STDOUT_FILENO);
396            if (dup2(socket_client, STDOUT_FILENO) == -1)
397            {
398                    log_error("Redirect stdout to client socket failed\n");
399                    goto cleanup;
400            }
401    
402            SYS_child_process_count = 0;
403    
404            bbs_main();
405    
406    cleanup:
407            // Child process exit
408            SYS_server_exit = 1;
409    
410            if (SSH_v2)
411            {
412                    close(cdata.pty_master);
413                    close(cdata.child_stdin);
414                    close(cdata.child_stdout);
415                    close(cdata.child_stderr);
416    
417                    ssh_channel_free(SSH_channel);
418                    ssh_disconnect(SSH_session);
419            }
420            else if (close(socket_client) == -1)
421            {
422                    log_error("Close client socket failed\n");
423            }
424    
425            ssh_free(SSH_session);
426            ssh_finalize();
427    
428            // Close Input and Output for client
429            close(STDIN_FILENO);
430            close(STDOUT_FILENO);
431    
432            log_common("Process exit normally\n");
433            log_end();
434    
435            _exit(0);
436    
437            return 0;
438    }
439    
440    int net_server(const char *hostaddr, in_port_t port[])
441    {
442            unsigned int addrlen;
443            int ret;
444            int flags[2];
445            struct sockaddr_in sin;
446            struct epoll_event ev, events[MAX_EVENTS];
447            int nfds, epollfd;
448            siginfo_t siginfo;
449            int notify_child_exit = 0;
450            time_t tm_notify_child_exit = time(NULL);
451            int sd_notify_stopping = 0;
452            MENU_SET bbs_menu_new;
453            MENU_SET top10_menu_new;
454            int i, j;
455            pid_t pid;
456            int ssh_log_level = SSH_LOG_NOLOG;
457    
458            ssh_init();
459    
460            sshbind = ssh_bind_new();
461    
462            if (ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, hostaddr) < 0 ||
463                    ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT, &port) < 0 ||
464                    ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, SSH_HOST_KEYFILE) < 0 ||
465                    ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS, "ssh-rsa,rsa-sha2-512,rsa-sha2-256") < 0 ||
466                    ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY, &ssh_log_level) < 0)
467            {
468                    log_error("Error setting SSH bind options: %s\n", ssh_get_error(sshbind));
469                    ssh_bind_free(sshbind);
470                    return -1;
471            }
472    
473            epollfd = epoll_create1(0);
474            if (epollfd < 0)
475            {
476                    log_error("epoll_create1() error (%d)\n", errno);
477                    return -1;
478            }
479    
480            // Server socket
481            for (i = 0; i < 2; i++)
482            {
483                    socket_server[i] = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
484    
485                    if (socket_server[i] < 0)
486                    {
487                            log_error("Create socket_server error (%d)\n", errno);
488                            return -1;
489                    }
490    
491                    sin.sin_family = AF_INET;
492                    sin.sin_addr.s_addr = (hostaddr[0] != '\0' ? inet_addr(hostaddr) : INADDR_ANY);
493                    sin.sin_port = htons(port[i]);
494    
495                    // Reuse address and port
496                    flags[i] = 1;
497                    if (setsockopt(socket_server[i], SOL_SOCKET, SO_REUSEADDR, &flags[i], sizeof(flags[i])) < 0)
498                    {
499                            log_error("setsockopt SO_REUSEADDR error (%d)\n", errno);
500                    }
501                    if (setsockopt(socket_server[i], SOL_SOCKET, SO_REUSEPORT, &flags[i], sizeof(flags[i])) < 0)
502                    {
503                            log_error("setsockopt SO_REUSEPORT error (%d)\n", errno);
504                    }
505    
506                    if (bind(socket_server[i], (struct sockaddr *)&sin, sizeof(sin)) < 0)
507                    {
508                            log_error("Bind address %s:%u error (%d)\n",
509                                              inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), errno);
510                            return -1;
511                    }
512    
513                    if (listen(socket_server[i], 10) < 0)
514                    {
515                            log_error("Telnet socket listen error (%d)\n", errno);
516                            return -1;
517                    }
518    
519                    log_common("Listening at %s:%u\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
520    
521                    ev.events = EPOLLIN;
522                    ev.data.fd = socket_server[i];
523                    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, socket_server[i], &ev) == -1)
524                    {
525                            log_error("epoll_ctl(socket_server[%d]) error (%d)\n", i, errno);
526                            if (close(epollfd) < 0)
527                            {
528                                    log_error("close(epoll) error (%d)\n");
529                            }
530                            return -1;
531                    }
532    
533                    flags[i] = fcntl(socket_server[i], F_GETFL, 0);
534                    fcntl(socket_server[i], F_SETFL, flags[i] | O_NONBLOCK);
535            }
536    
537            // Startup complete
538            sd_notifyf(0, "READY=1\n"
539                                      "STATUS=Listening at %s:%d (Telnet) and %s:%d (SSH2)\n"
540                                      "MAINPID=%d",
541                               hostaddr, port[0], hostaddr, port[1], getpid());
542    
543            while (!SYS_server_exit || SYS_child_process_count > 0)
544            {
545                    if (SYS_server_exit && !sd_notify_stopping)
546                    {
547                            sd_notify(0, "STOPPING=1");
548                            sd_notify_stopping = 1;
549                    }
550    
551                    while ((SYS_child_exit || SYS_server_exit) && SYS_child_process_count > 0)
552                    {
553                            SYS_child_exit = 0;
554    
555                            siginfo.si_pid = 0;
556                            ret = waitid(P_ALL, 0, &siginfo, WEXITED | WNOHANG);
557                            if (ret == 0 && siginfo.si_pid > 0)
558                            {
559                                    SYS_child_exit = 1; // Retry waitid
560    
561                                    SYS_child_process_count--;
562                                    log_common("Child process (%d) exited\n", siginfo.si_pid);
563    
564                                    if (siginfo.si_pid != section_list_loader_pid)
565                                    {
566                                            i = 0;
567                                            for (; i < BBS_max_client; i++)
568                                            {
569                                                    if (process_sockaddr_pool[i].pid == siginfo.si_pid)
570                                                    {
571                                                            process_sockaddr_pool[i].pid = 0;
572                                                            break;
573                                                    }
574                                            }
575                                            if (i >= BBS_max_client)
576                                            {
577                                                    log_error("Child process (%d) not found in process sockaddr pool\n", siginfo.si_pid);
578                                            }
579                                    }
580                            }
581                            else if (ret == 0)
582                            {
583                                    break;
584                            }
585                            else if (ret < 0)
586                            {
587                                    log_error("Error in waitid: %d\n", errno);
588                                    break;
589                            }
590                    }
591    
592                    if (SYS_server_exit && !SYS_child_exit && SYS_child_process_count > 0)
593                    {
594                            if (notify_child_exit == 0)
595                            {
596                                    sd_notifyf(0, "STATUS=Notify %d child process to exit", SYS_child_process_count);
597                                    log_common("Notify %d child process to exit\n", SYS_child_process_count);
598    
599                                    if (kill(0, SIGTERM) < 0)
600                                    {
601                                            log_error("Send SIGTERM signal failed (%d)\n", errno);
602                                    }
603    
604                                    notify_child_exit = 1;
605                                    tm_notify_child_exit = time(NULL);
606                            }
607                            else if (notify_child_exit == 1 && time(NULL) - tm_notify_child_exit >= WAIT_CHILD_PROCESS_EXIT_TIMEOUT)
608                            {
609                                    sd_notifyf(0, "STATUS=Kill %d child process", SYS_child_process_count);
610    
611                                    for (i = 0; i < BBS_max_client; i++)
612                                    {
613                                            if (process_sockaddr_pool[i].pid != 0)
614                                            {
615                                                    log_error("Kill child process (pid=%d)\n", process_sockaddr_pool[i].pid);
616                                                    if (kill(process_sockaddr_pool[i].pid, SIGKILL) < 0)
617                                                    {
618                                                            log_error("Send SIGKILL signal failed (%d)\n", errno);
619                                                    }
620                                            }
621                                    }
622    
623                                    notify_child_exit = 2;
624                                    tm_notify_child_exit = time(NULL);
625                            }
626                            else if (notify_child_exit == 2 && time(NULL) - tm_notify_child_exit >= WAIT_CHILD_PROCESS_KILL_TIMEOUT)
627                            {
628                                    log_error("Main process prepare to exit without waiting for %d child process any longer\n", SYS_child_process_count);
629                                    SYS_child_process_count = 0;
630                            }
631                    }
632    
633                    if (SYS_conf_reload && !SYS_server_exit)
634                    {
635                            SYS_conf_reload = 0;
636                            sd_notify(0, "RELOADING=1");
637    
638                            // Reload configuration
639                            if (load_conf(CONF_BBSD) < 0)
640                            {
641                                    log_error("Reload conf failed\n");
642                            }
643    
644                            if (load_menu(&bbs_menu_new, CONF_MENU) < 0)
645                            {
646                                    unload_menu(&bbs_menu_new);
647                                    log_error("Reload bbs menu failed\n");
648                            }
649                            else
650                            {
651                                    unload_menu(&bbs_menu);
652                                    memcpy(&bbs_menu, &bbs_menu_new, sizeof(bbs_menu_new));
653                                    log_common("Reload bbs menu successfully\n");
654                            }
655    
656                            if (load_menu(&top10_menu_new, CONF_TOP10_MENU) < 0)
657                            {
658                                    unload_menu(&top10_menu_new);
659                                    log_error("Reload top10 menu failed\n");
660                            }
661                            else
662                            {
663                                    unload_menu(&top10_menu);
664                                    top10_menu_new.allow_exit = 1;
665                                    memcpy(&top10_menu, &top10_menu_new, sizeof(top10_menu_new));
666                                    log_common("Reload top10 menu successfully\n");
667                            }
668    
669                            for (int i = 0; i < data_files_load_startup_count; i++)
670                            {
671                                    if (load_file(data_files_load_startup[i]) < 0)
672                                    {
673                                            log_error("load_file_mmap(%s) error\n", data_files_load_startup[i]);
674                                    }
675                            }
676                            log_common("Reload data files successfully\n");
677    
678                            // Load section config and gen_ex
679                            if (load_section_config_from_db(1) < 0)
680                            {
681                                    log_error("load_section_config_from_db(1) error\n");
682                            }
683                            else
684                            {
685                                    log_common("Reload section config and gen_ex successfully\n");
686                            }
687    
688                            sd_notify(0, "READY=1");
689                    }
690    
691                    nfds = epoll_wait(epollfd, events, MAX_EVENTS, 100); // 0.1 second
692    
693                    if (nfds < 0)
694                    {
695                            if (errno != EINTR)
696                            {
697                                    log_error("epoll_wait() error (%d)\n", errno);
698                                    break;
699                            }
700                            continue;
701                    }
702    
703                    // Stop accept new connection on exit
704                    if (SYS_server_exit)
705                    {
706                            continue;
707                    }
708    
709                    for (int i = 0; i < nfds; i++)
710                    {
711                            if (events[i].data.fd == socket_server[0] || events[i].data.fd == socket_server[1])
712                            {
713                                    SSH_v2 = (events[i].data.fd == socket_server[1] ? 1 : 0);
714    
715                                    while (!SYS_server_exit) // Accept all incoming connections until error
716                                    {
717                                            addrlen = sizeof(sin);
718                                            socket_client = accept(socket_server[SSH_v2], (struct sockaddr *)&sin, &addrlen);
719                                            if (socket_client < 0)
720                                            {
721                                                    if (errno == EAGAIN || errno == EWOULDBLOCK)
722                                                    {
723                                                            break;
724                                                    }
725                                                    else if (errno == EINTR)
726                                                    {
727                                                            continue;
728                                                    }
729                                                    else
730                                                    {
731                                                            log_error("accept(socket_server) error (%d)\n", errno);
732                                                            break;
733                                                    }
734                                            }
735    
736                                            strncpy(hostaddr_client, inet_ntoa(sin.sin_addr), sizeof(hostaddr_client) - 1);
737                                            hostaddr_client[sizeof(hostaddr_client) - 1] = '\0';
738    
739                                            port_client = ntohs(sin.sin_port);
740    
741                                            log_common("Accept %s connection from %s:%d\n", (SSH_v2 ? "SSH" : "telnet"), hostaddr_client, port_client);
742    
743                                            if (SYS_child_process_count - 1 < BBS_max_client)
744                                            {
745                                                    j = 0;
746                                                    for (i = 0; i < BBS_max_client; i++)
747                                                    {
748                                                            if (process_sockaddr_pool[i].pid != 0 && process_sockaddr_pool[i].s_addr == sin.sin_addr.s_addr)
749                                                            {
750                                                                    j++;
751                                                                    if (j >= BBS_max_client_per_ip)
752                                                                    {
753                                                                            log_common("Too many client connections (%d) from %s\n", j, hostaddr_client);
754                                                                            break;
755                                                                    }
756                                                            }
757                                                    }
758    
759                                                    if (j < BBS_max_client_per_ip)
760                                                    {
761                                                            if ((pid = fork_server()) < 0)
762                                                            {
763                                                                    log_error("fork_server() error\n");
764                                                            }
765                                                            else if (pid > 0)
766                                                            {
767                                                                    i = 0;
768                                                                    for (; i < BBS_max_client; i++)
769                                                                    {
770                                                                            if (process_sockaddr_pool[i].pid == 0)
771                                                                            {
772                                                                                    break;
773                                                                            }
774                                                                    }
775    
776                                                                    if (i >= BBS_max_client)
777                                                                    {
778                                                                            log_error("Process sockaddr pool depleted\n");
779                                                                    }
780                                                                    else
781                                                                    {
782                                                                            process_sockaddr_pool[i].pid = pid;
783                                                                            process_sockaddr_pool[i].s_addr = sin.sin_addr.s_addr;
784                                                                    }
785                                                            }
786                                                    }
787                                            }
788                                            else
789                                            {
790                                                    log_error("Rejected client connection over limit (%d)\n", SYS_child_process_count - 1);
791                                            }
792    
793                                            if (close(socket_client) == -1)
794                                            {
795                                                    log_error("close(socket_lient) error (%d)\n", errno);
796                                            }
797                                    }
798                            }
799                    }
800            }
801    
802            if (close(epollfd) < 0)
803            {
804                    log_error("close(epoll) error (%d)\n");
805            }
806    
807            for (i = 0; i < 2; i++)
808            {
809                    fcntl(socket_server[i], F_SETFL, flags[i]);
810    
811                    if (close(socket_server[i]) == -1)
812                    {
813                            log_error("Close server socket failed\n");
814                    }
815            }
816    
817            ssh_bind_free(sshbind);
818            ssh_finalize();
819    
820    return 0;          return 0;
821  }  }


Legend:
Removed lines/characters  
Changed lines/characters
  Added lines/characters

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1