예제 #1
0
파일: xl2tpd.c 프로젝트: greendev5/xl2tpd
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); }
}
예제 #2
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;
}
예제 #3
0
파일: network.c 프로젝트: edwacode/r6300v2
void control_xmit (void *b)
{
    struct buffer *buf = (struct buffer *) b;
    struct tunnel *t;
    struct timeval tv;
    int ns;
    if (!buf)
    {
        log (LOG_WARN, "%s: called on NULL buffer!\n", __FUNCTION__);
        return;
    }

    buf->retries++;
    t = buf->tunnel;
    ns = ntohs (((struct control_hdr *) (buf->start))->Ns);
    if (t)
    {
        if (ns < t->cLr)
        {
#ifdef DEBUG_CONTROL_XMIT
            log (LOG_DEBUG, "%s: Tossing packet %d\n", __FUNCTION__, ns);
#endif
            /* Okay, it's been received.  Let's toss it now */
            toss (buf);
            return;
        }
    }
    if (buf->retries > DEFAULT_MAX_RETRIES)
    {
        /*
           * Too many retries.  Either kill the tunnel, or
           * if there is no tunnel, just stop retransmitting.
         */
        if (t)
        {
            if (t->self->needclose)
            {
                log (LOG_DEBUG,
                     "%s: Unable to deliver closing message for tunnel %d. Destroying anyway.\n",
                     __FUNCTION__, t->ourtid);
                t->self->needclose = 0;
                t->self->closing = -1;
                /* , added by MJ., for terminate program when time out. */
                extern void death_handler (int signal);
                death_handler(SIGTERM);
                /* add end, by MJ.*/
            }
            else
            {
                log (LOG_DEBUG,
                     "%s: Maximum retries exceeded for tunnel %d.  Closing.\n",
                     __FUNCTION__, t->ourtid);
                strcpy (t->self->errormsg, "Timeout");
                t->self->needclose = -1;
            }
        }
    }
    else
    {
        /*
           * FIXME:  How about adaptive timeouts?
         */
        tv.tv_sec = 1;
        tv.tv_usec = 0;
        schedule (tv, control_xmit, buf);
#ifdef DEBUG_CONTROL_XMIT
        log (LOG_DEBUG, "%s: Scheduling and transmitting packet %d\n",
             __FUNCTION__, ns);
#endif
        udp_xmit (buf);
    }
}