예제 #1
0
파일: call.c 프로젝트: sina-ht/l2tpd
void destroy_call (struct call *c)
{
    /*
     * Here, we unconditionally destroy a call.
     */

    struct call *p;
    struct timeval tv;
    pid_t pid;
    /*
     * Close the tty
     */
    if (c->fd > 0)
        close (c->fd);
/*	if (c->dethrottle) deschedule(c->dethrottle); */
    if (c->zlb_xmit)
        deschedule (c->zlb_xmit);

#ifdef IP_ALLOCATION
    if (c->addr)
        unreserve_addr (c->addr);
#endif

    /*
     * Kill off pppd and wait for it to 
     * return to us.  This should only be called
     * in rare cases if pppd hasn't already died
     * voluntarily
     */
    pid = c->pppd;
    if (pid)
    {
        /* Set c->pppd to zero to prevent recursion with child_handler */
        c->pppd = 0;
        kill (pid, SIGTERM);
        waitpid (pid, NULL, 0);
    }
    if (c->container)
    {
#ifdef USE_KERNEL
        if (kernel_support)
            ioctl (server_socket, L2TPIOCDELCALL,
                   (c->container->ourtid << 16) | (c->ourcid));
#endif
        p = c->container->call_head;
        /*
         * Remove us from the call list, although
         * we might not actually be there
         */
        if (p)
        {
            if (p == c)
            {
                c->container->call_head = c->next;
                c->container->count--;
            }
            else
            {
                while (p->next && (p->next != c))
                    p = p->next;
                if (p->next)
                {
                    p->next = c->next;
                    c->container->count--;
                }
            }
        }
    }
    if (c->lac)
    {
        c->lac->c = NULL;
        if (c->lac->redial && (c->lac->rtimeout > 0) && !c->lac->rsched &&
            c->lac->active)
        {
#ifdef DEBUG_MAGIC
            l2tp_log (LOG_LOG, "%s: Will redial in %d seconds\n", __FUNCTION__,
                 c->lac->rtimeout);
#endif
            tv.tv_sec = c->lac->rtimeout;
            tv.tv_usec = 0;
            c->lac->rsched = schedule (tv, magic_lac_dial, c->lac);
        }
    }

    free (c);

}
void destroy_call (struct call *c)
{
    /*
     * Here, we unconditionally destroy a call.
     */

    struct call *p;
    struct timeval tv;
    pid_t pid;
    /*
     * Close the tty
     */
    if (c->fd > 0)
        close (c->fd);
    /*	if (c->dethrottle) deschedule(c->dethrottle); */
    if (c->zlb_xmit)
        deschedule (c->zlb_xmit);

#ifdef IP_ALLOCATION
    if (c->addr)
        unreserve_addr (c->addr);
#endif

    /*
     * Kill off pppd and wait for it to
     * return to us.  This should only be called
     * in rare cases if pppd hasn't already died
     * voluntarily
     */
    pid = c->pppd;
    if (pid)
    {
        /* Set c->pppd to zero to prevent recursion with child_handler */
        c->pppd = 0;
        /*
         * There is a bug in some pppd versions where sending a SIGTERM
         * does not actually seem to kill pppd, and xl2tpd waits indefinately
         * using waitpid, not accepting any new connections either. Therefor
         * we now use some more force and send it a SIGKILL instead of SIGTERM.
         * One confirmed buggy version of pppd is ppp-2.4.2-6.4.RHEL4
         * See http://bugs.xelerance.com/view.php?id=739
         *
         * Sometimes pppd takes 7 sec to go down! We don't have that much time,
         * since all other calls are suspended while doing this.
         */
#ifdef TRUST_PPPD_TO_DIE
#ifdef DEBUG_PPPD
        l2tp_log (LOG_DEBUG, "Terminating pppd: sending TERM signal to pid %d\n", pid);
#endif
        kill (pid, SIGTERM);
#else
#ifdef DEBUG_PPPD
        l2tp_log (LOG_DEBUG, "Terminating pppd: sending KILL signal to pid %d\n", pid);
#endif
        kill (pid, SIGTERM);
#endif
    }
    if (c->container)
    {
        p = c->container->call_head;
        /*
         * Remove us from the call list, although
         * we might not actually be there
         */
        if (p)
        {
            if (p == c)
            {
                c->container->call_head = c->next;
                c->container->count--;
            }
            else
            {
                while (p->next && (p->next != c))
                    p = p->next;
                if (p->next)
                {
                    p->next = c->next;
                    c->container->count--;
                }
            }
        }
    }
    if (c->lac)
    {
        c->lac->c = NULL;
        if (c->lac->redial && (c->lac->rtimeout > 0) && !c->lac->rsched &&
                c->lac->active)
        {
#ifdef DEBUG_MAGIC
            l2tp_log (LOG_DEBUG, "Will redial in %d seconds\n",
                      c->lac->rtimeout);
#endif
            tv.tv_sec = c->lac->rtimeout;
            tv.tv_usec = 0;
            c->lac->rsched = schedule (tv, magic_lac_dial, c->lac);
        }
    }

    free (c);
}