owamp/protocol.c
/*
 * Function:        _OWPReadTestRequest
 *
 * Description:        
 *         This function reads a test request off the wire and encodes
 *         the information in a TestSession record.
 *
 *         If it is called in a server context, the acceptval pointer will
 *         be non-null and will be set. (i.e. if there is a memory allocation
 *         error, it will be set to OWP_CNTRL_FAILURE. If there is invalid
 *         data in the TestRequest it will be set to OWP_CNTRL_REJECT.)
 *
 * In Args:        
 *
 * Out Args:        
 *
 * Scope:        
 * Returns:        
 * Side Effect:        
 */
_OWPReadTestRequest
Description:
This function reads a test request off the wire and encodes
the information in a TestSession record.

If it is called in a server context, the acceptval pointer will
be non-null and will be set.

In Args.

Out Args.

Side Effect.
_OWPReadTestRequest Description : This function reads a test request off the wire and encodes the information in a TestSession record . If it is called in a server context the acceptval pointer will be non - null and will be set . In Args . Out Args . Side Effect .
OWPErrSeverity
_OWPReadTestRequest(
        OWPControl      cntrl,
        int             *retn_on_intr,
        OWPTestSession  *test_session,
        OWPAcceptType   *accept_ret
        )
{
    char                    *buf = (char *)cntrl->msg;
    OWPErrSeverity          err_ret=OWPErrOK;
    struct sockaddr_storage sendaddr_rec;
    struct sockaddr_storage recvaddr_rec;
    socklen_t               addrlen = sizeof(sendaddr_rec);
    I2Addr                  SendAddr=NULL;
    I2Addr                  RecvAddr=NULL;
    uint8_t                 ipvn;
    OWPBoolean              conf_sender;
    OWPBoolean              conf_receiver;
    OWPSID                  sid;
    OWPTestSpec             tspec;
    int                     rc;
    OWPTestSession          tsession;
    OWPAcceptType           accept_mem;
    OWPAcceptType           *accept_ptr = &accept_mem;
    int                     ival=0;
    int                     *intr=&ival;
    const struct sockaddr   *remote_saddr;
    socklen_t               remote_saddrlen;
    *test_session = NULL;
    memset(&sendaddr_rec,0,addrlen);
    memset(&recvaddr_rec,0,addrlen);
    memset(&tspec,0,sizeof(tspec));
    memset(sid,0,sizeof(sid));
    if(!_OWPStateIs(cntrl->twoway ? _OWPStateTestRequestTW : _OWPStateTestRequest,cntrl)){
        OWPError(cntrl->ctx,OWPErrFATAL,OWPErrINVALID,
                "_OWPReadTestRequest: called in wrong state.");
        return OWPErrFATAL;
    }
    if(accept_ret)
        accept_ptr = accept_ret;
    *accept_ptr = OWP_CNTRL_ACCEPT;
    if(retn_on_intr){
        intr = retn_on_intr;
    }
    if(!accept_ret && (_OWPReceiveBlocksIntr(cntrl,(uint8_t *)&buf[0],1,intr) != 1)){
        OWPError(cntrl->ctx,OWPErrFATAL,errno,
                "_OWPReadTestRequest: Unable to read from socket.");
        cntrl->state = _OWPStateInvalid;
        *accept_ptr = OWP_CNTRL_INVALID;
        return OWPErrFATAL;
    }
    if(_OWPReceiveBlocksIntr(cntrl,(uint8_t *)&buf[16],_OWP_TEST_REQUEST_BLK_LEN-1,
                intr) != (_OWP_TEST_REQUEST_BLK_LEN-1)){
        OWPError(cntrl->ctx,OWPErrFATAL,errno,
                "_OWPReadTestRequest: Unable to read from socket.");
        cntrl->state = _OWPStateInvalid;
        *accept_ptr = OWP_CNTRL_INVALID;
        return OWPErrFATAL;
    }
    _OWPRecvHMACAdd(cntrl,buf,6);
    if(!_OWPRecvHMACCheckClear(cntrl,&buf[96])){
        OWPError(cntrl->ctx,OWPErrFATAL,EACCES,
                "_OWPReadTestRequest: Invalid HMAC");
        cntrl->state = _OWPStateInvalid;
        *accept_ptr = OWP_CNTRL_INVALID;
        return OWPErrFATAL;
    }
    if( (err_ret = _OWPDecodeTestRequestPreamble(cntrl->ctx,
                    (accept_ret!=NULL),cntrl->msg,
                    _OWP_TEST_REQUEST_BLK_LEN*_OWP_RIJNDAEL_BLOCK_SIZE,
                    cntrl->twoway,
                    (struct sockaddr*)&sendaddr_rec,
                    (struct sockaddr*)&recvaddr_rec,&addrlen,&ipvn,
                    &conf_sender,&conf_receiver,sid,&tspec)) != OWPErrOK){
        if(err_ret < OWPErrWARNING){
            cntrl->state = _OWPStateInvalid;
            *accept_ptr = OWP_CNTRL_INVALID;
            return OWPErrFATAL;
        }else if(accept_ret){
            *accept_ptr = OWP_CNTRL_UNSUPPORTED;
            return OWPErrFATAL;
        }
    }
    remote_saddr = I2AddrSAddr(cntrl->remote_addr,&remote_saddrlen);
    err_ret = _OWPTestSessionSetIPv6LLScope(
        cntrl->ctx,remote_saddr,remote_saddrlen,
        (struct sockaddr*)&sendaddr_rec,addrlen);
    if (err_ret != OWPErrOK) {
        *accept_ptr = OWP_CNTRL_UNSUPPORTED;
        return err_ret;
    }
    err_ret = _OWPTestSessionSetIPv6LLScope(
        cntrl->ctx,remote_saddr,remote_saddrlen,
        (struct sockaddr*)&recvaddr_rec,addrlen);
    if (err_ret != OWPErrOK) {
        *accept_ptr = OWP_CNTRL_UNSUPPORTED;
        return err_ret;
    }
    if (cntrl->twoway) {
        const struct sockaddr *local_saddr;
        socklen_t local_saddrlen;
        _OWPSetSAddrIfUnspec(cntrl->ctx,remote_saddr,
                             (struct sockaddr*)&sendaddr_rec);
        local_saddr = I2AddrSAddr(cntrl->local_addr,&local_saddrlen);
        _OWPSetSAddrIfUnspec(cntrl->ctx,local_saddr,
                             (struct sockaddr*)&recvaddr_rec);
    }
    cntrl->state &= ~_OWPStateTestRequest;
    cntrl->state |= _OWPStateTestRequestSlots;
    SendAddr = I2AddrBySAddr(OWPContextErrHandle(cntrl->ctx),
            (struct sockaddr*)&sendaddr_rec,addrlen,SOCK_DGRAM,IPPROTO_UDP);
    RecvAddr = I2AddrBySAddr(OWPContextErrHandle(cntrl->ctx),
            (struct sockaddr*)&recvaddr_rec,addrlen,SOCK_DGRAM,IPPROTO_UDP);
    if( !(tsession = _OWPTestSessionAlloc(cntrl,SendAddr,conf_sender,
                    RecvAddr,conf_receiver,&tspec))){
        err_ret = OWPErrWARNING;
        *accept_ptr = OWP_CNTRL_FAILURE;
        goto error;
    }
    if(!cntrl->twoway){
        memcpy(tsession->sid,sid,sizeof(sid));
        if(tsession->test_spec.nslots > _OWPSLOT_BUFSIZE){
            tsession->test_spec.slots =
                calloc(tsession->test_spec.nslots,sizeof(OWPSlot));
        }else{
            tsession->test_spec.slots = tsession->slot_buffer;
        }
        if( (rc = _OWPReadTestRequestSlots(cntrl,intr,
                                           tsession->test_spec.nslots,
                                           tsession->test_spec.slots)) < OWPErrOK){
            cntrl->state = _OWPStateInvalid;
            err_ret = (OWPErrSeverity)rc;
            *accept_ptr = OWP_CNTRL_INVALID;
            goto error;
        }
        if(!tsession->test_spec.slots){
            OWPError(cntrl->ctx,OWPErrFATAL,OWPErrUNKNOWN,
                     "calloc(%d,OWPSlot): %M",
                     tsession->test_spec.nslots);
            *accept_ptr = OWP_CNTRL_FAILURE;
            err_ret = OWPErrFATAL;
            goto error;
        }
    }
    if(accept_ret){
        cntrl->state |= _OWPStateAcceptSession;
    }else{
        cntrl->state |= _OWPStateFetching;
    }
    *test_session = tsession;
    return OWPErrOK;
error:
    if(tsession){
        _OWPTestSessionFree(tsession,OWP_CNTRL_FAILURE);
    }else{
        I2AddrFree(SendAddr);
        I2AddrFree(RecvAddr);
    }
    return err_ret;
}
OWPErrSeverity _OWPReadTestRequest ( OWPControl cntrl , int * retn_on_intr , OWPTestSession * test_session , OWPAcceptType * accept_ret ) { char * buf = ( char * ) cntrl -> msg ; OWPErrSeverity err_ret = OWPErrOK ; struct sockaddr_storage sendaddr_rec ; struct sockaddr_storage recvaddr_rec ; socklen_t addrlen = sizeof ( sendaddr_rec ) ; I2Addr SendAddr = NULL ; I2Addr RecvAddr = NULL ; uint8_t ipvn ; OWPBoolean conf_sender ; OWPBoolean conf_receiver ; OWPSID sid ; OWPTestSpec tspec ; int rc ; OWPTestSession tsession ; OWPAcceptType accept_mem ; OWPAcceptType * accept_ptr = & accept_mem ; int ival = 0 ; int * intr = & ival ; const struct sockaddr * remote_saddr ; socklen_t remote_saddrlen ; * test_session = NULL ; memset ( & sendaddr_rec , 0 , addrlen ) ; memset ( & recvaddr_rec , 0 , addrlen ) ; memset ( & tspec , 0 , sizeof ( tspec ) ) ; memset ( sid , 0 , sizeof ( sid ) ) ; if ( ! _OWPStateIs ( cntrl -> twoway ? _OWPStateTestRequestTW : _OWPStateTestRequest , cntrl ) ) { OWPError ( cntrl -> ctx , OWPErrFATAL , OWPErrINVALID , " " ) ; return OWPErrFATAL ; } if ( accept_ret ) accept_ptr = accept_ret ; * accept_ptr = OWP_CNTRL_ACCEPT ; if ( retn_on_intr ) { intr = retn_on_intr ; } if ( ! accept_ret && ( _OWPReceiveBlocksIntr ( cntrl , ( uint8_t * ) & buf [ 0 ] , 1 , intr ) != 1 ) ) { OWPError ( cntrl -> ctx , OWPErrFATAL , errno , " " ) ; cntrl -> state = _OWPStateInvalid ; * accept_ptr = OWP_CNTRL_INVALID ; return OWPErrFATAL ; } if ( _OWPReceiveBlocksIntr ( cntrl , ( uint8_t * ) & buf [ 16 ] , _OWP_TEST_REQUEST_BLK_LEN - 1 , intr ) != ( _OWP_TEST_REQUEST_BLK_LEN - 1 ) ) { OWPError ( cntrl -> ctx , OWPErrFATAL , errno , " " ) ; cntrl -> state = _OWPStateInvalid ; * accept_ptr = OWP_CNTRL_INVALID ; return OWPErrFATAL ; } _OWPRecvHMACAdd ( cntrl , buf , 6 ) ; if ( ! _OWPRecvHMACCheckClear ( cntrl , & buf [ 96 ] ) ) { OWPError ( cntrl -> ctx , OWPErrFATAL , EACCES , " " ) ; cntrl -> state = _OWPStateInvalid ; * accept_ptr = OWP_CNTRL_INVALID ; return OWPErrFATAL ; } if ( ( err_ret = _OWPDecodeTestRequestPreamble ( cntrl -> ctx , ( accept_ret != NULL ) , cntrl -> msg , _OWP_TEST_REQUEST_BLK_LEN * _OWP_RIJNDAEL_BLOCK_SIZE , cntrl -> twoway , ( struct sockaddr * ) & sendaddr_rec , ( struct sockaddr * ) & recvaddr_rec , & addrlen , & ipvn , & conf_sender , & conf_receiver , sid , & tspec ) ) != OWPErrOK ) { if ( err_ret < OWPErrWARNING ) { cntrl -> state = _OWPStateInvalid ; * accept_ptr = OWP_CNTRL_INVALID ; return OWPErrFATAL ; } else if ( accept_ret ) { * accept_ptr = OWP_CNTRL_UNSUPPORTED ; return OWPErrFATAL ; } } remote_saddr = I2AddrSAddr ( cntrl -> remote_addr , & remote_saddrlen ) ; err_ret = _OWPTestSessionSetIPv6LLScope ( cntrl -> ctx , remote_saddr , remote_saddrlen , ( struct sockaddr * ) & sendaddr_rec , addrlen ) ; if ( err_ret != OWPErrOK ) { * accept_ptr = OWP_CNTRL_UNSUPPORTED ; return err_ret ; } err_ret = _OWPTestSessionSetIPv6LLScope ( cntrl -> ctx , remote_saddr , remote_saddrlen , ( struct sockaddr * ) & recvaddr_rec , addrlen ) ; if ( err_ret != OWPErrOK ) { * accept_ptr = OWP_CNTRL_UNSUPPORTED ; return err_ret ; } if ( cntrl -> twoway ) { const struct sockaddr * local_saddr ; socklen_t local_saddrlen ; _OWPSetSAddrIfUnspec ( cntrl -> ctx , remote_saddr , ( struct sockaddr * ) & sendaddr_rec ) ; local_saddr = I2AddrSAddr ( cntrl -> local_addr , & local_saddrlen ) ; _OWPSetSAddrIfUnspec ( cntrl -> ctx , local_saddr , ( struct sockaddr * ) & recvaddr_rec ) ; } cntrl -> state &= ~ _OWPStateTestRequest ; cntrl -> state |= _OWPStateTestRequestSlots ; SendAddr = I2AddrBySAddr ( OWPContextErrHandle ( cntrl -> ctx ) , ( struct sockaddr * ) & sendaddr_rec , addrlen , SOCK_DGRAM , IPPROTO_UDP ) ; RecvAddr = I2AddrBySAddr ( OWPContextErrHandle ( cntrl -> ctx ) , ( struct sockaddr * ) & recvaddr_rec , addrlen , SOCK_DGRAM , IPPROTO_UDP ) ; if ( ! ( tsession = _OWPTestSessionAlloc ( cntrl , SendAddr , conf_sender , RecvAddr , conf_receiver , & tspec ) ) ) { err_ret = OWPErrWARNING ; * accept_ptr = OWP_CNTRL_FAILURE ; goto error ; } if ( ! cntrl -> twoway ) { memcpy ( tsession -> sid , sid , sizeof ( sid ) ) ; if ( tsession -> test_spec . nslots > _OWPSLOT_BUFSIZE ) { tsession -> test_spec . slots = calloc ( tsession -> test_spec . nslots , sizeof ( OWPSlot ) ) ; } else { tsession -> test_spec . slots = tsession -> slot_buffer ; } if ( ( rc = _OWPReadTestRequestSlots ( cntrl , intr , tsession -> test_spec . nslots , tsession -> test_spec . slots ) ) < OWPErrOK ) { cntrl -> state = _OWPStateInvalid ; err_ret = ( OWPErrSeverity ) rc ; * accept_ptr = OWP_CNTRL_INVALID ; goto error ; } if ( ! tsession -> test_spec . slots ) { OWPError ( cntrl -> ctx , OWPErrFATAL , OWPErrUNKNOWN , " " , tsession -> test_spec . nslots ) ; * accept_ptr = OWP_CNTRL_FAILURE ; err_ret = OWPErrFATAL ; goto error ; } } if ( accept_ret ) { cntrl -> state |= _OWPStateAcceptSession ; } else { cntrl -> state |= _OWPStateFetching ; } * test_session = tsession ; return OWPErrOK ; error : if ( tsession ) { _OWPTestSessionFree ( tsession , OWP_CNTRL_FAILURE ) ; } else { I2AddrFree ( SendAddr ) ; I2AddrFree ( RecvAddr ) ; } return err_ret ; }
Function:        _OWPReadTestRequest
 Description:
         This function reads a test request off the wire and encodes
         the information in a TestSession record.
Function : _OWPReadTestRequest Description : This function reads a test request off the wire and encodes the information in a TestSession record .
/*
     * Setup an OWPAcceptType return in the event this function is
     * called in a "server" context.
     */ /*
     * If this was called from the client side, we need to read
     * one block of data into the cntrl buffer. (Server side already
     * did this to determine the message type - client is doing this
     * as part of a fetch session.
     */ /*
     * Already read the first block - read the rest for this message
     * type.
     */ /*
     * Add data to HMAC and verify digest before decoding message
     */ /*
     * Now - fill in the Addr records, ipvn, server_conf varaibles,
     * sid and "tspec" with the values in the msg buffer.
     */ /*
         * INFO/WARNING indicates a request that we cannot honor.
         * FATAL indicates inproper formatting, and probable
         * control connection corruption.
         */ /*
             * only return in server context
             */ /*
     * To support test sessions listening on IPv6 link-local
     * addresses, the scope needs to be specified. So copy this over
     * from the control session remote address, unless it isn't a
     * link-local in which case the only option is to reject the
     * request.
     */ /*
     * TestRequest Preamble is read, now ready to read slots.
     */ /*
     * Prepare the address buffers.
     * (Don't bother checking for null return - it will be checked
     * by _OWPTestSessionAlloc.)
     */ /*
     * Allocate a record for this test.
     */ /*
         * copy sid into tsession - if the sid still needs to be
         * generated - it still will be in sapi.c:OWPProcessTestRequest
         */ /*
         * Allocate memory for slots...
         */ /*
             * Will check for memory allocation failure after
             * reading slots from socket. (We can gracefully
             * decline the request even if we can't allocate memory
             * to hold the slots this way.)
             */ /*
         * Now, read the slots of the control socket.
         */ /*
         * We were unable to save the slots - server should decline the request.
         */ /*
     * In the server context, we are going to _OWPStateAcceptSession.
     * In the client "fetching" context we are ready to read the
     * record header and the records.
     */