"Fossies" - the Fresh Open Source Software Archive

Member "ospfctl/parser.c" (14 Oct 2007, 7449 Bytes) of package /linux/privat/old/openospfd-4.6.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "parser.c" see the Fossies "Dox" file reference documentation.

    1 /*  $OpenBSD: parser.c,v 1.15 2007/10/14 01:28:08 deraadt Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
    5  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
    6  *
    7  * Permission to use, copy, modify, and distribute this software for any
    8  * purpose with or without fee is hereby granted, provided that the above
    9  * copyright notice and this permission notice appear in all copies.
   10  *
   11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   18  */
   19 
   20 #include <sys/types.h>
   21 #include <sys/socket.h>
   22 #include <netinet/in.h>
   23 #include <arpa/inet.h>
   24 #include <err.h>
   25 #include <errno.h>
   26 #include <limits.h>
   27 #include <stdio.h>
   28 #include <stdlib.h>
   29 #include <string.h>
   30 
   31 #include "ospfd.h"
   32 
   33 #include "parser.h"
   34 
   35 enum token_type {
   36     NOTOKEN,
   37     ENDTOKEN,
   38     KEYWORD,
   39     ADDRESS,
   40     FLAG,
   41     PREFIX,
   42     IFNAME
   43 };
   44 
   45 struct token {
   46     enum token_type      type;
   47     const char      *keyword;
   48     int          value;
   49     const struct token  *next;
   50 };
   51 
   52 static const struct token t_main[];
   53 static const struct token t_fib[];
   54 static const struct token t_show[];
   55 static const struct token t_show_iface[];
   56 static const struct token t_show_db[];
   57 static const struct token t_show_area[];
   58 static const struct token t_show_nbr[];
   59 static const struct token t_show_rib[];
   60 static const struct token t_show_fib[];
   61 
   62 static const struct token t_main[] = {
   63     {KEYWORD,   "reload",   RELOAD,     NULL},
   64     {KEYWORD,   "fib",      FIB,        t_fib},
   65     {KEYWORD,   "show",     SHOW,       t_show},
   66     {ENDTOKEN,  "",     NONE,       NULL}
   67 };
   68 
   69 static const struct token t_fib[] = {
   70     { KEYWORD,  "couple",   FIB_COUPLE, NULL},
   71     { KEYWORD,  "decouple", FIB_DECOUPLE,   NULL},
   72     { ENDTOKEN, "",     NONE,       NULL}
   73 };
   74 
   75 static const struct token t_show[] = {
   76     {NOTOKEN,   "",     NONE,       NULL},
   77     {KEYWORD,   "interfaces",   SHOW_IFACE, t_show_iface},
   78     {KEYWORD,   "database", SHOW_DB,    t_show_db},
   79     {KEYWORD,   "neighbor", SHOW_NBR,   t_show_nbr},
   80     {KEYWORD,   "rib",      SHOW_RIB,   t_show_rib},
   81     {KEYWORD,   "fib",      SHOW_FIB,   t_show_fib},
   82     {KEYWORD,   "summary",  SHOW_SUM,   NULL},
   83     {ENDTOKEN,  "",     NONE,       NULL}
   84 };
   85 
   86 static const struct token t_show_iface[] = {
   87     {NOTOKEN,   "",     NONE,           NULL},
   88     {KEYWORD,   "detail",   SHOW_IFACE_DTAIL,   NULL},
   89     {IFNAME,    "",     SHOW_IFACE_DTAIL,   NULL},
   90     {ENDTOKEN,  "",     NONE,           NULL}
   91 };
   92 
   93 static const struct token t_show_db[] = {
   94     {NOTOKEN,   "",         NONE,       NULL},
   95     {KEYWORD,   "area",         SHOW_DBBYAREA,  t_show_area},
   96     {KEYWORD,   "asbr",         SHOW_DBASBR,    NULL},
   97     {KEYWORD,   "external",     SHOW_DBEXT, NULL},
   98     {KEYWORD,   "network",      SHOW_DBNET, NULL},
   99     {KEYWORD,   "router",       SHOW_DBRTR, NULL},
  100     {KEYWORD,   "self-originated",  SHOW_DBSELF,    NULL},
  101     {KEYWORD,   "summary",      SHOW_DBSUM, NULL},
  102     {ENDTOKEN,  "",         NONE,       NULL}
  103 };
  104 
  105 static const struct token t_show_area[] = {
  106     {ADDRESS,   "",     NONE,       NULL},
  107     {ENDTOKEN,  "",     NONE,       NULL}
  108 };
  109 
  110 static const struct token t_show_nbr[] = {
  111     {NOTOKEN,   "",     NONE,       NULL},
  112     {KEYWORD,   "detail",   SHOW_NBR_DTAIL, NULL},
  113     {ENDTOKEN,  "",     NONE,       NULL}
  114 };
  115 
  116 static const struct token t_show_rib[] = {
  117     {NOTOKEN,   "",     NONE,       NULL},
  118     {KEYWORD,   "detail",   SHOW_RIB_DTAIL, NULL},
  119     {ENDTOKEN,  "",     NONE,       NULL}
  120 };
  121 
  122 static const struct token t_show_fib[] = {
  123     {NOTOKEN,   "",     NONE,           NULL},
  124     {KEYWORD,   "interface",    SHOW_FIB_IFACE,     t_show_iface},
  125     {FLAG,      "connected",    F_CONNECTED,        t_show_fib},
  126     {FLAG,      "static",   F_STATIC,       t_show_fib},
  127     {FLAG,      "ospf",     F_OSPFD_INSERTED,   t_show_fib},
  128     {ADDRESS,   "",     NONE,           NULL},
  129     {ENDTOKEN,  "",     NONE,           NULL}
  130 };
  131 
  132 static struct parse_result  res;
  133 
  134 struct parse_result *
  135 parse(int argc, char *argv[])
  136 {
  137     const struct token  *table = t_main;
  138     const struct token  *match;
  139 
  140     bzero(&res, sizeof(res));
  141 
  142     while (argc >= 0) {
  143         if ((match = match_token(argv[0], table)) == NULL) {
  144             fprintf(stderr, "valid commands/args:\n");
  145             show_valid_args(table);
  146             return (NULL);
  147         }
  148 
  149         argc--;
  150         argv++;
  151 
  152         if (match->type == NOTOKEN || match->next == NULL)
  153             break;
  154 
  155         table = match->next;
  156     }
  157 
  158     if (argc > 0) {
  159         fprintf(stderr, "superfluous argument: %s\n", argv[0]);
  160         return (NULL);
  161     }
  162 
  163     return (&res);
  164 }
  165 
  166 const struct token *
  167 match_token(const char *word, const struct token table[])
  168 {
  169     u_int            i, match;
  170     const struct token  *t = NULL;
  171 
  172     match = 0;
  173 
  174     for (i = 0; table[i].type != ENDTOKEN; i++) {
  175         switch (table[i].type) {
  176         case NOTOKEN:
  177             if (word == NULL || strlen(word) == 0) {
  178                 match++;
  179                 t = &table[i];
  180             }
  181             break;
  182         case KEYWORD:
  183             if (word != NULL && strncmp(word, table[i].keyword,
  184                 strlen(word)) == 0) {
  185                 match++;
  186                 t = &table[i];
  187                 if (t->value)
  188                     res.action = t->value;
  189             }
  190             break;
  191         case FLAG:
  192             if (word != NULL && strncmp(word, table[i].keyword,
  193                 strlen(word)) == 0) {
  194                 match++;
  195                 t = &table[i];
  196                 res.flags |= t->value;
  197             }
  198             break;
  199         case ADDRESS:
  200             if (parse_addr(word, &res.addr)) {
  201                 match++;
  202                 t = &table[i];
  203                 if (t->value)
  204                     res.action = t->value;
  205             }
  206             break;
  207         case PREFIX:
  208             if (parse_prefix(word, &res.addr, &res.prefixlen)) {
  209                 match++;
  210                 t = &table[i];
  211                 if (t->value)
  212                     res.action = t->value;
  213             }
  214             break;
  215         case IFNAME:
  216             if (!match && word != NULL && strlen(word) > 0) {
  217                 if (strlcpy(res.ifname, word,
  218                     sizeof(res.ifname)) >=
  219                     sizeof(res.ifname))
  220                     err(1, "interface name too long");
  221                 match++;
  222                 t = &table[i];
  223                 if (t->value)
  224                     res.action = t->value;
  225             }
  226             break;
  227 
  228         case ENDTOKEN:
  229             break;
  230         }
  231     }
  232 
  233     if (match != 1) {
  234         if (word == NULL)
  235             fprintf(stderr, "missing argument:\n");
  236         else if (match > 1)
  237             fprintf(stderr, "ambiguous argument: %s\n", word);
  238         else if (match < 1)
  239             fprintf(stderr, "unknown argument: %s\n", word);
  240         return (NULL);
  241     }
  242 
  243     return (t);
  244 }
  245 
  246 void
  247 show_valid_args(const struct token table[])
  248 {
  249     int i;
  250 
  251     for (i = 0; table[i].type != ENDTOKEN; i++) {
  252         switch (table[i].type) {
  253         case NOTOKEN:
  254             fprintf(stderr, "  <cr>\n");
  255             break;
  256         case KEYWORD:
  257         case FLAG:
  258             fprintf(stderr, "  %s\n", table[i].keyword);
  259             break;
  260         case ADDRESS:
  261             fprintf(stderr, "  <address>\n");
  262             break;
  263         case PREFIX:
  264             fprintf(stderr, "  <address>[/<len>]\n");
  265             break;
  266         case IFNAME:
  267             fprintf(stderr, "  <interface>\n");
  268             break;
  269         case ENDTOKEN:
  270             break;
  271         }
  272     }
  273 }
  274 
  275 int
  276 parse_addr(const char *word, struct in_addr *addr)
  277 {
  278     struct in_addr  ina;
  279 
  280     if (word == NULL)
  281         return (0);
  282 
  283     bzero(addr, sizeof(struct in_addr));
  284     bzero(&ina, sizeof(ina));
  285 
  286     if (inet_pton(AF_INET, word, &ina)) {
  287         addr->s_addr = ina.s_addr;
  288         return (1);
  289     }
  290 
  291     return (0);
  292 }
  293 
  294 int
  295 parse_prefix(const char *word, struct in_addr *addr, u_int8_t *prefixlen)
  296 {
  297     struct in_addr   ina;
  298     int      bits = 32;
  299 
  300     if (word == NULL)
  301         return (0);
  302 
  303     bzero(addr, sizeof(struct in_addr));
  304     bzero(&ina, sizeof(ina));
  305 
  306     if (strrchr(word, '/') != NULL) {
  307         if ((bits = inet_net_pton(AF_INET, word,
  308             &ina, sizeof(ina))) == -1)
  309             return (0);
  310         addr->s_addr = ina.s_addr & htonl(prefixlen2mask(bits));
  311         *prefixlen = bits;
  312         return (1);
  313     }
  314     *prefixlen = 32;
  315     return (parse_addr(word, addr));
  316 }
  317 
  318 /* XXX local copy from kroute.c, should go to shared file */
  319 in_addr_t
  320 prefixlen2mask(u_int8_t prefixlen)
  321 {
  322     if (prefixlen == 0)
  323         return (0);
  324 
  325     return (0xffffffff << (32 - prefixlen));
  326 }