Exemplo n.º 1
0
/* write timestamp-prepended message to file
 */
int
tmfputs( const char* s, FILE* stream )
{
    int n = -1, rc = 0, NO_RESET = 0;
    char tstamp[ 80 ] = {'\0'};
    size_t ts_len = sizeof(tstamp) - 1;
    struct timeval tv_now;
    const char* pidstr = get_pidstr( NO_RESET, NULL );

    (void)gettimeofday( &tv_now, NULL );

    errno = 0;
    do {
        rc = mk_tvstamp( &tv_now, tstamp, &ts_len, 0 );
        if( 0 != rc ) break;

        if( (n = fputs( tstamp, stream )) < 0  ||
            (n = fputs( "\t", stream ))   < 0  ||
            (n = fputs( pidstr, stream )) < 0  ||
            (n = fputs( "\t", stream ))   < 0 )
            break;

        if( (n = fputs( s, stream )) < 0 )
            break;
    } while(0);

    if( n < 0 && errno ) {
        perror( "fputs" );
    }

    return (0 != rc) ? -1 : n;
}
Exemplo n.º 2
0
/* write timestamp-prepended formatted message to file
 */
int
tmfprintf( FILE* stream, const char* format, ... )
{
    va_list ap;
    int n = -1, total = 0, rc = 0, NO_RESET = 0;
    char tstamp[ 80 ] = {'\0'};
    size_t ts_len = sizeof(tstamp) - 1;
    struct timeval tv_now;
    const char* pidstr = get_pidstr( NO_RESET, NULL );

    (void)gettimeofday( &tv_now, NULL );

    errno = 0;
    do {
        rc = mk_tvstamp( &tv_now, tstamp, &ts_len, 0 );
        if( 0 != rc ) break;

        n = fprintf( stream, "%s\t%s\t", tstamp, pidstr );
        if( n <= 0 ) break;
        total += n;

        va_start( ap, format );
        n = vfprintf( stream, format, ap );
        va_end( ap );

        if( n <= 0 ) break;
        total += n;

    } while(0);

    if( n <= 0 ) {
        perror( "fprintf/vfprintf" );
        return -1;
    }

    return (0 != rc) ? -1 : total;
}
Exemplo n.º 3
0
Arquivo: udpxy.c Projeto: avble/udpxy
/* process command to relay udp traffic
 *
 */
static int
udp_relay( int sockfd, const char* param, size_t plen,
           const struct in_addr* mifaddr,
           struct server_ctx* ctx )
{
    char                mcast_addr[ IPADDR_STR_SIZE ];
    struct sockaddr_in  addr;

    uint16_t    port;
    pid_t       new_pid;
    int         rc = 0, flags; 
    int         msockfd = -1, sfilefd = -1,
                dfilefd = -1, srcfd = -1;
    char        dfile_name[ MAXPATHLEN ];
    size_t      rcvbuf_len = 0;

    assert( (sockfd > 0) && param && plen && ctx );

    TRACE( (void)tmfprintf( g_flog, "udp_relay : new_socket=[%d] param=[%s]\n",
                        sockfd, param) );
    do {
        rc = parse_udprelay( param, plen, mcast_addr, IPADDR_STR_SIZE, &port );
        if( 0 != rc ) {
            (void) tmfprintf( g_flog, "Error [%d] parsing parameters [%s]\n",
                            rc, param );
            break;
        }

        if( 1 != inet_aton(mcast_addr, &addr.sin_addr) ) {
            (void) tmfprintf( g_flog, "Invalid address: [%s]\n", mcast_addr );
            rc = ERR_INTERNAL;
            break;
        }

        addr.sin_family = AF_INET;
        addr.sin_port = htons( (short)port );

    } while(0);

    if( 0 != rc ) {
        (void) send_http_response( sockfd, 500, "Service error" );
        return rc;
    }

    /* start the (new) process to relay traffic */

    if( 0 != (new_pid = fork()) ) {
        rc = add_client( ctx, new_pid, mcast_addr, port, sockfd );
        return rc; /* parent returns */
    }

    /* child process:
     */
    TRACE( (void)tmfprintf( g_flog, "Client process=[%d] started "
                "for socket=[%d]\n", getpid(), sockfd) );

    (void) get_pidstr( PID_RESET, "c" );

    (void)close( ctx->lsockfd );

    /* close the reading end of the comm. pipe */
    (void)close( ctx->cpipe[0] );
    ctx->cpipe[0] = -1;

    do {
        /* make write end of pipe non-blocking (we don't want to
        * block on pipe write while relaying traffic)
        */
        if( -1 == (flags = fcntl( ctx->cpipe[1], F_GETFL )) ||
            -1 == fcntl( ctx->cpipe[1], F_SETFL, flags | O_NONBLOCK ) ) {
            mperror( g_flog, errno, "%s: fcntl", __func__ );
            rc = -1;
            break;
        }

        if( NULL != g_uopt.dstfile ) {
            (void) snprintf( dfile_name, MAXPATHLEN - 1,
                    "%s.%d", g_uopt.dstfile, getpid() );
            dfilefd = creat( dfile_name, S_IRUSR | S_IWUSR | S_IRGRP );
            if( -1 == dfilefd ) {
                mperror( g_flog, errno, "%s: g_uopt.dstfile open", __func__ );
                rc = -1;
                break;
            }

            TRACE( (void)tmfprintf( g_flog,
                        "Dest file [%s] opened as fd=[%d]\n",
                        dfile_name, dfilefd ) );
        }
        else dfilefd = -1;

        if( NULL != g_uopt.srcfile ) {
            sfilefd = open( g_uopt.srcfile, O_RDONLY | O_NOCTTY );
            if( -1 == sfilefd ) {
                mperror( g_flog, errno, "%s: g_uopt.srcfile open", __func__ );
                rc = -1;
            }
            else {
                TRACE( (void) tmfprintf( g_flog, "Source file [%s] opened\n",
                            g_uopt.srcfile ) );
                srcfd = sfilefd;
            }
        }
        else {
            rc = calc_buf_settings( NULL, &rcvbuf_len );
            if (0 == rc ) {
                rc = setup_mcast_listener( &addr, mifaddr, &msockfd,
                    (g_uopt.nosync_sbuf ? 0 : rcvbuf_len) );
                srcfd = msockfd;
            }
        }
        if( 0 != rc ) break;

        rc = relay_traffic( srcfd, sockfd, ctx, dfilefd, mifaddr );
        if( 0 != rc ) break;

    } while(0);

    if( msockfd > 0 ) {
        close_mcast_listener( msockfd, mifaddr );
    }
    if( sfilefd > 0 ) {
       (void) close( sfilefd );
       TRACE( (void) tmfprintf( g_flog, "Source file [%s] closed\n",
                            g_uopt.srcfile ) );
    }
    if( dfilefd > 0 ) {
       (void) close( dfilefd );
       TRACE( (void) tmfprintf( g_flog, "Dest file [%s] closed\n",
                            dfile_name ) );
    }

    if( 0 != rc ) {
        (void) send_http_response( sockfd, 500, "Service error" );
    }

    (void) close( sockfd );
    free_server_ctx( ctx );

    closelog();

    TRACE( (void)tmfprintf( g_flog, "Child process=[%d] exits with rc=[%d]\n",
                getpid(), rc) );

    if( g_flog && (stderr != g_flog) ) {
        (void) fclose(g_flog);
    }

    free_uopt( &g_uopt );

    rc = ( 0 != rc ) ? ERR_INTERNAL : rc;
    exit(rc);   /* child exits */

    return rc;
}
Exemplo n.º 4
0
Arquivo: udpxy.c Projeto: avble/udpxy
int
udpxy_main( int argc, char* const argv[] )
{
    int rc = 0, ch = 0, port = -1,
        custom_log = 0, no_daemon = 0;

    char ipaddr[IPADDR_STR_SIZE] = "\0",
         mcast_addr[IPADDR_STR_SIZE] = "\0";

    char pidfile[ MAXPATHLEN ] = "\0";
    u_short MIN_MCAST_REFRESH = 0, MAX_MCAST_REFRESH = 0;

/* support for -r -w (file read/write) option is disabled by default;
 * those features are experimental and for dev debugging ONLY
 * */
#ifdef UDPXY_FILEIO
    static const char UDPXY_OPTMASK[] = "TvSa:l:p:m:c:B:n:R:r:w:H:M:";
#else
    static const char UDPXY_OPTMASK[] = "TvSa:l:p:m:c:B:n:R:H:M:";
#endif

    struct sigaction qact, iact, cact, oldact;

    init_app_info();
    (void) get_pidstr( PID_RESET, "S" );

    rc = init_uopt( &g_uopt );
    while( (0 == rc) && (-1 != (ch = getopt(argc, argv, UDPXY_OPTMASK))) ) {
        switch( ch ) {
            case 'v': set_verbose( &g_uopt.is_verbose );
                      break;
            case 'T': no_daemon = 1;
                      break;
            case 'S': g_uopt.cl_tpstat = uf_TRUE;
                      break;
            case 'a':
                      rc = get_ipv4_address( optarg, ipaddr, sizeof(ipaddr) );
                      if( 0 != rc ) {
                        (void) fprintf( stderr, "Invalid address: [%s]\n",
                                        optarg );
                          rc = ERR_PARAM;
                      }
                      break;

            case 'p':
                      port = atoi( optarg );
                      if( port <= 0 ) {
                        (void) fprintf( stderr, "Invalid port number: [%d]\n",
                                        port );
                        rc = ERR_PARAM;
                      }
                      break;

            case 'm':
                      rc = get_ipv4_address( optarg, mcast_addr,
                              sizeof(mcast_addr) );
                      if( 0 != rc ) {
                        (void) fprintf( stderr, "Invalid multicast address: "
                                "[%s]\n", optarg );
                          rc = ERR_PARAM;
                      }
                      break;

            case 'c':
                      g_uopt.max_clients = atoi( optarg );
                      if( (g_uopt.max_clients < MIN_CLIENT_COUNT) ||
                          (g_uopt.max_clients > MAX_CLIENT_COUNT) ) {
                        (void) fprintf( stderr,
                                "Client count should be between %d and %d\n",
                                MIN_CLIENT_COUNT, MAX_CLIENT_COUNT );
                        rc = ERR_PARAM;
                      }
                      break;

            case 'l':
                      g_flog = fopen( optarg, "a" );
                      if( NULL == g_flog ) {
                        rc = errno;
                        (void) fprintf( stderr, "Error opening logfile "
                                "[%s]: %s\n",
                                optarg, strerror(rc) );
                        rc = ERR_PARAM;
                        break;
                      }

                      Setlinebuf( g_flog );
                      custom_log = 1;
                      break;

            case 'B':
                      rc = a2size(optarg, &g_uopt.rbuf_len);
                      if( 0 != rc ) {
                            (void) fprintf( stderr, "Invalid buffer size: [%s]\n",
                                    optarg );
                            exit( ERR_PARAM );
                      }
                      else if( (g_uopt.rbuf_len < MIN_MCACHE_LEN) ||
                          (g_uopt.rbuf_len > MAX_MCACHE_LEN) ) {
                        fprintf(stderr, "Buffer size "
                                "must be within [%ld-%ld] bytes\n",
                                (long)MIN_MCACHE_LEN, (long)MAX_MCACHE_LEN );
                        rc = ERR_PARAM;
                      }
                      break;

            case 'n':
                      g_uopt.nice_incr = atoi( optarg );
                      if( 0 == g_uopt.nice_incr ) {
                        (void) fprintf( stderr,
                            "Invalid nice-value increment: [%s]\n", optarg );
                        rc = ERR_PARAM;
                        break;
                      }
                      break;

            case 'R':
                      g_uopt.rbuf_msgs = atoi( optarg );
                      if( (g_uopt.rbuf_msgs <= 0) && (-1 != g_uopt.rbuf_msgs) ) {
                        (void) fprintf( stderr,
                                "Invalid Rmsgs size: [%s]\n", optarg );
                        rc = ERR_PARAM;
                        break;
                      }
                      break;

            case 'H':
                      g_uopt.dhold_tmout = (time_t)atoi( optarg );
                      if( (0 == g_uopt.dhold_tmout) ||
                          ((g_uopt.dhold_tmout) < 0 && (-1 != g_uopt.dhold_tmout)) ) {
                        (void) fprintf( stderr, "Invalid value for max time "
                                "to hold buffered data: [%s]\n", optarg );
                        rc = ERR_PARAM;
                        break;
                      }
                      break;

    #ifdef UDPXY_FILEIO
            case 'r':
                      if( 0 != access(optarg, R_OK) ) {
                        perror("source file - access");
                        rc = ERR_PARAM;
                        break;
                      }

                      g_uopt.srcfile = strdup( optarg );
                      break;

            case 'w':
                      g_uopt.dstfile = strdup( optarg );
                      break;
    #endif /* UDPXY_FILEIO */
            case 'M':
                      g_uopt.mcast_refresh = (u_short)atoi( optarg );

                      MIN_MCAST_REFRESH = 30;
                      MAX_MCAST_REFRESH = 64000;
                      if( g_uopt.mcast_refresh &&
                         (g_uopt.mcast_refresh < MIN_MCAST_REFRESH ||
                          g_uopt.mcast_refresh > MAX_MCAST_REFRESH )) {
                            (void) fprintf( stderr, 
                                "Invalid multicast refresh period [%d] seconds, "
                                "min=[%d] sec, max=[%d] sec\n",
                                (int)g_uopt.mcast_refresh,
                                (int)MIN_MCAST_REFRESH, (int)MAX_MCAST_REFRESH );
                            rc = ERR_PARAM;
                            break;
                       }
                      break;

            case ':':
                      (void) fprintf( stderr,
                              "Option [-%c] requires an argument\n",
                                    optopt );
                      rc = ERR_PARAM;
                      break;
            case '?':
                      (void) fprintf( stderr,
                              "Unrecognized option: [-%c]\n", optopt );
                      rc = ERR_PARAM;
                      break;

            default:
                     usage( argv[0], stderr );
                     rc = ERR_PARAM;
                     break;
        }
    } /* while getopt */

    if (rc) {
        free_uopt( &g_uopt );
        return rc;
    }

    openlog( g_udpxy_app, LOG_CONS | LOG_PID, LOG_LOCAL0 );

    do {
        if( (argc < 2) || (port <= 0) || (rc != 0) ) {
            usage( argv[0], stderr );
            rc = ERR_PARAM; break;
        }

        if( '\0' == mcast_addr[0] ) {
            (void) strncpy( mcast_addr, IPv4_ALL, sizeof(mcast_addr) - 1 );
        }

        if( !custom_log ) {
            /* in debug mode output goes to stderr, otherwise to /dev/null */
            g_flog = ((uf_TRUE == g_uopt.is_verbose)
                    ? stderr
                    : fopen( "/dev/null", "a" ));
            if( NULL == g_flog ) {
                perror("fopen");
                rc = ERR_INTERNAL; break;
            }
        }

        if( 0 == geteuid() ) {
            if( !no_daemon ) {
                if( stderr == g_flog ) {
                    (void) fprintf( stderr,
                        "Logfile must be specified to run "
                        "in verbose mode in background\n" );
                    rc = ERR_PARAM; break;
                }

                if( 0 != (rc = daemonize(0, g_flog)) ) {
                    rc = ERR_INTERNAL; break;
                }
            }

            rc = set_pidfile( g_udpxy_app, port, pidfile, sizeof(pidfile) );
            if( 0 != rc ) {
                mperror( g_flog, errno, "set_pidfile" );
                rc = ERR_INTERNAL; break;
            }

            if( 0 != (rc = make_pidfile( pidfile, getpid(), g_flog )) )
                break;
        }

        qact.sa_handler = handle_quitsigs;
        sigemptyset(&qact.sa_mask);
        qact.sa_flags = 0;

        if( (sigaction(SIGTERM, &qact, &oldact) < 0) ||
            (sigaction(SIGQUIT, &qact, &oldact) < 0) ||
            (sigaction(SIGINT,  &qact, &oldact) < 0)) {
            perror("sigaction-quit");
            rc = ERR_INTERNAL; break;
        }

        iact.sa_handler = SIG_IGN;
        sigemptyset(&iact.sa_mask);
        iact.sa_flags = 0;

        if( (sigaction(SIGPIPE, &iact, &oldact) < 0) ) {
            perror("sigaction-ignore");
            rc = ERR_INTERNAL; break;
        }

        cact.sa_handler = handle_sigchld;
        sigemptyset(&cact.sa_mask);
        cact.sa_flags = 0;

        if( sigaction(SIGCHLD, &cact, &oldact) < 0 ) {
            perror("sigaction-sigchld");
            rc = ERR_INTERNAL; break;
        }

        syslog( LOG_NOTICE, "%s is starting\n", g_udpxy_finfo );
        TRACE( printcmdln( g_flog, g_udpxy_finfo, argc, argv ) );

        rc = srv_loop( ipaddr, port, mcast_addr );

        syslog( LOG_NOTICE, "%s is exiting with rc=[%d]\n",
                g_udpxy_finfo, rc);
        TRACE( tmfprintf( g_flog, "%s is exiting with rc=[%d]\n",
                    g_udpxy_app, rc ) );
        TRACE( printcmdln( g_flog, g_udpxy_finfo, argc, argv ) );
    } while(0);

    if( '\0' != pidfile[0] ) {
        if( -1 == unlink(pidfile) ) {
            mperror( g_flog, errno, "unlink [%s]", pidfile );
        }
    }

    if( g_flog && (stderr != g_flog) ) {
        (void) fclose(g_flog);
    }

    closelog();
    free_uopt( &g_uopt );

    return rc;
}