Example #1
0
void do_control ()
{
    char buf[1024];
    char *host;
    char *tunstr;
    char *callstr;

    char *sub_str;              /* jz: use by the strtok function */
    char *tmp_ptr;              /* jz: use by the strtok function */
    struct lac *lac;
    int call;
    int tunl;
    int cnt = -1;
    while (cnt)
    {
        cnt = read (control_fd, buf, sizeof (buf));
        if (cnt > 0)
        {
            if (buf[cnt - 1] == '\n')
                buf[--cnt] = 0;
#ifdef DEBUG_CONTROL
            log (LOG_DEBUG, "%s: Got message %s (%d bytes long)\n",
                 __FUNCTION__, buf, cnt);
#endif
            switch (buf[0])
            {
            case 't':
                host = strchr (buf, ' ') + 1;
#ifdef DEBUG_CONTROL
                log (LOG_DEBUG, "%s: Attempting to tunnel to %s\n",
                     __FUNCTION__, host);
#endif
                l2tp_call (host, UDP_LISTEN_PORT, NULL, NULL);
                break;
            case 'c':

                switch_io = 1;  /* jz: Switch for Incoming - Outgoing Calls */

                tunstr = strchr (buf, ' ') + 1;
                lac = laclist;
                while (lac)
                {
                    if (!strcasecmp (lac->entname, tunstr))
                    {
                        lac->active = -1;
                        lac->rtries = 0;
                        if (!lac->c)
                            magic_lac_dial (lac);
                        break;
                    }
                    lac = lac->next;
                }
                if (lac)
                    break;
                tunl = atoi (tunstr);
                if (!tunl)
                {
                    log (LOG_DEBUG, "No such tunnel '%s'\n", tunstr);
                    break;
                }
#ifdef DEBUG_CONTROL
                log (LOG_DEBUG, "%s: Attempting to call on tunnel %d\n",
                     __FUNCTION__, tunl);
#endif
                lac_call (tunl, NULL, NULL);
                break;

            case 'o':          /* jz: option 'o' for doing a outgoing call */

                switch_io = 0;  /* jz: Switch for incoming - outgoing Calls */

                sub_str = strchr (buf, ' ') + 1;

                tunstr = strtok (sub_str, " "); /* jz: using strtok function to get */
                tmp_ptr = strtok (NULL, " ");   /*     params out of the pipe       */
                strcpy (dial_no_tmp, tmp_ptr);

                lac = laclist;
                while (lac)
                {
                    if (!strcasecmp (lac->entname, tunstr))
                    {
                        lac->active = -1;
                        lac->rtries = 0;
                        if (!lac->c)
                            magic_lac_dial (lac);
                        else
                            log (LOG_DEBUG,
                                 "Session '%s' already active!\n",
                                lac->entname);
                        break;
                    }
                    lac = lac->next;
                }
                if (lac)
                    break;
                tunl = atoi (tunstr);
                if (!tunl)
                {
                    log (LOG_DEBUG, "No such tunnel '%s'\n", tunstr);
                    break;
                }
#ifdef DEBUG_CONTROL
                log (LOG_DEBUG, "%s: Attempting to call on tunnel %d\n",
                     __FUNCTION__, tunl);
#endif
                lac_call (tunl, NULL, NULL);
                break;

            case 'h':
                callstr = strchr (buf, ' ') + 1;
                call = atoi (callstr);
#ifdef DEBUG_CONTROL
                log (LOG_DEBUG, "%s: Attempting to hangup call %d\n", __FUNCTION__,
                     call);
#endif
                lac_hangup (call);
                break;
            case 'd':
                tunstr = strchr (buf, ' ') + 1;
                lac = laclist;
                while (lac)
                {
                    if (!strcasecmp (lac->entname, tunstr))
                    {
                        lac->active = 0;
                        lac->rtries = 0;
                        if (lac->t)
                            lac_disconnect (lac->t->ourtid);
                        else
                            log (LOG_DEBUG, "Session '%s' not up\n",
                                 lac->entname);
                        break;
                    }
                    lac = lac->next;
                }
                if (lac)
                    break;
                tunl = atoi (tunstr);
                if (!tunl)
                {
                    log (LOG_DEBUG, "No such tunnel '%s'\n",
                         tunstr);
                    break;
                }
#ifdef DEBUG_CONTROL
                log (LOG_DEBUG, "%s: Attempting to disconnect tunnel %d\n",
                     __FUNCTION__, tunl);
#endif
                lac_disconnect (tunl);
                break;
            case 's':
                show_status ();
                break;
            default:
                log (LOG_DEBUG, "Unknown command %c\n",
                     buf[0]);
            }
        }
    }
    /* Otherwise select goes nuts */
    close (control_fd);
    control_fd = open (gconfig.controlfile, O_RDONLY | O_NONBLOCK, 0600);
    if (control_fd < 0)
    {
        log (LOG_CRIT, "%s: Unable to open %s for reading.",
             __FUNCTION__, gconfig.controlfile);
    }
}
Example #2
0
void do_control ()
{
    char buf[1024];
    char *host;
    char *tunstr;
    char *callstr;

    char *authname = NULL;
    char *password = NULL;
    char delims[] = " ";
    char *sub_str;              /* jz: use by the strtok function */
    char *tmp_ptr;              /* jz: use by the strtok function */
    struct lac *lac;
    int call;
    int tunl;
    int cnt = -1;
    int done = 0;

    bzero(buf, sizeof(buf));
    buf[0]='\0';

    while (!done)
    {
        cnt = read (control_fd, buf, sizeof (buf));
        if (cnt <= 0)
        {
        if(cnt < 0 && errno != EINTR) {
                perror("controlfd");
        }
        done=1;
        break;
        }

        if (buf[cnt - 1] == '\n')
        buf[--cnt] = 0;
#ifdef DEBUG_CONTROL
        l2tp_log (LOG_DEBUG, "%s: Got message %s (%d bytes long)\n",
                   __FUNCTION__, buf, cnt);
#endif
        switch (buf[0])
        {
        case 't':
            host = strchr (buf, ' ') + 1;
#ifdef DEBUG_CONTROL
            l2tp_log (LOG_DEBUG, "%s: Attempting to tunnel to %s\n",
                      __FUNCTION__, host);
#endif
            l2tp_call (host, UDP_LISTEN_PORT, NULL, NULL);
            break;
        case 'c':
            switch_io = 1;  /* jz: Switch for Incoming - Outgoing Calls */
            
            tunstr = strtok (&buf[1], delims);

            /* Are these passed on the command line? */
            authname = strtok (NULL, delims);
            password = strtok (NULL, delims);

            lac = laclist;
            while (lac && strcasecmp (lac->entname, tunstr)!=0)
            {
               lac = lac->next;
            }

            if(lac) {
                lac->active = -1;
                lac->rtries = 0;
                if (authname != NULL)
                    strncpy (lac->authname, authname, STRLEN);
                if (password != NULL)
                    strncpy (lac->password, password, STRLEN);
                if (!lac->c)
                magic_lac_dial (lac);
                else {
                l2tp_log (LOG_DEBUG,
                          "Session '%s' already active!\n", lac->entname);
                }
                break;
            }

            /* did not find a tunnel by name, look by number */
            tunl = atoi (tunstr);
            if (!tunl)
            {
                l2tp_log (LOG_DEBUG, "No such tunnel '%s'\n", tunstr);
                break;
            }
#ifdef DEBUG_CONTROL
            l2tp_log (LOG_DEBUG, "%s: Attempting to call on tunnel %d\n",
                       __FUNCTION__, tunl);
#endif
            lac_call (tunl, NULL, NULL);
            break;
            
       case 'o':          /* jz: option 'o' for doing a outgoing call */
            switch_io = 0;  /* jz: Switch for incoming - outgoing Calls */
            
            sub_str = strchr (buf, ' ') + 1;
            tunstr = strtok (sub_str, " "); /* jz: using strtok function to get */
            tmp_ptr = strtok (NULL, " ");   /*     params out of the pipe       */
            strcpy (dial_no_tmp, tmp_ptr);
            
            lac = laclist;
            while (lac && strcasecmp (lac->entname, tunstr)!=0)
            {
                lac = lac->next;
            }

            if(lac) {
                lac->active = -1;
                lac->rtries = 0;
                if (!lac->c)
                    magic_lac_dial (lac);
                else
                    l2tp_log (LOG_DEBUG, "Session '%s' already active!\n",
                              lac->entname);
                break;
            }

            /* did not find a tunnel by name, look by number */
            tunl = atoi (tunstr);
            if (!tunl)
            {
                l2tp_log (LOG_DEBUG, "No such tunnel '%s'\n", tunstr);
                break;
            }
#ifdef DEBUG_CONTROL
            l2tp_log (LOG_DEBUG, "%s: Attempting to call on tunnel %d\n",
                       __FUNCTION__, tunl);
#endif
            lac_call (tunl, NULL, NULL);
            break;
            
        case 'h':
            callstr = strchr (buf, ' ') + 1;
            call = atoi (callstr);
#ifdef DEBUG_CONTROL
            l2tp_log (LOG_DEBUG, "%s: Attempting to hangup call %d\n", __FUNCTION__,
                      call);
#endif
            lac_hangup (call);
            break;

        case 'd':
            tunstr = strchr (buf, ' ') + 1;
            lac = laclist;
            while (lac)
            {
                if (!strcasecmp (lac->entname, tunstr))
                {
                    lac->active = 0;
                    lac->rtries = 0;
                    if (lac->t)
                        lac_disconnect (lac->t->ourtid);
                    else
                        l2tp_log (LOG_DEBUG, "Session '%s' not up\n",
                                  lac->entname);
                    break;
                }
                lac = lac->next;
            }
            if (lac)
                break;
            tunl = atoi (tunstr);
            if (!tunl)
            {
                l2tp_log (LOG_DEBUG, "No such tunnel '%s'\n",
                          tunstr);
                break;
            }
#ifdef DEBUG_CONTROL
            l2tp_log (LOG_DEBUG, "%s: Attempting to disconnect tunnel %d\n",
                      __FUNCTION__, tunl);
#endif
            lac_disconnect (tunl);
            break;
        case 's':
            show_status ();
            break;
        default:
            l2tp_log (LOG_DEBUG, "Unknown command %c\n", buf[0]);
        }
    }

    /* Otherwise select goes nuts. Yeah, this just seems wrong */
    close (control_fd);
    open_controlfd();
}
Example #3
0
void do_control ()
{
    char buf[CONTROL_PIPE_MESSAGE_SIZE];
    char *bufp; /* current buffer pointer */
    char *host;
    char *tunstr;
    char *callstr;

    char *authname = NULL;
    char *password = NULL;
    char delims[] = " ";
    char *sub_str;              /* jz: use by the strtok function */
    char *tmp_ptr;              /* jz: use by the strtok function */
    struct lac *lac;
    struct lac *prev_lac;     /* for lac removing */
    int call;
    int tunl;
    int cnt = -1;
    int done = 0;

    bzero(buf, sizeof(buf));
    buf[0]='\0';
    
    char* res_filename; /* name of file to write result of command */
    FILE* resf; /* stream for write result of command */

    while (!done)
    {
        cnt = read (control_fd, buf, sizeof (buf));
        if (cnt <= 0)
        {
            if(cnt < 0 && errno != EINTR) {
                perror("controlfd");
            }
            done = 1;
            break;
        }

        if (buf[cnt - 1] == '\n')
            buf[--cnt] = 0;
#ifdef DEBUG_CONTROL
        l2tp_log (LOG_DEBUG, "%s: Got message %s (%d bytes long)\n",
                   __FUNCTION__, buf, cnt);
#endif
        bufp = buf;
        /* check if caller want to get result */
        if (bufp[0] == '@')
        {
            /* parse filename (@/path/to/file *...), where * is command */
            res_filename = &bufp[1];
            int fnlength = strcspn(res_filename, " ");
            if ((fnlength == 0) || (res_filename[fnlength] == '\0')){
                l2tp_log (LOG_DEBUG,
                    "%s: Can't parse result filename or command\n",
                    __FUNCTION__
                );
                continue;
            }
            res_filename[fnlength] = '\0';
            bufp = &res_filename[fnlength + 1]; /* skip filename in bufp */

            /*FIXME: check quotes to allow filenames with spaces?
              (do not forget quotes escaping to allow filenames with quotes)*/

            /*FIXME: write to res_filename may cause SIGPIPE, need to catch it*/
            resf = fopen (res_filename, "w");
            if (!resf) {
                l2tp_log (LOG_DEBUG, "%s: Can't open result file %s\n",
                      __FUNCTION__, res_filename);
                continue;
            }
        } else
            resf = NULL;

        switch (bufp[0])
        {
        case 't':
            host = strchr (bufp, ' ') + 1;
#ifdef DEBUG_CONTROL
            l2tp_log (LOG_DEBUG, "%s: Attempting to tunnel to %s\n",
                      __FUNCTION__, host);
#endif            
            if (l2tp_call (host, UDP_LISTEN_PORT, NULL, NULL))
                write_res (resf, "%02i OK\n", 0);
            else
                write_res (resf, "%02i Error\n", 1);
            break;
        case 'c':
            switch_io = 1;  /* jz: Switch for Incoming - Outgoing Calls */
            
            tunstr = strtok (&bufp[1], delims);

            /* Are these passed on the command line? */
            authname = strtok (NULL, delims);
            password = strtok (NULL, delims);

            lac = laclist;
            while (lac && strcasecmp (lac->entname, tunstr)!=0)
            {
               lac = lac->next;
            }

            if(lac) {
                lac->active = -1;
                lac->rtries = 0;
                if (authname != NULL)
                    strncpy (lac->authname, authname, STRLEN);
                if (password != NULL)
                    strncpy (lac->password, password, STRLEN);
                if (!lac->c)
                {
                    magic_lac_dial (lac);
                    write_res (resf, "%02i OK\n", 0);
                } else {
                    l2tp_log (LOG_DEBUG,
                              "Session '%s' already active!\n", lac->entname);
                    write_res (resf, "%02i Session '%s' already active!\n", 1, 
                                 lac->entname);
                }
                break;
            }

            /* did not find a tunnel by name, look by number */
            tunl = atoi (tunstr);
            if (!tunl)
            {
                l2tp_log (LOG_DEBUG, "No such tunnel '%s'\n", tunstr);
                write_res (resf, "%02i No such tunnel '%s'\n", 1, tunstr);
                break;
            }
#ifdef DEBUG_CONTROL
            l2tp_log (LOG_DEBUG, "%s: Attempting to call on tunnel %d\n",
                       __FUNCTION__, tunl);
#endif
            if (lac_call (tunl, NULL, NULL))
                write_res (resf, "%02i OK\n", 0);
            else
                write_res (resf, "%02i Error\n", 1);
            break;
            
       case 'o':          /* jz: option 'o' for doing a outgoing call */
            switch_io = 0;  /* jz: Switch for incoming - outgoing Calls */
            
            sub_str = strchr (bufp, ' ') + 1;
            tunstr = strtok (sub_str, " "); /* jz: using strtok function to get */
            tmp_ptr = strtok (NULL, " ");   /*     params out of the pipe       */
            strcpy (dial_no_tmp, tmp_ptr);
            
            lac = laclist;
            while (lac && strcasecmp (lac->entname, tunstr)!=0)
            {
                lac = lac->next;
            }

            if(lac) {
                lac->active = -1;
                lac->rtries = 0;
                if (!lac->c)
                {
                    magic_lac_dial (lac);
                    write_res (resf, "%02i OK\n", 0);
                } else {
                    l2tp_log (LOG_DEBUG, "Session '%s' already active!\n",
                              lac->entname);
                    write_res (resf, "%02i Session '%s' already active!\n", 1, 
                               lac->entname);
                }
                break;
            }

            /* did not find a tunnel by name, look by number */
            tunl = atoi (tunstr);
            if (!tunl)
            {
                l2tp_log (LOG_DEBUG, "No such tunnel '%s'\n", tunstr);
                write_res (resf, "%02i No such tunnel '%s'\n", 1, tunstr);
                break;
            }
#ifdef DEBUG_CONTROL
            l2tp_log (LOG_DEBUG, "%s: Attempting to call on tunnel %d\n",
                       __FUNCTION__, tunl);
#endif
            if (lac_call (tunl, NULL, NULL))
                write_res (resf, "%02i OK\n", 0);
            else
                write_res (resf, "%02i Error\n", 1);
            break;
            
        case 'h':
            callstr = strchr (bufp, ' ') + 1;
            call = atoi (callstr);
#ifdef DEBUG_CONTROL
            l2tp_log (LOG_DEBUG, "%s: Attempting to hangup call %d\n", __FUNCTION__,
                      call);
#endif
            lac_hangup (call);
            write_res (resf, "%02i OK\n", 0);
            break;

        case 'd':
            tunstr = strchr (bufp, ' ') + 1;
            lac = laclist;
            while (lac)
            {
                if (!strcasecmp (lac->entname, tunstr))
                {
                    lac->active = 0;
                    lac->rtries = 0;
                    if (lac->t)
                    {
                        lac_disconnect (lac->t->ourtid);
                        write_res (resf, "%02i OK\n", 0);
                    } else {
                        l2tp_log (LOG_DEBUG, "Session '%s' not up\n",
                                  lac->entname);
                        write_res (resf, "%02i Session '%s' not up\n", 1,
                                  lac->entname);
                    }
                    break;
                }
                lac = lac->next;
            }
            if (lac)
                break;
            tunl = atoi (tunstr);
            if (!tunl)
            {
                l2tp_log (LOG_DEBUG, "No such tunnel '%s'\n", tunstr);
                write_res (resf, "%02i No such tunnel '%s'\n", 1, tunstr);
                break;
            }
#ifdef DEBUG_CONTROL
            l2tp_log (LOG_DEBUG, "%s: Attempting to disconnect tunnel %d\n",
                      __FUNCTION__, tunl);
#endif
            lac_disconnect (tunl);
            write_res (resf, "%02i OK\n", 0);
            break;
        case 's':
            show_status ();
            break;
        case 'a':
            /* add new or modify existing lac configuration */
            {               
                int create_new_lac = 0; 
                tunstr = strtok (&bufp[1], delims);
                if ((!tunstr) || (!strlen (tunstr)))
                {
                    write_res (resf,
                        "%02i Configuration parse error: lac-name expected\n", 1);
                    l2tp_log (LOG_CRIT, "%s: lac-name expected\n", __FUNCTION__);
                    break;
                }
                /* go to the end  of tunnel name*/
                bufp = tunstr + strlen (tunstr) + 1; 
                /* try to find lac with _tunstr_ name in laclist */
                lac = laclist;
                while (lac)
                {
                    if (!strcasecmp (tunstr, lac->entname))
                        break;
                    lac = lac->next;
                }
                if (!lac)
                {
                    /* nothing found, create new lac */
                    lac = new_lac ();
                    if (!lac)
                    {
                        write_res (resf,
                            "%02i Could't create new lac: no memory\n", 2);
                        l2tp_log (LOG_CRIT,
                            "%s: Couldn't create new lac\n", __FUNCTION__);
                        break;
                    }
                    create_new_lac = 1;
                }
                strncpy (lac->entname, tunstr, sizeof (lac->entname));

                if (parse_one_line_lac (bufp, lac))
                {
                    write_res (resf, "%02i Configuration parse error\n", 3);
                    break;
                }
                if (create_new_lac)
                {
                    lac->next = laclist;
                    laclist = lac;
                }
                if (lac->autodial)
                {
#ifdef DEBUG_MAGIC
                    l2tp_log (LOG_DEBUG, "%s: Autodialing '%s'\n", __FUNCTION__,
                         lac->entname[0] ? lac->entname : "(unnamed)");
#endif
                    lac->active = -1;
                    switch_io = 1;  /* If we're a LAC, autodials will be ICRQ's */
                    magic_lac_dial (lac);
                    /* FIXME: Should I check magic_lac_dial result somehow? */
                }
                write_res (resf, "%02i OK\n", 0);
            }
            break;
        case 'r':
            // find lac in laclist
            tunstr = strchr (bufp, ' ') + 1;
            lac = laclist;
            prev_lac = NULL;
            while (lac && strcasecmp (lac->entname, tunstr) != 0)
            {
                prev_lac = lac;
                lac = lac->next;
            }
            if (!lac)
            {
                l2tp_log (LOG_DEBUG, "No such tunnel '%s'\n",
                          tunstr);
                write_res (resf, "%02i No such tunnel '%s'\n", 1, tunstr);
                break;
            }
            // disconnect lac
            lac->active = 0;
            lac->rtries = 0;
            if (lac->t)
            {
                lac_disconnect (lac->t->ourtid);
            }
            // removes lac from laclist
            if (prev_lac == NULL)
                laclist = lac->next;
            else
                prev_lac->next = lac->next;
            free(lac);
            lac = NULL;
            write_res (resf, "%02i OK\n", 0);            
            break;
        default:
            l2tp_log (LOG_DEBUG, "Unknown command %c\n", bufp[0]);
            write_res (resf, "%02i Unknown command %c\n", 1, bufp[0]);
        }
        
        if (resf)
        {
            fclose (resf);
        }
    }

    /* Otherwise select goes nuts. Yeah, this just seems wrong */
    close (control_fd);
    open_controlfd();
}
void do_control (char *cmd)
{
    char buf[1024];
    char *host;
    char *tunstr;
    char *callstr;

    char *sub_str;              /* jz: use by the strtok function */
    char *tmp_ptr;              /* jz: use by the strtok function */
    struct lac *lac;
    int call;
    int tunl;
    int cnt = -1;
    int first_run = 0;


    while (cnt)
    {
        /* Foxconn, add by MJ. for building L2TP tunnel in the begining. */
        if(cmd != NULL)
        {
            first_run = 1;
            strcpy(buf, cmd);
            cnt = strlen(buf);
            log (LOG_DEBUG, "%s -> L2TP connect immediately. \n", __FUNCTION__);
        }
        else    
            cnt = read (control_fd, buf, sizeof (buf));
        /*add end, by MJ.*/
        if (cnt > 0)
        {
            if (buf[cnt - 1] == '\n')
                buf[--cnt] = 0;
#ifdef DEBUG_CONTROL
            log (LOG_DEBUG, "%s: Got message %s (%d bytes long)\n",
                 __FUNCTION__, buf, cnt);
#endif
            switch (buf[0])
            {
            case 't':
                host = strchr (buf, ' ') + 1;
#ifdef DEBUG_CONTROL
                log (LOG_DEBUG, "%s: Attempting to tunnel to %s\n",
                     __FUNCTION__, host);
#endif
                l2tp_call (host, UDP_LISTEN_PORT, NULL, NULL);
                break;
            case 'c':

                switch_io = 1;  /* jz: Switch for Incoming - Outgoing Calls */

                tunstr = strchr (buf, ' ') + 1;
                lac = laclist;
                while (lac)
                {
                    if (!strcasecmp (lac->entname, tunstr))
                    {
                        lac->active = -1;
                        lac->rtries = 0;
                        if (!lac->c)
                            magic_lac_dial (lac);
                        else
                            log (LOG_DEBUG,
                                 "%s: Session '%s' already active!\n",
                                 __FUNCTION__, lac->entname);
                        break;
                    }
                    lac = lac->next;
                }
                if (lac){
                    if (first_run) cnt = 0; /*Foxconn, by MJ., for leaving while*/
                    break; 
                }
                tunl = atoi (tunstr);
                if (!tunl)
                {
                    log (LOG_DEBUG, "%s: No such tunnel '%s'\n", __FUNCTION__,
                         tunstr);
                    if (first_run) cnt = 0; /*Foxconn, by MJ., for leaving while*/
                    break;
                }
#ifdef DEBUG_CONTROL
                log (LOG_DEBUG, "%s: Attempting to call on tunnel %d\n",
                     __FUNCTION__, tunl);
#endif
                lac_call (tunl, NULL, NULL);

                if (first_run) cnt = 0; /*Foxconn, by MJ., for leaving while*/
                break;

            case 'o':          /* jz: option 'o' for doing a outgoing call */

                switch_io = 0;  /* jz: Switch for incoming - outgoing Calls */

                sub_str = strchr (buf, ' ') + 1;

                tunstr = strtok (sub_str, " "); /* jz: using strtok function to get */
                tmp_ptr = strtok (NULL, " ");   /*     params out of the pipe       */
                strcpy (dial_no_tmp, tmp_ptr);

                lac = laclist;
                while (lac)
                {
                    if (!strcasecmp (lac->entname, tunstr))
                    {
                        lac->active = -1;
                        lac->rtries = 0;
                        if (!lac->c)
                            magic_lac_dial (lac);
                        else
                            log (LOG_DEBUG,
                                 "%s: Session '%s' already active!\n",
                                 __FUNCTION__, lac->entname);
                        break;
                    }
                    lac = lac->next;
                }
                if (lac)
                    break;
                tunl = atoi (tunstr);
                if (!tunl)
                {
                    log (LOG_DEBUG, "%s: No such tunnel '%s'\n", __FUNCTION__,
                         tunstr);
                    break;
                }
#ifdef DEBUG_CONTROL
                log (LOG_DEBUG, "%s: Attempting to call on tunnel %d\n",
                     __FUNCTION__, tunl);
#endif
                lac_call (tunl, NULL, NULL);
                break;

            case 'h':
                callstr = strchr (buf, ' ') + 1;
                call = atoi (callstr);
#ifdef DEBUG_CONTROL
                log (LOG_DEBUG, "%s: Attempting to call %d\n", __FUNCTION__,
                     call);
#endif
                lac_hangup (call);
                break;
            case 'd':
                tunstr = strchr (buf, ' ') + 1;
                lac = laclist;
                while (lac)
                {
                    if (!strcasecmp (lac->entname, tunstr))
                    {
                        lac->active = 0;
                        lac->rtries = 0;
                        if (lac->t)
                            lac_disconnect (lac->t->ourtid);
                        else
                            log (LOG_DEBUG, "%s: Session '%s' not up\n",
                                 __FUNCTION__, lac->entname);
                        break;
                    }
                    lac = lac->next;
                }
                if (lac)
                    break;
                tunl = atoi (tunstr);
                if (!tunl)
                {
                    log (LOG_DEBUG, "%s: No such tunnel '%s'\n", __FUNCTION__,
                         tunstr);
                    break;
                }
#ifdef DEBUG_CONTROL
                log (LOG_DEBUG, "%s: Attempting to disconnect tunnel %d\n",
                     __FUNCTION__, tunl);
#endif
                lac_disconnect (tunl);
                break;
            case 's':
                show_status (1);
                break;
            default:
                log (LOG_DEBUG, "%s: Unknown command %c\n", __FUNCTION__,
                     buf[0]);
            }
        }
    }
    /* Otherwise select goes nuts */
    close (control_fd);
    control_fd = open (CONTROL_PIPE, O_RDONLY | O_NONBLOCK, 0600);
}