Ejemplo n.º 1
0
Archivo: aaa.c Proyecto: aunoor/xl2tpd
struct lns *get_lns (struct tunnel *t)
{
    /*
     * Look through our list of LNS's and
     * find a reasonable LNS for this call
     * if one is available
     */
    struct lns *lns;
    struct iprange *ipr;
    int allow, checkdefault = 0;
    /* If access control is disabled, we give the default
       otherwise, we give nothing */
    allow = 0;
    lns = lnslist;
    if (!lns)
    {
        lns = deflns;
        checkdefault = -1;
    }
    while (lns)
    {
        ipr = lns->lacs;
        while (ipr)
        {
            if ((ntohl (t->peer.sin_addr.s_addr) >= ntohl (ipr->start)) &&
                (ntohl (t->peer.sin_addr.s_addr) <= ntohl (ipr->end)))
            {
#ifdef DEBUG_AAA
                l2tp_log (LOG_DEBUG,
                     "$s: Rule %s to %s, sense %s matched %s\n", __FUNCTION__,
                     IPADDY (ipr->start), IPADDY (ipr->end),
                     (ipr->sense ? "allow" : "deny"), IPADDY (t->peer.sin_addr.s_addr));
#endif
                allow = ipr->sense;
            }
            ipr = ipr->next;
        }
        if (allow)
            return lns;
        lns = lns->next;
        if (!lns && !checkdefault)
        {
            lns = deflns;
            checkdefault = -1;
        }
    }
    if (gconfig.accesscontrol)
        return NULL;
    else
        return deflns;
}
Ejemplo n.º 2
0
void udp_xmit (struct buffer *buf, struct tunnel *t)
{
    struct cmsghdr *cmsg;
    char cbuf[CMSG_SPACE(sizeof (unsigned int))];
    unsigned int *refp;
    struct msghdr msgh;
    int err;
    struct iovec iov;
    
    /*
     * OKAY, now send a packet with the right SAref values.
     */
    memset(&msgh, 0, sizeof(struct msghdr));

    msgh.msg_control = cbuf;
    msgh.msg_controllen = 0;

    if(gconfig.ipsecsaref && t->refhim != IPSEC_SAREF_NULL) {
	msgh.msg_controllen = sizeof(cbuf);

	cmsg = CMSG_FIRSTHDR(&msgh);
	cmsg->cmsg_level = IPPROTO_IP;
	cmsg->cmsg_type  = gconfig.sarefnum;
	cmsg->cmsg_len   = CMSG_LEN(sizeof(unsigned int));

	if(gconfig.debug_network) {
		l2tp_log(LOG_DEBUG,"sending with saref=%d using sarefnum=%d\n", t->refhim, gconfig.sarefnum);
	}
	refp = (unsigned int *)CMSG_DATA(cmsg);
	*refp = t->refhim;

	msgh.msg_controllen = cmsg->cmsg_len;
    }
    
    iov.iov_base = buf->start;
    iov.iov_len  = buf->len;

    /* return packet from whence it came */
    msgh.msg_name    = &buf->peer;
    msgh.msg_namelen = sizeof(buf->peer);
    
    msgh.msg_iov  = &iov;
    msgh.msg_iovlen = 1;
    msgh.msg_flags = 0;


    /* Receive one packet. */
    if ((err = sendmsg(server_socket, &msgh, 0)) < 0) {
	l2tp_log(LOG_ERR, "udp_xmit failed to %s:%d with err=%d:%s\n",
		 IPADDY(t->peer.sin_addr), ntohs(t->peer.sin_port),
		 err,strerror(errno));
    }
}
Ejemplo n.º 3
0
void lac_disconnect (int tid)
{
    struct tunnel *t = tunnels.head;
    while (t)
    {
        if (t->ourtid == tid)
        {
            log (LOG_LOG,
                 "Disconnecting from %s, Local: %d, Remote: %d\n",
                 IPADDY (t->peer.sin_addr), t->ourtid, t->tid);
            t->self->needclose = -1;
            strcpy (t->self->errormsg, "Goodbye!");
            call_close (t->self);
            return;
        }
        t = t->next;
    };
    log (LOG_DEBUG, "No such tunnel %d to hang up.\n", tid);
    return;
}
Ejemplo n.º 4
0
/* Now sends to syslog instead - MvO */
void show_status (void)
{
    struct schedule_entry *se;
    struct tunnel *t;
    struct call *c;
    struct lns *tlns;
    struct lac *tlac;
    struct host *h;
    unsigned long cnt = 0;

    int s = 0;
    log (LOG_WARN, "====== l2tpd statistics ========\n");
    log (LOG_WARN, " Scheduler entries:\n");
    se = events;
    while (se)
    {
        s++;
        t = (struct tunnel *) se->data;
        tlac = (struct lac *) se->data;
        c = (struct call *) se->data;
        if (se->func == &hello)
        {
            log (LOG_WARN, "%d: HELLO to %d\n", s, t->tid);
        }
        else if (se->func == &magic_lac_dial)
        {
            log (LOG_WARN, "%d: Magic dial on %s\n", s, tlac->entname);
        }
        else if (se->func == &send_zlb)
        {
            log (LOG_WARN, "%d: Send payload ZLB on call %d:%d\n", s,
                     c->container->tid, c->cid);
        }
        else if (se->func == &dethrottle)
        {
            log (LOG_WARN, "%d: Dethrottle call %d:%d\n", s, c->container->tid,
                     c->cid);
        }
        else
            log (LOG_WARN, "%d: Unknown event\n", s);
        se = se->next;
    };
    log (LOG_WARN, "Total Events scheduled: %d\n", s);
    log (LOG_WARN, "Number of tunnels open: %d\n", tunnels.count);
    t = tunnels.head;
    while (t)
    {
        log (LOG_WARN, "Tunnel %s, ID = %d (local), %d (remote) to %s:%d,"
                 " control_seq_num = %d, control_rec_seq_num = %d,"
                 " cLr = %d, call count = %d",
                 (t->lac ? t->lac->entname : (t->lns ? t->lns->entname : "")),
                 t->ourtid, t->tid, IPADDY (t->peer.sin_addr),
                 ntohs (t->peer.sin_port), t->control_seq_num,
                 t->control_rec_seq_num, t->cLr, t->count);
        c = t->call_head;
        while (c)
        {
            cnt++;
            log (LOG_WARN, 
                     "Call %s # %lu, ID = %d (local), %d (remote), serno = %u,"
                     " data_seq_num = %d, data_rec_seq_num = %d,"
                     " pLr = %d, tx = %u bytes (%u), rx= %u bytes (%u)",
                     (c->lac ? c->lac->
                      entname : (c->lns ? c->lns->entname : "")),
                     cnt, c->ourcid,
                     c->cid, c->serno, c->data_seq_num, c->data_rec_seq_num,
                     c->pLr, c->tx_bytes, c->tx_pkts, c->rx_bytes, c->rx_pkts);
            c = c->next;
        }
        t = t->next;
    }
    log (LOG_WARN, "==========Config File===========\n");
    tlns = lnslist;
    while (tlns)
    {
        log (LOG_WARN, "LNS entry %s\n",
                 tlns->entname[0] ? tlns->entname : "(unnamed)");
        tlns = tlns->next;
    };
    tlac = laclist;
    while (tlac)
    {
        log (LOG_WARN, "LAC entry %s, LNS is/are:",
                 tlac->entname[0] ? tlac->entname : "(unnamed)");
        h = tlac->lns;
        if (h)
        {
            while (h)
            {
                log (LOG_WARN, " %s", h->hostname);
                h = h->next;
            }
        }
        else
            log (LOG_WARN, " [none]");
        tlac = tlac->next;
    };
    log (LOG_WARN, "================================\n");
}
Ejemplo n.º 5
0
Archivo: call.c Proyecto: sina-ht/l2tpd
struct call *get_call (int tunnel, int call, unsigned int addr, int port)
{
    /*
     * Figure out which call struct should handle this. 
     * If we have tunnel and call ID's then they are unique.
     * Otherwise, if the tunnel is 0, look for an existing connection
     * or create a new tunnel.
     */
    struct tunnel *st;
    struct call *sc;
    if (tunnel)
    {
        st = tunnels.head;
        while (st)
        {
            if (st->ourtid == tunnel)
            {
                if (call)
                {
                    sc = st->call_head;
                    while (sc)
                    {
                        if (sc->ourcid == call)
                            return sc;
                        sc = sc->next;
                    }
                    l2tp_log (LOG_DEBUG, "%s: can't find call %d in tunnel %d\n",
                         __FUNCTION__, call, tunnel);
                    return NULL;
                }
                else
                {
                    return st->self;
                }
            }
            st = st->next;
        }
        l2tp_log (LOG_DEBUG, "%s:can't find tunnel %d\n", __FUNCTION__, tunnel);
        return NULL;
    }
    else
    {
#ifdef USE_KERNEL
        struct l2tp_tunnel_opts to;
#endif
        /* You can't specify a call number if you haven't specified
           a tunnel silly! */

        if (call)
        {
            l2tp_log (LOG_WARN,
                 "%s: call ID specified, but no tunnel ID specified.  tossing.\n",
                 __FUNCTION__);
            return NULL;
        }
        /*
         * Well, nothing appropriate...  Let's add a new tunnel, if
         * we are not at capacity.
         */
        if (debug_tunnel)
        {
            l2tp_log (LOG_DEBUG,
                 "%s: allocating new tunnel for host %s, port %d.\n",
                 __FUNCTION__, IPADDY (addr), ntohs (port));
        }
        if (!(st = new_tunnel ()))
        {
            l2tp_log (LOG_WARN,
                 "%s: unable to allocate new tunnel for host %s, port %d.\n",
                 __FUNCTION__, IPADDY (addr), ntohs (port));
            return NULL;
        };
        st->peer.sin_family = AF_INET;
        st->peer.sin_port = port;
        bcopy (&addr, &st->peer.sin_addr, sizeof (addr));
#ifdef USE_KERNEL
        if (kernel_support)
        {
            /* Update kernel as to peer's location */
            to.ourtid = st->ourtid;
            ioctl (server_socket, L2TPIOCGETTUNOPTS, &to);
            bcopy (&st->peer, &to.peer, sizeof (st->peer));
            to.addrlen = sizeof (st->peer);
            ioctl (server_socket, L2TPIOCSETTUNOPTS, &to);
        }
#endif
        st->next = tunnels.head;
        tunnels.head = st;
        tunnels.count++;
        return st->self;
    }
}
Ejemplo n.º 6
0
Archivo: call.c Proyecto: sina-ht/l2tpd
void call_close (struct call *c)
{
    struct buffer *buf;
    struct schedule_entry *se, *ose;
    struct call *tmp, *tmp2;
    if (!c || !c->container)
    {
        l2tp_log (LOG_DEBUG, "%s: called on null call or containerless call\n",
             __FUNCTION__);
        return;
    }
    if (c == c->container->self)
    {
        /*
         * We're actually closing the
         * entire tunnel
         */

        /* First deschedule any remaining packet transmissions
           for this tunnel.  That means Hello's and any reminaing
           packets scheduled for transmission.  This is a very
           nasty little piece of code here. */

        se = events;
        ose = NULL;
        while (se)
        {
            if ((((struct buffer *) se->data)->tunnel == c->container)
                || ((struct tunnel *) se->data == c->container))
            {
#ifdef DEBUG_CLOSE
                l2tp_log (LOG_DEBUG, "%s: Descheduling event\n", __FUNCTION__);
#endif
                if (ose)
                {
                    ose->next = se->next;
                    if ((struct tunnel *) se->data != c->container)
                        toss ((struct buffer *) (se->data));
                    free (se);
                    se = ose->next;
                }
                else
                {
                    events = se->next;
                    if ((struct tunnel *) se->data != c->container)
                        toss ((struct buffer *) (se->data));
                    free (se);
                    se = events;
                }
            }
            else
            {
                ose = se;
                se = se->next;
            }
        }

        if (c->closing)
        {
            /* Really close this tunnel, as our
               StopCCN has been ack'd */
#ifdef DEBUG_CLOSE
            l2tp_log (LOG_DEBUG, "%s: Actually closing tunnel %d\n", __FUNCTION__,
                 c->container->ourtid);
#endif
#ifdef USE_KERNEL
            if (kernel_support)
                ioctl (server_socket, L2TPIOCDELTUNNEL, c->container->ourtid);
#endif
            destroy_tunnel (c->container);
            return;
        }

        /*
           * We need to close, but need to provide reliable delivery
           * of the final StopCCN. We record our state to know when
           * we have actually received an ACK on our StopCCN
         */
        c->closeSs = c->container->control_seq_num;
        buf = new_outgoing (c->container);
        add_message_type_avp (buf, StopCCN);
        if (c->container->hbit)
        {
            mk_challenge (c->container->chal_them.vector, VECTOR_SIZE);
            add_randvect_avp (buf, c->container->chal_them.vector,
                              VECTOR_SIZE);
        }
        add_tunnelid_avp (buf, c->container->ourtid);
        if (c->result < 0)
            c->result = RESULT_CLEAR;
        if (c->error < 0)
            c->error = 0;
        add_result_code_avp (buf, c->result, c->error, c->errormsg,
                             strlen (c->errormsg));
        add_control_hdr (c->container, c, buf);
        if (packet_dump)
            do_packet_dump (buf);
#ifdef DEBUG_CLOSE
        l2tp_log (LOG_DEBUG, "%s: enqueing close message for tunnel\n",
             __FUNCTION__);
#endif
        control_xmit (buf);
        /*
           * We also need to stop all traffic on any calls contained
           * within us.
         */
        tmp = c->container->call_head;
        while (tmp)
        {
            tmp2 = tmp->next;
            tmp->needclose = 0;
            tmp->closing = -1;
            call_close (tmp);
            tmp = tmp2;
        }
	/* mf, 16.04.2003: change log message to show tunneltag */
        // l2tp_log (LOG_LOG,
        //      "%s : Connection %d closed to %s, port %d (%s)\n", __FUNCTION__,
        //      c->container->tid,
        //      IPADDY (c->container->peer.sin_addr),
        //      ntohs (c->container->peer.sin_port), c->errormsg);
        l2tp_log (LOG_LOG,
             "%s : Connection closed with peer %s, reason: %s\n",
             __FUNCTION__, c->container->tunneltag, c->errormsg);
    }
    else
    {
        /*
           * Just close a call
         */
#ifdef USE_KERNEL
        struct l2tp_call_opts co;
#endif
        if (c->zlb_xmit)
            deschedule (c->zlb_xmit);
/*		if (c->dethrottle) deschedule(c->dethrottle); */
        if (c->closing)
        {
#ifdef DEBUG_CLOSE
            l2tp_log (LOG_DEBUG, "%s: Actually closing call %d\n", __FUNCTION__,
                 c->ourcid);
#endif
            destroy_call (c);
            return;
        }
#ifdef USE_KERNEL
        if (kernel_support)
        {
            co.ourtid = c->container->ourtid;
            co.ourcid = c->ourcid;
            ioctl (server_socket, L2TPIOCGETCALLOPTS, &co);
            co.flags = co.flags & ~L2TP_FLAG_CALL_UP;
            ioctl (server_socket, L2TPIOCSETCALLOPTS, &co);
        }
#endif
        c->closeSs = c->container->control_seq_num;
        buf = new_outgoing (c->container);
        add_message_type_avp (buf, CDN);
        if (c->container->hbit)
        {
            mk_challenge (c->container->chal_them.vector, VECTOR_SIZE);
            add_randvect_avp (buf, c->container->chal_them.vector,
                              VECTOR_SIZE);
        }
        if (c->result < 0)
            c->result = RESULT_CLEAR;
        if (c->error < 0)
            c->error = 0;
        add_result_code_avp (buf, c->result, c->error, c->errormsg,
                             strlen (c->errormsg));
#ifdef TEST_HIDDEN
        add_callid_avp (buf, c->ourcid, c->container);
#else
        add_callid_avp (buf, c->ourcid);
#endif
        add_control_hdr (c->container, c, buf);
        if (packet_dump)
            do_packet_dump (buf);
#ifdef DEBUG_CLOSE
        l2tp_log (LOG_DEBUG, "%s: enqueuing close message for call %d\n",
             __FUNCTION__, c->ourcid);
#endif
        control_xmit (buf);
        l2tp_log (LOG_LOG, "%s: Call %d to %s disconnected\n", __FUNCTION__,
             c->ourcid, IPADDY (c->container->peer.sin_addr));
    }
    /*
       * Note that we're in the process of closing now
     */
    c->closing = -1;
}
Ejemplo n.º 7
0
struct call *get_call (int tunnel, int call,  unsigned int addr, int port,
                       IPsecSAref_t refme, IPsecSAref_t refhim)
{
    /*
     * Figure out which call struct should handle this.
     * If we have tunnel and call ID's then they are unique.
     * Otherwise, if the tunnel is 0, look for an existing connection
     * or create a new tunnel.
     */
    struct tunnel *st;
    struct call *sc;
    if (tunnel)
    {
        st = tunnels.head;
        while (st)
        {
            if (st->ourtid == tunnel &&
                    (gconfig.ipsecsaref==0 ||
                     (st->refhim == refhim
                      || refhim==IPSEC_SAREF_NULL
                      || st->refhim==IPSEC_SAREF_NULL)))
            {
                if (call)
                {
                    sc = st->call_head;
                    while (sc)
                    {
                        /* confirm that this is in fact a call with the right SA! */
                        if (sc->ourcid == call) return sc;
                        sc = sc->next;
                    }
                    l2tp_log (LOG_DEBUG, "%s: can't find call %d in tunnel %d\n (ref=%d/%d)",
                              __FUNCTION__, call, tunnel, refme, refhim);
                    return NULL;
                }
                else
                {
                    return st->self;
                }
            }
            st = st->next;
        }

        l2tp_log (LOG_DEBUG, "Can not find tunnel %u (refhim=%u)\n",
                  tunnel, refhim);
        return NULL;
    }
    else
    {
        /* You can't specify a call number if you haven't specified
           a tunnel silly! */

        if (call)
        {
            l2tp_log (LOG_WARNING,
                      "%s: call ID specified, but no tunnel ID specified.  tossing.\n",
                      __FUNCTION__);
            return NULL;
        }
        /*
         * Well, nothing appropriate...  Let's add a new tunnel, if
         * we are not at capacity.
         */
        if (gconfig.debug_tunnel)
        {
            l2tp_log (LOG_DEBUG,
                      "%s: allocating new tunnel for host %s, port %d.\n",
                      __FUNCTION__, IPADDY (addr), ntohs (port));
        }
        if (!(st = new_tunnel ()))
        {
            l2tp_log (LOG_WARNING,
                      "%s: unable to allocate new tunnel for host %s, port %d.\n",
                      __FUNCTION__, IPADDY (addr), ntohs (port));
            return NULL;
        };
        st->peer.sin_family = AF_INET;
        st->peer.sin_port = port;
        st->refme  = refme;
        st->refhim = refhim;
        // <-------  add for fix unable to connect to l2tp socket. By Jacky.Chen 2012.06.06
        st->u_fd = -1;
        st->m_fd = -1;
        // ------>
        bcopy (&addr, &st->peer.sin_addr, sizeof (addr));
        st->next = tunnels.head;
        tunnels.head = st;
        tunnels.count++;
        return st->self;
    }
}
Ejemplo n.º 8
0
void call_close (struct call *c)
{
    struct buffer *buf;
    struct schedule_entry *se, *ose;
    struct call *tmp, *tmp2;
    if (!c || !c->container)
    {
        l2tp_log (LOG_DEBUG, "%s: called on null call or containerless call\n",
                  __FUNCTION__);
        return;
    }
    if (c == c->container->self)
    {
        /*
         * We're actually closing the
         * entire tunnel
         */

        /* First deschedule any remaining packet transmissions
           for this tunnel.  That means Hello's and any reminaing
           packets scheduled for transmission.  This is a very
           nasty little piece of code here. */

        se = events;
        ose = NULL;
        while (se)
        {
            if ((((struct buffer *) se->data)->tunnel == c->container)
                    || ((struct tunnel *) se->data == c->container))
            {
#ifdef DEBUG_CLOSE
                l2tp_log (LOG_DEBUG, "%s: Descheduling event\n", __FUNCTION__);
#endif
                if (ose)
                {
                    ose->next = se->next;
                    if ((struct tunnel *) se->data != c->container)
                        toss ((struct buffer *) (se->data));
                    free (se);
                    se = ose->next;
                }
                else
                {
                    events = se->next;
                    if ((struct tunnel *) se->data != c->container)
                        toss ((struct buffer *) (se->data));
                    free (se);
                    se = events;
                }
            }
            else
            {
                ose = se;
                se = se->next;
            }
        }

        if (c->closing)
        {
            /* Really close this tunnel, as our
               StopCCN has been ack'd */
#ifdef DEBUG_CLOSE
            l2tp_log (LOG_DEBUG, "%s: Actually closing tunnel %d\n", __FUNCTION__,
                      c->container->ourtid);
#endif
            destroy_tunnel (c->container);
            return;
        }

        /*
           * We need to close, but need to provide reliable delivery
           * of the final StopCCN. We record our state to know when
           * we have actually received an ACK on our StopCCN
         */
        c->closeSs = c->container->control_seq_num;
        buf = new_outgoing (c->container);
        add_message_type_avp (buf, StopCCN);
        if (c->container->hbit)
        {
            mk_challenge (c->container->chal_them.vector, VECTOR_SIZE);
            add_randvect_avp (buf, c->container->chal_them.vector,
                              VECTOR_SIZE);
        }
        add_tunnelid_avp (buf, c->container->ourtid);
        if (c->result < 0)
            c->result = RESULT_CLEAR;
        if (c->error < 0)
            c->error = 0;
        add_result_code_avp (buf, c->result, c->error, c->errormsg,
                             strlen (c->errormsg));
        add_control_hdr (c->container, c, buf);
        if (gconfig.packet_dump)
            do_packet_dump (buf);
#ifdef DEBUG_CLOSE
        l2tp_log (LOG_DEBUG, "%s: enqueing close message for tunnel\n",
                  __FUNCTION__);
#endif
        control_xmit (buf);
        /*
           * We also need to stop all traffic on any calls contained
           * within us.
         */
        tmp = c->container->call_head;
        while (tmp)
        {
            tmp2 = tmp->next;
            tmp->needclose = 0;
            tmp->closing = -1;
            call_close (tmp);
            tmp = tmp2;
        }
        l2tp_log (LOG_DEBUG, "Connection %d closed to %s, port %d (%s)\n",
                  c->container->tid,
                  IPADDY (c->container->peer.sin_addr),
                  ntohs (c->container->peer.sin_port), c->errormsg);

        if(strcmp(c->errormsg,"Server closing") )
        {
            if(!strcmp(c->errormsg,"goodbye!") )
                l2tp_log (LOG_INFO,
                          "Terminated by router connect %s, cause manual disconnect.\n", IPADDY (c->container->peer.sin_addr) );
            else if( c->msgtype <= 0 || c->msgtype > 16 )
                l2tp_log (LOG_INFO, "Detect %s from %s, port %d \n",
                          c->errormsg, IPADDY (c->container->peer.sin_addr),
                          ntohs (c->container->peer.sin_port));
            else
                l2tp_log (LOG_INFO, "Detect %s %s from %s, port %d \n",
                          msgtypes[c->msgtype],c->errormsg, IPADDY (c->container->peer.sin_addr),
                          ntohs (c->container->peer.sin_port));
        }
        //if( (!strcmp(c->errormsg, "Timeout")) && (c->container->tid != 0) )
        //	l2tp_log(LOG_INFO, "Terminated by router, cause no response to echo-requests.");

    }
    else
    {
        /*
           * Just close a call
         */
        if (c->zlb_xmit)
            deschedule (c->zlb_xmit);
        /*		if (c->dethrottle) deschedule(c->dethrottle); */
        if (c->closing)
        {
#ifdef DEBUG_CLOSE
            l2tp_log (LOG_DEBUG, "%s: Actually closing call %d\n", __FUNCTION__,
                      c->ourcid);
#endif
            destroy_call (c);
            return;
        }
        c->closeSs = c->container->control_seq_num;
        buf = new_outgoing (c->container);
        add_message_type_avp (buf, CDN);
        if (c->container->hbit)
        {
            mk_challenge (c->container->chal_them.vector, VECTOR_SIZE);
            add_randvect_avp (buf, c->container->chal_them.vector,
                              VECTOR_SIZE);
        }
        if (c->result < 0)
            c->result = RESULT_CLEAR;
        if (c->error < 0)
            c->error = 0;
        add_result_code_avp (buf, c->result, c->error, c->errormsg,
                             strlen (c->errormsg));
#ifdef TEST_HIDDEN
        add_callid_avp (buf, c->ourcid, c->container);
#else
        add_callid_avp (buf, c->ourcid);
#endif
        add_control_hdr (c->container, c, buf);
        if (gconfig.packet_dump)
            do_packet_dump (buf);
#ifdef DEBUG_CLOSE
        l2tp_log (LOG_DEBUG, "%s: enqueuing close message for call %d\n",
                  __FUNCTION__, c->ourcid);
#endif
        control_xmit (buf);
        l2tp_log (LOG_DEBUG, "%s: Call %d to %s disconnected\n", __FUNCTION__,
                  c->ourcid, IPADDY (c->container->peer.sin_addr));
    }
    /*
       * Note that we're in the process of closing now
     */
    c->closing = -1;
}