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