static int pre_init_modemu(void) { switch (cmdarg.ttymode) { #ifdef HAVE_GRANTPT char * ptyslave; case CA_SHOWDEV: tty.rfd = tty.wfd = getPtyMaster(&ptyslave); printf("%s\n", ptyslave); return 0; case CA_COMMX: tty.rfd = tty.wfd = getPtyMaster(&ptyslave); commxForkExec(cmdarg.commx, ptyslave); break; #else char c10, c01; case CA_SHOWDEV: tty.rfd = tty.wfd = getPtyMaster(&c10, &c01); printf("%c%c\n", c10, c01); return 0; case CA_COMMX: tty.rfd = tty.wfd = getPtyMaster(&c10, &c01); commxForkExec(cmdarg.commx, c10, c01); break; #endif case CA_STDINOUT: tty.rfd = 0; tty.wfd = 1; setTty(); break; case CA_DEVGIVEN: tty.rfd = tty.wfd = openPtyMaster(cmdarg.dev); break; } return 1; }
int start_pppd (struct call *c, struct ppp_opts *opts) { char a, b; char tty[80]; char *stropt[80]; struct ppp_opts *p; #ifdef USE_KERNEL struct l2tp_call_opts co; #endif int pos = 1; int fd2; #ifdef DEBUG_PPPD int x; #endif struct termios ptyconf; struct call *sc; struct tunnel *st; p = opts; stropt[0] = strdup (PPPD); while (p) { stropt[pos] = (char *) malloc (strlen (p->option) + 1); strncpy (stropt[pos], p->option, strlen (p->option) + 1); pos++; p = p->next; } stropt[pos] = NULL; if (c->pppd > 0) { log (LOG_WARN, "%s: PPP already started on call!\n", __FUNCTION__); return -EINVAL; } if (c->fd > -1) { log (LOG_WARN, "%s: file descriptor already assigned!\n", __FUNCTION__); return -EINVAL; } #ifdef USE_KERNEL if (kernel_support) { co.ourtid = c->container->ourtid; co.ourcid = c->ourcid; ioctl (server_socket, L2TPIOCGETCALLOPTS, &co); stropt[pos++] = strdup ("channel"); stropt[pos] = (char *) malloc (10); snprintf (stropt[pos], 10, "%d", co.id); pos++; stropt[pos] = NULL; } else { #endif if ((c->fd = getPtyMaster (&a, &b)) < 0) { log (LOG_WARN, "%s: unable to allocate pty, abandoning!\n", __FUNCTION__); return -EINVAL; } /* set fd opened above to not echo so we don't see read our own packets back of the file descriptor that we just wrote them to */ tcgetattr (c->fd, &ptyconf); *(c->oldptyconf) = ptyconf; ptyconf.c_cflag &= ~(ICANON | ECHO); ptyconf.c_lflag &= ~ECHO; tcsetattr (c->fd, TCSANOW, &ptyconf); snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b); fd2 = open (tty, O_RDWR); if (fd2 < 0) { log (LOG_WARN, "unable to open tty %s, cannot start pppd", tty); return -EINVAL; } stropt[pos++] = strdup(tty); stropt[pos] = NULL; #ifdef USE_KERNEL } #endif #ifdef DEBUG_PPPD log (LOG_DEBUG, "%s: I'm running: ", __FUNCTION__); for (x = 0; stropt[x]; x++) { log (LOG_DEBUG, "\"%s\" ", stropt[x]); }; log (LOG_DEBUG, "\n"); #endif #ifdef __uClinux__ c->pppd = vfork (); #else c->pppd = fork (); #endif if (c->pppd < 0) { log (LOG_WARN, "%s: unable to fork(), abandoning!\n", __FUNCTION__); return -EINVAL; } else if (!c->pppd) { /* child */ close (0); /* redundant; the dup2() below would do that, too */ close (1); /* ditto */ /* close (2); No, we want to keep the connection to /dev/null. */ /* connect the pty to stdin and stdout */ dup2 (fd2, 0); dup2 (fd2, 1); /* close all the calls pty fds */ st = tunnels.head; while (st) { sc = st->call_head; while (sc) { close (sc->fd); sc = sc->next; } st = st->next; } /* close the UDP socket fd */ close (server_socket); /* close the control pipe fd */ close (control_fd); if( c->dialing[0] ) { setenv( "CALLER_ID", c->dialing, 1 ); } execv (PPPD, stropt); log (LOG_WARN, "%s: Exec of %s failed!\n", __FUNCTION__, PPPD); _exit (1); } close (fd2); pos = 0; while (stropt[pos]) { free (stropt[pos]); pos++; }; return 0; }
int start_pppd6 (struct call6 *c, struct ppp_opts *opts) { /* char a, b; */ char tty[512]; char *stropt[80]; struct ppp_opts *p; #ifdef USE_KERNEL struct sockaddr_pppol2tp sax; int flags; #endif int pos = 1; int fd2; #ifdef DEBUG_PPPD int x; #endif struct termios ptyconf; struct call6 *sc; struct tunnel6 *st; p = opts; stropt[0] = strdup (PPPD); while (p) { stropt[pos] = (char *) malloc (strlen (p->option) + 1); strncpy (stropt[pos], p->option, strlen (p->option) + 1); pos++; p = p->next; } stropt[pos] = NULL; if (c->pppd > 0) { l2tp_log(LOG_WARNING, "%s: PPP already started on call!\n", __FUNCTION__); return -EINVAL; } if (c->fd > -1) { l2tp_log (LOG_WARNING, "%s: file descriptor already assigned!\n", __FUNCTION__); return -EINVAL; } #ifdef USE_KERNEL if (kernel_support) { fd2 = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP); if (fd2 < 0) { l2tp_log (LOG_WARNING, "%s: Unable to allocate PPPoL2TP socket.\n", __FUNCTION__); return -EINVAL; } flags = fcntl(fd2, F_GETFL); if (flags == -1 || fcntl(fd2, F_SETFL, flags | O_NONBLOCK) == -1) { l2tp_log (LOG_WARNING, "%s: Unable to set PPPoL2TP socket nonblock.\n", __FUNCTION__); return -EINVAL; } sax.sa_family = AF_PPPOX; sax.sa_protocol = PX_PROTO_OL2TP; sax.pppol2tp.pid = 0; sax.pppol2tp.fd = server_socket6; sax.pppol2tp.addr.sin6_addr.s6_addr = c->container->peer.sin6_addr.s6_addr; sax.pppol2tp.addr.sin6_port = c->container->peer.sin6_port; sax.pppol2tp.addr.sin6_family = AF_INET6; sax.pppol2tp.s_tunnel = c->container->ourtid; sax.pppol2tp.s_session = c->ourcid; sax.pppol2tp.d_tunnel = c->container->tid; sax.pppol2tp.d_session = c->cid; if (connect(fd2, (struct sockaddr *)&sax, sizeof(sax)) < 0) { l2tp_log (LOG_WARNING, "%s: Unable to connect PPPoL2TP socket.\n", __FUNCTION__); return -EINVAL; } stropt[pos++] = strdup ("plugin"); stropt[pos++] = strdup ("pppol2tp.so"); stropt[pos++] = strdup ("pppol2tp"); stropt[pos] = (char *) malloc (10); snprintf (stropt[pos], 10, "%d", fd2); pos++; stropt[pos] = NULL; } else #endif { if ((c->fd = getPtyMaster (tty, sizeof(tty))) < 0) { l2tp_log (LOG_WARNING, "%s: unable to allocate pty, abandoning!\n", __FUNCTION__); return -EINVAL; } /* set fd opened above to not echo so we don't see read our own packets back of the file descriptor that we just wrote them to */ tcgetattr (c->fd, &ptyconf); *(c->oldptyconf) = ptyconf; ptyconf.c_cflag &= ~(ICANON | ECHO); ptyconf.c_lflag &= ~ECHO; tcsetattr (c->fd, TCSANOW, &ptyconf); if(fcntl(c->fd, F_SETFL, O_NONBLOCK)!=0) { l2tp_log(LOG_WARNING, "failed to set nonblock: %s\n", strerror(errno)); return -EINVAL; } fd2 = open (tty, O_RDWR); if (fd2 < 0) { l2tp_log (LOG_WARNING, "unable to open tty %s, cannot start pppd", tty); return -EINVAL; } stropt[pos++] = strdup(tty); stropt[pos] = NULL; } #ifdef DEBUG_PPPD l2tp_log (LOG_DEBUG, "%s: I'm running: \n", __FUNCTION__); for (x = 0; stropt[x]; x++) { l2tp_log (LOG_DEBUG, "\"%s\" \n", stropt[x]); }; #endif #ifdef __uClinux__ c->pppd = vfork (); #else c->pppd = fork (); #endif if (c->pppd < 0) { /* parent */ l2tp_log(LOG_WARNING,"%s: unable to fork(), abandoning!\n", __FUNCTION__); return -EINVAL; } else if (!c->pppd) { /* child */ close (0); /* redundant; the dup2() below would do that, too */ close (1); /* ditto */ /* close (2); No, we want to keep the connection to /dev/null. */ #ifdef USE_KERNEL if (!kernel_support) #endif { /* connect the pty to stdin and stdout */ dup2 (fd2, 0); dup2 (fd2, 1); /* close all the calls pty fds */ st = tunnels6.head; while (st) { sc = st->call_head; while (sc) { close (sc->fd); sc = sc->next; } st = st->next; } } //RY: start here // close the UDP socket fd close (server_socket6); /* close the control pipe fd */ close (control_fd); if( c->dialing[0] ) { setenv( "CALLER_ID", c->dialing, 1 ); } execv (PPPD, stropt); l2tp_log (LOG_WARNING, "%s: Exec of %s failed!\n", __FUNCTION__, PPPD); _exit (1); } close (fd2); pos = 0; while (stropt[pos]) { free (stropt[pos]); pos++; }; return 0; }
void death_handler (int signal) { /* * If we get here, somebody terminated us with a kill or a control-c. * we call call_close on each tunnel twice to get a StopCCN out * for each one (we can't pause to make sure it's received. * Then we close the connections */ struct tunnel *st, *st2; int sec; l2tp_log (LOG_INFO, "%s: Fatal signal %d received\n", __FUNCTION__, signal); #ifdef USE_KERNEL if (kernel_support || signal != SIGTERM) { #else if (signal != SIGTERM) { #endif st = tunnels.head; while (st) { st2 = st->next; strcpy (st->self->errormsg, "Server closing"); sec = st->self->closing; if (st->lac) st->lac->redial = 0; call_close (st->self); if (!sec) { st->self->closing = -1; call_close (st->self); } st = st2; } } /* erase pid and control files */ unlink (gconfig.pidfile); unlink (gconfig.controlfile); free(dial_no_tmp); close(server_socket); close(control_fd); closelog(); exit (1); } void sigterm_handler(int sig) { sigterm_received = 1; } void sigint_handler(int sig) { sigint_received = 1; } void sigchld_handler(int sig) { sigchld_received = 1; } void sigusr1_handler(int sig) { sigusr1_received = 1; } void sighup_handler(int sig) { sighup_received = 1; } void process_signal(void) { if (sigterm_received) { sigterm_received = 0; death_handler(SIGTERM); } if (sigint_received) { sigint_received = 0; death_handler(SIGINT); } if (sigchld_received) { sigchld_received = 0; child_handler(SIGCHLD); } if (sigusr1_received) { sigusr1_received = 0; status_handler(SIGUSR1); } if (sighup_received) { sighup_received = 0; null_handler(SIGHUP); } } int start_pppd (struct call *c, struct ppp_opts *opts) { /* char a, b; */ char tty[512]; char *stropt[80]; struct ppp_opts *p; #ifdef USE_KERNEL struct sockaddr_pppol2tp sax; int flags; #endif int pos = 1; int fd2 = -1; #ifdef DEBUG_PPPD int x; #endif struct termios ptyconf; struct call *sc; struct tunnel *st; p = opts; stropt[0] = strdup (PPPD); while (p) { stropt[pos] = (char *) malloc (strlen (p->option) + 1); strncpy (stropt[pos], p->option, strlen (p->option) + 1); pos++; p = p->next; } stropt[pos] = NULL; if (c->pppd > 0) { l2tp_log(LOG_WARNING, "%s: PPP already started on call!\n", __FUNCTION__); return -EINVAL; } if (c->fd > -1) { l2tp_log (LOG_WARNING, "%s: file descriptor already assigned!\n", __FUNCTION__); return -EINVAL; } #ifdef USE_KERNEL if (kernel_support) { fd2 = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP); if (fd2 < 0) { l2tp_log (LOG_WARNING, "%s: Unable to allocate PPPoL2TP socket.\n", __FUNCTION__); return -EINVAL; } flags = fcntl(fd2, F_GETFL); if (flags == -1 || fcntl(fd2, F_SETFL, flags | O_NONBLOCK) == -1) { l2tp_log (LOG_WARNING, "%s: Unable to set PPPoL2TP socket nonblock.\n", __FUNCTION__); close(fd2); return -EINVAL; } memset(&sax, 0, sizeof(sax)); sax.sa_family = AF_PPPOX; sax.sa_protocol = PX_PROTO_OL2TP; sax.pppol2tp.fd = c->container->udp_fd; sax.pppol2tp.addr.sin_addr.s_addr = c->container->peer.sin_addr.s_addr; sax.pppol2tp.addr.sin_port = c->container->peer.sin_port; sax.pppol2tp.addr.sin_family = AF_INET; sax.pppol2tp.s_tunnel = c->container->ourtid; sax.pppol2tp.s_session = c->ourcid; sax.pppol2tp.d_tunnel = c->container->tid; sax.pppol2tp.d_session = c->cid; if (connect(fd2, (struct sockaddr *)&sax, sizeof(sax)) < 0) { l2tp_log (LOG_WARNING, "%s: Unable to connect PPPoL2TP socket.\n", __FUNCTION__); close(fd2); return -EINVAL; } stropt[pos++] = strdup ("plugin"); stropt[pos++] = strdup ("pppol2tp.so"); stropt[pos++] = strdup ("pppol2tp"); stropt[pos] = (char *) malloc (10); snprintf (stropt[pos], 10, "%d", fd2); pos++; if (c->container->lns) { stropt[pos++] = strdup ("pppol2tp_lns_mode"); stropt[pos++] = strdup ("pppol2tp_tunnel_id"); stropt[pos] = (char *) malloc (10); snprintf (stropt[pos], 10, "%d", c->container->ourtid); pos++; stropt[pos++] = strdup ("pppol2tp_session_id"); stropt[pos] = (char *) malloc (10); snprintf (stropt[pos], 10, "%d", c->ourcid); pos++; } stropt[pos] = NULL; } else #endif { if ((c->fd = getPtyMaster (tty, sizeof(tty))) < 0) { l2tp_log (LOG_WARNING, "%s: unable to allocate pty, abandoning!\n", __FUNCTION__); return -EINVAL; } /* set fd opened above to not echo so we don't see read our own packets back of the file descriptor that we just wrote them to */ tcgetattr (c->fd, &ptyconf); ptyconf.c_cflag &= ~(ICANON | ECHO); ptyconf.c_lflag &= ~ECHO; tcsetattr (c->fd, TCSANOW, &ptyconf); if(fcntl(c->fd, F_SETFL, O_NONBLOCK)!=0) { l2tp_log(LOG_WARNING, "failed to set nonblock: %s\n", strerror(errno)); return -EINVAL; } fd2 = open (tty, O_RDWR); if (fd2 < 0) { l2tp_log (LOG_WARNING, "unable to open tty %s, cannot start pppd", tty); return -EINVAL; } stropt[pos++] = strdup(tty); stropt[pos] = NULL; } #ifdef DEBUG_PPPD l2tp_log (LOG_DEBUG, "%s: I'm running: \n", __FUNCTION__); for (x = 0; stropt[x]; x++) { l2tp_log (LOG_DEBUG, "\"%s\" \n", stropt[x]); }; #endif #ifdef __uClinux__ c->pppd = vfork (); #else c->pppd = fork (); #endif if (c->pppd < 0) { /* parent */ l2tp_log(LOG_WARNING,"%s: unable to fork(), abandoning!\n", __FUNCTION__); close(fd2); return -EINVAL; } else if (!c->pppd) { /* child */ close (0); /* redundant; the dup2() below would do that, too */ close (1); /* ditto */ /* close (2); No, we want to keep the connection to /dev/null. */ #ifdef USE_KERNEL if (!kernel_support) #endif { /* connect the pty to stdin and stdout */ dup2 (fd2, 0); dup2 (fd2, 1); close(fd2); } /* close all the calls pty fds */ st = tunnels.head; while (st) { sc = st->call_head; while (sc) { #ifdef USE_KERNEL if (kernel_support) { close(st->udp_fd); /* tunnel UDP fd */ close(st->pppox_fd); /* tunnel PPPoX fd */ } else #endif close (sc->fd); /* call pty fd */ sc = sc->next; } st = st->next; } /* close the UDP socket fd */ if (server_socket > 0) { close (server_socket); server_socket = -1; } /* close the control pipe fd */ if (control_fd > 0) { close (control_fd); control_fd = -1; } if( c->dialing[0] ) { setenv( "CALLER_ID", c->dialing, 1 ); } execv (PPPD, stropt); l2tp_log (LOG_WARNING, "%s: Exec of %s failed!\n", __FUNCTION__, PPPD); _exit (1); } close (fd2); pos = 0; while (stropt[pos]) { free (stropt[pos]); pos++; }; return 0; }