4f6a6779b47c58529cc3e3948c3d297129e77132
[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 (!chan) {
904                 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
905                 return -1;
906         }
907
908         if (!callerpres_deprecate_notify) {
909                 callerpres_deprecate_notify = 1;
910                 ast_log(LOG_WARNING, "CALLERPRES is deprecated."
911                         "  Use CALLERID(name-pres) or CALLERID(num-pres) instead.\n");
912         }
913         ast_copy_string(buf,
914                 ast_named_caller_presentation(ast_party_id_presentation(&ast_channel_caller(chan)->id)), len);
915         return 0;
916 }
917
918 /*!
919  * \internal
920  * \brief Write new values to the caller-id presentation information struct.
921  *
922  * \param chan Asterisk channel to update
923  * \param cmd Not used
924  * \param data Caller-id presentation function datatype string
925  * \param value Value to assign to the caller-id presentation information struct.
926  *
927  * \retval 0 on success.
928  * \retval -1 on error.
929  */
930 static int callerpres_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
931 {
932         int pres;
933
934         if (!chan) {
935                 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
936                 return -1;
937         }
938
939         if (!callerpres_deprecate_notify) {
940                 callerpres_deprecate_notify = 1;
941                 ast_log(LOG_WARNING, "CALLERPRES is deprecated."
942                         "  Use CALLERID(name-pres) or CALLERID(num-pres) instead.\n");
943         }
944
945         pres = ast_parse_caller_presentation(value);
946         if (pres < 0) {
947                 ast_log(LOG_WARNING, "'%s' is not a valid presentation (see 'show function CALLERPRES')\n", value);
948         } else {
949                 ast_channel_caller(chan)->id.name.presentation = pres;
950                 ast_channel_caller(chan)->id.number.presentation = pres;
951         }
952         return 0;
953 }
954
955 /*!
956  * \internal
957  * \brief Read values from the caller-id information struct.
958  *
959  * \param chan Asterisk channel to read
960  * \param cmd Not used
961  * \param data Caller-id function datatype string
962  * \param buf Buffer to fill with read value.
963  * \param len Length of the buffer
964  *
965  * \retval 0 on success.
966  * \retval -1 on error.
967  */
968 static int callerid_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
969 {
970         char *parms;
971         struct ast_party_members member;
972         AST_DECLARE_APP_ARGS(args,
973                 AST_APP_ARG(member);    /*!< Member name */
974                 AST_APP_ARG(cid);               /*!< Optional caller id to parse instead of from the channel. */
975                 );
976
977         /* Ensure that the buffer is empty */
978         *buf = 0;
979
980         if (!chan) {
981                 return -1;
982         }
983
984         parms = ast_strdupa(data);
985         AST_STANDARD_APP_ARGS(args, parms);
986         if (args.argc == 0) {
987                 /* Must have at least one argument. */
988                 return -1;
989         }
990
991         AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
992         if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
993                 /* Too few or too many subnames */
994                 return -1;
995         }
996
997         if (args.argc == 2) {
998                 char name[80];
999                 char num[80];
1000
1001                 ast_callerid_split(args.cid, name, sizeof(name), num, sizeof(num));
1002
1003                 if (member.argc == 1 && !strcasecmp("all", member.argv[0])) {
1004                         snprintf(buf, len, "\"%s\" <%s>", name, num);
1005                 } else if (member.argc == 1 && !strcasecmp("name", member.argv[0])) {
1006                         ast_copy_string(buf, name, len);
1007                 } else if (member.argc == 1 && !strncasecmp("num", member.argv[0], 3)) {
1008                         /* Accept num[ber] */
1009                         ast_copy_string(buf, num, len);
1010                 } else {
1011                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1012                 }
1013         } else {
1014                 enum ID_FIELD_STATUS status;
1015                 ast_channel_lock(chan);
1016
1017                 if (member.argc == 1 && !strcasecmp("rdnis", member.argv[0])) {
1018                         if (ast_channel_redirecting(chan)->from.number.valid
1019                                 && ast_channel_redirecting(chan)->from.number.str) {
1020                                 ast_copy_string(buf, ast_channel_redirecting(chan)->from.number.str, len);
1021                         }
1022                 } else if (!strcasecmp("dnid", member.argv[0])) {
1023                         if (member.argc == 1) {
1024                                 /* Setup as if user had given dnid-num instead. */
1025                                 member.argc = 2;
1026                                 member.argv[1] = "num";
1027                         }
1028                         if (!strncasecmp("num", member.argv[1], 3)) {
1029                                 /*
1030                                  * Accept num[ber]
1031                                  * dnid-num...
1032                                  */
1033                                 if (member.argc == 2) {
1034                                         /* dnid-num */
1035                                         if (ast_channel_dialed(chan)->number.str) {
1036                                                 ast_copy_string(buf, ast_channel_dialed(chan)->number.str, len);
1037                                         }
1038                                 } else if (member.argc == 3 && !strcasecmp("plan", member.argv[2])) {
1039                                         /* dnid-num-plan */
1040                                         snprintf(buf, len, "%d", ast_channel_dialed(chan)->number.plan);
1041                                 } else {
1042                                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1043                                 }
1044                         } else if (!strncasecmp("subaddr", member.argv[1], 7)) {
1045                                 /*
1046                                  * Accept subaddr[ess]
1047                                  * dnid-subaddr...
1048                                  */
1049                                 status = party_subaddress_read(buf, len, member.argc - 2, member.argv + 2,
1050                                         &ast_channel_dialed(chan)->subaddress);
1051                                 switch (status) {
1052                                 case ID_FIELD_VALID:
1053                                 case ID_FIELD_INVALID:
1054                                         break;
1055                                 default:
1056                                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1057                                         break;
1058                                 }
1059                         } else {
1060                                 ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1061                         }
1062                 } else if (member.argc == 1 && !strcasecmp("ani2", member.argv[0])) {
1063                         snprintf(buf, len, "%d", ast_channel_caller(chan)->ani2);
1064                 } else if (!strcasecmp("ani", member.argv[0])) {
1065                         if (member.argc == 1) {
1066                                 /* Setup as if user had given ani-num instead. */
1067                                 member.argc = 2;
1068                                 member.argv[1] = "num";
1069                         }
1070                         status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
1071                                 &ast_channel_caller(chan)->ani);
1072                         switch (status) {
1073                         case ID_FIELD_VALID:
1074                         case ID_FIELD_INVALID:
1075                                 break;
1076                         default:
1077                                 ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1078                                 break;
1079                         }
1080                 } else if (!strcasecmp("priv", member.argv[0])) {
1081                         status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
1082                                 &ast_channel_caller(chan)->priv);
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                 } else {
1092                         status = party_id_read(buf, len, member.argc, member.argv, &ast_channel_caller(chan)->id);
1093                         switch (status) {
1094                         case ID_FIELD_VALID:
1095                         case ID_FIELD_INVALID:
1096                                 break;
1097                         default:
1098                                 ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1099                                 break;
1100                         }
1101                 }
1102
1103                 ast_channel_unlock(chan);
1104         }
1105
1106         return 0;
1107 }
1108
1109 /*!
1110  * \internal
1111  * \brief Write new values to the caller-id information struct.
1112  *
1113  * \param chan Asterisk channel to update
1114  * \param cmd Not used
1115  * \param data Caller-id function datatype string
1116  * \param value Value to assign to the caller-id information struct.
1117  *
1118  * \retval 0 on success.
1119  * \retval -1 on error.
1120  */
1121 static int callerid_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
1122 {
1123         struct ast_party_caller caller;
1124         struct ast_party_dialed dialed;
1125         enum ID_FIELD_STATUS status;
1126         char *val;
1127         char *parms;
1128         struct ast_party_func_args args;
1129         struct ast_party_members member;
1130
1131         if (!value || !chan) {
1132                 return -1;
1133         }
1134
1135         parms = ast_strdupa(data);
1136         AST_STANDARD_APP_ARGS(args, parms);
1137         if (args.argc == 0) {
1138                 /* Must have at least one argument. */
1139                 return -1;
1140         }
1141
1142         AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
1143         if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
1144                 /* Too few or too many subnames */
1145                 return -1;
1146         }
1147
1148         value = ast_skip_blanks(value);
1149
1150         ast_channel_lock(chan);
1151         if (member.argc == 1 && !strcasecmp("rdnis", member.argv[0])) {
1152                 ast_channel_redirecting(chan)->from.number.valid = 1;
1153                 ast_free(ast_channel_redirecting(chan)->from.number.str);
1154                 ast_channel_redirecting(chan)->from.number.str = ast_strdup(value);
1155         } else if (!strcasecmp("dnid", member.argv[0])) {
1156                 ast_party_dialed_set_init(&dialed, ast_channel_dialed(chan));
1157                 if (member.argc == 1) {
1158                         /* Setup as if user had given dnid-num instead. */
1159                         member.argc = 2;
1160                         member.argv[1] = "num";
1161                 }
1162                 if (!strncasecmp("num", member.argv[1], 3)) {
1163                         /*
1164                          * Accept num[ber]
1165                          * dnid-num...
1166                          */
1167                         if (member.argc == 2) {
1168                                 /* dnid-num */
1169                                 dialed.number.str = ast_strdup(value);
1170                                 ast_trim_blanks(dialed.number.str);
1171                                 ast_party_dialed_set(ast_channel_dialed(chan), &dialed);
1172                         } else if (member.argc == 3 && !strcasecmp("plan", member.argv[2])) {
1173                                 /* dnid-num-plan */
1174                                 val = ast_strdupa(value);
1175                                 ast_trim_blanks(val);
1176
1177                                 if (('0' <= val[0]) && (val[0] <= '9')) {
1178                                         ast_channel_dialed(chan)->number.plan = atoi(val);
1179                                 } else {
1180                                         ast_log(LOG_ERROR,
1181                                                 "Unknown type-of-number/numbering-plan '%s', value unchanged\n", val);
1182                                 }
1183                         } else {
1184                                 ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1185                         }
1186                 } else if (!strncasecmp("subaddr", member.argv[1], 7)) {
1187                         /*
1188                          * Accept subaddr[ess]
1189                          * dnid-subaddr...
1190                          */
1191                         status = party_subaddress_write(&dialed.subaddress, member.argc - 2,
1192                                 member.argv + 2, value);
1193                         switch (status) {
1194                         case ID_FIELD_VALID:
1195                                 ast_party_dialed_set(ast_channel_dialed(chan), &dialed);
1196                                 break;
1197                         case ID_FIELD_INVALID:
1198                                 break;
1199                         default:
1200                                 ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1201                                 break;
1202                         }
1203                 } else {
1204                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1205                 }
1206                 ast_party_dialed_free(&dialed);
1207         } else if (member.argc == 1 && !strcasecmp("ani2", member.argv[0])) {
1208                 val = ast_strdupa(value);
1209                 ast_trim_blanks(val);
1210
1211                 if (('0' <= val[0]) && (val[0] <= '9')) {
1212                         ast_channel_caller(chan)->ani2 = atoi(val);
1213                 } else {
1214                         ast_log(LOG_ERROR, "Unknown callerid ani2 '%s', value unchanged\n", val);
1215                 }
1216         } else if (!strcasecmp("ani", member.argv[0])) {
1217                 ast_party_caller_set_init(&caller, ast_channel_caller(chan));
1218                 if (member.argc == 1) {
1219                         /* Setup as if user had given ani-num instead. */
1220                         member.argc = 2;
1221                         member.argv[1] = "num";
1222                 }
1223                 status = party_id_write(&caller.ani, member.argc - 1, member.argv + 1, value);
1224                 switch (status) {
1225                 case ID_FIELD_VALID:
1226                         ast_party_caller_set(ast_channel_caller(chan), &caller, NULL);
1227                         break;
1228                 case ID_FIELD_INVALID:
1229                         break;
1230                 default:
1231                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1232                         break;
1233                 }
1234                 ast_party_caller_free(&caller);
1235         } else if (!strcasecmp("priv", member.argv[0])) {
1236                 ast_party_caller_set_init(&caller, ast_channel_caller(chan));
1237                 status = party_id_write(&caller.priv, member.argc - 1, member.argv + 1, value);
1238                 switch (status) {
1239                 case ID_FIELD_VALID:
1240                         ast_party_caller_set(ast_channel_caller(chan), &caller, NULL);
1241                         break;
1242                 case ID_FIELD_INVALID:
1243                         break;
1244                 default:
1245                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1246                         break;
1247                 }
1248                 ast_party_caller_free(&caller);
1249         } else {
1250                 ast_party_caller_set_init(&caller, ast_channel_caller(chan));
1251                 status = party_id_write(&caller.id, member.argc, member.argv, value);
1252                 switch (status) {
1253                 case ID_FIELD_VALID:
1254                         ast_channel_set_caller_event(chan, &caller, NULL);
1255                         break;
1256                 case ID_FIELD_INVALID:
1257                         break;
1258                 default:
1259                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1260                         break;
1261                 }
1262                 ast_party_caller_free(&caller);
1263         }
1264         ast_channel_unlock(chan);
1265
1266         return 0;
1267 }
1268
1269 /*!
1270  * \internal
1271  * \brief Read values from the connected line information struct.
1272  *
1273  * \param chan Asterisk channel to read
1274  * \param cmd Not used
1275  * \param data Connected line function datatype string
1276  * \param buf Buffer to fill with read value.
1277  * \param len Length of the buffer
1278  *
1279  * \retval 0 on success.
1280  * \retval -1 on error.
1281  */
1282 static int connectedline_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
1283 {
1284         struct ast_party_members member;
1285         char *read_what;
1286         enum ID_FIELD_STATUS status;
1287
1288         /* Ensure that the buffer is empty */
1289         *buf = 0;
1290
1291         if (!chan) {
1292                 return -1;
1293         }
1294
1295         read_what = ast_strdupa(data);
1296         AST_NONSTANDARD_APP_ARGS(member, read_what, '-');
1297         if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
1298                 /* Too few or too many subnames */
1299                 return -1;
1300         }
1301
1302         ast_channel_lock(chan);
1303
1304         if (member.argc == 1 && !strcasecmp("source", member.argv[0])) {
1305                 ast_copy_string(buf, ast_connected_line_source_name(ast_channel_connected(chan)->source), len);
1306         } else if (!strcasecmp("priv", member.argv[0])) {
1307                 status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
1308                         &ast_channel_connected(chan)->priv);
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         } else {
1318                 status = party_id_read(buf, len, member.argc, member.argv, &ast_channel_connected(chan)->id);
1319                 switch (status) {
1320                 case ID_FIELD_VALID:
1321                 case ID_FIELD_INVALID:
1322                         break;
1323                 default:
1324                         ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
1325                         break;
1326                 }
1327         }
1328
1329         ast_channel_unlock(chan);
1330
1331         return 0;
1332 }
1333
1334 /*!
1335  * \internal
1336  * \brief Write new values to the connected line information struct.
1337  *
1338  * \param chan Asterisk channel to update
1339  * \param cmd Not used
1340  * \param data Connected line function datatype string
1341  * \param value Value to assign to the connected line information struct.
1342  *
1343  * \retval 0 on success.
1344  * \retval -1 on error.
1345  */
1346 static int connectedline_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
1347 {
1348         struct ast_party_connected_line connected;
1349         char *val;
1350         char *parms;
1351         void (*set_it)(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update);
1352         struct ast_party_func_args args;
1353         struct ast_party_members member;
1354         struct ast_flags opts;
1355         char *opt_args[CONNECTED_LINE_OPT_ARG_ARRAY_SIZE];
1356         enum ID_FIELD_STATUS status;
1357
1358         if (!value || !chan) {
1359                 return -1;
1360         }
1361
1362         parms = ast_strdupa(data);
1363         AST_STANDARD_APP_ARGS(args, parms);
1364         if (args.argc == 0) {
1365                 /* Must have at least one argument. */
1366                 return -1;
1367         }
1368
1369         AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
1370         if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
1371                 /* Too few or too many subnames */
1372                 return -1;
1373         }
1374
1375         if (ast_app_parse_options(connectedline_opts, &opts, opt_args, args.opts)) {
1376                 /* General invalid option syntax. */
1377                 return -1;
1378         }
1379
1380         /* Determine if the update indication inhibit option is present */
1381         if (ast_test_flag(&opts, CONNECTED_LINE_OPT_INHIBIT)) {
1382                 set_it = ast_channel_set_connected_line;
1383         } else {
1384                 set_it = ast_channel_update_connected_line;
1385         }
1386
1387         ast_channel_lock(chan);
1388         ast_party_connected_line_set_init(&connected, ast_channel_connected(chan));
1389         ast_channel_unlock(chan);
1390
1391         value = ast_skip_blanks(value);
1392
1393         if (member.argc == 1 && !strcasecmp("source", member.argv[0])) {
1394                 int source;
1395
1396                 val = ast_strdupa(value);
1397                 ast_trim_blanks(val);
1398
1399                 if (('0' <= val[0]) && (val[0] <= '9')) {
1400                         source = atoi(val);
1401                 } else {
1402                         source = ast_connected_line_source_parse(val);
1403                 }
1404
1405                 if (source < 0) {
1406                         ast_log(LOG_ERROR, "Unknown connectedline source '%s', value unchanged\n", val);
1407                 } else {
1408                         connected.source = source;
1409                         set_it(chan, &connected, NULL);
1410                 }
1411         } else if (!strcasecmp("priv", member.argv[0])) {
1412                 status = party_id_write(&connected.priv, member.argc - 1, member.argv + 1, value);
1413                 switch (status) {
1414                 case ID_FIELD_VALID:
1415                         set_it(chan, &connected, NULL);
1416                         break;
1417                 case ID_FIELD_INVALID:
1418                         break;
1419                 default:
1420                         ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
1421                         break;
1422                 }
1423                 ast_party_connected_line_free(&connected);
1424         } else {
1425                 status = party_id_write(&connected.id, member.argc, member.argv, value);
1426                 switch (status) {
1427                 case ID_FIELD_VALID:
1428                         set_it(chan, &connected, NULL);
1429                         break;
1430                 case ID_FIELD_INVALID:
1431                         break;
1432                 default:
1433                         ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
1434                         break;
1435                 }
1436                 ast_party_connected_line_free(&connected);
1437         }
1438
1439         return 0;
1440 }
1441
1442 /*!
1443  * \internal
1444  * \brief Read values from the redirecting information struct.
1445  *
1446  * \param chan Asterisk channel to read
1447  * \param cmd Not used
1448  * \param data Redirecting function datatype string
1449  * \param buf Buffer to fill with read value.
1450  * \param len Length of the buffer
1451  *
1452  * \retval 0 on success.
1453  * \retval -1 on error.
1454  */
1455 static int redirecting_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
1456 {
1457         struct ast_party_members member;
1458         char *read_what;
1459         const struct ast_party_redirecting *ast_redirecting;
1460         enum ID_FIELD_STATUS status;
1461
1462         /* Ensure that the buffer is empty */
1463         *buf = 0;
1464
1465         if (!chan) {
1466                 return -1;
1467         }
1468
1469         read_what = ast_strdupa(data);
1470         AST_NONSTANDARD_APP_ARGS(member, read_what, '-');
1471         if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
1472                 /* Too few or too many subnames */
1473                 return -1;
1474         }
1475
1476         ast_channel_lock(chan);
1477
1478         ast_redirecting = ast_channel_redirecting(chan);
1479         if (!strcasecmp("orig", member.argv[0])) {
1480                 if (member.argc == 2 && !strcasecmp("reason", member.argv[1])) {
1481                         ast_copy_string(buf,
1482                                 ast_redirecting_reason_name(&ast_redirecting->orig_reason), len);
1483                 } else {
1484                         status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
1485                                 &ast_redirecting->orig);
1486                         switch (status) {
1487                         case ID_FIELD_VALID:
1488                         case ID_FIELD_INVALID:
1489                                 break;
1490                         default:
1491                                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1492                                 break;
1493                         }
1494                 }
1495         } else if (!strcasecmp("from", member.argv[0])) {
1496                 status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
1497                         &ast_redirecting->from);
1498                 switch (status) {
1499                 case ID_FIELD_VALID:
1500                 case ID_FIELD_INVALID:
1501                         break;
1502                 default:
1503                         ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1504                         break;
1505                 }
1506         } else if (!strcasecmp("to", member.argv[0])) {
1507                 status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
1508                         &ast_redirecting->to);
1509                 switch (status) {
1510                 case ID_FIELD_VALID:
1511                 case ID_FIELD_INVALID:
1512                         break;
1513                 default:
1514                         ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1515                         break;
1516                 }
1517         } else if (member.argc == 1 && !strncasecmp("pres", member.argv[0], 4)) {
1518                 /*
1519                  * Accept pres[entation]
1520                  * This is the combined from name/number presentation.
1521                  */
1522                 ast_copy_string(buf,
1523                         ast_named_caller_presentation(
1524                                 ast_party_id_presentation(&ast_redirecting->from)), len);
1525         } else if (member.argc == 1 && !strcasecmp("reason", member.argv[0])) {
1526                 ast_copy_string(buf, ast_redirecting_reason_name(&ast_redirecting->reason), len);
1527         } else if (member.argc == 1 && !strcasecmp("count", member.argv[0])) {
1528                 snprintf(buf, len, "%d", ast_redirecting->count);
1529         } else if (1 < member.argc && !strcasecmp("priv", member.argv[0])) {
1530                 if (!strcasecmp("orig", member.argv[1])) {
1531                         status = party_id_read(buf, len, member.argc - 2, member.argv + 2,
1532                                 &ast_redirecting->priv_orig);
1533                         switch (status) {
1534                         case ID_FIELD_VALID:
1535                         case ID_FIELD_INVALID:
1536                                 break;
1537                         default:
1538                                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1539                                 break;
1540                         }
1541                 } else if (!strcasecmp("from", member.argv[1])) {
1542                         status = party_id_read(buf, len, member.argc - 2, member.argv + 2,
1543                                 &ast_redirecting->priv_from);
1544                         switch (status) {
1545                         case ID_FIELD_VALID:
1546                         case ID_FIELD_INVALID:
1547                                 break;
1548                         default:
1549                                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1550                                 break;
1551                         }
1552                 } else if (!strcasecmp("to", member.argv[1])) {
1553                         status = party_id_read(buf, len, member.argc - 2, member.argv + 2,
1554                                 &ast_redirecting->priv_to);
1555                         switch (status) {
1556                         case ID_FIELD_VALID:
1557                         case ID_FIELD_INVALID:
1558                                 break;
1559                         default:
1560                                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1561                                 break;
1562                         }
1563                 } else {
1564                         ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1565                 }
1566         } else {
1567                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1568         }
1569
1570         ast_channel_unlock(chan);
1571
1572         return 0;
1573 }
1574
1575 /*!
1576  * \internal
1577  * \brief Write new values to the redirecting information struct.
1578  *
1579  * \param chan Asterisk channel to update
1580  * \param cmd Not used
1581  * \param data Redirecting function datatype string
1582  * \param value Value to assign to the redirecting information struct.
1583  *
1584  * \retval 0 on success.
1585  * \retval -1 on error.
1586  */
1587 static int redirecting_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
1588 {
1589         struct ast_party_redirecting redirecting;
1590         enum ID_FIELD_STATUS status;
1591         char *val;
1592         char *parms;
1593         void (*set_it)(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update);
1594         struct ast_party_func_args args;
1595         struct ast_party_members member;
1596         struct ast_flags opts;
1597         char *opt_args[REDIRECTING_OPT_ARG_ARRAY_SIZE];
1598
1599         if (!value || !chan) {
1600                 return -1;
1601         }
1602
1603         parms = ast_strdupa(data);
1604         AST_STANDARD_APP_ARGS(args, parms);
1605         if (args.argc == 0) {
1606                 /* Must have at least one argument. */
1607                 return -1;
1608         }
1609
1610         AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
1611         if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
1612                 /* Too few or too many subnames */
1613                 return -1;
1614         }
1615
1616         if (ast_app_parse_options(redirecting_opts, &opts, opt_args, args.opts)) {
1617                 /* General invalid option syntax. */
1618                 return -1;
1619         }
1620
1621         /* Determine if the update indication inhibit option is present */
1622         if (ast_test_flag(&opts, REDIRECTING_OPT_INHIBIT)) {
1623                 set_it = ast_channel_set_redirecting;
1624         } else {
1625                 set_it = ast_channel_update_redirecting;
1626         }
1627
1628         ast_channel_lock(chan);
1629         ast_party_redirecting_set_init(&redirecting, ast_channel_redirecting(chan));
1630         ast_channel_unlock(chan);
1631
1632         value = ast_skip_blanks(value);
1633
1634         if (!strcasecmp("orig", member.argv[0])) {
1635                 if (member.argc == 2 && !strcasecmp("reason", member.argv[1])) {
1636                         int reason;
1637
1638                         val = ast_strdupa(value);
1639                         ast_trim_blanks(val);
1640
1641                         if (('0' <= val[0]) && (val[0] <= '9')) {
1642                                 reason = atoi(val);
1643                         } else {
1644                                 reason = ast_redirecting_reason_parse(val);
1645                         }
1646
1647                         if (reason < 0) {
1648                         /* The argument passed into the function does not correspond to a pre-defined
1649                          * reason, so we can just set the reason string to what was given and set the
1650                          * code to be unknown
1651                          */
1652                                 redirecting.orig_reason.code = AST_REDIRECTING_REASON_UNKNOWN;
1653                                 redirecting.orig_reason.str = val;
1654                                 set_it(chan, &redirecting, NULL);
1655                         } else {
1656                                 redirecting.orig_reason.code = reason;
1657                                 redirecting.orig_reason.str = "";
1658                                 set_it(chan, &redirecting, NULL);
1659                         }
1660                 } else {
1661                         status = party_id_write(&redirecting.orig, member.argc - 1, member.argv + 1,
1662                                 value);
1663                         switch (status) {
1664                         case ID_FIELD_VALID:
1665                                 set_it(chan, &redirecting, NULL);
1666                                 break;
1667                         case ID_FIELD_INVALID:
1668                                 break;
1669                         default:
1670                                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1671                                 break;
1672                         }
1673                         ast_party_redirecting_free(&redirecting);
1674                 }
1675         } else if (!strcasecmp("from", member.argv[0])) {
1676                 status = party_id_write(&redirecting.from, member.argc - 1, member.argv + 1,
1677                         value);
1678                 switch (status) {
1679                 case ID_FIELD_VALID:
1680                         set_it(chan, &redirecting, NULL);
1681                         break;
1682                 case ID_FIELD_INVALID:
1683                         break;
1684                 default:
1685                         ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1686                         break;
1687                 }
1688                 ast_party_redirecting_free(&redirecting);
1689         } else if (!strcasecmp("to", member.argv[0])) {
1690                 status = party_id_write(&redirecting.to, member.argc - 1, member.argv + 1, value);
1691                 switch (status) {
1692                 case ID_FIELD_VALID:
1693                         set_it(chan, &redirecting, NULL);
1694                         break;
1695                 case ID_FIELD_INVALID:
1696                         break;
1697                 default:
1698                         ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1699                         break;
1700                 }
1701                 ast_party_redirecting_free(&redirecting);
1702         } else if (member.argc == 1 && !strncasecmp("pres", member.argv[0], 4)) {
1703                 int pres;
1704
1705                 val = ast_strdupa(value);
1706                 ast_trim_blanks(val);
1707
1708                 if (('0' <= val[0]) && (val[0] <= '9')) {
1709                         pres = atoi(val);
1710                 } else {
1711                         pres = ast_parse_caller_presentation(val);
1712                 }
1713
1714                 if (pres < 0) {
1715                         ast_log(LOG_ERROR,
1716                                 "Unknown redirecting combined presentation '%s', value unchanged\n", val);
1717                 } else {
1718                         redirecting.from.name.presentation = pres;
1719                         redirecting.from.number.presentation = pres;
1720                         redirecting.to.name.presentation = pres;
1721                         redirecting.to.number.presentation = pres;
1722                         set_it(chan, &redirecting, NULL);
1723                 }
1724         } else if (member.argc == 1 && !strcasecmp("reason", member.argv[0])) {
1725                 int reason;
1726
1727                 val = ast_strdupa(value);
1728                 ast_trim_blanks(val);
1729
1730                 if (('0' <= val[0]) && (val[0] <= '9')) {
1731                         reason = atoi(val);
1732                 } else {
1733                         reason = ast_redirecting_reason_parse(val);
1734                 }
1735
1736                 if (reason < 0) {
1737                         /* The argument passed into the function does not correspond to a pre-defined
1738                          * reason, so we can just set the reason string to what was given and set the
1739                          * code to be unknown
1740                          */
1741                         redirecting.reason.code = AST_REDIRECTING_REASON_UNKNOWN;
1742                         redirecting.reason.str = val;
1743                         set_it(chan, &redirecting, NULL);
1744                 } else {
1745                         redirecting.reason.code = reason;
1746                         redirecting.reason.str = "";
1747                         set_it(chan, &redirecting, NULL);
1748                 }
1749         } else if (member.argc == 1 && !strcasecmp("count", member.argv[0])) {
1750                 val = ast_strdupa(value);
1751                 ast_trim_blanks(val);
1752
1753                 if (('0' <= val[0]) && (val[0] <= '9')) {
1754                         redirecting.count = atoi(val);
1755                         set_it(chan, &redirecting, NULL);
1756                 } else {
1757                         ast_log(LOG_ERROR, "Unknown redirecting count '%s', value unchanged\n", val);
1758                 }
1759         } else if (1 < member.argc && !strcasecmp("priv", member.argv[0])) {
1760                 if (!strcasecmp("orig", member.argv[1])) {
1761                         status = party_id_write(&redirecting.priv_orig, member.argc - 2, member.argv + 2,
1762                                 value);
1763                         switch (status) {
1764                         case ID_FIELD_VALID:
1765                                 set_it(chan, &redirecting, NULL);
1766                                 break;
1767                         case ID_FIELD_INVALID:
1768                                 break;
1769                         default:
1770                                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1771                                 break;
1772                         }
1773                         ast_party_redirecting_free(&redirecting);
1774                 } else if (!strcasecmp("from", member.argv[1])) {
1775                         status = party_id_write(&redirecting.priv_from, member.argc - 2, member.argv + 2,
1776                                 value);
1777                         switch (status) {
1778                         case ID_FIELD_VALID:
1779                                 set_it(chan, &redirecting, NULL);
1780                                 break;
1781                         case ID_FIELD_INVALID:
1782                                 break;
1783                         default:
1784                                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1785                                 break;
1786                         }
1787                         ast_party_redirecting_free(&redirecting);
1788                 } else if (!strcasecmp("to", member.argv[1])) {
1789                         status = party_id_write(&redirecting.priv_to, member.argc - 2, member.argv + 2, value);
1790                         switch (status) {
1791                         case ID_FIELD_VALID:
1792                                 set_it(chan, &redirecting, NULL);
1793                                 break;
1794                         case ID_FIELD_INVALID:
1795                                 break;
1796                         default:
1797                                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1798                                 break;
1799                         }
1800                         ast_party_redirecting_free(&redirecting);
1801                 } else {
1802                         ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1803                 }
1804         } else {
1805                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1806         }
1807
1808         return 0;
1809 }
1810
1811 static struct ast_custom_function callerid_function = {
1812         .name = "CALLERID",
1813         .read = callerid_read,
1814         .read_max = 256,
1815         .write = callerid_write,
1816 };
1817
1818 static struct ast_custom_function callerpres_function = {
1819         .name = "CALLERPRES",
1820         .read = callerpres_read,
1821         .read_max = 50,
1822         .write = callerpres_write,
1823 };
1824
1825 static struct ast_custom_function connectedline_function = {
1826         .name = "CONNECTEDLINE",
1827         .read = connectedline_read,
1828         .write = connectedline_write,
1829 };
1830
1831 static struct ast_custom_function redirecting_function = {
1832         .name = "REDIRECTING",
1833         .read = redirecting_read,
1834         .write = redirecting_write,
1835 };
1836
1837 /*!
1838  * \internal
1839  * \brief Unload the function module
1840  *
1841  * \retval 0 on success.
1842  * \retval -1 on error.
1843  */
1844 static int unload_module(void)
1845 {
1846         int res;
1847
1848         res = ast_custom_function_unregister(&callerpres_function);
1849         res |= ast_custom_function_unregister(&callerid_function);
1850         res |= ast_custom_function_unregister(&connectedline_function);
1851         res |= ast_custom_function_unregister(&redirecting_function);
1852         return res;
1853 }
1854
1855 /*!
1856  * \internal
1857  * \brief Load and initialize the function module.
1858  *
1859  * \retval AST_MODULE_LOAD_SUCCESS on success.
1860  * \retval AST_MODULE_LOAD_DECLINE on error.
1861  */
1862 static int load_module(void)
1863 {
1864         int res;
1865
1866         res = ast_custom_function_register(&callerpres_function);
1867         res |= ast_custom_function_register(&callerid_function);
1868         res |= ast_custom_function_register(&connectedline_function);
1869         res |= ast_custom_function_register(&redirecting_function);
1870         return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
1871 }
1872
1873 /* Do not wrap the following line. */
1874 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Party ID related dialplan functions (Caller-ID, Connected-line, Redirecting)");