Advertisement
FlyFar

server.c

May 16th, 2024
393
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.46 KB | Cybersecurity | 0 0
  1.  
  2. #ifdef STANDALONE
  3.  
  4. /* Routine "main" in here to define a standalone main server.
  5.  *  File:  server.c
  6.  *  Author: Derric Scott (dtscott@scott.net)
  7.  *  Copyright (c) 1998 Derric Scott (dtscott@scott.net)
  8.  *      All rights reserved
  9.  *  Created: 24Mar98
  10.  *
  11.  *  This program is a prefix to the in.pop3d daemon that will enable
  12.  *  it to be used as a standalone daemon without being run from inetd.
  13.  *
  14.  */
  15.  
  16. /* common includes and defines for UDP, TCP and T/TCP
  17.  * clients and servers */
  18.  
  19. #include    <sys/types.h>
  20. #include    <sys/wait.h>
  21. #include    <sys/socket.h>
  22. #include    <netinet/in.h>
  23. #include    <arpa/inet.h>
  24. #include    <stdio.h>
  25. #include    <stdlib.h>
  26. #include    <string.h>
  27. #include    <unistd.h>
  28. #include    <syslog.h>
  29. #include    <signal.h>
  30. #include    <errno.h>
  31.  
  32. typedef unsigned char uchar;
  33. char *naddr2str(struct sockaddr_in *saptr);
  34.  
  35. void err_quit(const char *);
  36. void err_sys(const char *);
  37.  
  38. #define     TCP_SERV_PORT   203
  39. #define     MAXSTR      128
  40. static  int port = TCP_SERV_PORT;
  41. static  int inet = 1;
  42. /* Global value of client's address. */
  43. char    client_ip[MAXSTR];
  44.  
  45. int
  46. main(int argc, char *argv[])
  47.  {  
  48.    char str[MAXSTR];
  49.    struct sockaddr_in serv, child;
  50.    int  listenfd, sockfd, n, childlen, on = 1;
  51.    int  sock_in, sock_out, pidstatus, child_process;
  52.    pid_t pid;
  53.    struct linger linger;
  54.    int addr_len = sizeof(struct sockaddr_in);
  55.  
  56.    parse_opts(argc,argv);
  57.    memset(client_ip, 0, MAXSTR);
  58.  
  59.    if( inet ) {     /* if it should run via inetd, then just go... */
  60.     getpeername(STDIN_FILENO, (struct sockaddr *) &serv, &addr_len);
  61.     strcpy(client_ip,inet_ntoa(serv.sin_addr));
  62. /*  strcpy(client_ip,"0.0.0.0"); */
  63.     inetd_main(argc, argv);
  64.     exit(0);
  65.    }
  66.  
  67.    /* Fork away from the parent and let child run on as the daemon */
  68.    if ( (pid = fork()) > 0 ) {  /* Am the parent, exit */
  69.     exit(0);
  70.    } else if (pid < 0 ) {   /* An error ocurred on the fork */
  71.     snprintf(str,MAXSTR,"initial fork error: %s",strerror(errno));
  72.     err_quit(str);
  73.    }
  74.  
  75.    /* Ok, we're the daemon child, so start the daemon processing */
  76.  
  77.    svrsetsigs();
  78.  
  79.    openlog( argv[0], LOG_PID, LOG_MAIL );
  80.    syslog(LOG_MAIL|LOG_INFO, "POP3 daemon starting");
  81.  
  82.    if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
  83.     snprintf(str,MAXSTR,"socket error: %s",strerror(errno));
  84.     err_quit(str);
  85.    }
  86.  
  87.    /* Try to set timeouts down for quick turn-arounds... */
  88.    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on));
  89.    linger.l_onoff = on;
  90.    linger.l_linger = 15;
  91.    setsockopt(listenfd, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger));
  92.  
  93.    memset(&serv, 0, sizeof(serv));
  94.    serv.sin_family = AF_INET;
  95.    serv.sin_addr.s_addr = htonl(INADDR_ANY);
  96.    serv.sin_port = htons(port);
  97.    
  98.    if (bind(listenfd, (struct sockaddr *) &serv, sizeof(serv)) < 0) {
  99.     snprintf(str,MAXSTR,"bind error: %s",strerror(errno));
  100.     err_quit(str);
  101.    }
  102.    
  103.    if (listen(listenfd, SOMAXCONN) < 0) {
  104.     snprintf(str,MAXSTR,"listen error: %s",strerror(errno));
  105.     err_quit(str);
  106.    }
  107.  
  108.    for (child_process=0;!child_process;)  { /* Main processing loop */
  109.  
  110.     memset(client_ip, 0, MAXSTR);
  111.     memset(&child, 0, sizeof(child));
  112.     childlen = sizeof(child);
  113.     if ((sockfd = accept(listenfd, (struct sockaddr *) &child, &childlen)) < 0) {
  114.           if (errno != EINTR) {
  115.         snprintf(str,MAXSTR,"accept error (%s): %s",
  116.             naddr2str(&child),strerror(errno));
  117.         err_sys(str);
  118.           }
  119.           continue;
  120.     }
  121.  
  122.     if ((pid = fork()) == 0) {  /* This is the child */
  123.         close(listenfd);
  124.         sock_in = sockfd;
  125.         sock_out = sockfd;
  126.         /* Get out of loop and proceed below into child code. */
  127.         child_process = 1;
  128.  
  129.     } else {    /* Am parent, continue to listen - check error. */
  130.         if (pid < 0) {
  131.             snprintf(str,MAXSTR,"fork error: %s",strerror(errno));
  132.             err_sys("fork error");
  133.         }
  134.  
  135.         /* Now a quick while loop to clear all exited processes */
  136.         while (waitpid( -1, &pidstatus, WNOHANG ) > 0 ) ;
  137.  
  138.         /* Close this, the child is using it. */
  139.         close (sockfd);
  140.    
  141.         child_process = 0;  /* Just guarantee parent never leaves */
  142.  
  143.     } /* end if fork */
  144.     } /* end for(;;) */
  145.  
  146.     /* Ok, from here on, the child picks up after the loop */
  147.     /* Let's close the parent listening socket */
  148.     close (listenfd);
  149.  
  150.     /* Prepare stdin and stdout for the "normal" inetd-like pop3d code */
  151.     dup2(sock_in, 0);
  152.     dup2(sock_out, 1);
  153.  
  154.     /* Save the client's IP address for logging later */
  155.     strncpy(client_ip,naddr2str(&child),MAXSTR-1);
  156.  
  157.     /* Just to be simple ... the extant code already has all this. */
  158.     closelog();
  159.  
  160.     /* Go do it - this is the entry to the original in.pop3d code. */
  161.     inetd_main(argc, argv);
  162.  
  163.     /* We'll never get back down here, but anyway.... */
  164.     close (sock_in);
  165.     close (sock_out);
  166.     exit(0);
  167. }
  168.  
  169. void
  170. err_sys(const char *msg) {
  171.     syslog(LOG_MAIL|LOG_INFO, msg );
  172. }
  173.  
  174. void
  175. err_quit(const char *msg) {
  176.     syslog(LOG_MAIL|LOG_INFO, msg );
  177.     exit(1);
  178. }
  179.  
  180. char *
  181. naddr2str(struct sockaddr_in *saptr) {
  182.     static char str[MAXSTR];
  183.     char    *bp, *ap;
  184.     int l;
  185.     struct sockaddr sa;
  186.    
  187.         /* check for null/zero family */
  188.         if (saptr == NULL)
  189.                 return "NULLADDR";
  190.         if (saptr->sin_family == 0)
  191.                 return "0";
  192.  
  193.         switch (saptr->sin_family)
  194.         {
  195. /*          case AF_UNIX:
  196.  *              if (saptr->sunix.sun_path[0] != '\0')
  197.  *                      snprintf(str,MAXSTR,"[UNIX: %.64s]", saptr->sunix.sun_path);
  198.  *              else
  199.  *                      snprintf(str,MAXSTR,"[UNIX: localhost]");
  200.  *              return str;
  201.  */
  202.           case AF_INET:
  203.                 return inet_ntoa(saptr->sin_addr);
  204.     }
  205.  
  206.         /* unknown family -- just dump bytes */
  207.     memcpy(&sa,saptr,sizeof(sa));
  208.         (void) snprintf(str,MAXSTR,"Family %d: ", sa.sa_family);
  209.         bp = &str[strlen(str)];
  210.         ap = sa.sa_data;
  211.         for (l = sizeof sa.sa_data; --l >= 0; )
  212.         {
  213.                 (void) sprintf(bp, "%02x:", *ap++ & 0377);
  214.                 bp += 3;
  215.         }
  216.         *--bp = '\0';
  217.         return str;
  218.  
  219. } /* end naddr2str */
  220.  
  221. static void d_catchint(int sig);
  222. static void d_hangup(int sig);
  223. static void d_sigchld(int sig);
  224.  
  225. int
  226. svrsetsigs(){
  227.     int i;
  228.  
  229.     for( i=0; i<NSIG; i++) {
  230.         /* default is to just log and continue */
  231.         signal(i,d_catchint);
  232.     }
  233.     /* and now let the following override certain ones... */
  234.  
  235.     /* Handle process signals ourself */
  236.     signal(SIGCHLD,d_sigchld);      /* A subprocess has exited */
  237.     signal(SIGHUP, d_hangup);       /* socket signals */
  238.     signal(SIGURG, d_hangup);
  239.     signal(SIGTERM,d_hangup);
  240.  
  241. #ifdef LINUX
  242. # ifdef SIGBUS
  243.     signal(SIGBUS, d_hangup);       /* fatal program errors */
  244. # endif
  245. #endif
  246.     signal(SIGSEGV,d_hangup);
  247.     signal(SIGILL, d_hangup);
  248.     signal(SIGIOT, d_hangup);
  249.     signal(SIGPIPE,d_hangup);
  250. }
  251.  
  252. static void
  253. d_catchint(int sig) {
  254.     syslog(LOG_MAIL|LOG_INFO, "ERROR - Caught unexpected signal: %d",sig);
  255.     signal(sig,d_catchint);     /* Reset to get it again. */
  256. }
  257.    
  258. static void
  259. d_hangup(int sig) {
  260.     syslog(LOG_MAIL|LOG_INFO, "Caught signal - Hanging up: %d",sig);
  261.     exit(0);
  262. }
  263.  
  264. static void
  265. d_sigchld(int sig) {
  266.     int pidstatus;
  267.     while (waitpid( -1, &pidstatus, WNOHANG ) > 0 ) ;
  268.     signal(SIGCHLD,d_sigchld);  /* Reset to get it again. */
  269. }
  270.  
  271. #else
  272. #include <stdio.h>
  273. #define     TCP_SERV_PORT   110
  274. #define     MAXSTR      128
  275.  
  276. static  int port = TCP_SERV_PORT;
  277. static  int inet = 1;
  278. /* Global value of client's address. */
  279. char    client_ip[MAXSTR];
  280.  
  281. #endif
  282.  
  283. extern  int niceval;
  284. extern  int debug;
  285.  
  286. int
  287. parse_opts(int argc, char *argv[]) {
  288.     extern char *optarg;
  289.     extern int optind;
  290.     int opt, got_b=0, got_i=0;
  291.  
  292.     while ((opt = getopt(argc, argv, "p:n:dibh")) != EOF) {
  293.         switch(opt) {
  294.           case 'p':
  295.             port = atoi(optarg);
  296.             break;
  297.           case 'n':
  298.             niceval = atoi(optarg);
  299.             break;
  300.           case 'd':
  301.             debug = 1;
  302.             break;
  303.           case 'b':
  304.             inet = 0;
  305.             got_b = 1;
  306.             break;
  307.           case 'i':
  308.             inet = 1;
  309.             got_i = 1;
  310.             break;
  311.           case 'h':
  312.           default:
  313.             fprintf(stderr,"Usage: %s [options]\n",argv[0]);
  314.             fprintf(stderr,"  -h       Help - this message\n");
  315.             fprintf(stderr,"  -d       Debug logging mode\n");
  316.             fprintf(stderr,"  -i       Inetd mode (default)\n");
  317.             fprintf(stderr,"  -b       Background daemon mode\n");
  318.             fprintf(stderr,"  -p port  Listening port number\n");
  319.             fprintf(stderr,"  -n nval  Children to run 'niced'\n");
  320.             exit(1);
  321.         } /* end switch */
  322.     } /* end while */
  323.  
  324.     if( got_b && got_i ) {
  325.         fprintf(stderr,"Options b and i are mutually exclusive.\n");
  326.         fprintf(stderr,"  Use '-h' for help.\n");
  327.         exit(1);
  328.     }
  329.  
  330. } /* end parse_opts */
  331.  
  332.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement