configlexer.lex revision 1.1.1.5
1%{ 2/* 3 * configlexer.lex - lexical analyzer for NSD config file 4 * 5 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved 6 * 7 * See LICENSE for the license. 8 * 9 */ 10/* because flex keeps having sign-unsigned compare problems that are unfixed*/ 11#if defined(__clang__)||(defined(__GNUC__)&&((__GNUC__ >4)||(defined(__GNUC_MINOR__)&&(__GNUC__ ==4)&&(__GNUC_MINOR__ >=2)))) 12#pragma GCC diagnostic ignored "-Wsign-compare" 13#endif 14 15#include "config.h" 16 17#include <ctype.h> 18#include <errno.h> 19#include <string.h> 20#include <strings.h> 21#ifdef HAVE_GLOB_H 22# include <glob.h> 23#endif 24 25#include "options.h" 26#include "configyyrename.h" 27#include "configparser.h" 28 29#if 0 30#define LEXOUT(s) printf s /* used ONLY when debugging */ 31#else 32#define LEXOUT(s) 33#endif 34 35struct inc_state { 36 char* filename; 37 int line; 38 YY_BUFFER_STATE buffer; 39 struct inc_state* next; 40}; 41static struct inc_state* config_include_stack = NULL; 42static int inc_depth = 0; 43static int inc_prev = 0; 44static int num_args = 0; 45 46void init_cfg_parse(void) 47{ 48 config_include_stack = NULL; 49 inc_depth = 0; 50 inc_prev = 0; 51 num_args = 0; 52} 53 54static void config_start_include(const char* filename) 55{ 56 FILE *input; 57 struct inc_state* s; 58 char* nm; 59 if(inc_depth++ > 10000000) { 60 yyerror("too many include files"); 61 return; 62 } 63 if(strlen(filename) == 0) { 64 yyerror("empty include file name"); 65 return; 66 } 67 s = (struct inc_state*)malloc(sizeof(*s)); 68 if(!s) { 69 yyerror("include %s: malloc failure", filename); 70 return; 71 } 72 nm = strdup(filename); 73 if(!nm) { 74 yyerror("include %s: strdup failure", filename); 75 free(s); 76 return; 77 } 78 input = fopen(filename, "r"); 79 if(!input) { 80 yyerror("cannot open include file '%s': %s", 81 filename, strerror(errno)); 82 free(s); 83 free(nm); 84 return; 85 } 86 LEXOUT(("switch_to_include_file(%s) ", filename)); 87 s->filename = cfg_parser->filename; 88 s->line = cfg_parser->line; 89 s->buffer = YY_CURRENT_BUFFER; 90 s->next = config_include_stack; 91 config_include_stack = s; 92 93 cfg_parser->filename = nm; 94 cfg_parser->line = 1; 95 yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE)); 96} 97 98static void config_start_include_glob(const char* filename) 99{ 100 /* check for wildcards */ 101#ifdef HAVE_GLOB 102 glob_t g; 103 int i, r, flags; 104#endif /* HAVE_GLOB */ 105 if (cfg_parser->chroot) { 106 int l = strlen(cfg_parser->chroot); /* chroot has trailing slash */ 107 if (strncmp(cfg_parser->chroot, filename, l) != 0) { 108 yyerror("include file '%s' is not relative to chroot '%s'", 109 filename, cfg_parser->chroot); 110 return; 111 } 112 filename += l - 1; /* strip chroot without trailing slash */ 113 } 114#ifdef HAVE_GLOB 115 if(!(!strchr(filename, '*') && !strchr(filename, '?') && 116 !strchr(filename, '[') && !strchr(filename, '{') && 117 !strchr(filename, '~'))) { 118 flags = 0 119#ifdef GLOB_ERR 120 | GLOB_ERR 121#endif 122 /* do not set GLOB_NOSORT so the results are sorted 123 and in a predictable order. */ 124#ifdef GLOB_BRACE 125 | GLOB_BRACE 126#endif 127#ifdef GLOB_TILDE 128 | GLOB_TILDE 129#endif 130 ; 131 memset(&g, 0, sizeof(g)); 132 r = glob(filename, flags, NULL, &g); 133 if(r) { 134 /* some error */ 135 globfree(&g); 136 if(r == GLOB_NOMATCH) 137 return; /* no matches for pattern */ 138 config_start_include(filename); /* let original deal with it */ 139 return; 140 } 141 /* process files found, if any */ 142 for(i=(int)g.gl_pathc-1; i>=0; i--) { 143 config_start_include(g.gl_pathv[i]); 144 } 145 globfree(&g); 146 return; 147 } 148#endif /* HAVE_GLOB */ 149 config_start_include(filename); 150} 151 152static void config_end_include(void) 153{ 154 struct inc_state* s = config_include_stack; 155 --inc_depth; 156 if(!s) return; 157 free(cfg_parser->filename); 158 cfg_parser->filename = s->filename; 159 cfg_parser->line = s->line; 160 yy_delete_buffer(YY_CURRENT_BUFFER); 161 yy_switch_to_buffer(s->buffer); 162 config_include_stack = s->next; 163 free(s); 164} 165 166#ifndef yy_set_bol /* compat definition, for flex 2.4.6 */ 167#define yy_set_bol(at_bol) \ 168 { \ 169 if ( ! yy_current_buffer ) \ 170 yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ 171 yy_current_buffer->yy_ch_buf[0] = ((at_bol)?'\n':' '); \ 172 } 173#endif 174 175%} 176%option noinput 177%option nounput 178%{ 179#ifndef YY_NO_UNPUT 180#define YY_NO_UNPUT 1 181#endif 182#ifndef YY_NO_INPUT 183#define YY_NO_INPUT 1 184#endif 185%} 186 187SPACE [ \t] 188LETTER [a-zA-Z] 189UNQUOTEDLETTER [^\"\n\r \t\\]|\\. 190NEWLINE [\r\n] 191COMMENT \# 192COLON \: 193ANY [^\"\n\r\\]|\\. 194 195%x quotedstring include include_quoted 196 197%% 198{SPACE}* { LEXOUT(("SP ")); /* ignore */ } 199{SPACE}*{COMMENT}.* { LEXOUT(("comment(%s) ", yytext)); /* ignore */ } 200server{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_SERVER;} 201name{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_NAME;} 202ip-address{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_IP_ADDRESS;} 203interface{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_IP_ADDRESS;} 204ip-transparent{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_IP_TRANSPARENT;} 205ip-freebind{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_IP_FREEBIND;} 206send-buffer-size{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_SEND_BUFFER_SIZE;} 207receive-buffer-size{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RECEIVE_BUFFER_SIZE;} 208debug-mode{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DEBUG_MODE;} 209use-systemd{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_USE_SYSTEMD;} 210hide-version{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_HIDE_VERSION;} 211hide-identity{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_HIDE_IDENTITY;} 212ip4-only{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_IP4_ONLY;} 213ip6-only{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_IP6_ONLY;} 214do-ip4{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DO_IP4;} 215do-ip6{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DO_IP6;} 216database{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DATABASE;} 217identity{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_IDENTITY;} 218version{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_VERSION;} 219nsid{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_NSID;} 220logfile{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_LOGFILE;} 221server-count{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_SERVER_COUNT;} 222tcp-count{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TCP_COUNT;} 223tcp-reject-overflow{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TCP_REJECT_OVERFLOW;} 224tcp-query-count{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TCP_QUERY_COUNT;} 225tcp-timeout{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TCP_TIMEOUT;} 226tcp-mss{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TCP_MSS;} 227outgoing-tcp-mss{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_OUTGOING_TCP_MSS;} 228ipv4-edns-size{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_IPV4_EDNS_SIZE;} 229ipv6-edns-size{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_IPV6_EDNS_SIZE;} 230pidfile{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_PIDFILE;} 231port{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_PORT;} 232reuseport{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_REUSEPORT;} 233statistics{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_STATISTICS;} 234chroot{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_CHROOT;} 235username{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_USERNAME;} 236zonesdir{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ZONESDIR;} 237zonelistfile{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ZONELISTFILE;} 238difffile{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DIFFFILE;} 239xfrdfile{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_XFRDFILE;} 240xfrdir{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_XFRDIR;} 241xfrd-reload-timeout{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_XFRD_RELOAD_TIMEOUT;} 242verbosity{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_VERBOSITY;} 243zone{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ZONE;} 244zonefile{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ZONEFILE;} 245zonestats{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ZONESTATS;} 246allow-notify{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ALLOW_NOTIFY;} 247size-limit-xfr{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_SIZE_LIMIT_XFR;} 248request-xfr{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_REQUEST_XFR;} 249notify{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_NOTIFY;} 250notify-retry{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_NOTIFY_RETRY;} 251provide-xfr{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_PROVIDE_XFR;} 252outgoing-interface{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_OUTGOING_INTERFACE;} 253allow-axfr-fallback{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ALLOW_AXFR_FALLBACK;} 254key{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_KEY;} 255algorithm{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ALGORITHM;} 256secret{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_SECRET;} 257pattern{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_PATTERN;} 258include-pattern{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_INCLUDE_PATTERN;} 259remote-control{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_REMOTE_CONTROL;} 260control-enable{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_CONTROL_ENABLE;} 261control-interface{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_CONTROL_INTERFACE;} 262control-port{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_CONTROL_PORT;} 263server-key-file{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_SERVER_KEY_FILE;} 264server-cert-file{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_SERVER_CERT_FILE;} 265control-key-file{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_CONTROL_KEY_FILE;} 266control-cert-file{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_CONTROL_CERT_FILE;} 267AXFR { LEXOUT(("v(%s) ", yytext)); return VAR_AXFR;} 268UDP { LEXOUT(("v(%s) ", yytext)); return VAR_UDP;} 269rrl-size{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RRL_SIZE;} 270rrl-ratelimit{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RRL_RATELIMIT;} 271rrl-slip{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RRL_SLIP;} 272rrl-ipv4-prefix-length{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RRL_IPV4_PREFIX_LENGTH;} 273rrl-ipv6-prefix-length{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RRL_IPV6_PREFIX_LENGTH;} 274rrl-whitelist-ratelimit{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RRL_WHITELIST_RATELIMIT;} 275rrl-whitelist{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RRL_WHITELIST;} 276zonefiles-check{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ZONEFILES_CHECK;} 277zonefiles-write{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ZONEFILES_WRITE;} 278dnstap{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP;} 279dnstap-enable{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_ENABLE;} 280dnstap-socket-path{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_SOCKET_PATH; } 281dnstap-send-identity{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_SEND_IDENTITY; } 282dnstap-send-version{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_SEND_VERSION; } 283dnstap-identity{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_IDENTITY; } 284dnstap-version{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_VERSION; } 285dnstap-log-auth-query-messages{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_LOG_AUTH_QUERY_MESSAGES; } 286dnstap-log-auth-response-messages{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_LOG_AUTH_RESPONSE_MESSAGES; } 287log-time-ascii{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_LOG_TIME_ASCII;} 288round-robin{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ROUND_ROBIN;} 289minimal-responses{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_MINIMAL_RESPONSES;} 290confine-to-zone{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_CONFINE_TO_ZONE;} 291refuse-any{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_REFUSE_ANY;} 292max-refresh-time{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_MAX_REFRESH_TIME;} 293min-refresh-time{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_MIN_REFRESH_TIME;} 294max-retry-time{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_MAX_RETRY_TIME;} 295min-retry-time{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_MIN_RETRY_TIME;} 296multi-master-check{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_MULTI_MASTER_CHECK;} 297tls-service-key{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TLS_SERVICE_KEY;} 298tls-service-ocsp{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TLS_SERVICE_OCSP;} 299tls-service-pem{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TLS_SERVICE_PEM;} 300tls-port{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TLS_PORT;} 301{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++;} 302 303 /* Quoted strings. Strip leading and ending quotes */ 304\" { BEGIN(quotedstring); LEXOUT(("QS ")); } 305<quotedstring><<EOF>> { 306 yyerror("EOF inside quoted string"); 307 BEGIN(INITIAL); 308} 309<quotedstring>{ANY}* { LEXOUT(("STR(%s) ", yytext)); yymore(); } 310<quotedstring>\n { cfg_parser->line++; yymore(); } 311<quotedstring>\" { 312 LEXOUT(("QE ")); 313 BEGIN(INITIAL); 314 yytext[yyleng - 1] = '\0'; 315 yylval.str = region_strdup(cfg_parser->opt->region, yytext); 316 return STRING; 317} 318 319 /* include: directive */ 320include{COLON} { LEXOUT(("v(%s) ", yytext)); BEGIN(include); } 321<include><<EOF>> { 322 yyerror("EOF inside include directive"); 323 BEGIN(INITIAL); 324} 325<include>{SPACE}* { LEXOUT(("ISP ")); /* ignore */ } 326<include>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++;} 327<include>\" { LEXOUT(("IQS ")); BEGIN(include_quoted); } 328<include>{UNQUOTEDLETTER}* { 329 LEXOUT(("Iunquotedstr(%s) ", yytext)); 330 config_start_include_glob(yytext); 331 BEGIN(INITIAL); 332} 333<include_quoted><<EOF>> { 334 yyerror("EOF inside quoted string"); 335 BEGIN(INITIAL); 336} 337<include_quoted>{ANY}* { LEXOUT(("ISTR(%s) ", yytext)); yymore(); } 338<include_quoted>{NEWLINE} { cfg_parser->line++; yymore(); } 339<include_quoted>\" { 340 LEXOUT(("IQE ")); 341 yytext[yyleng - 1] = '\0'; 342 config_start_include_glob(yytext); 343 BEGIN(INITIAL); 344} 345<INITIAL><<EOF>> { 346 yy_set_bol(1); /* Set beginning of line, so "^" rules match. */ 347 if (!config_include_stack) { 348 yyterminate(); 349 } else { 350 fclose(yyin); 351 config_end_include(); 352 } 353} 354 355{UNQUOTEDLETTER}* { LEXOUT(("unquotedstr(%s) ", yytext)); 356 yylval.str = region_strdup(cfg_parser->opt->region, yytext); return STRING; } 357 358%% 359