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: 134254 $")
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 <stdlib.h>
00045 #include <unistd.h>
00046 #include <string.h>
00047 #include <stdlib.h>
00048 #include <errno.h>
00049 #include <stdio.h>
00050 #include <fcntl.h>
00051
00052 #include "asterisk/lock.h"
00053 #include "asterisk/file.h"
00054 #include "asterisk/logger.h"
00055 #include "asterisk/channel.h"
00056 #include "asterisk/pbx.h"
00057 #include "asterisk/module.h"
00058 #include "asterisk/options.h"
00059
00060 #include "asterisk/dahdi_compat.h"
00061
00062 static char *dahdi_app = "DAHDIRAS";
00063 static char *zap_app = "ZapRAS";
00064
00065 static char *dahdi_synopsis = "Executes DAHDI ISDN RAS application";
00066 static char *zap_synopsis = "Executes Zaptel ISDN RAS application";
00067
00068 static char *dahdi_descrip =
00069 " DAHDIRAS(args): Executes a RAS server using pppd on the given channel.\n"
00070 "The channel must be a clear channel (i.e. PRI source) and a DAHDI\n"
00071 "channel to be able to use this function (no modem emulation is included).\n"
00072 "Your pppd must have the DAHDI plugin available. Arguments should be\n"
00073 "separated by | characters.\n";
00074
00075 static char *zap_descrip =
00076 " ZapRAS(args): Executes a RAS server using pppd on the given channel.\n"
00077 "The channel must be a clear channel (i.e. PRI source) and a Zaptel\n"
00078 "channel to be able to use this function (no modem emulation is included).\n"
00079 "Your pppd must have the Zaptel plugin available. Arguments should be\n"
00080 "separated by | characters.\n";
00081
00082 #define PPP_MAX_ARGS 32
00083 #define PPP_EXEC "/usr/sbin/pppd"
00084
00085 static pid_t spawn_ras(struct ast_channel *chan, char *args)
00086 {
00087 pid_t pid;
00088 int x;
00089 char *c;
00090
00091 char *argv[PPP_MAX_ARGS];
00092 int argc = 0;
00093 char *stringp=NULL;
00094 sigset_t fullset, oldset;
00095
00096 sigfillset(&fullset);
00097 pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
00098
00099
00100 pid = fork();
00101 if (pid) {
00102 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
00103 return pid;
00104 }
00105
00106
00107 for (x=0;x<NSIG;x++)
00108 signal(x, SIG_DFL);
00109
00110 pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
00111
00112
00113 dup2(chan->fds[0], STDIN_FILENO);
00114
00115
00116 if (ast_opt_high_priority)
00117 ast_set_priority(0);
00118
00119
00120 for (x=STDERR_FILENO + 1;x<1024;x++)
00121 close(x);
00122
00123
00124 memset(argv, 0, sizeof(argv));
00125
00126
00127
00128 argv[argc++] = PPP_EXEC;
00129 argv[argc++] = "nodetach";
00130
00131
00132 stringp=args;
00133 c = strsep(&stringp, "|");
00134 while(c && strlen(c) && (argc < (PPP_MAX_ARGS - 4))) {
00135 argv[argc++] = c;
00136 c = strsep(&stringp, "|");
00137 }
00138
00139 argv[argc++] = "plugin";
00140 #ifdef HAVE_ZAPTEL
00141 argv[argc++] = "zaptel.so";
00142 #else
00143 argv[argc++] = "dahdi.so";
00144 #endif
00145 argv[argc++] = "stdin";
00146
00147
00148 execv(PPP_EXEC, argv);
00149 fprintf(stderr, "Failed to exec PPPD!\n");
00150 exit(1);
00151 }
00152
00153 static void run_ras(struct ast_channel *chan, char *args)
00154 {
00155 pid_t pid;
00156 int status;
00157 int res;
00158 int signalled = 0;
00159 struct dahdi_bufferinfo savebi;
00160 int x;
00161
00162 res = ioctl(chan->fds[0], DAHDI_GET_BUFINFO, &savebi);
00163 if(res) {
00164 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %s\n", chan->name);
00165 return;
00166 }
00167
00168 pid = spawn_ras(chan, args);
00169 if (pid < 0) {
00170 ast_log(LOG_WARNING, "Failed to spawn RAS\n");
00171 } else {
00172 for (;;) {
00173 res = wait4(pid, &status, WNOHANG, NULL);
00174 if (!res) {
00175
00176 if (chan->_softhangup && !signalled) {
00177 ast_log(LOG_DEBUG, "Channel '%s' hungup. Signalling RAS at %d to die...\n", chan->name, pid);
00178 kill(pid, SIGTERM);
00179 signalled=1;
00180 }
00181
00182 sleep(1);
00183 continue;
00184 }
00185 if (res < 0) {
00186 ast_log(LOG_WARNING, "wait4 returned %d: %s\n", res, strerror(errno));
00187 }
00188 if (option_verbose > 2) {
00189 if (WIFEXITED(status)) {
00190 ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated with status %d\n", chan->name, WEXITSTATUS(status));
00191 } else if (WIFSIGNALED(status)) {
00192 ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated with signal %d\n",
00193 chan->name, WTERMSIG(status));
00194 } else {
00195 ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated weirdly.\n", chan->name);
00196 }
00197 }
00198
00199 x = 1;
00200 ioctl(chan->fds[0], DAHDI_AUDIOMODE, &x);
00201
00202
00203 res = ioctl(chan->fds[0], DAHDI_SET_BUFINFO, &savebi);
00204 if (res < 0) {
00205 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %s\n", chan->name);
00206 }
00207 break;
00208 }
00209 }
00210 }
00211
00212 static int exec(struct ast_channel *chan, void *data)
00213 {
00214 int res=-1;
00215 char *args;
00216 struct ast_module_user *u;
00217 struct dahdi_params ztp;
00218
00219 if (!data)
00220 data = "";
00221
00222 u = ast_module_user_add(chan);
00223
00224 args = ast_strdupa(data);
00225
00226
00227 if (chan->_state != AST_STATE_UP)
00228 ast_answer(chan);
00229 if (strcasecmp(chan->tech->type, dahdi_chan_name)) {
00230 if (option_verbose > 1)
00231 ast_verbose(VERBOSE_PREFIX_2 "Channel %s is not a %s channel\n", chan->name, dahdi_chan_name);
00232 sleep(2);
00233 } else {
00234 memset(&ztp, 0, sizeof(ztp));
00235 if (ioctl(chan->fds[0], DAHDI_GET_PARAMS, &ztp)) {
00236 ast_log(LOG_WARNING, "Unable to get parameters\n");
00237 } else if (ztp.sigtype != DAHDI_SIG_CLEAR) {
00238 if (option_verbose > 1)
00239 ast_verbose(VERBOSE_PREFIX_2 "Channel %s is not a clear channel\n", chan->name);
00240 } else {
00241
00242 if (option_verbose > 2)
00243 ast_verbose(VERBOSE_PREFIX_3 "Starting RAS on %s\n", chan->name);
00244
00245 run_ras(chan, args);
00246 }
00247 }
00248 ast_module_user_remove(u);
00249 return res;
00250 }
00251
00252 static int exec_warn(struct ast_channel *chan, void *data)
00253 {
00254 ast_log(LOG_WARNING, "Use of the command %s is deprecated, please use %s instead.\n", zap_app, dahdi_app);
00255
00256 return exec(chan, data);
00257 }
00258
00259 static int unload_module(void)
00260 {
00261 int res = 0;
00262
00263 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
00264 res |= ast_unregister_application(dahdi_app);
00265 }
00266
00267 res |= ast_unregister_application(zap_app);
00268
00269 ast_module_user_hangup_all();
00270
00271 return res;
00272 }
00273
00274 static int load_module(void)
00275 {
00276 int res = 0;
00277
00278 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
00279 res |= ast_register_application(dahdi_app, exec, dahdi_synopsis, dahdi_descrip);
00280 }
00281
00282 res |= ast_register_application(zap_app, exec_warn, zap_synopsis, zap_descrip);
00283
00284 return res;
00285 }
00286
00287 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "DAHDI RAS Application");
00288