Wed Jan 8 2020 09:49:40

Asterisk developer's documentation


app_osplookup.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*!
20  * \file
21  * \brief Open Settlement Protocol (OSP) Applications
22  *
23  * \author Mark Spencer <markster@digium.com>
24  *
25  * \extref The OSP Toolkit: http://www.transnexus.com
26  * \extref OpenSSL http://www.openssl.org
27  *
28  * \ingroup applications
29  */
30 
31 /*** MODULEINFO
32  <depend>osptk</depend>
33  <depend>openssl</depend>
34  <support_level>extended</support_level>
35  ***/
36 
37 #include "asterisk.h"
38 
39 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 370642 $")
40 
41 #include <osp/osp.h>
42 #include <osp/osputils.h>
43 #include <osp/ospb64.h>
44 
45 #include "asterisk/paths.h"
46 #include "asterisk/lock.h"
47 #include "asterisk/config.h"
48 #include "asterisk/utils.h"
49 #include "asterisk/causes.h"
50 #include "asterisk/channel.h"
51 #include "asterisk/app.h"
52 #include "asterisk/module.h"
53 #include "asterisk/pbx.h"
54 #include "asterisk/cli.h"
55 #include "asterisk/astosp.h"
56 
57 /*** DOCUMENTATION
58  <application name="OSPAuth" language="en_US">
59  <synopsis>
60  OSP Authentication.
61  </synopsis>
62  <syntax>
63  <parameter name="provider">
64  <para>The name of the provider that authenticates the call.</para>
65  </parameter>
66  <parameter name="options">
67  <para>Reserverd.</para>
68  </parameter>
69  </syntax>
70  <description>
71  <para>Authenticate a call by OSP.</para>
72  <para>Input variables:</para>
73  <variablelist>
74  <variable name="OSPINPEERIP">
75  <para>The last hop IP address.</para>
76  </variable>
77  <variable name="OSPINTOKEN">
78  <para>The inbound OSP token.</para>
79  </variable>
80  </variablelist>
81  <para>Output variables:</para>
82  <variablelist>
83  <variable name="OSPINHANDLE">
84  <para>The inbound call OSP transaction handle.</para>
85  </variable>
86  <variable name="OSPINTIMELIMIT">
87  <para>The inbound call duration limit in seconds.</para>
88  </variable>
89  </variablelist>
90  <para>This application sets the following channel variable upon completion:</para>
91  <variablelist>
92  <variable name="OSPAUTHSTATUS">
93  <para>The status of OSPAuth attempt as a text string, one of</para>
94  <value name="SUCCESS" />
95  <value name="FAILED" />
96  <value name="ERROR" />
97  </variable>
98  </variablelist>
99  </description>
100  <see-also>
101  <ref type="application">OSPLookup</ref>
102  <ref type="application">OSPNext</ref>
103  <ref type="application">OSPFinish</ref>
104  </see-also>
105  </application>
106  <application name="OSPLookup" language="en_US">
107  <synopsis>
108  Lookup destination by OSP.
109  </synopsis>
110  <syntax>
111  <parameter name="exten" required="true">
112  <para>The exten of the call.</para>
113  </parameter>
114  <parameter name="provider">
115  <para>The name of the provider that is used to route the call.</para>
116  </parameter>
117  <parameter name="options">
118  <enumlist>
119  <enum name="h">
120  <para>generate H323 call id for the outbound call</para>
121  </enum>
122  <enum name="s">
123  <para>generate SIP call id for the outbound call. Have not been implemented</para>
124  </enum>
125  <enum name="i">
126  <para>generate IAX call id for the outbound call. Have not been implemented</para>
127  </enum>
128  </enumlist>
129  </parameter>
130  </syntax>
131  <description>
132  <para>Looks up destination via OSP.</para>
133  <para>Input variables:</para>
134  <variablelist>
135  <variable name="OSPINACTUALSRC">
136  <para>The actual source device IP address in indirect mode.</para>
137  </variable>
138  <variable name="OSPINPEERIP">
139  <para>The last hop IP address.</para>
140  </variable>
141  <variable name="OSPINHANDLE">
142  <para>The inbound call OSP transaction handle.</para>
143  </variable>
144  <variable name="OSPINTIMELIMIT">
145  <para>The inbound call duration limit in seconds.</para>
146  </variable>
147  <variable name="OSPINNETWORKID">
148  <para>The inbound source network ID.</para>
149  </variable>
150  <variable name="OSPINNPRN">
151  <para>The inbound routing number.</para>
152  </variable>
153  <variable name="OSPINNPCIC">
154  <para>The inbound carrier identification code.</para>
155  </variable>
156  <variable name="OSPINNPDI">
157  <para>The inbound number portability database dip indicator.</para>
158  </variable>
159  <variable name="OSPINSPID">
160  <para>The inbound service provider identity.</para>
161  </variable>
162  <variable name="OSPINOCN">
163  <para>The inbound operator company number.</para>
164  </variable>
165  <variable name="OSPINSPN">
166  <para>The inbound service provider name.</para>
167  </variable>
168  <variable name="OSPINALTSPN">
169  <para>The inbound alternate service provider name.</para>
170  </variable>
171  <variable name="OSPINMCC">
172  <para>The inbound mobile country code.</para>
173  </variable>
174  <variable name="OSPINMNC">
175  <para>The inbound mobile network code.</para>
176  </variable>
177  <variable name="OSPINTOHOST">
178  <para>The inbound To header host part.</para>
179  </variable>
180  <variable name="OSPINDIVUSER">
181  <para>The inbound Diversion header user part.</para>
182  </variable>
183  <variable name="OSPINDIVHOST">
184  <para>The inbound Diversion header host part.</para>
185  </variable>
186  <variable name="OSPINCUSTOMINFOn">
187  <para>The inbound custom information, where <literal>n</literal> is the index beginning with <literal>1</literal>
188  upto <literal>8</literal>.</para>
189  </variable>
190  </variablelist>
191  <para>Output variables:</para>
192  <variablelist>
193  <variable name="OSPOUTHANDLE">
194  <para>The outbound call OSP transaction handle.</para>
195  </variable>
196  <variable name="OSPOUTTECH">
197  <para>The outbound channel technology for the call.</para>
198  </variable>
199  <variable name="OSPDESTINATION">
200  <para>The outbound destination IP address.</para>
201  </variable>
202  <variable name="OSPOUTCALLING">
203  <para>The outbound calling number.</para>
204  </variable>
205  <variable name="OSPOUTCALLED">
206  <para>The outbound called number.</para>
207  </variable>
208  <variable name="OSPOUTNETWORKID">
209  <para>The outbound destination network ID.</para>
210  </variable>
211  <variable name="OSPOUTNPRN">
212  <para>The outbound routing number.</para>
213  </variable>
214  <variable name="OSPOUTNPCIC">
215  <para>The outbound carrier identification code.</para>
216  </variable>
217  <variable name="OSPOUTNPDI">
218  <para>The outbound number portability database dip indicator.</para>
219  </variable>
220  <variable name="OSPOUTSPID">
221  <para>The outbound service provider identity.</para>
222  </variable>
223  <variable name="OSPOUTOCN">
224  <para>The outbound operator company number.</para>
225  </variable>
226  <variable name="OSPOUTSPN">
227  <para>The outbound service provider name.</para>
228  </variable>
229  <variable name="OSPOUTALTSPN">
230  <para>The outbound alternate service provider name.</para>
231  </variable>
232  <variable name="OSPOUTMCC">
233  <para>The outbound mobile country code.</para>
234  </variable>
235  <variable name="OSPOUTMNC">
236  <para>The outbound mobile network code.</para>
237  </variable>
238  <variable name="OSPOUTTOKEN">
239  <para>The outbound OSP token.</para>
240  </variable>
241  <variable name="OSPDESTREMAILS">
242  <para>The number of remained destinations.</para>
243  </variable>
244  <variable name="OSPOUTTIMELIMIT">
245  <para>The outbound call duration limit in seconds.</para>
246  </variable>
247  <variable name="OSPOUTCALLIDTYPES">
248  <para>The outbound Call-ID types.</para>
249  </variable>
250  <variable name="OSPOUTCALLID">
251  <para>The outbound Call-ID. Only for H.323.</para>
252  </variable>
253  <variable name="OSPDIALSTR">
254  <para>The outbound Dial command string.</para>
255  </variable>
256  </variablelist>
257  <para>This application sets the following channel variable upon completion:</para>
258  <variablelist>
259  <variable name="OSPLOOKUPSTATUS">
260  <para>The status of OSPLookup attempt as a text string, one of</para>
261  <value name="SUCCESS" />
262  <value name="FAILED" />
263  <value name="ERROR" />
264  </variable>
265  </variablelist>
266  </description>
267  <see-also>
268  <ref type="application">OSPAuth</ref>
269  <ref type="application">OSPNext</ref>
270  <ref type="application">OSPFinish</ref>
271  </see-also>
272  </application>
273  <application name="OSPNext" language="en_US">
274  <synopsis>
275  Lookup next destination by OSP.
276  </synopsis>
277  <description>
278  <para>Looks up the next destination via OSP.</para>
279  <para>Input variables:</para>
280  <variablelist>
281  <variable name="OSPINHANDLE">
282  <para>The inbound call OSP transaction handle.</para>
283  </variable>
284  <variable name="OSPOUTHANDLE">
285  <para>The outbound call OSP transaction handle.</para>
286  </variable>
287  <variable name="OSPINTIMELIMIT">
288  <para>The inbound call duration limit in seconds.</para>
289  </variable>
290  <variable name="OSPOUTCALLIDTYPES">
291  <para>The outbound Call-ID types.</para>
292  </variable>
293  <variable name="OSPDESTREMAILS">
294  <para>The number of remained destinations.</para>
295  </variable>
296  </variablelist>
297  <para>Output variables:</para>
298  <variablelist>
299  <variable name="OSPOUTTECH">
300  <para>The outbound channel technology.</para>
301  </variable>
302  <variable name="OSPDESTINATION">
303  <para>The destination IP address.</para>
304  </variable>
305  <variable name="OSPOUTCALLING">
306  <para>The outbound calling number.</para>
307  </variable>
308  <variable name="OSPOUTCALLED">
309  <para>The outbound called number.</para>
310  </variable>
311  <variable name="OSPOUTNETWORKID">
312  <para>The outbound destination network ID.</para>
313  </variable>
314  <variable name="OSPOUTNPRN">
315  <para>The outbound routing number.</para>
316  </variable>
317  <variable name="OSPOUTNPCIC">
318  <para>The outbound carrier identification code.</para>
319  </variable>
320  <variable name="OSPOUTNPDI">
321  <para>The outbound number portability database dip indicator.</para>
322  </variable>
323  <variable name="OSPOUTSPID">
324  <para>The outbound service provider identity.</para>
325  </variable>
326  <variable name="OSPOUTOCN">
327  <para>The outbound operator company number.</para>
328  </variable>
329  <variable name="OSPOUTSPN">
330  <para>The outbound service provider name.</para>
331  </variable>
332  <variable name="OSPOUTALTSPN">
333  <para>The outbound alternate service provider name.</para>
334  </variable>
335  <variable name="OSPOUTMCC">
336  <para>The outbound mobile country code.</para>
337  </variable>
338  <variable name="OSPOUTMNC">
339  <para>The outbound mobile network code.</para>
340  </variable>
341  <variable name="OSPOUTTOKEN">
342  <para>The outbound OSP token.</para>
343  </variable>
344  <variable name="OSPDESTREMAILS">
345  <para>The number of remained destinations.</para>
346  </variable>
347  <variable name="OSPOUTTIMELIMIT">
348  <para>The outbound call duration limit in seconds.</para>
349  </variable>
350  <variable name="OSPOUTCALLID">
351  <para>The outbound Call-ID. Only for H.323.</para>
352  </variable>
353  <variable name="OSPDIALSTR">
354  <para>The outbound Dial command string.</para>
355  </variable>
356  </variablelist>
357  <para>This application sets the following channel variable upon completion:</para>
358  <variablelist>
359  <variable name="OSPNEXTSTATUS">
360  <para>The status of the OSPNext attempt as a text string, one of</para>
361  <value name="SUCCESS" />
362  <value name="FAILED" />
363  <value name="ERROR" />
364  </variable>
365  </variablelist>
366  </description>
367  <see-also>
368  <ref type="application">OSPAuth</ref>
369  <ref type="application">OSPLookup</ref>
370  <ref type="application">OSPFinish</ref>
371  </see-also>
372  </application>
373  <application name="OSPFinish" language="en_US">
374  <synopsis>
375  Report OSP entry.
376  </synopsis>
377  <syntax>
378  <parameter name="cause">
379  <para>Hangup cause.</para>
380  </parameter>
381  <parameter name="options">
382  <para>Reserved.</para>
383  </parameter>
384  </syntax>
385  <description>
386  <para>Report call state.</para>
387  <para>Input variables:</para>
388  <variablelist>
389  <variable name="OSPINHANDLE">
390  <para>The inbound call OSP transaction handle.</para>
391  </variable>
392  <variable name="OSPOUTHANDLE">
393  <para>The outbound call OSP transaction handle.</para>
394  </variable>
395  <variable name="OSPAUTHSTATUS">
396  <para>The OSPAuth status.</para>
397  </variable>
398  <variable name="OSPLOOKUPSTATUS">
399  <para>The OSPLookup status.</para>
400  </variable>
401  <variable name="OSPNEXTSTATUS">
402  <para>The OSPNext status.</para>
403  </variable>
404  <variable name="OSPINAUDIOQOS">
405  <para>The inbound call leg audio QoS string.</para>
406  </variable>
407  <variable name="OSPOUTAUDIOQOS">
408  <para>The outbound call leg audio QoS string.</para>
409  </variable>
410  </variablelist>
411  <para>This application sets the following channel variable upon completion:</para>
412  <variablelist>
413  <variable name="OSPFINISHSTATUS">
414  <para>The status of the OSPFinish attempt as a text string, one of</para>
415  <value name="SUCCESS" />
416  <value name="FAILED" />
417  <value name="ERROR" />
418  </variable>
419  </variablelist>
420  </description>
421  <see-also>
422  <ref type="application">OSPAuth</ref>
423  <ref type="application">OSPLookup</ref>
424  <ref type="application">OSPNext</ref>
425  </see-also>
426  </application>
427  ***/
428 
429 /* OSP Buffer Sizes */
430 #define OSP_SIZE_INTSTR ((unsigned int)16) /* OSP signed/unsigned int string buffer size */
431 #define OSP_SIZE_NORSTR ((unsigned int)256) /* OSP normal string buffer size */
432 #define OSP_SIZE_KEYSTR ((unsigned int)1024) /* OSP certificate string buffer size */
433 #define OSP_SIZE_TOKSTR ((unsigned int)4096) /* OSP token string buffer size */
434 #define OSP_SIZE_TECHSTR ((unsigned int)32) /* OSP signed/unsigned int string buffer size */
435 #define OSP_SIZE_UUID ((unsigned int)16) /* UUID size */
436 #define OSP_SIZE_UUIDSTR ((unsigned int)36) /* UUID string size */
437 #define OSP_SIZE_QOSSTR ((unsigned int)1024) /* QoS string buffer size */
438 
439 /* Call ID Type*/
440 #define OSP_CALLID_UNDEF ((unsigned int)0) /* Undefined */
441 #define OSP_CALLID_SIP ((unsigned int)(1 << 0)) /* SIP */
442 #define OSP_CALLID_H323 ((unsigned int)(1 << 1)) /* H.323 */
443 #define OSP_CALLID_IAX ((unsigned int)(1 << 2)) /* IAX2 */
444 #define OSP_CALLID_MAXNUM ((unsigned int)3) /* Max number of call ID types */
445 
446 /* OSP Supported Destination Protocols */
447 #define OSP_PROT_SIP ((const char*)"SIP") /* SIP protocol name */
448 #define OSP_PROT_H323 ((const char*)"H323") /* H.323 Q.931 protocol name*/
449 #define OSP_PROT_IAX ((const char*)"IAX") /* IAX2 protocol name */
450 #define OSP_PROT_SKYPE ((const char*)"SKYPE") /* Skype protocol name */
451 
452 /* OSP supported Destination Tech */
453 #define OSP_TECH_SIP ((const char*)"SIP") /* SIP tech name */
454 #define OSP_TECH_H323 ((const char*)"H323") /* OH323 tech name */
455 #define OSP_TECH_IAX ((const char*)"IAX2") /* IAX2 tech name */
456 #define OSP_TECH_SKYPE ((const char*)"SKYPE") /* Skype tech name */
457 
458 /* SIP OSP header field name */
459 #define OSP_SIP_HEADER ((const char*)"P-OSP-Auth-Token")
460 
461 /* OSP Authentication Policy */
463  OSP_AUTH_NO = 0, /* Accept any call */
464  OSP_AUTH_YES, /* Accept call with valid OSP token or without OSP token */
465  OSP_AUTH_EXC /* Only accept call with valid OSP token */
466 };
467 
468 /* OSP Work Mode */
470  OSP_MODE_DIRECT= 0, /* Direct */
471  OSP_MODE_INDIRECT /* Indirect */
472 };
473 
474 /* OSP Service Type */
476  OSP_SRV_VOICE = 0, /* Normal voice service */
477  OSP_SRV_NPQUERY /* Ported number query service */
478 };
479 
480 /* OSP Constants */
481 #define OSP_OK ((int)1) /* OSP function call successful */
482 #define OSP_FAILED ((int)0) /* OSP function call failed */
483 #define OSP_ERROR ((int)-1) /* OSP function call error */
484 #define OSP_AST_OK ((int)0) /* Asterisk function call successful */
485 #define OSP_AST_ERROR ((int)-1) /* Asterisk function call error */
486 #define OSP_INVALID_HANDLE ((int)-1) /* Invalid OSP handle, provider, transaction etc. */
487 #define OSP_CONFIG_FILE ((const char*)"osp.conf") /* OSP configuration file name */
488 #define OSP_GENERAL_CAT ((const char*)"general") /* OSP global configuration context name */
489 #define OSP_DEF_PROVIDER ((const char*)"default") /* OSP default provider context name */
490 #define OSP_MAX_CERTS ((unsigned int)10) /* OSP max number of cacerts */
491 #define OSP_MAX_SPOINTS ((unsigned int)10) /* OSP max number of service points */
492 #define OSP_DEF_MAXCONNECT ((unsigned int)20) /* OSP default max_connections */
493 #define OSP_MIN_MAXCONNECT ((unsigned int)1) /* OSP min max_connections */
494 #define OSP_MAX_MAXCONNECT ((unsigned int)1000) /* OSP max max_connections */
495 #define OSP_DEF_RETRYDELAY ((unsigned int)0) /* OSP default retry delay */
496 #define OSP_MIN_RETRYDELAY ((unsigned int)0) /* OSP min retry delay */
497 #define OSP_MAX_RETRYDELAY ((unsigned int)10) /* OSP max retry delay */
498 #define OSP_DEF_RETRYLIMIT ((unsigned int)2) /* OSP default retry times */
499 #define OSP_MIN_RETRYLIMIT ((unsigned int)0) /* OSP min retry times */
500 #define OSP_MAX_RETRYLIMIT ((unsigned int)100) /* OSP max retry times */
501 #define OSP_DEF_TIMEOUT ((unsigned int)500) /* OSP default timeout in ms */
502 #define OSP_MIN_TIMEOUT ((unsigned int)200) /* OSP min timeout in ms */
503 #define OSP_MAX_TIMEOUT ((unsigned int)10000) /* OSP max timeout in ms */
504 #define OSP_DEF_AUTHPOLICY OSP_AUTH_YES /* OSP default auth policy, yes */
505 #define OSP_AUDIT_URL ((const char*)"localhost") /* OSP default Audit URL */
506 #define OSP_LOCAL_VALIDATION ((int)1) /* Validate OSP token locally */
507 #define OSP_SSL_LIFETIME ((unsigned int)300) /* SSL life time, in seconds */
508 #define OSP_HTTP_PERSISTENCE ((int)1) /* In seconds */
509 #define OSP_CUSTOMER_ID ((const char*)"") /* OSP customer ID */
510 #define OSP_DEVICE_ID ((const char*)"") /* OSP device ID */
511 #define OSP_DEF_MAXDESTS ((unsigned int)5) /* OSP default max number of destinations */
512 #define OSP_DEF_TIMELIMIT ((unsigned int)0) /* OSP default duration limit, no limit */
513 #define OSP_DEF_PROTOCOL OSP_PROT_SIP /* OSP default destination protocol, SIP */
514 #define OSP_DEF_WORKMODE OSP_MODE_DIRECT /* OSP default work mode, direct */
515 #define OSP_DEF_SRVTYPE OSP_SRV_VOICE /* OSP default service type, voice */
516 #define OSP_MAX_CUSTOMINFO ((unsigned int)8) /* OSP max number of custom info */
517 #define OSP_DEF_INTSTATS ((int)-1) /* OSP default int statistic */
518 #define OSP_DEF_FLOATSTATS ((float)-1) /* OSP default float statistic */
519 
520 /* OSP Provider */
521 struct osp_provider {
522  OSPTPROVHANDLE handle; /* OSP provider handle */
523  char name[OSP_SIZE_NORSTR]; /* OSP provider context name */
524  char privatekey[OSP_SIZE_NORSTR]; /* OSP private key file name */
525  char localcert[OSP_SIZE_NORSTR]; /* OSP local cert file name */
526  unsigned int canum; /* Number of cacerts */
527  char cacerts[OSP_MAX_CERTS][OSP_SIZE_NORSTR]; /* Cacert file names */
528  unsigned int spnum; /* Number of service points */
529  char spoints[OSP_MAX_SPOINTS][OSP_SIZE_NORSTR]; /* Service point URLs */
530  unsigned int maxconnect; /* Max number of connections */
531  unsigned int retrydelay; /* Retry delay */
532  unsigned int retrylimit; /* Retry limit */
533  unsigned int timeout; /* Timeout in ms */
534  char source[OSP_SIZE_NORSTR]; /* IP of self */
535  enum osp_authpolicy authpolicy; /* OSP authentication policy */
536  const char* defprotocol; /* OSP default destination protocol */
537  enum osp_workmode workmode; /* OSP work mode */
538  enum osp_srvtype srvtype; /* OSP service type */
539  struct osp_provider* next; /* Pointer to next OSP provider */
540 };
541 
542 /* Call ID */
543 struct osp_callid {
544  unsigned char buf[OSP_SIZE_NORSTR]; /* Call ID string */
545  unsigned int len; /* Call ID length */
546 };
547 
548 /* Number Portability Data */
549 struct osp_npdata {
550  const char* rn; /* Rounding Number */
551  const char* cic; /* Carrier Identification Code */
552  int npdi; /* NP Database Dip Indicator */
553  const char* opname[OSPC_OPNAME_NUMBER]; /* Operator Names */
554 };
555 
556 /* SIP Diversion Header Parameters */
558  const char* user; /* Diversion header user info */
559  const char* host; /* Diversion header host info */
560 };
561 
562 /* OSP Application In/Output Results */
563 struct osp_results {
564  int inhandle; /* Inbound transaction handle */
565  int outhandle; /* Outbound transaction handle */
566  unsigned int intimelimit; /* Inbound duration limit */
567  unsigned int outtimelimit; /* Outbound duration limit */
568  char tech[OSP_SIZE_TECHSTR]; /* Outbound Asterisk TECH string */
569  char dest[OSP_SIZE_NORSTR]; /* Outbound destination IP address */
570  char calling[OSP_SIZE_NORSTR]; /* Outbound calling number, may be translated */
571  char called[OSP_SIZE_NORSTR]; /* Outbound called number, may be translated */
572  char token[OSP_SIZE_TOKSTR]; /* Outbound OSP token */
573  char networkid[OSP_SIZE_NORSTR]; /* Outbound network ID */
574  char nprn[OSP_SIZE_NORSTR]; /* Outbound NP routing number */
575  char npcic[OSP_SIZE_NORSTR]; /* Outbound NP carrier identification code */
576  int npdi; /* Outbound NP database dip indicator */
577  char opname[OSPC_OPNAME_NUMBER][OSP_SIZE_NORSTR]; /* Outbound Operator names */
578  unsigned int numdests; /* Number of remain outbound destinations */
579  struct osp_callid outcallid; /* Outbound call ID */
580 };
581 
582 /* OSP Call Leg */
584  OSP_CALL_INBOUND, /* Inbound call leg */
585  OSP_CALL_OUTBOUND /* Outbound call leg */
586 };
587 
588 /* OSP Media Stream Direction */
590  OSP_DIR_RX = 0, /* Receive */
591  OSP_DIR_TX, /* Send */
592  OSP_DIR_NUMBER /* Number of directions */
593 };
594 
595 /* OSP Metrics */
596 struct osp_metrics {
597  int value; /* Value */
598  float min; /* Minimum */
599  float max; /* Maximum */
600  float avg; /* Average */
601  float ndev; /* Normal deviation */
602  float sdev; /* Standard deviation */
603 };
604 
605 /* OSP Module Global Variables */
606 AST_MUTEX_DEFINE_STATIC(osp_lock); /* Lock of OSP provider list */
607 static int osp_initialized = 0; /* Init flag */
608 static int osp_hardware = 0; /* Hardware accelleration flag */
609 static int osp_security = 0; /* Using security features flag */
610 static struct osp_provider* osp_providers = NULL; /* OSP provider list */
611 static unsigned int osp_tokenformat = TOKEN_ALGO_SIGNED; /* Token format supported */
612 
613 /* OSP default certificates */
614 const char* B64PKey = "MIIBOgIBAAJBAK8t5l+PUbTC4lvwlNxV5lpl+2dwSZGW46dowTe6y133XyVEwNiiRma2YNk3xKs/TJ3Wl9Wpns2SYEAJsFfSTukCAwEAAQJAPz13vCm2GmZ8Zyp74usTxLCqSJZNyMRLHQWBM0g44Iuy4wE3vpi7Wq+xYuSOH2mu4OddnxswCP4QhaXVQavTAQIhAOBVCKXtppEw9UaOBL4vW0Ed/6EA/1D8hDW6St0h7EXJAiEAx+iRmZKhJD6VT84dtX5ZYNVk3j3dAcIOovpzUj9a0CECIEduTCapmZQ5xqAEsLXuVlxRtQgLTUD4ZxDElPn8x0MhAiBE2HlcND0+qDbvtwJQQOUzDgqg5xk3w8capboVdzAlQQIhAMC+lDL7+gDYkNAft5Mu+NObJmQs4Cr+DkDFsKqoxqrm";
615 const char* B64LCert = "MIIBeTCCASMCEHqkOHVRRWr+1COq3CR/xsowDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTA1MDYyMzAwMjkxOFoXDTA2MDYyNDAwMjkxOFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCvLeZfj1G0wuJb8JTcVeZaZftncEmRluOnaME3ustd918lRMDYokZmtmDZN8SrP0yd1pfVqZ7NkmBACbBX0k7pAgMBAAEwDQYJKoZIhvcNAQEEBQADQQDnV8QNFVVJx/+7IselU0wsepqMurivXZzuxOmTEmTVDzCJx1xhA8jd3vGAj7XDIYiPub1PV23eY5a2ARJuw5w9";
616 const char* B64CACert = "MIIBYDCCAQoCAQEwDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTAyMDIwNDE4MjU1MloXDTEyMDIwMzE4MjU1MlowOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAPGeGwV41EIhX0jEDFLRXQhDEr50OUQPq+f55VwQd0TQNts06BP29+UiNdRW3c3IRHdZcJdC1Cg68ME9cgeq0h8CAwEAATANBgkqhkiG9w0BAQQFAANBAGkzBSj1EnnmUxbaiG1N4xjIuLAWydun7o3bFk2tV8dBIhnuh445obYyk1EnQ27kI7eACCILBZqi2MHDOIMnoN0=";
617 
618 /* OSP Client Wrapper APIs */
619 
620 /*!
621  * \brief Create OSP provider handle according to configuration
622  * \param cfg OSP configuration
623  * \param name OSP provider context name
624  * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
625  */
627  struct ast_config* cfg,
628  const char* name)
629 {
630  int res = OSP_FAILED;
631  struct ast_variable* var;
632  struct osp_provider* provider;
633  OSPTPRIVATEKEY privatekey;
634  OSPT_CERT localcert;
635  OSPT_CERT cacerts[OSP_MAX_CERTS];
636  const OSPT_CERT* pcacerts[OSP_MAX_CERTS];
637  const char* pspoints[OSP_MAX_SPOINTS];
638  unsigned char privatekeydata[OSP_SIZE_KEYSTR];
639  unsigned char localcertdata[OSP_SIZE_KEYSTR];
640  unsigned char cacertdata[OSP_SIZE_KEYSTR];
641  int i, num, error = OSPC_ERR_NO_ERROR;
642 
643  if (!(provider = ast_calloc(1, sizeof(*provider)))) {
644  ast_log(LOG_ERROR, "Out of memory\n");
645  return OSP_ERROR;
646  }
647 
648  /* ast_calloc has set 0 in provider */
649  provider->handle = OSP_INVALID_HANDLE;
650  ast_copy_string(provider->name, name, sizeof(provider->name));
651  snprintf(provider->privatekey, sizeof(provider->privatekey), "%s/%s-privatekey.pem", ast_config_AST_KEY_DIR, name);
652  snprintf(provider->localcert, sizeof(provider->localcert), "%s/%s-localcert.pem", ast_config_AST_KEY_DIR, name);
653  snprintf(provider->cacerts[0], sizeof(provider->cacerts[0]), "%s/%s-cacert_0.pem", ast_config_AST_KEY_DIR, name);
654  provider->maxconnect = OSP_DEF_MAXCONNECT;
655  provider->retrydelay = OSP_DEF_RETRYDELAY;
656  provider->retrylimit = OSP_DEF_RETRYLIMIT;
657  provider->timeout = OSP_DEF_TIMEOUT;
658  provider->authpolicy = OSP_DEF_AUTHPOLICY;
659  provider->defprotocol = OSP_DEF_PROTOCOL;
660  provider->workmode = OSP_DEF_WORKMODE;
661  provider->srvtype = OSP_DEF_SRVTYPE;
662 
663  for (var = ast_variable_browse(cfg, name); var != NULL; var = var->next) {
664  if (!strcasecmp(var->name, "privatekey")) {
665  if (osp_security) {
666  if (var->value[0] == '/') {
667  ast_copy_string(provider->privatekey, var->value, sizeof(provider->privatekey));
668  } else {
669  snprintf(provider->privatekey, sizeof(provider->privatekey), "%s/%s", ast_config_AST_KEY_DIR, var->value);
670  }
671  ast_debug(1, "OSP: privatekey '%s'\n", provider->privatekey);
672  }
673  } else if (!strcasecmp(var->name, "localcert")) {
674  if (osp_security) {
675  if (var->value[0] == '/') {
676  ast_copy_string(provider->localcert, var->value, sizeof(provider->localcert));
677  } else {
678  snprintf(provider->localcert, sizeof(provider->localcert), "%s/%s", ast_config_AST_KEY_DIR, var->value);
679  }
680  ast_debug(1, "OSP: localcert '%s'\n", provider->localcert);
681  }
682  } else if (!strcasecmp(var->name, "cacert")) {
683  if (osp_security) {
684  if (provider->canum < OSP_MAX_CERTS) {
685  if (var->value[0] == '/') {
686  ast_copy_string(provider->cacerts[provider->canum], var->value, sizeof(provider->cacerts[provider->canum]));
687  } else {
688  snprintf(provider->cacerts[provider->canum], sizeof(provider->cacerts[provider->canum]), "%s/%s", ast_config_AST_KEY_DIR, var->value);
689  }
690  ast_debug(1, "OSP: cacerts[%d]: '%s'\n", provider->canum, provider->cacerts[provider->canum]);
691  provider->canum++;
692  } else {
693  ast_log(LOG_WARNING, "OSP: Too many CA Certificates at line %d\n", var->lineno);
694  }
695  }
696  } else if (!strcasecmp(var->name, "servicepoint")) {
697  if (provider->spnum < OSP_MAX_SPOINTS) {
698  ast_copy_string(provider->spoints[provider->spnum], var->value, sizeof(provider->spoints[provider->spnum]));
699  ast_debug(1, "OSP: servicepoint[%d]: '%s'\n", provider->spnum, provider->spoints[provider->spnum]);
700  provider->spnum++;
701  } else {
702  ast_log(LOG_WARNING, "OSP: Too many Service Points at line %d\n", var->lineno);
703  }
704  } else if (!strcasecmp(var->name, "maxconnect")) {
705  if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_MAXCONNECT) && (num <= OSP_MAX_MAXCONNECT)) {
706  provider->maxconnect = num;
707  ast_debug(1, "OSP: maxconnect '%d'\n", num);
708  } else {
709  ast_log(LOG_WARNING, "OSP: maxconnect should be an integer from %d to %d, not '%s' at line %d\n",
711  }
712  } else if (!strcasecmp(var->name, "retrydelay")) {
713  if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_RETRYDELAY) && (num <= OSP_MAX_RETRYDELAY)) {
714  provider->retrydelay = num;
715  ast_debug(1, "OSP: retrydelay '%d'\n", num);
716  } else {
717  ast_log(LOG_WARNING, "OSP: retrydelay should be an integer from %d to %d, not '%s' at line %d\n",
719  }
720  } else if (!strcasecmp(var->name, "retrylimit")) {
721  if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_RETRYLIMIT) && (num <= OSP_MAX_RETRYLIMIT)) {
722  provider->retrylimit = num;
723  ast_debug(1, "OSP: retrylimit '%d'\n", num);
724  } else {
725  ast_log(LOG_WARNING, "OSP: retrylimit should be an integer from %d to %d, not '%s' at line %d\n",
727  }
728  } else if (!strcasecmp(var->name, "timeout")) {
729  if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_TIMEOUT) && (num <= OSP_MAX_TIMEOUT)) {
730  provider->timeout = num;
731  ast_debug(1, "OSP: timeout '%d'\n", num);
732  } else {
733  ast_log(LOG_WARNING, "OSP: timeout should be an integer from %d to %d, not '%s' at line %d\n",
735  }
736  } else if (!strcasecmp(var->name, "source")) {
737  ast_copy_string(provider->source, var->value, sizeof(provider->source));
738  ast_debug(1, "OSP: source '%s'\n", provider->source);
739  } else if (!strcasecmp(var->name, "authpolicy")) {
740  if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_AUTH_NO) || (num == OSP_AUTH_YES) || (num == OSP_AUTH_EXC))) {
741  provider->authpolicy = num;
742  ast_debug(1, "OSP: authpolicy '%d'\n", num);
743  } else {
744  ast_log(LOG_WARNING, "OSP: authpolicy should be %d, %d or %d, not '%s' at line %d\n",
746  }
747  } else if (!strcasecmp(var->name, "defprotocol")) {
748  if (!strcasecmp(var->value, OSP_PROT_SIP)) {
749  provider->defprotocol = OSP_PROT_SIP;
750  ast_debug(1, "OSP: default protocol SIP\n");
751  } else if (!strcasecmp(var->value, OSP_PROT_H323)) {
752  provider->defprotocol = OSP_PROT_H323;
753  ast_debug(1, "OSP: default protocol H.323\n");
754  } else if (!strcasecmp(var->value, OSP_PROT_IAX)) {
755  provider->defprotocol = OSP_PROT_IAX;
756  ast_debug(1, "OSP: default protocol IAX\n");
757  } else if (!strcasecmp(var->value, OSP_PROT_SKYPE)) {
758  provider->defprotocol = OSP_PROT_SKYPE;
759  ast_debug(1, "OSP: default protocol Skype\n");
760  } else {
761  ast_log(LOG_WARNING, "OSP: default protocol should be %s, %s, %s or %s not '%s' at line %d\n",
763  }
764  } else if (!strcasecmp(var->name, "workmode")) {
765  if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_MODE_DIRECT) || (num == OSP_MODE_INDIRECT))) {
766  provider->workmode = num;
767  ast_debug(1, "OSP: workmode '%d'\n", num);
768  } else {
769  ast_log(LOG_WARNING, "OSP: workmode should be %d or %d, not '%s' at line %d\n",
771  }
772  } else if (!strcasecmp(var->name, "servicetype")) {
773  if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_SRV_VOICE) || (num == OSP_SRV_NPQUERY))) {
774  provider->srvtype = num;
775  ast_debug(1, "OSP: servicetype '%d'\n", num);
776  } else {
777  ast_log(LOG_WARNING, "OSP: servicetype should be %d or %d, not '%s' at line %d\n",
779  }
780  }
781  }
782 
783  if (provider->canum == 0) {
784  provider->canum = 1;
785  }
786 
787  for (i = 0; i < provider->spnum; i++) {
788  pspoints[i] = provider->spoints[i];
789  }
790 
791  if (osp_security) {
792  privatekey.PrivateKeyData = NULL;
793  privatekey.PrivateKeyLength = 0;
794 
795  localcert.CertData = NULL;
796  localcert.CertDataLength = 0;
797 
798  for (i = 0; i < provider->canum; i++) {
799  cacerts[i].CertData = NULL;
800  cacerts[i].CertDataLength = 0;
801  }
802 
803  if ((error = OSPPUtilLoadPEMPrivateKey((unsigned char*)provider->privatekey, &privatekey)) != OSPC_ERR_NO_ERROR) {
804  ast_log(LOG_WARNING, "OSP: Unable to load privatekey '%s', error '%d'\n", provider->privatekey, error);
805  } else if ((error = OSPPUtilLoadPEMCert((unsigned char*)provider->localcert, &localcert)) != OSPC_ERR_NO_ERROR) {
806  ast_log(LOG_WARNING, "OSP: Unable to load localcert '%s', error '%d'\n", provider->localcert, error);
807  } else {
808  for (i = 0; i < provider->canum; i++) {
809  if ((error = OSPPUtilLoadPEMCert((unsigned char*)provider->cacerts[i], &cacerts[i])) != OSPC_ERR_NO_ERROR) {
810  ast_log(LOG_WARNING, "OSP: Unable to load cacert '%s', error '%d'\n", provider->cacerts[i], error);
811  break;
812  } else {
813  pcacerts[i] = &cacerts[i];
814  }
815  }
816  }
817  } else {
818  privatekey.PrivateKeyData = privatekeydata;
819  privatekey.PrivateKeyLength = sizeof(privatekeydata);
820 
821  localcert.CertData = localcertdata;
822  localcert.CertDataLength = sizeof(localcertdata);
823 
824  cacerts[0].CertData = cacertdata;
825  cacerts[0].CertDataLength = sizeof(cacertdata);
826  pcacerts[0] = &cacerts[0];
827 
828  if ((error = OSPPBase64Decode(B64PKey, strlen(B64PKey), privatekey.PrivateKeyData, &privatekey.PrivateKeyLength)) != OSPC_ERR_NO_ERROR) {
829  ast_log(LOG_WARNING, "OSP: Unable to decode private key, error '%d'\n", error);
830  } else if ((error = OSPPBase64Decode(B64LCert, strlen(B64LCert), localcert.CertData, &localcert.CertDataLength)) != OSPC_ERR_NO_ERROR) {
831  ast_log(LOG_WARNING, "OSP: Unable to decode local cert, error '%d'\n", error);
832  } else if ((error = OSPPBase64Decode(B64CACert, strlen(B64CACert), cacerts[0].CertData, &cacerts[0].CertDataLength)) != OSPC_ERR_NO_ERROR) {
833  ast_log(LOG_WARNING, "OSP: Unable to decode cacert, error '%d'\n", error);
834  }
835  }
836 
837  if (error == OSPC_ERR_NO_ERROR) {
838  error = OSPPProviderNew(provider->spnum,
839  pspoints,
840  NULL,
842  &privatekey,
843  &localcert,
844  provider->canum,
845  pcacerts,
848  provider->maxconnect,
850  provider->retrydelay,
851  provider->retrylimit,
852  provider->timeout,
855  &provider->handle);
856  if (error != OSPC_ERR_NO_ERROR) {
857  ast_log(LOG_WARNING, "OSP: Unable to create provider '%s', error '%d'\n", name, error);
858  res = OSP_ERROR;
859  } else {
860  ast_debug(1, "OSP: provider '%s'\n", name);
862  provider->next = osp_providers;
863  osp_providers = provider;
865  res = OSP_OK;
866  }
867  }
868 
869  if (osp_security) {
870  for (i = 0; i < provider->canum; i++) {
871  if (cacerts[i].CertData) {
872  ast_free(cacerts[i].CertData);
873  }
874  }
875  if (localcert.CertData) {
876  ast_free(localcert.CertData);
877  }
878  if (privatekey.PrivateKeyData) {
879  ast_free(privatekey.PrivateKeyData);
880  }
881  }
882 
883  if (res != OSP_OK) {
884  ast_free(provider);
885  }
886 
887  return res;
888 }
889 
890 /*!
891  * \brief Get OSP provider by name
892  * \param name OSP provider context name
893  * \param provider OSP provider structure
894  * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
895  */
896 static int osp_get_provider(
897  const char* name,
898  struct osp_provider** provider)
899 {
900  int res = OSP_FAILED;
901  struct osp_provider* p;
902 
903  *provider = NULL;
904 
906  for (p = osp_providers; p != NULL; p = p->next) {
907  if (!strcasecmp(p->name, name)) {
908  *provider = p;
909  ast_debug(1, "OSP: find provider '%s'\n", name);
910  res = OSP_OK;
911  break;
912  }
913  }
915 
916  return res;
917 }
918 
919 /*!
920  * \brief Create OSP transaction handle
921  * \param name OSP provider context name
922  * \param trans OSP transaction handle, output
923  * \param source Source of provider, output
924  * \param srcsize Size of source buffer, in
925  * \return OSK_OK Success, OSK_FAILED Failed, OSP_ERROR Error
926  */
928  const char* name,
929  int* trans,
930  char* source,
931  unsigned int srcsize)
932 {
933  int res = OSP_FAILED;
934  struct osp_provider* provider;
935  int error;
936 
937  if ((trans == NULL) || (source == NULL) || (srcsize <= 0)) {
938  ast_log(LOG_ERROR, "Invalid parameters\n");
939  return OSP_ERROR;
940  }
941 
942  *trans = OSP_INVALID_HANDLE;
943  *source = '\0';
944 
946  for (provider = osp_providers; provider; provider = provider->next) {
947  if (!strcasecmp(provider->name, name)) {
948  error = OSPPTransactionNew(provider->handle, trans);
949  if (error == OSPC_ERR_NO_ERROR) {
950  ast_debug(1, "OSP: transaction '%d'\n", *trans);
951  ast_copy_string(source, provider->source, srcsize);
952  ast_debug(1, "OSP: source '%s'\n", source);
953  res = OSP_OK;
954  } else {
955  *trans = OSP_INVALID_HANDLE;
956  ast_debug(1, "OSP: Unable to create transaction handle, error '%d'\n", error);
957  *source = '\0';
958  res = OSP_ERROR;
959  }
960  break;
961  }
962  }
964 
965  return res;
966 }
967 
968 /*!
969  * \brief Convert "address:port" to "[x.x.x.x]:port" or "hostname:port" format
970  * \param src Source address string
971  * \param dest Destination address string
972  * \param destsize Size of dest buffer
973  */
974 static void osp_convert_inout(
975  const char* src,
976  char* dest,
977  unsigned int destsize)
978 {
979  struct in_addr inp;
980  char buffer[OSP_SIZE_NORSTR];
981  char* port;
982 
983  if ((dest != NULL) && (destsize > 0)) {
984  if (!ast_strlen_zero(src)) {
985  ast_copy_string(buffer, src, sizeof(buffer));
986 
987  if((port = strchr(buffer, ':')) != NULL) {
988  *port = '\0';
989  port++;
990  }
991 
992  if (inet_pton(AF_INET, buffer, &inp) == 1) {
993  if (port != NULL) {
994  snprintf(dest, destsize, "[%s]:%s", buffer, port);
995  } else {
996  snprintf(dest, destsize, "[%s]", buffer);
997  }
998  dest[destsize - 1] = '\0';
999  } else {
1000  ast_copy_string(dest, src, destsize);
1001  }
1002  } else {
1003  *dest = '\0';
1004  }
1005  }
1006 }
1007 
1008 /*!
1009  * \brief Convert "[x.x.x.x]:port" or "hostname:prot" to "address:port" format
1010  * \param src Source address string
1011  * \param dest Destination address string
1012  * \param destsize Size of dest buffer
1013  */
1014 static void osp_convert_outin(
1015  const char* src,
1016  char* dest,
1017  unsigned int destsize)
1018 {
1019  char buffer[OSP_SIZE_NORSTR];
1020  char* end;
1021  char* port;
1022 
1023  if ((dest != NULL) && (destsize > 0)) {
1024  if (!ast_strlen_zero(src)) {
1025  ast_copy_string(buffer, src, sizeof(buffer));
1026 
1027  if (buffer[0] == '[') {
1028  if((port = strchr(buffer + 1, ':')) != NULL) {
1029  *port = '\0';
1030  port++;
1031  }
1032 
1033  if ((end = strchr(buffer + 1, ']')) != NULL) {
1034  *end = '\0';
1035  }
1036 
1037  if (port != NULL) {
1038  snprintf(dest, destsize, "%s:%s", buffer + 1, port);
1039  dest[destsize - 1] = '\0';
1040  } else {
1041  ast_copy_string(dest, buffer + 1, destsize);
1042  }
1043  } else {
1044  ast_copy_string(dest, src, destsize);
1045  }
1046  } else {
1047  *dest = '\0';
1048  }
1049  }
1050 }
1051 
1052 /*!
1053  * \brief Validate OSP token of inbound call
1054  * \param trans OSP transaction handle
1055  * \param source Source of inbound call
1056  * \param destination Destination of inbound call
1057  * \param calling Calling number
1058  * \param called Called number
1059  * \param token OSP token, may be empty
1060  * \param timelimit Call duration limit, output
1061  * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
1062  */
1064  int trans,
1065  const char* source,
1066  const char* destination,
1067  const char* calling,
1068  const char* called,
1069  const char* token,
1070  unsigned int* timelimit)
1071 {
1072  int res;
1073  int tokenlen;
1074  unsigned char tokenstr[OSP_SIZE_TOKSTR];
1075  char src[OSP_SIZE_NORSTR];
1076  char dest[OSP_SIZE_NORSTR];
1077  unsigned int authorised;
1078  unsigned int dummy = 0;
1079  int error;
1080 
1081  if (timelimit == NULL) {
1082  ast_log(LOG_ERROR, "Invalid parameters\n");
1083  return OSP_ERROR;
1084  }
1085 
1086  tokenlen = ast_base64decode(tokenstr, token, strlen(token));
1087  osp_convert_inout(source, src, sizeof(src));
1088  osp_convert_inout(destination, dest, sizeof(dest));
1089  error = OSPPTransactionValidateAuthorisation(trans,
1090  src,
1091  dest,
1092  NULL,
1093  NULL,
1094  calling ? calling : "",
1095  OSPC_NFORMAT_E164,
1096  called,
1097  OSPC_NFORMAT_E164,
1098  0,
1099  NULL,
1100  tokenlen,
1101  (char*)tokenstr,
1102  &authorised,
1103  timelimit,
1104  &dummy,
1105  NULL,
1106  osp_tokenformat);
1107  if (error != OSPC_ERR_NO_ERROR) {
1108  ast_log(LOG_WARNING, "OSP: Unable to validate inbound token, error '%d'\n", error);
1109  *timelimit = 0;
1110  res = OSP_ERROR;
1111  } else if (authorised) {
1112  ast_debug(1, "OSP: Authorised\n");
1113  res = OSP_OK;
1114  } else {
1115  ast_debug(1, "OSP: Unauthorised\n");
1116  res = OSP_FAILED;
1117  }
1118 
1119  return res;
1120 }
1121 
1122 /*!
1123  * \brief Choose min duration limit
1124  * \param in Inbound duration limit
1125  * \param out Outbound duration limit
1126  * \return min duration limit
1127  */
1128 static unsigned int osp_choose_timelimit(
1129  unsigned int in,
1130  unsigned int out)
1131 {
1132  if (in == OSP_DEF_TIMELIMIT) {
1133  return out;
1134  } else if (out == OSP_DEF_TIMELIMIT) {
1135  return in;
1136  } else {
1137  return in < out ? in : out;
1138  }
1139 }
1140 
1141 /*!
1142  * \brief Choose min duration limit
1143  * \param provider OSP provider
1144  * \param calling Calling number
1145  * \param called Called number
1146  * \param destination Destination IP in '[x.x.x.x]' format
1147  * \param tokenlen OSP token length
1148  * \param token OSP token
1149  * \param reason Failure reason, output
1150  * \param results OSP lookup results, in/output
1151  * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
1152  */
1154  struct osp_provider* provider,
1155  const char* calling,
1156  const char* called,
1157  const char* destination,
1158  unsigned int tokenlen,
1159  const char* token,
1160  OSPEFAILREASON* reason,
1161  struct osp_results* results)
1162 {
1163  int res;
1164  OSPE_DEST_OSPENABLED enabled;
1165  OSPE_DEST_PROTOCOL protocol;
1166  char dest[OSP_SIZE_NORSTR];
1167  OSPE_OPERATOR_NAME type;
1168  int error;
1169 
1170  if ((provider == NULL) || (reason == NULL) || (results == NULL)) {
1171  ast_log(LOG_ERROR, "Invalid parameters\n");
1172  return OSP_ERROR;
1173  }
1174 
1175  if ((error = OSPPTransactionIsDestOSPEnabled(results->outhandle, &enabled)) != OSPC_ERR_NO_ERROR) {
1176  ast_debug(1, "OSP: Unable to get destination OSP version, error '%d'\n", error);
1177  *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
1178  return OSP_ERROR;
1179  }
1180 
1181  if (enabled == OSPC_DOSP_FALSE) {
1182  results->token[0] = '\0';
1183  } else {
1184  ast_base64encode(results->token, (const unsigned char*)token, tokenlen, sizeof(results->token) - 1);
1185  }
1186 
1187  if ((error = OSPPTransactionGetDestinationNetworkId(results->outhandle, sizeof(results->networkid), results->networkid)) != OSPC_ERR_NO_ERROR) {
1188  ast_debug(1, "OSP: Unable to get destination network ID, error '%d'\n", error);
1189  results->networkid[0] = '\0';
1190  }
1191 
1192  error = OSPPTransactionGetNumberPortabilityParameters(results->outhandle,
1193  sizeof(results->nprn),
1194  results->nprn,
1195  sizeof(results->npcic),
1196  results->npcic,
1197  &results->npdi);
1198  if (error != OSPC_ERR_NO_ERROR) {
1199  ast_debug(1, "OSP: Unable to get number portability parameters, error '%d'\n", error);
1200  results->nprn[0] = '\0';
1201  results->npcic[0] = '\0';
1202  results->npdi = 0;
1203  }
1204 
1205  for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1206  error = OSPPTransactionGetOperatorName(results->outhandle, type, sizeof(results->opname[type]), results->opname[type]);
1207  if (error != OSPC_ERR_NO_ERROR) {
1208  ast_debug(1, "OSP: Unable to get operator name of type '%d', error '%d'\n", type, error);
1209  results->opname[type][0] = '\0';
1210  }
1211  }
1212 
1213  if ((error = OSPPTransactionGetDestProtocol(results->outhandle, &protocol)) != OSPC_ERR_NO_ERROR) {
1214  ast_debug(1, "OSP: Unable to get destination protocol, error '%d'\n", error);
1215  *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
1216  results->token[0] = '\0';
1217  results->networkid[0] = '\0';
1218  results->nprn[0] = '\0';
1219  results->npcic[0] = '\0';
1220  results->npdi = 0;
1221  for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1222  results->opname[type][0] = '\0';
1223  }
1224  return OSP_ERROR;
1225  }
1226 
1227  res = OSP_OK;
1228  osp_convert_outin(destination, dest, sizeof(dest));
1229  switch(protocol) {
1230  case OSPC_DPROT_SIP:
1231  ast_debug(1, "OSP: protocol SIP\n");
1232  ast_copy_string(results->tech, OSP_TECH_SIP, sizeof(results->tech));
1233  ast_copy_string(results->dest, dest, sizeof(results->dest));
1234  ast_copy_string(results->calling, calling, sizeof(results->calling));
1235  ast_copy_string(results->called, called, sizeof(results->called));
1236  break;
1237  case OSPC_DPROT_Q931:
1238  ast_debug(1, "OSP: protocol Q.931\n");
1239  ast_copy_string(results->tech, OSP_TECH_H323, sizeof(results->tech));
1240  ast_copy_string(results->dest, dest, sizeof(results->dest));
1241  ast_copy_string(results->calling, calling, sizeof(results->calling));
1242  ast_copy_string(results->called, called, sizeof(results->called));
1243  break;
1244  case OSPC_DPROT_IAX:
1245  ast_debug(1, "OSP: protocol IAX\n");
1246  ast_copy_string(results->tech, OSP_TECH_IAX, sizeof(results->tech));
1247  ast_copy_string(results->dest, dest, sizeof(results->dest));
1248  ast_copy_string(results->calling, calling, sizeof(results->calling));
1249  ast_copy_string(results->called, called, sizeof(results->called));
1250  break;
1251  case OSPC_DPROT_SKYPE:
1252  ast_debug(1, "OSP: protocol Skype\n");
1253  ast_copy_string(results->tech, OSP_TECH_SKYPE, sizeof(results->tech));
1254  ast_copy_string(results->dest, dest, sizeof(results->dest));
1255  ast_copy_string(results->calling, calling, sizeof(results->calling));
1256  ast_copy_string(results->called, called, sizeof(results->called));
1257  break;
1258  case OSPC_DPROT_UNDEFINED:
1259  case OSPC_DPROT_UNKNOWN:
1260  ast_debug(1, "OSP: unknown/undefined protocol '%d'\n", protocol);
1261  ast_debug(1, "OSP: use default protocol '%s'\n", provider->defprotocol);
1262  ast_copy_string(results->tech, provider->defprotocol, sizeof(results->tech));
1263  ast_copy_string(results->dest, dest, sizeof(results->dest));
1264  ast_copy_string(results->calling, calling, sizeof(results->calling));
1265  ast_copy_string(results->called, called, sizeof(results->called));
1266  break;
1267  case OSPC_DPROT_LRQ:
1268  case OSPC_DPROT_T37:
1269  case OSPC_DPROT_T38:
1270  case OSPC_DPROT_SMPP:
1271  case OSPC_DPROT_XMPP:
1272  default:
1273  ast_log(LOG_WARNING, "OSP: unsupported protocol '%d'\n", protocol);
1274  *reason = OSPC_FAIL_PROTOCOL_ERROR;
1275  results->token[0] = '\0';
1276  results->networkid[0] = '\0';
1277  results->nprn[0] = '\0';
1278  results->npcic[0] = '\0';
1279  results->npdi = 0;
1280  for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1281  results->opname[type][0] = '\0';
1282  }
1283  res = OSP_FAILED;
1284  break;
1285  }
1286 
1287  return res;
1288 }
1289 
1290 /*!
1291  * \brief Convert Asterisk status to TC code
1292  * \param cause Asterisk hangup cause
1293  * \return OSP TC code
1294  */
1295 static OSPEFAILREASON asterisk2osp(
1296  int cause)
1297 {
1298  return (OSPEFAILREASON)cause;
1299 }
1300 
1301 /*!
1302  * \brief OSP Authentication function
1303  * \param name OSP provider context name
1304  * \param trans OSP transaction handle, output
1305  * \param source Source of inbound call
1306  * \param calling Calling number
1307  * \param called Called number
1308  * \param token OSP token, may be empty
1309  * \param timelimit Call duration limit, output
1310  * \return OSP_OK Authenricated, OSP_FAILED Unauthenticated, OSP_ERROR Error
1311  */
1312 static int osp_auth(
1313  const char* name,
1314  int* trans,
1315  const char* source,
1316  const char* calling,
1317  const char* called,
1318  const char* token,
1319  unsigned int* timelimit)
1320 {
1321  int res;
1322  struct osp_provider* provider = NULL;
1323  char dest[OSP_SIZE_NORSTR];
1324 
1325  if ((trans == NULL) || (timelimit == NULL)) {
1326  ast_log(LOG_ERROR, "Invalid parameters\n");
1327  return OSP_ERROR;
1328  }
1329 
1330  *trans = OSP_INVALID_HANDLE;
1331  *timelimit = OSP_DEF_TIMELIMIT;
1332 
1333  if ((res = osp_get_provider(name, &provider)) <= 0) {
1334  ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
1335  return res;
1336  }
1337 
1338  switch (provider->authpolicy) {
1339  case OSP_AUTH_NO:
1340  res = OSP_OK;
1341  break;
1342  case OSP_AUTH_EXC:
1343  if (ast_strlen_zero(token)) {
1344  res = OSP_FAILED;
1345  } else if ((res = osp_create_transaction(name, trans, dest, sizeof(dest))) <= 0) {
1346  ast_debug(1, "OSP: Unable to generate transaction handle\n");
1347  *trans = OSP_INVALID_HANDLE;
1348  res = OSP_FAILED;
1349  } else if((res = osp_validate_token(*trans, source, dest, calling, called, token, timelimit)) <= 0) {
1350  OSPPTransactionRecordFailure(*trans, OSPC_FAIL_CALL_REJECTED);
1351  }
1352  break;
1353  case OSP_AUTH_YES:
1354  default:
1355  if (ast_strlen_zero(token)) {
1356  res = OSP_OK;
1357  } else if ((res = osp_create_transaction(name, trans, dest, sizeof(dest))) <= 0) {
1358  ast_debug(1, "OSP: Unable to generate transaction handle\n");
1359  *trans = OSP_INVALID_HANDLE;
1360  res = OSP_FAILED;
1361  } else if((res = osp_validate_token(*trans, source, dest, calling, called, token, timelimit)) <= 0) {
1362  OSPPTransactionRecordFailure(*trans, OSPC_FAIL_CALL_REJECTED);
1363  }
1364  break;
1365  }
1366 
1367  return res;
1368 }
1369 
1370 /*!
1371  * \brief Create a UUID
1372  * \param uuid UUID buffer
1373  * \param bufsize UUID buffer size
1374  * \return OSK_OK Created, OSP_ERROR Error
1375  */
1376 static int osp_create_uuid(
1377  unsigned char* uuid,
1378  unsigned int* bufsize)
1379 {
1380  int i, res;
1381  long int tmp[OSP_SIZE_UUID / sizeof(long int)];
1382 
1383  if ((uuid != NULL) && (*bufsize >= OSP_SIZE_UUID)) {
1384  for (i = 0; i < OSP_SIZE_UUID / sizeof(long int); i++) {
1385  tmp[i] = ast_random();
1386  }
1387  memcpy(uuid, tmp, OSP_SIZE_UUID);
1388  *bufsize = OSP_SIZE_UUID;
1389  res = OSP_OK;
1390  } else {
1391  ast_log(LOG_ERROR, "Invalid parameters\n");
1392  res = OSP_ERROR;
1393  }
1394 
1395  return res;
1396 }
1397 
1398 /*!
1399  * \brief UUID to string
1400  * \param uuid UUID
1401  * \param buffer String buffer
1402  * \param bufsize String buffer size
1403  * \return OSP_OK Successed, OSP_ERROR Error
1404  */
1405 static int osp_uuid2str(
1406  unsigned char* uuid,
1407  char* buffer,
1408  unsigned int bufsize)
1409 {
1410  int res;
1411 
1412  if ((uuid != NULL) && (bufsize > OSP_SIZE_UUIDSTR)) {
1413  snprintf(buffer, bufsize, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1414  uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
1415  uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
1416  res = OSP_OK;
1417  } else {
1418  ast_log(LOG_ERROR, "Invalid parameters\n");
1419  res = OSP_ERROR;
1420  }
1421 
1422  return res;
1423 }
1424 
1425 /*!
1426  * \brief Create a call ID according to the type
1427  * \param type Call ID type
1428  * \param callid Call ID buffer
1429  * \return OSK_OK Created, OSP_FAILED Not create, OSP_ERROR Error
1430  */
1432  unsigned int type,
1433  struct osp_callid* callid)
1434 {
1435  int res;
1436 
1437  if (callid == NULL) {
1438  ast_log(LOG_ERROR, "Invalid parameters\n");
1439  res = OSP_ERROR;
1440  }
1441 
1442  callid->len = sizeof(callid->buf);
1443  switch (type) {
1444  case OSP_CALLID_H323:
1445  res = osp_create_uuid(callid->buf, &callid->len);
1446  break;
1447  case OSP_CALLID_SIP:
1448  case OSP_CALLID_IAX:
1449  res = OSP_FAILED;
1450  default:
1451  res = OSP_ERROR;
1452  break;
1453  }
1454 
1455  if ((res != OSP_OK) && (callid->len != 0)) {
1456  callid->buf[0] = '\0';
1457  callid->len = 0;
1458  }
1459 
1460  return res;
1461 }
1462 
1463 /*!
1464  * \brief OSP Lookup function
1465  * \param name OSP provider context name
1466  * \param callidtypes Call ID types
1467  * \param actualsrc Actual source device in indirect mode
1468  * \param srcdev Source device of outbound call
1469  * \param calling Calling number
1470  * \param called Called number
1471  * \param snetid Source network ID
1472  * \param np NP parameters
1473  * \param div SIP Diversion header parameters
1474  * \param cinfo Custom info
1475  * \param results Lookup results
1476  * \return OSP_OK Found , OSP_FAILED No route, OSP_ERROR Error
1477  */
1478 static int osp_lookup(
1479  const char* name,
1480  unsigned int callidtypes,
1481  const char* actualsrc,
1482  const char* srcdev,
1483  const char* calling,
1484  const char* called,
1485  const char* snetid,
1486  struct osp_npdata* np,
1487  struct osp_diversion* div,
1488  const char* cinfo[],
1489  struct osp_results* results)
1490 {
1491  int res;
1492  struct osp_provider* provider = NULL;
1493  char source[OSP_SIZE_NORSTR];
1494  char callingnum[OSP_SIZE_NORSTR];
1495  char callednum[OSP_SIZE_NORSTR];
1496  char destination[OSP_SIZE_NORSTR];
1497  char* tmp;
1498  unsigned int tokenlen;
1499  char token[OSP_SIZE_TOKSTR];
1500  char src[OSP_SIZE_NORSTR];
1501  char dev[OSP_SIZE_NORSTR];
1502  char host[OSP_SIZE_NORSTR];
1503  unsigned int i, type;
1504  struct osp_callid callid;
1505  unsigned int callidnum;
1506  OSPT_CALL_ID* callids[OSP_CALLID_MAXNUM];
1507  char dest[OSP_SIZE_NORSTR];
1508  const char* preferred[2] = { NULL };
1509  unsigned int dummy = 0;
1510  OSPEFAILREASON reason;
1511  int error;
1512 
1513  if (results == NULL) {
1514  ast_log(LOG_ERROR, "Invalid parameters\n");
1515  res = OSP_ERROR;
1516  }
1517 
1518  osp_convert_inout(results->dest, dest, sizeof(dest));
1519 
1520  results->outhandle = OSP_INVALID_HANDLE;
1521  results->tech[0] = '\0';
1522  results->calling[0] = '\0';
1523  results->called[0] = '\0';
1524  results->token[0] = '\0';
1525  results->networkid[0] = '\0';
1526  results->nprn[0] = '\0';
1527  results->npcic[0] = '\0';
1528  results->npdi = 0;
1529  for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1530  results->opname[type][0] = '\0';
1531  }
1532  results->numdests = 0;
1533  results->outtimelimit = OSP_DEF_TIMELIMIT;
1534 
1535  if ((res = osp_get_provider(name, &provider)) <= 0) {
1536  ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
1537  return res;
1538  }
1539 
1540  if ((res = osp_create_transaction(name, &results->outhandle, source, sizeof(source))) <= 0) {
1541  ast_debug(1, "OSP: Unable to generate transaction handle\n");
1542  results->outhandle = OSP_INVALID_HANDLE;
1543  if (results->inhandle != OSP_INVALID_HANDLE) {
1544  OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1545  }
1546  return OSP_ERROR;
1547  }
1548 
1549  if (!ast_strlen_zero(snetid)) {
1550  OSPPTransactionSetNetworkIds(results->outhandle, snetid, "");
1551  }
1552 
1553  OSPPTransactionSetNumberPortability(results->outhandle, np->rn, np->cic, np->npdi);
1554 
1555  for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1556  OSPPTransactionSetOperatorName(results->outhandle, type, np->opname[type]);
1557  }
1558 
1559  osp_convert_inout(div->host, host, sizeof(host));
1560  OSPPTransactionSetDiversion(results->outhandle, div->user, host);
1561 
1562  if (cinfo != NULL) {
1563  for (i = 0; i < OSP_MAX_CUSTOMINFO; i++) {
1564  if (!ast_strlen_zero(cinfo[i])) {
1565  OSPPTransactionSetCustomInfo(results->outhandle, i, cinfo[i]);
1566  }
1567  }
1568  }
1569 
1570  ast_copy_string(callednum, called, sizeof(callednum));
1571  if((tmp = strchr(callednum, ';')) != NULL) {
1572  *tmp = '\0';
1573  }
1574 
1575  callidnum = 0;
1576  callids[0] = NULL;
1577  for (i = 0; i < OSP_CALLID_MAXNUM; i++) {
1578  type = 1 << i;
1579  if (callidtypes & type) {
1580  error = osp_create_callid(type, &callid);
1581  if (error == 1) {
1582  callids[callidnum] = OSPPCallIdNew(callid.len, callid.buf);
1583  callidnum++;
1584  }
1585  }
1586  }
1587 
1588  if (provider->workmode == OSP_MODE_INDIRECT) {
1589  osp_convert_inout(srcdev, src, sizeof(src));
1590  if (ast_strlen_zero(actualsrc)) {
1591  osp_convert_inout(srcdev, dev, sizeof(dev));
1592  } else {
1593  osp_convert_inout(actualsrc, dev, sizeof(dev));
1594  }
1595  } else {
1596  osp_convert_inout(source, src, sizeof(src));
1597  osp_convert_inout(srcdev, dev, sizeof(dev));
1598  }
1599 
1600  if (provider->srvtype == OSP_SRV_NPQUERY) {
1601  OSPPTransactionSetServiceType(results->outhandle, OSPC_SERVICE_NPQUERY);
1602  if (!ast_strlen_zero(dest)) {
1603  preferred[0] = dest;
1604  }
1605  results->numdests = 1;
1606  } else {
1607  OSPPTransactionSetServiceType(results->outhandle, OSPC_SERVICE_VOICE);
1608  results->numdests = OSP_DEF_MAXDESTS;
1609  }
1610  error = OSPPTransactionRequestAuthorisation(results->outhandle,
1611  src,
1612  dev,
1613  calling ? calling : "",
1614  OSPC_NFORMAT_E164,
1615  callednum,
1616  OSPC_NFORMAT_E164,
1617  NULL,
1618  callidnum,
1619  callids,
1620  preferred,
1621  &results->numdests,
1622  &dummy,
1623  NULL);
1624 
1625  for (i = 0; i < callidnum; i++) {
1626  OSPPCallIdDelete(&callids[i]);
1627  }
1628 
1629  if (error != OSPC_ERR_NO_ERROR) {
1630  ast_log(LOG_WARNING, "OSP: Unable to request authorization, error '%d'\n", error);
1631  results->numdests = 0;
1632  if (results->inhandle != OSP_INVALID_HANDLE) {
1633  OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1634  }
1635  return OSP_ERROR;
1636  }
1637 
1638  if (!results->numdests) {
1639  ast_debug(1, "OSP: No more destination\n");
1640  if (results->inhandle != OSP_INVALID_HANDLE) {
1641  OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1642  }
1643  return OSP_FAILED;
1644  }
1645 
1646  results->outcallid.len = sizeof(results->outcallid.buf);
1647  tokenlen = sizeof(token);
1648  error = OSPPTransactionGetFirstDestination(results->outhandle,
1649  0,
1650  NULL,
1651  NULL,
1652  &results->outtimelimit,
1653  &results->outcallid.len,
1654  results->outcallid.buf,
1655  sizeof(callednum),
1656  callednum,
1657  sizeof(callingnum),
1658  callingnum,
1659  sizeof(destination),
1660  destination,
1661  0,
1662  NULL,
1663  &tokenlen,
1664  token);
1665  if (error != OSPC_ERR_NO_ERROR) {
1666  ast_debug(1, "OSP: Unable to get first route, error '%d'\n", error);
1667  results->numdests = 0;
1668  results->outtimelimit = OSP_DEF_TIMELIMIT;
1669  if (results->inhandle != OSP_INVALID_HANDLE) {
1670  OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1671  }
1672  return OSP_ERROR;
1673  }
1674 
1675  results->numdests--;
1676  results->outtimelimit = osp_choose_timelimit(results->intimelimit, results->outtimelimit);
1677  ast_debug(1, "OSP: outtimelimit '%d'\n", results->outtimelimit);
1678  ast_debug(1, "OSP: calling '%s'\n", callingnum);
1679  ast_debug(1, "OSP: called '%s'\n", callednum);
1680  ast_debug(1, "OSP: destination '%s'\n", destination);
1681  ast_debug(1, "OSP: token size '%d'\n", tokenlen);
1682 
1683  if ((res = osp_check_destination(provider, callingnum, callednum, destination, tokenlen, token, &reason, results)) > 0) {
1684  return OSP_OK;
1685  }
1686 
1687  if (!results->numdests) {
1688  ast_debug(1, "OSP: No more destination\n");
1689  results->outtimelimit = OSP_DEF_TIMELIMIT;
1690  OSPPTransactionRecordFailure(results->outhandle, reason);
1691  if (results->inhandle != OSP_INVALID_HANDLE) {
1692  OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1693  }
1694  return OSP_FAILED;
1695  }
1696 
1697  while(results->numdests) {
1698  results->outcallid.len = sizeof(results->outcallid.buf);
1699  tokenlen = sizeof(token);
1700  error = OSPPTransactionGetNextDestination(results->outhandle,
1701  reason,
1702  0,
1703  NULL,
1704  NULL,
1705  &results->outtimelimit,
1706  &results->outcallid.len,
1707  results->outcallid.buf,
1708  sizeof(callednum),
1709  callednum,
1710  sizeof(callingnum),
1711  callingnum,
1712  sizeof(destination),
1713  destination,
1714  0,
1715  NULL,
1716  &tokenlen,
1717  token);
1718  if (error == OSPC_ERR_NO_ERROR) {
1719  results->numdests--;
1720  results->outtimelimit = osp_choose_timelimit(results->intimelimit, results->outtimelimit);
1721  ast_debug(1, "OSP: outtimelimit '%d'\n", results->outtimelimit);
1722  ast_debug(1, "OSP: calling '%s'\n", callingnum);
1723  ast_debug(1, "OSP: called '%s'\n", callednum);
1724  ast_debug(1, "OSP: destination '%s'\n", destination);
1725  ast_debug(1, "OSP: token size '%d'\n", tokenlen);
1726 
1727  if ((res = osp_check_destination(provider, callingnum, callednum, destination, tokenlen, token, &reason, results)) > 0) {
1728  break;
1729  } else if (!results->numdests) {
1730  ast_debug(1, "OSP: No more destination\n");
1731  OSPPTransactionRecordFailure(results->outhandle, reason);
1732  if (results->inhandle != OSP_INVALID_HANDLE) {
1733  OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1734  }
1735  res = OSP_FAILED;
1736  break;
1737  }
1738  } else {
1739  ast_debug(1, "OSP: Unable to get route, error '%d'\n", error);
1740  results->numdests = 0;
1741  results->outtimelimit = OSP_DEF_TIMELIMIT;
1742  if (results->inhandle != OSP_INVALID_HANDLE) {
1743  OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1744  }
1745  res = OSP_ERROR;
1746  break;
1747  }
1748  }
1749 
1750  return res;
1751 }
1752 
1753 /*!
1754  * \brief OSP Lookup Next function
1755  * \param name OSP provider name
1756  * \param cause Asterisk hangup cuase
1757  * \param results Lookup results, in/output
1758  * \return OSP_OK Found , OSP_FAILED No route, OSP_ERROR Error
1759  */
1760 static int osp_next(
1761  const char* name,
1762  int cause,
1763  struct osp_results* results)
1764 {
1765  int res;
1766  struct osp_provider* provider = NULL;
1767  char calling[OSP_SIZE_NORSTR];
1768  char called[OSP_SIZE_NORSTR];
1769  char dest[OSP_SIZE_NORSTR];
1770  unsigned int tokenlen;
1771  char token[OSP_SIZE_TOKSTR];
1772  OSPEFAILREASON reason;
1773  OSPE_OPERATOR_NAME type;
1774  int error;
1775 
1776  if (results == NULL) {
1777  ast_log(LOG_ERROR, "Invalid parameters\n");
1778  res = OSP_ERROR;
1779  }
1780 
1781  results->tech[0] = '\0';
1782  results->dest[0] = '\0';
1783  results->calling[0] = '\0';
1784  results->called[0] = '\0';
1785  results->token[0] = '\0';
1786  results->networkid[0] = '\0';
1787  results->nprn[0] = '\0';
1788  results->npcic[0] = '\0';
1789  results->npdi = 0;
1790  for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1791  results->opname[type][0] = '\0';
1792  }
1793  results->outtimelimit = OSP_DEF_TIMELIMIT;
1794 
1795  if ((res = osp_get_provider(name, &provider)) <= 0) {
1796  ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
1797  return res;
1798  }
1799 
1800  if (results->outhandle == OSP_INVALID_HANDLE) {
1801  ast_debug(1, "OSP: Transaction handle undefined\n");
1802  results->numdests = 0;
1803  if (results->inhandle != OSP_INVALID_HANDLE) {
1804  OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1805  }
1806  return OSP_ERROR;
1807  }
1808 
1809  reason = asterisk2osp(cause);
1810 
1811  if (!results->numdests) {
1812  ast_debug(1, "OSP: No more destination\n");
1813  OSPPTransactionRecordFailure(results->outhandle, reason);
1814  if (results->inhandle != OSP_INVALID_HANDLE) {
1815  OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1816  }
1817  return OSP_FAILED;
1818  }
1819 
1820  while(results->numdests) {
1821  results->outcallid.len = sizeof(results->outcallid.buf);
1822  tokenlen = sizeof(token);
1823  error = OSPPTransactionGetNextDestination(
1824  results->outhandle,
1825  reason,
1826  0,
1827  NULL,
1828  NULL,
1829  &results->outtimelimit,
1830  &results->outcallid.len,
1831  results->outcallid.buf,
1832  sizeof(called),
1833  called,
1834  sizeof(calling),
1835  calling,
1836  sizeof(dest),
1837  dest,
1838  0,
1839  NULL,
1840  &tokenlen,
1841  token);
1842  if (error == OSPC_ERR_NO_ERROR) {
1843  results->numdests--;
1844  results->outtimelimit = osp_choose_timelimit(results->intimelimit, results->outtimelimit);
1845  ast_debug(1, "OSP: outtimelimit '%d'\n", results->outtimelimit);
1846  ast_debug(1, "OSP: calling '%s'\n", calling);
1847  ast_debug(1, "OSP: called '%s'\n", called);
1848  ast_debug(1, "OSP: destination '%s'\n", dest);
1849  ast_debug(1, "OSP: token size '%d'\n", tokenlen);
1850 
1851  if ((res = osp_check_destination(provider, calling, called, dest, tokenlen, token, &reason, results)) > 0) {
1852  res = OSP_OK;
1853  break;
1854  } else if (!results->numdests) {
1855  ast_debug(1, "OSP: No more destination\n");
1856  OSPPTransactionRecordFailure(results->outhandle, reason);
1857  if (results->inhandle != OSP_INVALID_HANDLE) {
1858  OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1859  }
1860  res = OSP_FAILED;
1861  break;
1862  }
1863  } else {
1864  ast_debug(1, "OSP: Unable to get route, error '%d'\n", error);
1865  results->token[0] = '\0';
1866  results->numdests = 0;
1867  results->outtimelimit = OSP_DEF_TIMELIMIT;
1868  if (results->inhandle != OSP_INVALID_HANDLE) {
1869  OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1870  }
1871  res = OSP_ERROR;
1872  break;
1873  }
1874  }
1875 
1876  return res;
1877 }
1878 
1879 /*!
1880  * \brief Get integer from variable string
1881  * \param vstr Variable string
1882  * \return OSP_DEF_INTSTATS Error
1883  */
1884 static int osp_get_varint(
1885  const char* vstr)
1886 {
1887  char* tmp;
1888  int value = OSP_DEF_INTSTATS;
1889 
1890  if (!ast_strlen_zero(vstr)) {
1891  if ((tmp = strchr(vstr, '=')) != NULL) {
1892  tmp++;
1893  if (sscanf(tmp, "%30d", &value) != 1) {
1894  value = OSP_DEF_INTSTATS;
1895  }
1896  }
1897  }
1898 
1899  return value;
1900 }
1901 
1902 /*!
1903  * \brief Get float from variable string
1904  * \param vstr Variable string
1905  * \return OSP_DEF_FLOATSTATS Error
1906  */
1907 static float osp_get_varfloat(
1908  const char* vstr)
1909 {
1910  char* tmp;
1911  float value = OSP_DEF_FLOATSTATS;
1912 
1913  if (!ast_strlen_zero(vstr)) {
1914  if ((tmp = strchr(vstr, '=')) != NULL) {
1915  tmp++;
1916  if (sscanf(tmp, "%30f", &value) != 1) {
1917  value = OSP_DEF_FLOATSTATS;
1918  }
1919  }
1920  }
1921 
1922  return value;
1923 }
1924 
1925 /*!
1926  * \brief Report QoS
1927  * \param trans OSP in/outbound transaction handle
1928  * \param leg Inbound/outbound
1929  * \param qos QoS string
1930  * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
1931  */
1932 static int osp_report_qos(
1933  int trans,
1934  enum osp_callleg leg,
1935  const char* qos)
1936 {
1937  int res = OSP_FAILED;
1938  enum osp_direction dir;
1939  char buffer[OSP_SIZE_NORSTR];
1940  char* tmp;
1941  char* item;
1942  int totalpackets[OSP_DIR_NUMBER];
1943  struct osp_metrics lost[OSP_DIR_NUMBER];
1944  struct osp_metrics jitter[OSP_DIR_NUMBER];
1945  struct osp_metrics rtt;
1946  int value;
1947 
1948  if (!ast_strlen_zero(qos)) {
1949  for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
1950  totalpackets[dir] = OSP_DEF_INTSTATS;
1951  }
1952 
1953  for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
1954  lost[dir].value = OSP_DEF_INTSTATS;
1955  lost[dir].min = OSP_DEF_FLOATSTATS;
1956  lost[dir].max = OSP_DEF_FLOATSTATS;
1957  lost[dir].avg = OSP_DEF_FLOATSTATS;
1958  lost[dir].sdev = OSP_DEF_FLOATSTATS;
1959  }
1960 
1961  for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
1962  jitter[dir].value = OSP_DEF_INTSTATS;
1963  jitter[dir].min = OSP_DEF_FLOATSTATS;
1964  jitter[dir].max = OSP_DEF_FLOATSTATS;
1965  jitter[dir].avg = OSP_DEF_FLOATSTATS;
1966  jitter[dir].sdev = OSP_DEF_FLOATSTATS;
1967  }
1968 
1969  rtt.value = OSP_DEF_INTSTATS;
1970  rtt.min = OSP_DEF_FLOATSTATS;
1971  rtt.max = OSP_DEF_FLOATSTATS;
1972  rtt.avg = OSP_DEF_FLOATSTATS;
1973  rtt.sdev = OSP_DEF_FLOATSTATS;
1974 
1975  ast_copy_string(buffer, qos, sizeof(buffer));
1976  for (item = strtok_r(buffer, ";", &tmp); item; item = strtok_r(NULL, ";", &tmp)) {
1977  if (!strncasecmp(item, "rxcount", strlen("rxcount"))) {
1978  totalpackets[OSP_DIR_RX] = osp_get_varint(item);
1979  } else if (!strncasecmp(item, "txcount", strlen("txcount"))) {
1980  totalpackets[OSP_DIR_TX] = osp_get_varint(item);
1981  } else if (!strncasecmp(item, "lp", strlen("lp"))) {
1982  lost[OSP_DIR_RX].value = osp_get_varint(item);
1983  } else if (!strncasecmp(item, "minrxlost", strlen("minrxlost"))) {
1984  lost[OSP_DIR_RX].min = osp_get_varfloat(item);
1985  } else if (!strncasecmp(item, "maxrxlost", strlen("maxrxlost"))) {
1986  lost[OSP_DIR_RX].max = osp_get_varfloat(item);
1987  } else if (!strncasecmp(item, "avgrxlost", strlen("avgrxlost"))) {
1988  lost[OSP_DIR_RX].avg = osp_get_varfloat(item);
1989  } else if (!strncasecmp(item, "stdevrxlost", strlen("stdevrxlost"))) {
1990  lost[OSP_DIR_RX].sdev = osp_get_varfloat(item);
1991  } else if (!strncasecmp(item, "rlp", strlen("rlp"))) {
1992  lost[OSP_DIR_TX].value = osp_get_varint(item);
1993  } else if (!strncasecmp(item, "reported_minlost", strlen("reported_minlost"))) {
1994  lost[OSP_DIR_TX].min = osp_get_varfloat(item);
1995  } else if (!strncasecmp(item, "reported_maxlost", strlen("reported_maxlost"))) {
1996  lost[OSP_DIR_TX].max = osp_get_varfloat(item);
1997  } else if (!strncasecmp(item, "reported_avglost", strlen("reported_avglost"))) {
1998  lost[OSP_DIR_TX].avg = osp_get_varfloat(item);
1999  } else if (!strncasecmp(item, "reported_stdevlost", strlen("reported_stdevlost"))) {
2000  lost[OSP_DIR_TX].sdev = osp_get_varfloat(item);
2001  } else if (!strncasecmp(item, "rxjitter", strlen("rxjitter"))) {
2002  jitter[OSP_DIR_RX].value = osp_get_varint(item);
2003  } else if (!strncasecmp(item, "minrxjitter", strlen("minrxjitter"))) {
2004  jitter[OSP_DIR_RX].min = osp_get_varfloat(item);
2005  } else if (!strncasecmp(item, "maxrxjitter", strlen("maxrxjitter"))) {
2006  jitter[OSP_DIR_RX].max = osp_get_varfloat(item);
2007  } else if (!strncasecmp(item, "avgrxjitter", strlen("avgjitter"))) {
2008  jitter[OSP_DIR_RX].avg = osp_get_varfloat(item);
2009  } else if (!strncasecmp(item, "stdevrxjitter", strlen("stdevjitter"))) {
2010  jitter[OSP_DIR_RX].sdev = osp_get_varfloat(item);
2011  } else if (!strncasecmp(item, "txjitter", strlen("txjitter"))) {
2012  jitter[OSP_DIR_TX].value = osp_get_varint(item);
2013  } else if (!strncasecmp(item, "reported_minjitter", strlen("reported_minjitter"))) {
2014  jitter[OSP_DIR_TX].min = osp_get_varfloat(item);
2015  } else if (!strncasecmp(item, "reported_maxjitter", strlen("reported_maxjitter"))) {
2016  jitter[OSP_DIR_TX].max = osp_get_varfloat(item);
2017  } else if (!strncasecmp(item, "reported_avgjitter", strlen("reported_avgjitter"))) {
2018  jitter[OSP_DIR_TX].avg = osp_get_varfloat(item);
2019  } else if (!strncasecmp(item, "reported_stdevjitter", strlen("reported_stdevjitter"))) {
2020  jitter[OSP_DIR_TX].sdev = osp_get_varfloat(item);
2021  } else if (!strncasecmp(item, "rtt", strlen("rtt"))) {
2022  rtt.value = osp_get_varint(item);
2023  } else if (!strncasecmp(item, "minrtt", strlen("minrtt"))) {
2024  rtt.min = osp_get_varfloat(item);
2025  } else if (!strncasecmp(item, "maxrtt", strlen("maxrtt"))) {
2026  rtt.max = osp_get_varfloat(item);
2027  } else if (!strncasecmp(item, "avgrtt", strlen("avgrtt"))) {
2028  rtt.avg = osp_get_varfloat(item);
2029  } else if (!strncasecmp(item, "stdevrtt", strlen("stdevrtt"))) {
2030  rtt.sdev = osp_get_varfloat(item);
2031  }
2032  }
2033 
2034  ast_debug(1, "OSP: call leg '%d'\n", leg);
2035  ast_debug(1, "OSP: rxcount '%d'\n", totalpackets[OSP_DIR_RX]);
2036  ast_debug(1, "OSP: txcount '%d'\n", totalpackets[OSP_DIR_TX]);
2037  ast_debug(1, "OSP: lp '%d'\n",lost[OSP_DIR_RX].value);
2038  ast_debug(1, "OSP: minrxlost '%f'\n", lost[OSP_DIR_RX].min);
2039  ast_debug(1, "OSP: maxrxlost '%f'\n", lost[OSP_DIR_RX].max);
2040  ast_debug(1, "OSP: avgrxlost '%f'\n", lost[OSP_DIR_RX].avg);
2041  ast_debug(1, "OSP: stdevrxlost '%f'\n", lost[OSP_DIR_RX].sdev);
2042  ast_debug(1, "OSP: rlp '%d'\n", lost[OSP_DIR_TX].value);
2043  ast_debug(1, "OSP: reported_minlost '%f'\n", lost[OSP_DIR_TX].min);
2044  ast_debug(1, "OSP: reported_maxlost '%f'\n", lost[OSP_DIR_TX].max);
2045  ast_debug(1, "OSP: reported_avglost '%f'\n", lost[OSP_DIR_TX].avg);
2046  ast_debug(1, "OSP: reported_stdevlost '%f'\n", lost[OSP_DIR_TX].sdev);
2047  ast_debug(1, "OSP: rxjitter '%d'\n", jitter[OSP_DIR_RX].value);
2048  ast_debug(1, "OSP: minrxjitter '%f'\n", jitter[OSP_DIR_RX].min);
2049  ast_debug(1, "OSP: maxrxjitter '%f'\n", jitter[OSP_DIR_RX].max);
2050  ast_debug(1, "OSP: avgrxjitter '%f'\n", jitter[OSP_DIR_RX].avg);
2051  ast_debug(1, "OSP: stdevrxjitter '%f'\n", jitter[OSP_DIR_RX].sdev);
2052  ast_debug(1, "OSP: txjitter '%d'\n", jitter[OSP_DIR_TX].value);
2053  ast_debug(1, "OSP: reported_minjitter '%f'\n", jitter[OSP_DIR_TX].min);
2054  ast_debug(1, "OSP: reported_maxjitter '%f'\n", jitter[OSP_DIR_TX].max);
2055  ast_debug(1, "OSP: reported_avgjitter '%f'\n", jitter[OSP_DIR_TX].avg);
2056  ast_debug(1, "OSP: reported_stdevjitter '%f'\n", jitter[OSP_DIR_TX].sdev);
2057  ast_debug(1, "OSP: rtt '%d'\n", rtt.value);
2058  ast_debug(1, "OSP: minrtt '%f'\n", rtt.min);
2059  ast_debug(1, "OSP: maxrtt '%f'\n", rtt.max);
2060  ast_debug(1, "OSP: avgrtt '%f'\n", rtt.avg);
2061  ast_debug(1, "OSP: stdevrtt '%f'\n", rtt.sdev);
2062 
2063  if (leg == OSP_CALL_INBOUND) {
2064  OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_DOWNSTREAM, totalpackets[OSP_DIR_RX]);
2065  OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_UPSTREAM, totalpackets[OSP_DIR_TX]);
2066  if (lost[OSP_DIR_RX].value >= 0) {
2067  value = lost[OSP_DIR_RX].value;
2068  } else {
2069  value = (int)lost[OSP_DIR_RX].avg;
2070  }
2071  OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_DOWNSTREAM, value, OSP_DEF_INTSTATS);
2072  if (lost[OSP_DIR_TX].value >= 0) {
2073  value = lost[OSP_DIR_TX].value;
2074  } else {
2075  value = (int)lost[OSP_DIR_TX].avg;
2076  }
2077  OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_UPSTREAM, value, OSP_DEF_INTSTATS);
2078  if (jitter[OSP_DIR_RX].value >= 0) {
2079  value = jitter[OSP_DIR_RX].value;
2080  } else {
2081  value = (int)jitter[OSP_DIR_RX].avg;
2082  }
2083  OSPPTransactionSetJitter(trans,
2084  OSPC_SMETRIC_RTP,
2085  OSPC_SFLOW_DOWNSTREAM,
2087  (int)jitter[OSP_DIR_RX].min,
2088  (int)jitter[OSP_DIR_RX].max,
2089  value, jitter[OSP_DIR_RX].sdev);
2090  if (jitter[OSP_DIR_TX].value >= 0) {
2091  value = jitter[OSP_DIR_TX].value;
2092  } else {
2093  value = (int)jitter[OSP_DIR_TX].avg;
2094  }
2095  OSPPTransactionSetJitter(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_UPSTREAM,
2096  OSP_DEF_INTSTATS, (int)jitter[OSP_DIR_TX].min, (int)jitter[OSP_DIR_TX].max, value, jitter[OSP_DIR_TX].sdev);
2097  } else {
2098  OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_UPSTREAM, totalpackets[OSP_DIR_RX]);
2099  OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_DOWNSTREAM, totalpackets[OSP_DIR_TX]);
2100  OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_UPSTREAM, lost[OSP_DIR_RX].value, OSP_DEF_INTSTATS);
2101  OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_DOWNSTREAM, lost[OSP_DIR_TX].value, OSP_DEF_INTSTATS);
2102  if (jitter[OSP_DIR_RX].value >= 0) {
2103  value = jitter[OSP_DIR_RX].value;
2104  } else {
2105  value = (int)jitter[OSP_DIR_RX].avg;
2106  }
2107  OSPPTransactionSetJitter(trans,
2108  OSPC_SMETRIC_RTP,
2109  OSPC_SFLOW_UPSTREAM,
2111  (int)jitter[OSP_DIR_RX].min,
2112  (int)jitter[OSP_DIR_RX].max,
2113  value,
2114  jitter[OSP_DIR_RX].sdev);
2115  if (jitter[OSP_DIR_TX].value >= 0) {
2116  value = jitter[OSP_DIR_TX].value;
2117  } else {
2118  value = (int)jitter[OSP_DIR_TX].avg;
2119  }
2120  OSPPTransactionSetJitter(trans,
2121  OSPC_SMETRIC_RTCP,
2122  OSPC_SFLOW_DOWNSTREAM,
2124  (int)jitter[OSP_DIR_TX].min,
2125  (int)jitter[OSP_DIR_TX].max,
2126  value,
2127  jitter[OSP_DIR_TX].sdev);
2128  }
2129  if (rtt.value >= 0) {
2130  value = rtt.value;
2131  } else {
2132  value = (int)rtt.avg;
2133  }
2134  OSPPTransactionSetRoundTripDelay(trans, OSP_DEF_INTSTATS, (int)rtt.min, (int)rtt.max, value, rtt.sdev);
2135 
2136  res = OSP_OK;
2137  }
2138 
2139  return res;
2140 }
2141 
2142 /*!
2143  * \brief OSP Finish function
2144  * \param trans OSP in/outbound transaction handle
2145  * \param recorded If failure reason has been recorded
2146  * \param cause Asterisk hangup cause
2147  * \param start Call start time
2148  * \param connect Call connect time
2149  * \param end Call end time
2150  * \param release Who release first, 0 source, 1 destination
2151  * \param inqos Inbound QoS string
2152  * \param outqos Outbound QoS string
2153  * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
2154  */
2155 static int osp_finish(
2156  int trans,
2157  int recorded,
2158  int cause,
2159  time_t start,
2160  time_t connect,
2161  time_t end,
2162  unsigned int release,
2163  const char* inqos,
2164  const char* outqos)
2165 {
2166  int res;
2167  OSPEFAILREASON reason;
2168  time_t alert = 0;
2169  unsigned isPddInfoPresent = 0;
2170  unsigned pdd = 0;
2171  unsigned int dummy = 0;
2172  int error;
2173 
2174  if (trans == OSP_INVALID_HANDLE) {
2175  return OSP_FAILED;
2176  }
2177 
2178  if (!recorded) {
2179  reason = asterisk2osp(cause);
2180  OSPPTransactionRecordFailure(trans, reason);
2181  }
2182 
2183  osp_report_qos(trans, OSP_CALL_INBOUND, inqos);
2184  osp_report_qos(trans, OSP_CALL_OUTBOUND, outqos);
2185 
2186  error = OSPPTransactionReportUsage(trans,
2187  difftime(end, connect),
2188  start,
2189  end,
2190  alert,
2191  connect,
2192  isPddInfoPresent,
2193  pdd,
2194  release,
2195  NULL,
2200  &dummy,
2201  NULL);
2202  if (error == OSPC_ERR_NO_ERROR) {
2203  ast_debug(1, "OSP: Usage reported\n");
2204  res = OSP_OK;
2205  } else {
2206  ast_debug(1, "OSP: Unable to report usage, error '%d'\n", error);
2207  res = OSP_ERROR;
2208  }
2209  OSPPTransactionDelete(trans);
2210 
2211  return res;
2212 }
2213 
2214 /* OSP Application APIs */
2215 
2216 /*!
2217  * \brief OSP Application OSPAuth
2218  * \param chan Channel
2219  * \param data Parameter
2220  * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2221  */
2222 static int ospauth_exec(
2223  struct ast_channel *chan,
2224  const char *data)
2225 {
2226  int res;
2227  const char* provider = OSP_DEF_PROVIDER;
2228  struct varshead* headp;
2229  struct ast_var_t* current;
2230  const char* source = "";
2231  const char* token = "";
2232  int handle;
2233  unsigned int timelimit;
2234  char buffer[OSP_SIZE_INTSTR];
2235  const char* status;
2236  char* tmp;
2237 
2239  AST_APP_ARG(provider);
2240  AST_APP_ARG(options);
2241  );
2242 
2243  tmp = ast_strdupa(data);
2244 
2246 
2247  if (!ast_strlen_zero(args.provider)) {
2248  provider = args.provider;
2249  }
2250  ast_debug(1, "OSPAuth: provider '%s'\n", provider);
2251 
2252  headp = &chan->varshead;
2253  AST_LIST_TRAVERSE(headp, current, entries) {
2254  if (!strcasecmp(ast_var_name(current), "OSPINPEERIP")) {
2255  source = ast_var_value(current);
2256  } else if (!strcasecmp(ast_var_name(current), "OSPINTOKEN")) {
2257  token = ast_var_value(current);
2258  }
2259  }
2260 
2261  ast_debug(1, "OSPAuth: source '%s'\n", source);
2262  ast_debug(1, "OSPAuth: token size '%zd'\n", strlen(token));
2263 
2264  res = osp_auth(provider, &handle, source,
2265  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
2266  chan->exten, token, &timelimit);
2267  if (res > 0) {
2268  status = AST_OSP_SUCCESS;
2269  } else {
2270  timelimit = OSP_DEF_TIMELIMIT;
2271  if (!res) {
2272  status = AST_OSP_FAILED;
2273  } else {
2274  status = AST_OSP_ERROR;
2275  }
2276  }
2277 
2278  snprintf(buffer, sizeof(buffer), "%d", handle);
2279  pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
2280  ast_debug(1, "OSPAuth: OSPINHANDLE '%s'\n", buffer);
2281  snprintf(buffer, sizeof(buffer), "%d", timelimit);
2282  pbx_builtin_setvar_helper(chan, "OSPINTIMELIMIT", buffer);
2283  ast_debug(1, "OSPAuth: OSPINTIMELIMIT '%s'\n", buffer);
2284  pbx_builtin_setvar_helper(chan, "OSPAUTHSTATUS", status);
2285  ast_debug(1, "OSPAuth: %s\n", status);
2286 
2287  if(res != OSP_OK) {
2288  res = OSP_AST_ERROR;
2289  } else {
2290  res = OSP_AST_OK;
2291  }
2292 
2293  return res;
2294 }
2295 
2296 /*!
2297  * \brief OSP Application OSPLookup
2298  * \param chan Channel
2299  * \param data Parameter
2300  * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2301  */
2302 static int osplookup_exec(
2303  struct ast_channel* chan,
2304  const char * data)
2305 {
2306  int res, cres;
2307  const char* provider = OSP_DEF_PROVIDER;
2308  unsigned int callidtypes = OSP_CALLID_UNDEF;
2309  struct varshead* headp;
2310  struct ast_var_t* current;
2311  const char* actualsrc = "";
2312  const char* srcdev = "";
2313  const char* snetid = "";
2314  struct osp_npdata np;
2315  OSPE_OPERATOR_NAME type;
2316  struct osp_diversion div;
2317  unsigned int i;
2318  const char* cinfo[OSP_MAX_CUSTOMINFO] = { NULL };
2319  char buffer[OSP_SIZE_TOKSTR];
2320  struct osp_results results;
2321  const char* status;
2322  char* tmp;
2323 
2325  AST_APP_ARG(exten);
2326  AST_APP_ARG(provider);
2327  AST_APP_ARG(options);
2328  );
2329 
2330  if (ast_strlen_zero(data)) {
2331  ast_log(LOG_WARNING, "OSPLookup: Arg required, OSPLookup(exten[,provider[,options]])\n");
2332  return OSP_AST_ERROR;
2333  }
2334 
2335  tmp = ast_strdupa(data);
2336 
2338 
2339  ast_debug(1, "OSPLookup: exten '%s'\n", args.exten);
2340 
2341  if (!ast_strlen_zero(args.provider)) {
2342  provider = args.provider;
2343  }
2344  ast_debug(1, "OSPlookup: provider '%s'\n", provider);
2345 
2346  if (args.options) {
2347  if (strchr(args.options, 'h')) {
2348  callidtypes |= OSP_CALLID_H323;
2349  }
2350  if (strchr(args.options, 's')) {
2351  callidtypes |= OSP_CALLID_SIP;
2352  }
2353  if (strchr(args.options, 'i')) {
2354  callidtypes |= OSP_CALLID_IAX;
2355  }
2356  }
2357  ast_debug(1, "OSPLookup: call id types '%d'\n", callidtypes);
2358 
2359  results.inhandle = OSP_INVALID_HANDLE;
2360  results.intimelimit = OSP_DEF_TIMELIMIT;
2361  results.dest[0] = '\0';
2362 
2363  np.rn = "";
2364  np.cic = "";
2365  np.npdi = 0;
2366  for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
2367  np.opname[type] = "";
2368  }
2369 
2370  div.user = "";
2371  div.host = "";
2372 
2373  headp = &chan->varshead;
2374  AST_LIST_TRAVERSE(headp, current, entries) {
2375  if (!strcasecmp(ast_var_name(current), "OSPINACTUALSRC")) {
2376  actualsrc = ast_var_value(current);
2377  } else if (!strcasecmp(ast_var_name(current), "OSPINPEERIP")) {
2378  srcdev = ast_var_value(current);
2379  } else if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
2380  if (sscanf(ast_var_value(current), "%30d", &results.inhandle) != 1) {
2381  results.inhandle = OSP_INVALID_HANDLE;
2382  }
2383  } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
2384  if (sscanf(ast_var_value(current), "%30d", &results.intimelimit) != 1) {
2385  results.intimelimit = OSP_DEF_TIMELIMIT;
2386  }
2387  } else if (!strcasecmp(ast_var_name(current), "OSPINNETWORKID")) {
2388  snetid = ast_var_value(current);
2389  } else if (!strcasecmp(ast_var_name(current), "OSPINNPRN")) {
2390  np.rn = ast_var_value(current);
2391  } else if (!strcasecmp(ast_var_name(current), "OSPINNPCIC")) {
2392  np.cic = ast_var_value(current);
2393  } else if (!strcasecmp(ast_var_name(current), "OSPINNPDI")) {
2394  if (ast_true(ast_var_value(current))) {
2395  np.npdi = 1;
2396  }
2397  } else if (!strcasecmp(ast_var_name(current), "OSPINSPID")) {
2398  np.opname[OSPC_OPNAME_SPID] = ast_var_value(current);
2399  } else if (!strcasecmp(ast_var_name(current), "OSPINOCN")) {
2400  np.opname[OSPC_OPNAME_OCN] = ast_var_value(current);
2401  } else if (!strcasecmp(ast_var_name(current), "OSPINSPN")) {
2402  np.opname[OSPC_OPNAME_SPN] = ast_var_value(current);
2403  } else if (!strcasecmp(ast_var_name(current), "OSPINALTSPN")) {
2404  np.opname[OSPC_OPNAME_ALTSPN] = ast_var_value(current);
2405  } else if (!strcasecmp(ast_var_name(current), "OSPINMCC")) {
2406  np.opname[OSPC_OPNAME_MCC] = ast_var_value(current);
2407  } else if (!strcasecmp(ast_var_name(current), "OSPINMNC")) {
2408  np.opname[OSPC_OPNAME_MNC] = ast_var_value(current);
2409  } else if (!strcasecmp(ast_var_name(current), "OSPINTOHOST")) {
2410  ast_copy_string(results.dest, ast_var_value(current), sizeof(results.dest));
2411  } else if (!strcasecmp(ast_var_name(current), "OSPINDIVUSER")) {
2412  div.user = ast_var_value(current);
2413  } else if (!strcasecmp(ast_var_name(current), "OSPINDIVHOST")) {
2414  div.host = ast_var_value(current);
2415  } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO1")) {
2416  cinfo[0] = ast_var_value(current);
2417  } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO2")) {
2418  cinfo[1] = ast_var_value(current);
2419  } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO3")) {
2420  cinfo[2] = ast_var_value(current);
2421  } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO4")) {
2422  cinfo[3] = ast_var_value(current);
2423  } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO5")) {
2424  cinfo[4] = ast_var_value(current);
2425  } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO6")) {
2426  cinfo[5] = ast_var_value(current);
2427  } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO7")) {
2428  cinfo[6] = ast_var_value(current);
2429  } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO8")) {
2430  cinfo[7] = ast_var_value(current);
2431  }
2432  }
2433  ast_debug(1, "OSPLookup: actual source device '%s'\n", actualsrc);
2434  ast_debug(1, "OSPLookup: source device '%s'\n", srcdev);
2435  ast_debug(1, "OSPLookup: OSPINHANDLE '%d'\n", results.inhandle);
2436  ast_debug(1, "OSPLookup: OSPINTIMELIMIT '%d'\n", results.intimelimit);
2437  ast_debug(1, "OSPLookup: OSPINNETWORKID '%s'\n", snetid);
2438  ast_debug(1, "OSPLookup: OSPINNPRN '%s'\n", np.rn);
2439  ast_debug(1, "OSPLookup: OSPINNPCIC '%s'\n", np.cic);
2440  ast_debug(1, "OSPLookup: OSPINNPDI '%d'\n", np.npdi);
2441  ast_debug(1, "OSPLookup: OSPINSPID '%s'\n", np.opname[OSPC_OPNAME_SPID]);
2442  ast_debug(1, "OSPLookup: OSPINOCN '%s'\n", np.opname[OSPC_OPNAME_OCN]);
2443  ast_debug(1, "OSPLookup: OSPINSPN '%s'\n", np.opname[OSPC_OPNAME_SPN]);
2444  ast_debug(1, "OSPLookup: OSPINALTSPN '%s'\n", np.opname[OSPC_OPNAME_ALTSPN]);
2445  ast_debug(1, "OSPLookup: OSPINMCC '%s'\n", np.opname[OSPC_OPNAME_MCC]);
2446  ast_debug(1, "OSPLookup: OSPINMNC '%s'\n", np.opname[OSPC_OPNAME_MNC]);
2447  ast_debug(1, "OSPLookup: OSPINTOHOST '%s'\n", results.dest);
2448  ast_debug(1, "OSPLookup: OSPINDIVUSER '%s'\n", div.user);
2449  ast_debug(1, "OSPLookup: OSPINDIVHOST'%s'\n", div.host);
2450  for (i = 0; i < OSP_MAX_CUSTOMINFO; i++) {
2451  if (!ast_strlen_zero(cinfo[i])) {
2452  ast_debug(1, "OSPLookup: OSPINCUSTOMINFO%d '%s'\n", i, cinfo[i]);
2453  }
2454  }
2455 
2456  if ((cres = ast_autoservice_start(chan)) < 0) {
2457  return OSP_AST_ERROR;
2458  }
2459 
2460  res = osp_lookup(provider, callidtypes, actualsrc, srcdev,
2461  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
2462  args.exten, snetid, &np, &div, cinfo, &results);
2463  if (res > 0) {
2464  status = AST_OSP_SUCCESS;
2465  } else {
2466  results.tech[0] = '\0';
2467  results.dest[0] = '\0';
2468  results.calling[0] = '\0';
2469  results.called[0] = '\0';
2470  results.token[0] = '\0';
2471  results.networkid[0] = '\0';
2472  results.nprn[0] = '\0';
2473  results.npcic[0] = '\0';
2474  results.npdi = 0;
2475  for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
2476  results.opname[type][0] = '\0';
2477  }
2478  results.numdests = 0;
2479  results.outtimelimit = OSP_DEF_TIMELIMIT;
2480  results.outcallid.buf[0] = '\0';
2481  results.outcallid.len = 0;
2482  if (!res) {
2483  status = AST_OSP_FAILED;
2484  } else {
2485  status = AST_OSP_ERROR;
2486  }
2487  }
2488 
2489  snprintf(buffer, sizeof(buffer), "%d", results.outhandle);
2490  pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
2491  ast_debug(1, "OSPLookup: OSPOUTHANDLE '%s'\n", buffer);
2492  pbx_builtin_setvar_helper(chan, "OSPOUTTECH", results.tech);
2493  ast_debug(1, "OSPLookup: OSPOUTTECH '%s'\n", results.tech);
2494  pbx_builtin_setvar_helper(chan, "OSPDESTINATION", results.dest);
2495  ast_debug(1, "OSPLookup: OSPDESTINATION '%s'\n", results.dest);
2496  pbx_builtin_setvar_helper(chan, "OSPOUTCALLING", results.calling);
2497  ast_debug(1, "OSPLookup: OSPOUTCALLING '%s'\n", results.calling);
2498  pbx_builtin_setvar_helper(chan, "OSPOUTCALLED", results.called);
2499  ast_debug(1, "OSPLookup: OSPOUTCALLED '%s'\n", results.called);
2500  pbx_builtin_setvar_helper(chan, "OSPOUTNETWORKID", results.networkid);
2501  ast_debug(1, "OSPLookup: OSPOUTNETWORKID '%s'\n", results.networkid);
2502  pbx_builtin_setvar_helper(chan, "OSPOUTNPRN", results.nprn);
2503  ast_debug(1, "OSPLookup: OSPOUTNPRN '%s'\n", results.nprn);
2504  pbx_builtin_setvar_helper(chan, "OSPOUTNPCIC", results.npcic);
2505  ast_debug(1, "OSPLookup: OSPOUTNPCIC '%s'\n", results.npcic);
2506  snprintf(buffer, sizeof(buffer), "%d", results.npdi);
2507  pbx_builtin_setvar_helper(chan, "OSPOUTNPDI", buffer);
2508  ast_debug(1, "OSPLookup: OSPOUTNPDI'%s'\n", buffer);
2509  pbx_builtin_setvar_helper(chan, "OSPOUTSPID", results.opname[OSPC_OPNAME_SPID]);
2510  ast_debug(1, "OSPLookup: OSPOUTSPID '%s'\n", results.opname[OSPC_OPNAME_SPID]);
2511  pbx_builtin_setvar_helper(chan, "OSPOUTOCN", results.opname[OSPC_OPNAME_OCN]);
2512  ast_debug(1, "OSPLookup: OSPOUTOCN '%s'\n", results.opname[OSPC_OPNAME_OCN]);
2513  pbx_builtin_setvar_helper(chan, "OSPOUTSPN", results.opname[OSPC_OPNAME_SPN]);
2514  ast_debug(1, "OSPLookup: OSPOUTSPN '%s'\n", results.opname[OSPC_OPNAME_SPN]);
2515  pbx_builtin_setvar_helper(chan, "OSPOUTALTSPN", results.opname[OSPC_OPNAME_ALTSPN]);
2516  ast_debug(1, "OSPLookup: OSPOUTALTSPN '%s'\n", results.opname[OSPC_OPNAME_ALTSPN]);
2517  pbx_builtin_setvar_helper(chan, "OSPOUTMCC", results.opname[OSPC_OPNAME_MCC]);
2518  ast_debug(1, "OSPLookup: OSPOUTMCC '%s'\n", results.opname[OSPC_OPNAME_MCC]);
2519  pbx_builtin_setvar_helper(chan, "OSPOUTMNC", results.opname[OSPC_OPNAME_MNC]);
2520  ast_debug(1, "OSPLookup: OSPOUTMNC '%s'\n", results.opname[OSPC_OPNAME_MNC]);
2521  pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", results.token);
2522  ast_debug(1, "OSPLookup: OSPOUTTOKEN size '%zd'\n", strlen(results.token));
2523  snprintf(buffer, sizeof(buffer), "%d", results.numdests);
2524  pbx_builtin_setvar_helper(chan, "OSPDESTREMAILS", buffer);
2525  ast_debug(1, "OSPLookup: OSPDESTREMAILS '%s'\n", buffer);
2526  snprintf(buffer, sizeof(buffer), "%d", results.outtimelimit);
2527  pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
2528  ast_debug(1, "OSPLookup: OSPOUTTIMELIMIT '%s'\n", buffer);
2529  snprintf(buffer, sizeof(buffer), "%d", callidtypes);
2530  pbx_builtin_setvar_helper(chan, "OSPOUTCALLIDTYPES", buffer);
2531  ast_debug(1, "OSPLookup: OSPOUTCALLIDTYPES '%s'\n", buffer);
2532  pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", status);
2533  ast_debug(1, "OSPLookup: %s\n", status);
2534 
2535  if (!strcasecmp(results.tech, OSP_TECH_SIP)) {
2536  snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
2537  pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2538  if (!ast_strlen_zero(results.token)) {
2539  snprintf(buffer, sizeof(buffer), "%s: %s", OSP_SIP_HEADER, results.token);
2540  pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
2541  ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
2542  }
2543  } else if (!strcasecmp(results.tech, OSP_TECH_H323)) {
2544  if ((callidtypes & OSP_CALLID_H323) && (results.outcallid.len != 0)) {
2545  osp_uuid2str(results.outcallid.buf, buffer, sizeof(buffer));
2546  } else {
2547  buffer[0] = '\0';
2548  }
2549  pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
2550  snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
2551  pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2552  } else if (!strcasecmp(results.tech, OSP_TECH_IAX)) {
2553  snprintf(buffer, sizeof(buffer), "%s/%s/%s", results.tech, results.dest, results.called);
2554  pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2555  } else if (!strcasecmp(results.tech, OSP_TECH_SKYPE)) {
2556  snprintf(buffer, sizeof(buffer), "%s/%s", results.tech, results.called);
2557  pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2558  }
2559 
2560  if ((cres = ast_autoservice_stop(chan)) < 0) {
2561  return OSP_AST_ERROR;
2562  }
2563 
2564  if(res != OSP_OK) {
2565  res = OSP_AST_ERROR;
2566  } else {
2567  res = OSP_AST_OK;
2568  }
2569 
2570  return res;
2571 }
2572 
2573 /*!
2574  * \brief OSP Application OSPNext
2575  * \param chan Channel
2576  * \param data Parameter
2577  * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2578  */
2579 static int ospnext_exec(
2580  struct ast_channel* chan,
2581  const char * data)
2582 {
2583  int res;
2584  const char* provider = OSP_DEF_PROVIDER;
2585  int cause = 0;
2586  struct varshead* headp;
2587  struct ast_var_t* current;
2588  struct osp_results results;
2589  OSPE_OPERATOR_NAME type;
2590  char buffer[OSP_SIZE_TOKSTR];
2591  unsigned int callidtypes = OSP_CALLID_UNDEF;
2592  const char* status;
2593  char* tmp;
2594 
2596  AST_APP_ARG(cause);
2597  AST_APP_ARG(provider);
2598  AST_APP_ARG(options);
2599  );
2600 
2601  if (ast_strlen_zero(data)) {
2602  ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[,provider[,options]])\n");
2603  return OSP_AST_ERROR;
2604  }
2605 
2606  tmp = ast_strdupa(data);
2607 
2609 
2610  if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
2611  cause = 0;
2612  }
2613  ast_debug(1, "OSPNext: cause '%d'\n", cause);
2614 
2615  if (!ast_strlen_zero(args.provider)) {
2616  provider = args.provider;
2617  }
2618  ast_debug(1, "OSPlookup: provider '%s'\n", provider);
2619 
2620  results.inhandle = OSP_INVALID_HANDLE;
2621  results.outhandle = OSP_INVALID_HANDLE;
2622  results.intimelimit = OSP_DEF_TIMELIMIT;
2623  results.numdests = 0;
2624 
2625  headp = &chan->varshead;
2626  AST_LIST_TRAVERSE(headp, current, entries) {
2627  if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
2628  if (sscanf(ast_var_value(current), "%30d", &results.inhandle) != 1) {
2629  results.inhandle = OSP_INVALID_HANDLE;
2630  }
2631  } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
2632  if (sscanf(ast_var_value(current), "%30d", &results.outhandle) != 1) {
2633  results.outhandle = OSP_INVALID_HANDLE;
2634  }
2635  } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
2636  if (sscanf(ast_var_value(current), "%30d", &results.intimelimit) != 1) {
2637  results.intimelimit = OSP_DEF_TIMELIMIT;
2638  }
2639  } else if (!strcasecmp(ast_var_name(current), "OSPOUTCALLIDTYPES")) {
2640  if (sscanf(ast_var_value(current), "%30d", &callidtypes) != 1) {
2641  callidtypes = OSP_CALLID_UNDEF;
2642  }
2643  } else if (!strcasecmp(ast_var_name(current), "OSPDESTREMAILS")) {
2644  if (sscanf(ast_var_value(current), "%30d", &results.numdests) != 1) {
2645  results.numdests = 0;
2646  }
2647  }
2648  }
2649  ast_debug(1, "OSPNext: OSPINHANDLE '%d'\n", results.inhandle);
2650  ast_debug(1, "OSPNext: OSPOUTHANDLE '%d'\n", results.outhandle);
2651  ast_debug(1, "OSPNext: OSPINTIMELIMIT '%d'\n", results.intimelimit);
2652  ast_debug(1, "OSPNext: OSPOUTCALLIDTYPES '%d'\n", callidtypes);
2653  ast_debug(1, "OSPNext: OSPDESTREMAILS '%d'\n", results.numdests);
2654 
2655  if ((res = osp_next(provider, cause, &results)) > 0) {
2656  status = AST_OSP_SUCCESS;
2657  } else {
2658  results.tech[0] = '\0';
2659  results.dest[0] = '\0';
2660  results.calling[0] = '\0';
2661  results.called[0] = '\0';
2662  results.token[0] = '\0';
2663  results.networkid[0] = '\0';
2664  results.nprn[0] = '\0';
2665  results.npcic[0] = '\0';
2666  results.npdi = 0;
2667  for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
2668  results.opname[type][0] = '\0';
2669  }
2670  results.numdests = 0;
2671  results.outtimelimit = OSP_DEF_TIMELIMIT;
2672  results.outcallid.buf[0] = '\0';
2673  results.outcallid.len = 0;
2674  if (!res) {
2675  status = AST_OSP_FAILED;
2676  } else {
2677  status = AST_OSP_ERROR;
2678  }
2679  }
2680 
2681  pbx_builtin_setvar_helper(chan, "OSPOUTTECH", results.tech);
2682  ast_debug(1, "OSPNext: OSPOUTTECH '%s'\n", results.tech);
2683  pbx_builtin_setvar_helper(chan, "OSPDESTINATION", results.dest);
2684  ast_debug(1, "OSPNext: OSPDESTINATION '%s'\n", results.dest);
2685  pbx_builtin_setvar_helper(chan, "OSPOUTCALLING", results.calling);
2686  ast_debug(1, "OSPNext: OSPOUTCALLING '%s'\n", results.calling);
2687  pbx_builtin_setvar_helper(chan, "OSPOUTCALLED", results.called);
2688  ast_debug(1, "OSPNext: OSPOUTCALLED'%s'\n", results.called);
2689  pbx_builtin_setvar_helper(chan, "OSPOUTNETWORKID", results.networkid);
2690  ast_debug(1, "OSPLookup: OSPOUTNETWORKID '%s'\n", results.networkid);
2691  pbx_builtin_setvar_helper(chan, "OSPOUTNPRN", results.nprn);
2692  ast_debug(1, "OSPLookup: OSPOUTNPRN '%s'\n", results.nprn);
2693  pbx_builtin_setvar_helper(chan, "OSPOUTNPCIC", results.npcic);
2694  ast_debug(1, "OSPLookup: OSPOUTNPCIC '%s'\n", results.npcic);
2695  snprintf(buffer, sizeof(buffer), "%d", results.npdi);
2696  pbx_builtin_setvar_helper(chan, "OSPOUTNPDI", buffer);
2697  ast_debug(1, "OSPLookup: OSPOUTNPDI'%s'\n", buffer);
2698  pbx_builtin_setvar_helper(chan, "OSPOUTSPID", results.opname[OSPC_OPNAME_SPID]);
2699  ast_debug(1, "OSPLookup: OSPOUTSPID '%s'\n", results.opname[OSPC_OPNAME_SPID]);
2700  pbx_builtin_setvar_helper(chan, "OSPOUTOCN", results.opname[OSPC_OPNAME_OCN]);
2701  ast_debug(1, "OSPLookup: OSPOUTOCN '%s'\n", results.opname[OSPC_OPNAME_OCN]);
2702  pbx_builtin_setvar_helper(chan, "OSPOUTSPN", results.opname[OSPC_OPNAME_SPN]);
2703  ast_debug(1, "OSPLookup: OSPOUTSPN '%s'\n", results.opname[OSPC_OPNAME_SPN]);
2704  pbx_builtin_setvar_helper(chan, "OSPOUTALTSPN", results.opname[OSPC_OPNAME_ALTSPN]);
2705  ast_debug(1, "OSPLookup: OSPOUTALTSPN '%s'\n", results.opname[OSPC_OPNAME_ALTSPN]);
2706  pbx_builtin_setvar_helper(chan, "OSPOUTMCC", results.opname[OSPC_OPNAME_MCC]);
2707  ast_debug(1, "OSPLookup: OSPOUTMCC '%s'\n", results.opname[OSPC_OPNAME_MCC]);
2708  pbx_builtin_setvar_helper(chan, "OSPOUTMNC", results.opname[OSPC_OPNAME_MNC]);
2709  ast_debug(1, "OSPLookup: OSPOUTMNC '%s'\n", results.opname[OSPC_OPNAME_MNC]);
2710  pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", results.token);
2711  ast_debug(1, "OSPNext: OSPOUTTOKEN size '%zd'\n", strlen(results.token));
2712  snprintf(buffer, sizeof(buffer), "%d", results.numdests);
2713  pbx_builtin_setvar_helper(chan, "OSPDESTREMAILS", buffer);
2714  ast_debug(1, "OSPNext: OSPDESTREMAILS '%s'\n", buffer);
2715  snprintf(buffer, sizeof(buffer), "%d", results.outtimelimit);
2716  pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
2717  ast_debug(1, "OSPNext: OSPOUTTIMELIMIT '%s'\n", buffer);
2718  pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", status);
2719  ast_debug(1, "OSPNext: %s\n", status);
2720 
2721  if (!strcasecmp(results.tech, OSP_TECH_SIP)) {
2722  snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
2723  pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2724  if (!ast_strlen_zero(results.token)) {
2725  snprintf(buffer, sizeof(buffer), "%s: %s", OSP_SIP_HEADER, results.token);
2726  pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
2727  ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
2728  }
2729  } else if (!strcasecmp(results.tech, OSP_TECH_H323)) {
2730  if ((callidtypes & OSP_CALLID_H323) && (results.outcallid.len != 0)) {
2731  osp_uuid2str(results.outcallid.buf, buffer, sizeof(buffer));
2732  } else {
2733  buffer[0] = '\0';
2734  }
2735  pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
2736  snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
2737  pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2738  } else if (!strcasecmp(results.tech, OSP_TECH_IAX)) {
2739  snprintf(buffer, sizeof(buffer), "%s/%s/%s", results.tech, results.dest, results.called);
2740  pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2741  } else if (!strcasecmp(results.tech, OSP_TECH_SKYPE)) {
2742  snprintf(buffer, sizeof(buffer), "%s/%s", results.tech, results.called);
2743  pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2744  }
2745 
2746  if(res != OSP_OK) {
2747  res = OSP_AST_ERROR;
2748  } else {
2749  res = OSP_AST_OK;
2750  }
2751 
2752  return res;
2753 }
2754 
2755 /*!
2756  * \brief OSP Application OSPFinish
2757  * \param chan Channel
2758  * \param data Parameter
2759  * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2760  */
2761 static int ospfinished_exec(
2762  struct ast_channel* chan,
2763  const char * data)
2764 {
2765  int res = OSP_OK;
2766  int cause = 0;
2767  struct varshead* headp;
2768  struct ast_var_t* current;
2769  int inhandle = OSP_INVALID_HANDLE;
2770  int outhandle = OSP_INVALID_HANDLE;
2771  int recorded = 0;
2772  time_t start, connect, end;
2773  unsigned int release;
2774  char buffer[OSP_SIZE_INTSTR];
2775  char inqos[OSP_SIZE_QOSSTR] = { 0 };
2776  char outqos[OSP_SIZE_QOSSTR] = { 0 };
2777  const char* status;
2778  char* tmp;
2779 
2781  AST_APP_ARG(cause);
2782  AST_APP_ARG(options);
2783  );
2784 
2785  tmp = ast_strdupa(data);
2786 
2788 
2789  headp = &chan->varshead;
2790  AST_LIST_TRAVERSE(headp, current, entries) {
2791  if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
2792  if (sscanf(ast_var_value(current), "%30d", &inhandle) != 1) {
2793  inhandle = OSP_INVALID_HANDLE;
2794  }
2795  } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
2796  if (sscanf(ast_var_value(current), "%30d", &outhandle) != 1) {
2797  outhandle = OSP_INVALID_HANDLE;
2798  }
2799  } else if (!recorded &&
2800  (!strcasecmp(ast_var_name(current), "OSPAUTHSTATUS") ||
2801  !strcasecmp(ast_var_name(current), "OSPLOOKUPSTATUS") ||
2802  !strcasecmp(ast_var_name(current), "OSPNEXTSTATUS")))
2803  {
2804  if (strcasecmp(ast_var_value(current), AST_OSP_SUCCESS)) {
2805  recorded = 1;
2806  }
2807  } else if (!strcasecmp(ast_var_name(current), "OSPINAUDIOQOS")) {
2808  ast_copy_string(inqos, ast_var_value(current), sizeof(inqos));
2809  } else if (!strcasecmp(ast_var_name(current), "OSPOUTAUDIOQOS")) {
2810  ast_copy_string(outqos, ast_var_value(current), sizeof(outqos));
2811  }
2812  }
2813  ast_debug(1, "OSPFinish: OSPINHANDLE '%d'\n", inhandle);
2814  ast_debug(1, "OSPFinish: OSPOUTHANDLE '%d'\n", outhandle);
2815  ast_debug(1, "OSPFinish: recorded '%d'\n", recorded);
2816  ast_debug(1, "OSPFinish: OSPINAUDIOQOS '%s'\n", inqos);
2817  ast_debug(1, "OSPFinish: OSPOUTAUDIOQOS '%s'\n", outqos);
2818 
2819  if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
2820  cause = 0;
2821  }
2822  ast_debug(1, "OSPFinish: cause '%d'\n", cause);
2823 
2824  if (chan->cdr) {
2825  start = chan->cdr->start.tv_sec;
2826  connect = chan->cdr->answer.tv_sec;
2827  if (connect) {
2828  end = time(NULL);
2829  } else {
2830  end = connect;
2831  }
2832  } else {
2833  start = 0;
2834  connect = 0;
2835  end = 0;
2836  }
2837  ast_debug(1, "OSPFinish: start '%ld'\n", start);
2838  ast_debug(1, "OSPFinish: connect '%ld'\n", connect);
2839  ast_debug(1, "OSPFinish: end '%ld'\n", end);
2840 
2841  release = ast_check_hangup(chan) ? 0 : 1;
2842 
2843  if (osp_finish(outhandle, recorded, cause, start, connect, end, release, inqos, outqos) <= 0) {
2844  ast_debug(1, "OSPFinish: Unable to report usage for outbound call\n");
2845  }
2846  switch (cause) {
2848  break;
2849  default:
2851  break;
2852  }
2853  if (osp_finish(inhandle, recorded, cause, start, connect, end, release, inqos, outqos) <= 0) {
2854  ast_debug(1, "OSPFinish: Unable to report usage for inbound call\n");
2855  }
2856  snprintf(buffer, sizeof(buffer), "%d", OSP_INVALID_HANDLE);
2857  pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
2858  pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
2859 
2860  if (res > 0) {
2861  status = AST_OSP_SUCCESS;
2862  } else if (!res) {
2863  status = AST_OSP_FAILED;
2864  } else {
2865  status = AST_OSP_ERROR;
2866  }
2867  pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", status);
2868 
2869  if(res != OSP_OK) {
2870  res = OSP_AST_ERROR;
2871  } else {
2872  res = OSP_AST_OK;
2873  }
2874 
2875  return res;
2876 }
2877 
2878 /* OSP Module APIs */
2879 
2880 static int osp_unload(void)
2881 {
2882  struct osp_provider* provider;
2883  struct osp_provider* next;
2884 
2885  if (osp_initialized) {
2887  for (provider = osp_providers; provider; provider = next) {
2888  next = provider->next;
2889  OSPPProviderDelete(provider->handle, 0);
2890  ast_free(provider);
2891  }
2892  osp_providers = NULL;
2894 
2895  OSPPCleanup();
2896 
2897  osp_tokenformat = TOKEN_ALGO_SIGNED;
2898  osp_security = 0;
2899  osp_hardware = 0;
2900  osp_initialized = 0;
2901  }
2902 
2903  return 0;
2904 }
2905 
2906 static int osp_load(int reload)
2907 {
2908  const char* cvar;
2909  unsigned int ivar;
2910  struct ast_config* cfg;
2911  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2912  int error = OSPC_ERR_NO_ERROR;
2913 
2914  if ((cfg = ast_config_load(OSP_CONFIG_FILE, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
2915  return 0;
2916  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2917  ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", OSP_CONFIG_FILE);
2918  return 0;
2919  }
2920 
2921  if (cfg) {
2922  if (reload) {
2923  osp_unload();
2924  }
2925 
2926  if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "accelerate")) && ast_true(cvar)) {
2927  if ((error = OSPPInit(1)) != OSPC_ERR_NO_ERROR) {
2928  ast_log(LOG_WARNING, "OSP: Unable to enable hardware accelleration\n");
2929  OSPPInit(0);
2930  } else {
2931  osp_hardware = 1;
2932  }
2933  } else {
2934  OSPPInit(0);
2935  }
2936  ast_debug(1, "OSP: osp_hardware '%d'\n", osp_hardware);
2937 
2938  if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "securityfeatures")) && ast_true(cvar)) {
2939  osp_security = 1;
2940  }
2941  ast_debug(1, "OSP: osp_security '%d'\n", osp_security);
2942 
2943  if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "tokenformat"))) {
2944  if ((sscanf(cvar, "%30d", &ivar) == 1) &&
2945  ((ivar == TOKEN_ALGO_SIGNED) || (ivar == TOKEN_ALGO_UNSIGNED) || (ivar == TOKEN_ALGO_BOTH)))
2946  {
2947  osp_tokenformat = ivar;
2948  } else {
2949  ast_log(LOG_WARNING, "tokenformat should be an integer from %d, %d or %d, not '%s'\n",
2950  TOKEN_ALGO_SIGNED, TOKEN_ALGO_UNSIGNED, TOKEN_ALGO_BOTH, cvar);
2951  }
2952  }
2953  ast_debug(1, "OSP: osp_tokenformat '%d'\n", osp_tokenformat);
2954 
2955  for (cvar = ast_category_browse(cfg, NULL); cvar != NULL; cvar = ast_category_browse(cfg, cvar)) {
2956  if (strcasecmp(cvar, OSP_GENERAL_CAT)) {
2957  osp_create_provider(cfg, cvar);
2958  }
2959  }
2960 
2961  osp_initialized = 1;
2962 
2963  ast_config_destroy(cfg);
2964  } else {
2965  ast_log(LOG_WARNING, "OSP: Unable to find configuration. OSP support disabled\n");
2966  return 0;
2967  }
2968  ast_debug(1, "OSP: osp_initialized '%d'\n", osp_initialized);
2969 
2970  return 1;
2971 }
2972 
2973 static char *handle_cli_osp_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2974 {
2975  int i;
2976  int found = 0;
2977  struct osp_provider* provider;
2978  const char* name = NULL;
2979  const char* tokenalgo;
2980 
2981  switch (cmd) {
2982  case CLI_INIT:
2983  e->command = "osp show";
2984  e->usage =
2985  "Usage: osp show\n"
2986  " Displays information on Open Settlement Protocol support\n";
2987  return NULL;
2988  case CLI_GENERATE:
2989  return NULL;
2990  }
2991 
2992  if ((a->argc < 2) || (a->argc > 3)) {
2993  return CLI_SHOWUSAGE;
2994  }
2995 
2996  if (a->argc > 2) {
2997  name = a->argv[2];
2998  }
2999 
3000  if (!name) {
3001  switch (osp_tokenformat) {
3002  case TOKEN_ALGO_BOTH:
3003  tokenalgo = "Both";
3004  break;
3005  case TOKEN_ALGO_UNSIGNED:
3006  tokenalgo = "Unsigned";
3007  break;
3008  case TOKEN_ALGO_SIGNED:
3009  default:
3010  tokenalgo = "Signed";
3011  break;
3012  }
3013  ast_cli(a->fd, "OSP: %s/%s/%s/%s\n",
3014  osp_initialized ? "Initialized" : "Uninitialized",
3015  osp_hardware ? "Accelerated" : "Normal",
3016  osp_security ? "Enabled" : "Disabled",
3017  tokenalgo);
3018  }
3019 
3021  for (provider = osp_providers; provider; provider = provider->next) {
3022  if (!name || !strcasecmp(provider->name, name)) {
3023  if (found) {
3024  ast_cli(a->fd, "\n");
3025  }
3026  ast_cli(a->fd, " == OSP Provider '%s' == \n", provider->name);
3027  if (osp_security) {
3028  ast_cli(a->fd, "Local Private Key: %s\n", provider->privatekey);
3029  ast_cli(a->fd, "Local Certificate: %s\n", provider->localcert);
3030  for (i = 0; i < provider->canum; i++) {
3031  ast_cli(a->fd, "CA Certificate %d: %s\n", i + 1, provider->cacerts[i]);
3032  }
3033  }
3034  for (i = 0; i < provider->spnum; i++) {
3035  ast_cli(a->fd, "Service Point %d: %s\n", i + 1, provider->spoints[i]);
3036  }
3037  ast_cli(a->fd, "Max Connections: %d\n", provider->maxconnect);
3038  ast_cli(a->fd, "Retry Delay: %d seconds\n", provider->retrydelay);
3039  ast_cli(a->fd, "Retry Limit: %d\n", provider->retrylimit);
3040  ast_cli(a->fd, "Timeout: %d milliseconds\n", provider->timeout);
3041  ast_cli(a->fd, "Source: %s\n", strlen(provider->source) ? provider->source : "<unspecified>");
3042  ast_cli(a->fd, "Auth Policy %d\n", provider->authpolicy);
3043  ast_cli(a->fd, "Default protocol %s\n", provider->defprotocol);
3044  ast_cli(a->fd, "Work mode %d\n", provider->workmode);
3045  ast_cli(a->fd, "Service type %d\n", provider->srvtype);
3046  ast_cli(a->fd, "OSP Handle: %d\n", provider->handle);
3047  found++;
3048  }
3049  }
3051 
3052  if (!found) {
3053  if (name) {
3054  ast_cli(a->fd, "Unable to find OSP provider '%s'\n", name);
3055  } else {
3056  ast_cli(a->fd, "No OSP providers configured\n");
3057  }
3058  }
3059 
3060  return CLI_SUCCESS;
3061 }
3062 
3063 /* OSPAuth() dialplan application */
3064 static const char app1[] = "OSPAuth";
3065 
3066 /* OSPLookup() dialplan application */
3067 static const char app2[] = "OSPLookup";
3068 
3069 /* OSPNext() dialplan application */
3070 static const char app3[] = "OSPNext";
3071 
3072 /* OSPFinish() dialplan application */
3073 static const char app4[] = "OSPFinish";
3074 
3075 static struct ast_cli_entry cli_osp[] = {
3076  AST_CLI_DEFINE(handle_cli_osp_show, "Displays OSF information")
3077 };
3078 
3079 static int load_module(void)
3080 {
3081  int res;
3082 
3083  if (!osp_load(0))
3084  return AST_MODULE_LOAD_DECLINE;
3085 
3086  ast_cli_register_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
3091 
3092  return res;
3093 }
3094 
3095 static int unload_module(void)
3096 {
3097  int res;
3098 
3099  res = ast_unregister_application(app4);
3100  res |= ast_unregister_application(app3);
3101  res |= ast_unregister_application(app2);
3102  res |= ast_unregister_application(app1);
3103  ast_cli_unregister_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
3104  osp_unload();
3105 
3106  return res;
3107 }
3108 
3109 static int reload(void)
3110 {
3111  osp_load(1);
3112 
3113  return 0;
3114 }
3115 
3116 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Open Settlement Protocol Applications",
3117  .load = load_module,
3118  .unload = unload_module,
3119  .reload = reload,
3120 );
const char * ast_config_AST_KEY_DIR
Definition: asterisk.c:265
static int osp_hardware
#define OSP_LOCAL_VALIDATION
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
Main Channel structure associated with a channel.
Definition: channel.h:742
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
static int osp_unload(void)
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
#define OSP_TECH_SIP
#define OSP_MAX_RETRYDELAY
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:179
static int osp_next(const char *name, int cause, struct osp_results *results)
OSP Lookup Next function.
static int osp_lookup(const char *name, unsigned int callidtypes, const char *actualsrc, const char *srcdev, const char *calling, const char *called, const char *snetid, struct osp_npdata *np, struct osp_diversion *div, const char *cinfo[], struct osp_results *results)
OSP Lookup function.
#define OSP_PROT_SIP
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
const char * B64LCert
const char * host
#define OSP_DEF_MAXCONNECT
enum osp_authpolicy authpolicy
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:89
#define OSP_DEF_RETRYDELAY
const char * B64CACert
#define OSP_SIZE_QOSSTR
static int unload_module(void)
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:69
#define OSP_TECH_H323
#define OSP_HTTP_PERSISTENCE
const char * cic
descriptor for a cli entry.
Definition: cli.h:165
const int argc
Definition: cli.h:154
#define LOG_WARNING
Definition: logger.h:144
OSPTPROVHANDLE handle
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
static const char app1[]
static void dummy(char *unused,...)
Definition: chan_unistim.c:188
int lineno
Definition: config.h:87
static int osp_validate_token(int trans, const char *source, const char *destination, const char *calling, const char *called, const char *token, unsigned int *timelimit)
Validate OSP token of inbound call.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define OSP_DEF_PROTOCOL
#define var
Definition: ast_expr2f.c:606
char dest[OSP_SIZE_NORSTR]
#define OSP_DEVICE_ID
#define OSP_SIZE_TOKSTR
Definition: cli.h:146
Configuration File Parser.
#define OSP_OK
#define OSP_TECH_SKYPE
#define OSP_DEF_SRVTYPE
static const char app3[]
#define OSP_MIN_MAXCONNECT
#define OSP_MAX_TIMEOUT
static int osp_get_provider(const char *name, struct osp_provider **provider)
Get OSP provider by name.
#define ast_mutex_lock(a)
Definition: lock.h:155
struct ast_cdr * cdr
Definition: channel.h:766
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:374
static struct @81 qos
#define OSP_CALLID_H323
#define OSP_GENERAL_CAT
unsigned int maxconnect
int value
Definition: syslog.c:39
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
static int osp_uuid2str(unsigned char *uuid, char *buffer, unsigned int bufsize)
UUID to string.
unsigned int numdests
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
static int osp_create_provider(struct ast_config *cfg, const char *name)
Create OSP provider handle according to configuration.
static int osp_create_uuid(unsigned char *uuid, unsigned int *bufsize)
Create a UUID.
char nprn[OSP_SIZE_NORSTR]
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
char name[OSP_SIZE_NORSTR]
static const char app4[]
Utility functions.
unsigned int retrylimit
#define OSP_MIN_TIMEOUT
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
int ast_base64decode(unsigned char *dst, const char *src, int max)
Decode data from base64.
Definition: utils.c:279
static int osp_initialized
static int osp_load(int reload)
#define OSP_SIZE_KEYSTR
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static int osp_create_transaction(const char *name, int *trans, char *source, unsigned int srcsize)
Create OSP transaction handle.
static int ospnext_exec(struct ast_channel *chan, const char *data)
OSP Application OSPNext.
const char * value
Definition: config.h:79
static int reload(void)
General Asterisk PBX channel definitions.
Asterisk file paths, configured in asterisk.conf.
unsigned int outtimelimit
static int osp_auth(const char *name, int *trans, const char *source, const char *calling, const char *called, const char *token, unsigned int *timelimit)
OSP Authentication function.
const int fd
Definition: cli.h:153
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
unsigned int enabled
Definition: devicestate.c:205
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define AST_OSP_SUCCESS
Definition: astosp.h:27
char localcert[OSP_SIZE_NORSTR]
char calling[OSP_SIZE_NORSTR]
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
const char * defprotocol
#define OSP_CALLID_SIP
#define OSP_ERROR
#define OSP_SIZE_UUIDSTR
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
long int ast_random(void)
Definition: utils.c:1640
static void osp_convert_outin(const char *src, char *dest, unsigned int destsize)
Convert &quot;[x.x.x.x]:port&quot; or &quot;hostname:prot&quot; to &quot;address:port&quot; format.
#define AST_OSP_FAILED
Definition: astosp.h:28
static unsigned int osp_choose_timelimit(unsigned int in, unsigned int out)
Choose min duration limit.
#define OSP_CALLID_IAX
#define OSP_DEF_AUTHPOLICY
const char * name
Definition: config.h:77
osp_direction
unsigned int canum
static void osp_convert_inout(const char *src, char *dest, unsigned int destsize)
Convert &quot;address:port&quot; to &quot;[x.x.x.x]:port&quot; or &quot;hostname:port&quot; format.
osp_srvtype
Core PBX routines and definitions.
#define OSP_AST_ERROR
static int osp_get_varint(const char *vstr)
Get integer from variable string.
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:238
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
#define AST_OSP_ERROR
Definition: astosp.h:29
const char *const * argv
Definition: cli.h:155
osp_callleg
unsigned int intimelimit
static int osp_check_destination(struct osp_provider *provider, const char *calling, const char *called, const char *destination, unsigned int tokenlen, const char *token, OSPEFAILREASON *reason, struct osp_results *results)
Choose min duration limit.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
struct timeval answer
Definition: cdr.h:102
#define OSP_SIZE_INTSTR
#define LOG_ERROR
Definition: logger.h:155
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
char opname[OSPC_OPNAME_NUMBER][OSP_SIZE_NORSTR]
unsigned int timeout
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
Definition: utils.c:357
const char * user
static struct @350 args
#define OSP_TECH_IAX
osp_workmode
#define CLI_SHOWUSAGE
Definition: cli.h:44
static int ospfinished_exec(struct ast_channel *chan, const char *data)
OSP Application OSPFinish.
#define OSP_DEF_FLOATSTATS
static float osp_get_varfloat(const char *vstr)
Get float from variable string.
#define OSP_DEF_WORKMODE
static int ospauth_exec(struct ast_channel *chan, const char *data)
OSP Application OSPAuth.
char npcic[OSP_SIZE_NORSTR]
#define OSP_PROT_IAX
unsigned int retrydelay
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int load_module(void)
#define OSP_MAX_MAXCONNECT
#define OSP_CONFIG_FILE
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct timeval start
Definition: cdr.h:100
char cacerts[OSP_MAX_CERTS][OSP_SIZE_NORSTR]
static const char name[]
struct ast_var_t::@158 entries
const char * rn
#define ast_free(a)
Definition: astmm.h:97
char * command
Definition: cli.h:180
#define OSP_SIP_HEADER
enum osp_workmode workmode
char privatekey[OSP_SIZE_NORSTR]
#define OSP_DEF_TIMELIMIT
const char * B64PKey
#define OSP_PROT_H323
char networkid[OSP_SIZE_NORSTR]
static const char type[]
Definition: chan_nbs.c:57
static unsigned int osp_tokenformat
Structure used to handle boolean flags.
Definition: utils.h:200
static struct ast_cli_entry cli_osp[]
static int osp_security
static int osp_report_qos(int trans, enum osp_callleg leg, const char *qos)
Report QoS.
static OSPEFAILREASON asterisk2osp(int cause)
Convert Asterisk status to TC code.
const char * usage
Definition: cli.h:171
#define OSP_INVALID_HANDLE
#define OSP_DEF_PROVIDER
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
char token[OSP_SIZE_TOKSTR]
char tech[OSP_SIZE_TECHSTR]
#define OSP_MAX_CUSTOMINFO
#define CLI_SUCCESS
Definition: cli.h:43
static int osp_create_callid(unsigned int type, struct osp_callid *callid)
Create a call ID according to the type.
Open Settlement Protocol (OSP)
static struct osp_provider * osp_providers
static int osplookup_exec(struct ast_channel *chan, const char *data)
OSP Application OSPLookup.
#define AST_CAUSE_NO_ROUTE_DESTINATION
Definition: causes.h:99
Standard Command Line Interface.
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static const char app2[]
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
#define OSP_SIZE_UUID
#define OSP_MIN_RETRYLIMIT
#define OSP_CALLID_UNDEF
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define OSP_SIZE_NORSTR
Internal Asterisk hangup causes.
char called[OSP_SIZE_NORSTR]
struct osp_provider * next
#define OSP_CALLID_MAXNUM
#define OSP_DEF_MAXDESTS
#define OSP_MIN_RETRYDELAY
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
struct ast_variable * next
Definition: config.h:82
#define OSP_DEF_INTSTATS
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
unsigned char buf[OSP_SIZE_NORSTR]
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
#define OSP_SIZE_TECHSTR
struct osp_callid outcallid
#define OSP_MAX_CERTS
unsigned int spnum
#define OSP_CUSTOMER_ID
osp_authpolicy
char source[OSP_SIZE_NORSTR]
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
#define OSP_FAILED
Asterisk module definitions.
static int osp_finish(int trans, int recorded, int cause, time_t start, time_t connect, time_t end, unsigned int release, const char *inqos, const char *outqos)
OSP Finish function.
#define OSP_DEF_RETRYLIMIT
enum osp_srvtype srvtype
#define OSP_AUDIT_URL
static ast_mutex_t osp_lock
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
#define OSP_DEF_TIMEOUT
struct varshead varshead
Definition: channel.h:817
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:526
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
char spoints[OSP_MAX_SPOINTS][OSP_SIZE_NORSTR]
jack_status_t status
Definition: app_jack.c:143
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
#define OSP_PROT_SKYPE
#define OSP_MAX_RETRYLIMIT
#define CONFIG_STATUS_FILEUNCHANGED
Definition: config.h:51
static char * handle_cli_osp_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define OSP_AST_OK
#define ast_mutex_unlock(a)
Definition: lock.h:156
unsigned int len
#define OSP_MAX_SPOINTS
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
#define OSP_SSL_LIFETIME
const char * opname[OSPC_OPNAME_NUMBER]