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