summaryrefslogtreecommitdiffstats
path: root/contrib/ipfilter/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ipfilter/parse.c')
-rw-r--r--contrib/ipfilter/parse.c99
1 files changed, 88 insertions, 11 deletions
diff --git a/contrib/ipfilter/parse.c b/contrib/ipfilter/parse.c
index 1147ee1..0d8a617 100644
--- a/contrib/ipfilter/parse.c
+++ b/contrib/ipfilter/parse.c
@@ -68,10 +68,16 @@ extern u_char flags[];
/* parse()
*
* parse a line read from the input filter rule file
+ *
+ * status:
+ * < 0 error
+ * = 0 OK
+ * > 0 programmer error
*/
-struct frentry *parse(line, linenum)
+struct frentry *parse(line, linenum, status)
char *line;
int linenum;
+int *status; /* good, bad, or indifferent */
{
static struct frentry fil;
char *cps[31], **cpp, *endptr, *s;
@@ -79,10 +85,14 @@ int linenum;
int i, cnt = 1, j, ch;
u_int k;
+ *status = 100; /* default to error */
+
while (*line && isspace(*line))
line++;
- if (!*line)
+ if (!*line) {
+ *status = 0;
return NULL;
+ }
bzero((char *)&fil, sizeof(fil));
fil.fr_mip.fi_v = 0xf;
@@ -100,6 +110,7 @@ int linenum;
if (cnt < 3) {
fprintf(stderr, "%d: not enough segments in line\n", linenum);
+ *status = -1;
return NULL;
}
@@ -143,6 +154,7 @@ int linenum;
fprintf(stderr,
"%d: unrecognised icmp code %s\n",
linenum, *cpp + 20);
+ *status = -1;
return NULL;
}
fil.fr_icode = j;
@@ -172,6 +184,7 @@ int linenum;
else {
fprintf(stderr, "%d: integer must follow skip\n",
linenum);
+ *status = -1;
return NULL;
}
} else if (!strcasecmp("log", *cpp)) {
@@ -190,8 +203,11 @@ int linenum;
}
if (!strcasecmp(*(cpp+1), "level")) {
cpp++;
- if (loglevel(cpp, &fil.fr_loglevel, linenum) == -1)
+ if (loglevel(cpp, &fil.fr_loglevel, linenum) == -1) {
+ /* NB loglevel prints its own error message */
+ *status = -1;
return NULL;
+ }
cpp++;
}
} else {
@@ -199,10 +215,12 @@ int linenum;
* Doesn't start with one of the action words
*/
fprintf(stderr, "%d: unknown keyword (%s)\n", linenum, *cpp);
+ *status = -1;
return NULL;
}
if (!*++cpp) {
fprintf(stderr, "%d: missing 'in'/'out' keyword\n", linenum);
+ *status = -1;
return NULL;
}
@@ -218,16 +236,19 @@ int linenum;
fprintf(stderr,
"%d: Can only use return-icmp with 'in'\n",
linenum);
+ *status = -1;
return NULL;
} else if (fil.fr_flags & FR_RETRST) {
fprintf(stderr,
"%d: Can only use return-rst with 'in'\n",
linenum);
+ *status = -1;
return NULL;
}
}
if (!*++cpp) {
fprintf(stderr, "%d: missing source specification\n", linenum);
+ *status = -1;
return NULL;
}
@@ -235,6 +256,7 @@ int linenum;
if (!*++cpp) {
fprintf(stderr, "%d: missing source specification\n",
linenum);
+ *status = -1;
return NULL;
}
if (fil.fr_flags & FR_PASS)
@@ -254,14 +276,17 @@ int linenum;
fprintf(stderr,
"%d: or-block must be used with pass\n",
linenum);
+ *status = -1;
return NULL;
}
fil.fr_flags |= FR_LOGORBLOCK;
cpp++;
}
if (*cpp && !strcasecmp(*cpp, "level")) {
- if (loglevel(cpp, &fil.fr_loglevel, linenum) == -1)
+ if (loglevel(cpp, &fil.fr_loglevel, linenum) == -1) {
+ *status = -1;
return NULL;
+ }
cpp++;
cpp++;
}
@@ -271,6 +296,7 @@ int linenum;
if (fil.fr_skip != 0) {
fprintf(stderr, "%d: cannot use skip with quick\n",
linenum);
+ *status = -1;
return NULL;
}
cpp++;
@@ -287,6 +313,7 @@ int linenum;
if (!*++cpp) {
fprintf(stderr, "%d: interface name missing\n",
linenum);
+ *status = -1;
return NULL;
}
@@ -307,28 +334,35 @@ int linenum;
fprintf(stderr,
"%d: %s can only be used with TCP\n",
linenum, "return-rst");
+ *status = -1;
return NULL;
}
+ *status = 0;
return &fil;
}
if (*cpp) {
if (!strcasecmp(*cpp, "dup-to") && *(cpp + 1)) {
cpp++;
- if (to_interface(&fil.fr_dif, *cpp, linenum))
+ if (to_interface(&fil.fr_dif, *cpp, linenum)) {
+ *status = -1;
return NULL;
+ }
cpp++;
}
if (*cpp && !strcasecmp(*cpp, "to") && *(cpp + 1)) {
cpp++;
- if (to_interface(&fil.fr_tif, *cpp, linenum))
+ if (to_interface(&fil.fr_tif, *cpp, linenum)) {
+ *status = -1;
return NULL;
+ }
cpp++;
} else if (*cpp && !strcasecmp(*cpp, "fastroute")) {
if (!(fil.fr_flags & FR_INQUE)) {
fprintf(stderr,
"can only use %s with 'in'\n",
"fastroute");
+ *status = -1;
return NULL;
}
fil.fr_flags |= FR_FASTROUTE;
@@ -366,6 +400,7 @@ int linenum;
if (*cpp && !strcasecmp(*cpp, "tos")) {
if (!*++cpp) {
fprintf(stderr, "%d: tos missing value\n", linenum);
+ *status = -1;
return NULL;
}
fil.fr_tos = strtol(*cpp, NULL, 0);
@@ -377,6 +412,7 @@ int linenum;
if (!*++cpp) {
fprintf(stderr, "%d: ttl missing hopcount value\n",
linenum);
+ *status = -1;
return NULL;
}
if (ratoi(*cpp, &i, 0, 255))
@@ -384,6 +420,7 @@ int linenum;
else {
fprintf(stderr, "%d: invalid ttl (%s)\n",
linenum, *cpp);
+ *status = -1;
return NULL;
}
fil.fr_mip.fi_ttl = 0xff;
@@ -397,6 +434,7 @@ int linenum;
if (*cpp && !strcasecmp(*cpp, "proto")) {
if (!*++cpp) {
fprintf(stderr, "%d: protocol name missing\n", linenum);
+ *status = -1;
return NULL;
}
proto = *cpp++;
@@ -412,6 +450,7 @@ int linenum;
fprintf(stderr,
"%d: unknown protocol (%s)\n",
linenum, proto);
+ *status = -1;
return NULL;
}
if (p)
@@ -422,6 +461,7 @@ int linenum;
fprintf(stderr,
"%d: unknown protocol (%s)\n",
linenum, proto);
+ *status = -1;
return NULL;
}
fil.fr_proto = i;
@@ -433,6 +473,7 @@ int linenum;
((fil.fr_flags & FR_RETMASK) == FR_RETRST)) {
fprintf(stderr, "%d: %s can only be used with TCP\n",
linenum, "return-rst");
+ *status = -1;
return NULL;
}
@@ -442,21 +483,26 @@ int linenum;
if (!*cpp) {
fprintf(stderr, "%d: missing source specification\n", linenum);
+ *status = -1;
return NULL;
}
if (!strcasecmp(*cpp, "all")) {
cpp++;
- if (!*cpp)
+ if (!*cpp) {
+ *status = 0;
return &fil;
+ }
} else {
if (strcasecmp(*cpp, "from")) {
fprintf(stderr, "%d: unexpected keyword (%s) - from\n",
linenum, *cpp);
+ *status = -1;
return NULL;
}
if (!*++cpp) {
fprintf(stderr, "%d: missing host after from\n",
linenum);
+ *status = -1;
return NULL;
}
if (!strcmp(*cpp, "!")) {
@@ -465,6 +511,7 @@ int linenum;
fprintf(stderr,
"%d: missing host after from\n",
linenum);
+ *status = -1;
return NULL;
}
} else if (**cpp == '!') {
@@ -475,6 +522,7 @@ int linenum;
if (hostmask(&cpp, (u_32_t *)&fil.fr_src,
(u_32_t *)&fil.fr_smsk, &fil.fr_sport, &ch,
&fil.fr_stop, linenum)) {
+ *status = -1;
return NULL;
}
@@ -484,12 +532,14 @@ int linenum;
fprintf(stderr,
"%d: cannot use port and neither tcp or udp\n",
linenum);
+ *status = -1;
return NULL;
}
fil.fr_scmp = ch;
if (!*cpp) {
fprintf(stderr, "%d: missing to fields\n", linenum);
+ *status = -1;
return NULL;
}
@@ -499,10 +549,12 @@ int linenum;
if (strcasecmp(*cpp, "to")) {
fprintf(stderr, "%d: unexpected keyword (%s) - to\n",
linenum, *cpp);
+ *status = -1;
return NULL;
}
if (!*++cpp) {
fprintf(stderr, "%d: missing host after to\n", linenum);
+ *status = -1;
return NULL;
}
ch = 0;
@@ -512,6 +564,7 @@ int linenum;
fprintf(stderr,
"%d: missing host after from\n",
linenum);
+ *status = -1;
return NULL;
}
} else if (**cpp == '!') {
@@ -521,6 +574,7 @@ int linenum;
if (hostmask(&cpp, (u_32_t *)&fil.fr_dst,
(u_32_t *)&fil.fr_dmsk, &fil.fr_dport, &ch,
&fil.fr_dtop, linenum)) {
+ *status = -1;
return NULL;
}
if ((ch != 0) && (fil.fr_proto != IPPROTO_TCP) &&
@@ -529,6 +583,7 @@ int linenum;
fprintf(stderr,
"%d: cannot use port and neither tcp or udp\n",
linenum);
+ *status = -1;
return NULL;
}
@@ -542,20 +597,25 @@ int linenum;
if (fil.fr_proto && (fil.fr_dcmp || fil.fr_scmp) &&
fil.fr_proto != IPPROTO_TCP && fil.fr_proto != IPPROTO_UDP) {
fprintf(stderr, "%d: port operation on non tcp/udp\n", linenum);
+ *status = -1;
return NULL;
}
if (fil.fr_icmp && fil.fr_proto != IPPROTO_ICMP) {
fprintf(stderr, "%d: icmp comparisons on wrong protocol\n",
linenum);
+ *status = -1;
return NULL;
}
- if (!*cpp)
+ if (!*cpp) {
+ *status = 0;
return &fil;
+ }
if (*cpp && !strcasecmp(*cpp, "flags")) {
if (!*++cpp) {
fprintf(stderr, "%d: no flags present\n", linenum);
+ *status = -1;
return NULL;
}
fil.fr_tcpf = tcp_flags(*cpp, &fil.fr_tcpfm, linenum);
@@ -567,8 +627,10 @@ int linenum;
*/
if ((fil.fr_v == 4) && *cpp && (!strcasecmp(*cpp, "with") ||
!strcasecmp(*cpp, "and")))
- if (extras(&cpp, &fil, linenum))
+ if (extras(&cpp, &fil, linenum)) {
+ *status = -1;
return NULL;
+ }
/*
* icmp types for use with the icmp protocol
@@ -579,10 +641,13 @@ int linenum;
fprintf(stderr,
"%d: icmp with wrong protocol (%d)\n",
linenum, fil.fr_proto);
+ *status = -1;
return NULL;
}
- if (addicmp(&cpp, &fil, linenum))
+ if (addicmp(&cpp, &fil, linenum)) {
+ *status = -1;
return NULL;
+ }
fil.fr_icmp = htons(fil.fr_icmp);
fil.fr_icmpm = htons(fil.fr_icmpm);
}
@@ -591,8 +656,10 @@ int linenum;
* Keep something...
*/
while (*cpp && !strcasecmp(*cpp, "keep"))
- if (addkeep(&cpp, &fil, linenum))
+ if (addkeep(&cpp, &fil, linenum)) {
+ *status = -1;
return NULL;
+ }
/*
* This is here to enforce the old interface binding behaviour.
@@ -614,10 +681,12 @@ int linenum;
if (fil.fr_skip != 0) {
fprintf(stderr, "%d: cannot use skip with head\n",
linenum);
+ *status = -1;
return NULL;
}
if (!*++cpp) {
fprintf(stderr, "%d: head without group #\n", linenum);
+ *status = -1;
return NULL;
}
if (ratoui(*cpp, &k, 0, UINT_MAX))
@@ -625,6 +694,7 @@ int linenum;
else {
fprintf(stderr, "%d: invalid group (%s)\n",
linenum, *cpp);
+ *status = -1;
return NULL;
}
cpp++;
@@ -637,6 +707,7 @@ int linenum;
if (!*++cpp) {
fprintf(stderr, "%d: group without group #\n",
linenum);
+ *status = -1;
return NULL;
}
if (ratoui(*cpp, &k, 0, UINT_MAX))
@@ -644,6 +715,7 @@ int linenum;
else {
fprintf(stderr, "%d: invalid group (%s)\n",
linenum, *cpp);
+ *status = -1;
return NULL;
}
cpp++;
@@ -657,6 +729,7 @@ int linenum;
for (; *cpp; cpp++)
fprintf(stderr, "%s ", *cpp);
fprintf(stderr, "]\n");
+ *status = -1;
return NULL;
}
@@ -665,6 +738,7 @@ int linenum;
*/
if ((fil.fr_tcpf || fil.fr_tcpfm) && fil.fr_proto != IPPROTO_TCP) {
fprintf(stderr, "%d: TCP protocol not specified\n", linenum);
+ *status = -1;
return NULL;
}
if (!(fil.fr_ip.fi_fl & FI_TCPUDP) && (fil.fr_proto != IPPROTO_TCP) &&
@@ -676,6 +750,7 @@ int linenum;
fprintf(stderr,
"%d: port comparisons for non-TCP/UDP\n",
linenum);
+ *status = -1;
return NULL;
}
}
@@ -685,9 +760,11 @@ int linenum;
fprintf(stderr,
"%d: must use 'with frags' with 'keep frags'\n",
linenum);
+ *status = -1;
return NULL;
}
*/
+ *status = 0;
return &fil;
}
OpenPOWER on IntegriCloud