parser.c revision 1.14
1289467Scem/* $OpenBSD: parser.c,v 1.14 2007/10/19 12:08:55 pyr Exp $ */ 2289467Scem 3289467Scem/* 4289467Scem * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org> 5289467Scem * Copyright (c) 2004 Esben Norby <norby@openbsd.org> 6289467Scem * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 7289467Scem * 8289467Scem * Permission to use, copy, modify, and distribute this software for any 9289467Scem * purpose with or without fee is hereby granted, provided that the above 10289467Scem * copyright notice and this permission notice appear in all copies. 11289467Scem * 12289467Scem * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13289467Scem * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14289467Scem * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15289467Scem * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16289467Scem * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17289467Scem * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18289467Scem * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19289467Scem */ 20289467Scem 21289467Scem#include <sys/types.h> 22289467Scem#include <sys/socket.h> 23289467Scem#include <sys/queue.h> 24289467Scem#include <netinet/in.h> 25289467Scem#include <net/if.h> 26289467Scem#include <arpa/inet.h> 27320939Skib#include <err.h> 28289467Scem#include <errno.h> 29289467Scem#include <limits.h> 30289467Scem#include <stdio.h> 31289467Scem#include <stdlib.h> 32289467Scem#include <string.h> 33289467Scem#include <event.h> 34289467Scem 35289467Scem#include <openssl/ssl.h> 36289467Scem 37289467Scem#include "hoststated.h" 38289467Scem 39289467Scem#include "parser.h" 40289467Scem 41289467Scemenum token_type { 42289467Scem NOTOKEN, 43289467Scem ENDTOKEN, 44289467Scem HOSTID, 45289467Scem TABLEID, 46320939Skib SERVICEID, 47289467Scem KEYWORD 48289467Scem}; 49289467Scem 50289467Scemstruct token { 51289467Scem enum token_type type; 52319650Skib const char *keyword; 53289467Scem int value; 54319650Skib const struct token *next; 55289467Scem}; 56319650Skib 57319650Skibstatic const struct token t_main[]; 58319650Skibstatic const struct token t_show[]; 59289467Scemstatic const struct token t_service[]; 60289467Scemstatic const struct token t_table[]; 61289467Scemstatic const struct token t_host[]; 62289467Scemstatic const struct token t_service_id[]; 63289467Scemstatic const struct token t_table_id[]; 64289467Scemstatic const struct token t_host_id[]; 65289467Scem 66289467Scemstatic const struct token t_main[] = { 67289467Scem {KEYWORD, "monitor", MONITOR, NULL}, 68289467Scem {KEYWORD, "show", NULL, t_show}, 69289467Scem {KEYWORD, "poll", POLL, NULL}, 70289467Scem {KEYWORD, "reload", RELOAD, NULL}, 71289467Scem {KEYWORD, "stop", SHUTDOWN, NULL}, 72289467Scem {KEYWORD, "service", NONE, t_service}, 73289467Scem {KEYWORD, "table", NONE, t_table}, 74289467Scem {KEYWORD, "host", NONE, t_host}, 75289467Scem {ENDTOKEN, "", NONE, NULL} 76289467Scem}; 77289467Scem 78289467Scemstatic const struct token t_show[] = { 79289467Scem {KEYWORD, "summary", SHOW_SUM, NULL}, 80289467Scem {KEYWORD, "hosts", SHOW_HOSTS, NULL}, 81289467Scem {KEYWORD, "relays", SHOW_RELAYS, NULL}, 82289467Scem {KEYWORD, "sessions", SHOW_SESSIONS, NULL}, 83289467Scem {ENDTOKEN, "", NONE, NULL} 84289467Scem}; 85289467Scem 86303620Svangyzenstatic const struct token t_service[] = { 87289467Scem {NOTOKEN, "", NONE, NULL}, 88303620Svangyzen {KEYWORD, "disable", SERV_DISABLE, t_service_id}, 89320939Skib {KEYWORD, "enable", SERV_ENABLE, t_service_id}, 90320939Skib {ENDTOKEN, "", NONE, NULL} 91289467Scem}; 92289467Scem 93289467Scemstatic const struct token t_table[] = { 94289467Scem {NOTOKEN, "", NONE, NULL}, 95289467Scem {KEYWORD, "disable", TABLE_DISABLE, t_table_id}, 96289467Scem {KEYWORD, "enable", TABLE_ENABLE, t_table_id}, 97289467Scem {ENDTOKEN, "", NONE, NULL} 98289467Scem}; 99289467Scem 100289467Scemstatic const struct token t_host[] = { 101289467Scem {NOTOKEN, "", NONE, NULL}, 102289467Scem {KEYWORD, "disable", HOST_DISABLE, t_host_id}, 103289467Scem {KEYWORD, "enable", HOST_ENABLE, t_host_id}, 104289467Scem {ENDTOKEN, "", NONE, NULL} 105289467Scem}; 106319650Skib 107319650Skibstatic const struct token t_service_id[] = { 108319650Skib {SERVICEID, "", NONE, NULL}, 109319650Skib {ENDTOKEN, "", NONE, NULL} 110319650Skib}; 111319650Skib 112289467Scemstatic const struct token t_table_id[] = { 113319650Skib {TABLEID, "", NONE, NULL}, 114319650Skib {ENDTOKEN, "", NONE, NULL} 115319650Skib}; 116319650Skib 117319650Skibstatic const struct token t_host_id[] = { 118319650Skib {HOSTID, "", NONE, NULL}, 119289467Scem {ENDTOKEN, "", NONE, NULL} 120319650Skib}; 121319650Skib 122319650Skibstatic struct parse_result res; 123319650Skib 124319650Skibstruct parse_result * 125319650Skibparse(int argc, char *argv[]) 126319650Skib{ 127319650Skib const struct token *table = t_main; 128319650Skib const struct token *match; 129319650Skib 130319650Skib bzero(&res, sizeof(res)); 131319650Skib 132319650Skib while (argc >= 0) { 133289467Scem if ((match = match_token(argv[0], table)) == NULL) { 134289467Scem fprintf(stderr, "valid commands/args:\n"); 135289467Scem show_valid_args(table); 136289467Scem return (NULL); 137289467Scem } 138289467Scem 139289467Scem argc--; 140289467Scem argv++; 141289467Scem 142289467Scem if (match->type == NOTOKEN || match->next == NULL) 143289467Scem break; 144289467Scem 145289467Scem table = match->next; 146289467Scem } 147289467Scem 148289467Scem if (argc > 0) { 149289467Scem fprintf(stderr, "superfluous argument: %s\n", argv[0]); 150289467Scem return (NULL); 151289467Scem } 152289467Scem 153289467Scem return (&res); 154289467Scem} 155289467Scem 156289467Scemconst struct token * 157289467Scemmatch_token(const char *word, const struct token table[]) 158289467Scem{ 159289467Scem u_int i, match; 160289467Scem const struct token *t = NULL; 161289467Scem const char *errstr; 162289467Scem 163289467Scem match = 0; 164289467Scem 165289467Scem for (i = 0; table[i].type != ENDTOKEN; i++) { 166289467Scem switch (table[i].type) { 167289467Scem case NOTOKEN: 168289467Scem if (word == NULL || strlen(word) == 0) { 169289467Scem match++; 170289467Scem t = &table[i]; 171289467Scem } 172289467Scem break; 173289467Scem case KEYWORD: 174289467Scem if (word != NULL && strncmp(word, table[i].keyword, 175289467Scem strlen(word)) == 0) { 176289467Scem match++; 177289467Scem t = &table[i]; 178289467Scem if (t->value) 179289467Scem res.action = t->value; 180289467Scem } 181289467Scem break; 182289467Scem case HOSTID: 183289467Scem if (word == NULL) 184289467Scem break; 185289467Scem res.id.id = strtonum(word, 0, UINT_MAX, &errstr); 186289467Scem if (errstr) { 187289467Scem strlcpy(res.id.name, word, sizeof(res.id.name)); 188289467Scem res.id.id = EMPTY_ID; 189289467Scem } 190289467Scem t = &table[i]; 191289467Scem match++; 192289467Scem break; 193289467Scem case TABLEID: 194289467Scem if (word == NULL) 195289467Scem break; 196289467Scem res.id.id = strtonum(word, 0, UINT_MAX, &errstr); 197289467Scem if (errstr) { 198289467Scem strlcpy(res.id.name, word, sizeof(res.id.name)); 199289467Scem res.id.id = EMPTY_ID; 200289467Scem } 201289467Scem t = &table[i]; 202289467Scem match++; 203289467Scem break; 204289467Scem case SERVICEID: 205289467Scem if (word == NULL) 206289467Scem break; 207289467Scem res.id.id = strtonum(word, 0, UINT_MAX, &errstr); 208289467Scem if (errstr) { 209289467Scem strlcpy(res.id.name, word, sizeof(res.id.name)); 210289467Scem res.id.id = EMPTY_ID; 211289467Scem } 212289467Scem t = &table[i]; 213289467Scem match++; 214289467Scem break; 215289467Scem case ENDTOKEN: 216289467Scem break; 217289467Scem } 218289467Scem } 219289467Scem 220289467Scem if (match != 1) { 221289467Scem if (word == NULL) 222289467Scem fprintf(stderr, "missing argument:\n"); 223289467Scem else if (match > 1) 224289467Scem fprintf(stderr, "ambiguous argument: %s\n", word); 225289467Scem else if (match < 1) 226289467Scem fprintf(stderr, "unknown argument: %s\n", word); 227289467Scem return (NULL); 228289467Scem } 229289467Scem 230289467Scem return (t); 231289467Scem} 232289467Scem 233289467Scemvoid 234289467Scemshow_valid_args(const struct token table[]) 235289467Scem{ 236289467Scem int i; 237289467Scem 238289467Scem for (i = 0; table[i].type != ENDTOKEN; i++) { 239289467Scem switch (table[i].type) { 240289467Scem case NOTOKEN: 241289467Scem fprintf(stderr, " <cr>\n"); 242289467Scem break; 243289467Scem case KEYWORD: 244289467Scem fprintf(stderr, " %s\n", table[i].keyword); 245289467Scem break; 246289467Scem case SERVICEID: 247289467Scem fprintf(stderr, " <serviceid>\n"); 248289467Scem break; 249289467Scem case TABLEID: 250289467Scem fprintf(stderr, " <tableid>\n"); 251289467Scem break; 252289467Scem case HOSTID: 253289467Scem fprintf(stderr, " <hostid>\n"); 254289467Scem break; 255289467Scem case ENDTOKEN: 256289467Scem break; 257289467Scem } 258289467Scem } 259289467Scem} 260289467Scem