/* * OSP callback function * param t * param type * param ps */ static void ospTmcbFunc( struct cell* t, int type, struct tmcb_params* ps) { LOG(L_DBG, "osp: ospTmcbFunc\n"); if (type & TMCB_RESPONSE_OUT) { LOG(L_DBG, "osp: RESPONSE_OUT\n"); } else if (type & TMCB_E2EACK_IN) { LOG(L_DBG, "osp: E2EACK_IN\n"); } else if (type & TMCB_ON_FAILURE_RO) { LOG(L_DBG, "osp: FAILURE_RO\n"); } else if (type & TMCB_RESPONSE_IN) { LOG(L_DBG, "osp: RESPONSE_IN\n"); } else if (type & TMCB_REQUEST_FWDED) { LOG(L_DBG, "osp: REQUEST_FWDED\n"); } else if (type & TMCB_RESPONSE_FWDED) { LOG(L_DBG, "osp: RESPONSE_FWDED\n"); } else if (type & TMCB_ON_FAILURE) { LOG(L_DBG, "osp: FAILURE\n"); } else if (type & TMCB_LOCAL_COMPLETED) { LOG(L_DBG, "osp: COMPLETED\n"); } else { LOG(L_DBG, "osp: something else '%d'\n", type); } if (t) { ospRecordEvent(t->uac[t->nr_of_outgoings - 1].last_received, t->uas.status); } else { LOG(L_DBG, "osp: cell is empty\n"); } }
/* * OSP callback function * param t * param type * param ps */ static void ospTmcbFunc( struct cell* t, int type, struct tmcb_params* ps) { if (type & TMCB_RESPONSE_OUT) { LM_DBG("RESPONSE_OUT\n"); } else if (type & TMCB_E2EACK_IN) { LM_DBG("E2EACK_IN\n"); } else if (type & TMCB_ON_FAILURE_RO) { LM_DBG("FAILURE_RO\n"); } else if (type & TMCB_RESPONSE_IN) { LM_DBG("RESPONSE_IN\n"); } else if (type & TMCB_REQUEST_FWDED) { LM_DBG("REQUEST_FWDED\n"); } else if (type & TMCB_RESPONSE_FWDED) { LM_DBG("RESPONSE_FWDED\n"); } else if (type & TMCB_ON_FAILURE) { LM_DBG("FAILURE\n"); } else if (type & TMCB_LOCAL_COMPLETED) { LM_DBG("COMPLETED\n"); } else { LM_DBG("something else '%d'\n", type); } if (t) { ospRecordEvent(t->uac[t->first_branch].last_received, t->uas.status); } else { LM_DBG("cell is empty\n"); } }
/* * 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; }
/* * 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; }