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); }