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