static const struct token * match_token(const char *word, const struct token *table, struct parse_result *res) { unsigned int i, match; const struct token *t = NULL; match = 0; for (i = 0; table[i].type != ENDTOKEN; i++) { switch (table[i].type) { case NOTOKEN: if (word == NULL || strlen(word) == 0) { match++; t = &table[i]; } break; case KEYWORD: if (word != NULL && strncmp(word, table[i].keyword, strlen(word)) == 0) { match++; t = &table[i]; if (t->value) res->action = t->value; } break; case FLAG: if (word != NULL && strncmp(word, table[i].keyword, strlen(word)) == 0) { match++; t = &table[i]; res->flags |= t->value; } break; case FAMILY: if (word == NULL) break; if (!strcmp(word, "inet") || !strcasecmp(word, "IPv4")) { match++; t = &table[i]; res->family = AF_INET; } if (!strcmp(word, "inet6") || !strcasecmp(word, "IPv6")) { match++; t = &table[i]; res->family = AF_INET6; } break; case ASNUM: if (parse_asnum(word, &res->as)) { match++; t = &table[i]; } break; case ADDRESS: if (parse_addr(word, &res->family, &res->addr)) { match++; t = &table[i]; if (t->value) res->action = t->value; } break; case PREFIX: if (parse_prefix(word, &res->family, &res->addr, &res->prefixlen)) { match++; t = &table[i]; if (t->value) res->action = t->value; } break; case IFNAME: if (!match && word != NULL && strlen(word) > 0) { if (strlcpy(res->ifname, word, sizeof(res->ifname)) >= sizeof(res->ifname)) err(1, "interface name too long"); match++; t = &table[i]; if (t->value) res->action = t->value; } break; case ENDTOKEN: break; } } if (match != 1) { if (word == NULL) fprintf(stderr, "missing argument:\n"); else if (match > 1) fprintf(stderr, "ambiguous argument: %s\n", word); else if (match < 1) fprintf(stderr, "unknown argument: %s\n", word); return (NULL); } return (t); }
const struct token * match_token(int *argc, char **argv[], const struct token table[]) { u_int i, match; const struct token *t = NULL; struct filter_set *fs; const char *word = *argv[0]; match = 0; for (i = 0; table[i].type != ENDTOKEN; i++) { switch (table[i].type) { case NOTOKEN: if (word == NULL || strlen(word) == 0) { match++; t = &table[i]; } break; case KEYWORD: if (word != NULL && strncmp(word, table[i].keyword, strlen(word)) == 0) { match++; t = &table[i]; if (t->value) res.action = t->value; } break; case FLAG: if (word != NULL && strncmp(word, table[i].keyword, strlen(word)) == 0) { match++; t = &table[i]; res.flags |= t->value; } break; case FAMILY: if (word == NULL) break; if (!strcmp(word, "inet") || !strcasecmp(word, "IPv4")) { match++; t = &table[i]; res.aid = AID_INET; } if (!strcmp(word, "inet6") || !strcasecmp(word, "IPv6")) { match++; t = &table[i]; res.aid = AID_INET6; } if (!strcasecmp(word, "VPNv4")) { match++; t = &table[i]; res.aid = AID_VPN_IPv4; } break; case ADDRESS: if (parse_addr(word, &res.addr)) { match++; t = &table[i]; if (t->value) res.action = t->value; } break; case PEERADDRESS: if (parse_addr(word, &res.peeraddr)) { match++; t = &table[i]; if (t->value) res.action = t->value; } break; case PREFIX: if (parse_prefix(word, &res.addr, &res.prefixlen)) { match++; t = &table[i]; if (t->value) res.action = t->value; } break; case ASTYPE: if (word != NULL && strncmp(word, table[i].keyword, strlen(word)) == 0) { match++; t = &table[i]; res.as.type = t->value; } break; case ASNUM: if (parse_asnum(word, &res.as.as)) { match++; t = &table[i]; } break; case PEERDESC: if (!match && word != NULL && strlen(word) > 0) { if (strlcpy(res.peerdesc, word, sizeof(res.peerdesc)) >= sizeof(res.peerdesc)) errx(1, "neighbor description too " "long"); match++; t = &table[i]; } break; case RIBNAME: if (!match && word != NULL && strlen(word) > 0) { if (strlcpy(res.rib, word, sizeof(res.rib)) >= sizeof(res.rib)) errx(1, "rib name too long"); match++; t = &table[i]; } break; case COMMUNITY: if (word != NULL && strlen(word) > 0 && parse_community(word, &res)) { match++; t = &table[i]; } break; case LOCALPREF: case MED: case PREPNBR: case PREPSELF: case WEIGHT: case RTABLE: if (word != NULL && strlen(word) > 0 && parse_number(word, &res, table[i].type)) { match++; t = &table[i]; } break; case NEXTHOP: if (word != NULL && strlen(word) > 0 && parse_nexthop(word, &res)) { match++; t = &table[i]; } break; case PFTABLE: if (word != NULL && strlen(word) > 0) { if ((fs = calloc(1, sizeof(struct filter_set))) == NULL) err(1, NULL); if (strlcpy(fs->action.pftable, word, sizeof(fs->action.pftable)) >= sizeof(fs->action.pftable)) errx(1, "pftable name too long"); TAILQ_INSERT_TAIL(&res.set, fs, entry); match++; t = &table[i]; } break; case GETOPT: if (bgpctl_getopt(argc, argv, table[i].value)) { match++; t = &table[i]; } break; case FILENAME: if (word != NULL && strlen(word) > 0) { if ((res.mrtfd = open(word, O_RDONLY)) == -1) { /* * ignore error if path has no / and * does not exist. In hope to print * usage. */ if (errno == ENOENT && !strchr(word, '/')) break; err(1, "mrt open(%s)", word); } match++; t = &table[i]; } break; case ENDTOKEN: break; } } if (match != 1) { if (word == NULL) fprintf(stderr, "missing argument:\n"); else if (match > 1) fprintf(stderr, "ambiguous argument: %s\n", word); else if (match < 1) fprintf(stderr, "unknown argument: %s\n", word); return (NULL); } return (t); }