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