summaryrefslogtreecommitdiffstats
path: root/usr.sbin/ripd/parse.y
diff options
context:
space:
mode:
authorderaadt <deraadt@openbsd.org>2007-10-13 16:35:16 +0000
committerderaadt <deraadt@openbsd.org>2007-10-13 16:35:16 +0000
commit20741916113ca49abc055fadfc6b6cbc70e4fe62 (patch)
tree41dce2a5666e6d6666097f6a517584a1563db765 /usr.sbin/ripd/parse.y
parentAdd support for BCM5906. (diff)
downloadwireguard-openbsd-20741916113ca49abc055fadfc6b6cbc70e4fe62.tar.xz
wireguard-openbsd-20741916113ca49abc055fadfc6b6cbc70e4fe62.zip
in all these programs using the same pfctl-derived parse.y, re-unify the
yylex implementation and the code which interacts with yylex. this also brings the future potential for include support to all of the parsers. in the future please do not silly modifications to one of these files without checking if you are de-unifying the code. checked by developers in all these areas.
Diffstat (limited to 'usr.sbin/ripd/parse.y')
-rw-r--r--usr.sbin/ripd/parse.y230
1 files changed, 150 insertions, 80 deletions
diff --git a/usr.sbin/ripd/parse.y b/usr.sbin/ripd/parse.y
index 8ccac2102ad..cf8192e7b29 100644
--- a/usr.sbin/ripd/parse.y
+++ b/usr.sbin/ripd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.9 2007/10/11 14:39:17 deraadt Exp $ */
+/* $OpenBSD: parse.y,v 1.10 2007/10/13 16:35:22 deraadt Exp $ */
/*
* Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it>
@@ -25,11 +25,13 @@
%{
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
+#include <unistd.h>
#include <ifaddrs.h>
#include <limits.h>
#include <stdarg.h>
@@ -41,27 +43,35 @@
#include "ripe.h"
#include "log.h"
-static struct ripd_conf *conf;
-static FILE *fin = NULL;
-static int lineno = 1;
-static int errors = 0;
-char *infile;
-char *start_state;
+TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
+static struct file {
+ TAILQ_ENTRY(file) entry;
+ FILE *stream;
+ char *name;
+ int lineno;
+ int errors;
+} *file;
+struct file *pushfile(const char *, int);
+int popfile(void);
+int yyparse(void);
+int yylex(void);
+int yyerror(const char *, ...);
+int kw_cmp(const void *, const void *);
+int lookup(char *);
+int lgetc(int);
+int lungetc(int);
+int findeol(void);
-struct iface *iface = NULL;
-
-int yyerror(const char *, ...);
-int yyparse(void);
-int kw_cmp(const void *, const void *);
-int lookup(char *);
-int lgetc(int);
-int lungetc(int);
-int findeol(void);
-int yylex(void);
-void clear_config(struct ripd_conf *);
-int check_file_secrecy(int, const char *);
-u_int32_t get_rtr_id(void);
-int host(const char *, struct in_addr *, struct in_addr *);
+TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
+struct sym {
+ TAILQ_ENTRY(sym) entry;
+ int used;
+ int persist;
+ char *nam;
+ char *val;
+};
+int symset(const char *, const char *, int);
+char *symget(const char *);
static struct {
char auth_key[MAX_SIMPLE_AUTH_LEN];
@@ -71,18 +81,16 @@ static struct {
u_int8_t cost;
} *defs, globaldefs, ifacedefs;
-TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
-struct sym {
- TAILQ_ENTRY(sym) entries;
- int used;
- int persist;
- char *nam;
- char *val;
-};
+struct iface *iface = NULL;
+static struct ripd_conf *conf;
+static int errors = 0;
+char *start_state;
-int symset(const char *, const char *, int);
-char *symget(const char *);
-struct iface *conf_get_if(struct kif *);
+struct iface *conf_get_if(struct kif *);
+void clear_config(struct ripd_conf *);
+int check_file_secrecy(int, const char *);
+u_int32_t get_rtr_id(void);
+int host(const char *, struct in_addr *, struct in_addr *);
typedef struct {
union {
@@ -112,6 +120,7 @@ grammar : /* empty */
| grammar conf_main '\n'
| grammar varset '\n'
| grammar interface '\n'
+ | grammar error '\n' { file->errors++; }
;
string : string STRING {
@@ -305,7 +314,7 @@ optnl : '\n' optnl
nl : '\n' optnl
;
-interface : INTERFACE STRING {
+interface : INTERFACE STRING {
struct kif *kif;
if ((kif = kif_findname($2)) == NULL) {
@@ -333,11 +342,11 @@ interface : INTERFACE STRING {
}
;
-interface_block : '{' optnl interfaceopts_l '}'
+interface_block : '{' optnl interfaceopts_l '}'
| '{' optnl '}'
;
-interfaceopts_l : interfaceopts_l interfaceoptsl
+interfaceopts_l : interfaceopts_l interfaceoptsl
| interfaceoptsl
;
@@ -356,9 +365,9 @@ yyerror(const char *fmt, ...)
{
va_list ap;
- errors = 1;
+ file->errors++;
va_start(ap, fmt);
- fprintf(stderr, "%s:%d: ", infile, yylval.lineno);
+ fprintf(stderr, "%s:%d: ", file->name, yylval.lineno);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
@@ -410,10 +419,9 @@ char pushback_buffer[MAXPUSHBACK];
int pushback_index = 0;
int
-lgetc(int inquot)
+lgetc(int quotec)
{
- int c, next;
- FILE *f = fin;
+ int c, next;
if (parsebuf) {
/* Read character from the parsebuffer instead of input. */
@@ -429,29 +437,39 @@ lgetc(int inquot)
if (pushback_index)
return (pushback_buffer[--pushback_index]);
- if (inquot) {
- c = getc(f);
+ if (quotec) {
+ if ((c = getc(file->stream)) == EOF) {
+ yyerror("reached end of file while parsing quoted string");
+ if (popfile() == EOF)
+ return (EOF);
+ return (quotec);
+ }
return (c);
}
- while ((c = getc(f)) == '\\') {
- next = getc(f);
+ while ((c = getc(file->stream)) == '\\') {
+ next = getc(file->stream);
if (next != '\n') {
c = next;
break;
}
- yylval.lineno = lineno;
- lineno++;
+ yylval.lineno = file->lineno;
+ file->lineno++;
}
if (c == '\t' || c == ' ') {
/* Compress blanks to a single space. */
do {
- c = getc(f);
+ c = getc(file->stream);
} while (c == '\t' || c == ' ');
- ungetc(c, f);
+ ungetc(c, file->stream);
c = ' ';
}
+ while (c == EOF) {
+ if (popfile() == EOF)
+ return (EOF);
+ c = getc(file->stream);
+ }
return (c);
}
@@ -483,7 +501,7 @@ findeol(void)
while (1) {
c = lgetc(0);
if (c == '\n') {
- lineno++;
+ file->lineno++;
break;
}
if (c == EOF)
@@ -497,7 +515,7 @@ yylex(void)
{
char buf[8096];
char *p, *val;
- int endc, next, c;
+ int quotec, next, c;
int token;
top:
@@ -505,7 +523,7 @@ top:
while ((c = lgetc(0)) == ' ')
; /* nothing */
- yylval.lineno = lineno;
+ yylval.lineno = file->lineno;
if (c == '#')
while ((c = lgetc(0)) != '\n' && c != EOF)
; /* nothing */
@@ -539,21 +557,21 @@ top:
switch (c) {
case '\'':
case '"':
- endc = c;
+ quotec = c;
while (1) {
- if ((c = lgetc(1)) == EOF)
+ if ((c = lgetc(quotec)) == EOF)
return (0);
if (c == '\n') {
- lineno++;
+ file->lineno++;
continue;
} else if (c == '\\') {
- if ((next = lgetc(1)) == EOF)
+ if ((next = lgetc(quotec)) == EOF)
return (0);
- if (next == endc)
+ if (next == quotec)
c = next;
else
lungetc(next);
- } else if (c == endc) {
+ } else if (c == quotec) {
*p = '\0';
break;
}
@@ -627,14 +645,75 @@ nodigits:
return (token);
}
if (c == '\n') {
- yylval.lineno = lineno;
- lineno++;
+ yylval.lineno = file->lineno;
+ file->lineno++;
}
if (c == EOF)
return (0);
return (c);
}
+int
+check_file_secrecy(int fd, const char *fname)
+{
+ struct stat st;
+
+ if (fstat(fd, &st)) {
+ log_warn("cannot stat %s", fname);
+ return (-1);
+ }
+ if (st.st_uid != 0 && st.st_uid != getuid()) {
+ log_warnx("%s: owner not root or current user", fname);
+ return (-1);
+ }
+ if (st.st_mode & (S_IRWXG | S_IRWXO)) {
+ log_warnx("%s: group/world readable/writeable", fname);
+ return (-1);
+ }
+ return (0);
+}
+
+struct file *
+pushfile(const char *name, int secret)
+{
+ struct file *nfile;
+
+ if ((nfile = calloc(1, sizeof(struct file))) == NULL ||
+ (nfile->name = strdup(name)) == NULL)
+ return (NULL);
+ if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
+ free(nfile->name);
+ free(nfile);
+ return (NULL);
+ } else if (secret &&
+ check_file_secrecy(fileno(nfile->stream), nfile->name)) {
+ fclose(nfile->stream);
+ free(nfile->name);
+ free(nfile);
+ return (NULL);
+ }
+ nfile->lineno = 1;
+ TAILQ_INSERT_TAIL(&files, nfile, entry);
+ return (nfile);
+}
+
+int
+popfile(void)
+{
+ struct file *prev;
+
+ if ((prev = TAILQ_PREV(file, files, entry)) != NULL) {
+ prev->errors += file->errors;
+ TAILQ_REMOVE(&files, file, entry);
+ fclose(file->stream);
+ free(file->name);
+ free(file);
+ file = prev;
+ return (0);
+ }
+ return (EOF);
+}
+
struct ripd_conf *
parse_config(char *filename, int opts)
{
@@ -648,38 +727,29 @@ parse_config(char *filename, int opts)
TAILQ_INIT(&defs->md_list);
defs->cost = DEFAULT_COST;
defs->auth_type = AUTH_NONE;
+ conf->opts = opts;
+ SIMPLEQ_INIT(&conf->redist_list);
- if ((fin = fopen(filename, "r")) == NULL) {
+ if ((file = pushfile(filename, !(conf->opts & RIPD_OPT_NOACTION))) == NULL) {
warn("%s", filename);
free(conf);
return (NULL);
}
- infile = filename;
-
- conf->opts = opts;
- SIMPLEQ_INIT(&conf->redist_list);
-
- if (!(conf->opts & RIPD_OPT_NOACTION))
- if (check_file_secrecy(fileno(fin), filename)) {
- fclose(fin);
- free(conf);
- return (NULL);
- }
yyparse();
-
- fclose(fin);
+ errors = file->errors;
+ popfile();
/* Free macros and check which have not been used. */
for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
- next = TAILQ_NEXT(sym, entries);
+ next = TAILQ_NEXT(sym, entry);
if ((conf->opts & RIPD_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);
+ TAILQ_REMOVE(&symhead, sym, entry);
free(sym);
}
}
@@ -701,7 +771,7 @@ 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))
+ sym = TAILQ_NEXT(sym, entry))
; /* nothing */
if (sym != NULL) {
@@ -710,7 +780,7 @@ symset(const char *nam, const char *val, int persist)
else {
free(sym->nam);
free(sym->val);
- TAILQ_REMOVE(&symhead, sym, entries);
+ TAILQ_REMOVE(&symhead, sym, entry);
free(sym);
}
}
@@ -730,7 +800,7 @@ symset(const char *nam, const char *val, int persist)
}
sym->used = 0;
sym->persist = persist;
- TAILQ_INSERT_TAIL(&symhead, sym, entries);
+ TAILQ_INSERT_TAIL(&symhead, sym, entry);
return (0);
}
@@ -761,7 +831,7 @@ symget(const char *nam)
{
struct sym *sym;
- TAILQ_FOREACH(sym, &symhead, entries)
+ TAILQ_FOREACH(sym, &symhead, entry)
if (strcmp(nam, sym->nam) == 0) {
sym->used = 1;
return (sym->val);
@@ -772,7 +842,7 @@ symget(const char *nam)
struct iface *
conf_get_if(struct kif *kif)
{
- struct iface *i;
+ struct iface *i;
LIST_FOREACH(i, &conf->iface_list, entry)
if (i->ifindex == kif->ifindex) {