1 1.1 christos /* $NetBSD: conflex.c,v 1.3 2022/04/03 01:10:59 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.3 christos * Copyright (C) 2017-2022 Internet Systems Consortium, Inc. ("ISC") 5 1.1 christos * 6 1.1 christos * Permission to use, copy, modify, and distribute this software for any 7 1.1 christos * purpose with or without fee is hereby granted, provided that the above 8 1.1 christos * copyright notice and this permission notice appear in all copies. 9 1.1 christos * 10 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 11 1.1 christos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 1.1 christos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 13 1.1 christos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 1.1 christos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 1.1 christos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 1.1 christos * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 1.1 christos * 18 1.1 christos * Internet Systems Consortium, Inc. 19 1.3 christos * PO Box 360 20 1.3 christos * Newmarket, NH 03857 USA 21 1.1 christos * <info (at) isc.org> 22 1.1 christos * https://www.isc.org/ 23 1.1 christos * 24 1.1 christos */ 25 1.1 christos 26 1.1 christos #include <sys/cdefs.h> 27 1.1 christos __RCSID("$NetBSD: conflex.c,v 1.3 2022/04/03 01:10:59 christos Exp $"); 28 1.1 christos 29 1.1 christos /* From common/conflex.c */ 30 1.1 christos 31 1.1 christos #include "keama.h" 32 1.1 christos 33 1.1 christos #include <sys/types.h> 34 1.1 christos #include <sys/stat.h> 35 1.1 christos #include <sys/mman.h> 36 1.1 christos #include <assert.h> 37 1.1 christos #include <ctype.h> 38 1.1 christos #include <fcntl.h> 39 1.1 christos #include <stdlib.h> 40 1.1 christos #include <string.h> 41 1.1 christos #include <unistd.h> 42 1.1 christos 43 1.1 christos static int get_char(struct parse *); 44 1.1 christos static void unget_char(struct parse *, int); 45 1.1 christos static void skip_to_eol(struct parse *); 46 1.1 christos static enum dhcp_token read_whitespace(int c, struct parse *cfile); 47 1.1 christos static enum dhcp_token read_string(struct parse *); 48 1.1 christos static enum dhcp_token read_number(int, struct parse *); 49 1.1 christos static enum dhcp_token read_num_or_name(int, struct parse *); 50 1.1 christos static enum dhcp_token intern(char *, enum dhcp_token); 51 1.1 christos 52 1.1 christos struct parse * 53 1.1 christos new_parse(int file, char *inbuf, size_t buflen, const char *name, int eolp) 54 1.1 christos { 55 1.1 christos struct parse *tmp; 56 1.1 christos 57 1.1 christos tmp = (struct parse *)malloc(sizeof(struct parse)); 58 1.1 christos assert(tmp != NULL); 59 1.1 christos memset(tmp, 0, sizeof(struct parse)); 60 1.1 christos 61 1.1 christos TAILQ_INSERT_TAIL(&parses, tmp); 62 1.1 christos 63 1.1 christos tmp->tlname = name; 64 1.1 christos tmp->lpos = tmp->line = 1; 65 1.1 christos tmp->cur_line = tmp->line1; 66 1.1 christos tmp->prev_line = tmp->line2; 67 1.1 christos tmp->token_line = tmp->cur_line; 68 1.1 christos tmp->cur_line[0] = tmp->prev_line[0] = 0; 69 1.1 christos tmp->file = file; 70 1.1 christos tmp->eol_token = eolp; 71 1.1 christos TAILQ_INIT(&tmp->comments); 72 1.1 christos 73 1.1 christos if (inbuf != NULL) { 74 1.1 christos tmp->inbuf = inbuf; 75 1.1 christos tmp->buflen = buflen; 76 1.1 christos tmp->bufsiz = 0; 77 1.1 christos } else { 78 1.1 christos struct stat sb; 79 1.1 christos 80 1.1 christos if (fstat(file, &sb) < 0) { 81 1.1 christos fprintf(stderr, "can't stat input\n"); 82 1.1 christos exit(1); 83 1.1 christos } 84 1.1 christos 85 1.1 christos if (sb.st_size == 0) 86 1.1 christos return tmp; 87 1.1 christos 88 1.1 christos tmp->bufsiz = tmp->buflen = (size_t) sb.st_size; 89 1.1 christos tmp->inbuf = mmap(NULL, tmp->bufsiz, PROT_READ, MAP_SHARED, 90 1.1 christos file, 0); 91 1.1 christos 92 1.1 christos if (tmp->inbuf == MAP_FAILED) { 93 1.1 christos fprintf(stderr, "can't map input\n"); 94 1.1 christos exit(1); 95 1.1 christos } 96 1.1 christos } 97 1.1 christos 98 1.1 christos return tmp; 99 1.1 christos } 100 1.1 christos 101 1.1 christos void 102 1.1 christos end_parse(struct parse *cfile) 103 1.1 christos { 104 1.1 christos /* "Memory" config files have no file. */ 105 1.1 christos if (cfile->file != -1) { 106 1.1 christos munmap(cfile->inbuf, cfile->bufsiz); 107 1.1 christos close(cfile->file); 108 1.1 christos } 109 1.1 christos 110 1.1 christos while (TAILQ_NEXT(cfile) != NULL) { 111 1.1 christos struct parse *saved_state; 112 1.1 christos 113 1.1 christos saved_state = TAILQ_NEXT(cfile); 114 1.1 christos TAILQ_REMOVE(&parses, saved_state); 115 1.1 christos free(saved_state); 116 1.1 christos } 117 1.1 christos 118 1.1 christos cfile->stack_size = 0; 119 1.1 christos if (cfile->stack != NULL) 120 1.1 christos free(cfile->stack); 121 1.1 christos cfile->stack = NULL; 122 1.1 christos TAILQ_REMOVE(&parses, cfile); 123 1.1 christos free(cfile); 124 1.1 christos } 125 1.1 christos 126 1.1 christos /* 127 1.1 christos * Save the current state of the parser. 128 1.1 christos * 129 1.1 christos * Only one state may be saved. Any previous saved state is 130 1.1 christos * lost. 131 1.1 christos */ 132 1.1 christos void 133 1.1 christos save_parse_state(struct parse *cfile) { 134 1.1 christos struct parse *tmp; 135 1.1 christos 136 1.1 christos /* 137 1.1 christos * Free any previous saved states. 138 1.1 christos */ 139 1.1 christos while (TAILQ_NEXT(cfile) != NULL) { 140 1.1 christos struct parse *saved_state; 141 1.1 christos 142 1.1 christos saved_state = TAILQ_NEXT(cfile); 143 1.1 christos TAILQ_REMOVE(&parses, saved_state); 144 1.1 christos free(saved_state); 145 1.1 christos } 146 1.1 christos 147 1.1 christos /* 148 1.1 christos * Save our current state. 149 1.1 christos */ 150 1.1 christos tmp = (struct parse *)malloc(sizeof(struct parse)); 151 1.1 christos if (tmp == NULL) 152 1.1 christos parse_error(cfile, "can't allocate state to be saved"); 153 1.1 christos memset(tmp, 0, sizeof(struct parse)); 154 1.1 christos /* save up to comments field */ 155 1.1 christos memcpy(tmp, cfile, (size_t)&(((struct parse *)0)->comments)); 156 1.1 christos TAILQ_INSERT_AFTER(&parses, cfile, tmp); 157 1.1 christos } 158 1.1 christos 159 1.1 christos /* 160 1.1 christos * Return the parser to the previous saved state. 161 1.1 christos * 162 1.1 christos * You must call save_parse_state() every time before calling 163 1.1 christos * restore_parse_state(). 164 1.1 christos */ 165 1.1 christos void 166 1.1 christos restore_parse_state(struct parse *cfile) { 167 1.1 christos struct parse *saved_state; 168 1.1 christos 169 1.1 christos if (TAILQ_NEXT(cfile) == NULL) 170 1.1 christos parse_error(cfile, "can't find saved state"); 171 1.1 christos 172 1.1 christos saved_state = TAILQ_NEXT(cfile); 173 1.1 christos TAILQ_REMOVE(&parses, saved_state); 174 1.1 christos /* restore up to comments field */ 175 1.1 christos memcpy(cfile, saved_state, (size_t)&(((struct parse *)0)->comments)); 176 1.1 christos free(saved_state); 177 1.1 christos } 178 1.1 christos 179 1.1 christos static int 180 1.1 christos get_char(struct parse *cfile) 181 1.1 christos { 182 1.1 christos /* My kingdom for WITH... */ 183 1.1 christos int c; 184 1.1 christos 185 1.1 christos if (cfile->bufix == cfile->buflen) { 186 1.1 christos c = EOF; 187 1.1 christos } else { 188 1.1 christos c = cfile->inbuf[cfile->bufix]; 189 1.1 christos cfile->bufix++; 190 1.1 christos } 191 1.1 christos 192 1.1 christos if (!cfile->ugflag) { 193 1.1 christos if (c == EOL) { 194 1.3 christos if (cfile->cur_line == cfile->line1) { 195 1.1 christos cfile->cur_line = cfile->line2; 196 1.1 christos cfile->prev_line = cfile->line1; 197 1.1 christos } else { 198 1.1 christos cfile->cur_line = cfile->line1; 199 1.1 christos cfile->prev_line = cfile->line2; 200 1.1 christos } 201 1.1 christos cfile->line++; 202 1.1 christos cfile->lpos = 1; 203 1.1 christos cfile->cur_line[0] = 0; 204 1.1 christos } else if (c != EOF) { 205 1.1 christos if (cfile->lpos <= 80) { 206 1.1 christos cfile->cur_line[cfile->lpos - 1] = c; 207 1.1 christos cfile->cur_line[cfile->lpos] = 0; 208 1.1 christos } 209 1.1 christos cfile->lpos++; 210 1.1 christos } 211 1.1 christos } else 212 1.1 christos cfile->ugflag = 0; 213 1.1 christos return c; 214 1.1 christos } 215 1.1 christos 216 1.1 christos /* 217 1.1 christos * Return a character to our input buffer. 218 1.1 christos */ 219 1.1 christos static void 220 1.1 christos unget_char(struct parse *cfile, int c) { 221 1.1 christos if (c != EOF) { 222 1.1 christos cfile->bufix--; 223 1.1 christos cfile->ugflag = 1; /* do not put characters into 224 1.1 christos our error buffer on the next 225 1.1 christos call to get_char() */ 226 1.1 christos } 227 1.1 christos } 228 1.1 christos 229 1.1 christos /* 230 1.1 christos * GENERAL NOTE ABOUT TOKENS 231 1.1 christos * 232 1.3 christos * We normally only want non-whitespace tokens. There are some 233 1.1 christos * circumstances where we *do* want to see whitespace (for example 234 1.1 christos * when parsing IPv6 addresses). 235 1.1 christos * 236 1.3 christos * Generally we use the next_token() function to read tokens. This 237 1.1 christos * in turn calls get_next_token, which does *not* return tokens for 238 1.1 christos * whitespace. Rather, it skips these. 239 1.1 christos * 240 1.1 christos * When we need to see whitespace, we us next_raw_token(), which also 241 1.1 christos * returns the WHITESPACE token. 242 1.1 christos * 243 1.1 christos * The peek_token() and peek_raw_token() functions work as expected. 244 1.1 christos * 245 1.1 christos * Warning: if you invoke peek_token(), then if there is a whitespace 246 1.1 christos * token, it will be lost, and subsequent use of next_raw_token() or 247 1.1 christos * peek_raw_token() will NOT see it. 248 1.1 christos */ 249 1.1 christos 250 1.1 christos static enum dhcp_token 251 1.1 christos get_raw_token(struct parse *cfile) { 252 1.1 christos int c; 253 1.1 christos enum dhcp_token ttok; 254 1.1 christos static char tb[2]; 255 1.1 christos int l, p; 256 1.1 christos 257 1.1 christos for (;;) { 258 1.1 christos l = cfile->line; 259 1.1 christos p = cfile->lpos; 260 1.1 christos 261 1.1 christos c = get_char(cfile); 262 1.3 christos if (!((c == '\n') && cfile->eol_token) && 263 1.1 christos isascii(c) && isspace(c)) { 264 1.1 christos ttok = read_whitespace(c, cfile); 265 1.1 christos break; 266 1.1 christos } 267 1.1 christos if (c == '#') { 268 1.1 christos skip_to_eol(cfile); 269 1.1 christos continue; 270 1.1 christos } 271 1.1 christos if (c == '"') { 272 1.1 christos cfile->lexline = l; 273 1.1 christos cfile->lexchar = p; 274 1.1 christos ttok = read_string(cfile); 275 1.1 christos break; 276 1.1 christos } 277 1.1 christos if ((isascii(c) && isdigit(c)) || c == '-') { 278 1.1 christos cfile->lexline = l; 279 1.1 christos cfile->lexchar = p; 280 1.1 christos ttok = read_number(c, cfile); 281 1.1 christos break; 282 1.1 christos } else if (isascii(c) && isalpha(c)) { 283 1.1 christos cfile->lexline = l; 284 1.1 christos cfile->lexchar = p; 285 1.1 christos ttok = read_num_or_name(c, cfile); 286 1.1 christos break; 287 1.1 christos } else if (c == EOF) { 288 1.1 christos ttok = END_OF_FILE; 289 1.1 christos cfile->tlen = 0; 290 1.1 christos break; 291 1.1 christos } else { 292 1.1 christos cfile->lexline = l; 293 1.1 christos cfile->lexchar = p; 294 1.1 christos tb[0] = c; 295 1.1 christos tb[1] = 0; 296 1.1 christos cfile->tval = tb; 297 1.1 christos cfile->tlen = 1; 298 1.1 christos ttok = c; 299 1.1 christos break; 300 1.1 christos } 301 1.1 christos } 302 1.1 christos return ttok; 303 1.1 christos } 304 1.1 christos 305 1.1 christos /* 306 1.1 christos * The get_next_token() function consumes the next token and 307 1.1 christos * returns it to the caller. 308 1.1 christos * 309 1.3 christos * Since the code is almost the same for "normal" and "raw" 310 1.1 christos * input, we pass a flag to alter the way it works. 311 1.1 christos */ 312 1.1 christos 313 1.3 christos static enum dhcp_token 314 1.3 christos get_next_token(const char **rval, unsigned *rlen, 315 1.1 christos struct parse *cfile, isc_boolean_t raw) { 316 1.1 christos int rv; 317 1.1 christos 318 1.1 christos if (cfile->token) { 319 1.1 christos if (cfile->lexline != cfile->tline) 320 1.1 christos cfile->token_line = cfile->cur_line; 321 1.1 christos cfile->lexchar = cfile->tlpos; 322 1.1 christos cfile->lexline = cfile->tline; 323 1.1 christos rv = cfile->token; 324 1.1 christos cfile->token = 0; 325 1.1 christos } else { 326 1.1 christos rv = get_raw_token(cfile); 327 1.1 christos cfile->token_line = cfile->cur_line; 328 1.1 christos } 329 1.1 christos 330 1.1 christos if (!raw) { 331 1.1 christos while (rv == WHITESPACE) { 332 1.1 christos rv = get_raw_token(cfile); 333 1.1 christos cfile->token_line = cfile->cur_line; 334 1.1 christos } 335 1.1 christos } 336 1.3 christos 337 1.1 christos if (rval) 338 1.1 christos *rval = cfile->tval; 339 1.1 christos if (rlen) 340 1.1 christos *rlen = cfile->tlen; 341 1.1 christos return rv; 342 1.1 christos } 343 1.1 christos 344 1.1 christos /* 345 1.1 christos * Get the next token from cfile and return it. 346 1.1 christos * 347 1.3 christos * If rval is non-NULL, set the pointer it contains to 348 1.1 christos * the contents of the token. 349 1.1 christos * 350 1.3 christos * If rlen is non-NULL, set the integer it contains to 351 1.1 christos * the length of the token. 352 1.1 christos */ 353 1.1 christos 354 1.1 christos enum dhcp_token 355 1.1 christos next_token(const char **rval, unsigned *rlen, struct parse *cfile) { 356 1.1 christos return get_next_token(rval, rlen, cfile, ISC_FALSE); 357 1.1 christos } 358 1.1 christos 359 1.1 christos 360 1.1 christos /* 361 1.1 christos * The same as the next_token() function above, but will return space 362 1.1 christos * as the WHITESPACE token. 363 1.1 christos */ 364 1.1 christos 365 1.1 christos enum dhcp_token 366 1.1 christos next_raw_token(const char **rval, unsigned *rlen, struct parse *cfile) { 367 1.1 christos return get_next_token(rval, rlen, cfile, ISC_TRUE); 368 1.1 christos } 369 1.1 christos 370 1.1 christos 371 1.1 christos /* 372 1.1 christos * The do_peek_token() function checks the next token without 373 1.1 christos * consuming it, and returns it to the caller. 374 1.1 christos * 375 1.3 christos * Since the code is almost the same for "normal" and "raw" 376 1.3 christos * input, we pass a flag to alter the way it works. (See the 377 1.1 christos * warning in the GENERAL NOTES ABOUT TOKENS above though.) 378 1.1 christos */ 379 1.1 christos 380 1.1 christos enum dhcp_token 381 1.1 christos do_peek_token(const char **rval, unsigned int *rlen, 382 1.1 christos struct parse *cfile, isc_boolean_t raw) { 383 1.1 christos int x; 384 1.1 christos 385 1.1 christos if (!cfile->token || (!raw && (cfile->token == WHITESPACE))) { 386 1.1 christos cfile->tlpos = cfile->lexchar; 387 1.1 christos cfile->tline = cfile->lexline; 388 1.1 christos 389 1.1 christos do { 390 1.1 christos cfile->token = get_raw_token(cfile); 391 1.1 christos } while (!raw && (cfile->token == WHITESPACE)); 392 1.1 christos 393 1.1 christos if (cfile->lexline != cfile->tline) 394 1.1 christos cfile->token_line = cfile->prev_line; 395 1.1 christos 396 1.1 christos x = cfile->lexchar; 397 1.1 christos cfile->lexchar = cfile->tlpos; 398 1.1 christos cfile->tlpos = x; 399 1.1 christos 400 1.1 christos x = cfile->lexline; 401 1.1 christos cfile->lexline = cfile->tline; 402 1.1 christos cfile->tline = x; 403 1.1 christos } 404 1.1 christos if (rval) 405 1.1 christos *rval = cfile->tval; 406 1.1 christos if (rlen) 407 1.1 christos *rlen = cfile->tlen; 408 1.1 christos return cfile->token; 409 1.1 christos } 410 1.1 christos 411 1.1 christos 412 1.1 christos /* 413 1.3 christos * Get the next token from cfile and return it, leaving it for a 414 1.1 christos * subsequent call to next_token(). 415 1.1 christos * 416 1.1 christos * Note that it WILL consume whitespace tokens. 417 1.1 christos * 418 1.3 christos * If rval is non-NULL, set the pointer it contains to 419 1.1 christos * the contents of the token. 420 1.1 christos * 421 1.3 christos * If rlen is non-NULL, set the integer it contains to 422 1.1 christos * the length of the token. 423 1.1 christos */ 424 1.1 christos 425 1.1 christos enum dhcp_token 426 1.1 christos peek_token(const char **rval, unsigned *rlen, struct parse *cfile) { 427 1.1 christos return do_peek_token(rval, rlen, cfile, ISC_FALSE); 428 1.1 christos } 429 1.1 christos 430 1.1 christos 431 1.1 christos /* 432 1.1 christos * The same as the peek_token() function above, but will return space 433 1.1 christos * as the WHITESPACE token. 434 1.1 christos */ 435 1.1 christos 436 1.1 christos enum dhcp_token 437 1.1 christos peek_raw_token(const char **rval, unsigned *rlen, struct parse *cfile) { 438 1.1 christos return do_peek_token(rval, rlen, cfile, ISC_TRUE); 439 1.1 christos } 440 1.1 christos 441 1.1 christos /* 442 1.1 christos * The comment up to but not including EOL is saved. 443 1.1 christos */ 444 1.1 christos 445 1.1 christos static void 446 1.1 christos skip_to_eol(struct parse *cfile) 447 1.1 christos { 448 1.1 christos char buf[128]; 449 1.1 christos unsigned cc = 0; 450 1.1 christos struct comment *comment; 451 1.1 christos 452 1.1 christos memset(buf, 0, sizeof(buf)); 453 1.1 christos buf[0] = '#'; 454 1.1 christos for (;;) { 455 1.1 christos int c; 456 1.1 christos 457 1.1 christos c = get_char(cfile); 458 1.1 christos if (c == EOF) 459 1.1 christos break; 460 1.1 christos if (c == EOL) { 461 1.1 christos break; 462 1.1 christos } 463 1.1 christos if (++cc < sizeof(buf) - 1) 464 1.1 christos buf[cc] = c; 465 1.1 christos } 466 1.1 christos comment = createComment(buf); 467 1.1 christos TAILQ_INSERT_TAIL(&cfile->comments, comment); 468 1.1 christos } 469 1.1 christos 470 1.1 christos static enum dhcp_token 471 1.1 christos read_whitespace(int c, struct parse *cfile) { 472 1.1 christos int ofs; 473 1.1 christos 474 1.1 christos /* 475 1.1 christos * Read as much whitespace as we have available. 476 1.1 christos */ 477 1.1 christos ofs = 0; 478 1.1 christos do { 479 1.1 christos if (ofs >= (sizeof(cfile->tokbuf) - 1)) { 480 1.1 christos /* 481 1.1 christos * As the file includes a huge amount of whitespace, 482 1.1 christos * it's probably broken. 483 1.1 christos * Print out a warning and bail out. 484 1.1 christos */ 485 1.1 christos parse_error(cfile, 486 1.1 christos "whitespace too long, buffer overflow."); 487 1.1 christos } 488 1.1 christos cfile->tokbuf[ofs++] = c; 489 1.1 christos c = get_char(cfile); 490 1.1 christos if (c == EOF) 491 1.1 christos return END_OF_FILE; 492 1.3 christos } while (!((c == '\n') && cfile->eol_token) && 493 1.1 christos isascii(c) && isspace(c)); 494 1.1 christos 495 1.1 christos /* 496 1.1 christos * Put the last (non-whitespace) character back. 497 1.1 christos */ 498 1.1 christos unget_char(cfile, c); 499 1.1 christos 500 1.1 christos /* 501 1.1 christos * Return our token. 502 1.1 christos */ 503 1.1 christos cfile->tokbuf[ofs] = '\0'; 504 1.1 christos cfile->tlen = ofs; 505 1.1 christos cfile->tval = cfile->tokbuf; 506 1.1 christos return WHITESPACE; 507 1.1 christos } 508 1.1 christos 509 1.1 christos static enum dhcp_token 510 1.1 christos read_string(struct parse *cfile) 511 1.1 christos { 512 1.1 christos unsigned i; 513 1.1 christos int bs = 0; 514 1.1 christos int c; 515 1.1 christos int value = 0; 516 1.1 christos int hex = 0; 517 1.1 christos 518 1.1 christos for (i = 0; i < sizeof(cfile->tokbuf); i++) { 519 1.1 christos again: 520 1.1 christos c = get_char(cfile); 521 1.1 christos if (c == EOF) 522 1.1 christos parse_error(cfile, "eof in string constant"); 523 1.1 christos if (bs == 1) { 524 1.1 christos switch (c) { 525 1.1 christos case 't': 526 1.1 christos cfile->tokbuf[i] = '\t'; 527 1.1 christos break; 528 1.1 christos case 'r': 529 1.1 christos cfile->tokbuf[i] = '\r'; 530 1.1 christos break; 531 1.1 christos case 'n': 532 1.1 christos cfile->tokbuf[i] = '\n'; 533 1.1 christos break; 534 1.1 christos case 'b': 535 1.1 christos cfile->tokbuf[i] = '\b'; 536 1.1 christos break; 537 1.1 christos case '0': 538 1.1 christos case '1': 539 1.1 christos case '2': 540 1.1 christos case '3': 541 1.1 christos hex = 0; 542 1.1 christos value = c - '0'; 543 1.1 christos ++bs; 544 1.1 christos goto again; 545 1.1 christos case 'x': 546 1.1 christos hex = 1; 547 1.1 christos value = 0; 548 1.1 christos ++bs; 549 1.1 christos goto again; 550 1.1 christos default: 551 1.1 christos cfile->tokbuf[i] = c; 552 1.1 christos break; 553 1.1 christos } 554 1.1 christos bs = 0; 555 1.1 christos } else if (bs > 1) { 556 1.1 christos if (hex) { 557 1.1 christos if (c >= '0' && c <= '9') { 558 1.1 christos value = value * 16 + (c - '0'); 559 1.1 christos } else if (c >= 'a' && c <= 'f') { 560 1.1 christos value = value * 16 + (c - 'a' + 10); 561 1.1 christos } else if (c >= 'A' && c <= 'F') { 562 1.1 christos value = value * 16 + (c - 'A' + 10); 563 1.1 christos } else 564 1.1 christos parse_error(cfile, 565 1.1 christos "invalid hex digit: %x", 566 1.1 christos c); 567 1.1 christos if (++bs == 4) { 568 1.1 christos cfile->tokbuf[i] = value; 569 1.1 christos bs = 0; 570 1.1 christos } else 571 1.1 christos goto again; 572 1.1 christos } else { 573 1.1 christos if (c >= '0' && c <= '7') { 574 1.1 christos value = value * 8 + (c - '0'); 575 1.1 christos } else { 576 1.1 christos if (value != 0) 577 1.1 christos parse_error(cfile, 578 1.1 christos "invalid octal digit %x", 579 1.1 christos c); 580 1.1 christos else 581 1.1 christos cfile->tokbuf[i] = 0; 582 1.1 christos bs = 0; 583 1.1 christos } 584 1.1 christos if (++bs == 4) { 585 1.1 christos cfile->tokbuf[i] = value; 586 1.1 christos bs = 0; 587 1.1 christos } else 588 1.1 christos goto again; 589 1.1 christos } 590 1.1 christos } else if (c == '\\') { 591 1.1 christos bs = 1; 592 1.1 christos goto again; 593 1.1 christos } else if (c == '"') 594 1.1 christos break; 595 1.1 christos else 596 1.1 christos cfile->tokbuf[i] = c; 597 1.1 christos } 598 1.1 christos /* Normally, I'd feel guilty about this, but we're talking about 599 1.1 christos strings that'll fit in a DHCP packet here... */ 600 1.1 christos if (i == sizeof(cfile->tokbuf)) 601 1.1 christos parse_error(cfile, 602 1.1 christos "string constant larger than internal buffer"); 603 1.1 christos cfile->tokbuf[i] = 0; 604 1.1 christos cfile->tlen = i; 605 1.1 christos cfile->tval = cfile->tokbuf; 606 1.1 christos return STRING; 607 1.1 christos } 608 1.1 christos 609 1.1 christos static enum dhcp_token 610 1.1 christos read_number(int c, struct parse *cfile) 611 1.1 christos { 612 1.1 christos unsigned i = 0; 613 1.1 christos int token = NUMBER; 614 1.1 christos 615 1.1 christos cfile->tokbuf[i++] = c; 616 1.1 christos for (; i < sizeof(cfile->tokbuf); i++) { 617 1.1 christos c = get_char(cfile); 618 1.1 christos 619 1.1 christos /* Promote NUMBER->NUMBER_OR_NAME->NAME, never demote. 620 1.1 christos * Except in the case of '0x' syntax hex, which gets called 621 1.1 christos * a NAME at '0x', and returned to NUMBER_OR_NAME once it's 622 1.1 christos * verified to be at least 0xf or less. 623 1.1 christos */ 624 1.1 christos switch (isascii(c) ? token : BREAK) { 625 1.1 christos case NUMBER: 626 1.1 christos if (isdigit(c)) 627 1.1 christos break; 628 1.1 christos /* FALLTHROUGH */ 629 1.1 christos case NUMBER_OR_NAME: 630 1.1 christos if (isxdigit(c)) { 631 1.1 christos token = NUMBER_OR_NAME; 632 1.1 christos break; 633 1.1 christos } 634 1.1 christos /* FALLTHROUGH */ 635 1.1 christos case NAME: 636 1.1 christos if ((i == 2) && isxdigit(c) && 637 1.1 christos (cfile->tokbuf[0] == '0') && 638 1.1 christos ((cfile->tokbuf[1] == 'x') || 639 1.1 christos (cfile->tokbuf[1] == 'X'))) { 640 1.1 christos token = NUMBER_OR_NAME; 641 1.1 christos break; 642 1.1 christos } else if (((c == '-') || (c == '_') || isalnum(c))) { 643 1.1 christos token = NAME; 644 1.1 christos break; 645 1.1 christos } 646 1.1 christos /* FALLTHROUGH */ 647 1.1 christos case BREAK: 648 1.1 christos /* At this point c is either EOF or part of the next 649 1.1 christos * token. If not EOF, rewind the file one byte so 650 1.1 christos * the next token is read from there. 651 1.1 christos */ 652 1.1 christos unget_char(cfile, c); 653 1.1 christos goto end_read; 654 1.1 christos 655 1.1 christos default: 656 1.3 christos parse_error(cfile, 657 1.1 christos "read_number(): impossible case"); 658 1.1 christos } 659 1.1 christos 660 1.1 christos cfile->tokbuf[i] = c; 661 1.1 christos } 662 1.1 christos 663 1.1 christos if (i == sizeof(cfile->tokbuf)) 664 1.1 christos parse_error(cfile, 665 1.1 christos "numeric token larger than internal buffer"); 666 1.1 christos 667 1.1 christos end_read: 668 1.1 christos cfile->tokbuf[i] = 0; 669 1.1 christos cfile->tlen = i; 670 1.1 christos cfile->tval = cfile->tokbuf; 671 1.1 christos 672 1.1 christos /* 673 1.1 christos * If this entire token from start to finish was "-", such as 674 1.1 christos * the middle parameter in "42 - 7", return just the MINUS token. 675 1.1 christos */ 676 1.1 christos if ((i == 1) && (cfile->tokbuf[i] == '-')) 677 1.1 christos return MINUS; 678 1.1 christos else 679 1.1 christos return token; 680 1.1 christos } 681 1.1 christos 682 1.1 christos static enum dhcp_token 683 1.1 christos read_num_or_name(int c, struct parse *cfile) 684 1.1 christos { 685 1.1 christos unsigned i = 0; 686 1.1 christos enum dhcp_token rv = NUMBER_OR_NAME; 687 1.1 christos 688 1.1 christos cfile->tokbuf[i++] = c; 689 1.1 christos for (; i < sizeof(cfile->tokbuf); i++) { 690 1.1 christos c = get_char(cfile); 691 1.1 christos if (!isascii(c) || 692 1.1 christos (c != '-' && c != '_' && !isalnum(c))) { 693 1.1 christos unget_char(cfile, c); 694 1.1 christos break; 695 1.1 christos } 696 1.1 christos if (!isxdigit(c)) 697 1.1 christos rv = NAME; 698 1.1 christos cfile->tokbuf[i] = c; 699 1.1 christos } 700 1.1 christos if (i == sizeof(cfile->tokbuf)) 701 1.1 christos parse_error(cfile, "token larger than internal buffer"); 702 1.1 christos cfile->tokbuf[i] = 0; 703 1.1 christos cfile->tlen = i; 704 1.1 christos cfile->tval = cfile->tokbuf; 705 1.1 christos return intern(cfile->tval, rv); 706 1.1 christos } 707 1.1 christos 708 1.1 christos static enum dhcp_token 709 1.1 christos intern(char *atom, enum dhcp_token dfv) { 710 1.1 christos if (!isascii(atom[0])) 711 1.1 christos return dfv; 712 1.1 christos 713 1.1 christos switch (tolower((unsigned char)atom[0])) { 714 1.1 christos case '-': 715 1.1 christos if (atom [1] == 0) 716 1.1 christos return MINUS; 717 1.1 christos break; 718 1.1 christos 719 1.1 christos case 'a': 720 1.1 christos if (!strcasecmp(atom + 1, "bandoned")) 721 1.1 christos return TOKEN_ABANDONED; 722 1.1 christos if (!strcasecmp(atom + 1, "ctive")) 723 1.1 christos return TOKEN_ACTIVE; 724 1.1 christos if (!strncasecmp(atom + 1, "dd", 2)) { 725 1.1 christos if (atom[3] == '\0') 726 1.1 christos return TOKEN_ADD; 727 1.1 christos else if (!strcasecmp(atom + 3, "ress")) 728 1.1 christos return ADDRESS; 729 1.1 christos break; 730 1.1 christos } 731 1.1 christos if (!strcasecmp(atom + 1, "fter")) 732 1.1 christos return AFTER; 733 1.1 christos if (isascii(atom[1]) && 734 1.1 christos (tolower((unsigned char)atom[1]) == 'l')) { 735 1.1 christos if (!strcasecmp(atom + 2, "gorithm")) 736 1.1 christos return ALGORITHM; 737 1.1 christos if (!strcasecmp(atom + 2, "ias")) 738 1.1 christos return ALIAS; 739 1.1 christos if (isascii(atom[2]) && 740 1.1 christos (tolower((unsigned char)atom[2]) == 'l')) { 741 1.1 christos if (atom[3] == '\0') 742 1.1 christos return ALL; 743 1.1 christos else if (!strcasecmp(atom + 3, "ow")) 744 1.1 christos return ALLOW; 745 1.1 christos break; 746 1.1 christos } 747 1.1 christos if (!strcasecmp(atom + 2, "so")) 748 1.1 christos return TOKEN_ALSO; 749 1.1 christos break; 750 1.1 christos } 751 1.1 christos if (isascii(atom[1]) && 752 1.1 christos (tolower((unsigned char)atom[1]) == 'n')) { 753 1.1 christos if (!strcasecmp(atom + 2, "d")) 754 1.1 christos return AND; 755 1.1 christos if (!strcasecmp(atom + 2, "ycast-mac")) 756 1.1 christos return ANYCAST_MAC; 757 1.1 christos break; 758 1.1 christos } 759 1.1 christos if (!strcasecmp(atom + 1, "ppend")) 760 1.1 christos return APPEND; 761 1.1 christos if (!strcasecmp(atom + 1, "rray")) 762 1.1 christos return ARRAY; 763 1.1 christos if (isascii(atom[1]) && 764 1.1 christos (tolower((unsigned char)atom[1]) == 't')) { 765 1.1 christos if (atom[2] == '\0') 766 1.1 christos return AT; 767 1.1 christos if (!strcasecmp(atom + 2, "sfp")) 768 1.1 christos return ATSFP; 769 1.1 christos break; 770 1.1 christos } 771 1.1 christos if (!strcasecmp(atom + 1, "uthoring-byte-order")) 772 1.1 christos return AUTHORING_BYTE_ORDER; 773 1.1 christos if (!strncasecmp(atom + 1, "ut", 2)) { 774 1.1 christos if (isascii(atom[3]) && 775 1.1 christos (tolower((unsigned char)atom[3]) == 'h')) { 776 1.1 christos if (!strncasecmp(atom + 4, "enticat", 7)) { 777 1.1 christos if (!strcasecmp(atom + 11, "ed")) 778 1.1 christos return AUTHENTICATED; 779 1.1 christos if (!strcasecmp(atom + 11, "ion")) 780 1.1 christos return AUTHENTICATION; 781 1.1 christos break; 782 1.1 christos } 783 1.1 christos if (!strcasecmp(atom + 4, "oritative")) 784 1.1 christos return AUTHORITATIVE; 785 1.1 christos break; 786 1.1 christos } 787 1.1 christos if (!strcasecmp(atom + 3, "o-partner-down")) 788 1.1 christos return AUTO_PARTNER_DOWN; 789 1.1 christos break; 790 1.1 christos } 791 1.1 christos break; 792 1.1 christos case 'b': 793 1.1 christos if (!strcasecmp(atom + 1, "ackup")) 794 1.1 christos return TOKEN_BACKUP; 795 1.1 christos if (!strcasecmp(atom + 1, "ootp")) 796 1.1 christos return TOKEN_BOOTP; 797 1.1 christos if (!strcasecmp(atom + 1, "inding")) 798 1.1 christos return BINDING; 799 1.1 christos if (!strcasecmp(atom + 1, "inary-to-ascii")) 800 1.1 christos return BINARY_TO_ASCII; 801 1.1 christos if (!strcasecmp(atom + 1, "ackoff-cutoff")) 802 1.1 christos return BACKOFF_CUTOFF; 803 1.1 christos if (!strcasecmp(atom + 1, "ooting")) 804 1.1 christos return BOOTING; 805 1.1 christos if (!strcasecmp(atom + 1, "oot-unknown-clients")) 806 1.1 christos return BOOT_UNKNOWN_CLIENTS; 807 1.1 christos if (!strcasecmp(atom + 1, "reak")) 808 1.1 christos return BREAK; 809 1.1 christos if (!strcasecmp(atom + 1, "illing")) 810 1.1 christos return BILLING; 811 1.1 christos if (!strcasecmp(atom + 1, "oolean")) 812 1.1 christos return BOOLEAN; 813 1.1 christos if (!strcasecmp(atom + 1, "alance")) 814 1.1 christos return BALANCE; 815 1.1 christos if (!strcasecmp(atom + 1, "ound")) 816 1.1 christos return BOUND; 817 1.1 christos if (!strcasecmp(atom+1, "ig-endian")) { 818 1.1 christos return TOKEN_BIG_ENDIAN; 819 1.1 christos } 820 1.1 christos break; 821 1.1 christos case 'c': 822 1.1 christos if (!strcasecmp(atom + 1, "ase")) 823 1.1 christos return CASE; 824 1.1 christos if (!strcasecmp(atom + 1, "heck")) 825 1.1 christos return CHECK; 826 1.1 christos if (!strcasecmp(atom + 1, "iaddr")) 827 1.1 christos return CIADDR; 828 1.1 christos if (isascii(atom[1]) && 829 1.1 christos tolower((unsigned char)atom[1]) == 'l') { 830 1.1 christos if (!strcasecmp(atom + 2, "ass")) 831 1.1 christos return CLASS; 832 1.1 christos if (!strncasecmp(atom + 2, "ient", 4)) { 833 1.1 christos if (!strcasecmp(atom + 6, "s")) 834 1.1 christos return CLIENTS; 835 1.1 christos if (atom[6] == '-') { 836 1.1 christos if (!strcasecmp(atom + 7, "hostname")) 837 1.1 christos return CLIENT_HOSTNAME; 838 1.1 christos if (!strcasecmp(atom + 7, "identifier")) 839 1.1 christos return CLIENT_IDENTIFIER; 840 1.1 christos if (!strcasecmp(atom + 7, "state")) 841 1.1 christos return CLIENT_STATE; 842 1.1 christos if (!strcasecmp(atom + 7, "updates")) 843 1.1 christos return CLIENT_UPDATES; 844 1.1 christos break; 845 1.1 christos } 846 1.1 christos break; 847 1.1 christos } 848 1.1 christos if (!strcasecmp(atom + 2, "ose")) 849 1.1 christos return TOKEN_CLOSE; 850 1.1 christos if (!strcasecmp(atom + 2, "tt")) 851 1.1 christos return CLTT; 852 1.1 christos break; 853 1.1 christos } 854 1.1 christos if (isascii(atom[1]) && 855 1.1 christos tolower((unsigned char)atom[1]) == 'o') { 856 1.1 christos if (!strcasecmp(atom + 2, "de")) 857 1.1 christos return CODE; 858 1.1 christos if (isascii(atom[2]) && 859 1.1 christos tolower((unsigned char)atom[2]) == 'm') { 860 1.1 christos if (!strcasecmp(atom + 3, "mit")) 861 1.1 christos return COMMIT; 862 1.1 christos if (!strcasecmp(atom + 3, 863 1.1 christos "munications-interrupted")) 864 1.1 christos return COMMUNICATIONS_INTERRUPTED; 865 1.1 christos if (!strcasecmp(atom + 3, "pressed")) 866 1.1 christos return COMPRESSED; 867 1.1 christos break; 868 1.1 christos } 869 1.1 christos if (isascii(atom[2]) && 870 1.1 christos tolower((unsigned char)atom[2]) == 'n') { 871 1.1 christos if (!strcasecmp(atom + 3, "cat")) 872 1.1 christos return CONCAT; 873 1.1 christos if (!strcasecmp(atom + 3, "fig-option")) 874 1.1 christos return CONFIG_OPTION; 875 1.1 christos if (!strcasecmp(atom + 3, "flict-done")) 876 1.1 christos return CONFLICT_DONE; 877 1.1 christos if (!strcasecmp(atom + 3, "nect")) 878 1.1 christos return CONNECT; 879 1.1 christos break; 880 1.1 christos } 881 1.1 christos break; 882 1.1 christos } 883 1.1 christos if (!strcasecmp(atom + 1, "reate")) 884 1.1 christos return TOKEN_CREATE; 885 1.1 christos break; 886 1.1 christos case 'd': 887 1.1 christos if (!strcasecmp(atom + 1, "b-time-format")) 888 1.1 christos return DB_TIME_FORMAT; 889 1.1 christos if (!strcasecmp(atom + 1, "omain")) 890 1.1 christos return DOMAIN; 891 1.1 christos if (!strncasecmp(atom + 1, "omain-", 6)) { 892 1.1 christos if (!strcasecmp(atom + 7, "name")) 893 1.1 christos return DOMAIN_NAME; 894 1.1 christos if (!strcasecmp(atom + 7, "list")) 895 1.1 christos return DOMAIN_LIST; 896 1.1 christos } 897 1.1 christos if (!strcasecmp(atom + 1, "o-forward-updates")) 898 1.1 christos return DO_FORWARD_UPDATE; 899 1.1 christos /* do-forward-update is included for historical reasons */ 900 1.1 christos if (!strcasecmp(atom + 1, "o-forward-update")) 901 1.1 christos return DO_FORWARD_UPDATE; 902 1.1 christos if (!strcasecmp(atom + 1, "ebug")) 903 1.1 christos return TOKEN_DEBUG; 904 1.1 christos if (!strcasecmp(atom + 1, "eny")) 905 1.1 christos return DENY; 906 1.1 christos if (!strcasecmp(atom + 1, "eleted")) 907 1.1 christos return TOKEN_DELETED; 908 1.1 christos if (!strcasecmp(atom + 1, "elete")) 909 1.1 christos return TOKEN_DELETE; 910 1.1 christos if (!strncasecmp(atom + 1, "efault", 6)) { 911 1.1 christos if (!atom [7]) 912 1.1 christos return DEFAULT; 913 1.1 christos if (!strcasecmp(atom + 7, "-duid")) 914 1.1 christos return DEFAULT_DUID; 915 1.1 christos if (!strcasecmp(atom + 7, "-lease-time")) 916 1.1 christos return DEFAULT_LEASE_TIME; 917 1.1 christos break; 918 1.1 christos } 919 1.1 christos if (!strncasecmp(atom + 1, "ynamic", 6)) { 920 1.1 christos if (!atom [7]) 921 1.1 christos return DYNAMIC; 922 1.1 christos if (!strncasecmp(atom + 7, "-bootp", 6)) { 923 1.1 christos if (!atom [13]) 924 1.1 christos return DYNAMIC_BOOTP; 925 1.1 christos if (!strcasecmp(atom + 13, "-lease-cutoff")) 926 1.1 christos return DYNAMIC_BOOTP_LEASE_CUTOFF; 927 1.1 christos if (!strcasecmp(atom + 13, "-lease-length")) 928 1.1 christos return DYNAMIC_BOOTP_LEASE_LENGTH; 929 1.1 christos break; 930 1.1 christos } 931 1.1 christos } 932 1.1 christos if (!strcasecmp(atom + 1, "uplicates")) 933 1.1 christos return DUPLICATES; 934 1.1 christos if (!strcasecmp(atom + 1, "eclines")) 935 1.1 christos return DECLINES; 936 1.1 christos if (!strncasecmp(atom + 1, "efine", 5)) { 937 1.1 christos if (!strcasecmp(atom + 6, "d")) 938 1.1 christos return DEFINED; 939 1.1 christos if (!atom [6]) 940 1.1 christos return DEFINE; 941 1.1 christos } 942 1.1 christos break; 943 1.1 christos case 'e': 944 1.3 christos if (isascii(atom [1]) && 945 1.1 christos tolower((unsigned char)atom[1]) == 'x') { 946 1.1 christos if (!strcasecmp(atom + 2, "tract-int")) 947 1.1 christos return EXTRACT_INT; 948 1.1 christos if (!strcasecmp(atom + 2, "ists")) 949 1.1 christos return EXISTS; 950 1.1 christos if (!strcasecmp(atom + 2, "piry")) 951 1.1 christos return EXPIRY; 952 1.1 christos if (!strcasecmp(atom + 2, "pire")) 953 1.1 christos return EXPIRE; 954 1.1 christos if (!strcasecmp(atom + 2, "pired")) 955 1.1 christos return TOKEN_EXPIRED; 956 1.1 christos } 957 1.1 christos if (!strcasecmp(atom + 1, "ncode-int")) 958 1.1 christos return ENCODE_INT; 959 1.1 christos if (!strcasecmp(atom + 1, "poch")) 960 1.1 christos return EPOCH; 961 1.1 christos if (!strcasecmp(atom + 1, "thernet")) 962 1.1 christos return ETHERNET; 963 1.1 christos if (!strcasecmp(atom + 1, "nds")) 964 1.1 christos return ENDS; 965 1.1 christos if (!strncasecmp(atom + 1, "ls", 2)) { 966 1.1 christos if (!strcasecmp(atom + 3, "e")) 967 1.1 christos return ELSE; 968 1.1 christos if (!strcasecmp(atom + 3, "if")) 969 1.1 christos return ELSIF; 970 1.1 christos break; 971 1.1 christos } 972 1.1 christos if (!strcasecmp(atom + 1, "rror")) 973 1.1 christos return ERROR; 974 1.1 christos if (!strcasecmp(atom + 1, "val")) 975 1.1 christos return EVAL; 976 1.1 christos if (!strcasecmp(atom + 1, "ncapsulate")) 977 1.1 christos return ENCAPSULATE; 978 1.1 christos if (!strcasecmp(atom + 1, "xecute")) 979 1.1 christos return EXECUTE; 980 1.1 christos if (!strcasecmp(atom+1, "n")) { 981 1.1 christos return EN; 982 1.1 christos } 983 1.1 christos break; 984 1.1 christos case 'f': 985 1.1 christos if (!strcasecmp(atom + 1, "atal")) 986 1.1 christos return FATAL; 987 1.1 christos if (!strcasecmp(atom + 1, "ilename")) 988 1.1 christos return FILENAME; 989 1.1 christos if (!strcasecmp(atom + 1, "ixed-address")) 990 1.1 christos return FIXED_ADDR; 991 1.1 christos if (!strcasecmp(atom + 1, "ixed-address6")) 992 1.1 christos return FIXED_ADDR6; 993 1.1 christos if (!strcasecmp(atom + 1, "ixed-prefix6")) 994 1.1 christos return FIXED_PREFIX6; 995 1.1 christos if (!strcasecmp(atom + 1, "ddi")) 996 1.1 christos return TOKEN_FDDI; 997 1.1 christos if (!strcasecmp(atom + 1, "ormerr")) 998 1.1 christos return NS_FORMERR; 999 1.1 christos if (!strcasecmp(atom + 1, "unction")) 1000 1.1 christos return FUNCTION; 1001 1.1 christos if (!strcasecmp(atom + 1, "ailover")) 1002 1.1 christos return FAILOVER; 1003 1.1 christos if (!strcasecmp(atom + 1, "ree")) 1004 1.1 christos return TOKEN_FREE; 1005 1.1 christos break; 1006 1.1 christos case 'g': 1007 1.1 christos if (!strncasecmp(atom + 1, "et", 2)) { 1008 1.1 christos if (!strcasecmp(atom + 3, "-lease-hostnames")) 1009 1.1 christos return GET_LEASE_HOSTNAMES; 1010 1.1 christos if (!strcasecmp(atom + 3, "hostbyname")) 1011 1.1 christos return GETHOSTBYNAME; 1012 1.1 christos if (!strcasecmp(atom + 3, "hostname")) 1013 1.1 christos return GETHOSTNAME; 1014 1.1 christos break; 1015 1.1 christos } 1016 1.1 christos if (!strcasecmp(atom + 1, "iaddr")) 1017 1.1 christos return GIADDR; 1018 1.1 christos if (!strcasecmp(atom + 1, "roup")) 1019 1.1 christos return GROUP; 1020 1.1 christos break; 1021 1.1 christos case 'h': 1022 1.1 christos if (!strcasecmp(atom + 1, "ash")) 1023 1.1 christos return HASH; 1024 1.1 christos if (!strcasecmp(atom + 1, "ba")) 1025 1.1 christos return HBA; 1026 1.1 christos if (!strcasecmp(atom + 1, "ost")) 1027 1.1 christos return HOST; 1028 1.1 christos if (!strcasecmp(atom + 1, "ost-decl-name")) 1029 1.1 christos return HOST_DECL_NAME; 1030 1.1 christos if (!strcasecmp(atom + 1, "ost-identifier")) 1031 1.1 christos return HOST_IDENTIFIER; 1032 1.1 christos if (!strcasecmp(atom + 1, "ardware")) 1033 1.1 christos return HARDWARE; 1034 1.1 christos if (!strcasecmp(atom + 1, "ostname")) 1035 1.1 christos return HOSTNAME; 1036 1.1 christos if (!strcasecmp(atom + 1, "elp")) 1037 1.1 christos return TOKEN_HELP; 1038 1.1 christos if (!strcasecmp(atom + 1, "ex")) { 1039 1.1 christos return TOKEN_HEX; 1040 1.1 christos } 1041 1.1 christos break; 1042 1.1 christos case 'i': 1043 1.3 christos if (!strcasecmp(atom+1, "a-na")) 1044 1.1 christos return IA_NA; 1045 1.3 christos if (!strcasecmp(atom+1, "a-ta")) 1046 1.1 christos return IA_TA; 1047 1.3 christos if (!strcasecmp(atom+1, "a-pd")) 1048 1.1 christos return IA_PD; 1049 1.3 christos if (!strcasecmp(atom+1, "aaddr")) 1050 1.1 christos return IAADDR; 1051 1.3 christos if (!strcasecmp(atom+1, "aprefix")) 1052 1.1 christos return IAPREFIX; 1053 1.1 christos if (!strcasecmp(atom + 1, "nclude")) 1054 1.1 christos return INCLUDE; 1055 1.1 christos if (!strcasecmp(atom + 1, "nteger")) 1056 1.1 christos return INTEGER; 1057 1.1 christos if (!strcasecmp(atom + 1, "nfiniband")) 1058 1.1 christos return TOKEN_INFINIBAND; 1059 1.1 christos if (!strcasecmp(atom + 1, "nfinite")) 1060 1.1 christos return INFINITE; 1061 1.1 christos if (!strcasecmp(atom + 1, "nfo")) 1062 1.1 christos return INFO; 1063 1.1 christos if (!strcasecmp(atom + 1, "p-address")) 1064 1.1 christos return IP_ADDRESS; 1065 1.1 christos if (!strcasecmp(atom + 1, "p6-address")) 1066 1.1 christos return IP6_ADDRESS; 1067 1.1 christos if (!strcasecmp(atom + 1, "nitial-interval")) 1068 1.1 christos return INITIAL_INTERVAL; 1069 1.1 christos if (!strcasecmp(atom + 1, "nitial-delay")) 1070 1.1 christos return INITIAL_DELAY; 1071 1.1 christos if (!strcasecmp(atom + 1, "nterface")) 1072 1.1 christos return INTERFACE; 1073 1.1 christos if (!strcasecmp(atom + 1, "dentifier")) 1074 1.1 christos return IDENTIFIER; 1075 1.1 christos if (!strcasecmp(atom + 1, "f")) 1076 1.1 christos return IF; 1077 1.1 christos if (!strcasecmp(atom + 1, "s")) 1078 1.1 christos return IS; 1079 1.1 christos if (!strcasecmp(atom + 1, "gnore")) 1080 1.1 christos return IGNORE; 1081 1.1 christos break; 1082 1.1 christos case 'k': 1083 1.1 christos if (!strncasecmp(atom + 1, "nown", 4)) { 1084 1.1 christos if (!strcasecmp(atom + 5, "-clients")) 1085 1.1 christos return KNOWN_CLIENTS; 1086 1.1 christos if (!atom[5]) 1087 1.1 christos return KNOWN; 1088 1.1 christos break; 1089 1.1 christos } 1090 1.1 christos if (!strcasecmp(atom + 1, "ey")) 1091 1.1 christos return KEY; 1092 1.1 christos if (!strcasecmp (atom + 1, "ey-algorithm")) 1093 1.1 christos return KEY_ALGORITHM; 1094 1.1 christos break; 1095 1.1 christos case 'l': 1096 1.1 christos if (!strcasecmp(atom + 1, "case")) 1097 1.1 christos return LCASE; 1098 1.1 christos if (!strcasecmp(atom + 1, "ease")) 1099 1.1 christos return LEASE; 1100 1.1 christos if (!strcasecmp(atom + 1, "ease6")) 1101 1.1 christos return LEASE6; 1102 1.1 christos if (!strcasecmp(atom + 1, "eased-address")) 1103 1.1 christos return LEASED_ADDRESS; 1104 1.1 christos if (!strcasecmp(atom + 1, "ease-time")) 1105 1.1 christos return LEASE_TIME; 1106 1.1 christos if (!strcasecmp(atom + 1, "easequery")) 1107 1.1 christos return LEASEQUERY; 1108 1.1 christos if (!strcasecmp(atom + 1, "ength")) 1109 1.1 christos return LENGTH; 1110 1.1 christos if (!strcasecmp(atom + 1, "imit")) 1111 1.1 christos return LIMIT; 1112 1.1 christos if (!strcasecmp(atom + 1, "et")) 1113 1.1 christos return LET; 1114 1.1 christos if (!strcasecmp(atom + 1, "oad")) 1115 1.1 christos return LOAD; 1116 1.1 christos if (!strcasecmp(atom + 1, "ocal")) 1117 1.1 christos return LOCAL; 1118 1.1 christos if (!strcasecmp(atom + 1, "og")) 1119 1.1 christos return LOG; 1120 1.1 christos if (!strcasecmp(atom+1, "lt")) { 1121 1.1 christos return LLT; 1122 1.1 christos } 1123 1.1 christos if (!strcasecmp(atom+1, "l")) { 1124 1.1 christos return LL; 1125 1.1 christos } 1126 1.1 christos if (!strcasecmp(atom+1, "ittle-endian")) { 1127 1.1 christos return TOKEN_LITTLE_ENDIAN; 1128 1.1 christos } 1129 1.1 christos if (!strcasecmp(atom + 1, "ease-id-format")) { 1130 1.1 christos return LEASE_ID_FORMAT; 1131 1.1 christos } 1132 1.1 christos break; 1133 1.1 christos case 'm': 1134 1.1 christos if (!strncasecmp(atom + 1, "ax", 2)) { 1135 1.1 christos if (!atom [3]) 1136 1.1 christos return TOKEN_MAX; 1137 1.1 christos if (!strcasecmp(atom + 3, "-balance")) 1138 1.1 christos return MAX_BALANCE; 1139 1.1 christos if (!strncasecmp(atom + 3, "-lease-", 7)) { 1140 1.1 christos if (!strcasecmp(atom + 10, "misbalance")) 1141 1.1 christos return MAX_LEASE_MISBALANCE; 1142 1.1 christos if (!strcasecmp(atom + 10, "ownership")) 1143 1.1 christos return MAX_LEASE_OWNERSHIP; 1144 1.1 christos if (!strcasecmp(atom + 10, "time")) 1145 1.1 christos return MAX_LEASE_TIME; 1146 1.1 christos } 1147 1.1 christos if (!strcasecmp(atom + 3, "-life")) 1148 1.1 christos return MAX_LIFE; 1149 1.1 christos if (!strcasecmp(atom + 3, "-transmit-idle")) 1150 1.1 christos return MAX_TRANSMIT_IDLE; 1151 1.1 christos if (!strcasecmp(atom + 3, "-response-delay")) 1152 1.1 christos return MAX_RESPONSE_DELAY; 1153 1.1 christos if (!strcasecmp(atom + 3, "-unacked-updates")) 1154 1.1 christos return MAX_UNACKED_UPDATES; 1155 1.1 christos } 1156 1.1 christos if (!strncasecmp(atom + 1, "in-", 3)) { 1157 1.1 christos if (!strcasecmp(atom + 4, "balance")) 1158 1.1 christos return MIN_BALANCE; 1159 1.1 christos if (!strcasecmp(atom + 4, "lease-time")) 1160 1.1 christos return MIN_LEASE_TIME; 1161 1.1 christos if (!strcasecmp(atom + 4, "secs")) 1162 1.1 christos return MIN_SECS; 1163 1.1 christos break; 1164 1.1 christos } 1165 1.1 christos if (!strncasecmp(atom + 1, "edi", 3)) { 1166 1.1 christos if (!strcasecmp(atom + 4, "a")) 1167 1.1 christos return MEDIA; 1168 1.1 christos if (!strcasecmp(atom + 4, "um")) 1169 1.1 christos return MEDIUM; 1170 1.1 christos break; 1171 1.1 christos } 1172 1.1 christos if (!strcasecmp(atom + 1, "atch")) 1173 1.1 christos return MATCH; 1174 1.1 christos if (!strcasecmp(atom + 1, "embers")) 1175 1.1 christos return MEMBERS; 1176 1.1 christos if (!strcasecmp(atom + 1, "y")) 1177 1.1 christos return MY; 1178 1.1 christos if (!strcasecmp(atom + 1, "clt")) 1179 1.1 christos return MCLT; 1180 1.1 christos break; 1181 1.1 christos case 'n': 1182 1.1 christos if (!strcasecmp(atom + 1, "ormal")) 1183 1.1 christos return NORMAL; 1184 1.1 christos if (!strcasecmp(atom + 1, "ameserver")) 1185 1.1 christos return NAMESERVER; 1186 1.1 christos if (!strcasecmp(atom + 1, "etmask")) 1187 1.1 christos return NETMASK; 1188 1.1 christos if (!strcasecmp(atom + 1, "ever")) 1189 1.1 christos return NEVER; 1190 1.1 christos if (!strcasecmp(atom + 1, "ext-server")) 1191 1.1 christos return NEXT_SERVER; 1192 1.1 christos if (!strcasecmp(atom + 1, "ot")) 1193 1.1 christos return TOKEN_NOT; 1194 1.1 christos if (!strcasecmp(atom + 1, "o")) 1195 1.1 christos return TOKEN_NO; 1196 1.1 christos if (!strcasecmp(atom + 1, "oerror")) 1197 1.1 christos return NS_NOERROR; 1198 1.1 christos if (!strcasecmp(atom + 1, "otauth")) 1199 1.1 christos return NS_NOTAUTH; 1200 1.1 christos if (!strcasecmp(atom + 1, "otimp")) 1201 1.1 christos return NS_NOTIMP; 1202 1.1 christos if (!strcasecmp(atom + 1, "otzone")) 1203 1.1 christos return NS_NOTZONE; 1204 1.1 christos if (!strcasecmp(atom + 1, "xdomain")) 1205 1.1 christos return NS_NXDOMAIN; 1206 1.1 christos if (!strcasecmp(atom + 1, "xrrset")) 1207 1.1 christos return NS_NXRRSET; 1208 1.1 christos if (!strcasecmp(atom + 1, "ull")) 1209 1.1 christos return TOKEN_NULL; 1210 1.1 christos if (!strcasecmp(atom + 1, "ext")) 1211 1.1 christos return TOKEN_NEXT; 1212 1.1 christos if (!strcasecmp(atom + 1, "ew")) 1213 1.1 christos return TOKEN_NEW; 1214 1.1 christos break; 1215 1.1 christos case 'o': 1216 1.1 christos if (!strcasecmp(atom + 1, "mapi")) 1217 1.1 christos return OMAPI; 1218 1.1 christos if (!strcasecmp(atom + 1, "r")) 1219 1.1 christos return OR; 1220 1.1 christos if (!strcasecmp(atom + 1, "n")) 1221 1.1 christos return ON; 1222 1.1 christos if (!strcasecmp(atom + 1, "pen")) 1223 1.1 christos return TOKEN_OPEN; 1224 1.1 christos if (!strcasecmp(atom + 1, "ption")) 1225 1.1 christos return OPTION; 1226 1.1 christos if (!strcasecmp(atom + 1, "ne-lease-per-client")) 1227 1.1 christos return ONE_LEASE_PER_CLIENT; 1228 1.1 christos if (!strcasecmp(atom + 1, "f")) 1229 1.1 christos return OF; 1230 1.1 christos if (!strcasecmp(atom + 1, "wner")) 1231 1.1 christos return OWNER; 1232 1.1 christos if (!strcasecmp(atom + 1, "ctal")) { 1233 1.1 christos return TOKEN_OCTAL; 1234 1.1 christos } 1235 1.1 christos break; 1236 1.1 christos case 'p': 1237 1.1 christos if (!strcasecmp(atom + 1, "arse-vendor-option")) 1238 1.1 christos return PARSE_VENDOR_OPT; 1239 1.1 christos if (!strcasecmp(atom + 1, "repend")) 1240 1.1 christos return PREPEND; 1241 1.1 christos if (!strcasecmp(atom + 1, "referred-life")) 1242 1.1 christos return PREFERRED_LIFE; 1243 1.1 christos if (!strcasecmp(atom + 1, "acket")) 1244 1.1 christos return PACKET; 1245 1.1 christos if (!strcasecmp(atom + 1, "ool")) 1246 1.1 christos return POOL; 1247 1.1 christos if (!strcasecmp(atom + 1, "ool6")) 1248 1.1 christos return POOL6; 1249 1.1 christos if (!strcasecmp(atom + 1, "refix6")) 1250 1.1 christos return PREFIX6; 1251 1.1 christos if (!strcasecmp(atom + 1, "seudo")) 1252 1.1 christos return PSEUDO; 1253 1.1 christos if (!strcasecmp(atom + 1, "eer")) 1254 1.1 christos return PEER; 1255 1.1 christos if (!strcasecmp(atom + 1, "rimary")) 1256 1.1 christos return PRIMARY; 1257 1.1 christos if (!strcasecmp(atom + 1, "rimary6")) 1258 1.1 christos return PRIMARY6; 1259 1.1 christos if (!strncasecmp(atom + 1, "artner", 6)) { 1260 1.1 christos if (!atom [7]) 1261 1.1 christos return PARTNER; 1262 1.1 christos if (!strcasecmp(atom + 7, "-down")) 1263 1.1 christos return PARTNER_DOWN; 1264 1.1 christos } 1265 1.1 christos if (!strcasecmp(atom + 1, "ort")) 1266 1.1 christos return PORT; 1267 1.1 christos if (!strcasecmp(atom + 1, "otential-conflict")) 1268 1.1 christos return POTENTIAL_CONFLICT; 1269 1.1 christos if (!strcasecmp(atom + 1, "ick-first-value") || 1270 1.1 christos !strcasecmp(atom + 1, "ick")) 1271 1.1 christos return PICK; 1272 1.1 christos if (!strcasecmp(atom + 1, "aused")) 1273 1.1 christos return PAUSED; 1274 1.1 christos break; 1275 1.1 christos case 'r': 1276 1.1 christos if (!strcasecmp(atom + 1, "ange")) 1277 1.1 christos return RANGE; 1278 1.1 christos if (!strcasecmp(atom + 1, "ange6")) 1279 1.1 christos return RANGE6; 1280 1.1 christos if (isascii(atom[1]) && 1281 1.1 christos (tolower((unsigned char)atom[1]) == 'e')) { 1282 1.1 christos if (!strcasecmp(atom + 2, "bind")) 1283 1.1 christos return REBIND; 1284 1.1 christos if (!strcasecmp(atom + 2, "boot")) 1285 1.1 christos return REBOOT; 1286 1.1 christos if (!strcasecmp(atom + 2, "contact-interval")) 1287 1.1 christos return RECONTACT_INTERVAL; 1288 1.1 christos if (!strncasecmp(atom + 2, "cover", 5)) { 1289 1.1 christos if (atom[7] == '\0') 1290 1.1 christos return RECOVER; 1291 1.1 christos if (!strcasecmp(atom + 7, "-done")) 1292 1.1 christos return RECOVER_DONE; 1293 1.1 christos if (!strcasecmp(atom + 7, "-wait")) 1294 1.1 christos return RECOVER_WAIT; 1295 1.1 christos break; 1296 1.1 christos } 1297 1.1 christos if (!strcasecmp(atom + 2, "fresh")) 1298 1.1 christos return REFRESH; 1299 1.1 christos if (!strcasecmp(atom + 2, "fused")) 1300 1.1 christos return NS_REFUSED; 1301 1.1 christos if (!strcasecmp(atom + 2, "ject")) 1302 1.1 christos return REJECT; 1303 1.1 christos if (!strcasecmp(atom + 2, "lease")) 1304 1.1 christos return RELEASE; 1305 1.1 christos if (!strcasecmp(atom + 2, "leased")) 1306 1.1 christos return TOKEN_RELEASED; 1307 1.1 christos if (!strcasecmp(atom + 2, "move")) 1308 1.1 christos return REMOVE; 1309 1.1 christos if (!strcasecmp(atom + 2, "new")) 1310 1.1 christos return RENEW; 1311 1.1 christos if (!strcasecmp(atom + 2, "quest")) 1312 1.1 christos return REQUEST; 1313 1.1 christos if (!strcasecmp(atom + 2, "quire")) 1314 1.1 christos return REQUIRE; 1315 1.1 christos if (isascii(atom[2]) && 1316 1.1 christos (tolower((unsigned char)atom[2]) == 's')) { 1317 1.1 christos if (!strcasecmp(atom + 3, "erved")) 1318 1.1 christos return TOKEN_RESERVED; 1319 1.1 christos if (!strcasecmp(atom + 3, "et")) 1320 1.1 christos return TOKEN_RESET; 1321 1.1 christos if (!strcasecmp(atom + 3, 1322 1.1 christos "olution-interrupted")) 1323 1.1 christos return RESOLUTION_INTERRUPTED; 1324 1.1 christos break; 1325 1.1 christos } 1326 1.1 christos if (!strcasecmp(atom + 2, "try")) 1327 1.1 christos return RETRY; 1328 1.1 christos if (!strcasecmp(atom + 2, "turn")) 1329 1.1 christos return RETURN; 1330 1.1 christos if (!strcasecmp(atom + 2, "verse")) 1331 1.1 christos return REVERSE; 1332 1.1 christos if (!strcasecmp(atom + 2, "wind")) 1333 1.1 christos return REWIND; 1334 1.1 christos break; 1335 1.1 christos } 1336 1.1 christos break; 1337 1.1 christos case 's': 1338 1.1 christos if (!strcasecmp(atom + 1, "cript")) 1339 1.1 christos return SCRIPT; 1340 1.3 christos if (isascii(atom[1]) && 1341 1.1 christos tolower((unsigned char)atom[1]) == 'e') { 1342 1.1 christos if (!strcasecmp(atom + 2, "arch")) 1343 1.1 christos return SEARCH; 1344 1.3 christos if (isascii(atom[2]) && 1345 1.1 christos tolower((unsigned char)atom[2]) == 'c') { 1346 1.1 christos if (!strncasecmp(atom + 3, "ond", 3)) { 1347 1.1 christos if (!strcasecmp(atom + 6, "ary")) 1348 1.1 christos return SECONDARY; 1349 1.1 christos if (!strcasecmp(atom + 6, "ary6")) 1350 1.1 christos return SECONDARY6; 1351 1.1 christos if (!strcasecmp(atom + 6, "s")) 1352 1.1 christos return SECONDS; 1353 1.1 christos break; 1354 1.1 christos } 1355 1.1 christos if (!strcasecmp(atom + 3, "ret")) 1356 1.1 christos return SECRET; 1357 1.1 christos break; 1358 1.1 christos } 1359 1.1 christos if (!strncasecmp(atom + 2, "lect", 4)) { 1360 1.1 christos if (atom[6] == '\0') 1361 1.1 christos return SELECT; 1362 1.1 christos if (!strcasecmp(atom + 6, "-timeout")) 1363 1.1 christos return SELECT_TIMEOUT; 1364 1.1 christos break; 1365 1.1 christos } 1366 1.1 christos if (!strcasecmp(atom + 2, "nd")) 1367 1.1 christos return SEND; 1368 1.1 christos if (!strncasecmp(atom + 2, "rv", 2)) { 1369 1.1 christos if (!strncasecmp(atom + 4, "er", 2)) { 1370 1.1 christos if (atom[6] == '\0') 1371 1.1 christos return TOKEN_SERVER; 1372 1.1 christos if (atom[6] == '-') { 1373 1.1 christos if (!strcasecmp(atom + 7, 1374 1.3 christos "duid")) 1375 1.1 christos return SERVER_DUID; 1376 1.1 christos if (!strcasecmp(atom + 7, 1377 1.1 christos "name")) 1378 1.1 christos return SERVER_NAME; 1379 1.1 christos if (!strcasecmp(atom + 7, 1380 1.1 christos "identifier")) 1381 1.1 christos return SERVER_IDENTIFIER; 1382 1.1 christos break; 1383 1.1 christos } 1384 1.1 christos break; 1385 1.1 christos } 1386 1.1 christos if (!strcasecmp(atom + 4, "fail")) 1387 1.1 christos return NS_SERVFAIL; 1388 1.1 christos break; 1389 1.1 christos } 1390 1.1 christos if (!strcasecmp(atom + 2, "t")) 1391 1.1 christos return TOKEN_SET; 1392 1.1 christos break; 1393 1.1 christos } 1394 1.3 christos if (isascii(atom[1]) && 1395 1.1 christos tolower((unsigned char)atom[1]) == 'h') { 1396 1.1 christos if (!strcasecmp(atom + 2, "ared-network")) 1397 1.1 christos return SHARED_NETWORK; 1398 1.1 christos if (!strcasecmp(atom + 2, "utdown")) 1399 1.1 christos return SHUTDOWN; 1400 1.1 christos break; 1401 1.1 christos } 1402 1.3 christos if (isascii(atom[1]) && 1403 1.1 christos tolower((unsigned char)atom[1]) == 'i') { 1404 1.1 christos if (!strcasecmp(atom + 2, "addr")) 1405 1.1 christos return SIADDR; 1406 1.1 christos if (!strcasecmp(atom + 2, "gned")) 1407 1.1 christos return SIGNED; 1408 1.1 christos if (!strcasecmp(atom + 2, "ze")) 1409 1.1 christos return SIZE; 1410 1.1 christos break; 1411 1.1 christos } 1412 1.3 christos if (isascii(atom[1]) && 1413 1.1 christos tolower((unsigned char)atom[1]) == 'p') { 1414 1.3 christos if (isascii(atom[2]) && 1415 1.1 christos tolower((unsigned char)atom[2]) == 'a') { 1416 1.1 christos if (!strcasecmp(atom + 3, "ce")) 1417 1.1 christos return SPACE; 1418 1.1 christos if (!strcasecmp(atom + 3, "wn")) 1419 1.1 christos return SPAWN; 1420 1.1 christos break; 1421 1.1 christos } 1422 1.1 christos if (!strcasecmp(atom + 2, "lit")) 1423 1.1 christos return SPLIT; 1424 1.1 christos break; 1425 1.1 christos } 1426 1.3 christos if (isascii(atom[1]) && 1427 1.1 christos tolower((unsigned char)atom[1]) == 't') { 1428 1.3 christos if (isascii(atom[2]) && 1429 1.1 christos tolower((unsigned char)atom[2]) == 'a') { 1430 1.1 christos if (!strncasecmp(atom + 3, "rt", 2)) { 1431 1.1 christos if (!strcasecmp(atom + 5, "s")) 1432 1.1 christos return STARTS; 1433 1.1 christos if (!strcasecmp(atom + 5, "up")) 1434 1.1 christos return STARTUP; 1435 1.1 christos break; 1436 1.1 christos } 1437 1.1 christos if (isascii(atom[3]) && 1438 1.1 christos tolower((unsigned char)atom[3]) == 't') { 1439 1.1 christos if (!strcasecmp(atom + 4, "e")) 1440 1.1 christos return STATE; 1441 1.1 christos if (!strcasecmp(atom + 4, "ic")) 1442 1.1 christos return STATIC; 1443 1.1 christos break; 1444 1.1 christos } 1445 1.1 christos } 1446 1.1 christos if (!strcasecmp(atom + 2, "ring")) 1447 1.1 christos return STRING_TOKEN; 1448 1.1 christos break; 1449 1.1 christos } 1450 1.1 christos if (!strncasecmp(atom + 1, "ub", 2)) { 1451 1.1 christos if (!strcasecmp(atom + 3, "class")) 1452 1.1 christos return SUBCLASS; 1453 1.1 christos if (!strcasecmp(atom + 3, "net")) 1454 1.1 christos return SUBNET; 1455 1.1 christos if (!strcasecmp(atom + 3, "net6")) 1456 1.1 christos return SUBNET6; 1457 1.1 christos if (!strcasecmp(atom + 3, "string")) 1458 1.1 christos return SUBSTRING; 1459 1.1 christos break; 1460 1.1 christos } 1461 1.3 christos if (isascii(atom[1]) && 1462 1.1 christos tolower((unsigned char)atom[1]) == 'u') { 1463 1.1 christos if (!strcasecmp(atom + 2, "ffix")) 1464 1.1 christos return SUFFIX; 1465 1.1 christos if (!strcasecmp(atom + 2, "persede")) 1466 1.1 christos return SUPERSEDE; 1467 1.1 christos } 1468 1.1 christos if (!strcasecmp(atom + 1, "witch")) 1469 1.1 christos return SWITCH; 1470 1.1 christos break; 1471 1.1 christos case 't': 1472 1.1 christos if (!strcasecmp(atom + 1, "imestamp")) 1473 1.1 christos return TIMESTAMP; 1474 1.1 christos if (!strcasecmp(atom + 1, "imeout")) 1475 1.1 christos return TIMEOUT; 1476 1.1 christos if (!strcasecmp(atom + 1, "oken-ring")) 1477 1.1 christos return TOKEN_RING; 1478 1.1 christos if (!strcasecmp(atom + 1, "ext")) 1479 1.1 christos return TEXT; 1480 1.1 christos if (!strcasecmp(atom + 1, "stp")) 1481 1.1 christos return TSTP; 1482 1.1 christos if (!strcasecmp(atom + 1, "sfp")) 1483 1.1 christos return TSFP; 1484 1.1 christos if (!strcasecmp(atom + 1, "ransmission")) 1485 1.1 christos return TRANSMISSION; 1486 1.1 christos if (!strcasecmp(atom + 1, "emporary")) 1487 1.1 christos return TEMPORARY; 1488 1.1 christos break; 1489 1.1 christos case 'u': 1490 1.1 christos if (!strcasecmp(atom + 1, "case")) 1491 1.1 christos return UCASE; 1492 1.1 christos if (!strcasecmp(atom + 1, "nset")) 1493 1.1 christos return UNSET; 1494 1.1 christos if (!strcasecmp(atom + 1, "nsigned")) 1495 1.1 christos return UNSIGNED; 1496 1.1 christos if (!strcasecmp(atom + 1, "id")) 1497 1.1 christos return UID; 1498 1.1 christos if (!strncasecmp(atom + 1, "se", 2)) { 1499 1.1 christos if (!strcasecmp(atom + 3, "r-class")) 1500 1.1 christos return USER_CLASS; 1501 1.1 christos if (!strcasecmp(atom + 3, "-host-decl-names")) 1502 1.1 christos return USE_HOST_DECL_NAMES; 1503 1.1 christos if (!strcasecmp(atom + 3, 1504 1.1 christos "-lease-addr-for-default-route")) 1505 1.1 christos return USE_LEASE_ADDR_FOR_DEFAULT_ROUTE; 1506 1.1 christos break; 1507 1.1 christos } 1508 1.1 christos if (!strncasecmp(atom + 1, "nknown", 6)) { 1509 1.1 christos if (!strcasecmp(atom + 7, "-clients")) 1510 1.1 christos return UNKNOWN_CLIENTS; 1511 1.1 christos if (!strcasecmp(atom + 7, "-state")) 1512 1.1 christos return UNKNOWN_STATE; 1513 1.1 christos if (!atom [7]) 1514 1.1 christos return UNKNOWN; 1515 1.1 christos break; 1516 1.1 christos } 1517 1.1 christos if (!strcasecmp(atom + 1, "nauthenticated")) 1518 1.1 christos return UNAUTHENTICATED; 1519 1.1 christos if (!strcasecmp(atom + 1, "pdate")) 1520 1.1 christos return UPDATE; 1521 1.1 christos break; 1522 1.1 christos case 'v': 1523 1.1 christos if (!strcasecmp(atom + 1, "6relay")) 1524 1.1 christos return V6RELAY; 1525 1.1 christos if (!strcasecmp(atom + 1, "6relopt")) 1526 1.1 christos return V6RELOPT; 1527 1.1 christos if (!strcasecmp(atom + 1, "endor-class")) 1528 1.1 christos return VENDOR_CLASS; 1529 1.1 christos if (!strcasecmp(atom + 1, "endor")) 1530 1.1 christos return VENDOR; 1531 1.1 christos break; 1532 1.1 christos case 'w': 1533 1.1 christos if (!strcasecmp(atom + 1, "ith")) 1534 1.1 christos return WITH; 1535 1.1 christos if (!strcasecmp(atom + 1, "idth")) 1536 1.1 christos return WIDTH; 1537 1.1 christos break; 1538 1.1 christos case 'y': 1539 1.1 christos if (!strcasecmp(atom + 1, "iaddr")) 1540 1.1 christos return YIADDR; 1541 1.1 christos if (!strcasecmp(atom + 1, "xdomain")) 1542 1.1 christos return NS_YXDOMAIN; 1543 1.1 christos if (!strcasecmp(atom + 1, "xrrset")) 1544 1.1 christos return NS_YXRRSET; 1545 1.1 christos break; 1546 1.1 christos case 'z': 1547 1.1 christos if (!strcasecmp(atom + 1, "erolen")) 1548 1.1 christos return ZEROLEN; 1549 1.1 christos if (!strcasecmp(atom + 1, "one")) 1550 1.1 christos return ZONE; 1551 1.1 christos break; 1552 1.1 christos } 1553 1.1 christos return dfv; 1554 1.1 christos } 1555