Merge "jansson-bundled: Patch for off-nominal crash."
[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 #include <regex.h>
34 #include <ctype.h>
35
36 #include "asterisk/module.h"
37 #include "asterisk/channel.h"
38 #include "asterisk/bridge.h"
39 #include "asterisk/pbx.h"
40 #include "asterisk/utils.h"
41 #include "asterisk/app.h"
42 #include "asterisk/indications.h"
43 #include "asterisk/stringfields.h"
44 #include "asterisk/global_datastores.h"
45 #include "asterisk/bridge_basic.h"
46 #include "asterisk/bridge_after.h"
47 #include "asterisk/max_forwards.h"
48
49 /*** DOCUMENTATION
50         <function name="CHANNELS" language="en_US">
51                 <synopsis>
52                         Gets the list of channels, optionally filtering by a regular expression.
53                 </synopsis>
54                 <syntax>
55                         <parameter name="regular_expression" />
56                 </syntax>
57                 <description>
58                         <para>Gets the list of channels, optionally filtering by a <replaceable>regular_expression</replaceable>. If
59                         no argument is provided, all known channels are returned. The
60                         <replaceable>regular_expression</replaceable> must correspond to
61                         the POSIX.2 specification, as shown in <emphasis>regex(7)</emphasis>. The list returned
62                         will be space-delimited.</para>
63                 </description>
64         </function>
65         <function name="MASTER_CHANNEL" language="en_US">
66                 <synopsis>
67                         Gets or sets variables on the master channel
68                 </synopsis>
69                 <description>
70                         <para>Allows access to the oldest channel associated with the current
71                         channel if it still exists.  If the channel is the master channel or
72                         the master channel no longer exists then access local channel variables
73                         instead.  In other words, the master channel is the channel identified by
74                         the channel's linkedid.</para>
75                 </description>
76         </function>
77         <function name="CHANNEL" language="en_US">
78                 <synopsis>
79                         Gets/sets various pieces of information about the channel.
80                 </synopsis>
81                 <syntax>
82                         <parameter name="item" required="true">
83                                 <para>Standard items (provided by all channel technologies) are:</para>
84                                 <enumlist>
85                                         <enum name="amaflags">
86                                                 <para>R/W the Automatic Message Accounting (AMA) flags on the channel.
87                                                 When read from a channel, the integer value will always be returned.
88                                                 When written to a channel, both the string format or integer value
89                                                 is accepted.</para>
90                                                 <enumlist>
91                                                         <enum name="1"><para><literal>OMIT</literal></para></enum>
92                                                         <enum name="2"><para><literal>BILLING</literal></para></enum>
93                                                         <enum name="3"><para><literal>DOCUMENTATION</literal></para></enum>
94                                                 </enumlist>
95                                         </enum>
96                                         <enum name="accountcode">
97                                                 <para>R/W the channel's account code.</para>
98                                         </enum>
99                                         <enum name="audioreadformat">
100                                                 <para>R/O format currently being read.</para>
101                                         </enum>
102                                         <enum name="audionativeformat">
103                                                 <para>R/O format used natively for audio.</para>
104                                         </enum>
105                                         <enum name="audiowriteformat">
106                                                 <para>R/O format currently being written.</para>
107                                         </enum>
108                                         <enum name="dtmf_features">
109                                                 <para>R/W The channel's DTMF bridge features.
110                                                 May include one or more of 'T' 'K' 'H' 'W' and 'X' in a similar manner to options
111                                                 in the <literal>Dial</literal> application. When setting it, the features string
112                                                 must be all upper case.</para>
113                                         </enum>
114                                         <enum name="callgroup">
115                                                 <para>R/W numeric call pickup groups that this channel is a member.</para>
116                                         </enum>
117                                         <enum name="pickupgroup">
118                                                 <para>R/W numeric call pickup groups this channel can pickup.</para>
119                                         </enum>
120                                         <enum name="namedcallgroup">
121                                                 <para>R/W named call pickup groups that this channel is a member.</para>
122                                         </enum>
123                                         <enum name="namedpickupgroup">
124                                                 <para>R/W named call pickup groups this channel can pickup.</para>
125                                         </enum>
126                                         <enum name="channeltype">
127                                                 <para>R/O technology used for channel.</para>
128                                         </enum>
129                                         <enum name="checkhangup">
130                                                 <para>R/O Whether the channel is hanging up (1/0)</para>
131                                         </enum>
132                                         <enum name="after_bridge_goto">
133                                                 <para>R/W the parseable goto string indicating where the channel is
134                                                 expected to return to in the PBX after exiting the next bridge it joins
135                                                 on the condition that it doesn't hang up. The parseable goto string uses
136                                                 the same syntax as the <literal>Goto</literal> application.</para>
137                                         </enum>
138                                         <enum name="hangup_handler_pop">
139                                                 <para>W/O Replace the most recently added hangup handler
140                                                 with a new hangup handler on the channel if supplied.  The
141                                                 assigned string is passed to the Gosub application when
142                                                 the channel is hung up.  Any optionally omitted context
143                                                 and exten are supplied by the channel pushing the handler
144                                                 before it is pushed.</para>
145                                         </enum>
146                                         <enum name="hangup_handler_push">
147                                                 <para>W/O Push a hangup handler onto the channel hangup
148                                                 handler stack.  The assigned string is passed to the
149                                                 Gosub application when the channel is hung up.  Any
150                                                 optionally omitted context and exten are supplied by the
151                                                 channel pushing the handler before it is pushed.</para>
152                                         </enum>
153                                         <enum name="hangup_handler_wipe">
154                                                 <para>W/O Wipe the entire hangup handler stack and replace
155                                                 with a new hangup handler on the channel if supplied.  The
156                                                 assigned string is passed to the Gosub application when
157                                                 the channel is hung up.  Any optionally omitted context
158                                                 and exten are supplied by the channel pushing the handler
159                                                 before it is pushed.</para>
160                                         </enum>
161                                         <enum name="onhold">
162                                                 <para>R/O Whether or not the channel is onhold. (1/0)</para>
163                                         </enum>
164                                         <enum name="language">
165                                                 <para>R/W language for sounds played.</para>
166                                         </enum>
167                                         <enum name="musicclass">
168                                                 <para>R/W class (from musiconhold.conf) for hold music.</para>
169                                         </enum>
170                                         <enum name="name">
171                                                 <para>The name of the channel</para>
172                                         </enum>
173                                         <enum name="parkinglot">
174                                                 <para>R/W parkinglot for parking.</para>
175                                         </enum>
176                                         <enum name="rxgain">
177                                                 <para>R/W set rxgain level on channel drivers that support it.</para>
178                                         </enum>
179                                         <enum name="secure_bridge_signaling">
180                                                 <para>Whether or not channels bridged to this channel require secure signaling (1/0)</para>
181                                         </enum>
182                                         <enum name="secure_bridge_media">
183                                                 <para>Whether or not channels bridged to this channel require secure media (1/0)</para>
184                                         </enum>
185                                         <enum name="state">
186                                                 <para>R/O state of the channel</para>
187                                         </enum>
188                                         <enum name="tonezone">
189                                                 <para>R/W zone for indications played</para>
190                                         </enum>
191                                         <enum name="transfercapability">
192                                                 <para>R/W ISDN Transfer Capability, one of:</para>
193                                                 <enumlist>
194                                                         <enum name="SPEECH" />
195                                                         <enum name="DIGITAL" />
196                                                         <enum name="RESTRICTED_DIGITAL" />
197                                                         <enum name="3K1AUDIO" />
198                                                         <enum name="DIGITAL_W_TONES" />
199                                                         <enum name="VIDEO" />
200                                                 </enumlist>
201                                         </enum>
202                                         <enum name="txgain">
203                                                 <para>R/W set txgain level on channel drivers that support it.</para>
204                                         </enum>
205                                         <enum name="videonativeformat">
206                                                 <para>R/O format used natively for video</para>
207                                         </enum>
208                                         <enum name="hangupsource">
209                                                 <para>R/W returns the channel responsible for hangup.</para>
210                                         </enum>
211                                         <enum name="appname">
212                                                 <para>R/O returns the internal application name.</para>
213                                         </enum>
214                                         <enum name="appdata">
215                                                 <para>R/O returns the application data if available.</para>
216                                         </enum>
217                                         <enum name="exten">
218                                                 <para>R/O returns the extension for an outbound channel.</para>
219                                         </enum>
220                                         <enum name="context">
221                                                 <para>R/O returns the context for an outbound channel.</para>
222                                         </enum>
223                                         <enum name="channame">
224                                                 <para>R/O returns the channel name for an outbound channel.</para>
225                                         </enum>
226                                         <enum name="uniqueid">
227                                                 <para>R/O returns the channel uniqueid.</para>
228                                         </enum>
229                                         <enum name="linkedid">
230                                                 <para>R/O returns the linkedid if available, otherwise returns the uniqueid.</para>
231                                         </enum>
232                                         <enum name="max_forwards">
233                                                 <para>R/W The maximum number of forwards allowed.</para>
234                                         </enum>
235                                         <enum name="callid">
236                                                 <para>R/O Call identifier log tag associated with the channel
237                                                 e.g., <literal>[C-00000000]</literal>.</para>
238                                         </enum>
239                                 </enumlist>
240                                 <xi:include xpointer="xpointer(/docs/info[@name='CHANNEL'])" />
241                         </parameter>
242                 </syntax>
243                 <description>
244                         <para>Gets/sets various pieces of information about the channel, additional <replaceable>item</replaceable> may
245                         be available from the channel driver; see its documentation for details. Any <replaceable>item</replaceable>
246                         requested that is not available on the current channel will return an empty string.</para>
247                         <example title="Standard CHANNEL item examples">
248                                 ; Push a hangup handler subroutine existing at dialplan
249                                 ; location default,s,1 onto the current channel
250                                 same => n,Set(CHANNEL(hangup_handler_push)=default,s,1)
251
252                                 ; Set the current tonezone to Germany (de)
253                                 same => n,Set(CHANNEL(tonezone)=de)
254
255                                 ; Set the allowed maximum number of forwarding attempts
256                                 same => n,Set(CHANNEL(max_forwards)=10)
257
258                                 ; If this channel is ejected from its next bridge, and if
259                                 ; the channel is not hung up, begin executing dialplan at
260                                 ; location default,after-bridge,1
261                                 same => n,Set(CHANNEL(after_bridge_goto)=default,after-bridge,1)
262
263                                 ; Log the current state of the channel
264                                 same => n,Log(NOTICE, This channel is: ${CHANNEL(state)})
265                         </example>
266                         <xi:include xpointer="xpointer(/docs/info[@name='CHANNEL_EXAMPLES'])" />
267                 </description>
268         </function>
269  ***/
270
271 #define locked_copy_string(chan, dest, source, len) \
272         do { \
273                 ast_channel_lock(chan); \
274                 ast_copy_string(dest, source, len); \
275                 ast_channel_unlock(chan); \
276         } while (0)
277 #define locked_string_field_set(chan, field, source) \
278         do { \
279                 ast_channel_lock(chan); \
280                 ast_channel_##field##_set(chan, source); \
281                 ast_channel_unlock(chan); \
282         } while (0)
283
284 static const char * const transfercapability_table[0x20] = {
285         "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
286         "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
287         "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
288         "VIDEO", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", };
289
290 static int func_channel_read(struct ast_channel *chan, const char *function,
291                              char *data, char *buf, size_t len)
292 {
293         int ret = 0;
294         struct ast_format_cap *tmpcap;
295
296         if (!chan) {
297                 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
298                 return -1;
299         }
300
301         if (!strcasecmp(data, "audionativeformat")) {
302                 tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
303                 if (tmpcap) {
304                         struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
305
306                         ast_channel_lock(chan);
307                         ast_format_cap_append_from_cap(tmpcap, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_AUDIO);
308                         ast_channel_unlock(chan);
309                         ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len);
310                         ao2_ref(tmpcap, -1);
311                 }
312         } else if (!strcasecmp(data, "videonativeformat")) {
313                 tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
314                 if (tmpcap) {
315                         struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
316
317                         ast_channel_lock(chan);
318                         ast_format_cap_append_from_cap(tmpcap, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_VIDEO);
319                         ast_channel_unlock(chan);
320                         ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len);
321                         ao2_ref(tmpcap, -1);
322                 }
323         } else if (!strcasecmp(data, "audioreadformat")) {
324                 locked_copy_string(chan, buf, ast_format_get_name(ast_channel_readformat(chan)), len);
325         } else if (!strcasecmp(data, "audiowriteformat")) {
326                 locked_copy_string(chan, buf, ast_format_get_name(ast_channel_writeformat(chan)), len);
327         } else if (!strcasecmp(data, "tonezone") && ast_channel_zone(chan)) {
328                 locked_copy_string(chan, buf, ast_channel_zone(chan)->country, len);
329         } else if (!strcasecmp(data, "dtmf_features")) {
330                 if (ast_bridge_features_ds_get_string(chan, buf, len)) {
331                         buf[0] = '\0';
332                 }
333         } else if (!strcasecmp(data, "language"))
334                 locked_copy_string(chan, buf, ast_channel_language(chan), len);
335         else if (!strcasecmp(data, "musicclass"))
336                 locked_copy_string(chan, buf, ast_channel_musicclass(chan), len);
337         else if (!strcasecmp(data, "name")) {
338                 locked_copy_string(chan, buf, ast_channel_name(chan), len);
339         } else if (!strcasecmp(data, "parkinglot"))
340                 locked_copy_string(chan, buf, ast_channel_parkinglot(chan), len);
341         else if (!strcasecmp(data, "state"))
342                 locked_copy_string(chan, buf, ast_state2str(ast_channel_state(chan)), len);
343         else if (!strcasecmp(data, "onhold")) {
344                 locked_copy_string(chan, buf,
345                         ast_channel_hold_state(chan) == AST_CONTROL_HOLD ? "1" : "0", len);
346         } else if (!strcasecmp(data, "channeltype"))
347                 locked_copy_string(chan, buf, ast_channel_tech(chan)->type, len);
348         else if (!strcasecmp(data, "accountcode"))
349                 locked_copy_string(chan, buf, ast_channel_accountcode(chan), len);
350         else if (!strcasecmp(data, "checkhangup")) {
351                 locked_copy_string(chan, buf, ast_check_hangup(chan) ? "1" : "0", len);
352         } else if (!strcasecmp(data, "peeraccount"))
353                 locked_copy_string(chan, buf, ast_channel_peeraccount(chan), len);
354         else if (!strcasecmp(data, "hangupsource"))
355                 locked_copy_string(chan, buf, ast_channel_hangupsource(chan), len);
356         else if (!strcasecmp(data, "appname") && ast_channel_appl(chan))
357                 locked_copy_string(chan, buf, ast_channel_appl(chan), len);
358         else if (!strcasecmp(data, "appdata") && ast_channel_data(chan))
359                 locked_copy_string(chan, buf, ast_channel_data(chan), len);
360         else if (!strcasecmp(data, "exten") && ast_channel_data(chan))
361                 locked_copy_string(chan, buf, ast_channel_exten(chan), len);
362         else if (!strcasecmp(data, "context") && ast_channel_data(chan))
363                 locked_copy_string(chan, buf, ast_channel_context(chan), len);
364         else if (!strcasecmp(data, "userfield") && ast_channel_data(chan))
365                 locked_copy_string(chan, buf, ast_channel_userfield(chan), len);
366         else if (!strcasecmp(data, "channame") && ast_channel_data(chan))
367                 locked_copy_string(chan, buf, ast_channel_name(chan), len);
368         else if (!strcasecmp(data, "linkedid")) {
369                 ast_channel_lock(chan);
370                 if (ast_strlen_zero(ast_channel_linkedid(chan))) {
371                         /* fall back on the channel's uniqueid if linkedid is unset */
372                         ast_copy_string(buf, ast_channel_uniqueid(chan), len);
373                 }
374                 else {
375                         ast_copy_string(buf, ast_channel_linkedid(chan), len);
376                 }
377                 ast_channel_unlock(chan);
378         } else if (!strcasecmp(data, "peer")) {
379                 struct ast_channel *peer;
380
381                 peer = ast_channel_bridge_peer(chan);
382                 if (peer) {
383                         /* Only real channels could have a bridge peer this way. */
384                         ast_channel_lock(peer);
385                         ast_copy_string(buf, ast_channel_name(peer), len);
386                         ast_channel_unlock(peer);
387                         ast_channel_unref(peer);
388                 } else {
389                         buf[0] = '\0';
390                         ast_channel_lock(chan);
391                         if (!ast_channel_tech(chan)) {
392                                 const char *pname;
393
394                                 /*
395                                  * A dummy channel can still pass along bridged peer info
396                                  * via the BRIDGEPEER variable.
397                                  *
398                                  * A horrible kludge, but... how else?
399                                  */
400                                 pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
401                                 if (!ast_strlen_zero(pname)) {
402                                         ast_copy_string(buf, pname, len);
403                                 }
404                         }
405                         ast_channel_unlock(chan);
406                 }
407         } else if (!strcasecmp(data, "uniqueid")) {
408                 locked_copy_string(chan, buf, ast_channel_uniqueid(chan), len);
409         } else if (!strcasecmp(data, "transfercapability")) {
410                 locked_copy_string(chan, buf, transfercapability_table[ast_channel_transfercapability(chan) & 0x1f], len);
411         } else if (!strcasecmp(data, "callgroup")) {
412                 char groupbuf[256];
413
414                 locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_callgroup(chan)), len);
415         } else if (!strcasecmp(data, "pickupgroup")) {
416                 char groupbuf[256];
417
418                 locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_pickupgroup(chan)), len);
419         } else if (!strcasecmp(data, "namedcallgroup")) {
420                 struct ast_str *tmp_str = ast_str_alloca(1024);
421
422                 locked_copy_string(chan, buf,  ast_print_namedgroups(&tmp_str, ast_channel_named_callgroups(chan)), len);
423         } else if (!strcasecmp(data, "namedpickupgroup")) {
424                 struct ast_str *tmp_str = ast_str_alloca(1024);
425
426                 locked_copy_string(chan, buf,  ast_print_namedgroups(&tmp_str, ast_channel_named_pickupgroups(chan)), len);
427         } else if (!strcasecmp(data, "after_bridge_goto")) {
428                 ast_bridge_read_after_goto(chan, buf, len);
429         } else if (!strcasecmp(data, "amaflags")) {
430                 ast_channel_lock(chan);
431                 snprintf(buf, len, "%u", ast_channel_amaflags(chan));
432                 ast_channel_unlock(chan);
433         } else if (!strncasecmp(data, "secure_bridge_", 14)) {
434                 struct ast_datastore *ds;
435
436                 buf[0] = '\0';
437                 ast_channel_lock(chan);
438                 if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
439                         struct ast_secure_call_store *encrypt = ds->data;
440
441                         if (!strcasecmp(data, "secure_bridge_signaling")) {
442                                 snprintf(buf, len, "%s", encrypt->signaling ? "1" : "");
443                         } else if (!strcasecmp(data, "secure_bridge_media")) {
444                                 snprintf(buf, len, "%s", encrypt->media ? "1" : "");
445                         }
446                 }
447                 ast_channel_unlock(chan);
448         } else if (!strcasecmp(data, "max_forwards")) {
449                 ast_channel_lock(chan);
450                 snprintf(buf, len, "%d", ast_max_forwards_get(chan));
451                 ast_channel_unlock(chan);
452         } else if (!strcasecmp(data, "callid")) {
453                 ast_callid callid;
454
455                 buf[0] = '\0';
456                 ast_channel_lock(chan);
457                 callid = ast_channel_callid(chan);
458                 if (callid) {
459                         ast_callid_strnprint(buf, len, callid);
460                 }
461                 ast_channel_unlock(chan);
462         } 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)) {
463                 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
464                 ret = -1;
465         }
466
467         return ret;
468 }
469
470 static int func_channel_write_real(struct ast_channel *chan, const char *function,
471                               char *data, const char *value)
472 {
473         int ret = 0;
474         signed char gainset;
475
476         if (!strcasecmp(data, "language"))
477                 locked_string_field_set(chan, language, value);
478         else if (!strcasecmp(data, "parkinglot"))
479                 locked_string_field_set(chan, parkinglot, value);
480         else if (!strcasecmp(data, "musicclass"))
481                 locked_string_field_set(chan, musicclass, value);
482         else if (!strcasecmp(data, "accountcode"))
483                 locked_string_field_set(chan, accountcode, value);
484         else if (!strcasecmp(data, "userfield"))
485                 locked_string_field_set(chan, userfield, value);
486         else if (!strcasecmp(data, "after_bridge_goto")) {
487                 if (ast_strlen_zero(value)) {
488                         ast_bridge_discard_after_goto(chan);
489                 } else {
490                         ast_bridge_set_after_go_on(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), value);
491                 }
492         } else if (!strcasecmp(data, "amaflags")) {
493                 int amaflags;
494
495                 if (isdigit(*value)) {
496                         if (sscanf(value, "%30d", &amaflags) != 1) {
497                                 amaflags = AST_AMA_NONE;
498                         }
499                 } else {
500                         amaflags = ast_channel_string2amaflag(value);
501                 }
502                 ast_channel_lock(chan);
503                 ast_channel_amaflags_set(chan, amaflags);
504                 ast_channel_unlock(chan);
505         } else if (!strcasecmp(data, "peeraccount"))
506                 locked_string_field_set(chan, peeraccount, value);
507         else if (!strcasecmp(data, "hangupsource"))
508                 /* XXX - should we be forcing this here? */
509                 ast_set_hangupsource(chan, value, 0);
510         else if (!strcasecmp(data, "tonezone")) {
511                 struct ast_tone_zone *new_zone;
512                 if (!(new_zone = ast_get_indication_zone(value))) {
513                         ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
514                         ret = -1;
515                 } else {
516                         ast_channel_lock(chan);
517                         if (ast_channel_zone(chan)) {
518                                 ast_channel_zone_set(chan, ast_tone_zone_unref(ast_channel_zone(chan)));
519                         }
520                         ast_channel_zone_set(chan, ast_tone_zone_ref(new_zone));
521                         ast_channel_unlock(chan);
522                         new_zone = ast_tone_zone_unref(new_zone);
523                 }
524         } else if (!strcasecmp(data, "dtmf_features")) {
525                 ret = ast_bridge_features_ds_set_string(chan, value);
526         } else if (!strcasecmp(data, "callgroup")) {
527                 ast_channel_lock(chan);
528                 ast_channel_callgroup_set(chan, ast_get_group(value));
529                 ast_channel_unlock(chan);
530         } else if (!strcasecmp(data, "pickupgroup")) {
531                 ast_channel_lock(chan);
532                 ast_channel_pickupgroup_set(chan, ast_get_group(value));
533                 ast_channel_unlock(chan);
534         } else if (!strcasecmp(data, "namedcallgroup")) {
535                 struct ast_namedgroups *groups = ast_get_namedgroups(value);
536
537                 ast_channel_lock(chan);
538                 ast_channel_named_callgroups_set(chan, groups);
539                 ast_channel_unlock(chan);
540                 ast_unref_namedgroups(groups);
541         } else if (!strcasecmp(data, "namedpickupgroup")) {
542                 struct ast_namedgroups *groups = ast_get_namedgroups(value);
543
544                 ast_channel_lock(chan);
545                 ast_channel_named_pickupgroups_set(chan, groups);
546                 ast_channel_unlock(chan);
547                 ast_unref_namedgroups(groups);
548         } else if (!strcasecmp(data, "txgain")) {
549                 sscanf(value, "%4hhd", &gainset);
550                 ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
551         } else if (!strcasecmp(data, "rxgain")) {
552                 sscanf(value, "%4hhd", &gainset);
553                 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
554         } else if (!strcasecmp(data, "transfercapability")) {
555                 unsigned short i;
556
557                 ast_channel_lock(chan);
558                 for (i = 0; i < 0x20; i++) {
559                         if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
560                                 ast_channel_transfercapability_set(chan, i);
561                                 break;
562                         }
563                 }
564                 ast_channel_unlock(chan);
565         } else if (!strcasecmp(data, "hangup_handler_pop")) {
566                 /* Pop one hangup handler before pushing the new handler. */
567                 ast_pbx_hangup_handler_pop(chan);
568                 ast_pbx_hangup_handler_push(chan, value);
569         } else if (!strcasecmp(data, "hangup_handler_push")) {
570                 ast_pbx_hangup_handler_push(chan, value);
571         } else if (!strcasecmp(data, "hangup_handler_wipe")) {
572                 /* Pop all hangup handlers before pushing the new handler. */
573                 while (ast_pbx_hangup_handler_pop(chan)) {
574                 }
575                 ast_pbx_hangup_handler_push(chan, value);
576         } else if (!strncasecmp(data, "secure_bridge_", 14)) {
577                 struct ast_datastore *ds;
578                 struct ast_secure_call_store *store;
579
580                 if (!chan || !value) {
581                         return -1;
582                 }
583
584                 ast_channel_lock(chan);
585                 if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
586                         if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
587                                 ast_channel_unlock(chan);
588                                 return -1;
589                         }
590                         if (!(store = ast_calloc(1, sizeof(*store)))) {
591                                 ast_channel_unlock(chan);
592                                 ast_free(ds);
593                                 return -1;
594                         }
595                         ds->data = store;
596                         ast_channel_datastore_add(chan, ds);
597                 } else {
598                         store = ds->data;
599                 }
600
601                 if (!strcasecmp(data, "secure_bridge_signaling")) {
602                         store->signaling = ast_true(value) ? 1 : 0;
603                 } else if (!strcasecmp(data, "secure_bridge_media")) {
604                         store->media = ast_true(value) ? 1 : 0;
605                 }
606                 ast_channel_unlock(chan);
607         } else if (!strcasecmp(data, "max_forwards")) {
608                 int max_forwards;
609                 if (sscanf(value, "%d", &max_forwards) != 1) {
610                         ast_log(LOG_WARNING, "Unable to set max forwards to '%s'\n", value);
611                         ret = -1;
612                 } else {
613                         ast_channel_lock(chan);
614                         ret = ast_max_forwards_set(chan, max_forwards);
615                         ast_channel_unlock(chan);
616                 }
617         } else if (!ast_channel_tech(chan)->func_channel_write
618                  || ast_channel_tech(chan)->func_channel_write(chan, function, data, value)) {
619                 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
620                                 data);
621                 ret = -1;
622         }
623
624         return ret;
625 }
626
627 static int func_channel_write(struct ast_channel *chan, const char *function, char *data, const char *value)
628 {
629         int res;
630         ast_chan_write_info_t write_info = {
631                 .version = AST_CHAN_WRITE_INFO_T_VERSION,
632                 .write_fn = func_channel_write_real,
633                 .chan = chan,
634                 .function = function,
635                 .data = data,
636                 .value = value,
637         };
638
639         if (!chan) {
640                 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
641                 return -1;
642         }
643
644         res = func_channel_write_real(chan, function, data, value);
645         ast_channel_setoption(chan, AST_OPTION_CHANNEL_WRITE, &write_info, sizeof(write_info), 0);
646
647         return res;
648 }
649
650 static struct ast_custom_function channel_function = {
651         .name = "CHANNEL",
652         .read = func_channel_read,
653         .write = func_channel_write,
654 };
655
656 static int func_channels_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
657 {
658         struct ast_channel *c = NULL;
659         regex_t re;
660         int res;
661         size_t buflen = 0;
662         struct ast_channel_iterator *iter;
663
664         buf[0] = '\0';
665
666         if (!ast_strlen_zero(data)) {
667                 if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
668                         regerror(res, &re, buf, maxlen);
669                         ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf);
670                         return -1;
671                 }
672         }
673
674         if (!(iter = ast_channel_iterator_all_new())) {
675                 if (!ast_strlen_zero(data)) {
676                         regfree(&re);
677                 }
678                 return -1;
679         }
680
681         while ((c = ast_channel_iterator_next(iter))) {
682                 ast_channel_lock(c);
683                 if (ast_strlen_zero(data) || regexec(&re, ast_channel_name(c), 0, NULL, 0) == 0) {
684                         size_t namelen = strlen(ast_channel_name(c));
685                         if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
686                                 if (!ast_strlen_zero(buf)) {
687                                         strcat(buf, " ");
688                                         buflen++;
689                                 }
690                                 strcat(buf, ast_channel_name(c));
691                                 buflen += namelen;
692                         } else {
693                                 ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space.  Output will be truncated!\n");
694                         }
695                 }
696                 ast_channel_unlock(c);
697                 c = ast_channel_unref(c);
698         }
699
700         ast_channel_iterator_destroy(iter);
701
702         if (!ast_strlen_zero(data)) {
703                 regfree(&re);
704         }
705
706         return 0;
707 }
708
709 static struct ast_custom_function channels_function = {
710         .name = "CHANNELS",
711         .read = func_channels_read,
712 };
713
714 static int func_mchan_read(struct ast_channel *chan, const char *function,
715                              char *data, struct ast_str **buf, ssize_t len)
716 {
717         struct ast_channel *mchan;
718         char *template = ast_alloca(4 + strlen(data));
719
720         if (!chan) {
721                 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
722                 return -1;
723         }
724
725         mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
726         sprintf(template, "${%s}", data); /* SAFE */
727         ast_str_substitute_variables(buf, len, mchan ? mchan : chan, template);
728         if (mchan) {
729                 ast_channel_unref(mchan);
730         }
731         return 0;
732 }
733
734 static int func_mchan_write(struct ast_channel *chan, const char *function,
735                               char *data, const char *value)
736 {
737         struct ast_channel *mchan;
738
739         if (!chan) {
740                 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
741                 return -1;
742         }
743
744         mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
745         pbx_builtin_setvar_helper(mchan ? mchan : chan, data, value);
746         if (mchan) {
747                 ast_channel_unref(mchan);
748         }
749         return 0;
750 }
751
752 static struct ast_custom_function mchan_function = {
753         .name = "MASTER_CHANNEL",
754         .read2 = func_mchan_read,
755         .write = func_mchan_write,
756 };
757
758 static int unload_module(void)
759 {
760         int res = 0;
761
762         res |= ast_custom_function_unregister(&channel_function);
763         res |= ast_custom_function_unregister(&channels_function);
764         res |= ast_custom_function_unregister(&mchan_function);
765
766         return res;
767 }
768
769 static int load_module(void)
770 {
771         int res = 0;
772
773         res |= ast_custom_function_register(&channel_function);
774         res |= ast_custom_function_register(&channels_function);
775         res |= ast_custom_function_register(&mchan_function);
776
777         return res;
778 }
779
780 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel information dialplan functions");