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