00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "asterisk.h"
00033
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 134260 $")
00035
00036 #include <sys/ioctl.h>
00037 #include <sys/wait.h>
00038 #ifdef __linux__
00039 #include <sys/signal.h>
00040 #else
00041 #include <signal.h>
00042 #endif
00043
00044 #include <fcntl.h>
00045
00046 #include <dahdi/user.h>
00047
00048 #include "asterisk/lock.h"
00049 #include "asterisk/file.h"
00050 #include "asterisk/channel.h"
00051 #include "asterisk/pbx.h"
00052 #include "asterisk/module.h"
00053 #include "asterisk/app.h"
00054
00055 static char *app = "DAHDIRAS";
00056
00057 static char *synopsis = "Executes DAHDI ISDN RAS application";
00058
00059 static char *descrip =
00060 " DAHDIRAS(args): Executes a RAS server using pppd on the given channel.\n"
00061 "The channel must be a clear channel (i.e. PRI source) and a DAHDI\n"
00062 "channel to be able to use this function (No modem emulation is included).\n"
00063 "Your pppd must be patched to be DAHDI aware. Arguments should be\n"
00064 "separated by , characters.\n";
00065
00066
00067 #define PPP_MAX_ARGS 32
00068 #define PPP_EXEC "/usr/sbin/pppd"
00069
00070 static pid_t spawn_ras(struct ast_channel *chan, char *args)
00071 {
00072 pid_t pid;
00073 char *c;
00074
00075 char *argv[PPP_MAX_ARGS];
00076 int argc = 0;
00077 char *stringp=NULL;
00078
00079
00080 pid = ast_safe_fork(1);
00081 if (pid) {
00082 return pid;
00083 }
00084
00085
00086 dup2(chan->fds[0], STDIN_FILENO);
00087
00088
00089 if (ast_opt_high_priority)
00090 ast_set_priority(0);
00091
00092
00093 ast_close_fds_above_n(STDERR_FILENO);
00094
00095
00096 memset(argv, 0, sizeof(argv));
00097
00098
00099
00100 argv[argc++] = PPP_EXEC;
00101 argv[argc++] = "nodetach";
00102
00103
00104 stringp=args;
00105 c = strsep(&stringp, ",");
00106 while(c && strlen(c) && (argc < (PPP_MAX_ARGS - 4))) {
00107 argv[argc++] = c;
00108 c = strsep(&stringp, ",");
00109 }
00110
00111 argv[argc++] = "plugin";
00112 argv[argc++] = "dahdi.so";
00113 argv[argc++] = "stdin";
00114
00115
00116 execv(PPP_EXEC, argv);
00117 fprintf(stderr, "Failed to exec PPPD!\n");
00118 exit(1);
00119 }
00120
00121 static void run_ras(struct ast_channel *chan, char *args)
00122 {
00123 pid_t pid;
00124 int status;
00125 int res;
00126 int signalled = 0;
00127 struct dahdi_bufferinfo savebi;
00128 int x;
00129
00130 res = ioctl(chan->fds[0], DAHDI_GET_BUFINFO, &savebi);
00131 if(res) {
00132 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %s\n", chan->name);
00133 return;
00134 }
00135
00136 pid = spawn_ras(chan, args);
00137 if (pid < 0) {
00138 ast_log(LOG_WARNING, "Failed to spawn RAS\n");
00139 } else {
00140 for (;;) {
00141 res = wait4(pid, &status, WNOHANG, NULL);
00142 if (!res) {
00143
00144 if (ast_check_hangup(chan) && !signalled) {
00145 ast_debug(1, "Channel '%s' hungup. Signalling RAS at %d to die...\n", chan->name, pid);
00146 kill(pid, SIGTERM);
00147 signalled=1;
00148 }
00149
00150 sleep(1);
00151 continue;
00152 }
00153 if (res < 0) {
00154 ast_log(LOG_WARNING, "wait4 returned %d: %s\n", res, strerror(errno));
00155 }
00156 if (WIFEXITED(status)) {
00157 ast_verb(3, "RAS on %s terminated with status %d\n", chan->name, WEXITSTATUS(status));
00158 } else if (WIFSIGNALED(status)) {
00159 ast_verb(3, "RAS on %s terminated with signal %d\n",
00160 chan->name, WTERMSIG(status));
00161 } else {
00162 ast_verb(3, "RAS on %s terminated weirdly.\n", chan->name);
00163 }
00164
00165 x = 1;
00166 ioctl(chan->fds[0], DAHDI_AUDIOMODE, &x);
00167
00168
00169 res = ioctl(chan->fds[0], DAHDI_SET_BUFINFO, &savebi);
00170 if (res < 0) {
00171 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %s\n", chan->name);
00172 }
00173 break;
00174 }
00175 }
00176 ast_safe_fork_cleanup();
00177 }
00178
00179 static int dahdiras_exec(struct ast_channel *chan, void *data)
00180 {
00181 int res=-1;
00182 char *args;
00183 struct dahdi_params dahdip;
00184
00185 if (!data)
00186 data = "";
00187
00188 args = ast_strdupa(data);
00189
00190
00191 if (chan->_state != AST_STATE_UP)
00192 ast_answer(chan);
00193 if (strcasecmp(chan->tech->type, "DAHDI")) {
00194
00195
00196 ast_verb(2, "Channel %s is not a DAHDI channel\n", chan->name);
00197 sleep(2);
00198 } else {
00199 memset(&dahdip, 0, sizeof(dahdip));
00200 if (ioctl(chan->fds[0], DAHDI_GET_PARAMS, &dahdip)) {
00201 ast_log(LOG_WARNING, "Unable to get DAHDI parameters\n");
00202 } else if (dahdip.sigtype != DAHDI_SIG_CLEAR) {
00203 ast_verb(2, "Channel %s is not a clear channel\n", chan->name);
00204 } else {
00205
00206 ast_verb(3, "Starting RAS on %s\n", chan->name);
00207
00208 run_ras(chan, args);
00209 }
00210 }
00211 return res;
00212 }
00213
00214 static int unload_module(void)
00215 {
00216 return ast_unregister_application(app);
00217 }
00218
00219 static int load_module(void)
00220 {
00221 return ((ast_register_application(app, dahdiras_exec, synopsis, descrip)) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS);
00222 }
00223
00224 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "DAHDI ISDN Remote Access Server");
00225