示例#1
0
/*
 * Report OSP usage thread function
 * param usagearg OSP usage information
 * return
 */
static OSPTTHREADRETURN ospReportUsageWork(
    void* usagearg)
{
    int i;
    const int MAX_RETRIES = 5;
    osp_usage* usage;
    int errorcode;

    usage = (osp_usage*)usagearg;

    OSPPTransactionRecordFailure(
        usage->transaction,
        usage->cause);

#if 0
    OSPPTransactionSetTermCause(
        usage->transaction,
        OSPC_TCAUSE_SIP,
        usage->cause,
        NULL);
#endif

    for (i = 1; i <= MAX_RETRIES; i++) {
        errorcode = OSPPTransactionReportUsage(
            usage->transaction,
            usage->duration,
            usage->start,
            usage->end,
            usage->alert,
            usage->connect,
            usage->haspdd,
            usage->pdd * 1000,
            usage->release,
            NULL, -1, -1, -1, -1, NULL, NULL);

        if (errorcode == OSPC_ERR_NO_ERROR) {
            LM_DBG("reporte usage for '%llu'\n",
                ospGetTransactionId(usage->transaction));
            break;
        } else {
            LM_ERR("failed to report usage for '%llu' (%d) attempt '%d' of '%d'\n",
                ospGetTransactionId(usage->transaction),
                errorcode,
                i,
                MAX_RETRIES);
        }
    }

    OSPPTransactionDelete(usage->transaction);

    free(usage);

    OSPTTHREADRETURN_NULL();
}
示例#2
0
/*
 * Create a thread to report OSP usage
 * param ospvTransaction OSP transaction handle
 * param ospvReleaseCode Call release reason
 * param ospvDurating Call duration
 * param ospvStartTime Call start time
 * param ospvEndTime Call end time
 * param ospvAlertTime Call alert time
 * param ospvConnectTime Call connected  time
 * param ospvIsPDDInfoPresent If post dial delay information avaliable
 * param ospvPostDialDelay Post dial delay information, in seconds
 * param ospvReleaseSource Which side release the call
 */
void ospReportUsageWrapper(
    OSPTTRANHANDLE ospvTransaction,
    unsigned ospvReleaseCode,
    unsigned ospvDuration,
    time_t ospvStartTime,
    time_t ospvEndTime,
    time_t ospvAlertTime,
    time_t ospvConnectTime,
    unsigned ospvIsPDDInfoPresent,
    unsigned ospvPostDialDelay,
    OSPE_RELEASE ospvReleaseSource)
{
    osp_usage* usage;
    OSPTTHREADID threadid;
    OSPTTHRATTR threadattr;
    int errorcode;

    LM_DBG("schedule usage report for '%llu'\n", ospGetTransactionId(ospvTransaction));

    usage = (osp_usage*)malloc(sizeof(osp_usage));

    usage->transaction = ospvTransaction;
    usage->cause = ospvReleaseCode;
    usage->duration = ospvDuration;
    usage->start = ospvStartTime;
    usage->end = ospvEndTime;
    usage->alert = ospvAlertTime;
    usage->connect = ospvConnectTime;
    usage->haspdd = ospvIsPDDInfoPresent;
    usage->pdd = ospvPostDialDelay;
    usage->release = ospvReleaseSource;

    OSPM_THRATTR_INIT(threadattr, errorcode);

    OSPM_SETDETACHED_STATE(threadattr, errorcode);

    OSPM_CREATE_THREAD(threadid, &threadattr, ospReportUsageWork, usage, errorcode);

    OSPM_THRATTR_DESTROY(threadattr);
}
示例#3
0
/*
 * Get routes from AuthRsp
 * param transaction Transaction handle
 * param destcount Expected destination count
 * param inbound Inbound info
 * return 0 success, -1 failure
 */
static int ospLoadRoutes(
    OSPTTRANHANDLE trans,
    int destcount,
    osp_inbound* inbound)
{
    int count;
    int errcode;
    osp_dest* dest;
    osp_dest dests[OSP_DEF_DESTS];
    char host[OSP_STRBUF_SIZE];
    char destdev[OSP_STRBUF_SIZE];
    OSPE_OPERATOR_NAME type;
    OSPE_DEST_OSPENABLED enabled;
    int result = 0;

    ospSetIdentity(trans);

    for (count = 0; count < destcount; count++) {
        /* This is necessary because we will save destinations in reverse order */
        dest = ospInitDestination(&dests[count]);

        if (dest == NULL) {
            result = -1;
            break;
        }

        dest->destcount = count + 1;

        if (count == 0) {
            errcode = OSPPTransactionGetFirstDestination(
                trans,
                sizeof(dest->validafter),
                dest->validafter,
                dest->validuntil,
                &dest->timelimit,
                &dest->callidsize,
                (void*)dest->callid,
                sizeof(dest->called),
                dest->called,
                sizeof(dest->calling),
                dest->calling,
                sizeof(host),
                host,
                sizeof(destdev),
                destdev,
                &dest->tokensize,
                dest->token);
        } else {
            errcode = OSPPTransactionGetNextDestination(
                trans,
                0,
                sizeof(dest->validafter),
                dest->validafter,
                dest->validuntil,
                &dest->timelimit,
                &dest->callidsize,
                (void*)dest->callid,
                sizeof(dest->called),
                dest->called,
                sizeof(dest->calling),
                dest->calling,
                sizeof(host),
                host,
                sizeof(destdev),
                destdev,
                &dest->tokensize,
                dest->token);
        }

        if (errcode != OSPC_ERR_NO_ERROR) {
            LM_ERR("failed to load routes (%d) expected '%d' current '%d'\n",
                errcode,
                destcount,
                count);
            result = -1;
            break;
        }

        ospConvertToInAddress(host, dest->host, sizeof(dest->host));

        errcode = OSPPTransactionGetNumberPortabilityParameters(trans,
            sizeof(dest->nprn),
            dest->nprn,
            sizeof(dest->npcic),
            dest->npcic,
            &dest->npdi);
        if (errcode != OSPC_ERR_NO_ERROR) {
            LM_DBG("cannot get number portability parameters (%d)\n", errcode);
            dest->nprn[0] = '\0';
            dest->npcic[0] = '\0';
            dest->npdi = 0;
        }

        for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
            errcode = OSPPTransactionGetOperatorName(trans,
                type,
                sizeof(dest->opname[type]),
                dest->opname[type]);
            if (errcode != OSPC_ERR_NO_ERROR) {
                LM_DBG("cannot get operator name '%d' (%d)\n", type, errcode);
                dest->opname[type][0] = '\0';
            }
        }

        errcode = OSPPTransactionGetDestProtocol(trans, &dest->protocol);
        if (errcode != OSPC_ERR_NO_ERROR) {
            /* This does not mean an ERROR. The OSP server may not support OSP 2.1.1 */
            LM_DBG("cannot get dest protocol (%d)\n", errcode);
            dest->protocol = OSPC_PROTNAME_SIP;
        }
        switch (dest->protocol) {
            case OSPC_PROTNAME_Q931:
            case OSPC_PROTNAME_LRQ:
            case OSPC_PROTNAME_IAX:
            case OSPC_PROTNAME_T37:
            case OSPC_PROTNAME_T38:
            case OSPC_PROTNAME_SKYPE:
            case OSPC_PROTNAME_SMPP:
            case OSPC_PROTNAME_XMPP:
                if (_osp_non_sip) {
                    dest->supported = 1;
                } else {
                    dest->supported = 0;
                }
                break;
            case OSPC_PROTNAME_SIP:
            case OSPC_PROTNAME_UNDEFINED:
            case OSPC_PROTNAME_UNKNOWN:
            default:
                dest->supported = 1;
                break;
        }

        errcode = OSPPTransactionIsDestOSPEnabled(trans, &enabled);
        if (errcode != OSPC_ERR_NO_ERROR) {
            /* This does not mean an ERROR. The OSP server may not support OSP 2.1.1 */
            LM_DBG("cannot get dest OSP version (%d)\n", errcode);
        } else if (enabled == OSPC_DOSP_FALSE) {
            /* Destination device does not support OSP. Do not send token to it */
            dest->token[0] = '\0';
            dest->tokensize = 0;
        }

        errcode = OSPPTransactionGetDestinationNetworkId(trans, sizeof(dest->dnid), dest->dnid);
        if (errcode != OSPC_ERR_NO_ERROR) {
            /* This does not mean an ERROR. The OSP server may not support OSP 2.1.1 */
            LM_DBG("cannot get dest network ID (%d)\n", errcode);
            dest->dnid[0] = '\0';
        }

        errcode = OSPPTransactionGetCNAM(trans, sizeof(dest->cnam), dest->cnam);
        if (errcode != OSPC_ERR_NO_ERROR) {
            LM_DBG("cannot get CNAM (%d)\n", errcode);
            dest->cnam[0] = '\0';
        }

        OSPPTransactionGetServiceType(trans, &dest->srvtype);

        dest->type = OSPC_ROLE_SOURCE;
        dest->transid = ospGetTransactionId(trans);

        LM_INFO("get destination '%d': "
            "validafter '%s' "
            "validuntil '%s' "
            "timelimit '%d' seconds "
            "callid '%.*s' "
            "calling '%s' "
            "called '%s' "
            "host '%s' "
            "nprn '%s' "
            "npcic '%s' "
            "npdi '%d' "
            /*
            "spid '%s' "
            "ocn '%s' "
            "spn '%s' "
            "altspn '%s' "
            "mcc '%s' "
            "mnc '%s' "
            */
            "cnam '%s' "
            "service '%d' "
            "protocol '%d' "
            "supported '%d' "
            "networkid '%s' "
            "tokensize '%d'\n",
            count,
            dest->validafter,
            dest->validuntil,
            dest->timelimit,
            dest->callidsize,
            dest->callid,
            dest->calling,
            dest->called,
            host,
            dest->nprn,
            dest->npcic,
            dest->npdi,
            /*
            dest->opname[OSPC_OPNAME_SPID],
            dest->opname[OSPC_OPNAME_OCN],
            dest->opname[OSPC_OPNAME_SPN],
            dest->opname[OSPC_OPNAME_ALTSPN],
            dest->opname[OSPC_OPNAME_MCC],
            dest->opname[OSPC_OPNAME_MNC],
            */
            dest->cnam,
            dest->srvtype,
            dest->protocol,
            dest->supported,
            dest->dnid,
            dest->tokensize);
    }

    /*
     * Save destination in reverse order,
     * when we start searching avps the destinations
     * will be in order
     */
    if (result == 0) {
        if (ospSaveInboundInfo(inbound) == -1) {
            ospRecordEvent(0, 500);
            result = -1;
        } else {
            for(count = destcount -1; count >= 0; count--) {
                if (ospSaveOrigDestination(&dests[count]) == -1) {
                    LM_ERR("failed to save originate destination\n");
                    /* Report terminate CDR */
                    ospRecordEvent(0, 500);
                    result = -1;
                    break;
                }
            }
        }
    }

    return result;
}
示例#4
0
/*
 * Validate OSP token
 * param ignore1
 * param ignore2
 * return  MODULE_RETURNCODE_TRUE success, MODULE_RETURNCODE_FALSE failure
 */
int ospValidateHeader (
    struct sip_msg* msg, 
    char* ignore1, 
    char* ignore2)
{
    int errorcode; 
    OSPTTRANHANDLE transaction = -1;
    unsigned int authorized = 0;
    unsigned int timelimit = 0;
    void* detaillog = NULL;
    unsigned int logsize = 0;
    unsigned char* callidval = (unsigned char*)"";
    OSPTCALLID* callid = NULL;
    unsigned callidsize = 0;
    unsigned char token[OSP_TOKENBUF_SIZE];
    unsigned int tokensize = sizeof(token);
    osp_dest dest;
    int result = MODULE_RETURNCODE_FALSE;

    LOG(L_DBG, "osp: ospValidateHeader\n");

    ospInitDestination(&dest);

    if ((errorcode = OSPPTransactionNew(_osp_provider, &transaction) != 0)) {
        LOG(L_ERR, "osp: ERROR: failed to create a new OSP transaction handle (%d)\n", errorcode);
    } else if ((ospGetRpidUserpart(msg, dest.calling, sizeof(dest.calling)) != 0) && 
        (ospGetFromUserpart(msg, dest.calling, sizeof(dest.calling)) != 0))
    {
        LOG(L_ERR, "osp: ERROR: failed to extract calling number\n");
    } else if ((ospGetUriUserpart(msg, dest.called, sizeof(dest.called)) != 0) &&
        (ospGetToUserpart(msg, dest.called, sizeof(dest.called)) != 0))
    {
        LOG(L_ERR, "osp: ERROR: failed to extract called number\n");
    } else if (ospGetCallId(msg, &callid) != 0) {
        LOG(L_ERR, "osp: ERROR: failed to extract call id\n");
    } else if (ospGetSourceAddress(msg, dest.source, sizeof(dest.source)) != 0) {
        LOG(L_ERR, "osp: ERROR: failed to extract source address\n");
    } else if (ospGetOspHeader(msg, token, &tokensize) != 0) {
        LOG(L_ERR, "osp: ERROR: failed to extract OSP authorization token\n");
    } else {
        LOG(L_INFO, 
            "osp: validate token for: "
            "transaction_handle '%i' "
            "e164_source '%s' "
            "e164_dest '%s' "
            "validate_call_id '%s' "
            "call_id '%.*s'\n",
            transaction,
            dest.calling,
            dest.called,
            _osp_validate_callid == 0 ? "No" : "Yes",
            callid->ospmCallIdLen,
            callid->ospmCallIdVal);

        if (_osp_validate_callid != 0) {
            callidsize = callid->ospmCallIdLen;
            callidval = callid->ospmCallIdVal;
        }

        errorcode = OSPPTransactionValidateAuthorisation(
            transaction,
            "",
            "",
            "",
            "",
            dest.calling,
            OSPC_E164,
            dest.called,
            OSPC_E164,
            callidsize,
            callidval,
            tokensize,
            token,
            &authorized,
            &timelimit,
            &logsize,
            detaillog,
            _osp_token_format);
    
        if (callid->ospmCallIdLen > sizeof(dest.callid) - 1) {
            dest.callidsize = sizeof(dest.callid) - 1;
        } else {
            dest.callidsize = callid->ospmCallIdLen;
        }
        memcpy(dest.callid, callid->ospmCallIdVal, dest.callidsize);
        dest.callid[dest.callidsize] = 0;
        dest.tid = ospGetTransactionId(transaction);
        dest.type = OSPC_DESTINATION;
        dest.authtime = time(NULL);
        strcpy(dest.host, _osp_device_ip);

        ospSaveTermDestination(&dest);

        if ((errorcode == 0) && (authorized == 1)) {
            LOG(L_DBG, 
                "osp: call is authorized for %d seconds, call_id '%.*s' transaction_id '%lld'",
                timelimit,
                dest.callidsize,
                dest.callid,
                dest.tid);
            ospRecordTermTransaction(msg, transaction, dest.source, dest.calling, dest.called, dest.authtime);
            result = MODULE_RETURNCODE_TRUE;
        } else {
            LOG(L_ERR, "osp: ERROR: token is invalid (%i)\n", errorcode);

            /* 
             * Update terminating status code to 401 and report terminating setup usage.
             * We may need to make 401 configurable, just in case a user decides to reply with
             * a different code.  Other options - trigger call setup usage reporting from the cpl
             * (after replying with an error code), or maybe use a different tm callback.
             */
            ospRecordEvent(0, 401);
        }
    }

    if (transaction != -1) {
        OSPPTransactionDelete(transaction);
    }

    if (callid != NULL) {
        OSPPCallIdDelete(&callid);
    }
    
    return result;
}
示例#5
0
/*
 * Get routes from AuthRsp
 * param transaction Transaction handle
 * param destcount Expected destination count
 * param source Source IP
 * param sourcedev Source device IP
 * param origcalled Original called number
 * param authtime Request authorization time
 * return 0 success, -1 failure
 */
static int ospLoadRoutes(
    OSPTTRANHANDLE transaction, 
    int destcount, 
    char* source, 
    char* sourcedev, 
    char* origcalled, 
    time_t authtime)
{
    int count;
    int errorcode;
    osp_dest* dest;
    osp_dest dests[OSP_DEF_DESTS];
    OSPE_DEST_PROT protocol;
    OSPE_DEST_OSP_ENABLED enabled;
    int result = 0;
    
    LOG(L_DBG, "osp: ospLoadRoutes\n");

    for (count = 0; count < destcount; count++) {
        /* This is necessary becuase we will save destinations in reverse order */
        dest = ospInitDestination(&dests[count]);

        if (dest == NULL) {
            result = -1;
            break;
        }

        dest->destinationCount = count + 1;
        strncpy(dest->origcalled, origcalled, sizeof(dest->origcalled) - 1);

        if (count == 0) {
            errorcode = OSPPTransactionGetFirstDestination(
                transaction,
                sizeof(dest->validafter),
                dest->validafter,
                dest->validuntil,
                &dest->timelimit,
                &dest->callidsize,
                (void*)dest->callid,
                sizeof(dest->called),
                dest->called,
                sizeof(dest->calling),
                dest->calling,
                sizeof(dest->host),
                dest->host,
                sizeof(dest->destdev),
                dest->destdev,
                &dest->tokensize,
                dest->token);
        } else {
            errorcode = OSPPTransactionGetNextDestination(
                transaction,
                0,
                sizeof(dest->validafter),
                dest->validafter,
                dest->validuntil,
                &dest->timelimit,
                &dest->callidsize,
                (void*)dest->callid,
                sizeof(dest->called),
                dest->called,
                sizeof(dest->calling),
                dest->calling,
                sizeof(dest->host),
                dest->host,
                sizeof(dest->destdev),
                dest->destdev,
                &dest->tokensize,
                dest->token);
        }
        
        if (errorcode != OSPC_ERR_NO_ERROR) {
            LOG(L_ERR, 
                "osp: ERROR: failed to load routes (%d) expected '%d' current '%d'\n", 
                errorcode, 
                destcount, 
                count);
            result = -1;
            break;
        }

        errorcode = OSPPTransactionGetDestProtocol(transaction, &protocol);
        if (errorcode != OSPC_ERR_NO_ERROR) {
            /* This does not mean an ERROR. The OSP server may not support OSP 2.1.1 */
            LOG(L_DBG, "osp: cannot get dest protocol (%d)\n", errorcode);
            protocol = OSPE_DEST_PROT_SIP;
        }
        switch (protocol) {
            case OSPE_DEST_PROT_H323_LRQ:
            case OSPE_DEST_PROT_H323_SETUP:
            case OSPE_DEST_PROT_IAX:
                dest->supported = 0;
                break;
            case OSPE_DEST_PROT_SIP:
            case OSPE_DEST_PROT_UNDEFINED:
            case OSPE_DEST_PROT_UNKNOWN:
            default:
                dest->supported = 1;
                break;
        }

        errorcode = OSPPTransactionIsDestOSPEnabled(transaction, &enabled);
        if (errorcode != OSPC_ERR_NO_ERROR) {
            /* This does not mean an ERROR. The OSP server may not support OSP 2.1.1 */
            LOG(L_DBG, "osp: cannot get dest OSP version (%d)\n", errorcode);
        } else if (enabled == OSPE_OSP_FALSE) {
            /* Destination device does not support OSP. Do not send token to it */
            dest->token[0] = '\0';
            dest->tokensize = 0;
        }

        errorcode = OSPPTransactionGetDestNetworkId(transaction, dest->networkid);
        if (errorcode != OSPC_ERR_NO_ERROR) {
            /* This does not mean an ERROR. The OSP server may not support OSP 2.1.1 */
            LOG(L_DBG, "osp: cannot get dest network ID (%d)\n", errorcode);
            dest->networkid[0] = '\0';
        }

        strncpy(dest->source, source, sizeof(dest->source) - 1);
        strncpy(dest->srcdev, sourcedev, sizeof(dest->srcdev) - 1);
        dest->type = OSPC_SOURCE;
        dest->transid = ospGetTransactionId(transaction);
        dest->authtime = authtime;

        LOG(L_INFO,
            "osp: get destination '%d': "
            "valid after '%s' "
            "valid until '%s' "
            "time limit '%i' seconds "
            "call id '%.*s' "
            "calling number '%s' "
            "called number '%s' "
            "host '%s' "
            "supported '%d' "
            "network id '%s' "
            "token size '%i'\n",
            count, 
            dest->validafter, 
            dest->validuntil, 
            dest->timelimit, 
            dest->callidsize, 
            dest->callid, 
            dest->calling, 
            dest->called, 
            dest->host, 
            dest->supported,
            dest->networkid, 
            dest->tokensize);
    }

    /* 
     * Save destination in reverse order,
     * when we start searching avps the destinations
     * will be in order 
     */
    if (result == 0) {
        for(count = destcount -1; count >= 0; count--) {
            ospSaveOrigDestination(&dests[count]);
        }
    }

    return result;
}