Newer
Older
* Asterisk -- An open source telephony toolkit.
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
*
* \brief Execute an ISDN RAS
*
* \author Mark Spencer <markster@digium.com>
Kevin P. Fleming
committed
/*** MODULEINFO
<depend>dahdi</depend>
<support_level>deprecated</support_level>
Kevin P. Fleming
committed
***/
Kevin P. Fleming
committed
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
Tilghman Lesher
committed
#include "asterisk/app.h"
/*** DOCUMENTATION
<application name="DAHDIRAS" language="en_US">
<synopsis>
Executes DAHDI ISDN RAS application.
</synopsis>
<syntax>
<parameter name="args" required="true">
<para>A list of parameters to pass to the pppd daemon,
separated by <literal>,</literal> characters.</para>
</parameter>
</syntax>
<description>
<para>Executes a RAS server using pppd on the given channel.
The channel must be a clear channel (i.e. PRI source) and a DAHDI
channel to be able to use this function (No modem emulation is included).</para>
<para>Your pppd must be patched to be DAHDI aware.</para>
</description>
</application>
static const char app[] = "DAHDIRAS";
#define PPP_MAX_ARGS 32
#define PPP_EXEC "/usr/sbin/pppd"
static pid_t spawn_ras(struct ast_channel *chan, char *args)
{
pid_t pid;
char *c;
char *argv[PPP_MAX_ARGS];
int argc = 0;
Tilghman Lesher
committed
pid = ast_safe_fork(1);
dup2(ast_channel_fd(chan, 0), STDIN_FILENO);
/* Drop high priority */
if (ast_opt_high_priority)
ast_set_priority(0);
Tilghman Lesher
committed
ast_close_fds_above_n(STDERR_FILENO);
/* Reset all arguments */
memset(argv, 0, sizeof(argv));
/* First argument is executable, followed by standard
arguments for DAHDI PPP */
argv[argc++] = PPP_EXEC;
argv[argc++] = "nodetach";
/* And all the other arguments */
Tilghman Lesher
committed
c = strsep(&stringp, ",");
while(c && strlen(c) && (argc < (PPP_MAX_ARGS - 4))) {
argv[argc++] = c;
Tilghman Lesher
committed
c = strsep(&stringp, ",");
argv[argc++] = "dahdi.so";
argv[argc++] = "stdin";
/* Finally launch PPP */
execv(PPP_EXEC, argv);
fprintf(stderr, "Failed to exec PPPD!\n");
exit(1);
}
static void run_ras(struct ast_channel *chan, char *args)
{
pid_t pid;
int status;
int res;
int signalled = 0;
struct dahdi_bufferinfo savebi;
res = ioctl(ast_channel_fd(chan, 0), DAHDI_GET_BUFINFO, &savebi);
Kevin P. Fleming
committed
if(res) {
ast_log(LOG_WARNING, "Unable to check buffer policy on channel %s\n", ast_channel_name(chan));
Kevin P. Fleming
committed
return;
}
pid = spawn_ras(chan, args);
if (pid < 0) {
ast_log(LOG_WARNING, "Failed to spawn RAS\n");
} else {
for (;;) {
res = waitpid(pid, &status, WNOHANG);
Russell Bryant
committed
if (ast_check_hangup(chan) && !signalled) {
ast_debug(1, "Channel '%s' hungup. Signalling RAS at %d to die...\n", ast_channel_name(chan), pid);
kill(pid, SIGTERM);
signalled=1;
}
/* Try again */
sleep(1);
continue;
}
if (res < 0) {
ast_log(LOG_WARNING, "waitpid returned %d: %s\n", res, strerror(errno));
if (WIFEXITED(status)) {
ast_verb(3, "RAS on %s terminated with status %d\n", ast_channel_name(chan), WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
ast_verb(3, "RAS on %s terminated with signal %d\n",
ast_channel_name(chan), WTERMSIG(status));
} else {
ast_verb(3, "RAS on %s terminated weirdly.\n", ast_channel_name(chan));
}
ioctl(ast_channel_fd(chan, 0), DAHDI_AUDIOMODE, &x);
Kevin P. Fleming
committed
/* Restore saved values */
res = ioctl(ast_channel_fd(chan, 0), DAHDI_SET_BUFINFO, &savebi);
Kevin P. Fleming
committed
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set buffer policy on channel %s\n", ast_channel_name(chan));
Kevin P. Fleming
committed
}
Tilghman Lesher
committed
ast_safe_fork_cleanup();
static int dahdiras_exec(struct ast_channel *chan, const char *data)
Russell Bryant
committed
char *args;
Kevin P. Fleming
committed
struct dahdi_params dahdip;
Russell Bryant
committed
Russell Bryant
committed
args = ast_strdupa(data);
if (ast_channel_state(chan) != AST_STATE_UP)
if (strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {
/* If it's not a DAHDI channel, we're done. Wait a couple of
ast_verb(2, "Channel %s is not a DAHDI channel\n", ast_channel_name(chan));
memset(&dahdip, 0, sizeof(dahdip));
if (ioctl(ast_channel_fd(chan, 0), DAHDI_GET_PARAMS, &dahdip)) {
ast_log(LOG_WARNING, "Unable to get DAHDI parameters\n");
} else if (dahdip.sigtype != DAHDI_SIG_CLEAR) {
ast_verb(2, "Channel %s is not a clear channel\n", ast_channel_name(chan));
} else {
/* Everything should be okay. Run PPP. */
ast_verb(3, "Starting RAS on %s\n", ast_channel_name(chan));
/* Execute RAS */
run_ras(chan, args);
}
}
return res;
}
static int unload_module(void)
return ast_unregister_application(app);
static int load_module(void)
return ((ast_register_application_xml(app, dahdiras_exec)) ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS);
AST_MODULE_INFO_STANDARD_DEPRECATED(ASTERISK_GPL_KEY, "DAHDI ISDN Remote Access Server");