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