Merge "BuildSystem: Really do not pass unknown-warning options to the compiler."
[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="trace">
209                                                 <para>R/W whether or not context tracing is enabled, only available
210                                                 <emphasis>if CHANNEL_TRACE is defined</emphasis>.</para>
211                                         </enum>
212                                         <enum name="hangupsource">
213                                                 <para>R/W returns the channel responsible for hangup.</para>
214                                         </enum>
215                                         <enum name="appname">
216                                                 <para>R/O returns the internal application name.</para>
217                                         </enum>
218                                         <enum name="appdata">
219                                                 <para>R/O returns the application data if available.</para>
220                                         </enum>
221                                         <enum name="exten">
222                                                 <para>R/O returns the extension for an outbound channel.</para>
223                                         </enum>
224                                         <enum name="context">
225                                                 <para>R/O returns the context for an outbound channel.</para>
226                                         </enum>
227                                         <enum name="channame">
228                                                 <para>R/O returns the channel name for an outbound channel.</para>
229                                         </enum>
230                                         <enum name="uniqueid">
231                                                 <para>R/O returns the channel uniqueid.</para>
232                                         </enum>
233                                         <enum name="linkedid">
234                                                 <para>R/O returns the linkedid if available, otherwise returns the uniqueid.</para>
235                                         </enum>
236                                         <enum name="max_forwards">
237                                                 <para>R/W The maximum number of forwards allowed.</para>
238                                         </enum>
239                                         <enum name="callid">
240                                                 <para>R/O Call identifier log tag associated with the channel
241                                                 e.g., <literal>[C-00000000]</literal>.</para>
242                                         </enum>
243                                 </enumlist>
244                                 <xi:include xpointer="xpointer(/docs/info[@name='CHANNEL'])" />
245                         </parameter>
246                 </syntax>
247                 <description>
248                         <para>Gets/sets various pieces of information about the channel, additional <replaceable>item</replaceable> may
249                         be available from the channel driver; see its documentation for details. Any <replaceable>item</replaceable>
250                         requested that is not available on the current channel will return an empty string.</para>
251                         <example title="Standard CHANNEL item examples">
252                                 ; Push a hangup handler subroutine existing at dialplan
253                                 ; location default,s,1 onto the current channel
254                                 same => n,Set(CHANNEL(hangup_handler_push)=default,s,1)
255
256                                 ; Set the current tonezone to Germany (de)
257                                 same => n,Set(CHANNEL(tonezone)=de)
258
259                                 ; Set the allowed maximum number of forwarding attempts
260                                 same => n,Set(CHANNEL(max_forwards)=10)
261
262                                 ; If this channel is ejected from its next bridge, and if
263                                 ; the channel is not hung up, begin executing dialplan at
264                                 ; location default,after-bridge,1
265                                 same => n,Set(CHANNEL(after_bridge_goto)=default,after-bridge,1)
266
267                                 ; Log the current state of the channel
268                                 same => n,Log(NOTICE, This channel is: ${CHANNEL(state)})
269                         </example>
270                         <xi:include xpointer="xpointer(/docs/info[@name='CHANNEL_EXAMPLES'])" />
271                 </description>
272         </function>
273  ***/
274
275 #define locked_copy_string(chan, dest, source, len) \
276         do { \
277                 ast_channel_lock(chan); \
278                 ast_copy_string(dest, source, len); \
279                 ast_channel_unlock(chan); \
280         } while (0)
281 #define locked_string_field_set(chan, field, source) \
282         do { \
283                 ast_channel_lock(chan); \
284                 ast_channel_##field##_set(chan, source); \
285                 ast_channel_unlock(chan); \
286         } while (0)
287
288 static const char * const transfercapability_table[0x20] = {
289         "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
290         "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
291         "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
292         "VIDEO", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", };
293
294 static int func_channel_read(struct ast_channel *chan, const char *function,
295                              char *data, char *buf, size_t len)
296 {
297         int ret = 0;
298         struct ast_format_cap *tmpcap;
299
300         if (!chan) {
301                 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
302                 return -1;
303         }
304
305         if (!strcasecmp(data, "audionativeformat")) {
306                 tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
307                 if (tmpcap) {
308                         struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
309
310                         ast_channel_lock(chan);
311                         ast_format_cap_append_from_cap(tmpcap, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_AUDIO);
312                         ast_channel_unlock(chan);
313                         ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len);
314                         ao2_ref(tmpcap, -1);
315                 }
316         } else if (!strcasecmp(data, "videonativeformat")) {
317                 tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
318                 if (tmpcap) {
319                         struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
320
321                         ast_channel_lock(chan);
322                         ast_format_cap_append_from_cap(tmpcap, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_VIDEO);
323                         ast_channel_unlock(chan);
324                         ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len);
325                         ao2_ref(tmpcap, -1);
326                 }
327         } else if (!strcasecmp(data, "audioreadformat")) {
328                 locked_copy_string(chan, buf, ast_format_get_name(ast_channel_readformat(chan)), len);
329         } else if (!strcasecmp(data, "audiowriteformat")) {
330                 locked_copy_string(chan, buf, ast_format_get_name(ast_channel_writeformat(chan)), len);
331 #ifdef CHANNEL_TRACE
332         } else if (!strcasecmp(data, "trace")) {
333                 locked_copy_string(chan, buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
334 #endif
335         } else if (!strcasecmp(data, "tonezone") && ast_channel_zone(chan)) {
336                 locked_copy_string(chan, buf, ast_channel_zone(chan)->country, len);
337         } else if (!strcasecmp(data, "dtmf_features")) {
338                 if (ast_bridge_features_ds_get_string(chan, buf, len)) {
339                         buf[0] = '\0';
340                 }
341         } else if (!strcasecmp(data, "language"))
342                 locked_copy_string(chan, buf, ast_channel_language(chan), len);
343         else if (!strcasecmp(data, "musicclass"))
344                 locked_copy_string(chan, buf, ast_channel_musicclass(chan), len);
345         else if (!strcasecmp(data, "name")) {
346                 locked_copy_string(chan, buf, ast_channel_name(chan), len);
347         } else if (!strcasecmp(data, "parkinglot"))
348                 locked_copy_string(chan, buf, ast_channel_parkinglot(chan), len);
349         else if (!strcasecmp(data, "state"))
350                 locked_copy_string(chan, buf, ast_state2str(ast_channel_state(chan)), len);
351         else if (!strcasecmp(data, "onhold")) {
352                 locked_copy_string(chan, buf,
353                         ast_channel_hold_state(chan) == AST_CONTROL_HOLD ? "1" : "0", len);
354         } else if (!strcasecmp(data, "channeltype"))
355                 locked_copy_string(chan, buf, ast_channel_tech(chan)->type, len);
356         else if (!strcasecmp(data, "accountcode"))
357                 locked_copy_string(chan, buf, ast_channel_accountcode(chan), len);
358         else if (!strcasecmp(data, "checkhangup")) {
359                 locked_copy_string(chan, buf, ast_check_hangup(chan) ? "1" : "0", len);
360         } else if (!strcasecmp(data, "peeraccount"))
361                 locked_copy_string(chan, buf, ast_channel_peeraccount(chan), len);
362         else if (!strcasecmp(data, "hangupsource"))
363                 locked_copy_string(chan, buf, ast_channel_hangupsource(chan), len);
364         else if (!strcasecmp(data, "appname") && ast_channel_appl(chan))
365                 locked_copy_string(chan, buf, ast_channel_appl(chan), len);
366         else if (!strcasecmp(data, "appdata") && ast_channel_data(chan))
367                 locked_copy_string(chan, buf, ast_channel_data(chan), len);
368         else if (!strcasecmp(data, "exten") && ast_channel_data(chan))
369                 locked_copy_string(chan, buf, ast_channel_exten(chan), len);
370         else if (!strcasecmp(data, "context") && ast_channel_data(chan))
371                 locked_copy_string(chan, buf, ast_channel_context(chan), len);
372         else if (!strcasecmp(data, "userfield") && ast_channel_data(chan))
373                 locked_copy_string(chan, buf, ast_channel_userfield(chan), len);
374         else if (!strcasecmp(data, "channame") && ast_channel_data(chan))
375                 locked_copy_string(chan, buf, ast_channel_name(chan), len);
376         else if (!strcasecmp(data, "linkedid")) {
377                 ast_channel_lock(chan);
378                 if (ast_strlen_zero(ast_channel_linkedid(chan))) {
379                         /* fall back on the channel's uniqueid if linkedid is unset */
380                         ast_copy_string(buf, ast_channel_uniqueid(chan), len);
381                 }
382                 else {
383                         ast_copy_string(buf, ast_channel_linkedid(chan), len);
384                 }
385                 ast_channel_unlock(chan);
386         } else if (!strcasecmp(data, "peer")) {
387                 struct ast_channel *peer;
388
389                 peer = ast_channel_bridge_peer(chan);
390                 if (peer) {
391                         /* Only real channels could have a bridge peer this way. */
392                         ast_channel_lock(peer);
393                         ast_copy_string(buf, ast_channel_name(peer), len);
394                         ast_channel_unlock(peer);
395                         ast_channel_unref(peer);
396                 } else {
397                         buf[0] = '\0';
398                         ast_channel_lock(chan);
399                         if (!ast_channel_tech(chan)) {
400                                 const char *pname;
401
402                                 /*
403                                  * A dummy channel can still pass along bridged peer info
404                                  * via the BRIDGEPEER variable.
405                                  *
406                                  * A horrible kludge, but... how else?
407                                  */
408                                 pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
409                                 if (!ast_strlen_zero(pname)) {
410                                         ast_copy_string(buf, pname, len);
411                                 }
412                         }
413                         ast_channel_unlock(chan);
414                 }
415         } else if (!strcasecmp(data, "uniqueid")) {
416                 locked_copy_string(chan, buf, ast_channel_uniqueid(chan), len);
417         } else if (!strcasecmp(data, "transfercapability")) {
418                 locked_copy_string(chan, buf, transfercapability_table[ast_channel_transfercapability(chan) & 0x1f], len);
419         } else if (!strcasecmp(data, "callgroup")) {
420                 char groupbuf[256];
421
422                 locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_callgroup(chan)), len);
423         } else if (!strcasecmp(data, "pickupgroup")) {
424                 char groupbuf[256];
425
426                 locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_pickupgroup(chan)), len);
427         } else if (!strcasecmp(data, "namedcallgroup")) {
428                 struct ast_str *tmp_str = ast_str_alloca(1024);
429
430                 locked_copy_string(chan, buf,  ast_print_namedgroups(&tmp_str, ast_channel_named_callgroups(chan)), len);
431         } else if (!strcasecmp(data, "namedpickupgroup")) {
432                 struct ast_str *tmp_str = ast_str_alloca(1024);
433
434                 locked_copy_string(chan, buf,  ast_print_namedgroups(&tmp_str, ast_channel_named_pickupgroups(chan)), len);
435         } else if (!strcasecmp(data, "after_bridge_goto")) {
436                 ast_bridge_read_after_goto(chan, buf, len);
437         } else if (!strcasecmp(data, "amaflags")) {
438                 ast_channel_lock(chan);
439                 snprintf(buf, len, "%u", ast_channel_amaflags(chan));
440                 ast_channel_unlock(chan);
441         } else if (!strncasecmp(data, "secure_bridge_", 14)) {
442                 struct ast_datastore *ds;
443
444                 buf[0] = '\0';
445                 ast_channel_lock(chan);
446                 if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
447                         struct ast_secure_call_store *encrypt = ds->data;
448
449                         if (!strcasecmp(data, "secure_bridge_signaling")) {
450                                 snprintf(buf, len, "%s", encrypt->signaling ? "1" : "");
451                         } else if (!strcasecmp(data, "secure_bridge_media")) {
452                                 snprintf(buf, len, "%s", encrypt->media ? "1" : "");
453                         }
454                 }
455                 ast_channel_unlock(chan);
456         } else if (!strcasecmp(data, "max_forwards")) {
457                 ast_channel_lock(chan);
458                 snprintf(buf, len, "%d", ast_max_forwards_get(chan));
459                 ast_channel_unlock(chan);
460         } else if (!strcasecmp(data, "callid")) {
461                 ast_callid callid;
462
463                 buf[0] = '\0';
464                 ast_channel_lock(chan);
465                 callid = ast_channel_callid(chan);
466                 if (callid) {
467                         ast_callid_strnprint(buf, len, callid);
468                 }
469                 ast_channel_unlock(chan);
470         } 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)) {
471                 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
472                 ret = -1;
473         }
474
475         return ret;
476 }
477
478 static int func_channel_write_real(struct ast_channel *chan, const char *function,
479                               char *data, const char *value)
480 {
481         int ret = 0;
482         signed char gainset;
483
484         if (!strcasecmp(data, "language"))
485                 locked_string_field_set(chan, language, value);
486         else if (!strcasecmp(data, "parkinglot"))
487                 locked_string_field_set(chan, parkinglot, value);
488         else if (!strcasecmp(data, "musicclass"))
489                 locked_string_field_set(chan, musicclass, value);
490         else if (!strcasecmp(data, "accountcode"))
491                 locked_string_field_set(chan, accountcode, value);
492         else if (!strcasecmp(data, "userfield"))
493                 locked_string_field_set(chan, userfield, value);
494         else if (!strcasecmp(data, "after_bridge_goto")) {
495                 if (ast_strlen_zero(value)) {
496                         ast_bridge_discard_after_goto(chan);
497                 } else {
498                         ast_bridge_set_after_go_on(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), value);
499                 }
500         } else if (!strcasecmp(data, "amaflags")) {
501                 int amaflags;
502
503                 if (isdigit(*value)) {
504                         if (sscanf(value, "%30d", &amaflags) != 1) {
505                                 amaflags = AST_AMA_NONE;
506                         }
507                 } else {
508                         amaflags = ast_channel_string2amaflag(value);
509                 }
510                 ast_channel_lock(chan);
511                 ast_channel_amaflags_set(chan, amaflags);
512                 ast_channel_unlock(chan);
513         } else if (!strcasecmp(data, "peeraccount"))
514                 locked_string_field_set(chan, peeraccount, value);
515         else if (!strcasecmp(data, "hangupsource"))
516                 /* XXX - should we be forcing this here? */
517                 ast_set_hangupsource(chan, value, 0);
518 #ifdef CHANNEL_TRACE
519         else if (!strcasecmp(data, "trace")) {
520                 ast_channel_lock(chan);
521                 if (ast_true(value))
522                         ret = ast_channel_trace_enable(chan);
523                 else if (ast_false(value))
524                         ret = ast_channel_trace_disable(chan);
525                 else {
526                         ret = -1;
527                         ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).\n");
528                 }
529                 ast_channel_unlock(chan);
530         }
531 #endif
532         else if (!strcasecmp(data, "tonezone")) {
533                 struct ast_tone_zone *new_zone;
534                 if (!(new_zone = ast_get_indication_zone(value))) {
535                         ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
536                         ret = -1;
537                 } else {
538                         ast_channel_lock(chan);
539                         if (ast_channel_zone(chan)) {
540                                 ast_channel_zone_set(chan, ast_tone_zone_unref(ast_channel_zone(chan)));
541                         }
542                         ast_channel_zone_set(chan, ast_tone_zone_ref(new_zone));
543                         ast_channel_unlock(chan);
544                         new_zone = ast_tone_zone_unref(new_zone);
545                 }
546         } else if (!strcasecmp(data, "dtmf_features")) {
547                 ret = ast_bridge_features_ds_set_string(chan, value);
548         } else if (!strcasecmp(data, "callgroup")) {
549                 ast_channel_lock(chan);
550                 ast_channel_callgroup_set(chan, ast_get_group(value));
551                 ast_channel_unlock(chan);
552         } else if (!strcasecmp(data, "pickupgroup")) {
553                 ast_channel_lock(chan);
554                 ast_channel_pickupgroup_set(chan, ast_get_group(value));
555                 ast_channel_unlock(chan);
556         } else if (!strcasecmp(data, "namedcallgroup")) {
557                 struct ast_namedgroups *groups = ast_get_namedgroups(value);
558
559                 ast_channel_lock(chan);
560                 ast_channel_named_callgroups_set(chan, groups);
561                 ast_channel_unlock(chan);
562                 ast_unref_namedgroups(groups);
563         } else if (!strcasecmp(data, "namedpickupgroup")) {
564                 struct ast_namedgroups *groups = ast_get_namedgroups(value);
565
566                 ast_channel_lock(chan);
567                 ast_channel_named_pickupgroups_set(chan, groups);
568                 ast_channel_unlock(chan);
569                 ast_unref_namedgroups(groups);
570         } else if (!strcasecmp(data, "txgain")) {
571                 sscanf(value, "%4hhd", &gainset);
572                 ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
573         } else if (!strcasecmp(data, "rxgain")) {
574                 sscanf(value, "%4hhd", &gainset);
575                 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
576         } else if (!strcasecmp(data, "transfercapability")) {
577                 unsigned short i;
578
579                 ast_channel_lock(chan);
580                 for (i = 0; i < 0x20; i++) {
581                         if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
582                                 ast_channel_transfercapability_set(chan, i);
583                                 break;
584                         }
585                 }
586                 ast_channel_unlock(chan);
587         } else if (!strcasecmp(data, "hangup_handler_pop")) {
588                 /* Pop one hangup handler before pushing the new handler. */
589                 ast_pbx_hangup_handler_pop(chan);
590                 ast_pbx_hangup_handler_push(chan, value);
591         } else if (!strcasecmp(data, "hangup_handler_push")) {
592                 ast_pbx_hangup_handler_push(chan, value);
593         } else if (!strcasecmp(data, "hangup_handler_wipe")) {
594                 /* Pop all hangup handlers before pushing the new handler. */
595                 while (ast_pbx_hangup_handler_pop(chan)) {
596                 }
597                 ast_pbx_hangup_handler_push(chan, value);
598         } else if (!strncasecmp(data, "secure_bridge_", 14)) {
599                 struct ast_datastore *ds;
600                 struct ast_secure_call_store *store;
601
602                 if (!chan || !value) {
603                         return -1;
604                 }
605
606                 ast_channel_lock(chan);
607                 if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
608                         if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
609                                 ast_channel_unlock(chan);
610                                 return -1;
611                         }
612                         if (!(store = ast_calloc(1, sizeof(*store)))) {
613                                 ast_channel_unlock(chan);
614                                 ast_free(ds);
615                                 return -1;
616                         }
617                         ds->data = store;
618                         ast_channel_datastore_add(chan, ds);
619                 } else {
620                         store = ds->data;
621                 }
622
623                 if (!strcasecmp(data, "secure_bridge_signaling")) {
624                         store->signaling = ast_true(value) ? 1 : 0;
625                 } else if (!strcasecmp(data, "secure_bridge_media")) {
626                         store->media = ast_true(value) ? 1 : 0;
627                 }
628                 ast_channel_unlock(chan);
629         } else if (!strcasecmp(data, "max_forwards")) {
630                 int max_forwards;
631                 if (sscanf(value, "%d", &max_forwards) != 1) {
632                         ast_log(LOG_WARNING, "Unable to set max forwards to '%s'\n", value);
633                         ret = -1;
634                 } else {
635                         ast_channel_lock(chan);
636                         ret = ast_max_forwards_set(chan, max_forwards);
637                         ast_channel_unlock(chan);
638                 }
639         } else if (!ast_channel_tech(chan)->func_channel_write
640                  || ast_channel_tech(chan)->func_channel_write(chan, function, data, value)) {
641                 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
642                                 data);
643                 ret = -1;
644         }
645
646         return ret;
647 }
648
649 static int func_channel_write(struct ast_channel *chan, const char *function, char *data, const char *value)
650 {
651         int res;
652         ast_chan_write_info_t write_info = {
653                 .version = AST_CHAN_WRITE_INFO_T_VERSION,
654                 .write_fn = func_channel_write_real,
655                 .chan = chan,
656                 .function = function,
657                 .data = data,
658                 .value = value,
659         };
660
661         if (!chan) {
662                 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
663                 return -1;
664         }
665
666         res = func_channel_write_real(chan, function, data, value);
667         ast_channel_setoption(chan, AST_OPTION_CHANNEL_WRITE, &write_info, sizeof(write_info), 0);
668
669         return res;
670 }
671
672 static struct ast_custom_function channel_function = {
673         .name = "CHANNEL",
674         .read = func_channel_read,
675         .write = func_channel_write,
676 };
677
678 static int func_channels_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen)
679 {
680         struct ast_channel *c = NULL;
681         regex_t re;
682         int res;
683         size_t buflen = 0;
684         struct ast_channel_iterator *iter;
685
686         buf[0] = '\0';
687
688         if (!ast_strlen_zero(data)) {
689                 if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
690                         regerror(res, &re, buf, maxlen);
691                         ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf);
692                         return -1;
693                 }
694         }
695
696         if (!(iter = ast_channel_iterator_all_new())) {
697                 if (!ast_strlen_zero(data)) {
698                         regfree(&re);
699                 }
700                 return -1;
701         }
702
703         while ((c = ast_channel_iterator_next(iter))) {
704                 ast_channel_lock(c);
705                 if (ast_strlen_zero(data) || regexec(&re, ast_channel_name(c), 0, NULL, 0) == 0) {
706                         size_t namelen = strlen(ast_channel_name(c));
707                         if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
708                                 if (!ast_strlen_zero(buf)) {
709                                         strcat(buf, " ");
710                                         buflen++;
711                                 }
712                                 strcat(buf, ast_channel_name(c));
713                                 buflen += namelen;
714                         } else {
715                                 ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space.  Output will be truncated!\n");
716                         }
717                 }
718                 ast_channel_unlock(c);
719                 c = ast_channel_unref(c);
720         }
721
722         ast_channel_iterator_destroy(iter);
723
724         if (!ast_strlen_zero(data)) {
725                 regfree(&re);
726         }
727
728         return 0;
729 }
730
731 static struct ast_custom_function channels_function = {
732         .name = "CHANNELS",
733         .read = func_channels_read,
734 };
735
736 static int func_mchan_read(struct ast_channel *chan, const char *function,
737                              char *data, struct ast_str **buf, ssize_t len)
738 {
739         struct ast_channel *mchan;
740         char *template = ast_alloca(4 + strlen(data));
741
742         if (!chan) {
743                 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
744                 return -1;
745         }
746
747         mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
748         sprintf(template, "${%s}", data); /* SAFE */
749         ast_str_substitute_variables(buf, len, mchan ? mchan : chan, template);
750         if (mchan) {
751                 ast_channel_unref(mchan);
752         }
753         return 0;
754 }
755
756 static int func_mchan_write(struct ast_channel *chan, const char *function,
757                               char *data, const char *value)
758 {
759         struct ast_channel *mchan;
760
761         if (!chan) {
762                 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
763                 return -1;
764         }
765
766         mchan = ast_channel_get_by_name(ast_channel_linkedid(chan));
767         pbx_builtin_setvar_helper(mchan ? mchan : chan, data, value);
768         if (mchan) {
769                 ast_channel_unref(mchan);
770         }
771         return 0;
772 }
773
774 static struct ast_custom_function mchan_function = {
775         .name = "MASTER_CHANNEL",
776         .read2 = func_mchan_read,
777         .write = func_mchan_write,
778 };
779
780 static int unload_module(void)
781 {
782         int res = 0;
783
784         res |= ast_custom_function_unregister(&channel_function);
785         res |= ast_custom_function_unregister(&channels_function);
786         res |= ast_custom_function_unregister(&mchan_function);
787
788         return res;
789 }
790
791 static int load_module(void)
792 {
793         int res = 0;
794
795         res |= ast_custom_function_register(&channel_function);
796         res |= ast_custom_function_register(&channels_function);
797         res |= ast_custom_function_register(&mchan_function);
798
799         return res;
800 }
801
802 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel information dialplan functions");