Exemplo n.º 1
0
Arquivo: file.c Projeto: aunoor/xl2tpd
int parse_config (FILE * f)
{
    /* Read in the configuration file handed to us */
    /* FIXME: I should check for incompatible options */
    int context = 0;
    char buf[1024]; 
    char *s, *d, *t;
    int linenum = 0;
    int def = 0;
    int in_comment = 0;
    int has_lf;
    void *data = NULL;
    struct lns *tl;
    struct lac *tc;
    while (!feof (f))
    {
        if (NULL == fgets (buf, sizeof (buf), f))
        {
            /* Error or EOL */
            break;
        }
        /* Watch for continuation comments. */
        has_lf = buf[strlen(buf) - 1] == '\n';
        if (in_comment)
        {
            in_comment = !has_lf;
            continue;
        }
        linenum++;
        s = buf;
        /* Strip comments */
        while (*s && *s != ';')
            s++;
        if (*s == ';' && !has_lf)
            in_comment = 1;
        *s = 0;
        s = buf;
        if (!strlen (buf))
            continue;
        while ((*s < 33) && *s)
            s++;                /* Skip over beginning white space */
        t = s + strlen (s);
        while ((t >= s) && (*t < 33))
            *(t--) = 0;         /* Ditch trailing white space */
        if (!strlen (s))
            continue;
        if (s[0] == '[')
        {
            /* We've got a context description */
            if (!(t = strchr (s, ']')))
            {
                l2tp_log (LOG_CRIT, "parse_config: line %d: No closing bracket\n",
                     linenum);
                return -1;
            }
            t[0] = 0;
            s++;
            if ((d = strchr (s, ' ')))
            {
                /* There's a parameter */
                d[0] = 0;
                d++;
            }
            if (d && !strcasecmp (d, "default"))
                def = CONTEXT_DEFAULT;
            else
                def = 0;
            if (!strcasecmp (s, "global"))
            {
                context = CONTEXT_GLOBAL;
#ifdef DEBUG_FILE
                l2tp_log (LOG_DEBUG,
                     "parse_config: global context descriptor %s\n",
                     d ? d : "");
#endif
                data = &gconfig;
            }
            else if (!strcasecmp (s, "lns"))
            {
                context = CONTEXT_LNS;
                if (def)
                {
                    if (!deflns)
                    {
                        deflns = new_lns ();
                        strncpy (deflns->entname, "default",
                                 sizeof (deflns->entname));
                    }
                    data = deflns;
                    continue;
                }
                data = NULL;
                tl = lnslist;
                if (d)
                {
                    while (tl)
                    {
                        if (!strcasecmp (d, tl->entname))
                            break;
                        tl = tl->next;
                    }
                    if (tl)
                        data = tl;
                }
                if (!data)
                {
                    data = new_lns ();
                    if (!data)
                        return -1;
                    ((struct lns *) data)->next = lnslist;
                    lnslist = (struct lns *) data;
                }
                if (d)
                    strncpy (((struct lns *) data)->entname,
                             d, sizeof (((struct lns *) data)->entname));
#ifdef DEBUG_FILE
                l2tp_log (LOG_DEBUG, "parse_config: lns context descriptor %s\n",
                     d ? d : "");
#endif
            }
            else if (!strcasecmp (s, "lac"))
            {
                context = CONTEXT_LAC;
                if (def)
                {
                    if (!deflac)
                    {
                        deflac = new_lac ();
                        strncpy (deflac->entname, "default",
                                 sizeof (deflac->entname));
                    }
                    data = deflac;
                    continue;
                }
                data = NULL;
                tc = laclist;
                if (d)
                {
                    while (tc)
                    {
                        if (!strcasecmp (d, tc->entname))
                            break;
                        tc = tc->next;
                    }
                    if (tc)
                        data = tc;
                }
                if (!data)
                {
                    data = new_lac ();
                    if (!data)
                        return -1;
                    ((struct lac *) data)->next = laclist;
                    laclist = (struct lac *) data;
                }
                if (d)
                    strncpy (((struct lac *) data)->entname,
                             d, sizeof (((struct lac *) data)->entname));
#ifdef DEBUG_FILE
                l2tp_log (LOG_DEBUG, "parse_config: lac context descriptor %s\n",
                     d ? d : "");
#endif
            }
            else
            {
                l2tp_log (LOG_WARNING,
                     "parse_config: line %d: unknown context '%s'\n", linenum,
                     s);
                return -1;
            }
        }
        else
        {
            if (!context)
            {
                l2tp_log (LOG_WARNING,
                     "parse_config: line %d: data '%s' occurs with no context\n",
                     linenum, s);
                return -1;
            }
            if (!(t = strchr (s, '=')))
            {
                l2tp_log (LOG_WARNING, "parse_config: line %d: line too long or no '=' in data\n",
                     linenum);
                return -1;
            }
            d = t;
            d--;
            t++;
            while ((d >= s) && (*d < 33))
                d--;
            d++;
            *d = 0;
            while (*t && (*t < 33))
                t++;
#ifdef DEBUG_FILE
            l2tp_log (LOG_DEBUG, "parse_config: field is %s, value is %s\n", s, t);
#endif
            /* Okay, bit twiddling is done.  Let's handle this */
            
            switch (parse_one_option (s, t, context | def, data))
            {
            case -1:
                l2tp_log (LOG_WARNING, "parse_config: line %d: %s", linenum,
                             filerr);
                return -1;
            case -2:
                l2tp_log (LOG_CRIT, "parse_config: line %d: Unknown field '%s'\n",
                     linenum, s);
                return -1;
            }            
        }
    }
    return 0;
}
Exemplo n.º 2
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();
}