Wed Jan 8 2020 09:49:39

Asterisk developer's documentation


app_dahdiras.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief Execute an ISDN RAS
22  *
23  * \author Mark Spencer <markster@digium.com>
24  *
25  * \ingroup applications
26  */
27 
28 /*** MODULEINFO
29  <depend>dahdi</depend>
30  <support_level>extended</support_level>
31  ***/
32 
33 #include "asterisk.h"
34 
35 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
36 
37 #include <sys/ioctl.h>
38 #include <sys/wait.h>
39 #ifdef __linux__
40 #include <sys/signal.h>
41 #else
42 #include <signal.h>
43 #endif /* __linux__ */
44 
45 #include <fcntl.h>
46 
47 #include <dahdi/user.h>
48 
49 #include "asterisk/lock.h"
50 #include "asterisk/file.h"
51 #include "asterisk/channel.h"
52 #include "asterisk/pbx.h"
53 #include "asterisk/module.h"
54 #include "asterisk/app.h"
55 
56 /*** DOCUMENTATION
57  <application name="DAHDIRAS" language="en_US">
58  <synopsis>
59  Executes DAHDI ISDN RAS application.
60  </synopsis>
61  <syntax>
62  <parameter name="args" required="true">
63  <para>A list of parameters to pass to the pppd daemon,
64  separated by <literal>,</literal> characters.</para>
65  </parameter>
66  </syntax>
67  <description>
68  <para>Executes a RAS server using pppd on the given channel.
69  The channel must be a clear channel (i.e. PRI source) and a DAHDI
70  channel to be able to use this function (No modem emulation is included).</para>
71  <para>Your pppd must be patched to be DAHDI aware.</para>
72  </description>
73  </application>
74 
75  ***/
76 
77 static const char app[] = "DAHDIRAS";
78 
79 #define PPP_MAX_ARGS 32
80 #define PPP_EXEC "/usr/sbin/pppd"
81 
82 static pid_t spawn_ras(struct ast_channel *chan, char *args)
83 {
84  pid_t pid;
85  char *c;
86 
87  char *argv[PPP_MAX_ARGS];
88  int argc = 0;
89  char *stringp=NULL;
90 
91  /* Start by forking */
92  pid = ast_safe_fork(1);
93  if (pid) {
94  return pid;
95  }
96 
97  /* Execute RAS on File handles */
98  dup2(chan->fds[0], STDIN_FILENO);
99 
100  /* Drop high priority */
102  ast_set_priority(0);
103 
104  /* Close other file descriptors */
105  ast_close_fds_above_n(STDERR_FILENO);
106 
107  /* Reset all arguments */
108  memset(argv, 0, sizeof(argv));
109 
110  /* First argument is executable, followed by standard
111  arguments for DAHDI PPP */
112  argv[argc++] = PPP_EXEC;
113  argv[argc++] = "nodetach";
114 
115  /* And all the other arguments */
116  stringp=args;
117  c = strsep(&stringp, ",");
118  while(c && strlen(c) && (argc < (PPP_MAX_ARGS - 4))) {
119  argv[argc++] = c;
120  c = strsep(&stringp, ",");
121  }
122 
123  argv[argc++] = "plugin";
124  argv[argc++] = "dahdi.so";
125  argv[argc++] = "stdin";
126 
127  /* Finally launch PPP */
128  execv(PPP_EXEC, argv);
129  fprintf(stderr, "Failed to exec PPPD!\n");
130  exit(1);
131 }
132 
133 static void run_ras(struct ast_channel *chan, char *args)
134 {
135  pid_t pid;
136  int status;
137  int res;
138  int signalled = 0;
139  struct dahdi_bufferinfo savebi;
140  int x;
141 
142  res = ioctl(chan->fds[0], DAHDI_GET_BUFINFO, &savebi);
143  if(res) {
144  ast_log(LOG_WARNING, "Unable to check buffer policy on channel %s\n", chan->name);
145  return;
146  }
147 
148  pid = spawn_ras(chan, args);
149  if (pid < 0) {
150  ast_log(LOG_WARNING, "Failed to spawn RAS\n");
151  } else {
152  for (;;) {
153  res = wait4(pid, &status, WNOHANG, NULL);
154  if (!res) {
155  /* Check for hangup */
156  if (ast_check_hangup(chan) && !signalled) {
157  ast_debug(1, "Channel '%s' hungup. Signalling RAS at %d to die...\n", chan->name, pid);
158  kill(pid, SIGTERM);
159  signalled=1;
160  }
161  /* Try again */
162  sleep(1);
163  continue;
164  }
165  if (res < 0) {
166  ast_log(LOG_WARNING, "wait4 returned %d: %s\n", res, strerror(errno));
167  }
168  if (WIFEXITED(status)) {
169  ast_verb(3, "RAS on %s terminated with status %d\n", chan->name, WEXITSTATUS(status));
170  } else if (WIFSIGNALED(status)) {
171  ast_verb(3, "RAS on %s terminated with signal %d\n",
172  chan->name, WTERMSIG(status));
173  } else {
174  ast_verb(3, "RAS on %s terminated weirdly.\n", chan->name);
175  }
176  /* Throw back into audio mode */
177  x = 1;
178  ioctl(chan->fds[0], DAHDI_AUDIOMODE, &x);
179 
180  /* Restore saved values */
181  res = ioctl(chan->fds[0], DAHDI_SET_BUFINFO, &savebi);
182  if (res < 0) {
183  ast_log(LOG_WARNING, "Unable to set buffer policy on channel %s\n", chan->name);
184  }
185  break;
186  }
187  }
189 }
190 
191 static int dahdiras_exec(struct ast_channel *chan, const char *data)
192 {
193  int res=-1;
194  char *args;
195  struct dahdi_params dahdip;
196 
197  if (!data)
198  data = "";
199 
200  args = ast_strdupa(data);
201 
202  /* Answer the channel if it's not up */
203  if (chan->_state != AST_STATE_UP)
204  ast_answer(chan);
205  if (strcasecmp(chan->tech->type, "DAHDI")) {
206  /* If it's not a DAHDI channel, we're done. Wait a couple of
207  seconds and then hangup... */
208  ast_verb(2, "Channel %s is not a DAHDI channel\n", chan->name);
209  sleep(2);
210  } else {
211  memset(&dahdip, 0, sizeof(dahdip));
212  if (ioctl(chan->fds[0], DAHDI_GET_PARAMS, &dahdip)) {
213  ast_log(LOG_WARNING, "Unable to get DAHDI parameters\n");
214  } else if (dahdip.sigtype != DAHDI_SIG_CLEAR) {
215  ast_verb(2, "Channel %s is not a clear channel\n", chan->name);
216  } else {
217  /* Everything should be okay. Run PPP. */
218  ast_verb(3, "Starting RAS on %s\n", chan->name);
219  /* Execute RAS */
220  run_ras(chan, args);
221  }
222  }
223  return res;
224 }
225 
226 static int unload_module(void)
227 {
228  return ast_unregister_application(app);
229 }
230 
231 static int load_module(void)
232 {
234 }
235 
236 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "DAHDI ISDN Remote Access Server");
237 
static int dahdiras_exec(struct ast_channel *chan, const char *data)
Definition: app_dahdiras.c:191
Main Channel structure associated with a channel.
Definition: channel.h:742
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:396
const char *const type
Definition: channel.h:508
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
char * strsep(char **str, const char *delims)
int ast_safe_fork(int stop_reaper)
Common routine to safely fork without a chance of a signal handler firing badly in the child...
Definition: app.c:2242
#define LOG_WARNING
Definition: logger.h:144
void ast_safe_fork_cleanup(void)
Common routine to cleanup after fork&#39;ed process is complete (if reaping was stopped) ...
Definition: app.c:2306
static pid_t spawn_ras(struct ast_channel *chan, char *args)
Definition: app_dahdiras.c:82
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
#define WIFEXITED(status)
Definition: private.h:105
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
#define ast_verb(level,...)
Definition: logger.h:243
#define WEXITSTATUS(status)
Definition: private.h:108
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
General Asterisk PBX channel definitions.
static int load_module(void)
Definition: app_dahdiras.c:231
Core PBX routines and definitions.
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
int ast_set_priority(int)
We set ourselves to a high priority, that we might pre-empt everything else. If your PBX has heavy ac...
Definition: asterisk.c:1650
int fds[AST_MAX_FDS]
Definition: channel.h:829
static const char app[]
Definition: app_dahdiras.c:77
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static struct @350 args
enum ast_channel_state _state
Definition: channel.h:839
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
static int unload_module(void)
Definition: app_dahdiras.c:226
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
Definition: app.c:2237
#define PPP_MAX_ARGS
Definition: app_dahdiras.c:79
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static void run_ras(struct ast_channel *chan, char *args)
Definition: app_dahdiras.c:133
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
Asterisk module definitions.
struct ast_channel_tech * tech
Definition: channel.h:743
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
#define PPP_EXEC
Definition: app_dahdiras.c:80
jack_status_t status
Definition: app_jack.c:143
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
#define ast_opt_high_priority
Definition: options.h:108