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