This commit was generated by cvs2svn to compensate for changes in r22514,

which included commits to RCS files with non-trunk default branches.
This commit is contained in:
Darren Reed 1997-02-09 22:50:16 +00:00
commit d67150e941
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=22515
189 changed files with 28807 additions and 0 deletions

64
contrib/ipfilter/BNF Normal file
View File

@ -0,0 +1,64 @@
filter-rule = [ insert ] action in-out [ options ] [ tos ] [ ttl ]
[ proto ] [ ip ] .
insert = "@" decnumber .
action = block | "pass" | log | "count" | call .
in-out = "in" | "out" .
options = [ log ] [ "quick" ] [ "on" interface-name [ dup ] [ froute ] ] .
tos = "tos" decnumber | "tos" hexnumber .
ttl = "ttl" decnumber .
proto = "proto" protocol .
ip = srcdst [ flags ] [ with withopt ] [ icmp ] [ keep ] .
block = "block" [ "return-icmp"[return-code] | "return-rst" ] .
log = "log" [ "body" ] [ "first" ] [ "or-block" ] .
call = "call" [ "now" ] function-name .
dup = "dup-to" interface-name[":"ipaddr] .
froute = "fastroute" | "to" interface-name .
protocol = "tcp/udp" | "udp" | "tcp" | "icmp" | decnumber .
srcdst = "all" | fromto .
fromto = "from" object "to" object .
object = addr [ port-comp | port-range ] .
addr = "any" | nummask | host-name [ "mask" ipaddr | "mask" hexnumber ] .
port-comp = "port" compare port-num .
port-range = "port" port-num range port-num .
flags = "flags" flag { flag } [ "/" flag { flag } ] .
with = "with" | "and" .
icmp = "icmp-type" icmp-type [ "code" decnumber ] .
return-code = "("icmp-code")" .
keep = "keep" "state" | "keep" "frags" .
nummask = host-name [ "/" decnumber ] .
host-name = ipaddr | hostname | "any" .
ipaddr = host-num "." host-num "." host-num "." host-num .
host-num = digit [ digit [ digit ] ] .
port-num = service-name | decnumber .
withopt = [ "not" | "no" ] opttype [ withopt ] .
opttype = "ipopts" | "short" | "frag" | "opt" ipopts .
optname = ipopts [ "," optname ] .
ipopts = optlist | "sec-class" [ secname ] .
secname = seclvl [ "," secname ] .
seclvl = "unclass" | "confid" | "reserv-1" | "reserv-2" | "reserv-3" |
"reserv-4" | "secret" | "topsecret" .
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" .
optlist = "nop" | "rr" | "zsu" | "mtup" | "mtur" | "encode" | "ts" | "tr" |
"sec" | "lsrr" | "e-sec" | "cipso" | "satid" | "ssrr" | "addext" |
"visa" | "imitd" | "eip" | "finn" .
hexnumber = "0" "x" hexstring .
hexstring = hexdigit [ hexstring ] .
decnumber = digit [ decnumber ] .
compare = "=" | "!=" | "<" | ">" | "<=" | ">=" | "eq" | "ne" | "lt" | "gt" |
"le" | "ge" .
range = "<>" | "><" .
hexdigit = digit | "a" | "b" | "c" | "d" | "e" | "f" .
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" .
flag = "F" | "S" | "R" | "P" | "A" | "U" .

View File

@ -0,0 +1,11 @@
If you get the following error whilst compiling:
In file included from /usr/local/lib/gcc-lib/sparc-sun-solaris2.3/2.6.3/include/sys/user.h:48,
from /usr/include/sys/file.h:15,
from ../ip_nat.c:15:
/usr/include/sys/psw.h:19: #error Kernel include of psw.h
Remove (comment out) the line in
/usr/local/lib/gcc-lib/sparc-sun-solaris2.3/2.6.3include/sys/user.h
which includes psw.h

View File

@ -0,0 +1,16 @@
There are two patch files in this directory, each allowing for the Firewall
Toolkit to be used in a transparent proxy configuration.
ftp-gw.diff - A patch written by myself for use only with IP Filter and
ftp-gw from the Firewall Toolkit.
fwtkp - A set of patches written by James B. Croall (jcroall@foo.org)
for use with both IP Filter and ipfwadm (for Linux) and more
of the various FWTK gateway plugins, including:
ftp-gw http-gw plug-gw rlogin-gw tn-gw
Both patches when applied to the Firewall toolkit require the same
configuration for IP Filter.
Darren

View File

@ -0,0 +1,237 @@
*** ftp-gw.c.orig Sat Nov 5 10:30:16 1994
--- ftp-gw.c Sun Jul 7 12:25:15 1996
***************
*** 11,31 ****
*/
static char RcsId[] = "$Header: /devel/CVS/IP-Filter/FWTK/ftp-gw.diff,v 2.0.1.1 1997/01/09 15:14:46 darrenr Exp $";
#include <stdio.h>
#include <ctype.h>
#include <syslog.h>
#include <sys/signal.h>
#include <sys/ioctl.h>
#include <sys/errno.h>
- extern int errno;
- extern char *sys_errlist[];
#include <arpa/ftp.h>
#include <arpa/telnet.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
extern char *rindex();
extern char *index();
--- 11,37 ----
*/
static char RcsId[] = "$Header: /devel/CVS/IP-Filter/FWTK/ftp-gw.diff,v 2.0.1.1 1997/01/09 15:14:46 darrenr Exp $";
+ /*
+ * Patches for IP Filter NAT extensions written by Darren Reed, 7/7/96
+ * darrenr@cyber.com.au
+ */
+ static char vIpFilter[] = "v3.1.0";
#include <stdio.h>
#include <ctype.h>
#include <syslog.h>
+ #include <unistd.h>
+ #include <fcntl.h>
#include <sys/signal.h>
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <arpa/ftp.h>
#include <arpa/telnet.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
+ #include <net/if.h>
extern char *rindex();
extern char *index();
***************
*** 36,41 ****
--- 42,48 ----
#include "firewall.h"
+ #include "ip_nat.h"
#ifndef BSIZ
#define BSIZ 2048
***************
*** 83,88 ****
--- 90,97 ----
static int cmd_noop();
static int cmd_abor();
static int cmd_passthru();
+ static int nat_destination();
+ static int connectdest();
static void saveline();
static void flushsaved();
static void trap_sigurg();
***************
*** 317,323 ****
if(authallflg)
if(say(0,"220-Proxy first requires authentication"))
exit(1);
! sprintf(xuf,"220 %s FTP proxy (Version %s) ready.",huf,FWTK_VERSION_MINOR);
if(say(0,xuf))
exit(1);
}
--- 326,335 ----
if(authallflg)
if(say(0,"220-Proxy first requires authentication"))
exit(1);
! sprintf(xuf,"220-%s FTP proxy (Version %s) ready.",huf,FWTK_VERSION_MINOR);
! if(say(0,xuf))
! exit(1);
! sprintf(xuf,"220-%s TIS ftp-gw with IP Filter %s NAT extensions",huf,vIpFilter);
if(say(0,xuf))
exit(1);
}
***************
*** 338,343 ****
--- 350,357 ----
exit(1);
}
+ nat_destination(0);
+
/* main loop */
while(1) {
FD_ZERO(&rdy);
***************
*** 608,619 ****
static char narg[] = "501 Missing or extra username";
static char noad[] = "501 Use user@site to connect via proxy";
char buf[1024];
- char mbuf[512];
char *p;
char *dest;
char *user;
int x;
- int msg_int;
short port = FTPPORT;
/* kludgy but effective. if authorizing everything call auth instead */
--- 622,631 ----
***************
*** 643,648 ****
--- 655,681 ----
return(sayn(0,noad,sizeof(noad)));
}
+ if((rfd == -1) && (x = connectdest(dest,port)))
+ return x;
+ sprintf(buf,"USER %s",user);
+ if(say(rfd,buf))
+ return(1);
+ x = getresp(rfd,buf,sizeof(buf),1);
+ if(sendsaved(0,x))
+ return(1);
+ return(say(0,buf));
+ }
+
+ static int
+ connectdest(dest,port)
+ char *dest;
+ short port;
+ {
+ char buf[1024];
+ char mbuf[512];
+ int msg_int;
+ int x;
+
if(*dest == '\0')
dest = "localhost";
***************
*** 685,691 ****
char ebuf[512];
strcpy(ebuf,buf);
! sprintf(buf,"521 %s: %s",dest,ebuf);
return(say(0,buf));
}
sprintf(buf,"----GATEWAY CONNECTED TO %s----",dest);
--- 718,724 ----
char ebuf[512];
strcpy(ebuf,buf);
! sprintf(buf,"521 %s,%d: %s",dest,ntohs(port),ebuf);
return(say(0,buf));
}
sprintf(buf,"----GATEWAY CONNECTED TO %s----",dest);
***************
*** 698,711 ****
return(say(0,buf));
}
saveline(buf);
!
! sprintf(buf,"USER %s",user);
! if(say(rfd,buf))
! return(1);
! x = getresp(rfd,buf,sizeof(buf),1);
! if(sendsaved(0,x))
! return(1);
! return(say(0,buf));
}
--- 731,738 ----
return(say(0,buf));
}
saveline(buf);
! sendsaved(0,-1);
! return 0;
}
***************
*** 1591,1593 ****
--- 1618,1659 ----
dup(nread);
}
#endif
+
+
+ static int
+ nat_destination(fd)
+ int fd;
+ {
+ struct sockaddr_in laddr, faddr;
+ struct natlookup natlookup;
+ char *dest;
+ int slen, natfd;
+
+ bzero((char *)&laddr, sizeof(laddr));
+ bzero((char *)&faddr, sizeof(faddr));
+ slen = sizeof(laddr);
+ if(getsockname(fd,(struct sockaddr *)&laddr,&slen) < 0) {
+ perror("getsockname");
+ exit(1);
+ }
+ slen = sizeof(faddr);
+ if(getpeername(fd,(struct sockaddr *)&faddr,&slen) < 0) {
+ perror("getsockname");
+ exit(1);
+ }
+
+ natlookup.nl_inport = laddr.sin_port;
+ natlookup.nl_outport = faddr.sin_port;
+ natlookup.nl_inip = laddr.sin_addr;
+ natlookup.nl_outip = faddr.sin_addr;
+ if((natfd = open("/dev/ipl", O_RDONLY)) < 0) {
+ perror("open");
+ exit(1);
+ }
+ if(ioctl(natfd, SIOCGNATL, &natlookup) == -1) {
+ perror("ioctl");
+ exit(1);
+ }
+ close(natfd);
+ return connectdest(inet_ntoa(natlookup.nl_inip),ntohs(natlookup.nl_inport));
+ }

812
contrib/ipfilter/FWTK/fwtkp Normal file
View File

@ -0,0 +1,812 @@
diff -c -r ./ftp-gw/ftp-gw.c ../../NEW/fwtk/ftp-gw/ftp-gw.c
*** ./ftp-gw/ftp-gw.c Fri Sep 6 12:55:05 1996
--- ../../NEW/fwtk/ftp-gw/ftp-gw.c Wed Oct 9 02:51:35 1996
***************
*** 40,47 ****
extern char *optarg;
! #include "firewall.h"
#ifndef BSIZ
#define BSIZ 2048
--- 40,48 ----
extern char *optarg;
! char *getdsthost();
+ #include "firewall.h"
#ifndef BSIZ
#define BSIZ 2048
***************
*** 84,89 ****
--- 85,92 ----
static int cmdcnt = 0;
static int timeout = PROXY_TIMEOUT;
+ static int do_transparent=0;
+
static int cmd_user();
static int cmd_authorize();
***************
*** 98,103 ****
--- 101,107 ----
static void saveline();
static void flushsaved();
static void trap_sigurg();
+ static int connectdest();
#define OP_CONN 001 /* only valid if connected */
#define OP_WCON 002 /* writethrough if connected */
***************
*** 170,175 ****
--- 174,180 ----
char xuf[1024];
char huf[128];
char *passuser = (char *)0; /* passed user as av */
+ char *psychic, *hotline;
#ifndef LOG_DAEMON
openlog("ftp-gw",LOG_PID);
***************
*** 314,319 ****
--- 319,326 ----
} else
timeout = 60*60;
+ psychic=getdsthost(0,NULL);
+ if(psychic) { do_transparent++; }
/* display a welcome file or message */
if(passuser == (char *)0) {
***************
*** 322,327 ****
--- 329,340 ----
syslog(LLEV,"fwtkcfgerr: welcome-msg must have one parameter, line %d",cf->ln);
exit(1);
}
+ if(do_transparent) {
+ if(sayfile2(0,cf->argv[0],220)) {
+ syslog(LLEV,"fwtksyserr: cannot display welcome %s: %m",cf->argv[0]);
+ exit(1);
+ }
+ } else
if(sayfile(0,cf->argv[0],220)) {
syslog(LLEV,"fwtksyserr: cannot display welcome %s: %m",cf->argv[0]);
exit(1);
***************
*** 332,338 ****
if(authallflg)
if(say(0,"220-Proxy first requires authentication"))
exit(1);
! sprintf(xuf,"220 %s FTP proxy (Version %s) ready.",huf,FWTK_VERSION_MINOR);
if(say(0,xuf))
exit(1);
}
--- 345,357 ----
if(authallflg)
if(say(0,"220-Proxy first requires authentication"))
exit(1);
! /* foo */
! if(do_transparent)
! sprintf(xuf,"220-%s FTP proxy (Version %s) ready.",huf,FWTK_VERSION_MINOR);
! else
! sprintf(xuf,"220 %s FTP Proxy (Version %s) ready.",huf,FWTK_VERSION_MINOR);
! /* foo */
!
if(say(0,xuf))
exit(1);
}
***************
*** 353,358 ****
--- 372,381 ----
exit(1);
}
+ if(do_transparent) {
+ connectdest(psychic,21);
+ }
+
/* main loop */
while(1) {
FD_ZERO(&rdy);
***************
*** 676,681 ****
--- 699,713 ----
return(sayn(0,noad,sizeof(noad)-1));
}
+ if(do_transparent) {
+ if((rfd==(-1)) && (x=connectdest(dest,port))) return x;
+ sprintf(buf,"USER %s",user);
+ if(say(rfd,buf)) return(1);
+ x=getresp(rfd,buf,sizeof(buf),1);
+ if(sendsaved(0,x)) return(1);
+ return(say(0,buf));
+ }
+
if(*dest == '\0')
dest = "localhost";
***************
*** 701,708 ****
if(msg_int == 1) {
sprintf(mbuf,"Permission denied for user %s to connect to %s",authuser,dest);
syslog(LLEV,"deny host=%s/%s connect to %s user=%s",rladdr,riaddr,dest,authuser);
! say(0,mbuf);
! return(1);
} else {
if(msg_int == -1) {
sprintf(mbuf,"No match in netperm-table for %s to ftp to %s",authuser,dest);
--- 733,740 ----
if(msg_int == 1) {
sprintf(mbuf,"Permission denied for user %s to connect to %s",authuser,dest);
syslog(LLEV,"deny host=%s/%s connect to %s user=%s",rladdr,riaddr,dest,authuser);
! say(0,mbuf);
! return(1);
} else {
if(msg_int == -1) {
sprintf(mbuf,"No match in netperm-table for %s to ftp to %s",authuser,dest);
***************
*** 717,723 ****
char ebuf[512];
strcpy(ebuf,buf);
! sprintf(buf,"521 %s: %s",dest,ebuf);
rfd = -1;
return(say(0,buf));
}
--- 749,759 ----
char ebuf[512];
strcpy(ebuf,buf);
! if(do_transparent) {
! sprintf(buf,"521 %s,%d: %s",dest,ntohs(port),ebuf);
! } else {
! sprintf(buf,"521 %s: %s",dest,ebuf);
! }
rfd = -1;
return(say(0,buf));
}
***************
*** 732,737 ****
--- 768,778 ----
}
saveline(buf);
+ /* if(do_transparent) {
+ sendsaved(0,-1);
+ return(0);
+ } /* EEEk. I can't remember what this does. */
+
sprintf(buf,"USER %s",user);
if(say(rfd,buf))
return(1);
***************
*** 744,749 ****
--- 785,860 ----
return 0;
}
+ static int connectdest(dest, port)
+ char *dest;
+ short port;
+ {
+ char buf[1024], mbuf[512];
+ int msg_int, x;
+
+ if(*dest == '\0')
+ dest = "localhost";
+
+ if(validests != (char **)0) {
+ char **xp;
+ int x;
+
+ for(xp = validests; *xp != (char *)0; xp++) {
+ if(**xp == '!' && hostmatch(*xp + 1,dest)) {
+ return(baddest(0,dest));
+ } else {
+ if(hostmatch(*xp,dest))
+ break;
+ }
+ }
+ if(*xp == (char *)0)
+ return(baddest(0,dest));
+ }
+
+ /* Extended permissions processing goes in here for destination */
+ if(extendperm) {
+ msg_int = auth_perm(confp, authuser, "ftp-gw", dest,(char *)0);
+ if(msg_int == 1) {
+ sprintf(mbuf,"Permission denied for user %s to connect to %s",authuser,dest);
+ syslog(LLEV,"deny host=%s/%s connect to %s user=%s",rladdr,riaddr,dest,authuser);
+ say(0,mbuf);
+ return(1);
+ } else {
+ if(msg_int == -1) {
+ sprintf(mbuf,"No match in netperm-table for %s to ftp to %s",authuser,dest);
+ say(0,mbuf);
+ return(1);
+ }
+ }
+ }
+
+ syslog(LLEV,"permit host=%s/%s connect to %s",rladdr,riaddr,dest);
+
+ if((rfd = conn_server(dest,port,0,buf)) < 0) {
+ char ebuf[512];
+
+ strcpy(ebuf,buf);
+ sprintf(buf,"521 %s: %s",dest,ebuf);
+ rfd = -1;
+ return(say(0,buf));
+ }
+ if(!do_transparent) {
+ sprintf(buf,"----GATEWAY CONNECTED TO %s----",dest);
+ saveline(buf);
+ }
+
+ /* we are now connected and need to try the autologin thing */
+ x = getresp(rfd,buf,sizeof(buf),1);
+ if(x / 100 != COMPLETE) {
+ sendsaved(0,-1);
+ return(say(0,buf));
+ }
+ saveline(buf);
+
+ sendsaved(0,-1);
+ return 0;
+ }
+
static int
***************
*** 1053,1058 ****
--- 1164,1171 ----
static char nprn[] = "500 cannot get peername";
char buf[512];
+ /* syslog(LLEV,"DEBUG: port cmd"); */
+
if(ac < 2)
return(sayn(0,narg,sizeof(narg)-1));
***************
*** 1119,1124 ****
--- 1232,1238 ----
#define UC(c) (((int)c) & 0xff)
sprintf(buf,"PORT %d,%d,%d,%d,%d,%d\r\n",UC(k[0]),UC(k[1]),UC(k[2]),
UC(k[3]),UC(l[0]),UC(l[1]));
+ /* syslog(LLEV,"DEBUG: %s",buf); */
s = strlen(buf);
if (write(rfd, buf, s) != s)
return 1;
***************
*** 1330,1335 ****
--- 1444,1450 ----
callback()
{
/* if we haven't gotten a valid PORT scrub the connection */
+ /* syslog(LLEV,"DEBUG: callback()."); */
if((outgoing = accept(boundport,(struct sockaddr *)0,(int *)0)) < 0 || clntport.sin_port == 0)
goto bomb;
if(pasvport != -1) { /* incoming handled by PASVcallback */
***************
*** 1796,1801 ****
--- 1911,1960 ----
}
return(0);
}
+
+ /* ok, so i'm in a hurry. english paper due RSN. */
+ sayfile2(fd,fn,code)
+ int fd;
+ char *fn;
+ int code;
+ {
+ FILE *f;
+ char buf[BUFSIZ];
+ char yuf[BUFSIZ];
+ char *c;
+ int x;
+ int saidsomething = 0;
+
+ if((f = fopen(fn,"r")) == (FILE *)0)
+ return(1);
+ while(fgets(buf,sizeof(buf),f) != (char *)0) {
+ if((c = index(buf,'\n')) != (char *)0)
+ *c = '\0';
+ x = fgetc(f);
+ if(feof(f))
+ sprintf(yuf,"%3.3d-%s",code,buf);
+ else {
+ sprintf(yuf,"%3.3d-%s",code,buf);
+ ungetc(x,f);
+ }
+ if(say(fd,yuf)) {
+ fclose(f);
+ return(1);
+ }
+ saidsomething++;
+ }
+ fclose(f);
+ if (!saidsomething) {
+ syslog(LLEV,"fwtkcfgerr: sayfile for %d is empty",code);
+ sprintf(yuf, "%3.3d The file to display is empty",code);
+ if(say(fd,yuf)) {
+ fclose(f);
+ return(1);
+ }
+ }
+ return(0);
+ }
+
porttoaddr(s,a)
diff -c -r ./http-gw/http-gw.c ../../NEW/fwtk/http-gw/http-gw.c
*** ./http-gw/http-gw.c Mon Sep 9 14:40:53 1996
--- ../../NEW/fwtk/http-gw/http-gw.c Wed Oct 9 02:51:57 1996
***************
*** 27,32 ****
--- 27,37 ----
static char http_buffer[8192];
static char reason[8192];
static int checkBrowserType = 1;
+ /* foo */
+ static int do_transparent=0;
+ /* foo */
+
+ char *getdsthost();
static void do_logging()
{ char *proto = "GOPHER";
***************
*** 422,427 ****
--- 427,443 ----
/*(NOT A SPECIAL FORM)*/
if((rem_type & TYPE_LOCAL)== 0){
+ /* foo */
+ char *psychic=getdsthost(sockfd,&def_port);
+ if(psychic) {
+ if(strlen(psychic)<=MAXHOSTNAMELEN) {
+ do_transparent++;
+ strncpy(def_httpd,psychic,strlen(psychic));
+ strncpy(def_server,psychic,strlen(psychic));
+ }
+ }
+
+ /* foo */
/* See if it can be forwarded */
if( can_forward(buf)){
***************
*** 1513,1519 ****
parse_vec[0],
parse_vec[1],
ourname, ourport);
! }else{
sprintf(new_reply,"%s\tgopher://%s:%s/%c%s\t%s\t%u",
parse_vec[0], parse_vec[2],
parse_vec[3], chk_type_ch,
--- 1529,1541 ----
parse_vec[0],
parse_vec[1],
ourname, ourport);
! }
! /* FOO */
! else if(do_transparent) {
! sprintf(new_reply,"%s\t%s\t%s\t%s",parse_vec[0],parse_vec[1],parse_vec[2],parse_vec[3]);
! }
! /* FOO */
! else{
sprintf(new_reply,"%s\tgopher://%s:%s/%c%s\t%s\t%u",
parse_vec[0], parse_vec[2],
parse_vec[3], chk_type_ch,
diff -c -r ./lib/hnam.c ../../NEW/fwtk/lib/hnam.c
*** ./lib/hnam.c Fri Nov 4 18:30:19 1994
--- ../../NEW/fwtk/lib/hnam.c Wed Oct 9 02:34:13 1996
***************
*** 22,27 ****
--- 22,31 ----
#include "firewall.h"
+ #ifdef __FreeBSD__
+ #include <net/if.h>
+ #include "ip_nat.h"
+ #endif /* __FreeBSD__ */
char *
***************
*** 44,47 ****
--- 48,115 ----
bcopy(hp->h_addr,&sin.sin_addr,hp->h_length);
return(inet_ntoa(sin.sin_addr));
+ }
+
+ char *getdsthost(fd, ptr)
+ int fd;
+ int *ptr;
+ {
+ struct sockaddr_in sin;
+ struct hostent *hp;
+ int sl=sizeof(struct sockaddr_in), err=0, local_h=0, i=0;
+ char buf[255], hostbuf[255];
+ #ifdef __FreeBSD__
+ struct sockaddr_in rsin;
+ struct natlookup natlookup;
+ #endif
+
+ #ifdef linux
+ /* This should also work for UDP. Unfortunately, it doesn't.
+ Maybe when the Linux UDP proxy code gets a little cleaner.
+ */
+ if(!(err=getsockname(0,&sin,&sl))) {
+ if(ptr) *ptr=ntohs(sin.sin_port);
+ sprintf(buf,"%s",inet_ntoa(sin.sin_addr));
+ gethostname(hostbuf,254);
+ hp=gethostbyname(hostbuf);
+ while(hp->h_addr_list[i]) {
+ bzero(&sin,&sl);
+ memcpy(&sin.sin_addr,hp->h_addr_list[i++],sizeof(hp->h_addr_list[i++]));
+ if(!strcmp(buf,inet_ntoa(sin.sin_addr))) local_h++;
+ }
+ if(local_h) { /* syslog(LLEV,"DEBUG: hnam.c: non-transparent."); */ return(NULL); }
+ else { return(buf); }
+ }
+ #endif
+
+ #ifdef __FreeBSD__
+ /* The basis for this block of code is Darren Reed's
+ patches to the TIS ftwk's ftp-gw.
+ */
+ bzero((char*)&sin,sizeof(sin));
+ bzero((char*)&rsin,sizeof(rsin));
+ if(getsockname(fd,(struct sockaddr*)&sin,&sl)<0) {
+ return NULL;
+ }
+ sl=sizeof(rsin);
+ if(getpeername(fd,(struct sockaddr*)&rsin,&sl)<0) {
+ return NULL;
+ }
+ natlookup.nl_inport=sin.sin_port;
+ natlookup.nl_outport=rsin.sin_port;
+ natlookup.nl_inip=sin.sin_addr;
+ natlookup.nl_outip=rsin.sin_addr;
+ if((natfd=open("/dev/ipl",O_RDONLY))<0) {
+ return(NULL);
+ }
+ if(ioctl(natfd,SIOCGNATL,&natlookup)==(-1)) {
+ return(NULL);
+ }
+ close(natfd);
+ if(ptr) *ptr=ntohs(natlookup.nl_inport);
+ sprintf(buf,"%s",inet_ntoa(natlookup.nl_inip));
+ #endif
+
+ /* No transparent proxy support */
+ return(NULL);
}
Only in ./lib: hnam.c.orig
diff -c -r ./plug-gw/plug-gw.c ../../NEW/fwtk/plug-gw/plug-gw.c
*** ./plug-gw/plug-gw.c Thu Sep 5 15:36:33 1996
--- ../../NEW/fwtk/plug-gw/plug-gw.c Wed Oct 9 02:46:48 1996
***************
*** 39,44 ****
--- 39,48 ----
static char **validdests = (char **)0;
static Cfg *confp;
+ int do_transparent=0;
+
+ char *getdsthost();
+
main(ac,av)
int ac;
char *av[];
***************
*** 193,201 ****
--- 197,213 ----
char *ptr;
int state = 0;
int ssl_plug = 0;
+ int pport=0;
struct timeval timo;
+ /* Transparent plug-gw is probably a bad idea, but hey .. */
+ dhost=getdsthost(0,&pport);
+ if(dhost) {
+ do_transparent++;
+ portid=pport;
+ }
+
if(c->flags & PERM_DENY) {
if (p == -1)
syslog(LLEV,"deny host=%s/%s port=any",rhost,raddr);
***************
*** 215,221 ****
syslog(LLEV,"fwtkcfgerr: -plug-to takes an argument, line %d",c->ln);
exit (1);
}
! dhost = av[x];
continue;
}
--- 227,234 ----
syslog(LLEV,"fwtkcfgerr: -plug-to takes an argument, line %d",c->ln);
exit (1);
}
! if(!dhost) dhost = av[x];
! /* syslog(LLEV,"DEBUG: dhost now is [%s]",dhost); */
continue;
}
diff -c -r ./rlogin-gw/rlogin-gw.c ../../NEW/fwtk/rlogin-gw/rlogin-gw.c
*** ./rlogin-gw/rlogin-gw.c Fri Sep 6 12:56:33 1996
--- ../../NEW/fwtk/rlogin-gw/rlogin-gw.c Wed Oct 9 02:49:04 1996
***************
*** 39,45 ****
--- 39,47 ----
extern char *maphostname();
+ char *getdsthost();
+ int do_transparent=0;
static int cmd_quit();
static int cmd_help();
***************
*** 120,125 ****
--- 122,130 ----
static char *tokav[56];
int tokac;
struct timeval timo;
+ /* foo */
+ char *psychic;
+ /* foo */
#ifndef LOG_NDELAY
openlog("rlogin-gw",LOG_PID);
***************
*** 185,191 ****
xforwarder = cf->argv[0];
}
!
if((cf = cfg_get("directory",confp)) != (Cfg *)0) {
if(cf->argc != 1) {
--- 190,203 ----
xforwarder = cf->argv[0];
}
! /* foo */
! psychic=getdsthost(0,NULL);
! if(psychic) {
! do_transparent++;
! strncpy(dest,psychic,511);
! dest[511]='\0';
! }
! /* foo */
if((cf = cfg_get("directory",confp)) != (Cfg *)0) {
if(cf->argc != 1) {
***************
*** 260,269 ****
}
/* if present a host name, chop and save username and hostname */
! dest[0] = '\0';
if((p = index(rusername,'@')) != (char *)0) {
char *namp;
*p++ = '\0';
if(*p == '\0')
p = "localhost";
--- 272,282 ----
}
/* if present a host name, chop and save username and hostname */
! /* dest[0] = '\0'; */
if((p = index(rusername,'@')) != (char *)0) {
char *namp;
+ dest[0] = '\0';
*p++ = '\0';
if(*p == '\0')
p = "localhost";
***************
*** 293,300 ****
--- 306,326 ----
goto leave;
}
+ /* syslog(LLEV,"DEBUG: Uh-oh, $dest = %s\n",dest); */
+
if(dest[0] != '\0') {
/* Setup connection directly to remote machine */
+ if((cf = cfg_get("welcome-msg",confp)) != (Cfg *)0) {
+ if(cf->argc != 1) {
+ syslog(LLEV,"fwtkcfgerr: welcome-msg must have one parameter, line %d",cf->ln);
+ exit(1);
+ }
+ if(sayfile(0,cf->argv[0])) {
+ syslog(LLEV,"fwtksyserr: cannot display welcome %s: %m",cf->argv[0]);
+ exit(1);
+ }
+ }
+ /* Does this cmd_connect thing feel like a kludge or what? */
sprintf(buf,"connect %.1000s",dest);
tokac = enargv(buf, tokav, 56, tokbuf, sizeof(tokbuf));
if (cmd_connect(tokac, tokav, buf) != 2)
***************
*** 526,539 ****
char ebuf[512];
syslog(LLEV,"permit host=%s/%s connect to %s",rhost,raddr,namp);
if(strlen(namp) > 20)
namp[20] = '\0';
if(rusername[0] != '\0')
sprintf(ebuf,"Trying %s@%s...",rusername,namp);
else
sprintf(ebuf,"Trying %s...",namp);
! if(say(0,ebuf))
! return(1);
} else
syslog(LLEV,"permit host=%s/%s connect to %s",rhost,raddr,av[1]);
if((serfd = conn_server(av[1],RLOGINPORT,1,buf)) < 0) {
--- 552,567 ----
char ebuf[512];
syslog(LLEV,"permit host=%s/%s connect to %s",rhost,raddr,namp);
+ if(!do_transparent) {
if(strlen(namp) > 20)
namp[20] = '\0';
if(rusername[0] != '\0')
sprintf(ebuf,"Trying %s@%s...",rusername,namp);
else
sprintf(ebuf,"Trying %s...",namp);
! if(say(0,ebuf))
! return(1);
! }
} else
syslog(LLEV,"permit host=%s/%s connect to %s",rhost,raddr,av[1]);
if((serfd = conn_server(av[1],RLOGINPORT,1,buf)) < 0) {
diff -c -r ./tn-gw/tn-gw.c ../../NEW/fwtk/tn-gw/tn-gw.c
*** ./tn-gw/tn-gw.c Fri Sep 6 12:55:48 1996
--- ../../NEW/fwtk/tn-gw/tn-gw.c Wed Oct 9 02:50:17 1996
***************
*** 87,92 ****
--- 87,94 ----
static int cmd_xforward();
static int cmd_timeout();
+ char *getdsthost();
+
static int tn3270 = 1; /* don't do tn3270 stuff */
static int doX;
***************
*** 97,102 ****
--- 99,106 ----
static int timeout = PROXY_TIMEOUT;
static char timed_out_msg[] = "\r\nConnection closed due to inactivity";
+ int do_transparent=0;
+
typedef struct {
char *name;
char *hmsg;
***************
*** 140,145 ****
--- 144,151 ----
char tokbuf[BSIZ];
char *tokav[56];
int tokac;
+ int port;
+ char *psychic;
#ifndef LOG_DAEMON
openlog("tn-gw",LOG_PID);
***************
*** 308,313 ****
--- 314,346 ----
}
}
+ psychic=getdsthost(0,&port);
+ if(psychic) {
+ if((strlen(psychic) + 10) < 510) {
+ do_transparent++;
+ if(port)
+ sprintf(dest,"%s:%d",psychic,port);
+ else
+ sprintf(dest,"%s",psychic);
+
+
+ if(!welcomedone)
+ if((cf = cfg_get("welcome-msg",confp)) != (Cfg *)0) {
+ if(cf->argc != 1) {
+ syslog(LLEV,"fwtkcfgerr: welcome-msg must have one parameter, line %d",cf->ln);
+ exit(1);
+ }
+ if(sayfile(0,cf->argv[0])) {
+ syslog(LLEV,"fwtksyserr: cannot display welcome %s:%m",cf->argv[0]);
+ exit(1);
+ }
+ welcomedone = 1;
+ }
+
+
+ }
+ }
+
while (argc > 1) {
argc--;
argv++;
***************
*** 864,877 ****
}
}
-
if((namp = maphostname(av[1])) != (char *)0) {
char ebuf[512];
syslog(LLEV,"permit host=%s/%s destination=%s",rladdr,riaddr,namp);
! sprintf(ebuf,"Trying %s port %d...",namp,port);
! if(say(0,ebuf))
! return(1);
} else
syslog(LLEV,"permit host=%s/%s destination=%s",rladdr,riaddr,av[1]);
--- 897,911 ----
}
}
if((namp = maphostname(av[1])) != (char *)0) {
char ebuf[512];
syslog(LLEV,"permit host=%s/%s destination=%s",rladdr,riaddr,namp);
! if(!do_transparent) {
! sprintf(ebuf,"Trying %s port %d...",namp,port);
! if(say(0,ebuf))
! return(1);
! }
} else
syslog(LLEV,"permit host=%s/%s destination=%s",rladdr,riaddr,av[1]);
***************
*** 903,910 ****
syslog(LLEV,"connected host=%s/%s destination=%s",rladdr,riaddr,av[1]);
strncpy(dest,av[1], 511);
! sprintf(buf, "Connected to %s.", dest);
! say(0, buf);
return(2);
}
--- 937,946 ----
syslog(LLEV,"connected host=%s/%s destination=%s",rladdr,riaddr,av[1]);
strncpy(dest,av[1], 511);
! if(!do_transparent) {
! sprintf(buf, "Connected to %s.", dest);
! say(0, buf);
! }
return(2);
}

567
contrib/ipfilter/HISTORY Normal file
View File

@ -0,0 +1,567 @@
#
# NOTE: Quite a few patches and suggestions come from other sources, to whom
# I'm greatly indebted, even if no names are mentioned.
#
# Thanks to Craig Bishop of connect.com.au and Sun Microsystems for the
# loan of a machine to work on a Solaris 2.x port of this software.
#
3.1.7 8/2/97 - Released
Macros used for ntohs/htons supplied with gcc don't always work very well
when the assignment is the same variable being converted.
Filter matching doesn't not match rule which checks tcp flags on packets
which are fragments - David Wilson
3.1.7beta 30/1/97 - Released
Fix up NAT bugs introduced in last major change (now tested), including
nat_delete(), nat_lookupredir(), checksum changes, etc.
3.1.7alpha 30/1/97 - Released
Many changes to NAT code, including contributions from Laurent Joncheray
<lpj@ans.net>
Use "NO_SLEEP" when allocating memory under SunOS.
Make kernel printf's nicer for BSD/SunOS4
Always do a checksum for packets being filtered going out and being
processed by fastroute.
Leave kernel to play with cdevsw on *BSD systems with LKM's.
ipnat.1 man page fixes.
3.1.6 21/1/97 - Released
Allow NAT to work on BSD systems in conjunction with "pass .. to ifname"
Memory leak introduced in 3.1.3 in NAT lists, clearing of NAT table tried
to free memory twice.
NAT recalculates IP header checksum based on difference between IP#'s and
port numbers - should be just IP#'s (Solaris2 only)
3.1.5 13/1/97 - Released
fixed setting of NAT timeouts and use different timeouts for concurrent
TCP sessions using the same IP# mapping (when port mapping isn't used)
multiple loading/unloading of LKM's doesn't clean up cdevsw properly for
*BSD systems.
3.1.4 10/1/97 - Released
add command line options -C and -F to ipnat to flush NAT list and table
ipnat -l loops on output - Neil Readwin (nreadwin@nysales.micrognosis.com)
NetBSD/FreeBSD kernel malloc changes - Daniel Carosone
3.1.3 10/1/97 - Released
NAT chains not constructed correctly in hash tables - Antony Y.R Lu
(antony@hawk.ee.ncku.edu.tw)
Updated INSTALL.NetBSD, INSTALL.FreeBSD and INSTALL.Sol2
man page update (ipf.5) from Daniel Carosone (dan@geek.com.au)
ICMP header checksum update now included in NAT.
Solaris2 needs to modify IP header checksums in ip_natin and ip_natout.
3.1.2 4/12/96 - Released
ipmon doesn't use syslog all the time when given -s option
fixed mclput panic in ip_input.c and replace ntohs() with NTOHS() macro
check the results of hostname resolution in ipnat
"make *install" fixed for subdirectories.
problems with "ARCH:=" and gnu make resolved
parser reports an error for lines with whitespaces only rather than skipping
them. D.Carosone@abm.com.au (Daniel Carosone)
patches for integration into NetBSD-current (post 1.2).
add an option to allow non-IP packets going up/down the stream on Solaris2
to be dropped. John Bass.
3.1.2beta 21/11/96 - Released
make ipsend compile on Linux 2.0.24
changes to TCP kept state algorithm, making it watch state on TCP
connections in both directions. Also use the same algorithm for NAT TCP.
-Wall cleanup - Bernd Ernesti
added "or-block" for "pass .. log or-block" after a suggestion from
David Oppenheim (davido@optimation.com.au)
added subdirectories for building IP Filter in SunOS5/BSD for different
cpu architecures
Solaris2 fixes to logging and pre-filtering packet processing - 3.1.1p2
mbuf logging not using mtod(), remove iplbusy - 3.1.1p1 1/11/96
3.1.1 28/10/96 - Released
Installation script fixes and deinstall scripts for IP Filter on:
SunOS4/FreeBSD/NetBSD
Man page fixes - Paul Dubois (dubois@primate.wisc.edu)
Fix use of SOLARIS macro in ipmon, rewrote ipllog() (again!)
parsing isn't completely case insensitive - David Wilson
(davidw@optimation.com.au)
Release ipl_mutex across uiomove() calls
print entire rule entries out for "ipf -z" when zero'ing per-rule stats.
ipfstat returns same output for "hits" in "ipfstat -aio" - Terletsky Slavik
(ts@polynet.lviv.ua)
New algorithm for setting timeouts for TCP connection (more closely follow
TCP FSM) - Pradeep Krishnan (pkrishna@netcom.com)
Track both window sizes for TCP connections through "keep state".
Solaris2 doesn't like _KERNEL defined in stdargs.h - Jos van Wezel
(wezel@bio.vu.nl)
3.1.1-beta2 6/10/96 - Released
Solaris2 fastroute/dup-to/to now works
ipmon `record' reading rewritten
Added post-NetBSD1.2 packet filter patches - Mathew Green (mrg@eterna.com.au)
Attempt to use in_proto.c.diff, not "..diffs" for SunOS4 - David Wilson
(davidw@optimation.com.au)
Michael Ryan (mike@NetworX.ie) reports the following:
* The Trumpet WinSock under Windows always sends its SYN packet with an ACK
value of 1, unlike any other implementation I've seen, which would set it
to zero. The "keep state" feature of IP Filter doesn't work when receiving
non-zero ACK values on new connection requests.
* */Makefile install rule doesn't install all the binaries/man pages
* Make ipnat use "tcp/udp" instead of "tcpudp"
* Print out "tcp/udp" properly
* ipnat "portmap tcp" matches "portmap udp" when adding/removing
* NAT dest. ip# increased by one on mask of 0xffffffff when it shouldn't
3.1.1-beta 1/9/96 - Released
add better detection of TCP connections closing to TCP state monitoring.
fr_addstate() not called correctly for fragments. "keep state" and
"keep frag" code don't work together 100% - Songqing Cai
(songqing_cai@sterling.com)
call to fr_addstate() incorrect for adding state in combination with keeping
fragment information - Songqing Cai (songqing_cai@sterling.com)
KFREE() passed fp (incorrect) and not fr (correct) in ip_frag.c - John Hood
(cgull@smoke.marlboro.vt.us)
make ipf parser recognise '\\' as a `continued line' marker - Dima Ruban
(dima@best.net)
3.1.1-alpha 23/8/96 - Released
kernel panic's when ICMP packets go through NAT code
stats aren't zero'd properly with ipf -Z
ipnat doesn't show port numbers correctly all the time and also add the
protocol (tcp/udp/tcpudp) to rdr output - Carson Gaspar (carson@lehman.com)
fast checksum fixing not 100% - backout patch - Bill Dorsey (dorsey@lila.com)
NetBSD-1.2 patches from - VaX#n8 <vax@linkdead.paranoia.com>
Usage() call error in fils.c - Ajay Shekhawat (ajay@cedar.buffalo.edu)
ip_optcopy() staticly defined in ip_output.c in SunOS4 - Nick Hall
(nrh@tardis.ed.ac.uk)
3.1.0 7/7/96 - Released
Reformatted ipnat output to be compatible with it's input, so that
"ipnat -l | ipnat -rf -" is possible.
3.1.0beta 30/6/96 - Released
NetBSD-1.2 patches from Greg Woods (woods@most.weird.com)
kernel module must not be installed stripped (Solaris2), as created by
"make package" for Solaris2 - Peter Heimann
(peter@i3.informatik.rwth-aachen.de)
3.1.0alpha 5/6/96 - Released
include examples in package for solaris2
patches for removing an extra ip header checksum (FreeBSD/NetBSD/SunOS)
removed trailing space from printouts of rules in ipf.
ipresend supports the same range of inputs that ipftest does.
sending a duplicate copy of a packet to another network devices is now
supported. ("dup-to")
sending a packet to an arbitary interface is now supported, irrespective
of its actual route, with no ttl decrement. Can also be routed without
the ttl being decremented. ("to" and "fastroute").
"call" option added to support calling a generic function if a packet is
matched.
show all (upto 4) recorded bytes from the interface name in logging from
ipmon.
support for using unix file permissions for read/write access on the device
is now in place.
recursive mutex in nat_new() for Solaris 2.x - Per L. Hagen <per@stibo.dk>
ipftest doesn't call initparse() for THISHOST - Catherine Allen
(cla@connect.com.au)
Man page corrections from Rex Bona (rex@pengo.comsmiths.com.au)
3.0.4 10/4/96 - Released
looop in `parsing' IP packets with optlen 0 for ip options.
rule number not initialized and resulted in unexpected results for state
maching.
option parsing and printing bugs - Pradeep Krishnan
3.0.4beta 25/3/96 - Released
wouldn't parse "keep flags keep state" correctly.
SunOS4.1.x ip_input.c doesn't recognise all 1s broadcast address - Nigel Verdon
patches for BSDI's BSD/OS 2.1 and libpcap reader on little endian systems
from Thorsten Lockert <tholo@tetherless.com>
b* functions in fil.c on Solaris 2.4
3.0.3 17/3/96 - Released
added patches to support IP Filter initialisation when compiled into the
kernel.
added -x option to ipmon to display hex dumps of logged packets.
added -H option to ipftest to allow ascii-hex formatted input to specify
arbitary IP packets.
Sending TCP RSTs as a response now work for Solaris2 x86
add patches to make IP Filter compile into NetBSD kernels properly.
patch to stop SunOS 4.1.x kernels panicing with "data traps".
ipfboot script unloads and reloads ipf module on Solaris2 if it is already
loaded into the kernel.
Installation of IP Filter as a Solaris2 package is now supported.
Man pages for ipnat.4, ipnat.5 added.
added some more regression tests and fixed up IP Filter to pass the new tests
(previous versions failed some of the tests in set 12).
IP option filter processing has changed so that saying "with opt lsrr" will
check only for that one, but not mask out other options, so a packet with
strict source routing, along with loose source routing will match all of
"with opt lsrr", "with opt ssrr" and "with opt lsrr,ssrr".
IPL_NAME needed in ipnat.c - Kelly (kelly@count04.mry.scruznet.com)
patches for clean NetBSD compilation from Bernd Ernesti (bernd@arresum.inka.de)
make install is incorrect - Julian Briggs (julian@lightwork.co.uk)
strtol() returns 0x7fffffff for all negative numbers,
printfr() generates incorrect output for "opt sec-class *",
handling of "not opt xxx opt yyy" incorrect.
- Minh Tonthat (minht@sbei.com)/Pradeep Krishnan (pradeepk@sbei.com)
m_pullup() called only for input and not output; caused problems
with filtering icmp - Nigel Verdon (verdenn@gb.swissbank.com)
parsing problem for "port 1" and NetBSD patches incorrect -
Andreas Gustafsson (gson@guava.araneus.fi)
3.0.2 4/2/96 - Released
Corrected bug where NAT recalculates checksums for fragments.
make NAT recalculate UDP checksums (rather than setting them to 0),
if they're non-zero.
DNS patches - Real Page (Real.Page@Matrox.com)
alteration of checksum recalculations in NAT code and addition of
redirection with NAT - Mike Neuman
core dump, if tcp/udp is used with a port number and not service name,
in ipf - Mike Neuman (mcn@engarde.com)
initparse() call, missing to prime "<thishost>" hook - Craig Bishop
3.0.1 14/1/96 - Released
miscellaneous patches for Solaris2
3.0 14/1/96 - Released
Patch included for FDDI, from Richard Ohnemus
(Richard_Ohnemus@dallas.csd.sterling.com)
Code cleanup for release.
3.0beta4 10/1/96
recursive mutex in ipfr_slowtimer fixed, reported by Craig Bishop
recursive mutex in sending TCP RSTs fixed, reported by Tony Becker
3.0beta3 9/1/96
FIxup for Solaris2.5 install and interface name bug in ipftest from
Julian Briggs (julian@lightwork.co.uk)
Byte order patches for ipmon from Tony Becker (tony@mcrsys.com)
3.0beta2 7/1/96
Added the (somewhat warped) IP accounting as it exists in ipfw on FreeBSD.
Note, this isn't really what one would call IP account, when compared to
process accounting, sigh.
Split up ipresend into iptest/ipresend/ipsend
Added another m_pullup() inside fr_check() for BSD style kernels and
added some checks to ipllog() to not log more than is present (for short
packets).
Fixed bug where failed hostname/netname resolution goes undetecte and
becomes 0.0.0.0 (any) (reported Guido van Rooij)
3.0beta 11/11/95 - Released
Rewrote the way rule testing is done, reducing the number of files needed and
generated.
SIOCIPFFL was incorrectly affected by IPFILTER_LOG (Mathew Green)
Patches from Guido van Rooij to fix sending back TCP RSTs on Net-2/Net-3
BSD based Unixes (panic'd)
Patches for FreeBSD/i86 ipmon from Riku Kalinen <riku@tequila.nixu.fi>
(I think someone else already told me about these but they got lost :-/)
Changed Makefile structure to build object files for different operating
systems in separate directories by default.
BSDI has ef0 for first ethernet interface
Allow for a "not" operator before optional keywords.
The "rule number" was being incorrectly incremented every time it went through
the loop rather than when it matched a rule.
2.8.2 24/10/95 - Released
Fixed up problems with "textip" for doing lots of testing.
Fixed bug in detection of "short" tcp/ip packets (all reported as being short).
Solaris 2.4 port now works 100%.
Man page errors reported and fixed.
Removed duplicate entry in etc/services for login on port 49 (Craig Bishop).
Fixed ipmon output to put a space after the log-letter.
Patch from Guido van Rooij to fix parsing problem.
2.8.1 15/10/95 - Released
Added ttl and tos filtering.
Patches for fixing up compilation and port problems (little endian)
from Guido van Rooij <guido@IAEhv.nl>.
Man page problems reported and fixed by Carson Gaspar <carson@lehman.com>.
ipsend doesn't compile properly on Solaris2.4
Lots of work done for Solaris2.4 to make it MT/MP safe and work.
2.8 15/9/95 - Released
ipmon can now send messages to syslogd (-s) and use names instead of
numbers (-N).
IP packets are now "compiled" into a structure only containing filterable
bits.
Added regression testing in the test/ subdirectory, using a new option
(-b) with the ipftest program.
Added "nomatch" return to filter results. These are counted and show
up in reports from ipfstat.
Moved filter code out of ip_fil.c and into fil.c - there is now only one
instance of it in the package.
Added Solaris 2.4 support.
Added IPSO basic security option filtering.
Added name support for filtering on all 19 named IP options.
Patches from Ivan Brawley to log packet contents as well as packet headers.
Update for sun/conf.c.diff from Ivan Brawley <ibrawley@awadi.com.AU>
Added patches for FreeBSD 1, and added two new switches (-E, -D) to ipf,
along with a new ioctl, SIOCFRENB.
From: Dieter Dworkin Muller <dworkin@village.org>
2.7.3 31/7.95 - Released
Didn't compile cleanly without IPFILTER_LOG defined (Mathew Green).
ipftest now deals with tcpdump3 binary output files (from libpcap) with -P.
Brought ipftest program upto date with actual filter code.
Filter would cause a match to occur when it wasn't meant to if the packet
had short headers and was missing portions that should have been there.
Err, it would rightly not match on them, but their absence caused a match
when it shouldn't have been.
2.7.2 26/7/95 - Released
Problem with filtering just SYN flagged packets reported by
Dieter Dworkin Muller <dworkin@village.org>. To solve this
problem, added support for masking TCP flags for comparison "flags X/Y".
2.7.1 9/7/95 - Released
Added ip_dirbroadcast support for Sun ip_input.c
Fixed up the install scripts for FreeBSD/NetBSD to recognise where they are
better.
2.7 7/7/95 - Released
Added "return-rst" to return TCP RST's to TCP packets.
Actually ported it to FreeBSD-i386 2.0.0, so it works there properly now.
Added insertion of filter rules. Use "@<#>" at the beginning of a filter
to insert a rule at row #.
Filter keeps track of how many times each rule is matched.
Changed compile time things to match kernel option (IPFILTER_LKM &
IPFILTER_LOG).
Updated ip_input.c and ip_output.c with paches for 3.5 Multicast IP.
(No change required for 3.6)
Now includes TCP fragments which start inside the TCP header as being short.
Added counting the number of times each rule is matched.
2.6 11/5/95 - Released
Added -n option to ipf: when supplied, no changes are made to the kernel.
Added installation scripts for SunOS 4.1.x and NetBSD/FreeBSD/BSDI.
Rewrote filtering to use a more generic mask & match procedure for
checking if a packet matches a rule.
2.5.2 27/4/95 - Released
"tcp/udp" and a non-initialised pointer caused the "proto" to become
a `random' value; added "ip#/dotted.mask" notation to the BNF.
From Adam W. Feigin <feigin@iis.ee.ethz.ch>
2.5.1 22/3/95 - Released
"tcp/udp" had a strange effect (undesired) on getserv*() functions,
causing protocol/service lookups to fail. Reported by Matthew Green.
2.5 17/3/95 - Released
Added a new keyword "all" to BNF and parsing of tcpdump/etherfind/snoop
output through the ipftest program. Suggestions from:
Michael Ciavarella (mikec@phyto.apana.org.au)
Conflicts occur when "general" filter rules are used for ports and the
lack of a "proto" when used with "port" matches other packets when only
TCP/UDP are implied.
Reported Matthew Green (mrg@fulcom.com.au);
reported & fixed 6-8/3/95
Added filtering of short TCP packets using "with short" 28/2/95
(These can possibly slip by checks for the various flags). Short UDP
or ICMP are dropped to the floor and logged.
Added filtering of fragmented packets using "with frag" 24/2/95
Port to NetBSD-current completed 20/2/95, using LKM.
Added logging of the rule # which caused the logging to happen and the
interface on which the packet is currently as suggested by
Andreas Greulich (greulich@math-stat.unibe.ch) 10/2/95
2.4 9/2/95 - Released
Fixed saving of IP headers in ICMP packets.
2.3 29/1/95
Added ipf -F [in|out|all] to flush filter rule sets (SIOCIPFFL).
Fixed iplread() and iplsave() with help from Marc Huber.
2.2 7/1/95 - Released
Added code from Marc Huber <huber@fzi.de> to allow it to allocate
its own major char number dynamically when modload'ing. Fixed up
use of <, >, <=, >= and >< for ports.
2.1 21/12/94 - Released
repackaged to include the correct ip_output.c and ip_input.c *goof*
2.0 18/12/94 - Released
added code to check for port ranges - complete.
rewrote to work as a loadable kernel module - complete.
1.1
added code for ouput filtering as well as input filtering and added support for logging to a simple character device of packet headers.
1.0 22/04/93 - Released
First release cut.

View File

@ -0,0 +1,41 @@
****************************************
IMPORTANT NOTICE
****************************************
1)
If you're using this software and have a rule which ends like this:
flags S
(for TCP), then to make it totally effective, you need to change it to appear
as follows:
flags S/SA
The problem is that the old code would compare all the TCP flags against the
rule (which just has "S") to see if that matched exactly. It is very possible
for this to not be the case and in these cases, the rule would fail to match
a 'valid' TCP SYN packet.
Why does it need to be "S/SA" and not "S/S" ?
"S/S" will match the SYN-ACK as well the SYN.
By defalt, "flags S" will now be converted to "flags S/AUPRFS".
If you have any queries regarding this, see the examples and ipf(4).
If you still have a query or suggestion, please email me.
2)
If a filter rule used, in combination port comparisons and the flags
keywords, a "short" TCP packet, if not explicitly blocked high up in
the list of packets, would actually get matched even though it would
otherwise not have been (due to the ports not). This behaviour has
subsequently been fixed.
Darren
darrenr@cyber.com.au
****************************************

View File

@ -0,0 +1,41 @@
To build a kernel for use with the loadable kernel module, follow these
steps:
1. do "make bsd"
2. do "make install-bsd"
(probably has to be done as root)
3. run "FreeBSD/minstall" as root
4. build a new kernel
5. install and reboot with the new kernel
6. use modload(8) to load the packet filter with:
modload if_ipl.o
7. do "modstat" to confirm that it has been loaded successfully.
There is no need to use mknod to create the device in /dev;
- upon loading the module, it will create itself with the correct values,
under the name (IPL_NAME) from the Makefile. It will also remove itself
from /dev when it is modunload'd.
To build a kernel with the IP filter, follow these steps:
1. do "make bsd"
2. do "make install-bsd"
(probably has to be done as root)
3. run "FreeBSD/kinstall" as root
4. build a new kernel
5. create /dev/ipl with "mknod /dev/ipl c 20 0".
6. install and reboot with the new kernel
Darren Reed
darrenr@cyber.com.au

View File

@ -0,0 +1,48 @@
To build a kernel for use with the loadable kernel module, follow these
steps:
1. do "make bsd"
2. do "make install-bsd"
(probably has to be done as root)
3(a) NetBSD systems prior to 1.2:
run "NetBSD/minstall" as root
3(b) NetBSD 1.2 systems or later:
run "NetBSD-1.2/minstall" as root
4. build a new kernel
5. install and reboot with the new kernel
6. use modload(8) to load the packet filter with:
modload if_ipl.o
7. do "modstat" to confirm that it has been loaded successfully.
There is no need to use mknod to create the device in /dev;
- upon loading the module, it will create itself with the correct values,
under the name (IPL_NAME) from the Makefile. It will also remove itself
from /dev when it is modunload'd.
To build a kernel with the IP filter, follow these steps:
1. do "make bsd"
2. do "make install-bsd"
(probably has to be done as root)
3(a) NetBSD systems prior to 1.2:
run "NetBSD/kinstall" as root
3(b) NetBSD 1.2 systems or later:
run "NetBSD-1.2/kinstall" as root
4. build a new kernel
5. create /dev/ipl with "mknod /dev/ipl c 59 0".
(for NetBSD-1.2, use "mknod /dev/ipl c 49 0")
6. install and reboot with the new kernel
Darren Reed
darrenr@cyber.com.au

View File

@ -0,0 +1,27 @@
For those running Solaris 2.5, please read COMPILE.2.5 before building
IP Filter.
Type "make solaris" to build all the required binaries.
Once IP Filter has been successfully compiled, you may then install it using
the usual package method (using pkgadd), however, the package needs to be
created, prior to pkgadd'ing. To create the package in /var/spoo/pkg, change
directory to SunOS5 and enter the following command:
make package
If you wish to then install it using `pkgadd', run the following command:
pkgadd -s '/var/spool/pkg'
As part of the postinstall script, it will install loadable kernel module
as part of Solaris 2 (using add_drv) making it available for immeadiate use.
IP Filter will be installed into /opt/CYBSipf (programs, manual pages and
examples) and create a directory /etc/opt/CYBSipf with a null body file
called "ipf.conf" using touch. The rc scripts have been written to look
for the configuration file here, using the installed binaries in /sbin.
Darren Reed
darrenr@cyber.com.au

View File

@ -0,0 +1,36 @@
To install as a Loadable Kernel Module (LKM):
1. do a "make sunos4" in this directory
2. Run the script "SunOS4/minstall" as root.
3. change directory to SunOS4 and run "make install"
4. Reboot using the new kernel
5. use modload(8) to load the packet filter with:
modload if_ipl.o
6. do "modstat" to confirm that it has been loaded successfully.
There is no need to use mknod to create the device in /dev;
- upon loading the module, it will create itself with the correct
values, under the name (IPL_NAME) from the Makefile. It will
also remove itself from /dev when it is modunload'd.
To install as part of a SunOS 4.1.x kernel:
1. do a "make sunos4" in this directory
2. Run the script "SunOS4/kinstall" as root.
NOTE: This script sets up /dev/ipl as char. device 59,0
in /sys/sun/conf.c
3. Do "mknod /dev/ipl c 59 0" as root.
4. Reboot using the new kernel
Darren Reed
darrenr@cyber.com.au

View File

@ -0,0 +1,39 @@
To build a kernel for use with the loadable kernel module, follow these
steps:
1. do "make bsd"
2. cd to the "BSD" directory and type "make install"
3. run "4bsd/minstall" as root
4. build a new kernel
5. install and reboot with the new kernel
6. use modload(8) to load the packet filter with:
modload if_ipl.o
7. do "modstat" to confirm that it has been loaded successfully.
There is no need to use mknod to create the device in /dev;
- upon loading the module, it will create itself with the correct values,
under the name (IPL_NAME) from the Makefile. It will also remove itself
from /dev when it is modunload'd.
To build a kernel with the IP filter, follow these steps:
1. do "make bsd"
2. cd to the "BSD" directory and type "make install"
3. run "4bsd/kinstall" as root
4. build a new kernel
5. create /dev/ipl with "mknod /dev/ipl c 59 0".
6. install and reboot with the new kernel
Darren
darrenr@cyber.com.au

16
contrib/ipfilter/LICENCE Normal file
View File

@ -0,0 +1,16 @@
/*
* (C)opyright 1993, 1994, 1995 by Darren Reed.
*
* The author accepts no responsibility for the use of this software and
* provides it on an ``as is'' basis without express or implied warranty.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* I hate legaleese, don't you ?
*/

158
contrib/ipfilter/Makefile Normal file
View File

@ -0,0 +1,158 @@
#
# (C)opyright 1993, 1994, 1995 by Darren Reed.
#
# This code may be freely distributed as long as it retains this notice
# and is not changed in any way. The author accepts no responsibility
# for the use of this software. I hate legaleese, don't you ?
#
# $Id: Makefile,v 2.0.1.4 1997/02/08 06:39:28 darrenr Exp $
#
# where to put things.
#
BINDEST=/usr/local/ip_fil3.1.1/bin
SBINDEST=/usr/local/ip_fil3.1.1/sbin
MANDIR=/usr/local/ip_fil3.1.1/man
CC=gcc
DEBUG=-g
CFLAGS=-I$$(TOP)
DCPU=`uname -m`
#
# To enable this to work as a Loadable Kernel Module...
#
IPFLKM=-DIPFILTER_LKM
#
# To enable logging of blocked/passed packets...
#
IPFLOG=-DIPFILTER_LOG
#
# The facility you wish to log messages from ipmon to syslogd with.
#
LOGFAC=-DLOGFAC=LOG_LOCAL0
#
# For packets which don't match any pass rules or any block rules, set either
# FR_PASS or FR_BLOCK (respectively). It defaults to FR_PASS if left
# undefined. This is ignored for ipftest, which can thus return three
# results: pass, block and nomatch. This is the sort of "block unless
# explicitly allowed" type #define switch.
#
POLICY=-DNOMATCH=FR_PASS
#
MFLAGS="BINDEST=$(BINDEST)" "SBINDEST=$(SBINDEST)" "MANDIR=$(MANDIR)" \
"CC=$(CC)" 'CFLAGS=$(CFLAGS) $(SOLARIS2)' "IPFLKM=$(IPFLKM)" \
"IPFLOG=$(IPFLOG)" "LOGFAC=$(LOGFAC)" "POLICY=$(POLICY)" \
"SOLARIS2=$(SOLARIS2)" "DEBUG=$(DEBUG)" "ARCH=$(ARCH)"
#
########## ########## ########## ########## ########## ########## ##########
#
CP=/bin/cp
RM=/bin/rm
CHMOD=/bin/chmod
INSTALL=install
#
DFLAGS=$(IPFLKM) $(IPFLOG) $(DEF)
all:
@echo "Chose one of the following targets for making IP filter:"
@echo ""
@echo "solaris - auto-selects SunOS4.1.x/Solaris 2.[45]/Soalris2.[45]-x86"
@echo "bsd - compile for 4.4BSD based Unixes (FreeBSD/NetBSD/OpenBSD)"
@echo "bsdi - compile for BSD/OS"
@echo ""
tests:
@if [ -d test ]; then (cd test; make) \
else echo test directory not present, sorry; fi
sunos solaris:
./buildsunos
sunos4 solaris1:
(cd SunOS4; make build TOP=.. $(MFLAGS); cd ..)
(cd SunOS4; make -f Makefile.ipsend TOP=.. $(MFLAGS); cd ..)
sunos5 solaris2:
(cd SunOS5/$(DCPU); make build TOP=../.. $(MFLAGS) "SOLARIS2=$(SOLARIS2)" "CPU=-Dsparc -D__sparc__"; cd ..)
(cd SunOS5/$(DCPU); make -f Makefile.ipsend TOP=../.. $(MFLAGS); cd ..)
sunos5x86 solaris2x86:
(cd SunOS5/$(DCPU); make build TOP=../.. $(MFLAGS) "SOLARIS2=$(SOLARIS2)" "CPU=-Di86pc -Di386 -D__i386__"; cd ..)
(cd SunOS5/$(DCPU); make -f Makefile.ipsend TOP=../.. $(MFLAGS); cd ..)
bsd netbsd freebsd:
-if [ ! -d BSD/$(DCPU) ] ; then mkdir BSD/$(DCPU); fi
-rm -f BSD/$(DCPU)/Makefile BSD/$(DCPU)/Makefile.ipsend
-ln -s ../Makefile BSD/$(DCPU)/Makefile
-ln -s ../Makefile.ipsend BSD/$(DCPU)/Makefile.ipsend
(cd BSD/$(DCPU); make build "TOP=../.." $(MFLAGS); cd ..)
(cd BSD/$(DCPU); make -f Makefile.ipsend "TOP=../.." $(MFLAGS); cd ..)
bsdi bsdos:
-if [ ! -d BSD/$(DCPU) ] ; then mkdir BSD/$(DCPU); fi
-rm -f BSD/$(DCPU)/Makefile BSD/$(DCPU)/Makefile.ipsend
-ln -s ../Makefile BSD/$(DCPU)/Makefile
-ln -s ../Makefile.ipsend BSD/$(DCPU)/Makefile.ipsend
(cd BSD/$(DCPU); make build "TOP=../.." $(MFLAGS) LKM= ; cd ..)
(cd BSD/$(DCPU); make -f Makefile.ipsend "TOP=../.." $(MFLAGS); cd ..)
clean:
${RM} -f core *.o ipt fils ipf ipfstat ipftest ipmon if_ipl \
vnode_if.h $(LKM)
(cd SunOS4; make clean)
(cd SunOS5; make clean)
(cd BSD; make clean)
[ -d test ] && (cd test; make clean)
(cd ipsend; make clean)
clean-bsd:
(cd BSD; make clean)
clean-sunos4:
(cd SunOS4; make clean)
clean-sunos5:
(cd SunOS5; make clean)
get:
-@for i in ipf.c ipt.h solaris.c ipf.h kmem.c ipft_ef.c linux.h \
ipft_pc.c fil.c ipft_sn.c mln_ipl.c fils.c ipft_td.c \
mls_ipl.c ip_compat.h ipl.h opt.c ip_fil.c ipl_ldev.c \
parse.c ip_fil.h ipmon.c pcap.h ip_sfil.c ipt.c snoop.h \
ip_state.c ip_state.h ip_nat.c ip_nat.h ip_frag.c \
ip_frag.h ip_sfil.c misc.c; do \
if [ ! -f $$i ] ; then \
echo "getting $$i"; \
sccs get $$i; \
fi \
done
install-bsd: bsd
(cd BSD/$(DCPU); $(MAKE) "TOP=../.." install)
install-sunos4: solaris
(cd SunOS4; $(MAKE) "TOP=.." install)
install-sunos5: solaris
(cd SunOS5; $(MAKE) "TOP=.." install)
# XXX FIXME: bogus to depend on all!
install: all ip_fil.h
-$(CP) ip_fil.h /usr/include/netinet/ip_fil.h
-$(CHMOD) 444 /usr/include/netinet/ip_fil.h
-$(INSTALL) -cs -g wheel -m 755 -o root ipfstat ipf ipnat $(SBINDEST)
-$(INSTALL) -cs -g wheel -m 755 -o root ipmon ipftest $(BINDEST)
(cd man; $(MAKE) INSTALL=$(INSTALL) MANDIR=$(MANDIR) install; cd ..)
rcsget:
-@for i in ipf.c ipt.h solaris.c ipf.h kmem.c ipft_ef.c linux.h \
ipft_pc.c fil.c ipft_sn.c mln_ipl.c fils.c ipft_td.c \
mls_ipl.c ip_compat.h ipl.h opt.c ip_fil.c ipl_ldev.c \
parse.c ip_fil.h ipmon.c pcap.h ip_sfil.c ipt.c snoop.h \
ip_state.c ip_state.h ip_nat.c ip_nat.h ip_frag.c \
ip_frag.h ip_sfil.c misc.c; do \
if [ ! -f $$i ] ; then \
echo "getting $$i"; \
co $$i; \
fi \
done
do-cvs:
find . -type d -name CVS -print | xargs /bin/rm -rf
find . -type f -name .cvsignore -print | xargs /bin/rm -f

93
contrib/ipfilter/README Normal file
View File

@ -0,0 +1,93 @@
IP Filter - What's this about ?
============================
The idea behind this package is allow those who use Unix workstations as
routers (a common occurance in Universities it appears) to apply packet
filtering to packets going in and out of them. This package has been
tested on all versions of SunOS 4.1 and Solaris 2.4/2.5, running on Sparcs.
It is also quite possible for this small kernel extension to be installed
and used effectively on Sun workstations which don't route IP, just for
added security. It can also be integrated with the multicast patches.
It has also been tested successfully on all of the modern free BSDs as
well as BSDI.
The filter keeps a rule list for both inbound and outbound sides of
the IP packet queue and a check is made as early as possible, aiming to
stop the packet before it even gets as far as being checked for source
route options. In the file "BNF", a set of rules for constructing filter
rules understood by this package is given. The files in the directory
"rules", "example.1" ... "example.sr" show example rules you might apply.
In practise, I've successfully isolated a workstation from all
machines except the NFS file servers on its local subnets (yeah, ok, so
this doesn't really increase security, because of NFS, but you get the
drift on how it can be applied and used). I've also successfully
setup and maintained my own firewalls using it with TIS's Firewall Toolkit,
including using it on an mbone router.
When using it with multicast IP, the calls to fr_check() should be
before the packet is unwrapped and after it is encapsulated. So the
filter routines will see the packet as a UDP packet, protocol XYZ.
Whether this is better or worse than having it filter on class D addresses
is debateable, but the idea behind this package is to be able to
discriminate between packets as they are on the 'wire', before they
get routed anywhere, etc.
It is worth noting, that it is possible, using a small MTU and
generating tiny fragmented IP packets to generate a TCP packet which
doesn't contain enough information to filter on the "flags". Filtering
on these types of packets is possible, but under the more general case
of the packets being "short". ICMP and UDP packets which are too small
(they don't contain a complete header) are dropped and logged, no questions
asked. When filtering on fragmented packets, the last fragment will get
through for TCP/UDP/ICMP packets.
Some general notes.
-------------------
To add/delete a rule from memory, access to the device in /dev is needed,
allowing non-root maintenaince. The filter list in kernel memory is built
from the kernel's heap. Each packet coming *in* or *out* is checked against
the appropriate list, rejects dropped, others passed through. Thus this will
work on an individual host, not just gateways. Presently there is only one
list for all interfaces, the changes required to make it a per-interface list
require more .o replacements for the kernel. When checking a packet, the
packet is compared to the entire list from top to bottom, the last matching
line being effective.
What does what ?
----------------
if_fil.o (Loadable kernel module)
- additional kernel routines to check an access list as to whether
or not to drop or pass a packet. It currently defaults to pass
on all packets.
ipfstat
- digs through your kernel (need to check #define VMUNIX in fils.c)
and /dev/kmem for the access filter list and mini stats table.
Obviously needs to be run priviledged if required.
ipf
- reads the files passed as parameters as input files containing new
filter rules to add/delete to the kernel list. The lines are
inserted in order; the first line is inserted first, and ends up
first on the list. Subsequent invocations append to the list
unless specified otherwise.
ipftest
- test the ruleset given by filename. Reads in the ruleset and then
waits for stdin.
See the man pages (ipf.1, ipftest.1, ipfstat.8) for more detailed
information on what the above do.
mkfilters
- suggests a set of filter rules to employ and suggests how to add
routes to back these up.
BNF
- BNF rule set for the filter rules
Darren Reed
darrenr@cyber.com.au

83
contrib/ipfilter/bsdinstall Executable file
View File

@ -0,0 +1,83 @@
#! /bin/sh
#
# @(#)install.sh 4.5 (Berkeley) 10/12/83
#
cmd=/bin/mv
strip=""
chmod="chmod 755"
chown="chown -f root"
chgrp="chgrp -f bin"
while true ; do
case $1 in
-s ) strip="strip"
shift
;;
-c ) cmd="cp"
shift
;;
-m ) chmod="chmod $2"
shift
shift
;;
-o ) chown="chown -f $2"
shift
shift
;;
-g ) chgrp="chgrp -f $2"
shift
shift
;;
-d ) cmd="mkdir"
shift
;;
* ) break
;;
esac
done
if [ ! ${2-""} ]
then echo "install: no destination specified"
exit 1
fi
if [ ${3-""} ]
then echo "install: too many files specified -> $*"
exit 1
fi
if [ $1 = $2 -o $2 = . ]
then echo "install: can't move $1 onto itself"
exit 1
fi
case $cmd in
/bin/mkdir )
file=$2/$1
;;
* )
if [ '!' -f $1 ]
then echo "install: can't open $1"
exit 1
fi
if [ -d $2 ]
then file=$2/$1
else file=$2
fi
/bin/rm -f $file
;;
esac
case $cmd in
/bin/mkdir )
if [ ! -d "$file" ]
then $cmd $file
fi
;;
* )
$cmd $1 $file
if [ $strip ]
then $strip $file
fi
;;
esac
$chown $file
$chgrp $file
$chmod $file

23
contrib/ipfilter/buildsunos Executable file
View File

@ -0,0 +1,23 @@
#! /bin/sh
# $Id: buildsunos,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp $
:
rev=`uname -r | sed -e 's/^\([^\.]*\)\..*/\1/'`
cpu=`uname -m`
if [ $rev = 5 ] ; then
solrev=`uname -r | sed -e 's/^\([0-9]*\)\.\([0-9]*\)$/\2/'`
mkdir -p SunOS5/${cpu}
/bin/rm -f SunOS5/${cpu}/Makefile
/bin/rm -f SunOS5/${cpu}/Makefile.ipsend
ln -s ../Makefile SunOS5/${cpu}/Makefile
ln -s ../Makefile.ipsend SunOS5/${cpu}/Makefile.ipsend
fi
if [ $cpu = i86pc ] ; then
make ${1+"$@"} sunos5x86 SOLARIS2="-DSOLARIS2=$solrev" DCPU=${cpu}
exit $?
fi
if [ x$solrev = x ] ; then
make ${1+"$@"} sunos$rev "ARCH=`uname -m`"
exit $?
fi
make ${1+"$@"} sunos$rev SOLARIS2="-DSOLARIS2=$solrev" DCPU=${cpu}
exit $?

View File

@ -0,0 +1,95 @@
icmp 1 ICMP # Internet Control Message
igmp 2 IGMP # Internet Group Management
ggp 3 GGP # Gateway-to-Gateway
ip 4 IP # IP in IP (encasulation)
st 5 ST # Stream
tcp 6 TCP # Transmission Control
ucl 7 UCL # UCL
egp 8 EGP # Exterior Gateway Protocol
igp 9 IGP # any private interior gateway
bbn-rcc-mon 10 BBN-RCC-MON # BBN RCC Monitoring
nvp-ii 11 NVP-II # Network Voice Protocol
pup 12 PUP # PUP
argus 13 ARGUS # ARGUS
emcon 14 EMCON # EMCON
xnet 15 XNET # Cross Net Debugger
chaos 16 CHAOS # Chaos
udp 17 UDP # User Datagram
mux 18 MUX # Multiplexing
dcn-meas 19 DCN-MEAS # DCN Measurement Subsystems
hmp 20 HMP # Host Monitoring
prm 21 PRM # Packet Radio Measurement
xns-idp 22 XNS-IDP # XEROX NS IDP
trunk-1 23 TRUNK-1 # Trunk-1
trunk-2 24 TRUNK-2 # Trunk-2
leaf-1 25 LEAF-1 # Leaf-1
leaf-2 26 LEAF-2 # Leaf-2
rdp 27 RDP # Reliable Data Protocol
irtp 28 IRTP # Internet Reliable Transaction
iso-tp4 29 ISO-TP4 # ISO Transport Protocol Class 4
netblt 30 NETBLT # Bulk Data Transfer Protocol
mfe-nsp 31 MFE-NSP # MFE Network Services Protocol
merit-inp 32 MERIT-INP # MERIT Internodal Protocol
sep 33 SEP # Sequential Exchange Protocol
3pc 34 3PC # Third Party Connect Protocol
idpr 35 IDPR # Inter-Domain Policy Routing Protocol
xtp 36 XTP # XTP
ddp 37 DDP # Datagram Delivery Protocol
idpr-cmtp 38 IDPR-CMTP # IDPR Control Message Transport Proto
tp++ 39 TP++ # TP++ Transport Protocol
il 40 IL # IL Transport Protocol
sip 41 SIP # Simple Internet Protocol
sdrp 42 SDRP # Source Demand Routing Protocol
sip-sr 43 SIP-SR # SIP Source Route
sip-frag 44 SIP-FRAG # SIP Fragment
idrp 45 IDRP # Inter-Domain Routing Protocol
rsvp 46 RSVP # Reservation Protocol
gre 47 GRE # General Routing Encapsulation
mhrp 48 MHRP # Mobile Host Routing Protocol
bna 49 BNA # BNA
sipp-esp 50 SIPP-ESP # SIPP Encap Security Payload
sipp-ah 51 SIPP-AH # SIPP Authentication Header
i-nlsp 52 I-NLSP # Integrated Net Layer Security TUBA
swipe 53 SWIPE # IP with Encryption
nhrp 54 NHRP # NBMA Next Hop Resolution Protocol
any 61 any # host internal protocol
cftp 62 CFTP # CFTP
any 63 any # local network
sat-expak 64 SAT-EXPAK # SATNET and Backroom EXPAK
kryptolan 65 KRYPTOLAN # Kryptolan
rvd 66 RVD # MIT Remote Virtual Disk Protocol
ippc 67 IPPC # Internet Pluribus Packet Core
any 68 any # distributed file system
sat-mon 69 SAT-MON # SATNET Monitoring
visa 70 VISA # VISA Protocol
ipcv 71 IPCV # Internet Packet Core Utility
cpnx 72 CPNX # Computer Protocol Network Executive
cphb 73 CPHB # Computer Protocol Heart Beat
wsn 74 WSN # Wang Span Network
pvp 75 PVP # Packet Video Protocol
br-sat-mon 76 BR-SAT-MON # Backroom SATNET Monitoring
sun-nd 77 SUN-ND # SUN ND PROTOCOL-Temporary
wb-mon 78 WB-MON # WIDEBAND Monitoring
wb-expak 79 WB-EXPAK # WIDEBAND EXPAK
iso-ip 80 ISO-IP # ISO Internet Protocol
vmtp 81 VMTP # VMTP
secure-vmtp 82 SECURE-VMTP # SECURE-VMTP
vines 83 VINES # VINES
ttp 84 TTP # TTP
nsfnet-igp 85 NSFNET-IGP # NSFNET-IGP
dgp 86 DGP # Dissimilar Gateway Protocol
tcf 87 TCF # TCF
igrp 88 IGRP # IGRP
ospfigp 89 OSPFIGP # OSPFIGP
sprite-rpc 90 Sprite-RPC # Sprite RPC Protocol
larp 91 LARP # Locus Address Resolution Protocol
mtp 92 MTP # Multicast Transport Protocol
ax.25 93 AX.25 # AX.25 Frames
ipip 94 IPIP # IP-within-IP Encapsulation Protocol
micp 95 MICP # Mobile Internetworking Control Pro.
scc-sp 96 SCC-SP # Semaphore Communications Sec. Pro.
etherip 97 ETHERIP # Ethernet-within-IP Encapsulation
encap 98 ENCAP # Encapsulation Header
any 99 any # private encryption scheme
gmtp 100 GMTP # GMTP
reserved 255 Reserved #

View File

@ -0,0 +1,731 @@
tcpmux 1/tcp # TCP Port Service Multiplexer
tcpmux 1/udp # TCP Port Service Multiplexer
compressnet 2/tcp # Management Utility
compressnet 2/udp # Management Utility
compressnet 3/tcp # Compression Process
compressnet 3/udp # Compression Process
rje 5/tcp # Remote Job Entry
rje 5/udp # Remote Job Entry
echo 7/tcp # Echo
echo 7/udp # Echo
discard 9/tcp # Discard
discard 9/udp # Discard
systat 11/tcp # Active Users
systat 11/udp # Active Users
daytime 13/tcp # Daytime
daytime 13/udp # Daytime
qotd 17/tcp # Quote of the Day
qotd 17/udp # Quote of the Day
msp 18/tcp # Message Send Protocol
msp 18/udp # Message Send Protocol
chargen 19/tcp # Character Generator
chargen 19/udp # Character Generator
ftp-data 20/tcp # File Transfer
ftp-data 20/udp # File Transfer
ftp 21/tcp # File Transfer
ftp 21/udp # File Transfer
telnet 23/tcp # Telnet
telnet 23/udp # Telnet
smtp 25/tcp # Simple Mail Transfer
smtp 25/udp # Simple Mail Transfer
nsw-fe 27/tcp # NSW User System FE
nsw-fe 27/udp # NSW User System FE
msg-icp 29/tcp # MSG ICP
msg-icp 29/udp # MSG ICP
msg-auth 31/tcp # MSG Authentication
msg-auth 31/udp # MSG Authentication
dsp 33/tcp # Display Support Protocol
dsp 33/udp # Display Support Protocol
time 37/tcp # Time
time 37/udp # Time
rap 38/tcp # Route Access Protocol
rap 38/udp # Route Access Protocol
rlp 39/tcp # Resource Location Protocol
rlp 39/udp # Resource Location Protocol
graphics 41/tcp # Graphics
graphics 41/udp # Graphics
nameserver 42/tcp # Host Name Server
nameserver 42/udp # Host Name Server
nicname 43/tcp # Who Is
nicname 43/udp # Who Is
mpm-flags 44/tcp # MPM FLAGS Protocol
mpm-flags 44/udp # MPM FLAGS Protocol
mpm 45/tcp # Message Processing Module
mpm 45/udp # Message Processing Module
mpm-snd 46/tcp # MPM
mpm-snd 46/udp # MPM
ni-ftp 47/tcp # NI FTP
ni-ftp 47/udp # NI FTP
auditd 48/tcp # Digital Audit Daemon
auditd 48/udp # Digital Audit Daemon
re-mail-ck 50/tcp # Remote Mail Checking Protocol
re-mail-ck 50/udp # Remote Mail Checking Protocol
la-maint 51/tcp # IMP Logical Address Maintenance
la-maint 51/udp # IMP Logical Address Maintenance
xns-time 52/tcp # XNS Time Protocol
xns-time 52/udp # XNS Time Protocol
domain 53/tcp # Domain Name Server
domain 53/udp # Domain Name Server
xns-ch 54/tcp # XNS Clearinghouse
xns-ch 54/udp # XNS Clearinghouse
isi-gl 55/tcp # ISI Graphics Language
isi-gl 55/udp # ISI Graphics Language
xns-auth 56/tcp # XNS Authentication
xns-auth 56/udp # XNS Authentication
xns-mail 58/tcp # XNS Mail
xns-mail 58/udp # XNS Mail
ni-mail 61/tcp # NI MAIL
ni-mail 61/udp # NI MAIL
acas 62/tcp # ACA Services
acas 62/udp # ACA Services
covia 64/tcp # Communications Integrator (CI)
covia 64/udp # Communications Integrator (CI)
tacacs-ds 65/tcp # TACACS-Database Service
tacacs-ds 65/udp # TACACS-Database Service
sql*net 66/tcp # Oracle SQL*NET
sql*net 66/udp # Oracle SQL*NET
bootps 67/tcp # Bootstrap Protocol Server
bootps 67/udp # Bootstrap Protocol Server
bootpc 68/tcp # Bootstrap Protocol Client
bootpc 68/udp # Bootstrap Protocol Client
tftp 69/tcp # Trivial File Transfer
tftp 69/udp # Trivial File Transfer
gopher 70/tcp # Gopher
gopher 70/udp # Gopher
netrjs-1 71/tcp # Remote Job Service
netrjs-1 71/udp # Remote Job Service
netrjs-2 72/tcp # Remote Job Service
netrjs-2 72/udp # Remote Job Service
netrjs-3 73/tcp # Remote Job Service
netrjs-3 73/udp # Remote Job Service
netrjs-4 74/tcp # Remote Job Service
netrjs-4 74/udp # Remote Job Service
deos 76/tcp # Distributed External Object Store
deos 76/udp # Distributed External Object Store
vettcp 78/tcp # vettcp
vettcp 78/udp # vettcp
finger 79/tcp # Finger
finger 79/udp # Finger
www-http 80/tcp # World Wide Web HTTP
www-http 80/udp # World Wide Web HTTP
hosts2-ns 81/tcp # HOSTS2 Name Server
hosts2-ns 81/udp # HOSTS2 Name Server
xfer 82/tcp # XFER Utility
xfer 82/udp # XFER Utility
mit-ml-dev 83/tcp # MIT ML Device
mit-ml-dev 83/udp # MIT ML Device
ctf 84/tcp # Common Trace Facility
ctf 84/udp # Common Trace Facility
mit-ml-dev 85/tcp # MIT ML Device
mit-ml-dev 85/udp # MIT ML Device
mfcobol 86/tcp # Micro Focus Cobol
mfcobol 86/udp # Micro Focus Cobol
kerberos 88/tcp # Kerberos
kerberos 88/udp # Kerberos
su-mit-tg 89/tcp # SU/MIT Telnet Gateway
su-mit-tg 89/udp # SU/MIT Telnet Gateway
dnsix 90/tcp # DNSIX Securit Attribute Token Map
dnsix 90/udp # DNSIX Securit Attribute Token Map
mit-dov 91/tcp # MIT Dover Spooler
mit-dov 91/udp # MIT Dover Spooler
npp 92/tcp # Network Printing Protocol
npp 92/udp # Network Printing Protocol
dcp 93/tcp # Device Control Protocol
dcp 93/udp # Device Control Protocol
objcall 94/tcp # Tivoli Object Dispatcher
objcall 94/udp # Tivoli Object Dispatcher
supdup 95/tcp # SUPDUP
supdup 95/udp # SUPDUP
dixie 96/tcp # DIXIE Protocol Specification
dixie 96/udp # DIXIE Protocol Specification
swift-rvf 97/tcp # Swift Remote Vitural File Protocol
swift-rvf 97/udp # Swift Remote Vitural File Protocol
tacnews 98/tcp # TAC News
tacnews 98/udp # TAC News
metagram 99/tcp # Metagram Relay
metagram 99/udp # Metagram Relay
newacct 100/tcp
hostname 101/tcp # NIC Host Name Server
hostname 101/udp # NIC Host Name Server
iso-tsap 102/tcp # ISO-TSAP
iso-tsap 102/udp # ISO-TSAP
gppitnp 103/tcp # Genesis Point-to-Point Trans Net
gppitnp 103/udp # Genesis Point-to-Point Trans Net
acr-nema 104/tcp # ACR-NEMA Digital Imag. & Comm. 300
acr-nema 104/udp # ACR-NEMA Digital Imag. & Comm. 300
csnet-ns 105/tcp # Mailbox Name Nameserver
csnet-ns 105/udp # Mailbox Name Nameserver
3com-tsmux 106/tcp # 3COM-TSMUX
3com-tsmux 106/udp # 3COM-TSMUX
rtelnet 107/tcp # Remote Telnet Service
rtelnet 107/udp # Remote Telnet Service
snagas 108/tcp # SNA Gateway Access Server
snagas 108/udp # SNA Gateway Access Server
pop2 109/tcp # Post Office Protocol - Version 2
pop2 109/udp # Post Office Protocol - Version 2
pop3 110/tcp # Post Office Protocol - Version 3
pop3 110/udp # Post Office Protocol - Version 3
sunrpc 111/tcp # SUN Remote Procedure Call
sunrpc 111/udp # SUN Remote Procedure Call
mcidas 112/tcp # McIDAS Data Transmission Protocol
mcidas 112/udp # McIDAS Data Transmission Protocol
auth 113/tcp # Authentication Service
auth 113/udp # Authentication Service
audionews 114/tcp # Audio News Multicast
audionews 114/udp # Audio News Multicast
sftp 115/tcp # Simple File Transfer Protocol
sftp 115/udp # Simple File Transfer Protocol
ansanotify 116/tcp # ANSA REX Notify
ansanotify 116/udp # ANSA REX Notify
uucp-path 117/tcp # UUCP Path Service
uucp-path 117/udp # UUCP Path Service
sqlserv 118/tcp # SQL Services
sqlserv 118/udp # SQL Services
nntp 119/tcp # Network News Transfer Protocol
nntp 119/udp # Network News Transfer Protocol
cfdptkt 120/tcp # CFDPTKT
cfdptkt 120/udp # CFDPTKT
erpc 121/tcp # Encore Expedited Remote Pro.Call
erpc 121/udp # Encore Expedited Remote Pro.Call
smakynet 122/tcp # SMAKYNET
smakynet 122/udp # SMAKYNET
ntp 123/tcp # Network Time Protocol
ntp 123/udp # Network Time Protocol
ansatrader 124/tcp # ANSA REX Trader
ansatrader 124/udp # ANSA REX Trader
locus-map 125/tcp # Locus PC-Interface Net Map Ser
locus-map 125/udp # Locus PC-Interface Net Map Ser
unitary 126/tcp # Unisys Unitary Login
unitary 126/udp # Unisys Unitary Login
locus-con 127/tcp # Locus PC-Interface Conn Server
locus-con 127/udp # Locus PC-Interface Conn Server
gss-xlicen 128/tcp # GSS X License Verification
gss-xlicen 128/udp # GSS X License Verification
pwdgen 129/tcp # Password Generator Protocol
pwdgen 129/udp # Password Generator Protocol
cisco-fna 130/tcp # cisco FNATIVE
cisco-fna 130/udp # cisco FNATIVE
cisco-tna 131/tcp # cisco TNATIVE
cisco-tna 131/udp # cisco TNATIVE
cisco-sys 132/tcp # cisco SYSMAINT
cisco-sys 132/udp # cisco SYSMAINT
statsrv 133/tcp # Statistics Service
statsrv 133/udp # Statistics Service
ingres-net 134/tcp # INGRES-NET Service
ingres-net 134/udp # INGRES-NET Service
loc-srv 135/tcp # Location Service
loc-srv 135/udp # Location Service
profile 136/tcp # PROFILE Naming System
profile 136/udp # PROFILE Naming System
netbios-ns 137/tcp # NETBIOS Name Service
netbios-ns 137/udp # NETBIOS Name Service
netbios-dgm 138/tcp # NETBIOS Datagram Service
netbios-dgm 138/udp # NETBIOS Datagram Service
netbios-ssn 139/tcp # NETBIOS Session Service
netbios-ssn 139/udp # NETBIOS Session Service
emfis-data 140/tcp # EMFIS Data Service
emfis-data 140/udp # EMFIS Data Service
emfis-cntl 141/tcp # EMFIS Control Service
emfis-cntl 141/udp # EMFIS Control Service
bl-idm 142/tcp # Britton-Lee IDM
bl-idm 142/udp # Britton-Lee IDM
imap2 143/tcp # Interim Mail Access Protocol v2
imap2 143/udp # Interim Mail Access Protocol v2
news 144/tcp # NewS
news 144/udp # NewS
uaac 145/tcp # UAAC Protocol
uaac 145/udp # UAAC Protocol
iso-tp0 146/tcp # ISO-IP0
iso-tp0 146/udp # ISO-IP0
iso-ip 147/tcp # ISO-IP
iso-ip 147/udp # ISO-IP
cronus 148/tcp # CRONUS-SUPPORT
cronus 148/udp # CRONUS-SUPPORT
aed-512 149/tcp # AED 512 Emulation Service
aed-512 149/udp # AED 512 Emulation Service
sql-net 150/tcp # SQL-NET
sql-net 150/udp # SQL-NET
hems 151/tcp # HEMS
hems 151/udp # HEMS
bftp 152/tcp # Background File Transfer Program
bftp 152/udp # Background File Transfer Program
sgmp 153/tcp # SGMP
sgmp 153/udp # SGMP
netsc-prod 154/tcp # NETSC
netsc-prod 154/udp # NETSC
netsc-dev 155/tcp # NETSC
netsc-dev 155/udp # NETSC
sqlsrv 156/tcp # SQL Service
sqlsrv 156/udp # SQL Service
knet-cmp 157/tcp # KNET/VM Command/Message Protocol
knet-cmp 157/udp # KNET/VM Command/Message Protocol
pcmail-srv 158/tcp # PCMail Server
pcmail-srv 158/udp # PCMail Server
nss-routing 159/tcp # NSS-Routing
nss-routing 159/udp # NSS-Routing
sgmp-traps 160/tcp # SGMP-TRAPS
sgmp-traps 160/udp # SGMP-TRAPS
snmp 161/tcp # SNMP
snmp 161/udp # SNMP
snmptrap 162/tcp # SNMPTRAP
snmptrap 162/udp # SNMPTRAP
cmip-man 163/tcp # CMIP/TCP Manager
cmip-man 163/udp # CMIP/TCP Manager
cmip-agent 164/tcp # CMIP/TCP Agent
smip-agent 164/udp # CMIP/TCP Agent
xns-courier 165/tcp # Xerox
xns-courier 165/udp # Xerox
s-net 166/tcp # Sirius Systems
s-net 166/udp # Sirius Systems
namp 167/tcp # NAMP
namp 167/udp # NAMP
rsvd 168/tcp # RSVD
rsvd 168/udp # RSVD
send 169/tcp # SEND
send 169/udp # SEND
print-srv 170/tcp # Network PostScript
print-srv 170/udp # Network PostScript
multiplex 171/tcp # Network Innovations Multiplex
multiplex 171/udp # Network Innovations Multiplex
cl/1 172/tcp # Network Innovations CL/1
cl/1 172/udp # Network Innovations CL/1
xyplex-mux 173/tcp # Xyplex
xyplex-mux 173/udp # Xyplex
mailq 174/tcp # MAILQ
mailq 174/udp # MAILQ
vmnet 175/tcp # VMNET
vmnet 175/udp # VMNET
genrad-mux 176/tcp # GENRAD-MUX
genrad-mux 176/udp # GENRAD-MUX
xdmcp 177/tcp # X Display Manager Control Protocol
xdmcp 177/udp # X Display Manager Control Protocol
nextstep 178/tcp # NextStep Window Server
NextStep 178/udp # NextStep Window Server
bgp 179/tcp # Border Gateway Protocol
bgp 179/udp # Border Gateway Protocol
ris 180/tcp # Intergraph
ris 180/udp # Intergraph
unify 181/tcp # Unify
unify 181/udp # Unify
audit 182/tcp # Unisys Audit SITP
audit 182/udp # Unisys Audit SITP
ocbinder 183/tcp # OCBinder
ocbinder 183/udp # OCBinder
ocserver 184/tcp # OCServer
ocserver 184/udp # OCServer
remote-kis 185/tcp # Remote-KIS
remote-kis 185/udp # Remote-KIS
kis 186/tcp # KIS Protocol
kis 186/udp # KIS Protocol
aci 187/tcp # Application Communication Interface
aci 187/udp # Application Communication Interface
mumps 188/tcp # Plus Five's MUMPS
mumps 188/udp # Plus Five's MUMPS
qft 189/tcp # Queued File Transport
qft 189/udp # Queued File Transport
gacp 190/tcp # Gateway Access Control Protocol
cacp 190/udp # Gateway Access Control Protocol
prospero 191/tcp # Prospero Directory Service
prospero 191/udp # Prospero Directory Service
osu-nms 192/tcp # OSU Network Monitoring System
osu-nms 192/udp # OSU Network Monitoring System
srmp 193/tcp # Spider Remote Monitoring Protocol
srmp 193/udp # Spider Remote Monitoring Protocol
irc 194/tcp # Internet Relay Chat Protocol
irc 194/udp # Internet Relay Chat Protocol
dn6-nlm-aud 195/tcp # DNSIX Network Level Module Audit
dn6-nlm-aud 195/udp # DNSIX Network Level Module Audit
dn6-smm-red 196/tcp # DNSIX Session Mgt Module Audit Redir
dn6-smm-red 196/udp # DNSIX Session Mgt Module Audit Redir
dls 197/tcp # Directory Location Service
dls 197/udp # Directory Location Service
dls-mon 198/tcp # Directory Location Service Monitor
dls-mon 198/udp # Directory Location Service Monitor
smux 199/tcp # SMUX
smux 199/udp # SMUX
src 200/tcp # IBM System Resource Controller
src 200/udp # IBM System Resource Controller
at-rtmp 201/tcp # AppleTalk Routing Maintenance
at-rtmp 201/udp # AppleTalk Routing Maintenance
at-nbp 202/tcp # AppleTalk Name Binding
at-nbp 202/udp # AppleTalk Name Binding
at-3 203/tcp # AppleTalk Unused
at-3 203/udp # AppleTalk Unused
at-echo 204/tcp # AppleTalk Echo
at-echo 204/udp # AppleTalk Echo
at-5 205/tcp # AppleTalk Unused
at-5 205/udp # AppleTalk Unused
at-zis 206/tcp # AppleTalk Zone Information
at-zis 206/udp # AppleTalk Zone Information
at-7 207/tcp # AppleTalk Unused
at-7 207/udp # AppleTalk Unused
at-8 208/tcp # AppleTalk Unused
at-8 208/udp # AppleTalk Unused
tam 209/tcp # Trivial Authenticated Mail Protocol
tam 209/udp # Trivial Authenticated Mail Protocol
z39.50 210/tcp # ANSI Z39.50
z39.50 210/udp # ANSI Z39.50
914c/g 211/tcp # Texas Instruments 914C/G Terminal
914c/g 211/udp # Texas Instruments 914C/G Terminal
anet 212/tcp # ATEXSSTR
anet 212/udp # ATEXSSTR
ipx 213/tcp # IPX
ipx 213/udp # IPX
vmpwscs 214/tcp # VM PWSCS
vmpwscs 214/udp # VM PWSCS
softpc 215/tcp # Insignia Solutions
softpc 215/udp # Insignia Solutions
atls 216/tcp # Access Technology License Server
atls 216/udp # Access Technology License Server
dbase 217/tcp # dBASE Unix
dbase 217/udp # dBASE Unix
mpp 218/tcp # Netix Message Posting Protocol
mpp 218/udp # Netix Message Posting Protocol
uarps 219/tcp # Unisys ARPs
uarps 219/udp # Unisys ARPs
imap3 220/tcp # Interactive Mail Access Protocol v3
imap3 220/udp # Interactive Mail Access Protocol v3
fln-spx 221/tcp # Berkeley rlogind with SPX auth
fln-spx 221/udp # Berkeley rlogind with SPX auth
rsh-spx 222/tcp # Berkeley rshd with SPX auth
rsh-spx 222/udp # Berkeley rshd with SPX auth
cdc 223/tcp # Certificate Distribution Center
cdc 223/udp # Certificate Distribution Center
sur-meas 243/tcp # Survey Measurement
sur-meas 243/udp # Survey Measurement
link 245/tcp # LINK
link 245/udp # LINK
dsp3270 246/tcp # Display Systems Protocol
dsp3270 246/udp # Display Systems Protocol
pdap 344/tcp # Prospero Data Access Protocol
pdap 344/udp # Prospero Data Access Protocol
pawserv 345/tcp # Perf Analysis Workbench
pawserv 345/udp # Perf Analysis Workbench
zserv 346/tcp # Zebra server
zserv 346/udp # Zebra server
fatserv 347/tcp # Fatmen Server
fatserv 347/udp # Fatmen Server
csi-sgwp 348/tcp # Cabletron Management Protocol
csi-sgwp 348/udp # Cabletron Management Protocol
clearcase 371/tcp # Clearcase
clearcase 371/udp # Clearcase
ulistserv 372/tcp # Unix Listserv
ulistserv 372/udp # Unix Listserv
legent-1 373/tcp # Legent Corporation
legent-1 373/udp # Legent Corporation
legent-2 374/tcp # Legent Corporation
legent-2 374/udp # Legent Corporation
hassle 375/tcp # Hassle
hassle 375/udp # Hassle
nip 376/tcp # Amiga Envoy Network Inquiry Proto
nip 376/udp # Amiga Envoy Network Inquiry Proto
tnETOS 377/tcp # NEC Corporation
tnETOS 377/udp # NEC Corporation
dsETOS 378/tcp # NEC Corporation
dsETOS 378/udp # NEC Corporation
is99c 379/tcp # TIA/EIA/IS-99 modem client
is99c 379/udp # TIA/EIA/IS-99 modem client
is99s 380/tcp # TIA/EIA/IS-99 modem server
is99s 380/udp # TIA/EIA/IS-99 modem server
hp-collector 381/tcp # hp performance data collector
hp-collector 381/udp # hp performance data collector
hp-managed-node 382/tcp # hp performance data managed node
hp-managed-node 382/udp # hp performance data managed node
hp-alarm-mgr 383/tcp # hp performance data alarm manager
hp-alarm-mgr 383/udp # hp performance data alarm manager
arns 384/tcp # A Remote Network Server System
arns 384/udp # A Remote Network Server System
ibm-app 385/tcp # IBM Application
ibm-app 385/tcp # IBM Application
asa 386/tcp # ASA Message Router Object Def.
asa 386/udp # ASA Message Router Object Def.
aurp 387/tcp # Appletalk Update-Based Routing Pro.
aurp 387/udp # Appletalk Update-Based Routing Pro.
unidata-ldm 388/tcp # Unidata LDM Version 4
unidata-ldm 388/udp # Unidata LDM Version 4
ldap 389/tcp # Lightweight Directory Access Protocol
ldap 389/udp # Lightweight Directory Access Protocol
uis 390/tcp # UIS
uis 390/udp # UIS
synotics-relay 391/tcp # SynOptics SNMP Relay Port
synotics-relay 391/udp # SynOptics SNMP Relay Port
synotics-broker 392/tcp # SynOptics Port Broker Port
synotics-broker 392/udp # SynOptics Port Broker Port
dis 393/tcp # Data Interpretation System
dis 393/udp # Data Interpretation System
embl-ndt 394/tcp # EMBL Nucleic Data Transfer
embl-ndt 394/udp # EMBL Nucleic Data Transfer
netcp 395/tcp # NETscout Control Protocol
netcp 395/udp # NETscout Control Protocol
netware-ip 396/tcp # Novell Netware over IP
netware-ip 396/udp # Novell Netware over IP
mptn 397/tcp # Multi Protocol Trans. Net.
mptn 397/udp # Multi Protocol Trans. Net.
kryptolan 398/tcp # Kryptolan
kryptolan 398/udp # Kryptolan
work-sol 400/tcp # Workstation Solutions
work-sol 400/udp # Workstation Solutions
ups 401/tcp # Uninterruptible Power Supply
ups 401/udp # Uninterruptible Power Supply
genie 402/tcp # Genie Protocol
genie 402/udp # Genie Protocol
decap 403/tcp # decap
decap 403/udp # decap
nced 404/tcp # nced
nced 404/udp # nced
ncld 405/tcp # ncld
ncld 405/udp # ncld
imsp 406/tcp # Interactive Mail Support Protocol
imsp 406/udp # Interactive Mail Support Protocol
timbuktu 407/tcp # Timbuktu
timbuktu 407/udp # Timbuktu
prm-sm 408/tcp # Prospero Resource Manager Sys. Man.
prm-sm 408/udp # Prospero Resource Manager Sys. Man.
prm-nm 409/tcp # Prospero Resource Manager Node Man.
prm-nm 409/udp # Prospero Resource Manager Node Man.
decladebug 410/tcp # DECLadebug Remote Debug Protocol
decladebug 410/udp # DECLadebug Remote Debug Protocol
rmt 411/tcp # Remote MT Protocol
rmt 411/udp # Remote MT Protocol
synoptics-trap 412/tcp # Trap Convention Port
synoptics-trap 412/udp # Trap Convention Port
smsp 413/tcp # SMSP
smsp 413/udp # SMSP
infoseek 414/tcp # InfoSeek
infoseek 414/udp # InfoSeek
bnet 415/tcp # BNet
bnet 415/udp # BNet
silverplatter 416/tcp # Silverplatter
silverplatter 416/udp # Silverplatter
onmux 417/tcp # Onmux
onmux 417/udp # Onmux
hyper-g 418/tcp # Hyper-G
hyper-g 418/udp # Hyper-G
ariel1 419/tcp # Ariel
ariel1 419/udp # Ariel
smpte 420/tcp # SMPTE
smpte 420/udp # SMPTE
ariel2 421/tcp # Ariel
ariel2 421/udp # Ariel
ariel3 422/tcp # Ariel
ariel3 422/udp # Ariel
opc-job-start 423/tcp # IBM Operations Planning and Control Start
opc-job-start 423/udp # IBM Operations Planning and Control Start
opc-job-track 424/tcp # IBM Operations Planning and Control Track
opc-job-track 424/udp # IBM Operations Planning and Control Track
icad-el 425/tcp # ICAD
icad-el 425/udp # ICAD
smartsdp 426/tcp # smartsdp
smartsdp 426/udp # smartsdp
svrloc 427/tcp # Server Location
svrloc 427/udp # Server Location
ocs_cmu 428/tcp # OCS_CMU
ocs_cmu 428/udp # OCS_CMU
ocs_amu 429/tcp # OCS_AMU
ocs_amu 429/udp # OCS_AMU
utmpsd 430/tcp # UTMPSD
utmpsd 430/udp # UTMPSD
utmpcd 431/tcp # UTMPCD
utmpcd 431/udp # UTMPCD
iasd 432/tcp # IASD
iasd 432/udp # IASD
nnsp 433/tcp # NNSP
nnsp 433/udp # NNSP
mobileip-agent 434/tcp # MobileIP-Agent
mobileip-agent 434/udp # MobileIP-Agent
mobilip-mn 435/tcp # MobilIP-MN
mobilip-mn 435/udp # MobilIP-MN
dna-cml 436/tcp # DNA-CML
dna-cml 436/udp # DNA-CML
comscm 437/tcp # comscm
comscm 437/udp # comscm
dsfgw 438/tcp # dsfgw
dsfgw 438/udp # dsfgw
dasp 439/tcp # dasp Thomas Obermair
dasp 439/udp # dasp tommy@inlab.m.eunet.de
sgcp 440/tcp # sgcp
sgcp 440/udp # sgcp
decvms-sysmgt 441/tcp # decvms-sysmgt
decvms-sysmgt 441/udp # decvms-sysmgt
cvc_hostd 442/tcp # cvc_hostd
cvc_hostd 442/udp # cvc_hostd
https 443/tcp # https MCom
https 443/udp # https MCom
snpp 444/tcp # Simple Network Paging Protocol
snpp 444/udp # Simple Network Paging Protocol
microsoft-ds 445/tcp # Microsoft-DS
microsoft-ds 445/udp # Microsoft-DS
ddm-rdb 446/tcp # DDM-RDB
ddm-rdb 446/udp # DDM-RDB
ddm-dfm 447/tcp # DDM-RFM
ddm-dfm 447/udp # DDM-RFM
ddm-byte 448/tcp # DDM-BYTE
ddm-byte 448/udp # DDM-BYTE
as-servermap 449/tcp # AS Server Mapper
as-servermap 449/udp # AS Server Mapper
tserver 450/tcp # TServer
tserver 450/udp # TServer
exec 512/tcp # remote process execution;
biff 512/udp # used by mail system to notify users
login 513/tcp # remote login a la telnet;
who 513/udp # maintains data bases showing who's
cmd 514/tcp # like exec, but automatic
syslog 514/udp
printer 515/tcp # spooler
printer 515/udp # spooler
talk 517/tcp # like tenex link, but across
talk 517/udp # like tenex link, but across tcp connection is established)
ntalk 518/tcp
ntalk 518/udp
utime 519/tcp # unixtime
utime 519/udp # unixtime
efs 520/tcp # extended file name server
router 520/udp # local routing process (on site);
timed 525/tcp # timeserver
timed 525/udp # timeserver
tempo 526/tcp # newdate
tempo 526/udp # newdate
courier 530/tcp # rpc
courier 530/udp # rpc
conference 531/tcp # chat
conference 531/udp # chat
netnews 532/tcp # readnews
netnews 532/udp # readnews
netwall 533/tcp # for emergency broadcasts
netwall 533/udp # for emergency broadcasts
apertus-ldp 539/tcp # Apertus Technologies Load Determination
apertus-ldp 539/udp # Apertus Technologies Load Determination
uucp 540/tcp # uucpd
uucp 540/udp # uucpd
uucp-rlogin 541/tcp # uucp-rlogin Stuart Lynne
uucp-rlogin 541/udp # uucp-rlogin sl@wimsey.com
klogin 543/tcp
klogin 543/udp
kshell 544/tcp # krcmd
kshell 544/udp # krcmd
new-rwho 550/tcp # new-who
new-rwho 550/udp # new-who
dsf 555/tcp
dsf 555/udp
remotefs 556/tcp # rfs server
remotefs 556/udp # rfs server
rmonitor 560/tcp # rmonitord
rmonitor 560/udp # rmonitord
monitor 561/tcp
monitor 561/udp
chshell 562/tcp # chcmd
chshell 562/udp # chcmd
9pfs 564/tcp # plan 9 file service
9pfs 564/udp # plan 9 file service
whoami 565/tcp # whoami
whoami 565/udp # whoami
meter 570/tcp # demon
meter 570/udp # demon
meter 571/tcp # udemon
meter 571/udp # udemon
ipcserver 600/tcp # Sun IPC server
ipcserver 600/udp # Sun IPC server
nqs 607/tcp # nqs
nqs 607/udp # nqs
urm 606/tcp # Cray Unified Resource Manager
urm 606/udp # Cray Unified Resource Manager
sift-uft 608/tcp # Sender-Initiated/Unsolicited File Transfer
sift-uft 608/udp # Sender-Initiated/Unsolicited File Transfer
npmp-trap 609/tcp # npmp-trap
npmp-trap 609/udp # npmp-trap
npmp-local 610/tcp # npmp-local
npmp-local 610/udp # npmp-local
npmp-gui 611/tcp # npmp-gui
npmp-gui 611/udp # npmp-gui
ginad 634/tcp # ginad
ginad 634/udp # ginad
mdqs 666/tcp
mdqs 666/udp
doom 666/tcp # doom Id Software
doom 666/tcp # doom Id Software
elcsd 704/tcp # errlog copy/server daemon
elcsd 704/udp # errlog copy/server daemon
entrustmanager 709/tcp # EntrustManager
entrustmanager 709/udp # EntrustManager
netviewdm1 729/tcp # IBM NetView DM/6000 Server/Client
netviewdm1 729/udp # IBM NetView DM/6000 Server/Client
netviewdm2 730/tcp # IBM NetView DM/6000 send/tcp
netviewdm2 730/udp # IBM NetView DM/6000 send/tcp
netviewdm3 731/tcp # IBM NetView DM/6000 receive/tcp
netviewdm3 731/udp # IBM NetView DM/6000 receive/tcp
netgw 741/tcp # netGW
netgw 741/udp # netGW
netrcs 742/tcp # Network based Rev. Cont. Sys.
netrcs 742/udp # Network based Rev. Cont. Sys.
flexlm 744/tcp # Flexible License Manager
flexlm 744/udp # Flexible License Manager
fujitsu-dev 747/tcp # Fujitsu Device Control
fujitsu-dev 747/udp # Fujitsu Device Control
ris-cm 748/tcp # Russell Info Sci Calendar Manager
ris-cm 748/udp # Russell Info Sci Calendar Manager
kerberos-adm 749/tcp # kerberos administration
kerberos-adm 749/udp # kerberos administration
rfile 750/tcp
loadav 750/udp
pump 751/tcp
pump 751/udp
qrh 752/tcp
qrh 752/udp
rrh 753/tcp
rrh 753/udp
tell 754/tcp # send
tell 754/udp # send
nlogin 758/tcp
nlogin 758/udp
con 759/tcp
con 759/udp
ns 760/tcp
ns 760/udp
rxe 761/tcp
rxe 761/udp
quotad 762/tcp
quotad 762/udp
cycleserv 763/tcp
cycleserv 763/udp
omserv 764/tcp
omserv 764/udp
webster 765/tcp
webster 765/udp
phonebook 767/tcp # phone
phonebook 767/udp # phone
vid 769/tcp
vid 769/udp
cadlock 770/tcp
cadlock 770/udp
rtip 771/tcp
rtip 771/udp
cycleserv2 772/tcp
cycleserv2 772/udp
submit 773/tcp
notify 773/udp
rpasswd 774/tcp
acmaint_dbd 774/udp
entomb 775/tcp
acmaint_transd 775/udp
wpages 776/tcp
wpages 776/udp
wpgs 780/tcp
wpgs 780/udp
concert 786/tcp # Concert
concert 786/udp # Concert
mdbs_daemon 800/tcp
mdbs_daemon 800/udp
device 801/tcp
device 801/udp
xtreelic 996/tcp # Central Point Software
xtreelic 996/udp # Central Point Software
maitrd 997/tcp
maitrd 997/udp
busboy 998/tcp
puparp 998/udp
garcon 999/tcp
applix 999/udp # Applix ac
puprouter 999/tcp
puprouter 999/udp
cadlock 1000/tcp
ock 1000/udp

762
contrib/ipfilter/fil.c Normal file
View File

@ -0,0 +1,762 @@
/*
* (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.
*/
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed";
static char rcsid[] = "$Id: fil.c,v 2.0.1.4 1997/02/04 13:59:41 darrenr Exp $";
#endif
#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>
#else
# include <stdio.h>
# include <string.h>
#endif
#include <sys/uio.h>
#if !defined(__SVR4) && !defined(__svr4__)
# 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>
#include "ip_fil.h"
#include "ip_compat.h"
#include "ip_nat.h"
#include "ip_frag.h"
#include "ip_state.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
#define FR_SCANLIST(p, ip, fi, m) fr_scanlist(p, ip, fi)
# if SOLARIS
# define bcmp memcmp
# endif
#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)
#define FR_SCANLIST(p, ip, fi, m) fr_scanlist(p, ip, fi, m)
extern int send_reset();
# if SOLARIS
extern int icmp_error(), ipfr_fastroute();
extern kmutex_t ipf_mutex, ipl_mutex;
# else
extern void ipfr_fastroute();
# endif
extern int ipl_unreach, ipllog();
#endif
#if SOLARIS
# 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
# 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 *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } },
*ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } };
int fr_flags = 0, fr_active = 0;
fr_info_t frcache[2];
/*
* 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.
*/
void fr_makefrip(hlen, ip, fin)
int hlen;
ip_t *ip;
fr_info_t *fin;
{
struct optlist *op;
tcphdr_t *tcp;
fr_ip_t *fi = &fin->fin_fi;
u_short optmsk = 0, secmsk = 0, auth = 0;
int i, mv, ol, off;
u_char *s, opt;
fin->fin_fr = NULL;
fin->fin_tcpf = 0;
fin->fin_data[0] = 0;
fin->fin_data[1] = 0;
fin->fin_rule = -1;
#ifdef _KERNEL
fin->fin_icode = ipl_unreach;
#endif
fi->fi_v = ip->ip_v;
fi->fi_tos = ip->ip_tos;
fin->fin_hlen = hlen;
fin->fin_dlen = ip->ip_len - hlen;
tcp = (tcphdr_t *)((char *)ip + hlen);
fin->fin_dp = (void *)tcp;
(*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4));
(*(((u_long *)fi) + 1)) = (*(((u_long *)ip) + 3));
(*(((u_long *)fi) + 2)) = (*(((u_long *)ip) + 4));
fi->fi_fl = (hlen > sizeof(struct ip)) ? FI_OPTIONS : 0;
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;
if (fin->fin_dlen > 1)
fin->fin_data[0] = *(u_short *)tcp;
break;
case IPPROTO_TCP :
fi->fi_fl |= FI_TCPUDP;
if ((!IPMINLEN(ip, tcphdr) && !off) ||
(off && off < sizeof(struct tcphdr)))
fi->fi_fl |= FI_SHORT;
if (!(fi->fi_fl & FI_SHORT) && !off)
fin->fin_tcpf = tcp->th_flags;
goto getports;
case IPPROTO_UDP :
fi->fi_fl |= FI_TCPUDP;
if ((!IPMINLEN(ip, udphdr) && !off) ||
(off && off < sizeof(struct udphdr)))
fi->fi_fl |= FI_SHORT;
getports:
if (!off && (fin->fin_dlen > 3)) {
fin->fin_data[0] = ntohs(tcp->th_sport);
fin->fin_data[1] = ntohs(tcp->th_dport);
}
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 < 2 || 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 + 2); /* 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;
}
/*
* check an IP packet for TCP/UDP characteristics such as ports and flags.
*/
int fr_tcpudpchk(fr, fin)
frentry_t *fr;
fr_info_t *fin;
{
register u_short po, tup;
register char i;
register 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 = fr->fr_dport;
tup = fin->fin_data[1];
/*
* 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 <= fr->fr_dtop))
err = 0;
else if (!--i && /* In range */
(tup <= po || tup >= fr->fr_dtop))
err = 0;
}
/*
* compare source ports
*/
if (err && (i = (int)fr->fr_scmp)) {
po = fr->fr_sport;
tup = fin->fin_data[0];
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 <= fr->fr_stop))
err = 0;
else if (!--i && /* In range */
(tup <= po || tup >= 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 && (fin->fin_fi.fi_p == IPPROTO_TCP)) {
if (fin->fin_fi.fi_fl & FI_SHORT)
return !(fr->fr_tcpf | fr->fr_tcpfm);
/*
* Match the flags ? If not, abort this match.
*/
if (fr->fr_tcpf &&
fr->fr_tcpf != (fin->fin_tcpf & fr->fr_tcpfm)) {
FR_DEBUG(("f. %#x & %#x != %#x\n", fin->fin_tcpf,
fr->fr_tcpfm, fr->fr_tcpf));
err = 0;
}
}
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, fin, m)
int pass;
ip_t *ip;
register fr_info_t *fin;
void *m;
{
register struct frentry *fr;
register fr_ip_t *fi = &fin->fin_fi;
int rulen, portcmp = 0, off;
fr = fin->fin_fr;
fin->fin_fr = NULL;
fin->fin_rule = 0;
off = ip->ip_off & 0x1fff;
pass |= (fi->fi_fl << 20);
if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off)
portcmp = 1;
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 != fin->fin_ifp)
continue;
#else
if (opts & (OPT_VERBOSE|OPT_DEBUG))
printf("\n");
FR_VERBOSE(("%c", (pass & FR_PASS) ? 'p' : 'b'));
if (fin->fin_ifp && *fr->fr_ifname &&
strcasecmp((char *)fin->fin_ifp, 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 (fi->fi_fl & FI_TCPUDP) {
if (portcmp) {
if (!fr_tcpudpchk(fr, fin))
continue;
} else if (fr->fr_dcmp || fr->fr_scmp || fr->fr_tcpf ||
fr->fr_tcpfm)
continue;
} else if (fi->fi_p == IPPROTO_ICMP) {
if (!off && (fin->fin_dlen > 1)) {
if ((fin->fin_data[0] & fr->fr_icmpm) !=
fr->fr_icmp) {
FR_DEBUG(("i. %#x & %#x != %#x\n",
fin->fin_data[0],
fr->fr_icmpm, fr->fr_icmp));
continue;
}
} else if (fr->fr_icmpm || fr->fr_icmp)
continue;
}
FR_VERBOSE(("*"));
/*
* Just log this packet...
*/
pass = fr->fr_flags;
if ((pass & FR_CALLNOW) && fr->fr_func)
pass = (*fr->fr_func)(pass, ip, fin);
#ifdef IPFILTER_LOG
if ((pass & FR_LOGMASK) == FR_LOG) {
if (!ipllog(fr->fr_flags, ip, fin, m))
frstats[fin->fin_out].fr_skip++;
frstats[fin->fin_out].fr_pkl++;
}
#endif /* IPFILTER_LOG */
FR_DEBUG(("pass %#x\n", pass));
fr->fr_hits++;
if (pass & FR_ACCOUNT)
fr->fr_bytes += ip->ip_len;
else
fin->fin_icode = fr->fr_icode;
fin->fin_rule = rulen;
fin->fin_fr = fr;
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
#ifdef _KERNEL
# if SOLARIS
, qif, q, mp)
qif_t *qif;
queue_t *q;
mblk_t **mp;
# else
, mp)
struct mbuf **mp;
# endif
#else
)
#endif
ip_t *ip;
int hlen;
struct ifnet *ifp;
int out;
{
/*
* The above really sucks, but short of writing a diff
*/
fr_info_t frinfo, *fc;
register fr_info_t *fin = &frinfo;
frentry_t *fr = NULL;
int pass, changed;
#if !defined(__SVR4) && !defined(__svr4__) && defined(_KERNEL)
register struct mbuf *m = *mp;
struct mbuf *mc = NULL;
if ((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) {
frstats[out].fr_pull[1]++;
return -1;
} else {
frstats[out].fr_pull[0]++;
m = *mp;
ip = mtod(m, struct ip *);
}
}
}
#endif
#if SOLARIS && defined(_KERNEL)
mblk_t *mc = NULL, *m = qif->qf_m;
#endif
fr_makefrip(hlen, ip, fin);
fin->fin_ifp = ifp;
fin->fin_out = out;
MUTEX_ENTER(&ipf_mutex);
if (!out) {
changed = ip_natin(ip, hlen, fin);
if ((fin->fin_fr = ipacct[0][fr_active]) &&
(FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT))
frstats[0].fr_acct++;
}
if ((pass = ipfr_knownfrag(ip, fin))) {
if ((pass & FR_KEEPSTATE)) {
if (fr_addstate(ip, fin, pass) == -1)
frstats[out].fr_bads++;
else
frstats[out].fr_ads++;
}
} else if ((pass = fr_checkstate(ip, fin))) {
if ((pass & FR_KEEPFRAG)) {
if (fin->fin_fi.fi_fl & FI_FRAG) {
if (ipfr_newfrag(ip, fin, pass) == -1)
frstats[out].fr_bnfr++;
else
frstats[out].fr_nfr++;
} else
frstats[out].fr_cfr++;
}
} else {
fc = frcache + out;
if (fc->fin_fr && !bcmp((char *)fin, (char *)fc, FI_CSIZE)) {
/*
* copy cached data so we can unlock the mutex
* earlier.
*/
bcopy((char *)fc, (char *)fin, sizeof(*fin));
frstats[out].fr_chit++;
pass = fin->fin_fr->fr_flags;
} else {
pass = FR_NOMATCH;
if ((fin->fin_fr = ipfilter[out][fr_active]))
pass = FR_SCANLIST(FR_NOMATCH, ip, fin, m);
bcopy((char *)fin, (char *)fc, FI_CSIZE);
if (pass & FR_NOMATCH) {
frstats[out].fr_nom++;
#ifdef NOMATCH
pass |= NOMATCH;
#endif
}
}
fr = fin->fin_fr;
if ((pass & FR_KEEPFRAG)) {
if (fin->fin_fi.fi_fl & FI_FRAG) {
if (ipfr_newfrag(ip, fin, pass) == -1)
frstats[out].fr_bnfr++;
else
frstats[out].fr_nfr++;
} else
frstats[out].fr_cfr++;
}
if (pass & FR_KEEPSTATE) {
if (fr_addstate(ip, fin, pass) == -1)
frstats[out].fr_bads++;
else
frstats[out].fr_ads++;
}
}
if (fr && fr->fr_func)
pass = (*fr->fr_func)(pass, ip, fin);
if (out) {
if ((fin->fin_fr = ipacct[1][fr_active]) &&
(FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT))
frstats[1].fr_acct++;
fin->fin_fr = NULL;
changed = ip_natout(ip, hlen, fin);
}
fin->fin_fr = fr;
MUTEX_EXIT(&ipf_mutex);
#ifdef IPFILTER_LOG
if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) {
if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) {
pass |= FF_LOGNOMATCH;
frstats[out].fr_npkl++;
goto logit;
} else if (((pass & FR_LOGMASK) == FR_LOGP) ||
((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) {
if ((pass & FR_LOGMASK) != FR_LOGP)
pass |= FF_LOGPASS;
frstats[out].fr_ppkl++;
goto logit;
} else if (((pass & FR_LOGMASK) == FR_LOGB) ||
((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) {
if ((pass & FR_LOGMASK) != FR_LOGB)
pass |= FF_LOGBLOCK;
frstats[out].fr_bpkl++;
logit:
if (!ipllog(pass, ip, fin, m)) {
frstats[out].fr_skip++;
if ((pass & (FR_PASS|FR_LOGORBLOCK)) ==
(FR_PASS|FR_LOGORBLOCK))
pass ^= FR_PASS|FR_BLOCK;
}
}
}
#endif /* IPFILTER_LOG */
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 ?
*/
#ifdef _KERNEL
if (pass & FR_RETICMP) {
# if SOLARIS
ICMP_ERROR(q, ip, ICMP_UNREACH, fin->fin_icode,
qif, ip->ip_src);
# else
ICMP_ERROR(m, ip, ICMP_UNREACH, fin->fin_icode,
ifp, ip->ip_src);
m = NULL; /* freed by icmp_error() */
# endif
frstats[0].fr_ret++;
} else if ((pass & FR_RETRST) &&
!(fin->fin_fi.fi_fl & FI_SHORT)) {
if (SEND_RESET(ip, qif, q) == 0)
frstats[1].fr_ret++;
}
#else
if (pass & FR_RETICMP) {
verbose("- ICMP unreachable sent\n");
frstats[0].fr_ret++;
} else if ((pass & FR_RETRST) &&
!(fin->fin_fi.fi_fl & FI_SHORT)) {
verbose("- TCP RST sent\n");
frstats[1].fr_ret++;
}
#endif
}
#ifdef _KERNEL
# if !SOLARIS
if (pass & FR_DUP)
mc = m_copy(m, 0, M_COPYALL);
if (fr) {
frdest_t *fdp = &fr->fr_tif;
if ((pass & FR_FASTROUTE) ||
(fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
ipfr_fastroute(m, fin, fdp);
m = *mp = NULL;
pass = 0;
}
if (mc)
ipfr_fastroute(mc, fin, &fr->fr_dif);
}
if (!(pass & FR_PASS) && m)
m_freem(m);
return (pass & FR_PASS) ? 0 : -1;
# else
if (pass & FR_DUP)
mc = dupmsg(m);
if (fr) {
frdest_t *fdp = &fr->fr_tif;
if ((pass & FR_FASTROUTE) ||
(fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
ipfr_fastroute(qif, ip, m, mp, fin, fdp);
m = *mp = NULL;
}
if (mc)
ipfr_fastroute(qif, ip, mc, mp, fin, &fr->fr_dif);
}
return (pass & FR_PASS) ? changed : -1;
# endif
#else
if (pass & FR_NOMATCH)
return 1;
if (pass & FR_PASS)
return 0;
return -1;
#endif
}
#ifdef IPFILTER_LOG
# if !(defined(_KERNEL))
static void ipllog()
{
verbose("l");
}
# endif
int fr_copytolog(buf, len)
char *buf;
int len;
{
int clen, tail;
tail = (iplh >= iplt) ? (iplbuf + IPLLOGSIZE - iplh) : (iplt - iplh);
clen = MIN(tail, len);
bcopy(buf, iplh, clen);
len -= clen;
tail -= clen;
iplh += clen;
buf += clen;
if (iplh == iplbuf + IPLLOGSIZE) {
iplh = iplbuf;
tail = iplt - iplh;
}
if (len && tail) {
clen = MIN(tail, len);
bcopy(buf, iplh, clen);
len -= clen;
iplh += clen;
}
return len;
}
#endif

366
contrib/ipfilter/fils.c Normal file
View File

@ -0,0 +1,366 @@
/*
* (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.
*/
#include <stdio.h>
#include <string.h>
#if !defined(__SVR4) && !defined(__svr4__)
#include <strings.h>
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <sys/file.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stddef.h>
#include <nlist.h>
#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 "ip_fil.h"
#include "ip_compat.h"
#include "ip_nat.h"
#include "ip_frag.h"
#include "ip_state.h"
#include <netdb.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include "ipf.h"
#include "kmem.h"
#ifdef __NetBSD__
#include <paths.h>
#endif
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-1996 Darren Reed";
static char rcsid[] = "$Id: fils.c,v 2.0.1.2 1997/01/30 10:21:48 darrenr Exp $";
#endif
#ifdef _PATH_UNIX
#define VMUNIX _PATH_UNIX
#else
#define VMUNIX "/vmunix"
#endif
extern char *optarg;
#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(), showfrstates();
static void showlist(), showipstates();
void Usage(name)
char *name;
{
fprintf(stderr, "Usage: %s [-afhIiosv] [-d <device>]\n", name);
exit(1);
}
int main(argc,argv)
int argc;
char *argv[];
{
friostat_t fio;
ips_stat_t ipsst;
ipfrstat_t ifrst;
char c, *name = NULL, *device = IPL_NAME;
int fd;
if (openkmem() == -1)
exit(-1);
(void)setuid(getuid());
(void)setgid(getgid());
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 'i' :
opts |= OPT_INQUE|OPT_SHOWLIST;
break;
case 'n' :
opts |= OPT_SHOWLINENO;
break;
case 'I' :
opts |= OPT_INACTIVE;
break;
case 'o' :
opts |= OPT_OUTQUE|OPT_SHOWLIST;
break;
case 's' :
opts |= OPT_IPSTATES;
break;
case 'v' :
opts |= OPT_VERBOSE;
break;
default :
Usage(argv[0]);
break;
}
}
if ((fd = open(device, O_RDONLY)) < 0) {
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) {
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);
}
return 0;
}
/*
* read the kernel stats for packets blocked and passed
*/
static void showstats(fd, fp)
int fd;
struct friostat *fp;
{
int frf = 0;
if (ioctl(fd, SIOCGETFF, &frf) == -1)
perror("ioctl(SIOCGETFF)");
#if SOLARIS
PRINTF("dropped packets:\tin %lu\tout %lu\n",
fp->f_st[0].fr_drop, fp->f_st[1].fr_drop);
PRINTF("non-ip packets:\t\tin %lu\tout %lu\n",
fp->f_st[0].fr_notip, fp->f_st[1].fr_notip);
PRINTF(" bad packets:\t\tin %lu\tout %lu\n",
fp->f_st[0].fr_bad, fp->f_st[1].fr_bad);
#endif
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);
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);
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);
PRINTF("output packets logged:\tblocked %lu passed %lu\n",
fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl);
PRINTF(" packets logged:\tinput %lu output %lu\n",
fp->f_st[0].fr_pkl, fp->f_st[1].fr_pkl);
PRINTF(" log failures:\t\tinput %lu output %lu\n",
fp->f_st[0].fr_skip, fp->f_st[1].fr_skip);
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);
PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n",
fp->f_st[0].fr_chit, fp->f_st[1].fr_chit);
PRINTF("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n",
fp->f_st[0].fr_pull[0], fp->f_st[0].fr_pull[1]);
PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n",
fp->f_st[1].fr_pull[0], fp->f_st[1].fr_pull[1]);
PRINTF("Packet log flags set: (%#x)\n", frf);
if (frf & FF_LOGPASS)
PRINTF("\tpackets passed through filter\n");
if (frf & FF_LOGBLOCK)
PRINTF("\tpackets blocked by filter\n");
if (!frf)
PRINTF("\tnone\n");
}
/*
* print out filter rule list
*/
static void showlist(fiop)
struct friostat *fiop;
{
struct frentry fb;
struct frentry *fp = NULL;
int i, set, n;
set = fiop->f_active;
if (opts & OPT_INACTIVE)
set = 1 - set;
if (opts & OPT_ACCNT) {
i = F_AC;
if (opts & OPT_OUTQUE) {
fp = (struct frentry *)fiop->f_acctout[set];
i++;
} else if (opts & OPT_INQUE)
fp = (struct frentry *)fiop->f_acctin[set];
} 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)
FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i);
if (opts & OPT_VERBOSE)
PRINTF("fp %#x set %d\n", (u_int)fp, set);
if (!fp) {
FPRINTF(stderr, "empty list for %s%s\n",
(opts & OPT_INACTIVE) ? "inactive " : "", filters[i]);
return;
}
for (n = 1; fp; n++) {
if (kmemcpy((char *)&fb, (u_long)fp, sizeof(fb)) == -1) {
perror("kmemcpy");
return;
}
fp = &fb;
if (opts & OPT_OUTQUE)
fp->fr_flags |= FR_OUTQUE;
if (opts & (OPT_HITS|OPT_VERBOSE))
PRINTF("%ld ", fp->fr_hits);
if (opts & (OPT_ACCNT|OPT_VERBOSE))
PRINTF("%ld ", fp->fr_bytes);
if (opts & OPT_SHOWLINENO)
PRINTF("@%d ", n);
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 state %d/%d\n",
inet_ntoa(ips.is_dst), ips.is_age,
ips.is_pass, ips.is_p, ips.is_state[0],
ips.is_state[1]);
if (ips.is_p == IPPROTO_TCP)
PRINTF("\t%hu -> %hu %lu:%lu %hu:%hu\n",
ntohs(ips.is_sport),
ntohs(ips.is_dport),
ips.is_seq, ips.is_ack,
ips.is_swin, ips.is_dwin);
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;
}
}

View File

@ -0,0 +1,182 @@
/*
* ++Copyright++ 1983, 1990, 1993
* -
* Copyright (c) 1983, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* -
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies, and that
* the name of Digital Equipment Corporation not be used in advertising or
* publicity pertaining to distribution of the document or software without
* specific, written prior permission.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
* -
* --Copyright--
*/
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
static char rcsid[] = "$Id: inet_addr.c,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
/*
* Check whether "cp" is a valid ascii representation
* of an Internet address and convert to a binary address.
* Returns 1 if the address is valid, 0 if not.
* This replaces inet_addr, the return value from which
* cannot distinguish between failure and a local broadcast address.
*/
int
inet_aton(cp, addr)
register const char *cp;
struct in_addr *addr;
{
register u_long val;
register int base, n;
register char c;
u_int parts[4];
register u_int *pp = parts;
c = *cp;
for (;;) {
/*
* Collect number up to ``.''.
* Values are specified as for C:
* 0x=hex, 0=octal, isdigit=decimal.
*/
if (!isdigit(c))
return (0);
val = 0; base = 10;
if (c == '0') {
c = *++cp;
if (c == 'x' || c == 'X')
base = 16, c = *++cp;
else
base = 8;
}
for (;;) {
if (isascii(c) && isdigit(c)) {
val = (val * base) + (c - '0');
c = *++cp;
} else if (base == 16 && isascii(c) && isxdigit(c)) {
val = (val << 4) |
(c + 10 - (islower(c) ? 'a' : 'A'));
c = *++cp;
} else
break;
}
if (c == '.') {
/*
* Internet format:
* a.b.c.d
* a.b.c (with c treated as 16 bits)
* a.b (with b treated as 24 bits)
*/
if (pp >= parts + 3)
return (0);
*pp++ = val;
c = *++cp;
} else
break;
}
/*
* Check for trailing characters.
*/
if (c != '\0' && (!isascii(c) || !isspace(c)))
return (0);
/*
* Concoct the address according to
* the number of parts specified.
*/
n = pp - parts + 1;
switch (n) {
case 0:
return (0); /* initial nondigit */
case 1: /* a -- 32 bits */
break;
case 2: /* a.b -- 8.24 bits */
if (val > 0xffffff)
return (0);
val |= parts[0] << 24;
break;
case 3: /* a.b.c -- 8.8.16 bits */
if (val > 0xffff)
return (0);
val |= (parts[0] << 24) | (parts[1] << 16);
break;
case 4: /* a.b.c.d -- 8.8.8.8 bits */
if (val > 0xff)
return (0);
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
break;
}
if (addr)
addr->s_addr = htonl(val);
return (1);
}
/* these are compatibility routines, not needed on recent BSD releases */
/*
* Ascii internet address interpretation routine.
* The value returned is in network order.
*/
u_long
inet_addr(cp)
register const char *cp;
{
struct in_addr val;
if (inet_aton(cp, &val))
return (val.s_addr);
return (0xffffffff);
}

View File

@ -0,0 +1,342 @@
/*
* (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_compat.h 1.8 1/14/96
* $Id: ip_compat.h,v 2.0.1.4 1997/02/04 14:24:25 darrenr Exp $
*/
#ifndef __IP_COMPAT_H_
#define __IP_COMPAT_H__
#ifndef SOLARIS
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
#endif
#if SOLARIS
#define MTYPE(m) ((m)->b_datap->db_type)
#endif
#define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h)))
#ifndef IP_OFFMASK
#define IP_OFFMASK 0x1fff
#endif
#ifndef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#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
/*
* IP option #defines
*/
/*#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 */
/*
* Build some macros and #defines to enable the same code to compile anywhere
* Well, that's the idea, anyway :-)
*/
#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)
# 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;
int (*qf_inp)();
int (*qf_outp)();
mblk_t *qf_m;
int qf_len;
char qf_name[8];
/*
* 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)
# define htons(x) (x)
# define htonl(x) (x)
# endif
# define KMALLOC(x) kmem_alloc((x), KM_NOSLEEP)
# define GET_MINOR(x) getminor(x)
# else
# define KMALLOC(x) new_kmem_alloc((x), KMEM_NOSLEEP)
# endif /* __svr4__ */
# endif /* sun && !linux */
# ifndef GET_MINOR
# define GET_MINOR(x) minor(x)
# endif
# if BSD >= 199306 || defined(__FreeBSD__)
# include <vm/vm.h>
# if !defined(__FreeBSD__)
# include <vm/vm_extern.h>
# include <sys/proc.h>
extern vm_map_t kmem_map;
# else
# include <vm/vm_kern.h>
# endif /* __FreeBSD__ */
/*
** # define KMALLOC(x) kmem_alloc(kmem_map, (x))
** # define KFREE(x) kmem_free(kmem_map, (vm_offset_t)(x), \
sizeof(*(x)))
*/
# ifdef M_PFIL
# define KMALLOC(x) malloc((x), M_PFIL, M_NOWAIT)
# define KFREE(x) FREE((x), M_PFIL)
# else
# define KMALLOC(x) malloc((x), M_TEMP, M_NOWAIT)
# define KFREE(x) FREE((x), M_TEMP)
# endif
# define UIOMOVE(a,b,c,d) uiomove(a,b,d)
# define SLEEP(id, n) tsleep((id), PPAUSE|PCATCH, n, 0)
# endif /* BSD */
# 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
# ifndef linux
# 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
#endif /* KERNEL */
#ifdef linux
# define ICMP_UNREACH ICMP_DEST_UNREACH
# define ICMP_SOURCEQUENCH ICMP_SOURCE_QUENCH
# define ICMP_TIMXCEED ICMP_TIME_EXCEEDED
# define ICMP_PARAMPROB ICMP_PARAMETERPROB
# define TH_FIN 0x01
# define TH_SYN 0x02
# define TH_RST 0x04
# define TH_PUSH 0x08
# define TH_ACK 0x10
# define TH_URG 0x20
typedef struct {
__u16 th_sport;
__u16 th_dport;
__u32 th_seq;
__u32 th_ack;
__u8 th_x;
__u8 th_flags;
__u16 th_win;
__u16 th_sum;
__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)
__u8 ip_hl:4;
__u8 ip_v:4;
# else
__u8 ip_hl:4;
__u8 ip_v:4;
# endif
__u8 ip_tos;
__u16 ip_len;
__u16 ip_id;
__u16 ip_off;
__u8 ip_ttl;
__u8 ip_p;
__u16 ip_sum;
struct in_addr ip_src;
struct in_addr ip_dst;
} ip_t;
/*
* Structure of an icmp header.
*/
struct icmp {
u_char icmp_type; /* type of message, see below */
u_char icmp_code; /* type sub code */
u_short icmp_cksum; /* ones complement cksum of struct */
union {
u_char ih_pptr; /* ICMP_PARAMPROB */
struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
struct ih_idseq {
n_short icd_id;
n_short icd_seq;
} ih_idseq;
int ih_void;
} icmp_hun;
# define icmp_pptr icmp_hun.ih_pptr
# define icmp_gwaddr icmp_hun.ih_gwaddr
# define icmp_id icmp_hun.ih_idseq.icd_id
# define icmp_seq icmp_hun.ih_idseq.icd_seq
# define icmp_void icmp_hun.ih_void
union {
struct id_ts {
n_time its_otime;
n_time its_rtime;
n_time its_ttime;
} id_ts;
struct id_ip {
ip_t idi_ip;
/* options and then 64 bits of data */
} id_ip;
u_long id_mask;
char id_data[1];
} icmp_dun;
# define icmp_otime icmp_dun.id_ts.its_otime
# define icmp_rtime icmp_dun.id_ts.its_rtime
# define icmp_ttime icmp_dun.id_ts.its_ttime
# define icmp_ip icmp_dun.id_ip.idi_ip
# define icmp_mask icmp_dun.id_mask
# define icmp_data icmp_dun.id_data
};
struct ipovly {
caddr_t ih_next, ih_prev; /* for protocol sequence q's */
u_char ih_x1; /* (unused) */
u_char ih_pr; /* protocol */
short ih_len; /* protocol length */
struct in_addr ih_src; /* source internet address */
struct in_addr ih_dst; /* destination internet address */
};
# 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)
# define UNITNAME(n) dev_get((n))
# define ifnet device
# define KMALLOC(x) kmalloc((x), GFP_ATOMIC)
# define KFREE(x) kfree_s((x), sizeof(*(x)))
# define IRCOPY(a,b,c) { \
error = verify_area(VERIFY_READ, \
(b) ,sizeof((b))); \
if (!error) \
memcpy_fromfs((b), (a), (c)); \
}
# define IWCOPY(a,b,c) { \
error = verify_area(VERIFY_WRITE, \
(b) ,sizeof((b))); \
if (!error) \
memcpy_tofs((b), (a), (c)); \
}
#else
typedef struct tcphdr tcphdr_t;
typedef struct udphdr udphdr_t;
typedef struct icmp icmphdr_t;
typedef struct ip ip_t;
#endif /* linux */
#endif /* __IP_COMPAT_H__ */

885
contrib/ipfilter/ip_fil.c Normal file
View File

@ -0,0 +1,885 @@
/*
* (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.
*/
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-1995 Darren Reed";
static char rcsid[] = "$Id: ip_fil.c,v 2.0.1.5 1997/01/29 13:41:45 darrenr Exp $";
#endif
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/systm.h>
#include <sys/uio.h>
#include <sys/mbuf.h>
#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_var.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_compat.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 struct protosw inetsw[];
extern int (*fr_checkp)();
#if BSD < 199306
extern int ipfr_slowtimer();
static int (*fr_saveslowtimo)();
extern int tcp_ttl;
#else
extern void ipfr_slowtimer();
static void (*fr_saveslowtimo)();
#endif
int ipl_inited = 0;
int ipl_unreach = ICMP_UNREACH_FILTER;
int send_reset();
#ifdef IPFILTER_LOG
# define LOGSIZE 8192
int ipllog();
char iplbuf[LOGSIZE];
caddr_t iplh = iplbuf, iplt = iplbuf;
static int iplused = 0;
#endif /* IPFILTER_LOG */
static void frflush();
static int frrequest();
static int (*fr_savep)();
#if _BSDI_VERSION >= 199501
# include <sys/device.h>
# include <sys/conf.h>
int iplioctl __P((dev_t, int, caddr_t, int, struct proc *));
int iplopen __P((dev_t, int, int, struct proc *));
int iplclose __P((dev_t, int, int, struct proc *));
# ifdef IPFILTER_LOG
int iplread __P((dev_t, struct uio *, int));
# else
# define iplread noread
# endif
int iplioctl __P((dev_t, int, caddr_t, int, struct proc *));
struct cfdriver iplcd = {
NULL, "ipl", NULL, NULL, DV_DULL, 0
};
struct devsw iplsw = {
&iplcd,
iplopen, iplclose, iplread, nowrite, iplioctl, noselect, nommap,
nostrat, nodump, nopsize, 0,
nostop
};
#endif /* _BSDI_VERSION >= 199501 */
#ifdef IPFILTER_LKM
int iplidentify(s)
char *s;
{
if (strcmp(s, "ipl") == 0)
return 1;
return 0;
}
#endif /* IPFILTER_LKM */
int iplattach()
{
int s;
SPLNET(s);
if (ipl_inited || (fr_checkp == fr_check)) {
printf("IP Filter: already initialized\n");
SPLX(s);
return EBUSY;
}
ipl_inited = 1;
bzero((char *)nat_table, sizeof(nat_t *) * NAT_SIZE * 2);
fr_savep = fr_checkp;
fr_checkp = fr_check;
fr_saveslowtimo = inetsw[0].pr_slowtimo;
inetsw[0].pr_slowtimo = ipfr_slowtimer;
SPLX(s);
return 0;
}
int ipldetach()
{
int s, i = FR_INQUE|FR_OUTQUE;
SPLNET(s);
if (!ipl_inited)
{
printf("IP Filter: not initialized\n");
SPLX(s);
return EBUSY;
}
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;
}
static void frzerostats(data)
caddr_t data;
{
struct friostat fio;
bcopy((char *)frstats, (char *)fio.f_st,
sizeof(struct filterstats) * 2);
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) * 2);
}
static void frflush(data)
caddr_t data;
{
struct frentry *f, **fp;
int flags = *(int *)data, flushed = 0, set = fr_active;
bzero((char *)frcache, sizeof(frcache[0]) * 2);
if (flags & FR_INACTIVE)
set = 1 - set;
if (flags & FR_OUTQUE) {
for (fp = &ipfilter[1][set]; (f = *fp); ) {
*fp = f->fr_next;
KFREE(f);
flushed++;
}
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;
}
/*
* Filter ioctl interface.
*/
int iplioctl(dev, cmd, data, mode
#if _BSDI_VERSION >= 199501
, p)
struct proc *p;
#else
)
#endif
dev_t dev;
int cmd;
caddr_t data;
int mode;
{
int error = 0, s, unit;
unit = minor(dev);
if (unit != 0)
return ENXIO;
SPLNET(s);
switch (cmd) {
case FIONREAD :
#ifdef IPFILTER_LOG
*(int *)data = iplused;
#endif
break;
#ifndef IPFILTER_LKM
case SIOCFRENB :
{
u_int enable;
if (!(mode & FWRITE))
error = EPERM;
else {
IRCOPY(data, (caddr_t)&enable, sizeof(enable));
if (enable)
error = iplattach();
else
error = ipldetach();
}
break;
}
#endif
case SIOCSETFF :
if (!(mode & FWRITE))
error = EPERM;
else
IRCOPY(data, (caddr_t)&fr_flags, sizeof(fr_flags));
break;
case SIOCGETFF :
IWCOPY((caddr_t)&fr_flags, data, sizeof(fr_flags));
break;
case SIOCINAFR :
case SIOCRMAFR :
case SIOCADAFR :
case SIOCZRLST :
if (!(mode & FWRITE))
error = EPERM;
else
error = frrequest(cmd, data, fr_active);
break;
case SIOCINIFR :
case SIOCRMIFR :
case SIOCADIFR :
if (!(mode & FWRITE))
error = EPERM;
else
error = frrequest(cmd, data, 1 - fr_active);
break;
case SIOCSWAPA :
if (!(mode & FWRITE))
error = EPERM;
else {
bzero((char *)frcache, sizeof(frcache[0]) * 2);
*(u_int *)data = fr_active;
fr_active = 1 - fr_active;
}
break;
case SIOCGETFS :
{
struct friostat fio;
bcopy((char *)frstats, (char *)fio.f_st,
sizeof(struct filterstats) * 2);
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;
}
case SIOCFRZST :
if (!(mode & FWRITE))
error = EPERM;
else
frzerostats(data);
break;
case SIOCIPFFL :
if (!(mode & FWRITE))
error = EPERM;
else
frflush(data);
break;
#ifdef IPFILTER_LOG
case SIOCIPFFB :
if (!(mode & FWRITE))
error = EPERM;
else {
*(int *)data = iplused;
iplh = iplt = iplbuf;
iplused = 0;
}
break;
#endif /* IPFILTER_LOG */
case SIOCADNAT :
case SIOCRMNAT :
case SIOCGNATS :
case SIOCGNATL :
case SIOCFLNAT :
case SIOCCNATL :
error = nat_ioctl(data, cmd, mode);
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;
}
SPLX(s);
return error;
}
static int frrequest(req, data, set)
int req, set;
caddr_t data;
{
register frentry_t *fp, *f, **fprev;
register frentry_t **ftail;
frentry_t fr;
frdest_t *fdp;
struct frentry frd;
int error = 0, in;
fp = &fr;
IRCOPY(data, (caddr_t)fp, sizeof(*fp));
bzero((char *)frcache, sizeof(frcache[0]) * 2);
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;
IRCOPY((char *)fp, (char *)&frd, sizeof(frd));
fp = &frd;
if (*fp->fr_ifname) {
fp->fr_ifa = GETUNIT(fp->fr_ifname);
if (!fp->fr_ifa)
fp->fr_ifa = (struct ifnet *)-1;
}
fdp = &fp->fr_dif;
fp->fr_flags &= ~FR_DUP;
if (*fdp->fd_ifname) {
fdp->fd_ifp = GETUNIT(fdp->fd_ifname);
if (!fdp->fd_ifp)
fdp->fd_ifp = (struct ifnet *)-1;
else
fp->fr_flags |= FR_DUP;
}
fdp = &fp->fr_tif;
if (*fdp->fd_ifname) {
fdp->fd_ifp = GETUNIT(fdp->fd_ifname);
if (!fdp->fd_ifp)
fdp->fd_ifp = (struct ifnet *)-1;
}
/*
* Look for a matching filter rule, but don't include the next or
* interface pointer in the comparison (fr_next, fr_ifa).
*/
for (; (f = *ftail); ftail = &f->fr_next)
if (bcmp((char *)&f->fr_ip, (char *)&fp->fr_ip,
FR_CMPSIZ) == 0)
break;
/*
* If zero'ing statistics, copy current to caller and zero.
*/
if (req == SIOCZRLST) {
if (!f)
return ESRCH;
IWCOPY((caddr_t)f, data, sizeof(*f));
f->fr_hits = 0;
f->fr_bytes = 0;
return 0;
}
if (!f) {
ftail = fprev;
if (req != SIOCINAFR && req != SIOCINIFR)
while ((f = *ftail))
ftail = &f->fr_next;
else if (fp->fr_hits)
while (--fp->fr_hits && (f = *ftail))
ftail = &f->fr_next;
f = NULL;
}
if (req == SIOCDELFR || req == SIOCRMIFR) {
if (!f)
error = ESRCH;
else {
*ftail = f->fr_next;
(void) KFREE(f);
}
} else {
if (f)
error = EEXIST;
else {
if ((f = (struct frentry *)KMALLOC(sizeof(*f)))) {
bcopy((char *)fp, (char *)f, sizeof(*f));
f->fr_hits = 0;
f->fr_next = *ftail;
*ftail = f;
} else
error = ENOMEM;
}
}
return (error);
}
#if !defined(linux)
/*
* routines below for saving IP headers to buffer
*/
int iplopen(dev, flags
#if _BSDI_VERSION >= 199501
, devtype, p)
int devtype;
struct proc *p;
#else
)
#endif
dev_t dev;
int flags;
{
u_int min = minor(dev);
if (min)
min = ENXIO;
return min;
}
int iplclose(dev, flags
#if _BSDI_VERSION >= 199501
, devtype, p)
int devtype;
struct proc *p;
#else
)
#endif
dev_t dev;
int flags;
{
u_int min = minor(dev);
if (min)
min = ENXIO;
return min;
}
# ifdef IPFILTER_LOG
/*
* iplread/ipllog
* both of these must operate with at least splnet() lest they be
* called during packet processing and cause an inconsistancy to appear in
* the filter lists.
*/
# if BSD >= 199306
int iplread(dev, uio, ioflag)
int ioflag;
# else
int iplread(dev, uio)
# endif
dev_t dev;
register struct uio *uio;
{
register int ret, s;
register size_t sz, sx;
int error;
if (!uio->uio_resid)
return 0;
while (!iplused) {
error = SLEEP(iplbuf, "ipl sleep");
if (error)
return error;
}
SPLNET(s);
sx = sz = MIN(uio->uio_resid, iplused);
if (iplh < iplt)
sz = MIN(sz, LOGSIZE - (iplt - iplbuf));
sx -= sz;
# if BSD >= 199306 || defined(__FreeBSD__)
uio->uio_rw = UIO_READ;
# endif
if (!(ret = UIOMOVE(iplt, sz, UIO_READ, uio))) {
iplt += sz;
iplused -= sz;
if ((iplh < iplt) && (iplt == iplbuf + LOGSIZE))
iplt = iplbuf;
if (sx && !(ret = UIOMOVE(iplt, sx, UIO_READ, uio))) {
iplt += sx;
iplused -= sx;
if ((iplh < iplt) && (iplt == iplbuf + LOGSIZE))
iplt = iplbuf;
}
if (!iplused) /* minimise wrapping around the end */
iplh = iplt = iplbuf;
}
SPLX(s);
return ret;
}
# endif /* IPFILTER_LOG */
#endif /* linux */
#ifdef IPFILTER_LOG
int ipllog(flags, ip, fin, m)
u_int flags;
ip_t *ip;
register fr_info_t *fin;
struct mbuf *m;
{
struct ipl_ci iplci;
register int len, mlen, hlen;
struct ifnet *ifp = fin->fin_ifp;
hlen = fin->fin_hlen;
if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
hlen += MIN(sizeof(tcphdr_t), fin->fin_dlen);
else if (ip->ip_p == IPPROTO_ICMP) {
struct icmp *icmp = (struct icmp *)((char *)ip + hlen);
switch (icmp->icmp_type) {
case ICMP_UNREACH :
case ICMP_SOURCEQUENCH :
case ICMP_REDIRECT :
case ICMP_TIMXCEED :
case ICMP_PARAMPROB :
hlen += MIN(sizeof(struct icmp) + 8, fin->fin_dlen);
break;
default :
hlen += MIN(sizeof(struct icmp), fin->fin_dlen);
break;
}
}
mlen = (flags & FR_LOGBODY) ? MIN(ip->ip_len - hlen, 128) : 0;
len = hlen + sizeof(iplci) + mlen;
if (iplused + len > LOGSIZE)
return 0;
iplused += len;
# ifdef sun
uniqtime(&iplci);
# endif
# if BSD >= 199306 || defined(__FreeBSD__)
microtime((struct timeval *)&iplci);
# endif
iplci.flags = flags;
iplci.hlen = (u_char)hlen;
iplci.plen = (u_char)mlen;
iplci.rule = fin->fin_rule;
# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603))
strncpy(iplci.ifname, ifp->if_xname, IFNAMSIZ);
# else
iplci.unit = (u_char)ifp->if_unit;
if ((iplci.ifname[0] = ifp->if_name[0]))
if ((iplci.ifname[1] = ifp->if_name[1]))
if ((iplci.ifname[2] = ifp->if_name[2]))
iplci.ifname[3] = ifp->if_name[3];
# endif
/*
* Gauranteed to succeed from above
*/
(void) fr_copytolog(&iplci, sizeof(iplci));
for (len -= sizeof(iplci); m && len > 0; m = m->m_next, len -= hlen) {
hlen = MIN(len, m->m_len);
if (fr_copytolog(mtod(m, char *), hlen))
break;
}
wakeup(iplbuf);
return 1;
}
#endif /* IPFILTER_LOG */
/*
* send_reset - this could conceivably be a call to tcp_respond(), but that
* requires a large amount of setting up and isn't any more efficient.
*/
int send_reset(ti)
struct tcpiphdr *ti;
{
struct tcpiphdr *tp;
struct ip *ip;
struct tcphdr *tcp;
struct mbuf *m;
int tlen = 0;
if (ti->ti_flags & TH_RST)
return -1; /* feedback loop */
#if BSD < 199306
m = m_get(M_DONTWAIT, MT_HEADER);
#else
m = m_gethdr(M_DONTWAIT, MT_HEADER);
m->m_data += max_linkhdr;
#endif
if (m == NULL)
return -1;
if (ti->ti_flags & TH_SYN)
tlen = 1;
m->m_len = sizeof (struct tcpiphdr);
#if BSD >= 199306
m->m_pkthdr.len = sizeof (struct tcpiphdr);
m->m_pkthdr.rcvif = (struct ifnet *)0;
#endif
bzero(mtod(m, char *), sizeof(struct tcpiphdr));
ip = mtod(m, struct ip *);
tp = mtod(m, struct tcpiphdr *);
tcp = (struct tcphdr *)((char *)ip + sizeof(struct ip));
ip->ip_src.s_addr = ti->ti_dst.s_addr;
ip->ip_dst.s_addr = ti->ti_src.s_addr;
tcp->th_dport = ti->ti_sport;
tcp->th_sport = ti->ti_dport;
tcp->th_ack = htonl(ntohl(ti->ti_seq) + tlen);
tcp->th_off = sizeof(struct tcphdr) >> 2;
tcp->th_flags = TH_RST|TH_ACK;
tp->ti_pr = ((struct ip *)ti)->ip_p;
tp->ti_len = htons(sizeof(struct tcphdr));
tcp->th_sum = in_cksum(m, sizeof(struct tcpiphdr));
ip->ip_tos = ((struct ip *)ti)->ip_tos;
ip->ip_p = ((struct ip *)ti)->ip_p;
ip->ip_len = sizeof (struct tcpiphdr);
#if BSD < 199306
ip->ip_ttl = tcp_ttl;
#else
ip->ip_ttl = ip_defttl;
#endif
/*
* extra 0 in case of multicast
*/
(void) ip_output(m, (struct mbuf *)0, 0, 0, 0);
return 0;
}
#ifndef IPFILTER_LKM
void iplinit()
{
(void) iplattach();
ip_init();
}
#endif
void ipfr_fastroute(m0, fin, fdp)
struct mbuf *m0;
fr_info_t *fin;
frdest_t *fdp;
{
register struct ip *ip, *mhip;
register struct mbuf *m = m0;
register struct route *ro;
struct ifnet *ifp = fdp->fd_ifp;
int len, off, error = 0;
int hlen = fin->fin_hlen;
struct route iproute;
struct sockaddr_in *dst;
ip = mtod(m0, struct ip *);
/*
* Route packet.
*/
ro = &iproute;
bzero((caddr_t)ro, sizeof (*ro));
dst = (struct sockaddr_in *)&ro->ro_dst;
dst->sin_family = AF_INET;
dst->sin_addr = fdp->fd_ip.s_addr ? fdp->fd_ip : ip->ip_dst;
#if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__)
# ifdef RTF_CLONING
rtalloc_ign(ro, RTF_CLONING);
# else
rtalloc_ign(ro, RTF_PRCLONING);
# endif
#else
rtalloc(ro);
#endif
if (!ifp) {
if (!(fin->fin_fr->fr_flags & FR_FASTROUTE)) {
error = -2;
goto bad;
}
if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) {
if (in_localaddr(ip->ip_dst))
error = EHOSTUNREACH;
else
error = ENETUNREACH;
goto bad;
}
if (ro->ro_rt->rt_flags & RTF_GATEWAY)
dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway;
}
ro->ro_rt->rt_use++;
/*
* For input packets which are being "fastrouted", they won't
* go back through output filtering and miss their chance to get
* NAT'd.
*/
(void) ip_natout(ip, hlen, fin);
if (fin->fin_out)
ip->ip_sum = 0;
/*
* If small enough for interface, can just send directly.
*/
if (ip->ip_len <= ifp->if_mtu) {
#ifndef sparc
ip->ip_id = htons(ip->ip_id);
ip->ip_len = htons(ip->ip_len);
ip->ip_off = htons(ip->ip_off);
#endif
if (!ip->ip_sum)
ip->ip_sum = in_cksum(m, hlen);
#if BSD >= 199306
error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
ro->ro_rt);
#else
error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst);
#endif
goto done;
}
/*
* Too large for interface; fragment if possible.
* Must be able to put at least 8 bytes per fragment.
*/
if (ip->ip_off & IP_DF) {
error = EMSGSIZE;
goto bad;
}
len = (ifp->if_mtu - hlen) &~ 7;
if (len < 8) {
error = EMSGSIZE;
goto bad;
}
{
int mhlen, firstlen = len;
struct mbuf **mnext = &m->m_act;
/*
* Loop through length of segment after first fragment,
* make new header and copy data of each part and link onto chain.
*/
m0 = m;
mhlen = sizeof (struct ip);
for (off = hlen + len; off < ip->ip_len; off += len) {
MGET(m, M_DONTWAIT, MT_HEADER);
if (m == 0) {
error = ENOBUFS;
goto bad;
}
#if BSD >= 199306
m->m_data += max_linkhdr;
#else
m->m_off = MMAXOFF - hlen;
#endif
mhip = mtod(m, struct ip *);
bcopy((char *)ip, (char *)mhip, sizeof(*ip));
if (hlen > sizeof (struct ip)) {
mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
mhip->ip_hl = mhlen >> 2;
}
m->m_len = mhlen;
mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
if (ip->ip_off & IP_MF)
mhip->ip_off |= IP_MF;
if (off + len >= ip->ip_len)
len = ip->ip_len - off;
else
mhip->ip_off |= IP_MF;
mhip->ip_len = htons((u_short)(len + mhlen));
m->m_next = m_copy(m0, off, len);
if (m->m_next == 0) {
error = ENOBUFS; /* ??? */
goto sendorfree;
}
#ifndef sparc
mhip->ip_off = htons((u_short)mhip->ip_off);
#endif
mhip->ip_sum = 0;
mhip->ip_sum = in_cksum(m, mhlen);
*mnext = m;
mnext = &m->m_act;
}
/*
* Update first fragment by trimming what's been copied out
* and updating header, then send each fragment (in order).
*/
m_adj(m0, hlen + firstlen - ip->ip_len);
ip->ip_len = htons((u_short)(hlen + firstlen));
ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
ip->ip_sum = 0;
ip->ip_sum = in_cksum(m0, hlen);
sendorfree:
for (m = m0; m; m = m0) {
m0 = m->m_act;
m->m_act = 0;
if (error == 0)
#if BSD >= 199306
error = (*ifp->if_output)(ifp, m,
(struct sockaddr *)dst, ro->ro_rt);
#else
error = (*ifp->if_output)(ifp, m,
(struct sockaddr *)dst);
#endif
else
m_freem(m);
}
}
done:
if (ro->ro_rt) {
RTFREE(ro->ro_rt);
}
return;
bad:
m_freem(m);
goto done;
}

293
contrib/ipfilter/ip_fil.h Normal file
View File

@ -0,0 +1,293 @@
/*
* (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.
*
* @(#)ip_fil.h 1.35 6/5/96
* $Id: ip_fil.h,v 2.0.1.2 1997/01/10 00:28:15 darrenr Exp $
*/
#ifndef __IP_FIL_H__
#define __IP_FIL_H__
#ifndef SOLARIS
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
#endif
#if defined(KERNEL) && !defined(_KERNEL)
#define _KERNEL
#endif
#if SOLARIS
# include <sys/ioccom.h>
# include <sys/sysmacros.h>
# ifdef _KERNEL
# include <inet/common.h>
/*
* because Solaris 2 defines these in two places :-/
*/
#undef IPOPT_EOL
#undef IPOPT_NOP
#undef IPOPT_LSRR
#undef IPOPT_RR
#undef IPOPT_SSRR
# include <inet/ip.h>
# endif
#endif
#if defined(__STDC__) || defined(__GNUC__)
#define SIOCADAFR _IOW('r', 60, struct frentry)
#define SIOCRMAFR _IOW('r', 61, struct frentry)
#define SIOCSETFF _IOW('r', 62, u_int)
#define SIOCGETFF _IOR('r', 63, u_int)
#define SIOCGETFS _IOR('r', 64, struct friostat)
#define SIOCIPFFL _IOWR('r', 65, int)
#define SIOCIPFFB _IOR('r', 66, int)
#define SIOCADIFR _IOW('r', 67, struct frentry)
#define SIOCRMIFR _IOW('r', 68, struct frentry)
#define SIOCSWAPA _IOR('r', 69, u_int)
#define SIOCINAFR _IOW('r', 70, struct frentry)
#define SIOCINIFR _IOW('r', 71, struct frentry)
#define SIOCFRENB _IOW('r', 72, u_int)
#define SIOCFRSYN _IOW('r', 73, u_int)
#define SIOCFRZST _IOWR('r', 74, struct friostat)
#define SIOCZRLST _IOWR('r', 75, struct frentry)
#else
#define SIOCADAFR _IOW(r, 60, struct frentry)
#define SIOCRMAFR _IOW(r, 61, struct frentry)
#define SIOCSETFF _IOW(r, 62, u_int)
#define SIOCGETFF _IOR(r, 63, u_int)
#define SIOCGETFS _IOR(r, 64, struct friostat)
#define SIOCIPFFL _IOWR(r, 65, int)
#define SIOCIPFFB _IOR(r, 66, int)
#define SIOCADIFR _IOW(r, 67, struct frentry)
#define SIOCRMIFR _IOW(r, 68, struct frentry)
#define SIOCSWAPA _IOR(r, 69, u_int)
#define SIOCINAFR _IOW(r, 70, struct frentry)
#define SIOCINIFR _IOW(r, 71, struct frentry)
#define SIOCFRENB _IOW(r, 72, u_int)
#define SIOCFRSYN _IOW(r, 73, u_int)
#define SIOCFRZST _IOWR(r, 74, struct friostat)
#define SIOCZRLST _IOWR(r, 75, struct frentry)
#endif
#define SIOCADDFR SIOCADAFR
#define SIOCDELFR SIOCRMAFR
#define SIOCINSFR SIOCINAFR
typedef struct fr_ip {
u_char fi_v:4; /* IP version */
u_char fi_fl:4; /* packet flags */
u_char fi_tos;
u_char fi_ttl;
u_char fi_p;
struct in_addr fi_src;
struct in_addr fi_dst;
u_long fi_optmsk; /* bitmask composed from IP options */
u_short fi_secmsk; /* bitmask composed from IP security options */
u_short fi_auth;
} fr_ip_t;
#define FI_OPTIONS 0x01
#define FI_TCPUDP 0x02 /* TCP/UCP implied comparison involved */
#define FI_FRAG 0x04
#define FI_SHORT 0x08
typedef struct fr_info {
struct fr_ip fin_fi;
void *fin_ifp;
u_short fin_data[2];
u_short fin_out;
u_char fin_tcpf;
u_char fin_icode;
u_short fin_rule;
u_short fin_hlen;
u_short fin_dlen;
char *fin_dp; /* start of data past IP header */
struct frentry *fin_fr;
} fr_info_t;
#define FI_CSIZE (sizeof(struct fr_ip) + 11)
typedef struct frdest {
void *fd_ifp;
struct in_addr fd_ip;
char fd_ifname[IFNAMSIZ];
} frdest_t;
typedef struct frentry {
struct frentry *fr_next;
struct ifnet *fr_ifa;
u_long fr_hits;
u_long fr_bytes; /* this is only incremented when a packet */
/* matches this rule and it is the last match*/
/*
* Fields after this may not change whilst in the kernel.
*/
struct fr_ip fr_ip;
struct fr_ip fr_mip; /* mask structure */
u_char fr_tcpfm; /* tcp flags mask */
u_char fr_tcpf; /* tcp flags */
u_short fr_icmpm; /* data for ICMP packets (mask) */
u_short fr_icmp;
u_char fr_scmp; /* data for port comparisons */
u_char fr_dcmp;
u_short fr_dport;
u_short fr_sport;
u_short fr_stop; /* top port for <> and >< */
u_short fr_dtop; /* top port for <> and >< */
u_long fr_flags; /* per-rule flags && options (see below) */
int (*fr_func)(); /* call this function */
char fr_icode; /* return ICMP code */
char fr_ifname[IFNAMSIZ];
struct frdest fr_tif; /* "to" interface */
struct frdest fr_dif; /* duplicate packet interfaces */
} frentry_t;
#define fr_proto fr_ip.fi_p
#define fr_ttl fr_ip.fi_ttl
#define fr_tos fr_ip.fi_tos
#define fr_dst fr_ip.fi_dst
#define fr_src fr_ip.fi_src
#define fr_dmsk fr_mip.fi_dst
#define fr_smsk fr_mip.fi_src
#ifndef offsetof
#define offsetof(t,m) (int)((&((t *)0L)->m))
#endif
#define FR_CMPSIZ (sizeof(struct frentry) - offsetof(frentry_t, fr_ip))
/*
* fr_flags
*/
#define FR_BLOCK 0x00001
#define FR_PASS 0x00002
#define FR_OUTQUE 0x00004
#define FR_INQUE 0x00008
#define FR_LOG 0x00010 /* Log */
#define FR_LOGB 0x00011 /* Log-fail */
#define FR_LOGP 0x00012 /* Log-pass */
#define FR_LOGBODY 0x00020 /* Log the body */
#define FR_LOGFIRST 0x00040 /* Log the first byte if state held */
#define FR_RETRST 0x00080 /* Return TCP RST packet - reset connection */
#define FR_RETICMP 0x00100 /* Return ICMP unreachable packet */
#define FR_NOMATCH 0x00200
#define FR_ACCOUNT 0x00400 /* count packet bytes */
#define FR_KEEPFRAG 0x00800 /* keep fragment information */
#define FR_KEEPSTATE 0x01000 /* keep `connection' state information */
#define FR_INACTIVE 0x02000
#define FR_QUICK 0x04000 /* match & stop processing list */
#define FR_FASTROUTE 0x08000 /* bypass normal routing */
#define FR_CALLNOW 0x10000 /* call another function (fr_func) if matches */
#define FR_DUP 0x20000 /* duplicate packet */
#define FR_LOGORBLOCK 0x40000 /* block the packet if it can't be logged */
#define FR_LOGMASK (FR_LOG|FR_LOGP|FR_LOGB)
/*
* recognized flags for SIOCGETFF and SIOCSETFF
*/
#define FF_LOGPASS 0x100000
#define FF_LOGBLOCK 0x200000
#define FF_LOGNOMATCH 0x400000
#define FF_LOGGING (FF_LOGPASS|FF_LOGBLOCK|FF_LOGNOMATCH)
#define FF_BLOCKNONIP 0x800000 /* Solaris2 Only */
#define FR_NONE 0
#define FR_EQUAL 1
#define FR_NEQUAL 2
#define FR_LESST 3
#define FR_GREATERT 4
#define FR_LESSTE 5
#define FR_GREATERTE 6
#define FR_OUTRANGE 7
#define FR_INRANGE 8
typedef struct filterstats {
u_long fr_pass; /* packets allowed */
u_long fr_block; /* packets denied */
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_cfr; /* add new fragment state but complete pkt */
u_long fr_bads; /* bad attempts to allocate packet state */
u_long fr_ads; /* new packet state kept */
u_long fr_chit; /* cached hit */
u_long fr_pull[2]; /* good and bad pullup attempts */
#if SOLARIS
u_long fr_bad; /* bad IP packets to the filter */
u_long fr_notip; /* packets passed through no on ip queue */
u_long fr_drop; /* packets dropped - no info for them! */
#endif
} filterstats_t;
/*
* For SIOCGETFS
*/
typedef struct friostat {
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;
typedef struct optlist {
u_short ol_val;
int ol_bit;
} optlist_t;
/*
* Log structure. Each packet header logged is prepended by one of these,
* minimize size to make most effective use of log space which should
* (ideally) be a muliple of the most common log entry size.
*/
typedef struct ipl_ci {
u_long sec;
u_long usec;
u_char hlen;
u_char plen;
u_short rule; /* assume never more than 64k rules, total */
#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603))
u_long flags;
u_char ifname[IFNAMSIZ]; /* = 32 bytes */
#else
u_long flags:24;
u_long unit:8;
u_char ifname[4]; /* = 20 bytes */
#endif
} ipl_ci_t;
#ifndef ICMP_UNREACH_FILTER
#define ICMP_UNREACH_FILTER 13
#endif
#define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h)))
#define IPLLOGSIZE 8192
extern int fr_check();
extern int fr_copytolog();
extern fr_info_t frcache[];
extern char *iplh, *iplt;
extern char iplbuf[IPLLOGSIZE];
#ifdef _KERNEL
extern struct frentry *ipfilter[2][2], *ipacct[2][2];
extern struct filterstats frstats[];
# if SOLARIS
extern int ipfsync();
# endif
#endif /* _KERNEL */
#endif /* __IP_FIL_H__ */

278
contrib/ipfilter/ip_frag.c Normal file
View File

@ -0,0 +1,278 @@
/*
* (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.
*/
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-1995 Darren Reed";
static char rcsid[] = "$Id: ip_frag.c,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp $";
#endif
#if !defined(_KERNEL) && !defined(KERNEL)
# include <string.h>
# include <stdlib.h>
#endif
#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>
#ifdef _KERNEL
# include <sys/systm.h>
#endif
#if !defined(__SVR4) && !defined(__svr4__)
# 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 "ip_fil.h"
#include "ip_compat.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,
fr_ipfrttl = 120; /* 60 seconds */
#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, fin, pass)
ip_t *ip;
fr_info_t *fin;
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 = fr_ipfrttl;
fr->ipfr_pass = pass & ~(FR_LOGFIRST|FR_LOG);
fr->ipfr_off = (ip->ip_off & 0x1fff) + (fin->fin_dlen >> 3);
*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, fin)
ip_t *ip;
fr_info_t *fin;
{
ipfr_t *f, frag;
u_int idx;
int ret;
/*
* 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)) {
u_short atoff, off;
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;
}
ret = f->ipfr_pass;
off = ip->ip_off;
atoff = (off & 0x1fff) - (fin->fin_dlen >> 3);
/*
* If we've follwed the fragments, and this is the
* last (in order), shrink expiration time.
*/
if (atoff == f->ipfr_off) {
if (!(off & IP_MF))
f->ipfr_ttl = 1;
else
f->ipfr_off = off;
}
ipfr_stats.ifs_hits++;
MUTEX_EXIT(&ipf_frag);
return ret;
}
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 && defined(_KERNEL)
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(fr);
}
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(fr);
} 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();
# if BSD < 199306
return 0;
# endif
# endif
}
#endif /* defined(_KERNEL) */

View File

@ -0,0 +1,47 @@
/*
* (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.5 3/24/96
* $Id: ip_frag.h,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp $
*/
#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_char ipfr_p;
u_char ipfr_tos;
u_short ipfr_off;
u_short ipfr_ttl;
u_char ipfr_pass;
} ipfr_t;
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__ */

886
contrib/ipfilter/ip_nat.c Normal file
View File

@ -0,0 +1,886 @@
/*
* (C)opyright 1995-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.
*
* Added redirect stuff and a LOT of bug fixes. (mcn@EnGarde.com)
*/
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)ip_nat.c 1.11 6/5/96 (C) 1995 Darren Reed";
static char rcsid[] = "$Id: ip_nat.c,v 2.0.1.10 1997/02/08 06:38:49 darrenr Exp $";
#endif
#if !defined(_KERNEL) && !defined(KERNEL)
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
#endif
#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>
#ifdef _KERNEL
# include <sys/systm.h>
#endif
#if !defined(__SVR4) && !defined(__svr4__)
# 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>
#ifdef RFC1825
#include <vpn/md5.h>
#include <vpn/ipsec.h>
extern struct ifnet vpnif;
#endif
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/tcpip.h>
#include <netinet/ip_icmp.h>
#include "ip_fil.h"
#include "ip_compat.h"
#include "ip_nat.h"
#include "ip_state.h"
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
nat_t *nat_table[2][NAT_SIZE], *nat_instances = NULL;
ipnat_t *nat_list = NULL;
u_long nat_inuse = 0,
fr_defnatage = 1200;
natstat_t nat_stats;
#if SOLARIS
# ifndef _KERNEL
#define bzero(a,b) memset(a,0,b)
#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
static int flush_nattable(), clear_natlist();
static void nattable_sync();
void fix_outcksum(sp, n)
u_short *sp;
u_long n;
{
register u_short sumshort;
register u_long sum1;
#ifdef sparc
sum1 = (~(*sp)) & 0xffff;
#else
sum1 = (~ntohs(*sp)) & 0xffff;
#endif
sum1 += (n);
sum1 = (sum1 >> 16) + (sum1 & 0xffff);
/* Again */
sum1 = (sum1 >> 16) + (sum1 & 0xffff);
sumshort = ~(u_short)sum1;
*(sp) = htons(sumshort);
}
void fix_incksum(sp, n)
u_short *sp;
u_long n;
{
register u_short sumshort;
register u_long sum1;
#ifdef sparc
sum1 = (~(*sp)) & 0xffff;
#else
sum1 = (~ntohs(*sp)) & 0xffff;
#endif
sum1 += ~(n) & 0xffff;
sum1 = (sum1 >> 16) + (sum1 & 0xffff);
/* Again */
sum1 = (sum1 >> 16) + (sum1 & 0xffff);
sumshort = ~(u_short)sum1;
*(sp) = htons(sumshort);
}
/*
* 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, mode)
caddr_t data;
int cmd, mode;
{
register ipnat_t *nat, *n = NULL, **np = NULL;
ipnat_t natd;
int error = 0, ret;
/*
* For add/delete, look to see if the NAT entry is already present
*/
MUTEX_ENTER(&ipf_nat);
if ((cmd == SIOCADNAT) || (cmd == SIOCRMNAT)) {
IRCOPY(data, (char *)&natd, sizeof(natd));
nat = &natd;
for (np = &nat_list; (n = *np); np = &n->in_next)
if (!bcmp((char *)&nat->in_flags, (char *)&n->in_flags,
IPN_CMPSIZ))
break;
}
switch (cmd)
{
case SIOCADNAT :
if (!(mode & FWRITE)) {
error = EPERM;
break;
}
if (n) {
error = EEXIST;
break;
}
if (!(n = (ipnat_t *)KMALLOC(sizeof(*n)))) {
error = ENOMEM;
break;
}
IRCOPY((char *)data, (char *)n, sizeof(*n));
n->in_ifp = (void *)GETUNIT(n->in_ifname);
n->in_next = *np;
n->in_use = 0;
n->in_space = ~(0xffffffff & ntohl(n->in_outmsk));
if (n->in_space) /* lose 2: broadcast + network address */
n->in_space -= 2;
else
n->in_space = 1; /* single IP# mapping */
if (n->in_outmsk != 0xffffffff)
n->in_nip = ntohl(n->in_outip) + 1;
else
n->in_nip = ntohl(n->in_outip);
if (n->in_redir == NAT_MAP) {
n->in_pnext = ntohs(n->in_pmin);
/*
* Multiply by the number of ports made available.
*/
if (ntohs(n->in_pmax) > ntohs(n->in_pmin))
n->in_space *= (ntohs(n->in_pmax) -
ntohs(n->in_pmin));
}
/* Otherwise, these fields are preset */
*np = n;
break;
case SIOCRMNAT :
if (!(mode & FWRITE)) {
error = EPERM;
break;
}
if (!n) {
error = ESRCH;
break;
}
*np = n->in_next;
KFREE(n);
nattable_sync();
break;
case SIOCGNATS :
nat_stats.ns_table[0] = nat_table[0];
nat_stats.ns_table[1] = nat_table[1];
nat_stats.ns_list = nat_list;
nat_stats.ns_inuse = nat_inuse;
IWCOPY((char *)&nat_stats, (char *)data, sizeof(nat_stats));
break;
case SIOCGNATL :
{
natlookup_t nl;
IRCOPY((char *)data, (char *)&nl, sizeof(nl));
if (nat_lookupredir(&nl))
IWCOPY((char *)&nl, (char *)data, sizeof(nl));
else
error = ESRCH;
break;
}
case SIOCFLNAT :
if (!(mode & FWRITE)) {
error = EPERM;
break;
}
ret = flush_nattable();
IWCOPY((caddr_t)&ret, data, sizeof(ret));
break;
case SIOCCNATL :
if (!(mode & FWRITE)) {
error = EPERM;
break;
}
ret = clear_natlist();
IWCOPY((caddr_t)&ret, data, sizeof(ret));
break;
}
MUTEX_EXIT(&ipf_nat);
return error;
}
static void nat_delete(natd)
struct nat *natd;
{
register struct nat **natp, *nat;
for (natp = natd->nat_hstart[0]; (nat = *natp);
natp = &nat->nat_hnext[0])
if (nat == natd) {
*natp = nat->nat_hnext[0];
break;
}
for (natp = natd->nat_hstart[1]; (nat = *natp);
natp = &nat->nat_hnext[1])
if (nat == natd) {
*natp = nat->nat_hnext[1];
break;
}
if (natd->nat_ptr) {
natd->nat_ptr->in_space++;
natd->nat_ptr->in_use--;
}
KFREE(natd);
nat_inuse--;
}
/*
* flush_nattable - clear the NAT table of all mapping entries.
*/
static int flush_nattable()
{
register nat_t *nat, **natp;
register int j = 0;
/*
* Everything will be deleted, so lets just make it the deletions
* quicker.
*/
bzero((char *)nat_table[0], sizeof(nat_table[0]));
bzero((char *)nat_table[1], sizeof(nat_table[1]));
for (natp = &nat_instances; (nat = *natp); ) {
*natp = nat->nat_next;
nat_delete(nat);
j++;
}
return j;
}
/*
* I know this is O(N*M), but it can't be avoided.
*/
static void nattable_sync()
{
register nat_t *nat;
register ipnat_t *np;
int i;
for (i = NAT_SIZE - 1; i >= 0; i--)
for (nat = nat_instances; nat; nat = nat->nat_next) {
for (np = nat_list; np; np = np->in_next)
if (nat->nat_ptr == np)
break;
/*
* XXX - is it better to remove this if ? works the
* same if it is just "nat->nat_ptr = np".
*/
if (!np)
nat->nat_ptr = NULL;
}
}
/*
* clear_natlist - delete all entries in the active NAT mapping list.
*/
static int clear_natlist()
{
register ipnat_t *n, **np;
int i = 0;
for (np = &nat_list; (n = *np); i++) {
*np = n->in_next;
KFREE(n);
}
nattable_sync();
return i;
}
/*
* Create a new NAT table entry.
*/
nat_t *nat_new(np, ip, fin, flags, direction)
ipnat_t *np;
ip_t *ip;
fr_info_t *fin;
u_short flags;
int direction;
{
register u_long sum1, sum2, sumd;
u_short port = 0, sport = 0, dport = 0, nport = 0;
struct in_addr in;
tcphdr_t *tcp = NULL;
nat_t *nat, **natp;
u_short nflags;
nflags = flags & np->in_flags;
if (flags & IPN_TCPUDP) {
tcp = (tcphdr_t *)fin->fin_dp;
sport = tcp->th_sport;
dport = tcp->th_dport;
}
/* Give me a new nat */
if (!(nat = (nat_t *)KMALLOC(sizeof(*nat))))
return NULL;
bzero((char *)nat, sizeof(*nat));
/*
* Search the current table for a match.
*/
if (direction == NAT_OUTBOUND) {
/*
* If it's an outbound packet which doesn't match any existing
* record, then create a new port
*/
do {
port = 0;
in.s_addr = np->in_nip;
if (nflags & IPN_TCPUDP) {
port = htons(np->in_pnext++);
if (np->in_pnext >= ntohs(np->in_pmax)) {
np->in_pnext = ntohs(np->in_pmin);
np->in_space--;
if (np->in_outmsk != 0xffffffff)
np->in_nip++;
}
} else if (np->in_outmsk != 0xffffffff) {
np->in_space--;
np->in_nip++;
}
if (!port && (flags & IPN_TCPUDP))
port = sport;
if ((np->in_nip & ntohl(np->in_outmsk)) >
ntohl(np->in_outip))
np->in_nip = ntohl(np->in_outip) + 1;
} while (nat_inlookup(flags, ip->ip_dst, dport, in, port));
/* Setup the NAT table */
nat->nat_inip = ip->ip_src;
nat->nat_outip.s_addr = htonl(in.s_addr);
nat->nat_oip = ip->ip_dst;
sum1 = (ntohl(ip->ip_src.s_addr) & 0xffff) +
(ntohl(ip->ip_src.s_addr) >> 16) + ntohs(sport);
sum2 = (in.s_addr & 0xffff) + (in.s_addr >> 16) + ntohs(port);
if (flags & IPN_TCPUDP) {
nat->nat_inport = sport;
nat->nat_outport = port;
nat->nat_oport = dport;
}
} else {
/*
* Otherwise, it's an inbound packet. Most likely, we don't
* want to rewrite source ports and source addresses. Instead,
* we want to rewrite to a fixed internal address and fixed
* internal port.
*/
in.s_addr = ntohl(np->in_inip);
if (!(nport = np->in_pnext))
nport = dport;
nat->nat_inip.s_addr = htonl(in.s_addr);
nat->nat_outip = ip->ip_dst;
nat->nat_oip = ip->ip_src;
sum1 = (ntohl(ip->ip_dst.s_addr) & 0xffff) +
(ntohl(ip->ip_dst.s_addr) >> 16) + ntohs(dport);
sum2 = (in.s_addr & 0xffff) + (in.s_addr >> 16) + ntohs(nport);
if (flags & IPN_TCPUDP) {
nat->nat_inport = nport;
nat->nat_outport = dport;
nat->nat_oport = sport;
}
}
/* Do it twice */
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
/* Do it twice */
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
if (sum1 > sum2)
sum2--; /* Because ~1 == -2, We really need ~1 == -1 */
sumd = sum2 - sum1;
sumd = (sumd & 0xffff) + (sumd >> 16);
nat->nat_sumd = (sumd & 0xffff) + (sumd >> 16);
if ((flags & IPN_TCPUDP) && ((sport != port) || (dport != nport))) {
if (direction == NAT_OUTBOUND)
sum1 = (ntohl(ip->ip_src.s_addr) & 0xffff) +
(ntohl(ip->ip_src.s_addr) >> 16);
else
sum1 = (ntohl(ip->ip_dst.s_addr) & 0xffff) +
(ntohl(ip->ip_dst.s_addr) >> 16);
sum2 = (in.s_addr & 0xffff) + (in.s_addr >> 16);
/* Do it twice */
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
/* Do it twice */
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
if (sum1 > sum2)
sum2--; /* Because ~1 == -2, We really need ~1 == -1 */
sumd = sum2 - sum1;
sumd = (sumd & 0xffff) + (sumd >> 16);
nat->nat_ipsumd = (sumd & 0xffff) + (sumd >> 16);
} else
nat->nat_ipsumd = nat->nat_sumd;
in.s_addr = htonl(in.s_addr);
nat->nat_next = nat_instances;
nat_instances = nat;
natp = &nat_table[0][nat->nat_inip.s_addr % NAT_SIZE];
nat->nat_hstart[0] = natp;
nat->nat_hnext[0] = *natp;
*natp = nat;
natp = &nat_table[1][nat->nat_outip.s_addr % NAT_SIZE];
nat->nat_hstart[1] = natp;
nat->nat_hnext[1] = *natp;
*natp = nat;
nat->nat_ptr = np;
np->in_use++;
if (direction == NAT_OUTBOUND) {
if (flags & IPN_TCPUDP)
tcp->th_sport = htons(port);
} else {
if (flags & IPN_TCPUDP)
tcp->th_dport = htons(nport);
}
nat_stats.ns_added++;
nat_inuse++;
return nat;
}
/*
* NB: these lookups don't lock access to the list, it assume it has already
* been done!
*/
/*
* Lookup a nat entry based on the mapped destination ip address/port and
* real source address/port. We use this lookup when receiving a packet,
* we're looking for a table entry, based on the destination address.
* NOTE: THE PACKET BEING CHECKED (IF FOUND) HAS A MAPPING ALREADY.
*/
nat_t *nat_inlookup(flags, src, sport, mapdst, mapdport)
register int flags;
struct in_addr src , mapdst;
u_short sport, mapdport;
{
register nat_t *nat;
flags &= IPN_TCPUDP;
nat = nat_table[1][mapdst.s_addr % NAT_SIZE];
for (; nat; nat = nat->nat_hnext[1])
if (nat->nat_oip.s_addr == src.s_addr &&
nat->nat_outip.s_addr == mapdst.s_addr &&
(!flags || (nat->nat_oport == sport &&
nat->nat_outport == mapdport)))
return nat;
return NULL;
}
/*
* Lookup a nat entry based on the source 'real' ip address/port and
* destination address/port. We use this lookup when sending a packet out,
* we're looking for a table entry, based on the source address.
* NOTE: THE PACKET BEING CHECKED (IF FOUND) HAS A MAPPING ALREADY.
*/
nat_t *nat_outlookup(flags, src, sport, dst, dport)
register int flags;
struct in_addr src , dst;
u_short sport, dport;
{
register nat_t *nat;
flags &= IPN_TCPUDP;
nat = nat_table[0][src.s_addr % NAT_SIZE];
for (; nat; nat = nat->nat_hnext[0])
if (nat->nat_inip.s_addr == src.s_addr &&
nat->nat_oip.s_addr == dst.s_addr &&
(!flags || (nat->nat_inport == sport &&
nat->nat_oport == dport)))
return nat;
return NULL;
}
/*
* Lookup a nat entry based on the mapped source ip address/port and
* real destination address/port. We use this lookup when sending a packet
* out, we're looking for a table entry, based on the source address.
*/
nat_t *nat_lookupmapip(flags, mapsrc, mapsport, dst, dport)
register int flags;
struct in_addr mapsrc , dst;
u_short mapsport, dport;
{
register nat_t *nat;
flags &= IPN_TCPUDP;
nat = nat_table[1][mapsrc.s_addr % NAT_SIZE];
for (; nat; nat = nat->nat_hnext[0])
if (nat->nat_outip.s_addr == mapsrc.s_addr &&
nat->nat_oip.s_addr == dst.s_addr &&
(!flags || (nat->nat_outport == mapsport &&
nat->nat_oport == dport)))
return nat;
return NULL;
}
/*
* Lookup the NAT tables to search for a matching redirect
*/
nat_t *nat_lookupredir(np)
register natlookup_t *np;
{
nat_t *nat;
/*
* If nl_inip is non null, this is a lookup based on the real
* ip address. Else, we use the fake.
*/
if ((nat = nat_outlookup(IPN_TCPUDP, np->nl_inip, np->nl_inport,
np->nl_outip, np->nl_outport))) {
np->nl_inip = nat->nat_outip;
np->nl_inport = nat->nat_outport;
}
return nat;
}
/*
* Packets going out on the external interface go through this.
* Here, the source address requires alteration, if anything.
*/
int ip_natout(ip, hlen, fin)
ip_t *ip;
int hlen;
fr_info_t *fin;
{
register ipnat_t *np;
register u_long ipa;
tcphdr_t *tcp = NULL;
nat_t *nat;
u_short nflags = 0, sport = 0, dport = 0, *csump = NULL;
struct ifnet *ifp;
frentry_t *fr;
if ((fr = fin->fin_fr) && !(fr->fr_flags & FR_DUP) &&
fr->fr_tif.fd_ifp && fr->fr_tif.fd_ifp != (void *)-1)
ifp = fr->fr_tif.fd_ifp;
else
ifp = fin->fin_ifp;
if (!(ip->ip_off & 0x1fff) && !(fin->fin_fi.fi_fl & FI_SHORT)) {
if (ip->ip_p == IPPROTO_TCP)
nflags = IPN_TCP;
else if (ip->ip_p == IPPROTO_UDP)
nflags = IPN_UDP;
if (nflags) {
tcp = (tcphdr_t *)fin->fin_dp;
sport = tcp->th_sport;
dport = tcp->th_dport;
}
}
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) &&
((np->in_redir == NAT_MAP) ||
(np->in_pnext == sport))) {
/*
* If there is no current entry in the nat table for
* this IP#, create one for it.
*/
if (!(nat = nat_outlookup(nflags, ip->ip_src, sport,
ip->ip_dst, dport))) {
if (np->in_redir == NAT_REDIRECT)
continue;
/*
* if it's a redirection, then we don't want
* to create new outgoing port stuff.
* Redirections are only for incoming
* connections.
*/
if (!(nat = nat_new(np, ip, fin, nflags,
NAT_OUTBOUND)))
break;
}
ip->ip_src = nat->nat_outip;
nat->nat_age = fr_defnatage; /* 5 mins */
/*
* Fix up checksums, not by recalculating them, but
* simply computing adjustments.
*/
#if SOLARIS
if (np->in_redir == NAT_MAP)
fix_outcksum(&ip->ip_sum, nat->nat_ipsumd);
else
fix_incksum(&ip->ip_sum, nat->nat_ipsumd);
#endif
if (nflags && !(ip->ip_off & 0x1fff) &&
!(fin->fin_fi.fi_fl & FI_SHORT)) {
if (nat->nat_outport)
tcp->th_sport = nat->nat_outport;
if (ip->ip_p == IPPROTO_TCP) {
csump = &tcp->th_sum;
set_tcp_age(&nat->nat_age,
nat->nat_state, ip, fin,1);
} else if (ip->ip_p == IPPROTO_UDP) {
udphdr_t *udp = (udphdr_t *)tcp;
if (udp->uh_sum)
csump = &udp->uh_sum;
} else if (ip->ip_p == IPPROTO_ICMP) {
icmphdr_t *ic = (icmphdr_t *)tcp;
csump = &ic->icmp_cksum;
}
if (csump) {
if (np->in_redir == NAT_MAP)
fix_outcksum(csump,
nat->nat_sumd);
else
fix_incksum(csump,
nat->nat_sumd);
}
}
nat_stats.ns_mapped[1]++;
MUTEX_EXIT(&ipf_nat);
return 1;
}
MUTEX_EXIT(&ipf_nat);
return 0;
}
/*
* Packets coming in from the external interface go through this.
* Here, the destination address requires alteration, if anything.
*/
int ip_natin(ip, hlen, fin)
ip_t *ip;
int hlen;
fr_info_t *fin;
{
register ipnat_t *np;
register struct in_addr in;
struct ifnet *ifp = fin->fin_ifp;
tcphdr_t *tcp = NULL;
u_short sport = 0, dport = 0, nflags = 0, *csump = NULL;
nat_t *nat;
if (!(ip->ip_off & 0x1fff) && !(fin->fin_fi.fi_fl & FI_SHORT)) {
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);
dport = tcp->th_dport;
sport = tcp->th_sport;
}
}
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) &&
(np->in_redir == NAT_MAP || np->in_pmin == dport)) {
if (!(nat = nat_inlookup(nflags, ip->ip_src, sport,
ip->ip_dst, dport))) {
if (np->in_redir == NAT_MAP)
continue;
else {
/*
* If this rule (np) is a redirection,
* rather than a mapping, then do a
* nat_new. Otherwise, if it's just a
* mapping, do a continue;
*/
if (!(nat = nat_new(np, ip, fin,
nflags,
NAT_INBOUND)))
break;
}
}
ip->ip_dst = nat->nat_inip;
nat->nat_age = fr_defnatage;
/*
* Fix up checksums, not by recalculating them, but
* simply computing adjustments.
*/
#if SOLARIS
if (np->in_redir == NAT_MAP)
fix_incksum(&ip->ip_sum, nat->nat_ipsumd);
else
fix_outcksum(&ip->ip_sum, nat->nat_ipsumd);
#endif
if (nflags && !(ip->ip_off & 0x1fff) &&
!(fin->fin_fi.fi_fl & FI_SHORT)) {
if (nat->nat_inport)
tcp->th_dport = nat->nat_inport;
if (ip->ip_p == IPPROTO_TCP) {
csump = &tcp->th_sum;
set_tcp_age(&nat->nat_age,
nat->nat_state, ip, fin,0);
} else if (ip->ip_p == IPPROTO_UDP) {
udphdr_t *udp = (udphdr_t *)tcp;
if (udp->uh_sum)
csump = &udp->uh_sum;
} else if (ip->ip_p == IPPROTO_ICMP) {
icmphdr_t *ic = (icmphdr_t *)tcp;
csump = &ic->icmp_cksum;
}
if (csump) {
if (np->in_redir == NAT_MAP)
fix_incksum(csump,
nat->nat_sumd);
else
fix_outcksum(csump,
nat->nat_sumd);
}
}
nat_stats.ns_mapped[0]++;
MUTEX_EXIT(&ipf_nat);
return 1;
}
MUTEX_EXIT(&ipf_nat);
return 0;
}
/*
* Free all memory used by NAT structures allocated at runtime.
*/
void ip_natunload()
{
MUTEX_ENTER(&ipf_nat);
(void) clear_natlist();
(void) flush_nattable();
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;
MUTEX_ENTER(&ipf_nat);
for (natp = &nat_instances; (nat = *natp); natp = &nat->nat_next) {
if (--nat->nat_age)
continue;
*natp = nat->nat_next;
nat_delete(nat);
nat_stats.ns_expire++;
}
MUTEX_EXIT(&ipf_nat);
}

118
contrib/ipfilter/ip_nat.h Normal file
View File

@ -0,0 +1,118 @@
/*
* (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.5 2/4/96
* $Id: ip_nat.h,v 2.0.1.7 1997/01/30 12:39:41 darrenr Exp $
*/
#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)
#define SIOCGNATL _IOWR('r', 83, struct natlookup)
#define SIOCGFRST _IOR('r', 84, struct ipfrstat)
#define SIOCGIPST _IOR('r', 85, struct ips_stat)
#define SIOCFLNAT _IOWR('r', 86, int)
#define SIOCCNATL _IOWR('r', 87, int)
#else
#define SIOCADNAT _IOW(r, 80, struct ipnat)
#define SIOCRMNAT _IOW(r, 81, struct ipnat)
#define SIOCGNATS _IOR(r, 82, struct natstat)
#define SIOCGNATL _IOWR(r, 83, struct natlookup)
#define SIOCGFRST _IOR(r, 84, struct ipfrstat)
#define SIOCGIPST _IOR(r, 85, struct ips_stat)
#define SIOCFLNAT _IOWR(r, 86, int)
#define SIOCCNATL _IOWR(r, 87, int)
#endif
#define NAT_SIZE 367
typedef struct nat {
int nat_age;
u_long nat_sumd;
u_long nat_ipsumd;
struct in_addr nat_inip;
struct in_addr nat_outip;
struct in_addr nat_oip; /* other ip */
u_short nat_oport; /* other port */
u_short nat_inport;
u_short nat_outport;
u_short nat_use;
u_char nat_state[2];
struct ipnat *nat_ptr;
struct nat *nat_next;
struct nat *nat_hnext[2];
struct nat **nat_hstart[2];
} nat_t;
typedef struct ipnat {
struct ipnat *in_next;
void *in_ifp;
u_int in_space;
u_int in_use;
struct in_addr in_nextip;
u_short in_pnext;
u_short in_flags;
u_short in_port[2];
struct in_addr in_in[2];
struct in_addr in_out[2];
int in_redir; /* 0 if it's a mapping, 1 if it's a hard redir */
char in_ifname[IFNAMSIZ];
} ipnat_t;
#define in_pmin in_port[0] /* Also holds static redir port */
#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 NAT_INBOUND 0
#define NAT_OUTBOUND 1
#define NAT_MAP 0
#define NAT_REDIRECT 1
#define IPN_CMPSIZ (sizeof(struct in_addr) * 4 + sizeof(u_short) * 3 + \
sizeof(int))
typedef struct natlookup {
struct in_addr nl_inip;
struct in_addr nl_outip;
u_short nl_inport;
u_short nl_outport;
} natlookup_t;
typedef struct natstat {
u_long ns_mapped[2];
u_long ns_added;
u_long ns_expire;
u_long ns_inuse;
nat_t **ns_table[2];
ipnat_t *ns_list;
} natstat_t;
#define IPN_ANY 0
#define IPN_TCP 1
#define IPN_UDP 2
#define IPN_TCPUDP 3
extern nat_t *nat_table[2][NAT_SIZE];
extern int nat_ioctl();
extern nat_t *nat_outlookup(), *nat_inlookup(), *nat_lookupredir();
extern int ip_natout(), ip_natin();
extern void ip_natunload(), ip_natexpire();
#endif /* __IP_NAT_H__ */

731
contrib/ipfilter/ip_sfil.c Normal file
View File

@ -0,0 +1,731 @@
/*
* (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.
*
* I hate legaleese, don't you ?
*/
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "%W% %G% (C) 1993-1995 Darren Reed";
static char rcsid[] = "$Id: ip_sfil.c,v 2.0.1.3 1997/02/04 14:49:15 darrenr Exp $";
#endif
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/param.h>
#include <sys/cpuvar.h>
#include <sys/open.h>
#include <sys/ioctl.h>
#include <sys/systm.h>
#include <sys/cred.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/ksynch.h>
#include <sys/kmem.h>
#include <sys/mkdev.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/dditypes.h>
#include <sys/cmn_err.h>
#include <net/if.h>
#include <net/af.h>
#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 "ip_fil.h"
#include "ip_compat.h"
#include "ip_state.h"
#include "ip_frag.h"
#include "ip_nat.h"
#include <inet/ip_ire.h>
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
extern fr_flags, fr_active;
int ipfr_timer_id = 0;
int ipl_unreach = ICMP_UNREACH_HOST;
int send_reset();
#ifdef IPFILTER_LOG
int ipllog();
static void frflush();
char iplbuf[IPLLOGSIZE];
caddr_t iplh = iplbuf, iplt = iplbuf;
static int iplused = 0;
#endif /* IPFILTER_LOG */
static int frrequest();
kmutex_t ipl_mutex, ipf_mutex, ipfs_mutex;
kmutex_t ipf_frag, ipf_state, ipf_nat;
kcondvar_t iplwait;
extern void ipfr_slowtimer();
int ipldetach()
{
int i = FR_INQUE|FR_OUTQUE;
untimeout(ipfr_timer_id);
frflush((caddr_t)&i);
ipfr_unload();
fr_stateunload();
ip_natunload();
cv_destroy(&iplwait);
mutex_destroy(&ipl_mutex);
mutex_destroy(&ipf_mutex);
mutex_destroy(&ipfs_mutex);
mutex_destroy(&ipf_frag);
mutex_destroy(&ipf_state);
mutex_destroy(&ipf_nat);
return 0;
}
int iplattach()
{
bzero((char *)nat_table, sizeof(nat_t *) * NAT_SIZE * 2);
mutex_init(&ipl_mutex, "ipf log mutex", MUTEX_DRIVER, NULL);
mutex_init(&ipf_mutex, "ipf filter mutex", MUTEX_DRIVER, NULL);
mutex_init(&ipfs_mutex, "ipf solaris mutex", MUTEX_DRIVER, NULL);
mutex_init(&ipf_frag, "ipf fragment mutex", MUTEX_DRIVER, NULL);
mutex_init(&ipf_state, "ipf IP state mutex", MUTEX_DRIVER, NULL);
mutex_init(&ipf_nat, "ipf IP NAT mutex", MUTEX_DRIVER, NULL);
cv_init(&iplwait, "ipl condvar", CV_DRIVER, NULL);
ipfr_timer_id = timeout(ipfr_slowtimer, NULL, HZ/2);
return 0;
}
static void frzerostats(data)
caddr_t data;
{
struct friostat fio;
bcopy((char *)frstats, (char *)fio.f_st,
sizeof(struct filterstats) * 2);
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) * 2);
}
#ifdef IPFILTER_LOG
static void frflush(data)
caddr_t data;
{
struct frentry *f, **fp;
int flags, flushed = 0, set = fr_active;
IRCOPY(data, (caddr_t)&flags, sizeof(flags));
bzero((char *)frcache, sizeof(frcache[0]) * 2);
if (flags & FR_INACTIVE)
set = 1 - set;
if (flags & FR_OUTQUE) {
for (fp = &ipfilter[1][set]; (f = *fp); ) {
*fp = f->fr_next;
KFREE(f);
flushed++;
}
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++;
}
}
IWCOPY((caddr_t)&flushed, data, sizeof(flushed));
}
#endif /* IPFILTER_LOG */
/*
* Filter ioctl interface.
*/
int iplioctl(dev, cmd, data, mode, cp, rp)
dev_t dev;
int cmd;
caddr_t data;
int mode;
cred_t *cp;
int *rp;
{
int error = 0;
switch (cmd) {
case SIOCFRENB :
{
u_int enable;
if (!(mode & FWRITE))
return EPERM;
IRCOPY(data, (caddr_t)&enable, sizeof(enable));
break;
}
case SIOCSETFF :
if (!(mode & FWRITE))
return EPERM;
mutex_enter(&ipf_mutex);
IRCOPY(data, (caddr_t)&fr_flags, sizeof(fr_flags));
mutex_exit(&ipf_mutex);
break;
case SIOCGETFF :
IWCOPY((caddr_t)&fr_flags, data, sizeof(fr_flags));
break;
case SIOCINAFR :
case SIOCRMAFR :
case SIOCADAFR :
case SIOCZRLST :
if (!(mode & FWRITE))
return EPERM;
mutex_enter(&ipf_mutex);
error = frrequest(cmd, data, fr_active);
mutex_exit(&ipf_mutex);
break;
case SIOCINIFR :
case SIOCRMIFR :
case SIOCADIFR :
if (!(mode & FWRITE))
return EPERM;
mutex_enter(&ipf_mutex);
error = frrequest(cmd, data, 1 - fr_active);
mutex_exit(&ipf_mutex);
break;
case SIOCSWAPA :
if (!(mode & FWRITE))
return EPERM;
mutex_enter(&ipf_mutex);
bzero((char *)frcache, sizeof(frcache[0]) * 2);
IWCOPY((caddr_t)&fr_active, (caddr_t)data, sizeof(fr_active));
fr_active = 1 - fr_active;
mutex_exit(&ipf_mutex);
break;
case SIOCGETFS :
{
struct friostat fio;
mutex_enter(&ipf_mutex);
bcopy((char *)frstats, (char *)fio.f_st,
sizeof(struct filterstats) * 2);
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;
mutex_exit(&ipf_mutex);
IWCOPY((caddr_t)&fio, data, sizeof(fio));
break;
}
case SIOCFRZST :
if (!(mode & FWRITE))
return EPERM;
frzerostats(data);
break;
#ifdef IPFILTER_LOG
case SIOCIPFFL :
if (!(mode & FWRITE))
return EPERM;
mutex_enter(&ipf_mutex);
frflush(data);
mutex_exit(&ipf_mutex);
break;
case SIOCIPFFB :
if (!(mode & FWRITE))
return EPERM;
mutex_enter(&ipl_mutex);
IWCOPY((caddr_t)&iplused, data, sizeof(iplused));
iplh = iplt = iplbuf;
iplused = 0;
mutex_exit(&ipl_mutex);
break;
#endif /* IPFILTER_LOG */
case SIOCFRSYN :
if (!(mode & FWRITE))
return EPERM;
error = ipfsync();
break;
case SIOCADNAT :
case SIOCRMNAT :
case SIOCGNATS :
case SIOCGNATL :
case SIOCFLNAT :
case SIOCCNATL :
error = nat_ioctl(data, cmd, mode);
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;
}
return error;
}
ill_t *get_unit(name)
char *name;
{
ill_t *il;
int len = strlen(name) + 1; /* includes \0 */
for (il = ill_g_head; il; il = il->ill_next)
if ((len == il->ill_name_length) &&
!strncmp(il->ill_name, name, len))
return il;
return NULL;
}
static int frrequest(req, data, set)
int req, set;
caddr_t data;
{
register frentry_t *fp, *f, **fprev;
register frentry_t **ftail;
frentry_t fr;
frdest_t *fdp;
int error = 0, in;
ill_t *ill;
ipif_t *ipif;
ire_t *ire;
fp = &fr;
IRCOPY(data, (caddr_t)fp, sizeof(*fp));
bzero((char *)frcache, sizeof(frcache[0]) * 2);
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;
if (*fp->fr_ifname) {
fp->fr_ifa = (struct ifnet *)get_unit((char *)fp->fr_ifname);
if (!fp->fr_ifa)
fp->fr_ifa = (struct ifnet *)-1;
}
fdp = &fp->fr_dif;
fp->fr_flags &= ~FR_DUP;
if (*fdp->fd_ifname) {
ill = get_unit(fdp->fd_ifname);
if (!ill)
ire = (ire_t *)-1;
else if ((ipif = ill->ill_ipif)) {
ire = ire_lookup_myaddr(ipif->ipif_local_addr);
if (!ire)
ire = (ire_t *)-1;
else
fp->fr_flags |= FR_DUP;
}
fdp->fd_ifp = (struct ifnet *)ire;
}
fdp = &fp->fr_tif;
if (*fdp->fd_ifname) {
ill = get_unit(fdp->fd_ifname);
if (!ill)
ire = (ire_t *)-1;
else if ((ipif = ill->ill_ipif)) {
ire = ire_lookup_myaddr(ipif->ipif_local_addr);
if (!ire)
ire = (ire_t *)-1;
}
fdp->fd_ifp = (struct ifnet *)ire;
}
/*
* Look for a matching filter rule, but don't include the next or
* interface pointer in the comparison (fr_next, fr_ifa).
*/
for (; (f = *ftail); ftail = &f->fr_next)
if (bcmp((char *)&f->fr_ip, (char *)&fp->fr_ip,
FR_CMPSIZ) == 0)
break;
/*
* If zero'ing statistics, copy current to caller and zero.
*/
if (req == SIOCZRLST) {
if (!f)
return ESRCH;
IWCOPY((caddr_t)f, data, sizeof(*f));
f->fr_hits = 0;
f->fr_bytes = 0;
return 0;
}
if (!f) {
ftail = fprev;
if (req != SIOCINAFR && req != SIOCINIFR)
while ((f = *ftail))
ftail = &f->fr_next;
else if (fp->fr_hits)
while (--fp->fr_hits && (f = *ftail))
ftail = &f->fr_next;
f = NULL;
}
if (req == SIOCDELFR || req == SIOCRMIFR) {
if (!f)
error = ESRCH;
else {
*ftail = f->fr_next;
KFREE(f);
}
} else {
if (f)
error = EEXIST;
else {
if ((f = (struct frentry *)KMALLOC(sizeof(*f)))) {
bcopy((char *)fp, (char *)f, sizeof(*f));
f->fr_hits = 0;
f->fr_next = *ftail;
*ftail = f;
} else
error = ENOMEM;
}
}
return (error);
}
/*
* routines below for saving IP headers to buffer
*/
int iplopen(devp, flags, otype, cred)
dev_t *devp;
int flags, otype;
cred_t *cred;
{
u_int min = getminor(*devp);
if (!(otype & OTYP_CHR))
return ENXIO;
if (min)
min = ENXIO;
return min;
}
int iplclose(dev, flags, otype, cred)
dev_t dev;
int flags, otype;
cred_t *cred;
{
u_int min = getminor(dev);
if (min)
min = ENXIO;
return min;
}
#ifdef IPFILTER_LOG
/*
* iplread/ipllog
* both of these must operate with at least splnet() lest they be
* called during packet processing and cause an inconsistancy to appear in
* the filter lists.
*/
int iplread(dev, uio, cp)
dev_t dev;
register struct uio *uio;
cred_t *cp;
{
register int ret;
register size_t sz, sx;
char *h, *t;
int error, used, usedo, copied;
if (!uio->uio_resid)
return 0;
if ((uio->uio_resid < 0) || (uio->uio_resid > IPLLOGSIZE))
return EINVAL;
/*
* Lock the log so we can snapshot the variables. Wait for a signal
* if the log is empty.
*/
mutex_enter(&ipl_mutex);
while (!iplused) {
error = cv_wait_sig(&iplwait, &ipl_mutex);
if (!error) {
mutex_exit(&ipl_mutex);
return EINTR;
}
}
h = iplh;
t = iplt;
used = iplused;
mutex_exit(&ipl_mutex);
usedo = used;
/*
* Given up the mutex, the log can grow more, but we can't hold the
* mutex across the uiomove's.
*/
sx = sz = MIN(uio->uio_resid, used);
if (h <= t)
sz = MIN(sz, IPLLOGSIZE + iplbuf - t);
if (!(ret = uiomove(t, sz, UIO_READ, uio))) {
t += sz;
sx -= sz;
used -= sz;
if ((h < t) && (t >= iplbuf + IPLLOGSIZE))
t = iplbuf;
if (sx && !(ret = uiomove(t, sx, UIO_READ, uio)))
used -= sx;
}
/*
* copied all the data, now adjust variables to match this.
*/
mutex_enter(&ipl_mutex);
copied = usedo - used;
iplused -= copied;
if (!iplused) /* minimise wrapping around the end */
iplh = iplt = iplbuf;
else {
iplt += copied;
if (iplt >= iplbuf + IPLLOGSIZE)
iplt -= IPLLOGSIZE;
if (iplt == iplbuf + IPLLOGSIZE)
iplt = iplbuf;
}
mutex_exit(&ipl_mutex);
return ret;
}
int ipllog(flags, ip, fin, m)
u_int flags;
ip_t *ip;
fr_info_t *fin;
mblk_t *m;
{
struct ipl_ci iplci;
register int len, mlen, hlen;
register u_char *s = (u_char *)ip;
ill_t *il = fin->fin_ifp;
hlen = fin->fin_hlen;
if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
hlen += MIN(sizeof(tcphdr_t), fin->fin_dlen);
else if (ip->ip_p == IPPROTO_ICMP) {
struct icmp *icmp = (struct icmp *)(s + hlen);
switch (icmp->icmp_type) {
case ICMP_UNREACH :
case ICMP_SOURCEQUENCH :
case ICMP_REDIRECT :
case ICMP_TIMXCEED :
case ICMP_PARAMPROB :
hlen += MIN(sizeof(struct icmp) + 8, fin->fin_dlen);
break;
default :
hlen += MIN(sizeof(struct icmp), fin->fin_dlen);
break;
}
}
mlen = (flags & FR_LOGBODY) ? MIN(msgdsize(m) - hlen, 128) : 0;
len = hlen + sizeof(iplci) + mlen;
mutex_enter(&ipl_mutex);
if ((iplused + len) > IPLLOGSIZE) {
mutex_exit(&ipl_mutex);
return 0;
}
iplused += len;
uniqtime((struct timeval *)&iplci);
iplci.flags = flags;
iplci.hlen = (u_char)hlen;
iplci.plen = (u_char)mlen;
iplci.rule = fin->fin_rule;
iplci.unit = (u_char)il->ill_ppa;
bcopy(il->ill_name, (char *)iplci.ifname, MIN(il->ill_name_length, 4));
/*
* Gauranteed to succeed from above
*/
(void) fr_copytolog(&iplci, sizeof(iplci));
len -= sizeof(iplci);
if (len && m) {
s = m->b_rptr;
do {
if ((hlen = MIN(m->b_wptr - s, len))) {
if (fr_copytolog(s, hlen))
break;
len -= hlen;
}
if ((m = m->b_cont))
s = m->b_rptr;
} while (m && len);
}
cv_signal(&iplwait);
mutex_exit(&ipl_mutex);
return 1;
}
#endif /* IPFILTER_LOG */
u_short ipf_cksum(addr, len)
register u_short *addr;
register int len;
{
register u_long sum = 0;
for (sum = 0; len > 1; len -= 2)
sum += *addr++;
/* mop up an odd byte, if necessary */
if (len == 1)
sum += *(u_char *)addr;
/*
* add back carry outs from top 16 bits to low 16 bits
*/
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
return (u_short)(~sum);
}
/*
* send_reset - this could conceivably be a call to tcp_respond(), but that
* requires a large amount of setting up and isn't any more efficient.
*/
int send_reset(ti, qif, q)
struct tcpiphdr *ti;
qif_t *qif;
queue_t *q;
{
struct ip *ip;
struct tcphdr *tcp;
mblk_t *m;
int tlen = 0;
if (ti->ti_flags & TH_RST)
return -1;
if (ti->ti_flags & TH_SYN)
tlen = 1;
if ((m = (mblk_t *)allocb(sizeof(struct tcpiphdr), BPRI_HI)) == NULL)
return -1;
MTYPE(m) = M_DATA;
m->b_wptr += sizeof(struct tcpiphdr);
bzero((char *)m->b_rptr, sizeof(struct tcpiphdr));
ip = (ip_t *)m->b_rptr;
tcp = (struct tcphdr *)(m->b_rptr + sizeof(*ip));
ip->ip_src.s_addr = ti->ti_dst.s_addr;
ip->ip_dst.s_addr = ti->ti_src.s_addr;
tcp->th_dport = ti->ti_sport;
tcp->th_sport = ti->ti_dport;
tcp->th_ack = htonl(ntohl(ti->ti_seq) + tlen);
tcp->th_off = sizeof(struct tcphdr) >> 2;
tcp->th_flags = TH_RST|TH_ACK;
/*
* This is to get around a bug in the Solaris 2.4/2.5 TCP checksum
* computation that is done by their put routine.
*/
tcp->th_sum = htons(0x14);
ip->ip_hl = sizeof(*ip) >> 2;
ip->ip_v = IPVERSION;
ip->ip_p = IPPROTO_TCP;
ip->ip_len = htons(sizeof(struct tcpiphdr));
ip->ip_tos = ((struct ip *)ti)->ip_tos;
ip->ip_off = 0;
ip->ip_ttl = 60;
ip->ip_sum = 0;
ip_wput(qif->qf_ill->ill_wq, m);
return 0;
}
int icmp_error(q, ip, type, code, qif, src)
queue_t *q;
ip_t *ip;
int type, code;
qif_t *qif;
struct in_addr src;
{
mblk_t *mb;
struct icmp *icmp;
ip_t *nip;
int sz = sizeof(*nip) + sizeof(*icmp) + 8;
if ((mb = (mblk_t *)allocb(sz, BPRI_HI)) == NULL)
return -1;
MTYPE(mb) = M_DATA;
mb->b_wptr += sz;
bzero((char *)mb->b_rptr, sz);
nip = (ip_t *)mb->b_rptr;
icmp = (struct icmp *)(nip + 1);
nip->ip_v = IPVERSION;
nip->ip_hl = (sizeof(*nip) >> 2);
nip->ip_p = IPPROTO_ICMP;
nip->ip_id = ip->ip_id;
nip->ip_sum = 0;
nip->ip_ttl = 60;
nip->ip_tos = ip->ip_tos;
nip->ip_len = htons(sz);
nip->ip_src.s_addr = ip->ip_dst.s_addr;
nip->ip_dst.s_addr = ip->ip_src.s_addr;
icmp->icmp_type = type;
icmp->icmp_code = code;
icmp->icmp_cksum = 0;
bcopy((char *)ip, (char *)&icmp->icmp_ip, sizeof(*ip));
bcopy((char *)ip + (ip->ip_hl << 2),
(char *)&icmp->icmp_ip + sizeof(*ip), 8); /* 64 bits */
icmp->icmp_cksum = ipf_cksum(icmp, sizeof(*icmp) + 8);
ip_wput(qif->qf_ill->ill_wq, mb);
return 0;
}

536
contrib/ipfilter/ip_state.c Normal file
View File

@ -0,0 +1,536 @@
/*
* (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.
*/
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-1995 Darren Reed";
static char rcsid[] = "$Id: ip_state.c,v 2.0.1.2 1997/01/09 15:22:45 darrenr Exp $";
#endif
#if !defined(_KERNEL) && !defined(KERNEL)
# include <stdlib.h>
# include <string.h>
#endif
#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>
#ifdef _KERNEL
# include <sys/systm.h>
#endif
#if !defined(__SVR4) && !defined(__svr4__)
# 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/tcp_fsm.h>
#include <netinet/udp.h>
#include <netinet/tcpip.h>
#include <netinet/ip_icmp.h>
#include "ip_fil.h"
#include "ip_compat.h"
#include "ip_state.h"
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
void set_tcp_age();
#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
#define FIVE_DAYS (2 * 5 * 86400) /* 5 days: half closed session */
u_long fr_tcpidletimeout = FIVE_DAYS,
fr_tcpclosewait = 60,
fr_tcplastack = 20,
fr_tcptimeout = 120,
fr_tcpclosed = 1,
fr_udptimeout = 120,
fr_icmptimeout = 120;
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, fin, pass)
ip_t *ip;
fr_info_t *fin;
u_int pass;
{
ipstate_t ips;
register ipstate_t *is = &ips;
register u_int hv;
if ((ip->ip_off & 0x1fff) || (fin->fin_fi.fi_fl & FI_SHORT))
return -1;
if (ips_num == IPSTATE_MAX) {
ips_stats.iss_max++;
return -1;
}
ips.is_age = 1;
ips.is_state[0] = 0;
ips.is_state[1] = 0;
/*
* 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 *)fin->fin_dp;
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 = fr_icmptimeout;
break;
}
case IPPROTO_TCP :
{
register tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp;
/*
* 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_swin = ntohs(tcp->th_win);
is->is_dwin = is->is_swin; /* start them the same */
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_ack = 0; /* Trumpet WinSock 'ism */
set_tcp_age(&is->is_age, is->is_state, ip, fin,
tcp->th_sport == is->is_sport);
break;
}
case IPPROTO_UDP :
{
register tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp;
hv += (is->is_dport = tcp->th_dport);
hv += (is->is_sport = tcp->th_sport);
ips_stats.iss_udp++;
is->is_age = fr_udptimeout;
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;
if (pass & FR_LOGFIRST)
is->is_pass &= ~(FR_LOGFIRST|FR_LOG);
ips_num++;
MUTEX_EXIT(&ipf_state);
return 0;
}
/*
* check to see if a packet with TCP headers fits within the TCP window.
* change timeout depending on whether new packet is a SYN-ACK returning for a
* SYN or a RST or FIN which indicate time to close up shop.
*/
int fr_tcpstate(is, fin, ip, tcp, sport
#ifndef _KERNEL
,isp)
ipstate_t **isp;
#else
)
#endif
register ipstate_t *is;
fr_info_t *fin;
ip_t *ip;
tcphdr_t *tcp;
u_short sport;
{
register int seqskew, ackskew;
register u_short swin, dwin;
register tcp_seq seq, ack;
int source;
/*
* 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.
*/
is->is_ack = seq;
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 ((source = (sport == is->is_sport))) {
swin = is->is_swin;
dwin = is->is_dwin;
} else {
dwin = is->is_swin;
swin = is->is_dwin;
}
if ((seqskew <= swin) && (ackskew <= dwin)) {
if (source) {
is->is_seq = seq;
is->is_ack = ack;
is->is_swin = ntohs(tcp->th_win);
} else {
is->is_seq = ack;
is->is_ack = seq;
is->is_dwin = ntohs(tcp->th_win);
}
ips_stats.iss_hits++;
/*
* Nearing end of connection, start timeout.
*/
set_tcp_age(&is->is_age, is->is_state, ip, fin,
tcp->th_sport == is->is_sport);
return 1;
}
return 0;
}
/*
* Check if a packet has a registered state.
*/
int fr_checkstate(ip, fin)
ip_t *ip;
fr_info_t *fin;
{
register struct in_addr dst, src;
register ipstate_t *is, **isp;
register u_char pr;
struct icmp *ic;
tcphdr_t *tcp;
u_int hv, hlen;
if ((ip->ip_off & 0x1fff) || (fin->fin_fi.fi_fl & FI_SHORT))
return 0;
hlen = fin->fin_hlen;
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 = fr_icmptimeout;
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;
hv += dport;
hv += sport;
hv %= IPSTATE_SIZE;
MUTEX_ENTER(&ipf_state);
for (isp = &ips_table[hv]; (is = *isp); isp = &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))
if (fr_tcpstate(is, fin, ip, tcp, sport)) {
#ifdef _KERNEL
MUTEX_EXIT(&ipf_state);
return is->is_pass;
#else
int pass = is->is_pass;
if (tcp->th_flags & TCP_CLOSE) {
*isp = is->is_next;
isp = &ips_table[hv];
KFREE(is);
}
return 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 = fr_udptimeout;
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);
}
/*
* Original idea freom Pradeep Krishnan for use primarily with NAT code.
* (pkrishna@netcom.com)
*/
void set_tcp_age(age, state, ip, fin, dir)
int *age;
u_char *state;
ip_t *ip;
fr_info_t *fin;
int dir;
{
tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp;
u_char flags = tcp->th_flags;
int dlen, ostate;
ostate = state[1 - dir];
dlen = ip->ip_len - fin->fin_hlen - (tcp->th_off << 2);
if (flags & TH_RST) {
if (!(tcp->th_flags & TH_PUSH) && !dlen) {
*age = fr_tcpclosed;
state[dir] = TCPS_CLOSED;
} else {
*age = fr_tcpclosewait;
state[dir] = TCPS_CLOSE_WAIT;
}
return;
}
*age = fr_tcptimeout; /* 1 min */
switch(state[dir])
{
case TCPS_FIN_WAIT_2:
case TCPS_CLOSED:
if ((flags & TH_OPENING) == TH_OPENING)
state[dir] = TCPS_SYN_RECEIVED;
else if (flags & TH_SYN)
state[dir] = TCPS_SYN_SENT;
break;
case TCPS_SYN_RECEIVED:
if ((flags & (TH_FIN|TH_ACK)) == TH_ACK) {
state[dir] = TCPS_ESTABLISHED;
*age = fr_tcpidletimeout;
}
break;
case TCPS_SYN_SENT:
if ((flags & (TH_FIN|TH_ACK)) == TH_ACK) {
state[dir] = TCPS_ESTABLISHED;
*age = fr_tcpidletimeout;
}
break;
case TCPS_ESTABLISHED:
if (flags & TH_FIN) {
state[dir] = TCPS_CLOSE_WAIT;
if (!(flags & TH_PUSH) && !dlen &&
ostate > TCPS_ESTABLISHED)
*age = fr_tcplastack;
else
*age = fr_tcpclosewait;
} else
*age = fr_tcpidletimeout;
break;
case TCPS_CLOSE_WAIT:
if ((flags & TH_FIN) && !(flags & TH_PUSH) && !dlen &&
ostate > TCPS_ESTABLISHED) {
*age = fr_tcplastack;
state[dir] = TCPS_LAST_ACK;
} else
*age = fr_tcpclosewait;
break;
case TCPS_LAST_ACK:
if (flags & TH_ACK) {
state[dir] = TCPS_FIN_WAIT_2;
if (!(flags & TH_PUSH) && !dlen &&
ostate > TCPS_ESTABLISHED)
*age = fr_tcplastack;
else {
*age = fr_tcpclosewait;
state[dir] = TCPS_CLOSE_WAIT;
}
}
break;
}
}

View File

@ -0,0 +1,86 @@
/*
* (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
* $Id: ip_state.h,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp $
*/
#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_swin;
u_short ts_dwin;
u_char ts_state[2];
} 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;
u_char is_flags;
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_dwin is_tcp.ts_dwin
#define is_swin is_tcp.ts_swin
#define is_sport is_tcp.ts_sport
#define is_dport is_tcp.ts_dport
#define is_state is_tcp.ts_state
#define TH_OPENING (TH_SYN|TH_ACK)
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(), set_tcp_age();
# ifdef _KERNEL
extern void fr_stateunload();
# endif
#endif /* __IP_STATE_H__ */

434
contrib/ipfilter/ipf.c Normal file
View File

@ -0,0 +1,434 @@
/*
* (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.
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#if !defined(__SVR4) && !defined(__GNUC__)
#include <strings.h>
#endif
#if !defined(__SVR4) && defined(__GNUC__)
extern char *index();
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <sys/file.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <net/if.h>
#include <netinet/ip.h>
#include "ip_fil.h"
#include <netdb.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include "ipf.h"
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-1995 Darren Reed";
static char rcsid[] = "$Id: ipf.c,v 2.0.1.2 1997/02/04 14:37:46 darrenr Exp $";
#endif
#if SOLARIS
void frsync(), blockunknown();
#endif
void zerostats();
extern char *optarg;
int opts = 0;
static int fd = -1;
static void procfile(), flushfilter(), set_state();
static void packetlogon(), swapactive(), showstats();
static char *getline();
int main(argc,argv)
int argc;
char *argv[];
{
char c;
while ((c = getopt(argc, argv, "AdDEf:F:Il:noprsUvyzZ")) != -1) {
switch (c)
{
case 'E' :
set_state(1);
break;
case 'D' :
set_state(0);
break;
case 'A' :
opts &= ~OPT_INACTIVE;
break;
case 'd' :
opts |= OPT_DEBUG;
break;
case 'f' :
procfile(argv[0], optarg);
break;
case 'F' :
flushfilter(optarg);
break;
case 'I' :
opts |= OPT_INACTIVE;
break;
case 'l' :
packetlogon(optarg);
break;
case 'n' :
opts |= OPT_DONOTHING;
break;
case 'o' :
opts |= OPT_OUTQUE;
break;
case 'p' :
opts |= OPT_PRINTFR;
break;
case 'r' :
opts |= OPT_REMOVE;
break;
case 's' :
swapactive();
break;
#if SOLARIS
case 'U' :
blockunknown();
break;
#endif
case 'v' :
opts |= OPT_VERBOSE;
break;
#if SOLARIS
case 'y' :
frsync();
break;
#endif
case 'z' :
opts |= OPT_ZERORULEST;
break;
case 'Z' :
zerostats();
break;
}
}
if (fd != -1)
(void) close(fd);
exit(0);
/* NOTREACHED */
}
static int opendevice()
{
if (opts & OPT_DONOTHING)
return -2;
if (!(opts & OPT_DONOTHING) && fd == -1)
if ((fd = open(IPL_NAME, O_RDWR)) == -1)
if ((fd = open(IPL_NAME, O_RDONLY)) == -1)
perror("open device");
return fd;
}
static void set_state(enable)
u_int enable;
{
if (opendevice() != -2)
if (ioctl(fd, SIOCFRENB, &enable) == -1)
perror("SIOCFRENB");
return;
}
static void procfile(name, file)
char *name, *file;
{
FILE *fp;
char line[513], *s;
struct frentry *fr;
u_int add = SIOCADAFR, del = SIOCRMAFR;
(void) opendevice();
if (opts & OPT_INACTIVE) {
add = SIOCADIFR;
del = SIOCRMIFR;
}
if (opts & OPT_DEBUG)
printf("add %x del %x\n", add, del);
initparse();
if (!strcmp(file, "-"))
fp = stdin;
else if (!(fp = fopen(file, "r"))) {
fprintf(stderr, "%s: fopen(%s) failed: %s\n", name, file,
STRERROR(errno));
exit(1);
}
while (getline(line, sizeof(line)-1, fp)) {
/*
* treat both CR and LF as EOL
*/
if ((s = index(line, '\n')))
*s = '\0';
if ((s = index(line, '\r')))
*s = '\0';
/*
* # is comment marker, everything after is a ignored
*/
if ((s = index(line, '#')))
*s = '\0';
if (!*line)
continue;
if (opts & OPT_VERBOSE)
(void)fprintf(stderr, "[%s]\n",line);
fr = parse(line);
(void)fflush(stdout);
if (fr) {
if (opts & OPT_ZERORULEST)
add = SIOCZRLST;
else if (opts & OPT_INACTIVE)
add = fr->fr_hits ? SIOCINIFR : SIOCADIFR;
else
add = fr->fr_hits ? SIOCINAFR : SIOCADAFR;
if (fr->fr_hits)
fr->fr_hits--;
if (fr && (opts & OPT_VERBOSE))
printfr(fr);
if (fr && (opts & OPT_OUTQUE))
fr->fr_flags |= FR_OUTQUE;
if (opts & OPT_DEBUG)
binprint(fr);
if ((opts & OPT_ZERORULEST) &&
!(opts & OPT_DONOTHING)) {
if (ioctl(fd, add, fr) == -1)
perror("ioctl(SIOCZRLST)");
else {
printf("hits %ld bytes %ld ",
fr->fr_hits, fr->fr_bytes);
printfr(fr);
}
} else if ((opts & OPT_REMOVE) &&
!(opts & OPT_DONOTHING)) {
if (ioctl(fd, del, fr) == -1)
perror("ioctl(SIOCDELFR)");
} else if (!(opts & OPT_DONOTHING)) {
if (ioctl(fd, add, fr) == -1)
perror("ioctl(SIOCADDFR)");
}
}
}
(void)fclose(fp);
}
/*
* Similar to fgets(3) but can handle '\\'
*/
static char *getline(str, size, file)
register char *str;
size_t size;
FILE *file;
{
register char *p;
do {
for (p = str;; p+= strlen(p) - 1) {
if (!fgets(p, size, file))
return(NULL);
p[strlen(p) -1] = '\0';
if (p[strlen(p) - 1] != '\\')
break;
}
} while (*str == '\0' || *str == '\n');
return(str);
}
static void packetlogon(opt)
char *opt;
{
int err, flag = 0;
if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
if ((err = ioctl(fd, SIOCGETFF, &flag)))
perror("ioctl(SIOCGETFF)");
printf("log flag is currently %#x\n", flag);
}
flag &= ~(FF_LOGPASS|FF_LOGNOMATCH|FF_LOGBLOCK);
if (index(opt, 'p')) {
flag |= FF_LOGPASS;
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)
printf("set log flag: block\n");
}
if (opendevice() != -2 && (err = ioctl(fd, SIOCSETFF, &flag)))
perror("ioctl(SIOCSETFF)");
if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
if ((err = ioctl(fd, SIOCGETFF, &flag)))
perror("ioctl(SIOCGETFF)");
printf("log flag is now %#x\n", flag);
}
}
static void flushfilter(arg)
char *arg;
{
int fl = 0, rem;
if (!arg || !*arg)
return;
if (strchr(arg, 'i') || strchr(arg, 'I'))
fl = FR_INQUE;
if (strchr(arg, 'o') || strchr(arg, 'O'))
fl = FR_OUTQUE;
if (strchr(arg, 'a') || strchr(arg, 'A'))
fl = FR_OUTQUE|FR_INQUE;
fl |= (opts & FR_INACTIVE);
rem = fl;
if (opendevice() != -2 && ioctl(fd, SIOCIPFFL, &fl) == -1)
perror("ioctl(SIOCIPFFL)");
if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
printf("remove flags %s%s (%d)\n", (rem & FR_INQUE) ? "I" : "",
(rem & FR_OUTQUE) ? "O" : "", rem);
printf("removed %d filter rules\n", fl);
}
return;
}
static void swapactive()
{
int in = 2;
if (opendevice() != -2 && ioctl(fd, SIOCSWAPA, &in) == -1)
perror("ioctl(SIOCSWAPA)");
else
printf("Set %d now inactive\n", in);
}
#if defined(sun) && (defined(__SVR4) || defined(__svr4__))
void frsync()
{
if (opendevice() != -2 && ioctl(fd, SIOCFRSYN, 0) == -1)
perror("SIOCFRSYN");
else
printf("filter sync'd\n");
}
#endif
void zerostats()
{
friostat_t fio;
if (opendevice() != -2) {
if (ioctl(fd, SIOCFRZST, &fio) == -1) {
perror("ioctl(SIOCFRZST)");
exit(-1);
}
showstats(&fio);
}
}
/*
* read the kernel stats for packets blocked and passed
*/
static void showstats(fp)
friostat_t *fp;
{
#if SOLARIS
printf("dropped packets:\tin %lu\tout %lu\n",
fp->f_st[0].fr_drop, fp->f_st[1].fr_drop);
printf("non-ip packets:\t\tin %lu\tout %lu\n",
fp->f_st[0].fr_notip, fp->f_st[1].fr_notip);
printf(" bad packets:\t\tin %lu\tout %lu\n",
fp->f_st[0].fr_bad, fp->f_st[1].fr_bad);
#endif
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);
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);
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);
printf("output packets logged:\tblocked %lu passed %lu\n",
fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl);
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);
}
#if SOLARIS
void blockunknown()
{
int flag;
if (opendevice() == -1)
return;
if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
if (ioctl(fd, SIOCGETFF, &flag))
perror("ioctl(SIOCGETFF)");
printf("log flag is currently %#x\n", flag);
}
flag ^= FF_BLOCKNONIP;
if (opendevice() != -2 && ioctl(fd, SIOCSETFF, &flag))
perror("ioctl(SIOCSETFF)");
if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
if (ioctl(fd, SIOCGETFF, &flag))
perror("ioctl(SIOCGETFF)");
printf("log flag is now %#x\n", flag);
}
}
#endif

67
contrib/ipfilter/ipf.h Normal file
View File

@ -0,0 +1,67 @@
/*
* (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.12 6/5/96
* $Id: ipf.h,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp $
*/
#ifndef SOLARIS
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
#endif
#define OPT_REMOVE 0x00001
#define OPT_DEBUG 0x00002
#define OPT_OUTQUE FR_OUTQUE /* 0x0004 */
#define OPT_INQUE FR_INQUE /* 0x0008 */
#define OPT_LOG FR_LOG /* 0x0010 */
#define OPT_SHOWLIST 0x00020
#define OPT_VERBOSE 0x00040
#define OPT_DONOTHING 0x00080
#define OPT_HITS 0x00100
#define OPT_BRIEF 0x00200
#define OPT_ACCNT FR_ACCOUNT /* 0x0400 */
#define OPT_FRSTATES FR_KEEPFRAG /* 0x0800 */
#define OPT_IPSTATES FR_KEEPSTATE /* 0x1000 */
#define OPT_INACTIVE FR_INACTIVE /* 0x2000 */
#define OPT_SHOWLINENO 0x04000
#define OPT_PRINTFR 0x08000
#define OPT_ZERORULEST 0x10000
extern struct frentry *parse();
extern void printfr(), binprint(), initparse();
#if defined(__SVR4) || defined(__svr4__)
#define index strchr
#define bzero(a,b) memset(a, 0, b)
#define bcopy(a,b,c) memmove(b,a,c)
#endif
struct ipopt_names {
int on_value;
int on_bit;
int on_siz;
char *on_name;
};
extern u_long hostnum(), optname();
extern void printpacket();
#if SOLARIS
extern int inet_aton();
#endif
#ifdef sun
#define STRERROR(x) sys_errlist[x]
extern char *sys_errlist[];
#else
#define STRERROR(x) strerror(x)
#endif
#ifndef MIN
#define MIN(a,b) ((a) > (b) ? (b) : (a))
#endif

148
contrib/ipfilter/ipft_ef.c Normal file
View File

@ -0,0 +1,148 @@
/*
* (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.
*/
/*
icmp type
lnth proto source destination src port dst port
etherfind -n
60 tcp 128.250.20.20 128.250.133.13 2419 telnet
etherfind -n -t
0.32 91 04 131.170.1.10 128.250.133.13
0.33 566 udp 128.250.37.155 128.250.133.3 901 901
*/
#include <stdio.h>
#include <string.h>
#if !defined(__SVR4) && !defined(__GNUC__)
#include <strings.h>
#endif
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/param.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/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include <netinet/tcpip.h>
#include <net/if.h>
#include <netdb.h>
#include "ipf.h"
#include "ipt.h"
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)ipft_ef.c 1.6 2/4/96 (C)1995 Darren Reed";
static char rcsid[] = "$Id: ipft_ef.c,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp $";
#endif
static int etherf_open(), etherf_close(), etherf_readip();
struct ipread etherf = { etherf_open, etherf_close, etherf_readip };
static FILE *efp = NULL;
static int efd = -1;
static int etherf_open(fname)
char *fname;
{
if (efd != -1)
return efd;
if (!strcmp(fname, "-")) {
efd = 0;
efp = stdin;
} else {
efd = open(fname, O_RDONLY);
efp = fdopen(efd, "r");
}
return efd;
}
static int etherf_close()
{
return close(efd);
}
static int etherf_readip(buf, cnt, ifn, dir)
char *buf, **ifn;
int cnt, *dir;
{
struct tcpiphdr pkt;
struct ip *ip = (struct ip *)&pkt;
struct protoent *p = NULL;
char src[16], dst[16], sprt[16], dprt[16];
char lbuf[128], len[8], prot[8], time[8], *s;
int slen, extra = 0, i, n;
if (!fgets(lbuf, sizeof(lbuf) - 1, efp))
return 0;
if ((s = strchr(lbuf, '\n')))
*s = '\0';
lbuf[sizeof(lbuf)-1] = '\0';
bzero(&pkt, sizeof(pkt));
if ((n = sscanf(lbuf, "%s %s %s %s %s %s", len, prot, src, dst,
sprt, dprt)) != 6)
if ((n = sscanf(lbuf, "%s %s %s %s %s %s %s", time,
len, prot, src, dst, sprt, dprt)) != 7)
return -1;
ip->ip_p = atoi(prot);
if (ip->ip_p == 0) {
if (!(p = getprotobyname(prot)))
return -1;
ip->ip_p = p->p_proto;
}
switch (ip->ip_p) {
case IPPROTO_TCP :
case IPPROTO_UDP :
s = strtok(NULL, " :");
ip->ip_len += atoi(s);
if (p->p_proto == IPPROTO_TCP)
extra = sizeof(struct tcphdr);
else if (p->p_proto == IPPROTO_UDP)
extra = sizeof(struct udphdr);
break;
#ifdef IGMP
case IPPROTO_IGMP :
extra = sizeof(struct igmp);
break;
#endif
case IPPROTO_ICMP :
extra = sizeof(struct icmp);
break;
default :
break;
}
(void) inet_aton(src, &ip->ip_src);
(void) inet_aton(dst, &ip->ip_dst);
ip->ip_len = atoi(len);
ip->ip_hl = sizeof(struct ip);
slen = ip->ip_hl + extra;
i = MIN(cnt, slen);
bcopy((char *)&pkt, buf, i);
return i;
}

140
contrib/ipfilter/ipft_hx.c Normal file
View File

@ -0,0 +1,140 @@
/*
* (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.
*/
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include <string.h>
#if !defined(__SVR4) && !defined(__svr4__)
#include <strings.h>
#else
#include <sys/byteorder.h>
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip_var.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>
#include <netinet/tcpip.h>
#include <net/if.h>
#include <netdb.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include "ipf.h"
#include "ipt.h"
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)ipft_hx.c 1.1 3/9/96 (C) 1996 Darren Reed";
static char rcsid[] = "$Id: ipft_hx.c,v 2.0.1.2 1997/02/04 13:57:56 darrenr Exp $";
#endif
extern int opts;
extern u_short portnum();
extern u_long buildopts();
static int hex_open(), hex_close(), hex_readip();
static char *readhex();
struct ipread iphex = { hex_open, hex_close, hex_readip };
static FILE *tfp = NULL;
static int tfd = -1;
static int hex_open(fname)
char *fname;
{
if (tfp && tfd != -1) {
rewind(tfp);
return tfd;
}
if (!strcmp(fname, "-")) {
tfd = 0;
tfp = stdin;
} else {
tfd = open(fname, O_RDONLY);
if (tfd != -1)
tfp = fdopen(tfd, "r");
}
return tfd;
}
static int hex_close()
{
int cfd = tfd;
tfd = -1;
return close(cfd);
}
static int hex_readip(buf, cnt, ifn, dir)
char *buf, **ifn;
int cnt, *dir;
{
register char *s;
struct ip *ip;
char line[513];
ip = (struct ip *)buf;
while (fgets(line, sizeof(line)-1, tfp)) {
if ((s = index(line, '\n'))) {
if (s == line)
return (char *)ip - buf;
*s = '\0';
}
if ((s = index(line, '#')))
*s = '\0';
if (!*line)
continue;
if (!(opts & OPT_BRIEF)) {
printf("input: %s\n", line);
fflush(stdout);
}
ip = (struct ip *)readhex(line, (char *)ip);
}
return -1;
}
static char *readhex(src, dst)
register char *src, *dst;
{
int state = 0;
char c;
while ((c = *src++)) {
if (isspace(c)) {
if (state) {
dst++;
state = 0;
}
continue;
} else if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
(c >= 'A' && c <= 'F')) {
c = isdigit(c) ? (c - '0') : (toupper(c) - 55);
if (state == 0) {
*dst = (c << 4);
state++;
} else {
*dst++ |= c;
state = 0;
}
} else
break;
}
return dst;
}

224
contrib/ipfilter/ipft_pc.c Normal file
View File

@ -0,0 +1,224 @@
/*
* (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.
*/
#include <stdio.h>
#include <string.h>
#if !defined(__SVR4) && !defined(__GNUC__)
#include <strings.h>
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip_var.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <net/if.h>
#include "ipf.h"
#include "ipt.h"
#include "pcap.h"
#if !defined(lint) && defined(LIBC_SCCS)
static char rcsid[] = "$Id: ipft_pc.c,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $";
#endif
struct llc {
int lc_sz; /* LLC header length */
int lc_to; /* LLC Type offset */
int lc_tl; /* LLC Type length */
};
/*
* While many of these maybe the same, some do have different header formats
* which make this useful.
*/
#define DLT_MAX 10
static struct llc llcs[DLT_MAX+1] = {
{ 0, 0, 0 }, /* DLT_NULL */
{ 14, 12, 2 }, /* DLT_E10MB */
{ 0, 0, 0 }, /* DLT_EN3MB */
{ 0, 0, 0 }, /* DLT_AX25 */
{ 0, 0, 0 }, /* DLT_PRONET */
{ 0, 0, 0 }, /* DLT_CHAOS */
{ 0, 0, 0 }, /* DLT_IEEE802 */
{ 0, 0, 0 }, /* DLT_ARCNET */
{ 0, 0, 0 }, /* DLT_SLIP */
{ 0, 0, 0 }, /* DLT_PPP */
{ 0, 0, 0 } /* DLT_FDDI */
};
static int pcap_open(), pcap_close(), pcap_readip();
static int pfd = -1, s_type = -1, swapped = 0;
struct ipread pcap = { pcap_open, pcap_close, pcap_readip };
#define SWAPLONG(y) \
((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
#define SWAPSHORT(y) \
( (((y)&0xff)<<8) | (((y)&0xff00)>>8) )
static void swap_hdr(p)
pcaphdr_t *p;
{
p->pc_v_maj = SWAPSHORT(p->pc_v_maj);
p->pc_v_min = SWAPSHORT(p->pc_v_min);
p->pc_zone = SWAPLONG(p->pc_zone);
p->pc_sigfigs = SWAPLONG(p->pc_sigfigs);
p->pc_slen = SWAPLONG(p->pc_slen);
p->pc_type = SWAPLONG(p->pc_type);
}
static int pcap_open(fname)
char *fname;
{
pcaphdr_t ph;
int fd;
if (pfd != -1)
return pfd;
if (!strcmp(fname, "-"))
fd = 0;
else if ((fd = open(fname, O_RDONLY)) == -1)
return -1;
if (read(fd, (char *)&ph, sizeof(ph)) != sizeof(ph))
return -2;
if (ph.pc_id != TCPDUMP_MAGIC) {
if (SWAPLONG(ph.pc_id) != TCPDUMP_MAGIC) {
(void) close(fd);
return -2;
}
swapped = 1;
swap_hdr(&ph);
}
if (ph.pc_v_maj != PCAP_VERSION_MAJ || ph.pc_type > DLT_MAX) {
(void) close(fd);
return -2;
}
pfd = fd;
s_type = ph.pc_type;
printf("opened pcap file %s:\n", fname);
printf("\tid: %08x version: %d.%d type: %d snap %d\n",
ph.pc_id, ph.pc_v_maj, ph.pc_v_min, ph.pc_type, ph.pc_slen);
return fd;
}
static int pcap_close()
{
return close(pfd);
}
/*
* read in the header (and validate) which should be the first record
* in a pcap file.
*/
static int pcap_read_rec(rec)
struct pcap_pkthdr *rec;
{
int n, p;
if (read(pfd, (char *)rec, sizeof(*rec)) != sizeof(*rec))
return -2;
if (swapped) {
rec->ph_clen = SWAPLONG(rec->ph_clen);
rec->ph_len = SWAPLONG(rec->ph_len);
rec->ph_ts.tv_sec = SWAPLONG(rec->ph_ts.tv_sec);
rec->ph_ts.tv_usec = SWAPLONG(rec->ph_ts.tv_usec);
}
p = rec->ph_clen;
n = MIN(p, rec->ph_len);
if (!n || n < 0)
return -3;
return p;
}
#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.
*/
static int pcap_read(buf, cnt)
char *buf;
int cnt;
{
struct pcap_pkthdr rec;
static char *bufp = NULL;
int i, n;
if ((i = pcap_read_rec(&rec)) <= 0)
return i;
if (!bufp)
bufp = malloc(i);
else
bufp = realloc(bufp, i);
if (read(pfd, bufp, i) != i)
return -2;
n = MIN(i, cnt);
bcopy(bufp, buf, n);
return n;
}
#endif
/*
* return only an IP packet read into buf
*/
static int pcap_readip(buf, cnt, ifn, dir)
char *buf, **ifn;
int cnt, *dir;
{
static char *bufp = NULL;
struct pcap_pkthdr rec;
struct llc *l;
char *s, ty[4];
int i, n;
do {
if ((i = pcap_read_rec(&rec)) <= 0)
return i;
if (!bufp)
bufp = malloc(i);
else
bufp = realloc(bufp, i);
s = bufp;
if (read(pfd, s, i) != i)
return -2;
l = &llcs[s_type];
i -= l->lc_sz;
s += l->lc_to;
bcopy(s, ty, l->lc_tl);
s += l->lc_tl;
} while (ty[0] != 0x8 && ty[1] != 0);
n = MIN(i, cnt);
bcopy(s, buf, n);
return n;
}

206
contrib/ipfilter/ipft_sn.c Normal file
View File

@ -0,0 +1,206 @@
/*
* (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.
*/
/*
* Written to comply with the recent RFC 1761 from Sun.
*/
#include <stdio.h>
#include <string.h>
#if !defined(__SVR4) && !defined(__GNUC__)
#include <strings.h>
#endif
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip_var.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <net/if.h>
#include "ipf.h"
#include "ipt.h"
#include "snoop.h"
#if !defined(lint) && defined(LIBC_SCCS)
static char rcsid[] = "$Id: ipft_sn.c,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $";
#endif
struct llc {
int lc_sz; /* LLC header length */
int lc_to; /* LLC Type offset */
int lc_tl; /* LLC Type length */
};
/*
* While many of these maybe the same, some do have different header formats
* which make this useful.
*/
static struct llc llcs[SDL_MAX+1] = {
{ 0, 0, 0 }, /* SDL_8023 */
{ 0, 0, 0 }, /* SDL_8024 */
{ 0, 0, 0 }, /* SDL_8025 */
{ 0, 0, 0 }, /* SDL_8026 */
{ 14, 12, 2 }, /* SDL_ETHER */
{ 0, 0, 0 }, /* SDL_HDLC */
{ 0, 0, 0 }, /* SDL_CHSYNC */
{ 0, 0, 0 }, /* SDL_IBMCC */
{ 0, 0, 0 }, /* SDL_FDDI */
{ 0, 0, 0 }, /* SDL_OTHER */
};
static int snoop_open(), snoop_close(), snoop_readip();
static int sfd = -1, s_type = -1;
struct ipread snoop = { snoop_open, snoop_close, snoop_readip };
static int snoop_open(fname)
char *fname;
{
struct snoophdr sh;
int fd;
if (sfd != -1)
return sfd;
if (!strcmp(fname, "-"))
fd = 0;
else if ((fd = open(fname, O_RDONLY)) == -1)
return -1;
if (read(fd, (char *)&sh, sizeof(sh)) != sizeof(sh))
return -2;
if (sh.s_v != SNOOP_VERSION ||
sh.s_type < 0 || sh.s_type > SDL_MAX) {
(void) close(fd);
return -2;
}
sfd = fd;
s_type = sh.s_type;
printf("opened snoop file %s:\n", fname);
printf("\tid: %8.8s version: %d type: %d\n", sh.s_id, sh.s_v, s_type);
return fd;
}
static int snoop_close()
{
return close(sfd);
}
/*
* read in the header (and validate) which should be the first record
* in a snoop file.
*/
static int snoop_read_rec(rec)
struct snooppkt *rec;
{
int n, p;
if (read(sfd, (char *)rec, sizeof(*rec)) != sizeof(*rec))
return -2;
if (rec->sp_ilen > rec->sp_plen || rec->sp_plen < sizeof(*rec))
return -2;
p = rec->sp_plen - sizeof(*rec);
n = MIN(p, rec->sp_ilen);
if (!n || n < 0)
return -3;
return p;
}
#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.
*/
static int snoop_read(buf, cnt)
char *buf;
int cnt;
{
struct snooppkt rec;
static char *bufp = NULL;
int i, n;
if ((i = snoop_read_rec(&rec)) <= 0)
return i;
if (!bufp)
bufp = malloc(i);
else
bufp = realloc(bufp, i);
if (read(sfd, bufp, i) != i)
return -2;
n = MIN(i, cnt);
bcopy(bufp, buf, n);
return n;
}
#endif
/*
* return only an IP packet read into buf
*/
static int snoop_readip(buf, cnt, ifn, dir)
char *buf, **ifn;
int cnt, *dir;
{
static char *bufp = NULL;
struct snooppkt rec;
struct llc *l;
char ty[4], *s;
int i, n;
do {
if ((i = snoop_read_rec(&rec)) <= 0)
return i;
if (!bufp)
bufp = malloc(i);
else
bufp = realloc(bufp, i);
s = bufp;
if (read(sfd, s, i) != i)
return -2;
l = &llcs[s_type];
i -= l->lc_to;
s += l->lc_to;
/*
* XXX - bogus assumption here on the part of the time field
* that it won't be greater than 4 bytes and the 1st two will
* have the values 8 and 0 for IP. Should be a table of
* these too somewhere. Really only works for SDL_ETHER.
*/
bcopy(s, ty, l->lc_tl);
} while (ty[0] != 0x8 && ty[1] != 0);
i -= l->lc_tl;
s += l->lc_tl;
n = MIN(i, cnt);
bcopy(s, buf, n);
return n;
}

184
contrib/ipfilter/ipft_td.c Normal file
View File

@ -0,0 +1,184 @@
/*
* (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.
*/
/*
tcpdump -n
00:05:47.816843 128.231.76.76.3291 > 224.2.252.231.36573: udp 36 (encap)
tcpdump -nq
00:33:48.410771 192.73.213.11.1463 > 224.2.248.153.59360: udp 31 (encap)
tcpdump -nqt
128.250.133.13.23 > 128.250.20.20.2419: tcp 27
tcpdump -nqtt
123456789.1234567 128.250.133.13.23 > 128.250.20.20.2419: tcp 27
tcpdump -nqte
8:0:20:f:65:f7 0:0:c:1:8a:c5 81: 128.250.133.13.23 > 128.250.20.20.2419: tcp 27
*/
#include <stdio.h>
#include <string.h>
#if !defined(__SVR4) && !defined(__GNUC__)
#include <strings.h>
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#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/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include <netinet/tcpip.h>
#include <net/if.h>
#include <netdb.h>
#include "ipf.h"
#include "ipt.h"
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)ipft_td.c 1.8 2/4/96 (C)1995 Darren Reed";
static char rcsid[] = "$Id: ipft_td.c,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $";
#endif
static int tcpd_open(), tcpd_close(), tcpd_readip();
struct ipread tcpd = { tcpd_open, tcpd_close, tcpd_readip };
static FILE *tfp = NULL;
static int tfd = -1;
static int tcpd_open(fname)
char *fname;
{
if (tfd != -1)
return tfd;
if (!strcmp(fname, "-")) {
tfd = 0;
tfp = stdin;
} else {
tfd = open(fname, O_RDONLY);
tfp = fdopen(tfd, "r");
}
return tfd;
}
static int tcpd_close()
{
(void) fclose(tfp);
return close(tfd);
}
static int count_dots(str)
char *str;
{
int i = 0;
while (*str)
if (*str++ == '.')
i++;
return i;
}
static int tcpd_readip(buf, cnt, ifn, dir)
char *buf, **ifn;
int cnt, *dir;
{
struct tcpiphdr pkt;
struct ip *ip = (struct ip *)&pkt;
struct protoent *p;
char src[32], dst[32], misc[256], time[32], link1[32], link2[32];
char lbuf[160], *s;
int n, dots, slen, extra = 0;
if (!fgets(lbuf, sizeof(lbuf) - 1, tfp))
return 0;
if ((s = strchr(lbuf, '\n')))
*s = '\0';
lbuf[sizeof(lbuf)-1] = '\0';
bzero(&pkt, sizeof(pkt));
if ((n = sscanf(lbuf, "%s > %s: %s", src, dst, misc)) != 3)
if ((n = sscanf(lbuf, "%s %s > %s: %s",
time, src, dst, misc)) != 4)
if ((n = sscanf(lbuf, "%s %s: %s > %s: %s",
link1, link2, src, dst, misc)) != 5) {
n = sscanf(lbuf, "%s %s %s: %s > %s: %s",
time, link1, link2, src, dst, misc);
if (n != 6)
return -1;
}
if ((dots = count_dots(dst)) == 4) {
s = strrchr(src, '.');
*s++ = '\0';
(void) inet_aton(src, &ip->ip_src);
pkt.ti_sport = htons(atoi(s));
*--s = '.';
s = strrchr(dst, '.');
*s++ = '\0';
(void) inet_aton(src, &ip->ip_dst);
pkt.ti_dport = htons(atoi(s));
*--s = '.';
} else {
(void) inet_aton(src, &ip->ip_src);
(void) inet_aton(src, &ip->ip_dst);
}
ip->ip_len = ip->ip_hl = sizeof(struct ip);
s = strtok(misc, " :");
if ((p = getprotobyname(s))) {
ip->ip_p = p->p_proto;
switch (p->p_proto) {
case IPPROTO_TCP :
case IPPROTO_UDP :
s = strtok(NULL, " :");
ip->ip_len += atoi(s);
if (p->p_proto == IPPROTO_TCP)
extra = sizeof(struct tcphdr);
else if (p->p_proto == IPPROTO_UDP)
extra = sizeof(struct udphdr);
break;
#ifdef IGMP
case IPPROTO_IGMP :
extra = sizeof(struct igmp);
break;
#endif
case IPPROTO_ICMP :
extra = sizeof(struct icmp);
break;
default :
break;
}
}
slen = ip->ip_hl + extra + ip->ip_len;
return slen;
}

338
contrib/ipfilter/ipft_tx.c Normal file
View File

@ -0,0 +1,338 @@
/*
* (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.
*/
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include <string.h>
#if !defined(__SVR4) && !defined(__svr4__)
#include <strings.h>
#else
#include <sys/byteorder.h>
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip_var.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>
#include <netinet/tcpip.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netdb.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include "ip_compat.h"
#include "ipf.h"
#include "ipt.h"
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)ipft_tx.c 1.7 6/5/96 (C) 1993 Darren Reed";
static char rcsid[] = "$Id: ipft_tx.c,v 2.0.1.2 1997/01/19 04:52:25 darrenr Exp $";
#endif
extern int opts;
extern u_long buildopts();
static char *tx_proto = "";
static int text_open(), text_close(), text_readip(), parseline();
static char tcp_flagset[] = "FSRPAU";
static u_char tcp_flags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH,
TH_ACK, TH_URG };
struct ipread iptext = { text_open, text_close, text_readip };
static FILE *tfp = NULL;
static int tfd = -1;
static u_long tx_hostnum();
static u_short tx_portnum();
/*
* returns an ip address as a long var as a result of either a DNS lookup or
* straight inet_addr() call
*/
static u_long tx_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 (!(hp = gethostbyname(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;
}
/*
* find the port number given by the name, either from getservbyname() or
* straight atoi()
*/
static u_short tx_portnum(name)
char *name;
{
struct servent *sp, *sp2;
u_short p1 = 0;
if (isdigit(*name))
return (u_short)atoi(name);
if (!tx_proto)
tx_proto = "tcp/udp";
if (strcasecmp(tx_proto, "tcp/udp")) {
sp = getservbyname(name, tx_proto);
if (sp)
return ntohs(sp->s_port);
(void) fprintf(stderr, "unknown service \"%s\".\n", name);
return 0;
}
sp = getservbyname(name, "tcp");
if (sp)
p1 = sp->s_port;
sp2 = getservbyname(name, "udp");
if (!sp || !sp2) {
(void) fprintf(stderr, "unknown tcp/udp service \"%s\".\n",
name);
return 0;
}
if (p1 != sp2->s_port) {
(void) fprintf(stderr, "%s %d/tcp is a different port to ",
name, p1);
(void) fprintf(stderr, "%s %d/udp\n", name, sp->s_port);
return 0;
}
return ntohs(p1);
}
char *tx_icmptypes[] = {
"echorep", (char *)NULL, (char *)NULL, "unreach", "squench",
"redir", (char *)NULL, (char *)NULL, "echo", (char *)NULL,
(char *)NULL, "timex", "paramprob", "timest", "timestrep",
"inforeq", "inforep", "maskreq", "maskrep", "END"
};
static int text_open(fname)
char *fname;
{
if (tfp && tfd != -1) {
rewind(tfp);
return tfd;
}
if (!strcmp(fname, "-")) {
tfd = 0;
tfp = stdin;
} else {
tfd = open(fname, O_RDONLY);
if (tfd != -1)
tfp = fdopen(tfd, "r");
}
return tfd;
}
static int text_close()
{
int cfd = tfd;
tfd = -1;
return close(cfd);
}
static int text_readip(buf, cnt, ifn, dir)
char *buf, **ifn;
int cnt, *dir;
{
register char *s;
struct ip *ip;
char line[513];
ip = (struct ip *)buf;
*ifn = NULL;
while (fgets(line, sizeof(line)-1, tfp)) {
if ((s = index(line, '\n')))
*s = '\0';
if ((s = index(line, '\r')))
*s = '\0';
if ((s = index(line, '#')))
*s = '\0';
if (!*line)
continue;
if (!(opts & OPT_BRIEF))
printf("input: %s\n", line);
*ifn = NULL;
*dir = 0;
if (!parseline(line, buf, ifn, dir))
#if 0
return sizeof(struct tcpiphdr);
#else
return sizeof(struct ip);
#endif
}
return -1;
}
static int parseline(line, ip, ifn, out)
char *line;
struct ip *ip;
char **ifn;
int *out;
{
tcphdr_t th, *tcp = &th;
struct icmp icmp, *ic = &icmp;
char *cps[20], **cpp, c, ipopts[68];
int i, r;
bzero((char *)ip, MAX(sizeof(*tcp), sizeof(*ic)) + sizeof(*ip));
bzero((char *)tcp, sizeof(*tcp));
bzero((char *)ic, sizeof(*ic));
bzero(ipopts, sizeof(ipopts));
ip->ip_hl = sizeof(*ip) >> 2;
ip->ip_v = IPVERSION;
for (i = 0, cps[0] = strtok(line, " \b\t\r\n"); cps[i] && i < 19; )
cps[++i] = strtok(NULL, " \b\t\r\n");
if (i < 2)
return 1;
cpp = cps;
c = **cpp;
if (!isalpha(c) || (tolower(c) != 'o' && tolower(c) != 'i')) {
fprintf(stderr, "bad direction \"%s\"\n", *cpp);
return 1;
}
*out = (tolower(c) == 'o') ? 1 : 0;
cpp++;
if (!strcasecmp(*cpp, "on")) {
cpp++;
if (!*cpp)
return 1;
*ifn = *cpp++;
}
c = **cpp;
ip->ip_len = sizeof(struct ip);
if (!strcasecmp(*cpp, "tcp") || !strcasecmp(*cpp, "udp") ||
!strcasecmp(*cpp, "icmp")) {
if (c == 't') {
ip->ip_p = IPPROTO_TCP;
ip->ip_len += sizeof(struct tcphdr);
tx_proto = "tcp";
} else if (c == 'u') {
ip->ip_p = IPPROTO_UDP;
ip->ip_len += sizeof(struct udphdr);
tx_proto = "udp";
} else {
ip->ip_p = IPPROTO_ICMP;
ip->ip_len += sizeof(struct icmp);
tx_proto = "icmp";
}
cpp++;
} else
ip->ip_p = IPPROTO_IP;
if (!*cpp)
return 1;
if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) {
char *last;
last = index(*cpp, ',');
if (!last) {
fprintf(stderr, "tcp/udp with no source port\n");
return 1;
}
*last++ = '\0';
tcp->th_sport = htons(tx_portnum(last));
}
ip->ip_src.s_addr = tx_hostnum(*cpp, &r);
cpp++;
if (!*cpp)
return 1;
if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) {
char *last;
last = index(*cpp, ',');
if (!last) {
fprintf(stderr, "tcp/udp with no destination port\n");
return 1;
}
*last++ = '\0';
tcp->th_dport = htons(tx_portnum(last));
}
ip->ip_dst.s_addr = tx_hostnum(*cpp, &r);
cpp++;
if (*cpp && ip->ip_p == IPPROTO_TCP) {
extern char tcp_flagset[];
extern u_char tcp_flags[];
char *s, *t;
for (s = *cpp; *s; s++)
if ((t = index(tcp_flagset, *s)))
tcp->th_flags |= tcp_flags[t - tcp_flagset];
if (tcp->th_flags)
cpp++;
assert(tcp->th_flags != 0);
} else if (*cpp && ip->ip_p == IPPROTO_ICMP) {
extern char *tx_icmptypes[];
char **s, *t;
int i;
for (s = tx_icmptypes, i = 0; !*s || strcmp(*s, "END");
s++, i++)
if (*s && !strncasecmp(*cpp, *s, strlen(*s))) {
ic->icmp_type = i;
if ((t = index(*cpp, ',')))
ic->icmp_code = atoi(t+1);
cpp++;
break;
}
}
if (*cpp && !strcasecmp(*cpp, "opt")) {
u_long olen;
cpp++;
olen = buildopts(*cpp, ipopts);
if (olen) {
bcopy(ipopts, (char *)(ip + 1), olen);
ip->ip_hl += olen >> 2;
}
}
if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
bcopy((char *)tcp, ((char *)ip) + (ip->ip_hl << 2),
sizeof(*tcp));
else if (ip->ip_p == IPPROTO_ICMP)
bcopy((char *)ic, ((char *)ip) + (ip->ip_hl << 2),
sizeof(*ic));
return 0;
}

16
contrib/ipfilter/ipl.h Normal file
View File

@ -0,0 +1,16 @@
/*
* (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.
*
* @(#)ipl.h 1.21 6/5/96
*/
#ifndef __IPL_H_
#define __IPL_H__
#define IPL_VERSION "IP Filter v3.1.7 - 8/2/97"
#endif

View File

@ -0,0 +1,83 @@
/*
* (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.
*/
/*
* routines below for saving IP headers to buffer
*/
int iplopen(struct inode * inode, struct file * filp)
{
u_int min = MINOR(inode->i_rdev);
if (flags & FWRITE)
return ENXIO;
if (min)
return ENXIO;
iplbusy++;
return 0;
}
int iplclose(struct inode * inode, struct file * filp)
{
u_int min = MINOR(inode->i_rdev);
if (min)
return ENXIO;
iplbusy--;
return 0;
}
/*
* iplread/ipllog
* all three of these must operate with at least splnet() lest they be
* called during packet processing and cause an inconsistancy to appear in
* the filter lists.
*/
int iplread(struct inode *inode, struct file *file, char *buf, int count)
{
register int ret, s;
register size_t sz, sx;
int error;
if (!uio->uio_resid)
return 0;
while (!iplused) {
error = SLEEP(iplbuf, "ipl sleep");
if (error)
return error;
}
SPLNET(s);
ret = sx = sz = MIN(count, iplused);
if (iplh < iplt)
sz = MIN(sz, LOGSIZE - (iplt - iplbuf));
sx -= sz;
memcpy_tofs(buf, iplt, sz);
buf += sz;
iplt += sz;
iplused -= sz;
if ((iplh < iplt) && (iplt == iplbuf + LOGSIZE))
iplt = iplbuf;
if (sx) {
memcpy_tofs(buf, iplt, sx);
ret += sx;
iplt += sx;
iplused -= sx;
if ((iplh < iplt) && (iplt == iplbuf + LOGSIZE))
iplt = iplbuf;
}
if (!iplused) /* minimise wrapping around the end */
iplh = iplt = iplbuf;
SPLX(s);
return ret;
}

582
contrib/ipfilter/ipmon.c Normal file
View File

@ -0,0 +1,582 @@
/*
* (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.
*/
#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
#include <sys/errno.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/uio.h>
#if !defined(__SVR4) && !defined(__svr4__)
#include <sys/dir.h>
#include <sys/mbuf.h>
#else
#include <sys/byteorder.h>
#endif
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/user.h>
#include <net/if.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/tcpip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <ctype.h>
#if !defined(lint) && defined(LIBC_SCCS)
static char rcsid[] = "$Id: ipmon.c,v 2.0.1.2 1997/02/04 14:49:19 darrenr Exp $";
#endif
#include "ip_fil.h"
struct flags {
int value;
char flag;
};
struct flags tcpfl[] = {
{ TH_ACK, 'A' },
{ TH_RST, 'R' },
{ TH_SYN, 'S' },
{ TH_FIN, 'F' },
{ TH_URG, 'U' },
{ TH_PUSH,'P' },
{ 0, '\0' }
};
static char line[2048];
static void printpacket(), dumphex();
static int opts = 0;
#define OPT_SYSLOG 0x01
#define OPT_RESOLVE 0x02
#define OPT_HEXBODY 0x04
#define OPT_VERBOSE 0x08
#define OPT_HEXHDR 0x10
#ifndef LOGFAC
#define LOGFAC LOG_LOCAL0
#endif
void printiplci(icp)
struct ipl_ci *icp;
{
printf("sec %ld usec %ld hlen %d plen %d\n", icp->sec, icp->usec,
icp->hlen, icp->plen);
}
void resynclog(fd, iplcp, log)
int fd;
struct ipl_ci *iplcp;
FILE *log;
{
time_t now;
char *s = NULL;
int len, nr = 0;
do {
if (s) {
s = (char *)&iplcp->sec;
if (opts & OPT_SYSLOG) {
syslog(LOG_INFO, "Sync bytes:");
syslog(LOG_INFO, " %02x %02x %02x %02x",
*s, *(s+1), *(s+2), *(s+3));
syslog(LOG_INFO, " %02x %02x %02x %02x\n",
*(s+4), *(s+5), *(s+6), *(s+7));
} else {
fprintf(log, "Sync bytes:");
fprintf(log, " %02x %02x %02x %02x",
*s, *(s+1), *(s+2), *(s+3));
fprintf(log, " %02x %02x %02x %02x\n",
*(s+4), *(s+5), *(s+6), *(s+7));
}
}
do {
s = (char *)&iplcp->sec;
len = sizeof(iplcp->sec);
while (len) {
switch ((nr = read(fd, s, len)))
{
case -1:
case 0:
return;
default :
s += nr;
len -= nr;
now = time(NULL);
break;
}
}
} while ((now < iplcp->sec) ||
((iplcp->sec - now) > (86400*5)));
len = sizeof(iplcp->usec);
while (len) {
switch ((nr = read(fd, s, len)))
{
case -1:
case 0:
return;
default :
s += nr;
len -= nr;
break;
}
}
} while (iplcp->usec > 1000000);
len = sizeof(*iplcp) - sizeof(iplcp->sec) - sizeof(iplcp->usec);
while (len) {
switch ((nr = read(fd, s, len)))
{
case -1:
case 0:
return;
default :
s += nr;
len -= nr;
break;
}
}
}
int readlogentry(fd, lenp, buf, bufsize, log)
int fd, bufsize, *lenp;
char *buf;
FILE *log;
{
struct ipl_ci *icp = (struct ipl_ci *)buf;
time_t now;
char *s;
int len, n = bufsize, tr = sizeof(struct ipl_ci), nr;
if (bufsize < tr)
return 1;
for (s = buf; (n > 0) && (tr > 0); s += nr, n -= nr) {
nr = read(fd, s, tr);
if (nr > 0)
tr -= nr;
else
return -1;
}
now = time(NULL);
if ((icp->hlen > 92) || (now < icp->sec) ||
((now - icp->sec) > (86400*5))) {
if (opts & OPT_SYSLOG)
syslog(LOG_INFO, "Out of sync! (1,%x)\n", now);
else
fprintf(log, "Out of sync! (1,%x)\n", now);
dumphex(log, buf, sizeof(struct ipl_ci));
resynclog(fd, icp, log);
}
len = (int)((u_int)icp->plen);
if (len > 128 || len < 0) {
if (opts & OPT_SYSLOG)
syslog(LOG_INFO, "Out of sync! (2,%d)\n", len);
else
fprintf(log, "Out of sync! (2,%d)\n", len);
dumphex(log, buf, sizeof(struct ipl_ci));
resynclog(fd, icp, log);
}
tr = icp->hlen + icp->plen;
if (n < tr)
return 1;
for (; (n > 0) && (tr > 0); s += nr, n-= nr) {
nr = read(fd, s, tr);
if (nr > 0)
tr -= nr;
else
return -1;
}
*lenp = s - buf;
return 0;
}
char *hostname(res, ip)
int res;
struct in_addr ip;
{
struct hostent *hp;
if (!res)
return inet_ntoa(ip);
hp = gethostbyaddr((char *)&ip, sizeof(ip), AF_INET);
if (!hp)
return inet_ntoa(ip);
return hp->h_name;
}
char *portname(res, proto, port)
int res;
char *proto;
u_short port;
{
static char pname[8];
struct servent *serv;
(void) sprintf(pname, "%hu", htons(port));
if (!res)
return pname;
serv = getservbyport((int)port, proto);
if (!serv)
return pname;
return serv->s_name;
}
static void dumphex(log, buf, len)
FILE *log;
u_char *buf;
int len;
{
char line[80];
int i, j, k;
u_char *s = buf, *t = (u_char *)line;
for (i = len, j = 0; i; i--, j++, s++) {
if (j && !(j & 0xf)) {
*t++ = '\n';
*t = '\0';
fputs(line, stdout);
t = (u_char *)line;
*t = '\0';
}
sprintf(t, "%02x", *s & 0xff);
t += 2;
if (!((j + 1) & 0xf)) {
s -= 15;
sprintf(t, " ");
t += 8;
for (k = 16; k; k--, s++)
*t++ = (isprint(*s) ? *s : '.');
s--;
}
if ((j + 1) & 0xf)
*t++ = ' ';;
}
if (j & 0xf) {
for (k = 16 - (j & 0xf); k; k--) {
*t++ = ' ';
*t++ = ' ';
*t++ = ' ';
}
sprintf(t, " ");
t += 7;
s -= j & 0xf;
for (k = j & 0xf; k; k--, s++)
*t++ = (isprint(*s) ? *s : '.');
*t++ = '\n';
*t = '\0';
}
fputs(line, stdout);
fflush(stdout);
}
static void printpacket(log, buf, blen)
FILE *log;
char *buf;
int blen;
{
struct protoent *pr;
struct tcphdr *tp;
struct icmp *ic;
struct ip *ipc;
struct tm *tm;
char c[3], pname[8], *t, *proto;
u_short hl, p;
int i, lvl, res;
#if !SOLARIS && !(defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603))
int len;
#endif
struct ip *ip;
struct ipl_ci *lp;
lp = (struct ipl_ci *)buf;
ip = (struct ip *)(buf + sizeof(*lp));
res = (opts & OPT_RESOLVE) ? 1 : 0;
t = line;
*t = '\0';
hl = (ip->ip_hl << 2);
p = (u_short)ip->ip_p;
tm = localtime((time_t *)&lp->sec);
if (!(opts & OPT_SYSLOG)) {
(void) sprintf(t, "%2d/%02d/%4d ",
tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900);
t += strlen(t);
}
#if SOLARIS || (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603))
(void) sprintf(t, "%02d:%02d:%02d.%-.6ld %.*s @%hd ",
tm->tm_hour, tm->tm_min, tm->tm_sec, lp->usec,
(int)sizeof(lp->ifname), lp->ifname, lp->rule);
#else
for (len = 0; len < 3; len++)
if (!lp->ifname[len])
break;
if (lp->ifname[len])
len++;
(void) sprintf(t, "%02d:%02d:%02d.%-.6ld %*.*s%ld @%hd ",
tm->tm_hour, tm->tm_min, tm->tm_sec, lp->usec,
len, len, lp->ifname, lp->unit, lp->rule);
#endif
pr = getprotobynumber((int)p);
if (!pr) {
proto = pname;
sprintf(proto, "%d", (u_int)p);
} else
proto = pr->p_name;
if (lp->flags & (FI_SHORT << 20)) {
c[0] = 'S';
lvl = LOG_ERR;
} else if (lp->flags & FR_PASS) {
if (lp->flags & FR_LOGP)
c[0] = 'p';
else
c[0] = 'P';
lvl = LOG_NOTICE;
} else if (lp->flags & FR_BLOCK) {
if (lp->flags & FR_LOGB)
c[0] = 'b';
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[1] = ' ';
c[2] = '\0';
(void) strcat(line, c);
t = line + strlen(line);
if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !(ip->ip_off & 0x1fff)) {
tp = (struct tcphdr *)((char *)ip + hl);
if (!(lp->flags & (FI_SHORT << 16))) {
(void) sprintf(t, "%s,%s -> ",
hostname(res, ip->ip_src),
portname(res, proto, tp->th_sport));
t += strlen(t);
(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) {
*t++ = '-';
for (i = 0; tcpfl[i].value; i++)
if (tp->th_flags & tcpfl[i].value)
*t++ = tcpfl[i].flag;
}
if (opts & OPT_VERBOSE) {
(void) sprintf(t, " %lu %lu %hu",
(u_long)tp->th_seq,
(u_long)tp->th_ack, tp->th_win);
t += strlen(t);
}
*t = '\0';
} else {
(void) sprintf(t, "%s -> ", hostname(res, ip->ip_src));
t += strlen(t);
(void) sprintf(t, "%s PR %s len %hu %hu",
hostname(res, ip->ip_dst), proto,
hl, ip->ip_len);
}
} else if (p == IPPROTO_ICMP) {
ic = (struct icmp *)((char *)ip + hl);
(void) sprintf(t, "%s -> ", hostname(res, ip->ip_src));
t += strlen(t);
(void) sprintf(t, "%s PR icmp len %hu (%hu) icmp %d/%d",
hostname(res, ip->ip_dst), hl,
ip->ip_len, ic->icmp_type, ic->icmp_code);
if (ic->icmp_type == ICMP_UNREACH ||
ic->icmp_type == ICMP_SOURCEQUENCH ||
ic->icmp_type == ICMP_PARAMPROB ||
ic->icmp_type == ICMP_REDIRECT ||
ic->icmp_type == ICMP_TIMXCEED) {
ipc = &ic->icmp_ip;
tp = (struct tcphdr *)((char *)ipc + hl);
p = (u_short)ipc->ip_p;
pr = getprotobynumber((int)p);
if (!pr) {
proto = pname;
(void) sprintf(proto, "%d", (int)p);
} else
proto = pr->p_name;
t += strlen(t);
(void) sprintf(t, " for %s,%s -",
hostname(res, ipc->ip_src),
portname(res, proto, tp->th_sport));
t += strlen(t);
(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);
}
} else {
(void) sprintf(t, "%s -> ", hostname(res, ip->ip_src));
t += strlen(t);
(void) sprintf(t, "%s PR %s len %hu (%hu)",
hostname(res, ip->ip_dst), proto, hl, ip->ip_len);
t += strlen(t);
if (ip->ip_off & 0x1fff)
(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);
if (lp->flags & FR_KEEPSTATE) {
(void) strcpy(t, " K-S");
t += strlen(t);
}
if (lp->flags & FR_KEEPFRAG) {
(void) strcpy(t, " K-F");
t += strlen(t);
}
*t++ = '\n';
*t++ = '\0';
if (opts & OPT_SYSLOG)
syslog(lvl, "%s", line);
else
(void) fprintf(log, "%s", line);
if (opts & OPT_HEXHDR)
dumphex(log, buf, sizeof(struct ipl_ci));
if (opts & OPT_HEXBODY)
dumphex(log, ip, lp->plen + lp->hlen);
fflush(log);
}
int main(argc, argv)
int argc;
char *argv[];
{
FILE *log = NULL;
int fd = -1, flushed = 0, doread, n;
char buf[512], c, *iplfile = IPL_NAME;
extern int optind;
extern char *optarg;
while ((c = getopt(argc, argv, "Nf:FsvxX")) != -1)
switch (c)
{
case 'f' :
iplfile = optarg;
break;
case 'F' :
if ((fd == -1) &&
(fd = open(iplfile, O_RDWR)) == -1) {
(void) fprintf(stderr, "%s: ", IPL_NAME);
perror("open");
exit(-1);
}
if (ioctl(fd, SIOCIPFFB, &flushed) == 0) {
printf("%d bytes flushed from log buffer\n",
flushed);
fflush(stdout);
} else
perror("SIOCIPFFB");
break;
case 'N' :
opts |= OPT_RESOLVE;
break;
case 's' :
openlog(argv[0], LOG_NDELAY|LOG_PID, LOGFAC);
opts |= OPT_SYSLOG;
break;
case 'v' :
opts |= OPT_VERBOSE;
break;
case 'x' :
opts |= OPT_HEXBODY;
break;
case 'X' :
opts |= OPT_HEXHDR;
break;
}
if ((fd == -1) && (fd = open(iplfile, O_RDONLY)) == -1) {
(void) fprintf(stderr, "%s: ", IPL_NAME);
perror("open");
exit(-1);
}
if (!(opts & OPT_SYSLOG)) {
log = argv[optind] ? fopen(argv[optind], "a") : stdout;
setvbuf(log, NULL, _IONBF, 0);
}
if (flushed) {
if (opts & OPT_SYSLOG)
syslog(LOG_INFO, "%d bytes flushed from log\n",
flushed);
else
fprintf(log, "%d bytes flushed from log\n", flushed);
}
for (doread = 1; doread; )
switch (readlogentry(fd, &n, buf, sizeof(buf), log))
{
case -1 :
if (opts & OPT_SYSLOG)
syslog(LOG_ERR, "read: %m\n");
else
perror("read");
doread = 0;
break;
case 1 :
if (opts & OPT_SYSLOG)
syslog(LOG_ERR, "aborting logging\n");
else
fprintf(log, "aborting logging\n");
doread = 0;
break;
case 2 :
break;
case 0 :
printpacket(log, buf, n, opts);
break;
}
exit(0);
/* NOTREACHED */
}

692
contrib/ipfilter/ipnat.c Normal file
View File

@ -0,0 +1,692 @@
/*
* (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.
*
* Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com)
*
* Broken still:
* Displaying the nat with redirect entries is way confusing
*
* Example redirection line:
* rdr le1 0.0.0.0/0 port 79 -> 199.165.219.129 port 9901
*
* Will redirect all incoming packets on le1 to any machine, port 79 to
* host 199.165.219.129, port 9901
*/
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#if !defined(__SVR4) && !defined(__svr4__)
#include <strings.h>
#else
#include <sys/byteorder.h>
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#if defined(sun) && (defined(__svr4__) || defined(__SVR4))
# include <sys/ioccom.h>
# include <sys/sysmacros.h>
#endif
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <net/if.h>
#include "ip_compat.h"
#include <netdb.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <resolv.h>
#include "ip_nat.h"
#include <ctype.h>
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed";
static char rcsid[] = "$Id: ipnat.c,v 2.0.1.7 1997/01/30 12:02:32 darrenr Exp $";
#endif
#if SOLARIS
#define bzero(a,b) memset(a,0,b)
#endif
extern char *optarg;
extern int kmemcpy();
void dostats(), printnat(), parsefile(), flushtable();
#define OPT_REM 1
#define OPT_NODO 2
#define OPT_STAT 4
#define OPT_LIST 8
#define OPT_VERBOSE 16
#define OPT_FLUSH 32
#define OPT_CLEAR 64
void usage(name)
char *name;
{
fprintf(stderr, "%s: [-CFlnrsv] [-f filename]\n", name);
exit(1);
}
int main(argc, argv)
int argc;
char *argv[];
{
char *file = NULL, c;
int fd, opts = 1;
while ((c = getopt(argc, argv, "CFf:lnrsv")) != -1)
switch (c)
{
case 'C' :
opts |= OPT_CLEAR;
break;
case 'f' :
file = optarg;
break;
case 'F' :
opts |= OPT_FLUSH;
break;
case 'l' :
opts |= OPT_LIST;
break;
case 'n' :
opts |= OPT_NODO;
break;
case 'r' :
opts &= ~OPT_REM;
break;
case 's' :
opts |= OPT_STAT;
break;
case 'v' :
opts |= OPT_VERBOSE;
break;
default :
usage(argv[0]);
}
if (!(opts & OPT_NODO) && ((fd = open(IPL_NAME, O_RDWR)) == -1) &&
((fd = open(IPL_NAME, O_RDONLY)) == -1)) {
perror("open");
exit(-1);
}
if (opts & (OPT_FLUSH|OPT_CLEAR))
flushtable(fd, opts);
if (file)
parsefile(fd, file, opts);
if (opts & (OPT_LIST|OPT_STAT))
dostats(fd, opts);
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 #
* of bits.
*/
int countbits(ip)
u_long ip;
{
u_long ipn;
int cnt = 0, i, j;
ip = ipn = ntohl(ip);
for (i = 32; i; i--, ipn *= 2)
if (ipn & 0x80000000)
cnt++;
else
break;
ipn = 0;
for (i = 32, j = cnt; i; i--, j--) {
ipn *= 2;
if (j > 0)
ipn++;
}
if (ipn == ip)
return cnt;
return -1;
}
void printnat(np, verbose, ptr)
ipnat_t *np;
int verbose;
void *ptr;
{
int bits;
if (np->in_redir == NAT_REDIRECT) {
printf("rdr %s %s", np->in_ifname, inet_ntoa(np->in_out[0]));
bits = countbits(np->in_out[1].s_addr);
if (bits != -1)
printf("/%d ", bits);
else
printf("/%s ", inet_ntoa(np->in_out[1]));
if (np->in_pmin)
printf("port %d ", ntohs(np->in_pmin));
printf("-> %s", inet_ntoa(np->in_in[0]));
if (np->in_pnext)
printf(" port %d", ntohs(np->in_pnext));
if (np->in_flags & IPN_TCPUDP)
printf(" tcp/udp");
else if (np->in_flags & IPN_TCP)
printf(" tcp");
else if (np->in_flags & IPN_UDP)
printf(" udp");
printf("\n");
if (verbose)
printf("\t%x %u %x %u %x %d\n", (u_int)np->in_ifp,
np->in_space, np->in_flags, np->in_pnext, np,
np->in_use);
} else {
np->in_nextip.s_addr = htonl(np->in_nextip.s_addr);
printf("map %s %s/", np->in_ifname, inet_ntoa(np->in_in[0]));
bits = countbits(np->in_in[1].s_addr);
if (bits != -1)
printf("%d ", bits);
else
printf("%s", inet_ntoa(np->in_in[1]));
printf(" -> %s/", inet_ntoa(np->in_out[0]));
bits = countbits(ntohl(np->in_out[1].s_addr));
if (bits != -1)
printf("%d ", bits);
else
printf("%s", inet_ntoa(np->in_out[1]));
if (np->in_pmin || np->in_pmax) {
printf(" portmap");
if ((np->in_flags & IPN_TCPUDP) == IPN_TCPUDP)
printf(" tcp/udp");
else if (np->in_flags & IPN_TCP)
printf(" tcp");
else if (np->in_flags & IPN_UDP)
printf(" udp");
printf(" %d:%d", ntohs(np->in_pmin),
ntohs(np->in_pmax));
}
printf("\n");
if (verbose)
printf("\t%x %u %s %d %x\n", (u_int)np->in_ifp,
np->in_space, inet_ntoa(np->in_nextip),
np->in_pnext, np->in_flags);
}
}
/*
* Get a nat filter type given its kernel address.
*/
char *getnattype(ipnat)
ipnat_t *ipnat;
{
ipnat_t ipnatbuff;
if (ipnat && kmemcpy(&ipnatbuff, ipnat, sizeof(ipnatbuff)))
return "???";
return (ipnatbuff.in_redir == NAT_MAP) ? "MAP" : "RDR";
}
void dostats(fd, opts)
int fd, opts;
{
natstat_t ns;
ipnat_t ipn;
nat_t **nt[2], *np, nat;
int i = 0;
bzero((char *)&ns, sizeof(ns));
if (!(opts & OPT_NODO) && ioctl(fd, SIOCGNATS, &ns) == -1) {
perror("ioctl(SIOCGNATS)");
return;
}
if (opts & OPT_STAT) {
printf("mapped\tin\t%lu\tout\t%lu\n",
ns.ns_mapped[0], ns.ns_mapped[1]);
printf("added\t%lu\texpired\t%lu\n",
ns.ns_added, ns.ns_expire);
printf("inuse\t%lu\n", ns.ns_inuse);
if (opts & OPT_VERBOSE)
printf("table %#x list %#x\n",
(u_int)ns.ns_table, (u_int)ns.ns_list);
}
if (opts & OPT_LIST) {
printf("List of active MAP/Redirect filters:\n");
while (ns.ns_list) {
if (kmemcpy(&ipn, ns.ns_list, sizeof(ipn))) {
perror("kmemcpy");
break;
}
printnat(&ipn, opts & OPT_VERBOSE, (void *)ns.ns_list);
ns.ns_list = ipn.in_next;
}
nt[0] = (nat_t **)malloc(sizeof(*nt) * NAT_SIZE);
if (kmemcpy(nt[0], ns.ns_table[0], sizeof(**nt) * NAT_SIZE)) {
perror("kmemcpy");
return;
}
printf("\nList of active sessions:\n");
for (i = 0; i < NAT_SIZE; i++)
for (np = nt[0][i]; np; np = nat.nat_hnext[0]) {
if (kmemcpy(&nat, np, sizeof(nat)))
break;
printf("%s %-15s %-5hu <- ->",
getnattype(nat.nat_ptr),
inet_ntoa(nat.nat_inip),
ntohs(nat.nat_inport));
printf(" %-15s %-5hu",
inet_ntoa(nat.nat_outip),
ntohs(nat.nat_outport));
printf(" [%s %hu]", inet_ntoa(nat.nat_oip),
ntohs(nat.nat_oport));
printf(" %d %hu %lx", nat.nat_age,
nat.nat_use, nat.nat_sumd);
#if SOLARIS
printf(" %lx", nat.nat_ipsumd);
#endif
putchar('\n');
}
free(nt[0]);
}
}
u_short portnum(name, proto)
char *name, *proto;
{
struct servent *sp, *sp2;
u_short p1 = 0;
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)
return sp->s_port;
(void) fprintf(stderr, "unknown service \"%s\".\n", name);
return 0;
}
sp = getservbyname(name, "tcp");
if (sp)
p1 = sp->s_port;
sp2 = getservbyname(name, "udp");
if (!sp || !sp2) {
(void) fprintf(stderr, "unknown tcp/udp service \"%s\".\n",
name);
return 0;
}
if (p1 != sp2->s_port) {
(void) fprintf(stderr, "%s %d/tcp is a different port to ",
name, p1);
(void) fprintf(stderr, "%s %d/udp\n", name, sp->s_port);
return 0;
}
return p1;
}
u_long hostmask(msk)
char *msk;
{
int bits = -1;
u_long mask;
if (!isdigit(*msk))
return (u_long)-1;
if (strchr(msk, '.'))
return inet_addr(msk);
if (strchr(msk, 'x'))
return (u_long)strtol(msk, NULL, 0);
/*
* set x most significant bits
*/
for (mask = 0, bits = atoi(msk); bits; bits--) {
mask /= 2;
mask |= ntohl(inet_addr("128.0.0.0"));
}
mask = htonl(mask);
return mask;
}
/*
* 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, 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 (!(hp = gethostbyname(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;
}
ipnat_t *parse(line)
char *line;
{
static ipnat_t ipn;
char *s, *t;
char *shost, *snetm, *dhost, *proto;
char *dnetm = NULL, *dport = NULL, *tport = NULL;
int resolved;
bzero((char *)&ipn, sizeof(ipn));
if ((s = strchr(line, '\n')))
*s = '\0';
if ((s = strchr(line, '#')))
*s = '\0';
if (!*line)
return NULL;
if (!(s = strtok(line, " \t")))
return NULL;
if (!strcasecmp(s, "map"))
ipn.in_redir = NAT_MAP;
else if (!strcasecmp(s, "rdr"))
ipn.in_redir = NAT_REDIRECT;
else {
(void)fprintf(stderr,
"expected \"map\" or \"rdr\", got \"%s\"\n", s);
return NULL;
}
if (!(s = strtok(NULL, " \t"))) {
fprintf(stderr, "missing fields (interface)\n");
return NULL;
}
strncpy(ipn.in_ifname, s, sizeof(ipn.in_ifname) - 1);
ipn.in_ifname[sizeof(ipn.in_ifname) - 1] = '\0';
if (!(s = strtok(NULL, " \t"))) {
fprintf(stderr, "missing fields (%s)\n",
ipn.in_redir ? "destination": "source");
return NULL;
}
shost = s;
if (ipn.in_redir == NAT_REDIRECT) {
if (!(s = strtok(NULL, " \t"))) {
fprintf(stderr, "missing fields (destination port)\n");
return NULL;
}
if (strcasecmp(s, "port")) {
fprintf(stderr, "missing fields (port)\n");
return NULL;
}
if (!(s = strtok(NULL, " \t"))) {
fprintf(stderr, "missing fields (destination port)\n");
return NULL;
}
dport = s;
}
if (!(s = strtok(NULL, " \t"))) {
fprintf(stderr, "missing fields (->)\n");
return NULL;
}
if (!strcmp(s, "->")) {
snetm = strrchr(shost, '/');
if (!snetm) {
fprintf(stderr, "missing fields (%s netmask)\n",
ipn.in_redir ? "destination":"source");
return NULL;
}
} else {
if (strcasecmp(s, "netmask")) {
fprintf(stderr, "missing fields (netmask)\n");
return NULL;
}
if (!(s = strtok(NULL, " \t"))) {
fprintf(stderr, "missing fields (%s netmask)\n",
ipn.in_redir ? "destination":"source");
return NULL;
}
snetm = s;
}
if (!(s = strtok(NULL, " \t"))) {
fprintf(stderr, "missing fields (%s)\n",
ipn.in_redir ? "destination":"target");
return NULL;
}
dhost = s;
if (ipn.in_redir == NAT_MAP) {
if (!(s = strtok(NULL, " \t"))) {
dnetm = strrchr(dhost, '/');
if (!dnetm) {
fprintf(stderr,
"missing fields (dest netmask)\n");
return NULL;
}
}
if (!s || !strcasecmp(s, "portmap")) {
dnetm = strrchr(dhost, '/');
if (!dnetm) {
fprintf(stderr,
"missing fields (dest netmask)\n");
return NULL;
}
} else {
if (strcasecmp(s, "netmask")) {
fprintf(stderr,
"missing fields (dest netmask)\n");
return NULL;
}
if (!(s = strtok(NULL, " \t"))) {
fprintf(stderr,
"missing fields (dest netmask)\n");
return NULL;
}
dnetm = s;
}
if (*dnetm == '/')
*dnetm++ = '\0';
} else {
/* If it's a in_redir, expect target port */
if (!(s = strtok(NULL, " \t"))) {
fprintf(stderr, "missing fields (destination port)\n");
return NULL;
}
if (strcasecmp(s, "port")) {
fprintf(stderr, "missing fields (port)\n");
return NULL;
}
if (!(s = strtok(NULL, " \t"))) {
fprintf(stderr, "missing fields (destination port)\n");
return NULL;
}
tport = s;
}
if (*snetm == '/')
*snetm++ = '\0';
if (ipn.in_redir == NAT_MAP) {
ipn.in_inip = hostnum(shost, &resolved);
if (resolved == -1)
return NULL;
ipn.in_inmsk = hostmask(snetm);
ipn.in_outip = hostnum(dhost, &resolved);
if (resolved == -1)
return NULL;
ipn.in_outmsk = hostmask(dnetm);
} else {
ipn.in_inip = hostnum(dhost, &resolved); /* Inside is target */
if (resolved == -1)
return NULL;
ipn.in_inmsk = hostmask("255.255.255.255");
ipn.in_outip = hostnum(shost, &resolved);
if (resolved == -1)
return NULL;
ipn.in_outmsk = hostmask(snetm);
if (!(s = strtok(NULL, " \t"))) {
ipn.in_flags = IPN_TCP; /* XXX- TCP only by default */
proto = "tcp";
} else {
if (!strcasecmp(s, "tcp"))
ipn.in_flags = IPN_TCP;
else if (!strcasecmp(s, "udp"))
ipn.in_flags = IPN_UDP;
else if (!strcasecmp(s, "tcp/udp"))
ipn.in_flags = IPN_TCPUDP;
else if (!strcasecmp(s, "tcpudp"))
ipn.in_flags = IPN_TCPUDP;
else {
fprintf(stderr,
"expected protocol - got \"%s\"\n", s);
return NULL;
}
proto = s;
if ((s = strtok(NULL, " \t"))) {
fprintf(stderr,
"extra junk at the end of rdr: %s\n",
s);
return NULL;
}
}
ipn.in_pmin = portnum(dport, proto); /* dest port */
ipn.in_pmax = ipn.in_pmin; /* NECESSARY of removing nats */
ipn.in_pnext = portnum(tport, proto); /* target port */
s = NULL; /* That's all she wrote! */
}
if (!s)
return &ipn;
if (strcasecmp(s, "portmap")) {
fprintf(stderr, "expected \"portmap\" - got \"%s\"\n", s);
return NULL;
}
if (!(s = strtok(NULL, " \t")))
return NULL;
if (!strcasecmp(s, "tcp"))
ipn.in_flags = IPN_TCP;
else if (!strcasecmp(s, "udp"))
ipn.in_flags = IPN_UDP;
else if (!strcasecmp(s, "tcpudp"))
ipn.in_flags = IPN_TCPUDP;
else if (!strcasecmp(s, "tcp/udp"))
ipn.in_flags = IPN_TCPUDP;
else {
fprintf(stderr, "expected protocol name - got \"%s\"\n", s);
return NULL;
}
proto = s;
if (!(s = strtok(NULL, " \t"))) {
fprintf(stderr, "no port range found\n");
return NULL;
}
if (!(t = strchr(s, ':'))) {
fprintf(stderr, "no port range in \"%s\"\n", s);
return NULL;
}
*t++ = '\0';
ipn.in_pmin = portnum(s, proto);
ipn.in_pmax = portnum(t, proto);
return &ipn;
}
void parsefile(fd, file, opts)
int fd;
char *file;
int opts;
{
char line[512], *s;
ipnat_t *np;
FILE *fp;
int linenum = 1;
if (strcmp(file, "-"))
fp = fopen(file, "r");
else
fp = stdin;
while (fgets(line, sizeof(line) - 1, fp)) {
line[sizeof(line) - 1] = '\0';
if ((s = strchr(line, '\n')))
*s = '\0';
if (!(np = parse(line))) {
if (*line)
fprintf(stderr, "%d: syntax error in \"%s\"\n",
linenum, line);
} else if (!(opts & OPT_NODO)) {
if ((opts & OPT_VERBOSE) && np)
printnat(np, opts & OPT_VERBOSE, NULL);
if (opts & OPT_REM) {
if (ioctl(fd, SIOCADNAT, np) == -1)
perror("ioctl(SIOCADNAT)");
} else if (ioctl(fd, SIOCRMNAT, np) == -1)
perror("ioctl(SIOCRMNAT)");
}
linenum++;
}
fclose(stdin);
}
void flushtable(fd, opts)
int fd, opts;
{
int n = 0;
if (opts & OPT_FLUSH) {
n = 0;
if (!(opts & OPT_NODO) && ioctl(fd, SIOCFLNAT, &n) == -1)
perror("ioctl(SIOCFLNAT)");
else
printf("%d entries flushed from NAT table\n", n);
}
if (opts & OPT_CLEAR) {
n = 0;
if (!(opts & OPT_NODO) && ioctl(fd, SIOCCNATL, &n) == -1)
perror("ioctl(SIOCCNATL)");
else
printf("%d entries flushed from NAT list\n", n);
}
}

View File

@ -0,0 +1,63 @@
#
# (C)opyright 1993-1996 by Darren Reed.
#
# This code may be freely distributed as long as it retains this notice
# and is not changed in any way. The author accepts no responsibility
# for the use of this software. I hate legaleese, don't you ?
#
OBJS=ipsd.o
BINDEST=/usr/local/bin
SBINDEST=/sbin
MANDIR=/usr/share/man
BPF=sbpf.o
NIT=snit.o
SUNOS4=
BSD=
LINUX=slinux.o
SUNOS5=dlcommon.o sdlpi.o
CC=gcc
CFLAGS=-g -I..
all:
@echo "Use one of these targets:"
@echo " sunos4-nit (standard SunOS 4.1.x)"
@echo " sunos4-bpf (SunOS4.1.x with BPF in the kernel)"
@echo " bsd-bpf (4.4BSD variant with BPF in the kernel)"
@echo " linux (Linux kernels)"
@echo " sunos5 (Solaris 2.x)"
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
ipsdr: ipsdr.o
$(CC) ipsdr.o -o $@ $(LIBS)
bpf sunos4-bpf :
make ipsd "OBJS=$(OBJS)" "UNIXOBJS=$(BPF) $(SUNOS4)" "CC=$(CC)" \
"CFLAGS=$(CFLAGS)"
nit sunos4 sunos4-nit :
make ipsd "OBJS=$(OBJS)" "UNIXOBJS=$(NIT) $(SUNOS4)" "CC=$(CC)" \
"CFLAGS=$(CFLAGS)"
sunos5 :
make ipsd "OBJS=$(OBJS)" "UNIXOBJS=$(SUNOS5)" "CC=$(CC)" \
CFLAGS="$(CFLAGS) -Dsolaris" "LIBS=-lsocket -lnsl"
bsd-bpf :
make ipsd "OBJS=$(OBJS)" "UNIXOBJS=$(BPF) $(BSD)" "CC=$(CC)" \
"CFLAGS=$(CFLAGS)"
linux :
make ipsd "OBJS=$(OBJS)" "UNIXOBJS=$(LINUX)" "CC=$(CC)" \
CFLAGS="$(CFLAGS) -I /usr/src/linux"
ipsd: $(OBJS) $(UNIXOBJS)
$(CC) $(OBJS) $(UNIXOBJS) -o $@ $(LIBS)
../ipft_sn.o ../ipft_pc.o:
(cd ..; make $(@:../%=%))
clean:
rm -rf *.o core a.out ipsd ipsdr

View File

@ -0,0 +1,32 @@
IP Scan Detetor.
----------------
This program is designed to be a passive listener for TCP packets sent to
the host. It does not exercise the promiscous mode of interfaces. For
routing Unix boxes (and firewalls which route/proxy) this is sufficient to
detect all packets going to/through them.
Upon compiling, a predefined set of "sensitive" ports are configured into
the program. Any TCP packets which are seen sent to these ports are counted
and the IP# of the sending host recorded, along with the time of the first
packet to that port for that IP#.
After a given number of "hits", it will write the current table of packets
out to disk. This number defaults to 10,000.
To analyze the information written to disk, a sample program called "ipsdr"
is used (should but doesn't implement a tree algorithm for storing data)
which reads all log files it recognises and totals up the number of ports
each host hit. By default, all ports have the same weighting (1). Another
group of passes is then made over this table using a netmask of 0xfffffffe,
grouping all results which fall under the same resulting IP#. This netmask
is then shrunk back to 0, with a output for each level given. This is aimed
at detecting port scans done from different hosts on the same subnet (although
I've not seen this done, if one was trying to do it obscurely...)
Lastly, being passive means that no action is taken to stop port scans being
done or discourage them.
Darren
darrenr@cyber.com.au

View File

@ -0,0 +1,201 @@
/*
* (C)opyright 1995 by Darren Reed.
*
* This code may be freely distributed as long as it retains this notice
* and is not changed in any way. The author accepts no responsibility
* for the use of this software. I hate legaleese, don't you ?
*
* @(#)ip_compat.h 1.1 9/14/95
*/
/*
* These #ifdef's are here mainly for linux, but who knows, they may
* not be in other places or maybe one day linux will grow up and some
* of these will turn up there too.
*/
#ifndef ICMP_UNREACH
# define ICMP_UNREACH ICMP_DEST_UNREACH
#endif
#ifndef ICMP_SOURCEQUENCH
# define ICMP_SOURCEQUENCH ICMP_SOURCE_QUENCH
#endif
#ifndef ICMP_TIMXCEED
# define ICMP_TIMXCEED ICMP_TIME_EXCEEDED
#endif
#ifndef ICMP_PARAMPROB
# define ICMP_PARAMPROB ICMP_PARAMETERPROB
#endif
#ifndef IPVERSION
# define IPVERSION 4
#endif
#ifndef IPOPT_MINOFF
# define IPOPT_MINOFF 4
#endif
#ifndef IPOPT_COPIED
# define IPOPT_COPIED(x) ((x)&0x80)
#endif
#ifndef IPOPT_EOL
# define IPOPT_EOL 0
#endif
#ifndef IPOPT_NOP
# define IPOPT_NOP 1
#endif
#ifndef IP_MF
# define IP_MF ((u_short)0x2000)
#endif
#ifndef ETHERTYPE_IP
# define ETHERTYPE_IP ((u_short)0x0800)
#endif
#ifndef TH_FIN
# define TH_FIN 0x01
#endif
#ifndef TH_SYN
# define TH_SYN 0x02
#endif
#ifndef TH_RST
# define TH_RST 0x04
#endif
#ifndef TH_PUSH
# define TH_PUSH 0x08
#endif
#ifndef TH_ACK
# define TH_ACK 0x10
#endif
#ifndef TH_URG
# define TH_URG 0x20
#endif
#ifndef IPOPT_EOL
# define IPOPT_EOL 0
#endif
#ifndef IPOPT_NOP
# define IPOPT_NOP 1
#endif
#ifndef IPOPT_RR
# define IPOPT_RR 7
#endif
#ifndef IPOPT_TS
# define IPOPT_TS 68
#endif
#ifndef IPOPT_SECURITY
# define IPOPT_SECURITY 130
#endif
#ifndef IPOPT_LSRR
# define IPOPT_LSRR 131
#endif
#ifndef IPOPT_SATID
# define IPOPT_SATID 136
#endif
#ifndef IPOPT_SSRR
# define IPOPT_SSRR 137
#endif
#ifndef IPOPT_SECUR_UNCLASS
# define IPOPT_SECUR_UNCLASS ((u_short)0x0000)
#endif
#ifndef IPOPT_SECUR_CONFID
# define IPOPT_SECUR_CONFID ((u_short)0xf135)
#endif
#ifndef IPOPT_SECUR_EFTO
# define IPOPT_SECUR_EFTO ((u_short)0x789a)
#endif
#ifndef IPOPT_SECUR_MMMM
# define IPOPT_SECUR_MMMM ((u_short)0xbc4d)
#endif
#ifndef IPOPT_SECUR_RESTR
# define IPOPT_SECUR_RESTR ((u_short)0xaf13)
#endif
#ifndef IPOPT_SECUR_SECRET
# define IPOPT_SECUR_SECRET ((u_short)0xd788)
#endif
#ifndef IPOPT_SECUR_TOPSECRET
# define IPOPT_SECUR_TOPSECRET ((u_short)0x6bc5)
#endif
#ifdef linux
# define icmp icmphdr
# define icmp_type type
# define icmp_code code
/*
* From /usr/include/netinet/ip_var.h
* !%@#!$@# linux...
*/
struct ipovly {
caddr_t ih_next, ih_prev; /* for protocol sequence q's */
u_char ih_x1; /* (unused) */
u_char ih_pr; /* protocol */
short ih_len; /* protocol length */
struct in_addr ih_src; /* source internet address */
struct in_addr ih_dst; /* destination internet address */
};
typedef struct {
__u16 th_sport;
__u16 th_dport;
__u32 th_seq;
__u32 th_ack;
# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\
defined(vax)
__u8 th_res:4;
__u8 th_off:4;
#else
__u8 th_off:4;
__u8 th_res:4;
#endif
__u8 th_flags;
__u16 th_win;
__u16 th_sum;
__u16 th_urp;
} tcphdr_t;
typedef struct {
__u16 uh_sport;
__u16 uh_dport;
__s16 uh_ulen;
__u16 uh_sum;
} udphdr_t;
typedef struct {
# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\
defined(vax)
__u8 ip_hl:4;
__u8 ip_v:4;
# else
__u8 ip_hl:4;
__u8 ip_v:4;
# endif
__u8 ip_tos;
__u16 ip_len;
__u16 ip_id;
__u16 ip_off;
__u8 ip_ttl;
__u8 ip_p;
__u16 ip_sum;
struct in_addr ip_src;
struct in_addr ip_dst;
} ip_t;
typedef struct {
__u8 ether_dhost[6];
__u8 ether_shost[6];
__u16 ether_type;
} ether_header_t;
# define bcopy(a,b,c) memmove(b,a,c)
# define bcmp(a,b,c) memcmp(a,b,c)
# define ifnet device
#else
typedef struct udphdr udphdr_t;
typedef struct tcphdr tcphdr_t;
typedef struct ip ip_t;
typedef struct ether_header ether_header_t;
#endif
#ifdef solaris
# define bcopy(a,b,c) memmove(b,a,c)
# define bcmp(a,b,c) memcmp(a,b,c)
# define bzero(a,b) memset(a,0,b)
#endif

View File

@ -0,0 +1,297 @@
/*
* (C)opyright December 1995 Darren Reed.
*
* This software may be freely distributed as long as it is not altered
* in any way and that this messagge always accompanies it.
*
* The author of this software makes no garuntee about the
* performance of this package or its suitability to fulfill any purpose.
*
*/
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#ifndef linux
#include <netinet/ip_var.h>
#include <netinet/tcpip.h>
#endif
#include "ip_compat.h"
#ifdef linux
#include <linux/sockios.h>
#include "tcpip.h"
#endif
#include "ipsd.h"
#ifndef lint
static char sccsid[] = "@(#)ipsd.c 1.3 12/3/95 (C)1995 Darren Reed";
#endif
extern char *optarg;
extern int optind;
#ifdef linux
char default_device[] = "eth0";
#else
# ifdef sun
char default_device[] = "le0";
# else
# ifdef ultrix
char default_device[] = "ln0";
# else
char default_device[] = "lan0";
# endif
# endif
#endif
#define NPORTS 21
u_short defports[NPORTS] = {
7, 9, 20, 21, 23, 25, 53, 69, 79, 111,
123, 161, 162, 512, 513, 514, 515, 520, 540, 6000, 0
};
ipsd_t *iphits[NPORTS];
int writes = 0;
int ipcmp(sh1, sh2)
sdhit_t *sh1, *sh2;
{
return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr;
}
/*
* Check to see if we've already received a packet from this host for this
* port.
*/
int findhit(ihp, src, dport)
ipsd_t *ihp;
struct in_addr src;
u_short dport;
{
int i, j, k;
sdhit_t *sh;
sh = NULL;
if (ihp->sd_sz == 4) {
for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++)
if (src.s_addr == sh->sh_ip.s_addr)
return 1;
} else {
for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) {
k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr;
if (!k)
return 1;
else if (k < 0)
i -= j;
else
i += j;
}
}
return 0;
}
/*
* Search for port number amongst the sorted array of targets we're
* interested in.
*/
int detect(ip, tcp)
ip_t *ip;
tcphdr_t *tcp;
{
ipsd_t *ihp;
sdhit_t *sh;
int i, j, k;
for (i = 10, j = 4; j >= 0; j--) {
k = tcp->th_dport - defports[i];
if (!k) {
ihp = iphits[i];
if (findhit(ihp, ip->ip_src, tcp->th_dport))
return 0;
sh = ihp->sd_hit + ihp->sd_cnt;
sh->sh_date = time(NULL);
sh->sh_ip.s_addr = ip->ip_src.s_addr;
if (++ihp->sd_cnt == ihp->sd_sz)
{
ihp->sd_sz += 8;
sh = realloc(sh, ihp->sd_sz * sizeof(*sh));
ihp->sd_hit = sh;
}
qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp);
return 0;
}
if (k < 0)
i -= j;
else
i += j;
}
return -1;
}
/*
* Allocate initial storage for hosts
*/
setuphits()
{
int i;
for (i = 0; i < NPORTS; i++) {
if (iphits[i]) {
if (iphits[i]->sd_hit)
free(iphits[i]->sd_hit);
free(iphits[i]);
}
iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t));
iphits[i]->sd_port = defports[i];
iphits[i]->sd_cnt = 0;
iphits[i]->sd_sz = 4;
iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4);
}
}
/*
* cleanup exits
*/
waiter()
{
wait(0);
}
/*
* Write statistics out to a file
*/
writestats(nwrites)
int nwrites;
{
ipsd_t **ipsd, *ips;
char fname[32];
int i, fd;
(void) sprintf(fname, "/var/log/ipsd/ipsd-hits.%d", nwrites);
fd = open(fname, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0644);
for (i = 0, ipsd = iphits; i < NPORTS; i++, ipsd++) {
ips = *ipsd;
if (ips->sd_cnt) {
write(fd, ips, sizeof(ipsd_t));
write(fd, ips->sd_hit, sizeof(sdhit_t) * ips->sd_sz);
}
}
(void) close(fd);
exit(0);
}
void writenow()
{
signal(SIGCHLD, waiter);
switch (fork())
{
case 0 :
writestats(writes);
exit(0);
case -1 :
perror("vfork");
break;
default :
writes++;
setuphits();
break;
}
}
void usage(prog)
char *prog;
{
fprintf(stderr, "Usage: %s [-d device]\n", prog);
exit(1);
}
void detecthits(fd, writecount)
int fd, writecount;
{
struct in_addr ip;
int hits = 0;
while (1) {
hits += readloop(fd, ip);
if (hits > writecount) {
writenow();
hits = 0;
}
}
}
main(argc, argv)
int argc;
char *argv[];
{
char c, *name = argv[0], *dev = NULL;
int fd, writeafter = 10000, angelic = 0;
while ((c = getopt(argc, argv, "ad:n:")) != -1)
switch (c)
{
case 'a' :
angelic = 1;
break;
case 'd' :
dev = optarg;
break;
case 'n' :
writeafter = atoi(optarg);
break;
default :
fprintf(stderr, "Unknown option \"%c\"\n", c);
usage(name);
}
bzero(iphits, sizeof(iphits));
setuphits();
if (!dev)
dev = default_device;
printf("Device: %s\n", dev);
fd = initdevice(dev, 60);
if (!angelic) {
switch (fork())
{
case 0 :
(void) close(0);
(void) close(1);
(void) close(2);
(void) setpgrp(0, getpgrp());
(void) setsid();
break;
case -1:
perror("fork");
exit(-1);
default:
exit(0);
}
}
signal(SIGUSR1, writenow);
detecthits(fd, writeafter);
}

View File

@ -0,0 +1,30 @@
/*
* (C)opyright December 1995 Darren Reed.
*
* This software may be freely distributed as long as it is not altered
* in any way and that this messagge always accompanies it.
*
* The author of this software makes no garuntee about the
* performance of this package or its suitability to fulfill any purpose.
*
* @(#)ipsd.h 1.3 12/3/95
*/
typedef struct {
time_t sh_date;
struct in_addr sh_ip;
} sdhit_t;
typedef struct {
u_int sd_sz;
u_int sd_cnt;
u_short sd_port;
sdhit_t *sd_hit;
} ipsd_t;
typedef struct {
struct in_addr ss_ip;
int ss_hits;
u_long ss_ports;
} ipss_t;

View File

@ -0,0 +1,315 @@
/*
* (C)opyright December 1995 Darren Reed.
*
* This software may be freely distributed as long as it is not altered
* in any way and that this messagge always accompanies it.
*
* The author of this software makes no garuntee about the
* performance of this package or its suitability to fulfill any purpose.
*
*/
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <malloc.h>
#include <netdb.h>
#include <string.h>
#include <sys/dir.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#ifndef linux
#include <netinet/ip_var.h>
#include <netinet/tcpip.h>
#endif
#include "ip_compat.h"
#ifdef linux
#include <linux/sockios.h>
#include "tcpip.h"
#endif
#include "ipsd.h"
#ifndef lint
static char sccsid[] = "@(#)ipsdr.c 1.3 12/3/95 (C)1995 Darren Reed";
#endif
extern char *optarg;
extern int optind;
#define NPORTS 21
u_short defports[NPORTS] = {
7, 9, 20, 21, 23, 25, 53, 69, 79, 111,
123, 161, 162, 512, 513, 513, 515, 520, 540, 6000, 0
};
u_short pweights[NPORTS] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
};
ipsd_t *iphits[NPORTS];
int pkts;
int ipcmp(sh1, sh2)
sdhit_t *sh1, *sh2;
{
return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr;
}
int ssipcmp(sh1, sh2)
ipss_t *sh1, *sh2;
{
return sh1->ss_ip.s_addr - sh2->ss_ip.s_addr;
}
int countpbits(num)
u_long num;
{
int i, j;
for (i = 1, j = 0; i; i <<= 1)
if (num & i)
j++;
return j;
}
/*
* Check to see if we've already received a packet from this host for this
* port.
*/
int findhit(ihp, src, dport)
ipsd_t *ihp;
struct in_addr src;
u_short dport;
{
int i, j, k;
sdhit_t *sh;
sh = NULL;
if (ihp->sd_sz == 4) {
for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++)
if (src.s_addr == sh->sh_ip.s_addr)
return 1;
} else {
for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) {
k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr;
if (!k)
return 1;
else if (k < 0)
i -= j;
else
i += j;
}
}
return 0;
}
/*
* Search for port number amongst the sorted array of targets we're
* interested in.
*/
int detect(srcip, dport, date)
struct in_addr srcip;
u_short dport;
time_t date;
{
ipsd_t *ihp;
sdhit_t *sh;
int i, j, k;
for (i = 10, j = 4; j >= 0; j--) {
k = dport - defports[i];
if (!k) {
ihp = iphits[i];
if (findhit(ihp, srcip, dport))
return 0;
sh = ihp->sd_hit + ihp->sd_cnt;
sh->sh_date = date;
sh->sh_ip = srcip;
if (++ihp->sd_cnt == ihp->sd_sz)
{
ihp->sd_sz += 8;
sh = realloc(sh, ihp->sd_sz * sizeof(*sh));
ihp->sd_hit = sh;
}
qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp);
return 0;
}
if (k < 0)
i -= j;
else
i += j;
}
return -1;
}
/*
* Allocate initial storage for hosts
*/
setuphits()
{
int i;
for (i = 0; i < NPORTS; i++) {
if (iphits[i]) {
if (iphits[i]->sd_hit)
free(iphits[i]->sd_hit);
free(iphits[i]);
}
iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t));
iphits[i]->sd_port = defports[i];
iphits[i]->sd_cnt = 0;
iphits[i]->sd_sz = 4;
iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4);
}
}
/*
* Write statistics out to a file
*/
addfile(file)
char *file;
{
ipsd_t ipsd, *ips = &ipsd;
sdhit_t hit, *hp;
char fname[32];
int i, fd, sz;
if ((fd = open(file, O_RDONLY)) == -1) {
perror("open");
return;
}
printf("opened %s\n", file);
do {
if (read(fd, ips, sizeof(*ips)) != sizeof(*ips))
break;
sz = ips->sd_sz * sizeof(*hp);
hp = (sdhit_t *)malloc(sz);
if (read(fd, hp, sz) != sz)
break;
for (i = 0; i < ips->sd_cnt; i++)
detect(hp[i].sh_ip, ips->sd_port, hp[i].sh_date);
} while (1);
(void) close(fd);
}
readfiles(dir)
char *dir;
{
struct direct **d;
int i, j;
d = NULL;
i = scandir(dir, &d, NULL, NULL);
for (j = 0; j < i; j++) {
if (strncmp(d[j]->d_name, "ipsd-hits.", 10))
continue;
addfile(d[j]->d_name);
}
}
void printreport(ss, num)
ipss_t *ss;
int num;
{
struct in_addr ip;
ipss_t *sp;
int i, j, mask;
u_long ports;
printf("Hosts detected: %d\n", num);
if (!num)
return;
for (i = 0; i < num; i++)
printf("%s %d %d\n", inet_ntoa(ss[i].ss_ip), ss[i].ss_hits,
countpbits(ss[i].ss_ports));
printf("--------------------------\n");
for (mask = 0xfffffffe, j = 32; j; j--, mask <<= 1) {
ip.s_addr = ss[0].ss_ip.s_addr & mask;
ports = ss[0].ss_ports;
for (i = 1; i < num; i++) {
sp = ss + i;
if (ip.s_addr != (sp->ss_ip.s_addr & mask)) {
printf("Netmask: 0x%08x\n", mask);
printf("%s %d\n", inet_ntoa(ip),
countpbits(ports));
ip.s_addr = sp->ss_ip.s_addr & mask;
ports = 0;
}
ports |= sp->ss_ports;
}
if (ports) {
printf("Netmask: 0x%08x\n", mask);
printf("%s %d\n", inet_ntoa(ip), countpbits(ports));
}
}
}
collectips()
{
ipsd_t *ips;
ipss_t *ss;
int i, num, nip, in, j, k;
for (i = 0; i < NPORTS; i++)
nip += iphits[i]->sd_cnt;
ss = (ipss_t *)malloc(sizeof(ipss_t) * nip);
for (in = 0, i = 0, num = 0; i < NPORTS; i++) {
ips = iphits[i];
for (j = 0; j < ips->sd_cnt; j++) {
for (k = 0; k < num; k++)
if (!bcmp(&ss[k].ss_ip, &ips->sd_hit[j].sh_ip,
sizeof(struct in_addr))) {
ss[k].ss_hits += pweights[i];
ss[k].ss_ports |= (1 << i);
break;
}
if (k == num) {
ss[num].ss_ip = ips->sd_hit[j].sh_ip;
ss[num].ss_hits = pweights[i];
ss[k].ss_ports |= (1 << i);
num++;
}
}
}
qsort(ss, num, sizeof(*ss), ssipcmp);
printreport(ss, num);
}
main(argc, argv)
int argc;
char *argv[];
{
char c, *name = argv[0], *dir = NULL;
int fd;
setuphits();
dir = dir ? dir : ".";
readfiles(dir);
collectips();
}

View File

@ -0,0 +1,17 @@
/*
* (C)opyright 1995 by Darren Reed.
*
* This code may be freely distributed as long as it retains this notice
* and is not changed in any way. The author accepts no responsibility
* for the use of this software. I hate legaleese, don't you ?
*
* @(#)linux.h 1.1 8/19/95
*/
#include <linux/config.h>
#ifdef MODULE
#include <linux/module.h>
#include <linux/version.h>
#endif /* MODULE */
#include "ip_compat.h"

View File

@ -0,0 +1,195 @@
/*
* (C)opyright October 1995 Darren Reed. (from tcplog)
*
* This software may be freely distributed as long as it is not altered
* in any way and that this messagge always accompanies it.
*
*/
#include <stdio.h>
#include <netdb.h>
#include <ctype.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/mbuf.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#if BSD < 199103
#include <sys/fcntlcom.h>
#endif
#include <sys/dir.h>
#include <net/bpf.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include "ip_compat.h"
#ifndef lint
static char sbpf[] = "@(#)sbpf.c 1.2 12/3/95 (C)1995 Darren Reed";
#endif
/*
(000) ldh [12]
(001) jeq #0x800 jt 2 jf 5
(002) ldb [23]
(003) jeq #0x6 jt 4 jf 5
(004) ret #68
(005) ret #0
*/
struct bpf_insn filter[] = {
/* 0. */ { BPF_LD|BPF_H|BPF_ABS, 0, 0, 12 },
/* 1. */ { BPF_JMP|BPF_JEQ, 0, 3, 0x0800 },
/* 2. */ { BPF_LD|BPF_B|BPF_ABS, 0, 0, 23 },
/* 3. */ { BPF_JMP|BPF_JEQ, 0, 1, 0x06 },
/* 4. */ { BPF_RET, 0, 0, 68 },
/* 5. */ { BPF_RET, 0, 0, 0 }
};
/*
* the code herein is dervied from libpcap.
*/
static u_char *buf = NULL;
static u_int bufsize = 32768, timeout = 1;
int ack_recv(ep)
char *ep;
{
struct tcpiphdr tip;
tcphdr_t *tcp;
ip_t *ip;
ip = (ip_t *)&tip;
tcp = (tcphdr_t *)(ip + 1);
bcopy(ep + 14, (char *)ip, sizeof(*ip));
bcopy(ep + 14 + (ip->ip_hl << 2), (char *)tcp, sizeof(*tcp));
if (ip->ip_p != IPPROTO_TCP && ip->ip_p != IPPROTO_UDP)
return -1;
if (ip->ip_p & 0x1fff != 0)
return 0;
if (0 == detect(ip, tcp))
return 1;
return 0;
}
int readloop(fd, port, dst)
int fd, port;
struct in_addr dst;
{
register u_char *bp, *cp, *bufend;
register struct bpf_hdr *bh;
register int cc;
time_t in = time(NULL);
int done = 0;
while ((cc = read(fd, buf, bufsize)) >= 0) {
if (!cc && (time(NULL) - in) > timeout)
return done;
bp = buf;
bufend = buf + cc;
/*
* loop through each snapshot in the chunk
*/
while (bp < bufend) {
bh = (struct bpf_hdr *)bp;
cp = bp + bh->bh_hdrlen;
done += ack_recv(cp);
bp += BPF_WORDALIGN(bh->bh_caplen + bh->bh_hdrlen);
}
return done;
}
perror("read");
exit(-1);
}
int initdevice(device, tout)
char *device;
int tout;
{
struct bpf_program prog;
struct bpf_version bv;
struct timeval to;
struct ifreq ifr;
char bpfname[16];
int fd, i;
for (i = 0; i < 16; i++)
{
(void) sprintf(bpfname, "/dev/bpf%d", i);
if ((fd = open(bpfname, O_RDWR)) >= 0)
break;
}
if (i == 16)
{
fprintf(stderr, "no bpf devices available as /dev/bpfxx\n");
return -1;
}
if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0)
{
perror("BIOCVERSION");
return -1;
}
if (bv.bv_major != BPF_MAJOR_VERSION ||
bv.bv_minor < BPF_MINOR_VERSION)
{
fprintf(stderr, "kernel bpf (v%d.%d) filter out of date:\n",
bv.bv_major, bv.bv_minor);
fprintf(stderr, "current version: %d.%d\n",
BPF_MAJOR_VERSION, BPF_MINOR_VERSION);
return -1;
}
(void) strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
if (ioctl(fd, BIOCSETIF, &ifr) == -1)
{
fprintf(stderr, "%s(%d):", ifr.ifr_name, fd);
perror("BIOCSETIF");
exit(1);
}
/*
* set the timeout
*/
timeout = tout;
to.tv_sec = 1;
to.tv_usec = 0;
if (ioctl(fd, BIOCSRTIMEOUT, (caddr_t)&to) == -1)
{
perror("BIOCSRTIMEOUT");
exit(-1);
}
/*
* get kernel buffer size
*/
if (ioctl(fd, BIOCSBLEN, &bufsize) == -1)
perror("BIOCSBLEN");
if (ioctl(fd, BIOCGBLEN, &bufsize) == -1)
{
perror("BIOCGBLEN");
exit(-1);
}
printf("BPF buffer size: %d\n", bufsize);
buf = (u_char*)malloc(bufsize);
prog.bf_len = sizeof(filter) / sizeof(struct bpf_insn);
prog.bf_insns = filter;
if (ioctl(fd, BIOCSETF, (caddr_t)&prog) == -1)
{
perror("BIOCSETF");
exit(-1);
}
(void) ioctl(fd, BIOCFLUSH, 0);
return fd;
}

View File

@ -0,0 +1,263 @@
/*
* (C)opyright October 1992 Darren Reed. (from tcplog)
*
* This software may be freely distributed as long as it is not altered
* in any way and that this messagge always accompanies it.
*
* The author of this software makes no garuntee about the
* performance of this package or its suitability to fulfill any purpose.
*
*/
#include <stdio.h>
#include <netdb.h>
#include <ctype.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/stropts.h>
#include <sys/pfmod.h>
#include <sys/bufmod.h>
#include <sys/dlpi.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include "ip_compat.h"
#ifndef lint
static char snitid[] = "%W% %G% (C)1995 Darren Reed";
#endif
#define BUFSPACE 32768
static int solfd;
/*
* Be careful to only include those defined in the flags option for the
* interface are included in the header size.
*/
static int timeout;
void nullbell()
{
return 0;
}
int ack_recv(ep)
char *ep;
{
struct tcpiphdr tip;
tcphdr_t *tcp;
ip_t *ip;
ip = (ip_t *)&tip;
tcp = (tcphdr_t *)(ip + 1);
bcopy(ep, (char *)ip, sizeof(*ip));
bcopy(ep + (ip->ip_hl << 2), (char *)tcp, sizeof(*tcp));
if (ip->ip_off & 0x1fff != 0)
return 0;
if (0 == detect(ip, tcp))
return 1;
return 0;
}
int readloop(fd, port, dst)
int fd, port;
struct in_addr dst;
{
static u_char buf[BUFSPACE];
register u_char *bp, *cp, *bufend;
register struct sb_hdr *hp;
register int cc;
struct strbuf dbuf;
ether_header_t eh;
time_t now = time(NULL);
int flags = 0, i, done = 0;
fd = solfd;
dbuf.len = 0;
dbuf.buf = buf;
dbuf.maxlen = sizeof(buf);
/*
* no control data buffer...
*/
while (1) {
(void) signal(SIGALRM, nullbell);
alarm(1);
i = getmsg(fd, NULL, &dbuf, &flags);
alarm(0);
(void) signal(SIGALRM, nullbell);
cc = dbuf.len;
if ((time(NULL) - now) > timeout)
return done;
if (i == -1)
if (errno == EINTR)
continue;
else
break;
bp = buf;
bufend = buf + cc;
/*
* loop through each snapshot in the chunk
*/
while (bp < bufend) {
/*
* get past bufmod header
*/
hp = (struct sb_hdr *)bp;
cp = (u_char *)((char *)bp + sizeof(*hp));
bcopy(cp, (char *)&eh, sizeof(eh));
/*
* next snapshot
*/
bp += hp->sbh_totlen;
cc -= hp->sbh_totlen;
if (eh.ether_type != ETHERTYPE_IP)
continue;
cp += sizeof(eh);
done += ack_recv(cp);
}
alarm(1);
}
perror("getmsg");
exit(-1);
}
int initdevice(device, tout)
char *device;
int tout;
{
struct strioctl si;
struct timeval to;
struct ifreq ifr;
struct packetfilt pfil;
u_long if_flags;
u_short *fwp = pfil.Pf_Filter;
char devname[16], *s, buf[256];
int i, offset, fd, snaplen= 58, chunksize = BUFSPACE;
(void) sprintf(devname, "/dev/%s", device);
s = devname + 5;
while (*s && !isdigit(*s))
s++;
if (!*s)
{
fprintf(stderr, "bad device name %s\n", devname);
exit(-1);
}
i = atoi(s);
*s = '\0';
/*
* For reading
*/
if ((fd = open(devname, O_RDWR)) < 0)
{
fprintf(stderr, "O_RDWR(0) ");
perror(devname);
exit(-1);
}
if (dlattachreq(fd, i) == -1 || dlokack(fd, buf) == -1)
{
fprintf(stderr, "DLPI error\n");
exit(-1);
}
dlbindreq(fd, ETHERTYPE_IP, 0, DL_CLDLS, 0, 0);
dlbindack(fd, buf);
/*
* read full headers
*/
if (strioctl(fd, DLIOCRAW, -1, 0, NULL) == -1)
{
fprintf(stderr, "DLIOCRAW error\n");
exit(-1);
}
/*
* Create some filter rules for our TCP watcher. We only want ethernet
* pacets which are IP protocol and only the TCP packets from IP.
*/
offset = 6;
*fwp++ = ENF_PUSHWORD + offset;
*fwp++ = ENF_PUSHLIT | ENF_CAND;
*fwp++ = htons(ETHERTYPE_IP);
*fwp++ = ENF_PUSHWORD + sizeof(struct ether_header)/sizeof(short)+4;
*fwp++ = ENF_PUSHLIT | ENF_AND;
*fwp++ = htons(0x00ff);
*fwp++ = ENF_PUSHLIT | ENF_COR;
*fwp++ = htons(IPPROTO_TCP);
*fwp++ = ENF_PUSHWORD + sizeof(struct ether_header)/sizeof(short)+4;
*fwp++ = ENF_PUSHLIT | ENF_AND;
*fwp++ = htons(0x00ff);
*fwp++ = ENF_PUSHLIT | ENF_CAND;
*fwp++ = htons(IPPROTO_UDP);
pfil.Pf_FilterLen = (fwp - &pfil.Pf_Filter[0]);
/*
* put filter in place.
*/
if (ioctl(fd, I_PUSH, "pfmod") == -1)
{
perror("ioctl: I_PUSH pf");
exit(1);
}
if (strioctl(fd, PFIOCSETF, -1, sizeof(pfil), (char *)&pfil) == -1)
{
perror("ioctl: PFIOCSETF");
exit(1);
}
/*
* arrange to get messages from the NIT STREAM and use NIT_BUF option
*/
if (ioctl(fd, I_PUSH, "bufmod") == -1)
{
perror("ioctl: I_PUSH bufmod");
exit(1);
}
i = 128;
strioctl(fd, SBIOCSSNAP, -1, sizeof(i), (char *)&i);
/*
* set the timeout
*/
to.tv_sec = 1;
to.tv_usec = 0;
if (strioctl(fd, SBIOCSTIME, -1, sizeof(to), (char *)&to) == -1)
{
perror("strioctl(SBIOCSTIME)");
exit(-1);
}
/*
* flush read queue
*/
if (ioctl(fd, I_FLUSH, FLUSHR) == -1)
{
perror("I_FLUSHR");
exit(-1);
}
timeout = tout;
solfd = fd;
return fd;
}

View File

@ -0,0 +1,120 @@
/*
* (C)opyright October 1992 Darren Reed. (from tcplog)
*
* This software may be freely distributed as long as it is not altered
* in any way and that this messagge always accompanies it.
*
* The author of this software makes no garuntee about the
* performance of this package or its suitability to fulfill any purpose.
*
*/
#include <stdio.h>
#include <netdb.h>
#include <ctype.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/dir.h>
#include <linux/netdevice.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include "ip_compat.h"
#include "tcpip.h"
#ifndef lint
static char sccsid[] = "@(#)slinux.c 1.1 12/3/95 (C) 1995 Darren Reed";
#endif
#define BUFSPACE 32768
/*
* Be careful to only include those defined in the flags option for the
* interface are included in the header size.
*/
static int timeout;
static char *eth_dev = NULL;
int ack_recv(bp)
char *bp;
{
struct tcpip tip;
tcphdr_t *tcp;
ip_t *ip;
ip = (struct ip *)&tip;
tcp = (tcphdr_t *)(ip + 1);
bcopy(bp, (char *)&tip, sizeof(tip));
bcopy(bp + (ip.ip_hl << 2), (char *)tcp, sizeof(*tcp));
if (0 == detect(ip, tcp))
return 1;
return 0;
}
void readloop(fd, port, dst)
int fd, port;
struct in_addr dst;
{
static u_char buf[BUFSPACE];
struct sockaddr dest;
register u_char *bp = buf;
register int cc;
int dlen, done = 0;
time_t now = time(NULL);
do {
fflush(stdout);
dlen = sizeof(dest);
bzero((char *)&dest, dlen);
cc = recvfrom(fd, buf, BUFSPACE, 0, &dest, &dlen);
if (!cc)
if ((time(NULL) - now) > timeout)
return done;
else
continue;
if (bp[12] != 0x8 || bp[13] != 0)
continue; /* not ip */
/*
* get rid of non-tcp or fragmented packets here.
*/
if (cc >= sizeof(struct tcpiphdr))
{
if (((bp[14+9] != IPPROTO_TCP) &&
(bp[14+9] != IPPROTO_UDP)) ||
(bp[14+6] & 0x1f) || (bp[14+6] & 0xff))
continue;
done += ack_recv(bp + 14);
}
} while (cc >= 0);
perror("read");
exit(-1);
}
int initdevice(dev, tout)
char *dev;
int tout;
{
int fd;
eth_dev = strdup(dev);
if ((fd = socket(AF_INET, SOCK_PACKET, htons(ETHERTYPE_IP))) == -1)
{
perror("socket(SOCK_PACKET)");
exit(-1);
}
return fd;
}

View File

@ -0,0 +1,230 @@
/*
* (C)opyright October 1992 Darren Reed. (from tcplog)
*
* This software may be freely distributed as long as it is not altered
* in any way and that this messagge always accompanies it.
*
* The author of this software makes no garuntee about the
* performance of this package or its suitability to fulfill any purpose.
*
*/
#include <stdio.h>
#include <netdb.h>
#include <ctype.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <net/nit.h>
#include <sys/fcntlcom.h>
#include <sys/dir.h>
#include <net/nit_if.h>
#include <net/nit_pf.h>
#include <net/nit_buf.h>
#include <net/packetfilt.h>
#include <sys/stropts.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#ifndef lint
static char snitid[] = "@(#)snit.c 1.2 12/3/95 (C)1995 Darren Reed";
#endif
#define BUFSPACE 32768
/*
* Be careful to only include those defined in the flags option for the
* interface are included in the header size.
*/
#define BUFHDR_SIZE (sizeof(struct nit_bufhdr))
#define NIT_HDRSIZE (BUFHDR_SIZE)
static int timeout;
int ack_recv(ep)
char *ep;
{
struct tcpiphdr tip;
struct tcphdr *tcp;
struct ip *ip;
ip = (struct ip *)&tip;
tcp = (struct tcphdr *)(ip + 1);
bcopy(ep + 14, (char *)ip, sizeof(*ip));
bcopy(ep + 14 + (ip->ip_hl << 2), (char *)tcp, sizeof(*tcp));
if (ip->ip_off & 0x1fff != 0)
return 0;
if (0 == detect(ip, tcp))
return 1;
return 0;
}
int readloop(fd, dst)
int fd;
struct in_addr dst;
{
static u_char buf[BUFSPACE];
register u_char *bp, *cp, *bufend;
register struct nit_bufhdr *hp;
register int cc;
time_t now = time(NULL);
int done = 0;
while ((cc = read(fd, buf, BUFSPACE-1)) >= 0) {
if (!cc)
if ((time(NULL) - now) > timeout)
return done;
else
continue;
bp = buf;
bufend = buf + cc;
/*
* loop through each snapshot in the chunk
*/
while (bp < bufend) {
cp = (u_char *)((char *)bp + NIT_HDRSIZE);
/*
* get past NIT buffer
*/
hp = (struct nit_bufhdr *)bp;
/*
* next snapshot
*/
bp += hp->nhb_totlen;
done += ack_recv(cp);
}
return done;
}
perror("read");
exit(-1);
}
int initdevice(device, tout)
char *device;
int tout;
{
struct strioctl si;
struct timeval to;
struct ifreq ifr;
struct packetfilt pfil;
u_long if_flags;
u_short *fwp = pfil.Pf_Filter;
int ret, offset, fd, snaplen= 76, chunksize = BUFSPACE;
if ((fd = open("/dev/nit", O_RDWR)) < 0)
{
perror("/dev/nit");
exit(-1);
}
/*
* Create some filter rules for our TCP watcher. We only want ethernet
* pacets which are IP protocol and only the TCP packets from IP.
*/
offset = 6;
*fwp++ = ENF_PUSHWORD + offset;
*fwp++ = ENF_PUSHLIT | ENF_CAND;
*fwp++ = htons(ETHERTYPE_IP);
*fwp++ = ENF_PUSHWORD + sizeof(struct ether_header)/sizeof(short)+4;
*fwp++ = ENF_PUSHLIT | ENF_AND;
*fwp++ = htons(0x00ff);
*fwp++ = ENF_PUSHLIT | ENF_COR;
*fwp++ = htons(IPPROTO_TCP);
*fwp++ = ENF_PUSHWORD + sizeof(struct ether_header)/sizeof(short)+4;
*fwp++ = ENF_PUSHLIT | ENF_AND;
*fwp++ = htons(0x00ff);
*fwp++ = ENF_PUSHLIT | ENF_CAND;
*fwp++ = htons(IPPROTO_UDP);
pfil.Pf_FilterLen = fwp - &pfil.Pf_Filter[0];
/*
* put filter in place.
*/
if (ioctl(fd, I_PUSH, "pf") == -1)
{
perror("ioctl: I_PUSH pf");
exit(1);
}
if (ioctl(fd, NIOCSETF, &pfil) == -1)
{
perror("ioctl: NIOCSETF");
exit(1);
}
/*
* arrange to get messages from the NIT STREAM and use NIT_BUF option
*/
ioctl(fd, I_SRDOPT, (char*)RMSGD);
ioctl(fd, I_PUSH, "nbuf");
/*
* set the timeout
*/
timeout = tout;
si.ic_timout = 1;
to.tv_sec = 1;
to.tv_usec = 0;
si.ic_cmd = NIOCSTIME;
si.ic_len = sizeof(to);
si.ic_dp = (char*)&to;
if (ioctl(fd, I_STR, (char*)&si) == -1)
{
perror("ioctl: NIT timeout");
exit(-1);
}
/*
* set the chunksize
*/
si.ic_cmd = NIOCSCHUNK;
si.ic_len = sizeof(chunksize);
si.ic_dp = (char*)&chunksize;
if (ioctl(fd, I_STR, (char*)&si) == -1)
perror("ioctl: NIT chunksize");
if (ioctl(fd, NIOCGCHUNK, (char*)&chunksize) == -1)
{
perror("ioctl: NIT chunksize");
exit(-1);
}
printf("NIT buffer size: %d\n", chunksize);
/*
* request the interface
*/
strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' ';
si.ic_cmd = NIOCBIND;
si.ic_len = sizeof(ifr);
si.ic_dp = (char*)&ifr;
if (ioctl(fd, I_STR, (char*)&si) == -1)
{
perror(ifr.ifr_name);
exit(1);
}
/*
* set the snapshot length
*/
si.ic_cmd = NIOCSSNAP;
si.ic_len = sizeof(snaplen);
si.ic_dp = (char*)&snaplen;
if (ioctl(fd, I_STR, (char*)&si) == -1)
{
perror("ioctl: NIT snaplen");
exit(1);
}
(void) ioctl(fd, I_FLUSH, (char*)FLUSHR);
return fd;
}

View File

@ -0,0 +1,95 @@
/*
* Based upon 4.4BSD's /usr/sbin/arp
*/
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <nlist.h>
#include <stdio.h>
/*
* lookup host and return
* its IP address in address
* (4 bytes)
*/
int resolve(host, address)
char *host, *address;
{
struct hostent *hp;
u_long add;
add = inet_addr(host);
if (add == -1)
{
if (!(hp = gethostbyname(host)))
{
fprintf(stderr, "unknown host: %s\n", host);
return -1;
}
bcopy((char *)hp->h_addr, (char *)address, 4);
return 0;
}
bcopy((char*)&add, address, 4);
return 0;
}
int arp(addr, eaddr)
char *addr, *eaddr;
{
int mib[6];
size_t needed;
char *malloc(), *lim, *buf, *next;
struct rt_msghdr *rtm;
struct sockaddr_inarp *sin;
struct sockaddr_dl *sdl;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = AF_INET;
mib[4] = NET_RT_FLAGS;
mib[5] = RTF_LLINFO;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
{
perror("route-sysctl-estimate");
exit(-1);
}
if ((buf = malloc(needed)) == NULL)
{
perror("malloc");
exit(-1);
}
if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1)
{
perror("actual retrieval of routing table");
exit(-1);
}
lim = buf + needed;
for (next = buf; next < lim; next += rtm->rtm_msglen)
{
rtm = (struct rt_msghdr *)next;
sin = (struct sockaddr_inarp *)(rtm + 1);
sdl = (struct sockaddr_dl *)(sin + 1);
if (addr && !bcmp(addr, (char *)&sin->sin_addr,
sizeof(struct in_addr)))
{
bcopy(LLADDR(sdl), eaddr, sdl->sdl_alen);
return 0;
}
}
return -1;
}

View File

@ -0,0 +1,20 @@
Test 1:
Solaris 2.4 - upto and including 101945-34, > 34 ?
Solaris 2.5 - 11/95
Linux 1.2.13, < 1.3.45(?)
3com/sonix bridge
Instant Internet
KA9Q NOS
Netblazer 40i, Version 3.2 OS
Irix 6.x
HP-UX 9.0
HP-UX 10.1
LivingstonsComOS
Test 6:
SunOS 4.1.x
ULtrix 4.3
Test 7:
SunOS 4.1.x
Linux <= 1.3.84

View File

@ -0,0 +1,91 @@
#
# (C)opyright 1993-1996 by Darren Reed.
#
# This code may be freely distributed as long as it retains this notice
# and is not changed in any way. The author accepts no responsibility
# for the use of this software. I hate legaleese, don't you ?
#
OBJS=ipsend.o ip.o ipsopt.o
ROBJS=ipresend.o ip.o resend.o
TOBJS=iptest.o iptests.o ip.o
BPF=sbpf.o
NIT=snit.o
SUNOS4=sock.o arp.o
BSD=sock.o 44arp.o
LINUX=lsock.o slinux.o larp.o
LINUXK=
TOP=..
SUNOS5=dlcommon.o sdlpi.o arp.o
CC=gcc
CFLAGS=-g -I.. -DNO_IPF
all:
@echo "Use one of these targets:"
@echo " sunos4-nit (standard SunOS 4.1.x)"
@echo " sunos4-bpf (SunOS4.1.x with BPF in the kernel)"
@echo " bsd-bpf (4.4BSD variant with BPF in the kernel)"
@echo " linux10 (Linux 1.0 kernels)"
@echo " linux20 (Linux 2.0 kernels)"
@echo " sunos5 (Solaris 2.x)"
.c.o:
$(CC) $(CFLAGS) $(LINUXK) -c $< -o $@
bpf sunos4-bpf :
make ipsend "OBJS=$(OBJS)" "UNIXOBJS=$(BPF) $(SUNOS4)" "CC=$(CC)" \
"CFLAGS=$(CFLAGS) -DDOSOCKET"
make ipresend "ROBJS=$(ROBJS)" "UNIXOBJS=$(BPF) $(SUNOS4)" "CC=$(CC)" \
"CFLAGS=$(CFLAGS) -DDOSOCKET"
make iptest "TOBJS=$(TOBJS)" "UNIXOBJS=$(BPF) $(SUNOS4)" "CC=$(CC)" \
"CFLAGS=$(CFLAGS) -DDOSOCKET"
nit sunos4 sunos4-nit :
make ipsend "OBJS=$(OBJS)" "UNIXOBJS=$(NIT) $(SUNOS4)" "CC=$(CC)" \
"CFLAGS=$(CFLAGS) -DDOSOCKET"
make ipresend "ROBJS=$(ROBJS)" "UNIXOBJS=$(NIT) $(SUNOS4)" "CC=$(CC)" \
"CFLAGS=$(CFLAGS) -DDOSOCKET"
make iptest "TOBJS=$(TOBJS)" "UNIXOBJS=$(NIT) $(SUNOS4)" "CC=$(CC)" \
"CFLAGS=$(CFLAGS) -DDOSOCKET"
dlpi sunos5 :
make ipsend "OBJS=$(OBJS)" "UNIXOBJS=$(SUNOS5)" "CC=$(CC)" \
CFLAGS="$(CFLAGS) -Dsolaris" "LIBS=-lsocket -lnsl"
make ipresend "ROBJS=$(ROBJS)" "UNIXOBJS=$(SUNOS5)" "CC=$(CC)" \
CFLAGS="$(CFLAGS) -Dsolaris" "LIBS=-lsocket -lnsl"
make iptest "TOBJS=$(TOBJS)" "UNIXOBJS=$(SUNOS5)" "CC=$(CC)" \
CFLAGS="$(CFLAGS) -Dsolaris" "LIBS=-lsocket -lnsl"
bsd-bpf :
make ipsend "OBJS=$(OBJS)" "UNIXOBJS=$(BPF) $(BSD)" "CC=$(CC)" \
"CFLAGS=$(CFLAGS) -DDOSOCKET"
make ipresend "ROBJS=$(ROBJS)" "UNIXOBJS=$(BPF) $(BSD)" "CC=$(CC)" \
"CFLAGS=$(CFLAGS) -DDOSOCKET"
make iptest "TOBJS=$(TOBJS)" "UNIXOBJS=$(BPF) $(BSD)" "CC=$(CC)" \
"CFLAGS=$(CFLAGS) -DDOSOCKET"
linuxrev :
make ipsend "OBJS=$(OBJS)" "UNIXOBJS=$(LINUX)" "CC=$(CC)" \
CFLAGS="$(CFLAGS) -I/usr/src/linux/include -DDOSOCKET" $(LINUXK)
make ipresend "ROBJS=$(ROBJS)" "UNIXOBJS=$(LINUX)" "CC=$(CC)" \
CFLAGS="$(CFLAGS) -I/usr/src/linux/include -DDOSOCKET" $(LINUXK)
make iptest "TOBJS=$(TOBJS)" "UNIXOBJS=$(LINUX)" "CC=$(CC)" \
CFLAGS="$(CFLAGS) -I/usr/src/linux/include -DDOSOCKET" $(LINUXK)
linux10:
make linuxrev 'LINUXK="LINUXK=-DLINUX=0100"'
linux20:
make linuxrev 'LINUXK="LINUXK=-DLINUX=0200"'
ipsend: $(OBJS) $(UNIXOBJS)
$(CC) $(OBJS) $(UNIXOBJS) -o $@ $(LIBS)
ipresend: $(ROBJS) $(UNIXOBJS)
$(CC) $(ROBJS) $(UNIXOBJS) -o $@ $(LIBS)
iptest: $(TOBJS) $(UNIXOBJS)
$(CC) $(TOBJS) $(UNIXOBJS) -o $@ $(LIBS)
clean:
rm -rf *.o *core a.out ipsend ipresend iptest

View File

@ -0,0 +1,119 @@
/*
* arp.c (C) 1995 Darren Reed
*
* The author provides this program as-is, with no gaurantee for its
* suitability for any specific purpose. The author takes no responsibility
* for the misuse/abuse of this program and provides it for the sole purpose
* of testing packet filter policies. This file maybe distributed freely
* providing it is not modified and that this notice remains in tact.
*/
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)arp.c 1.4 1/11/96 (C)1995 Darren Reed";
#endif
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/ioctl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <net/if.h>
#include <net/if_arp.h>
#if defined(__SVR4) || defined(__svr4__)
#define bcopy(a,b,c) memmove(b,a,c)
#define bzero(a,c) memset(a,0,c)
#define bcmp(a,b,c) memcmp(a,b,c)
#endif
/*
* lookup host and return
* its IP address in address
* (4 bytes)
*/
int resolve(host, address)
char *host, *address;
{
struct hostent *hp;
u_long add;
add = inet_addr(host);
if (add == -1)
{
if (!(hp = gethostbyname(host)))
{
fprintf(stderr, "unknown host: %s\n", host);
return -1;
}
bcopy((char *)hp->h_addr, (char *)address, 4);
return 0;
}
bcopy((char*)&add, address, 4);
return 0;
}
/*
* ARP for the MAC address corresponding
* to the IP address. This taken from
* some BSD program, I cant remember which.
*/
int arp(ip, ether)
char *ip;
char *ether;
{
static int sfd = -1;
static char ethersave[6], ipsave[4];
struct arpreq ar;
struct sockaddr_in *sin, san;
struct hostent *hp;
char *inet_ntoa();
int fd;
if (!bcmp(ipsave, ip, 4)) {
bcopy(ethersave, ether, 6);
return 0;
}
fd = -1;
bzero((char *)&ar, sizeof(ar));
sin = (struct sockaddr_in *)&ar.arp_pa;
sin->sin_family = AF_INET;
bcopy(ip, (char *)&sin->sin_addr.s_addr, 4);
if ((hp = gethostbyaddr(ip, 4, AF_INET)))
if (!(ether_hostton(hp->h_name, ether)))
goto savearp;
if (sfd == -1)
if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("arp: socket");
return -1;
}
tryagain:
if (ioctl(sfd, SIOCGARP, (caddr_t)&ar) == -1)
{
if (fd == -1)
{
bzero((char *)&san, sizeof(san));
san.sin_family = AF_INET;
san.sin_port = htons(1);
bcopy(ip, &san.sin_addr.s_addr, 4);
fd = socket(AF_INET, SOCK_DGRAM, 0);
(void) sendto(fd, ip, 4, 0,
(struct sockaddr *)&san, sizeof(san));
sleep(1);
(void) close(fd);
goto tryagain;
}
fprintf(stderr, "(%s):", inet_ntoa(sin->sin_addr));
if (errno != ENXIO)
perror("SIOCGARP");
return -1;
}
bcopy(ar.arp_ha.sa_data, ether, 6);
savearp:
bcopy(ether, ethersave, 6);
bcopy(ip, ipsave, 4);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,32 @@
/*
* Common DLPI Test Suite header file
*
*/
/*
* Maximum control/data buffer size (in long's !!) for getmsg().
*/
#define MAXDLBUF 8192
/*
* Maximum number of seconds we'll wait for any
* particular DLPI acknowledgment from the provider
* after issuing a request.
*/
#define MAXWAIT 15
/*
* Maximum address buffer length.
*/
#define MAXDLADDR 1024
/*
* Handy macro.
*/
#define OFFADDR(s, n) (u_char*)((char*)(s) + (int)(n))
/*
* externs go here
*/
extern void sigalrm();

View File

@ -0,0 +1,177 @@
/* @(#)in_var.h 1.3 88/08/19 SMI; from UCB 7.1 6/5/86 */
/*
* Copyright (c) 1985, 1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
/*
* Interface address, Internet version. One of these structures
* is allocated for each interface with an Internet address.
* The ifaddr structure contains the protocol-independent part
* of the structure and is assumed to be first.
*/
#ifndef _netinet_in_var_h
#define _netinet_in_var_h
struct in_ifaddr {
struct ifaddr ia_ifa; /* protocol-independent info */
#define ia_addr ia_ifa.ifa_addr
#define ia_broadaddr ia_ifa.ifa_broadaddr
#define ia_dstaddr ia_ifa.ifa_dstaddr
#define ia_ifp ia_ifa.ifa_ifp
u_long ia_net; /* network number of interface */
u_long ia_netmask; /* mask of net part */
u_long ia_subnet; /* subnet number, including net */
u_long ia_subnetmask; /* mask of net + subnet */
struct in_addr ia_netbroadcast; /* broadcast addr for (logical) net */
int ia_flags;
struct in_ifaddr *ia_next; /* next in list of internet addresses */
struct in_multi *ia_multiaddrs;/* list of multicast addresses */
};
/*
* Given a pointer to an in_ifaddr (ifaddr),
* return a pointer to the addr as a sockadd_in.
*/
#define IA_SIN(ia) ((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_addr))
/*
* ia_flags
*/
#define IFA_ROUTE 0x01 /* routing entry installed */
#ifdef KERNEL
struct in_ifaddr *in_ifaddr;
struct in_ifaddr *in_iaonnetof();
struct ifqueue ipintrq; /* ip packet input queue */
#endif
#ifdef KERNEL
/*
* Macro for finding the interface (ifnet structure) corresponding to one
* of our IP addresses.
*/
#define INADDR_TO_IFP(addr, ifp) \
/* struct in_addr addr; */ \
/* struct ifnet *ifp; */ \
{ \
register struct in_ifaddr *ia; \
\
for (ia = in_ifaddr; \
ia != NULL && IA_SIN(ia)->sin_addr.s_addr != (addr).s_addr; \
ia = ia->ia_next); \
(ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \
}
/*
* Macro for finding the internet address structure (in_ifaddr) corresponding
* to a given interface (ifnet structure).
*/
#define IFP_TO_IA(ifp, ia) \
/* struct ifnet *ifp; */ \
/* struct in_ifaddr *ia; */ \
{ \
for ((ia) = in_ifaddr; \
(ia) != NULL && (ia)->ia_ifp != (ifp); \
(ia) = (ia)->ia_next); \
}
#endif KERNEL
/*
* Per-interface router version information is kept in this list.
* This information should be part of the ifnet structure but we don't wish
* to change that - as it might break a number of things
*/
struct router_info {
struct ifnet *ifp;
int type; /* type of router which is querier on this interface */
int time; /* # of slow timeouts since last old query */
struct router_info *next;
};
/*
* Internet multicast address structure. There is one of these for each IP
* multicast group to which this host belongs on a given network interface.
* They are kept in a linked list, rooted in the interface's in_ifaddr
* structure.
*/
struct in_multi {
struct in_addr inm_addr; /* IP multicast address */
struct ifnet *inm_ifp; /* back pointer to ifnet */
struct in_ifaddr *inm_ia; /* back pointer to in_ifaddr */
u_int inm_refcount;/* no. membership claims by sockets */
u_int inm_timer; /* IGMP membership report timer */
struct in_multi *inm_next; /* ptr to next multicast address */
u_int inm_state; /* state of the membership */
struct router_info *inm_rti; /* router info*/
};
#ifdef KERNEL
/*
* Structure used by macros below to remember position when stepping through
* all of the in_multi records.
*/
struct in_multistep {
struct in_ifaddr *i_ia;
struct in_multi *i_inm;
};
/*
* Macro for looking up the in_multi record for a given IP multicast address
* on a given interface. If no matching record is found, "inm" returns NULL.
*/
#define IN_LOOKUP_MULTI(addr, ifp, inm) \
/* struct in_addr addr; */ \
/* struct ifnet *ifp; */ \
/* struct in_multi *inm; */ \
{ \
register struct in_ifaddr *ia; \
\
IFP_TO_IA((ifp), ia); \
if (ia == NULL) \
(inm) = NULL; \
else \
for ((inm) = ia->ia_multiaddrs; \
(inm) != NULL && (inm)->inm_addr.s_addr != (addr).s_addr; \
(inm) = inm->inm_next); \
}
/*
* Macro to step through all of the in_multi records, one at a time.
* The current position is remembered in "step", which the caller must
* provide. IN_FIRST_MULTI(), below, must be called to initialize "step"
* and get the first record. Both macros return a NULL "inm" when there
* are no remaining records.
*/
#define IN_NEXT_MULTI(step, inm) \
/* struct in_multistep step; */ \
/* struct in_multi *inm; */ \
{ \
if (((inm) = (step).i_inm) != NULL) { \
(step).i_inm = (inm)->inm_next; \
} \
else while ((step).i_ia != NULL) { \
(inm) = (step).i_ia->ia_multiaddrs; \
(step).i_ia = (step).i_ia->ia_next; \
if ((inm) != NULL) { \
(step).i_inm = (inm)->inm_next; \
break; \
} \
} \
}
#define IN_FIRST_MULTI(step, inm) \
/* struct in_multistep step; */ \
/* struct in_multi *inm; */ \
{ \
(step).i_ia = in_ifaddr; \
(step).i_inm = NULL; \
IN_NEXT_MULTI((step), (inm)); \
}
struct in_multi *in_addmulti();
#endif KERNEL
#endif /*!_netinet_in_var_h*/

View File

@ -0,0 +1,346 @@
/*
* ip.c (C) 1995 Darren Reed
*
* The author provides this program as-is, with no gaurantee for its
* suitability for any specific purpose. The author takes no responsibility
* for the misuse/abuse of this program and provides it for the sole purpose
* of testing packet filter policies. This file maybe distributed freely
* providing it is not modified and that this notice remains in tact.
*/
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "%W% %G% (C)1995";
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in_systm.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#ifndef linux
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/tcpip.h>
#endif
#include "ip_compat.h"
#ifdef linux
#include "tcpip.h"
#endif
static char *ipbuf = NULL, *ethbuf = NULL;
extern int arp(), sendip();
u_short chksum(buf,len)
u_short *buf;
int len;
{
u_long sum = 0;
int nwords = len >> 1;
for(; nwords > 0; nwords--)
sum += *buf++;
sum = (sum>>16) + (sum & 0xffff);
sum += (sum >>16);
return (~sum);
}
int send_ether(nfd, buf, len, gwip)
int nfd, len;
char *buf;
struct in_addr gwip;
{
static struct in_addr last_gw;
static char last_arp[6] = { 0, 0, 0, 0, 0, 0};
ether_header_t *eh;
char *s;
int err;
if (!ethbuf)
ethbuf = (char *)calloc(1, 65536+1024);
s = ethbuf;
eh = (ether_header_t *)s;
bcopy((char *)buf, s + sizeof(*eh), len);
if (gwip.s_addr == last_gw.s_addr)
bcopy(last_arp, (char *)&eh->ether_dhost, 6);
else if (arp((char *)&gwip, &eh->ether_dhost) == -1)
{
perror("arp");
return -2;
}
eh->ether_type = ETHERTYPE_IP;
last_gw.s_addr = gwip.s_addr;
err = sendip(nfd, s, sizeof(*eh) + len);
return err;
}
/*
*/
int send_ip(nfd, mtu, ip, gwip, frag)
int nfd, mtu;
ip_t *ip;
struct in_addr gwip;
int frag;
{
static struct in_addr last_gw;
static char last_arp[6] = { 0, 0, 0, 0, 0, 0};
static u_short id = 0;
ether_header_t *eh;
ip_t ipsv;
int err;
if (!ipbuf)
ipbuf = (char *)malloc(65536);
eh = (ether_header_t *)ipbuf;
bzero((char *)&eh->ether_shost, sizeof(eh->ether_shost));
if (last_gw.s_addr && (gwip.s_addr == last_gw.s_addr))
bcopy(last_arp, (char *)&eh->ether_dhost, 6);
else if (arp((char *)&gwip, &eh->ether_dhost) == -1)
{
perror("arp");
return -2;
}
bcopy((char *)&eh->ether_dhost, last_arp, sizeof(last_arp));
eh->ether_type = ETHERTYPE_IP;
bcopy((char *)ip, (char *)&ipsv, sizeof(*ip));
last_gw.s_addr = gwip.s_addr;
ip->ip_len = htons(ip->ip_len);
ip->ip_off = htons(ip->ip_off);
if (!ip->ip_v)
ip->ip_v = IPVERSION;
if (!ip->ip_id)
ip->ip_id = htons(id++);
if (!ip->ip_ttl)
ip->ip_ttl = 60;
if (!frag || (sizeof(*eh) + ntohs(ip->ip_len) < mtu))
{
ip->ip_sum = 0;
ip->ip_sum = chksum(ip, ip->ip_hl << 2);
bcopy((char *)ip, ipbuf + sizeof(*eh), ntohs(ip->ip_len));
err = sendip(nfd, ipbuf, sizeof(*eh) + ntohs(ip->ip_len));
}
else
{
/*
* Actually, this is bogus because we're putting all IP
* options in every packet, which isn't always what should be
* done. Will do for now.
*/
ether_header_t eth;
char optcpy[48], ol;
char *s;
int i, iplen, sent = 0, ts, hlen, olen;
hlen = ip->ip_hl << 2;
if (mtu < (hlen + 8)) {
fprintf(stderr, "mtu (%d) < ip header size (%d) + 8\n",
mtu, hlen);
fprintf(stderr, "can't fragment data\n");
return -2;
}
ol = (ip->ip_hl << 2) - sizeof(*ip);
for (i = 0, s = (char*)(ip + 1); ol > 0; )
if (*s == IPOPT_EOL) {
optcpy[i++] = *s;
break;
} else if (*s == IPOPT_NOP) {
s++;
ol--;
} else
{
olen = (int)(*(u_char *)(s + 1));
ol -= olen;
if (IPOPT_COPIED(*s))
{
bcopy(s, optcpy + i, olen);
i += olen;
s += olen;
}
}
if (i)
{
/*
* pad out
*/
while ((i & 3) && (i & 3) != 3)
optcpy[i++] = IPOPT_NOP;
if ((i & 3) == 3)
optcpy[i++] = IPOPT_EOL;
}
bcopy((char *)eh, (char *)&eth, sizeof(eth));
s = (char *)ip + hlen;
iplen = ntohs(ip->ip_len) - hlen;
ip->ip_off |= htons(IP_MF);
while (1)
{
if ((sent + (mtu - hlen)) >= iplen)
{
ip->ip_off ^= htons(IP_MF);
ts = iplen - sent;
}
else
ts = (mtu - hlen);
ip->ip_off &= htons(0xe000);
ip->ip_off |= htons(sent >> 3);
ts += hlen;
ip->ip_len = htons(ts);
ip->ip_sum = 0;
ip->ip_sum = chksum(ip, hlen);
bcopy((char *)ip, ipbuf + sizeof(*eh), hlen);
bcopy(s + sent, ipbuf + sizeof(*eh) + hlen, ts - hlen);
err = sendip(nfd, ipbuf, sizeof(*eh) + ts);
bcopy((char *)&eth, ipbuf, sizeof(eth));
sent += (ts - hlen);
if (!(ntohs(ip->ip_off) & IP_MF))
break;
else if (!(ip->ip_off & htons(0x1fff)))
{
hlen = i + sizeof(*ip);
ip->ip_hl = (sizeof(*ip) + i) >> 2;
bcopy(optcpy, (char *)(ip + 1), i);
}
}
}
bcopy((char *)&ipsv, (char *)ip, sizeof(*ip));
return err;
}
/*
* send a tcp packet.
*/
int send_tcp(nfd, mtu, ip, gwip)
int nfd, mtu;
ip_t *ip;
struct in_addr gwip;
{
static tcp_seq iss = 2;
struct tcpiphdr *ti;
int thlen, i;
u_long lbuf[20];
ti = (struct tcpiphdr *)lbuf;
bzero((char *)ti, sizeof(*ti));
thlen = sizeof(tcphdr_t);
ip->ip_p = IPPROTO_TCP;
ti->ti_pr = ip->ip_p;
ti->ti_src = ip->ip_src;
ti->ti_dst = ip->ip_dst;
bcopy((char *)ip + (ip->ip_hl << 2),
(char *)&ti->ti_sport, sizeof(tcphdr_t));
if (!ti->ti_win)
ti->ti_win = htons(4096);
if (!ti->ti_seq)
ti->ti_seq = htonl(iss);
iss += 64;
if ((ti->ti_flags == TH_SYN) && !ip->ip_off)
{
ip = (ip_t *)realloc((char *)ip, ntohs(ip->ip_len) + 4);
i = sizeof(struct tcpiphdr) / sizeof(long);
lbuf[i] = htonl(0x020405b4);
bcopy((char *)(lbuf + i), (char*)ip + ntohs(ip->ip_len),
sizeof(u_long));
thlen += 4;
}
if (!ti->ti_off)
ti->ti_off = thlen >> 2;
ti->ti_len = htons(thlen);
ip->ip_len = (ip->ip_hl << 2) + thlen;
ti->ti_sum = 0;
ti->ti_sum = chksum(ti, thlen + sizeof(ip_t));
bcopy((char *)&ti->ti_sport,
(char *)ip + (ip->ip_hl << 2), thlen);
return send_ip(nfd, mtu, ip, gwip, 1);
}
/*
* send a udp packet.
*/
int send_udp(nfd, mtu, ip, gwip)
int nfd, mtu;
ip_t *ip;
struct in_addr gwip;
{
struct tcpiphdr *ti;
int thlen;
u_long lbuf[20];
ti = (struct tcpiphdr *)lbuf;
bzero((char *)ti, sizeof(*ti));
thlen = sizeof(udphdr_t);
ti->ti_pr = ip->ip_p;
ti->ti_src = ip->ip_src;
ti->ti_dst = ip->ip_dst;
bcopy((char *)ip + (ip->ip_hl << 2),
(char *)&ti->ti_sport, sizeof(udphdr_t));
ti->ti_len = htons(thlen);
ip->ip_len = (ip->ip_hl << 2) + thlen;
ti->ti_sum = 0;
ti->ti_sum = chksum(ti, thlen + sizeof(ip_t));
bcopy((char *)&ti->ti_sport,
(char *)ip + (ip->ip_hl << 2), sizeof(udphdr_t));
return send_ip(nfd, mtu, ip, gwip, 1);
}
/*
* send an icmp packet.
*/
int send_icmp(nfd, mtu, ip, gwip)
int nfd, mtu;
ip_t *ip;
struct in_addr gwip;
{
struct icmp *ic;
ic = (struct icmp *)((char *)ip + (ip->ip_hl << 2));
ic->icmp_cksum = 0;
ic->icmp_cksum = chksum((char *)ic, sizeof(struct icmp));
return send_ip(nfd, mtu, ip, gwip, 1);
}
int send_packet(nfd, mtu, ip, gwip)
int nfd, mtu;
ip_t *ip;
struct in_addr gwip;
{
switch (ip->ip_p)
{
case IPPROTO_TCP :
return send_tcp(nfd, mtu, ip, gwip);
case IPPROTO_UDP :
return send_udp(nfd, mtu, ip, gwip);
case IPPROTO_ICMP :
return send_icmp(nfd, mtu, ip, gwip);
default :
return send_ip(nfd, mtu, ip, gwip, 1);
}
}

View File

@ -0,0 +1,242 @@
/*
* (C)opyright 1995 by Darren Reed.
*
* This code may be freely distributed as long as it retains this notice
* and is not changed in any way. The author accepts no responsibility
* for the use of this software. I hate legaleese, don't you ?
*
* @(#)ip_compat.h 1.2 12/7/95
*/
/*
* These #ifdef's are here mainly for linux, but who knows, they may
* not be in other places or maybe one day linux will grow up and some
* of these will turn up there too.
*/
#ifndef ICMP_UNREACH
# define ICMP_UNREACH ICMP_DEST_UNREACH
#endif
#ifndef ICMP_SOURCEQUENCH
# define ICMP_SOURCEQUENCH ICMP_SOURCE_QUENCH
#endif
#ifndef ICMP_TIMXCEED
# define ICMP_TIMXCEED ICMP_TIME_EXCEEDED
#endif
#ifndef ICMP_PARAMPROB
# define ICMP_PARAMPROB ICMP_PARAMETERPROB
#endif
#ifndef IPVERSION
# define IPVERSION 4
#endif
#ifndef IPOPT_MINOFF
# define IPOPT_MINOFF 4
#endif
#ifndef IPOPT_COPIED
# define IPOPT_COPIED(x) ((x)&0x80)
#endif
#ifndef IPOPT_EOL
# define IPOPT_EOL 0
#endif
#ifndef IPOPT_NOP
# define IPOPT_NOP 1
#endif
#ifndef IP_MF
# define IP_MF ((u_short)0x2000)
#endif
#ifndef ETHERTYPE_IP
# define ETHERTYPE_IP ((u_short)0x0800)
#endif
#ifndef TH_FIN
# define TH_FIN 0x01
#endif
#ifndef TH_SYN
# define TH_SYN 0x02
#endif
#ifndef TH_RST
# define TH_RST 0x04
#endif
#ifndef TH_PUSH
# define TH_PUSH 0x08
#endif
#ifndef TH_ACK
# define TH_ACK 0x10
#endif
#ifndef TH_URG
# define TH_URG 0x20
#endif
#ifndef IPOPT_EOL
# define IPOPT_EOL 0
#endif
#ifndef IPOPT_NOP
# define IPOPT_NOP 1
#endif
#ifndef IPOPT_RR
# define IPOPT_RR 7
#endif
#ifndef IPOPT_TS
# define IPOPT_TS 68
#endif
#ifndef IPOPT_SECURITY
# define IPOPT_SECURITY 130
#endif
#ifndef IPOPT_LSRR
# define IPOPT_LSRR 131
#endif
#ifndef IPOPT_SATID
# define IPOPT_SATID 136
#endif
#ifndef IPOPT_SSRR
# define IPOPT_SSRR 137
#endif
#ifndef IPOPT_SECUR_UNCLASS
# define IPOPT_SECUR_UNCLASS ((u_short)0x0000)
#endif
#ifndef IPOPT_SECUR_CONFID
# define IPOPT_SECUR_CONFID ((u_short)0xf135)
#endif
#ifndef IPOPT_SECUR_EFTO
# define IPOPT_SECUR_EFTO ((u_short)0x789a)
#endif
#ifndef IPOPT_SECUR_MMMM
# define IPOPT_SECUR_MMMM ((u_short)0xbc4d)
#endif
#ifndef IPOPT_SECUR_RESTR
# define IPOPT_SECUR_RESTR ((u_short)0xaf13)
#endif
#ifndef IPOPT_SECUR_SECRET
# define IPOPT_SECUR_SECRET ((u_short)0xd788)
#endif
#ifndef IPOPT_SECUR_TOPSECRET
# define IPOPT_SECUR_TOPSECRET ((u_short)0x6bc5)
#endif
#ifdef linux
# if LINUX < 0200
# define icmp icmphdr
# define icmp_type type
# define icmp_code code
# endif
/*
* From /usr/include/netinet/ip_var.h
* !%@#!$@# linux...
*/
struct ipovly {
caddr_t ih_next, ih_prev; /* for protocol sequence q's */
u_char ih_x1; /* (unused) */
u_char ih_pr; /* protocol */
short ih_len; /* protocol length */
struct in_addr ih_src; /* source internet address */
struct in_addr ih_dst; /* destination internet address */
};
typedef struct {
__u16 th_sport;
__u16 th_dport;
__u32 th_seq;
__u32 th_ack;
# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\
defined(vax)
__u8 th_res:4;
__u8 th_off:4;
#else
__u8 th_off:4;
__u8 th_res:4;
#endif
__u8 th_flags;
__u16 th_win;
__u16 th_sum;
__u16 th_urp;
} tcphdr_t;
typedef struct {
__u16 uh_sport;
__u16 uh_dport;
__s16 uh_ulen;
__u16 uh_sum;
} udphdr_t;
typedef struct {
# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\
defined(vax)
__u8 ip_hl:4;
__u8 ip_v:4;
# else
__u8 ip_hl:4;
__u8 ip_v:4;
# endif
__u8 ip_tos;
__u16 ip_len;
__u16 ip_id;
__u16 ip_off;
__u8 ip_ttl;
__u8 ip_p;
__u16 ip_sum;
struct in_addr ip_src;
struct in_addr ip_dst;
} ip_t;
typedef struct {
__u8 ether_dhost[6];
__u8 ether_shost[6];
__u16 ether_type;
} ether_header_t;
typedef struct icmp {
u_char icmp_type; /* type of message, see below */
u_char icmp_code; /* type sub code */
u_short icmp_cksum; /* ones complement cksum of struct */
union {
u_char ih_pptr; /* ICMP_PARAMPROB */
struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
struct ih_idseq {
n_short icd_id;
n_short icd_seq;
} ih_idseq;
int ih_void;
} icmp_hun;
#define icmp_pptr icmp_hun.ih_pptr
#define icmp_gwaddr icmp_hun.ih_gwaddr
#define icmp_id icmp_hun.ih_idseq.icd_id
#define icmp_seq icmp_hun.ih_idseq.icd_seq
#define icmp_void icmp_hun.ih_void
union {
struct id_ts {
n_time its_otime;
n_time its_rtime;
n_time its_ttime;
} id_ts;
struct id_ip {
ip_t idi_ip;
/* options and then 64 bits of data */
} id_ip;
u_long id_mask;
char id_data[1];
} icmp_dun;
#define icmp_otime icmp_dun.id_ts.its_otime
#define icmp_rtime icmp_dun.id_ts.its_rtime
#define icmp_ttime icmp_dun.id_ts.its_ttime
#define icmp_ip icmp_dun.id_ip.idi_ip
#define icmp_mask icmp_dun.id_mask
#define icmp_data icmp_dun.id_data
} icmphdr_t;
# define bcopy(a,b,c) memmove(b,a,c)
# define bcmp(a,b,c) memcmp(a,b,c)
# define ifnet device
#else
typedef struct udphdr udphdr_t;
typedef struct tcphdr tcphdr_t;
typedef struct ip ip_t;
typedef struct ether_header ether_header_t;
#endif
#if defined(__SVR4) || defined(__svr4__)
# define bcopy(a,b,c) memmove(b,a,c)
# define bcmp(a,b,c) memcmp(a,b,c)
# define bzero(a,b) memset(a,0,b)
#endif

View File

@ -0,0 +1,123 @@
/* @(#)ip_var.h 1.11 88/08/19 SMI; from UCB 7.1 6/5/86 */
/*
* Copyright (c) 1982, 1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
/*
* Overlay for ip header used by other protocols (tcp, udp).
*/
#ifndef _netinet_ip_var_h
#define _netinet_ip_var_h
struct ipovly {
caddr_t ih_next, ih_prev; /* for protocol sequence q's */
u_char ih_x1; /* (unused) */
u_char ih_pr; /* protocol */
short ih_len; /* protocol length */
struct in_addr ih_src; /* source internet address */
struct in_addr ih_dst; /* destination internet address */
};
/*
* Ip reassembly queue structure. Each fragment
* being reassembled is attached to one of these structures.
* They are timed out after ipq_ttl drops to 0, and may also
* be reclaimed if memory becomes tight.
*/
struct ipq {
struct ipq *next,*prev; /* to other reass headers */
u_char ipq_ttl; /* time for reass q to live */
u_char ipq_p; /* protocol of this fragment */
u_short ipq_id; /* sequence id for reassembly */
struct ipasfrag *ipq_next,*ipq_prev;
/* to ip headers of fragments */
struct in_addr ipq_src,ipq_dst;
};
/*
* Ip header, when holding a fragment.
*
* Note: ipf_next must be at same offset as ipq_next above
*/
struct ipasfrag {
#if defined(vax) || defined(i386)
u_char ip_hl:4,
ip_v:4;
#endif
#if defined(mc68000) || defined(sparc)
u_char ip_v:4,
ip_hl:4;
#endif
u_char ipf_mff; /* copied from (ip_off&IP_MF) */
short ip_len;
u_short ip_id;
short ip_off;
u_char ip_ttl;
u_char ip_p;
u_short ip_sum;
struct ipasfrag *ipf_next; /* next fragment */
struct ipasfrag *ipf_prev; /* previous fragment */
};
/*
* Structure stored in mbuf in inpcb.ip_options
* and passed to ip_output when ip options are in use.
* The actual length of the options (including ipopt_dst)
* is in m_len.
*/
#define MAX_IPOPTLEN 40
struct ipoption {
struct in_addr ipopt_dst; /* first-hop dst if source routed */
char ipopt_list[MAX_IPOPTLEN]; /* options proper */
};
/*
* Structure stored in an mbuf attached to inpcb.ip_moptions and
* passed to ip_output when IP multicast options are in use.
*/
struct ip_moptions {
struct ifnet *imo_multicast_ifp; /* ifp for outgoing multicasts */
u_char imo_multicast_ttl; /* TTL for outgoing multicasts */
u_char imo_multicast_loop; /* 1 => hear sends if a member */
u_short imo_num_memberships;/* no. memberships this socket */
struct in_multi *imo_membership[IP_MAX_MEMBERSHIPS];
#ifdef RSVP_ISI
long imo_multicast_vif; /* vif for outgoing multicasts */
#endif /* RSVP_ISI */
};
struct ipstat {
long ips_total; /* total packets received */
long ips_badsum; /* checksum bad */
long ips_tooshort; /* packet too short */
long ips_toosmall; /* not enough data */
long ips_badhlen; /* ip header length < data size */
long ips_badlen; /* ip length < ip header length */
long ips_fragments; /* fragments received */
long ips_fragdropped; /* frags dropped (dups, out of space) */
long ips_fragtimeout; /* fragments timed out */
long ips_forward; /* packets forwarded */
long ips_cantforward; /* packets rcvd for unreachable dest */
long ips_redirectsent; /* packets forwarded on same net */
};
#ifdef KERNEL
/* flags passed to ip_output as last parameter */
#define IP_FORWARDING 0x1 /* most of ip header exists */
#define IP_MULTICASTOPTS 0x2 /* multicast opts present */
#define IP_ROUTETOIF SO_DONTROUTE /* bypass routing tables */
#define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */
struct ipstat ipstat;
struct ipq ipq; /* ip reass. queue */
u_short ip_id; /* ip packet ctr, for ids */
struct mbuf *ip_srcroute();
#endif
#endif /*!_netinet_ip_var_h*/

View File

@ -0,0 +1,165 @@
/*
* ipsend.c (C) 1995 Darren Reed
*
* This was written to test what size TCP fragments would get through
* various TCP/IP packet filters, as used in IP firewalls. In certain
* conditions, enough of the TCP header is missing for unpredictable
* results unless the filter is aware that this can happen.
*
* The author provides this program as-is, with no gaurantee for its
* suitability for any specific purpose. The author takes no responsibility
* for the misuse/abuse of this program and provides it for the sole purpose
* of testing packet filter policies. This file maybe distributed freely
* providing it is not modified and that this notice remains in tact.
*
* This was written and tested (successfully) on SunOS 4.1.x.
*/
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "%W% %G% (C)1995 Darren Reed";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#ifndef linux
#include <netinet/ip_var.h>
#include <netinet/tcpip.h>
#endif
#include "ip_compat.h"
#ifdef linux
#include <linux/sockios.h>
#include "tcpip.h"
#endif
#include "ipt.h"
extern char *optarg;
extern int optind;
#ifndef NO_IPF
extern struct ipread snoop, pcap, etherf, iphex, tcpd, iptext;
#endif
extern int resolve(), ip_resend();
int opts = 0;
#ifndef DEFAULT_DEVICE
# ifdef linux
char default_device[] = "eth0";
# else
# ifdef sun
char default_device[] = "le0";
# else
# ifdef ultrix
char default_device[] = "ln0";
# else
# ifdef __bsdi__
char default_device[] = "ef0";
# else
char default_device[] = "lan0";
# endif
# endif
# endif
# endif
#else
char default_device[] = DEFAULT_DEVICE;
#endif
void usage(prog)
char *prog;
{
fprintf(stderr, "Usage: %s [options] <-r filename|-R filename>\n\
\t\t-r filename\tsnoop data file to resend\n\
\t\t-R filename\tlibpcap data file to resend\n\
\toptions:\n\
\t\t-d device\tSend out on this device\n\
\t\t-g gateway\tIP gateway to use if non-local dest.\n\
\t\t-m mtu\t\tfake MTU to use when sending out\n\
", prog);
exit(1);
}
int main(argc, argv)
int argc;
char **argv;
{
struct in_addr gwip;
struct ipread *ipr = NULL;
char *name = argv[0], *gateway = NULL, *dev = NULL;
char c, *resend = NULL;
int mtu = 1500;
while ((c = getopt(argc, argv, "EHPSTXd:g:m:r:")) != -1)
switch (c)
{
case 'd' :
dev = optarg;
break;
case 'g' :
gateway = optarg;
break;
case 'm' :
mtu = atoi(optarg);
if (mtu < 28)
{
fprintf(stderr, "mtu must be > 28\n");
exit(1);
}
case 'r' :
resend = optarg;
break;
#ifndef NO_IPF
case 'E' :
ipr = &etherf;
break;
case 'H' :
ipr = &iphex;
break;
case 'P' :
ipr = &pcap;
break;
case 'S' :
ipr = &snoop;
break;
case 'T' :
ipr = &tcpd;
break;
case 'X' :
ipr = &iptext;
break;
#endif
default :
fprintf(stderr, "Unknown option \"%c\"\n", c);
usage(name);
}
if (!ipr || !resend)
usage(name);
gwip.s_addr = 0;
if (gateway && resolve(gateway, (char *)&gwip) == -1)
{
fprintf(stderr,"Cant resolve %s\n", gateway);
exit(2);
}
if (!dev)
dev = default_device;
printf("Device: %s\n", dev);
printf("Gateway: %s\n", inet_ntoa(gwip));
printf("mtu: %d\n", mtu);
return ip_resend(dev, mtu, ipr, gwip, resend);
}

View File

@ -0,0 +1,350 @@
/*
* ipsend.c (C) 1995 Darren Reed
*
* This was written to test what size TCP fragments would get through
* various TCP/IP packet filters, as used in IP firewalls. In certain
* conditions, enough of the TCP header is missing for unpredictable
* results unless the filter is aware that this can happen.
*
* The author provides this program as-is, with no gaurantee for its
* suitability for any specific purpose. The author takes no responsibility
* for the misuse/abuse of this program and provides it for the sole purpose
* of testing packet filter policies. This file maybe distributed freely
* providing it is not modified and that this notice remains in tact.
*
* This was written and tested (successfully) on SunOS 4.1.x.
*/
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)ipsend.c 1.5 12/10/95 (C)1995 Darren Reed";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#ifndef linux
#include <netinet/ip_var.h>
#include <netinet/tcpip.h>
#endif
#include "ip_compat.h"
#ifdef linux
#include <linux/sockios.h>
#include "tcpip.h"
#endif
#include "ipt.h"
extern char *optarg;
extern int optind;
extern int resolve(), optname(), initdevice(), send_packet();
char options[68];
#ifdef linux
char default_device[] = "eth0";
#else
# ifdef sun
char default_device[] = "le0";
# else
# ifdef ultrix
char default_device[] = "ln0";
# else
# ifdef __bsdi__
char default_device[] = "ef0";
# else
char default_device[] = "lan0";
# endif
# endif
# endif
#endif
void usage(prog)
char *prog;
{
fprintf(stderr, "Usage: %s [options] dest [flags]\n\
\toptions:\n\
\t\t-d device\tSend out on this device\n\
\t\t-f fragflags\tcan set IP_MF or IP_DF\n\
\t\t-g gateway\tIP gateway to use if non-local dest.\n\
\t\t-I code,type[,gw[,dst[,src]]]\tSet ICMP protocol\n\
\t\t-m mtu\t\tfake MTU to use when sending out\n\
\t\t-P protocol\tSet protocol by name\n\
\t\t-s src\t\tsource address for IP packet\n\
\t\t-T\t\tSet TCP protocol\n\
\t\t-t port\t\tdestination port\n\
\t\t-U\t\tSet UDP protocol\n\
", prog);
exit(1);
}
void do_icmp(ip, args)
ip_t *ip;
char *args;
{
struct icmp *ic;
char *s;
ip->ip_p = IPPROTO_ICMP;
ip->ip_len += sizeof(*ic);
ic = (struct icmp *)(ip + 1);
bzero((char *)ic, sizeof(*ic));
if (!(s = strchr(args, ',')))
{
fprintf(stderr, "ICMP args missing: ,\n");
return;
}
*s++ = '\0';
ic->icmp_type = atoi(args);
ic->icmp_code = atoi(s);
if (ic->icmp_type == ICMP_REDIRECT && strchr(s, ','))
{
char *t;
t = strtok(s, ",");
t = strtok(NULL, ",");
if (resolve(t, (char *)&ic->icmp_gwaddr) == -1)
{
fprintf(stderr,"Cant resolve %s\n", t);
exit(2);
}
if ((t = strtok(NULL, ",")))
{
if (resolve(t, (char *)&ic->icmp_ip.ip_dst) == -1)
{
fprintf(stderr,"Cant resolve %s\n", t);
exit(2);
}
if ((t = strtok(NULL, ",")))
{
if (resolve(t,
(char *)&ic->icmp_ip.ip_src) == -1)
{
fprintf(stderr,"Cant resolve %s\n", t);
exit(2);
}
}
}
}
}
int send_packets(dev, mtu, ip, gwip)
char *dev;
int mtu;
ip_t *ip;
struct in_addr gwip;
{
u_short sport = 0;
int wfd;
if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
sport = ((struct tcpiphdr *)ip)->ti_sport;
wfd = initdevice(dev, sport, 5);
return send_packet(wfd, mtu, ip, gwip);
}
int main(argc, argv)
int argc;
char **argv;
{
struct tcpiphdr *ti;
struct in_addr gwip;
tcphdr_t *tcp;
ip_t *ip;
char *name = argv[0], host[64], *gateway = NULL, *dev = NULL;
char *src = NULL, *dst, c, *s;
int mtu = 1500, olen = 0;
/*
* 65535 is maximum packet size...you never know...
*/
ip = (ip_t *)calloc(1, 65536);
ti = (struct tcpiphdr *)ip;
tcp = (tcphdr_t *)&ti->ti_sport;
ip->ip_len = sizeof(*ip);
ip->ip_hl = sizeof(*ip) >> 2;
while ((c = getopt(argc, argv, "IP:TUd:f:g:m:o:s:t:")) != -1)
switch (c)
{
case 'I' :
if (ip->ip_p)
{
fprintf(stderr, "Protocol already set: %d\n",
ip->ip_p);
break;
}
do_icmp(ip, optarg);
break;
case 'P' :
{
struct protoent *p;
if (ip->ip_p)
{
fprintf(stderr, "Protocol already set: %d\n",
ip->ip_p);
break;
}
if ((p = getprotobyname(optarg)))
ip->ip_p = p->p_proto;
else
fprintf(stderr, "Unknown protocol: %s\n",
optarg);
break;
}
case 'T' :
if (ip->ip_p)
{
fprintf(stderr, "Protocol already set: %d\n",
ip->ip_p);
break;
}
ip->ip_p = IPPROTO_TCP;
ip->ip_len += sizeof(tcphdr_t);
break;
case 'U' :
if (ip->ip_p)
{
fprintf(stderr, "Protocol already set: %d\n",
ip->ip_p);
break;
}
ip->ip_p = IPPROTO_UDP;
ip->ip_len += sizeof(udphdr_t);
break;
case 'd' :
dev = optarg;
break;
case 'f' :
ip->ip_off = strtol(optarg, NULL, 0);
break;
case 'g' :
gateway = optarg;
break;
case 'm' :
mtu = atoi(optarg);
if (mtu < 28)
{
fprintf(stderr, "mtu must be > 28\n");
exit(1);
}
break;
case 'o' :
olen = optname(optarg, options);
break;
case 's' :
src = optarg;
break;
case 't' :
if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
tcp->th_dport = htons(atoi(optarg));
break;
case 'w' :
if (ip->ip_p == IPPROTO_TCP)
tcp->th_win = atoi(optarg);
else
fprintf(stderr, "set protocol to TCP first\n");
break;
default :
fprintf(stderr, "Unknown option \"%c\"\n", c);
usage(name);
}
if (argc - optind < 2)
usage(name);
dst = argv[optind++];
if (!src)
{
gethostname(host, sizeof(host));
src = host;
}
if (resolve(src, (char *)&ip->ip_src) == -1)
{
fprintf(stderr,"Cant resolve %s\n", src);
exit(2);
}
if (resolve(dst, (char *)&ip->ip_dst) == -1)
{
fprintf(stderr,"Cant resolve %s\n", dst);
exit(2);
}
if (!gateway)
gwip = ip->ip_dst;
else if (resolve(gateway, (char *)&gwip) == -1)
{
fprintf(stderr,"Cant resolve %s\n", gateway);
exit(2);
}
if (ip->ip_p == IPPROTO_TCP)
for (s = argv[optind]; (c = *s); s++)
switch(c)
{
case 'S' : case 's' :
tcp->th_flags |= TH_SYN;
break;
case 'A' : case 'a' :
tcp->th_flags |= TH_ACK;
break;
case 'F' : case 'f' :
tcp->th_flags |= TH_FIN;
break;
case 'R' : case 'r' :
tcp->th_flags |= TH_RST;
break;
case 'P' : case 'p' :
tcp->th_flags |= TH_PUSH;
break;
case 'U' : case 'u' :
tcp->th_flags |= TH_URG;
break;
}
if (!dev)
dev = default_device;
printf("Device: %s\n", dev);
printf("Source: %s\n", inet_ntoa(ip->ip_src));
printf("Dest: %s\n", inet_ntoa(ip->ip_dst));
printf("Gateway: %s\n", inet_ntoa(gwip));
if (ip->ip_p == IPPROTO_TCP && tcp->th_flags)
printf("Flags: %#x\n", tcp->th_flags);
printf("mtu: %d\n", mtu);
if (olen)
{
printf("Options: %d\n", olen);
ti = (struct tcpiphdr *)malloc(olen + ip->ip_len);
bcopy((char *)ip, (char *)ti, sizeof(*ip));
ip = (ip_t *)ti;
ip->ip_hl += (olen >> 2);
bcopy(options, (char *)(ip + 1), olen);
bcopy((char *)tcp, (char *)(ip + 1) + olen, sizeof(*tcp));
tcp = (tcphdr_t *)((char *)(ip + 1) + olen);
ip->ip_len += olen;
}
#ifdef DOSOCKET
if (tcp->th_dport)
return do_socket(dev, mtu, ti, gwip);
#endif
return send_packets(dev, mtu, ti, gwip);
}

View File

@ -0,0 +1,111 @@
/*
* (C)opyright 1995 by Darren Reed.
*
* This code may be freely distributed as long as it retains this notice
* and is not changed in any way. The author accepts no responsibility
* for the use of this software. I hate legaleese, don't you ?
*/
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)ipsopt.c 1.2 1/11/96 (C)1995 Darren Reed";
#endif
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include "ip_compat.h"
struct ipopt_names {
int on_value;
int on_bit;
int on_siz;
char *on_name;
};
struct ipopt_names ionames[] = {
{ IPOPT_EOL, 0x01, 1, "eol" },
{ IPOPT_NOP, 0x02, 1, "nop" },
{ IPOPT_RR, 0x04, 7, "rr" }, /* 1 route */
{ IPOPT_TS, 0x08, 8, "ts" }, /* 1 TS */
{ IPOPT_SECURITY, 0x08, 11, "sec-level" },
{ IPOPT_LSRR, 0x10, 7, "lsrr" }, /* 1 route */
{ IPOPT_SATID, 0x20, 4, "satid" },
{ IPOPT_SSRR, 0x40, 7, "ssrr" }, /* 1 route */
{ 0, 0, 0, NULL } /* must be last */
};
struct ipopt_names secnames[] = {
{ IPOPT_SECUR_UNCLASS, 0x0100, 0, "unclass" },
{ IPOPT_SECUR_CONFID, 0x0200, 0, "confid" },
{ IPOPT_SECUR_EFTO, 0x0400, 0, "efto" },
{ IPOPT_SECUR_MMMM, 0x0800, 0, "mmmm" },
{ IPOPT_SECUR_RESTR, 0x1000, 0, "restr" },
{ IPOPT_SECUR_SECRET, 0x2000, 0, "secret" },
{ IPOPT_SECUR_TOPSECRET, 0x4000,0, "topsecret" },
{ 0, 0, 0, NULL } /* must be last */
};
u_short seclevel(slevel)
char *slevel;
{
struct ipopt_names *so;
for (so = secnames; so->on_name; so++)
if (!strcasecmp(slevel, so->on_name))
break;
if (!so->on_name) {
fprintf(stderr, "no such security level: %s\n", slevel);
return 0;
}
return so->on_value;
}
u_long optname(cp, op)
char *cp, *op;
{
struct ipopt_names *io;
u_short lvl;
u_long msk = 0;
char *s, *t;
int len = 0;
for (s = strtok(cp, ","); s; s = strtok(NULL, ",")) {
if ((t = strchr(s, '=')))
*t++ = '\0';
for (io = ionames; io->on_name; io++) {
if (strcasecmp(s, io->on_name) || (msk & io->on_bit))
continue;
if ((len + io->on_siz) > 48) {
fprintf(stderr, "options too long\n");
return 0;
}
len += io->on_siz;
*op++ = io->on_value;
if (io->on_siz > 1) {
*op++ = io->on_siz;
*op++ = IPOPT_MINOFF;
if (t && !strcasecmp(s, "sec-level")) {
lvl = seclevel(t);
bcopy(&lvl, op, sizeof(lvl));
}
op += io->on_siz - 3;
}
msk |= io->on_bit;
break;
}
if (!io->on_name) {
fprintf(stderr, "unknown IP option name %s\n", s);
return 0;
}
}
*op++ = IPOPT_EOL;
len++;
return len;
}

View File

@ -0,0 +1,211 @@
/*
* ipsend.c (C) 1995 Darren Reed
*
* This was written to test what size TCP fragments would get through
* various TCP/IP packet filters, as used in IP firewalls. In certain
* conditions, enough of the TCP header is missing for unpredictable
* results unless the filter is aware that this can happen.
*
* The author provides this program as-is, with no gaurantee for its
* suitability for any specific purpose. The author takes no responsibility
* for the misuse/abuse of this program and provides it for the sole purpose
* of testing packet filter policies. This file maybe distributed freely
* providing it is not modified and that this notice remains in tact.
*
* This was written and tested (successfully) on SunOS 4.1.x.
*/
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "%W% %G% (C)1995 Darren Reed";
#endif
#include <stdio.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#ifndef linux
#include <netinet/ip_var.h>
#include <netinet/tcpip.h>
#endif
#include "ip_compat.h"
#ifdef linux
#include <linux/sockios.h>
#include "tcpip.h"
#endif
#include "ipt.h"
extern char *optarg;
extern int optind;
extern int initdevice(), resolve();
extern int ip_test1(), ip_test2(), ip_test3(), ip_test4(), ip_test5();
extern int ip_test6(), ip_test7();
char options[68];
#ifdef linux
char default_device[] = "eth0";
#else
# ifdef sun
char default_device[] = "le0";
# else
# ifdef ultrix
char default_device[] = "ln0";
# else
# ifdef __bsdi__
char default_device[] = "ef0";
# else
char default_device[] = "lan0";
# endif
# endif
# endif
#endif
void usage(prog)
char *prog;
{
fprintf(stderr, "Usage: %s [options] dest\n\
\toptions:\n\
\t\t-d device\tSend out on this device\n\
\t\t-g gateway\tIP gateway to use if non-local dest.\n\
\t\t-m mtu\t\tfake MTU to use when sending out\n\
\t\t-p pointtest\t\n\
\t\t-s src\t\tsource address for IP packet\n\
\t\t-1 \t\tPerform test 1 (IP header)\n\
\t\t-2 \t\tPerform test 2 (IP options)\n\
\t\t-3 \t\tPerform test 3 (ICMP)\n\
\t\t-4 \t\tPerform test 4 (UDP)\n\
\t\t-5 \t\tPerform test 5 (TCP)\n\
\t\t-6 \t\tPerform test 6 (overlapping fragments)\n\
\t\t-7 \t\tPerform test 7 (random packets)\n\
", prog);
exit(1);
}
int main(argc, argv)
int argc;
char **argv;
{
struct tcpiphdr *ti;
struct in_addr gwip;
ip_t *ip;
char *name = argv[0], host[64], *gateway = NULL, *dev = NULL;
char *src = NULL, *dst, c;
int mtu = 1500, tests = 0, pointtest = 0;
/*
* 65535 is maximum packet size...you never know...
*/
ip = (ip_t *)calloc(1, 65536);
ti = (struct tcpiphdr *)ip;
ip->ip_len = sizeof(*ip);
ip->ip_hl = sizeof(*ip) >> 2;
while ((c = getopt(argc, argv, "1234567IP:TUd:f:g:m:o:p:s:t:")) != -1)
switch (c)
{
case '1' :
case '2' :
case '3' :
case '4' :
case '5' :
case '6' :
case '7' :
tests = c - '0';
break;
case 'd' :
dev = optarg;
break;
case 'g' :
gateway = optarg;
break;
case 'm' :
mtu = atoi(optarg);
if (mtu < 28)
{
fprintf(stderr, "mtu must be > 28\n");
exit(1);
}
break;
case 'p' :
pointtest = atoi(optarg);
break;
case 's' :
src = optarg;
break;
default :
fprintf(stderr, "Unknown option \"%c\"\n", c);
usage(name);
}
if (argc - optind < 2 && !tests)
usage(name);
dst = argv[optind++];
if (!src)
{
gethostname(host, sizeof(host));
src = host;
}
if (resolve(dst, (char *)&ip->ip_dst) == -1)
{
fprintf(stderr,"Cant resolve %s\n", dst);
exit(2);
}
if (resolve(src, (char *)&ip->ip_src) == -1)
{
fprintf(stderr,"Cant resolve %s\n", src);
exit(2);
}
if (!gateway)
gwip = ip->ip_dst;
else if (resolve(gateway, (char *)&gwip) == -1)
{
fprintf(stderr,"Cant resolve %s\n", gateway);
exit(2);
}
if (!dev)
dev = default_device;
printf("Device: %s\n", dev);
printf("Source: %s\n", inet_ntoa(ip->ip_src));
printf("Dest: %s\n", inet_ntoa(ip->ip_dst));
printf("Gateway: %s\n", inet_ntoa(gwip));
printf("mtu: %d\n", mtu);
switch (tests)
{
case 1 :
return ip_test1(dev, mtu, ti, gwip, pointtest);
case 2 :
return ip_test2(dev, mtu, ti, gwip, pointtest);
case 3 :
return ip_test3(dev, mtu, ti, gwip, pointtest);
case 4 :
return ip_test4(dev, mtu, ti, gwip, pointtest);
case 5 :
return ip_test5(dev, mtu, ti, gwip, pointtest);
case 6 :
return ip_test6(dev, mtu, ti, gwip, pointtest);
case 7 :
return ip_test7(dev, mtu, ti, gwip, pointtest);
default :
break;
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,85 @@
/*
* larp.c (C) 1995 Darren Reed
*
* The author provides this program as-is, with no gaurantee for its
* suitability for any specific purpose. The author takes no responsibility
* for the misuse/abuse of this program and provides it for the sole purpose
* of testing packet filter policies. This file maybe distributed freely
* providing it is not modified and that this notice remains in tact.
*/
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)larp.c 1.1 8/19/95 (C)1995 Darren Reed";
#endif
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <net/if.h>
#include <net/if_arp.h>
/*
* lookup host and return
* its IP address in address
* (4 bytes)
*/
int resolve(host, address)
char *host, *address;
{
struct hostent *hp;
u_long add;
add = inet_addr(host);
if (add == -1)
{
if (!(hp = gethostbyname(host)))
{
fprintf(stderr, "unknown host: %s\n", host);
return -1;
}
bcopy((char *)hp->h_addr, (char *)address, 4);
return 0;
}
bcopy((char*)&add, address, 4);
return 0;
}
/*
* ARP for the MAC address corresponding
* to the IP address. This taken from
* some BSD program, I cant remember which.
*/
int arp(ip, ether)
char *ip;
char *ether;
{
static int s = -1;
struct arpreq ar;
struct sockaddr_in *sin;
char *inet_ntoa();
bzero((char *)&ar, sizeof(ar));
sin = (struct sockaddr_in *)&ar.arp_pa;
sin->sin_family = AF_INET;
bcopy(ip, (char *)&sin->sin_addr.s_addr, 4);
if (s == -1)
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("arp: socket");
return -1;
}
if (ioctl(s, SIOCGARP, (caddr_t)&ar) == -1)
{
fprintf(stderr, "(%s):", inet_ntoa(sin->sin_addr));
if (errno != ENXIO)
perror("SIOCGARP");
return -1;
}
bcopy(ar.arp_ha.sa_data, ether, 6);
return 0;
}

View File

@ -0,0 +1,17 @@
/*
* (C)opyright 1995 by Darren Reed.
*
* This code may be freely distributed as long as it retains this notice
* and is not changed in any way. The author accepts no responsibility
* for the use of this software. I hate legaleese, don't you ?
*
* @(#)linux.h 1.1 8/19/95
*/
#include <linux/config.h>
#ifdef MODULE
#include <linux/module.h>
#include <linux/version.h>
#endif /* MODULE */
#include "ip_compat.h"

View File

@ -0,0 +1,261 @@
/*
* lsock.c (C) 1995 Darren Reed
*
* The author provides this program as-is, with no gaurantee for its
* suitability for any specific purpose. The author takes no responsibility
* for the misuse/abuse of this program and provides it for the sole purpose
* of testing packet filter policies. This file maybe distributed freely
* providing it is not modified and that this notice remains in tact.
*/
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)lsock.c 1.2 1/11/96 (C)1995 Darren Reed";
#endif
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/dir.h>
#define __KERNEL__
#if LINUX >= 0200
# undef UINT_MAX
# undef INT_MAX
# undef ULONG_MAX
# undef LONG_MAX
# include <linux/notifier.h>
#endif
#include <linux/fs.h>
#if LINUX >= 0200
#include "linux/netdevice.h"
#include "net/sock.h"
#endif
#undef __KERNEL__
#include <linux/sched.h>
#include <linux/netdevice.h>
#include <nlist.h>
#include <sys/user.h>
#include <sys/socket.h>
#include <math.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <net/if.h>
#if LINUX < 0103
#include <net/inet/sock.h>
#endif
#include "ip_compat.h"
#include "tcpip.h"
int nproc;
struct task_struct *proc;
#ifndef KMEM
# ifdef _PATH_KMEM
# define KMEM _PATH_KMEM
# endif
#endif
#ifndef KMEM
# define KMEM "/dev/kmem"
#endif
#ifndef KERNEL
# define KERNEL "/System.map"
#endif
int kmemcpy(buf, pos, n)
char *buf;
void *pos;
int n;
{
static int kfd = -1;
if (kfd == -1)
kfd = open(KMEM, O_RDONLY);
if (lseek(kfd, (off_t)pos, SEEK_SET) == -1)
{
perror("lseek");
return -1;
}
if (read(kfd, buf, n) == -1)
{
perror("read");
return -1;
}
return n;
}
struct nlist names[3] = {
{ "_task" },
{ "_nr_tasks" },
{ NULL }
};
struct task_struct *getproc()
{
struct task_struct *p, **pp;
void *v;
pid_t pid = getpid();
int siz, n;
n = nlist(KERNEL, names);
if (n != 0)
{
fprintf(stderr, "nlist(%#x) == %d\n", names, n);
return NULL;
}
if (kmemcpy((char *)&nproc, (void *)names[1].n_value,
sizeof(nproc)) == -1)
{
fprintf(stderr, "read nproc (%#x)\n", names[1].n_value);
return NULL;
}
siz = nproc * sizeof(struct task_struct *);
if (kmemcpy((char *)&v, (void *)names[0].n_value, sizeof(v)) == -1)
{
fprintf(stderr, "read(%#x,%#x,%d) proc\n",
names[0].n_value, &v, sizeof(v));
return NULL;
}
pp = (struct task_struct **)malloc(siz);
if (kmemcpy((char *)pp, (void *)v, siz) == -1)
{
fprintf(stderr, "read(%#x,%#x,%d) proc\n",
v, pp, siz);
return NULL;
}
proc = (struct task_struct *)malloc(siz);
for (n = 0; n < NR_TASKS; n++)
{
if (kmemcpy((char *)(proc + n), (void *)pp[n],
sizeof(*proc)) == -1)
{
fprintf(stderr, "read(%#x,%#x,%d) proc\n",
pp[n], proc + n, sizeof(*proc));
return NULL;
}
}
p = proc;
for (n = NR_TASKS; n; n--, p++)
if (p->pid == pid)
break;
if (!n)
return NULL;
return p;
}
struct sock *find_tcp(fd, ti)
int fd;
struct tcpiphdr *ti;
{
struct sock *s;
struct inode *i;
struct files_struct *fs;
struct task_struct *p;
struct file *f, **o;
if (!(p = getproc()))
return NULL;
fs = p->files;
o = (struct file **)calloc(1, sizeof(*o) * (fs->count + 1));
if (kmemcpy((char *)o, (void *)fs->fd,
(fs->count + 1) * sizeof(*o)) == -1)
{
fprintf(stderr, "read(%#x,%#x,%d) - fd - failed\n",
fs->fd, o, sizeof(*o));
return NULL;
}
f = (struct file *)calloc(1, sizeof(*f));
if (kmemcpy((char *)f, (void *)o[fd], sizeof(*f)) == -1)
{
fprintf(stderr, "read(%#x,%#x,%d) - o[fd] - failed\n",
o[fd], f, sizeof(*f));
return NULL;
}
i = (struct inode *)calloc(1, sizeof(*i));
if (kmemcpy((char *)i, (void *)f->f_inode, sizeof(*i)) == -1)
{
fprintf(stderr, "read(%#x,%#x,%d) - f_inode - failed\n",
f->f_inode, i, sizeof(*i));
return NULL;
}
return i->u.socket_i.data;
}
int do_socket(dev, mtu, ti, gwip, flags)
char *dev;
int mtu;
struct tcpiphdr *ti;
struct in_addr gwip;
int flags;
{
struct sockaddr_in rsin, lsin;
struct sock *s, sk;
int fd, nfd, len;
printf("Dest. Port: %d\n", ti->ti_dport);
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1)
{
perror("socket");
return -1;
}
if (fcntl(fd, F_SETFL, FNDELAY) == -1)
{
perror("fcntl");
return -1;
}
bzero((char *)&lsin, sizeof(lsin));
lsin.sin_family = AF_INET;
bcopy((char *)&ti->ti_src, (char *)&lsin.sin_addr,
sizeof(struct in_addr));
if (bind(fd, (struct sockaddr *)&lsin, sizeof(lsin)) == -1)
{
perror("bind");
return -1;
}
len = sizeof(lsin);
(void) getsockname(fd, (struct sockaddr *)&lsin, &len);
ti->ti_sport = lsin.sin_port;
printf("sport %d\n", ntohs(lsin.sin_port));
nfd = initdevice(dev, ntohs(lsin.sin_port));
if (!(s = find_tcp(fd, ti)))
return -1;
bzero((char *)&rsin, sizeof(rsin));
rsin.sin_family = AF_INET;
bcopy((char *)&ti->ti_dst, (char *)&rsin.sin_addr,
sizeof(struct in_addr));
rsin.sin_port = ti->ti_dport;
if (connect(fd, (struct sockaddr *)&rsin, sizeof(rsin)) == -1 &&
errno != EINPROGRESS)
{
perror("connect");
return -1;
}
kmemcpy((char*)&sk, (void *)s, sizeof(sk));
ti->ti_win = sk.window;
ti->ti_seq = sk.sent_seq - 1;
ti->ti_ack = sk.rcv_ack_seq;
if (send_tcp(nfd, mtu, ti, gwip, TH_SYN) == -1)
return -1;
(void)write(fd, "Hello World\n", 12);
sleep(2);
close(fd);
return 0;
}

View File

@ -0,0 +1,130 @@
/*
* resend.c (C) 1995 Darren Reed
*
* This was written to test what size TCP fragments would get through
* various TCP/IP packet filters, as used in IP firewalls. In certain
* conditions, enough of the TCP header is missing for unpredictable
* results unless the filter is aware that this can happen.
*
*/
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)resend.c 1.3 1/11/96 (C)1995 Darren Reed";
#endif
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#ifndef linux
#include <netinet/ip_var.h>
#include <netinet/tcpip.h>
#include <netinet/if_ether.h>
#endif
#include "ip_compat.h"
#ifdef linux
#include <linux/sockios.h>
#include "tcpip.h"
#endif
#include "ipt.h"
static u_char buf[65536]; /* 1 big packet */
extern int initdevice(), arp(), sendip();
void printpacket(ip)
ip_t *ip;
{
tcphdr_t *t;
int i, j;
t = (tcphdr_t *)((char *)ip + (ip->ip_hl << 2));
if (ip->ip_tos)
printf("tos %#x ", ip->ip_tos);
if (ip->ip_off & 0x3fff)
printf("frag @%#x ", (ip->ip_off & 0x1fff) << 3);
printf("len %d id %d ", ip->ip_len, ip->ip_id);
printf("ttl %d p %d src %s", ip->ip_ttl, ip->ip_p,
inet_ntoa(ip->ip_src));
if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
printf(",%d", t->th_sport);
printf(" dst %s", inet_ntoa(ip->ip_dst));
if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
printf(",%d", t->th_dport);
if (ip->ip_p == IPPROTO_TCP) {
printf(" seq %lu:%lu flags ",
(u_long)t->th_seq, (u_long)t->th_ack);
for (j = 0, i = 1; i < 256; i *= 2, j++)
if (t->th_flags & i)
printf("%c", "FSRPAU--"[j]);
}
putchar('\n');
}
int ip_resend(dev, mtu, r, gwip, datain)
char *dev;
int mtu;
struct in_addr gwip;
struct ipread *r;
char *datain;
{
ether_header_t *eh;
char dhost[6];
ip_t *ip;
int fd, wfd = initdevice(dev, 0, 5), len, i;
if (datain)
fd = (*r->r_open)(datain);
else
fd = (*r->r_open)("-");
if (fd < 0)
exit(-1);
ip = (struct ip *)buf;
eh = (ether_header_t *)malloc(sizeof(*eh));
bzero(&eh->ether_shost, sizeof(eh->ether_shost));
if (gwip.s_addr && (arp((char *)&gwip, dhost) == -1))
{
perror("arp");
return -2;
}
while ((i = (*r->r_readip)(buf, sizeof(buf), NULL, NULL)) > 0)
{
len = ntohs(ip->ip_len);
eh = (ether_header_t *)realloc((char *)eh, sizeof(*eh) + len);
eh->ether_type = htons((u_short)ETHERTYPE_IP);
if (!gwip.s_addr) {
if (arp((char *)&gwip,
(char *)&eh->ether_dhost) == -1) {
perror("arp");
continue;
}
} else
bcopy(dhost, (char *)&eh->ether_dhost, sizeof(dhost));
bcopy(ip, (char *)(eh + 1), len);
printpacket(ip);
if (sendip(wfd, eh, sizeof(*eh) + len) == -1)
{
perror("send_packet");
break;
}
}
(*r->r_close)();
return 0;
}

View File

@ -0,0 +1,136 @@
/*
* (C)opyright October 1995 Darren Reed. (from tcplog)
*
* This software may be freely distributed as long as it is not altered
* in any way and that this messagge always accompanies it.
*
*/
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/mbuf.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#if BSD < 199103
#include <sys/fcntlcom.h>
#endif
#include <sys/dir.h>
#include <net/bpf.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#if !defined(lint) && defined(LIBC_SCCS)
static char sbpf[] = "@(#)sbpf.c 1.3 8/25/95 (C)1995 Darren Reed";
#endif
/*
* the code herein is dervied from libpcap.
*/
static u_char *buf = NULL;
static int bufsize = 0, timeout = 1;
int initdevice(device, sport, tout)
char *device;
int sport, tout;
{
struct bpf_version bv;
struct timeval to;
struct ifreq ifr;
char bpfname[16];
int fd, i;
for (i = 0; i < 16; i++)
{
(void) sprintf(bpfname, "/dev/bpf%d", i);
if ((fd = open(bpfname, O_RDWR)) >= 0)
break;
}
if (i == 16)
{
fprintf(stderr, "no bpf devices available as /dev/bpfxx\n");
return -1;
}
if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0)
{
perror("BIOCVERSION");
return -1;
}
if (bv.bv_major != BPF_MAJOR_VERSION ||
bv.bv_minor < BPF_MINOR_VERSION)
{
fprintf(stderr, "kernel bpf (v%d.%d) filter out of date:\n",
bv.bv_major, bv.bv_minor);
fprintf(stderr, "current version: %d.%d\n",
BPF_MAJOR_VERSION, BPF_MINOR_VERSION);
return -1;
}
(void) strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
if (ioctl(fd, BIOCSETIF, &ifr) == -1)
{
fprintf(stderr, "%s(%d):", ifr.ifr_name, fd);
perror("BIOCSETIF");
exit(1);
}
/*
* get kernel buffer size
*/
if (ioctl(fd, BIOCGBLEN, &bufsize) == -1)
{
perror("BIOCSBLEN");
exit(-1);
}
buf = (u_char*)malloc(bufsize);
/*
* set the timeout
*/
timeout = tout;
to.tv_sec = 1;
to.tv_usec = 0;
if (ioctl(fd, BIOCSRTIMEOUT, (caddr_t)&to) == -1)
{
perror("BIOCSRTIMEOUT");
exit(-1);
}
(void) ioctl(fd, BIOCFLUSH, 0);
return fd;
}
/*
* output an IP packet onto a fd opened for /dev/bpf
*/
int sendip(fd, pkt, len)
int fd, len;
char *pkt;
{
if (write(fd, pkt, len) == -1)
{
perror("send");
return -1;
}
return len;
}

View File

@ -0,0 +1,130 @@
/*
* (C)opyright October 1992 Darren Reed. (from tcplog)
*
* This software may be freely distributed as long as it is not altered
* in any way and that this messagge always accompanies it.
*
* The author of this software makes no garuntee about the
* performance of this package or its suitability to fulfill any purpose.
*
*/
#include <stdio.h>
#include <netdb.h>
#include <ctype.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/stropts.h>
#include <sys/pfmod.h>
#include <sys/bufmod.h>
#include <sys/dlpi.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include "ip_compat.h"
#if !defined(lint) && defined(LIBC_SCCS)
static char snitid[] = "@(#)sdlpi.c 1.3 10/30/95 (C)1995 Darren Reed";
#endif
#define CHUNKSIZE 8192
#define BUFSPACE (4*CHUNKSIZE)
/*
* Be careful to only include those defined in the flags option for the
* interface are included in the header size.
*/
int initdevice(device, sport, tout)
char *device;
int sport, tout;
{
char devname[16], *s, buf[256];
int i, fd;
(void) sprintf(devname, "/dev/%s", device);
s = devname + 5;
while (*s && !isdigit(*s))
s++;
if (!*s)
{
fprintf(stderr, "bad device name %s\n", devname);
exit(-1);
}
i = atoi(s);
*s = '\0';
/*
* For writing
*/
if ((fd = open(devname, O_RDWR)) < 0)
{
fprintf(stderr, "O_RDWR(1) ");
perror(devname);
exit(-1);
}
if (dlattachreq(fd, i) == -1 || dlokack(fd, buf) == -1)
{
fprintf(stderr, "DLPI error\n");
exit(-1);
}
dlbindreq(fd, ETHERTYPE_IP, 0, DL_CLDLS, 0, 0);
dlbindack(fd, buf);
/*
* write full headers
*/
if (strioctl(fd, DLIOCRAW, -1, 0, NULL) == -1)
{
fprintf(stderr, "DLIOCRAW error\n");
exit(-1);
}
return fd;
}
/*
* output an IP packet onto a fd opened for /dev/nit
*/
int sendip(fd, pkt, len)
int fd, len;
char *pkt;
{
struct strbuf dbuf, *dp = &dbuf;
/*
* construct NIT STREAMS messages, first control then data.
*/
dp->buf = pkt;
dp->len = len;
dp->maxlen = dp->len;
if (putmsg(fd, NULL, dp, 0) == -1)
{
perror("putmsg");
return -1;
}
if (ioctl(fd, I_FLUSH, FLUSHW) == -1)
{
perror("I_FLUSHW");
return -1;
}
return len;
}

View File

@ -0,0 +1,94 @@
/*
* (C)opyright October 1992 Darren Reed. (from tcplog)
*
* This software may be freely distributed as long as it is not altered
* in any way and that this messagge always accompanies it.
*
* The author of this software makes no garuntee about the
* performance of this package or its suitability to fulfill any purpose.
*
*/
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <ctype.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/dir.h>
#include <linux/netdevice.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include "ip_compat.h"
#include "tcpip.h"
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)slinux.c 1.2 8/25/95";
#endif
#define CHUNKSIZE 8192
#define BUFSPACE (4*CHUNKSIZE)
/*
* Be careful to only include those defined in the flags option for the
* interface are included in the header size.
*/
static int timeout;
static char *eth_dev = NULL;
int initdevice(dev, sport, tout)
char *dev;
int sport, tout;
{
int fd;
eth_dev = strdup(dev);
if ((fd = socket(AF_INET, SOCK_PACKET, htons(ETHERTYPE_IP))) == -1)
{
perror("socket(SOCK_PACKET)");
exit(-1);
}
return fd;
}
/*
* output an IP packet onto a fd opened for /dev/nit
*/
int sendip(fd, pkt, len)
int fd, len;
char *pkt;
{
struct sockaddr s;
struct ifreq ifr;
strncpy(ifr.ifr_name, eth_dev, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1)
{
perror("SIOCGIFHWADDR");
return -1;
}
bcopy(ifr.ifr_hwaddr.sa_data, pkt + 6, 6);
s.sa_family = ETHERTYPE_IP;
strncpy(s.sa_data, eth_dev, sizeof(s.sa_data));
if (sendto(fd, pkt, len, 0, &s, sizeof(s)) == -1)
{
perror("send");
return -1;
}
return len;
}

View File

@ -0,0 +1,160 @@
/*
* (C)opyright October 1992 Darren Reed. (from tcplog)
*
* This software may be freely distributed as long as it is not altered
* in any way and that this messagge always accompanies it.
*
* The author of this software makes no garuntee about the
* performance of this package or its suitability to fulfill any purpose.
*
*/
#include <stdio.h>
#include <netdb.h>
#include <ctype.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <net/nit.h>
#include <sys/fcntlcom.h>
#include <sys/dir.h>
#include <net/nit_if.h>
#include <net/nit_pf.h>
#include <net/nit_buf.h>
#include <net/packetfilt.h>
#include <sys/stropts.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#if !defined(lint) && defined(LIBC_SCCS)
static char snitid[] = "@(#)snit.c 1.5 1/11/96 (C)1995 Darren Reed";
#endif
#define CHUNKSIZE 8192
#define BUFSPACE (4*CHUNKSIZE)
/*
* Be careful to only include those defined in the flags option for the
* interface are included in the header size.
*/
#define BUFHDR_SIZE (sizeof(struct nit_bufhdr))
#define NIT_HDRSIZE (BUFHDR_SIZE)
static int timeout;
int initdevice(device, sport, tout)
char *device;
int sport, tout;
{
struct strioctl si;
struct timeval to;
struct ifreq ifr;
int fd;
if ((fd = open("/dev/nit", O_RDWR)) < 0)
{
perror("/dev/nit");
exit(-1);
}
/*
* arrange to get messages from the NIT STREAM and use NIT_BUF option
*/
ioctl(fd, I_SRDOPT, (char*)RMSGD);
ioctl(fd, I_PUSH, "nbuf");
/*
* set the timeout
*/
timeout = tout;
si.ic_timout = 1;
to.tv_sec = 1;
to.tv_usec = 0;
si.ic_cmd = NIOCSTIME;
si.ic_len = sizeof(to);
si.ic_dp = (char*)&to;
if (ioctl(fd, I_STR, (char*)&si) == -1)
{
perror("ioctl: NIT timeout");
exit(-1);
}
/*
* request the interface
*/
strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' ';
si.ic_cmd = NIOCBIND;
si.ic_len = sizeof(ifr);
si.ic_dp = (char*)&ifr;
if (ioctl(fd, I_STR, (char*)&si) == -1)
{
perror(ifr.ifr_name);
exit(1);
}
return fd;
}
/*
* output an IP packet onto a fd opened for /dev/nit
*/
int sendip(fd, pkt, len)
int fd, len;
char *pkt;
{
struct sockaddr sk, *sa = &sk;
struct strbuf cbuf, *cp = &cbuf, dbuf, *dp = &dbuf;
/*
* For ethernet, need at least 802.3 header and IP header.
*/
if (len < (sizeof(sa->sa_data) + sizeof(struct ip)))
return -1;
/*
* to avoid any output processing for IP, say we're not.
*/
sa->sa_family = AF_UNSPEC;
bcopy(pkt, sa->sa_data, sizeof(sa->sa_data));
pkt += sizeof(sa->sa_data);
len -= sizeof(sa->sa_data);
/*
* construct NIT STREAMS messages, first control then data.
*/
cp->len = sizeof(*sa);
cp->maxlen = sizeof(*sa);
cp->buf = (char *)sa;
dp->buf = pkt;
dp->len = len;
dp->maxlen = dp->len;
if (putmsg(fd, cp, dp, 0) == -1)
{
perror("putmsg");
return -1;
}
if (ioctl(fd, I_FLUSH, FLUSHW) == -1)
{
perror("I_FLUSH");
return -1;
}
return len;
}

View File

@ -0,0 +1,370 @@
/*
* sock.c (C) 1995 Darren Reed
*
* The author provides this program as-is, with no gaurantee for its
* suitability for any specific purpose. The author takes no responsibility
* for the misuse/abuse of this program and provides it for the sole purpose
* of testing packet filter policies. This file maybe distributed freely
* providing it is not modified and that this notice remains in tact.
*/
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)sock.c 1.2 1/11/96 (C)1995 Darren Reed";
#endif
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/dir.h>
#define _KERNEL
#define KERNEL
#include <sys/file.h>
#undef _KERNEL
#undef KERNEL
#include <nlist.h>
#include <sys/user.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/proc.h>
#include <kvm.h>
#ifdef sun
#include <sys/systm.h>
#include <sys/session.h>
#endif
#if BSD >= 199103
#include <sys/sysctl.h>
#include <sys/filedesc.h>
#include <paths.h>
#endif
#include <math.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/ip_var.h>
#include <netinet/in_pcb.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#include <netinet/tcpip.h>
int nproc;
struct proc *proc;
extern int initdevice(), send_tcp();
#ifndef KMEM
# ifdef _PATH_KMEM
# define KMEM _PATH_KMEM
# endif
#endif
#ifndef KERNEL
# ifdef _PATH_UNIX
# define KERNEL _PATH_UNIX
# endif
#endif
#ifndef KMEM
# define KMEM "/dev/kmem"
#endif
#ifndef KERNEL
# define KERNEL "/vmunix"
#endif
int kmemcpy(buf, pos, n)
char *buf;
off_t pos;
int n;
{
static int kfd = -1;
if (kfd == -1)
kfd = open(KMEM, O_RDONLY);
if (lseek(kfd, pos, SEEK_SET) == -1)
{
perror("lseek");
return -1;
}
if (read(kfd, buf, n) == -1)
{
perror("read");
return -1;
}
return n;
}
struct nlist names[3] = {
{ "_proc" },
{ "_nproc" },
{ NULL }
};
#if BSD < 199103
struct proc *getproc()
{
struct proc *p;
pid_t pid = getpid();
int siz, n;
n = nlist(KERNEL, names);
if (n != 0)
{
fprintf(stderr, "nlist(%#x) == %d\n", names, n);
return NULL;
}
if (kmemcpy((char *)&nproc, (off_t)names[1].n_value,
sizeof(nproc)) == -1)
{
fprintf(stderr, "read nproc (%#x)\n", names[1].n_value);
return NULL;
}
siz = nproc * sizeof(struct proc);
if (kmemcpy((char *)&p, (off_t)names[0].n_value, sizeof(p)) == -1)
{
fprintf(stderr, "read(%#x,%#x,%d) proc\n",
names[0].n_value, &p, sizeof(p));
return NULL;
}
proc = (struct proc *)malloc(siz);
if (kmemcpy((char *)proc, (off_t)p, siz) == -1)
{
fprintf(stderr, "read(%#x,%#x,%d) proc\n",
p, proc, siz);
return NULL;
}
p = proc;
for (n = nproc; n; n--, p++)
if (p->p_pid == pid)
break;
if (!n)
return NULL;
return p;
}
struct tcpcb *find_tcp(fd, ti)
int fd;
struct tcpiphdr *ti;
{
struct tcpcb *t;
struct inpcb *i;
struct socket *s;
struct user *up;
struct proc *p;
struct file *f, **o;
if (!(p = getproc()))
return NULL;
up = (struct user *)malloc(sizeof(*up));
if (kmemcpy((char *)up, (off_t)p->p_uarea, sizeof(*up)) == -1)
{
fprintf(stderr, "read(%#x,%#x) failed\n", p, p->p_uarea);
return NULL;
}
o = (struct file **)calloc(1, sizeof(*o) * (up->u_lastfile + 1));
if (kmemcpy((char *)o, (off_t)up->u_ofile,
(up->u_lastfile + 1) * sizeof(*o)) == -1)
{
fprintf(stderr, "read(%#x,%#x,%d) - u_ofile - failed\n",
up->u_ofile_arr, o, sizeof(*o));
return NULL;
}
f = (struct file *)calloc(1, sizeof(*f));
if (kmemcpy((char *)f, (off_t)o[fd], sizeof(*f)) == -1)
{
fprintf(stderr, "read(%#x,%#x,%d) - o[fd] - failed\n",
up->u_ofile_arr[fd], f, sizeof(*f));
return NULL;
}
s = (struct socket *)calloc(1, sizeof(*s));
if (kmemcpy((char *)s, (off_t)f->f_data, sizeof(*s)) == -1)
{
fprintf(stderr, "read(%#x,%#x,%d) - f_data - failed\n",
o[fd], s, sizeof(*s));
return NULL;
}
i = (struct inpcb *)calloc(1, sizeof(*i));
if (kmemcpy((char *)i, (off_t)s->so_pcb, sizeof(*i)) == -1)
{
fprintf(stderr, "kvm_read(%#x,%#x,%d) - so_pcb - failed\n",
s->so_pcb, i, sizeof(*i));
return NULL;
}
t = (struct tcpcb *)calloc(1, sizeof(*t));
if (kmemcpy((char *)t, (off_t)i->inp_ppcb, sizeof(*t)) == -1)
{
fprintf(stderr, "read(%#x,%#x,%d) - inp_ppcb - failed\n",
i->inp_ppcb, t, sizeof(*t));
return NULL;
}
return (struct tcpcb *)i->inp_ppcb;
}
#else
struct kinfo_proc *getproc()
{
static struct kinfo_proc kp;
pid_t pid = getpid();
int n, mib[4];
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = pid;
n = 1;
if (sysctl(mib, 4, &kp, &n, NULL, 0) == -1)
{
perror("sysctl");
return NULL;
}
return &kp;
}
struct tcpcb *find_tcp(tfd, ti)
int tfd;
struct tcpiphdr *ti;
{
struct tcpcb *t;
struct inpcb *i;
struct socket *s;
struct filedesc *fd;
struct kinfo_proc *p;
struct file *f, **o;
if (!(p = getproc()))
return NULL;
fd = (struct filedesc *)malloc(sizeof(*fd));
if (kmemcpy((char *)fd, (void *)p->kp_proc.p_fd, sizeof(*fd)) == -1)
{
fprintf(stderr, "read(%#lx,%#lx) failed\n",
(u_long)p, (u_long)p->kp_proc.p_fd);
return NULL;
}
o = (struct file **)calloc(1, sizeof(*o) * (fd->fd_lastfile + 1));
if (kmemcpy((char *)o, (void *)fd->fd_ofiles,
(fd->fd_lastfile + 1) * sizeof(*o)) == -1)
{
fprintf(stderr, "read(%#lx,%#lx,%d) - u_ofile - failed\n",
(u_long)fd->fd_ofiles, (u_long)o, sizeof(*o));
return NULL;
}
f = (struct file *)calloc(1, sizeof(*f));
if (kmemcpy((char *)f, (void *)o[tfd], sizeof(*f)) == -1)
{
fprintf(stderr, "read(%#lx,%#lx,%d) - o[tfd] - failed\n",
(u_long)o[tfd], (u_long)f, sizeof(*f));
return NULL;
}
s = (struct socket *)calloc(1, sizeof(*s));
if (kmemcpy((char *)s, (void *)f->f_data, sizeof(*s)) == -1)
{
fprintf(stderr, "read(%#lx,%#lx,%d) - f_data - failed\n",
(u_long)f->f_data, (u_long)s, sizeof(*s));
return NULL;
}
i = (struct inpcb *)calloc(1, sizeof(*i));
if (kmemcpy((char *)i, (void *)s->so_pcb, sizeof(*i)) == -1)
{
fprintf(stderr, "kvm_read(%#lx,%#lx,%d) - so_pcb - failed\n",
(u_long)s->so_pcb, (u_long)i, sizeof(*i));
return NULL;
}
t = (struct tcpcb *)calloc(1, sizeof(*t));
if (kmemcpy((char *)t, (void *)i->inp_ppcb, sizeof(*t)) == -1)
{
fprintf(stderr, "read(%#lx,%#lx,%d) - inp_ppcb - failed\n",
(u_long)i->inp_ppcb, (u_long)t, sizeof(*t));
return NULL;
}
return (struct tcpcb *)i->inp_ppcb;
}
#endif /* BSD < 199301 */
int do_socket(dev, mtu, ti, gwip, flags)
char *dev;
int mtu;
struct tcpiphdr *ti;
struct in_addr gwip;
int flags;
{
struct sockaddr_in rsin, lsin;
struct tcpcb *t, tcb;
int fd, nfd, len;
printf("Dest. Port: %d\n", ti->ti_dport);
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1)
{
perror("socket");
return -1;
}
if (fcntl(fd, F_SETFL, FNDELAY) == -1)
{
perror("fcntl");
return -1;
}
bzero((char *)&lsin, sizeof(lsin));
lsin.sin_family = AF_INET;
bcopy((char *)&ti->ti_src, (char *)&lsin.sin_addr,
sizeof(struct in_addr));
if (bind(fd, (struct sockaddr *)&lsin, sizeof(lsin)) == -1)
{
perror("bind");
return -1;
}
len = sizeof(lsin);
(void) getsockname(fd, (struct sockaddr *)&lsin, &len);
ti->ti_sport = lsin.sin_port;
printf("sport %d\n", ntohs(lsin.sin_port));
nfd = initdevice(dev, ntohs(lsin.sin_port));
if (!(t = find_tcp(fd, ti)))
return -1;
bzero((char *)&rsin, sizeof(rsin));
rsin.sin_family = AF_INET;
bcopy((char *)&ti->ti_dst, (char *)&rsin.sin_addr,
sizeof(struct in_addr));
rsin.sin_port = ti->ti_dport;
if (connect(fd, (struct sockaddr *)&rsin, sizeof(rsin)) == -1 &&
errno != EINPROGRESS)
{
perror("connect");
return -1;
}
kmemcpy((char*)&tcb, (void *)t, sizeof(tcb));
ti->ti_win = tcb.rcv_adv;
ti->ti_seq = tcb.snd_nxt - 1;
ti->ti_ack = tcb.rcv_nxt;
if (send_tcp(nfd, mtu, ti, gwip, TH_SYN) == -1)
return -1;
(void)write(fd, "Hello World\n", 12);
sleep(2);
close(fd);
return 0;
}

View File

@ -0,0 +1,38 @@
/* @(#)tcpip.h 1.7 88/08/19 SMI; from UCB 7.1 6/5/85 */
/*
* Copyright (c) 1982, 1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
/*
* Tcp+ip header, after ip options removed.
*/
#ifndef _netinet_tcpip_h
#define _netinet_tcpip_h
struct tcpiphdr {
struct ipovly ti_i; /* overlaid ip structure */
tcphdr_t ti_t; /* tcp header */
};
#define ti_next ti_i.ih_next
#define ti_prev ti_i.ih_prev
#define ti_x1 ti_i.ih_x1
#define ti_pr ti_i.ih_pr
#define ti_len ti_i.ih_len
#define ti_src ti_i.ih_src
#define ti_dst ti_i.ih_dst
#define ti_sport ti_t.th_sport
#define ti_dport ti_t.th_dport
#define ti_seq ti_t.th_seq
#define ti_ack ti_t.th_ack
#define ti_x2 ti_t.th_x2
#define ti_off ti_t.th_off
#define ti_flags ti_t.th_flags
#define ti_win ti_t.th_win
#define ti_sum ti_t.th_sum
#define ti_urp ti_t.th_urp
#endif /*!_netinet_tcpip_h*/

199
contrib/ipfilter/ipt.c Normal file
View File

@ -0,0 +1,199 @@
/*
* (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.
*/
#include <stdio.h>
#include <assert.h>
#include <string.h>
#if !defined(__SVR4) && !defined(__svr4__)
#include <strings.h>
#else
#include <sys/byteorder.h>
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip_var.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>
#include <netinet/tcpip.h>
#include <net/if.h>
#include "ip_fil.h"
#include <netdb.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <resolv.h>
#include "ipf.h"
#include "ipt.h"
#include <ctype.h>
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)ipt.c 1.19 6/3/96 (C) 1993-1996 Darren Reed";
static char rcsid[] = "$Id: ipt.c,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $";
#endif
extern int fr_check();
extern char *optarg;
extern struct frentry *ipfilter[2][2];
extern struct ipread snoop, etherf, tcpd, pcap, iptext, iphex;
extern void debug(), verbose();
struct frentry *ft_in = NULL, *ft_out = NULL;
int opts = 0;
int main(argc,argv)
int argc;
char *argv[];
{
struct ipread *r = &iptext;
struct frentry *f;
struct ip *ip;
u_long buf[64];
char c;
char *rules = NULL, *datain = NULL, *iface = NULL;
int fd, i, dir = 0;
while ((c = getopt(argc, argv, "bdEHi:I:Pr:STvX")) != -1)
switch (c)
{
case 'b' :
opts |= OPT_BRIEF;
break;
case 'd' :
opts |= OPT_DEBUG;
break;
case 'i' :
datain = optarg;
break;
case 'I' :
iface = optarg;
break;
case 'r' :
rules = optarg;
break;
case 'v' :
opts |= OPT_VERBOSE;
break;
case 'E' :
r = &etherf;
break;
case 'H' :
r = &iphex;
break;
case 'P' :
r = &pcap;
break;
case 'S' :
r = &snoop;
break;
case 'T' :
r = &tcpd;
break;
case 'X' :
r = &iptext;
break;
}
if (!rules) {
(void)fprintf(stderr,"no rule file present\n");
exit(-1);
}
initparse();
if (rules) {
struct frentry *fr;
char line[513], *s;
FILE *fp;
if (!strcmp(rules, "-"))
fp = stdin;
else if (!(fp = fopen(rules, "r"))) {
(void)fprintf(stderr, "couldn't open %s\n", rules);
exit(-1);
}
if (!(opts & OPT_BRIEF))
(void)printf("opening rule file \"%s\"\n", rules);
while (fgets(line, sizeof(line)-1, fp)) {
/*
* treat both CR and LF as EOL
*/
if ((s = index(line, '\n')))
*s = '\0';
if ((s = index(line, '\r')))
*s = '\0';
/*
* # is comment marker, everything after is a ignored
*/
if ((s = index(line, '#')))
*s = '\0';
if (!*line)
continue;
if (!(fr = parse(line)))
continue;
f = (struct frentry *)malloc(sizeof(*f));
if (fr->fr_flags & FR_INQUE) {
if (!ft_in)
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 = ipfilter[1][0] = f;
else
ft_out->fr_next = f, ft_out = f;
}
bcopy((char *)fr, (char *)f, sizeof(*fr));
}
(void)fclose(fp);
}
if (datain)
fd = (*r->r_open)(datain);
else
fd = (*r->r_open)("-");
if (fd < 0)
exit(-1);
ip = (struct ip *)buf;
while ((i = (*r->r_readip)(buf, sizeof(buf), &iface, &dir)) > 0) {
ip->ip_off = ntohs(ip->ip_off);
ip->ip_len = ntohs(ip->ip_len);
switch (fr_check(ip, ip->ip_hl << 2, iface, dir))
{
case -1 :
(void)printf("block");
break;
case 0 :
(void)printf("pass");
break;
case 1 :
(void)printf("nomatch");
break;
}
if (!(opts & OPT_BRIEF)) {
putchar(' ');
printpacket(buf);
printf("--------------");
}
putchar('\n');
dir = 0;
}
(*r->r_close)();
return 0;
}

16
contrib/ipfilter/ipt.h Normal file
View File

@ -0,0 +1,16 @@
/*
* (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.
* $Id: ipt.h,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $
*/
#include <fcntl.h>
struct ipread {
int (*r_open)();
int (*r_close)();
int (*r_readip)();
};

68
contrib/ipfilter/kmem.c Normal file
View File

@ -0,0 +1,68 @@
/*
* (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.
*/
/*
* kmemcpy() - copies n bytes from kernel memory into user buffer.
* returns 0 on success, -1 on error.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/file.h>
#define KMEM "/dev/kmem"
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)kmem.c 1.4 1/12/96 (C) 1992 Darren Reed";
static char rcsid[] = "$Id: kmem.c,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $";
#endif
static int kmemfd = -1;
int openkmem()
{
if ((kmemfd = open(KMEM,O_RDONLY)) == -1)
{
perror("kmeminit:open");
return -1;
}
return kmemfd;
}
int kmemcpy(buf, pos, n)
register char *buf;
long pos;
register int n;
{
register int r;
if (!n)
return 0;
if (kmemfd == -1)
if (openkmem() == -1)
return -1;
if (lseek(kmemfd, pos, 0) == -1)
{
perror("kmemcpy:lseek");
return -1;
}
while ((r = read(kmemfd, buf, n)) < n)
if (r <= 0)
{
perror("kmemcpy:read");
return -1;
}
else
{
buf += r;
n -= r;
}
return 0;
}

12
contrib/ipfilter/kmem.h Normal file
View File

@ -0,0 +1,12 @@
/*
* (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.
* $Id: kmem.h,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $
*/
extern int openkmem();
extern int kmemcpy();

19
contrib/ipfilter/linux.h Normal file
View File

@ -0,0 +1,19 @@
/*
* (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. The author accepts no
* responsibility and is not changed in any way.
*
* I hate legaleese, don't you ?
* $Id: linux.h,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $
*/
#include <linux/config.h>
#ifdef MODULE
#include <linux/module.h>
#include <linux/version.h>
#endif /* MODULE */
#include "ip_compat.h"

View File

@ -0,0 +1,21 @@
#
# (C)opyright 1993, 1994, 1995 by Darren Reed.
#
# This code may be freely distributed as long as it retains this notice
# and is not changed in any way. The author accepts no responsibility
# for the use of this software. I hate legaleese, don't you ?
all:
install:
$(INSTALL) -m 0644 -c -o root -g bin ipf.1 $(MANDIR)/man1
$(INSTALL) -m 0644 -c -o root -g bin ipftest.1 $(MANDIR)/man1
$(INSTALL) -m 0644 -c -o root -g bin ipnat.1 $(MANDIR)/man1
$(INSTALL) -m 0644 -c -o root -g bin ipf.4 $(MANDIR)/man4
$(INSTALL) -m 0644 -c -o root -g bin ipl.4 $(MANDIR)/man4
$(INSTALL) -m 0644 -c -o root -g bin ipnat.4 $(MANDIR)/man4
$(INSTALL) -m 0644 -c -o root -g bin ipf.5 $(MANDIR)/man5
$(INSTALL) -m 0644 -c -o root -g bin ipnat.5 $(MANDIR)/man5
$(INSTALL) -m 0644 -c -o root -g bin ipmon.8 $(MANDIR)/man8
$(INSTALL) -m 0644 -c -o root -g bin ipfstat.8 $(MANDIR)/man8
@echo "Remember to rebuild the whatis database."

109
contrib/ipfilter/man/ipf.1 Normal file
View File

@ -0,0 +1,109 @@
.TH IPF 1
.SH NAME
ipf \- alters packet filtering lists for IP packet input and ouput
.SH SYNOPSIS
.B ipf
[
.B \-AdDEInorsUvyzZ
] [
.B \-l
<block|pass|nomatch>
] [
.B \-F
<i|o|a>
]
.B \-f
<\fIfilename\fP>
[
.B \-f
<\fIfilename\fP>
[...]]
.SH DESCRIPTION
.PP
\fBipf\fP opens the filenames listed (treating "\-" as stdin) and parses the
file for a set of rules which are to be added or removed from the packet
filter rule set.
.PP
Each rule processed by \fBipf\fP
is added to the kernel's internal lists if there are no parsing problems.
Rules are added to the end of the internal lists, matching the order in
which they appear when given to \fBipf\fP.
.SH OPTIONS
.TP
.B \-A
Set the list to make changes to the active list (default).
.TP
.B \-d
Turn debug mode on. Causes a hexdump of filter rules to be generated as
it processes each one.
.TP
.B \-D
Disable the filter (if enabled). Not effective for loadable kernel versions.
.TP
.B \-E
Enable the filter (if disabled). Not effective for loadable kernel versions.
.TP
.BR \-F \0<param>
This option specifies which filter list to flush. The parameter should
either be "i" (input), "o" (output) or "a" (remove all filter rules).
Either a single letter or an entire word starting with the appropriate
letter maybe used. This option maybe before, or after, any other with
the order on the command line being that used to execute options.
.TP
.BR \-f \0<filename>
This option specifies which files
\fBipf\fP should use to get input from for modifying the packet filter rule
lists.
.TP
.B \-I
Set the list to make changes to the inactive list.
.TP
.B \-l \0<param>
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.
.TP
.B \-n
This flag (no-change) prevents \fBipf\fP from actually making any ioctl
calls or doing anything which would alter the currently running kernel.
.TP
.B \-o
Force rules by default to be added/deleted to/from the output list, rather
than the (default) input list.
.TP
.B \-r
Remove matching filter rules rather than add them to the internal lists
.TP
.B \-s
Swap the active filter list in use to be the "other" one.
.TP
.B \-U
(SOLARIS 2 ONLY) Block packets travelling along the data stream which aren't
recognised as IP packets. They will be printed out on the console.
.TP
.B \-v
Turn verbose mode on. Displays information relating to rule processing.
.TP
.B \-y
(SOLARIS 2 ONLY) Manually resync the in-kernel interface list maintained
by IP Filter with the current interface status list.
.TP
.B \-z
For each rule in the input file, reset the statistics for it to zero and
display the statistics prior to them being zero'd.
.TP
.B \-Z
Zero global statistics held in the kernel for filtering only (this doesn't
affect fragment or state statistics).
.DT
.SH SEE ALSO
ipfstat(1), ipftest(1), ipf(5)
.SH DIAGNOSTICS
.PP
Needs to be run as root for the packet filtering lists to actually
be affected inside the kernel.
.SH BUGS
.PP
If you find any, please send email to me at darrenr@cyber.com.au

184
contrib/ipfilter/man/ipf.4 Normal file
View File

@ -0,0 +1,184 @@
.TH IPF 4
.SH NAME
ipf \- packet filtering kernel interface
.SH SYNOPSIS
#include <sys/ip_fil.h>
.SH IOCTLS
.PP
To add and delete rules to the filter list, three 'basic' ioctls are provided
for use. The ioctl's are called as:
.LP
.nf
ioctl(fd, SIOCADDFR, struct frentry *)
ioctl(fd, SIOCDELFR, struct frentry *)
ioctl(fd, SIOCIPFFL, int *)
.fi
.PP
However, the full complement is as follows:
.LP
.nf
ioctl(fd, SIOCADAFR, struct frentry *) (same as SUICADDFR)
ioctl(fd, SIOCRMAFR, struct frentry *) (same as SUICDELFR)
ioctl(fd, SIOCADIFR, struct frentry *)
ioctl(fd, SIOCRMIFR, struct frentry *)
ioctl(fd, SIOCINAFR, struct frentry *)
ioctl(fd, SIOCINIFR, struct frentry *)
ioctl(fd, SIOCIPFFL, int *)
.fi
.PP
The variations, SIOCADAFR vs. SIOCADIFR, allow operation on the two lists,
active and inactive, respectively. All of these ioctl's are implemented
as being routing ioctls and thus the same rules for the various routing
ioctls and the file descriptor are employed, mainly being that the fd must
be that of the device associated with the module (i.e., /dev/ipl).
.LP
.PP
The three groups of ioctls above perform adding rules to the end of the
list (SIOCAD*), deletion of rules from any place in the list (SIOCRM*)
and insertion of a rule into the list (SIOCIN*). The rule place into
which it is inserted is stored in the "fr_hits" field, below.
.LP
.nf
typedef struct frentry {
struct frentry *fr_next;
struct ifnet *fr_ifa;
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.
*/
struct fr_ip fr_ip;
struct fr_ip fr_mip;
u_char fr_tcpfm; /* tcp flags mask */
u_char fr_tcpf; /* tcp flags */
u_short fr_icmpm; /* data for ICMP packets (mask) */
u_short fr_icmp;
u_char fr_scmp; /* data for port comparisons */
u_char fr_dcmp;
u_short fr_dport;
u_short fr_sport;
u_short fr_stop; /* top port for <> and >< */
u_short fr_dtop; /* top port for <> and >< */
u_long fr_flags; /* per-rule flags && options (see below) */
int (*fr_func)(); /* call this function */
char fr_icode; /* return ICMP code */
char fr_ifname[IFNAMSIZ];
struct frdest fr_tif; /* "to" interface */
struct frdest fr_dif; /* duplicate packet interfaces */
} frentry_t;
.fi
.PP
When adding a new rule, all unused fields (in the filter rule) should be
initialised to be zero. To insert a rule, at a particular position in the
filter list, the number of the rule which it is to be inserted before must
be put in the "fr_hits" field (the first rule is number 0).
.LP
.PP
Flags which are recognised in fr_pass:
.nf
FR_BLOCK 0x00001 /* do not allow packet to pass */
FR_PASS 0x00002 /* allow packet to pass */
FR_OUTQUE 0x00004 /* outgoing packets */
FR_INQUE 0x00008 /* ingoing packets */
FR_LOG 0x00010 /* Log */
FR_LOGP 0x00011 /* Log-pass */
FR_LOGB 0x00012 /* Log-fail */
FR_LOGBODY 0x00020 /* log the body of packets too */
FR_LOGFIRST 0x00040 /* log only the first packet to match */
FR_RETRST 0x00080 /* return a TCP RST packet if blocked */
FR_RETICMP 0x00100 /* return an ICMP packet if blocked */
FR_NOMATCH 0x00200 /* no match occured */
FR_ACCOUNT 0x00400 /* count packet bytes */
FR_KEEPFRAG 0x00800
FR_KEEPSTATE 0x01000 /* keep packet flow state information */
FR_INACTIVE 0x02000
FR_QUICK 0x04000 /* quick-match and return */
FR_FASTROUTE 0x08000
FR_CALLFUNC 0x10000
FR_CALLNOW 0x20000
FR_DUP 0x40000 /* duplicate the packet (not Solaris2)
.fi
.PP
Values for fr_scomp and fr_dcomp (source and destination port value
comparisons) :
.LP
.nf
FR_NONE 0
FR_EQUAL 1
FR_NEQUAL 2
FR_LESST 3
FR_GREATERT 4
FR_LESSTE 5
FR_GREATERTE 6
FR_OUTRANGE 7
FR_INRANGE 8
.fi
.PP
The third ioctl, SIOCIPFFL, flushes either the input filter list, the
output filter list or both and it returns the number of filters removed
from the list(s). The values which it will take and recognise are FR_INQUE
and FR_OUTQUE (see above).
\fBGeneral Logging Flags\fP
There are two flags which can be set to log packets independantly of the
rules used. These allow for packets which are either passed or blocked
to be logged. To set (and clear)/get these flags, two ioctls are
provided:
.IP SIOCSETFF 16
Takes an unsigned integer as the parameter. The flags are then set to
those provided (clearing/setting all in one).
.nf
FF_LOGPASS 1
FF_LOGBLOCK 2
.fi
.IP SIOCGETFF 16
Takes a pointer to an unsigned integer as the parameter. A copy of the
flags currently in used is copied to user space.
.LP
\fBFilter statistics\fP
Statistics on the various operations performed by this package on packets
is kept inside the kernel. These statistics apply to packets traversing
through the kernel. To retrieve this structure, use this ioctl:
.nf
ioctl(fd, SIOCGETFS, struct friostat *)
struct friostat {
struct filterstats f_st[2];
struct frentry *f_fin;
struct frentry *f_fout;
};
struct filterstats {
u_long fr_pass; /* packets allowed */
u_long fr_block; /* packets denied */
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_cfr; /* add new fragment state but complete pkt */
u_long fr_bads; /* bad attempts to allocate packet state */
u_long fr_ads; /* new packet state kept */
u_long fr_chit; /* cached hit */
#if SOLARIS
u_long fr_bad; /* bad IP packets to the filter */
u_long fr_notip; /* packets passed through no on ip queue */
u_long fr_drop; /* packets dropped - no info for them! */
#endif
};
.fi
.SH SEE ALSO
ipfstat(1), ipf(1), ipf(5)

433
contrib/ipfilter/man/ipf.5 Normal file
View File

@ -0,0 +1,433 @@
.TH IPF 5
.SH NAME
ipf \- IP packet filter rule syntax
.SH DESCRIPTION
.PP
A rule file for \fBipf\fP may have any name or even be stdin. As
\fBipfstat\fP produces parseable rules as output when displaying the internal
kernel filter lists, it is quite plausible to use its output to feed back
into \fBipf\fP. Thus, to remove all filters on input packets, the following
could be done:
.nf
\fC# ipfstat \-i | ipf \-rf \-\fP
.fi
.SH GRAMMAR
.PP
The format used by \fBipf\fP for construction of filtering rules can be
described using the following grammar in BNF:
\fC
.nf
filter-rule = [ insert ] action in-out [ options ] [ match ] [ keep ]
insert = "@" decnumber .
action = block | "pass" | log | "count" | call .
in-out = "in" | "out" .
options = [ log ] [ "quick" ] [ "on" interface-name [ dup ] [ froute ] ] .
match = [ tos ] [ ttl ] [ proto ] [ ip ] .
keep = "keep state" | "keep frags" .
block = "block" [ "return-icmp"[return-code] | "return-rst" ] .
log = "log" [ "body" ] [ "first" ] [ "or-block" ] .
call = "call" [ "now" ] function-name .
dup = "dup-to" interface-name[":"ipaddr] .
froute = "fastroute" | "to" interface-name .
tos = "tos" decnumber | "tos" hexnumber .
ttl = "ttl" decnumber .
proto = "proto" protocol .
ip = srcdst [ flags ] [ with withopt ] [ icmp ] [ keep ] .
protocol = "tcp/udp" | "udp" | "tcp" | "icmp" | decnumber .
srcdst = "all" | fromto .
fromto = "from" object "to" object .
object = addr [ port-comp | port-range ] .
addr = "any" | nummask | host-name [ "mask" ipaddr | "mask" hexnumber ] .
port-comp = "port" compare port-num .
port-range = "port" port-num range port-num .
flags = "flags" flag { flag } [ "/" flag { flag } ] .
with = "with" | "and" .
icmp = "icmp-type" icmp-type [ "code" decnumber ] .
return-code = "("icmp-code")" .
nummask = host-name [ "/" decnumber ] .
host-name = ipaddr | hostname | "any" .
ipaddr = host-num "." host-num "." host-num "." host-num .
host-num = digit [ digit [ digit ] ] .
port-num = service-name | decnumber .
withopt = [ "not" | "no" ] opttype [ withopt ] .
opttype = "ipopts" | "short" | "frag" | "opt" ipopts .
optname = ipopts [ "," optname ] .
ipopts = optlist | "sec-class" [ secname ] .
secname = seclvl [ "," secname ] .
seclvl = "unclass" | "confid" | "reserv-1" | "reserv-2" | "reserv-3" |
"reserv-4" | "secret" | "topsecret" .
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" .
optlist = "nop" | "rr" | "zsu" | "mtup" | "mtur" | "encode" | "ts" | "tr" |
"sec" | "lsrr" | "e-sec" | "cipso" | "satid" | "ssrr" | "addext" |
"visa" | "imitd" | "eip" | "finn" .
hexnumber = "0" "x" hexstring .
hexstring = hexdigit [ hexstring ] .
decnumber = digit [ decnumber ] .
compare = "=" | "!=" | "<" | ">" | "<=" | ">=" | "eq" | "ne" | "lt" | "gt" |
"le" | "ge" .
range = "<>" | "><" .
hexdigit = digit | "a" | "b" | "c" | "d" | "e" | "f" .
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" .
flag = "F" | "S" | "R" | "P" | "A" | "U" .
.fi
.PP
This syntax is somewhat simplified for readability, some combinations
that match this grammar are disallowed by the software because they do
not make sense (such as tcp \fBflags\fP for non-TCP packets).
.SH FILTER RULES
.PP
The "briefest" valid rules are (currently) no-ops and are of the form:
.nf
block in
pass in
log in
count in
.fi
.PP
These are supposed to be the same as, but currently differ from:
.\" XXX How, why do they differ??
.nf
block in all
pass in from any to any
log in all
count in all
.fi
.PP
Filter rules are checked in order, with the last matching rule
determining the fate of the packet (but see the \fBquick\fP option,
below).
.PP
Filters are installed by default at the end of the kernel's filter
lists, prepending the rule with \fB@n\fP will cause it to be inserted
as the n'th entry in the current list. This is especially useful when
modifying and testing active filter rulesets. See ipf(1) for more
information.
.SH ACTIONS
.PP
The action indicates what to do with the packet if it matches the rest
of the filter rule. Each rule MUST have an action. The following
actions are recognised:
.TP
.B block
indicates that the packet should be flagged to be dropped. In response
to blocking a packet, the filter may be instructed to send a reply
packet, either an ICMP packet (\fBreturn-icmp\fP) or a TCP "reset"
(\fBreturn-rst\fP). An ICMP packet may be generated in response to
any IP packet, and its type may optionally be specified, but a TCP
reset may only be used with a rule which is being applied to TCP
packets.
.TP
.B pass
will flag the packet to be let through the filter.
.TP
.B log
causes the packet to be logged (as described in the LOGGING section
below) and has no effect on whether the packet will be allowed through
the filter.
.TP
.B count
causes the packet to be included in the accounting statistics kept by
the filter, and has no effect on whether the packet will be allowed through
the filter. These statistics are viewable with ipfstat(8).
.TP
.B call
this action is used to invoke the named function in the kernel, which
must conform to a specific calling interface. Customised actions and
semantics can thus be implemented to supplement those available. This
feature is for use by knowledgeable hackers, and is not currently
documented.
.PP
The next word must be either \fBin\fP or \fBout\fP. Each packet
moving through the kernel is either inbound (just been received on an
interface, and moving towards the kernel's protocol processing) or
outbound (transmitted or forwarded by the stack, and on its way to an
interface). There is a requirement that each filter rule explicitly
state which side of the I/O it is to be used on.
.SH OPTIONS
.PP
The list of options is brief, and all are indeed optional. Where
options are used, they must be present in the order shown here. These
are the currently supported options:
.TP
.B log
indicates that, should this be the last matching rule, the packet
header will be written to the \fBipl\fP log (as described in the
LOGGING section below).
.TP
.B quick
allows "short-cut" rules in order to speed up the filter or override
later rules. If a packet matches a filter rule which is marked as
\fBquick\fP, this rule will be the last rule checked, allowing a
"short-circuit" path to avoid processing later rules for this
packet. The current status of the packet (after any effects of the
current rule) will determine whether it is passed or blocked.
.IP
If this option is missing, the rule is taken to be a "fall-through"
rule, meaning that the result of the match (block/pass) is saved and
that processing will continue to see if there are any more matches.
.TP
.B on
allows an interface name to be incorporated into the matching
procedure. Interface names are as printed by "netstat \-i". If this
option is used, the rule will only match if the packet is going
through that interface in the specified direction (in/out). If this
option is absent, the rule is taken to be applied to a packet
regardless of the interface it is present on (i.e. on all interfaces).
Filter rulesets are common to all interfaces, rather than having a
filter list for each interface.
.IP
This option is especially useful for simple IP-spoofing protection:
packets should only be allowed to pass inbound on the interface from
which the specified source address would be expected, others may be
logged and/or dropped.
.TP
.B dup-to
causes the packet to be copied, and the duplicate packet to be sent outbound on the specified interface, optionally with the destination IP address changed to that specified. This is useful for off-host logging, using a network sniffer.
.TP
.B to
causes the packet to be moved to the outbound queue on the
specified interface. This can be used to circumvent kernel routing
decisions, and even to bypass the rest of the kernel processing of the
packet (if applied to an inbound rule). It is thus possible to
construct a firewall that behaves transparently, like a filtering hub
or switch, rather than a router. The \fBfastroute\fP keyword is a
synonym for this option.
.SH MATCHING PARAMETERS
.PP
The keywords described in this section are used to describe attributes
of the packet to be used when determining whether rules match or don't
match. The following general-purpose attributes are provided for
matching, and must be used in this order:
.TP
.B tos
packets with different Type-Of-Service values can be filtered.
Individual service levels or combinations can be filtered upon. The
value for the TOS mask can either be represented as a hex number or a
decimal integer value.
.\" XXX TOS mask?? not in grammar!
.TP
.B ttl
packets may also be selected by their Time-To-Live value. The value given in
the filter rule must exactly match that in the packet for a match to occur.
This value can only be given as a decimal integer value.
.TP
.B proto
allows a specific protocol to be matched against. All protocol names
found in \fB/etc/protocols\fP are recognised and may be used.
However, the protocol may also be given as a DECIMAL number, allowing
for rules to match your own protocols, or new ones which would
out-date any attempted listing.
.IP
The special protocol keyword \fBtcp/udp\fP may be used to match either
a TCP or a UDP packet, and has been added as a convenience to save
duplication of otherwise-identical rules.
.\" XXX grammar should reflect this (/etc/protocols)
.PP
The \fBfrom\fP and \fBto\fP keywords are used to match against IP
addresses (and optionally port numbers). Rules must specify BOTH
source and destination parameters.
.PP
IP addresses may be specified in one of two ways: as a numerical
address\fB/\fPmask, or as a hostname \fBmask\fP netmask. The hostname
may either be a valid hostname, from either the hosts file or DNS
(depending on your configuration and library) or of the dotted numeric
form. There is no special designation for networks but network names
are recognised. Note that having your filter rules depend on DNS
results can introduce an avenue of attack, and is discouraged.
.PP
There is a special case for the hostname \fBany\fP which is taken to
be 0.0.0.0/0 (see below for mask syntax) and matches all IP addresses.
Only the presence of "any" has an implied mask, in all other
situations, a hostname MUST be accompanied by a mask. It is possible
to give "any" a hostmask, but in the context of this language, it is
non-sensical.
.PP
The numerical format "x\fB/\fPy" indicates that a mask of y
consecutive 1 bits set is generated, starting with the MSB, so a y value
of 16 would give 0xffff0000. The symbolic "x \fBmask\fP y" indicates
that the mask y is in dotted IP notation or a hexadecimal number of
the form 0x12345678. Note that all the bits of the IP address
indicated by the bitmask must match the address on the packet exactly;
there isn't currently a way to invert the sense of the match, or to
match ranges of IP addresses which do not express themselves easily as
bitmasks (anthropomorphization; it's not just for breakfast anymore).
.PP
If a \fBport\fP match is included, for either or both of source and
destination, then it is only applied to
.\" XXX - "may only be" ? how does this apply to other protocols? will it not match, or will it be ignored?
TCP and UDP packets. If there is no \fBproto\fP match parameter,
packets from both protocols are compared. This is equivalent to "proto
tcp/udp". When composing \fBport\fP comparisons, either the service
name or an integer port number may be used. Port comparisons may be
done in a number of forms, with a number of comparison operators, or
port ranges may be specified. See the examples for more information.
.PP
The \fBall\fP keyword is essentially a synonym for "from any to any"
with no other match parameters.
.PP
Following the source and destination matching parameters, the
following additional parameters may be used:
.TP
.B with
is used to match irregular attributes that some packets may have
associated with them. To match the presence of IP options in general,
use \fBwith ipopts\fP. To match packets that are too short to contain
a complete header, use \fBwith short\fP. To match fragmented packets,
use \fBwith frag\fP. For more specific filtering on IP options,
individual options can be listed.
.IP
Before any parameter used after the \fBwith\fP keyword, the word
\fBnot\fP or \fBno\fP may be inserted to cause the filter rule to only
match if the option(s) is not present.
.IP
Multiple consecutive \fBwith\fP clauses are allowed. Alternatively,
the keyword \fBand\fP may be used in place of \fBwith\fP, this is
provided purely to make the rules more readable ("with ... and ...").
When multiple clauses are listed, all those must match to cause a
match of the rule.
.\" XXX describe the options more specifically in a separate section
.TP
.B flags
is only effective for TCP filtering. Each of the letters possible
represents one of the possible flags that can be set in the TCP
header. The association is as follows:
.LP
.nf
F - FIN
S - SYN
R - RST
P - PUSH
A - ACK
U - URG
.fi
.IP
The various flag symbols may be used in combination, so that "SA"
would represent a SYN-ACK combination present in a packet. There is
nothing preventing the specification of combinations, such as "SFR",
that would not normally be generated by law-abiding TCP
implementations. However, to guard against weird aberrations, it is
necessary to state which flags you are filtering against. To allow
this, it is possible to set a mask indicating which TCP flags you wish
to compare (i.e., those you deem significant). This is done by
appending "/<flags>" to the set of TCP flags you wish to match
against, e.g.:
.LP
.nf
... flags S
# becomes "flags S/AUPRFS" and will match
# packets with ONLY the SYN flag set.
... flags SA
# becomes "flags SA/AUPRFS" and will match any
# packet with only the SYN and ACK flags set.
... flags S/SA
# will match any packet with just the SYN flag set
# out of the SYN-ACK pair; the common "establish"
# keyword action. "S/SA" will NOT match a packet
# with BOTH SYN and ACK set, but WILL match "SFP".
.fi
.TP
.B icmp-type
is only effective when used with \fBproto icmp\fP and must NOT be used
in conjuction with \fBflags\fP. There are a number of types, which can be
referred to by an abbreviation recognised by this language, or the numbers
with which they are associated can be used. The most important from
a security point of view is the ICMP redirect.
.SH KEEP HISTORY
.PP
The last parameter which can be set for a filter rule is whether on not to
record historical information for that packet, and what sort to keep. The following information can be kept:
.TP
.B state
keeps information about the flow of a communication session. State can
be kept for TCP, UDP, and ICMP packets.
.TP
.B frags
keeps information on fragmented packets, to be applied to later
fragments.
.PP
allowing packets which match these to flow straight through, rather
than going through the access control list.
.SH LOGGING
.PP
When a packet is logged, with either the \fBlog\fP action or option,
the headers of the packet are written to the \fBipl\fP packet logging
psuedo-device. Immediately following the \fBlog\fP keyword, the
following qualifiers may be used (in order):
.TP
.B body
indicates that the first 128 bytes of the packet contents will be
logged after the headers.
.TP
.B first
??
.TP
.B or-block
indicates that, if for some reason the filter is unable to log the packet (such as the log reader being too slow) then the rule should be interpreted as if the action was \fBblock\fP for this packet.
.PP
See ipl(4) for the format of records written
to this device. The ipmon(8) program can be used to read and format
this log.
.SH EXAMPLES
.PP
The \fBquick\fP option is good for rules such as:
\fC
.nf
block in quick from any to any with ipopts
.fi
.PP
which will match any packet with a non-standard header length (IP
options present) and abort further processing of later rules,
recording a match and also that the packet should be blocked.
.PP
The "fall-through" rule parsing allows for effects such as this:
.LP
.nf
block in from any to any port < 6000
pass in from any to any port >= 6000
block in from any to port > 6003
.fi
.PP
which sets up the range 6000-6003 as being permitted and all others being
denied. Note that the effect of the first rule is overridden by subsequent
rules. Another (easier) way to do the same is:
.LP
.nf
block in from any to any port 6000 <> 6003
pass in from any to any port 5999 >< 6004
.fi
.PP
Note that both the "block" and "pass" are needed here to effect a
result as a failed match on the "block" action does not imply a pass,
only that the rule hasn't taken effect. To then allow ports < 1024, a
rule such as:
.LP
.nf
pass in quick from any to any port < 1024
.fi
.PP
would be needed before the first block.
.SH FILES
/etc/services
.br
/etc/hosts
.SH SEE ALSO
ipf(1), ipftest(1)

View File

@ -0,0 +1,73 @@
.TH ipfstat 8
.SH NAME
ipfstat \- reports on packet filter statistics and filter list
.SH SYNOPSIS
.B ipfstat
[
.B \-hIinov
] [
.B \-d
<device>
]
.SH DESCRIPTION
.PP
\fBipfstat\fP examines /dev/kmem using the symbols \fB_fr_flags\fP,
\fB_frstats\fP, \fB_filterin\fP, and \fB_filterout\fP.
To run and work, it needs to be able to read both /dev/kmem and the
kernel itself. The kernel name defaults to \fB/vmunix\fP.
.PP
The default behaviour of \fBipfstat\fP
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
.TP
.B \-a
Display the accounting filter list and show bytes counted against each rule.
.TP
.BR \-d \0<device>
Use a device other than \fB/dev/ipl\fP for interfacing with the kernel.
.TP
.B \-f
Show fragment state information (statistics) and held state information (in
the kernel) if any is present.
.TP
.B \-h
Show per-rule the number of times each one scores a "hit". For use in
combination with \fB\-i\fP.
.TP
.B \-i
Display the filter list used for the input side of the kernel IP processing.
.TP
.B \-I
Swap between retrieving "inactive"/"active" filter list details. For use
in combination with \fB\-i\fP.
.TP
.B \-n
Show the "rule number" for each rule as it is printed.
.TP
.B \-o
Display the filter list used for the output side of the kernel IP processing.
.TP
.B \-s
Show packet/flow state information (statistics) and held state information (in
the kernel) if any is present.
.TP
.B \-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
out of the kernel. This is the default operation when no command line
parameters are present.
.PP
When supplied with either \fB\-i\fP or \fB\-o\fP, it will retrieve and display
the appropriate list of filter rules currently installed and in use by the
kernel.
.SH FILES
/dev/kmem
.br
/vmunix
.SH SEE ALSO
ipf(1), ipfstat(1)
.SH BUGS
none known.

View File

@ -0,0 +1,127 @@
.TH ipftest 8
.SH NAME
ipftest \- test packet filter rules with arbitary input.
.SH SYNOPSIS
.B ipftest
[
.B \-vbdPSTEHX
] [
.B \-I
interface
]
.B \-r
<filename>
[
.B \-i
<filename>
]
.SH DESCRIPTION
.PP
\fBipftest\fP is provided for the purpose of being able to test a set of
filter rules without having to put them in place, in operation and proceed
to test their effectiveness. The hope is that this minimises disruptions
in providing a secure IP environment.
.PP
\fBipftest\fP will parse any standard ruleset for use with \fBipf\fP
and apply input, returning output as to the result. However, \fBipftest\fP
will return one of three values for packets passed through the filter:
pass, block or nomatch. This is intended to give the operator a better
idea of what is happening with packets passing through their filter
ruleset.
.PP
When used without either of \fB\-S\fP, \fB\-T\fP or \fB\-E\fP,
\fBipftest\fP uses its own text input format to generate "fake" IP packets.
The format used is as follows:
.nf
"in"|"out" "on" if ["tcp"|"udp"|"icmp"]
srchost[,srcport] dsthost[,destport] [FSRPAU]
.fi
.PP
This allows for a packet going "in" or "out" of an interface (if) to be
generated, being one of the three main protocols (optionally), and if
either TCP or UDP, a port parameter is also expected. If TCP is selected,
it is possible to (optionally) supply TCP flags at the end. Some examples
are:
.nf
# a UDP packet coming in on le0
in on le0 udp 10.1.1.1,2210 10.2.1.5,23
# an IP packet coming in on le0 from localhost - hmm :)
in on le0 localhost 10.4.12.1
# a TCP packet going out of le0 with the SYN flag set.
out on le0 tcp 10.4.12.1,2245 10.1.1.1,23 S
.fi
.SH OPTIONS
.TP
.B \-v
Verbose mode. This provides more information about which parts of rule
matching the input packet passes and fails.
.TP
.B \-d
Turn on filter rule debugging. Currently, this only shows you what caused
the rule to not match in the IP header checking (addresses/netmasks, etc).
.TP
.B \-b
Cause the output to be a brief summary (one-word) of the result of passing
the packet through the filter; either "pass", "block" or "nomatch".
This is used in the regression testing.
.TP
.BR \-I \0<interface>
Set the interface name (used in rule matching) to be the name supplied.
This is useful with the \fB\-P, \-S, \-T\fP and \fB\-E\fP options, where it is
not otherwise possible to associate a packet with an interface. Normal
"text packets" can override this setting.
.TP
.B \-P
The input file specified by \fB\-i\fP is a binary file produced using libpcap
(i.e., tcpdump version 3). Packets are read from this file as being input
(for rule purposes). An interface maybe specified using \fB\-I\fP.
.TP
.B \-S
The input file is to be in "snoop" format (see RFC 1761). Packets are read
from this file and used as input from any interface. This is perhaps the
most useful input type, currently.
.TP
.B \-T
The input file is to be text output from tcpdump. The text formats which
are currently supported are those which result from the following tcpdump
option combinations:
.PP
.nf
tcpdump -n
tcpdump -nq
tcpdump -nqt
tcpdump -nqtt
tcpdump -nqte
.fi
.LP
.TP
.B \-H
The input file is to be hex digits, representing the binary makeup of the
packet. No length correction is made, if an incorrect length is put in
the IP header.
.TP
.B \-X
The input file is composed of text descriptions of IP packets.
.TP
.B \-E
The input file is to be text output from etherfind. The text formats which
are currently supported are those which result from the following etherfind
option combinations:
.PP
.nf
etherfind -n
etherfind -n -t
.fi
.LP
.TP
.BR \-i \0<filename>
Specify the filename from which to take input. Default is stdin.
.TP
.BR \-r \0<filename>
Specify the filename from which to read filter rules.
.SH FILES
.SH SEE ALSO
ipf(1), ipf(5), snoop(1m), tcpdump(8), etherfind(8c)
.SH BUGS
Not all of the input formats are sufficiently capable of introducing a
wide enough variety of packets for them to be all useful in testing.

View File

@ -0,0 +1,62 @@
.TH IPL 4
.SH NAME
ipl \- IP packet log device
.SH DESCRIPTION
The \fBipl\fP pseudo device's purpose is to provide an easy way to gather
packet headers of packets you wish to log. If a packet header is to be
logged, the entire header is logged (including any IP options \- TCP/UDP
options are not included when it calculates header size) or not at all.
The packet contents are also logged after the header.
.PP
Prepending every packet header logged is a structure containing information
relevant to the packet following and why it was logged. The structure's
format is as follows:
.LP
.nf
struct ipl_ci {
u_long sec; /* time when the packet was logged */
u_long usec;
u_long plen; /* length of packet data logged */
u_short hlen; /* length of headers logged */
u_short rule; /* rule number (for log ...) or 0 if result = log */
u_long flags:24; /* XXX FIXME do we care about the extra bytes? */
#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606))
u_long filler:8; /* XXX FIXME do we care? */
u_char ifname[IFNAMSIZ];
#else
u_long unit:8;
u_char ifname[4];
#endif
};
.fi
.PP
In the case of the header causing the buffer to finish on a non-32bit
boundary, padding will be `appended' to ensure that the next log entry
is aligned to a 32bit boundary.
.LP
.PP
If the packet contents is more then 128 bytes, then only 128 bytes of the
packet contents is logged. Should the packet contents finish on a non-32bit
boundary, then the last few bytes are not logged to ensure the log entry
is aligned to a 32bit boundary.
\fBipl\fP is a read-only (sequential) character pseudo-device.
The ioctls which are loaded with this device can be found under \fBipf(4)\fP.
The only ioctl which is used for logging and doesn't affect the filter is:
.LP
.nf
ioctl(fd, SIOCIPFFB, int *)
.fi
.PP
This ioctl flushes the log buffer and returns the number of bytes flushed.
.PP
There is currently no support for non-blocking IO with this device, meaning
all read operations should be considered blocking in nature (if there is no
data to read, it will sleep until some is made available).
.SH SEE ALSO
ipf(4)
.SH BUGS
Packet headers are dropped when the internal buffer (static size) fills.
.SH FILES
/dev/ipl0

View File

@ -0,0 +1,56 @@
.TH ipmon 8
.SH NAME
ipmon \- monitors /dev/ipl for logged packets
.SH SYNOPSIS
.B ipmon
[
.B \-sfN
] [
<filename>
]
.SH DESCRIPTION
.LP
\fBipmon\fP opens \fB/dev/ipl\fP for reading and awaits data to be saved from
the packet filter. The binary data read from the device is reprinted in
human readable for, however, IP#'s are not mapped back to hostnames, nor are
ports mapped back to service names. The output goes to standard output by
default or a filename, if given on the command line. Should the \fB\-s\fP
option be used, output is instead sent to \fBsyslogd(8)\fP. Messages sent
via syslog have the day, month and year removed from the message, but the
time (including microseconds), as recorded in the log, is still included.
.SH OPTIONS
.TP
.B \-s
Packet information read in will be sent through syslogd rather than
saved to a file. The following levels are used:
.IP
.B LOG_INFO
\- packets logged using the "log" keyword as the action rather
than pass or block.
.IP
.B LOG_NOTICE
\- packets logged which are also passed
.IP
.B LOG_WARNING
\- packets logged which are also blocked
.IP
.B LOG_ERR
\- packets which have been logged and which can be considered
"short".
.TP
.B \-f
Flush the current packet log buffer. The number of bytes flushed is displayed,
even should the result be zero.
.TP
.B \-N
IP addresses and port numbers will be mapped, where possible, back into
hostnames and service names.
.SH DIAGNOSTICS
\fBipmon\fP expects data that it reads to be consistant with how it should be
saved and will abort if it fails an assertion which detects an anomoly in the
recorded data.
.SH FILES
/dev/ipl
.SH SEE ALSO
ipf(1), ipfstat(1)
.SH BUGS

View File

@ -0,0 +1,45 @@
.TH IPNAT 1
.SH NAME
ipnat \- user interface to the NAT
.SH SYNOPSIS
.B ipnat
[
.B \-lnrsvCF
]
.B \-f <\fIfilename\fP>
.SH DESCRIPTION
.PP
\fBipnat\fP opens the filename given (treating "\-" as stdin) and parses the
file for a set of rules which are to be added or removed from the IP NAT.
.PP
Each rule processed by \fBipnat\fP
is added to the kernels internal lists if there are no parsing problems.
Rules are added to the end of the internal lists, matching the order in
which they appear when given to \fBipnat\fP.
.SH OPTIONS
.TP
.B \-C
delete all entries in the current NAT listing (NAT rules)
.TP
.B \-F
delete all active entries in the current NAT table (currently active
NAT mappings)
.TP
.B \-l
Show the list of current NAT table entry mappings.
.TP
.B \-n
This flag (no-change) prevents \fBipf\fP from actually making any ioctl
calls or doing anything which would alter the currently running kernel.
.TP
.B \-s
Retrieve and display NAT statistics
.TP
.B \-r
Remove matching NAT rules rather than add them to the internal lists
.TP
.B \-v
Turn verbose mode on. Displays information relating to rule processing.
.DT
.SH SEE ALSO
ipfstat(1), ipftest(1), ipf(1), ipnat(5)

View File

@ -0,0 +1,88 @@
.TH IPNAT 4
.SH NAME
ipnat \- Network Address Translation kernel interface
.SH SYNOPSIS
#include <sys/ip_fil.h>
.SH IOCTLS
.PP
To add and delete rules to the NAT list, two 'basic' ioctls are provided
for use. The ioctl's are called as:
.LP
.nf
ioctl(fd, SIOCADNAT, struct ipnat *)
ioctl(fd, SIOCRMNAT, struct ipnat *)
.fi
.PP
Unlike \fBipf(4)\fP, there is only a single list supported by the kernel NAT
interface. An inactive list which can be swapped to is not currently
supported.
These ioctl's are implemented as being routing ioctls and thus the same rules
for the various routing ioctls and the file descriptor are employed, mainly
being that the fd must be that of the device associated with the module
(i.e., /dev/ipl).
.LP
.PP
The strcture used with the NAT interface is described below:
.LP
.nf
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;
int in_redir; /* 0 if it's a mapping, 1 if it's a hard redir */
char in_ifname[IFNAMSIZ];
} ipnat_t;
#define in_pmin in_port[0] /* Also holds static redir port */
#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
.fi
.PP
Recognised values for in_redir:
.LP
.nf
#define NAT_MAP 0
#define NAT_REDIRECT 1
.fi
.PP
.LP
\fBNAT statistics\fP
Statistics on the the number of packets mapped, going in and out are kept,
the number of times a new entry is added and deleted (through expiration) to
the NAT table and the current usage level of the NAT table.
.PP
Pointers to the NAT table inside the kernel, as well as to the top of the
internal NAT lists constructed with the \fBSIOCADNAT\fP ioctls. The table
itself is a hash table of size NAT_SIZE (default size is 367).
.PP
To retrieve the statistics, the \fBSIOCGNATS\fP ioctl must be used, with
the appropriate structure passed by reference, as follows:
.nf
ioctl(fd, SIOCGNATS, struct natstat *)
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;
.fi
.SH BUGS
It would be nice if there were more flexibility when adding and deleting
filter rules.
.SH SEE ALSO
ipfstat(1), ipf(1), ipf(4), ipnat(5)

View File

@ -0,0 +1,70 @@
.TH IPNAT 5
.SH NAME
ipnat \- IP NAT file format
.SH DESCRIPTION
The format for files accepted by ipnat is described by the following grammar:
.LP
.nf
ipmap :: = mapit ifname ipmask "->" ipmask [ mapport ] .
mapit ::= "map" | "rdr" .
ipmask ::= ip "/" bits | ip "/" mask | ip "netmask" mask .
mapport ::= "portmap" tcpudp portnumber ":" portnumber .
tcpudp ::= "tcp" | "udp" | "tcp/udp" .
portnumber ::= number { numbers } .
ifname ::= 'A' - 'Z' { 'A' - 'Z' } numbers .
numbers ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' .
.fi
.PP
For standard NAT functionality, a rule should start with \fBmap\fP and then
proceeds to specify the interface for which outgoing packets will have their
source address rewritten.
.PP
Packets which will be rewritten can only be selected by matching the original
source address. A netmask must be specified with the IP address.
.PP
The address selected for replacing the original is chosen from an IP#/netmask
pair. A netmask of all 1's indicating a hostname is valid. A netmask of
31 1's (255.255.255.254) is considered invalid as there is no space for
allocating host IP#'s after consideration for broadcast and network
addresses.
.PP
When remapping TCP and UDP packets, it is also possible to change the source
port number. Either TCP or UDP or both can be selected by each rule, with a
range of port numbers to remap into given as \fBport-number:port-number\fP.
.SH Examples
.PP
To change IP#'s used internally from network 10 into an ISP provided 8 bit
subnet at 209.1.2.0, the following would be used:
.LP
.nf
map 10.0.0.0/8 -> 209.1.2.0/24
.fi
.PP
The obvious problem here is we're trying to squeeze over 16,000,000 IP
addresses into a 254 address space. To increase the scope, remapping for TCP
and/or UDP, port remapping can be used;
.LP
.nf
map 10.0.0.0/8 -> 209.1.2.0/24 portmap tcp/udp 1025:65000
.fi
.PP
which falls only 527,566 `addresses' short of the space available in network
10. If we were to combine these rules, they would need to be specified as
follows:
.LP
.nf
map 10.0.0.0/8 -> 209.1.2.0/24 portmap tcp/udp 1025:65000
map 10.0.0.0/8 -> 209.1.2.0/24
.fi
.PP
so that all TCP/UDP packets were port mapped and only other protocols, such as
ICMP, only have their IP# changed.
.SH FILES
/etc/services
.br
/etc/hosts
.SH SEE ALSO
ipnat(1), ipf(5), ipnat(4)

85
contrib/ipfilter/misc.c Normal file
View File

@ -0,0 +1,85 @@
/*
* (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.
*/
#include <stdio.h>
#include <assert.h>
#include <string.h>
#if !defined(__SVR4) && !defined(__svr4__)
#include <strings.h>
#else
#include <sys/byteorder.h>
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#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/udp.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>
#include <netinet/tcpip.h>
#include <net/if.h>
#include "ip_fil.h"
#include <netdb.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include "ipf.h"
#include "ipt.h"
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid[] = "@(#)misc.c 1.3 2/4/96 (C) 1995 Darren Reed";
static char rcsid[] = "$Id: misc.c,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $";
#endif
void debug(), verbose();
extern int opts;
void printpacket(ip)
struct ip *ip;
{
struct tcphdr *tcp;
tcp = (struct tcphdr *)((char *)ip + (ip->ip_hl << 2));
printf("ip %d(%d) %d ", ip->ip_len, ip->ip_hl << 2, ip->ip_p);
if (ip->ip_off & 0x1fff)
printf("@%d", ip->ip_off << 3);
(void)printf(" %s", inet_ntoa(ip->ip_src));
if (!(ip->ip_off & 0x1fff))
if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
(void)printf(",%d", ntohs(tcp->th_sport));
(void)printf(" > ");
(void)printf("%s", inet_ntoa(ip->ip_dst));
if (!(ip->ip_off & 0x1fff))
if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
(void)printf(",%d", ntohs(tcp->th_dport));
putchar('\n');
}
void verbose(fmt, p1, p2, p3, p4, p5, p6, p7, p8, p9)
char *fmt, *p1, *p2, *p3, *p4, *p5, *p6, *p7,*p8,*p9;
{
if (opts & OPT_VERBOSE)
printf(fmt, p1, p2, p3, p4, p5, p6, p7, p8, p9);
}
void debug(fmt, p1, p2, p3, p4, p5, p6, p7, p8, p9)
char *fmt, *p1, *p2, *p3, *p4, *p5, *p6, *p7,*p8,*p9;
{
if (opts & OPT_DEBUG)
printf(fmt, p1, p2, p3, p4, p5, p6, p7, p8, p9);
}

View File

@ -0,0 +1,65 @@
#!/usr/local/bin/perl
# for best results, bring up all your interfaces before running this
open(I, "ifconfig -a|") || die $!;
while (<I>) {
chop;
if (/^[a-zA-Z]+\d+:/) {
($iface = $_) =~ s/^([a-zA-Z]+\d+).*/$1/;
$ifaces{$iface} = $iface;
next;
}
if (/inet/) {
if (/\-\-\>/) { # PPP, (SLIP?)
($inet{$iface} = $_) =~ s/.*inet ([^ ]+) \-\-\> ([^ ]+).*/$1/;
($ppp{$iface} = $_) =~ s/.*inet ([^ ]+) \-\-\> ([^ ]+).*/$2/;
} else {
($inet{$iface} = $_) =~ s/.*inet ([^ ]+).*/$1/;
}
}
if (/netmask/) {
($mask = $_) =~ s/.*netmask ([^ ]+).*/$1/;
$mask =~ s/^/0x/ if ($mask =~ /^[0-9a-f]*$/);
$netmask{$iface} = $mask;
}
if (/broadcast/) {
($bcast{$iface} = $_) =~ s/.*broadcast ([^ ]+).*/$1/;
}
}
foreach $i (keys %ifaces) {
$net{$i} = $inet{$i}."/".$netmask{$i} if (defined($inet{$i}));
}
#
# print out route suggestions
#
print "#\n";
print "# The following routes should be configured, if not already:\n";
print "#\n";
foreach $i (keys %ifaces) {
next if (($i =~ /lo/) || !defined($net{$i}) || defined($ppp{$i}));
print "# route add $inet{$i} localhost 0\n";
}
print "#\n";
#
# print out some generic filters which people should use somewhere near the top
#
print "block in log quick from any to any with ipopts\n";
print "block in log quick proto tcp from any to any with short\n";
foreach $i (keys %ifaces) {
if (!defined($inet{$i})) {
next;
}
if ($i !~ /lo/) {
print "block in on $i from 127.0.0.0/8 to any\n";
print "block out on $i from 127.0.0.0/8 to any\n";
print "block out on $i from any to 127.0.0.0/8\n";
print "block in on $i from $inet{$i}/32 to any\n";
print "block out on $i from any to $inet{$i}/32\n";
foreach $j (keys %ifaces) {
if ($i ne $j && $j !~ /^lo/ && defined($net{$j})) {
print "block in on $i from $net{$j} to any\n";
}
}
}
}

167
contrib/ipfilter/ml_ipl.c Normal file
View File

@ -0,0 +1,167 @@
/*
* (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. The author accepts no
* responsibility and is not changed in any way.
*
* I hate legaleese, don't you ?
*/
/*
* 29/12/94 Added code from Marc Huber <huber@fzi.de> to allow it to allocate
* its own major char number! Way cool patch!
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/conf.h>
#include <sys/syslog.h>
#include <sys/buf.h>
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/uio.h>
#include <sys/vnode.h>
#include <sundev/mbvar.h>
#include <sun/autoconf.h>
#include <sun/vddrv.h>
#if defined(sun4c) || defined(sun4m)
#include <sun/openprom.h>
#endif
#ifndef IPL_NAME
#define IPL_NAME "/dev/ipl"
#endif
extern int iplattach(), iplopen(), iplclose(), iplioctl(), iplread();
extern int nulldev(), iplidentify(), errno;
struct cdevsw ipldevsw =
{
iplopen, iplclose, iplread, nulldev,
iplioctl, nulldev, nulldev, nulldev,
0, nulldev,
};
struct dev_ops ipl_ops =
{
1,
iplidentify,
iplattach,
iplopen,
iplclose,
iplread,
NULL, /* write */
NULL, /* strategy */
NULL, /* dump */
0, /* psize */
iplioctl,
NULL, /* reset */
NULL /* mmap */
};
int ipl_major = 0;
#ifdef sun4m
struct vdldrv vd =
{
VDMAGIC_PSEUDO,
"ipl",
&ipl_ops,
NULL,
&ipldevsw,
0,
0,
NULL,
NULL,
NULL,
0,
1,
};
#else /* sun4m */
struct vdldrv vd =
{
VDMAGIC_PSEUDO, /* magic */
"ipl", /* name */
#ifdef sun4c
&ipl_ops, /* dev_ops */
#else
NULL, /* struct mb_ctlr *mb_ctlr */
NULL, /* struct mb_driver *mb_driver */
NULL, /* struct mb_device *mb_device */
0, /* num ctlrs */
1, /* numdevs */
#endif /* sun4c */
NULL, /* bdevsw */
&ipldevsw, /* cdevsw */
0, /* block major */
0, /* char major */
};
#endif /* sun4m */
extern int vd_unuseddev();
extern struct cdevsw cdevsw[];
extern int nchrdev;
xxxinit(fc, vdp, vdi, vds)
u_int fc;
struct vddrv *vdp;
caddr_t vdi;
struct vdstat *vds;
{
struct vdlinkage *v;
int i;
switch (fc)
{
case VDLOAD:
while (ipl_major < nchrdev &&
cdevsw[ipl_major].d_open != vd_unuseddev)
ipl_major++;
if (ipl_major == nchrdev)
return ENODEV;
vd.Drv_charmajor = ipl_major;
vdp->vdd_vdtab = (struct vdlinkage *)&vd;
return ipl_attach(vdi);
case VDUNLOAD:
return unload(vdp, vdi);
case VDSTAT:
return 0;
default:
return EIO;
}
}
static unload(vdp, vdi)
struct vddrv *vdp;
struct vdioctl_unload *vdi;
{
int i;
(void) vn_remove(IPL_NAME, UIO_SYSSPACE, FILE);
return ipldetach();
}
static int ipl_attach(vdi)
struct vdioctl_load *vdi;
{
struct vnode *vp;
struct vattr vattr;
int error = 0, fmode = S_IFCHR|0600;
(void) vn_remove(IPL_NAME, UIO_SYSSPACE, FILE);
vattr_null(&vattr);
vattr.va_type = MFTOVT(fmode);
vattr.va_mode = (fmode & 07777);
vattr.va_rdev = ipl_major<<8;
error = vn_create(IPL_NAME, UIO_SYSSPACE, &vattr, EXCL, 0, &vp);
if (error == 0)
VN_RELE(vp);
return iplattach(0);
}

237
contrib/ipfilter/mln_ipl.c Normal file
View File

@ -0,0 +1,237 @@
/*
* (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.
*/
/*
* 29/12/94 Added code from Marc Huber <huber@fzi.de> to allow it to allocate
* its own major char number! Way cool patch!
*/
#include <sys/param.h>
/*
* Post NetBSD 1.2 has the PFIL interface for packet filters. This turns
* on those hooks. We don't need any special mods with this!
*/
#if (defined(NetBSD) && (NetBSD > 199609) && (NetBSD <= 1991011)) || \
(defined(NetBSD1_2) && NetBSD1_2 > 1)
# define NETBSD_PF
#endif
#if defined(__FreeBSD__) && (__FreeBSD__ > 1)
# include <osreldate.h>
#endif
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/proc.h>
#include <sys/uio.h>
#include <sys/kernel.h>
#include <sys/vnode.h>
#include <sys/namei.h>
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/exec.h>
#include <sys/mbuf.h>
#if defined(__NetBSD__) || (defined(__FreeBSD_version) && \
(__FreeBSD_version >= 199607))
#include <net/if.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#endif
#ifndef __NetBSD__
#include <sys/sysent.h>
#endif
#include <sys/lkm.h>
#include "ipl.h"
#include "ip_fil.h"
#ifndef IPL_NAME
#define IPL_NAME "/dev/ipl"
#endif
#if !defined(VOP_LEASE) && defined(LEASE_CHECK)
#define VOP_LEASE LEASE_CHECK
#endif
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
extern int lkmenodev(), lkmexists(), lkmdispatch();
extern int iplattach(), iplopen(), iplclose(), iplioctl(), ipldetach();
#ifdef NETBSD_PF
#include <net/pfil.h>
#endif
#ifdef IPFILTER_LOG
extern int iplread();
#else
#ifdef NETBSD_PF
#define iplread enodev
#else
#define iplread nodev
#endif
#endif
extern int iplidentify();
#ifdef NETBSD_PF
int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)) = NULL;
#endif
static int ipl_unload(), ipl_load();
#if (defined(NetBSD1_0) && (NetBSD1_0 > 1)) || \
(defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199511))
struct cdevsw ipldevsw =
{
iplopen, /* open */
iplclose, /* close */
iplread, /* read */
0, /* write */
iplioctl, /* ioctl */
0, /* stop */
0, /* tty */
0, /* select */
0, /* mmap */
NULL /* strategy */
};
#else
struct cdevsw ipldevsw =
{
iplopen, /* open */
iplclose, /* close */
iplread, /* read */
(void *)nullop, /* write */
iplioctl, /* ioctl */
(void *)nullop, /* stop */
(void *)nullop, /* reset */
(void *)NULL, /* tty */
(void *)nullop, /* select */
(void *)nullop, /* mmap */
NULL /* strategy */
};
#endif
static struct cdevsw cdev_sav;
int ipl_major = 0;
MOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipldevsw);
extern int vd_unuseddev();
extern struct cdevsw cdevsw[];
extern int nchrdev;
static int iplaction(lkmtp, cmd)
struct lkm_table *lkmtp;
int cmd;
{
int i;
struct lkm_dev *args = lkmtp->private.lkm_dev;
int err = 0;
switch (cmd)
{
case LKM_E_LOAD :
if (lkmexists(lkmtp))
return EEXIST;
for (i = 0; i < nchrdev; i++)
if (cdevsw[i].d_open == lkmenodev ||
cdevsw[i].d_open == iplopen)
break;
if (i == nchrdev) {
printf("IP Filter: No free cdevsw slots\n");
return ENODEV;
}
ipl_major = i;
args->lkm_offset = i; /* slot in cdevsw[] */
printf("IP Filter: loaded into slot %d\n", ipl_major);
return ipl_load();
case LKM_E_UNLOAD :
printf("IP Filter: unloaded from slot %d\n", ipl_major);
return ipl_unload();
case LKM_E_STAT :
break;
default:
err = EIO;
break;
}
return 0;
}
static int ipl_remove()
{
struct nameidata nd;
int error;
NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, IPL_NAME, curproc);
if ((error = namei(&nd)))
return (error);
VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE);
VOP_LOCK(nd.ni_vp);
VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
return VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
}
static int ipl_unload()
{
int error;
error = ipldetach();
#ifdef NETBSD_PF
pfil_remove_hook(fr_check, PFIL_IN|PFIL_OUT);
#endif
if (!error)
error = ipl_remove();
return error;
}
static int ipl_load()
{
struct nameidata nd;
struct vattr vattr;
int error, fmode = S_IFCHR|0600;
error = iplattach();
#ifdef NETBSD_PF
pfil_add_hook(fr_check, PFIL_IN|PFIL_OUT);
#endif
if (error)
return error;
(void) ipl_remove();
error = 0;
NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, IPL_NAME, curproc);
if (error = namei(&nd))
return error;
if (nd.ni_vp != NULL) {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
if (nd.ni_dvp == nd.ni_vp)
vrele(nd.ni_dvp);
else
vput(nd.ni_dvp);
vrele(nd.ni_vp);
return (EEXIST);
}
VATTR_NULL(&vattr);
vattr.va_type = VCHR;
vattr.va_mode = (fmode & 07777);
vattr.va_rdev = ipl_major<<8;
VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
return VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
}
int xxxinit(lkmtp, cmd, ver)
struct lkm_table *lkmtp;
int cmd, ver;
{
DISPATCH(lkmtp, cmd, ver, iplaction, iplaction, iplaction);
}

Some files were not shown because too many files have changed in this diff Show More