#include <sys/cdefs.h>
#ifndef lint
#if 0
static char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93";
#else
__IDSTRING(yyrcsid, "$NetBSD: skeleton.c,v 1.14 1997/10/20 03:41:16 lukem Exp $");
#endif
#endif
#include <stdlib.h>
#define YYBYACC 1
#define YYMAJOR 1
#define YYMINOR 9
#define YYLEX yylex()
#define YYEMPTY -1
#define yyclearin (yychar=(YYEMPTY))
#define yyerrok (yyerrflag=0)
#define YYRECOVERING (yyerrflag!=0)
#define YYPREFIX "yy"
#line 25 "parse.y"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <ifaddrs.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "ospf.h"
#include "ospfd.h"
#include "ospfe.h"
#include "log.h"
static struct ospfd_conf *conf;
static FILE *fin = NULL;
static int lineno = 1;
static int errors = 0;
static int pdebug = 1;
char *infile;
char *start_state;
struct area *area = NULL;
struct iface *iface = NULL;
int yyerror(const char *, ...);
int yyparse(void);
int kw_cmp(const void *, const void *);
int lookup(char *);
int lgetc(FILE *);
int lungetc(int);
int findeol(void);
int yylex(void);
void clear_config(struct ospfd_conf *xconf);
int check_file_secrecy(int fd, const char *fname);
u_int32_t get_rtr_id(void);
int host(const char *, struct in_addr *, struct in_addr *);
struct config_defaults {
char auth_key[MAX_SIMPLE_AUTH_LEN];
struct auth_md_head md_list;
u_int32_t dead_interval;
u_int16_t transmit_delay;
u_int16_t hello_interval;
u_int16_t rxmt_interval;
u_int16_t metric;
enum auth_type auth_type;
u_int8_t auth_keyid;
u_int8_t priority;
};
struct config_defaults globaldefs;
struct config_defaults areadefs;
struct config_defaults ifacedefs;
struct config_defaults *defs;
TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
struct sym {
TAILQ_ENTRY(sym) entries;
int used;
int persist;
char *nam;
char *val;
};
int symset(const char *, const char *, int);
char *symget(const char *);
int atoul(char *, u_long *);
struct area *conf_get_area(struct in_addr);
struct iface *conf_get_if(struct kif *);
typedef struct {
union {
u_int32_t number;
char *string;
} v;
int lineno;
} YYSTYPE;
#line 104 "parse.c"
#define AREA 257
#define INTERFACE 258
#define ROUTERID 259
#define FIBUPDATE 260
#define REDISTRIBUTE 261
#define RTLABEL 262
#define RFC1583COMPAT 263
#define SPFDELAY 264
#define SPFHOLDTIME 265
#define AUTHKEY 266
#define AUTHTYPE 267
#define AUTHMD 268
#define AUTHMDKEYID 269
#define METRIC 270
#define PASSIVE 271
#define HELLOINTERVAL 272
#define TRANSMITDELAY 273
#define RETRANSMITINTERVAL 274
#define ROUTERDEADTIME 275
#define ROUTERPRIORITY 276
#define YES 277
#define NO 278
#define ERROR 279
#define STRING 280
#define YYERRCODE 256
short yylhs[] = { -1,
0, 0, 0, 0, 0, 0, 1, 4, 4, 2,
2, 3, 3, 6, 5, 5, 5, 5, 5, 5,
5, 5, 9, 10, 11, 12, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 13, 13, 14, 15,
7, 16, 16, 17, 17, 20, 18, 19, 19, 19,
21, 21, 22, 22,
};
short yylen[] = { 2,
0, 2, 3, 3, 3, 3, 1, 2, 1, 1,
1, 0, 1, 3, 2, 2, 3, 4, 2, 2,
2, 1, 3, 2, 2, 2, 2, 2, 2, 2,
2, 2, 1, 1, 1, 1, 2, 0, 2, 0,
7, 2, 1, 2, 2, 0, 4, 4, 3, 0,
2, 1, 2, 2,
};
short yydefred[] = { 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 13, 0,
2, 0, 0, 0, 0, 22, 36, 35, 33, 34,
6, 40, 15, 10, 11, 16, 19, 7, 20, 21,
26, 25, 0, 24, 27, 31, 30, 32, 29, 28,
0, 0, 3, 4, 5, 0, 23, 9, 0, 0,
17, 0, 8, 18, 0, 0, 37, 0, 0, 0,
43, 0, 46, 0, 45, 41, 42, 44, 0, 39,
0, 47, 0, 0, 49, 0, 0, 52, 53, 54,
48, 51,
};
short yydgoto[] = { 1,
39, 36, 22, 59, 23, 24, 25, 69, 27, 28,
29, 30, 66, 75, 56, 70, 71, 72, 82, 79,
87, 88,
};
short yysindex[] = { 0,
-10, -5, -271, -270, -274, -274, -269, -269, -268, -267,
-269, -269, -269, -269, -269, -269, -269, -269, 0, -55,
0, -247, 17, 18, 20, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, -248, 0, 0, 0, 0, 0, 0, 0,
-246, -254, 0, 0, 0, -90, 0, 0, -245, -244,
0, 40, 0, 0, 40, -251, 0, -228, 41, -105,
0, 41, 0, 40, 0, 0, 0, 0, -69, 0,
40, 0, -94, 41, 0, 41, -83, 0, 0, 0,
0, 0,
};
short yyrindex[] = { 0,
-206, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 46, 0,
0, -229, 0, 0, -124, 0, 0, 0, 0, 0,
0, 0, 0, -124, 0, 0, 0, 0, 48, 0,
-72, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
};
short yygindex[] = { 0,
54, 53, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, -17, -23, 0, 0, 3, 0, 0, 0,
0, -27,
};
#define YYTABLESIZE 270
short yytable[] = { 21,
38, 26, 34, 35, 31, 51, 68, 60, 32, 33,
38, 41, 42, 52, 9, 10, 11, 12, 13, 76,
14, 15, 16, 17, 18, 61, 53, 54, 38, 55,
85, 57, 62, 58, 63, 64, 38, 38, 38, 38,
38, 91, 38, 38, 38, 38, 38, 67, 78, 65,
74, 73, 38, 81, 12, 14, 80, 50, 37, 92,
89, 40, 90, 83, 43, 44, 45, 46, 47, 48,
49, 50, 77, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 86, 0, 0, 0, 86, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 38, 0, 0, 0, 0, 0, 0,
0, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 68, 0, 0, 0, 0, 0, 0, 0,
9, 10, 11, 12, 13, 0, 14, 15, 16, 17,
18, 9, 10, 11, 12, 13, 84, 14, 15, 16,
17, 18, 9, 10, 11, 12, 13, 84, 14, 15,
16, 17, 18, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 2, 3, 0, 4, 5,
0, 0, 6, 7, 8, 9, 10, 11, 12, 13,
0, 14, 15, 16, 17, 18, 0, 19, 0, 20,
};
short yycheck[] = { 10,
125, 1, 277, 278, 10, 61, 258, 262, 280, 280,
280, 280, 280, 261, 266, 267, 268, 269, 270, 125,
272, 273, 274, 275, 276, 280, 10, 10, 258, 10,
125, 280, 123, 280, 280, 280, 266, 267, 268, 269,
270, 125, 272, 273, 274, 275, 276, 65, 72, 10,
10, 280, 125, 123, 261, 10, 74, 10, 6, 87,
84, 8, 86, 81, 11, 12, 13, 14, 15, 16,
17, 18, 70, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 83, -1, -1, -1, 87, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 258, -1, -1, -1, -1, -1, -1,
-1, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 258, -1, -1, -1, -1, -1, -1, -1,
266, 267, 268, 269, 270, -1, 272, 273, 274, 275,
276, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 266, 267, 268, 269, 270, 271, 272, 273,
274, 275, 276, 266, 267, 268, 269, 270, 271, 272,
273, 274, 275, 276, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 256, 257, -1, 259, 260,
-1, -1, 263, 264, 265, 266, 267, 268, 269, 270,
-1, 272, 273, 274, 275, 276, -1, 278, -1, 280,
};
#define YYFINAL 1
#ifndef YYDEBUG
#define YYDEBUG 0
#endif
#define YYMAXTOKEN 280
#if YYDEBUG
char *yyname[] = {
"end-of-file",0,0,0,0,0,0,0,0,0,"'\\n'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'='",0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'{'",0,"'}'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"AREA",
"INTERFACE","ROUTERID","FIBUPDATE","REDISTRIBUTE","RTLABEL","RFC1583COMPAT",
"SPFDELAY","SPFHOLDTIME","AUTHKEY","AUTHTYPE","AUTHMD","AUTHMDKEYID","METRIC",
"PASSIVE","HELLOINTERVAL","TRANSMITDELAY","RETRANSMITINTERVAL","ROUTERDEADTIME",
"ROUTERPRIORITY","YES","NO","ERROR","STRING",
};
char *yyrule[] = {
"$accept : grammar",
"grammar :",
"grammar : grammar '\\n'",
"grammar : grammar conf_main '\\n'",
"grammar : grammar varset '\\n'",
"grammar : grammar area '\\n'",
"grammar : grammar error '\\n'",
"number : STRING",
"string : string STRING",
"string : STRING",
"yesno : YES",
"yesno : NO",
"no :",
"no : NO",
"varset : STRING '=' string",
"conf_main : ROUTERID STRING",
"conf_main : FIBUPDATE yesno",
"conf_main : no REDISTRIBUTE STRING",
"conf_main : no REDISTRIBUTE RTLABEL STRING",
"conf_main : RFC1583COMPAT yesno",
"conf_main : SPFDELAY number",
"conf_main : SPFHOLDTIME number",
"conf_main : defaults",
"authmd : AUTHMD number STRING",
"authmdkeyid : AUTHMDKEYID number",
"authtype : AUTHTYPE STRING",
"authkey : AUTHKEY STRING",
"defaults : METRIC number",
"defaults : ROUTERPRIORITY number",
"defaults : ROUTERDEADTIME number",
"defaults : TRANSMITDELAY number",
"defaults : HELLOINTERVAL number",
"defaults : RETRANSMITINTERVAL number",
"defaults : authtype",
"defaults : authkey",
"defaults : authmdkeyid",
"defaults : authmd",
"optnl : '\\n' optnl",
"optnl :",
"nl : '\\n' optnl",
"$$1 :",
"area : AREA STRING $$1 '{' optnl areaopts_l '}'",
"areaopts_l : areaopts_l areaoptsl",
"areaopts_l : areaoptsl",
"areaoptsl : interface nl",
"areaoptsl : defaults nl",
"$$2 :",
"interface : INTERFACE STRING $$2 interface_block",
"interface_block : '{' optnl interfaceopts_l '}'",
"interface_block : '{' optnl '}'",
"interface_block :",
"interfaceopts_l : interfaceopts_l interfaceoptsl",
"interfaceopts_l : interfaceoptsl",
"interfaceoptsl : PASSIVE nl",
"interfaceoptsl : defaults nl",
};
#endif
#ifdef YYSTACKSIZE
#undef YYMAXDEPTH
#define YYMAXDEPTH YYSTACKSIZE
#else
#ifdef YYMAXDEPTH
#define YYSTACKSIZE YYMAXDEPTH
#else
#define YYSTACKSIZE 10000
#define YYMAXDEPTH 10000
#endif
#endif
#define YYINITSTACKSIZE 200
int yydebug;
int yynerrs;
int yyerrflag;
int yychar;
short *yyssp;
YYSTYPE *yyvsp;
YYSTYPE yyval;
YYSTYPE yylval;
short *yyss;
short *yysslim;
YYSTYPE *yyvs;
int yystacksize;
#line 467 "parse.y"
struct keywords {
const char *k_name;
int k_val;
};
int
yyerror(const char *fmt, ...)
{
va_list ap;
errors = 1;
va_start(ap, fmt);
fprintf(stderr, "%s:%d: ", infile, yylval.lineno);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
return (0);
}
int
kw_cmp(const void *k, const void *e)
{
return (strcmp(k, ((const struct keywords *)e)->k_name));
}
int
lookup(char *s)
{
/* this has to be sorted always */
static const struct keywords keywords[] = {
{"area", AREA},
{"auth-key", AUTHKEY},
{"auth-md", AUTHMD},
{"auth-md-keyid", AUTHMDKEYID},
{"auth-type", AUTHTYPE},
{"fib-update", FIBUPDATE},
{"hello-interval", HELLOINTERVAL},
{"interface", INTERFACE},
{"metric", METRIC},
{"no", NO},
{"passive", PASSIVE},
{"redistribute", REDISTRIBUTE},
{"retransmit-interval", RETRANSMITINTERVAL},
{"rfc1583compat", RFC1583COMPAT},
{"router-dead-time", ROUTERDEADTIME},
{"router-id", ROUTERID},
{"router-priority", ROUTERPRIORITY},
{"rtlabel", RTLABEL},
{"spf-delay", SPFDELAY},
{"spf-holdtime", SPFHOLDTIME},
{"transmit-delay", TRANSMITDELAY},
{"yes", YES}
};
const struct keywords *p;
p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
sizeof(keywords[0]), kw_cmp);
if (p) {
if (pdebug > 1)
fprintf(stderr, "%s: %d\n", s, p->k_val);
return (p->k_val);
} else {
if (pdebug > 1)
fprintf(stderr, "string: %s\n", s);
return (STRING);
}
}
#define MAXPUSHBACK 128
char *parsebuf;
int parseindex;
char pushback_buffer[MAXPUSHBACK];
int pushback_index = 0;
int
lgetc(FILE *f)
{
int c, next;
if (parsebuf) {
/* Read character from the parsebuffer instead of input. */
if (parseindex >= 0) {
c = parsebuf[parseindex++];
if (c != '\0')
return (c);
parsebuf = NULL;
} else
parseindex++;
}
if (pushback_index)
return (pushback_buffer[--pushback_index]);
while ((c = getc(f)) == '\\') {
next = getc(f);
if (next != '\n') {
c = next;
break;
}
yylval.lineno = lineno;
lineno++;
}
if (c == '\t' || c == ' ') {
/* Compress blanks to a single space. */
do {
c = getc(f);
} while (c == '\t' || c == ' ');
ungetc(c, f);
c = ' ';
}
return (c);
}
int
lungetc(int c)
{
if (c == EOF)
return (EOF);
if (parsebuf) {
parseindex--;
if (parseindex >= 0)
return (c);
}
if (pushback_index < MAXPUSHBACK-1)
return (pushback_buffer[pushback_index++] = c);
else
return (EOF);
}
int
findeol(void)
{
int c;
parsebuf = NULL;
pushback_index = 0;
/* skip to either EOF or the first real EOL */
while (1) {
c = lgetc(fin);
if (c == '\n') {
lineno++;
break;
}
if (c == EOF)
break;
}
return (ERROR);
}
int
yylex(void)
{
char buf[8096];
char *p, *val;
int endc, c;
int token;
top:
p = buf;
while ((c = lgetc(fin)) == ' ')
; /* nothing */
yylval.lineno = lineno;
if (c == '#')
while ((c = lgetc(fin)) != '\n' && c != EOF)
; /* nothing */
if (c == '$' && parsebuf == NULL) {
while (1) {
if ((c = lgetc(fin)) == EOF)
return (0);
if (p + 1 >= buf + sizeof(buf) - 1) {
yyerror("string too long");
return (findeol());
}
if (isalnum(c) || c == '_') {
*p++ = (char)c;
continue;
}
*p = '\0';
lungetc(c);
break;
}
val = symget(buf);
if (val == NULL) {
yyerror("macro '%s' not defined", buf);
return (findeol());
}
parsebuf = val;
parseindex = 0;
goto top;
}
switch (c) {
case '\'':
case '"':
endc = c;
while (1) {
if ((c = lgetc(fin)) == EOF)
return (0);
if (c == endc) {
*p = '\0';
break;
}
if (c == '\n') {
lineno++;
continue;
}
if (p + 1 >= buf + sizeof(buf) - 1) {
yyerror("string too long");
return (findeol());
}
*p++ = (char)c;
}
yylval.v.string = strdup(buf);
if (yylval.v.string == NULL)
errx(1, "yylex: strdup");
return (STRING);
}
#define allowed_in_string(x) \
(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
x != '{' && x != '}' && \
x != '!' && x != '=' && x != '#' && \
x != ','))
if (isalnum(c) || c == ':' || c == '_') {
do {
*p++ = c;
if ((unsigned)(p-buf) >= sizeof(buf)) {
yyerror("string too long");
return (findeol());
}
} while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
lungetc(c);
*p = '\0';
if ((token = lookup(buf)) == STRING)
if ((yylval.v.string = strdup(buf)) == NULL)
err(1, "yylex: strdup");
return (token);
}
if (c == '\n') {
yylval.lineno = lineno;
lineno++;
}
if (c == EOF)
return (0);
return (c);
}
struct ospfd_conf *
parse_config(char *filename, int opts)
{
struct sym *sym, *next;
if ((conf = calloc(1, sizeof(struct ospfd_conf))) == NULL)
fatal("parse_config");
bzero(&globaldefs, sizeof(globaldefs));
defs = &globaldefs;
TAILQ_INIT(&defs->md_list);
defs->dead_interval = DEFAULT_RTR_DEAD_TIME;
defs->transmit_delay = DEFAULT_TRANSMIT_DELAY;
defs->hello_interval = DEFAULT_HELLO_INTERVAL;
defs->rxmt_interval = DEFAULT_RXMT_INTERVAL;
defs->metric = DEFAULT_METRIC;
defs->priority = DEFAULT_PRIORITY;
conf->options = OSPF_OPTION_E;
conf->spf_delay = DEFAULT_SPF_DELAY;
conf->spf_hold_time = DEFAULT_SPF_HOLDTIME;
conf->spf_state = SPF_IDLE;
if ((fin = fopen(filename, "r")) == NULL) {
warn("%s", filename);
free(conf);
return (NULL);
}
infile = filename;
conf->opts = opts;
LIST_INIT(&conf->area_list);
LIST_INIT(&conf->cand_list);
STAILQ_INIT(&conf->redist_list);
if (!(conf->opts & OSPFD_OPT_NOACTION))
if (check_file_secrecy(fileno(fin), filename)) {
fclose(fin);
free(conf);
return (NULL);
}
yyparse();
fclose(fin);
/* Free macros and check which have not been used. */
for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
next = TAILQ_NEXT(sym, entries);
if ((conf->opts & OSPFD_OPT_VERBOSE2) && !sym->used)
fprintf(stderr, "warning: macro '%s' not "
"used\n", sym->nam);
if (!sym->persist) {
free(sym->nam);
free(sym->val);
TAILQ_REMOVE(&symhead, sym, entries);
free(sym);
}
}
/* free global config defaults */
md_list_clr(&globaldefs.md_list);
if (errors) {
clear_config(conf);
return (NULL);
}
if (conf->rtr_id.s_addr == 0)
conf->rtr_id.s_addr = get_rtr_id();
return (conf);
}
int
symset(const char *nam, const char *val, int persist)
{
struct sym *sym;
for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
sym = TAILQ_NEXT(sym, entries))
; /* nothing */
if (sym != NULL) {
if (sym->persist == 1)
return (0);
else {
free(sym->nam);
free(sym->val);
TAILQ_REMOVE(&symhead, sym, entries);
free(sym);
}
}
if ((sym = calloc(1, sizeof(*sym))) == NULL)
return (-1);
sym->nam = strdup(nam);
if (sym->nam == NULL) {
free(sym);
return (-1);
}
sym->val = strdup(val);
if (sym->val == NULL) {
free(sym->nam);
free(sym);
return (-1);
}
sym->used = 0;
sym->persist = persist;
TAILQ_INSERT_TAIL(&symhead, sym, entries);
return (0);
}
int
cmdline_symset(char *s)
{
char *sym, *val;
int ret;
size_t len;
if ((val = strrchr(s, '=')) == NULL)
return (-1);
len = strlen(s) - strlen(val) + 1;
if ((sym = malloc(len)) == NULL)
errx(1, "cmdline_symset: malloc");
strlcpy(sym, s, len);
ret = symset(sym, val + 1, 1);
free(sym);
return (ret);
}
char *
symget(const char *nam)
{
struct sym *sym;
TAILQ_FOREACH(sym, &symhead, entries)
if (strcmp(nam, sym->nam) == 0) {
sym->used = 1;
return (sym->val);
}
return (NULL);
}
int
atoul(char *s, u_long *ulvalp)
{
u_long ulval;
char *ep;
errno = 0;
ulval = strtoul(s, &ep, 0);
if (s[0] == '\0' || *ep != '\0')
return (-1);
if (errno == ERANGE && ulval == ULONG_MAX)
return (-1);
*ulvalp = ulval;
return (0);
}
struct area *
conf_get_area(struct in_addr id)
{
struct area *a;
a = area_find(conf, id);
if (a)
return (a);
a = area_new();
LIST_INSERT_HEAD(&conf->area_list, a, entry);
a->id.s_addr = id.s_addr;
return (a);
}
struct iface *
conf_get_if(struct kif *kif)
{
struct area *a;
struct iface *i;
LIST_FOREACH(a, &conf->area_list, entry)
LIST_FOREACH(i, &a->iface_list, entry)
if (i->ifindex == kif->ifindex) {
yyerror("interface %s already configured",
kif->ifname);
return (NULL);
}
i = if_new(kif);
i->auth_keyid = 1;
return (i);
}
void
clear_config(struct ospfd_conf *xconf)
{
struct area *a;
while ((a = LIST_FIRST(&xconf->area_list)) != NULL) {
LIST_REMOVE(a, entry);
area_del(a);
}
free(xconf);
}
u_int32_t
get_rtr_id(void)
{
struct ifaddrs *ifap, *ifa;
u_int32_t ip = 0, cur, localnet;
localnet = htonl(INADDR_LOOPBACK & IN_CLASSA_NET);
if (getifaddrs(&ifap) == -1)
fatal("getifaddrs");
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (ifa->ifa_addr->sa_family != AF_INET)
continue;
cur = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
if ((cur & localnet) == localnet) /* skip 127/8 */
continue;
if (cur > ip || ip == 0)
ip = cur;
}
freeifaddrs(ifap);
if (ip == 0)
fatal("router-id is 0.0.0.0");
return (ip);
}
int
host(const char *s, struct in_addr *addr, struct in_addr *mask)
{
struct in_addr ina;
int bits = 32;
bzero(&ina, sizeof(struct in_addr));
if (strrchr(s, '/') != NULL) {
if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1)
return (0);
} else {
if (inet_pton(AF_INET, s, &ina) != 1)
return (0);
}
addr->s_addr = ina.s_addr;
mask->s_addr = prefixlen2mask(bits);
return (1);
}
#line 871 "parse.c"
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
int yyparse __P((void));
static int yygrowstack __P((void));
static int yygrowstack()
{
int newsize, i;
short *newss;
YYSTYPE *newvs;
if ((newsize = yystacksize) == 0)
newsize = YYINITSTACKSIZE;
else if (newsize >= YYMAXDEPTH)
return -1;
else if ((newsize *= 2) > YYMAXDEPTH)
newsize = YYMAXDEPTH;
i = yyssp - yyss;
if ((newss = (short *)realloc(yyss, newsize * sizeof *newss)) == NULL)
return -1;
yyss = newss;
yyssp = newss + i;
if ((newvs = (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs)) == NULL)
return -1;
yyvs = newvs;
yyvsp = newvs + i;
yystacksize = newsize;
yysslim = yyss + newsize - 1;
return 0;
}
#define YYABORT goto yyabort
#define YYREJECT goto yyabort
#define YYACCEPT goto yyaccept
#define YYERROR goto yyerrlab
int
yyparse()
{
int yym, yyn, yystate;
#if YYDEBUG
char *yys;
if ((yys = getenv("YYDEBUG")) != NULL)
{
yyn = *yys;
if (yyn >= '0' && yyn <= '9')
yydebug = yyn - '0';
}
#endif
yynerrs = 0;
yyerrflag = 0;
yychar = (-1);
if (yyss == NULL && yygrowstack()) goto yyoverflow;
yyssp = yyss;
yyvsp = yyvs;
*yyssp = yystate = 0;
yyloop:
if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
if (yychar < 0)
{
if ((yychar = yylex()) < 0) yychar = 0;
#if YYDEBUG
if (yydebug)
{
yys = 0;
if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
if (!yys) yys = "illegal-symbol";
printf("%sdebug: state %d, reading %d (%s)\n",
YYPREFIX, yystate, yychar, yys);
}
#endif
}
if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
{
#if YYDEBUG
if (yydebug)
printf("%sdebug: state %d, shifting to state %d\n",
YYPREFIX, yystate, yytable[yyn]);
#endif
if (yyssp >= yysslim && yygrowstack())
{
goto yyoverflow;
}
*++yyssp = yystate = yytable[yyn];
*++yyvsp = yylval;
yychar = (-1);
if (yyerrflag > 0) --yyerrflag;
goto yyloop;
}
if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
{
yyn = yytable[yyn];
goto yyreduce;
}
if (yyerrflag) goto yyinrecovery;
goto yynewerror;
yynewerror:
yyerror("syntax error");
goto yyerrlab;
yyerrlab:
++yynerrs;
yyinrecovery:
if (yyerrflag < 3)
{
yyerrflag = 3;
for (;;)
{
if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
{
#if YYDEBUG
if (yydebug)
printf("%sdebug: state %d, error recovery shifting\
to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
#endif
if (yyssp >= yysslim && yygrowstack())
{
goto yyoverflow;
}
*++yyssp = yystate = yytable[yyn];
*++yyvsp = yylval;
goto yyloop;
}
else
{
#if YYDEBUG
if (yydebug)
printf("%sdebug: error recovery discarding state %d\n",
YYPREFIX, *yyssp);
#endif
if (yyssp <= yyss) goto yyabort;
--yyssp;
--yyvsp;
}
}
}
else
{
if (yychar == 0) goto yyabort;
#if YYDEBUG
if (yydebug)
{
yys = 0;
if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
if (!yys) yys = "illegal-symbol";
printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
YYPREFIX, yystate, yychar, yys);
}
#endif
yychar = (-1);
goto yyloop;
}
yyreduce:
#if YYDEBUG
if (yydebug)
printf("%sdebug: state %d, reducing by rule %d (%s)\n",
YYPREFIX, yystate, yyn, yyrule[yyn]);
#endif
yym = yylen[yyn];
yyval = yyvsp[1-yym];
switch (yyn)
{
case 6:
#line 129 "parse.y"
{ errors++; }
break;
case 7:
#line 132 "parse.y"
{
u_long ulval;
if (atoul(yyvsp[0].v.string, &ulval) == -1) {
yyerror("%s is not a number", yyvsp[0].v.string);
free(yyvsp[0].v.string);
YYERROR;
} else
yyval.v.number = ulval;
free(yyvsp[0].v.string);
}
break;
case 8:
#line 145 "parse.y"
{
if (asprintf(&yyval.v.string, "%s %s", yyvsp[-1].v.string, yyvsp[0].v.string) == -1) {
free(yyvsp[-1].v.string);
free(yyvsp[0].v.string);
yyerror("string: asprintf");
YYERROR;
}
free(yyvsp[-1].v.string);
free(yyvsp[0].v.string);
}
break;
case 10:
#line 158 "parse.y"
{ yyval.v.number = 1; }
break;
case 11:
#line 159 "parse.y"
{ yyval.v.number = 0; }
break;
case 12:
#line 162 "parse.y"
{ yyval.v.number = 0; }
break;
case 13:
#line 163 "parse.y"
{ yyval.v.number = 1; }
break;
case 14:
#line 165 "parse.y"
{
if (conf->opts & OSPFD_OPT_VERBOSE)
printf("%s = \"%s\"\n", yyvsp[-2].v.string, yyvsp[0].v.string);
if (symset(yyvsp[-2].v.string, yyvsp[0].v.string, 0) == -1)
fatal("cannot store variable");
free(yyvsp[-2].v.string);
free(yyvsp[0].v.string);
}
break;
case 15:
#line 175 "parse.y"
{
if (!inet_aton(yyvsp[0].v.string, &conf->rtr_id)) {
yyerror("error parsing router-id");
free(yyvsp[0].v.string);
YYERROR;
}
free(yyvsp[0].v.string);
}
break;
case 16:
#line 183 "parse.y"
{
if (yyvsp[0].v.number == 0)
conf->flags |= OSPFD_FLAG_NO_FIB_UPDATE;
else
conf->flags &= ~OSPFD_FLAG_NO_FIB_UPDATE;
}
break;
case 17:
#line 189 "parse.y"
{
struct redistribute *r;
if (!strcmp(yyvsp[0].v.string, "default")) {
conf->redistribute |= REDISTRIBUTE_DEFAULT;
if (yyvsp[-2].v.number) {
yyerror("cannot use 'no' with "
"redistribute default");
free(yyvsp[0].v.string);
YYERROR;
}
} else {
if ((r = calloc(1, sizeof(*r))) == NULL)
fatal(NULL);
if (!strcmp(yyvsp[0].v.string, "static"))
r->type = REDIST_STATIC;
else if (!strcmp(yyvsp[0].v.string, "connected"))
r->type = REDIST_CONNECTED;
else if (host(yyvsp[0].v.string, &r->addr, &r->mask))
r->type = REDIST_ADDR;
else {
yyerror("unknown redistribute type");
free(yyvsp[0].v.string);
free(r);
YYERROR;
}
if (yyvsp[-2].v.number)
r->type |= REDIST_NO;
STAILQ_INSERT_TAIL(&conf->redist_list, r,
entry);
}
conf->redistribute |= REDISTRIBUTE_ON;
free(yyvsp[0].v.string);
}
break;
case 18:
#line 226 "parse.y"
{
struct redistribute *r;
if ((r = calloc(1, sizeof(*r))) == NULL)
fatal(NULL);
r->type = REDIST_LABEL;
r->label = rtlabel_name2id(yyvsp[0].v.string);
if (yyvsp[-3].v.number)
r->type |= REDIST_NO;
free(yyvsp[0].v.string);
STAILQ_INSERT_TAIL(&conf->redist_list, r, entry);
conf->redistribute |= REDISTRIBUTE_ON;
}
break;
case 19:
#line 240 "parse.y"
{
conf->rfc1583compat = yyvsp[0].v.number;
}
break;
case 20:
#line 243 "parse.y"
{
if (yyvsp[0].v.number < MIN_SPF_DELAY || yyvsp[0].v.number > MAX_SPF_DELAY) {
yyerror("spf-delay out of range "
"(%d-%d)", MIN_SPF_DELAY,
MAX_SPF_DELAY);
YYERROR;
}
conf->spf_delay = yyvsp[0].v.number;
}
break;
case 21:
#line 252 "parse.y"
{
if (yyvsp[0].v.number < MIN_SPF_HOLDTIME || yyvsp[0].v.number > MAX_SPF_HOLDTIME) {
yyerror("spf-holdtime out of range "
"(%d-%d)", MIN_SPF_HOLDTIME,
MAX_SPF_HOLDTIME);
YYERROR;
}
conf->spf_hold_time = yyvsp[0].v.number;
}
break;
case 23:
#line 264 "parse.y"
{
if (yyvsp[-1].v.number < MIN_MD_ID || yyvsp[-1].v.number > MAX_MD_ID) {
yyerror("auth-md key-id out of range "
"(%d-%d)", MIN_MD_ID, MAX_MD_ID);
free(yyvsp[0].v.string);
YYERROR;
}
if (strlen(yyvsp[0].v.string) > MD5_DIGEST_LENGTH) {
yyerror("auth-md key length out of range "
"(max length %d)",
MD5_DIGEST_LENGTH);
free(yyvsp[0].v.string);
YYERROR;
}
md_list_add(&defs->md_list, yyvsp[-1].v.number, yyvsp[0].v.string);
free(yyvsp[0].v.string);
}
break;
case 24:
#line 282 "parse.y"
{
if (yyvsp[0].v.number < MIN_MD_ID || yyvsp[0].v.number > MAX_MD_ID) {
yyerror("auth-md-keyid out of range "
"(%d-%d)", MIN_MD_ID, MAX_MD_ID);
YYERROR;
}
defs->auth_keyid = yyvsp[0].v.number;
}
break;
case 25:
#line 291 "parse.y"
{
enum auth_type type;
if (!strcmp(yyvsp[0].v.string, "none"))
type = AUTH_NONE;
else if (!strcmp(yyvsp[0].v.string, "simple"))
type = AUTH_SIMPLE;
else if (!strcmp(yyvsp[0].v.string, "crypt"))
type = AUTH_CRYPT;
else {
yyerror("unknown auth-type");
free(yyvsp[0].v.string);
YYERROR;
}
free(yyvsp[0].v.string);
defs->auth_type = type;
}
break;
case 26:
#line 310 "parse.y"
{
if (strlen(yyvsp[0].v.string) > MAX_SIMPLE_AUTH_LEN) {
yyerror("auth-key too long (max length %d)",
MAX_SIMPLE_AUTH_LEN);
free(yyvsp[0].v.string);
YYERROR;
}
strncpy(defs->auth_key, yyvsp[0].v.string,
sizeof(defs->auth_key));
free(yyvsp[0].v.string);
}
break;
case 27:
#line 323 "parse.y"
{
if (yyvsp[0].v.number < MIN_METRIC || yyvsp[0].v.number > MAX_METRIC) {
yyerror("metric out of range (%d-%d)",
MIN_METRIC, MAX_METRIC);
YYERROR;
}
defs->metric = yyvsp[0].v.number;
}
break;
case 28:
#line 331 "parse.y"
{
if (yyvsp[0].v.number < MIN_PRIORITY || yyvsp[0].v.number > MAX_PRIORITY) {
yyerror("router-priority out of range (%d-%d)",
MIN_PRIORITY, MAX_PRIORITY);
YYERROR;
}
defs->priority = yyvsp[0].v.number;
}
break;
case 29:
#line 339 "parse.y"
{
if (yyvsp[0].v.number < MIN_RTR_DEAD_TIME || yyvsp[0].v.number > MAX_RTR_DEAD_TIME) {
yyerror("router-dead-time out of range (%d-%d)",
MIN_RTR_DEAD_TIME, MAX_RTR_DEAD_TIME);
YYERROR;
}
defs->dead_interval = yyvsp[0].v.number;
}
break;
case 30:
#line 347 "parse.y"
{
if (yyvsp[0].v.number < MIN_TRANSMIT_DELAY ||
yyvsp[0].v.number > MAX_TRANSMIT_DELAY) {
yyerror("transmit-delay out of range (%d-%d)",
MIN_TRANSMIT_DELAY, MAX_TRANSMIT_DELAY);
YYERROR;
}
defs->transmit_delay = yyvsp[0].v.number;
}
break;
case 31:
#line 356 "parse.y"
{
if (yyvsp[0].v.number < MIN_HELLO_INTERVAL ||
yyvsp[0].v.number > MAX_HELLO_INTERVAL) {
yyerror("hello-interval out of range (%d-%d)",
MIN_HELLO_INTERVAL, MAX_HELLO_INTERVAL);
YYERROR;
}
defs->hello_interval = yyvsp[0].v.number;
}
break;
case 32:
#line 365 "parse.y"
{
if (yyvsp[0].v.number < MIN_RXMT_INTERVAL || yyvsp[0].v.number > MAX_RXMT_INTERVAL) {
yyerror("retransmit-interval out of range "
"(%d-%d)", MIN_RXMT_INTERVAL,
MAX_RXMT_INTERVAL);
YYERROR;
}
defs->rxmt_interval = yyvsp[0].v.number;
}
break;
case 40:
#line 387 "parse.y"
{
struct in_addr id;
if (inet_aton(yyvsp[0].v.string, &id) == 0) {
yyerror("error parsing area");
free(yyvsp[0].v.string);
YYERROR;
}
free(yyvsp[0].v.string);
area = conf_get_area(id);
memcpy(&areadefs, defs, sizeof(areadefs));
md_list_copy(&areadefs.md_list, &defs->md_list);
defs = &areadefs;
}
break;
case 41:
#line 400 "parse.y"
{
area = NULL;
md_list_clr(&defs->md_list);
defs = &globaldefs;
}
break;
case 46:
#line 415 "parse.y"
{
struct kif *kif;
if ((kif = kif_findname(yyvsp[0].v.string)) == NULL) {
yyerror("unknown interface %s", yyvsp[0].v.string);
free(yyvsp[0].v.string);
YYERROR;
}
free(yyvsp[0].v.string);
iface = conf_get_if(kif);
if (iface == NULL)
YYERROR;
iface->area = area;
LIST_INSERT_HEAD(&area->iface_list,
iface, entry);
memcpy(&ifacedefs, defs, sizeof(ifacedefs));
md_list_copy(&ifacedefs.md_list, &defs->md_list);
defs = &ifacedefs;
}
break;
case 47:
#line 434 "parse.y"
{
iface->dead_interval = defs->dead_interval;
iface->transmit_delay = defs->transmit_delay;
iface->hello_interval = defs->hello_interval;
iface->rxmt_interval = defs->rxmt_interval;
iface->metric = defs->metric;
iface->priority = defs->priority;
iface->auth_type = defs->auth_type;
iface->auth_keyid = defs->auth_keyid;
memcpy(iface->auth_key, defs->auth_key,
sizeof(iface->auth_key));
md_list_copy(&iface->auth_md_list, &defs->md_list);
md_list_clr(&defs->md_list);
iface = NULL;
/* interface is always part of an area */
defs = &areadefs;
}
break;
case 53:
#line 462 "parse.y"
{ iface->passive = 1; }
break;
#line 1408 "parse.c"
}
yyssp -= yym;
yystate = *yyssp;
yyvsp -= yym;
yym = yylhs[yyn];
if (yystate == 0 && yym == 0)
{
#if YYDEBUG
if (yydebug)
printf("%sdebug: after reduction, shifting from state 0 to\
state %d\n", YYPREFIX, YYFINAL);
#endif
yystate = YYFINAL;
*++yyssp = YYFINAL;
*++yyvsp = yyval;
if (yychar < 0)
{
if ((yychar = yylex()) < 0) yychar = 0;
#if YYDEBUG
if (yydebug)
{
yys = 0;
if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
if (!yys) yys = "illegal-symbol";
printf("%sdebug: state %d, reading %d (%s)\n",
YYPREFIX, YYFINAL, yychar, yys);
}
#endif
}
if (yychar == 0) goto yyaccept;
goto yyloop;
}
if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
yystate = yytable[yyn];
else
yystate = yydgoto[yym];
#if YYDEBUG
if (yydebug)
printf("%sdebug: after reduction, shifting from state %d \
to state %d\n", YYPREFIX, *yyssp, yystate);
#endif
if (yyssp >= yysslim && yygrowstack())
{
goto yyoverflow;
}
*++yyssp = yystate;
*++yyvsp = yyval;
goto yyloop;
yyoverflow:
yyerror("yacc stack overflow");
yyabort:
return (1);
yyaccept:
return (0);
}
syntax highlighted by Code2HTML, v. 0.9.1