parser.c revision 1.23
1/* $OpenBSD: parser.c,v 1.23 2010/01/11 06:40:14 jsg Exp $ */ 2 3/* 4 * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org> 5 * Copyright (c) 2004 Esben Norby <norby@openbsd.org> 6 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21#include <sys/types.h> 22#include <sys/socket.h> 23#include <sys/queue.h> 24 25#include <net/if.h> 26#include <netinet/in.h> 27#include <arpa/inet.h> 28 29#include <err.h> 30#include <errno.h> 31#include <limits.h> 32#include <stdio.h> 33#include <stdlib.h> 34#include <string.h> 35#include <event.h> 36 37#include <openssl/ssl.h> 38 39#include "relayd.h" 40 41#include "parser.h" 42 43enum token_type { 44 NOTOKEN, 45 ENDTOKEN, 46 HOSTID, 47 TABLEID, 48 RDRID, 49 KEYWORD 50}; 51 52struct token { 53 enum token_type type; 54 const char *keyword; 55 int value; 56 const struct token *next; 57}; 58 59static const struct token t_main[]; 60static const struct token t_show[]; 61static const struct token t_rdr[]; 62static const struct token t_table[]; 63static const struct token t_host[]; 64static const struct token t_rdr_id[]; 65static const struct token t_table_id[]; 66static const struct token t_host_id[]; 67static const struct token t_log[]; 68 69static const struct token t_main[] = { 70 {KEYWORD, "monitor", MONITOR, NULL}, 71 {KEYWORD, "show", NONE, t_show}, 72 {KEYWORD, "poll", POLL, NULL}, 73 {KEYWORD, "reload", RELOAD, NULL}, 74 {KEYWORD, "stop", SHUTDOWN, NULL}, 75 {KEYWORD, "redirect", NONE, t_rdr}, 76 {KEYWORD, "table", NONE, t_table}, 77 {KEYWORD, "host", NONE, t_host}, 78 {KEYWORD, "log", NONE, t_log}, 79 {ENDTOKEN, "", NONE, NULL} 80}; 81 82static const struct token t_show[] = { 83 {KEYWORD, "summary", SHOW_SUM, NULL}, 84 {KEYWORD, "hosts", SHOW_HOSTS, NULL}, 85 {KEYWORD, "redirects", SHOW_RDRS, NULL}, 86 {KEYWORD, "relays", SHOW_RELAYS, NULL}, 87 {KEYWORD, "routers", SHOW_ROUTERS, NULL}, 88 {KEYWORD, "sessions", SHOW_SESSIONS, NULL}, 89 {ENDTOKEN, "", NONE, NULL} 90}; 91 92static const struct token t_rdr[] = { 93 {NOTOKEN, "", NONE, NULL}, 94 {KEYWORD, "disable", RDR_DISABLE, t_rdr_id}, 95 {KEYWORD, "enable", RDR_ENABLE, t_rdr_id}, 96 {ENDTOKEN, "", NONE, NULL} 97}; 98 99static const struct token t_table[] = { 100 {NOTOKEN, "", NONE, NULL}, 101 {KEYWORD, "disable", TABLE_DISABLE, t_table_id}, 102 {KEYWORD, "enable", TABLE_ENABLE, t_table_id}, 103 {ENDTOKEN, "", NONE, NULL} 104}; 105 106static const struct token t_host[] = { 107 {NOTOKEN, "", NONE, NULL}, 108 {KEYWORD, "disable", HOST_DISABLE, t_host_id}, 109 {KEYWORD, "enable", HOST_ENABLE, t_host_id}, 110 {ENDTOKEN, "", NONE, NULL} 111}; 112 113static const struct token t_rdr_id[] = { 114 {RDRID, "", NONE, NULL}, 115 {ENDTOKEN, "", NONE, NULL} 116}; 117 118static const struct token t_table_id[] = { 119 {TABLEID, "", NONE, NULL}, 120 {ENDTOKEN, "", NONE, NULL} 121}; 122 123static const struct token t_host_id[] = { 124 {HOSTID, "", NONE, NULL}, 125 {ENDTOKEN, "", NONE, NULL} 126}; 127 128static const struct token t_log[] = { 129 {KEYWORD, "verbose", LOG_VERBOSE, NULL}, 130 {KEYWORD, "brief", LOG_BRIEF, NULL}, 131 {ENDTOKEN, "", NONE, NULL} 132}; 133 134static struct parse_result res; 135 136struct parse_result * 137parse(int argc, char *argv[]) 138{ 139 const struct token *table = t_main; 140 const struct token *match; 141 142 bzero(&res, sizeof(res)); 143 144 while (argc >= 0) { 145 if ((match = match_token(argv[0], table)) == NULL) { 146 fprintf(stderr, "valid commands/args:\n"); 147 show_valid_args(table); 148 return (NULL); 149 } 150 151 argc--; 152 argv++; 153 154 if (match->type == NOTOKEN || match->next == NULL) 155 break; 156 157 table = match->next; 158 } 159 160 if (argc > 0) { 161 fprintf(stderr, "superfluous argument: %s\n", argv[0]); 162 return (NULL); 163 } 164 165 return (&res); 166} 167 168const struct token * 169match_token(const char *word, const struct token *table) 170{ 171 u_int i, match; 172 const struct token *t = NULL; 173 const char *errstr; 174 175 match = 0; 176 177 for (i = 0; table[i].type != ENDTOKEN; i++) { 178 switch (table[i].type) { 179 case NOTOKEN: 180 if (word == NULL || strlen(word) == 0) { 181 match++; 182 t = &table[i]; 183 } 184 break; 185 case KEYWORD: 186 if (word != NULL && strncmp(word, table[i].keyword, 187 strlen(word)) == 0) { 188 match++; 189 t = &table[i]; 190 if (t->value) 191 res.action = t->value; 192 } 193 break; 194 case HOSTID: 195 if (word == NULL) 196 break; 197 res.id.id = strtonum(word, 0, UINT_MAX, &errstr); 198 if (errstr) { 199 strlcpy(res.id.name, word, sizeof(res.id.name)); 200 res.id.id = EMPTY_ID; 201 } 202 t = &table[i]; 203 match++; 204 break; 205 case TABLEID: 206 if (word == NULL) 207 break; 208 res.id.id = strtonum(word, 0, UINT_MAX, &errstr); 209 if (errstr) { 210 strlcpy(res.id.name, word, sizeof(res.id.name)); 211 res.id.id = EMPTY_ID; 212 } 213 t = &table[i]; 214 match++; 215 break; 216 case RDRID: 217 if (word == NULL) 218 break; 219 res.id.id = strtonum(word, 0, UINT_MAX, &errstr); 220 if (errstr) { 221 strlcpy(res.id.name, word, sizeof(res.id.name)); 222 res.id.id = EMPTY_ID; 223 } 224 t = &table[i]; 225 match++; 226 break; 227 case ENDTOKEN: 228 break; 229 } 230 } 231 232 if (match != 1) { 233 if (word == NULL) 234 fprintf(stderr, "missing argument:\n"); 235 else if (match > 1) 236 fprintf(stderr, "ambiguous argument: %s\n", word); 237 else if (match < 1) 238 fprintf(stderr, "unknown argument: %s\n", word); 239 return (NULL); 240 } 241 242 return (t); 243} 244 245void 246show_valid_args(const struct token *table) 247{ 248 int i; 249 250 for (i = 0; table[i].type != ENDTOKEN; i++) { 251 switch (table[i].type) { 252 case NOTOKEN: 253 fprintf(stderr, " <cr>\n"); 254 break; 255 case KEYWORD: 256 fprintf(stderr, " %s\n", table[i].keyword); 257 break; 258 case RDRID: 259 fprintf(stderr, " <redirectid>\n"); 260 break; 261 case TABLEID: 262 fprintf(stderr, " <tableid>\n"); 263 break; 264 case HOSTID: 265 fprintf(stderr, " <hostid>\n"); 266 break; 267 case ENDTOKEN: 268 break; 269 } 270 } 271} 272