Named call pickup groups. Fixes, missing functionality, and improvements.
[asterisk/asterisk.git] / funcs / func_channel.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2006, 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 Channel info dialplan functions
20  *
21  * \author Kevin P. Fleming <kpfleming@digium.com>
22  * \author Ben Winslow
23  * 
24  * \ingroup functions
25  */
26
27 /*** MODULEINFO
28         <support_level>core</support_level>
29  ***/
30
31 #include "asterisk.h"
32
33 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
34
35 #include <regex.h>
36 #include <ctype.h>
37
38 #include "asterisk/module.h"
39 #include "asterisk/channel.h"
40 #include "asterisk/pbx.h"
41 #include "asterisk/utils.h"
42 #include "asterisk/app.h"
43 #include "asterisk/indications.h"
44 #include "asterisk/stringfields.h"
45 #include "asterisk/global_datastores.h"
46
47 /*** DOCUMENTATION
48         <function name="CHANNELS" language="en_US">
49                 <synopsis>
50                         Gets the list of channels, optionally filtering by a regular expression.
51                 </synopsis>
52                 <syntax>
53                         <parameter name="regular_expression" />
54                 </syntax>
55                 <description>
56                         <para>Gets the list of channels, optionally filtering by a <replaceable>regular_expression</replaceable>. If
57                         no argument is provided, all known channels are returned. The
58                         <replaceable>regular_expression</replaceable> must correspond to
59                         the POSIX.2 specification, as shown in <emphasis>regex(7)</emphasis>. The list returned
60                         will be space-delimited.</para>
61                 </description>
62         </function>
63         <function name="MASTER_CHANNEL" language="en_US">
64                 <synopsis>
65                         Gets or sets variables on the master channel
66                 </synopsis>
67                 <description>
68                         <para>Allows access to the channel which created the current channel, if any.  If the channel is already
69                         a master channel, then accesses local channel variables.</para>
70                 </description>
71         </function>
72         <function name="CHANNEL" language="en_US">
73                 <synopsis>
74                         Gets/sets various pieces of information about the channel.
75                 </synopsis>
76                 <syntax>
77                         <parameter name="item" required="true">
78                                 <para>Standard items (provided by all channel technologies) are:</para>
79                                 <enumlist>
80                                         <enum name="audioreadformat">
81                                                 <para>R/O format currently being read.</para>
82                                         </enum>
83                                         <enum name="audionativeformat">
84                                                 <para>R/O format used natively for audio.</para>
85                                         </enum>
86                                         <enum name="audiowriteformat">
87                                                 <para>R/O format currently being written.</para>
88                                         </enum>
89                                         <enum name="callgroup">
90                                                 <para>R/W numeric call pickup groups that this channel is a member.</para>
91                                         </enum>
92                                         <enum name="pickupgroup">
93                                                 <para>R/W numeric call pickup groups this channel can pickup.</para>
94                                         </enum>
95                                         <enum name="namedcallgroup">
96                                                 <para>R/W named call pickup groups that this channel is a member.</para>
97                                         </enum>
98                                         <enum name="namedpickupgroup">
99                                                 <para>R/W named call pickup groups this channel can pickup.</para>
100                                         </enum>
101                                         <enum name="channeltype">
102                                                 <para>R/O technology used for channel.</para>
103                                         </enum>
104                                         <enum name="checkhangup">
105                                                 <para>R/O Whether the channel is hanging up (1/0)</para>
106                                         </enum>
107                                         <enum name="hangup_handler_pop">
108                                                 <para>W/O Replace the most recently added hangup handler
109                                                 with a new hangup handler on the channel if supplied.  The
110                                                 assigned string is passed to the Gosub application when
111                                                 the channel is hung up.  Any optionally omitted context
112                                                 and exten are supplied by the channel pushing the handler
113                                                 before it is pushed.</para>
114                                         </enum>
115                                         <enum name="hangup_handler_push">
116                                                 <para>W/O Push a hangup handler onto the channel hangup
117                                                 handler stack.  The assigned string is passed to the
118                                                 Gosub application when the channel is hung up.  Any
119                                                 optionally omitted context and exten are supplied by the
120                                                 channel pushing the handler before it is pushed.</para>
121                                         </enum>
122                                         <enum name="hangup_handler_wipe">
123                                                 <para>W/O Wipe the entire hangup handler stack and replace
124                                                 with a new hangup handler on the channel if supplied.  The
125                                                 assigned string is passed to the Gosub application when
126                                                 the channel is hung up.  Any optionally omitted context
127                                                 and exten are supplied by the channel pushing the handler
128                                                 before it is pushed.</para>
129                                         </enum>
130                                         <enum name="language">
131                                                 <para>R/W language for sounds played.</para>
132                                         </enum>
133                                         <enum name="musicclass">
134                                                 <para>R/W class (from musiconhold.conf) for hold music.</para>
135                                         </enum>
136                                         <enum name="name">
137                                                 <para>The name of the channel</para>
138                                         </enum>
139                                         <enum name="parkinglot">
140                                                 <para>R/W parkinglot for parking.</para>
141                                         </enum>
142                                         <enum name="rxgain">
143                                                 <para>R/W set rxgain level on channel drivers that support it.</para>
144                                         </enum>
145                                         <enum name="secure_bridge_signaling">
146                                                 <para>Whether or not channels bridged to this channel require secure signaling</para>
147                                         </enum>
148                                         <enum name="secure_bridge_media">
149                                                 <para>Whether or not channels bridged to this channel require secure media</para>
150                                         </enum>
151                                         <enum name="state">
152                                                 <para>R/O state for channel</para>
153                                         </enum>
154                                         <enum name="tonezone">
155                                                 <para>R/W zone for indications played</para>
156                                         </enum>
157                                         <enum name="transfercapability">
158                                                 <para>R/W ISDN Transfer Capability, one of:</para>
159                                                 <enumlist>
160                                                         <enum name="SPEECH" />
161                                                         <enum name="DIGITAL" />
162                                                         <enum name="RESTRICTED_DIGITAL" />
163                                                         <enum name="3K1AUDIO" />
164                                                         <enum name="DIGITAL_W_TONES" />
165                                                         <enum name="VIDEO" />
166                                                 </enumlist>
167                                         </enum>
168                                         <enum name="txgain">
169                                                 <para>R/W set txgain level on channel drivers that support it.</para>
170                                         </enum>
171                                         <enum name="videonativeformat">
172                                                 <para>R/O format used natively for video</para>
173                                         </enum>
174                                         <enum name="trace">
175                                                 <para>R/W whether or not context tracing is enabled, only available
176                                                 <emphasis>if CHANNEL_TRACE is defined</emphasis>.</para>
177                                         </enum>
178                                 </enumlist>
179                                 <para><emphasis>chan_sip</emphasis> provides the following additional options:</para>
180                                 <enumlist>
181                                         <enum name="peerip">
182                                                 <para>R/O Get the IP address of the peer.</para>
183                                         </enum>
184                                         <enum name="recvip">
185                                                 <para>R/O Get the source IP address of the peer.</para>
186                                         </enum>
187                                         <enum name="from">
188                                                 <para>R/O Get the URI from the From: header.</para>
189                                         </enum>
190                                         <enum name="uri">
191                                                 <para>R/O Get the URI from the Contact: header.</para>
192                                         </enum>
193                                         <enum name="useragent">
194                                                 <para>R/O Get the useragent.</para>
195                                         </enum>
196                                         <enum name="peername">
197                                                 <para>R/O Get the name of the peer.</para>
198                                         </enum>
199                                         <enum name="t38passthrough">
200                                                 <para>R/O <literal>1</literal> if T38 is offered or enabled in this channel,
201                                                 otherwise <literal>0</literal></para>
202                                         </enum>
203                                         <enum name="rtpqos">
204                                                 <para>R/O Get QOS information about the RTP stream</para>
205                                                 <para>    This option takes two additional arguments:</para>
206                                                 <para>    Argument 1:</para>
207                                                 <para>     <literal>audio</literal>             Get data about the audio stream</para>
208                                                 <para>     <literal>video</literal>             Get data about the video stream</para>
209                                                 <para>     <literal>text</literal>              Get data about the text stream</para>
210                                                 <para>    Argument 2:</para>
211                                                 <para>     <literal>local_ssrc</literal>        Local SSRC (stream ID)</para>
212                                                 <para>     <literal>local_lostpackets</literal> Local lost packets</para>
213                                                 <para>     <literal>local_jitter</literal>      Local calculated jitter</para>
214                                                 <para>     <literal>local_maxjitter</literal>   Local calculated jitter (maximum)</para>
215                                                 <para>     <literal>local_minjitter</literal>   Local calculated jitter (minimum)</para>
216                                                 <para>     <literal>local_normdevjitter</literal>Local calculated jitter (normal deviation)</para>
217                                                 <para>     <literal>local_stdevjitter</literal> Local calculated jitter (standard deviation)</para>
218                                                 <para>     <literal>local_count</literal>       Number of received packets</para>
219                                                 <para>     <literal>remote_ssrc</literal>       Remote SSRC (stream ID)</para>
220                                                 <para>     <literal>remote_lostpackets</literal>Remote lost packets</para>
221                                                 <para>     <literal>remote_jitter</literal>     Remote reported jitter</para>
222                                                 <para>     <literal>remote_maxjitter</literal>  Remote calculated jitter (maximum)</para>
223                                                 <para>     <literal>remote_minjitter</literal>  Remote calculated jitter (minimum)</para>
224                                                 <para>     <literal>remote_normdevjitter</literal>Remote calculated jitter (normal deviation)</para>
225                                                 <para>     <literal>remote_stdevjitter</literal>Remote calculated jitter (standard deviation)</para>
226                                                 <para>     <literal>remote_count</literal>      Number of transmitted packets</para>
227                                                 <para>     <literal>rtt</literal>               Round trip time</para>
228                                                 <para>     <literal>maxrtt</literal>            Round trip time (maximum)</para>
229                                                 <para>     <literal>minrtt</literal>            Round trip time (minimum)</para>
230                                                 <para>     <literal>normdevrtt</literal>        Round trip time (normal deviation)</para>
231                                                 <para>     <literal>stdevrtt</literal>          Round trip time (standard deviation)</para>
232                                                 <para>     <literal>all</literal>               All statistics (in a form suited to logging,
233                                                 but not for parsing)</para>
234                                         </enum>
235                                         <enum name="rtpdest">
236                                                 <para>R/O Get remote RTP destination information.</para>
237                                                 <para>   This option takes one additional argument:</para>
238                                                 <para>    Argument 1:</para>
239                                                 <para>     <literal>audio</literal>             Get audio destination</para>
240                                                 <para>     <literal>video</literal>             Get video destination</para>
241                                                 <para>     <literal>text</literal>              Get text destination</para>
242                                         </enum>
243                                 </enumlist>
244                                 <para><emphasis>chan_iax2</emphasis> provides the following additional options:</para>
245                                 <enumlist>
246                                         <enum name="peerip">
247                                                 <para>R/O Get the peer's ip address.</para>
248                                         </enum>
249                                         <enum name="peername">
250                                                 <para>R/O Get the peer's username.</para>
251                                         </enum>
252                                 </enumlist>
253                                 <para><emphasis>chan_dahdi</emphasis> provides the following additional options:</para>
254                                 <enumlist>
255                                         <enum name="dahdi_channel">
256                                                 <para>R/O DAHDI channel related to this channel.</para>
257                                         </enum>
258                                         <enum name="dahdi_span">
259                                                 <para>R/O DAHDI span related to this channel.</para>
260                                         </enum>
261                                         <enum name="dahdi_type">
262                                                 <para>R/O DAHDI channel type, one of:</para>
263                                                 <enumlist>
264                                                         <enum name="analog" />
265                                                         <enum name="mfc/r2" />
266                                                         <enum name="pri" />
267                                                         <enum name="pseudo" />
268                                                         <enum name="ss7" />
269                                                 </enumlist>
270                                         </enum>
271                                         <enum name="keypad_digits">
272                                                 <para>R/O PRI Keypad digits that came in with the SETUP message.</para>
273                                         </enum>
274                                         <enum name="reversecharge">
275                                                 <para>R/O PRI Reverse Charging Indication, one of:</para>
276                                                 <enumlist>
277                                                         <enum name="-1"> <para>None</para></enum>
278                                                         <enum name=" 1"> <para>Reverse Charging Requested</para></enum>
279                                                 </enumlist>
280                                         </enum>
281                                         <enum name="no_media_path">
282                                                 <para>R/O PRI Nonzero if the channel has no B channel.
283                                                 The channel is either on hold or a call waiting call.</para>
284                                         </enum>
285                                         <enum name="buffers">
286                                                 <para>W/O Change the channel's buffer policy (for the current call only)</para>
287                                                 <para>This option takes two arguments:</para>
288                                                 <para>  Number of buffers,</para>
289                                                 <para>  Buffer policy being one of:</para>
290                                                 <para>      <literal>full</literal></para>
291                                                 <para>      <literal>immediate</literal></para>
292                                                 <para>      <literal>half</literal></para>
293                                         </enum>
294                                         <enum name="echocan_mode">
295                                                 <para>W/O Change the configuration of the active echo
296                                                 canceller on the channel (if any), for the current call
297                                                 only.</para>
298                                                 <para>Possible values are:</para>
299                                                 <para>  <literal>on</literal>   Normal mode (the echo canceller is actually reinitalized)</para>
300                                                 <para>  <literal>off</literal>  Disabled</para>
301                                                 <para>  <literal>fax</literal>  FAX/data mode (NLP disabled if possible, otherwise
302                                                         completely disabled)</para>
303                                                 <para>  <literal>voice</literal>        Voice mode (returns from FAX mode, reverting the changes that were made)</para>
304                                         </enum>
305                                 </enumlist>
306                                 <para><emphasis>chan_ooh323</emphasis> provides the following additional options:</para>
307                                 <enumlist>
308                                         <enum name="faxdetect">
309                                                 <para>Fax Detect [R/W]</para>
310                                                 <para>Returns 0 or 1</para>
311                                                 <para>Write yes or no</para>
312                                         </enum>
313                                         <enum name="t38support">
314                                                 <para>t38support [R/W]</para>
315                                                 <para>Returns 0 or 1</para>
316                                                 <para>Write yes or no</para>
317                                         </enum>
318                                         <enum name="h323id">
319                                                 <para>Returns h323id [R]</para>
320                                         </enum>
321                                 </enumlist>
322                         </parameter>
323                 </syntax>
324                 <description>
325                         <para>Gets/sets various pieces of information about the channel, additional <replaceable>item</replaceable> may
326                         be available from the channel driver; see its documentation for details. Any <replaceable>item</replaceable>
327                         requested that is not available on the current channel will return an empty string.</para>
328                 </description>
329         </function>
330  ***/
331
332 #define locked_copy_string(chan, dest, source, len) \
333         do { \
334                 ast_channel_lock(chan); \
335                 ast_copy_string(dest, source, len); \
336                 ast_channel_unlock(chan); \
337         } while (0)
338 #define locked_string_field_set(chan, field, source) \
339         do { \
340                 ast_channel_lock(chan); \
341                 ast_channel_##field##_set(chan, source); \
342                 ast_channel_unlock(chan); \
343         } while (0)
344
345 static const char * const transfercapability_table[0x20] = {
346         "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
347         "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
348         "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
349         "VIDEO", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", };
350
351 static int func_channel_read(struct ast_channel *chan, const char *function,
352                              char *data, char *buf, size_t len)
353 {
354         int ret = 0;
355         struct ast_format_cap *tmpcap;
356
357         if (!strcasecmp(data, "audionativeformat")) {
358                 char tmp[512];
359
360                 if ((tmpcap = ast_format_cap_get_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_AUDIO))) {
361                         ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
362                         tmpcap = ast_format_cap_destroy(tmpcap);
363                 }
364         } else if (!strcasecmp(data, "videonativeformat")) {
365                 char tmp[512];
366
367                 if ((tmpcap = ast_format_cap_get_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_VIDEO))) {
368                         ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
369                         tmpcap = ast_format_cap_destroy(tmpcap);
370                 }
371         } else if (!strcasecmp(data, "audioreadformat")) {
372                 ast_copy_string(buf, ast_getformatname(ast_channel_readformat(chan)), len);
373         } else if (!strcasecmp(data, "audiowriteformat")) {
374                 ast_copy_string(buf, ast_getformatname(ast_channel_writeformat(chan)), len);
375 #ifdef CHANNEL_TRACE
376         } else if (!strcasecmp(data, "trace")) {
377                 ast_channel_lock(chan);
378                 ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
379                 ast_channel_unlock(chan);
380 #endif
381         } else if (!strcasecmp(data, "tonezone") && ast_channel_zone(chan))
382                 locked_copy_string(chan, buf, ast_channel_zone(chan)->country, len);
383         else if (!strcasecmp(data, "language"))
384                 locked_copy_string(chan, buf, ast_channel_language(chan), len);
385         else if (!strcasecmp(data, "musicclass"))
386                 locked_copy_string(chan, buf, ast_channel_musicclass(chan), len);
387         else if (!strcasecmp(data, "name")) {
388                 locked_copy_string(chan, buf, ast_channel_name(chan), len);
389         } else if (!strcasecmp(data, "parkinglot"))
390                 locked_copy_string(chan, buf, ast_channel_parkinglot(chan), len);
391         else if (!strcasecmp(data, "state"))
392                 locked_copy_string(chan, buf, ast_state2str(ast_channel_state(chan)), len);
393         else if (!strcasecmp(data, "channeltype"))
394                 locked_copy_string(chan, buf, ast_channel_tech(chan)->type, len);
395         else if (!strcasecmp(data, "accountcode"))
396                 locked_copy_string(chan, buf, ast_channel_accountcode(chan), len);
397         else if (!strcasecmp(data, "checkhangup")) {
398                 ast_channel_lock(chan);
399                 ast_copy_string(buf, ast_check_hangup(chan) ? "1" : "0", len);
400                 ast_channel_unlock(chan);
401         } else if (!strcasecmp(data, "peeraccount"))
402                 locked_copy_string(chan, buf, ast_channel_peeraccount(chan), len);
403         else if (!strcasecmp(data, "hangupsource"))
404                 locked_copy_string(chan, buf, ast_channel_hangupsource(chan), len);
405         else if (!strcasecmp(data, "appname") && ast_channel_appl(chan))
406                 locked_copy_string(chan, buf, ast_channel_appl(chan), len);
407         else if (!strcasecmp(data, "appdata") && ast_channel_data(chan))
408                 locked_copy_string(chan, buf, ast_channel_data(chan), len);
409         else if (!strcasecmp(data, "exten") && ast_channel_data(chan))
410                 locked_copy_string(chan, buf, ast_channel_exten(chan), len);
411         else if (!strcasecmp(data, "context") && ast_channel_data(chan))
412                 locked_copy_string(chan, buf, ast_channel_context(chan), len);
413         else if (!strcasecmp(data, "userfield") && ast_channel_data(chan))
414                 locked_copy_string(chan, buf, ast_channel_userfield(chan), len);
415         else if (!strcasecmp(data, "channame") && ast_channel_data(chan))
416                 locked_copy_string(chan, buf, ast_channel_name(chan), len);
417         else if (!strcasecmp(data, "linkedid")) {
418                 ast_channel_lock(chan);
419                 if (ast_strlen_zero(ast_channel_linkedid(chan))) {
420                         /* fall back on the channel's uniqueid if linkedid is unset */
421                         ast_copy_string(buf, ast_channel_uniqueid(chan), len);
422                 }
423                 else {
424                         ast_copy_string(buf, ast_channel_linkedid(chan), len);
425                 }
426                 ast_channel_unlock(chan);
427         } else if (!strcasecmp(data, "peer")) {
428                 struct ast_channel *p;
429
430                 ast_channel_lock(chan);
431                 p = ast_bridged_channel(chan);
432                 if (p || ast_channel_tech(chan) || ast_channel_cdr(chan)) /* dummy channel? if so, we hid the peer name in the language */
433                         ast_copy_string(buf, (p ? ast_channel_name(p) : ""), len);
434                 else {
435                         /* a dummy channel can still pass along bridged peer info via
436                            the BRIDGEPEER variable */
437                         const char *pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
438                         if (!ast_strlen_zero(pname))
439                                 ast_copy_string(buf, pname, len); /* a horrible kludge, but... how else? */
440                         else
441                                 buf[0] = 0;
442                 }
443                 ast_channel_unlock(chan);
444         } else if (!strcasecmp(data, "uniqueid")) {
445                 locked_copy_string(chan, buf, ast_channel_uniqueid(chan), len);
446         } else if (!strcasecmp(data, "transfercapability")) {
447                 locked_copy_string(chan, buf, transfercapability_table[ast_channel_transfercapability(chan) & 0x1f], len);
448         } else if (!strcasecmp(data, "callgroup")) {
449                 char groupbuf[256];
450
451                 locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_callgroup(chan)), len);
452         } else if (!strcasecmp(data, "pickupgroup")) {
453                 char groupbuf[256];
454
455                 locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_pickupgroup(chan)), len);
456         } else if (!strcasecmp(data, "namedcallgroup")) {
457                 struct ast_str *tmp_str = ast_str_alloca(1024);
458
459                 locked_copy_string(chan, buf,  ast_print_namedgroups(&tmp_str, ast_channel_named_callgroups(chan)), len);
460         } else if (!strcasecmp(data, "namedpickupgroup")) {
461                 struct ast_str *tmp_str = ast_str_alloca(1024);
462
463                 locked_copy_string(chan, buf,  ast_print_namedgroups(&tmp_str, ast_channel_named_pickupgroups(chan)), len);
464         } else if (!strcasecmp(data, "amaflags")) {
465                 ast_channel_lock(chan);
466                 snprintf(buf, len, "%d", ast_channel_amaflags(chan));
467                 ast_channel_unlock(chan);
468         } else if (!strncasecmp(data, "secure_bridge_", 14)) {
469                 struct ast_datastore *ds;
470
471                 ast_channel_lock(chan);
472                 if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
473                         struct ast_secure_call_store *encrypt = ds->data;
474                         if (!strcasecmp(data, "secure_bridge_signaling")) {
475                                 snprintf(buf, len, "%s", encrypt->signaling ? "1" : "");
476                         } else if (!strcasecmp(data, "secure_bridge_media")) {
477                                 snprintf(buf, len, "%s", encrypt->media ? "1" : "");
478                         }
479                 }
480                 ast_channel_unlock(chan);
481         } else if (!ast_channel_tech(chan) || !ast_channel_tech(chan)->func_channel_read || ast_channel_tech(chan)->func_channel_read(chan, function, data, buf, len)) {
482                 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
483                 ret = -1;
484         }
485
486         return ret;
487 }
488
489 static int func_channel_write_real(struct ast_channel *chan, const char *function,
490                               char *data, const char *value)
491 {
492         int ret = 0;
493         signed char gainset;
494
495         if (!strcasecmp(data, "language"))
496                 locked_string_field_set(chan, language, value);
497         else if (!strcasecmp(data, "parkinglot"))
498                 locked_string_field_set(chan, parkinglot, value);
499         else if (!strcasecmp(data, "musicclass"))
500                 locked_string_field_set(chan, musicclass, value);
501         else if (!strcasecmp(data, "accountcode"))
502                 locked_string_field_set(chan, accountcode, value);
503         else if (!strcasecmp(data, "userfield"))
504                 locked_string_field_set(chan, userfield, value);
505         else if (!strcasecmp(data, "amaflags")) {
506                 ast_channel_lock(chan);
507                 if(isdigit(*value)) {
508                         int amaflags;
509                         sscanf(value, "%30d", &amaflags);
510                         ast_channel_amaflags_set(chan, amaflags);
511                 } else if (!strcasecmp(value,"OMIT")){
512                         ast_channel_amaflags_set(chan, 1);
513                 } else if (!strcasecmp(value,"BILLING")){
514                         ast_channel_amaflags_set(chan, 2);
515                 } else if (!strcasecmp(value,"DOCUMENTATION")){
516                         ast_channel_amaflags_set(chan, 3);
517                 }
518                 ast_channel_unlock(chan);
519         } else if (!strcasecmp(data, "peeraccount"))
520                 locked_string_field_set(chan, peeraccount, value);
521         else if (!strcasecmp(data, "hangupsource"))
522                 /* XXX - should we be forcing this here? */
523                 ast_set_hangupsource(chan, value, 0);
524 #ifdef CHANNEL_TRACE
525         else if (!strcasecmp(data, "trace")) {
526                 ast_channel_lock(chan);
527                 if (ast_true(value)) 
528                         ret = ast_channel_trace_enable(chan);
529                 else if (ast_false(value))
530                         ret = ast_channel_trace_disable(chan);
531                 else {
532                         ret = -1;
533                         ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).\n");
534                 }
535                 ast_channel_unlock(chan);
536         }
537 #endif
538         else if (!strcasecmp(data, "tonezone")) {
539                 struct ast_tone_zone *new_zone;
540                 if (!(new_zone = ast_get_indication_zone(value))) {
541                         ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
542                         ret = -1;       
543                 } else {
544                         ast_channel_lock(chan);
545                         if (ast_channel_zone(chan)) {
546                                 ast_channel_zone_set(chan, ast_tone_zone_unref(ast_channel_zone(chan)));
547                         }
548                         ast_channel_zone_set(chan, ast_tone_zone_ref(new_zone));
549                         ast_channel_unlock(chan);
550                         new_zone = ast_tone_zone_unref(new_zone);
551                 }
552         } else if (!strcasecmp(data, "callgroup")) {
553                 ast_channel_lock(chan);
554                 ast_channel_callgroup_set(chan, ast_get_group(value));
555                 ast_channel_unlock(chan);
556         } else if (!strcasecmp(data, "pickupgroup")) {
557                 ast_channel_lock(chan);
558                 ast_channel_pickupgroup_set(chan, ast_get_group(value));
559                 ast_channel_unlock(chan);
560         } else if (!strcasecmp(data, "namedcallgroup")) {
561                 struct ast_namedgroups *groups = ast_get_namedgroups(value);
562
563                 ast_channel_lock(chan);
564                 ast_channel_named_callgroups_set(chan, groups);
565                 ast_channel_unlock(chan);
566                 ast_unref_namedgroups(groups);
567         } else if (!strcasecmp(data, "namedpickupgroup")) {
568                 struct ast_namedgroups *groups = ast_get_namedgroups(value);
569
570                 ast_channel_lock(chan);
571                 ast_channel_named_pickupgroups_set(chan, groups);
572                 ast_channel_unlock(chan);
573                 ast_unref_namedgroups(groups);
574         } else if (!strcasecmp(data, "txgain")) {
575                 sscanf(value, "%4hhd", &gainset);
576                 ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
577         } else if (!strcasecmp(data, "rxgain")) {
578                 sscanf(value, "%4hhd", &gainset);
579                 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
580         } else if (!strcasecmp(data, "transfercapability")) {
581                 unsigned short i;
582
583                 ast_channel_lock(chan);
584                 for (i = 0; i < 0x20; i++) {
585                         if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
586                                 ast_channel_transfercapability_set(chan, i);
587                                 break;
588                         }
589                 }
590                 ast_channel_unlock(chan);
591         } else if (!strcasecmp(data, "hangup_handler_pop")) {
592                 /* Pop one hangup handler before pushing the new handler. */
593                 ast_pbx_hangup_handler_pop(chan);
594                 ast_pbx_hangup_handler_push(chan, value);
595         } else if (!strcasecmp(data, "hangup_handler_push")) {
596                 ast_pbx_hangup_handler_push(chan, value);
597         } else if (!strcasecmp(data, "hangup_handler_wipe")) {
598                 /* Pop all hangup handlers before pushing the new handler. */
599                 while (ast_pbx_hangup_handler_pop(chan)) {
600                 }
601                 ast_pbx_hangup_handler_push(chan, value);
602         } else if (!strncasecmp(data, "secure_bridge_", 14)) {
603                 struct ast_datastore *ds;
604                 struct ast_secure_call_store *store;
605
606                 if (!chan || !value) {
607                         return -1;
608                 }
609
610                 ast_channel_lock(chan);
611                 if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
612                         if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
613                                 ast_channel_unlock(chan);
614                                 return -1;
615                         }
616                         if (!(store = ast_calloc(1, sizeof(*store)))) {
617                                 ast_channel_unlock(chan);
618                                 ast_free(ds);
619                                 return -1;
620                         }
621                         ds->data = store;
622                         ast_channel_datastore_add(chan, ds);
623                 } else {
624                         store = ds->data;
625                 }
626
627                 if (!strcasecmp(data, "secure_bridge_signaling")) {
628                         store->signaling = ast_true(value) ? 1 : 0;
629                 } else if (!strcasecmp(data, "secure_bridge_media")) {
630                         store->media = ast_true(value) ? 1 : 0;
631                 }
632                 ast_channel_unlock(chan);
633         } else if (!ast_channel_tech(chan)->func_channel_write
634                  || ast_channel_tech(chan)->func_channel_write(chan, function, data, value)) {
635                 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
636                                 data);
637                 ret = -1;
638         }
639
640         return ret;
641 }
642
643 static int func_channel_write(struct ast_channel *chan, const char *function, char *data, const char *value)
644 {
645         int res;
646         ast_chan_write_info_t write_info = {
647                 .version = AST_CHAN_WRITE_INFO_T_VERSION,
648                 .write_fn = func_channel_write_real,
649                 .chan = chan,
650                 .function = function,
651                 .data = data,
652                 .value = value,
653         };
654
655         res = func_channel_write_real(chan, function, data, value);
656         ast_channel_setoption(chan, AST_OPTION_CHANNEL_WRITE, &write_info, sizeof(write_info), 0);
657
658         return res;
659 }
660
661 static struct ast_custom_function channel_function = {
662         .name = "CHANNEL",
663         .read = func_channel_read,
664         .write = func_channel_write,
665 };
666
667 static int func_channels_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
668 {
669         struct ast_channel *c = NULL;
670         regex_t re;
671         int res;
672         size_t buflen = 0;
673         struct ast_channel_iterator *iter;
674
675         buf[0] = '\0';
676
677         if (!ast_strlen_zero(data)) {
678                 if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
679                         regerror(res, &re, buf, maxlen);
680                         ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf);
681                         return -1;
682                 }
683         }
684
685         if (!(iter = ast_channel_iterator_all_new())) {
686                 if (!ast_strlen_zero(data)) {
687                         regfree(&re);
688                 }
689                 return -1;
690         }
691
692         while ((c = ast_channel_iterator_next(iter))) {
693                 ast_channel_lock(c);
694                 if (ast_strlen_zero(data) || regexec(&re, ast_channel_name(c), 0, NULL, 0) == 0) {
695                         size_t namelen = strlen(ast_channel_name(c));
696                         if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
697                                 if (!ast_strlen_zero(buf)) {
698                                         strcat(buf, " ");
699                                         buflen++;
700                                 }
701                                 strcat(buf, ast_channel_name(c));
702                                 buflen += namelen;
703                         } else {
704                                 ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space.  Output will be truncated!\n");
705                         }
706                 }
707                 ast_channel_unlock(c);
708                 c = ast_channel_unref(c);
709         }
710
711         ast_channel_iterator_destroy(iter);
712
713         if (!ast_strlen_zero(data)) {
714                 regfree(&re);
715         }
716
717         return 0;
718 }
719
720 static struct ast_custom_function channels_function = {
721         .name = "CHANNELS",
722         .read = func_channels_read,
723 };
724
725 static int func_mchan_read(struct ast_channel *chan, const char *function,
726                              char *data, struct ast_str **buf, ssize_t len)
727 {
728         struct ast_channel *mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
729         char *template = ast_alloca(4 + strlen(data));
730         sprintf(template, "${%s}", data); /* SAFE */
731         ast_str_substitute_variables(buf, len, mchan ? mchan : chan, template);
732         if (mchan) {
733                 ast_channel_unref(mchan);
734         }
735         return 0;
736 }
737
738 static int func_mchan_write(struct ast_channel *chan, const char *function,
739                               char *data, const char *value)
740 {
741         struct ast_channel *mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
742         pbx_builtin_setvar_helper(mchan ? mchan : chan, data, value);
743         if (mchan) {
744                 ast_channel_unref(mchan);
745         }
746         return 0;
747 }
748
749 static struct ast_custom_function mchan_function = {
750         .name = "MASTER_CHANNEL",
751         .read2 = func_mchan_read,
752         .write = func_mchan_write,
753 };
754
755 static int unload_module(void)
756 {
757         int res = 0;
758
759         res |= ast_custom_function_unregister(&channel_function);
760         res |= ast_custom_function_unregister(&channels_function);
761         res |= ast_custom_function_unregister(&mchan_function);
762
763         return res;
764 }
765
766 static int load_module(void)
767 {
768         int res = 0;
769
770         res |= ast_custom_function_register(&channel_function);
771         res |= ast_custom_function_register(&channels_function);
772         res |= ast_custom_function_register(&mchan_function);
773
774         return res;
775 }
776
777 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel information dialplan functions");