res/res_rtp_asterisk: Enable rxjitter calculation for video
[asterisk/asterisk.git] / funcs / func_callerid.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999-2010, Digium, Inc.
5  *
6  * See http://www.asterisk.org for more information about
7  * the Asterisk project. Please do not directly contact
8  * any of the maintainers of this project for assistance;
9  * the project provides a web site, mailing lists and IRC
10  * channels for your use.
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License Version 2. See the LICENSE file
14  * at the top of the source tree.
15  */
16
17 /*! \file
18  *
19  * \brief Party ID related dialplan functions (Caller-ID, Connected-line, Redirecting)
20  *
21  * \ingroup functions
22  *
23  * See Also:
24  * \arg \ref AstCREDITS
25  */
26
27 /*** MODULEINFO
28         <support_level>core</support_level>
29  ***/
30
31 #include "asterisk.h"
32
33 #include "asterisk/module.h"
34 #include "asterisk/channel.h"
35 #include "asterisk/pbx.h"
36 #include "asterisk/utils.h"
37 #include "asterisk/app.h"
38 #include "asterisk/callerid.h"
39
40 /*
41  * The CALLERID(pres) datatype is shorthand for getting/setting the
42  * combined value of name-pres and num-pres.  Some channel drivers
43  * don't make a distinction, so it makes sense to only use one property
44  * to get/set it.  The same applies to CONNECTEDLINE(pres),
45  * REDIRECTING(orig-pres), REDIRECTING(from-pres) and REDIRECTING(to-pres).
46  *
47  * Do not document the CALLERID(ton) datatype.
48  * It is an alias for num-plan.
49  *
50  * Do not document the CALLERID(ANI-subaddr-...) datatype.
51  * This is not used.
52  *
53  * Do not document the CONNECTEDLINE(source) datatype.
54  * It has turned out to not be needed.  The source value is really
55  * only useful as a possible tracing aid.
56  *
57  * Do not document the CONNECTEDLINE(ton) datatype.
58  * It is an alias for num-plan.
59  *
60  * Do not document the REDIRECTING(pres) datatype.
61  * It has turned out that the from-pres and to-pres values must be kept
62  * separate.  They represent two different parties and there is a case when
63  * they are active at the same time.  The plain pres option will simply
64  * live on as a historical relic.
65  *
66  * Do not document the REDIRECTING(orig-ton), REDIRECTING(from-ton),
67  * or REDIRECTING(to-ton) datatypes.
68  * They are aliases for orig-num-plan, from-num-plan, and to-num-plan
69  * respectively.
70  */
71 /*** DOCUMENTATION
72         <function name="CALLERID" language="en_US">
73                 <synopsis>
74                         Gets or sets Caller*ID data on the channel.
75                 </synopsis>
76                 <syntax>
77                         <parameter name="datatype" required="true">
78                                 <para>The allowable datatypes are:</para>
79                                 <enumlist>
80                                         <enum name = "all" />
81                                         <enum name = "name" />
82                                         <enum name = "name-valid" />
83                                         <enum name = "name-charset" />
84                                         <enum name = "name-pres" />
85                                         <enum name = "num" />
86                                         <enum name = "num-valid" />
87                                         <enum name = "num-plan" />
88                                         <enum name = "num-pres" />
89                                         <enum name = "pres" />
90                                         <enum name = "subaddr" />
91                                         <enum name = "subaddr-valid" />
92                                         <enum name = "subaddr-type" />
93                                         <enum name = "subaddr-odd" />
94                                         <enum name = "tag" />
95                                         <enum name = "priv-all" />
96                                         <enum name = "priv-name" />
97                                         <enum name = "priv-name-valid" />
98                                         <enum name = "priv-name-charset" />
99                                         <enum name = "priv-name-pres" />
100                                         <enum name = "priv-num" />
101                                         <enum name = "priv-num-valid" />
102                                         <enum name = "priv-num-plan" />
103                                         <enum name = "priv-num-pres" />
104                                         <enum name = "priv-subaddr" />
105                                         <enum name = "priv-subaddr-valid" />
106                                         <enum name = "priv-subaddr-type" />
107                                         <enum name = "priv-subaddr-odd" />
108                                         <enum name = "priv-tag" />
109                                         <enum name = "ANI-all" />
110                                         <enum name = "ANI-name" />
111                                         <enum name = "ANI-name-valid" />
112                                         <enum name = "ANI-name-charset" />
113                                         <enum name = "ANI-name-pres" />
114                                         <enum name = "ANI-num" />
115                                         <enum name = "ANI-num-valid" />
116                                         <enum name = "ANI-num-plan" />
117                                         <enum name = "ANI-num-pres" />
118                                         <enum name = "ANI-tag" />
119                                         <enum name = "RDNIS" />
120                                         <enum name = "DNID" />
121                                         <enum name = "dnid-num-plan" />
122                                         <enum name = "dnid-subaddr" />
123                                         <enum name = "dnid-subaddr-valid" />
124                                         <enum name = "dnid-subaddr-type" />
125                                         <enum name = "dnid-subaddr-odd" />
126                                 </enumlist>
127                         </parameter>
128                         <parameter name="CID">
129                                 <para>Optional Caller*ID to parse instead of using the Caller*ID from the
130                                 channel. This parameter is only optional when reading the Caller*ID.</para>
131                         </parameter>
132                 </syntax>
133                 <description>
134                         <para>Gets or sets Caller*ID data on the channel. Uses channel callerid by
135                         default or optional callerid, if specified.</para>
136                         <para>The <replaceable>pres</replaceable> field gets/sets a combined value
137                         for <replaceable>name-pres</replaceable> and
138                         <replaceable>num-pres</replaceable>.</para>
139                         <para>The allowable values for the <replaceable>name-charset</replaceable>
140                         field are the following:</para>
141                         <enumlist>
142                                 <enum name = "unknown"><para>Unknown</para></enum>
143                                 <enum name = "iso8859-1"><para>ISO8859-1</para></enum>
144                                 <enum name = "withdrawn"><para>Withdrawn</para></enum>
145                                 <enum name = "iso8859-2"><para>ISO8859-2</para></enum>
146                                 <enum name = "iso8859-3"><para>ISO8859-3</para></enum>
147                                 <enum name = "iso8859-4"><para>ISO8859-4</para></enum>
148                                 <enum name = "iso8859-5"><para>ISO8859-5</para></enum>
149                                 <enum name = "iso8859-7"><para>ISO8859-7</para></enum>
150                                 <enum name = "bmp"><para>ISO10646 Bmp String</para></enum>
151                                 <enum name = "utf8"><para>ISO10646 UTF-8 String</para></enum>
152                         </enumlist>
153                         <para>The allowable values for the <replaceable>num-pres</replaceable>,
154                         <replaceable>name-pres</replaceable>, and <replaceable>pres</replaceable>
155                         fields are the following:</para>
156                         <enumlist>
157                                 <enum name="allowed_not_screened">
158                                         <para>Presentation Allowed, Not Screened.</para>
159                                 </enum>
160                                 <enum name="allowed_passed_screen">
161                                         <para>Presentation Allowed, Passed Screen.</para>
162                                 </enum>
163                                 <enum name="allowed_failed_screen">
164                                         <para>Presentation Allowed, Failed Screen.</para>
165                                 </enum>
166                                 <enum name="allowed">
167                                         <para>Presentation Allowed, Network Number.</para>
168                                 </enum>
169                                 <enum name="prohib_not_screened">
170                                         <para>Presentation Prohibited, Not Screened.</para>
171                                 </enum>
172                                 <enum name="prohib_passed_screen">
173                                         <para>Presentation Prohibited, Passed Screen.</para>
174                                 </enum>
175                                 <enum name="prohib_failed_screen">
176                                         <para>Presentation Prohibited, Failed Screen.</para>
177                                 </enum>
178                                 <enum name="prohib">
179                                         <para>Presentation Prohibited, Network Number.</para>
180                                 </enum>
181                                 <enum name="unavailable">
182                                         <para>Number Unavailable.</para>
183                                 </enum>
184                         </enumlist>
185                 </description>
186         </function>
187         <function name="CONNECTEDLINE" language="en_US">
188                 <synopsis>
189                         Gets or sets Connected Line data on the channel.
190                 </synopsis>
191                 <syntax>
192                         <parameter name="datatype" required="true">
193                                 <para>The allowable datatypes are:</para>
194                                 <enumlist>
195                                         <enum name = "all" />
196                                         <enum name = "name" />
197                                         <enum name = "name-valid" />
198                                         <enum name = "name-charset" />
199                                         <enum name = "name-pres" />
200                                         <enum name = "num" />
201                                         <enum name = "num-valid" />
202                                         <enum name = "num-plan" />
203                                         <enum name = "num-pres" />
204                                         <enum name = "pres" />
205                                         <enum name = "subaddr" />
206                                         <enum name = "subaddr-valid" />
207                                         <enum name = "subaddr-type" />
208                                         <enum name = "subaddr-odd" />
209                                         <enum name = "tag" />
210                                         <enum name = "priv-all" />
211                                         <enum name = "priv-name" />
212                                         <enum name = "priv-name-valid" />
213                                         <enum name = "priv-name-charset" />
214                                         <enum name = "priv-name-pres" />
215                                         <enum name = "priv-num" />
216                                         <enum name = "priv-num-valid" />
217                                         <enum name = "priv-num-plan" />
218                                         <enum name = "priv-num-pres" />
219                                         <enum name = "priv-subaddr" />
220                                         <enum name = "priv-subaddr-valid" />
221                                         <enum name = "priv-subaddr-type" />
222                                         <enum name = "priv-subaddr-odd" />
223                                         <enum name = "priv-tag" />
224                                 </enumlist>
225                         </parameter>
226                         <parameter name="i">
227                                 <para>If set, this will prevent the channel from sending out protocol
228                                 messages because of the value being set</para>
229                         </parameter>
230                 </syntax>
231                 <description>
232                         <para>Gets or sets Connected Line data on the channel.</para>
233                         <para>The <replaceable>pres</replaceable> field gets/sets a combined value
234                         for <replaceable>name-pres</replaceable> and
235                         <replaceable>num-pres</replaceable>.</para>
236                         <para>The allowable values for the <replaceable>name-charset</replaceable>
237                         field are the following:</para>
238                         <enumlist>
239                                 <enum name = "unknown"><para>Unknown</para></enum>
240                                 <enum name = "iso8859-1"><para>ISO8859-1</para></enum>
241                                 <enum name = "withdrawn"><para>Withdrawn</para></enum>
242                                 <enum name = "iso8859-2"><para>ISO8859-2</para></enum>
243                                 <enum name = "iso8859-3"><para>ISO8859-3</para></enum>
244                                 <enum name = "iso8859-4"><para>ISO8859-4</para></enum>
245                                 <enum name = "iso8859-5"><para>ISO8859-5</para></enum>
246                                 <enum name = "iso8859-7"><para>ISO8859-7</para></enum>
247                                 <enum name = "bmp"><para>ISO10646 Bmp String</para></enum>
248                                 <enum name = "utf8"><para>ISO10646 UTF-8 String</para></enum>
249                         </enumlist>
250                         <para>The allowable values for the <replaceable>num-pres</replaceable>,
251                         <replaceable>name-pres</replaceable>, and <replaceable>pres</replaceable>
252                         fields are the following:</para>
253                         <enumlist>
254                                 <enum name="allowed_not_screened">
255                                         <para>Presentation Allowed, Not Screened.</para>
256                                 </enum>
257                                 <enum name="allowed_passed_screen">
258                                         <para>Presentation Allowed, Passed Screen.</para>
259                                 </enum>
260                                 <enum name="allowed_failed_screen">
261                                         <para>Presentation Allowed, Failed Screen.</para>
262                                 </enum>
263                                 <enum name="allowed">
264                                         <para>Presentation Allowed, Network Number.</para>
265                                 </enum>
266                                 <enum name="prohib_not_screened">
267                                         <para>Presentation Prohibited, Not Screened.</para>
268                                 </enum>
269                                 <enum name="prohib_passed_screen">
270                                         <para>Presentation Prohibited, Passed Screen.</para>
271                                 </enum>
272                                 <enum name="prohib_failed_screen">
273                                         <para>Presentation Prohibited, Failed Screen.</para>
274                                 </enum>
275                                 <enum name="prohib">
276                                         <para>Presentation Prohibited, Network Number.</para>
277                                 </enum>
278                                 <enum name="unavailable">
279                                         <para>Number Unavailable.</para>
280                                 </enum>
281                         </enumlist>
282                 </description>
283         </function>
284         <function name="REDIRECTING" language="en_US">
285                 <synopsis>
286                         Gets or sets Redirecting data on the channel.
287                 </synopsis>
288                 <syntax>
289                         <parameter name="datatype" required="true">
290                                 <para>The allowable datatypes are:</para>
291                                 <enumlist>
292                                         <enum name = "orig-all" />
293                                         <enum name = "orig-name" />
294                                         <enum name = "orig-name-valid" />
295                                         <enum name = "orig-name-charset" />
296                                         <enum name = "orig-name-pres" />
297                                         <enum name = "orig-num" />
298                                         <enum name = "orig-num-valid" />
299                                         <enum name = "orig-num-plan" />
300                                         <enum name = "orig-num-pres" />
301                                         <enum name = "orig-pres" />
302                                         <enum name = "orig-subaddr" />
303                                         <enum name = "orig-subaddr-valid" />
304                                         <enum name = "orig-subaddr-type" />
305                                         <enum name = "orig-subaddr-odd" />
306                                         <enum name = "orig-tag" />
307                                         <enum name = "orig-reason" />
308                                         <enum name = "from-all" />
309                                         <enum name = "from-name" />
310                                         <enum name = "from-name-valid" />
311                                         <enum name = "from-name-charset" />
312                                         <enum name = "from-name-pres" />
313                                         <enum name = "from-num" />
314                                         <enum name = "from-num-valid" />
315                                         <enum name = "from-num-plan" />
316                                         <enum name = "from-num-pres" />
317                                         <enum name = "from-pres" />
318                                         <enum name = "from-subaddr" />
319                                         <enum name = "from-subaddr-valid" />
320                                         <enum name = "from-subaddr-type" />
321                                         <enum name = "from-subaddr-odd" />
322                                         <enum name = "from-tag" />
323                                         <enum name = "to-all" />
324                                         <enum name = "to-name" />
325                                         <enum name = "to-name-valid" />
326                                         <enum name = "to-name-charset" />
327                                         <enum name = "to-name-pres" />
328                                         <enum name = "to-num" />
329                                         <enum name = "to-num-valid" />
330                                         <enum name = "to-num-plan" />
331                                         <enum name = "to-num-pres" />
332                                         <enum name = "to-pres" />
333                                         <enum name = "to-subaddr" />
334                                         <enum name = "to-subaddr-valid" />
335                                         <enum name = "to-subaddr-type" />
336                                         <enum name = "to-subaddr-odd" />
337                                         <enum name = "to-tag" />
338                                         <enum name = "priv-orig-all" />
339                                         <enum name = "priv-orig-name" />
340                                         <enum name = "priv-orig-name-valid" />
341                                         <enum name = "priv-orig-name-charset" />
342                                         <enum name = "priv-orig-name-pres" />
343                                         <enum name = "priv-orig-num" />
344                                         <enum name = "priv-orig-num-valid" />
345                                         <enum name = "priv-orig-num-plan" />
346                                         <enum name = "priv-orig-num-pres" />
347                                         <enum name = "priv-orig-subaddr" />
348                                         <enum name = "priv-orig-subaddr-valid" />
349                                         <enum name = "priv-orig-subaddr-type" />
350                                         <enum name = "priv-orig-subaddr-odd" />
351                                         <enum name = "priv-orig-tag" />
352                                         <enum name = "priv-from-all" />
353                                         <enum name = "priv-from-name" />
354                                         <enum name = "priv-from-name-valid" />
355                                         <enum name = "priv-from-name-charset" />
356                                         <enum name = "priv-from-name-pres" />
357                                         <enum name = "priv-from-num" />
358                                         <enum name = "priv-from-num-valid" />
359                                         <enum name = "priv-from-num-plan" />
360                                         <enum name = "priv-from-num-pres" />
361                                         <enum name = "priv-from-subaddr" />
362                                         <enum name = "priv-from-subaddr-valid" />
363                                         <enum name = "priv-from-subaddr-type" />
364                                         <enum name = "priv-from-subaddr-odd" />
365                                         <enum name = "priv-from-tag" />
366                                         <enum name = "priv-to-all" />
367                                         <enum name = "priv-to-name" />
368                                         <enum name = "priv-to-name-valid" />
369                                         <enum name = "priv-to-name-charset" />
370                                         <enum name = "priv-to-name-pres" />
371                                         <enum name = "priv-to-num" />
372                                         <enum name = "priv-to-num-valid" />
373                                         <enum name = "priv-to-num-plan" />
374                                         <enum name = "priv-to-num-pres" />
375                                         <enum name = "priv-to-subaddr" />
376                                         <enum name = "priv-to-subaddr-valid" />
377                                         <enum name = "priv-to-subaddr-type" />
378                                         <enum name = "priv-to-subaddr-odd" />
379                                         <enum name = "priv-to-tag" />
380                                         <enum name = "reason" />
381                                         <enum name = "count" />
382                                 </enumlist>
383                         </parameter>
384                         <parameter name="i">
385                                 <para>If set, this will prevent the channel from sending out protocol
386                                 messages because of the value being set</para>
387                         </parameter>
388                 </syntax>
389                 <description>
390                         <para>Gets or sets Redirecting data on the channel.</para>
391                         <para>The <replaceable>orig-pres</replaceable>,
392                         <replaceable>from-pres</replaceable> and <replaceable>to-pres</replaceable>
393                         fields get/set a combined value for the corresponding
394                         <replaceable>...-name-pres</replaceable> and <replaceable>...-num-pres</replaceable>
395                         fields.</para>
396                         <para>The recognized values for the <replaceable>reason</replaceable>
397                         and <replaceable>orig-reason</replaceable> fields are the following:</para>
398                         <enumlist>
399                                 <enum name = "away"><para>Callee is Away</para></enum>
400                                 <enum name = "cf_dte"><para>Call Forwarding By The Called DTE</para></enum>
401                                 <enum name = "cfb"><para>Call Forwarding Busy</para></enum>
402                                 <enum name = "cfnr"><para>Call Forwarding No Reply</para></enum>
403                                 <enum name = "cfu"><para>Call Forwarding Unconditional</para></enum>
404                                 <enum name = "deflection"><para>Call Deflection</para></enum>
405                                 <enum name = "dnd"><para>Do Not Disturb</para></enum>
406                                 <enum name = "follow_me"><para>Follow Me</para></enum>
407                                 <enum name = "out_of_order"><para>Called DTE Out-Of-Order</para></enum>
408                                 <enum name = "send_to_vm"><para>Send the call to voicemail</para></enum>
409                                 <enum name = "time_of_day"><para>Time of Day</para></enum>
410                                 <enum name = "unavailable"><para>Callee is Unavailable</para></enum>
411                                 <enum name = "unknown"><para>Unknown</para></enum>
412                         </enumlist>
413                         <note><para>You can set a user defined reason string that SIP can
414                         send/receive instead.  The user defined reason string my need to be
415                         quoted depending upon SIP or the peer's requirements.  These strings
416                         are treated as unknown by the non-SIP channel drivers.</para></note>
417                         <para>The allowable values for the <replaceable>xxx-name-charset</replaceable>
418                         field are the following:</para>
419                         <enumlist>
420                                 <enum name = "unknown"><para>Unknown</para></enum>
421                                 <enum name = "iso8859-1"><para>ISO8859-1</para></enum>
422                                 <enum name = "withdrawn"><para>Withdrawn</para></enum>
423                                 <enum name = "iso8859-2"><para>ISO8859-2</para></enum>
424                                 <enum name = "iso8859-3"><para>ISO8859-3</para></enum>
425                                 <enum name = "iso8859-4"><para>ISO8859-4</para></enum>
426                                 <enum name = "iso8859-5"><para>ISO8859-5</para></enum>
427                                 <enum name = "iso8859-7"><para>ISO8859-7</para></enum>
428                                 <enum name = "bmp"><para>ISO10646 Bmp String</para></enum>
429                                 <enum name = "utf8"><para>ISO10646 UTF-8 String</para></enum>
430                         </enumlist>
431                 </description>
432         </function>
433  ***/
434
435 enum ID_FIELD_STATUS {
436         ID_FIELD_VALID,
437         ID_FIELD_INVALID,
438         ID_FIELD_UNKNOWN
439 };
440
441 AST_DEFINE_APP_ARGS_TYPE(ast_party_func_args,
442         AST_APP_ARG(member);    /*!< Member name */
443         AST_APP_ARG(opts);              /*!< Options token */
444         AST_APP_ARG(other);             /*!< Any remining unused arguments */
445         );
446
447 AST_DEFINE_APP_ARGS_TYPE(ast_party_members,
448         AST_APP_ARG(subnames[10]);      /*!< Option member subnames */
449         );
450
451 enum CONNECTED_LINE_OPT_FLAGS {
452         CONNECTED_LINE_OPT_INHIBIT = (1 << 0),
453 };
454 enum CONNECTED_LINE_OPT_ARGS {
455         CONNECTED_LINE_OPT_DUMMY,       /*!< Delete this if CONNECTED_LINE ever gets an option with parameters. */
456
457         /*! \note This entry _MUST_ be the last one in the enum */
458         CONNECTED_LINE_OPT_ARG_ARRAY_SIZE
459 };
460
461 AST_APP_OPTIONS(connectedline_opts, BEGIN_OPTIONS
462         AST_APP_OPTION('i', CONNECTED_LINE_OPT_INHIBIT),
463 END_OPTIONS);
464
465 enum REDIRECTING_OPT_FLAGS {
466         REDIRECTING_OPT_INHIBIT = (1 << 0),
467 };
468 enum REDIRECTING_OPT_ARGS {
469         REDIRECTING_OPT_DUMMY,  /*!< Delete this if REDIRECTING ever gets an option with parameters. */
470
471         /*! \note This entry _MUST_ be the last one in the enum */
472         REDIRECTING_OPT_ARG_ARRAY_SIZE
473 };
474
475 AST_APP_OPTIONS(redirecting_opts, BEGIN_OPTIONS
476         AST_APP_OPTION('i', REDIRECTING_OPT_INHIBIT),
477 END_OPTIONS);
478
479 /*!
480  * \internal
481  * \brief Read values from the party name struct.
482  * \since 1.8
483  *
484  * \param buf Buffer to fill with read value.
485  * \param len Length of the buffer.
486  * \param argc Number of party member subnames.
487  * \param argv Party member subnames given.
488  * \param name Party name to get values from.
489  *
490  * \retval ID_FIELD_VALID on success.
491  * \retval ID_FIELD_UNKNOWN on unknown field name.
492  */
493 static enum ID_FIELD_STATUS party_name_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_name *name)
494 {
495         enum ID_FIELD_STATUS status;
496
497         status = ID_FIELD_VALID;
498
499         if (argc == 0) {
500                 /* We want the name string */
501                 if (name->valid && name->str) {
502                         ast_copy_string(buf, name->str, len);
503                 }
504         } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
505                 snprintf(buf, len, "%d", name->valid);
506         } else if (argc == 1 && !strcasecmp("charset", argv[0])) {
507                 ast_copy_string(buf, ast_party_name_charset_str(name->char_set), len);
508         } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
509                 /* Accept pres[entation] */
510                 ast_copy_string(buf, ast_named_caller_presentation(name->presentation), len);
511         } else {
512                 status = ID_FIELD_UNKNOWN;
513         }
514
515         return status;
516 }
517
518 /*!
519  * \internal
520  * \brief Read values from the party number struct.
521  * \since 1.8
522  *
523  * \param buf Buffer to fill with read value.
524  * \param len Length of the buffer.
525  * \param argc Number of party member subnames.
526  * \param argv Party member subnames given.
527  * \param number Party number to get values from.
528  *
529  * \retval ID_FIELD_VALID on success.
530  * \retval ID_FIELD_UNKNOWN on unknown field name.
531  */
532 static enum ID_FIELD_STATUS party_number_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_number *number)
533 {
534         enum ID_FIELD_STATUS status;
535
536         status = ID_FIELD_VALID;
537
538         if (argc == 0) {
539                 /* We want the number string */
540                 if (number->valid && number->str) {
541                         ast_copy_string(buf, number->str, len);
542                 }
543         } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
544                 snprintf(buf, len, "%d", number->valid);
545         } else if (argc == 1 && !strcasecmp("plan", argv[0])) {
546                 snprintf(buf, len, "%d", number->plan);
547         } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
548                 /* Accept pres[entation] */
549                 ast_copy_string(buf, ast_named_caller_presentation(number->presentation), len);
550         } else {
551                 status = ID_FIELD_UNKNOWN;
552         }
553
554         return status;
555 }
556
557 /*!
558  * \internal
559  * \brief Read values from the party subaddress struct.
560  * \since 1.8
561  *
562  * \param buf Buffer to fill with read value.
563  * \param len Length of the buffer.
564  * \param argc Number of party member subnames.
565  * \param argv Party member subnames given.
566  * \param subaddress Party subaddress to get values from.
567  *
568  * \retval ID_FIELD_VALID on success.
569  * \retval ID_FIELD_UNKNOWN on unknown field name.
570  */
571 static enum ID_FIELD_STATUS party_subaddress_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_subaddress *subaddress)
572 {
573         enum ID_FIELD_STATUS status;
574
575         status = ID_FIELD_VALID;
576
577         if (argc == 0) {
578                 /* We want the subaddress string */
579                 if (subaddress->str) {
580                         ast_copy_string(buf, subaddress->str, len);
581                 }
582         } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
583                 snprintf(buf, len, "%d", subaddress->valid);
584         } else if (argc == 1 && !strcasecmp("type", argv[0])) {
585                 snprintf(buf, len, "%d", subaddress->type);
586         } else if (argc == 1 && !strcasecmp("odd", argv[0])) {
587                 snprintf(buf, len, "%d", subaddress->odd_even_indicator);
588         } else {
589                 status = ID_FIELD_UNKNOWN;
590         }
591
592         return status;
593 }
594
595 /*!
596  * \internal
597  * \brief Read values from the party id struct.
598  * \since 1.8
599  *
600  * \param buf Buffer to fill with read value.
601  * \param len Length of the buffer.
602  * \param argc Number of party member subnames.
603  * \param argv Party member subnames given.
604  * \param id Party id to get values from.
605  *
606  * \retval ID_FIELD_VALID on success.
607  * \retval ID_FIELD_UNKNOWN on unknown field name.
608  */
609 static enum ID_FIELD_STATUS party_id_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_id *id)
610 {
611         enum ID_FIELD_STATUS status;
612
613         if (argc == 0) {
614                 /* Must have at least one subname. */
615                 return ID_FIELD_UNKNOWN;
616         }
617
618         status = ID_FIELD_VALID;
619
620         if (argc == 1 && !strcasecmp("all", argv[0])) {
621                 snprintf(buf, len, "\"%s\" <%s>",
622                          S_COR(id->name.valid, id->name.str, ""),
623                          S_COR(id->number.valid, id->number.str, ""));
624         } else if (!strcasecmp("name", argv[0])) {
625                 status = party_name_read(buf, len, argc - 1, argv + 1, &id->name);
626         } else if (!strncasecmp("num", argv[0], 3)) {
627                 /* Accept num[ber] */
628                 status = party_number_read(buf, len, argc - 1, argv + 1, &id->number);
629         } else if (!strncasecmp("subaddr", argv[0], 7)) {
630                 /* Accept subaddr[ess] */
631                 status = party_subaddress_read(buf, len, argc - 1, argv + 1, &id->subaddress);
632         } else if (argc == 1 && !strcasecmp("tag", argv[0])) {
633                 if (id->tag) {
634                         ast_copy_string(buf, id->tag, len);
635                 }
636         } else if (argc == 1 && !strcasecmp("ton", argv[0])) {
637                 /* ton is an alias for num-plan */
638                 snprintf(buf, len, "%d", id->number.plan);
639         } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
640                 /*
641                  * Accept pres[entation]
642                  * This is the combined name/number presentation.
643                  */
644                 ast_copy_string(buf,
645                         ast_named_caller_presentation(ast_party_id_presentation(id)), len);
646         } else {
647                 status = ID_FIELD_UNKNOWN;
648         }
649
650         return status;
651 }
652
653 /*!
654  * \internal
655  * \brief Write new values to the party name struct
656  * \since 1.8
657  *
658  * \param name Party name struct to write values
659  * \param argc Number of party member subnames.
660  * \param argv Party member subnames given.
661  * \param value Value to assign to the party name.
662  *
663  * \retval ID_FIELD_VALID on success.
664  * \retval ID_FIELD_INVALID on error with field value.
665  * \retval ID_FIELD_UNKNOWN on unknown field name.
666  */
667 static enum ID_FIELD_STATUS party_name_write(struct ast_party_name *name, int argc, char *argv[], const char *value)
668 {
669         char *val;
670         enum ID_FIELD_STATUS status;
671
672         status = ID_FIELD_VALID;
673
674         if (argc == 0) {
675                 /* We are setting the name string */
676                 name->valid = 1;
677                 name->str = ast_strdup(value);
678                 ast_trim_blanks(name->str);
679         } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
680                 name->valid = atoi(value) ? 1 : 0;
681         } else if (argc == 1 && !strcasecmp("charset", argv[0])) {
682                 int char_set;
683
684                 val = ast_strdupa(value);
685                 ast_trim_blanks(val);
686
687                 if (('0' <= val[0]) && (val[0] <= '9')) {
688                         char_set = atoi(val);
689                 } else {
690                         char_set = ast_party_name_charset_parse(val);
691                 }
692
693                 if (char_set < 0) {
694                         ast_log(LOG_ERROR,
695                                 "Unknown name char-set '%s', value unchanged\n", val);
696                         status = ID_FIELD_INVALID;
697                 } else {
698                         name->char_set = char_set;
699                 }
700         } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
701                 int pres;
702
703                 /* Accept pres[entation] */
704                 val = ast_strdupa(value);
705                 ast_trim_blanks(val);
706
707                 if (('0' <= val[0]) && (val[0] <= '9')) {
708                         pres = atoi(val);
709                 } else {
710                         pres = ast_parse_caller_presentation(val);
711                 }
712
713                 if (pres < 0) {
714                         ast_log(LOG_ERROR,
715                                 "Unknown name presentation '%s', value unchanged\n", val);
716                         status = ID_FIELD_INVALID;
717                 } else {
718                         name->presentation = pres;
719                 }
720         } else {
721                 status = ID_FIELD_UNKNOWN;
722         }
723
724         return status;
725 }
726
727 /*!
728  * \internal
729  * \brief Write new values to the party number struct
730  * \since 1.8
731  *
732  * \param number Party number struct to write values
733  * \param argc Number of party member subnames.
734  * \param argv Party member subnames given.
735  * \param value Value to assign to the party number.
736  *
737  * \retval ID_FIELD_VALID on success.
738  * \retval ID_FIELD_INVALID on error with field value.
739  * \retval ID_FIELD_UNKNOWN on unknown field name.
740  */
741 static enum ID_FIELD_STATUS party_number_write(struct ast_party_number *number, int argc, char *argv[], const char *value)
742 {
743         char *val;
744         enum ID_FIELD_STATUS status;
745
746         status = ID_FIELD_VALID;
747
748         if (argc == 0) {
749                 /* We are setting the number string */
750                 number->valid = 1;
751                 number->str = ast_strdup(value);
752                 ast_trim_blanks(number->str);
753         } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
754                 number->valid = atoi(value) ? 1 : 0;
755         } else if (argc == 1 && !strcasecmp("plan", argv[0])) {
756                 val = ast_strdupa(value);
757                 ast_trim_blanks(val);
758
759                 if (('0' <= val[0]) && (val[0] <= '9')) {
760                         number->plan = atoi(val);
761                 } else {
762                         ast_log(LOG_ERROR,
763                                 "Unknown type-of-number/numbering-plan '%s', value unchanged\n", val);
764                         status = ID_FIELD_INVALID;
765                 }
766         } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
767                 int pres;
768
769                 /* Accept pres[entation] */
770                 val = ast_strdupa(value);
771                 ast_trim_blanks(val);
772
773                 if (('0' <= val[0]) && (val[0] <= '9')) {
774                         pres = atoi(val);
775                 } else {
776                         pres = ast_parse_caller_presentation(val);
777                 }
778
779                 if (pres < 0) {
780                         ast_log(LOG_ERROR,
781                                 "Unknown number presentation '%s', value unchanged\n", val);
782                         status = ID_FIELD_INVALID;
783                 } else {
784                         number->presentation = pres;
785                 }
786         } else {
787                 status = ID_FIELD_UNKNOWN;
788         }
789
790         return status;
791 }
792
793 /*!
794  * \internal
795  * \brief Write new values to the party subaddress struct
796  * \since 1.8
797  *
798  * \param subaddress Party subaddress struct to write values
799  * \param argc Number of party member subnames.
800  * \param argv Party member subnames given.
801  * \param value Value to assign to the party subaddress.
802  *
803  * \retval ID_FIELD_VALID on success.
804  * \retval ID_FIELD_INVALID on error with field value.
805  * \retval ID_FIELD_UNKNOWN on unknown field name.
806  */
807 static enum ID_FIELD_STATUS party_subaddress_write(struct ast_party_subaddress *subaddress, int argc, char *argv[], const char *value)
808 {
809         enum ID_FIELD_STATUS status;
810
811         status = ID_FIELD_VALID;
812
813         if (argc == 0) {
814                 /* We are setting the subaddress string */
815                 subaddress->str = ast_strdup(value);
816                 ast_trim_blanks(subaddress->str);
817         } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
818                 subaddress->valid = atoi(value) ? 1 : 0;
819         } else if (argc == 1 && !strcasecmp("type", argv[0])) {
820                 subaddress->type = atoi(value) ? 2 : 0;
821         } else if (argc == 1 && !strcasecmp("odd", argv[0])) {
822                 subaddress->odd_even_indicator = atoi(value) ? 1 : 0;
823         } else {
824                 status = ID_FIELD_UNKNOWN;
825         }
826
827         return status;
828 }
829
830 /*!
831  * \internal
832  * \brief Write new values to the party id struct
833  * \since 1.8
834  *
835  * \param id Party ID struct to write values
836  * \param argc Number of party member subnames.
837  * \param argv Party member subnames given.
838  * \param value Value to assign to the party id.
839  *
840  * \retval ID_FIELD_VALID on success.
841  * \retval ID_FIELD_INVALID on error with field value.
842  * \retval ID_FIELD_UNKNOWN on unknown field name.
843  */
844 static enum ID_FIELD_STATUS party_id_write(struct ast_party_id *id, int argc, char *argv[], const char *value)
845 {
846         char *val;
847         enum ID_FIELD_STATUS status;
848
849         if (argc == 0) {
850                 /* Must have at least one subname. */
851                 return ID_FIELD_UNKNOWN;
852         }
853
854         status = ID_FIELD_VALID;
855
856         if (argc == 1 && !strcasecmp("all", argv[0])) {
857                 char name[256];
858                 char num[256];
859
860                 ast_callerid_split(value, name, sizeof(name), num, sizeof(num));
861                 id->name.valid = 1;
862                 id->name.str = ast_strdup(name);
863                 if (!id->name.str) {
864                         return ID_FIELD_INVALID;
865                 }
866                 id->number.valid = 1;
867                 id->number.str = ast_strdup(num);
868                 if (!id->number.str) {
869                         return ID_FIELD_INVALID;
870                 }
871         } else if (!strcasecmp("name", argv[0])) {
872                 status = party_name_write(&id->name, argc - 1, argv + 1, value);
873         } else if (!strncasecmp("num", argv[0], 3)) {
874                 /* Accept num[ber] */
875                 status = party_number_write(&id->number, argc - 1, argv + 1, value);
876         } else if (!strncasecmp("subaddr", argv[0], 7)) {
877                 /* Accept subaddr[ess] */
878                 status = party_subaddress_write(&id->subaddress, argc - 1, argv + 1, value);
879         } else if (argc == 1 && !strcasecmp("tag", argv[0])) {
880                 id->tag = ast_strdup(value);
881                 ast_trim_blanks(id->tag);
882         } else if (argc == 1 && !strcasecmp("ton", argv[0])) {
883                 /* ton is an alias for num-plan */
884                 argv[0] = "plan";
885                 status = party_number_write(&id->number, argc, argv, value);
886         } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
887                 int pres;
888
889                 /*
890                  * Accept pres[entation]
891                  * This is the combined name/number presentation.
892                  */
893                 val = ast_strdupa(value);
894                 ast_trim_blanks(val);
895
896                 if (('0' <= val[0]) && (val[0] <= '9')) {
897                         pres = atoi(val);
898                 } else {
899                         pres = ast_parse_caller_presentation(val);
900                 }
901
902                 if (pres < 0) {
903                         ast_log(LOG_ERROR,
904                                 "Unknown combined presentation '%s', value unchanged\n", val);
905                         status = ID_FIELD_INVALID;
906                 } else {
907                         id->name.presentation = pres;
908                         id->number.presentation = pres;
909                 }
910         } else {
911                 status = ID_FIELD_UNKNOWN;
912         }
913
914         return status;
915 }
916
917 /*!
918  * \internal
919  * \brief Read values from the caller-id information struct.
920  *
921  * \param chan Asterisk channel to read
922  * \param cmd Not used
923  * \param data Caller-id function datatype string
924  * \param buf Buffer to fill with read value.
925  * \param len Length of the buffer
926  *
927  * \retval 0 on success.
928  * \retval -1 on error.
929  */
930 static int callerid_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
931 {
932         char *parms;
933         struct ast_party_members member = { 0, };
934         AST_DECLARE_APP_ARGS(args,
935                 AST_APP_ARG(member);    /*!< Member name */
936                 AST_APP_ARG(cid);               /*!< Optional caller id to parse instead of from the channel. */
937                 );
938
939         /* Ensure that the buffer is empty */
940         *buf = 0;
941
942         if (!chan) {
943                 return -1;
944         }
945
946         parms = ast_strdupa(data);
947         AST_STANDARD_APP_ARGS(args, parms);
948         if (args.argc == 0) {
949                 /* Must have at least one argument. */
950                 return -1;
951         }
952
953         AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
954         if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
955                 /* Too few or too many subnames */
956                 return -1;
957         }
958
959         if (args.argc == 2) {
960                 char name[80];
961                 char num[80];
962
963                 ast_callerid_split(args.cid, name, sizeof(name), num, sizeof(num));
964
965                 if (member.argc == 1 && !strcasecmp("all", member.argv[0])) {
966                         snprintf(buf, len, "\"%s\" <%s>", name, num);
967                 } else if (member.argc == 1 && !strcasecmp("name", member.argv[0])) {
968                         ast_copy_string(buf, name, len);
969                 } else if (member.argc == 1 && !strncasecmp("num", member.argv[0], 3)) {
970                         /* Accept num[ber] */
971                         ast_copy_string(buf, num, len);
972                 } else {
973                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
974                 }
975         } else {
976                 enum ID_FIELD_STATUS status;
977                 ast_channel_lock(chan);
978
979                 if (member.argc == 1 && !strcasecmp("rdnis", member.argv[0])) {
980                         if (ast_channel_redirecting(chan)->from.number.valid
981                                 && ast_channel_redirecting(chan)->from.number.str) {
982                                 ast_copy_string(buf, ast_channel_redirecting(chan)->from.number.str, len);
983                         }
984                 } else if (!strcasecmp("dnid", member.argv[0])) {
985                         if (member.argc == 1) {
986                                 /* Setup as if user had given dnid-num instead. */
987                                 member.argc = 2;
988                                 member.argv[1] = "num";
989                         }
990                         if (!strncasecmp("num", member.argv[1], 3)) {
991                                 /*
992                                  * Accept num[ber]
993                                  * dnid-num...
994                                  */
995                                 if (member.argc == 2) {
996                                         /* dnid-num */
997                                         if (ast_channel_dialed(chan)->number.str) {
998                                                 ast_copy_string(buf, ast_channel_dialed(chan)->number.str, len);
999                                         }
1000                                 } else if (member.argc == 3 && !strcasecmp("plan", member.argv[2])) {
1001                                         /* dnid-num-plan */
1002                                         snprintf(buf, len, "%d", ast_channel_dialed(chan)->number.plan);
1003                                 } else {
1004                                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1005                                 }
1006                         } else if (!strncasecmp("subaddr", member.argv[1], 7)) {
1007                                 /*
1008                                  * Accept subaddr[ess]
1009                                  * dnid-subaddr...
1010                                  */
1011                                 status = party_subaddress_read(buf, len, member.argc - 2, member.argv + 2,
1012                                         &ast_channel_dialed(chan)->subaddress);
1013                                 switch (status) {
1014                                 case ID_FIELD_VALID:
1015                                 case ID_FIELD_INVALID:
1016                                         break;
1017                                 default:
1018                                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1019                                         break;
1020                                 }
1021                         } else {
1022                                 ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1023                         }
1024                 } else if (member.argc == 1 && !strcasecmp("ani2", member.argv[0])) {
1025                         snprintf(buf, len, "%d", ast_channel_caller(chan)->ani2);
1026                 } else if (!strcasecmp("ani", member.argv[0])) {
1027                         if (member.argc == 1) {
1028                                 /* Setup as if user had given ani-num instead. */
1029                                 member.argc = 2;
1030                                 member.argv[1] = "num";
1031                         }
1032                         status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
1033                                 &ast_channel_caller(chan)->ani);
1034                         switch (status) {
1035                         case ID_FIELD_VALID:
1036                         case ID_FIELD_INVALID:
1037                                 break;
1038                         default:
1039                                 ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1040                                 break;
1041                         }
1042                 } else if (!strcasecmp("priv", member.argv[0])) {
1043                         status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
1044                                 &ast_channel_caller(chan)->priv);
1045                         switch (status) {
1046                         case ID_FIELD_VALID:
1047                         case ID_FIELD_INVALID:
1048                                 break;
1049                         default:
1050                                 ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1051                                 break;
1052                         }
1053                 } else {
1054                         status = party_id_read(buf, len, member.argc, member.argv, &ast_channel_caller(chan)->id);
1055                         switch (status) {
1056                         case ID_FIELD_VALID:
1057                         case ID_FIELD_INVALID:
1058                                 break;
1059                         default:
1060                                 ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1061                                 break;
1062                         }
1063                 }
1064
1065                 ast_channel_unlock(chan);
1066         }
1067
1068         return 0;
1069 }
1070
1071 /*!
1072  * \internal
1073  * \brief Write new values to the caller-id information struct.
1074  *
1075  * \param chan Asterisk channel to update
1076  * \param cmd Not used
1077  * \param data Caller-id function datatype string
1078  * \param value Value to assign to the caller-id information struct.
1079  *
1080  * \retval 0 on success.
1081  * \retval -1 on error.
1082  */
1083 static int callerid_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
1084 {
1085         struct ast_party_caller caller;
1086         struct ast_party_dialed dialed;
1087         enum ID_FIELD_STATUS status;
1088         char *val;
1089         char *parms;
1090         struct ast_party_func_args args = { 0, };
1091         struct ast_party_members member = { 0, };
1092
1093         if (!value || !chan) {
1094                 return -1;
1095         }
1096
1097         parms = ast_strdupa(data);
1098         AST_STANDARD_APP_ARGS(args, parms);
1099         if (args.argc == 0) {
1100                 /* Must have at least one argument. */
1101                 return -1;
1102         }
1103
1104         AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
1105         if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
1106                 /* Too few or too many subnames */
1107                 return -1;
1108         }
1109
1110         value = ast_skip_blanks(value);
1111
1112         ast_channel_lock(chan);
1113         if (member.argc == 1 && !strcasecmp("rdnis", member.argv[0])) {
1114                 ast_channel_redirecting(chan)->from.number.valid = 1;
1115                 ast_free(ast_channel_redirecting(chan)->from.number.str);
1116                 ast_channel_redirecting(chan)->from.number.str = ast_strdup(value);
1117         } else if (!strcasecmp("dnid", member.argv[0])) {
1118                 ast_party_dialed_set_init(&dialed, ast_channel_dialed(chan));
1119                 if (member.argc == 1) {
1120                         /* Setup as if user had given dnid-num instead. */
1121                         member.argc = 2;
1122                         member.argv[1] = "num";
1123                 }
1124                 if (!strncasecmp("num", member.argv[1], 3)) {
1125                         /*
1126                          * Accept num[ber]
1127                          * dnid-num...
1128                          */
1129                         if (member.argc == 2) {
1130                                 /* dnid-num */
1131                                 dialed.number.str = ast_strdup(value);
1132                                 ast_trim_blanks(dialed.number.str);
1133                                 ast_party_dialed_set(ast_channel_dialed(chan), &dialed);
1134                         } else if (member.argc == 3 && !strcasecmp("plan", member.argv[2])) {
1135                                 /* dnid-num-plan */
1136                                 val = ast_strdupa(value);
1137                                 ast_trim_blanks(val);
1138
1139                                 if (('0' <= val[0]) && (val[0] <= '9')) {
1140                                         ast_channel_dialed(chan)->number.plan = atoi(val);
1141                                 } else {
1142                                         ast_log(LOG_ERROR,
1143                                                 "Unknown type-of-number/numbering-plan '%s', value unchanged\n", val);
1144                                 }
1145                         } else {
1146                                 ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1147                         }
1148                 } else if (!strncasecmp("subaddr", member.argv[1], 7)) {
1149                         /*
1150                          * Accept subaddr[ess]
1151                          * dnid-subaddr...
1152                          */
1153                         status = party_subaddress_write(&dialed.subaddress, member.argc - 2,
1154                                 member.argv + 2, value);
1155                         switch (status) {
1156                         case ID_FIELD_VALID:
1157                                 ast_party_dialed_set(ast_channel_dialed(chan), &dialed);
1158                                 break;
1159                         case ID_FIELD_INVALID:
1160                                 break;
1161                         default:
1162                                 ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1163                                 break;
1164                         }
1165                 } else {
1166                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1167                 }
1168                 ast_party_dialed_free(&dialed);
1169         } else if (member.argc == 1 && !strcasecmp("ani2", member.argv[0])) {
1170                 val = ast_strdupa(value);
1171                 ast_trim_blanks(val);
1172
1173                 if (('0' <= val[0]) && (val[0] <= '9')) {
1174                         ast_channel_caller(chan)->ani2 = atoi(val);
1175                 } else {
1176                         ast_log(LOG_ERROR, "Unknown callerid ani2 '%s', value unchanged\n", val);
1177                 }
1178         } else if (!strcasecmp("ani", member.argv[0])) {
1179                 ast_party_caller_set_init(&caller, ast_channel_caller(chan));
1180                 if (member.argc == 1) {
1181                         /* Setup as if user had given ani-num instead. */
1182                         member.argc = 2;
1183                         member.argv[1] = "num";
1184                 }
1185                 status = party_id_write(&caller.ani, member.argc - 1, member.argv + 1, value);
1186                 switch (status) {
1187                 case ID_FIELD_VALID:
1188                         ast_party_caller_set(ast_channel_caller(chan), &caller, NULL);
1189                         break;
1190                 case ID_FIELD_INVALID:
1191                         break;
1192                 default:
1193                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1194                         break;
1195                 }
1196                 ast_party_caller_free(&caller);
1197         } else if (!strcasecmp("priv", member.argv[0])) {
1198                 ast_party_caller_set_init(&caller, ast_channel_caller(chan));
1199                 status = party_id_write(&caller.priv, member.argc - 1, member.argv + 1, value);
1200                 switch (status) {
1201                 case ID_FIELD_VALID:
1202                         ast_party_caller_set(ast_channel_caller(chan), &caller, NULL);
1203                         break;
1204                 case ID_FIELD_INVALID:
1205                         break;
1206                 default:
1207                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1208                         break;
1209                 }
1210                 ast_party_caller_free(&caller);
1211         } else {
1212                 ast_party_caller_set_init(&caller, ast_channel_caller(chan));
1213                 status = party_id_write(&caller.id, member.argc, member.argv, value);
1214                 switch (status) {
1215                 case ID_FIELD_VALID:
1216                         ast_channel_set_caller_event(chan, &caller, NULL);
1217                         break;
1218                 case ID_FIELD_INVALID:
1219                         break;
1220                 default:
1221                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1222                         break;
1223                 }
1224                 ast_party_caller_free(&caller);
1225         }
1226         ast_channel_unlock(chan);
1227
1228         return 0;
1229 }
1230
1231 /*!
1232  * \internal
1233  * \brief Read values from the connected line information struct.
1234  *
1235  * \param chan Asterisk channel to read
1236  * \param cmd Not used
1237  * \param data Connected line function datatype string
1238  * \param buf Buffer to fill with read value.
1239  * \param len Length of the buffer
1240  *
1241  * \retval 0 on success.
1242  * \retval -1 on error.
1243  */
1244 static int connectedline_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
1245 {
1246         struct ast_party_members member = { 0, };
1247         char *read_what;
1248         enum ID_FIELD_STATUS status;
1249
1250         /* Ensure that the buffer is empty */
1251         *buf = 0;
1252
1253         if (!chan) {
1254                 return -1;
1255         }
1256
1257         read_what = ast_strdupa(data);
1258         AST_NONSTANDARD_APP_ARGS(member, read_what, '-');
1259         if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
1260                 /* Too few or too many subnames */
1261                 return -1;
1262         }
1263
1264         ast_channel_lock(chan);
1265
1266         if (member.argc == 1 && !strcasecmp("source", member.argv[0])) {
1267                 ast_copy_string(buf, ast_connected_line_source_name(ast_channel_connected(chan)->source), len);
1268         } else if (!strcasecmp("priv", member.argv[0])) {
1269                 status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
1270                         &ast_channel_connected(chan)->priv);
1271                 switch (status) {
1272                 case ID_FIELD_VALID:
1273                 case ID_FIELD_INVALID:
1274                         break;
1275                 default:
1276                         ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
1277                         break;
1278                 }
1279         } else {
1280                 status = party_id_read(buf, len, member.argc, member.argv, &ast_channel_connected(chan)->id);
1281                 switch (status) {
1282                 case ID_FIELD_VALID:
1283                 case ID_FIELD_INVALID:
1284                         break;
1285                 default:
1286                         ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
1287                         break;
1288                 }
1289         }
1290
1291         ast_channel_unlock(chan);
1292
1293         return 0;
1294 }
1295
1296 /*!
1297  * \internal
1298  * \brief Write new values to the connected line information struct.
1299  *
1300  * \param chan Asterisk channel to update
1301  * \param cmd Not used
1302  * \param data Connected line function datatype string
1303  * \param value Value to assign to the connected line information struct.
1304  *
1305  * \retval 0 on success.
1306  * \retval -1 on error.
1307  */
1308 static int connectedline_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
1309 {
1310         struct ast_party_connected_line connected;
1311         char *val;
1312         char *parms;
1313         void (*set_it)(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update);
1314         struct ast_party_func_args args = { 0, };
1315         struct ast_party_members member = { 0, };
1316         struct ast_flags opts;
1317         char *opt_args[CONNECTED_LINE_OPT_ARG_ARRAY_SIZE];
1318         enum ID_FIELD_STATUS status;
1319
1320         if (!value || !chan) {
1321                 return -1;
1322         }
1323
1324         parms = ast_strdupa(data);
1325         AST_STANDARD_APP_ARGS(args, parms);
1326         if (args.argc == 0) {
1327                 /* Must have at least one argument. */
1328                 return -1;
1329         }
1330
1331         AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
1332         if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
1333                 /* Too few or too many subnames */
1334                 return -1;
1335         }
1336
1337         if (ast_app_parse_options(connectedline_opts, &opts, opt_args, args.opts)) {
1338                 /* General invalid option syntax. */
1339                 return -1;
1340         }
1341
1342         /* Determine if the update indication inhibit option is present */
1343         if (ast_test_flag(&opts, CONNECTED_LINE_OPT_INHIBIT)) {
1344                 set_it = ast_channel_set_connected_line;
1345         } else {
1346                 set_it = ast_channel_update_connected_line;
1347         }
1348
1349         ast_channel_lock(chan);
1350         ast_party_connected_line_set_init(&connected, ast_channel_connected(chan));
1351         ast_channel_unlock(chan);
1352
1353         value = ast_skip_blanks(value);
1354
1355         if (member.argc == 1 && !strcasecmp("source", member.argv[0])) {
1356                 int source;
1357
1358                 val = ast_strdupa(value);
1359                 ast_trim_blanks(val);
1360
1361                 if (('0' <= val[0]) && (val[0] <= '9')) {
1362                         source = atoi(val);
1363                 } else {
1364                         source = ast_connected_line_source_parse(val);
1365                 }
1366
1367                 if (source < 0) {
1368                         ast_log(LOG_ERROR, "Unknown connectedline source '%s', value unchanged\n", val);
1369                 } else {
1370                         connected.source = source;
1371                         set_it(chan, &connected, NULL);
1372                 }
1373         } else if (!strcasecmp("priv", member.argv[0])) {
1374                 status = party_id_write(&connected.priv, member.argc - 1, member.argv + 1, value);
1375                 switch (status) {
1376                 case ID_FIELD_VALID:
1377                         set_it(chan, &connected, NULL);
1378                         break;
1379                 case ID_FIELD_INVALID:
1380                         break;
1381                 default:
1382                         ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
1383                         break;
1384                 }
1385                 ast_party_connected_line_free(&connected);
1386         } else {
1387                 status = party_id_write(&connected.id, member.argc, member.argv, value);
1388                 switch (status) {
1389                 case ID_FIELD_VALID:
1390                         set_it(chan, &connected, NULL);
1391                         break;
1392                 case ID_FIELD_INVALID:
1393                         break;
1394                 default:
1395                         ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
1396                         break;
1397                 }
1398                 ast_party_connected_line_free(&connected);
1399         }
1400
1401         return 0;
1402 }
1403
1404 /*!
1405  * \internal
1406  * \brief Read values from the redirecting information struct.
1407  *
1408  * \param chan Asterisk channel to read
1409  * \param cmd Not used
1410  * \param data Redirecting function datatype string
1411  * \param buf Buffer to fill with read value.
1412  * \param len Length of the buffer
1413  *
1414  * \retval 0 on success.
1415  * \retval -1 on error.
1416  */
1417 static int redirecting_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
1418 {
1419         struct ast_party_members member = { 0, };
1420         char *read_what;
1421         const struct ast_party_redirecting *ast_redirecting;
1422         enum ID_FIELD_STATUS status;
1423
1424         /* Ensure that the buffer is empty */
1425         *buf = 0;
1426
1427         if (!chan) {
1428                 return -1;
1429         }
1430
1431         read_what = ast_strdupa(data);
1432         AST_NONSTANDARD_APP_ARGS(member, read_what, '-');
1433         if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
1434                 /* Too few or too many subnames */
1435                 return -1;
1436         }
1437
1438         ast_channel_lock(chan);
1439
1440         ast_redirecting = ast_channel_redirecting(chan);
1441         if (!strcasecmp("orig", member.argv[0])) {
1442                 if (member.argc == 2 && !strcasecmp("reason", member.argv[1])) {
1443                         ast_copy_string(buf,
1444                                 ast_redirecting_reason_name(&ast_redirecting->orig_reason), len);
1445                 } else {
1446                         status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
1447                                 &ast_redirecting->orig);
1448                         switch (status) {
1449                         case ID_FIELD_VALID:
1450                         case ID_FIELD_INVALID:
1451                                 break;
1452                         default:
1453                                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1454                                 break;
1455                         }
1456                 }
1457         } else if (!strcasecmp("from", member.argv[0])) {
1458                 status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
1459                         &ast_redirecting->from);
1460                 switch (status) {
1461                 case ID_FIELD_VALID:
1462                 case ID_FIELD_INVALID:
1463                         break;
1464                 default:
1465                         ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1466                         break;
1467                 }
1468         } else if (!strcasecmp("to", member.argv[0])) {
1469                 status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
1470                         &ast_redirecting->to);
1471                 switch (status) {
1472                 case ID_FIELD_VALID:
1473                 case ID_FIELD_INVALID:
1474                         break;
1475                 default:
1476                         ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1477                         break;
1478                 }
1479         } else if (member.argc == 1 && !strncasecmp("pres", member.argv[0], 4)) {
1480                 /*
1481                  * Accept pres[entation]
1482                  * This is the combined from name/number presentation.
1483                  */
1484                 ast_copy_string(buf,
1485                         ast_named_caller_presentation(
1486                                 ast_party_id_presentation(&ast_redirecting->from)), len);
1487         } else if (member.argc == 1 && !strcasecmp("reason", member.argv[0])) {
1488                 ast_copy_string(buf, ast_redirecting_reason_name(&ast_redirecting->reason), len);
1489         } else if (member.argc == 1 && !strcasecmp("count", member.argv[0])) {
1490                 snprintf(buf, len, "%d", ast_redirecting->count);
1491         } else if (1 < member.argc && !strcasecmp("priv", member.argv[0])) {
1492                 if (!strcasecmp("orig", member.argv[1])) {
1493                         status = party_id_read(buf, len, member.argc - 2, member.argv + 2,
1494                                 &ast_redirecting->priv_orig);
1495                         switch (status) {
1496                         case ID_FIELD_VALID:
1497                         case ID_FIELD_INVALID:
1498                                 break;
1499                         default:
1500                                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1501                                 break;
1502                         }
1503                 } else if (!strcasecmp("from", member.argv[1])) {
1504                         status = party_id_read(buf, len, member.argc - 2, member.argv + 2,
1505                                 &ast_redirecting->priv_from);
1506                         switch (status) {
1507                         case ID_FIELD_VALID:
1508                         case ID_FIELD_INVALID:
1509                                 break;
1510                         default:
1511                                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1512                                 break;
1513                         }
1514                 } else if (!strcasecmp("to", member.argv[1])) {
1515                         status = party_id_read(buf, len, member.argc - 2, member.argv + 2,
1516                                 &ast_redirecting->priv_to);
1517                         switch (status) {
1518                         case ID_FIELD_VALID:
1519                         case ID_FIELD_INVALID:
1520                                 break;
1521                         default:
1522                                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1523                                 break;
1524                         }
1525                 } else {
1526                         ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1527                 }
1528         } else {
1529                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1530         }
1531
1532         ast_channel_unlock(chan);
1533
1534         return 0;
1535 }
1536
1537 /*!
1538  * \internal
1539  * \brief Write new values to the redirecting information struct.
1540  *
1541  * \param chan Asterisk channel to update
1542  * \param cmd Not used
1543  * \param data Redirecting function datatype string
1544  * \param value Value to assign to the redirecting information struct.
1545  *
1546  * \retval 0 on success.
1547  * \retval -1 on error.
1548  */
1549 static int redirecting_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
1550 {
1551         struct ast_party_redirecting redirecting;
1552         enum ID_FIELD_STATUS status;
1553         char *val;
1554         char *parms;
1555         void (*set_it)(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update);
1556         struct ast_party_func_args args = { 0, };
1557         struct ast_party_members member = { 0, };
1558         struct ast_flags opts;
1559         char *opt_args[REDIRECTING_OPT_ARG_ARRAY_SIZE];
1560
1561         if (!value || !chan) {
1562                 return -1;
1563         }
1564
1565         parms = ast_strdupa(data);
1566         AST_STANDARD_APP_ARGS(args, parms);
1567         if (args.argc == 0) {
1568                 /* Must have at least one argument. */
1569                 return -1;
1570         }
1571
1572         AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
1573         if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
1574                 /* Too few or too many subnames */
1575                 return -1;
1576         }
1577
1578         if (ast_app_parse_options(redirecting_opts, &opts, opt_args, args.opts)) {
1579                 /* General invalid option syntax. */
1580                 return -1;
1581         }
1582
1583         /* Determine if the update indication inhibit option is present */
1584         if (ast_test_flag(&opts, REDIRECTING_OPT_INHIBIT)) {
1585                 set_it = ast_channel_set_redirecting;
1586         } else {
1587                 set_it = ast_channel_update_redirecting;
1588         }
1589
1590         ast_channel_lock(chan);
1591         ast_party_redirecting_set_init(&redirecting, ast_channel_redirecting(chan));
1592         ast_channel_unlock(chan);
1593
1594         value = ast_skip_blanks(value);
1595
1596         if (!strcasecmp("orig", member.argv[0])) {
1597                 if (member.argc == 2 && !strcasecmp("reason", member.argv[1])) {
1598                         int reason;
1599
1600                         val = ast_strdupa(value);
1601                         ast_trim_blanks(val);
1602
1603                         if (('0' <= val[0]) && (val[0] <= '9')) {
1604                                 reason = atoi(val);
1605                         } else {
1606                                 reason = ast_redirecting_reason_parse(val);
1607                         }
1608
1609                         if (reason < 0) {
1610                         /* The argument passed into the function does not correspond to a pre-defined
1611                          * reason, so we can just set the reason string to what was given and set the
1612                          * code to be unknown
1613                          */
1614                                 redirecting.orig_reason.code = AST_REDIRECTING_REASON_UNKNOWN;
1615                                 redirecting.orig_reason.str = val;
1616                                 set_it(chan, &redirecting, NULL);
1617                         } else {
1618                                 redirecting.orig_reason.code = reason;
1619                                 redirecting.orig_reason.str = "";
1620                                 set_it(chan, &redirecting, NULL);
1621                         }
1622                 } else {
1623                         status = party_id_write(&redirecting.orig, member.argc - 1, member.argv + 1,
1624                                 value);
1625                         switch (status) {
1626                         case ID_FIELD_VALID:
1627                                 set_it(chan, &redirecting, NULL);
1628                                 break;
1629                         case ID_FIELD_INVALID:
1630                                 break;
1631                         default:
1632                                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1633                                 break;
1634                         }
1635                         ast_party_redirecting_free(&redirecting);
1636                 }
1637         } else if (!strcasecmp("from", member.argv[0])) {
1638                 status = party_id_write(&redirecting.from, member.argc - 1, member.argv + 1,
1639                         value);
1640                 switch (status) {
1641                 case ID_FIELD_VALID:
1642                         set_it(chan, &redirecting, NULL);
1643                         break;
1644                 case ID_FIELD_INVALID:
1645                         break;
1646                 default:
1647                         ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1648                         break;
1649                 }
1650                 ast_party_redirecting_free(&redirecting);
1651         } else if (!strcasecmp("to", member.argv[0])) {
1652                 status = party_id_write(&redirecting.to, member.argc - 1, member.argv + 1, value);
1653                 switch (status) {
1654                 case ID_FIELD_VALID:
1655                         set_it(chan, &redirecting, NULL);
1656                         break;
1657                 case ID_FIELD_INVALID:
1658                         break;
1659                 default:
1660                         ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1661                         break;
1662                 }
1663                 ast_party_redirecting_free(&redirecting);
1664         } else if (member.argc == 1 && !strncasecmp("pres", member.argv[0], 4)) {
1665                 int pres;
1666
1667                 val = ast_strdupa(value);
1668                 ast_trim_blanks(val);
1669
1670                 if (('0' <= val[0]) && (val[0] <= '9')) {
1671                         pres = atoi(val);
1672                 } else {
1673                         pres = ast_parse_caller_presentation(val);
1674                 }
1675
1676                 if (pres < 0) {
1677                         ast_log(LOG_ERROR,
1678                                 "Unknown redirecting combined presentation '%s', value unchanged\n", val);
1679                 } else {
1680                         redirecting.from.name.presentation = pres;
1681                         redirecting.from.number.presentation = pres;
1682                         redirecting.to.name.presentation = pres;
1683                         redirecting.to.number.presentation = pres;
1684                         set_it(chan, &redirecting, NULL);
1685                 }
1686         } else if (member.argc == 1 && !strcasecmp("reason", member.argv[0])) {
1687                 int reason;
1688
1689                 val = ast_strdupa(value);
1690                 ast_trim_blanks(val);
1691
1692                 if (('0' <= val[0]) && (val[0] <= '9')) {
1693                         reason = atoi(val);
1694                 } else {
1695                         reason = ast_redirecting_reason_parse(val);
1696                 }
1697
1698                 if (reason < 0) {
1699                         /* The argument passed into the function does not correspond to a pre-defined
1700                          * reason, so we can just set the reason string to what was given and set the
1701                          * code to be unknown
1702                          */
1703                         redirecting.reason.code = AST_REDIRECTING_REASON_UNKNOWN;
1704                         redirecting.reason.str = val;
1705                         set_it(chan, &redirecting, NULL);
1706                 } else {
1707                         redirecting.reason.code = reason;
1708                         redirecting.reason.str = "";
1709                         set_it(chan, &redirecting, NULL);
1710                 }
1711         } else if (member.argc == 1 && !strcasecmp("count", member.argv[0])) {
1712                 val = ast_strdupa(value);
1713                 ast_trim_blanks(val);
1714
1715                 if (('0' <= val[0]) && (val[0] <= '9')) {
1716                         redirecting.count = atoi(val);
1717                         set_it(chan, &redirecting, NULL);
1718                 } else {
1719                         ast_log(LOG_ERROR, "Unknown redirecting count '%s', value unchanged\n", val);
1720                 }
1721         } else if (1 < member.argc && !strcasecmp("priv", member.argv[0])) {
1722                 if (!strcasecmp("orig", member.argv[1])) {
1723                         status = party_id_write(&redirecting.priv_orig, member.argc - 2, member.argv + 2,
1724                                 value);
1725                         switch (status) {
1726                         case ID_FIELD_VALID:
1727                                 set_it(chan, &redirecting, NULL);
1728                                 break;
1729                         case ID_FIELD_INVALID:
1730                                 break;
1731                         default:
1732                                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1733                                 break;
1734                         }
1735                         ast_party_redirecting_free(&redirecting);
1736                 } else if (!strcasecmp("from", member.argv[1])) {
1737                         status = party_id_write(&redirecting.priv_from, member.argc - 2, member.argv + 2,
1738                                 value);
1739                         switch (status) {
1740                         case ID_FIELD_VALID:
1741                                 set_it(chan, &redirecting, NULL);
1742                                 break;
1743                         case ID_FIELD_INVALID:
1744                                 break;
1745                         default:
1746                                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1747                                 break;
1748                         }
1749                         ast_party_redirecting_free(&redirecting);
1750                 } else if (!strcasecmp("to", member.argv[1])) {
1751                         status = party_id_write(&redirecting.priv_to, member.argc - 2, member.argv + 2, value);
1752                         switch (status) {
1753                         case ID_FIELD_VALID:
1754                                 set_it(chan, &redirecting, NULL);
1755                                 break;
1756                         case ID_FIELD_INVALID:
1757                                 break;
1758                         default:
1759                                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1760                                 break;
1761                         }
1762                         ast_party_redirecting_free(&redirecting);
1763                 } else {
1764                         ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1765                 }
1766         } else {
1767                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1768         }
1769
1770         return 0;
1771 }
1772
1773 static struct ast_custom_function callerid_function = {
1774         .name = "CALLERID",
1775         .read = callerid_read,
1776         .read_max = 256,
1777         .write = callerid_write,
1778 };
1779
1780 static struct ast_custom_function connectedline_function = {
1781         .name = "CONNECTEDLINE",
1782         .read = connectedline_read,
1783         .write = connectedline_write,
1784 };
1785
1786 static struct ast_custom_function redirecting_function = {
1787         .name = "REDIRECTING",
1788         .read = redirecting_read,
1789         .write = redirecting_write,
1790 };
1791
1792 /*!
1793  * \internal
1794  * \brief Unload the function module
1795  *
1796  * \retval 0 on success.
1797  * \retval -1 on error.
1798  */
1799 static int unload_module(void)
1800 {
1801         ast_custom_function_unregister(&callerid_function);
1802         ast_custom_function_unregister(&connectedline_function);
1803         ast_custom_function_unregister(&redirecting_function);
1804         return 0;
1805 }
1806
1807 /*!
1808  * \internal
1809  * \brief Load and initialize the function module.
1810  *
1811  * \retval AST_MODULE_LOAD_SUCCESS on success.
1812  * \retval AST_MODULE_LOAD_DECLINE on error.
1813  */
1814 static int load_module(void)
1815 {
1816         int res;
1817
1818         res = ast_custom_function_register(&callerid_function);
1819         res |= ast_custom_function_register(&connectedline_function);
1820         res |= ast_custom_function_register(&redirecting_function);
1821
1822         if (res) {
1823                 unload_module();
1824                 return AST_MODULE_LOAD_DECLINE;
1825         }
1826
1827         return AST_MODULE_LOAD_SUCCESS;
1828 }
1829
1830 /* Do not wrap the following line. */
1831 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Party ID related dialplan functions (Caller-ID, Connected-line, Redirecting)");