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: 178306 $")
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 <dahdi/user.h>
00046
00047 #include <fcntl.h>
00048 #ifdef HAVE_CAP
00049 #include <sys/capability.h>
00050 #endif
00051
00052 #include "asterisk/lock.h"
00053 #include "asterisk/file.h"
00054 #include "asterisk/channel.h"
00055 #include "asterisk/pbx.h"
00056 #include "asterisk/module.h"
00057
00058 static char *app = "DAHDIRAS";
00059
00060 static char *synopsis = "Executes DAHDI ISDN RAS application";
00061
00062 static char *descrip =
00063 " DAHDIRAS(args): Executes a RAS server using pppd on the given channel.\n"
00064 "The channel must be a clear channel (i.e. PRI source) and a DAHDI\n"
00065 "channel to be able to use this function (No modem emulation is included).\n"
00066 "Your pppd must be patched to be dahdi aware. Arguments should be\n"
00067 "separated by , characters.\n";
00068
00069
00070 #define PPP_MAX_ARGS 32
00071 #define PPP_EXEC "/usr/sbin/pppd"
00072
00073 static pid_t spawn_ras(struct ast_channel *chan, char *args)
00074 {
00075 pid_t pid;
00076 int x;
00077 char *c;
00078
00079 char *argv[PPP_MAX_ARGS];
00080 int argc = 0;
00081 char *stringp=NULL;
00082 sigset_t fullset, oldset;
00083 #ifdef HAVE_CAP
00084 cap_t cap;
00085 #endif
00086
00087 sigfillset(&fullset);
00088 pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
00089
00090
00091 pid = fork();
00092 if (pid) {
00093 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
00094 return pid;
00095 }
00096
00097 #ifdef HAVE_CAP
00098 cap = cap_from_text("cap_net_admin-eip");
00099
00100 if (cap_set_proc(cap)) {
00101
00102 ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
00103 }
00104 cap_free(cap);
00105 #endif
00106
00107
00108 for (x=0;x<NSIG;x++)
00109 signal(x, SIG_DFL);
00110
00111 pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
00112
00113
00114 dup2(chan->fds[0], STDIN_FILENO);
00115
00116
00117 if (ast_opt_high_priority)
00118 ast_set_priority(0);
00119
00120
00121 for (x=STDERR_FILENO + 1;x<1024;x++)
00122 close(x);
00123
00124
00125 memset(argv, 0, sizeof(argv));
00126
00127
00128
00129 argv[argc++] = PPP_EXEC;
00130 argv[argc++] = "nodetach";
00131
00132
00133 stringp=args;
00134 c = strsep(&stringp, ",");
00135 while(c && strlen(c) && (argc < (PPP_MAX_ARGS - 4))) {
00136 argv[argc++] = c;
00137 c = strsep(&stringp, ",");
00138 }
00139
00140 argv[argc++] = "plugin";
00141 argv[argc++] = "dahdi.so";
00142 argv[argc++] = "stdin";
00143
00144
00145 execv(PPP_EXEC, argv);
00146 fprintf(stderr, "Failed to exec PPPD!\n");
00147 exit(1);
00148 }
00149
00150 static void run_ras(struct ast_channel *chan, char *args)
00151 {
00152 pid_t pid;
00153 int status;
00154 int res;
00155 int signalled = 0;
00156 struct dahdi_bufferinfo savebi;
00157 int x;
00158
00159 res = ioctl(chan->fds[0], DAHDI_GET_BUFINFO, &savebi);
00160 if(res) {
00161 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %s\n", chan->name);
00162 return;
00163 }
00164
00165 pid = spawn_ras(chan, args);
00166 if (pid < 0) {
00167 ast_log(LOG_WARNING, "Failed to spawn RAS\n");
00168 } else {
00169 for (;;) {
00170 res = wait4(pid, &status, WNOHANG, NULL);
00171 if (!res) {
00172
00173 if (ast_check_hangup(chan) && !signalled) {
00174 ast_debug(1, "Channel '%s' hungup. Signalling RAS at %d to die...\n", chan->name, pid);
00175 kill(pid, SIGTERM);
00176 signalled=1;
00177 }
00178
00179 sleep(1);
00180 continue;
00181 }
00182 if (res < 0) {
00183 ast_log(LOG_WARNING, "wait4 returned %d: %s\n", res, strerror(errno));
00184 }
00185 if (WIFEXITED(status)) {
00186 ast_verb(3, "RAS on %s terminated with status %d\n", chan->name, WEXITSTATUS(status));
00187 } else if (WIFSIGNALED(status)) {
00188 ast_verb(3, "RAS on %s terminated with signal %d\n",
00189 chan->name, WTERMSIG(status));
00190 } else {
00191 ast_verb(3, "RAS on %s terminated weirdly.\n", chan->name);
00192 }
00193
00194 x = 1;
00195 ioctl(chan->fds[0], DAHDI_AUDIOMODE, &x);
00196
00197
00198 res = ioctl(chan->fds[0], DAHDI_SET_BUFINFO, &savebi);
00199 if (res < 0) {
00200 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %s\n", chan->name);
00201 }
00202 break;
00203 }
00204 }
00205 }
00206
00207 static int dahdiras_exec(struct ast_channel *chan, void *data)
00208 {
00209 int res=-1;
00210 char *args;
00211 struct dahdi_params dahdip;
00212
00213 if (!data)
00214 data = "";
00215
00216 args = ast_strdupa(data);
00217
00218
00219 if (chan->_state != AST_STATE_UP)
00220 ast_answer(chan);
00221 if (strcasecmp(chan->tech->type, "DAHDI")) {
00222
00223
00224 ast_verb(2, "Channel %s is not a DAHDI channel\n", chan->name);
00225 sleep(2);
00226 } else {
00227 memset(&dahdip, 0, sizeof(dahdip));
00228 if (ioctl(chan->fds[0], DAHDI_GET_PARAMS, &dahdip)) {
00229 ast_log(LOG_WARNING, "Unable to get DAHDI parameters\n");
00230 } else if (dahdip.sigtype != DAHDI_SIG_CLEAR) {
00231 ast_verb(2, "Channel %s is not a clear channel\n", chan->name);
00232 } else {
00233
00234 ast_verb(3, "Starting RAS on %s\n", chan->name);
00235
00236 run_ras(chan, args);
00237 }
00238 }
00239 return res;
00240 }
00241
00242 static int unload_module(void)
00243 {
00244 return ast_unregister_application(app);
00245 }
00246
00247 static int load_module(void)
00248 {
00249 return ((ast_register_application(app, dahdiras_exec, synopsis, descrip)) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS);
00250 }
00251
00252 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "DAHDI ISDN Remote Access Server");
00253