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