"Fossies" - the Fresh Open Source Software Archive

Member "stud-0.3/stud.c" (2 Nov 2011, 38430 Bytes) of package /linux/privat/old/stud-0.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "stud.c" see the Fossies "Dox" file reference documentation.

    1 /**
    2   * Copyright 2011 Bump Technologies, Inc. All rights reserved.
    3   *
    4   * Redistribution and use in source and binary forms, with or without modification, are
    5   * permitted provided that the following conditions are met:
    6   *
    7   *    1. Redistributions of source code must retain the above copyright notice, this list of
    8   *       conditions and the following disclaimer.
    9   *
   10   *    2. Redistributions in binary form must reproduce the above copyright notice, this list
   11   *       of conditions and the following disclaimer in the documentation and/or other materials
   12   *       provided with the distribution.
   13   *
   14   * THIS SOFTWARE IS PROVIDED BY BUMP TECHNOLOGIES, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED
   15   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   16   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BUMP TECHNOLOGIES, INC. OR
   17   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   18   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   19   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
   20   * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   21   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   22   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   23   *
   24   * The views and conclusions contained in the software and documentation are those of the
   25   * authors and should not be interpreted as representing official policies, either expressed
   26   * or implied, of Bump Technologies, Inc.
   27   *
   28   **/
   29 
   30 #include <sys/types.h>
   31 #include <sys/ioctl.h>
   32 #include <sys/socket.h>
   33 #include <netdb.h>
   34 #include <sys/wait.h>
   35 #include <netinet/in.h>
   36 #include <netinet/tcp.h>
   37 #include <arpa/inet.h>
   38 #include <stdio.h>
   39 #include <stdlib.h>
   40 #include <string.h>
   41 #include <assert.h>
   42 #include <unistd.h>
   43 #include <fcntl.h>
   44 #include <errno.h>
   45 #include <getopt.h>
   46 #include <pwd.h>
   47 #include <limits.h>
   48 #include <syslog.h>
   49 
   50 #include <sched.h>
   51 #include <signal.h>
   52 
   53 #include <openssl/x509.h>
   54 #include <openssl/ssl.h>
   55 #include <openssl/err.h>
   56 #include <openssl/engine.h>
   57 #include <ev.h>
   58 
   59 #include "ringbuffer.h"
   60 #include "shctx.h"
   61 
   62 #ifndef MSG_NOSIGNAL
   63 # define MSG_NOSIGNAL 0
   64 #endif
   65 #ifndef AI_ADDRCONFIG
   66 # define AI_ADDRCONFIG 0
   67 #endif
   68 
   69 /* Globals */
   70 static struct ev_loop *loop;
   71 static struct addrinfo *backaddr;
   72 static pid_t master_pid;
   73 static ev_io listener;
   74 static int listener_socket;
   75 static int child_num;
   76 static pid_t *child_pids;
   77 static SSL_CTX *ssl_ctx;
   78 
   79 /* Command line Options */
   80 typedef enum {
   81     ENC_TLS,
   82     ENC_SSL
   83 } ENC_TYPE;
   84 
   85 typedef struct stud_options {
   86     ENC_TYPE ETYPE;
   87     int WRITE_IP_OCTET;
   88     int WRITE_PROXY_LINE;
   89     const char* CHROOT;
   90     uid_t UID;
   91     gid_t GID;
   92     const char *FRONT_IP;
   93     const char *FRONT_PORT;
   94     const char *BACK_IP;
   95     const char *BACK_PORT;
   96     long NCORES;
   97     const char *CERT_FILE;
   98     const char *CIPHER_SUITE;
   99     const char *ENGINE;
  100     int BACKLOG;
  101 #ifdef USE_SHARED_CACHE
  102     int SHARED_CACHE;
  103 #endif
  104     int QUIET;
  105     int SYSLOG;
  106     int TCP_KEEPALIVE;
  107 } stud_options;
  108 
  109 static stud_options OPTIONS = {
  110     ENC_TLS,      // ETYPE
  111     0,            // WRITE_IP_OCTET
  112     0,            // WRITE_PROXY_LINE
  113     NULL,         // CHROOT
  114     0,            // UID
  115     0,            // GID
  116     NULL,         // FRONT_IP
  117     "8443",       // FRONT_PORT
  118     "127.0.0.1",  // BACK_IP
  119     "8000",       // BACK_PORT
  120     1,            // NCORES
  121     NULL,         // CERT_FILE
  122     NULL,         // CIPHER_SUITE
  123     NULL,         // ENGINE
  124     100,          // BACKLOG
  125 #ifdef USE_SHARED_CACHE
  126     0,            // SHARED_CACHE
  127 #endif
  128     0,            // QUIET
  129     0,            // SYSLOG
  130     3600          // TCP_KEEPALIVE
  131 };
  132 
  133 
  134 
  135 static char tcp_proxy_line[128] = "";
  136 
  137 /* What agent/state requests the shutdown--for proper half-closed
  138  * handling */
  139 typedef enum _SHUTDOWN_REQUESTOR {
  140     SHUTDOWN_HARD,
  141     SHUTDOWN_DOWN,
  142     SHUTDOWN_UP
  143 } SHUTDOWN_REQUESTOR;
  144 
  145 /*
  146  * Proxied State
  147  *
  148  * All state associated with one proxied connection
  149  */
  150 typedef struct proxystate {
  151     ringbuffer ring_down; /* pushing bytes from client to backend */
  152     ringbuffer ring_up;   /* pushing bytes from backend to client */
  153 
  154     ev_io ev_r_up;        /* Upstream write event */
  155     ev_io ev_w_up;        /* Upstream read event */
  156 
  157     ev_io ev_r_handshake; /* Downstream write event */
  158     ev_io ev_w_handshake; /* Downstream read event */
  159 
  160     ev_io ev_r_down;      /* Downstream write event */
  161     ev_io ev_w_down;      /* Downstream read event */
  162 
  163     int fd_up;            /* Upstream (client) socket */
  164     int fd_down;          /* Downstream (backend) socket */
  165 
  166     int want_shutdown:1;  /* Connection is half-shutdown */
  167     int handshaked:1;     /* Initial handshake happened */
  168     int renegotiation:1;  /* Renegotation is occuring */
  169 
  170     SSL *ssl;             /* OpenSSL SSL state */
  171 
  172     struct sockaddr_storage remote_ip;  /* Remote ip returned from `accept` */
  173 } proxystate;
  174 
  175 #define LOG(...)                                        \
  176     do {                                                \
  177       if (!OPTIONS.QUIET) fprintf(stdout, __VA_ARGS__); \
  178       if (OPTIONS.SYSLOG) syslog(LOG_INFO, __VA_ARGS__);                    \
  179     } while(0)
  180 
  181 #define ERR(...)                    \
  182     do {                            \
  183       fprintf(stderr, __VA_ARGS__); \
  184       if (OPTIONS.SYSLOG) syslog(LOG_ERR, __VA_ARGS__); \
  185     } while(0)
  186 
  187 
  188 /* set a file descriptor (socket) to non-blocking mode */
  189 static void setnonblocking(int fd) {
  190     int flag = 1;
  191 
  192     assert (ioctl(fd, FIONBIO, &flag) == 0);
  193 }
  194 
  195 /* set a tcp socket to use TCP Keepalive */
  196 static void settcpkeepalive(int fd) {
  197     int optval = 1;
  198     socklen_t optlen = sizeof(optval);
  199 
  200     if(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) {
  201         ERR("Error activating SO_KEEPALIVE on client socket: %s", strerror(errno));
  202     }
  203 
  204     optval = OPTIONS.TCP_KEEPALIVE;
  205     optlen = sizeof(optval);
  206     if(setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &optval, optlen) < 0) {
  207         ERR("Error setting TCP_KEEPIDLE on client socket: %s", strerror(errno));
  208     }
  209 }
  210 
  211 static void fail(const char* s) {
  212     perror(s);
  213     exit(1);
  214 }
  215 
  216 #ifndef OPENSSL_NO_DH
  217 static int init_dh(SSL_CTX *ctx, const char *cert) {
  218     DH *dh;
  219     BIO *bio;
  220 
  221     assert(cert);
  222 
  223     bio = BIO_new_file(cert, "r");
  224     if (!bio) {
  225       ERR_print_errors_fp(stderr);
  226       return -1;
  227     }
  228 
  229     dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
  230     BIO_free(bio);
  231     if (!dh) {
  232         ERR("{core} Note: no DH parameters found in %s\n", cert);
  233         return -1;
  234     }
  235 
  236     LOG("{core} Using DH parameters from %s\n", cert);
  237     SSL_CTX_set_tmp_dh(ctx, dh);
  238     LOG("{core} DH initialized with %d bit key\n", 8*DH_size(dh));
  239     DH_free(dh);
  240 
  241     return 0;
  242 }
  243 #endif /* OPENSSL_NO_DH */
  244 
  245 /* This callback function is executed while OpenSSL processes the SSL
  246  * handshake and does SSL record layer stuff.  It's used to trap
  247  * client-initiated renegotiations.
  248  */
  249 static void info_callback(const SSL *ssl, int where, int ret) {
  250     (void)ret;
  251     if (where & SSL_CB_HANDSHAKE_START) {
  252         proxystate *ps = (proxystate *)SSL_get_app_data(ssl);
  253         if (ps->handshaked) {
  254             ps->renegotiation = 1;
  255             LOG("{core} SSL renegotiation asked by client\n");
  256         }
  257     }
  258 }
  259 
  260 /* Init library and load specified certificate.
  261  * Establishes a SSL_ctx, to act as a template for
  262  * each connection */
  263 static SSL_CTX * init_openssl() {
  264     SSL_library_init();
  265     SSL_load_error_strings();
  266     SSL_CTX *ctx = NULL;
  267     long ssloptions = SSL_OP_NO_SSLv2 | SSL_OP_ALL | 
  268             SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
  269 
  270     if (OPTIONS.ETYPE == ENC_TLS)
  271         ctx = SSL_CTX_new(TLSv1_server_method());
  272     else if (OPTIONS.ETYPE == ENC_SSL)
  273         ctx = SSL_CTX_new(SSLv23_server_method());
  274     else
  275         assert(OPTIONS.ETYPE == ENC_TLS || OPTIONS.ETYPE == ENC_SSL);
  276 
  277 #ifdef SSL_OP_NO_COMPRESSION
  278     ssloptions |= SSL_OP_NO_COMPRESSION;
  279 #endif
  280 
  281     SSL_CTX_set_options(ctx, ssloptions);
  282     SSL_CTX_set_info_callback(ctx, info_callback);
  283 
  284     if (SSL_CTX_use_certificate_chain_file(ctx, OPTIONS.CERT_FILE) <= 0) {
  285         ERR_print_errors_fp(stderr);
  286         exit(1);
  287     }
  288     if (SSL_CTX_use_RSAPrivateKey_file(ctx, OPTIONS.CERT_FILE, SSL_FILETYPE_PEM) <= 0) {
  289         ERR_print_errors_fp(stderr);
  290         exit(1);
  291     }
  292 
  293 #ifndef OPENSSL_NO_DH
  294     init_dh(ctx, OPTIONS.CERT_FILE);
  295 #endif /* OPENSSL_NO_DH */
  296 
  297     if (OPTIONS.ENGINE) {
  298         ENGINE *e = NULL;
  299         ENGINE_load_builtin_engines();
  300         if (!strcmp(OPTIONS.ENGINE, "auto"))
  301             ENGINE_register_all_complete();
  302         else {
  303             if ((e = ENGINE_by_id(OPTIONS.ENGINE)) == NULL ||
  304                 !ENGINE_init(e) ||
  305                 !ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
  306                 ERR_print_errors_fp(stderr);
  307                 exit(1);
  308             }
  309             LOG("{core} will use OpenSSL engine %s.\n", ENGINE_get_id(e));
  310             ENGINE_finish(e);
  311             ENGINE_free(e);
  312         }
  313     }
  314 
  315     if (OPTIONS.CIPHER_SUITE)
  316         if (SSL_CTX_set_cipher_list(ctx, OPTIONS.CIPHER_SUITE) != 1)
  317             ERR_print_errors_fp(stderr);
  318 
  319 #ifdef USE_SHARED_CACHE
  320     if (OPTIONS.SHARED_CACHE) {
  321         if (shared_context_init(ctx, OPTIONS.SHARED_CACHE) < 0) {
  322             ERR("Unable to alloc memory for shared cache.\n");
  323             exit(1);
  324         }
  325     }
  326 #endif
  327 
  328     return ctx;
  329 }
  330 
  331 static void prepare_proxy_line(struct sockaddr* ai_addr) {
  332     tcp_proxy_line[0] = 0;
  333     char tcp6_address_string[INET6_ADDRSTRLEN];
  334 
  335     if (ai_addr->sa_family == AF_INET) {
  336         struct sockaddr_in* addr = (struct sockaddr_in*)ai_addr;
  337         size_t res = snprintf(tcp_proxy_line,
  338                 sizeof(tcp_proxy_line),
  339                 "PROXY %%s %%s %s %%hu %hu\r\n",
  340                 inet_ntoa(addr->sin_addr),
  341                 ntohs(addr->sin_port));
  342         assert(res < sizeof(tcp_proxy_line));
  343     }
  344     else if (ai_addr->sa_family == AF_INET6 ) {
  345       struct sockaddr_in6* addr = (struct sockaddr_in6*)ai_addr;
  346       inet_ntop(AF_INET6,&(addr->sin6_addr),tcp6_address_string,INET6_ADDRSTRLEN);
  347       size_t res = snprintf(tcp_proxy_line,
  348                 sizeof(tcp_proxy_line),
  349                 "PROXY %%s %%s %s %%hu %hu\r\n",
  350                 tcp6_address_string,
  351                 ntohs(addr->sin6_port));
  352       assert(res < sizeof(tcp_proxy_line));
  353     }
  354     else {
  355         ERR("The --write-proxy mode is not implemented for this address family.\n");
  356         exit(1);
  357     }
  358 }
  359 
  360 /* Create the bound socket in the parent process */
  361 static int create_main_socket() {
  362     struct addrinfo *ai, hints;
  363     memset(&hints, 0, sizeof hints);
  364     hints.ai_family = AF_UNSPEC;
  365     hints.ai_socktype = SOCK_STREAM;
  366     hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
  367     const int gai_err = getaddrinfo(OPTIONS.FRONT_IP, OPTIONS.FRONT_PORT,
  368                                     &hints, &ai);
  369     if (gai_err != 0) {
  370         ERR("{getaddrinfo}: [%s]\n", gai_strerror(gai_err));
  371         exit(1);
  372     }
  373 
  374     int s = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
  375     
  376     if (s == -1)
  377       fail("{socket: main}");
  378 
  379     int t = 1;
  380     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(int));
  381 #ifdef SO_REUSEPORT
  382     setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &t, sizeof(int));
  383 #endif
  384     setnonblocking(s);
  385 
  386     if (bind(s, ai->ai_addr, ai->ai_addrlen)) {
  387         fail("{bind-socket}");
  388     }
  389 
  390 #if TCP_DEFER_ACCEPT
  391     int timeout = 1; 
  392     setsockopt(s, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, sizeof(int) );
  393 #endif /* TCP_DEFER_ACCEPT */
  394 
  395     prepare_proxy_line(ai->ai_addr);
  396 
  397     freeaddrinfo(ai);
  398     listen(s, OPTIONS.BACKLOG);
  399 
  400     return s;
  401 }
  402 
  403 /* Initiate a clear-text nonblocking connect() to the backend IP on behalf
  404  * of a newly connected upstream (encrypted) client*/
  405 static int create_back_socket() {
  406     int s = socket(backaddr->ai_family, SOCK_STREAM, IPPROTO_TCP);
  407 
  408     if (s == -1)
  409       return -1;
  410 
  411     int flag = 1;
  412     int ret = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag));
  413     if (ret == -1) {
  414       perror("Couldn't setsockopt to backend (TCP_NODELAY)\n");
  415     }
  416 
  417     int t = 1;
  418     setnonblocking(s);
  419     t = connect(s, backaddr->ai_addr, backaddr->ai_addrlen);
  420     if (t == 0 || errno == EINPROGRESS || errno == EINTR)
  421         return s;
  422 
  423     perror("{backend-connect}");
  424 
  425     return -1;
  426 }
  427 
  428 /* Only enable a libev ev_io event if the proxied connection still
  429  * has both up and down connected */
  430 static void safe_enable_io(proxystate *ps, ev_io *w) {
  431     if (!ps->want_shutdown)
  432         ev_io_start(loop, w);
  433 }
  434 
  435 /* Only enable a libev ev_io event if the proxied connection still
  436  * has both up and down connected */
  437 static void shutdown_proxy(proxystate *ps, SHUTDOWN_REQUESTOR req) {
  438     if (ps->want_shutdown || req == SHUTDOWN_HARD) {
  439         ev_io_stop(loop, &ps->ev_w_up);
  440         ev_io_stop(loop, &ps->ev_r_up);
  441         ev_io_stop(loop, &ps->ev_w_handshake);
  442         ev_io_stop(loop, &ps->ev_r_handshake);
  443         ev_io_stop(loop, &ps->ev_w_down);
  444         ev_io_stop(loop, &ps->ev_r_down);
  445 
  446         close(ps->fd_up);
  447         close(ps->fd_down);
  448 
  449         SSL_set_shutdown(ps->ssl, SSL_SENT_SHUTDOWN);
  450         SSL_free(ps->ssl);
  451 
  452         free(ps);
  453     }
  454     else {
  455         ps->want_shutdown = 1;
  456         if (req == SHUTDOWN_DOWN && ringbuffer_is_empty(&ps->ring_up))
  457             shutdown_proxy(ps, SHUTDOWN_HARD);
  458         else if (req == SHUTDOWN_UP && ringbuffer_is_empty(&ps->ring_down))
  459             shutdown_proxy(ps, SHUTDOWN_HARD);
  460     }
  461 }
  462 
  463 /* Handle various socket errors */
  464 static void handle_socket_errno(proxystate *ps) {
  465     if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
  466         return;
  467 
  468     if (errno == ECONNRESET)
  469         ERR("{backend} Connection reset by peer\n");
  470     else if (errno == ETIMEDOUT)
  471         ERR("{backend} Connection to backend timed out\n");
  472     else if (errno == EPIPE)
  473         ERR("{backend} Broken pipe to backend (EPIPE)\n");
  474     else
  475         perror("{backend} [errno]");
  476     shutdown_proxy(ps, SHUTDOWN_DOWN);
  477 }
  478 
  479 /* Read some data from the backend when libev says data is available--
  480  * write it into the upstream buffer and make sure the write event is
  481  * enabled for the upstream socket */
  482 static void back_read(struct ev_loop *loop, ev_io *w, int revents) {
  483     (void) revents;
  484     int t;
  485     proxystate *ps = (proxystate *)w->data;
  486     if (ps->want_shutdown) {
  487         ev_io_stop(loop, &ps->ev_r_down);
  488         return;
  489     }
  490     int fd = w->fd;
  491     char * buf = ringbuffer_write_ptr(&ps->ring_up);
  492     t = recv(fd, buf, RING_DATA_LEN, 0);
  493 
  494     if (t > 0) {
  495         ringbuffer_write_append(&ps->ring_up, t);
  496         if (ringbuffer_is_full(&ps->ring_up))
  497             ev_io_stop(loop, &ps->ev_r_down);
  498         safe_enable_io(ps, &ps->ev_w_up);
  499     }
  500     else if (t == 0) {
  501         LOG("{backend} Connection closed\n");
  502         shutdown_proxy(ps, SHUTDOWN_DOWN);
  503     }
  504     else {
  505         assert(t == -1);
  506         handle_socket_errno(ps);
  507     }
  508 }
  509 /* Write some data, previously received on the secure upstream socket,
  510  * out of the downstream buffer and onto the backend socket */
  511 static void back_write(struct ev_loop *loop, ev_io *w, int revents) {
  512     (void) revents;
  513     int t;
  514     proxystate *ps = (proxystate *)w->data;
  515     int fd = w->fd;
  516     int sz;
  517 
  518     assert(!ringbuffer_is_empty(&ps->ring_down));
  519 
  520     char *next = ringbuffer_read_next(&ps->ring_down, &sz);
  521     t = send(fd, next, sz, MSG_NOSIGNAL);
  522 
  523     if (t > 0) {
  524         if (t == sz) {
  525             ringbuffer_read_pop(&ps->ring_down);
  526             safe_enable_io(ps, &ps->ev_r_up);
  527             if (ringbuffer_is_empty(&ps->ring_down)) {
  528                 if (ps->want_shutdown) {
  529                     shutdown_proxy(ps, SHUTDOWN_HARD);
  530                     return; // dealloc'd
  531                 }
  532                 ev_io_stop(loop, &ps->ev_w_down);
  533             }
  534         }
  535         else {
  536             ringbuffer_read_skip(&ps->ring_down, t);
  537         }
  538     }
  539     else {
  540         assert(t == -1);
  541         handle_socket_errno(ps);
  542     }
  543 }
  544 
  545 static void start_handshake(proxystate *ps, int err);
  546 
  547 /* Continue/complete the asynchronous connect() before starting data transmission
  548  * between front/backend */
  549 static void handle_connect(struct ev_loop *loop, ev_io *w, int revents) {
  550     (void) revents;
  551     int t;
  552     proxystate *ps = (proxystate *)w->data;
  553     char tcp6_address_string[INET6_ADDRSTRLEN];
  554     size_t written = 0;
  555     t = connect(ps->fd_down, backaddr->ai_addr, backaddr->ai_addrlen);
  556     if (!t || errno == EISCONN || !errno) {
  557         /* INIT */
  558         ev_io_stop(loop, &ps->ev_w_down);
  559         ev_io_init(&ps->ev_r_down, back_read, ps->fd_down, EV_READ);
  560         ev_io_init(&ps->ev_w_down, back_write, ps->fd_down, EV_WRITE);
  561         start_handshake(ps, SSL_ERROR_WANT_READ); /* for client-first handshake */
  562         ev_io_start(loop, &ps->ev_r_down);
  563         if (OPTIONS.WRITE_PROXY_LINE) {
  564             char *ring_pnt = ringbuffer_write_ptr(&ps->ring_down);
  565             assert(ps->remote_ip.ss_family == AF_INET ||
  566            ps->remote_ip.ss_family == AF_INET6);
  567         if(ps->remote_ip.ss_family == AF_INET) {
  568           struct sockaddr_in* addr = (struct sockaddr_in*)&ps->remote_ip;
  569           written = snprintf(ring_pnt,
  570                  RING_DATA_LEN,
  571                  tcp_proxy_line,
  572                  "TCP4",
  573                  inet_ntoa(addr->sin_addr),
  574                  ntohs(addr->sin_port));
  575         }
  576         else if (ps->remote_ip.ss_family == AF_INET6) {
  577           struct sockaddr_in6* addr = (struct sockaddr_in6*)&ps->remote_ip;
  578           inet_ntop(AF_INET6,&(addr->sin6_addr),tcp6_address_string,INET6_ADDRSTRLEN);
  579           written = snprintf(ring_pnt,
  580                  RING_DATA_LEN,
  581                  tcp_proxy_line,
  582                  "TCP6",
  583                  tcp6_address_string,
  584                  ntohs(addr->sin6_port));
  585         }   
  586             ringbuffer_write_append(&ps->ring_down, written);
  587             ev_io_start(loop, &ps->ev_w_down);
  588         }
  589         else if (OPTIONS.WRITE_IP_OCTET) {
  590             char *ring_pnt = ringbuffer_write_ptr(&ps->ring_down);
  591             assert(ps->remote_ip.ss_family == AF_INET ||
  592                    ps->remote_ip.ss_family == AF_INET6);
  593             *ring_pnt++ = (unsigned char) ps->remote_ip.ss_family;
  594             if (ps->remote_ip.ss_family == AF_INET6) {
  595                 memcpy(ring_pnt, &((struct sockaddr_in6 *) &ps->remote_ip)
  596                        ->sin6_addr.s6_addr, 16U);
  597                 ringbuffer_write_append(&ps->ring_down, 1U + 16U);
  598             } else {
  599                 memcpy(ring_pnt, &((struct sockaddr_in *) &ps->remote_ip)
  600                        ->sin_addr.s_addr, 4U);
  601                 ringbuffer_write_append(&ps->ring_down, 1U + 4U);
  602             }
  603             ev_io_start(loop, &ps->ev_w_down);
  604         }
  605     }
  606     else if (errno == EINPROGRESS || errno == EINTR || errno == EALREADY) {
  607         /* do nothing, we'll get phoned home again... */
  608     }
  609     else {
  610         perror("{backend-connect}");
  611         shutdown_proxy(ps, SHUTDOWN_HARD);
  612     }
  613 }
  614 
  615 /* Upon receiving a signal from OpenSSL that a handshake is required, re-wire
  616  * the read/write events to hook up to the handshake handlers */
  617 static void start_handshake(proxystate *ps, int err) {
  618     ev_io_stop(loop, &ps->ev_r_up);
  619     ev_io_stop(loop, &ps->ev_w_up);
  620     if (err == SSL_ERROR_WANT_READ)
  621         ev_io_start(loop, &ps->ev_r_handshake);
  622     else if (err == SSL_ERROR_WANT_WRITE)
  623         ev_io_start(loop, &ps->ev_w_handshake);
  624 }
  625 
  626 /* After OpenSSL is done with a handshake, re-wire standard read/write handlers
  627  * for data transmission */
  628 static void end_handshake(proxystate *ps) {
  629     ev_io_stop(loop, &ps->ev_r_handshake);
  630     ev_io_stop(loop, &ps->ev_w_handshake);
  631 
  632     /* Disable renegotiation (CVE-2009-3555) */
  633     if (ps->ssl->s3) {
  634         ps->ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
  635     }
  636     ps->handshaked = 1;
  637 
  638     /* if incoming buffer is not full */
  639     if (!ringbuffer_is_full(&ps->ring_down))
  640         safe_enable_io(ps, &ps->ev_r_up);
  641 
  642     /* if outgoing buffer is not empty */
  643     if (!ringbuffer_is_empty(&ps->ring_up))
  644         // not safe.. we want to resume stream even during half-closed
  645         ev_io_start(loop, &ps->ev_w_up);
  646 }
  647 
  648 /* The libev I/O handler during the OpenSSL handshake phase.  Basically, just
  649  * let OpenSSL do what it likes with the socket and obey its requests for reads
  650  * or writes */
  651 static void client_handshake(struct ev_loop *loop, ev_io *w, int revents) {
  652     (void) revents;
  653     int t;
  654     proxystate *ps = (proxystate *)w->data;
  655 
  656     t = SSL_do_handshake(ps->ssl);
  657     if (t == 1) {
  658         end_handshake(ps);
  659     }
  660     else {
  661         int err = SSL_get_error(ps->ssl, t);
  662         if (err == SSL_ERROR_WANT_READ) {
  663             ev_io_stop(loop, &ps->ev_w_handshake);
  664             ev_io_start(loop, &ps->ev_r_handshake);
  665         }
  666         else if (err == SSL_ERROR_WANT_WRITE) {
  667             ev_io_stop(loop, &ps->ev_r_handshake);
  668             ev_io_start(loop, &ps->ev_w_handshake);
  669         }
  670         else if (err == SSL_ERROR_ZERO_RETURN) {
  671             LOG("{client} Connection closed (in handshake)\n");
  672             shutdown_proxy(ps, SHUTDOWN_UP);
  673         }
  674         else {
  675             LOG("{client} Unexpected SSL error (in handshake): %d\n", err);
  676             shutdown_proxy(ps, SHUTDOWN_UP);
  677         }
  678     }
  679 }
  680 
  681 /* Handle a socket error condition passed to us from OpenSSL */
  682 static void handle_fatal_ssl_error(proxystate *ps, int err) {
  683     if (err == SSL_ERROR_ZERO_RETURN)
  684         ERR("{client} Connection closed (in data)\n");
  685     else if (err == SSL_ERROR_SYSCALL)
  686         if (errno == 0)
  687             ERR("{client} Connection closed (in data)\n");
  688         else
  689             perror("{client} [errno] ");
  690     else
  691         ERR("{client} Unexpected SSL_read error: %d\n", err);
  692     shutdown_proxy(ps, SHUTDOWN_UP);
  693 }
  694 
  695 /* Read some data from the upstream secure socket via OpenSSL,
  696  * and buffer anything we get for writing to the backend */
  697 static void client_read(struct ev_loop *loop, ev_io *w, int revents) {
  698     (void) revents;
  699     int t;    
  700     proxystate *ps = (proxystate *)w->data;
  701     if (ps->want_shutdown) {
  702         ev_io_stop(loop, &ps->ev_r_up);
  703         return;
  704     }
  705     char * buf = ringbuffer_write_ptr(&ps->ring_down);
  706     t = SSL_read(ps->ssl, buf, RING_DATA_LEN);
  707 
  708     /* Fix CVE-2009-3555. Disable reneg if started by client. */
  709     if (ps->renegotiation) {
  710         shutdown_proxy(ps, SHUTDOWN_UP);
  711         return;
  712     }
  713 
  714     if (t > 0) {
  715         ringbuffer_write_append(&ps->ring_down, t);
  716         if (ringbuffer_is_full(&ps->ring_down))
  717             ev_io_stop(loop, &ps->ev_r_up);
  718         safe_enable_io(ps, &ps->ev_w_down);
  719     }
  720     else {
  721         int err = SSL_get_error(ps->ssl, t);
  722         if (err == SSL_ERROR_WANT_WRITE) {
  723             start_handshake(ps, err);
  724         }
  725         else if (err == SSL_ERROR_WANT_READ) { } /* incomplete SSL data */
  726         else
  727             handle_fatal_ssl_error(ps, err);
  728     }
  729 }
  730 
  731 /* Write some previously-buffered backend data upstream on the
  732  * secure socket using OpenSSL */
  733 static void client_write(struct ev_loop *loop, ev_io *w, int revents) {
  734     (void) revents;
  735     int t;
  736     int sz;
  737     proxystate *ps = (proxystate *)w->data;
  738     assert(!ringbuffer_is_empty(&ps->ring_up));
  739     char * next = ringbuffer_read_next(&ps->ring_up, &sz);
  740     t = SSL_write(ps->ssl, next, sz);
  741     if (t > 0) {
  742         if (t == sz) {
  743             ringbuffer_read_pop(&ps->ring_up);
  744             safe_enable_io(ps, &ps->ev_r_down); // can be re-enabled b/c we've popped
  745             if (ringbuffer_is_empty(&ps->ring_up)) {
  746                 if (ps->want_shutdown) {
  747                     shutdown_proxy(ps, SHUTDOWN_HARD);
  748                     return;
  749                 }
  750                 ev_io_stop(loop, &ps->ev_w_up);
  751             }
  752         }
  753         else {
  754             ringbuffer_read_skip(&ps->ring_up, t);
  755         }
  756     }
  757     else {
  758         int err = SSL_get_error(ps->ssl, t);
  759         if (err == SSL_ERROR_WANT_READ) {
  760             start_handshake(ps, err);
  761         }
  762         else if (err == SSL_ERROR_WANT_WRITE) {} /* incomplete SSL data */
  763         else
  764             handle_fatal_ssl_error(ps, err);
  765     }
  766 }
  767 
  768 /* libev read handler for the bound socket.  Socket is accepted,
  769  * the proxystate is allocated and initalized, and we're off the races
  770  * connecting to the backend */
  771 static void handle_accept(struct ev_loop *loop, ev_io *w, int revents) {
  772     (void) revents;
  773     struct sockaddr_storage addr;
  774     socklen_t sl = sizeof(addr);
  775     int client = accept(w->fd, (struct sockaddr *) &addr, &sl);
  776     if (client == -1) {
  777         switch (errno) {
  778         case EMFILE:
  779             ERR("{client} accept() failed; too many open files for this process\n");
  780             break;
  781 
  782         case ENFILE:
  783             ERR("{client} accept() failed; too many open files for this system\n");
  784             break;
  785 
  786         case 'k':
  787             OPTIONS.TCP_KEEPALIVE = atoi(optarg);
  788             break;
  789 
  790         default:
  791             assert(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN);
  792             break;
  793         }
  794         return;
  795     }
  796 
  797     int flag = 1;
  798     int ret = setsockopt(client, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag) );
  799     if (ret == -1) {
  800       perror("Couldn't setsockopt on client (TCP_NODELAY)\n");
  801     }
  802 #ifdef TCP_CWND
  803     int cwnd = 10;
  804     ret = setsockopt(client, IPPROTO_TCP, TCP_CWND, &cwnd, sizeof(cwnd));
  805     if (ret == -1) {
  806       perror("Couldn't setsockopt on client (TCP_CWND)\n");
  807     }
  808 #endif
  809 
  810     setnonblocking(client);
  811     settcpkeepalive(client);
  812 
  813     int back = create_back_socket();
  814 
  815     if (back == -1) {
  816         close(client);
  817         perror("{backend-connect}");
  818         return;
  819     }
  820 
  821     SSL_CTX * ctx = (SSL_CTX *)w->data;
  822     SSL *ssl = SSL_new(ctx);
  823     long mode = SSL_MODE_ENABLE_PARTIAL_WRITE;
  824 #ifdef SSL_MODE_RELEASE_BUFFERS
  825     mode |= SSL_MODE_RELEASE_BUFFERS;
  826 #endif
  827     SSL_set_mode(ssl, mode);
  828     SSL_set_accept_state(ssl);
  829     SSL_set_fd(ssl, client);
  830 
  831     proxystate *ps = (proxystate *)malloc(sizeof(proxystate));
  832 
  833     ps->fd_up = client;
  834     ps->fd_down = back;
  835     ps->ssl = ssl;
  836     ps->want_shutdown = 0;
  837     ps->handshaked = 0;
  838     ps->renegotiation = 0;
  839     ps->remote_ip = addr;
  840     ringbuffer_init(&ps->ring_up);
  841     ringbuffer_init(&ps->ring_down);
  842 
  843     /* set up events */
  844     ev_io_init(&ps->ev_r_up, client_read, client, EV_READ);
  845     ev_io_init(&ps->ev_w_up, client_write, client, EV_WRITE);
  846 
  847     ev_io_init(&ps->ev_r_handshake, client_handshake, client, EV_READ);
  848     ev_io_init(&ps->ev_w_handshake, client_handshake, client, EV_WRITE);
  849 
  850     ev_io_init(&ps->ev_w_down, handle_connect, back, EV_WRITE);
  851     ev_io_init(&ps->ev_r_down, back_read, back, EV_READ);
  852 
  853     ev_io_start(loop, &ps->ev_w_down);
  854 
  855     ps->ev_r_up.data = ps;
  856     ps->ev_w_up.data = ps;
  857     ps->ev_r_down.data = ps;
  858     ps->ev_w_down.data = ps;
  859     ps->ev_r_handshake.data = ps;
  860     ps->ev_w_handshake.data = ps;
  861 
  862     /* Link back proxystate to SSL state */
  863     SSL_set_app_data(ssl, ps);
  864 }
  865 
  866 
  867 static void check_ppid(struct ev_loop *loop, ev_timer *w, int revents) {
  868     (void) revents;
  869     pid_t ppid = getppid();
  870     if (ppid != master_pid) {
  871         ERR("{core} Process %d detected parent death, closing listener socket.\n", child_num);
  872         ev_timer_stop(loop, w);
  873         ev_io_stop(loop, &listener);
  874         close(listener_socket);
  875     }
  876 
  877 }
  878 
  879 
  880 /* Set up the child (worker) process including libev event loop, read event
  881  * on the bound socket, etc */
  882 static void handle_connections() {
  883     LOG("{core} Process %d online\n", child_num);
  884 #if defined(CPU_ZERO) && defined(CPU_SET)
  885     cpu_set_t cpus;
  886 
  887     CPU_ZERO(&cpus);
  888     CPU_SET(child_num, &cpus);
  889 
  890     int res = sched_setaffinity(0, sizeof(cpus), &cpus);
  891     if (!res)
  892         LOG("{core} Successfully attached to CPU #%d\n", child_num);
  893     else
  894         ERR("{core-warning} Unable to attach to CPU #%d; do you have that many cores?\n", child_num);
  895 #endif
  896 
  897     loop = ev_default_loop(EVFLAG_AUTO);
  898 
  899     ev_timer timer_ppid_check;
  900     ev_timer_init(&timer_ppid_check, check_ppid, 1.0, 1.0);
  901     ev_timer_start(loop, &timer_ppid_check);
  902 
  903     ev_io_init(&listener, handle_accept, listener_socket, EV_READ);
  904     listener.data = ssl_ctx;
  905     ev_io_start(loop, &listener);
  906 
  907     ev_loop(loop, 0);
  908     ERR("{core} Child %d exiting.\n", child_num);
  909     exit(1);
  910 }
  911 
  912 
  913 /* Print usage w/error message and exit failure */
  914 static void usage_fail(const char *prog, const char *msg) {
  915     if (msg)
  916         fprintf(stderr, "%s: %s\n", prog, msg);
  917     fprintf(stderr, "usage: %s [OPTION] PEM\n", prog);
  918 
  919     fprintf(stderr,
  920 "Encryption Methods:\n"
  921 "  --tls                    TLSv1 (default)\n"
  922 "  --ssl                    SSLv3 (implies no TLSv1)\n"
  923 "  -c CIPHER_SUITE          set allowed ciphers (default is OpenSSL defaults)\n"
  924 "  -e ENGINE                set OpenSSL engine\n"
  925 "\n"
  926 "Socket:\n"
  927 "  -b HOST,PORT             backend [connect] (default is \"127.0.0.1,8000\")\n"
  928 "  -f HOST,PORT             frontend [bind] (default is \"*,8443\")\n"
  929 "\n"
  930 "Performance:\n"
  931 "  -n CORES                 number of worker processes (default is 1)\n"
  932 "  -B BACKLOG               set listen backlog size (default is 100)\n"
  933 "  -k SECS                  Change default tcp keepalive on client socket\n"
  934 #ifdef USE_SHARED_CACHE
  935 "  -C SHARED_CACHE          set shared cache size in sessions (default no shared cache)\n"
  936 #endif
  937 "\n"
  938 "Security:\n"
  939 "  -r PATH                  chroot\n"
  940 "  -u USERNAME              set gid/uid after binding the socket\n"
  941 "\n"
  942 "Logging:\n"
  943 "  -q                       be quiet; emit only error messages\n"
  944 "  -s                       send log message to syslog in addition to stderr/stdout\n"
  945 "\n"
  946 "Special:\n"
  947 "  --write-ip               write 1 octet with the IP family followed by the IP\n"
  948 "                           address in 4 (IPv4) or 16 (IPv6) octets little-endian\n"
  949 "                           to backend before the actual data\n"
  950 "  --write-proxy            write HaProxy's PROXY (IPv4 or IPv6) protocol line\n" 
  951 "                           before actual data\n"
  952 );
  953     exit(1);
  954 }
  955 
  956 
  957 static void parse_host_and_port(const char *prog, const char *name, char *inp, int wildcard_okay, const char **ip, const char **port) {
  958     char buf[150];
  959     char *sp;
  960 
  961     if (strlen(inp) >= sizeof buf) {
  962         snprintf(buf, sizeof buf, "invalid option for %s HOST,PORT\n", name);
  963         usage_fail(prog, buf);
  964     }
  965 
  966     sp = strchr(inp, ',');
  967     if (!sp) {
  968         snprintf(buf, sizeof buf, "invalid option for %s HOST,PORT\n", name);
  969         usage_fail(prog, buf);
  970     }
  971 
  972     if (!strncmp(inp, "*", sp - inp)) {
  973         if (!wildcard_okay) {
  974             snprintf(buf, sizeof buf, "wildcard host specification invalid for %s\n", name);
  975             usage_fail(prog, buf);
  976         }
  977         *ip = NULL;
  978     }
  979     else {
  980         *sp = 0;
  981         *ip = inp;
  982     }
  983     *port = sp + 1;
  984 }
  985 
  986 
  987 /* Handle command line arguments modifying behavior */
  988 static void parse_cli(int argc, char **argv) {
  989     const char *prog = argv[0];
  990 
  991     static int tls = 0, ssl = 0;
  992     int c;
  993     struct passwd* passwd;
  994 
  995     static struct option long_options[] =
  996     {
  997         {"tls", 0, &tls, 1},
  998         {"ssl", 0, &ssl, 1},
  999         {"write-ip", 0, &OPTIONS.WRITE_IP_OCTET, 1},
 1000         {"write-proxy", 0, &OPTIONS.WRITE_PROXY_LINE, 1},
 1001         {0, 0, 0, 0}
 1002     };
 1003 
 1004     while (1) {
 1005         int option_index = 0;
 1006         c = getopt_long(argc, argv, "hf:b:n:c:e:u:r:B:C:k:qs",
 1007                 long_options, &option_index);
 1008 
 1009         if (c == -1)
 1010             break;
 1011 
 1012         switch (c) {
 1013 
 1014         case 0:
 1015             break;
 1016 
 1017         case 'n':
 1018             errno = 0;
 1019             OPTIONS.NCORES = strtol(optarg, NULL, 10);
 1020             if ((errno == ERANGE &&
 1021                 (OPTIONS.NCORES == LONG_MAX || OPTIONS.NCORES == LONG_MIN)) ||
 1022                 OPTIONS.NCORES < 1 || OPTIONS.NCORES > 128) {
 1023                 usage_fail(prog, "invalid option for -n CORES; please provide an integer between 1 and 128\n");
 1024             }
 1025             break;
 1026 
 1027         case 'b':
 1028             parse_host_and_port(prog, "-b", optarg, 0, &(OPTIONS.BACK_IP), &(OPTIONS.BACK_PORT));
 1029             break;
 1030 
 1031         case 'f':
 1032             parse_host_and_port(prog, "-f", optarg, 1, &(OPTIONS.FRONT_IP), &(OPTIONS.FRONT_PORT));
 1033             break;
 1034             
 1035         case 'c':
 1036             OPTIONS.CIPHER_SUITE = optarg;
 1037             break;
 1038 
 1039         case 'e':
 1040             OPTIONS.ENGINE = optarg;
 1041             break;
 1042 
 1043         case 'u':
 1044             passwd = getpwnam(optarg);
 1045             if (!passwd) {
 1046                 if (errno)
 1047                     fail("getpwnam failed");
 1048                 else
 1049                     ERR("user not found: %s\n", optarg);
 1050                 exit(1);
 1051             }
 1052             OPTIONS.UID = passwd->pw_uid;
 1053             OPTIONS.GID = passwd->pw_gid;
 1054             break;
 1055 
 1056         case 'r':
 1057             if (optarg && optarg[0] == '/')
 1058                 OPTIONS.CHROOT = optarg;
 1059             else {
 1060                 ERR("chroot must be absolute path: \"%s\"\n", optarg);
 1061                 exit(1);
 1062             }
 1063             break;
 1064 
 1065         case 'B':
 1066             OPTIONS.BACKLOG = atoi(optarg);
 1067             if ( OPTIONS.BACKLOG <= 0 ) {
 1068                 ERR("listen backlog can not be set to %d\n", OPTIONS.BACKLOG);
 1069                 exit(1);
 1070             }
 1071             break;
 1072 
 1073 #ifdef USE_SHARED_CACHE
 1074         case 'C':
 1075             OPTIONS.SHARED_CACHE = atoi(optarg);
 1076             if ( OPTIONS.SHARED_CACHE < 0 ) {
 1077                 ERR("shared cache size can not be set to %d\n", OPTIONS.SHARED_CACHE);
 1078                 exit(1);
 1079             }
 1080             break;
 1081 #endif
 1082 
 1083         case 'q':
 1084             OPTIONS.QUIET = 1;
 1085             break;
 1086         
 1087         case 's':
 1088             OPTIONS.SYSLOG = 1;
 1089             break;
 1090             
 1091         default:
 1092             usage_fail(prog, NULL);
 1093         }
 1094     }
 1095 
 1096     /* Post-processing */
 1097     if (tls && ssl)
 1098         usage_fail(prog, "Cannot specify both --tls and --ssl");
 1099 
 1100     if (ssl)
 1101         OPTIONS.ETYPE = ENC_SSL; // implied.. else, TLS
 1102 
 1103     if (OPTIONS.WRITE_IP_OCTET && OPTIONS.WRITE_PROXY_LINE)
 1104         usage_fail(prog, "Cannot specify both --write-ip and --write-proxy; pick one!");
 1105 
 1106     argc -= optind;
 1107     argv += optind;
 1108 
 1109     if (argc != 1)
 1110         usage_fail(prog, "exactly one argument is required: path to PEM file with cert/key");
 1111 
 1112     OPTIONS.CERT_FILE = argv[0];
 1113 }
 1114 
 1115 
 1116 void change_root() {
 1117     if (chroot(OPTIONS.CHROOT) == -1)
 1118         fail("chroot");
 1119     if (chdir("/"))
 1120         fail("chdir");
 1121 }
 1122 
 1123 void drop_privileges() {
 1124     if (setgid(OPTIONS.GID))
 1125         fail("setgid failed");
 1126     if (setuid(OPTIONS.UID))
 1127         fail("setuid failed");
 1128 }
 1129 
 1130 
 1131 void init_globals() {
 1132     /* backaddr */
 1133     struct addrinfo hints;
 1134     memset(&hints, 0, sizeof hints);
 1135     hints.ai_family = AF_UNSPEC;
 1136     hints.ai_socktype = SOCK_STREAM;
 1137     hints.ai_flags = 0;
 1138     const int gai_err = getaddrinfo(OPTIONS.BACK_IP, OPTIONS.BACK_PORT,
 1139                                     &hints, &backaddr);
 1140     if (gai_err != 0) {
 1141         ERR("{getaddrinfo}: [%s]", gai_strerror(gai_err));
 1142         exit(1);
 1143     }
 1144 
 1145     /* child_pids */
 1146     if ((child_pids = calloc(OPTIONS.NCORES, sizeof(pid_t))) == NULL)
 1147         fail("calloc");
 1148 
 1149     if (OPTIONS.SYSLOG)
 1150         openlog("stud", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_DAEMON);
 1151 }
 1152 
 1153 /* Forks COUNT children starting with START_INDEX.
 1154  * Each child's index is stored in child_num and its pid is stored in child_pids[child_num]
 1155  * so the parent can manage it later. */
 1156 void start_children(int start_index, int count) {
 1157     for (child_num = start_index; child_num < start_index + count; child_num++) {
 1158         int pid = fork();
 1159         if (pid == -1) {
 1160             ERR("{core} fork() failed! Goodbye cruel world!\n");
 1161             exit(1);
 1162         }
 1163         else if (pid == 0) { /* child */
 1164             handle_connections();
 1165             exit(0);
 1166         }
 1167         else { /* parent. Track new child. */
 1168             child_pids[child_num] = pid;
 1169         }
 1170     }
 1171 }
 1172 
 1173 /* Forks a new child to replace the old, dead, one with the given PID.*/
 1174 void replace_child_with_pid(pid_t pid) {
 1175     int i;
 1176 
 1177     /* find old child's slot and put a new child there */ 
 1178     for (i = 0; i < OPTIONS.NCORES; i++) {
 1179         if (child_pids[i] == pid) {
 1180             start_children(i, 1);
 1181             return;
 1182         }
 1183     }
 1184 
 1185     ERR("Cannot find index for child pid %d", pid);
 1186 }
 1187 
 1188 /* Manage status changes in child processes */
 1189 static void do_wait(int __attribute__ ((unused)) signo) {
 1190 
 1191     int status;
 1192     int pid = wait(&status);
 1193 
 1194     if (pid == -1) {
 1195         if (errno == ECHILD) {
 1196             ERR("{core} All children have exited! Restarting...\n");
 1197             start_children(0, OPTIONS.NCORES);
 1198         }
 1199         else if (errno == EINTR) {
 1200             ERR("{core} Interrupted wait\n");
 1201         }
 1202         else {
 1203             fail("wait");
 1204         }
 1205     }
 1206     else {
 1207         if (WIFEXITED(status)) {
 1208             ERR("{core} Child %d exited with status %d. Replacing...\n", pid, WEXITSTATUS(status));
 1209             replace_child_with_pid(pid);
 1210         }
 1211         else if (WIFSIGNALED(status)) {
 1212             ERR("{core} Child %d was terminated by signal %d. Replacing...\n", pid, WTERMSIG(status));
 1213             replace_child_with_pid(pid);
 1214         }
 1215     }
 1216 }
 1217 
 1218 void init_signals() {
 1219     struct sigaction act;
 1220 
 1221     sigemptyset(&act.sa_mask);
 1222     act.sa_flags = 0;
 1223     act.sa_handler = SIG_IGN;
 1224 
 1225     /* Avoid getting PIPE signal when writing to a closed file descriptor */
 1226     if (sigaction(SIGPIPE, &act, NULL) < 0)
 1227         fail("sigaction - sigpipe");
 1228 
 1229     /* We don't care if someone stops and starts a child process with kill (1) */
 1230     act.sa_flags = SA_NOCLDSTOP;
 1231 
 1232     act.sa_handler = do_wait;
 1233 
 1234     /* We do care when child processes change status */
 1235     if (sigaction(SIGCHLD, &act, NULL) < 0)
 1236         fail("sigaction - sigchld");
 1237 }
 1238 
 1239 /* Process command line args, create the bound socket,
 1240  * spawn child (worker) processes, and respawn if any die */
 1241 int main(int argc, char **argv) {
 1242     parse_cli(argc, argv);
 1243 
 1244     init_signals();
 1245 
 1246     init_globals();
 1247 
 1248     listener_socket = create_main_socket();
 1249 
 1250     /* load certificate, pass to handle_connections */
 1251     ssl_ctx = init_openssl();
 1252 
 1253     master_pid = getpid();
 1254 
 1255     if (OPTIONS.CHROOT && OPTIONS.CHROOT[0])
 1256         change_root();
 1257 
 1258     if (OPTIONS.UID || OPTIONS.GID)
 1259         drop_privileges();
 1260 
 1261     start_children(0, OPTIONS.NCORES);
 1262 
 1263     for (;;) {
 1264         /* Sleep and let the children work.
 1265          * Parent will be woken up if a signal arrives */
 1266         pause();
 1267     }
 1268 
 1269     exit(0); /* just a formality; we never get here */
 1270 }