Beispiel #1
0
/* subscribe to the (configured) multicast channel
 */
static int
subscribe( int* sockfd, struct in_addr* mcast_inaddr )
{
    struct sockaddr_in sa;
    const char* ipaddr = g_recopt.rec_channel;
    size_t rcvbuf_len = 0;
    int rc = 0;

    assert( sockfd && mcast_inaddr );

    if( 1 != inet_aton( ipaddr, &sa.sin_addr ) ) {
        mperror( g_flog, errno,
                "%s: Invalid subscription [%s:%d]: inet_aton",
                __func__, ipaddr, g_recopt.rec_port );
        return -1;
    }

    sa.sin_family = AF_INET;
    sa.sin_port = htons( (uint16_t)g_recopt.rec_port );

    if( 1 != inet_aton( g_recopt.mcast_addr, mcast_inaddr ) ) {
        mperror( g_flog, errno,
                "%s: Invalid multicast interface: [%s]: inet_aton",
                __func__, g_recopt.mcast_addr );
        return -1;
    }

    rc = calc_buf_settings( NULL, &rcvbuf_len );
    if (0 != rc) return rc;

    return setup_mcast_listener( &sa, mcast_inaddr,
            sockfd, (g_recopt.nosync_sbuf ? 0 : rcvbuf_len) );
}
Beispiel #2
0
/* 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;
}