diff options
-rw-r--r-- | apps/app_osplookup.c | 879 |
1 files changed, 677 insertions, 202 deletions
diff --git a/apps/app_osplookup.c b/apps/app_osplookup.c index 235d19df3..d8f437bcb 100644 --- a/apps/app_osplookup.c +++ b/apps/app_osplookup.c @@ -21,7 +21,7 @@ * \brief Open Settlement Protocol (OSP) Applications * * \author Mark Spencer <markster@digium.com> - * + * * \ingroup applications */ @@ -56,20 +56,54 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/astosp.h" /* OSP Buffer Sizes */ -#define OSP_INTSTR_SIZE ((unsigned int)16) /* OSP signed/unsigned int string buffer size */ -#define OSP_NORSTR_SIZE ((unsigned int)256) /* OSP normal string buffer size */ -#define OSP_TOKSTR_SIZE ((unsigned int)4096) /* OSP token string buffer size */ +#define OSP_INTSTR_SIZE ((unsigned int)16) /* OSP signed/unsigned int string buffer size */ +#define OSP_NORSTR_SIZE ((unsigned int)256) /* OSP normal string buffer size */ +#define OSP_TOKSTR_SIZE ((unsigned int)4096) /* OSP token string buffer size */ +#define OSP_TECHSTR_SIZE ((unsigned int)32) /* OSP signed/unsigned int string buffer size */ +#define OSP_UUID_SIZE ((unsigned int)16) /* UUID size */ +#define OSP_UUIDSTR_SIZE ((unsigned int)36) /* UUID string size */ + +/* OSP Authentication Policy */ +enum osp_authpolicy { + OSP_AUTH_NO, /* Accept any call */ + OSP_AUTH_YES, /* Accept call with valid OSP token or without OSP token */ + OSP_AUTH_EXCLUSIVE /* Only accept call with valid OSP token */ +}; + +/* Call ID type*/ +#define OSP_CALLID_UNDEFINED ((unsigned int)0) /* UNDEFINED */ +#define OSP_CALLID_H323 ((unsigned int)(1 << 0)) /* H.323 */ +#define OSP_CALLID_SIP ((unsigned int)(1 << 1)) /* SIP */ +#define OSP_CALLID_IAX ((unsigned int)(1 << 2)) /* IAX2 */ +#define OSP_CALLID_MAXNUM ((unsigned int)3) /* Max number of call ID type */ + +/* OSP Supported Destination Protocols */ +#define OSP_PROT_H323 ((char*)"H323") /* H323 Q931 protocol name*/ +#define OSP_PROT_SIP ((char*)"SIP") /* SIP protocol name */ +#define OSP_PROT_IAX ((char*)"IAX") /* IAX protocol name */ +#define OSP_PROT_OTHER ((char*)"OTHER") /* Other protocol name */ + +/* OSP supported Destination Tech */ +#if 0 +#define OSP_TECH_H323 ((char*)"OOH323") /* OOH323 tech name */ +#endif +#define OSP_TECH_H323 ((char*)"H323") /* OH323 tech name */ +#define OSP_TECH_SIP ((char*)"SIP") /* SIP tech name */ +#define OSP_TECH_IAX ((char*)"IAX2") /* IAX2 tech name */ + +/* SIP OSP header field name */ +#define OSP_SIP_HEADER ((char*)"P-OSP-Auth-Token: ") /* OSP Constants */ -#define OSP_INVALID_HANDLE ((int)-1) /* Invalid OSP handle, provider, transaction etc. */ -#define OSP_CONFIG_FILE ((const char*)"osp.conf") /* OSP configuration file name */ -#define OSP_GENERAL_CAT ((const char*)"general") /* OSP global configuration context name */ -#define OSP_DEF_PROVIDER ((const char*)"default") /* OSP default provider context name */ +#define OSP_INVALID_HANDLE ((int)-1) /* Invalid OSP handle, provider, transaction etc. */ +#define OSP_CONFIG_FILE ((const char*)"osp.conf") /* OSP configuration file name */ +#define OSP_GENERAL_CAT ((const char*)"general") /* OSP global configuration context name */ +#define OSP_DEF_PROVIDER ((const char*)"default") /* OSP default provider context name */ #define OSP_MAX_CERTS ((unsigned int)10) /* OSP max number of cacerts */ #define OSP_MAX_SRVS ((unsigned int)10) /* OSP max number of service points */ -#define OSP_DEF_MAXCONNECTIONS ((unsigned int)20) /* OSP default max_connections */ -#define OSP_MIN_MAXCONNECTIONS ((unsigned int)1) /* OSP min max_connections */ -#define OSP_MAX_MAXCONNECTIONS ((unsigned int)1000) /* OSP max max_connections */ +#define OSP_DEF_MAXCONNECTIONS ((unsigned int)20) /* OSP default max_connections */ +#define OSP_MIN_MAXCONNECTIONS ((unsigned int)1) /* OSP min max_connections */ +#define OSP_MAX_MAXCONNECTIONS ((unsigned int)1000) /* OSP max max_connections */ #define OSP_DEF_RETRYDELAY ((unsigned int)0) /* OSP default retry delay */ #define OSP_MIN_RETRYDELAY ((unsigned int)0) /* OSP min retry delay */ #define OSP_MAX_RETRYDELAY ((unsigned int)10) /* OSP max retry delay */ @@ -78,61 +112,65 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #define OSP_MAX_RETRYLIMIT ((unsigned int)100) /* OSP max retry times */ #define OSP_DEF_TIMEOUT ((unsigned int)500) /* OSP default timeout in ms */ #define OSP_MIN_TIMEOUT ((unsigned int)200) /* OSP min timeout in ms */ -#define OSP_MAX_TIMEOUT ((unsigned int)10000) /* OSP max timeout in ms */ +#define OSP_MAX_TIMEOUT ((unsigned int)10000) /* OSP max timeout in ms */ #define OSP_DEF_AUTHPOLICY ((enum osp_authpolicy)OSP_AUTH_YES) -#define OSP_AUDIT_URL ((const char*)"localhost") /* OSP default Audit URL */ -#define OSP_LOCAL_VALIDATION ((int)1) /* Validate OSP token locally */ +#define OSP_AUDIT_URL ((const char*)"localhost") /* OSP default Audit URL */ +#define OSP_LOCAL_VALIDATION ((int)1) /* Validate OSP token locally */ #define OSP_SSL_LIFETIME ((unsigned int)300) /* SSL life time, in seconds */ -#define OSP_HTTP_PERSISTENCE ((int)1) /* In seconds */ +#define OSP_HTTP_PERSISTENCE ((int)1) /* In seconds */ #define OSP_CUSTOMER_ID ((const char*)"") /* OSP customer ID */ #define OSP_DEVICE_ID ((const char*)"") /* OSP device ID */ -#define OSP_DEF_DESTINATIONS ((unsigned int)5) /* OSP default max number of destinations */ +#define OSP_DEF_DESTINATIONS ((unsigned int)5) /* OSP default max number of destinations */ #define OSP_DEF_TIMELIMIT ((unsigned int)0) /* OSP default duration limit, no limit */ - -/* OSP Authentication Policy */ -enum osp_authpolicy { - OSP_AUTH_NO, /* Accept any call */ - OSP_AUTH_YES, /* Accept call with valid OSP token or without OSP token */ - OSP_AUTH_EXCLUSIVE /* Only accept call with valid OSP token */ -}; +#define OSP_DEF_PROTOCOL OSP_PROT_SIP /* OSP default destination protocol, SIP */ /* OSP Provider */ struct osp_provider { - char name[OSP_NORSTR_SIZE]; /* OSP provider context name */ - char privatekey[OSP_NORSTR_SIZE]; /* OSP private key file name */ - char localcert[OSP_NORSTR_SIZE]; /* OSP local cert file name */ - unsigned int cacount; /* Number of cacerts */ - char cacerts[OSP_MAX_CERTS][OSP_NORSTR_SIZE]; /* Cacert file names */ - unsigned int spcount; /* Number of service points */ - char srvpoints[OSP_MAX_SRVS][OSP_NORSTR_SIZE]; /* Service point URLs */ - int maxconnections; /* Max number of connections */ - int retrydelay; /* Retry delay */ - int retrylimit; /* Retry limit */ - int timeout; /* Timeout in ms */ - char source[OSP_NORSTR_SIZE]; /* IP of self */ - enum osp_authpolicy authpolicy; /* OSP authentication policy */ - OSPTPROVHANDLE handle; /* OSP provider handle */ - struct osp_provider* next; /* Pointer to next OSP provider */ + char name[OSP_NORSTR_SIZE]; /* OSP provider context name */ + char privatekey[OSP_NORSTR_SIZE]; /* OSP private key file name */ + char localcert[OSP_NORSTR_SIZE]; /* OSP local cert file name */ + unsigned int cacount; /* Number of cacerts */ + char cacerts[OSP_MAX_CERTS][OSP_NORSTR_SIZE]; /* Cacert file names */ + unsigned int spcount; /* Number of service points */ + char srvpoints[OSP_MAX_SRVS][OSP_NORSTR_SIZE]; /* Service point URLs */ + int maxconnections; /* Max number of connections */ + int retrydelay; /* Retry delay */ + int retrylimit; /* Retry limit */ + int timeout; /* Timeout in ms */ + char source[OSP_NORSTR_SIZE]; /* IP of self */ + enum osp_authpolicy authpolicy; /* OSP authentication policy */ + char* defaultprotocol; /* OSP default destination protocol */ + OSPTPROVHANDLE handle; /* OSP provider handle */ + struct osp_provider* next; /* Pointer to next OSP provider */ +}; + +/* Call ID */ +struct osp_callid { + char buf[OSPC_CALLID_MAXSIZE]; /* Call ID string */ + unsigned int len; /* Call ID length */ }; /* OSP Application In/Output Results */ struct osp_result { int inhandle; /* Inbound transaction handle */ int outhandle; /* Outbound transaction handle */ - unsigned int intimelimit; /* Inbound duration limit */ - unsigned int outtimelimit; /* Outbound duration limit */ - char tech[20]; /* Asterisk TECH string */ - char dest[OSP_NORSTR_SIZE]; /* Destination in called@IP format */ - char calling[OSP_NORSTR_SIZE]; /* Calling number, may be translated */ - char token[OSP_TOKSTR_SIZE]; /* Outbound OSP token */ - unsigned int numresults; /* Number of remain destinations */ + unsigned int intimelimit; /* Inbound duration limit */ + unsigned int outtimelimit; /* Outbound duration limit */ + char tech[OSP_TECHSTR_SIZE]; /* Outbound Asterisk TECH string */ + char dest[OSP_NORSTR_SIZE]; /* Outbound destination IP address */ + char called[OSP_NORSTR_SIZE]; /* Outbound called number, may be translated */ + char calling[OSP_NORSTR_SIZE]; /* Outbound calling number, may be translated */ + char token[OSP_TOKSTR_SIZE]; /* Outbound OSP token */ + char networkid[OSP_NORSTR_SIZE]; /* Outbound network ID */ + unsigned int numresults; /* Number of remain outbound destinations */ + struct osp_callid outcallid; /* Outbound call ID */ }; /* OSP Module Global Variables */ -AST_MUTEX_DEFINE_STATIC(osplock); /* Lock of OSP provider list */ -static int osp_initialized = 0; /* Init flag */ -static int osp_hardware = 0; /* Hardware acceleration flag */ -static struct osp_provider* ospproviders = NULL; /* OSP provider list */ +AST_MUTEX_DEFINE_STATIC(osplock); /* Lock of OSP provider list */ +static int osp_initialized = 0; /* Init flag */ +static int osp_hardware = 0; /* Hardware accelleration flag */ +static struct osp_provider* ospproviders = NULL; /* OSP provider list */ static unsigned int osp_tokenformat = TOKEN_ALGO_SIGNED; /* Token format supported */ /* OSP Client Wrapper APIs */ @@ -143,7 +181,9 @@ static unsigned int osp_tokenformat = TOKEN_ALGO_SIGNED; /* Token format support * \param provider OSP provider context name * \return 1 Success, 0 Failed, -1 Error */ -static int osp_create_provider(struct ast_config* cfg, const char* provider) +static int osp_create_provider( + struct ast_config* cfg, + const char* provider) { int res; unsigned int t, i, j; @@ -169,6 +209,7 @@ static int osp_create_provider(struct ast_config* cfg, const char* provider) p->retrylimit = OSP_DEF_RETRYLIMIT; p->timeout = OSP_DEF_TIMEOUT; p->authpolicy = OSP_DEF_AUTHPOLICY; + p->defaultprotocol = OSP_DEF_PROTOCOL; p->handle = OSP_INVALID_HANDLE; v = ast_variable_browse(cfg, provider); @@ -217,7 +258,7 @@ static int osp_create_provider(struct ast_config* cfg, const char* provider) if (option_debug) ast_log(LOG_DEBUG, "OSP: maxconnections '%d'\n", t); } else { - ast_log(LOG_WARNING, "OSP: maxconnections should be an integer from %d to %d, not '%s' at line %d\n", + ast_log(LOG_WARNING, "OSP: maxconnections should be an integer from %d to %d, not '%s' at line %d\n", OSP_MIN_MAXCONNECTIONS, OSP_MAX_MAXCONNECTIONS, v->value, v->lineno); } } else if (!strcasecmp(v->name, "retrydelay")) { @@ -226,7 +267,7 @@ static int osp_create_provider(struct ast_config* cfg, const char* provider) if (option_debug) ast_log(LOG_DEBUG, "OSP: retrydelay '%d'\n", t); } else { - ast_log(LOG_WARNING, "OSP: retrydelay should be an integer from %d to %d, not '%s' at line %d\n", + ast_log(LOG_WARNING, "OSP: retrydelay should be an integer from %d to %d, not '%s' at line %d\n", OSP_MIN_RETRYDELAY, OSP_MAX_RETRYDELAY, v->value, v->lineno); } } else if (!strcasecmp(v->name, "retrylimit")) { @@ -235,7 +276,7 @@ static int osp_create_provider(struct ast_config* cfg, const char* provider) if (option_debug) ast_log(LOG_DEBUG, "OSP: retrylimit '%d'\n", t); } else { - ast_log(LOG_WARNING, "OSP: retrylimit should be an integer from %d to %d, not '%s' at line %d\n", + ast_log(LOG_WARNING, "OSP: retrylimit should be an integer from %d to %d, not '%s' at line %d\n", OSP_MIN_RETRYLIMIT, OSP_MAX_RETRYLIMIT, v->value, v->lineno); } } else if (!strcasecmp(v->name, "timeout")) { @@ -244,7 +285,7 @@ static int osp_create_provider(struct ast_config* cfg, const char* provider) if (option_debug) ast_log(LOG_DEBUG, "OSP: timeout '%d'\n", t); } else { - ast_log(LOG_WARNING, "OSP: timeout should be an integer from %d to %d, not '%s' at line %d\n", + ast_log(LOG_WARNING, "OSP: timeout should be an integer from %d to %d, not '%s' at line %d\n", OSP_MIN_TIMEOUT, OSP_MAX_TIMEOUT, v->value, v->lineno); } } else if (!strcasecmp(v->name, "source")) { @@ -257,21 +298,38 @@ static int osp_create_provider(struct ast_config* cfg, const char* provider) if (option_debug) ast_log(LOG_DEBUG, "OSP: authpolicy '%d'\n", t); } else { - ast_log(LOG_WARNING, "OSP: authpolicy should be %d, %d or %d, not '%s' at line %d\n", + ast_log(LOG_WARNING, "OSP: authpolicy should be %d, %d or %d, not '%s' at line %d\n", OSP_AUTH_NO, OSP_AUTH_YES, OSP_AUTH_EXCLUSIVE, v->value, v->lineno); } + } else if (!strcasecmp(v->name, "defaultprotocol")) { + if (!strcasecmp(v->value, OSP_PROT_SIP)) { + p->defaultprotocol = OSP_PROT_SIP; + if (option_debug) + ast_log(LOG_DEBUG, "OSP: default protocol '%s'\n", p->defaultprotocol); + } else if (!strcasecmp(v->value, OSP_PROT_H323)) { + p->defaultprotocol = OSP_PROT_H323; + if (option_debug) + ast_log(LOG_DEBUG, "OSP: default protocol '%s'\n", p->defaultprotocol); + } else if (!strcasecmp(v->value, OSP_PROT_IAX)) { + p->defaultprotocol = OSP_PROT_IAX; + if (option_debug) + ast_log(LOG_DEBUG, "OSP: default protocol '%s'\n", p->defaultprotocol); + } else { + ast_log(LOG_WARNING, "OSP: default protocol should be %s, %s, %s, or %s not '%s' at line %d\n", + OSP_PROT_SIP, OSP_PROT_H323, OSP_PROT_IAX, OSP_PROT_OTHER, v->value, v->lineno); + } } v = v->next; } - error = OSPPUtilLoadPEMPrivateKey((unsigned char *) p->privatekey, &privatekey); + error = OSPPUtilLoadPEMPrivateKey((unsigned char*)p->privatekey, &privatekey); if (error != OSPC_ERR_NO_ERROR) { ast_log(LOG_WARNING, "OSP: Unable to load privatekey '%s', error '%d'\n", p->privatekey, error); free(p); return 0; } - error = OSPPUtilLoadPEMCert((unsigned char *) p->localcert, &localcert); + error = OSPPUtilLoadPEMCert((unsigned char*)p->localcert, &localcert); if (error != OSPC_ERR_NO_ERROR) { ast_log(LOG_WARNING, "OSP: Unable to load localcert '%s', error '%d'\n", p->localcert, error); if (privatekey.PrivateKeyData) { @@ -288,7 +346,7 @@ static int osp_create_provider(struct ast_config* cfg, const char* provider) p->cacount++; } for (i = 0; i < p->cacount; i++) { - error = OSPPUtilLoadPEMCert((unsigned char *) p->cacerts[i], &cacerts[i]); + error = OSPPUtilLoadPEMCert((unsigned char*)p->cacerts[i], &cacerts[i]); if (error != OSPC_ERR_NO_ERROR) { ast_log(LOG_WARNING, "OSP: Unable to load cacert '%s', error '%d'\n", p->cacerts[i], error); for (j = 0; j < i; j++) { @@ -307,14 +365,30 @@ static int osp_create_provider(struct ast_config* cfg, const char* provider) } pcacerts[i] = &cacerts[i]; } - + for (i = 0; i < p->spcount; i++) { psrvpoints[i] = p->srvpoints[i]; } - error = OSPPProviderNew(p->spcount, psrvpoints, NULL, OSP_AUDIT_URL, &privatekey, &localcert, p->cacount, pcacerts, OSP_LOCAL_VALIDATION, - OSP_SSL_LIFETIME, p->maxconnections, OSP_HTTP_PERSISTENCE, p->retrydelay, p->retrylimit,p->timeout, OSP_CUSTOMER_ID, - OSP_DEVICE_ID, &p->handle); + error = OSPPProviderNew( + p->spcount, + psrvpoints, + NULL, + OSP_AUDIT_URL, + &privatekey, + &localcert, + p->cacount, + pcacerts, + OSP_LOCAL_VALIDATION, + OSP_SSL_LIFETIME, + p->maxconnections, + OSP_HTTP_PERSISTENCE, + p->retrydelay, + p->retrylimit, + p->timeout, + OSP_CUSTOMER_ID, + OSP_DEVICE_ID, + &p->handle); if (error != OSPC_ERR_NO_ERROR) { ast_log(LOG_WARNING, "OSP: Unable to create provider '%s', error '%d'\n", provider, error); free(p); @@ -325,7 +399,7 @@ static int osp_create_provider(struct ast_config* cfg, const char* provider) ast_mutex_lock(&osplock); p->next = ospproviders; ospproviders = p; - ast_mutex_unlock(&osplock); + ast_mutex_unlock(&osplock); res = 1; } @@ -345,12 +419,14 @@ static int osp_create_provider(struct ast_config* cfg, const char* provider) } /*! - * \brief Get OSP authenticiation policy of provider - * \param provider OSP provider context name - * \param policy OSP authentication policy, output + * \brief Get OSP provider by name + * \param name OSP provider context name + * \param provider OSP provider structure * \return 1 Success, 0 Failed, -1 Error */ -static int osp_get_policy(const char* provider, int* policy) +static int osp_get_provider( + const char* name, + struct osp_provider** provider) { int res = 0; struct osp_provider* p; @@ -358,10 +434,10 @@ static int osp_get_policy(const char* provider, int* policy) ast_mutex_lock(&osplock); p = ospproviders; while(p) { - if (!strcasecmp(p->name, provider)) { - *policy = p->authpolicy; + if (!strcasecmp(p->name, name)) { + *provider = p; if (option_debug) - ast_log(LOG_DEBUG, "OSP: authpolicy '%d'\n", *policy); + ast_log(LOG_DEBUG, "OSP: find provider '%s'\n", name); res = 1; break; } @@ -380,7 +456,11 @@ static int osp_get_policy(const char* provider, int* policy) * \param source Source of provider, output * \return 1 Success, 0 Failed, -1 Error */ -static int osp_create_transaction(const char* provider, int* transaction, unsigned int sourcesize, char* source) +static int osp_create_transaction( + const char* provider, + int* transaction, + unsigned int sourcesize, + char* source) { int res = 0; struct osp_provider* p; @@ -414,37 +494,76 @@ static int osp_create_transaction(const char* provider, int* transaction, unsign } /*! + * \brief Convert address to "[x.x.x.x]" or "host.domain" format + * \param src Source address string + * \param dst Destination address string + * \param buffersize Size of dst buffer + */ +static void osp_convert_address( + const char* src, + char* dst, + int buffersize) +{ + struct in_addr inp; + + if (inet_aton(src, &inp) != 0) { + snprintf(dst, buffersize, "[%s]", src); + } else { + snprintf(dst, buffersize, "%s", src); + } +} + +/*! * \brief Validate OSP token of inbound call * \param transaction OSP transaction handle * \param source Source of inbound call - * \param dest Destination of inbound call + * \param destination Destination of inbound call * \param calling Calling number * \param called Called number * \param token OSP token, may be empty * \param timelimit Call duration limit, output * \return 1 Success, 0 Failed, -1 Error */ -static int osp_validate_token(int transaction, const char* source, const char* dest, const char* calling, const char* called, const char* token, unsigned int* timelimit) +static int osp_validate_token( + int transaction, + const char* source, + const char* destination, + const char* calling, + const char* called, + const char* token, + unsigned int* timelimit) { int res; int tokenlen; unsigned char tokenstr[OSP_TOKSTR_SIZE]; + char src[OSP_TOKSTR_SIZE]; + char dst[OSP_TOKSTR_SIZE]; unsigned int authorised; unsigned int dummy = 0; int error; tokenlen = ast_base64decode(tokenstr, token, strlen(token)); + osp_convert_address(source, src, sizeof(src)); + osp_convert_address(destination, dst, sizeof(dst)); error = OSPPTransactionValidateAuthorisation( - transaction, - source, dest, NULL, NULL, - calling ? calling : "", OSPC_E164, - called, OSPC_E164, - 0, NULL, - tokenlen, (char *) tokenstr, - &authorised, - timelimit, - &dummy, NULL, - osp_tokenformat); + transaction, + src, + dst, + NULL, + NULL, + calling ? calling : "", + OSPC_E164, + called, + OSPC_E164, + 0, + NULL, + tokenlen, + (char*)tokenstr, + &authorised, + timelimit, + &dummy, + NULL, + osp_tokenformat); if (error != OSPC_ERR_NO_ERROR) { if (option_debug) ast_log(LOG_DEBUG, "OSP: Unable to validate inbound token\n"); @@ -458,7 +577,7 @@ static int osp_validate_token(int transaction, const char* source, const char* d ast_log(LOG_DEBUG, "OSP: Unauthorised\n"); res = 0; } - + return res; } @@ -468,7 +587,9 @@ static int osp_validate_token(int transaction, const char* source, const char* d * \param out Outbound duration limit * \return min duration limit */ -static unsigned int osp_choose_timelimit(unsigned int in, unsigned int out) +static unsigned int osp_choose_timelimit( + unsigned int in, + unsigned int out) { if (in == OSP_DEF_TIMELIMIT) { return out; @@ -481,6 +602,7 @@ static unsigned int osp_choose_timelimit(unsigned int in, unsigned int out) /*! * \brief Choose min duration limit + * \param provider OSP provider * \param called Called number * \param calling Calling number * \param destination Destination IP in '[x.x.x.x]' format @@ -490,7 +612,15 @@ static unsigned int osp_choose_timelimit(unsigned int in, unsigned int out) * \param result OSP lookup results, in/output * \return 1 Success, 0 Failed, -1 Error */ -static int osp_check_destination(const char* called, const char* calling, char* destination, unsigned int tokenlen, const char* token, enum OSPEFAILREASON* reason, struct osp_result* result) +static int osp_check_destination( + struct osp_provider* provider, + const char* called, + const char* calling, + char* destination, + unsigned int tokenlen, + const char* token, + enum OSPEFAILREASON* reason, + struct osp_result* result) { int res; OSPE_DEST_OSP_ENABLED enabled; @@ -502,7 +632,7 @@ static int osp_check_destination(const char* called, const char* calling, char* ast_log(LOG_DEBUG, "OSP: Wrong destination format '%s'\n", destination); *reason = OSPC_FAIL_NORMAL_UNSPECIFIED; return -1; - } + } if ((error = OSPPTransactionIsDestOSPEnabled(result->outhandle, &enabled)) != OSPC_ERR_NO_ERROR) { if (option_debug) @@ -514,16 +644,23 @@ static int osp_check_destination(const char* called, const char* calling, char* if (enabled == OSPE_OSP_FALSE) { result->token[0] = '\0'; } else { - ast_base64encode(result->token, (const unsigned char *) token, tokenlen, sizeof(result->token) - 1); + ast_base64encode(result->token, (const unsigned char*)token, tokenlen, sizeof(result->token) - 1); + } + + if ((error = OSPPTransactionGetDestNetworkId(result->outhandle, result->networkid)) != OSPC_ERR_NO_ERROR) { + if (option_debug) + ast_log(LOG_DEBUG, "OSP: Unable to get destination network ID, error '%d'\n", error); + result->networkid[0] = '\0'; } if ((error = OSPPTransactionGetDestProtocol(result->outhandle, &protocol)) != OSPC_ERR_NO_ERROR) { if (option_debug) ast_log(LOG_DEBUG, "OSP: Unable to get destination protocol, error '%d'\n", error); - *reason = OSPC_FAIL_NORMAL_UNSPECIFIED; + *reason = OSPC_FAIL_NORMAL_UNSPECIFIED; result->token[0] = '\0'; + result->networkid[0] = '\0'; return -1; - } + } res = 1; /* Strip leading and trailing brackets */ @@ -531,31 +668,47 @@ static int osp_check_destination(const char* called, const char* calling, char* switch(protocol) { case OSPE_DEST_PROT_H323_SETUP: if (option_debug) - ast_log(LOG_DEBUG, "OSP: protocol '%d'\n", protocol); - ast_copy_string(result->tech, "H323", sizeof(result->tech)); - snprintf(result->dest, sizeof(result->dest), "%s@%s", called, destination + 1); + ast_log(LOG_DEBUG, "OSP: protocol '%s'\n", OSP_PROT_H323); + ast_copy_string(result->tech, OSP_TECH_H323, sizeof(result->tech)); + ast_copy_string(result->dest, destination + 1, sizeof(result->dest)); + ast_copy_string(result->called, called, sizeof(result->called)); ast_copy_string(result->calling, calling, sizeof(result->calling)); break; case OSPE_DEST_PROT_SIP: if (option_debug) - ast_log(LOG_DEBUG, "OSP: protocol '%d'\n", protocol); - ast_copy_string(result->tech, "SIP", sizeof(result->tech)); - snprintf(result->dest, sizeof(result->dest), "%s@%s", called, destination + 1); + ast_log(LOG_DEBUG, "OSP: protocol '%s'\n", OSP_PROT_SIP); + ast_copy_string(result->tech, OSP_TECH_SIP, sizeof(result->tech)); + ast_copy_string(result->dest, destination + 1, sizeof(result->dest)); + ast_copy_string(result->called, called, sizeof(result->called)); ast_copy_string(result->calling, calling, sizeof(result->calling)); break; case OSPE_DEST_PROT_IAX: if (option_debug) - ast_log(LOG_DEBUG, "OSP: protocol '%d'\n", protocol); - ast_copy_string(result->tech, "IAX", sizeof(result->tech)); - snprintf(result->dest, sizeof(result->dest), "%s@%s", called, destination + 1); + ast_log(LOG_DEBUG, "OSP: protocol '%s'\n", OSP_PROT_IAX); + ast_copy_string(result->tech, OSP_TECH_IAX, sizeof(result->tech)); + ast_copy_string(result->dest, destination + 1, sizeof(result->dest)); + ast_copy_string(result->called, called, sizeof(result->called)); + ast_copy_string(result->calling, calling, sizeof(result->calling)); + break; + case OSPE_DEST_PROT_UNDEFINED: + case OSPE_DEST_PROT_UNKNOWN: + if (option_debug) { + ast_log(LOG_DEBUG, "OSP: unknown/undefined protocol '%d'\n", protocol); + ast_log(LOG_DEBUG, "OSP: use default protocol '%s'\n", provider->defaultprotocol); + } + ast_copy_string(result->tech, provider->defaultprotocol, sizeof(result->tech)); + ast_copy_string(result->dest, destination + 1, sizeof(result->dest)); + ast_copy_string(result->called, called, sizeof(result->called)); ast_copy_string(result->calling, calling, sizeof(result->calling)); break; + case OSPE_DEST_PROT_H323_LRQ: default: - if (option_debug) - ast_log(LOG_DEBUG, "OSP: Unknown protocol '%d'\n", protocol); - *reason = OSPC_FAIL_PROTOCOL_ERROR; + ast_log(LOG_WARNING, "OSP: unsupported protocol '%d'\n", protocol); + *reason = OSPC_FAIL_PROTOCOL_ERROR; result->token[0] = '\0'; + result->networkid[0] = '\0'; res = 0; + break; } return res; @@ -566,7 +719,8 @@ static int osp_check_destination(const char* called, const char* calling, char* * \param cause Asterisk hangup cause * \return OSP TC code */ -static enum OSPEFAILREASON asterisk2osp(int cause) +static enum OSPEFAILREASON asterisk2osp( + int cause) { return (enum OSPEFAILREASON)cause; } @@ -582,22 +736,29 @@ static enum OSPEFAILREASON asterisk2osp(int cause) * \param timelimit Call duration limit, output * \return 1 Authenricated, 0 Unauthenticated, -1 Error */ -static int osp_auth(const char* provider, int* transaction, const char* source, const char* calling, const char* called, const char* token, unsigned int* timelimit) +static int osp_auth( + const char* provider, + int* transaction, + const char* source, + const char* calling, + const char* called, + const char* token, + unsigned int* timelimit) { int res; - int policy = OSP_AUTH_YES; + struct osp_provider* p; char dest[OSP_NORSTR_SIZE]; *transaction = OSP_INVALID_HANDLE; *timelimit = OSP_DEF_TIMELIMIT; - res = osp_get_policy(provider, &policy); - if (!res) { + + if ((res = osp_get_provider(provider, &p)) <= 0) { if (option_debug) - ast_log(LOG_DEBUG, "OSP: Unabe to find OSP authentication policy\n"); + ast_log(LOG_DEBUG, "OSP: Unabe to find OSP provider '%s'\n", provider); return res; } - switch (policy) { + switch (p->authpolicy) { case OSP_AUTH_NO: res = 1; break; @@ -632,25 +793,123 @@ static int osp_auth(const char* provider, int* transaction, const char* source, } /*! + * \brief Create a UUID + * \param uuid UUID buffer + * \param buffersize UUID buffer size + * \return 1 Created, -1 Error + */ +static int osp_create_uuid( + unsigned char* uuid, + unsigned int* buffersize) +{ + int i, res; + long int* tmp; + + if (*buffersize >= OSP_UUID_SIZE) { + tmp = (long int*)uuid; + for (i = 0; i < OSP_UUID_SIZE / sizeof(long int); i++) { + tmp[i] = ast_random(); + } + *buffersize = OSP_UUID_SIZE; + res = 1; + } else { + res = -1; + } + + return res; +} + +/*! + * \brief UUID to string + * \param uuid UUID + * \param buffer String buffer + * \param buffersize String buffer size + * \return 1 Successed, -1 Error + */ +static int osp_uuid2str( + unsigned char* uuid, + char* buffer, + unsigned int buffersize) +{ + int res; + + if (buffersize > OSP_UUIDSTR_SIZE) { + snprintf(buffer, buffersize, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7], + uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]); + res = 1; + } else { + res = -1; + } + + return res; +} + +/*! + * \brief Create a call ID according to the type + * \param type Call ID type + * \param callid Call ID buffer + * \return 1 Created, 0 Not create, -1 Error + */ +static int osp_create_callid( + unsigned int type, + struct osp_callid* callid) +{ + int res; + + callid->len = sizeof(callid->buf); + switch (type) { + case OSP_CALLID_H323: + res = osp_create_uuid(callid->buf, &callid->len); + break; + case OSP_CALLID_SIP: + case OSP_CALLID_IAX: + res = 0; + default: + res = -1; + break; + } + + if ((res != 1) && (callid->len != 0)) { + callid->buf[0] = '\0'; + callid->len = 0; + } + + return res; +} + +/*! * \brief OSP Lookup function * \param provider OSP provider context name * \param srcdev Source device of outbound call * \param calling Calling number * \param called Called number + * \param callidtypes Call ID types * \param result Lookup results * \return 1 Found , 0 No route, -1 Error */ -static int osp_lookup(const char* provider, const char* srcdev, const char* calling, const char* called, struct osp_result* result) +static int osp_lookup( + const char* provider, + const char* srcdev, + const char* calling, + const char* called, + unsigned int callidtypes, + struct osp_result* result) { int res; + struct osp_provider* p; char source[OSP_NORSTR_SIZE]; - unsigned int callidlen; - char callid[OSPC_CALLID_MAXSIZE]; char callingnum[OSP_NORSTR_SIZE]; char callednum[OSP_NORSTR_SIZE]; char destination[OSP_NORSTR_SIZE]; unsigned int tokenlen; char token[OSP_TOKSTR_SIZE]; + char src[OSP_NORSTR_SIZE]; + char dev[OSP_NORSTR_SIZE]; + unsigned int i, type; + struct osp_callid callid; + unsigned int callidnum; + OSPTCALLID* callids[OSP_CALLID_MAXNUM]; unsigned int dummy = 0; enum OSPEFAILREASON reason; int error; @@ -658,11 +917,19 @@ static int osp_lookup(const char* provider, const char* srcdev, const char* call result->outhandle = OSP_INVALID_HANDLE; result->tech[0] = '\0'; result->dest[0] = '\0'; + result->called[0] = '\0'; result->calling[0] = '\0'; result->token[0] = '\0'; + result->networkid[0] = '\0'; result->numresults = 0; result->outtimelimit = OSP_DEF_TIMELIMIT; + if ((res = osp_get_provider(provider, &p)) <= 0) { + if (option_debug) + ast_log(LOG_DEBUG, "OSP: Unabe to find OSP provider '%s'\n", provider); + return res; + } + if ((res = osp_create_transaction(provider, &result->outhandle, sizeof(source), source)) <= 0) { if (option_debug) ast_log(LOG_DEBUG, "OSP: Unable to generate transaction handle\n"); @@ -673,9 +940,42 @@ static int osp_lookup(const char* provider, const char* srcdev, const char* call return -1; } + callidnum = 0; + callids[0] = NULL; + for (i = 0; i < OSP_CALLID_MAXNUM; i++) { + type = 1 << i; + if (callidtypes & type) { + error = osp_create_callid(type, &callid); + if (error == 1) { + callids[callidnum] = OSPPCallIdNew(callid.len, callid.buf); + callidnum++; + } + } + } + + osp_convert_address(source, src, sizeof(src)); + osp_convert_address(srcdev, dev, sizeof(dev)); result->numresults = OSP_DEF_DESTINATIONS; - error = OSPPTransactionRequestAuthorisation(result->outhandle, source, srcdev, calling ? calling : "", - OSPC_E164, called, OSPC_E164, NULL, 0, NULL, NULL, &result->numresults, &dummy, NULL); + error = OSPPTransactionRequestAuthorisation( + result->outhandle, + src, + dev, + calling ? calling : "", + OSPC_E164, + called, + OSPC_E164, + NULL, + callidnum, + callids, + NULL, + &result->numresults, + &dummy, + NULL); + + for (i = 0; i < callidnum; i++) { + OSPPCallIdDelete(&callids[i]); + } + if (error != OSPC_ERR_NO_ERROR) { if (option_debug) ast_log(LOG_DEBUG, "OSP: Unable to request authorization\n"); @@ -695,10 +995,26 @@ static int osp_lookup(const char* provider, const char* srcdev, const char* call return 0; } - callidlen = sizeof(callid); + result->outcallid.len = sizeof(result->outcallid.buf); tokenlen = sizeof(token); - error = OSPPTransactionGetFirstDestination(result->outhandle, 0, NULL, NULL, &result->outtimelimit, &callidlen, callid, - sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token); + error = OSPPTransactionGetFirstDestination( + result->outhandle, + 0, + NULL, + NULL, + &result->outtimelimit, + &result->outcallid.len, + result->outcallid.buf, + sizeof(callednum), + callednum, + sizeof(callingnum), + callingnum, + sizeof(destination), + destination, + 0, + NULL, + &tokenlen, + token); if (error != OSPC_ERR_NO_ERROR) { if (option_debug) ast_log(LOG_DEBUG, "OSP: Unable to get first route\n"); @@ -720,7 +1036,7 @@ static int osp_lookup(const char* provider, const char* srcdev, const char* call ast_log(LOG_DEBUG, "OSP: token size '%d'\n", tokenlen); } - if ((res = osp_check_destination(callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) { + if ((res = osp_check_destination(p, callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) { return 1; } @@ -736,10 +1052,27 @@ static int osp_lookup(const char* provider, const char* srcdev, const char* call } while(result->numresults) { - callidlen = sizeof(callid); + result->outcallid.len = sizeof(result->outcallid.buf); tokenlen = sizeof(token); - error = OSPPTransactionGetNextDestination(result->outhandle, reason, 0, NULL, NULL, &result->outtimelimit, &callidlen, callid, - sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token); + error = OSPPTransactionGetNextDestination( + result->outhandle, + reason, + 0, + NULL, + NULL, + &result->outtimelimit, + &result->outcallid.len, + result->outcallid.buf, + sizeof(callednum), + callednum, + sizeof(callingnum), + callingnum, + sizeof(destination), + destination, + 0, + NULL, + &tokenlen, + token); if (error == OSPC_ERR_NO_ERROR) { result->numresults--; result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit); @@ -750,7 +1083,7 @@ static int osp_lookup(const char* provider, const char* srcdev, const char* call ast_log(LOG_DEBUG, "OSP: destination '%s'\n", destination); ast_log(LOG_DEBUG, "OSP: token size '%d'\n", tokenlen); } - if ((res = osp_check_destination(callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) { + if ((res = osp_check_destination(p, callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) { break; } else if (!result->numresults) { if (option_debug) @@ -783,11 +1116,13 @@ static int osp_lookup(const char* provider, const char* srcdev, const char* call * \param result Lookup results, in/output * \return 1 Found , 0 No route, -1 Error */ -static int osp_next(int cause, struct osp_result* result) +static int osp_next( + const char* provider, + int cause, + struct osp_result* result) { int res; - unsigned int callidlen; - char callid[OSPC_CALLID_MAXSIZE]; + struct osp_provider* p; char callingnum[OSP_NORSTR_SIZE]; char callednum[OSP_NORSTR_SIZE]; char destination[OSP_NORSTR_SIZE]; @@ -798,10 +1133,18 @@ static int osp_next(int cause, struct osp_result* result) result->tech[0] = '\0'; result->dest[0] = '\0'; + result->called[0] = '\0'; result->calling[0] = '\0'; result->token[0] = '\0'; + result->networkid[0] = '\0'; result->outtimelimit = OSP_DEF_TIMELIMIT; + if ((res = osp_get_provider(provider, &p)) <= 0) { + if (option_debug) + ast_log(LOG_DEBUG, "OSP: Unabe to find OSP provider '%s'\n", provider); + return res; + } + if (result->outhandle == OSP_INVALID_HANDLE) { if (option_debug) ast_log(LOG_DEBUG, "OSP: Transaction handle undefined\n"); @@ -825,10 +1168,27 @@ static int osp_next(int cause, struct osp_result* result) } while(result->numresults) { - callidlen = sizeof(callid); + result->outcallid.len = sizeof(result->outcallid.buf); tokenlen = sizeof(token); - error = OSPPTransactionGetNextDestination(result->outhandle, reason, 0, NULL, NULL, &result->outtimelimit, &callidlen, - callid, sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token); + error = OSPPTransactionGetNextDestination( + result->outhandle, + reason, + 0, + NULL, + NULL, + &result->outtimelimit, + &result->outcallid.len, + result->outcallid.buf, + sizeof(callednum), + callednum, + sizeof(callingnum), + callingnum, + sizeof(destination), + destination, + 0, + NULL, + &tokenlen, + token); if (error == OSPC_ERR_NO_ERROR) { result->numresults--; result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit); @@ -839,7 +1199,7 @@ static int osp_next(int cause, struct osp_result* result) ast_log(LOG_DEBUG, "OSP: destination '%s'\n", destination); ast_log(LOG_DEBUG, "OSP: token size '%d'\n", tokenlen); } - if ((res = osp_check_destination(callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) { + if ((res = osp_check_destination(p, callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) { res = 1; break; } else if (!result->numresults) { @@ -880,7 +1240,14 @@ static int osp_next(int cause, struct osp_result* result) * \param release Who release first, 0 source, 1 destination * \return 1 Success, 0 Failed, -1 Error */ -static int osp_finish(int handle, int recorded, int cause, time_t start, time_t connect, time_t end, unsigned int release) +static int osp_finish( + int handle, + int recorded, + int cause, + time_t start, + time_t connect, + time_t end, + unsigned int release) { int res; enum OSPEFAILREASON reason; @@ -889,7 +1256,7 @@ static int osp_finish(int handle, int recorded, int cause, time_t start, time_t unsigned pdd = 0; unsigned int dummy = 0; int error; - + if (handle == OSP_INVALID_HANDLE) { return 0; } @@ -899,8 +1266,23 @@ static int osp_finish(int handle, int recorded, int cause, time_t start, time_t OSPPTransactionRecordFailure(handle, reason); } - error = OSPPTransactionReportUsage(handle, difftime(end, connect), start, end, alert, connect, isPddInfoPresent, pdd, - release, (unsigned char *) "", 0, 0, 0, 0, &dummy, NULL); + error = OSPPTransactionReportUsage( + handle, + difftime(end, connect), + start, + end, + alert, + connect, + isPddInfoPresent, + pdd, + release, + (unsigned char*)"", + 0, + 0, + 0, + 0, + &dummy, + NULL); if (error == OSPC_ERR_NO_ERROR) { if (option_debug) ast_log(LOG_DEBUG, "OSP: Usage reported\n"); @@ -923,21 +1305,23 @@ static int osp_finish(int handle, int recorded, int cause, time_t start, time_t * \param data Parameter * \return 0 Success, -1 Failed */ -static int ospauth_exec(struct ast_channel* chan, void* data) +static int ospauth_exec( + struct ast_channel* chan, + void* data) { int res; - struct ast_module_user *u; + struct ast_module_user* u; const char* provider = OSP_DEF_PROVIDER; int priority_jump = 0; - struct varshead *headp; - struct ast_var_t *current; - const char *source = ""; - const char *token = ""; + struct varshead* headp; + struct ast_var_t* current; + const char* source = ""; + const char* token = ""; int handle; unsigned int timelimit; char buffer[OSP_INTSTR_SIZE]; - const char *status; - char *tmp; + const char* status; + char* tmp; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(provider); @@ -979,7 +1363,7 @@ static int ospauth_exec(struct ast_channel* chan, void* data) ast_log(LOG_DEBUG, "OSPAuth: source '%s'\n", source); ast_log(LOG_DEBUG, "OSPAuth: token size '%zd'\n", strlen(token)); } - + if ((res = osp_auth(provider, &handle, source, chan->cid.cid_num, chan->exten, token, &timelimit)) > 0) { status = AST_OSP_SUCCESS; } else { @@ -1025,26 +1409,30 @@ static int ospauth_exec(struct ast_channel* chan, void* data) * \param data Parameter * \return 0 Success, -1 Failed */ -static int osplookup_exec(struct ast_channel* chan, void* data) +static int osplookup_exec( + struct ast_channel* chan, + void* data) { int res, cres; - struct ast_module_user *u; - const char *provider = OSP_DEF_PROVIDER; + struct ast_module_user* u; + const char* provider = OSP_DEF_PROVIDER; int priority_jump = 0; - struct varshead *headp; + struct varshead* headp; struct ast_var_t* current; - const char *srcdev = ""; + const char* srcdev = ""; + const char* netid = ""; char buffer[OSP_TOKSTR_SIZE]; + unsigned int callidtypes = OSP_CALLID_UNDEFINED; struct osp_result result; - const char *status; - char *tmp; + const char* status; + char* tmp; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(exten); AST_APP_ARG(provider); AST_APP_ARG(options); ); - + if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "OSPLookup: Arg required, OSPLookup(exten[|provider[|options]])\n"); return -1; @@ -1069,11 +1457,24 @@ static int osplookup_exec(struct ast_channel* chan, void* data) if (option_debug) ast_log(LOG_DEBUG, "OSPlookup: provider '%s'\n", provider); - if ((args.options) && (strchr(args.options, 'j'))) { - priority_jump = 1; + if (args.options) { + if (strchr(args.options, 'j')) { + priority_jump = 1; + } + if (strchr(args.options, 'h')) { + callidtypes |= OSP_CALLID_H323; + } + if (strchr(args.options, 's')) { + callidtypes |= OSP_CALLID_SIP; + } + if (strchr(args.options, 'i')) { + callidtypes |= OSP_CALLID_IAX; + } } - if (option_debug) + if (option_debug) { ast_log(LOG_DEBUG, "OSPLookup: priority jump '%d'\n", priority_jump); + ast_log(LOG_DEBUG, "OSPLookup: call id types '%d'\n", callidtypes); + } result.inhandle = OSP_INVALID_HANDLE; result.intimelimit = OSP_DEF_TIMELIMIT; @@ -1088,6 +1489,8 @@ static int osplookup_exec(struct ast_channel* chan, void* data) if (sscanf(ast_var_value(current), "%d", &result.intimelimit) != 1) { result.intimelimit = OSP_DEF_TIMELIMIT; } + } else if (!strcasecmp(ast_var_name(current), "OSPINNETWORKID")) { + netid = ast_var_value(current); } else if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) { srcdev = ast_var_value(current); } @@ -1095,23 +1498,28 @@ static int osplookup_exec(struct ast_channel* chan, void* data) if (option_debug) { ast_log(LOG_DEBUG, "OSPLookup: OSPINHANDLE '%d'\n", result.inhandle); ast_log(LOG_DEBUG, "OSPLookup: OSPINTIMELIMIT '%d'\n", result.intimelimit); + ast_log(LOG_DEBUG, "OSPLookup: OSPINNETWORKID '%s'\n", netid); ast_log(LOG_DEBUG, "OSPLookup: source device '%s'\n", srcdev); } - + if ((cres = ast_autoservice_start(chan)) < 0) { ast_module_user_remove(u); return -1; } - if ((res = osp_lookup(provider, srcdev, chan->cid.cid_num, args.exten, &result)) > 0) { + if ((res = osp_lookup(provider, srcdev, chan->cid.cid_num, args.exten, callidtypes, &result)) > 0) { status = AST_OSP_SUCCESS; } else { result.tech[0] = '\0'; result.dest[0] = '\0'; + result.called[0] = '\0'; result.calling[0] = '\0'; - result.token[0] = '\0'; + result.token[0] = '\0'; + result.networkid[0] = '\0'; result.numresults = 0; result.outtimelimit = OSP_DEF_TIMELIMIT; + result.outcallid.buf[0] = '\0'; + result.outcallid.len = 0; if (!res) { status = AST_OSP_FAILED; } else { @@ -1129,6 +1537,9 @@ static int osplookup_exec(struct ast_channel* chan, void* data) pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest); if (option_debug) ast_log(LOG_DEBUG, "OSPLookup: OSPDEST '%s'\n", result.dest); + pbx_builtin_setvar_helper(chan, "OSPCALLED", result.called); + if (option_debug) + ast_log(LOG_DEBUG, "OSPLookup: OSPCALLED '%s'\n", result.called); pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling); if (option_debug) ast_log(LOG_DEBUG, "OSPLookup: OSPCALLING '%s'\n", result.calling); @@ -1143,19 +1554,35 @@ static int osplookup_exec(struct ast_channel* chan, void* data) pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer); if (option_debug) ast_log(LOG_DEBUG, "OSPLookup: OSPOUTTIMELIMIT '%s'\n", buffer); + snprintf(buffer, sizeof(buffer), "%d", callidtypes); + pbx_builtin_setvar_helper(chan, "OSPOUTCALLIDTYPES", buffer); + if (option_debug) + ast_log(LOG_DEBUG, "OSPLookup: OSPOUTCALLIDTYPES '%s'\n", buffer); pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", status); if (option_debug) ast_log(LOG_DEBUG, "OSPLookup: %s\n", status); - if (!strcasecmp(result.tech, "SIP")) { + if (!strcasecmp(result.tech, OSP_TECH_H323)) { + if ((callidtypes & OSP_CALLID_H323) && (result.outcallid.len != 0)) { + osp_uuid2str(result.outcallid.buf, buffer, sizeof(buffer)); + } else { + buffer[0] = '\0'; + } + pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer); + snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest); + pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer); + } else if (!strcasecmp(result.tech, OSP_TECH_SIP)) { + snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest); + pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer); if (!ast_strlen_zero(result.token)) { - snprintf(buffer, sizeof(buffer), "P-OSP-Auth-Token: %s", result.token); + snprintf(buffer, sizeof(buffer), "%s%s", OSP_SIP_HEADER, result.token); pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer); if (option_debug) ast_log(LOG_DEBUG, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer)); } - } else if (!strcasecmp(result.tech, "H323")) { - } else if (!strcasecmp(result.tech, "IAX")) { + } else if (!strcasecmp(result.tech, OSP_TECH_IAX)) { + snprintf(buffer, sizeof(buffer), "%s/%s/%s", result.tech, result.dest, result.called); + pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer); } if ((cres = ast_autoservice_stop(chan)) < 0) { @@ -1185,26 +1612,31 @@ static int osplookup_exec(struct ast_channel* chan, void* data) * \param data Parameter * \return 0 Success, -1 Failed */ -static int ospnext_exec(struct ast_channel* chan, void* data) +static int ospnext_exec( + struct ast_channel* chan, + void* data) { int res; - struct ast_module_user *u; + struct ast_module_user* u; + const char* provider = OSP_DEF_PROVIDER; int priority_jump = 0; int cause = 0; struct varshead* headp; struct ast_var_t* current; struct osp_result result; char buffer[OSP_TOKSTR_SIZE]; + unsigned int callidtypes = OSP_CALLID_UNDEFINED; const char* status; char* tmp; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(cause); + AST_APP_ARG(provider); AST_APP_ARG(options); ); - + if (ast_strlen_zero(data)) { - ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[|options])\n"); + ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[|provider[|options]])\n"); return -1; } @@ -1224,6 +1656,12 @@ static int ospnext_exec(struct ast_channel* chan, void* data) if (option_debug) ast_log(LOG_DEBUG, "OSPNext: cause '%d'\n", cause); + if (!ast_strlen_zero(args.provider)) { + provider = args.provider; + } + if (option_debug) + ast_log(LOG_DEBUG, "OSPlookup: provider '%s'\n", provider); + if ((args.options) && (strchr(args.options, 'j'))) { priority_jump = 1; } @@ -1249,6 +1687,10 @@ static int ospnext_exec(struct ast_channel* chan, void* data) if (sscanf(ast_var_value(current), "%d", &result.intimelimit) != 1) { result.intimelimit = OSP_DEF_TIMELIMIT; } + } else if (!strcasecmp(ast_var_name(current), "OSPOUTCALLIDTYPES")) { + if (sscanf(ast_var_value(current), "%d", &callidtypes) != 1) { + callidtypes = OSP_CALLID_UNDEFINED; + } } else if (!strcasecmp(ast_var_name(current), "OSPRESULTS")) { if (sscanf(ast_var_value(current), "%d", &result.numresults) != 1) { result.numresults = 0; @@ -1259,18 +1701,23 @@ static int ospnext_exec(struct ast_channel* chan, void* data) ast_log(LOG_DEBUG, "OSPNext: OSPINHANDLE '%d'\n", result.inhandle); ast_log(LOG_DEBUG, "OSPNext: OSPOUTHANDLE '%d'\n", result.outhandle); ast_log(LOG_DEBUG, "OSPNext: OSPINTIMELIMIT '%d'\n", result.intimelimit); + ast_log(LOG_DEBUG, "OSPNext: OSPOUTCALLIDTYPES '%d'\n", callidtypes); ast_log(LOG_DEBUG, "OSPNext: OSPRESULTS '%d'\n", result.numresults); } - if ((res = osp_next(cause, &result)) > 0) { + if ((res = osp_next(provider, cause, &result)) > 0) { status = AST_OSP_SUCCESS; } else { result.tech[0] = '\0'; result.dest[0] = '\0'; + result.called[0] = '\0'; result.calling[0] = '\0'; - result.token[0] = '\0'; + result.token[0] = '\0'; + result.networkid[0] = '\0'; result.numresults = 0; result.outtimelimit = OSP_DEF_TIMELIMIT; + result.outcallid.buf[0] = '\0'; + result.outcallid.len = 0; if (!res) { status = AST_OSP_FAILED; } else { @@ -1284,6 +1731,9 @@ static int ospnext_exec(struct ast_channel* chan, void* data) pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest); if (option_debug) ast_log(LOG_DEBUG, "OSPNext: OSPDEST '%s'\n", result.dest); + pbx_builtin_setvar_helper(chan, "OSPCALLED", result.called); + if (option_debug) + ast_log(LOG_DEBUG, "OSPNext: OSPCALLED'%s'\n", result.called); pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling); if (option_debug) ast_log(LOG_DEBUG, "OSPNext: OSPCALLING '%s'\n", result.calling); @@ -1302,15 +1752,27 @@ static int ospnext_exec(struct ast_channel* chan, void* data) if (option_debug) ast_log(LOG_DEBUG, "OSPNext: %s\n", status); - if (!strcasecmp(result.tech, "SIP")) { + if (!strcasecmp(result.tech, OSP_TECH_H323)) { + if ((callidtypes & OSP_CALLID_H323) && (result.outcallid.len != 0)) { + osp_uuid2str(result.outcallid.buf, buffer, sizeof(buffer)); + } else { + buffer[0] = '\0'; + } + pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer); + snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest); + pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer); + } else if (!strcasecmp(result.tech, OSP_TECH_SIP)) { + snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest); + pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer); if (!ast_strlen_zero(result.token)) { - snprintf(buffer, sizeof(buffer), "P-OSP-Auth-Token: %s", result.token); + snprintf(buffer, sizeof(buffer), "%s%s", OSP_SIP_HEADER, result.token); pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer); if (option_debug) ast_log(LOG_DEBUG, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer)); } - } else if (!strcasecmp(result.tech, "H323")) { - } else if (!strcasecmp(result.tech, "IAX")) { + } else if (!strcasecmp(result.tech, OSP_TECH_IAX)) { + snprintf(buffer, sizeof(buffer), "%s/%s/%s", result.tech, result.dest, result.called); + pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer); } if(res <= 0) { @@ -1335,28 +1797,30 @@ static int ospnext_exec(struct ast_channel* chan, void* data) * \param data Parameter * \return 0 Success, -1 Failed */ -static int ospfinished_exec(struct ast_channel* chan, void* data) +static int ospfinished_exec( + struct ast_channel* chan, + void* data) { int res = 1; - struct ast_module_user *u; + struct ast_module_user* u; int priority_jump = 0; int cause = 0; - struct varshead *headp; - struct ast_var_t *current; + struct varshead* headp; + struct ast_var_t* current; int inhandle = OSP_INVALID_HANDLE; int outhandle = OSP_INVALID_HANDLE; int recorded = 0; time_t start, connect, end; unsigned int release; char buffer[OSP_INTSTR_SIZE]; - const char *status; - char *tmp; + const char* status; + char* tmp; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(cause); AST_APP_ARG(options); ); - + u = ast_module_user_add(chan); if (!(tmp = ast_strdupa(data))) { @@ -1385,8 +1849,8 @@ static int ospfinished_exec(struct ast_channel* chan, void* data) } } else if (!recorded && (!strcasecmp(ast_var_name(current), "OSPAUTHSTATUS") || - !strcasecmp(ast_var_name(current), "OSPLOOKUPSTATUS") || - !strcasecmp(ast_var_name(current), "OSPNEXTSTATUS"))) + !strcasecmp(ast_var_name(current), "OSPLOOKUPSTATUS") || + !strcasecmp(ast_var_name(current), "OSPNEXTSTATUS"))) { if (strcasecmp(ast_var_value(current), AST_OSP_SUCCESS)) { recorded = 1; @@ -1484,7 +1948,7 @@ static int osp_load(void) t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "accelerate"); if (t && ast_true(t)) { if ((error = OSPPInit(1)) != OSPC_ERR_NO_ERROR) { - ast_log(LOG_WARNING, "OSP: Unable to enable hardware acceleration\n"); + ast_log(LOG_WARNING, "OSP: Unable to enable hardware accelleration\n"); OSPPInit(0); } else { osp_hardware = 1; @@ -1497,12 +1961,12 @@ static int osp_load(void) t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "tokenformat"); if (t) { - if ((sscanf(t, "%d", &v) == 1) && - ((v == TOKEN_ALGO_SIGNED) || (v == TOKEN_ALGO_UNSIGNED) || (v == TOKEN_ALGO_BOTH))) + if ((sscanf(t, "%d", &v) == 1) && + ((v == TOKEN_ALGO_SIGNED) || (v == TOKEN_ALGO_UNSIGNED) || (v == TOKEN_ALGO_BOTH))) { osp_tokenformat = v; } else { - ast_log(LOG_WARNING, "tokenformat should be an integer from %d, %d or %d, not '%s'\n", + ast_log(LOG_WARNING, "tokenformat should be an integer from %d, %d or %d, not '%s'\n", TOKEN_ALGO_SIGNED, TOKEN_ALGO_UNSIGNED, TOKEN_ALGO_BOTH, t); } } @@ -1556,7 +2020,10 @@ static int osp_unload(void) return 0; } -static int osp_show(int fd, int argc, char* argv[]) +static int osp_show( + int fd, + int argc, + char* argv[]) { int i; int found = 0; @@ -1583,7 +2050,7 @@ static int osp_show(int fd, int argc, char* argv[]) tokenalgo = "Signed"; break; } - ast_cli(fd, "OSP: %s %s %s\n", + ast_cli(fd, "OSP: %s %s %s\n", osp_initialized ? "Initialized" : "Uninitialized", osp_hardware ? "Accelerated" : "Normal", tokenalgo); } @@ -1609,6 +2076,7 @@ static int osp_show(int fd, int argc, char* argv[]) ast_cli(fd, "Timeout: %d milliseconds\n", p->timeout); ast_cli(fd, "Source: %s\n", strlen(p->source) ? p->source : "<unspecified>"); ast_cli(fd, "Auth Policy %d\n", p->authpolicy); + ast_cli(fd, "Default protocol %s\n", p->defaultprotocol); ast_cli(fd, "OSP Handle: %d\n", p->handle); found++; } @@ -1628,7 +2096,7 @@ static int osp_show(int fd, int argc, char* argv[]) static const char* app1= "OSPAuth"; static const char* synopsis1 = "OSP authentication"; -static const char* descrip1 = +static const char* descrip1 = " OSPAuth([provider[|options]]): Authenticate a SIP INVITE by OSP and sets\n" "the variables:\n" " ${OSPINHANDLE}: The inbound call transaction handle\n" @@ -1642,38 +2110,45 @@ static const char* descrip1 = static const char* app2= "OSPLookup"; static const char* synopsis2 = "Lookup destination by OSP"; -static const char* descrip2 = +static const char* descrip2 = " OSPLookup(exten[|provider[|options]]): Looks up an extension via OSP and sets\n" "the variables, where 'n' is the number of the result beginning with 1:\n" " ${OSPOUTHANDLE}: The OSP Handle for anything remaining\n" " ${OSPTECH}: The technology to use for the call\n" " ${OSPDEST}: The destination to use for the call\n" +" ${OSPCALLED}: The called number to use for the call\n" " ${OSPCALLING}: The calling number to use for the call\n" +" ${OSPDIALSTR}: The dial command string\n" " ${OSPOUTTOKEN}: The actual OSP token as a string\n" " ${OSPOUTTIMELIMIT}: The outbound call duration limit in seconds\n" +" ${OSPOUTCALLIDTYPES}: The outbound call id types\n" +" ${OSPOUTCALLID}: The outbound call id\n" " ${OSPRESULTS}: The number of OSP results total remaining\n" "\n" "The option string may contain the following character:\n" " 'j' -- jump to n+101 priority if the lookup was NOT successful\n" +" 'h' -- generate H323 call id for the outbound call\n" +" 's' -- generate SIP call id for the outbound call. Have not been implemented\n" +" 'i' -- generate IAX call id for the outbound call. Have not been implemented\n" "This application sets the following channel variable upon completion:\n" -" OSPLOOKUPSTATUS The status of the OSP Lookup attempt as a text string, one of\n" +" OSPLOOKUPSTATUS The status of the OSP Lookup attempt as a text string, one of\n" " SUCCESS | FAILED | ERROR\n"; static const char* app3 = "OSPNext"; static const char* synopsis3 = "Lookup next destination by OSP"; -static const char* descrip3 = -" OSPNext(cause[|options]): Looks up the next OSP Destination for ${OSPOUTHANDLE}\n" +static const char* descrip3 = +" OSPNext(cause[|provider[|options]]): Looks up the next OSP Destination for ${OSPOUTHANDLE}\n" "See OSPLookup for more information\n" "\n" "The option string may contain the following character:\n" " 'j' -- jump to n+101 priority if the lookup was NOT successful\n" "This application sets the following channel variable upon completion:\n" -" OSPNEXTSTATUS The status of the OSP Next attempt as a text string, one of\n" -" SUCCESS | FAILED |ERROR\n"; +" OSPNEXTSTATUS The status of the OSP Next attempt as a text string, one of\n" +" SUCCESS | FAILED | ERROR\n"; static const char* app4 = "OSPFinish"; static const char* synopsis4 = "Record OSP entry"; -static const char* descrip4 = +static const char* descrip4 = " OSPFinish([status[|options]]): Records call state for ${OSPINHANDLE}, according to\n" "status, which should be one of BUSY, CONGESTION, ANSWER, NOANSWER, or CHANUNAVAIL\n" "or coincidentally, just what the Dial application stores in its ${DIALSTATUS}.\n" @@ -1681,15 +2156,15 @@ static const char* descrip4 = "The option string may contain the following character:\n" " 'j' -- jump to n+101 priority if the finish attempt was NOT successful\n" "This application sets the following channel variable upon completion:\n" -" OSPFINISHSTATUS The status of the OSP Finish attempt as a text string, one of\n" -" SUCCESS | FAILED |ERROR \n"; +" OSPFINISHSTATUS The status of the OSP Finish attempt as a text string, one of\n" +" SUCCESS | FAILED | ERROR \n"; static const char osp_usage[] = "Usage: osp show\n" " Displays information on Open Settlement Protocol support\n"; static struct ast_cli_entry cli_osp[] = { - { { "osp", "show", NULL}, + { {"osp", "show", NULL}, osp_show, "Displays OSP information", osp_usage }, }; @@ -1697,7 +2172,7 @@ static struct ast_cli_entry cli_osp[] = { static int load_module(void) { int res; - + if(!osp_load()) return AST_MODULE_LOAD_DECLINE; @@ -1713,7 +2188,7 @@ static int load_module(void) static int unload_module(void) { int res; - + res = ast_unregister_application(app4); res |= ast_unregister_application(app3); res |= ast_unregister_application(app2); @@ -1735,7 +2210,7 @@ static int reload(void) } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Open Settlement Protocol Applications", - .load = load_module, - .unload = unload_module, - .reload = reload, - ); + .load = load_module, + .unload = unload_module, + .reload = reload, + ); |