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.c1510
1 files changed, 0 insertions, 1510 deletions
diff --git a/contrib/ipfilter/parse.c b/contrib/ipfilter/parse.c
deleted file mode 100644
index 0d8a617..0000000
--- a/contrib/ipfilter/parse.c
+++ /dev/null
@@ -1,1510 +0,0 @@
-/*
- * Copyright (C) 1993-2001 by Darren Reed.
- *
- * See the IPFILTER.LICENCE file for details on licencing.
- */
-#if defined(__sgi) && (IRIX > 602)
-# include <sys/ptimers.h>
-#endif
-#include <sys/types.h>
-#if !defined(__SVR4) && !defined(__svr4__)
-#include <strings.h>
-#else
-#include <sys/byteorder.h>
-#endif
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/tcp.h>
-#include <net/if.h>
-#if __FreeBSD_version >= 300000
-# include <net/if_var.h>
-#endif
-#include <stdio.h>
-#include <string.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stddef.h>
-#include <netdb.h>
-#include <arpa/nameser.h>
-#include <arpa/inet.h>
-#include <resolv.h>
-#include <ctype.h>
-#include <syslog.h>
-#include "ip_compat.h"
-#include "ip_fil.h"
-#include "ipf.h"
-#include "facpri.h"
-
-#if !defined(lint)
-static const char sccsid[] = "@(#)parse.c 1.44 6/5/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$IPFilter: parse.c,v 2.8 1999/12/28 10:49:46 darrenr Exp $";
-#endif
-
-extern struct ipopt_names ionames[], secclass[];
-extern int opts;
-extern int use_inet6;
-
-int addicmp __P((char ***, struct frentry *, int));
-int extras __P((char ***, struct frentry *, int));
-
-int icmpcode __P((char *)), addkeep __P((char ***, struct frentry *, int));
-int to_interface __P((frdest_t *, char *, int));
-void print_toif __P((char *, frdest_t *));
-void optprint __P((u_short *, u_long, u_long));
-int loglevel __P((char **, u_int *, int));
-void printlog __P((frentry_t *));
-void printifname __P((char *, char *, void *));
-
-extern char *proto;
-extern char flagset[];
-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, status)
-char *line;
-int linenum;
-int *status; /* good, bad, or indifferent */
-{
- static struct frentry fil;
- char *cps[31], **cpp, *endptr, *s;
- struct protoent *p = NULL;
- int i, cnt = 1, j, ch;
- u_int k;
-
- *status = 100; /* default to error */
-
- while (*line && isspace(*line))
- line++;
- if (!*line) {
- *status = 0;
- return NULL;
- }
-
- bzero((char *)&fil, sizeof(fil));
- fil.fr_mip.fi_v = 0xf;
- fil.fr_ip.fi_v = use_inet6 ? 6 : 4;
- fil.fr_loglevel = 0xffff;
-
- /*
- * break line up into max of 20 segments
- */
- if (opts & OPT_DEBUG)
- fprintf(stderr, "parse [%s]\n", line);
- for (i = 0, *cps = strtok(line, " \b\t\r\n"); cps[i] && i < 30; cnt++)
- cps[++i] = strtok(NULL, " \b\t\r\n");
- cps[i] = NULL;
-
- if (cnt < 3) {
- fprintf(stderr, "%d: not enough segments in line\n", linenum);
- *status = -1;
- return NULL;
- }
-
- cpp = cps;
- /*
- * The presence of an '@' followed by a number gives the position in
- * the current rule list to insert this one.
- */
- if (**cpp == '@')
- fil.fr_hits = (U_QUAD_T)atoi(*cpp++ + 1) + 1;
-
-
- /*
- * Check the first keyword in the rule and any options that are
- * expected to follow it.
- */
- if (!strcasecmp("block", *cpp)) {
- fil.fr_flags |= FR_BLOCK;
- if (!strncasecmp(*(cpp+1), "return-icmp-as-dest", 19) &&
- (i = 19))
- fil.fr_flags |= FR_FAKEICMP;
- else if (!strncasecmp(*(cpp+1), "return-icmp", 11) && (i = 11))
- fil.fr_flags |= FR_RETICMP;
- if (fil.fr_flags & FR_RETICMP) {
- cpp++;
- if (strlen(*cpp) == i) {
- if (*(cpp + 1) && **(cpp +1) == '(') {
- cpp++;
- i = 0;
- } else
- i = -1;
- }
-
- /*
- * The ICMP code is not required to follow in ()'s
- */
- if ((i >= 0) && (*(*cpp + i) == '(')) {
- i++;
- j = icmpcode(*cpp + i);
- if (j == -1) {
- fprintf(stderr,
- "%d: unrecognised icmp code %s\n",
- linenum, *cpp + 20);
- *status = -1;
- return NULL;
- }
- fil.fr_icode = j;
- }
- } else if (!strcasecmp(*(cpp+1), "return-rst")) {
- fil.fr_flags |= FR_RETRST;
- cpp++;
- }
- } else if (!strcasecmp("count", *cpp)) {
- fil.fr_flags |= FR_ACCOUNT;
- } else if (!strcasecmp("pass", *cpp)) {
- fil.fr_flags |= FR_PASS;
- } else if (!strcasecmp("nomatch", *cpp)) {
- fil.fr_flags |= FR_NOMATCH;
- } else if (!strcasecmp("auth", *cpp)) {
- fil.fr_flags |= FR_AUTH;
- if (!strncasecmp(*(cpp+1), "return-rst", 10)) {
- fil.fr_flags |= FR_RETRST;
- cpp++;
- }
- } else if (!strcasecmp("preauth", *cpp)) {
- fil.fr_flags |= FR_PREAUTH;
- } else if (!strcasecmp("skip", *cpp)) {
- cpp++;
- if (ratoui(*cpp, &k, 0, UINT_MAX))
- fil.fr_skip = k;
- else {
- fprintf(stderr, "%d: integer must follow skip\n",
- linenum);
- *status = -1;
- return NULL;
- }
- } else if (!strcasecmp("log", *cpp)) {
- fil.fr_flags |= FR_LOG;
- if (!strcasecmp(*(cpp+1), "body")) {
- fil.fr_flags |= FR_LOGBODY;
- cpp++;
- }
- if (!strcasecmp(*(cpp+1), "first")) {
- fil.fr_flags |= FR_LOGFIRST;
- cpp++;
- }
- if (*cpp && !strcasecmp(*(cpp+1), "or-block")) {
- fil.fr_flags |= FR_LOGORBLOCK;
- cpp++;
- }
- if (!strcasecmp(*(cpp+1), "level")) {
- cpp++;
- if (loglevel(cpp, &fil.fr_loglevel, linenum) == -1) {
- /* NB loglevel prints its own error message */
- *status = -1;
- return NULL;
- }
- cpp++;
- }
- } else {
- /*
- * 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;
- }
-
- /*
- * Get the direction for filtering. Impose restrictions on direction
- * if blocking with returning ICMP or an RST has been requested.
- */
- if (!strcasecmp("in", *cpp))
- fil.fr_flags |= FR_INQUE;
- else if (!strcasecmp("out", *cpp)) {
- fil.fr_flags |= FR_OUTQUE;
- if (fil.fr_flags & FR_RETICMP) {
- 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;
- }
-
- if (!strcasecmp("log", *cpp)) {
- if (!*++cpp) {
- fprintf(stderr, "%d: missing source specification\n",
- linenum);
- *status = -1;
- return NULL;
- }
- if (fil.fr_flags & FR_PASS)
- fil.fr_flags |= FR_LOGP;
- else if (fil.fr_flags & FR_BLOCK)
- fil.fr_flags |= FR_LOGB;
- if (*cpp && !strcasecmp(*cpp, "body")) {
- fil.fr_flags |= FR_LOGBODY;
- cpp++;
- }
- if (*cpp && !strcasecmp(*cpp, "first")) {
- fil.fr_flags |= FR_LOGFIRST;
- cpp++;
- }
- if (*cpp && !strcasecmp(*cpp, "or-block")) {
- if (!(fil.fr_flags & FR_PASS)) {
- 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) {
- *status = -1;
- return NULL;
- }
- cpp++;
- cpp++;
- }
- }
-
- if (*cpp && !strcasecmp("quick", *cpp)) {
- if (fil.fr_skip != 0) {
- fprintf(stderr, "%d: cannot use skip with quick\n",
- linenum);
- *status = -1;
- return NULL;
- }
- cpp++;
- fil.fr_flags |= FR_QUICK;
- }
-
- /*
- * Parse rule options that are available if a rule is tied to an
- * interface.
- */
- *fil.fr_ifname = '\0';
- *fil.fr_oifname = '\0';
- if (*cpp && !strcasecmp(*cpp, "on")) {
- if (!*++cpp) {
- fprintf(stderr, "%d: interface name missing\n",
- linenum);
- *status = -1;
- return NULL;
- }
-
- s = index(*cpp, ',');
- if (s != NULL) {
- *s++ = '\0';
- (void)strncpy(fil.fr_ifnames[1], s, IFNAMSIZ - 1);
- fil.fr_ifnames[1][IFNAMSIZ - 1] = '\0';
- } else
- strcpy(fil.fr_ifnames[1], "*");
-
- (void)strncpy(fil.fr_ifnames[0], *cpp, IFNAMSIZ - 1);
- fil.fr_ifnames[0][IFNAMSIZ - 1] = '\0';
-
- cpp++;
- if (!*cpp) {
- if ((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;
- }
- *status = 0;
- return &fil;
- }
-
- if (*cpp) {
- if (!strcasecmp(*cpp, "dup-to") && *(cpp + 1)) {
- cpp++;
- 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)) {
- *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;
- cpp++;
- }
- }
-
- /*
- * Set the "other" interface name. Lets you specify both
- * inbound and outbound interfaces for state rules. Do not
- * prevent both interfaces from being the same.
- */
- strcpy(fil.fr_ifnames[3], "*");
- if ((*cpp != NULL) && (*(cpp + 1) != NULL) &&
- ((((fil.fr_flags & FR_INQUE) != 0) &&
- (strcasecmp(*cpp, "out-via") == 0)) ||
- (((fil.fr_flags & FR_OUTQUE) != 0) &&
- (strcasecmp(*cpp, "in-via") == 0)))) {
- cpp++;
-
- s = index(*cpp, ',');
- if (s != NULL) {
- *s++ = '\0';
- (void)strncpy(fil.fr_ifnames[3], s,
- IFNAMSIZ - 1);
- fil.fr_ifnames[3][IFNAMSIZ - 1] = '\0';
- }
-
- (void)strncpy(fil.fr_ifnames[2], *cpp, IFNAMSIZ - 1);
- fil.fr_ifnames[2][IFNAMSIZ - 1] = '\0';
- cpp++;
- } else
- strcpy(fil.fr_ifnames[2], "*");
- }
- 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);
- fil.fr_mip.fi_tos = 0xff;
- cpp++;
- }
-
- if (*cpp && !strcasecmp(*cpp, "ttl")) {
- if (!*++cpp) {
- fprintf(stderr, "%d: ttl missing hopcount value\n",
- linenum);
- *status = -1;
- return NULL;
- }
- if (ratoi(*cpp, &i, 0, 255))
- fil.fr_ttl = i;
- else {
- fprintf(stderr, "%d: invalid ttl (%s)\n",
- linenum, *cpp);
- *status = -1;
- return NULL;
- }
- fil.fr_mip.fi_ttl = 0xff;
- cpp++;
- }
-
- /*
- * check for "proto <protoname>" only decode udp/tcp/icmp as protoname
- */
- proto = NULL;
- if (*cpp && !strcasecmp(*cpp, "proto")) {
- if (!*++cpp) {
- fprintf(stderr, "%d: protocol name missing\n", linenum);
- *status = -1;
- return NULL;
- }
- proto = *cpp++;
- if (!strcasecmp(proto, "tcp/udp")) {
- fil.fr_ip.fi_fl |= FI_TCPUDP;
- fil.fr_mip.fi_fl |= FI_TCPUDP;
- } else if (use_inet6 && !strcasecmp(proto, "icmp")) {
- fprintf(stderr,
-"%d: use proto ipv6-icmp with IPv6 (or use proto 1 if you really mean icmp)\n",
- linenum);
- } else {
- if (!(p = getprotobyname(proto)) && !isdigit(*proto)) {
- fprintf(stderr,
- "%d: unknown protocol (%s)\n",
- linenum, proto);
- *status = -1;
- return NULL;
- }
- if (p)
- fil.fr_proto = p->p_proto;
- else if (isdigit(*proto)) {
- i = (int)strtol(proto, &endptr, 0);
- if (*endptr != '\0' || i < 0 || i > 255) {
- fprintf(stderr,
- "%d: unknown protocol (%s)\n",
- linenum, proto);
- *status = -1;
- return NULL;
- }
- fil.fr_proto = i;
- }
- fil.fr_mip.fi_p = 0xff;
- }
- }
- if ((fil.fr_proto != IPPROTO_TCP) &&
- ((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;
- }
-
- /*
- * get the from host and bit mask to use against packets
- */
-
- if (!*cpp) {
- fprintf(stderr, "%d: missing source specification\n", linenum);
- *status = -1;
- return NULL;
- }
- if (!strcasecmp(*cpp, "all")) {
- 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, "!")) {
- fil.fr_flags |= FR_NOTSRCIP;
- if (!*++cpp) {
- fprintf(stderr,
- "%d: missing host after from\n",
- linenum);
- *status = -1;
- return NULL;
- }
- } else if (**cpp == '!') {
- fil.fr_flags |= FR_NOTSRCIP;
- (*cpp)++;
- }
- ch = 0;
- 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;
- }
-
- if ((ch != 0) && (fil.fr_proto != IPPROTO_TCP) &&
- (fil.fr_proto != IPPROTO_UDP) &&
- !(fil.fr_ip.fi_fl & FI_TCPUDP)) {
- 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;
- }
-
- /*
- * do the same for the to field (destination host)
- */
- 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;
- if (!strcmp(*cpp, "!")) {
- fil.fr_flags |= FR_NOTDSTIP;
- if (!*++cpp) {
- fprintf(stderr,
- "%d: missing host after from\n",
- linenum);
- *status = -1;
- return NULL;
- }
- } else if (**cpp == '!') {
- fil.fr_flags |= FR_NOTDSTIP;
- (*cpp)++;
- }
- 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) &&
- (fil.fr_proto != IPPROTO_UDP) &&
- !(fil.fr_ip.fi_fl & FI_TCPUDP)) {
- fprintf(stderr,
- "%d: cannot use port and neither tcp or udp\n",
- linenum);
- *status = -1;
- return NULL;
- }
-
- fil.fr_dcmp = ch;
- }
-
- /*
- * check some sanity, make sure we don't have icmp checks with tcp
- * or udp or visa versa.
- */
- 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) {
- *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);
- cpp++;
- }
-
- /*
- * extras...
- */
- if ((fil.fr_v == 4) && *cpp && (!strcasecmp(*cpp, "with") ||
- !strcasecmp(*cpp, "and")))
- if (extras(&cpp, &fil, linenum)) {
- *status = -1;
- return NULL;
- }
-
- /*
- * icmp types for use with the icmp protocol
- */
- if (*cpp && !strcasecmp(*cpp, "icmp-type")) {
- if (fil.fr_proto != IPPROTO_ICMP &&
- fil.fr_proto != IPPROTO_ICMPV6) {
- fprintf(stderr,
- "%d: icmp with wrong protocol (%d)\n",
- linenum, fil.fr_proto);
- *status = -1;
- return NULL;
- }
- if (addicmp(&cpp, &fil, linenum)) {
- *status = -1;
- return NULL;
- }
- fil.fr_icmp = htons(fil.fr_icmp);
- fil.fr_icmpm = htons(fil.fr_icmpm);
- }
-
- /*
- * Keep something...
- */
- while (*cpp && !strcasecmp(*cpp, "keep"))
- if (addkeep(&cpp, &fil, linenum)) {
- *status = -1;
- return NULL;
- }
-
- /*
- * This is here to enforce the old interface binding behaviour.
- * That is, "on X" is equivalent to "<dir> on X <!dir>-via -,X"
- */
- if (fil.fr_flags & FR_KEEPSTATE) {
- if (*fil.fr_ifnames[0] && !*fil.fr_ifnames[3]) {
- bcopy(fil.fr_ifnames[0], fil.fr_ifnames[3],
- sizeof(fil.fr_ifnames[3]));
- strncpy(fil.fr_ifnames[2], "*",
- sizeof(fil.fr_ifnames[3]));
- }
- }
-
- /*
- * head of a new group ?
- */
- if (*cpp && !strcasecmp(*cpp, "head")) {
- 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))
- fil.fr_grhead = (u_32_t)k;
- else {
- fprintf(stderr, "%d: invalid group (%s)\n",
- linenum, *cpp);
- *status = -1;
- return NULL;
- }
- cpp++;
- }
-
- /*
- * head of a new group ?
- */
- if (*cpp && !strcasecmp(*cpp, "group")) {
- if (!*++cpp) {
- fprintf(stderr, "%d: group without group #\n",
- linenum);
- *status = -1;
- return NULL;
- }
- if (ratoui(*cpp, &k, 0, UINT_MAX))
- fil.fr_group = k;
- else {
- fprintf(stderr, "%d: invalid group (%s)\n",
- linenum, *cpp);
- *status = -1;
- return NULL;
- }
- cpp++;
- }
-
- /*
- * leftovers...yuck
- */
- if (*cpp && **cpp) {
- fprintf(stderr, "%d: unknown words at end: [", linenum);
- for (; *cpp; cpp++)
- fprintf(stderr, "%s ", *cpp);
- fprintf(stderr, "]\n");
- *status = -1;
- return NULL;
- }
-
- /*
- * lazy users...
- */
- 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) &&
- (fil.fr_proto != IPPROTO_UDP) && (fil.fr_dcmp || fil.fr_scmp)) {
- if (!fil.fr_proto) {
- fil.fr_ip.fi_fl |= FI_TCPUDP;
- fil.fr_mip.fi_fl |= FI_TCPUDP;
- } else {
- fprintf(stderr,
- "%d: port comparisons for non-TCP/UDP\n",
- linenum);
- *status = -1;
- return NULL;
- }
- }
-/*
- if ((fil.fr_flags & FR_KEEPFRAG) &&
- (!(fil.fr_ip.fi_fl & FI_FRAG) || !(fil.fr_ip.fi_fl & FI_FRAG))) {
- fprintf(stderr,
- "%d: must use 'with frags' with 'keep frags'\n",
- linenum);
- *status = -1;
- return NULL;
- }
-*/
- *status = 0;
- return &fil;
-}
-
-
-int loglevel(cpp, facpri, linenum)
-char **cpp;
-u_int *facpri;
-int linenum;
-{
- int fac, pri;
- char *s;
-
- fac = 0;
- pri = 0;
- if (!*++cpp) {
- fprintf(stderr, "%d: %s\n", linenum,
- "missing identifier after level");
- return -1;
- }
-
- s = index(*cpp, '.');
- if (s) {
- *s++ = '\0';
- fac = fac_findname(*cpp);
- if (fac == -1) {
- fprintf(stderr, "%d: %s %s\n", linenum,
- "Unknown facility", *cpp);
- return -1;
- }
- pri = pri_findname(s);
- if (pri == -1) {
- fprintf(stderr, "%d: %s %s\n", linenum,
- "Unknown priority", s);
- return -1;
- }
- } else {
- pri = pri_findname(*cpp);
- if (pri == -1) {
- fprintf(stderr, "%d: %s %s\n", linenum,
- "Unknown priority", *cpp);
- return -1;
- }
- }
- *facpri = fac|pri;
- return 0;
-}
-
-
-int to_interface(fdp, to, linenum)
-frdest_t *fdp;
-char *to;
-int linenum;
-{
- char *s;
-
- s = index(to, ':');
- fdp->fd_ifp = NULL;
- if (s) {
- *s++ = '\0';
- if (hostnum((u_32_t *)&fdp->fd_ip, s, linenum) == -1)
- return -1;
- }
- (void) strncpy(fdp->fd_ifname, to, sizeof(fdp->fd_ifname) - 1);
- fdp->fd_ifname[sizeof(fdp->fd_ifname) - 1] = '\0';
- return 0;
-}
-
-
-void print_toif(tag, fdp)
-char *tag;
-frdest_t *fdp;
-{
- printf("%s %s%s", tag, fdp->fd_ifname,
- (fdp->fd_ifp || (long)fdp->fd_ifp == -1) ? "" : "(!)");
-#ifdef USE_INET6
- if (use_inet6 && IP6_NOTZERO(&fdp->fd_ip6.in6)) {
- char ipv6addr[80];
-
- inet_ntop(AF_INET6, &fdp->fd_ip6, ipv6addr,
- sizeof(fdp->fd_ip6));
- printf(":%s", ipv6addr);
- } else
-#endif
- if (fdp->fd_ip.s_addr)
- printf(":%s", inet_ntoa(fdp->fd_ip));
- putchar(' ');
-}
-
-
-/*
- * deal with extra bits on end of the line
- */
-int extras(cp, fr, linenum)
-char ***cp;
-struct frentry *fr;
-int linenum;
-{
- u_short secmsk;
- u_long opts;
- int notopt;
- char oflags;
-
- opts = 0;
- secmsk = 0;
- notopt = 0;
- (*cp)++;
- if (!**cp)
- return -1;
-
- while (**cp && (!strncasecmp(**cp, "ipopt", 5) ||
- !strcasecmp(**cp, "not") || !strncasecmp(**cp, "opt", 3) ||
- !strncasecmp(**cp, "frag", 4) || !strcasecmp(**cp, "no") ||
- !strcasecmp(**cp, "short"))) {
- if (***cp == 'n' || ***cp == 'N') {
- notopt = 1;
- (*cp)++;
- continue;
- } else if (***cp == 'i' || ***cp == 'I') {
- if (!notopt)
- fr->fr_ip.fi_fl |= FI_OPTIONS;
- fr->fr_mip.fi_fl |= FI_OPTIONS;
- goto nextopt;
- } else if (***cp == 'f' || ***cp == 'F') {
- if (!notopt)
- fr->fr_ip.fi_fl |= FI_FRAG;
- fr->fr_mip.fi_fl |= FI_FRAG;
- goto nextopt;
- } else if (***cp == 'o' || ***cp == 'O') {
- if (!*(*cp + 1)) {
- fprintf(stderr,
- "%d: opt missing arguements\n",
- linenum);
- return -1;
- }
- (*cp)++;
- if (!(opts = optname(cp, &secmsk, linenum)))
- return -1;
- oflags = FI_OPTIONS;
- } else if (***cp == 's' || ***cp == 'S') {
- if (fr->fr_tcpf) {
- fprintf(stderr,
- "%d: short cannot be used with TCP flags\n",
- linenum);
- return -1;
- }
-
- if (!notopt)
- fr->fr_ip.fi_fl |= FI_SHORT;
- fr->fr_mip.fi_fl |= FI_SHORT;
- goto nextopt;
- } else
- return -1;
-
- if (!notopt || !opts)
- fr->fr_mip.fi_fl |= oflags;
- if (notopt) {
- if (!secmsk) {
- fr->fr_mip.fi_optmsk |= opts;
- } else {
- fr->fr_mip.fi_optmsk |= (opts & ~0x0100);
- }
- } else {
- fr->fr_mip.fi_optmsk |= opts;
- }
- fr->fr_mip.fi_secmsk |= secmsk;
-
- if (notopt) {
- fr->fr_ip.fi_fl &= (~oflags & 0xf);
- fr->fr_ip.fi_optmsk &= ~opts;
- fr->fr_ip.fi_secmsk &= ~secmsk;
- } else {
- fr->fr_ip.fi_fl |= oflags;
- fr->fr_ip.fi_optmsk |= opts;
- fr->fr_ip.fi_secmsk |= secmsk;
- }
-nextopt:
- notopt = 0;
- opts = 0;
- oflags = 0;
- secmsk = 0;
- (*cp)++;
- }
- return 0;
-}
-
-
-u_32_t optname(cp, sp, linenum)
-char ***cp;
-u_short *sp;
-int linenum;
-{
- struct ipopt_names *io, *so;
- u_long msk = 0;
- u_short smsk = 0;
- char *s;
- int sec = 0;
-
- for (s = strtok(**cp, ","); s; s = strtok(NULL, ",")) {
- for (io = ionames; io->on_name; io++)
- if (!strcasecmp(s, io->on_name)) {
- msk |= io->on_bit;
- break;
- }
- if (!io->on_name) {
- fprintf(stderr, "%d: unknown IP option name %s\n",
- linenum, s);
- return 0;
- }
- if (!strcasecmp(s, "sec-class"))
- sec = 1;
- }
-
- if (sec && !*(*cp + 1)) {
- fprintf(stderr, "%d: missing security level after sec-class\n",
- linenum);
- return 0;
- }
-
- if (sec) {
- (*cp)++;
- for (s = strtok(**cp, ","); s; s = strtok(NULL, ",")) {
- for (so = secclass; so->on_name; so++)
- if (!strcasecmp(s, so->on_name)) {
- smsk |= so->on_bit;
- break;
- }
- if (!so->on_name) {
- fprintf(stderr,
- "%d: no such security level: %s\n",
- linenum, s);
- return 0;
- }
- }
- if (smsk)
- *sp = smsk;
- }
- return msk;
-}
-
-
-#ifdef __STDC__
-void optprint(u_short *sec, u_long optmsk, u_long optbits)
-#else
-void optprint(sec, optmsk, optbits)
-u_short *sec;
-u_long optmsk, optbits;
-#endif
-{
- u_short secmsk = sec[0], secbits = sec[1];
- struct ipopt_names *io, *so;
- char *s;
-
- s = " opt ";
- for (io = ionames; io->on_name; io++)
- if ((io->on_bit & optmsk) &&
- ((io->on_bit & optmsk) == (io->on_bit & optbits))) {
- if ((io->on_value != IPOPT_SECURITY) ||
- (!secmsk && !secbits)) {
- printf("%s%s", s, io->on_name);
- if (io->on_value == IPOPT_SECURITY)
- io++;
- s = ",";
- }
- }
-
-
- if (secmsk & secbits) {
- printf("%ssec-class", s);
- s = " ";
- for (so = secclass; so->on_name; so++)
- if ((secmsk & so->on_bit) &&
- ((so->on_bit & secmsk) == (so->on_bit & secbits))) {
- printf("%s%s", s, so->on_name);
- s = ",";
- }
- }
-
- if ((optmsk && (optmsk != optbits)) ||
- (secmsk && (secmsk != secbits))) {
- s = " ";
- printf(" not opt");
- if (optmsk != optbits) {
- for (io = ionames; io->on_name; io++)
- if ((io->on_bit & optmsk) &&
- ((io->on_bit & optmsk) !=
- (io->on_bit & optbits))) {
- if ((io->on_value != IPOPT_SECURITY) ||
- (!secmsk && !secbits)) {
- printf("%s%s", s, io->on_name);
- s = ",";
- if (io->on_value ==
- IPOPT_SECURITY)
- io++;
- } else
- io++;
- }
- }
-
- if (secmsk != secbits) {
- printf("%ssec-class", s);
- s = " ";
- for (so = secclass; so->on_name; so++)
- if ((so->on_bit & secmsk) &&
- ((so->on_bit & secmsk) !=
- (so->on_bit & secbits))) {
- printf("%s%s", s, so->on_name);
- s = ",";
- }
- }
- }
-}
-
-char *icmptypes[] = {
- "echorep", (char *)NULL, (char *)NULL, "unreach", "squench",
- "redir", (char *)NULL, (char *)NULL, "echo", "routerad",
- "routersol", "timex", "paramprob", "timest", "timestrep",
- "inforeq", "inforep", "maskreq", "maskrep", "END"
-};
-
-/*
- * set the icmp field to the correct type if "icmp" word is found
- */
-int addicmp(cp, fp, linenum)
-char ***cp;
-struct frentry *fp;
-int linenum;
-{
- char **t;
- int i;
-
- (*cp)++;
- if (!**cp)
- return -1;
-
- if (isdigit(***cp)) {
- if (!ratoi(**cp, &i, 0, 255)) {
- fprintf(stderr,
- "%d: Invalid icmp-type (%s) specified\n",
- linenum, **cp);
- return -1;
- }
- } else if (fp->fr_proto == IPPROTO_ICMPV6) {
- fprintf(stderr, "%d: Unknown ICMPv6 type (%s) specified, %s",
- linenum, **cp, "(use numeric value instead)\n");
- return -1;
- } else {
- for (t = icmptypes, i = 0; ; t++, i++) {
- if (!*t)
- continue;
- if (!strcasecmp("END", *t)) {
- i = -1;
- break;
- }
- if (!strcasecmp(*t, **cp))
- break;
- }
- if (i == -1) {
- fprintf(stderr,
- "%d: Invalid icmp-type (%s) specified\n",
- linenum, **cp);
- return -1;
- }
- }
- fp->fr_icmp = (u_short)(i << 8);
- fp->fr_icmpm = (u_short)0xff00;
- (*cp)++;
- if (!**cp)
- return 0;
-
- if (**cp && strcasecmp("code", **cp))
- return 0;
- (*cp)++;
- if (isdigit(***cp)) {
- if (!ratoi(**cp, &i, 0, 255)) {
- fprintf(stderr,
- "%d: Invalid icmp code (%s) specified\n",
- linenum, **cp);
- return -1;
- }
- } else {
- i = icmpcode(**cp);
- if (i == -1) {
- fprintf(stderr,
- "%d: Invalid icmp code (%s) specified\n",
- linenum, **cp);
- return -1;
- }
- }
- i &= 0xff;
- fp->fr_icmp |= (u_short)i;
- fp->fr_icmpm = (u_short)0xffff;
- (*cp)++;
- return 0;
-}
-
-
-#define MAX_ICMPCODE 15
-
-char *icmpcodes[] = {
- "net-unr", "host-unr", "proto-unr", "port-unr", "needfrag",
- "srcfail", "net-unk", "host-unk", "isolate", "net-prohib",
- "host-prohib", "net-tos", "host-tos", "filter-prohib", "host-preced",
- "preced-cutoff", NULL };
-/*
- * Return the number for the associated ICMP unreachable code.
- */
-int icmpcode(str)
-char *str;
-{
- char *s;
- int i, len;
-
- if ((s = strrchr(str, ')')))
- *s = '\0';
- if (isdigit(*str)) {
- if (!ratoi(str, &i, 0, 255))
- return -1;
- else
- return i;
- }
- len = strlen(str);
- for (i = 0; icmpcodes[i]; i++)
- if (!strncasecmp(str, icmpcodes[i], MIN(len,
- strlen(icmpcodes[i])) ))
- return i;
- return -1;
-}
-
-
-/*
- * set the icmp field to the correct type if "icmp" word is found
- */
-int addkeep(cp, fp, linenum)
-char ***cp;
-struct frentry *fp;
-int linenum;
-{
- char *s;
-
- (*cp)++;
- if (!**cp) {
- fprintf(stderr, "%d: Missing keyword after keep\n",
- linenum);
- return -1;
- }
-
- if (strcasecmp(**cp, "state") == 0)
- fp->fr_flags |= FR_KEEPSTATE;
- else if (strncasecmp(**cp, "frag", 4) == 0)
- fp->fr_flags |= FR_KEEPFRAG;
- else if (strcasecmp(**cp, "state-age") == 0) {
- if (fp->fr_ip.fi_p == IPPROTO_TCP) {
- fprintf(stderr, "%d: cannot use state-age with tcp\n",
- linenum);
- return -1;
- }
- if ((fp->fr_flags & FR_KEEPSTATE) == 0) {
- fprintf(stderr, "%d: state-age with no 'keep state'\n",
- linenum);
- return -1;
- }
- (*cp)++;
- if (!**cp) {
- fprintf(stderr, "%d: state-age with no arg\n",
- linenum);
- return -1;
- }
- fp->fr_age[0] = atoi(**cp);
- s = index(**cp, '/');
- if (s != NULL) {
- s++;
- fp->fr_age[1] = atoi(s);
- } else
- fp->fr_age[1] = fp->fr_age[0];
- } else {
- fprintf(stderr, "%d: Unrecognised state keyword \"%s\"\n",
- linenum, **cp);
- return -1;
- }
- (*cp)++;
- return 0;
-}
-
-
-void printifname(format, name, ifp)
-char *format, *name;
-void *ifp;
-{
- printf("%s%s", format, name);
- if ((ifp == NULL) && strcmp(name, "-") && strcmp(name, "*"))
- printf("(!)");
-}
-
-
-/*
- * print the filter structure in a useful way
- */
-void printfr(fp)
-struct frentry *fp;
-{
- struct protoent *p;
- u_short sec[2];
- char *s;
- u_char *t;
- int pr;
-
- if (fp->fr_flags & FR_PASS)
- printf("pass");
- if (fp->fr_flags & FR_NOMATCH)
- printf("nomatch");
- else if (fp->fr_flags & FR_BLOCK) {
- printf("block");
- if (fp->fr_flags & FR_RETICMP) {
- if ((fp->fr_flags & FR_RETMASK) == FR_FAKEICMP)
- printf(" return-icmp-as-dest");
- else if ((fp->fr_flags & FR_RETMASK) == FR_RETICMP)
- printf(" return-icmp");
- if (fp->fr_icode) {
- if (fp->fr_icode <= MAX_ICMPCODE)
- printf("(%s)",
- icmpcodes[(int)fp->fr_icode]);
- else
- printf("(%d)", fp->fr_icode);
- }
- } else if ((fp->fr_flags & FR_RETMASK) == FR_RETRST)
- printf(" return-rst");
- } else if ((fp->fr_flags & FR_LOGMASK) == FR_LOG) {
- printlog(fp);
- } else if (fp->fr_flags & FR_ACCOUNT)
- printf("count");
- else if (fp->fr_flags & FR_AUTH) {
- printf("auth");
- if ((fp->fr_flags & FR_RETMASK) == FR_RETRST)
- printf(" return-rst");
- } else if (fp->fr_flags & FR_PREAUTH)
- printf("preauth");
- else if (fp->fr_skip)
- printf("skip %hu", fp->fr_skip);
-
- if (fp->fr_flags & FR_OUTQUE)
- printf(" out ");
- else
- printf(" in ");
-
- if (((fp->fr_flags & FR_LOGB) == FR_LOGB) ||
- ((fp->fr_flags & FR_LOGP) == FR_LOGP)) {
- printlog(fp);
- putchar(' ');
- }
-
- if (fp->fr_flags & FR_QUICK)
- printf("quick ");
-
- if (*fp->fr_ifname) {
- printifname("on ", fp->fr_ifname, fp->fr_ifa);
- if (*fp->fr_ifnames[1] && strcmp(fp->fr_ifnames[1], "*"))
- printifname(",", fp->fr_ifnames[1], fp->fr_ifas[1]);
- putchar(' ');
-
- if (*fp->fr_dif.fd_ifname)
- print_toif("dup-to", &fp->fr_dif);
- if (*fp->fr_tif.fd_ifname)
- print_toif("to", &fp->fr_tif);
- if (fp->fr_flags & FR_FASTROUTE)
- printf("fastroute ");
-
- if ((*fp->fr_ifnames[2] && strcmp(fp->fr_ifnames[2], "*")) ||
- (*fp->fr_ifnames[3] && strcmp(fp->fr_ifnames[3], "*"))) {
- if (fp->fr_flags & FR_OUTQUE)
- printf("in-via ");
- else
- printf("out-via ");
-
- if (*fp->fr_ifnames[2]) {
- printifname("", fp->fr_ifnames[2],
- fp->fr_ifas[2]);
- putchar(',');
- }
-
- if (*fp->fr_ifnames[3])
- printifname("", fp->fr_ifnames[3],
- fp->fr_ifas[3]);
- putchar(' ');
- }
- }
-
- if (fp->fr_mip.fi_tos)
- printf("tos %#x ", fp->fr_tos);
- if (fp->fr_mip.fi_ttl)
- printf("ttl %d ", fp->fr_ttl);
- if (fp->fr_ip.fi_fl & FI_TCPUDP) {
- printf("proto tcp/udp ");
- pr = -1;
- } else if ((pr = fp->fr_mip.fi_p)) {
- if ((p = getprotobynumber(fp->fr_proto)))
- printf("proto %s ", p->p_name);
- else
- printf("proto %d ", fp->fr_proto);
- }
-
- printf("from %s", fp->fr_flags & FR_NOTSRCIP ? "!" : "");
- printhostmask(fp->fr_v, (u_32_t *)&fp->fr_src.s_addr,
- (u_32_t *)&fp->fr_smsk.s_addr);
- if (fp->fr_scmp)
- printportcmp(pr, &fp->fr_tuc.ftu_src);
-
- printf(" to %s", fp->fr_flags & FR_NOTDSTIP ? "!" : "");
- printhostmask(fp->fr_v, (u_32_t *)&fp->fr_dst.s_addr,
- (u_32_t *)&fp->fr_dmsk.s_addr);
- if (fp->fr_dcmp)
- printportcmp(pr, &fp->fr_tuc.ftu_dst);
-
- if ((fp->fr_ip.fi_fl & ~FI_TCPUDP) ||
- (fp->fr_mip.fi_fl & ~FI_TCPUDP) ||
- fp->fr_ip.fi_optmsk || fp->fr_mip.fi_optmsk ||
- fp->fr_ip.fi_secmsk || fp->fr_mip.fi_secmsk) {
- printf(" with");
- if (fp->fr_ip.fi_optmsk || fp->fr_mip.fi_optmsk ||
- fp->fr_ip.fi_secmsk || fp->fr_mip.fi_secmsk) {
- sec[0] = fp->fr_mip.fi_secmsk;
- sec[1] = fp->fr_ip.fi_secmsk;
- optprint(sec,
- fp->fr_mip.fi_optmsk, fp->fr_ip.fi_optmsk);
- } else if (fp->fr_mip.fi_fl & FI_OPTIONS) {
- if (!(fp->fr_ip.fi_fl & FI_OPTIONS))
- printf(" not");
- printf(" ipopt");
- }
- if (fp->fr_mip.fi_fl & FI_SHORT) {
- if (!(fp->fr_ip.fi_fl & FI_SHORT))
- printf(" not");
- printf(" short");
- }
- if (fp->fr_mip.fi_fl & FI_FRAG) {
- if (!(fp->fr_ip.fi_fl & FI_FRAG))
- printf(" not");
- printf(" frag");
- }
- }
- if (fp->fr_proto == IPPROTO_ICMP && fp->fr_icmpm != 0) {
- int type = fp->fr_icmp, code;
-
- type = ntohs(fp->fr_icmp);
- code = type & 0xff;
- type /= 256;
- if (type < (sizeof(icmptypes) / sizeof(char *) - 1) &&
- icmptypes[type])
- printf(" icmp-type %s", icmptypes[type]);
- else
- printf(" icmp-type %d", type);
- if (ntohs(fp->fr_icmpm) & 0xff)
- printf(" code %d", code);
- }
- if (fp->fr_proto == IPPROTO_ICMPV6 && fp->fr_icmpm != 0) {
- int type = fp->fr_icmp, code;
-
- type = ntohs(fp->fr_icmp);
- code = type & 0xff;
- type /= 256;
- printf(" icmp-type %d", type);
- if (ntohs(fp->fr_icmpm) & 0xff)
- printf(" code %d", code);
- }
- if (fp->fr_proto == IPPROTO_TCP && (fp->fr_tcpf || fp->fr_tcpfm)) {
- printf(" flags ");
- if (fp->fr_tcpf & ~TCPF_ALL)
- printf("0x%x", fp->fr_tcpf);
- else
- for (s = flagset, t = flags; *s; s++, t++)
- if (fp->fr_tcpf & *t)
- (void)putchar(*s);
- if (fp->fr_tcpfm) {
- (void)putchar('/');
- if (fp->fr_tcpfm & ~TCPF_ALL)
- printf("0x%x", fp->fr_tcpfm);
- else
- for (s = flagset, t = flags; *s; s++, t++)
- if (fp->fr_tcpfm & *t)
- (void)putchar(*s);
- }
- }
-
- if (fp->fr_flags & FR_KEEPSTATE)
- printf(" keep state");
- if (fp->fr_flags & FR_KEEPFRAG)
- printf(" keep frags");
- if (fp->fr_age[0] != 0 || fp->fr_age[1]!= 0)
- printf(" state-age %u/%u", fp->fr_age[0], fp->fr_age[1]);
- if (fp->fr_grhead)
- printf(" head %d", fp->fr_grhead);
- if (fp->fr_group)
- printf(" group %d", fp->fr_group);
- (void)putchar('\n');
-}
-
-void binprint(fp)
-struct frentry *fp;
-{
- int i = sizeof(*fp), j = 0;
- u_char *s;
-
- for (s = (u_char *)fp; i; i--, s++) {
- j++;
- printf("%02x ", *s);
- if (j == 16) {
- printf("\n");
- j = 0;
- }
- }
- putchar('\n');
- (void)fflush(stdout);
-}
-
-
-void printlog(fp)
-frentry_t *fp;
-{
- char *s, *u;
-
- printf("log");
- if (fp->fr_flags & FR_LOGBODY)
- printf(" body");
- if (fp->fr_flags & FR_LOGFIRST)
- printf(" first");
- if (fp->fr_flags & FR_LOGORBLOCK)
- printf(" or-block");
- if (fp->fr_loglevel != 0xffff) {
- printf(" level ");
- if (fp->fr_loglevel & LOG_FACMASK) {
- s = fac_toname(fp->fr_loglevel);
- if (s == NULL)
- s = "!!!";
- } else
- s = "";
- u = pri_toname(fp->fr_loglevel);
- if (u == NULL)
- u = "!!!";
- if (*s)
- printf("%s.%s", s, u);
- else
- printf("%s", u);
- }
-}
OpenPOWER on IntegriCloud