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