/* $KAME: cftoken.l,v 1.35 2005/01/12 06:06:11 suz Exp $ */ %{ /* * Copyright (C) 2002 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #ifdef HAVE_STDARG_H #include #else #include #endif #include "dhcp6.h" #include "config.h" #include "common.h" #include "y.tab.h" #define YY_NO_UNPUT 1 char *configfilename; int lineno = 1; /* Recursion limit for includes */ #define MAX_INCLUDE_DEPTH 10 static struct include_stack { char *path; YY_BUFFER_STATE state; int lineno; } incstack[MAX_INCLUDE_DEPTH]; int incstackp = 0; static int yy_first_time = 1; static int yyerrorcount = 0; #ifndef NOCONFIG_DEBUG #define YYDEBUG 1 int cfdebug = 1; #else int cfdebug = 0; #endif extern int yyparse __P((void)); extern int cf_post_config __P((void)); static void cfdebug_print __P((char *, char *, int)); #define DP(str) if (cfdebug) cfdebug_print(str, yytext, yyleng) #define DECHO if (cfdebug) cfdebug_print(NULL, yytext, yyleng); #define DNOECHO if (cfdebug) cfdebug_print(NULL, "****", yyleng); %} /* abbreviations */ nl \n ws [ \t]+ comma , comment \#.* semi \; quotedstring \"[^\"]*\" string [a-zA-Z0-9:\._\-][a-zA-Z0-9:\._\-]* digit [0-9] integer {digit}+ number {integer}|({digit}*\.{integer}) hexdigit [0-9A-Fa-f] hexpair {hexdigit}{hexdigit} hexstring 0[xX]{hexpair}+ duid {hexpair}(:{hexpair})* ifname {string} slash \/ bcl \{ ecl \} %s S_CNF %s S_IFACE %s S_PROFILE %s S_PREF %s S_HOST %s S_DUID %s S_IA %s S_AUTH %s S_KEY %s S_SECRET %s S_ADDRPOOL %s S_INCL %% %{ if (yy_first_time) { BEGIN S_CNF; yy_first_time = 0; } %} /* interface configuration */ interface { DECHO; BEGIN S_IFACE; return (INTERFACE); } {ifname} { DECHO; yylval.str = strdup(yytext); BEGIN S_CNF; return (IFNAME); } /* profile configuration */ profile { DECHO; BEGIN S_PROFILE; return (PROFILE); } {string} { DECHO; yylval.str = strdup(yytext); BEGIN S_CNF; return (PROFILENAME); } /* host configuration */ host { DECHO; BEGIN S_HOST; return (HOST); } {string} { DECHO; yylval.str = strdup(yytext); BEGIN S_CNF; return (HOSTNAME); } /* address pool configuration */ pool { DECHO; BEGIN S_ADDRPOOL; return (ADDRPOOL); } {string} { DECHO; yylval.str = strdup(yytext); BEGIN S_CNF; return (POOLNAME); } duid { DECHO; BEGIN S_DUID; return (DUID); } {duid} { DECHO; yylval.str = strdup(yytext); BEGIN S_CNF; return (DUID_ID); } address { DECHO; return (ADDRESS); } prefix { DECHO; return (PREFIX); } preference { DECHO; return (PREFERENCE); } script { DECHO; return (SCRIPT); } delayedkey { DECHO; return (DELAYEDKEY); } /* request */ request { DECHO; return (REQUEST); } /* send */ send { DECHO; return (SEND); } /* range */ range { DECHO; return (RANGE); } to { DECHO; return (TO); } /* address-pool */ address-pool { DECHO; return (ADDRESS_POOL); } /* DHCP options */ option { DECHO; return (OPTION); } rapid-commit { DECHO; return (RAPID_COMMIT); } ia-pd { DECHO; return (IA_PD); } ia-na { DECHO; return (IA_NA); } domain-name-servers { DECHO; return (DNS_SERVERS); } domain-name { DECHO; return (DNS_NAME); } sip-server-address { DECHO; return (SIP_SERVERS); } sip-server-domain-name { DECHO; return (SIP_NAME); } ntp-servers { DECHO; return (NTP_SERVERS); } nis-server-address { DECHO; return (NIS_SERVERS); } nis-domain-name { DECHO; return (NIS_NAME); } nisp-server-address { DECHO; return (NISP_SERVERS); } nisp-domain-name { DECHO; return (NISP_NAME); } bcmcs-server-address { DECHO; return (BCMCS_SERVERS); } bcmcs-server-domain-name { DECHO; return (BCMCS_NAME); } refreshtime { DECHO; return (REFRESHTIME); } /* provided for a backward compatibility to WIDE-DHCPv6 before Oct 1 2006 */ nis-server-domain-name { DECHO; return (NIS_NAME); } nisp-server-domain-name { DECHO; return (NISP_NAME); } /* generic options */ information-only { DECHO; return (INFO_ONLY); } allow { DECHO; return (ALLOW); } /* identity association */ id-assoc { DECHO; BEGIN S_IA; return(ID_ASSOC); } pd { DECHO; return(IA_PD); } na { DECHO; return(IA_NA); } {number} { DECHO; yylval.str = strdup(yytext); return(IAID); } {bcl} { DP("begin of closure"); BEGIN S_CNF; return (BCL); } /* * interface parameters for delegated prefix configuration. * when lex reads an interface name, the state will be back to * S_CNF. */ prefix-interface { DECHO; BEGIN S_IFACE; return (PREFIX_INTERFACE); } sla-id { DECHO; return (SLA_ID); } sla-len { DECHO; return (SLA_LEN); } ifid { DECHO; return (IFID); } /* duration */ infinity { DECHO; return (INFINITY); } /* authentication option */ authentication { DECHO; BEGIN S_AUTH; return (AUTHENTICATION); } {string} { DECHO; yylval.str = strdup(yytext); BEGIN S_CNF; return (AUTHNAME); } /* authentication parameters */ protocol { DECHO; return (PROTOCOL); }; algorithm { DECHO; return (ALGORITHM); }; rdm { DECHO; return (RDM); }; key { DECHO; return (KEY); }; /* authentication protocols */ delayed { DECHO; return (DELAYED); }; reconfig { DECHO; return (RECONFIG); }; /* authentication algorithms */ hmac-md5 { DECHO; return (HMACMD5); }; HMAC-MD5 { DECHO; return (HMACMD5); }; hmacmd5 { DECHO; return (HMACMD5); }; HMACMD5 { DECHO; return (HMACMD5); }; /* authentication RDM */ monocounter { DECHO; return (MONOCOUNTER); }; /* secret keys */ keyinfo { DECHO; BEGIN S_KEY; return (KEYINFO); } {string} { DECHO; yylval.str = strdup(yytext); BEGIN S_CNF; return (KEYNAME); } /* key parameters */ realm { DECHO; return (REALM); } keyid { DECHO; return (KEYID); } secret { DECHO; BEGIN S_SECRET; return (SECRET); } {quotedstring} { DNOECHO; yylval.str = strdup(yytext); BEGIN S_CNF; return (QSTRING); } expire { DECHO; return (EXPIRE); } /* include */ include { DECHO; BEGIN S_INCL; return (INCLUDE); } {quotedstring} { DECHO; yylval.str = strdup(yytext); BEGIN S_CNF; return (QSTRING); } /* quoted string */ {quotedstring} { DECHO; yylval.str = strdup(yytext); return (QSTRING); } /* misc */ {ws} { ; } {nl} { lineno++; } {comment} { DP("comment"); } {number} { DECHO; yylval.num = strtoll(yytext, NULL, 10); return (NUMBER); } {slash} { DECHO; return (SLASH); } {comma} { DECHO; return (COMMA); } {semi} { DP("end of sentence"); return (EOS); } {bcl} { DP("begin of closure"); return (BCL); } {ecl} { DP("end of closure"); return (ECL); } /* generic string */ {string} { DECHO; yylval.str = strdup(yytext); return (STRING); } <> { if (--incstackp < 0) yyterminate(); else { yy_delete_buffer(YY_CURRENT_BUFFER); free(incstack[incstackp + 1].path); configfilename = incstack[incstackp].path; lineno = incstack[incstackp].lineno; yy_switch_to_buffer(incstack[incstackp].state); } } %% static void cfdebug_print(w, t, l) char *w, *t; int l; { if (w) { debug_printf(LOG_DEBUG, FNAME, "<%d>%s [%s] (%d)", yy_start, w, t, l); } else { debug_printf(LOG_DEBUG, FNAME, "<%d>[%s] (%d)", yy_start, t, l); } } static void yyerror0(int level, char *s, va_list ap) { char ebuf[BUFSIZ], *bp, *ep; bp = ebuf; ep = ebuf + sizeof(ebuf); bp += snprintf(bp, ep - bp, "%s %d: ", configfilename, lineno); if (bp < ep) bp += vsnprintf(bp, ep - bp, s, ap); debug_printf(level, FNAME, ebuf); } void yyerror(char *s, ...) { va_list ap; #ifdef HAVE_STDARG_H va_start(ap, s); #else va_start(ap); #endif yyerror0(LOG_ERR, s, ap); va_end(ap); yyerrorcount++; } void yywarn(char *s, ...) { va_list ap; #ifdef HAVE_STDARG_H va_start(ap, s); #else va_start(ap); #endif yyerror0(LOG_WARNING, s, ap); va_end(ap); } int cfswitch_buffer(incl) char *incl; { char *path = qstrdup(incl); FILE *fp; if (incstackp >= MAX_INCLUDE_DEPTH) { debug_printf(LOG_ERR, FNAME, "cfparse: includes nested too deeply"); return (-1); } incstack[incstackp].path = configfilename; incstack[incstackp].state = YY_CURRENT_BUFFER; incstack[incstackp].lineno = lineno; fp = fopen(path, "r"); if (fp == NULL) { debug_printf(LOG_ERR, FNAME, "cfparse: fopen(%s): %s", path, strerror(errno)); if (errno == ENOENT) return (0); return (-1); } incstackp++; configfilename = path; lineno = 1; yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); BEGIN(S_CNF); return (0); } int cfparse(conf) char *conf; { configfilename = conf; if ((yyin = fopen(configfilename, "r")) == NULL) { debug_printf(LOG_ERR, FNAME, "cfparse: fopen(%s): %s", configfilename, strerror(errno)); if (errno == ENOENT) return (0); return (-1); } if (yyparse() || yyerrorcount) { if (yyerrorcount) { yyerror("fatal parse failure: exiting (%d errors)", yyerrorcount); } else yyerror("fatal parse failure: exiting"); return (-1); } return (cf_post_config()); }