diff options
Diffstat (limited to 'contrib/bind/bin/named/ns_lexer.c')
-rw-r--r-- | contrib/bind/bin/named/ns_lexer.c | 826 |
1 files changed, 0 insertions, 826 deletions
diff --git a/contrib/bind/bin/named/ns_lexer.c b/contrib/bind/bin/named/ns_lexer.c deleted file mode 100644 index 3c09cf0..0000000 --- a/contrib/bind/bin/named/ns_lexer.c +++ /dev/null @@ -1,826 +0,0 @@ -#if !defined(lint) && !defined(SABER) -static const char rcsid[] = "$Id: ns_lexer.c,v 8.31.10.1 2003/06/02 09:56:35 marka Exp $"; -#endif /* not lint */ - -/* - * Copyright (c) 1996-2000 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include "port_before.h" - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> - -#include <netinet/in.h> -#include <arpa/nameser.h> -#include <arpa/inet.h> - -#include <resolv.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <time.h> -#include <stdarg.h> -#include <syslog.h> - -#include <isc/eventlib.h> -#include <isc/logging.h> -#include <isc/memcluster.h> - -#include "port_after.h" - -#include "named.h" -#include "ns_parser.h" -#include "ns_parseutil.h" -#include "ns_lexer.h" - -typedef enum lexer_state { - scan, number, identifier, ipv4, quoted_string -} LexerState; - -#define LEX_EOF 0x01 -#define LEXER_MAX_PUSHBACK 2 - -typedef struct lexer_file_context { - char * name; - FILE * stream; - int line_number; - LexerState state; - u_int flags; - int warnings; - int errors; - u_int pushback_count; - char pushback[LEXER_MAX_PUSHBACK]; - struct lexer_file_context * - next; -} *LexerFileContext; - -LexerFileContext current_file = NULL; - -#define LEX_LAST_WAS_DOT 0x01 -#define LEX_CONSECUTIVE_DOTS 0x02 - -typedef struct lexer_identifier { - char buffer[LEX_MAX_IDENT_SIZE+1]; - int index; - int num_dots; - unsigned int flags; -} *LexerIdentifier; - -static LexerIdentifier id; - -static char special_chars[256]; - -#define whitespace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') -#define domain_char(c) (isalnum((c)) || (c) == '.' || (c) == '-') -#define special_char(c) (special_chars[(c)] == 1) -#define identifier_char(c) (!whitespace(c) && !special_char(c)) - -static int last_token; -static YYSTYPE last_yylval; - -static int lexer_initialized = 0; - -/* - * Problem Reporting - */ - -static char * -token_to_text(int token, YYSTYPE lval) { - static char buffer[LEX_MAX_IDENT_SIZE+50]; - - if (token < 128) { - if (token == 0) - strcpy(buffer, "<end of file>"); - else - sprintf(buffer, "'%c'", token); - } else { - switch (token) { - case L_EOS: - strcpy(buffer, ";"); - break; - case L_STRING: - sprintf(buffer, "'%s'", lval.cp); - break; - case L_QSTRING: - sprintf(buffer, "\"%s\"", lval.cp); - break; - case L_IPADDR: - sprintf(buffer, "%s", inet_ntoa(lval.ip_addr)); - break; - case L_NUMBER: - sprintf(buffer, "%ld", lval.num); - break; - case L_END_INCLUDE: - sprintf(buffer, "<end of include>"); - break; - default: - sprintf(buffer, "%s", lval.cp); - } - } - - return (buffer); -} - -static char where[MAXPATHLEN + 100]; -static char message[20480]; - -static void -parser_complain(int is_warning, int print_last_token, const char *format, - va_list args) ISC_FORMAT_PRINTF(3, 0); - -static void -parser_complain(int is_warning, int print_last_token, const char *format, - va_list args) -{ - LexerFileContext lf; - int severity; - - if (is_warning) { - severity = log_warning; - } else { - severity = log_error; - } - - INSIST(current_file != NULL); - if (current_file->next != NULL) { - for (lf = current_file; lf != NULL; lf = lf->next) { - log_write(log_ctx, ns_log_parser, severity, - "%s '%s' line %d", - (lf == current_file) ? - "In" : "included from", - lf->name, lf->line_number); - } - } - sprintf(where, "%s:%d: ", current_file->name, - current_file->line_number); - vsprintf(message, format, args); - if (print_last_token) - log_write(log_ctx, ns_log_parser, severity, "%s%s near %s", - where, message, - token_to_text(last_token, last_yylval)); - else - log_write(log_ctx, ns_log_parser, severity, - "%s%s", where, message); -} - -int -parser_warning(int print_last_token, const char *format, ...) { - va_list args; - - va_start(args, format); - parser_complain(1, print_last_token, format, args); - va_end(args); - current_file->warnings++; - return (1); -} - -int -parser_error(int print_last_token, const char *format, ...) { - va_list args; - - va_start(args, format); - parser_complain(0, print_last_token, format, args); - va_end(args); - current_file->errors++; - return (1); -} - -void -yyerror(const char *message) { - parser_error(1, "%s", message); -} - -/* - * Keywords - */ - -struct keyword { - const char *name; - int token; -}; - -/* - * "keywords" is an array of the keywords which are the fixed syntactic - * elements of the configuration file. Each keyword has a string version - * of the keyword and a token id, which should be an identifier which - * matches that in a %token statement inside the parser.y file. - */ -static struct keyword keywords[] = { - {"acl", T_ACL}, - {"address", T_ADDRESS}, - {"algorithm", T_ALGID}, - {"allow", T_ALLOW}, - {"allow-query", T_ALLOW_QUERY}, - {"allow-recursion", T_ALLOW_RECURSION}, - {"allow-transfer", T_ALLOW_TRANSFER}, - {"allow-update", T_ALLOW_UPDATE}, -#ifdef BIND_NOTIFY - {"also-notify", T_ALSO_NOTIFY}, -#endif - {"auth-nxdomain", T_AUTH_NXDOMAIN}, - {"blackhole", T_BLACKHOLE}, - {"bogus", T_BOGUS}, - {"category", T_CATEGORY}, - {"class", T_CLASS}, - {"channel", T_CHANNEL}, - {"check-names", T_CHECK_NAMES}, - {"cleaning-interval", T_CLEAN_INTERVAL}, - {"controls", T_CONTROLS}, - {"coresize", T_CORESIZE}, - {"datasize", T_DATASIZE}, - {"deallocate-on-exit", T_DEALLOC_ON_EXIT}, - {"debug", T_DEBUG}, - {"default", T_DEFAULT}, - {"dialup", T_DIALUP}, - {"directory", T_DIRECTORY}, - {"dump-file", T_DUMP_FILE}, - {"dynamic", T_DYNAMIC}, - {"edns", T_EDNS}, - {"edns-udp-size", T_EDNS_UDP_SIZE}, - {"explicit", T_EXPLICIT}, - {"fail", T_FAIL}, - {"fake-iquery", T_FAKE_IQUERY}, - {"false", T_FALSE}, - {"fetch-glue", T_FETCH_GLUE}, - {"file", T_FILE}, - {"files", T_FILES}, - {"first", T_FIRST}, - {"forward", T_FORWARD}, - {"forwarders", T_FORWARDERS}, - {"group", T_GROUP}, - {"has-old-clients", T_HAS_OLD_CLIENTS}, - {"heartbeat-interval", T_HEARTBEAT}, - {"hint", T_HINT}, -#ifdef HITCOUNTS - {"hit-count", T_HITCOUNT}, -#endif /* HITCOUNTS */ - {"host-statistics", T_HOSTSTATS}, - {"host-statistics-max", T_HOSTSTATSMAX}, - {"hostname", T_HOSTNAME}, - {"if-no-answer", T_IF_NO_ANSWER}, - {"if-no-domain", T_IF_NO_DOMAIN}, - {"ignore", T_IGNORE}, - {"include", T_INCLUDE}, - {"inet", T_INET}, - {"interface-interval", T_INTERFACE_INTERVAL}, - {"ixfr-base", T_FILE_IXFR}, - {"ixfr-tmp-file", T_IXFR_TMP}, - {"key", T_SEC_KEY}, - {"keys", T_KEYS}, - {"lame-ttl", T_LAME_TTL}, - {"listen-on", T_LISTEN_ON}, - {"logging", T_LOGGING}, - {"maintain-ixfr-base", T_MAINTAIN_IXFR_BASE}, - {"many-answers", T_MANY_ANSWERS}, - {"master", T_MASTER}, - {"masters", T_MASTERS}, - {"max-ixfr-log-size", T_MAX_LOG_SIZE_IXFR}, - {"max-ncache-ttl", T_MAX_NCACHE_TTL}, - {"max-transfer-time-in", T_MAX_TRANSFER_TIME_IN}, - {"memstatistics-file", T_MEMSTATS_FILE}, - {"min-roots", T_MIN_ROOTS}, - {"multiple-cnames", T_MULTIPLE_CNAMES}, - {"name", T_NAME}, - {"named-xfer", T_NAMED_XFER}, - {"no", T_NO}, -#ifdef BIND_NOTIFY - {"notify", T_NOTIFY}, -#endif - {"null", T_NULL_OUTPUT}, - {"one-answer", T_ONE_ANSWER}, - {"only", T_ONLY}, - {"order", T_ORDER}, - {"options", T_OPTIONS}, - {"owner", T_OWNER}, - {"perm", T_PERM}, - {"pid-file", T_PIDFILE}, - {"port", T_PORT}, - {"preferred-glue", T_PREFERRED_GLUE}, - {"print-category", T_PRINT_CATEGORY}, - {"print-severity", T_PRINT_SEVERITY}, - {"print-time", T_PRINT_TIME}, - {"pubkey", T_PUBKEY}, - {"query-source", T_QUERY_SOURCE}, - {"rfc2308-type1", T_RFC2308_TYPE1}, - {"rrset-order", T_RRSET_ORDER}, - {"recursion", T_RECURSION}, - {"response", T_RESPONSE}, - {"secret", T_SECRET}, - {"serial-queries", T_SERIAL_QUERIES}, - {"server", T_SERVER}, - {"severity", T_SEVERITY}, - {"size", T_SIZE}, - {"slave", T_SLAVE}, - {"sortlist", T_SORTLIST}, - {"stacksize", T_STACKSIZE}, - {"statistics-file", T_STATS_FILE}, - {"statistics-interval", T_STATS_INTERVAL}, - {"stub", T_STUB}, - {"support-ixfr", T_SUPPORT_IXFR}, -#ifdef BIND_NOTIFY - {"suppress-initial-notify", T_NOTIFY_INITIAL}, -#endif - {"syslog", T_SYSLOG}, - {"topology", T_TOPOLOGY}, - {"transfer-format", T_TRANSFER_FORMAT}, - {"transfer-source", T_TRANSFER_SOURCE}, - {"transfers", T_TRANSFERS}, - {"transfers-in", T_TRANSFERS_IN}, - {"transfers-out", T_TRANSFERS_OUT}, - {"transfers-per-ns", T_TRANSFERS_PER_NS}, - {"treat-cr-as-space", T_TREAT_CR_AS_SPACE}, - {"true", T_TRUE}, - {"trusted-keys", T_TRUSTED_KEYS}, - {"type", T_TYPE}, - {"unix", T_UNIX}, - {"unlimited", T_UNLIMITED}, - {"use-id-pool", T_USE_ID_POOL}, - {"use-ixfr", T_USE_IXFR}, - {"version", T_VERSION}, - {"versions", T_VERSIONS}, - {"warn", T_WARN}, - {"yes", T_YES}, - {"zone", T_ZONE}, - {(char *) NULL, 0}, -}; - -/* - * The table size should be a prime chosen to minimize collisions. - */ -#define KEYWORD_TABLE_SIZE 461 - -static symbol_table keyword_table = NULL; - -static void -init_keywords() { - struct keyword *k; - symbol_value value; - - if (keyword_table != NULL) - free_symbol_table(keyword_table); - keyword_table = new_symbol_table(KEYWORD_TABLE_SIZE, NULL); - for (k = keywords; k->name != NULL; k++) { - value.integer = k->token; - define_symbol(keyword_table, k->name, 0, value, 0); - } - dprint_symbol_table(99, keyword_table); -} - -/* - * File Contexts - */ - -void -lexer_begin_file(const char *filename, FILE *stream) { - LexerFileContext lf; - - if (stream == NULL) { - stream = fopen(filename, "r"); - if (stream == NULL) { - parser_error(0, "couldn't open include file '%s'", - filename); - return; - } - } - lf = (LexerFileContext)memget(sizeof (struct lexer_file_context)); - if (lf == NULL) - panic("memget failed in lexer_begin_file", NULL); - INSIST(stream != NULL); - lf->stream = stream; - lf->name = savestr(filename, 1); - lf->line_number = 1; - lf->state = scan; - lf->flags = 0; - lf->warnings = 0; - lf->errors = 0; - lf->pushback_count = 0; - lf->next = current_file; - current_file = lf; -} - -void -lexer_end_file(void) { - LexerFileContext lf; - - INSIST(current_file != NULL); - lf = current_file; - current_file = lf->next; - fclose(lf->stream); - freestr(lf->name); - memput(lf, sizeof *lf); -} - -/* - * Character Input - */ - -#define LEXER_GETC(c, cf) \ - do { \ - if ((cf)->pushback_count > 0) { \ - (cf)->pushback_count--; \ - (c) = (cf)->pushback[(cf)->pushback_count]; \ - } else \ - (c) = getc((cf)->stream); \ - } while (0); - -#define LEXER_UNGETC(c, cf) \ - do { \ - INSIST((cf)->pushback_count < LEXER_MAX_PUSHBACK); \ - (cf)->pushback[(cf)->pushback_count++] = (c); \ - } while (0); - -static void -scan_to_comment_end(int c_plus_plus_style) { - int c; - int done = 0; - int prev_was_star = 0; - - while (!done) { - LEXER_GETC(c, current_file); - switch (c) { - case EOF: - if (!c_plus_plus_style) - parser_error(0, "EOF in comment"); - current_file->flags |= LEX_EOF; - done = 1; - break; - case '*': - prev_was_star = 1; - break; - case '/': - if (prev_was_star && !c_plus_plus_style) - done = 1; - prev_was_star = 0; - break; - case '\n': - if (c_plus_plus_style) { - /* don't consume the newline because - we want it to be a delimiter for - anything before the comment - started */ - LEXER_UNGETC(c, current_file); - done = 1; - } else { - current_file->line_number++; - } - prev_was_star = 0; - break; - default: - prev_was_star = 0; - } - } -} - -static int -get_next_char(int comment_ok) { - int c, nc; - - if (current_file->flags & LEX_EOF) - return (EOF); - - LEXER_GETC(c, current_file); - - if (comment_ok) { - while (c == '/' || c == '#') { - if (c == '#') { - scan_to_comment_end(1); - if (current_file->flags & LEX_EOF) - return (EOF); - LEXER_GETC(c, current_file); - } else { - LEXER_GETC(nc, current_file); - switch (nc) { - case EOF: - current_file->flags |= LEX_EOF; - return ('/'); - case '*': - case '/': - scan_to_comment_end((nc == '/')); - if (current_file->flags & LEX_EOF) - return (EOF); - LEXER_GETC(c, current_file); - break; - default: - LEXER_UNGETC(nc, current_file); - return ('/'); - } - } - } - } - - if (c == EOF) - current_file->flags |= LEX_EOF; - else if (c == '\n') - current_file->line_number++; - return (c); -} - -static void -put_back_char(int c) { - if (c == EOF) - current_file->flags |= LEX_EOF; - else { - LEXER_UNGETC(c, current_file); - if (c == '\n') - current_file->line_number--; - } -} - - -/* - * Identifiers - */ - -static void -clear_identifier(LexerIdentifier id) { - INSIST(id != NULL); - id->index = 0; - id->num_dots = 0; - id->flags = 0; -} - -static char * -dup_identifier(LexerIdentifier id) { - char *duplicate; - - INSIST(id != NULL); - duplicate = savestr(id->buffer, 1); - return (duplicate); -} - -static void -finish_identifier(LexerIdentifier id) { - INSIST(id != NULL && id->index < LEX_MAX_IDENT_SIZE); - id->buffer[id->index] = '\0'; -} - -static void -add_to_identifier(LexerIdentifier id, int c) { - INSIST(id != NULL); - id->buffer[id->index] = c; - id->index++; - if (id->index >= LEX_MAX_IDENT_SIZE) { - parser_error(0, "identifier too long"); - current_file->state = scan; - /* discard chars until we hit a non-identifier char */ - while (c != EOF && identifier_char(c)) { - c = get_next_char(1); - } - put_back_char(c); - clear_identifier(id); - } else { - if (c == '.') { - if (id->flags & LEX_LAST_WAS_DOT) - id->flags |= LEX_CONSECUTIVE_DOTS; - id->flags |= LEX_LAST_WAS_DOT; - id->num_dots++; - } else { - id->flags &= ~LEX_LAST_WAS_DOT; - } - } -} - -/* - * yylex() -- return the next token from the current input stream - */ -int -yylex() { - int c; - int comment_ok = 1; - int token = -1; - symbol_value value; - - while (token < 0) { - c = get_next_char(comment_ok); - switch(current_file->state) { - case scan: - if (c == EOF) { - if (current_file->next == NULL) - /* - * We don't want to call - * lexer_end_file() here because we - * want to keep the toplevel file - * context to log errors against. - */ - token = 0; - else { - lexer_end_file(); - token = L_END_INCLUDE; - } - break; - } - if (whitespace(c)) - break; - if (identifier_char(c)) { - if (isdigit(c)) - current_file->state = number; - else - current_file->state = identifier; - clear_identifier(id); - add_to_identifier(id, c); - } else - if (special_char(c)) { - if (c == ';') { - token = L_EOS; - break; - } - if (c == '"') { - clear_identifier(id); - current_file->state = - quoted_string; - comment_ok = 0; - break; - } - token = c; - } else { - parser_error(0, - "invalid character '%c'", - c); - } - break; - - case number: - if (c != EOF && identifier_char(c)) { - if (!isdigit(c)) - current_file->state = - (c == '.') ? ipv4 : identifier; - add_to_identifier(id, c); - } else { - put_back_char(c); - current_file->state = scan; - finish_identifier(id); - yylval.num = strtol(id->buffer, (char**)0, 0); - token = L_NUMBER; - } - break; - - case identifier: - if (c != EOF && identifier_char(c)) { - add_to_identifier(id, c); - } else { - put_back_char(c); - current_file->state = scan; - finish_identifier(id); - /* is it a keyword? */ - if (lookup_symbol(keyword_table, id->buffer, - 0, &value)) { - yylval.cp = id->buffer; - token = value.integer; - } else { - yylval.cp = dup_identifier(id); - token = L_STRING; - } - } - break; - - case ipv4: - if (c != EOF && identifier_char(c)) { - if (!isdigit(c)) { - if (c != '.' || - (id->flags & LEX_CONSECUTIVE_DOTS)) - current_file->state = - identifier; - } - add_to_identifier(id, c); - } else { - put_back_char(c); - if (id->num_dots > 3 || - (id->flags & LEX_LAST_WAS_DOT)) - current_file->state = identifier; - else { - if (id->num_dots == 1) { - add_to_identifier(id, '.'); - add_to_identifier(id, '0'); - add_to_identifier(id, '.'); - add_to_identifier(id, '0'); - } else if (id->num_dots == 2) { - add_to_identifier(id, '.'); - add_to_identifier(id, '0'); - } - current_file->state = scan; - finish_identifier(id); - token = L_IPADDR; - if (inet_aton(id->buffer, - &(yylval.ip_addr))==0) { - yylval.cp = dup_identifier(id); - token = L_STRING; - } - } - } - break; - - case quoted_string: - if (c == EOF) { - parser_error(0, "EOF in quoted string"); - return 0; - } else { - if (c == '"') { - comment_ok = 1; - current_file->state = scan; - finish_identifier(id); - yylval.cp = dup_identifier(id); - token = L_QSTRING; - } else { - /* XXX add backslash escapes here */ - add_to_identifier(id, c); - } - } - break; - - default: - panic("unhandled state in yylex", NULL); - } - } - - last_token = token; - last_yylval = yylval; - return (token); -} - -/* - * Initialization - */ - -symbol_table constants; - -static void -import_constants(const struct ns_sym *s, int type) { - symbol_value value; - for ((void)NULL; s != NULL && s->name != NULL; s++) { - value.integer = s->number; - define_symbol(constants, s->name, type, value, 0); - } -} - -static void -import_res_constants(const struct res_sym *r, int type) { - symbol_value value; - for ((void)NULL; r != NULL && r->name != NULL; r++) { - value.integer = r->number; - define_symbol(constants, r->name, type, value, 0); - } -} - -#define CONSTANTS_TABLE_SIZE 397 /* should be prime */ - -static void -import_all_constants() { - constants = new_symbol_table(CONSTANTS_TABLE_SIZE, NULL); - import_res_constants(__p_class_syms, SYM_CLASS); - import_constants(category_constants, SYM_CATEGORY); - import_constants(logging_constants, SYM_LOGGING); - import_constants(syslog_constants, SYM_SYSLOG); -} - -void -lexer_initialize() { - memset(special_chars, 0, sizeof special_chars); - special_chars[';'] = 1; - special_chars['{'] = 1; - special_chars['}'] = 1; - special_chars['!'] = 1; - special_chars['/'] = 1; - special_chars['"'] = 1; - special_chars['*'] = 1; - id = (LexerIdentifier)memget(sizeof (struct lexer_identifier)); - if (id == NULL) - panic("memget failed in lexer_initialize", NULL); - init_keywords(); - import_all_constants(); - lexer_initialized = 1; -} - -void -lexer_setup(void) { - REQUIRE(lexer_initialized); - - current_file = NULL; /* XXX should we INSIST(current_file==NULL)? */ - INSIST(id != NULL); -} - -void -lexer_shutdown(void) { - REQUIRE(lexer_initialized); - - free_symbol_table(keyword_table); - free_symbol_table(constants); - memput(id, sizeof (struct lexer_identifier)); - id = NULL; - lexer_initialized = 0; -} |