PROG= ipf
MAN= ipf.1 ipf.4 ipf.5
SRCS= ipf.c parse.c opt.c
-CFLAGS+=-DIPL_NAME=\"/dev/ipl\"
+CFLAGS+=-DIPL_NAME=\"/dev/ipl\" -I${.CURDIR}/../../sys/netinet
.include <bsd.prog.mk>
.SH NAME
ipf - alters packet filtering lists for IP packet input and ouput
.SH SYNOPSIS
-ipf [-AEDIsnovdr] [-F <i|o|a>] -f <\fIfilename\fP>
-[ -f <\fIfilename\fP> [...]]
+ipf [-AEDIsnovdr] [-l <block|pass|nomatch>] [-F <i|o|a>]
+-f <\fIfilename\fP> [ -f <\fIfilename\fP> [...]]
.SH DESCRIPTION
.PP
\fBipf\fP opens the filenames listed (treating "-" as stdin) and parses the
lists.
.IP -I
set the list to make changes to the inactive list.
+.IP -l
+Use of the \fB-l\fP flag toggles default logging of packets. Valid
+arguments to this option are \fBpass\fP, \fBblock\fP and \fBnomatch\fP.
+When an option is set, any packet which exits filtering and matches the
+set category is logged. This is most useful for causing all packets
+which don't match any of the loaded rules to be logged.
.IP -n
This flag (no-change) prevents \fBipf\fP from actually making any ioctl
calls or doing anything which would alter the currently running kernel.
be affected inside the kernel.
.SH BUGS
.PP
-If you find any, please send email to me at darrenr@arbld.unimelb.edu.au
+If you find any, please send email to me at darrenr@cyber.com.au
[ proto ] [ ip ] .
insert = "@" decnumber
-action = block | "pass" | log .
+action = block | "pass" | log | "count" .
in-out = "in" | "out" .
options = [ log ] [ "quick" ] [ "on" interface-name] .
tos = "tos" decnumber | "tos" hexnumber .
ttl = "ttl" decnumber .
proto = "proto" protocol .
-ip = srcdst [ flags ] [ with withopt ] [ icmp ] .
+ip = srcdst [ flags ] [ with withopt ] [ icmp ] [ keep ] .
-block = "block" [ "return-icmp" ] [ "return-rst" ].
-log = "log" [ "body" ] .
+block = "block" [ "return-icmp" [ return-code ] | "return-rst" ].
+log = "log" [ "body" ] [ "first" ] .
protocol = "tcp/udp" | "udp" | "tcp" | "icmp" | decnumber .
srcdst = "all" | fromto .
fromto = "from" object "to" object .
flags = "flags" flag { flag } [ "/" flag { flag } ] .
with = "with" | "and" .
icmp = "icmp-type" icmp-type .
+return-code = "(" icmp-code ")" .
+keep = "keep" "state" | "keep" "frags" .
nummask = host-name [ "/" decnumber ] .
host-name = ipaddr | hostname | "any" .
icmp-type = "unreach" | "echo" | "echorep" | "squench" | "redir" |
"timex" | "paramprob" | "timest" | "timestrep" | "inforeq" |
"inforep" | "maskreq" | "maskrep" | decnumber .
+icmp-code = decumber | "net-unr" | "host-unr" | "proto-unr" | "port-unr" |
+ "needfrag" | "srcfail" | "net-unk" | "host-unk" | "isolate" |
+ "net-prohib" | "host-prohib" | "net-tos" | "host-tos" .
hexnumber = "0" "x" hexstring .
hexstring = hexdigit [ hexstring ] .
# with BOTH SYN and ACK set, but WILL match "SFP".
.fi
.PP
-The last parameter set for the filter rule is the optional \fBicmp-type\fP.
+The next parameter set for the filter rule is the optional \fBicmp-type\fP.
It is only effective when used with \fB"proto icmp"\fP and must NOT be used
in conjuction with \fBflags\fP. There are a number of types which can be
refered to by an abbreviation recognised by this language or the numbers
with which they are associated can be used.
+.PP
+The last parameter which can be set for a filter rule is whether on not to
+record state information for that packet, and what sort to keep. Either
+information relating to the packet's `flow' or if fragment details can be
+kept, allowing packets which match these to flow straight through, rather
+than going through the access control list.
.SH FILES
/etc/services
/etc/hosts
#include <netinet/in_systm.h>
#include <net/if.h>
#include <netinet/ip.h>
-#include <netinet/ip_fil.h>
+#include "ip_fil.h"
#include <netdb.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include "ipf.h"
#ifndef lint
-static char sccsid[] = "@(#)ipf.c 1.18 11/11/95 (C) 1993-1995 Darren Reed";
+static char sccsid[] = "@(#)ipf.c 1.21 1/14/96 (C) 1993-1995 Darren Reed";
#endif
+#if SOLARIS
+void frsync();
+#endif
+void zerostats();
+
extern char *optarg;
int opts = 0;
case 'v' :
opts |= OPT_VERBOSE;
break;
-#if defined(sun) && (defined(__SVR4) || defined(__svr4__))
+#if SOLARIS
case 'y' :
frsync();
break;
if (!strcmp(file, "-"))
fp = stdin;
- else if (!(fp = fopen(file, "r")))
- return;
+ else if (!(fp = fopen(file, "r"))) {
+ perror("fopen");
+ exit(1);;
+ }
while (fgets(line, sizeof(line)-1, fp)) {
/*
if (opts & OPT_VERBOSE)
printf("set log flag: pass\n");
}
+ if (index(opt, 'm') && (*opt == 'n' || *opt == 'N')) {
+ flag |= FF_LOGNOMATCH;
+ if (opts & OPT_VERBOSE)
+ printf("set log flag: nomatch\n");
+ }
if (index(opt, 'b') || index(opt, 'd')) {
flag |= FF_LOGBLOCK;
if (opts & OPT_VERBOSE)
if (!arg || !*arg)
return;
- if (*arg == 'i' || *arg == 'I')
+ if (strchr(arg, 'i') || strchr(arg, 'I'))
fl = FR_INQUE;
- else if (*arg == 'o' || *arg == 'O')
+ if (strchr(arg, 'o') || strchr(arg, 'O'))
fl = FR_OUTQUE;
- else if (*arg == 'a' || *arg == 'A')
+ if (strchr(arg, 'a') || strchr(arg, 'A'))
fl = FR_OUTQUE|FR_INQUE;
fl |= (opts & FR_INACTIVE);
rem = fl;
#if defined(sun) && (defined(__SVR4) || defined(__svr4__))
-frsync()
+void frsync()
{
if (ioctl(fd, SIOCFRSYN, 0) == -1)
perror("SIOCFRSYN");
#endif
-zerostats()
+void zerostats()
{
struct friostat fio;
/*
- * (C)opyright 1993,1994,1995 by Darren Reed.
+ * (C)opyright 1993-1996 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*
- * @(#)ipf.h 1.7 10/15/95
+ * @(#)ipf.h 1.9 1/7/96
*/
-#define OPT_INQUE FR_INQUE /* 0x0001 */
-#define OPT_REMOVE 0x0002
+#define OPT_REMOVE 0x0001
+#define OPT_DEBUG 0x0002
#define OPT_OUTQUE FR_OUTQUE /* 0x0004 */
-#define OPT_DEBUG 0x0008
-#define OPT_SHOWLIST 0x0010
-#define OPT_VERBOSE 0x0020
-#define OPT_LOG FR_LOG /* 0x0040 */
+#define OPT_INQUE FR_INQUE /* 0x0008 */
+#define OPT_LOG FR_LOG /* 0x0010 */
+#define OPT_SHOWLIST 0x0020
+#define OPT_VERBOSE 0x0040
#define OPT_DONOTHING 0x0080
-#define OPT_INACTIVE FR_INACTIVE /* 0x0800 */
-#define OPT_HITS 0x10000
-#define OPT_BRIEF 0x20000
+#define OPT_HITS 0x100
+#define OPT_BRIEF 0x200
+#define OPT_ACCNT FR_ACCOUNT /* 0x0800 */
+#define OPT_FRSTATES FR_KEEPFRAG /* 0x1000 */
+#define OPT_IPSTATES FR_KEEPSTATE /* 0x2000 */
+#define OPT_INACTIVE FR_INACTIVE /* 0x4000 */
extern struct frentry *parse();
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <net/if.h>
-#include <netinet/ip_fil.h>
+#include "ip_fil.h"
#include "ipf.h"
#ifndef lint
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <net/if.h>
-#include <netinet/ip_fil.h>
+#include "ip_fil.h"
#include <netdb.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <ctype.h>
#ifndef lint
-static char sccsid[] ="@(#)parse.c 1.25 11/11/95 (C) 1993 Darren Reed";
+static char sccsid[] ="@(#)parse.c 1.33 1/14/96 (C) 1993 Darren Reed";
#endif
extern struct ipopt_names ionames[], secclass[];
extern int opts;
+extern int gethostname();
u_long hostnum(), optname();
u_short portnum();
u_char tcp_flags();
struct frentry *parse();
void binprint(), printfr();
-int addicmp(), extras(), hostmask(), ports();
+int addicmp(), extras(), hostmask(), ports(), icmpcode(), addkeep();
char *proto = NULL;
char flagset[] = "FSRPAU";
u_char flags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH, TH_ACK, TH_URG };
+static char thishost[64];
+
+
+void initparse()
+{
+ gethostname(thishost, sizeof(thishost));
+ thishost[sizeof(thishost) - 1] = '\0';
+}
+
+
/* parse()
*
* parse a line read from the input filter rule file
* does it start with one of the two possible first words ?
*/
if (strcasecmp("block",*cpp) && strcasecmp("pass",*cpp) &&
- strcasecmp("log",*cpp)) {
+ strcasecmp("log",*cpp) && strcasecmp("count",*cpp)) {
(void)fprintf(stderr, "unknown keyword (%s)\n", *cpp);
return NULL;
}
if (!strncasecmp(*(cpp+1), "return-icmp", 11)) {
fil.fr_flags |= FR_RETICMP;
cpp++;
+ if (*(*cpp + 11) == '(') {
+ fil.fr_icode = icmpcode(*cpp + 12);
+ if (fil.fr_icode == -1) {
+ fprintf(stderr,
+ "uncrecognised icmp code %s\n",
+ *cpp + 12);
+ return NULL;
+ }
+ }
} else if (!strncasecmp(*(cpp+1), "return-rst", 10)) {
fil.fr_flags |= FR_RETRST;
cpp++;
}
- } else if (**cpp == 'p')
+ } else if (**cpp == 'c')
+ fil.fr_flags = FR_ACCOUNT;
+ else if (**cpp == 'p')
fil.fr_flags = FR_PASS;
else if (**cpp == 'l') {
fil.fr_flags = FR_LOG;
fil.fr_flags |= FR_LOGBODY;
cpp++;
}
+ if (!strcasecmp(*(cpp+1), "first")) {
+ fil.fr_flags |= FR_LOGFIRST;
+ cpp++;
+ }
}
cpp++;
else if (!strcasecmp("out", *cpp))
fil.fr_flags |= FR_OUTQUE;
else {
- (void)fprintf(stderr, "missing 'in'/'out' keyword (%s)\n",
- *cpp);
+ (void)fprintf(stderr,
+ "missing 'in'/'out' keyword (%s)\n", *cpp);
return NULL;
}
-
if (!*++cpp)
return NULL;
+
if (!strcasecmp("log", *cpp)) {
cpp++;
if (fil.fr_flags & FR_PASS)
fil.fr_flags |= FR_LOGBODY;
cpp++;
}
+ if (!strcasecmp(*cpp, "first")) {
+ fil.fr_flags |= FR_LOGFIRST;
+ cpp++;
+ }
}
if (!strcasecmp("quick", *cpp)) {
fil.fr_icmpm = htons(fil.fr_icmpm);
}
+ /*
+ * Keep something...
+ */
+ if (*cpp && !strcasecmp(*cpp, "keep"))
+ if (addkeep(&cpp, &fil))
+ return NULL;
+
/*
* leftovers...yuck
*/
u_char *cp;
{
char *s;
- int bits = -1;
+ int bits = -1, resolved;
/*
* is it possibly hostname/num ?
}
*msk = htonl(*msk);
}
- *sa = hostnum(**seg) & *msk;
+ *sa = hostnum(**seg, &resolved) & *msk;
+ if (resolved == -1)
+ return -1;
(*seg)++;
return ports(seg, pp, cp, tp);
}
* look for extra segments if "mask" found in right spot
*/
if (*(*seg+1) && *(*seg+2) && !strcasecmp(*(*seg+1), "mask")) {
- *sa = hostnum(**seg);
+ *sa = hostnum(**seg, &resolved);
+ if (resolved == -1)
+ return -1;
(*seg)++;
(*seg)++;
- *msk = inet_addr(**seg);
+ if (index(**seg, '.'))
+ *msk = inet_addr(**seg);
+ else
+ *msk = (u_long)strtol(**seg, NULL, 0);
(*seg)++;
*sa &= *msk;
return ports(seg, pp, cp, tp);
}
if (**seg) {
- *sa = hostnum(**seg);
+ *sa = hostnum(**seg, &resolved);
+ if (resolved == -1)
+ return -1;
(*seg)++;
*msk = (*sa ? inet_addr("255.255.255.255") : 0L);
*sa &= *msk;
* returns an ip address as a long var as a result of either a DNS lookup or
* straight inet_addr() call
*/
-u_long hostnum(host)
+u_long hostnum(host, resolved)
char *host;
+int *resolved;
{
struct hostent *hp;
struct netent *np;
+ *resolved = 0;
if (!strcasecmp("any",host))
return 0L;
if (isdigit(*host))
return inet_addr(host);
+ if (!strcasecmp("<thishost>", host))
+ host = thishost;
if (!(hp = gethostbyname(host))) {
- if (!(np = getnetbyname(host)))
+ if (!(np = getnetbyname(host))) {
+ *resolved = -1;
+ fprintf(stderr, "can't resolve hostname: %s\n", host);
return 0;
+ }
return np->n_net;
}
return *(u_long *)hp->h_addr;
struct servent *sp, *sp2;
u_short p1 = 0;
- if (isdigit(*name) || !proto)
+ if (isdigit(*name))
return htons((u_short)atoi(name));
+ if (!proto)
+ proto = "tcp/udp";
if (strcasecmp(proto, "tcp/udp")) {
sp = getservbyname(name, proto);
if (sp)
}
+#define MAX_ICMPCODE 12
+
+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", NULL };
+/*
+ * Return the number for the associated ICMP unreachable code.
+ */
+int icmpcode(str)
+char *str;
+{
+ char *s;
+ int i, len;
+
+ if (!(s = strrchr(str, ')')))
+ return -1;
+ *s = '\0';
+ if (isdigit(*str))
+ return atoi(str);
+ 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)
+char ***cp;
+struct frentry *fp;
+{
+ if (fp->fr_proto != IPPROTO_TCP && fp->fr_proto != IPPROTO_UDP &&
+ fp->fr_proto != IPPROTO_ICMP) {
+ (void)fprintf(stderr, "Can only use keep with UDP/ICMP/TCP\n");
+ return -1;
+ }
+
+ (*cp)++;
+ if (**cp && strcasecmp(**cp, "state") && strcasecmp(**cp, "frags")) {
+ (void)fprintf(stderr, "Unrecognised state keyword \"%s\"\n",
+ **cp);
+ return -1;
+ }
+
+ if (***cp == 's')
+ fp->fr_flags |= FR_KEEPSTATE;
+ else if (***cp == 'f')
+ fp->fr_flags |= FR_KEEPFRAG;
+ (*cp)++;
+ return 0;
+}
+
+
/*
* count consecutive 1's in bit mask. If the mask generated by counting
* consecutive 1's is different to that passed, return -1, else return #
(void)printf("log");
if (fp->fr_flags & FR_LOGBODY)
(void)printf(" body");
+ if (fp->fr_flags & FR_LOGFIRST)
+ (void)printf(" first");
} else if (fp->fr_flags & FR_BLOCK) {
(void)printf("block");
- if (fp->fr_flags & FR_RETICMP)
+ if (fp->fr_flags & FR_RETICMP) {
(void)printf(" return-icmp");
+ if (fp->fr_icode)
+ if (fp->fr_icode <= MAX_ICMPCODE)
+ printf("(%s)",icmpcodes[fp->fr_icode]);
+ else
+ printf("(%d)", fp->fr_icode);
+ }
if (fp->fr_flags & FR_RETRST)
(void)printf(" return-rst");
- }
+ } else if (fp->fr_flags & FR_ACCOUNT)
+ (void)printf("count");
if (fp->fr_flags & FR_OUTQUE)
(void)printf(" out ");
else
(void)printf(" in ");
- if (fp->fr_flags & (FR_LOGB|FR_LOGP)) {
+ if (((fp->fr_flags & FR_LOGB) == FR_LOGB) ||
+ ((fp->fr_flags & FR_LOGP) == FR_LOGP)) {
(void)printf("log ");
if (fp->fr_flags & FR_LOGBODY)
- (void)printf(" body");
+ (void)printf("body ");
+ if (fp->fr_flags & FR_LOGFIRST)
+ (void)printf("first ");
}
if (fp->fr_flags & FR_QUICK)
(void)printf("quick ");
(void)putchar(*s);
}
}
+ if (fp->fr_flags & (FR_KEEPFRAG|FR_KEEPSTATE))
+ printf(" keep %s ",
+ (fp->fr_flags & FR_KEEPFRAG) ? "frags" : "state");
(void)putchar('\n');
}
MAN= ipfstat.8
SRCS= fils.c parse.c opt.c kmem.c
.PATH: ${.CURDIR}/../../sbin/ipf
-CFLAGS+=-DIPL_NAME=\"/dev/ipl\" -I${.CURDIR}/../../sbin/ipf
+CFLAGS+=-DIPL_NAME=\"/dev/ipl\" -I${.CURDIR}/../../sbin/ipf -I${.CURDIR}/../../sys/netinet
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*/
+
#include <stdio.h>
#include <string.h>
#if !defined(__SVR4) && !defined(__svr4__)
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <net/if.h>
-#include <netinet/ip_fil.h>
+#include "ip_fil.h"
+#include "ip_frag.h"
+#include "ip_state.h"
#include <netdb.h>
#include <arpa/nameser.h>
#include <resolv.h>
#endif
#ifndef lint
-static char sccsid[] = "@(#)fils.c 1.15 11/11/95 (C) 1993 Darren Reed";
+static char sccsid[] = "@(#)fils.c 1.18 1/12/96 (C) 1993 Darren Reed";
#endif
#ifdef _PATH_UNIX
#define VMUNIX _PATH_UNIX
#endif
extern char *optarg;
-#define F_ST 0
-#define F_IN 1
-#define F_OUT 2
-#define F_FL 3
+
+#define PRINTF (void)printf
+#define FPRINTF (void)fprintf
+#define F_IN 0
+#define F_OUT 1
+#define F_AC 2
+static char *filters[4] = { "ipfilter(in)", "ipfilter(out)",
+ "ipacct(in)", "ipacct(out)" };
int opts = 0;
-static void showstats();
-static void showlist();
+static void showstats(), showfrstates();
+static void showlist(), showipstates();
int main(argc,argv)
int argc;
char *argv[];
{
- struct friostat fio;
+ friostat_t fio;
+ ips_stat_t ipsst;
+ ipfrstat_t ifrst;
char c, *name = NULL, *device = IPL_NAME;
int fd;
(void)setuid(getuid());
(void)setgid(getgid());
- while ((c = getopt(argc, argv, "hIiovd:")) != -1)
+ while ((c = getopt(argc, argv, "afhIiosvd:")) != -1)
{
switch (c)
{
+ case 'a' :
+ opts |= OPT_ACCNT|OPT_SHOWLIST;
+ break;
case 'd' :
device = optarg;
break;
+ case 'f' :
+ opts |= OPT_FRSTATES;
+ break;
case 'h' :
opts |= OPT_HITS;
break;
case 'o' :
opts |= OPT_OUTQUE|OPT_SHOWLIST;
break;
+ case 's' :
+ opts |= OPT_IPSTATES;
+ break;
case 'v' :
opts |= OPT_VERBOSE;
break;
perror("open");
exit(-1);
}
+
bzero((char *)&fio, sizeof(fio));
+ bzero((char *)&ipsst, sizeof(ipsst));
+ bzero((char *)&ifrst, sizeof(ifrst));
+
if (ioctl(fd, SIOCGETFS, &fio) == -1) {
perror("ioctl(SIOCGETFS)");
exit(-1);
}
+ if ((opts & OPT_IPSTATES) && (ioctl(fd, SIOCGIPST, &ipsst) == -1)) {
+ perror("ioctl(SIOCGIPST)");
+ exit(-1);
+ }
+ if ((opts & OPT_FRSTATES) && (ioctl(fd, SIOCGFRST, &ifrst) == -1)) {
+ perror("ioctl(SIOCGFRST)");
+ exit(-1);
+ }
if (opts & OPT_VERBOSE)
- printf("opts %#x name %s\n", opts, name ? name : "<>");
- if (opts & OPT_SHOWLIST){
+ PRINTF("opts %#x name %s\n", opts, name ? name : "<>");
+ if (opts & OPT_SHOWLIST) {
showlist(&fio);
if((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){
opts &= ~OPT_OUTQUE;
showlist(&fio);
}
+ } else {
+ if (opts & OPT_IPSTATES)
+ showipstates(fd, &ipsst);
+ else if (opts & OPT_FRSTATES)
+ showfrstates(fd, &ifrst);
+ else
+ showstats(fd, &fio);
}
- else
- showstats(fd, &fio);
return 0;
}
perror("ioctl(SIOCGETFF)");
#if SOLARIS
- (void)printf("dropped packets:\tin %ld\tout %ld\n",
+ PRINTF("dropped packets:\tin %lu\tout %lu\n",
fp->f_st[0].fr_drop, fp->f_st[1].fr_drop);
- (void)printf("non-ip packets:\t\tin %ld\tout %ld\n",
+ PRINTF("non-ip packets:\t\tin %lu\tout %lu\n",
fp->f_st[0].fr_notip, fp->f_st[1].fr_notip);
- (void)printf(" bad packets:\t\tin %ld\tout %ld\n",
+ PRINTF(" bad packets:\t\tin %lu\tout %lu\n",
fp->f_st[0].fr_bad, fp->f_st[1].fr_bad);
#endif
- (void)printf(" input packets:\t\tblocked %ld passed %ld nomatch %ld\n",
+ PRINTF(" input packets:\t\tblocked %lu passed %lu nomatch %lu",
fp->f_st[0].fr_block, fp->f_st[0].fr_pass,
fp->f_st[0].fr_nom);
- (void)printf("output packets:\t\tblocked %ld passed %ld nomatch %ld\n",
+ PRINTF(" counted %lu\n", fp->f_st[0].fr_acct);
+ PRINTF("output packets:\t\tblocked %lu passed %lu nomatch %lu",
fp->f_st[1].fr_block, fp->f_st[1].fr_pass,
fp->f_st[1].fr_nom);
- (void)printf(" input packets logged:\tblocked %ld passed %ld\n",
+ PRINTF(" counted %lu\n", fp->f_st[0].fr_acct);
+ PRINTF(" input packets logged:\tblocked %lu passed %lu\n",
fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl);
- (void)printf("output packets logged:\tblocked %ld passed %ld\n",
+ PRINTF("output packets logged:\tblocked %lu passed %lu\n",
fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl);
- (void)printf(" packets logged:\tinput %ld-%ld output %ld-%ld\n",
+ PRINTF(" packets logged:\tinput %lu-%lu output %lu-%lu\n",
fp->f_st[0].fr_pkl, fp->f_st[0].fr_skip,
fp->f_st[1].fr_pkl, fp->f_st[1].fr_skip);
- (void)printf("ICMP replies:\t%ld\tTCP RSTs sent:\t%ld\n",
+ PRINTF("fragment state(in):\tkept %lu\tlost %lu\n",
+ fp->f_st[0].fr_nfr, fp->f_st[0].fr_bnfr);
+ PRINTF("fragment state(out):\tkept %lu\tlost %lu\n",
+ fp->f_st[1].fr_nfr, fp->f_st[1].fr_bnfr);
+ PRINTF("packet state(in):\tkept %lu\tlost %lu\n",
+ fp->f_st[0].fr_ads, fp->f_st[0].fr_bads);
+ PRINTF("packet state(out):\tkept %lu\tlost %lu\n",
+ fp->f_st[1].fr_ads, fp->f_st[1].fr_bads);
+ PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n",
fp->f_st[0].fr_ret, fp->f_st[1].fr_ret);
- (void)printf("Packet log flags set: (%#x)\n", frf);
+ PRINTF("Packet log flags set: (%#x)\n", frf);
if (frf & FF_LOGPASS)
- printf("\tpackets passed through filter\n");
+ PRINTF("\tpackets passed through filter\n");
if (frf & FF_LOGBLOCK)
- printf("\tpackets blocked by filter\n");
+ PRINTF("\tpackets blocked by filter\n");
if (!frf)
- printf("\tnone\n");
+ PRINTF("\tnone\n");
}
/*
struct frentry *fp = NULL;
int i, set;
- if (opts & OPT_OUTQUE)
- i = F_OUT;
- else if (opts & OPT_INQUE)
- i = F_IN;
- else
- return;
set = fiop->f_active;
if (opts & OPT_INACTIVE)
set = 1 - set;
- fp = (i == F_IN) ? (struct frentry *)fiop->f_fin[set] :
- (struct frentry *)fiop->f_fout[set];
+ if (opts & OPT_ACCNT) {
+ i = F_AC;
+ if (opts & OPT_INQUE)
+ fp = (struct frentry *)fiop->f_acctin[set];
+ else {
+ fp = (struct frentry *)fiop->f_acctout[set];
+ i++;
+ }
+ } else if (opts & OPT_OUTQUE) {
+ i = F_OUT;
+ fp = (struct frentry *)fiop->f_fout[set];
+ } else if (opts & OPT_INQUE) {
+ i = F_IN;
+ fp = (struct frentry *)fiop->f_fin[set];
+ } else
+ return;
if (opts & OPT_VERBOSE)
- (void)fprintf(stderr, "showlist:opts %#x i %d\n", opts, i);
+ FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i);
if (opts & OPT_VERBOSE)
- printf("fp %#x set %d\n", (u_int)fp, set);
+ PRINTF("fp %#x set %d\n", (u_int)fp, set);
if (!fp) {
- (void)fprintf(stderr, "empty list for filter%s\n",
- (i == F_IN) ? "in" : "out");
+ FPRINTF(stderr, "empty list for %s%s\n",
+ (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]);
return;
}
while (fp) {
if (opts & OPT_OUTQUE)
fp->fr_flags |= FR_OUTQUE;
if (opts & (OPT_HITS|OPT_VERBOSE))
- printf("%d ", fp->fr_hits);
+ PRINTF("%ld ", fp->fr_hits);
+ if (opts & (OPT_ACCNT|OPT_VERBOSE))
+ PRINTF("%ld ", fp->fr_bytes);
printfr(fp);
if (opts & OPT_VERBOSE)
binprint(fp);
fp = fp->fr_next;
}
}
+
+
+static void showipstates(fd, ipsp)
+int fd;
+ips_stat_t *ipsp;
+{
+ ipstate_t *istab[IPSTATE_SIZE], ips;
+ int i;
+
+ PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n",
+ ipsp->iss_tcp, ipsp->iss_udp, ipsp->iss_icmp);
+ PRINTF("\t%lu hits\n\t%lu misses\n", ipsp->iss_hits, ipsp->iss_miss);
+ PRINTF("\t%lu maximum\n\t%lu no memory\n",
+ ipsp->iss_max, ipsp->iss_nomem);
+ PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n",
+ ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin);
+ if (kmemcpy((char *)istab, (u_long)ipsp->iss_table, sizeof(istab)))
+ return;
+ for (i = 0; i < IPSTATE_SIZE; i++)
+ while (istab[i]) {
+ if (kmemcpy(&ips, istab[i], sizeof(ips)) == -1)
+ break;
+ PRINTF("%s -> ", inet_ntoa(ips.is_src));
+ PRINTF("%s age %d pass %d pr %d\n",
+ inet_ntoa(ips.is_dst), ips.is_age,
+ ips.is_pass, ips.is_p);
+ if (ips.is_p == IPPROTO_TCP)
+ PRINTF("\t%hu -> %hu %lu:%lu %hu\n",
+ ntohs(ips.is_sport),
+ ntohs(ips.is_dport),
+ ips.is_seq, ips.is_ack, ips.is_win);
+ else if (ips.is_p == IPPROTO_UDP)
+ PRINTF("\t%hu -> %hu\n", ntohs(ips.is_sport),
+ ntohs(ips.is_dport));
+ else if (ips.is_p == IPPROTO_ICMP)
+ PRINTF("\t%hu %hu %d\n", ips.is_icmp.ics_id,
+ ips.is_icmp.ics_seq,
+ ips.is_icmp.ics_type);
+ istab[i] = ips.is_next;
+ }
+}
+
+
+static void showfrstates(fd, ifsp)
+int fd;
+ipfrstat_t *ifsp;
+{
+ struct ipfr *ipfrtab[IPFT_SIZE], ifr;
+ int i;
+
+ PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n",
+ ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits);
+ PRINTF("\t%lu no memory\n\t%lu already exist\n",
+ ifsp->ifs_nomem, ifsp->ifs_exists);
+ PRINTF("\t%lu inuse\n", ifsp->ifs_inuse);
+ if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_table, sizeof(ipfrtab)))
+ return;
+ for (i = 0; i < IPFT_SIZE; i++)
+ while (ipfrtab[i]) {
+ if (kmemcpy(&ifr, (u_long)ipfrtab[i],
+ sizeof(ifr)) == -1)
+ break;
+ PRINTF("%s -> ", inet_ntoa(ifr.ipfr_src));
+ PRINTF("%s %d %d %d %#02x = %#x\n",
+ inet_ntoa(ifr.ipfr_dst), ifr.ipfr_id,
+ ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_tos,
+ ifr.ipfr_pass);
+ ipfrtab[i] = ifr.ipfr_next;
+ }
+}
is to retrieve and display the accumulated statistics which have been
accumulated over time as the kernel has put packets through the filter.
.SH OPTIONS
-.IP -o
-display the filter list used for the output side of the kernel IP processing.
-.IP -i
-display the filter list used for the input side of the kernel IP processing.
-.IP -v
-turn verbose mode on. Displays more debugging information.
+.IP -a
+display the accounting filter list and show bytes counted against each rule.
.IP -d <device>
use a device other than \fB/dev/ipl\fP for interfacing with the kernel.
-.IP -I
-swap between retrieving "inactive"/"active" filter list details. For use
-in combination with \fB-i\fP.
+.IP -f
+show fragment state information (statistics) and held state information (in
+the kernel) if any is present.
.IP -h
show per-rule the number of times each one scores a "hit". For use in
combination with \fB-i\fP.
+.IP -i
+display the filter list used for the input side of the kernel IP processing.
+.IP -I
+swap between retrieving "inactive"/"active" filter list details. For use
+in combination with \fB-i\fP.
+.IP -o
+display the filter list used for the output side of the kernel IP processing.
+.IP -s
+show packet/flow state information (statistics) and held state information (in
+the kernel) if any is present.
+.IP -v
+turn verbose mode on. Displays more debugging information.
.SH SYNOPSIS
The role of \fBipfstat\fP is to display current kernel statistics gathered
as a result of applying the filters in place (if any) to packets going in and
* returns 0 on success, -1 on error.
*/
+#include <stdio.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#define KMEM "/dev/kmem"
#ifndef lint
-static char sccsid[] = "@(#)kmem.c 1.3 10/15/95 (C) 1992 Darren Reed";
+static char sccsid[] = "@(#)kmem.c 1.4 1/12/96 (C) 1992 Darren Reed";
#endif
static int kmemfd = -1;
file netinet/udp_usrreq.c inet
file netinet/ip_fil.c ipfilter
file netinet/fil.c ipfilter
+file netinet/ip_nat.c ipfilter
+file netinet/ip_frag.c ipfilter
+file netinet/ip_state.c ipfilter
file netiso/clnp_debug.c iso
file netiso/clnp_er.c iso
file netiso/clnp_frag.c iso
netinet/udp_usrreq.c optional inet
netinet/ip_fil.c optional ipfilter requires inet
netinet/fil.c optional ipfilter requires inet
+netinet/ip_nat.c optional ipfilter requires inet
+netinet/ip_frag.c optional ipfilter requires inet
+netinet/ip_state.c optional ipfilter requires inet
netiso/clnp_debug.c optional iso
netiso/clnp_er.c optional iso
netiso/clnp_frag.c optional iso
* to the original author and the contributors.
*/
#ifndef lint
-static char sccsid[] = "@(#)fil.c 1.18 10/24/95 (C) 1993-1995 Darren Reed";
+static char sccsid[] = "@(#)fil.c 1.26 1/14/96 (C) 1993-1996 Darren Reed";
#endif
#ifndef linux
# include <sys/ioctl.h>
# if defined(_KERNEL) || defined(KERNEL)
# include <sys/systm.h>
+# else
+# include <string.h>
# endif
# include <sys/uio.h>
# if !defined(__SVR4) && !defined(__svr4__)
# include <netinet/tcpip.h>
# include <netinet/ip_icmp.h>
#endif
-#include <netinet/ip_fil.h>
+#include "ip_fil.h"
+#include "ip_nat.h"
+#include "ip_frag.h"
+#include "ip_state.h"
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
#define FR_IFDEBUG(ex,second,verb_pr) if (ex) { debug verb_pr; second; }
#define FR_VERBOSE(verb_pr) verbose verb_pr
#define FR_DEBUG(verb_pr) debug verb_pr
+#define FR_SCANLIST(p, ip, if, fi, m) fr_scanlist(p, ip, ifp, fi)
#else
#define FR_IFVERBOSE(ex,second,verb_pr) ;
#define FR_IFDEBUG(ex,second,verb_pr) ;
#define FR_VERBOSE(verb_pr)
#define FR_DEBUG(verb_pr)
-
+extern int send_reset();
+# if SOLARIS
+extern int icmp_error();
+extern kmutex_t ipf_mutex;
+# define FR_SCANLIST(p, ip, if, fi, m) fr_scanlist(p, ip, ifp, fi)
+# else
+# define FR_SCANLIST(p, ip, if, fi, m) fr_scanlist(p, ip, ifp, fi, m)
+# endif
extern int ipl_unreach, ipllog();
#endif
+#if SOLARIS
+# define IPLLOG(fl, ip, if, fi, m) ipllog(fl, ip, if, fi)
+# define SEND_RESET(ip, if, q) send_reset(ip, qif, q)
+# define ICMP_ERROR(b, ip, t, c, if, src) \
+ icmp_error(b, ip, t, c, if, src)
+#else
+#ifdef _KERNEL
+# define IPLLOG(fl, ip, if, fi, m) ipllog(fl, ip, if, fi, m)
+#else
+# define IPLLOG(fl, ip, if, fi, m) ipllog()
+#endif
+# define SEND_RESET(ip, if, q) send_reset(ip)
+# if BSD < 199103
+# define ICMP_ERROR(b, ip, t, c, if, src) \
+ icmp_error(mtod(b, ip_t *), t, c, if, src)
+# else
+# define ICMP_ERROR(b, ip, t, c, if, src) \
+ icmp_error(b, t, c, (src).s_addr, if)
+# endif
+#endif
+
struct filterstats frstats[2] = {{0,0,0,0,0},{0,0,0,0,0}};
-struct frentry *filterin[2] = { NULL, NULL },
- *filterout[2] = { NULL, NULL };
+struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } },
+ *ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } };
int fr_flags = 0, fr_active = 0;
-int fr_check();
/*
int i, mv, ol, off;
u_char *s, opt;
+#ifdef _KERNEL
+ fi.fi_icode = ipl_unreach;
+#endif
fi.fi_fl = 0;
fi.fi_v = ip->ip_v;
fi.fi_tos = ip->ip_tos;
+ fi.fi_hlen = hlen;
(*(((u_short *)&fi) + 1)) = (*(((u_short *)ip) + 4));
(*(((u_long *)&fi) + 1)) = (*(((u_long *)ip) + 3));
(*(((u_long *)&fi) + 2)) = (*(((u_long *)ip) + 4));
if (hlen > sizeof(struct ip))
fi.fi_fl |= FI_OPTIONS;
+#if SOLARIS
+ off = (ntohs(ip->ip_off) & 0x1fff) << 3;
+ if (ntohs(ip->ip_off) & 0x3fff)
+ fi.fi_fl |= FI_FRAG;
+#else
off = (ip->ip_off & 0x1fff) << 3;
if (ip->ip_off & 0x3fff)
fi.fi_fl |= FI_FRAG;
+#endif
switch (ip->ip_p)
{
case IPPROTO_ICMP :
* Could be per interface, but this gets real nasty when you don't have
* kernel sauce.
*/
-int fr_scanlist(pass, ip, hlen, ifp, out, rule)
+int fr_scanlist(pass, ip, ifp, fi, m)
int pass;
ip_t *ip;
-int hlen, out;
struct ifnet *ifp;
-u_short *rule;
+register struct fr_ip *fi;
+void *m;
{
register struct frentry *fr;
- register struct fr_ip *fi;
tcphdr_t *tcp;
int rulen;
- *rule = 1;
- tcp = (tcphdr_t *)((char *)ip + hlen);
- fr = (out) ? filterout[fr_active] : filterin[fr_active];
- fi = fr_makefrip(hlen, ip);
+ fi->fi_rule = 0;
+ tcp = (tcphdr_t *)((char *)ip + fi->fi_hlen);
+ pass |= (fi->fi_fl << 20);
- for (rulen = 0; fr; fr = fr->fr_next, rulen++) {
+ for (rulen = 0, fr = fi->fi_fr; fr; fr = fr->fr_next, rulen++) {
/*
* In all checks below, a null (zero) value in the
* filter struture is taken to mean a wildcard.
if (opts & (OPT_VERBOSE|OPT_DEBUG))
printf("\n");
FR_VERBOSE(("%c", (pass & FR_PASS) ? 'p' : 'b'));
- if (ifp && *fr->fr_ifname && strcasecmp(ifp->if_name,
+ if (ifp && *fr->fr_ifname && strcasecmp((char *)ifp,
fr->fr_ifname))
continue;
FR_VERBOSE((":i"));
* If a fragment, then only the first has what we're looking
* for here...
*/
- if (!(ip->ip_off & 0x1fff)) {
+ if (!(ntohs(ip->ip_off) & 0x1fff)) {
if ((fi->fi_fl & FI_TCPUDP) &&
!fr_tcpudpchk(ip, tcp, fr))
continue;
else if (ip->ip_p == IPPROTO_ICMP &&
- (*(u_short *)((char *)ip + hlen) &
+ (*(u_short *)((char *)ip + fi->fi_hlen) &
fr->fr_icmpm) != fr->fr_icmp) {
FR_DEBUG(("i. %#x & %#x != %#x\n",
- *(u_short *)((char *)ip + hlen),
+ *(u_short *)((char *)ip + fi->fi_hlen),
fr->fr_icmpm, fr->fr_icmp));
continue;
}
*/
if (fr->fr_flags & FR_LOG) {
#ifdef IPFILTER_LOG
- if (!ipllog(hlen, fr->fr_flags, ip, ifp, *rule))
- frstats[out].fr_skip++;
- frstats[out].fr_pkl++;
+ if (!IPLLOG(fr->fr_flags, ip, ifp, fi, m))
+ frstats[fi->fi_out].fr_skip++;
+ frstats[fi->fi_out].fr_pkl++;
#endif /* IPFILTER_LOG */
} else
pass = fr->fr_flags;
FR_DEBUG(("pass %#x\n", pass));
fr->fr_hits++;
- *rule = rulen;
+ fi->fi_rule = rulen;
+ fi->fi_icode = fr->fr_icode;
+ if (pass & FR_ACCOUNT)
+ fr->fr_bytes += ip->ip_len;
+ else {
+ fi->fi_rule = rulen;
+ fi->fi_icode = fr->fr_icode;
+ }
if (pass & FR_QUICK)
break;
}
* or not to pass it on or not.
*/
int fr_check(ip, hlen, ifp, out
-#if SOLARIS && defined(_KERNEL)
+#ifdef _KERNEL
+# if SOLARIS
, qif, q)
qif_t *qif;
queue_t *q;
+# else
+, mp)
+struct mbuf **mp;
+# endif
#else
)
#endif
struct ifnet *ifp;
int out;
{
- int pass = FR_NOMATCH;
- int sl;
- u_short rule;
+ /*
+ * The above really sucks, but short of writing a diff
+ */
+ register struct fr_ip *fi;
+ int pass;
+
+#if !defined(__SVR4) && !defined(__svr4__) && defined(_KERNEL)
+ register struct mbuf *m = *mp;
+
+ if (!out && (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ||
+ ip->ip_p == IPPROTO_ICMP)) {
+ register int up = MIN(hlen + 8, ip->ip_len);
+
+ if ((up > m->m_len)) {
+ if ((*mp = m_pullup(m, up)) == 0)
+ return -1;
+ else {
+ m = *mp;
+ ip = mtod(m, struct ip *);
+ }
+ }
+ }
+#endif
+ fi = fr_makefrip(hlen, ip);
+ fi->fi_out = out;
- SPLNET(sl);
+ MUTEX_ENTER(&ipf_mutex);
+ if (!out) {
+ ip_natin(ifp, ip, hlen);
+ if ((fi->fi_fr = ipacct[0][fr_active]) &&
+ (FR_SCANLIST(FR_NOMATCH, ip, ifp, fi, m) & FR_ACCOUNT))
+ frstats[0].fr_acct++;
+ }
- pass = fr_scanlist(pass, ip, hlen, ifp, out, &rule);
- if (pass == FR_NOMATCH) {
- frstats[out].fr_nom++;
+ if (!(pass = ipfr_knownfrag(ip)) &&
+ !(pass = fr_checkstate(ip, hlen))) {
+ pass = FR_NOMATCH;
+ if ((fi->fi_fr = ipfilter[out][fr_active]))
+ pass = FR_SCANLIST(FR_NOMATCH, ip, ifp, fi, m);
+ if (pass & FR_NOMATCH) {
+ frstats[out].fr_nom++;
#ifdef NOMATCH
- pass |= NOMATCH;
+ pass |= NOMATCH;
#endif
+ }
+ if (pass & FR_KEEPFRAG) {
+ if (ipfr_newfrag(ip, pass) == -1)
+ frstats[out].fr_bnfr++;
+ else
+ frstats[out].fr_nfr++;
+ }
+ if (pass & FR_KEEPSTATE) {
+ if (fr_addstate(ip, hlen, pass) == -1)
+ frstats[out].fr_bads++;
+ else
+ frstats[out].fr_ads++;
+ }
+ } else if (pass & FR_LOGFIRST)
+ pass &= ~(FR_LOGFIRST|FR_LOG);
+
+
+ if (out) {
+ if ((fi->fi_fr = ipacct[1][fr_active]) &&
+ (FR_SCANLIST(FR_NOMATCH, ip, ifp, fi, m) & FR_ACCOUNT))
+ frstats[1].fr_acct++;
+ ip_natout(ifp, ip, hlen);
}
+ MUTEX_EXIT(&ipf_mutex);
#ifdef IPFILTER_LOG
- if ((pass & FR_LOGP) ||
+ if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) {
+ pass |= FF_LOGNOMATCH;
+ if (!IPLLOG(pass, ip, ifp, fi, m))
+ frstats[out].fr_skip++;
+ frstats[out].fr_npkl++;
+ } else if (((pass & FR_LOGP) == FR_LOGP) ||
((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) {
- if (!(pass & FR_LOGP))
- pass |= FF_LOGPASS << 8;
- if (!ipllog(hlen, pass, ip, ifp, rule))
+ if ((pass & FR_LOGP) != FR_LOGP)
+ pass |= FF_LOGPASS;
+ if (!IPLLOG(pass, ip, ifp, fi, m))
frstats[out].fr_skip++;
frstats[out].fr_ppkl++;
- } else if ((pass & FR_LOGB) ||
+ } else if (((pass & FR_LOGB) == FR_LOGB) ||
((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) {
- if (!(pass & FR_LOGB))
- pass |= FF_LOGBLOCK << 8;
- if (!ipllog(hlen, pass, ip, ifp, rule))
+ if ((pass & FR_LOGB) != FR_LOGB)
+ pass |= FF_LOGBLOCK;
+ if (!IPLLOG(pass, ip, ifp, fi, m))
frstats[out].fr_skip++;
frstats[out].fr_bpkl++;
}
#endif /* IPFILTER_LOG */
- SPLX(sl);
+
if (pass & FR_PASS)
frstats[out].fr_pass++;
else if (pass & FR_BLOCK) {
/*
* Should we return an ICMP packet to indicate error
* status passing through the packet filter ?
- * XXX - copy mbuf as icmp_error() calls mfree() - fix this
- * later, but preserve backward compatibility for now.
*/
#ifdef _KERNEL
if (pass & FR_RETICMP) {
# if SOLARIS
- icmp_error(q, ip, ICMP_UNREACH, ipl_unreach, qif,
- ip->ip_src);
+ ICMP_ERROR(q, ip, ICMP_UNREACH, fi->fi_icode,
+ qif, ip->ip_src);
# else
- struct mbuf *copy;
-
- copy = m_copy(dtom(ip), 0, imin((int)ip->ip_len, 64));
-# if BSD < 199103
- icmp_error(mtod(copy, struct ip *),
- ICMP_UNREACH, ipl_unreach, ifp, ip->ip_src);
-# else
- icmp_error(copy, ICMP_UNREACH, ipl_unreach,
- ip->ip_src.s_addr, ifp);
-# endif
+ ICMP_ERROR(m, ip, ICMP_UNREACH, fi->fi_icode,
+ ifp, ip->ip_src);
+ m = NULL; /* freed by icmp_error() */
# endif
+
frstats[0].fr_ret++;
} else if (pass & FR_RETRST && IPMINLEN(ip, tcphdr)) {
-# if SOLARIS
- if (send_reset(ip, qif, q) == 0)
-# else
- if (send_reset(ip) == 0)
-# endif
+ if (SEND_RESET(ip, qif, q) == 0)
frstats[1].fr_ret++;
}
#else
#endif
}
#ifdef _KERNEL
+# if !SOLARIS
+ if (!(pass & FR_PASS) && m)
+ m_freem(m);
+# endif
return (pass & FR_PASS) ? 0 : -1;
#else
if (pass & FR_NOMATCH)
int ipllog()
{
verbose("l");
- return 1;
}
#endif
* to the original author and the contributors.
*/
#ifndef lint
-static char sccsid[] = "@(#)ip_fil.c 2.26 11/8/95 (C) 1993-1995 Darren Reed";
+static char sccsid[] = "@(#)ip_fil.c 2.31 1/14/96 (C) 1993-1995 Darren Reed";
#endif
#ifndef linux
#include <syslog.h>
#endif
#include "ip_fil.h"
+#include "ip_frag.h"
+#include "ip_nat.h"
+#include "ip_state.h"
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
extern fr_flags, fr_active;
-extern int fr_check(), (*fr_checkp)();
+extern struct protosw inetsw[];
+extern int (*fr_checkp)();
#if BSD < 199306
+extern int ipfr_slowtimer();
+static int (*fr_saveslowtimo)();
extern int tcp_ttl;
#else
-extern int ip_defttl;
+extern void ipfr_slowtimer();
+static void (*fr_saveslowtimo)();
#endif
int ipl_inited = 0;
return 1;
return 0;
}
+#endif /* IPFILTER_LKM */
int iplattach()
ipl_inited = 1;
fr_savep = fr_checkp;
fr_checkp = fr_check;
-
+#if BSD >= 199306
+ fr_saveslowtimo = inetsw[0].pr_slowtimo;
+ inetsw[0].pr_slowtimo = ipfr_slowtimer;
+#else
+ fr_saveslowtimo = inetsw[0].pr_slowtimo;
+ inetsw[0].pr_slowtimo = ipfr_slowtimer;
+#endif
SPLX(s);
return 0;
}
}
fr_checkp = fr_savep;
+ inetsw[0].pr_slowtimo = fr_saveslowtimo;
frflush((caddr_t)&i);
ipl_inited = 0;
+ ipfr_unload();
+ ip_natunload();
+ fr_stateunload();
+
SPLX(s);
return 0;
}
-#endif /* IPFILTER_LKM */
static void frzerostats(data)
bcopy((char *)frstats, (char *)fio.f_st,
sizeof(struct filterstats) * 2);
- fio.f_fin[0] = filterin[0];
- fio.f_fin[1] = filterin[1];
- fio.f_fout[0] = filterout[0];
- fio.f_fout[1] = filterout[1];
+ fio.f_fin[0] = ipfilter[0][0];
+ fio.f_fin[1] = ipfilter[0][1];
+ fio.f_fout[0] = ipfilter[1][0];
+ fio.f_fout[1] = ipfilter[1][1];
+ fio.f_acctin[0] = ipacct[0][0];
+ fio.f_acctin[1] = ipacct[0][1];
+ fio.f_acctout[0] = ipacct[1][0];
+ fio.f_acctout[1] = ipacct[1][1];
fio.f_active = fr_active;
IWCOPY((caddr_t)&fio, data, sizeof(fio));
bzero((char *)frstats, sizeof(*frstats));
caddr_t data;
{
struct frentry *f, **fp;
- int flags = *(int *)data, flushed = 0, set = fr_active;
+ int flags = *(int *)data, flushed = 0, set = fr_active, in;
if (flags & FR_INACTIVE)
set = 1 - set;
- if (flags & FR_OUTQUE)
- for (fp = &filterout[set]; (f = *fp); ) {
+ if (flags & FR_OUTQUE) {
+ for (fp = &ipfilter[1][set]; (f = *fp); ) {
*fp = f->fr_next;
KFREE(f);
flushed++;
}
- if (flags & FR_INQUE)
- for (fp = &filterin[set]; (f = *fp); ) {
+ for (fp = &ipacct[1][set]; (f = *fp); ) {
+ *fp = f->fr_next;
+ KFREE(f);
+ flushed++;
+ }
+ }
+ if (flags & FR_INQUE) {
+ for (fp = &ipfilter[0][set]; (f = *fp); ) {
*fp = f->fr_next;
KFREE(f);
flushed++;
}
+ for (fp = &ipacct[0][set]; (f = *fp); ) {
+ *fp = f->fr_next;
+ KFREE(f);
+ flushed++;
+ }
+ }
*(int *)data = flushed;
}
u_int enable;
IRCOPY(data, (caddr_t)&enable, sizeof(enable));
- if (enable) {
- if (fr_checkp != fr_check) {
- fr_savep = fr_checkp;
- fr_checkp = fr_check;
- }
- } else
- fr_checkp = fr_savep;
+ if (enable)
+ error = iplattach();
+ else
+ error = ipldetach();
break;
}
#endif
bcopy((char *)frstats, (char *)fio.f_st,
sizeof(struct filterstats) * 2);
- fio.f_fin[0] = filterin[0];
- fio.f_fin[1] = filterin[1];
- fio.f_fout[0] = filterout[0];
- fio.f_fout[1] = filterout[1];
+ fio.f_fin[0] = ipfilter[0][0];
+ fio.f_fin[1] = ipfilter[0][1];
+ fio.f_fout[0] = ipfilter[1][0];
+ fio.f_fout[1] = ipfilter[1][1];
+ fio.f_acctin[0] = ipacct[0][0];
+ fio.f_acctin[1] = ipacct[0][1];
+ fio.f_acctout[0] = ipacct[1][0];
+ fio.f_acctout[1] = ipacct[1][1];
fio.f_active = fr_active;
IWCOPY((caddr_t)&fio, data, sizeof(fio));
break;
iplused = 0;
break;
#endif /* IPFILTER_LOG */
+ case SIOCADNAT :
+ case SIOCRMNAT :
+ case SIOCGNATS :
+ error = nat_ioctl(data, cmd);
+ break;
+ case SIOCGFRST :
+ IWCOPY((caddr_t)ipfr_fragstats(), data, sizeof(ipfrstat_t));
+ break;
+ case SIOCGIPST :
+ IWCOPY((caddr_t)fr_statetstats(), data, sizeof(ips_stat_t));
+ break;
default :
error = -EINVAL;
break;
register struct frentry *f, **fprev;
register struct frentry **ftail;
struct frentry frd;
- int error = 0;
+ int error = 0, in;
- if (fp->fr_flags & FR_OUTQUE)
- ftail = fprev = &filterout[set];
- else if (fp->fr_flags & FR_INQUE)
- ftail = fprev = &filterin[set];
+ in = (fp->fr_flags & FR_INQUE) ? 0 : 1;
+ if (fp->fr_flags & FR_ACCOUNT) {
+ ftail = fprev = &ipacct[in][set];
+ } else if (fp->fr_flags & (FR_OUTQUE|FR_INQUE))
+ ftail = fprev = &ipfilter[in][set];
else
return ESRCH;
#ifdef IPFILTER_LOG
-int ipllog(hlen, flags, ip, ifp, rule)
-register int hlen;
+int ipllog(flags, ip, ifp, fi, m)
u_int flags;
ip_t *ip;
struct ifnet *ifp;
-u_short rule;
+register struct fr_ip *fi;
+struct mbuf *m;
{
struct ipl_ci iplci;
register size_t tail = 0;
- register int len, mlen;
- register struct mbuf *m = dtom(ip);
+ register int len, mlen, hlen;
+ hlen = fi->fi_hlen;
if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
- hlen += sizeof(tcphdr_t);
+ hlen += MIN(sizeof(tcphdr_t), ip->ip_len - hlen);
else if (ip->ip_p == IPPROTO_ICMP) {
struct icmp *icmp = (struct icmp *)((char *)ip + hlen);
case ICMP_REDIRECT :
case ICMP_TIMXCEED :
case ICMP_PARAMPROB :
- hlen += 8;
+ hlen += MIN(sizeof(struct icmp) + 8, ip->ip_len - hlen);
+ break;
default :
- hlen += sizeof(struct icmp);
+ hlen += MIN(sizeof(struct icmp), ip->ip_len - hlen);
+ break;
}
}
iplci.flags = flags;
iplci.hlen = (u_char)hlen;
iplci.plen = (flags & FR_LOGBODY) ? (u_char)mlen : 0 ;
- iplci.rule = rule;
+ iplci.rule = fi->fi_rule;
iplci.unit = (u_char)ifp->if_unit;
iplci.ifname[0] = ifp->if_name[0];
iplci.ifname[1] = ifp->if_name[1];
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*
- * @(#)ip_fil.h 1.23 11/11/95
+ * @(#)ip_fil.h 1.29 1/12/96
*/
#ifndef __IP_FIL_H_
#define __IP_FIL_H__
#ifndef IPFILTER_LOG
-#define IPFILTER_LOG 1
+#define IPFILTER_LOG
#endif
+#ifndef SOLARIS
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
+#endif
+
#if defined(KERNEL) && !defined(_KERNEL)
#define _KERNEL
#endif
u_long fi_optmsk;
u_short fi_secmsk;
u_short fi_auth;
+ u_short fi_out;
+ u_short fi_rule;
+ u_short fi_hlen;
+ u_char fi_icode;
+ struct frentry *fi_fr;
} fr_ip_t;
-#define FI_SHORT 0x01
-#define FI_OPTIONS 0x02
+#define FI_OPTIONS 0x01
+#define FI_TCPUDP 0x02 /* TCP/UCP implied comparison involved */
#define FI_FRAG 0x04
-#define FI_TCPUDP 0x08 /* TCP/UCP implied comparison involved */
+#define FI_SHORT 0x08
typedef struct frentry {
struct frentry *fr_next;
struct ifnet *fr_ifa;
- u_int fr_hits;
-
+ u_long fr_hits;
+ u_long fr_bytes; /* this is only incremented when a packet */
+ /* stops matching on this rule */
/*
* Fields after this may not change whilst in the kernel.
*/
u_short fr_sport;
u_short fr_stop; /* top port for <> and >< */
u_short fr_dtop; /* top port for <> and >< */
- u_short fr_flags; /* per-rule flags && options (see below) */
+ u_long fr_flags; /* per-rule flags && options (see below) */
+ char fr_icode; /* return ICMP code */
char fr_ifname[IFNAMSIZ];
} frentry_t;
/*
* fr_flags
- */
+*/
#define FR_BLOCK 0x0001
#define FR_PASS 0x0002
#define FR_OUTQUE 0x0004
#define FR_INQUE 0x0008
-#define FR_LOGP 0x0010 /* Log-pass */
-#define FR_LOGB 0x0020 /* Log-fail */
-#define FR_LOG 0x0040 /* Log */
-#define FR_LOGBODY 0x0080 /* Log the body */
-#define FR_QUICK 0x0100
-#define FR_RETRST 0x0200
-#define FR_RETICMP 0x0400
-#define FR_INACTIVE 0x0800
-#define FR_NOMATCH 0x1000
+#define FR_LOG 0x0010 /* Log */
+#define FR_LOGB 0x0021 /* Log-fail */
+#define FR_LOGP 0x0022 /* Log-pass */
+#define FR_LOGBODY 0x0040 /* Log the body */
+#define FR_LOGFIRST 0x0080
+#define FR_RETRST 0x0100
+#define FR_RETICMP 0x0200
+#define FR_NOMATCH 0x0400
+#define FR_ACCOUNT 0x0800 /* count packet bytes */
+#define FR_KEEPFRAG 0x1000
+#define FR_KEEPSTATE 0x2000
+#define FR_INACTIVE 0x4000
+#define FR_QUICK 0x8000
+/*
+ * recognized flags for SIOCGETFF and SIOCSETFF
+ */
+#define FF_LOGPASS 0x100000
+#define FF_LOGBLOCK 0x200000
+#define FF_LOGNOMATCH 0x400000
#define FR_NONE 0
#define FR_EQUAL 1
u_long fr_nom; /* packets which don't match any rule */
u_long fr_ppkl; /* packets allowed and logged */
u_long fr_bpkl; /* packets denied and logged */
+ u_long fr_npkl; /* packets unmatched and logged */
u_long fr_pkl; /* packets logged */
u_long fr_skip; /* packets to be logged but buffer full */
u_long fr_ret; /* packets for which a return is sent */
+ u_long fr_acct; /* packets for which counting was performed */
+ u_long fr_bnfr; /* bad attempts to allocate fragment state */
+ u_long fr_nfr; /* new fragment state kept */
+ u_long fr_bads; /* bad attempts to allocate packet state */
+ u_long fr_ads; /* new packet state kept */
#if SOLARIS
u_long fr_bad; /* bad IP packets to the filter */
u_long fr_notip; /* packets passed through no on ip queue */
#endif
} filterstats_t;
-/*
- * recognized flags for SIOCGETFF and SIOCSETFF
- */
-#define FF_LOGPASS 1
-#define FF_LOGBLOCK 2
-
/*
* For SIOCGETFS
*/
struct filterstats f_st[2];
struct frentry *f_fin[2];
struct frentry *f_fout[2];
+ struct frentry *f_acctin[2];
+ struct frentry *f_acctout[2];
int f_active;
} friostat_t;
int ol_bit;
} optlist_t;
-#ifdef _KERNEL
-extern struct frentry *filterin[], *filterout[];
-extern struct filterstats frstats[];
-#endif
-
typedef struct ipl_ci {
u_long sec;
u_long usec;
u_char ifname[4];
} ipl_ci_t;
-#ifdef _KERNEL
-typedef struct ipfr {
- struct ipfr *ipfr_next, *ipfr_prev;
- struct in_addr ipfr_src;
- struct in_addr ipfr_dst;
- u_short ipfr_id;
- u_short ipfr_age;
- u_char ipfr_p;
- u_char ipfr_tos;
- u_char ipfr_pass;
-} ipfr_t;
+#ifndef ICMP_UNREACH_FILTER
+#define ICMP_UNREACH_FILTER 13
+#endif
+/*
+ * Security Options for Intenet Protocol (IPSO) as defined in RFC 1108.
+ *
+ * Basic Option
+ *
+ * 00000001 - (Reserved 4)
+ * 00111101 - Top Secret
+ * 01011010 - Secret
+ * 10010110 - Confidential
+ * 01100110 - (Reserved 3)
+ * 11001100 - (Reserved 2)
+ * 10101011 - Unclassified
+ * 11110001 - (Reserved 1)
+ */
+#define IPSO_CLASS_RES4 0x01
+#define IPSO_CLASS_TOPS 0x3d
+#define IPSO_CLASS_SECR 0x5a
+#define IPSO_CLASS_CONF 0x96
+#define IPSO_CLASS_RES3 0x66
+#define IPSO_CLASS_RES2 0xcc
+#define IPSO_CLASS_UNCL 0xab
+#define IPSO_CLASS_RES1 0xf1
+
+#define IPSO_AUTH_GENSER 0x80
+#define IPSO_AUTH_ESI 0x40
+#define IPSO_AUTH_SCI 0x20
+#define IPSO_AUTH_NSA 0x10
+#define IPSO_AUTH_DOE 0x08
+#define IPSO_AUTH_UN 0x06
+#define IPSO_AUTH_FTE 0x01
+
+/*#define IPOPT_RR 7 */
+#define IPOPT_ZSU 10 /* ZSU */
+#define IPOPT_MTUP 11 /* MTUP */
+#define IPOPT_MTUR 12 /* MTUR */
+#define IPOPT_ENCODE 15 /* ENCODE */
+/*#define IPOPT_TS 68 */
+#define IPOPT_TR 82 /* TR */
+/*#define IPOPT_SECURITY 130 */
+/*#define IPOPT_LSRR 131 */
+#define IPOPT_E_SEC 133 /* E-SEC */
+#define IPOPT_CIPSO 134 /* CIPSO */
+/*#define IPOPT_SATID 136 */
+#ifndef IPOPT_SID
+# define IPOPT_SID IPOPT_SATID
+#endif
+/*#define IPOPT_SSRR 137 */
+#define IPOPT_ADDEXT 147 /* ADDEXT */
+#define IPOPT_VISA 142 /* VISA */
+#define IPOPT_IMITD 144 /* IMITD */
+#define IPOPT_EIP 145 /* EIP */
+#define IPOPT_FINN 205 /* FINN */
+
+#define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h)))
+
+extern int fr_check();
+
+#ifdef _KERNEL
+
+extern struct frentry *ipfilter[2][2], *ipacct[2][2];
+extern struct filterstats frstats[];
+# if SOLARIS
+extern int ipfsync();
+# endif
+#endif /* _KERNEL */
+
+#ifndef SOLARIS
+#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
+#endif
+#define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h)))
-#define IPFR_CMPSZ (4 + 4 + 2 + 1 + 1)
+#ifndef IP_OFFMASK
+#define IP_OFFMASK 0x1fff
+#endif
-# if defined(sun) && !defined(linux)
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifdef _KERNEL
+# if SOLARIS
+# define MUTEX_ENTER(x) mutex_enter(x)
+# define MUTEX_EXIT(x) mutex_exit(x)
+# define MTOD(m,t) (t)((m)->b_rptr)
+# define IRCOPY(a,b,c) copyin((a), (b), (c))
+# define IWCOPY(a,b,c) copyout((a), (b), (c))
+# else
+# define MUTEX_ENTER(x) ;
+# define MUTEX_EXIT(x) ;
+# ifndef linux
+# define MTOD(m,t) mtod(m,t)
+# define IRCOPY(a,b,c) bcopy((a), (b), (c))
+# define IWCOPY(a,b,c) bcopy((a), (b), (c))
+# endif
+# endif /* SOLARIS */
+
+# ifdef sun
+# if defined(__svr4__) || defined(__SVR4)
+# define GETUNIT(n) get_unit((n))
+# else
+# include <sys/kmem_alloc.h>
+# define GETUNIT(n) ifunit((n), IFNAMSIZ)
+# endif
+# else
+# define GETUNIT(n) ifunit((n))
+# endif /* sun */
+
+# if defined(sun) && !defined(linux) && !defined(__NetBSD__) && !defined (__OpenBSD__)
# define UIOMOVE(a,b,c,d) uiomove(a,b,c,d)
# define SLEEP(id, n) sleep((id), PZERO+1)
# define KFREE(x) kmem_free((char *)(x), sizeof(*(x)))
# if SOLARIS
+typedef struct qif {
+ struct qif *qf_next;
+ ill_t *qf_ill;
+ kmutex_t qf_lock;
+ void *qf_iptr;
+ void *qf_optr;
+ queue_t *qf_in;
+ queue_t *qf_out;
+ void *qf_wqinfo;
+ void *qf_rqinfo;
+ char qf_name[8];
+ int (*qf_inp)();
+ int (*qf_outp)();
+ /*
+ * in case the ILL has disappeared...
+ */
+ int qf_hl; /* header length */
+} qif_t;
+# define SPLNET(x) ;
+# undef SPLX
+# define SPLX(x) ;
# ifdef sparc
# define ntohs(x) (x)
# define ntohl(x) (x)
# else
# define KMALLOC(x) new_kmem_alloc((x), KMEM_SLEEP)
# endif /* __svr4__ */
-# endif /* sun && !linux */
+# endif /* sun && !linux && !__NetBSD__ && !__OpenBSD__*/
# ifndef GET_MINOR
# define GET_MINOR(x) minor(x)
# endif
sizeof(*(x)))
# define UIOMOVE(a,b,c,d) uiomove(a,b,d)
# define SLEEP(id, n) tsleep((id), PPAUSE|PCATCH, n, 0)
-# else
# endif /* BSD */
-#endif /* _KERNEL */
+# if defined(NetBSD1_0) && (NetBSD1_0 > 1)
+# define SPLNET(x) x = splsoftnet()
+# else
+# if !SOLARIS
+# define SPLNET(x) x = splnet()
+# define SPLX(x) (void) splx(x)
+# endif
+# endif
+#else
+# define MUTEX_ENTER(x) ;
+# define MUTEX_EXIT(x) ;
+# define SPLNET(x) ;
+# define SPLX(x) ;
+# define KMALLOC(x) malloc(x)
+# define KFREE(x) free(x)
+# define GETUNIT(x) (x)
+# define IRCOPY(a,b,c) bcopy((a), (b), (c))
+# define IWCOPY(a,b,c) bcopy((a), (b), (c))
+#endif /* KERNEL */
#ifdef linux
# define ICMP_UNREACH ICMP_DEST_UNREACH
__u16 th_urp;
} tcphdr_t;
+typedef struct {
+ __u16 uh_sport;
+ __u16 uh_dport;
+ __u16 uh_ulen;
+ __u16 uh_sun;
+} udphdr_t;
+
typedef struct {
# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\
defined(vax)
__u32 ip_dst;
} ip_t;
-# define SPLX(x) ;
-# define SPLNET(x) ;
+# define SPLX(x) (void)
+# define SPLNET(x) (void)
# define bcopy(a,b,c) memmove(b,a,c)
# define bcmp(a,b,c) memcmp(a,b,c)
memcpy_tofs((b), (a), (c)); \
}
#else
-
typedef struct tcphdr tcphdr_t;
+typedef struct udphdr udphdr_t;
typedef struct ip ip_t;
-
-# if SOLARIS
-# define MTOD(m,t) (t)((m)->b_rptr)
-# define IRCOPY(a,b,c) copyin((a), (b), (c))
-# define IWCOPY(a,b,c) copyout((a), (b), (c))
-# ifdef _KERNEL
-typedef struct qif {
- struct qif *qf_next;
- ill_t *qf_ill;
- kmutex_t qf_lock;
- void *qf_iptr;
- void *qf_optr;
- queue_t *qf_in;
- queue_t *qf_out;
- void *qf_wqinfo;
- void *qf_rqinfo;
- char qf_name[8];
- int (*qf_inp)();
- int (*qf_outp)();
- /*
- * in case the ILL has disappeared...
- */
- int qf_hl; /* header length */
-} qif_t;
-# endif /* _KERNEL */
-# else
-# define MTOD(m,t) mtod(m,t)
-# define IRCOPY(a,b,c) bcopy((a), (b), (c))
-# define IWCOPY(a,b,c) bcopy((a), (b), (c))
-# endif /* SOLARIS */
-# ifdef _KERNEL
-# if defined(NetBSD1_0) && (NetBSD1_0 > 1)
-# define SPLNET(x) x = splsoftnet()
-# else
-# if SOLARIS
-# define SPLNET(x) ;
-# else
-# define SPLNET(x) x = splnet()
-# endif
-# endif
-# ifdef SPLX
-# undef SPLX
-# endif
-# if SOLARIS
-# define SPLX(x) ;
-# else
-# define SPLX(x) (void) splx(x)
-# endif
-# else
-# define SPLNET(x) ;
-# define SPLX(x) ;
-# endif /* KERNEL */
-
-# ifdef sun
-# if !defined(__sysv__) && !defined(__SVR4)
-# define GETUNIT(n) ifunit((n), IFNAMSIZ)
-# endif
-# else
-# define GETUNIT(n) ifunit((n))
-# endif /* sun */
-extern struct ifnet *ifunit();
#endif /* linux */
-#define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h)))
-
-/*#define IPOPT_RR 7 */
-#define IPOPT_ZSU 10 /* ZSU */
-#define IPOPT_MTUP 11 /* MTUP */
-#define IPOPT_MTUR 12 /* MTUR */
-#define IPOPT_ENCODE 15 /* ENCODE */
-/*#define IPOPT_TS 68 */
-#define IPOPT_TR 82 /* TR */
-/*#define IPOPT_SECURITY 130 */
-/*#define IPOPT_LSRR 131 */
-#define IPOPT_E_SEC 133 /* E-SEC */
-#define IPOPT_CIPSO 134 /* CIPSO */
-/*#define IPOPT_SATID 136 */
-#ifndef IPOPT_SID
-# define IPOPT_SID IPOPT_SATID
-#endif
-/*#define IPOPT_SSRR 137 */
-#define IPOPT_ADDEXT 147 /* ADDEXT */
-#define IPOPT_VISA 142 /* VISA */
-#define IPOPT_IMITD 144 /* IMITD */
-#define IPOPT_EIP 145 /* EIP */
-#define IPOPT_FINN 205 /* FINN */
-
-#ifndef ICMP_UNREACH_FILTER
-#define ICMP_UNREACH_FILTER 13
-#endif
-/*
- * Security Options for Intenet Protocol (IPSO) as defined in RFC 1108.
- *
- * Basic Option
- *
- * 00000001 - (Reserved 4)
- * 00111101 - Top Secret
- * 01011010 - Secret
- * 10010110 - Confidential
- * 01100110 - (Reserved 3)
- * 11001100 - (Reserved 2)
- * 10101011 - Unclassified
- * 11110001 - (Reserved 1)
- */
-#define IPSO_CLASS_RES4 0x01
-#define IPSO_CLASS_TOPS 0x3d
-#define IPSO_CLASS_SECR 0x5a
-#define IPSO_CLASS_CONF 0x96
-#define IPSO_CLASS_RES3 0x66
-#define IPSO_CLASS_RES2 0xcc
-#define IPSO_CLASS_UNCL 0xab
-#define IPSO_CLASS_RES1 0xf1
-
-#define IPSO_AUTH_GENSER 0x80
-#define IPSO_AUTH_ESI 0x40
-#define IPSO_AUTH_SCI 0x20
-#define IPSO_AUTH_NSA 0x10
-#define IPSO_AUTH_DOE 0x08
-#define IPSO_AUTH_UN 0x06
-#define IPSO_AUTH_FTE 0x01
-
#endif /* __IP_FIL_H__ */
--- /dev/null
+/*
+ * (C)opyright 1993,1994,1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+#ifndef lint
+static char sccsid[] = "@(#)ip_frag.c 1.5 1/14/96 (C) 1993-1995 Darren Reed";
+#endif
+
+#include <string.h>
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#if !defined(__SVR4) && !defined(__svr4__)
+# include <sys/dir.h>
+# include <sys/mbuf.h>
+#else
+# include <sys/byteorder.h>
+# include <sys/dditypes.h>
+# include <sys/stream.h>
+# include <sys/kmem.h>
+#endif
+
+#include <net/if.h>
+#ifdef sun
+#include <net/af.h>
+#endif
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/tcpip.h>
+#include <netinet/ip_icmp.h>
+#include <syslog.h>
+#include "ip_fil.h"
+#include "ip_frag.h"
+#include "ip_nat.h"
+#include "ip_state.h"
+
+ipfr_t *ipfr_heads[IPFT_SIZE];
+ipfrstat_t ipfr_stats;
+u_long ipfr_inuse = 0;
+#ifdef _KERNEL
+extern int ipfr_timer_id;
+#endif
+#if SOLARIS
+# ifdef _KERNEL
+extern kmutex_t ipf_frag;
+# else
+#define bcmp(a,b,c) memcmp(a,b,c)
+#define bcopy(a,b,c) memmove(b,a,c)
+# endif
+#endif
+
+
+ipfrstat_t *ipfr_fragstats()
+{
+ ipfr_stats.ifs_table = ipfr_heads;
+ ipfr_stats.ifs_inuse = ipfr_inuse;
+ return &ipfr_stats;
+}
+
+
+/*
+ * add a new entry to the fragment cache, registering it as having come
+ * through this box, with the result of the filter operation.
+ */
+int ipfr_newfrag(ip, pass)
+ip_t *ip;
+int pass;
+{
+ ipfr_t **fp, *fr, frag;
+ u_int idx;
+
+ frag.ipfr_p = ip->ip_p;
+ idx = ip->ip_p;
+ frag.ipfr_id = ip->ip_id;
+ idx += ip->ip_id;
+ frag.ipfr_tos = ip->ip_tos;
+ frag.ipfr_src.s_addr = ip->ip_src.s_addr;
+ idx += ip->ip_src.s_addr;
+ frag.ipfr_dst.s_addr = ip->ip_dst.s_addr;
+ idx += ip->ip_dst.s_addr;
+ idx *= 127;
+ idx %= IPFT_SIZE;
+
+ /*
+ * first, make sure it isn't already there...
+ */
+ MUTEX_ENTER(&ipf_frag);
+ for (fp = &ipfr_heads[idx]; (fr = *fp); fp = &fr->ipfr_next)
+ if (!bcmp((char *)&frag.ipfr_src, (char *)&fr->ipfr_src,
+ IPFR_CMPSZ)) {
+ ipfr_stats.ifs_exists++;
+ MUTEX_EXIT(&ipf_frag);
+ return -1;
+ }
+
+ if (!(fr = (ipfr_t *)KMALLOC(sizeof(*fr)))) {
+ ipfr_stats.ifs_nomem++;
+ MUTEX_EXIT(&ipf_frag);
+ return -1;
+ }
+ if ((fr->ipfr_next = ipfr_heads[idx]))
+ ipfr_heads[idx]->ipfr_prev = fr;
+ fr->ipfr_prev = NULL;
+ ipfr_heads[idx] = fr;
+ bcopy((char *)&frag.ipfr_src, (char *)&fr->ipfr_src, IPFR_CMPSZ);
+ fr->ipfr_ttl = 120; /* 60 seconds */
+ fr->ipfr_pass = pass;
+ *fp = fr;
+ ipfr_stats.ifs_new++;
+ ipfr_inuse++;
+ MUTEX_EXIT(&ipf_frag);
+ return 0;
+}
+
+
+/*
+ * check the fragment cache to see if there is already a record of this packet
+ * with its filter result known.
+ */
+int ipfr_knownfrag(ip)
+ip_t *ip;
+{
+ ipfr_t *f, frag;
+ u_int idx;
+
+ /*
+ * For fragments, we record protocol, packet id, TOS and both IP#'s
+ * (these should all be the same for all fragments of a packet).
+ */
+ frag.ipfr_p = ip->ip_p;
+ idx = ip->ip_p;
+ frag.ipfr_id = ip->ip_id;
+ idx += ip->ip_id;
+ frag.ipfr_tos = ip->ip_tos;
+ frag.ipfr_src.s_addr = ip->ip_src.s_addr;
+ idx += ip->ip_src.s_addr;
+ frag.ipfr_dst.s_addr = ip->ip_dst.s_addr;
+ idx += ip->ip_dst.s_addr;
+ idx *= 127;
+ idx %= IPFT_SIZE;
+
+ MUTEX_ENTER(&ipf_frag);
+ for (f = ipfr_heads[idx]; f; f = f->ipfr_next)
+ if (!bcmp((char *)&frag.ipfr_src, (char *)&f->ipfr_src,
+ IPFR_CMPSZ)) {
+ if (f != ipfr_heads[idx]) {
+ /*
+ * move fragment info. to the top of the list
+ * to speed up searches.
+ */
+ if ((f->ipfr_prev->ipfr_next = f->ipfr_next))
+ f->ipfr_next->ipfr_prev = f->ipfr_prev;
+ f->ipfr_next = ipfr_heads[idx];
+ ipfr_heads[idx]->ipfr_prev = f;
+ f->ipfr_prev = NULL;
+ ipfr_heads[idx] = f;
+ }
+ ipfr_stats.ifs_hits++;
+ return f->ipfr_pass;
+ }
+ MUTEX_EXIT(&ipf_frag);
+ return 0;
+}
+
+
+/*
+ * Free memory in use by fragment state info. kept.
+ */
+void ipfr_unload()
+{
+ ipfr_t **fp, *fr;
+ int idx;
+#if !SOLARIS
+ int s;
+#endif
+
+ MUTEX_ENTER(&ipf_frag);
+ SPLNET(s);
+ for (idx = IPFT_SIZE - 1; idx >= 0; idx--)
+ for (fp = &ipfr_heads[idx]; (fr = *fp); ) {
+ *fp = fr->ipfr_next;
+ KFREE(fp);
+ }
+ SPLX(s);
+ MUTEX_EXIT(&ipf_frag);
+}
+
+
+#ifdef _KERNEL
+/*
+ * Slowly expire held state for fragments. Timeouts are set * in expectation
+ * of this being called twice per second.
+ */
+# if BSD < 199306
+int ipfr_slowtimer()
+#else
+void ipfr_slowtimer()
+#endif
+{
+ ipfr_t **fp, *fr;
+ int s, idx;
+
+ MUTEX_ENTER(&ipf_frag);
+ SPLNET(s);
+
+ for (idx = IPFT_SIZE - 1; idx >= 0; idx--)
+ for (fp = &ipfr_heads[idx]; (fr = *fp); ) {
+ --fr->ipfr_ttl;
+ if (fr->ipfr_ttl == 0) {
+ if (fr->ipfr_prev)
+ fr->ipfr_prev->ipfr_next =
+ fr->ipfr_next;
+ if (fr->ipfr_next)
+ fr->ipfr_next->ipfr_prev =
+ fr->ipfr_prev;
+ *fp = fr->ipfr_next;
+ ipfr_stats.ifs_expire++;
+ ipfr_inuse--;
+ KFREE(fp);
+ } else
+ fp = &fr->ipfr_next;
+ }
+ SPLX(s);
+#if SOLARIS
+ MUTEX_EXIT(&ipf_frag);
+ fr_timeoutstate();
+ ip_natexpire();
+ ipfr_timer_id = timeout(ipfr_slowtimer, NULL, HZ/2);
+#else
+ fr_timeoutstate();
+ ip_natexpire();
+ ip_slowtimo();
+#endif
+# if BSD < 199306
+ return 0;
+# endif
+}
+#endif /* defined(_KERNEL) */
--- /dev/null
+/*
+ * (C)opyright 1993, 1994, 1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ *
+ * @(#)ip_frag.h 1.3 1/12/96
+ */
+
+#ifndef __IP_FRAG_H_
+#define __IP_FRAG_H__
+
+#define IPFT_SIZE 257
+
+typedef struct ipfr {
+ struct ipfr *ipfr_next, *ipfr_prev;
+ struct in_addr ipfr_src;
+ struct in_addr ipfr_dst;
+ u_short ipfr_id;
+ u_short ipfr_ttl;
+ u_char ipfr_p;
+ u_char ipfr_tos;
+ u_char ipfr_pass;
+} ipfr_t;
+
+#if defined(__STDC__) || defined(__GNUC__)
+#define SIOCGFRST _IOR('r', 76, struct ipfrstat)
+#else
+#define SIOCGFRST _IOR(r, 76, struct ipfrstat)
+#endif
+
+typedef struct ipfrstat {
+ u_long ifs_exists; /* add & already exists */
+ u_long ifs_nomem;
+ u_long ifs_new;
+ u_long ifs_hits;
+ u_long ifs_expire;
+ u_long ifs_inuse;
+ struct ipfr **ifs_table;
+} ipfrstat_t;
+
+#define IPFR_CMPSZ (4 + 4 + 2 + 1 + 1)
+
+extern ipfrstat_t *ipfr_fragstats();
+extern int ipfr_newfrag(), ipfr_knownfrag();
+# ifdef _KERNEL
+extern void ipfr_unload();
+# endif
+#endif /* __IP_FIL_H__ */
struct in_ifaddrhead in_ifaddr;
struct ifqueue ipintrq;
#if defined(IPFILTER) || defined(IPFILTER_LKM)
-int fr_nullcheck();
-int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int)) = fr_nullcheck;
+int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **));
#endif
char *
* Check if we want to allow this packet to be processed.
* Consider it to be bad if not.
*/
- if ((*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0))
- goto bad;
+ {
+ struct mbuf *m0 = m;
+ if (fr_checkp && (*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m0))
+ goto next;
+ else
+ ip = mtod(m = m0, struct ip *);
+ }
#endif
/*
* Process options and, if not destined for us,
}
/* NOTREACHED */
}
-
-#if defined(IPFILTER) || defined(IPFILTER_LKM)
-int fr_nullcheck()
-{
- return 0;
-}
-#endif
--- /dev/null
+/*
+ * (C)opyright 1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+#ifndef lint
+static char sccsid[] = "@(#)ip_nat.c 1.3 1/12/96 (C) 1995 Darren Reed";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#if !defined(__SVR4) && !defined(__svr4__)
+# include <sys/dir.h>
+# include <sys/mbuf.h>
+#else
+# include <sys/byteorder.h>
+# include <sys/dditypes.h>
+# include <sys/stream.h>
+# include <sys/kmem.h>
+#endif
+
+#include <net/if.h>
+#ifdef sun
+#include <net/af.h>
+#endif
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/tcpip.h>
+#include <netinet/ip_icmp.h>
+#include <syslog.h>
+#include "ip_fil.h"
+#include "ip_nat.h"
+#ifndef MIN
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+
+nat_t *nat_table[2][NAT_SIZE];
+ipnat_t *nat_list = NULL;
+u_long nat_inuse = 0;
+natstat_t nat_stats;
+#if SOLARIS
+# ifndef _KERNEL
+#define bcmp(a,b,c) memcpy(a,b,c)
+#define bcopy(a,b,c) memmove(b,a,c)
+# else
+extern kmutex_t ipf_nat;
+# endif
+#endif
+
+
+/*
+ * How the NAT is organised and works.
+ *
+ * Inside (interface y) NAT Outside (interface x)
+ * -------------------- -+- -------------------------------------
+ * Packet going | out, processsed by ip_natout() for x
+ * ------------> | ------------>
+ * src=10.1.1.1 | src=192.1.1.1
+ * |
+ * | in, processed by ip_natin() for x
+ * <------------ | <------------
+ * dst=10.1.1.1 | dst=192.1.1.1
+ * -------------------- -+- -------------------------------------
+ * ip_natout() - changes ip_src and if required, sport
+ * - creates a new mapping, if required.
+ * ip_natin() - changes ip_dst and if required, dport
+ *
+ * In the NAT table, internal source is recorded as "in" and externally
+ * seen as "out".
+ */
+
+/*
+ * Handle ioctls which manipulate the NAT.
+ */
+int nat_ioctl(data, cmd)
+caddr_t data;
+int cmd;
+{
+ register ipnat_t *nat, *n, **np;
+
+ /*
+ * For add/delete, look to see if the NAT entry is already present
+ */
+ MUTEX_ENTER(&ipf_nat);
+ if ((cmd == SIOCADNAT) || (cmd == SIOCRMNAT)) {
+ nat = (ipnat_t *)data;
+ for (np = &nat_list; (n = *np); np = &n->in_next)
+ if (!bcmp((char *)&nat->in_port, (char *)&n->in_port,
+ IPN_CMPSIZ))
+ break;
+ }
+
+ switch (cmd)
+ {
+ case SIOCADNAT :
+ if (n) {
+ MUTEX_EXIT(&ipf_nat);
+ return EEXIST;
+ }
+ if (!(n = (ipnat_t *)KMALLOC(sizeof(*n)))) {
+ MUTEX_EXIT(&ipf_nat);
+ return ENOMEM;
+ }
+ IRCOPY((char *)data, (char *)np, sizeof(*np));
+ bcopy((char *)nat, (char *)n, sizeof(*n));
+ n->in_ifp = (void *)GETUNIT(n->in_ifname);
+ n->in_next = *np;
+ n->in_space = ~(0xffffffff & ntohl(n->in_outmsk));
+ n->in_space--; /* lose 1 for broadcast address */
+ n->in_nip = ntohl(n->in_outip) + 1;
+ n->in_pnext = ntohs(n->in_pmin);
+ *np = n;
+ break;
+ case SIOCRMNAT :
+ if (!n) {
+ MUTEX_EXIT(&ipf_nat);
+ return ESRCH;
+ }
+ *np = n->in_next;
+ KFREE(n);
+ break;
+ case SIOCGNATS :
+ nat_stats.ns_table = (nat_t ***)nat_table;
+ nat_stats.ns_list = nat_list;
+ nat_stats.ns_inuse = nat_inuse;
+ IWCOPY((char *)&nat_stats, (char *)data, sizeof(nat_stats));
+ break;
+ }
+ MUTEX_EXIT(&ipf_nat);
+ return 0;
+}
+
+
+/*
+ * Create a new NAT table entry.
+ */
+nat_t *nat_new(ip, hlen, flags)
+ip_t *ip;
+int hlen;
+u_short flags;
+{
+ u_short port = 0, sport = 0;
+ struct in_addr in;
+ tcphdr_t *tcp;
+ ipnat_t *np;
+ nat_t *nat, **natp;
+
+ if (flags) {
+ tcp = (tcphdr_t *)((char *)ip + hlen);
+ sport = tcp->th_sport;
+ }
+
+ MUTEX_ENTER(&ipf_nat);
+ /*
+ * Search the current table for a match.
+ */
+ do {
+ in.s_addr = np->in_nip;
+ if (np->in_flags & IPN_TCPUDP) {
+ port = htons(np->in_pnext++);
+ if (np->in_pnext >= ntohs(np->in_pmax)) {
+ np->in_pnext = ntohs(np->in_pmin);
+ np->in_nip++;
+ np->in_space--;
+ }
+ } else {
+ np->in_space--;
+ np->in_nip++;
+ }
+ if ((np->in_nip & ntohl(np->in_outmsk)) > ntohl(np->in_outip))
+ np->in_nip = ntohl(np->in_outip) + 1;
+ } while (nat_lookupinip(in, sport));
+
+ if (!(nat = (nat_t *)KMALLOC(sizeof(*nat)))) {
+ MUTEX_EXIT(&ipf_nat);
+ return NULL;
+ }
+ nat->nat_use = 0;
+ in.s_addr = htonl(in.s_addr);
+ nat->nat_inip = ip->ip_src;
+ nat->nat_outip = in;
+ nat->nat_sumd = (ntohl(ip->ip_src.s_addr) & 0xffff) +
+ (ntohl(ip->ip_src.s_addr) >> 16);
+ nat->nat_sumd -= ((ntohl(in.s_addr) & 0xffff) +
+ (ntohl(in.s_addr) >> 16));
+ if (sport) {
+ nat->nat_inport = sport;
+ nat->nat_outport = port;
+ nat->nat_sumd += (ntohs(sport) - ntohs(port));
+ } else {
+ nat->nat_inport = 0;
+ nat->nat_outport = 0;
+ }
+ natp = &nat_table[0][nat->nat_inip.s_addr % NAT_SIZE];
+ nat->nat_next = *natp;
+ *natp = nat;
+ nat->nat_use++;
+ natp = &nat_table[1][nat->nat_outip.s_addr % NAT_SIZE];
+ nat->nat_next = *natp;
+ *natp = nat;
+ nat->nat_use++;
+ ip->ip_src = in;
+ if (flags)
+ tcp->th_sport = htons(port);
+ nat_stats.ns_added++;
+ nat_inuse++;
+ MUTEX_EXIT(&ipf_nat);
+ return nat;
+}
+
+
+nat_t *nat_lookupoutip(ipaddr, sport)
+struct in_addr ipaddr;
+u_short sport;
+{
+ nat_t *nat;
+
+ nat = nat_table[1][ipaddr.s_addr % NAT_SIZE];
+
+ MUTEX_ENTER(&ipf_nat);
+ for (; nat; nat = nat->nat_next)
+ if (nat->nat_outip.s_addr == ipaddr.s_addr) {
+ if (nat->nat_outport && (sport != nat->nat_outport))
+ continue;
+ return nat;
+ }
+ MUTEX_EXIT(&ipf_nat);
+ return NULL;
+}
+
+
+/*
+ * Packets going out on the external interface go through this.
+ * Here, the source address requires alteration, if anything.
+ */
+void ip_natout(ifp, ip, hlen)
+struct ifnet *ifp;
+ip_t *ip;
+int hlen;
+{
+ register ipnat_t *np;
+ register u_long ipa;
+ register u_long sum1, sum2;
+ tcphdr_t *tcp;
+ nat_t *nat;
+ u_short nflags = 0, sport = 0;
+
+ if (ip->ip_p == IPPROTO_TCP)
+ nflags = IPN_TCP;
+ else if (ip->ip_p == IPPROTO_UDP)
+ nflags = IPN_UDP;
+ if (nflags) {
+ tcp = (tcphdr_t *)((char *)ip + hlen);
+ sport = tcp->th_sport;
+ }
+
+ ipa = ip->ip_src.s_addr;
+
+ MUTEX_ENTER(&ipf_nat);
+ for (np = nat_list; np; np = np->in_next)
+ if ((np->in_ifp == ifp) && np->in_space &&
+ (!np->in_flags || (np->in_flags & nflags)) &&
+ ((ipa & np->in_inmsk) == np->in_inip)) {
+ /*
+ * If there is no current entry in the nat table for
+ * this IP#, create one for it.
+ */
+ if (!(nat = nat_lookupinip(ip->ip_src, sport))) {
+ if (!(nat = nat_new(ip, hlen,
+ nflags & np->in_flags))) {
+ MUTEX_EXIT(&ipf_nat);
+ return;
+ }
+ } else
+ ip->ip_src = nat->nat_outip;
+
+ nat->nat_age = 1200; /* 5 mins */
+
+ /*
+ * Fix up checksums, not by recalculating them, but
+ * simply computing adjustments.
+ */
+ if (nflags) {
+ if (nat->nat_outport) {
+ sum1 += sport;
+ tcp->th_sport = nat->nat_outport;
+ sum2 += tcp->th_sport;
+ }
+
+ sum2 = nat->nat_sumd;
+
+ if (ip->ip_p == IPPROTO_TCP) {
+ sum2 += ntohs(tcp->th_sum);
+ sum2 = (sum2 >> 16) + (sum2 & 0xffff);
+ sum2 += (sum2 >> 16);
+ tcp->th_sum = htons(sum2);
+ } else if (ip->ip_p == IPPROTO_UDP) {
+ udphdr_t *udp = (udphdr_t *)tcp;
+
+ udp->uh_sum = 0;
+ }
+ }
+ nat_stats.ns_mapped[1]++;
+ MUTEX_EXIT(&ipf_nat);
+ return;
+ }
+ MUTEX_EXIT(&ipf_nat);
+ return;
+}
+
+nat_t *nat_lookupinip(ipaddr, sport)
+struct in_addr ipaddr;
+u_short sport;
+{
+ nat_t *nat;
+
+ nat = nat_table[0][ipaddr.s_addr % NAT_SIZE];
+
+ MUTEX_ENTER(&ipf_nat);
+ for (; nat; nat = nat->nat_next)
+ if (nat->nat_inip.s_addr == ipaddr.s_addr) {
+ if (nat->nat_inport && (sport != nat->nat_inport))
+ continue;
+ return nat;
+ }
+ MUTEX_EXIT(&ipf_nat);
+ return NULL;
+}
+
+
+/*
+ * Packets coming in from the external interface go through this.
+ * Here, the destination address requires alteration, if anything.
+ */
+void ip_natin(ifp, ip, hlen)
+struct ifnet *ifp;
+ip_t *ip;
+int hlen;
+{
+ register ipnat_t *np;
+ register struct in_addr in;
+ register u_long sum1, sum2;
+ tcphdr_t *tcp;
+ u_short port = 0, nflags;
+ nat_t *nat;
+
+ if (ip->ip_p == IPPROTO_TCP)
+ nflags = IPN_TCP;
+ else if (ip->ip_p == IPPROTO_UDP)
+ nflags = IPN_UDP;
+ if (nflags) {
+ tcp = (tcphdr_t *)((char *)ip + hlen);
+ port = tcp->th_dport;
+ }
+
+ in = ip->ip_dst;
+
+ MUTEX_ENTER(&ipf_nat);
+ for (np = nat_list; np; np = np->in_next)
+ if ((np->in_ifp == ifp) &&
+ (!np->in_flags || (nflags & np->in_flags)) &&
+ ((in.s_addr & np->in_outmsk) == np->in_outip)) {
+ if (!(nat = nat_lookupoutip(in, port)))
+ continue;
+ nat->nat_age = 1200;
+ ip->ip_dst = nat->nat_inip;
+
+ /*
+ * Fix up checksums, not by recalculating them, but
+ * simply computing adjustments.
+ */
+
+ if (nflags) {
+ u_short *sp = NULL;
+
+ if (nat->nat_inport) {
+ sum1 += port;
+ tcp->th_dport = nat->nat_inport;
+ sum2 += tcp->th_dport;
+ }
+
+ sum2 = nat->nat_sumd;
+
+ if (ip->ip_p == IPPROTO_TCP) {
+ sp = &tcp->th_sum;
+ if (ntohs(*sp) > sum2)
+ sum2--;
+ sum2 -= ntohs(*sp);
+ sum2 = (sum2 >> 16) + (sum2 & 0xffff);
+ sum2 += (sum2 >> 16);
+ *sp = htons(~sum2);
+ } else if (ip->ip_p == IPPROTO_UDP) {
+ udphdr_t *udp = (udphdr_t *)tcp;
+
+ udp->uh_sum = 0;
+ }
+ }
+ nat_stats.ns_mapped[0]++;
+ MUTEX_EXIT(&ipf_nat);
+ return;
+ }
+ MUTEX_EXIT(&ipf_nat);
+ return;
+}
+
+
+/*
+ * Free all memory used by NAT structures allocated at runtime.
+ */
+void ip_natunload()
+{
+ register struct nat *nat, **natp;
+ register struct ipnat *ipn, **ipnp;
+ register int i;
+
+ MUTEX_ENTER(&ipf_nat);
+ for (i = 0; i < NAT_SIZE; i++)
+ for (natp = &nat_table[0][i]; (nat = *natp); ) {
+ *natp = nat->nat_next;
+ if (!--nat->nat_use)
+ KFREE(nat);
+ }
+ for (i = 0; i < NAT_SIZE; i++)
+ for (natp = &nat_table[1][i]; (nat = *natp); ) {
+ *natp = nat->nat_next;
+ if (!--nat->nat_use)
+ KFREE(nat);
+ }
+
+ for (ipnp = &nat_list; (ipn = *ipnp); ) {
+ *ipnp = ipn->in_next;
+ KFREE(ipn);
+ }
+ MUTEX_EXIT(&ipf_nat);
+}
+
+
+/*
+ * Slowly expire held state for NAT entries. Timeouts are set in
+ * expectation of this being called twice per second.
+ */
+void ip_natexpire()
+{
+ register struct nat *nat, **natp;
+ register int i;
+
+ MUTEX_ENTER(&ipf_nat);
+ for (i = 0; i < NAT_SIZE; i++)
+ for (natp = &nat_table[0][i]; (nat = *natp); ) {
+ if (nat->nat_age > 0)
+ nat->nat_age--;
+ if (!nat->nat_use || !nat->nat_age) {
+ *natp = nat->nat_next;
+ if (nat->nat_use)
+ nat->nat_use--;
+ if (!nat->nat_use) {
+ KFREE(nat);
+ nat_stats.ns_expire++;
+ nat_inuse--;
+ }
+ } else
+ natp = &nat->nat_next;
+ }
+
+ for (i = 0; i < NAT_SIZE; i++)
+ for (natp = &nat_table[1][i]; (nat = *natp); ) {
+ if (nat->nat_age > 0)
+ nat->nat_age--;
+ if (!nat->nat_use || !nat->nat_age) {
+ *natp = nat->nat_next;
+ if (nat->nat_use)
+ nat->nat_use--;
+ if (!nat->nat_use) {
+ KFREE(nat);
+ nat_stats.ns_expire++;
+ nat_inuse--;
+ }
+ } else
+ natp = &nat->nat_next;
+ }
+ MUTEX_EXIT(&ipf_nat);
+}
--- /dev/null
+/*
+ * (C)opyright 1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ *
+ * @(#)ip_nat.h 1.3 1/12/96
+ */
+
+#ifndef __IP_NAT_H_
+#define __IP_NAT_H__
+
+#ifndef SOLARIS
+#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
+#endif
+
+#if defined(__STDC__) || defined(__GNUC__)
+#define SIOCADNAT _IOW('r', 80, struct ipnat)
+#define SIOCRMNAT _IOW('r', 81, struct ipnat)
+#define SIOCGNATS _IOR('r', 82, struct natstat)
+#else
+#define SIOCADNAT _IOW(r, 80, struct ipnat)
+#define SIOCRMNAT _IOW(r, 81, struct ipnat)
+#define SIOCGNATS _IOR(r, 82, struct natstat)
+#endif
+
+#define NAT_SIZE 367
+
+typedef struct nat {
+ struct nat *nat_next;
+ u_short nat_use;
+ short nat_age;
+ u_long nat_sumd;
+ struct in_addr nat_inip;
+ struct in_addr nat_outip;
+ u_short nat_inport;
+ u_short nat_outport;
+} nat_t;
+
+typedef struct ipnat {
+ struct ipnat *in_next;
+ void *in_ifp;
+ u_short in_flags;
+ u_short in_pnext;
+ u_short in_port[2];
+ struct in_addr in_in[2];
+ struct in_addr in_out[2];
+ struct in_addr in_nextip;
+ int in_space;
+ char in_ifname[IFNAMSIZ];
+} ipnat_t;
+
+#define in_pmin in_port[0]
+#define in_pmax in_port[1]
+#define in_nip in_nextip.s_addr
+#define in_inip in_in[0].s_addr
+#define in_inmsk in_in[1].s_addr
+#define in_outip in_out[0].s_addr
+#define in_outmsk in_out[1].s_addr
+
+#define IPN_CMPSIZ (sizeof(struct in_addr) * 4 + sizeof(u_short) * 2)
+
+typedef struct natstat {
+ u_long ns_mapped[2];
+ u_long ns_added;
+ u_long ns_expire;
+ u_long ns_inuse;
+ nat_t ***ns_table;
+ ipnat_t *ns_list;
+} natstat_t;
+
+#define IPN_ANY 0
+#define IPN_TCP 1
+#define IPN_UDP 2
+#define IPN_TCPUDP 3
+
+extern int nat_ioctl();
+extern nat_t *nat_lookupoutip(), *nat_lookupinip();
+extern void ip_natout(), ip_natin(), ip_natunload(), ip_natexpire();
+#endif /* __IP_NAT_H__ */
static void ip_mloopback
__P((struct ifnet *, struct mbuf *, struct sockaddr_in *));
#if defined(IPFILTER) || defined(IPFILTER_LKM)
-extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int));
+extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **));
#endif
/*
/*
* looks like most checking has been done now...do a filter check
*/
- if ((*fr_checkp)(ip, hlen, ifp, 1))
{
- error = EHOSTUNREACH;
- goto bad;
+ struct mbuf *m0 = m;
+ if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 1, &m0)) {
+ error = EHOSTUNREACH;
+ goto done;
+ } else
+ ip = mtod(m = m0, struct ip *);
}
#endif
sendit:
--- /dev/null
+/*
+ * (C)opyright 1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+#ifndef lint
+static char sccsid[] = "@(#)ip_state.c 1.3 1/12/96 (C) 1993-1995 Darren Reed";
+#endif
+
+#include <string.h>
+#ifndef linux
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#if !defined(__SVR4) && !defined(__svr4__)
+# include <sys/dir.h>
+# include <sys/mbuf.h>
+#else
+# include <sys/byteorder.h>
+# include <sys/dditypes.h>
+# include <sys/stream.h>
+# include <sys/kmem.h>
+#endif
+
+#include <net/if.h>
+#ifdef sun
+#include <net/af.h>
+#endif
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/tcpip.h>
+#include <netinet/ip_icmp.h>
+#include <syslog.h>
+#endif
+#include "ip_fil.h"
+#include "ip_state.h"
+#ifndef MIN
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+
+#define TCP_CLOSE (TH_FIN|TH_RST)
+
+ipstate_t *ips_table[IPSTATE_SIZE];
+int ips_num = 0;
+ips_stat_t ips_stats;
+#if SOLARIS
+extern kmutex_t ipf_state;
+# if !defined(_KERNEL)
+#define bcopy(a,b,c) memmove(b,a,c)
+# endif
+#endif
+
+
+ips_stat_t *fr_statetstats()
+{
+ ips_stats.iss_active = ips_num;
+ ips_stats.iss_table = ips_table;
+ return &ips_stats;
+}
+
+
+#define PAIRS(s1,d1,s2,d2) ((((s1) == (s2)) && ((d1) == (d2))) ||\
+ (((s1) == (d2)) && ((d1) == (s2))))
+#define IPPAIR(s1,d1,s2,d2) PAIRS((s1).s_addr, (d1).s_addr, \
+ (s2).s_addr, (d2).s_addr)
+
+/*
+ * Create a new ipstate structure and hang it off the hash table.
+ */
+int fr_addstate(ip, hlen, pass)
+ip_t *ip;
+int hlen;
+u_int pass;
+{
+ ipstate_t ips;
+ register ipstate_t *is = &ips;
+ register u_int hv;
+
+ if (ips_num == IPSTATE_MAX) {
+ ips_stats.iss_max++;
+ return -1;
+ }
+ /*
+ * Copy and calculate...
+ */
+ hv = (is->is_p = ip->ip_p);
+ hv += (is->is_src.s_addr = ip->ip_src.s_addr);
+ hv += (is->is_dst.s_addr = ip->ip_dst.s_addr);
+
+ switch (ip->ip_p)
+ {
+ case IPPROTO_ICMP :
+ {
+ struct icmp *ic = (struct icmp *)((char *)ip + hlen);
+
+ switch (ic->icmp_type)
+ {
+ case ICMP_ECHO :
+ is->is_icmp.ics_type = 0;
+ hv += (is->is_icmp.ics_id = ic->icmp_id);
+ hv += (is->is_icmp.ics_seq = ic->icmp_seq);
+ break;
+ case ICMP_TSTAMP :
+ case ICMP_IREQ :
+ case ICMP_MASKREQ :
+ is->is_icmp.ics_type = ic->icmp_type + 1;
+ break;
+ default :
+ return -1;
+ }
+ ips_stats.iss_icmp++;
+ is->is_age = 120;
+ break;
+ }
+ case IPPROTO_TCP :
+ {
+ register tcphdr_t *tcp = (tcphdr_t *)((char *)ip + hlen);
+
+ /*
+ * The endian of the ports doesn't matter, but the ack and
+ * sequence numbers do as we do mathematics on them later.
+ */
+ hv += (is->is_dport = tcp->th_dport);
+ hv += (is->is_sport = tcp->th_sport);
+ is->is_seq = ntohl(tcp->th_seq);
+ is->is_ack = ntohl(tcp->th_ack);
+ is->is_win = ntohs(tcp->th_win);
+ ips_stats.iss_tcp++;
+ /*
+ * If we're creating state for a starting connectoin, start the
+ * timer on it as we'll never see an error if it fails to
+ * connect.
+ */
+ if ((tcp->th_flags & (TH_SYN|TH_ACK)) == TH_SYN)
+ is->is_age = 120;
+ else
+ is->is_age = 0;
+ break;
+ }
+ case IPPROTO_UDP :
+ {
+ register tcphdr_t *tcp = (tcphdr_t *)((char *)ip + hlen);
+
+ hv += (is->is_dport = tcp->th_dport);
+ hv += (is->is_sport = tcp->th_sport);
+ ips_stats.iss_udp++;
+ is->is_age = 120;
+ break;
+ }
+ default :
+ return -1;
+ }
+
+ if (!(is = (ipstate_t *)KMALLOC(sizeof(*is)))) {
+ ips_stats.iss_nomem++;
+ return -1;
+ }
+ bcopy((char *)&ips, (char *)is, sizeof(*is));
+ hv %= IPSTATE_SIZE;
+ MUTEX_ENTER(&ipf_state);
+ is->is_next = ips_table[hv];
+ ips_table[hv] = is;
+ is->is_pass = pass;
+ ips_num++;
+ MUTEX_EXIT(&ipf_state);
+ return 0;
+}
+
+
+/*
+ * Check if a packet has a registered state.
+ */
+int fr_checkstate(ip, hlen)
+ip_t *ip;
+int hlen;
+{
+ register struct in_addr dst, src;
+ register ipstate_t *is, **isp;
+ register u_char pr;
+ struct icmp *ic;
+ tcphdr_t *tcp;
+ u_int hv;
+
+ tcp = (tcphdr_t *)((char *)ip + hlen);
+ ic = (struct icmp *)tcp;
+ hv = (pr = ip->ip_p);
+ hv += (src.s_addr = ip->ip_src.s_addr);
+ hv += (dst.s_addr = ip->ip_dst.s_addr);
+
+ /*
+ * Search the hash table for matching packet header info.
+ */
+ switch (ip->ip_p)
+ {
+ case IPPROTO_ICMP :
+ hv += ic->icmp_id;
+ hv += ic->icmp_seq;
+ hv %= IPSTATE_SIZE;
+ MUTEX_ENTER(&ipf_state);
+ for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_next)
+ if ((is->is_p == pr) &&
+ (ic->icmp_id == is->is_icmp.ics_id) &&
+ (ic->icmp_seq == is->is_icmp.ics_seq) &&
+ IPPAIR(src, dst, is->is_src, is->is_dst)) {
+ /*
+ * If we have type 0 stored, allow any icmp
+ * replies through.
+ */
+ if (is->is_icmp.ics_type &&
+ is->is_icmp.ics_type != ic->icmp_type)
+ continue;
+ is->is_age = 120;
+ ips_stats.iss_hits++;
+ MUTEX_EXIT(&ipf_state);
+ return is->is_pass;
+ }
+ MUTEX_EXIT(&ipf_state);
+ break;
+ case IPPROTO_TCP :
+ {
+ register u_short dport = tcp->th_dport, sport = tcp->th_sport;
+ register u_short win = ntohs(tcp->th_win);
+ tcp_seq seq, ack;
+
+ hv += dport;
+ hv += sport;
+ hv %= IPSTATE_SIZE;
+ MUTEX_ENTER(&ipf_state);
+ for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_next) {
+ register int dl, seqskew, ackskew;
+
+ if ((is->is_p == pr) &&
+ PAIRS(sport, dport, is->is_sport, is->is_dport) &&
+ IPPAIR(src, dst, is->is_src, is->is_dst)) {
+ dl = ip->ip_len - hlen - sizeof(tcphdr_t);
+ /*
+ * Find difference between last checked packet
+ * and this packet.
+ */
+ seq = ntohl(tcp->th_seq);
+ ack = ntohl(tcp->th_ack);
+ if (sport == is->is_sport) {
+ seqskew = seq - is->is_seq;
+ ackskew = ack - is->is_ack;
+ } else {
+ seqskew = ack - is->is_seq;
+ if (!is->is_ack) {
+ /*
+ * Must be a SYN-ACK in reply
+ * to a SYN. Set age timeout
+ * to 0 to stop deletion.
+ */
+ is->is_ack = seq;
+ is->is_age = 0;
+ }
+ ackskew = seq - is->is_ack;
+ }
+
+ /*
+ * Make skew values absolute
+ */
+ if (seqskew < 0)
+ seqskew = -seqskew;
+ if (ackskew < 0)
+ ackskew = -ackskew;
+ /*
+ * If the difference in sequence and ack
+ * numbers is within the window size of the
+ * connection, store these values and match
+ * the packet.
+ */
+ if ((seqskew <= win) && (ackskew <= win)) {
+ is->is_win = win;
+ if (sport == is->is_sport) {
+ is->is_seq = seq;
+ is->is_ack = ack;
+ } else {
+ is->is_seq = ack;
+ is->is_ack = seq;
+ }
+ ips_stats.iss_hits++;
+ /*
+ * Nearing end of connection, start
+ * timeout.
+ */
+#ifdef _KERNEL
+ if ((tcp->th_flags & TCP_CLOSE) &&
+ !is->is_age)
+ is->is_age = 120;
+ MUTEX_EXIT(&ipf_state);
+ return is->is_pass;
+#else
+ if (tcp->th_flags & TCP_CLOSE) {
+ int pass = is->is_pass;
+
+ *isp = is->is_next;
+ isp = &ips_table[hv];
+ KFREE(is);
+ return pass;
+ }
+ return is->is_pass;
+#endif
+ }
+ }
+ }
+ MUTEX_EXIT(&ipf_state);
+ break;
+ }
+ case IPPROTO_UDP :
+ {
+ register u_short dport = tcp->th_dport, sport = tcp->th_sport;
+
+ hv += dport;
+ hv += sport;
+ hv %= IPSTATE_SIZE;
+ /*
+ * Nothing else to match on but ports. and IP#'s
+ */
+ MUTEX_ENTER(&ipf_state);
+ for (is = ips_table[hv]; is; is = is->is_next)
+ if ((is->is_p == pr) &&
+ PAIRS(sport, dport, is->is_sport, is->is_dport) &&
+ IPPAIR(src, dst, is->is_src, is->is_dst)) {
+ ips_stats.iss_hits++;
+ is->is_age = 120;
+ MUTEX_EXIT(&ipf_state);
+ return is->is_pass;
+ }
+ MUTEX_EXIT(&ipf_state);
+ break;
+ }
+ default :
+ break;
+ }
+ ips_stats.iss_miss++;
+ return 0;
+}
+
+
+/*
+ * Free memory in use by all state info. kept.
+ */
+void fr_stateunload()
+{
+ register int i;
+ register ipstate_t *is, **isp;
+
+ MUTEX_ENTER(&ipf_state);
+ for (i = 0; i < IPSTATE_SIZE; i++)
+ for (isp = &ips_table[i]; (is = *isp); ) {
+ *isp = is->is_next;
+ KFREE(is);
+ }
+ MUTEX_EXIT(&ipf_state);
+}
+
+
+/*
+ * Slowly expire held state for thingslike UDP and ICMP. Timeouts are set
+ * in expectation of this being called twice per second.
+ */
+void fr_timeoutstate()
+{
+ register int i;
+ register ipstate_t *is, **isp;
+
+ MUTEX_ENTER(&ipf_state);
+ for (i = 0; i < IPSTATE_SIZE; i++)
+ for (isp = &ips_table[i]; (is = *isp); )
+ if (is->is_age && !--is->is_age) {
+ *isp = is->is_next;
+ if (is->is_p == IPPROTO_TCP)
+ ips_stats.iss_fin++;
+ else
+ ips_stats.iss_expire++;
+ KFREE(is);
+ ips_num--;
+ } else
+ isp = &is->is_next;
+ MUTEX_EXIT(&ipf_state);
+}
--- /dev/null
+/*
+ * (C)opyright 1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ *
+ * @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed
+ */
+#ifndef __IP_STATE_H__
+#define __IP_STATE_H__
+
+#define IPSTATE_SIZE 257
+#define IPSTATE_MAX 2048 /* Maximum number of states held */
+
+typedef struct udpstate {
+ u_short us_sport;
+ u_short us_dport;
+} udpstate_t;
+
+typedef struct icmpstate {
+ u_short ics_id;
+ u_short ics_seq;
+ u_char ics_type;
+} icmpstate_t;
+
+typedef struct tcpstate {
+ u_short ts_sport;
+ u_short ts_dport;
+ u_long ts_seq;
+ u_long ts_ack;
+ u_short ts_win;
+} tcpstate_t;
+
+typedef struct ipstate {
+ struct ipstate *is_next;
+ int is_age;
+ u_int is_pass;
+ struct in_addr is_src;
+ struct in_addr is_dst;
+ u_char is_p;
+ union {
+ icmpstate_t is_ics;
+ tcpstate_t is_ts;
+ udpstate_t is_us;
+ } is_ps;
+} ipstate_t;
+
+#define is_icmp is_ps.is_ics
+#define is_tcp is_ps.is_ts
+#define is_udp is_ps.is_us
+#define is_seq is_tcp.ts_seq
+#define is_ack is_tcp.ts_ack
+#define is_win is_tcp.ts_win
+#define is_sport is_tcp.ts_sport
+#define is_dport is_tcp.ts_dport
+
+#if defined(__STDC__) || defined(__GNUC__)
+#define SIOCGIPST _IOR('r', 75, struct ips_stat)
+#else
+#define SIOCGIPST _IOR(r, 75, struct ips_stat)
+#endif
+
+typedef struct ips_stat {
+ u_long iss_hits;
+ u_long iss_miss;
+ u_long iss_max;
+ u_long iss_tcp;
+ u_long iss_udp;
+ u_long iss_icmp;
+ u_long iss_nomem;
+ u_long iss_expire;
+ u_long iss_fin;
+ u_long iss_active;
+ ipstate_t **iss_table;
+} ips_stat_t;
+
+extern ips_stat_t *fr_statetstats();
+extern int fr_addstate(), fr_checkstate();
+extern void fr_timeoutstate();
+# ifdef _KERNEL
+extern void fr_stateunload();
+# endif
+#endif /* __IP_STATE_H__ */
PROG= ipftest
MAN= ipftest.1
-SRCS= ipt.c fil.c ipft_sn.c ipft_ef.c ipft_td.c ipft_pc.c ipft_tx.c misc.c parse.c opt.c
-.PATH: ${.CURDIR}/../../sbin/ipf ${.CURDIR}/../../sbin/ipfstat
-CFLAGS+=-DIPL_NAME=\"/dev/ipl\" -I${.CURDIR}/../../sbin/ipf
+SRCS= ipt.c fil.c ipft_sn.c ipft_ef.c ipft_td.c ipft_pc.c ipft_tx.c \
+ misc.c parse.c opt.c ip_frag.c ip_nat.c ip_state.c
+.PATH: ${.CURDIR}/../../sbin/ipf ${.CURDIR}/../../sbin/ipfstat ${.CURDIR}/../../sys/netinet
+CFLAGS+=-DIPL_NAME=\"/dev/ipl\" -I${.CURDIR}/../../sbin/ipf -I${.CURDIR}/../../sys/netinet
.include <bsd.prog.mk>
+++ /dev/null
-/*
- * (C)opyright 1993,1994,1995 by Darren Reed.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and due credit is given
- * to the original author and the contributors.
- */
-#ifndef lint
-static char sccsid[] = "@(#)fil.c 1.18 10/24/95 (C) 1993-1995 Darren Reed";
-#endif
-
-#ifndef linux
-# include <sys/errno.h>
-# include <sys/types.h>
-# include <sys/param.h>
-# include <sys/file.h>
-# include <sys/ioctl.h>
-# if defined(_KERNEL) || defined(KERNEL)
-# include <sys/systm.h>
-# endif
-# include <sys/uio.h>
-# if !defined(__SVR4) && !defined(__svr4__)
-# include <sys/dir.h>
-# include <sys/mbuf.h>
-# else
-# include <sys/byteorder.h>
-# include <sys/dditypes.h>
-# include <sys/stream.h>
-# endif
-# include <sys/protosw.h>
-# include <sys/socket.h>
-# include <net/if.h>
-# ifdef sun
-# include <net/af.h>
-# endif
-# include <net/route.h>
-# include <netinet/in.h>
-# include <netinet/in_systm.h>
-# include <netinet/ip.h>
-# include <netinet/ip_var.h>
-# include <netinet/tcp.h>
-# include <netinet/udp.h>
-# include <netinet/tcpip.h>
-# include <netinet/ip_icmp.h>
-#endif
-#include <netinet/ip_fil.h>
-#ifndef MIN
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#endif
-
-#ifndef _KERNEL
-#include "ipf.h"
-extern int opts;
-extern void debug(), verbose();
-
-#define FR_IFVERBOSE(ex,second,verb_pr) if (ex) { verbose verb_pr; second; }
-#define FR_IFDEBUG(ex,second,verb_pr) if (ex) { debug verb_pr; second; }
-#define FR_VERBOSE(verb_pr) verbose verb_pr
-#define FR_DEBUG(verb_pr) debug verb_pr
-#else
-#define FR_IFVERBOSE(ex,second,verb_pr) ;
-#define FR_IFDEBUG(ex,second,verb_pr) ;
-#define FR_VERBOSE(verb_pr)
-#define FR_DEBUG(verb_pr)
-
-extern int ipl_unreach, ipllog();
-#endif
-
-struct filterstats frstats[2] = {{0,0,0,0,0},{0,0,0,0,0}};
-struct frentry *filterin[2] = { NULL, NULL },
- *filterout[2] = { NULL, NULL };
-int fr_flags = 0, fr_active = 0;
-int fr_check();
-
-
-/*
- * bit values for identifying presence of individual IP options
- */
-struct optlist ipopts[20] = {
- { IPOPT_NOP, 0x000001 },
- { IPOPT_RR, 0x000002 },
- { IPOPT_ZSU, 0x000004 },
- { IPOPT_MTUP, 0x000008 },
- { IPOPT_MTUR, 0x000010 },
- { IPOPT_ENCODE, 0x000020 },
- { IPOPT_TS, 0x000040 },
- { IPOPT_TR, 0x000080 },
- { IPOPT_SECURITY, 0x000100 },
- { IPOPT_LSRR, 0x000200 },
- { IPOPT_E_SEC, 0x000400 },
- { IPOPT_CIPSO, 0x000800 },
- { IPOPT_SATID, 0x001000 },
- { IPOPT_SSRR, 0x002000 },
- { IPOPT_ADDEXT, 0x004000 },
- { IPOPT_VISA, 0x008000 },
- { IPOPT_IMITD, 0x010000 },
- { IPOPT_EIP, 0x020000 },
- { IPOPT_FINN, 0x040000 },
- { 0, 0x000000 }
-};
-
-/*
- * bit values for identifying presence of individual IP security options
- */
-struct optlist secopt[8] = {
- { IPSO_CLASS_RES4, 0x01 },
- { IPSO_CLASS_TOPS, 0x02 },
- { IPSO_CLASS_SECR, 0x04 },
- { IPSO_CLASS_RES3, 0x08 },
- { IPSO_CLASS_CONF, 0x10 },
- { IPSO_CLASS_UNCL, 0x20 },
- { IPSO_CLASS_RES2, 0x40 },
- { IPSO_CLASS_RES1, 0x80 }
-};
-
-
-/*
- * compact the IP header into a structure which contains just the info.
- * which is useful for comparing IP headers with.
- */
-struct fr_ip *fr_makefrip(hlen, ip)
-int hlen;
-ip_t *ip;
-{
- static struct fr_ip fi;
- struct optlist *op;
- u_short optmsk = 0, secmsk = 0, auth = 0;
- int i, mv, ol, off;
- u_char *s, opt;
-
- fi.fi_fl = 0;
- fi.fi_v = ip->ip_v;
- fi.fi_tos = ip->ip_tos;
- (*(((u_short *)&fi) + 1)) = (*(((u_short *)ip) + 4));
- (*(((u_long *)&fi) + 1)) = (*(((u_long *)ip) + 3));
- (*(((u_long *)&fi) + 2)) = (*(((u_long *)ip) + 4));
-
- if (hlen > sizeof(struct ip))
- fi.fi_fl |= FI_OPTIONS;
- off = (ip->ip_off & 0x1fff) << 3;
- if (ip->ip_off & 0x3fff)
- fi.fi_fl |= FI_FRAG;
- switch (ip->ip_p)
- {
- case IPPROTO_ICMP :
- if ((!IPMINLEN(ip, icmp) && !off) ||
- (off && off < sizeof(struct icmp)))
- fi.fi_fl |= FI_SHORT;
- break;
- case IPPROTO_TCP :
- fi.fi_fl |= FI_TCPUDP;
- if ((!IPMINLEN(ip, tcphdr) && !off) ||
- (off && off < sizeof(struct tcphdr)))
- fi.fi_fl |= FI_SHORT;
- break;
- case IPPROTO_UDP :
- fi.fi_fl |= FI_TCPUDP;
- if ((!IPMINLEN(ip, udphdr) && !off) ||
- (off && off < sizeof(struct udphdr)))
- fi.fi_fl |= FI_SHORT;
- break;
- default :
- break;
- }
-
- for (s = (u_char *)(ip + 1), hlen -= sizeof(*ip); hlen; ) {
- if (!(opt = *s))
- break;
- ol = (opt == IPOPT_NOP) ? 1 : (int)*(s+1);
- if (opt > 1 && (ol < 0 || ol > hlen))
- break;
- for (i = 9, mv = 4; mv >= 0; ) {
- op = ipopts + i;
- if (opt == (u_char)op->ol_val) {
- optmsk |= op->ol_bit;
- if (opt == IPOPT_SECURITY) {
- struct optlist *sp;
- u_char sec;
- int j, m;
-
- sec = *(s + 3); /* classification */
- for (j = 3, m = 2; m >= 0; ) {
- sp = secopt + j;
- if (sec == sp->ol_val) {
- secmsk |= sp->ol_bit;
- auth = *(s + 3);
- auth *= 256;
- auth += *(s + 4);
- break;
- }
- if (sec < sp->ol_val)
- j -= m--;
- else
- j += m--;
- }
- }
- break;
- }
- if (opt < op->ol_val)
- i -= mv--;
- else
- i += mv--;
- }
- hlen -= ol;
- s += ol;
- }
- if (auth && !(auth & 0x0100))
- auth &= 0xff00;
- fi.fi_optmsk = optmsk;
- fi.fi_secmsk = secmsk;
- fi.fi_auth = auth;
- return &fi;
-}
-
-
-/*
- * check an IP packet for TCP/UDP characteristics such as ports and flags.
- */
-int fr_tcpudpchk(ip, tcp, fr)
-ip_t *ip;
-tcphdr_t *tcp;
-struct frentry *fr;
-{
- register u_short po, tup;
- register char i;
- int err = 1;
-
- /*
- * Both ports should *always* be in the first fragment.
- * So far, I cannot find any cases where they can not be.
- *
- * compare destination ports
- */
- if ((i = (int)fr->fr_dcmp)) {
- po = ntohs(fr->fr_dport);
- tup = ntohs(tcp->th_dport);
- /*
- * Do opposite test to that required and
- * continue if that succeeds.
- */
- if (!--i && tup != po) /* EQUAL */
- err = 0;
- else if (!--i && tup == po) /* NOTEQUAL */
- err = 0;
- else if (!--i && tup >= po) /* LESSTHAN */
- err = 0;
- else if (!--i && tup <= po) /* GREATERTHAN */
- err = 0;
- else if (!--i && tup > po) /* LT or EQ */
- err = 0;
- else if (!--i && tup < po) /* GT or EQ */
- err = 0;
- else if (!--i && /* Out of range */
- (tup >= po && tup <= ntohs(fr->fr_dtop)))
- err = 0;
- else if (!--i && /* In range */
- (tup <= po || tup >= ntohs(fr->fr_dtop)))
- err = 0;
- }
- /*
- * compare source ports
- */
- if (err && (i = (int)fr->fr_scmp)) {
- po = ntohs(fr->fr_sport);
- tup = ntohs(tcp->th_sport);
- if (!--i && tup != po)
- err = 0;
- else if (!--i && tup == po)
- err = 0;
- else if (!--i && tup >= po)
- err = 0;
- else if (!--i && tup <= po)
- err = 0;
- else if (!--i && tup > po)
- err = 0;
- else if (!--i && tup < po)
- err = 0;
- else if (!--i && /* Out of range */
- (tup >= po && tup <= ntohs(fr->fr_stop)))
- err = 0;
- else if (!--i && /* In range */
- (tup <= po || tup >= ntohs(fr->fr_stop)))
- err = 0;
- }
-
- /*
- * If we don't have all the TCP/UDP header, then how can we
- * expect to do any sort of match on it ? If we were looking for
- * TCP flags, then NO match. If not, then match (which should
- * satisfy the "short" class too).
- */
- if (err)
- if (ip->ip_p == IPPROTO_TCP) {
- if (!IPMINLEN(ip, tcphdr))
- return !(fr->fr_tcpf);
- /*
- * Match the flags ? If not, abort this match.
- */
- if (fr->fr_tcpf &&
- fr->fr_tcpf != (tcp->th_flags & fr->fr_tcpfm)) {
- FR_DEBUG(("f. %#x & %#x != %#x\n",
- tcp->th_flags, fr->fr_tcpfm,
- fr->fr_tcpf));
- err = 0;
- }
- }
- else if (!IPMINLEN(ip, udphdr)) /* must be UDP */
- return 1;
- return err;
-}
-
-/*
- * Check the input/output list of rules for a match and result.
- * Could be per interface, but this gets real nasty when you don't have
- * kernel sauce.
- */
-int fr_scanlist(pass, ip, hlen, ifp, out, rule)
-int pass;
-ip_t *ip;
-int hlen, out;
-struct ifnet *ifp;
-u_short *rule;
-{
- register struct frentry *fr;
- register struct fr_ip *fi;
- tcphdr_t *tcp;
- int rulen;
-
- *rule = 1;
- tcp = (tcphdr_t *)((char *)ip + hlen);
- fr = (out) ? filterout[fr_active] : filterin[fr_active];
- fi = fr_makefrip(hlen, ip);
-
- for (rulen = 0; fr; fr = fr->fr_next, rulen++) {
- /*
- * In all checks below, a null (zero) value in the
- * filter struture is taken to mean a wildcard.
- *
- * check that we are working for the right interface
- */
-#ifdef _KERNEL
- if (fr->fr_ifa && fr->fr_ifa != ifp)
- continue;
-#else
- if (opts & (OPT_VERBOSE|OPT_DEBUG))
- printf("\n");
- FR_VERBOSE(("%c", (pass & FR_PASS) ? 'p' : 'b'));
- if (ifp && *fr->fr_ifname && strcasecmp(ifp->if_name,
- fr->fr_ifname))
- continue;
- FR_VERBOSE((":i"));
-#endif
- {
- register u_long *ld, *lm, *lip;
- register int i;
-
- lip = (u_long *)fi;
- lm = (u_long *)&fr->fr_mip;
- ld = (u_long *)&fr->fr_ip;
- i = ((lip[0] & lm[0]) != ld[0]);
- FR_IFDEBUG(i,continue,("0. %#08x & %#08x != %#08x\n",
- lip[0], lm[0], ld[0]));
- i |= ((lip[1] & lm[1]) != ld[1]);
- FR_IFDEBUG(i,continue,("1. %#08x & %#08x != %#08x\n",
- lip[1], lm[1], ld[1]));
- i |= ((lip[2] & lm[2]) != ld[2]);
- FR_IFDEBUG(i,continue,("2. %#08x & %#08x != %#08x\n",
- lip[2], lm[2], ld[2]));
- i |= ((lip[3] & lm[3]) != ld[3]);
- FR_IFDEBUG(i,continue,("3. %#08x & %#08x != %#08x\n",
- lip[3], lm[3], ld[3]));
- i |= ((lip[4] & lm[4]) != ld[4]);
- FR_IFDEBUG(i,continue,("4. %#08x & %#08x != %#08x\n",
- lip[4], lm[4], ld[4]));
- if (i)
- continue;
- }
-
- /*
- * If a fragment, then only the first has what we're looking
- * for here...
- */
- if (!(ip->ip_off & 0x1fff)) {
- if ((fi->fi_fl & FI_TCPUDP) &&
- !fr_tcpudpchk(ip, tcp, fr))
- continue;
- else if (ip->ip_p == IPPROTO_ICMP &&
- (*(u_short *)((char *)ip + hlen) &
- fr->fr_icmpm) != fr->fr_icmp) {
- FR_DEBUG(("i. %#x & %#x != %#x\n",
- *(u_short *)((char *)ip + hlen),
- fr->fr_icmpm, fr->fr_icmp));
- continue;
- }
- } else if (fr->fr_dcmp || fr->fr_scmp || fr->fr_icmpm ||
- fr->fr_tcpfm)
- continue;
- FR_VERBOSE(("*"));
- /*
- * Just log this packet...
- */
- if (fr->fr_flags & FR_LOG) {
-#ifdef IPFILTER_LOG
- if (!ipllog(hlen, fr->fr_flags, ip, ifp, *rule))
- frstats[out].fr_skip++;
- frstats[out].fr_pkl++;
-#endif /* IPFILTER_LOG */
- } else
- pass = fr->fr_flags;
- FR_DEBUG(("pass %#x\n", pass));
- fr->fr_hits++;
- *rule = rulen;
- if (pass & FR_QUICK)
- break;
- }
- return pass;
-}
-
-
-/*
- * frcheck - filter check
- * check using source and destination addresses/pors in a packet whether
- * or not to pass it on or not.
- */
-int fr_check(ip, hlen, ifp, out
-#if SOLARIS && defined(_KERNEL)
-, qif, q)
-qif_t *qif;
-queue_t *q;
-#else
-)
-#endif
-ip_t *ip;
-int hlen;
-struct ifnet *ifp;
-int out;
-{
- int pass = FR_NOMATCH;
- int sl;
- u_short rule;
-
- SPLNET(sl);
-
- pass = fr_scanlist(pass, ip, hlen, ifp, out, &rule);
- if (pass == FR_NOMATCH) {
- frstats[out].fr_nom++;
-#ifdef NOMATCH
- pass |= NOMATCH;
-#endif
- }
-
-#ifdef IPFILTER_LOG
- if ((pass & FR_LOGP) ||
- ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) {
- if (!(pass & FR_LOGP))
- pass |= FF_LOGPASS << 8;
- if (!ipllog(hlen, pass, ip, ifp, rule))
- frstats[out].fr_skip++;
- frstats[out].fr_ppkl++;
- } else if ((pass & FR_LOGB) ||
- ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) {
- if (!(pass & FR_LOGB))
- pass |= FF_LOGBLOCK << 8;
- if (!ipllog(hlen, pass, ip, ifp, rule))
- frstats[out].fr_skip++;
- frstats[out].fr_bpkl++;
- }
-#endif /* IPFILTER_LOG */
- SPLX(sl);
- if (pass & FR_PASS)
- frstats[out].fr_pass++;
- else if (pass & FR_BLOCK) {
- frstats[out].fr_block++;
- /*
- * Should we return an ICMP packet to indicate error
- * status passing through the packet filter ?
- * XXX - copy mbuf as icmp_error() calls mfree() - fix this
- * later, but preserve backward compatibility for now.
- */
-#ifdef _KERNEL
- if (pass & FR_RETICMP) {
-# if SOLARIS
- icmp_error(q, ip, ICMP_UNREACH, ipl_unreach, qif,
- ip->ip_src);
-# else
- struct mbuf *copy;
-
- copy = m_copy(dtom(ip), 0, imin((int)ip->ip_len, 64));
-# if BSD < 199103
- icmp_error(mtod(copy, struct ip *),
- ICMP_UNREACH, ipl_unreach, ifp, ip->ip_src);
-# else
- icmp_error(copy, ICMP_UNREACH, ipl_unreach,
- ip->ip_src.s_addr, ifp);
-# endif
-# endif
- frstats[0].fr_ret++;
- } else if (pass & FR_RETRST && IPMINLEN(ip, tcphdr)) {
-# if SOLARIS
- if (send_reset(ip, qif, q) == 0)
-# else
- if (send_reset(ip) == 0)
-# endif
- frstats[1].fr_ret++;
- }
-#else
- if (pass & FR_RETICMP) {
- verbose("- ICMP unreachable sent\n");
- frstats[0].fr_ret++;
- } else if (pass & FR_RETRST && IPMINLEN(ip, tcphdr)) {
- verbose("- TCP RST sent\n");
- frstats[1].fr_ret++;
- }
-#endif
- }
-#ifdef _KERNEL
- return (pass & FR_PASS) ? 0 : -1;
-#else
- if (pass & FR_NOMATCH)
- return 1;
- if (pass & FR_PASS)
- return 0;
- return -1;
-#endif
-}
-
-
-#ifndef _KERNEL
-int ipllog()
-{
- verbose("l");
- return 1;
-}
-#endif
#include <netinet/tcpip.h>
#include <net/if.h>
#include <netdb.h>
-#include <netinet/ip_fil.h>
+#include "ip_fil.h"
#include "ipf.h"
#include "ipt.h"
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <net/if.h>
-#include <netinet/ip_fil.h>
+#include "ip_fil.h"
#include "ipf.h"
#include "ipt.h"
#include "pcap.h"
}
+#ifdef notyet
/*
* read an entire pcap packet record. only the data part is copied into
* the available buffer, with the number of bytes copied returned.
bcopy(bufp, buf, n);
return n;
}
+#endif
/*
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <net/if.h>
-#include <netinet/ip_fil.h>
+#include "ip_fil.h"
#include "ipf.h"
#include "ipt.h"
#include "snoop.h"
}
+#ifdef notyet
/*
* read an entire snoop packet record. only the data part is copied into
* the available buffer, with the number of bytes copied returned.
bcopy(bufp, buf, n);
return n;
}
+#endif
/*
#include <netinet/tcpip.h>
#include <net/if.h>
#include <netdb.h>
-#include <netinet/ip_fil.h>
+#include "ip_fil.h"
#include "ipf.h"
#include "ipt.h"
#ifndef lint
-static char sccsid[] = "@(#)ipft_td.c 1.6 10/15/95 (C)1995 Darren Reed";
+static char sccsid[] = "@(#)ipft_td.c 1.7 1/12/96 (C)1995 Darren Reed";
#endif
static int tcpd_open(), tcpd_close(), tcpd_readip();
#ifdef NEED_INET_ATON
-static u_long inet_aton();
+extern u_long inet_aton();
#else
#include <arpa/inet.h>
#endif
* to the original author and the contributors.
*/
#include <stdio.h>
+#include <ctype.h>
#include <assert.h>
#include <string.h>
#if !defined(__SVR4) && !defined(__svr4__)
#include <netinet/ip_icmp.h>
#include <netinet/tcpip.h>
#include <net/if.h>
-#include <netinet/ip_fil.h>
+#include "ip_fil.h"
#include <netdb.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include "ipt.h"
#ifndef lint
-static char sccsid[] = "@(#)ipft_tx.c 1.2 10/17/95 (C) 1993 Darren Reed";
+static char sccsid[] = "@(#)ipft_tx.c 1.5 1/12/96 (C) 1993 Darren Reed";
#endif
extern int opts;
+extern u_short portnum();
+extern u_long buildopts();
static int text_open(), text_close(), text_readip(), parseline();
tcphdr_t th, *tcp = &th;
struct icmp icmp, *ic = &icmp;
char *cps[20], **cpp, c, opts[68];
- int i;
+ int i, r;
bzero((char *)ip, MAX(sizeof(*tcp), sizeof(*ic)) + sizeof(*ip));
bzero((char *)tcp, sizeof(*tcp));
*last++ = '\0';
tcp->th_sport = portnum(last);
}
- ip->ip_src.s_addr = hostnum(*cpp);
+ ip->ip_src.s_addr = hostnum(*cpp, &r);
cpp++;
if (!*cpp)
return 1;
*last++ = '\0';
tcp->th_dport = portnum(last);
}
- ip->ip_dst.s_addr = hostnum(*cpp);
+ ip->ip_dst.s_addr = hostnum(*cpp, &r);
cpp++;
if (*cpp && ip->ip_p == IPPROTO_TCP) {
extern char flagset[];
/*
- * (C)opyright 1993,1994,1995 by Darren Reed.
+ * (C)opyright 1993-1996 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
#include <netinet/ip_icmp.h>
#include <netinet/tcpip.h>
#include <net/if.h>
-#include <netinet/ip_fil.h>
+#include "ip_fil.h"
#include <netdb.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <ctype.h>
#ifndef lint
-static char sccsid[] = "@(#)ipt.c 1.13 11/11/95 (C) 1993 Darren Reed";
+static char sccsid[] = "@(#)ipt.c 1.15 1/7/96 (C) 1993-1996 Darren Reed";
#endif
extern int fr_check();
extern char *optarg;
-extern struct frentry *filterin[], *filterout[];
+extern struct frentry *ipfilter[2][2];
extern struct ipread snoop, etherf, tcpd, pcap, iptext;
extern void debug(), verbose();
f = (struct frentry *)malloc(sizeof(*f));
if (fr->fr_flags & FR_INQUE) {
if (!ft_in)
- ft_in = filterin[0] = f;
+ ft_in = ipfilter[0][0] = f;
else
ft_in->fr_next = f, ft_in = f;
} else if (fr->fr_flags & FR_OUTQUE) {
if (!ft_out)
- ft_out = filterout[0] = f;
+ ft_out = ipfilter[1][0] = f;
else
ft_out->fr_next = f, ft_out = f;
}
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip_var.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/tcpip.h>
#include <net/if.h>
-#include <netinet/ip_fil.h>
+#include "ip_fil.h"
#include <netdb.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include "ipt.h"
#ifndef lint
-static char sccsid[] = "@(#)misc.c 1.1 10/15/95 (C) 1995 Darren Reed";
+static char sccsid[] = "@(#)misc.c 1.2 1/12/96 (C) 1995 Darren Reed";
#endif
void debug(), verbose();
PROG= ipmon
MAN= ipmon.8
-CFLAGS+=-DIPL_NAME=\"/dev/ipl\" -DLOGFAC=LOG_LOCAL0
+CFLAGS+=-DIPL_NAME=\"/dev/ipl\" -DLOGFAC=LOG_LOCAL0 \
+ -I${.CURDIR}/../../sys/netinet
.include <bsd.prog.mk>
#include <arpa/inet.h>
#ifndef lint
-static char sccsid[] = "@(#)ipmon.c 1.13 11/11/95 (C)1995 Darren Reed";
+static char sccsid[] = "@(#)ipmon.c 1.16 1/12/96 (C)1995 Darren Reed";
#endif
-#include <netinet/ip_fil.h>
+#include "ip_fil.h"
struct flags {
int value;
tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900);
t += strlen(t);
}
- (void) sprintf(t, "%02d:%02d:%02d.%-.6d %c%c%d @%d ",
+ (void) sprintf(t, "%02d:%02d:%02d.%-.6ld %c%c%ld @%hd ",
tm->tm_hour, tm->tm_min, tm->tm_sec, lp->usec,
lp->ifname[0], lp->ifname[1], lp->unit, lp->rule);
pr = getprotobynumber((int)p);
} else
proto = pr->p_name;
- if (lp->flags & (FI_SHORT << 16)) {
+ if (lp->flags & (FI_SHORT << 20)) {
c[0] = 'S';
lvl = LOG_ERR;
} else if (lp->flags & FR_PASS) {
else
c[0] = 'B';
lvl = LOG_WARNING;
+ } else if (lp->flags & FF_LOGNOMATCH) {
+ c[0] = 'n';
+ lvl = LOG_NOTICE;
} else {
c[0] = 'L';
lvl = LOG_INFO;
c[2] = '\0';
(void) strcat(line, c);
t = line + strlen(line);
+#if SOLARIS
+ ip->ip_off = ntohs(ip->ip_off);
+ ip->ip_len = ntohs(ip->ip_len);
+#endif
if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !(ip->ip_off & 0x1fff)) {
tp = (struct tcphdr *)((char *)ip + hl);
hostname(res, ip->ip_src),
portname(res, proto, tp->th_sport));
t += strlen(t);
- (void) sprintf(t, "%s,%s PR %s len %hu (%hu) ",
+ (void) sprintf(t, "%s,%s PR %s len %hu %hu ",
hostname(res, ip->ip_dst),
portname(res, proto, tp->th_dport),
proto, hl, ip->ip_len);
t += strlen(t);
- if (p == IPPROTO_TCP)
+ if (p == IPPROTO_TCP) {
+ *t++ = '-';
for (i = 0; tcpfl[i].value; i++)
if (tp->th_flags & tcpfl[i].value)
*t++ = tcpfl[i].flag;
+ }
*t = '\0';
} else {
(void) sprintf(t, "%s -> ", hostname(res, ip->ip_src));
t += strlen(t);
- (void) sprintf(t, "%s PR %s len %hu (%hu)",
+ (void) sprintf(t, "%s PR %s len %hu %hu",
hostname(res, ip->ip_dst), proto,
hl, ip->ip_len);
}
hostname(res, ipc->ip_src),
portname(res, proto, tp->th_sport));
t += strlen(t);
- (void) sprintf(t, " %s,%s PR %s len %hu (%hu)",
+ (void) sprintf(t, " %s,%s PR %s len %hu %hu",
hostname(res, ipc->ip_dst),
portname(res, proto, tp->th_dport),
proto, ipc->ip_hl << 2, ipc->ip_len);
hostname(res, ip->ip_dst), proto, hl, ip->ip_len);
t += strlen(t);
if (ip->ip_off & 0x1fff)
- (void) sprintf(t, " frag %s%hu@%hu",
+ (void) sprintf(t, " frag %s%s%hu@%hu",
ip->ip_off & IP_MF ? "+" : "",
+ ip->ip_off & IP_DF ? "-" : "",
ip->ip_len - hl, (ip->ip_off & 0x1fff) << 3);
}
t += strlen(t);
switch (c)
{
case 'f' :
- (void) ioctl(fd, SIOCIPFFB, &flushed);
+ if (ioctl(fd, SIOCIPFFB, &flushed) == 0) {
+ printf("%d bytes flushed from log buffer\n",
+ flushed);
+ fflush(stdout);
+ }
break;
case 'N' :
opts |= 2;
NOMAN=
SRCS= iptests.c ip.c ipsend.c ipsopt.c resend.c sbpf.c sock.c 44arp.c ipft_sn.c ipft_pc.c
.PATH: ${.CURDIR}/../../usr.sbin/ipftest
-CFLAGS+= -DDOSOCKET -I${.CURDIR}/../../usr.sbin/ipftest -I${.CURDIR}/../../sbin/ipf
+CFLAGS+= -DDOSOCKET -I${.CURDIR}/../../usr.sbin/ipftest -I${.CURDIR}/../../sbin/ipf -I${.CURDIR}/../../sys/netinet
LDADD+= -lpcap