diff options
author | Darren Reed <darrenr@FreeBSD.org> | 1997-02-09 22:50:16 +0000 |
---|---|---|
committer | Darren Reed <darrenr@FreeBSD.org> | 1997-02-09 22:50:16 +0000 |
commit | b4ebec5bf8828aa1cc3f5a1a50faf812b5b6ba48 (patch) | |
tree | 93c7db298b1fd70f9e27663b3fd527da063d0008 | |
download | src-b4ebec5bf8828aa1cc3f5a1a50faf812b5b6ba48.tar.gz src-b4ebec5bf8828aa1cc3f5a1a50faf812b5b6ba48.zip |
Import IP Filter v3.1.7 into FreeBSD treevendor/ipfilter/3.1.7
Notes
Notes:
svn path=/vendor/ipfilter/dist/; revision=22514
svn path=/vendor/ipfilter/3.1.7/; revision=22516; tag=vendor/ipfilter/3.1.7
189 files changed, 28807 insertions, 0 deletions
diff --git a/contrib/ipfilter/BNF b/contrib/ipfilter/BNF new file mode 100644 index 000000000000..7cb556e1a0a8 --- /dev/null +++ b/contrib/ipfilter/BNF @@ -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" . diff --git a/contrib/ipfilter/COMPILE.2.5 b/contrib/ipfilter/COMPILE.2.5 new file mode 100644 index 000000000000..ae550f896e49 --- /dev/null +++ b/contrib/ipfilter/COMPILE.2.5 @@ -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 diff --git a/contrib/ipfilter/FWTK/README b/contrib/ipfilter/FWTK/README new file mode 100644 index 000000000000..216d20582036 --- /dev/null +++ b/contrib/ipfilter/FWTK/README @@ -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 diff --git a/contrib/ipfilter/FWTK/ftp-gw.diff b/contrib/ipfilter/FWTK/ftp-gw.diff new file mode 100644 index 000000000000..075e6eb2fdb8 --- /dev/null +++ b/contrib/ipfilter/FWTK/ftp-gw.diff @@ -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)); ++ } diff --git a/contrib/ipfilter/FWTK/fwtkp b/contrib/ipfilter/FWTK/fwtkp new file mode 100644 index 000000000000..8f4819a16f81 --- /dev/null +++ b/contrib/ipfilter/FWTK/fwtkp @@ -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); + } + + + diff --git a/contrib/ipfilter/HISTORY b/contrib/ipfilter/HISTORY new file mode 100644 index 000000000000..7cd91069beb4 --- /dev/null +++ b/contrib/ipfilter/HISTORY @@ -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. + diff --git a/contrib/ipfilter/IMPORTANT b/contrib/ipfilter/IMPORTANT new file mode 100644 index 000000000000..00272f2b1f53 --- /dev/null +++ b/contrib/ipfilter/IMPORTANT @@ -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 + **************************************** diff --git a/contrib/ipfilter/INSTALL.FreeBSD b/contrib/ipfilter/INSTALL.FreeBSD new file mode 100644 index 000000000000..3910f4d47577 --- /dev/null +++ b/contrib/ipfilter/INSTALL.FreeBSD @@ -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 diff --git a/contrib/ipfilter/INSTALL.NetBSD b/contrib/ipfilter/INSTALL.NetBSD new file mode 100644 index 000000000000..2387827ea3ca --- /dev/null +++ b/contrib/ipfilter/INSTALL.NetBSD @@ -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 diff --git a/contrib/ipfilter/INSTALL.Sol2 b/contrib/ipfilter/INSTALL.Sol2 new file mode 100644 index 000000000000..6ed6473579dc --- /dev/null +++ b/contrib/ipfilter/INSTALL.Sol2 @@ -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 diff --git a/contrib/ipfilter/INSTALL.SunOS b/contrib/ipfilter/INSTALL.SunOS new file mode 100644 index 000000000000..836d1214589a --- /dev/null +++ b/contrib/ipfilter/INSTALL.SunOS @@ -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 diff --git a/contrib/ipfilter/INSTALL.xBSD b/contrib/ipfilter/INSTALL.xBSD new file mode 100644 index 000000000000..9ab66f12932c --- /dev/null +++ b/contrib/ipfilter/INSTALL.xBSD @@ -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 diff --git a/contrib/ipfilter/LICENCE b/contrib/ipfilter/LICENCE new file mode 100644 index 000000000000..c5a7767d12cf --- /dev/null +++ b/contrib/ipfilter/LICENCE @@ -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 ? + */ diff --git a/contrib/ipfilter/Makefile b/contrib/ipfilter/Makefile new file mode 100644 index 000000000000..d0d5309d98e6 --- /dev/null +++ b/contrib/ipfilter/Makefile @@ -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 diff --git a/contrib/ipfilter/README b/contrib/ipfilter/README new file mode 100644 index 000000000000..b959d408f293 --- /dev/null +++ b/contrib/ipfilter/README @@ -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 diff --git a/contrib/ipfilter/bsdinstall b/contrib/ipfilter/bsdinstall new file mode 100755 index 000000000000..ce921b60fa47 --- /dev/null +++ b/contrib/ipfilter/bsdinstall @@ -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 diff --git a/contrib/ipfilter/buildsunos b/contrib/ipfilter/buildsunos new file mode 100755 index 000000000000..dd2aa38a36ca --- /dev/null +++ b/contrib/ipfilter/buildsunos @@ -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 $? diff --git a/contrib/ipfilter/etc/protocols b/contrib/ipfilter/etc/protocols new file mode 100644 index 000000000000..b41aa1df4372 --- /dev/null +++ b/contrib/ipfilter/etc/protocols @@ -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 # diff --git a/contrib/ipfilter/etc/services b/contrib/ipfilter/etc/services new file mode 100644 index 000000000000..90dd07af595b --- /dev/null +++ b/contrib/ipfilter/etc/services @@ -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 diff --git a/contrib/ipfilter/fil.c b/contrib/ipfilter/fil.c new file mode 100644 index 000000000000..de776f9fc5c8 --- /dev/null +++ b/contrib/ipfilter/fil.c @@ -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 diff --git a/contrib/ipfilter/fils.c b/contrib/ipfilter/fils.c new file mode 100644 index 000000000000..249611b25343 --- /dev/null +++ b/contrib/ipfilter/fils.c @@ -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; + } +} diff --git a/contrib/ipfilter/inet_addr.c b/contrib/ipfilter/inet_addr.c new file mode 100644 index 000000000000..91faec3eeed7 --- /dev/null +++ b/contrib/ipfilter/inet_addr.c @@ -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); +} diff --git a/contrib/ipfilter/ip_compat.h b/contrib/ipfilter/ip_compat.h new file mode 100644 index 000000000000..5a36cc318ad6 --- /dev/null +++ b/contrib/ipfilter/ip_compat.h @@ -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__ */ diff --git a/contrib/ipfilter/ip_fil.c b/contrib/ipfilter/ip_fil.c new file mode 100644 index 000000000000..7a244345640e --- /dev/null +++ b/contrib/ipfilter/ip_fil.c @@ -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; +} diff --git a/contrib/ipfilter/ip_fil.h b/contrib/ipfilter/ip_fil.h new file mode 100644 index 000000000000..389a161bc2df --- /dev/null +++ b/contrib/ipfilter/ip_fil.h @@ -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__ */ diff --git a/contrib/ipfilter/ip_frag.c b/contrib/ipfilter/ip_frag.c new file mode 100644 index 000000000000..6665404b9830 --- /dev/null +++ b/contrib/ipfilter/ip_frag.c @@ -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) */ diff --git a/contrib/ipfilter/ip_frag.h b/contrib/ipfilter/ip_frag.h new file mode 100644 index 000000000000..a356785e528c --- /dev/null +++ b/contrib/ipfilter/ip_frag.h @@ -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__ */ diff --git a/contrib/ipfilter/ip_nat.c b/contrib/ipfilter/ip_nat.c new file mode 100644 index 000000000000..afe9761bc093 --- /dev/null +++ b/contrib/ipfilter/ip_nat.c @@ -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); +} diff --git a/contrib/ipfilter/ip_nat.h b/contrib/ipfilter/ip_nat.h new file mode 100644 index 000000000000..d64183ac3920 --- /dev/null +++ b/contrib/ipfilter/ip_nat.h @@ -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__ */ diff --git a/contrib/ipfilter/ip_sfil.c b/contrib/ipfilter/ip_sfil.c new file mode 100644 index 000000000000..debc512707d6 --- /dev/null +++ b/contrib/ipfilter/ip_sfil.c @@ -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; +} diff --git a/contrib/ipfilter/ip_state.c b/contrib/ipfilter/ip_state.c new file mode 100644 index 000000000000..62a49aa250ed --- /dev/null +++ b/contrib/ipfilter/ip_state.c @@ -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; + } +} diff --git a/contrib/ipfilter/ip_state.h b/contrib/ipfilter/ip_state.h new file mode 100644 index 000000000000..ee30b986d844 --- /dev/null +++ b/contrib/ipfilter/ip_state.h @@ -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__ */ diff --git a/contrib/ipfilter/ipf.c b/contrib/ipfilter/ipf.c new file mode 100644 index 000000000000..da6baa244648 --- /dev/null +++ b/contrib/ipfilter/ipf.c @@ -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 diff --git a/contrib/ipfilter/ipf.h b/contrib/ipfilter/ipf.h new file mode 100644 index 000000000000..3ac76fc288e5 --- /dev/null +++ b/contrib/ipfilter/ipf.h @@ -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 + diff --git a/contrib/ipfilter/ipft_ef.c b/contrib/ipfilter/ipft_ef.c new file mode 100644 index 000000000000..2c4cc0f0d21b --- /dev/null +++ b/contrib/ipfilter/ipft_ef.c @@ -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; +} diff --git a/contrib/ipfilter/ipft_hx.c b/contrib/ipfilter/ipft_hx.c new file mode 100644 index 000000000000..26dbc83d15a4 --- /dev/null +++ b/contrib/ipfilter/ipft_hx.c @@ -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; +} diff --git a/contrib/ipfilter/ipft_pc.c b/contrib/ipfilter/ipft_pc.c new file mode 100644 index 000000000000..3d3d8879bd80 --- /dev/null +++ b/contrib/ipfilter/ipft_pc.c @@ -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; +} diff --git a/contrib/ipfilter/ipft_sn.c b/contrib/ipfilter/ipft_sn.c new file mode 100644 index 000000000000..3185b56157dc --- /dev/null +++ b/contrib/ipfilter/ipft_sn.c @@ -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; +} diff --git a/contrib/ipfilter/ipft_td.c b/contrib/ipfilter/ipft_td.c new file mode 100644 index 000000000000..ecd2badae454 --- /dev/null +++ b/contrib/ipfilter/ipft_td.c @@ -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; +} diff --git a/contrib/ipfilter/ipft_tx.c b/contrib/ipfilter/ipft_tx.c new file mode 100644 index 000000000000..0522f96cfae5 --- /dev/null +++ b/contrib/ipfilter/ipft_tx.c @@ -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; +} diff --git a/contrib/ipfilter/ipl.h b/contrib/ipfilter/ipl.h new file mode 100644 index 000000000000..9a2e43d995d2 --- /dev/null +++ b/contrib/ipfilter/ipl.h @@ -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 diff --git a/contrib/ipfilter/ipl_ldev.c b/contrib/ipfilter/ipl_ldev.c new file mode 100644 index 000000000000..a2893257e72e --- /dev/null +++ b/contrib/ipfilter/ipl_ldev.c @@ -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; +} diff --git a/contrib/ipfilter/ipmon.c b/contrib/ipfilter/ipmon.c new file mode 100644 index 000000000000..2ea34efb1874 --- /dev/null +++ b/contrib/ipfilter/ipmon.c @@ -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 */ +} diff --git a/contrib/ipfilter/ipnat.c b/contrib/ipfilter/ipnat.c new file mode 100644 index 000000000000..6458cde86b92 --- /dev/null +++ b/contrib/ipfilter/ipnat.c @@ -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); + } +} diff --git a/contrib/ipfilter/ipsd/Makefile b/contrib/ipfilter/ipsd/Makefile new file mode 100644 index 000000000000..eb1986e1c9b2 --- /dev/null +++ b/contrib/ipfilter/ipsd/Makefile @@ -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 diff --git a/contrib/ipfilter/ipsd/README b/contrib/ipfilter/ipsd/README new file mode 100644 index 000000000000..6746d01d3852 --- /dev/null +++ b/contrib/ipfilter/ipsd/README @@ -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 diff --git a/contrib/ipfilter/ipsd/ip_compat.h b/contrib/ipfilter/ipsd/ip_compat.h new file mode 100644 index 000000000000..a911fd83c3f3 --- /dev/null +++ b/contrib/ipfilter/ipsd/ip_compat.h @@ -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 diff --git a/contrib/ipfilter/ipsd/ipsd.c b/contrib/ipfilter/ipsd/ipsd.c new file mode 100644 index 000000000000..96364dda483e --- /dev/null +++ b/contrib/ipfilter/ipsd/ipsd.c @@ -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); +} diff --git a/contrib/ipfilter/ipsd/ipsd.h b/contrib/ipfilter/ipsd/ipsd.h new file mode 100644 index 000000000000..a9f3920b4c55 --- /dev/null +++ b/contrib/ipfilter/ipsd/ipsd.h @@ -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; + diff --git a/contrib/ipfilter/ipsd/ipsdr.c b/contrib/ipfilter/ipsd/ipsdr.c new file mode 100644 index 000000000000..b3bf95765a94 --- /dev/null +++ b/contrib/ipfilter/ipsd/ipsdr.c @@ -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(); +} diff --git a/contrib/ipfilter/ipsd/linux.h b/contrib/ipfilter/ipsd/linux.h new file mode 100644 index 000000000000..7eb382b4b7e1 --- /dev/null +++ b/contrib/ipfilter/ipsd/linux.h @@ -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" diff --git a/contrib/ipfilter/ipsd/sbpf.c b/contrib/ipfilter/ipsd/sbpf.c new file mode 100644 index 000000000000..d008a5f00d25 --- /dev/null +++ b/contrib/ipfilter/ipsd/sbpf.c @@ -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; +} diff --git a/contrib/ipfilter/ipsd/sdlpi.c b/contrib/ipfilter/ipsd/sdlpi.c new file mode 100644 index 000000000000..1d0e41d7f66f --- /dev/null +++ b/contrib/ipfilter/ipsd/sdlpi.c @@ -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; +} diff --git a/contrib/ipfilter/ipsd/slinux.c b/contrib/ipfilter/ipsd/slinux.c new file mode 100644 index 000000000000..1115b86954ec --- /dev/null +++ b/contrib/ipfilter/ipsd/slinux.c @@ -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; +} diff --git a/contrib/ipfilter/ipsd/snit.c b/contrib/ipfilter/ipsd/snit.c new file mode 100644 index 000000000000..4b5fd0346b2a --- /dev/null +++ b/contrib/ipfilter/ipsd/snit.c @@ -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*)𝔦 + 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; +} diff --git a/contrib/ipfilter/ipsend/44arp.c b/contrib/ipfilter/ipsend/44arp.c new file mode 100644 index 000000000000..621d84c86d5b --- /dev/null +++ b/contrib/ipfilter/ipsend/44arp.c @@ -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; +} diff --git a/contrib/ipfilter/ipsend/Crashable b/contrib/ipfilter/ipsend/Crashable new file mode 100644 index 000000000000..dbe1b87c1174 --- /dev/null +++ b/contrib/ipfilter/ipsend/Crashable @@ -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 diff --git a/contrib/ipfilter/ipsend/Makefile b/contrib/ipfilter/ipsend/Makefile new file mode 100644 index 000000000000..1f049125c307 --- /dev/null +++ b/contrib/ipfilter/ipsend/Makefile @@ -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 diff --git a/contrib/ipfilter/ipsend/arp.c b/contrib/ipfilter/ipsend/arp.c new file mode 100644 index 000000000000..47f6fce3e397 --- /dev/null +++ b/contrib/ipfilter/ipsend/arp.c @@ -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; +} diff --git a/contrib/ipfilter/ipsend/dlcommon.c b/contrib/ipfilter/ipsend/dlcommon.c new file mode 100644 index 000000000000..59b283d2b82f --- /dev/null +++ b/contrib/ipfilter/ipsend/dlcommon.c @@ -0,0 +1,1359 @@ +/* + * Common (shared) DLPI test routines. + * Mostly pretty boring boilerplate sorta stuff. + * These can be split into individual library routines later + * but it's just convenient to keep them in a single file + * while they're being developed. + * + * Not supported: + * Connection Oriented stuff + * QOS stuff + */ + +/* +typedef unsigned long ulong; +*/ + + +#include <sys/types.h> +#include <sys/stream.h> +#include <sys/stropts.h> +#include <sys/dlpi.h> +#include <sys/signal.h> +#include <stdio.h> +#include <string.h> +#include "dltest.h" + +#define CASERET(s) case s: return ("s") + +char *dlprim(); +char *dlstate(); +char *dlerrno(); +char *dlpromisclevel(); +char *dlservicemode(); +char *dlstyle(); +char *dlmactype(); + + +dlinforeq(fd) +int fd; +{ + dl_info_req_t info_req; + struct strbuf ctl; + int flags; + + info_req.dl_primitive = DL_INFO_REQ; + + ctl.maxlen = 0; + ctl.len = sizeof (info_req); + ctl.buf = (char *) &info_req; + + flags = RS_HIPRI; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dlinforeq: putmsg"); +} + +dlinfoack(fd, bufp) +int fd; +char *bufp; +{ + union DL_primitives *dlp; + struct strbuf ctl; + int flags; + + ctl.maxlen = MAXDLBUF; + ctl.len = 0; + ctl.buf = bufp; + + strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlinfoack"); + + dlp = (union DL_primitives *) ctl.buf; + + expecting(DL_INFO_ACK, dlp); + + if (ctl.len < sizeof (dl_info_ack_t)) + err("dlinfoack: response ctl.len too short: %d", ctl.len); + + if (flags != RS_HIPRI) + err("dlinfoack: DL_INFO_ACK was not M_PCPROTO"); + + if (ctl.len < sizeof (dl_info_ack_t)) + err("dlinfoack: short response ctl.len: %d", ctl.len); +} + +dlattachreq(fd, ppa) +int fd; +u_long ppa; +{ + dl_attach_req_t attach_req; + struct strbuf ctl; + int flags; + + attach_req.dl_primitive = DL_ATTACH_REQ; + attach_req.dl_ppa = ppa; + + ctl.maxlen = 0; + ctl.len = sizeof (attach_req); + ctl.buf = (char *) &attach_req; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dlattachreq: putmsg"); +} + +dlenabmultireq(fd, addr, length) +int fd; +char *addr; +int length; +{ + long buf[MAXDLBUF]; + union DL_primitives *dlp; + struct strbuf ctl; + int flags; + + dlp = (union DL_primitives*) buf; + + dlp->enabmulti_req.dl_primitive = DL_ENABMULTI_REQ; + dlp->enabmulti_req.dl_addr_length = length; + dlp->enabmulti_req.dl_addr_offset = sizeof (dl_enabmulti_req_t); + + (void) memcpy((char*)OFFADDR(buf, sizeof (dl_enabmulti_req_t)), addr, length); + + ctl.maxlen = 0; + ctl.len = sizeof (dl_enabmulti_req_t) + length; + ctl.buf = (char*) buf; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dlenabmultireq: putmsg"); +} + +dldisabmultireq(fd, addr, length) +int fd; +char *addr; +int length; +{ + long buf[MAXDLBUF]; + union DL_primitives *dlp; + struct strbuf ctl; + int flags; + + dlp = (union DL_primitives*) buf; + + dlp->disabmulti_req.dl_primitive = DL_ENABMULTI_REQ; + dlp->disabmulti_req.dl_addr_length = length; + dlp->disabmulti_req.dl_addr_offset = sizeof (dl_disabmulti_req_t); + + (void) memcpy((char*)OFFADDR(buf, sizeof (dl_disabmulti_req_t)), addr, length); + + ctl.maxlen = 0; + ctl.len = sizeof (dl_disabmulti_req_t) + length; + ctl.buf = (char*) buf; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dldisabmultireq: putmsg"); +} + +dlpromisconreq(fd, level) +int fd; +u_long level; +{ + dl_promiscon_req_t promiscon_req; + struct strbuf ctl; + int flags; + + promiscon_req.dl_primitive = DL_PROMISCON_REQ; + promiscon_req.dl_level = level; + + ctl.maxlen = 0; + ctl.len = sizeof (promiscon_req); + ctl.buf = (char *) &promiscon_req; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dlpromiscon: putmsg"); + +} + +dlpromiscoff(fd, level) +int fd; +u_long level; +{ + dl_promiscoff_req_t promiscoff_req; + struct strbuf ctl; + int flags; + + promiscoff_req.dl_primitive = DL_PROMISCOFF_REQ; + promiscoff_req.dl_level = level; + + ctl.maxlen = 0; + ctl.len = sizeof (promiscoff_req); + ctl.buf = (char *) &promiscoff_req; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dlpromiscoff: putmsg"); +} + +dlphysaddrreq(fd, addrtype) +int fd; +u_long addrtype; +{ + dl_phys_addr_req_t phys_addr_req; + struct strbuf ctl; + int flags; + + phys_addr_req.dl_primitive = DL_PHYS_ADDR_REQ; + phys_addr_req.dl_addr_type = addrtype; + + ctl.maxlen = 0; + ctl.len = sizeof (phys_addr_req); + ctl.buf = (char *) &phys_addr_req; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dlphysaddrreq: putmsg"); +} + +dlsetphysaddrreq(fd, addr, length) +int fd; +char *addr; +int length; +{ + long buf[MAXDLBUF]; + union DL_primitives *dlp; + struct strbuf ctl; + int flags; + + dlp = (union DL_primitives*) buf; + + dlp->set_physaddr_req.dl_primitive = DL_ENABMULTI_REQ; + dlp->set_physaddr_req.dl_addr_length = length; + dlp->set_physaddr_req.dl_addr_offset = sizeof (dl_set_phys_addr_req_t); + + (void) memcpy((char*)OFFADDR(buf, sizeof (dl_set_phys_addr_req_t)), addr, length); + + ctl.maxlen = 0; + ctl.len = sizeof (dl_set_phys_addr_req_t) + length; + ctl.buf = (char*) buf; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dlsetphysaddrreq: putmsg"); +} + +dldetachreq(fd) +int fd; +{ + dl_detach_req_t detach_req; + struct strbuf ctl; + int flags; + + detach_req.dl_primitive = DL_DETACH_REQ; + + ctl.maxlen = 0; + ctl.len = sizeof (detach_req); + ctl.buf = (char *) &detach_req; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dldetachreq: putmsg"); +} + +dlbindreq(fd, sap, max_conind, service_mode, conn_mgmt, xidtest) +int fd; +u_long sap; +u_long max_conind; +u_long service_mode; +u_long conn_mgmt; +u_long xidtest; +{ + dl_bind_req_t bind_req; + struct strbuf ctl; + int flags; + + bind_req.dl_primitive = DL_BIND_REQ; + bind_req.dl_sap = sap; + bind_req.dl_max_conind = max_conind; + bind_req.dl_service_mode = service_mode; + bind_req.dl_conn_mgmt = conn_mgmt; + bind_req.dl_xidtest_flg = xidtest; + + ctl.maxlen = 0; + ctl.len = sizeof (bind_req); + ctl.buf = (char *) &bind_req; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dlbindreq: putmsg"); +} + +dlunitdatareq(fd, addrp, addrlen, minpri, maxpri, datap, datalen) +int fd; +u_char *addrp; +int addrlen; +u_long minpri, maxpri; +u_char *datap; +int datalen; +{ + long buf[MAXDLBUF]; + union DL_primitives *dlp; + struct strbuf data, ctl; + + dlp = (union DL_primitives*) buf; + + dlp->unitdata_req.dl_primitive = DL_UNITDATA_REQ; + dlp->unitdata_req.dl_dest_addr_length = addrlen; + dlp->unitdata_req.dl_dest_addr_offset = sizeof (dl_unitdata_req_t); + dlp->unitdata_req.dl_priority.dl_min = minpri; + dlp->unitdata_req.dl_priority.dl_max = maxpri; + + (void) memcpy(OFFADDR(dlp, sizeof (dl_unitdata_req_t)), addrp, addrlen); + + ctl.maxlen = 0; + ctl.len = sizeof (dl_unitdata_req_t) + addrlen; + ctl.buf = (char *) buf; + + data.maxlen = 0; + data.len = datalen; + data.buf = (char *) datap; + + if (putmsg(fd, &ctl, &data, 0) < 0) + syserr("dlunitdatareq: putmsg"); +} + +dlunbindreq(fd) +int fd; +{ + dl_unbind_req_t unbind_req; + struct strbuf ctl; + int flags; + + unbind_req.dl_primitive = DL_UNBIND_REQ; + + ctl.maxlen = 0; + ctl.len = sizeof (unbind_req); + ctl.buf = (char *) &unbind_req; + + flags = 0; + + if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) + syserr("dlunbindreq: putmsg"); +} + +dlokack(fd, bufp) +int fd; +char *bufp; +{ + union DL_primitives *dlp; + struct strbuf ctl; + int flags; + + ctl.maxlen = MAXDLBUF; + ctl.len = 0; + ctl.buf = bufp; + + strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlokack"); + + dlp = (union DL_primitives *) ctl.buf; + + expecting(DL_OK_ACK, dlp); + + if (ctl.len < sizeof (dl_ok_ack_t)) + err("dlokack: response ctl.len too short: %d", ctl.len); + + if (flags != RS_HIPRI) + err("dlokack: DL_OK_ACK was not M_PCPROTO"); + + if (ctl.len < sizeof (dl_ok_ack_t)) + err("dlokack: short response ctl.len: %d", ctl.len); +} + +dlerrorack(fd, bufp) +int fd; +char *bufp; +{ + union DL_primitives *dlp; + struct strbuf ctl; + int flags; + + ctl.maxlen = MAXDLBUF; + ctl.len = 0; + ctl.buf = bufp; + + strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlerrorack"); + + dlp = (union DL_primitives *) ctl.buf; + + expecting(DL_ERROR_ACK, dlp); + + if (ctl.len < sizeof (dl_error_ack_t)) + err("dlerrorack: response ctl.len too short: %d", ctl.len); + + if (flags != RS_HIPRI) + err("dlerrorack: DL_OK_ACK was not M_PCPROTO"); + + if (ctl.len < sizeof (dl_error_ack_t)) + err("dlerrorack: short response ctl.len: %d", ctl.len); +} + +dlbindack(fd, bufp) +int fd; +char *bufp; +{ + union DL_primitives *dlp; + struct strbuf ctl; + int flags; + + ctl.maxlen = MAXDLBUF; + ctl.len = 0; + ctl.buf = bufp; + + strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlbindack"); + + dlp = (union DL_primitives *) ctl.buf; + + expecting(DL_BIND_ACK, dlp); + + if (flags != RS_HIPRI) + err("dlbindack: DL_OK_ACK was not M_PCPROTO"); + + if (ctl.len < sizeof (dl_bind_ack_t)) + err("dlbindack: short response ctl.len: %d", ctl.len); +} + +dlphysaddrack(fd, bufp) +int fd; +char *bufp; +{ + union DL_primitives *dlp; + struct strbuf ctl; + int flags; + + ctl.maxlen = MAXDLBUF; + ctl.len = 0; + ctl.buf = bufp; + + strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlphysaddrack"); + + dlp = (union DL_primitives *) ctl.buf; + + expecting(DL_PHYS_ADDR_ACK, dlp); + + if (flags != RS_HIPRI) + err("dlbindack: DL_OK_ACK was not M_PCPROTO"); + + if (ctl.len < sizeof (dl_phys_addr_ack_t)) + err("dlphysaddrack: short response ctl.len: %d", ctl.len); +} + +void +sigalrm() +{ + (void) err("sigalrm: TIMEOUT"); +} + +strgetmsg(fd, ctlp, datap, flagsp, caller) +int fd; +struct strbuf *ctlp, *datap; +int *flagsp; +char *caller; +{ + int rc; + static char errmsg[80]; + + /* + * Start timer. + */ + (void) signal(SIGALRM, sigalrm); + if (alarm(MAXWAIT) < 0) { + (void) sprintf(errmsg, "%s: alarm", caller); + syserr(errmsg); + } + + /* + * Set flags argument and issue getmsg(). + */ + *flagsp = 0; + if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0) { + (void) sprintf(errmsg, "%s: getmsg", caller); + syserr(errmsg); + } + + /* + * Stop timer. + */ + if (alarm(0) < 0) { + (void) sprintf(errmsg, "%s: alarm", caller); + syserr(errmsg); + } + + /* + * Check for MOREDATA and/or MORECTL. + */ + if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA)) + err("%s: MORECTL|MOREDATA", caller); + if (rc & MORECTL) + err("%s: MORECTL", caller); + if (rc & MOREDATA) + err("%s: MOREDATA", caller); + + /* + * Check for at least sizeof (long) control data portion. + */ + if (ctlp->len < sizeof (long)) + err("getmsg: control portion length < sizeof (long): %d", ctlp->len); +} + +expecting(prim, dlp) +int prim; +union DL_primitives *dlp; +{ + if (dlp->dl_primitive != (u_long)prim) { + printdlprim(dlp); + err("expected %s got %s", dlprim(prim), + dlprim(dlp->dl_primitive)); + exit(1); + } +} + +/* + * Print any DLPI msg in human readable format. + */ +printdlprim(dlp) +union DL_primitives *dlp; +{ + switch (dlp->dl_primitive) { + case DL_INFO_REQ: + printdlinforeq(dlp); + break; + + case DL_INFO_ACK: + printdlinfoack(dlp); + break; + + case DL_ATTACH_REQ: + printdlattachreq(dlp); + break; + + case DL_OK_ACK: + printdlokack(dlp); + break; + + case DL_ERROR_ACK: + printdlerrorack(dlp); + break; + + case DL_DETACH_REQ: + printdldetachreq(dlp); + break; + + case DL_BIND_REQ: + printdlbindreq(dlp); + break; + + case DL_BIND_ACK: + printdlbindack(dlp); + break; + + case DL_UNBIND_REQ: + printdlunbindreq(dlp); + break; + + case DL_SUBS_BIND_REQ: + printdlsubsbindreq(dlp); + break; + + case DL_SUBS_BIND_ACK: + printdlsubsbindack(dlp); + break; + + case DL_SUBS_UNBIND_REQ: + printdlsubsunbindreq(dlp); + break; + + case DL_ENABMULTI_REQ: + printdlenabmultireq(dlp); + break; + + case DL_DISABMULTI_REQ: + printdldisabmultireq(dlp); + break; + + case DL_PROMISCON_REQ: + printdlpromisconreq(dlp); + break; + + case DL_PROMISCOFF_REQ: + printdlpromiscoffreq(dlp); + break; + + case DL_UNITDATA_REQ: + printdlunitdatareq(dlp); + break; + + case DL_UNITDATA_IND: + printdlunitdataind(dlp); + break; + + case DL_UDERROR_IND: + printdluderrorind(dlp); + break; + + case DL_UDQOS_REQ: + printdludqosreq(dlp); + break; + + case DL_PHYS_ADDR_REQ: + printdlphysaddrreq(dlp); + break; + + case DL_PHYS_ADDR_ACK: + printdlphysaddrack(dlp); + break; + + case DL_SET_PHYS_ADDR_REQ: + printdlsetphysaddrreq(dlp); + break; + + default: + err("printdlprim: unknown primitive type 0x%x", + dlp->dl_primitive); + break; + } +} + +/* ARGSUSED */ +printdlinforeq(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_INFO_REQ\n"); +} + +printdlinfoack(dlp) +union DL_primitives *dlp; +{ + u_char addr[MAXDLADDR]; + u_char brdcst[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->info_ack.dl_addr_offset), + dlp->info_ack.dl_addr_length, addr); + addrtostring(OFFADDR(dlp, dlp->info_ack.dl_brdcst_addr_offset), + dlp->info_ack.dl_brdcst_addr_length, brdcst); + + (void) printf("DL_INFO_ACK: max_sdu %d min_sdu %d\n", + dlp->info_ack.dl_max_sdu, + dlp->info_ack.dl_min_sdu); + (void) printf("addr_length %d mac_type %s current_state %s\n", + dlp->info_ack.dl_addr_length, + dlmactype(dlp->info_ack.dl_mac_type), + dlstate(dlp->info_ack.dl_current_state)); + (void) printf("sap_length %d service_mode %s qos_length %d\n", + dlp->info_ack.dl_sap_length, + dlservicemode(dlp->info_ack.dl_service_mode), + dlp->info_ack.dl_qos_length); + (void) printf("qos_offset %d qos_range_length %d qos_range_offset %d\n", + dlp->info_ack.dl_qos_offset, + dlp->info_ack.dl_qos_range_length, + dlp->info_ack.dl_qos_range_offset); + (void) printf("provider_style %s addr_offset %d version %d\n", + dlstyle(dlp->info_ack.dl_provider_style), + dlp->info_ack.dl_addr_offset, + dlp->info_ack.dl_version); + (void) printf("brdcst_addr_length %d brdcst_addr_offset %d\n", + dlp->info_ack.dl_brdcst_addr_length, + dlp->info_ack.dl_brdcst_addr_offset); + (void) printf("addr %s\n", addr); + (void) printf("brdcst_addr %s\n", brdcst); +} + +printdlattachreq(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_ATTACH_REQ: ppa %d\n", + dlp->attach_req.dl_ppa); +} + +printdlokack(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_OK_ACK: correct_primitive %s\n", + dlprim(dlp->ok_ack.dl_correct_primitive)); +} + +printdlerrorack(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_ERROR_ACK: error_primitive %s errno %s unix_errno %d\n", + dlprim(dlp->error_ack.dl_error_primitive), + dlerrno(dlp->error_ack.dl_errno), + dlp->error_ack.dl_unix_errno); +} + +printdlenabmultireq(dlp) +union DL_primitives *dlp; +{ + u_char addr[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->enabmulti_req.dl_addr_offset), + dlp->enabmulti_req.dl_addr_length, addr); + + (void) printf("DL_ENABMULTI_REQ: addr_length %d addr_offset %d\n", + dlp->enabmulti_req.dl_addr_length, + dlp->enabmulti_req.dl_addr_offset); + (void) printf("addr %s\n", addr); +} + +printdldisabmultireq(dlp) +union DL_primitives *dlp; +{ + u_char addr[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->disabmulti_req.dl_addr_offset), + dlp->disabmulti_req.dl_addr_length, addr); + + (void) printf("DL_DISABMULTI_REQ: addr_length %d addr_offset %d\n", + dlp->disabmulti_req.dl_addr_length, + dlp->disabmulti_req.dl_addr_offset); + (void) printf("addr %s\n", addr); +} + +printdlpromisconreq(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_PROMISCON_REQ: level %s\n", + dlpromisclevel(dlp->promiscon_req.dl_level)); +} + +printdlpromiscoffreq(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_PROMISCOFF_REQ: level %s\n", + dlpromisclevel(dlp->promiscoff_req.dl_level)); +} + +printdlphysaddrreq(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_PHYS_ADDR_REQ: addr_type 0x%x\n", + dlp->physaddr_req.dl_addr_type); +} + +printdlphysaddrack(dlp) +union DL_primitives *dlp; +{ + u_char addr[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->physaddr_ack.dl_addr_offset), + dlp->physaddr_ack.dl_addr_length, addr); + + (void) printf("DL_PHYS_ADDR_ACK: addr_length %d addr_offset %d\n", + dlp->physaddr_ack.dl_addr_length, + dlp->physaddr_ack.dl_addr_offset); + (void) printf("addr %s\n", addr); +} + +printdlsetphysaddrreq(dlp) +union DL_primitives *dlp; +{ + u_char addr[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->set_physaddr_req.dl_addr_offset), + dlp->set_physaddr_req.dl_addr_length, addr); + + (void) printf("DL_SET_PHYS_ADDR_REQ: addr_length %d addr_offset %d\n", + dlp->set_physaddr_req.dl_addr_length, + dlp->set_physaddr_req.dl_addr_offset); + (void) printf("addr %s\n", addr); +} + +/* ARGSUSED */ +printdldetachreq(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_DETACH_REQ\n"); +} + +printdlbindreq(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_BIND_REQ: sap %d max_conind %d\n", + dlp->bind_req.dl_sap, + dlp->bind_req.dl_max_conind); + (void) printf("service_mode %s conn_mgmt %d xidtest_flg 0x%x\n", + dlservicemode(dlp->bind_req.dl_service_mode), + dlp->bind_req.dl_conn_mgmt, + dlp->bind_req.dl_xidtest_flg); +} + +printdlbindack(dlp) +union DL_primitives *dlp; +{ + u_char addr[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->bind_ack.dl_addr_offset), + dlp->bind_ack.dl_addr_length, addr); + + (void) printf("DL_BIND_ACK: sap %d addr_length %d addr_offset %d\n", + dlp->bind_ack.dl_sap, + dlp->bind_ack.dl_addr_length, + dlp->bind_ack.dl_addr_offset); + (void) printf("max_conind %d xidtest_flg 0x%x\n", + dlp->bind_ack.dl_max_conind, + dlp->bind_ack.dl_xidtest_flg); + (void) printf("addr %s\n", addr); +} + +/* ARGSUSED */ +printdlunbindreq(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_UNBIND_REQ\n"); +} + +printdlsubsbindreq(dlp) +union DL_primitives *dlp; +{ + u_char sap[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->subs_bind_req.dl_subs_sap_offset), + dlp->subs_bind_req.dl_subs_sap_length, sap); + + (void) printf("DL_SUBS_BIND_REQ: subs_sap_offset %d sub_sap_len %d\n", + dlp->subs_bind_req.dl_subs_sap_offset, + dlp->subs_bind_req.dl_subs_sap_length); + (void) printf("sap %s\n", sap); +} + +printdlsubsbindack(dlp) +union DL_primitives *dlp; +{ + u_char sap[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->subs_bind_ack.dl_subs_sap_offset), + dlp->subs_bind_ack.dl_subs_sap_length, sap); + + (void) printf("DL_SUBS_BIND_ACK: subs_sap_offset %d sub_sap_length %d\n", + dlp->subs_bind_ack.dl_subs_sap_offset, + dlp->subs_bind_ack.dl_subs_sap_length); + (void) printf("sap %s\n", sap); +} + +printdlsubsunbindreq(dlp) +union DL_primitives *dlp; +{ + u_char sap[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->subs_unbind_req.dl_subs_sap_offset), + dlp->subs_unbind_req.dl_subs_sap_length, sap); + + (void) printf("DL_SUBS_UNBIND_REQ: subs_sap_offset %d sub_sap_length %d\n", + dlp->subs_unbind_req.dl_subs_sap_offset, + dlp->subs_unbind_req.dl_subs_sap_length); + (void) printf("sap %s\n", sap); +} + +printdlunitdatareq(dlp) +union DL_primitives *dlp; +{ + u_char addr[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->unitdata_req.dl_dest_addr_offset), + dlp->unitdata_req.dl_dest_addr_length, addr); + + (void) printf("DL_UNITDATA_REQ: dest_addr_length %d dest_addr_offset %d\n", + dlp->unitdata_req.dl_dest_addr_length, + dlp->unitdata_req.dl_dest_addr_offset); + (void) printf("dl_priority.min %d dl_priority.max %d\n", + dlp->unitdata_req.dl_priority.dl_min, + dlp->unitdata_req.dl_priority.dl_max); + (void) printf("addr %s\n", addr); +} + +printdlunitdataind(dlp) +union DL_primitives *dlp; +{ + u_char dest[MAXDLADDR]; + u_char src[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->unitdata_ind.dl_dest_addr_offset), + dlp->unitdata_ind.dl_dest_addr_length, dest); + addrtostring(OFFADDR(dlp, dlp->unitdata_ind.dl_src_addr_offset), + dlp->unitdata_ind.dl_src_addr_length, src); + + (void) printf("DL_UNITDATA_IND: dest_addr_length %d dest_addr_offset %d\n", + dlp->unitdata_ind.dl_dest_addr_length, + dlp->unitdata_ind.dl_dest_addr_offset); + (void) printf("src_addr_length %d src_addr_offset %d\n", + dlp->unitdata_ind.dl_src_addr_length, + dlp->unitdata_ind.dl_src_addr_offset); + (void) printf("group_address 0x%x\n", + dlp->unitdata_ind.dl_group_address); + (void) printf("dest %s\n", dest); + (void) printf("src %s\n", src); +} + +printdluderrorind(dlp) +union DL_primitives *dlp; +{ + u_char addr[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->uderror_ind.dl_dest_addr_offset), + dlp->uderror_ind.dl_dest_addr_length, addr); + + (void) printf("DL_UDERROR_IND: dest_addr_length %d dest_addr_offset %d\n", + dlp->uderror_ind.dl_dest_addr_length, + dlp->uderror_ind.dl_dest_addr_offset); + (void) printf("unix_errno %d errno %s\n", + dlp->uderror_ind.dl_unix_errno, + dlerrno(dlp->uderror_ind.dl_errno)); + (void) printf("addr %s\n", addr); +} + +printdltestreq(dlp) +union DL_primitives *dlp; +{ + u_char addr[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->test_req.dl_dest_addr_offset), + dlp->test_req.dl_dest_addr_length, addr); + + (void) printf("DL_TEST_REQ: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", + dlp->test_req.dl_flag, + dlp->test_req.dl_dest_addr_length, + dlp->test_req.dl_dest_addr_offset); + (void) printf("dest_addr %s\n", addr); +} + +printdltestind(dlp) +union DL_primitives *dlp; +{ + u_char dest[MAXDLADDR]; + u_char src[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->test_ind.dl_dest_addr_offset), + dlp->test_ind.dl_dest_addr_length, dest); + addrtostring(OFFADDR(dlp, dlp->test_ind.dl_src_addr_offset), + dlp->test_ind.dl_src_addr_length, src); + + (void) printf("DL_TEST_IND: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", + dlp->test_ind.dl_flag, + dlp->test_ind.dl_dest_addr_length, + dlp->test_ind.dl_dest_addr_offset); + (void) printf("src_addr_length %d src_addr_offset %d\n", + dlp->test_ind.dl_src_addr_length, + dlp->test_ind.dl_src_addr_offset); + (void) printf("dest_addr %s\n", dest); + (void) printf("src_addr %s\n", src); +} + +printdltestres(dlp) +union DL_primitives *dlp; +{ + u_char dest[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->test_res.dl_dest_addr_offset), + dlp->test_res.dl_dest_addr_length, dest); + + (void) printf("DL_TEST_RES: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", + dlp->test_res.dl_flag, + dlp->test_res.dl_dest_addr_length, + dlp->test_res.dl_dest_addr_offset); + (void) printf("dest_addr %s\n", dest); +} + +printdltestcon(dlp) +union DL_primitives *dlp; +{ + u_char dest[MAXDLADDR]; + u_char src[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->test_con.dl_dest_addr_offset), + dlp->test_con.dl_dest_addr_length, dest); + addrtostring(OFFADDR(dlp, dlp->test_con.dl_src_addr_offset), + dlp->test_con.dl_src_addr_length, src); + + (void) printf("DL_TEST_CON: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", + dlp->test_con.dl_flag, + dlp->test_con.dl_dest_addr_length, + dlp->test_con.dl_dest_addr_offset); + (void) printf("src_addr_length %d src_addr_offset %d\n", + dlp->test_con.dl_src_addr_length, + dlp->test_con.dl_src_addr_offset); + (void) printf("dest_addr %s\n", dest); + (void) printf("src_addr %s\n", src); +} + +printdlxidreq(dlp) +union DL_primitives *dlp; +{ + u_char dest[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->xid_req.dl_dest_addr_offset), + dlp->xid_req.dl_dest_addr_length, dest); + + (void) printf("DL_XID_REQ: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", + dlp->xid_req.dl_flag, + dlp->xid_req.dl_dest_addr_length, + dlp->xid_req.dl_dest_addr_offset); + (void) printf("dest_addr %s\n", dest); +} + +printdlxidind(dlp) +union DL_primitives *dlp; +{ + u_char dest[MAXDLADDR]; + u_char src[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->xid_ind.dl_dest_addr_offset), + dlp->xid_ind.dl_dest_addr_length, dest); + addrtostring(OFFADDR(dlp, dlp->xid_ind.dl_src_addr_offset), + dlp->xid_ind.dl_src_addr_length, src); + + (void) printf("DL_XID_IND: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", + dlp->xid_ind.dl_flag, + dlp->xid_ind.dl_dest_addr_length, + dlp->xid_ind.dl_dest_addr_offset); + (void) printf("src_addr_length %d src_addr_offset %d\n", + dlp->xid_ind.dl_src_addr_length, + dlp->xid_ind.dl_src_addr_offset); + (void) printf("dest_addr %s\n", dest); + (void) printf("src_addr %s\n", src); +} + +printdlxidres(dlp) +union DL_primitives *dlp; +{ + u_char dest[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->xid_res.dl_dest_addr_offset), + dlp->xid_res.dl_dest_addr_length, dest); + + (void) printf("DL_XID_RES: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", + dlp->xid_res.dl_flag, + dlp->xid_res.dl_dest_addr_length, + dlp->xid_res.dl_dest_addr_offset); + (void) printf("dest_addr %s\n", dest); +} + +printdlxidcon(dlp) +union DL_primitives *dlp; +{ + u_char dest[MAXDLADDR]; + u_char src[MAXDLADDR]; + + addrtostring(OFFADDR(dlp, dlp->xid_con.dl_dest_addr_offset), + dlp->xid_con.dl_dest_addr_length, dest); + addrtostring(OFFADDR(dlp, dlp->xid_con.dl_src_addr_offset), + dlp->xid_con.dl_src_addr_length, src); + + (void) printf("DL_XID_CON: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", + dlp->xid_con.dl_flag, + dlp->xid_con.dl_dest_addr_length, + dlp->xid_con.dl_dest_addr_offset); + (void) printf("src_addr_length %d src_addr_offset %d\n", + dlp->xid_con.dl_src_addr_length, + dlp->xid_con.dl_src_addr_offset); + (void) printf("dest_addr %s\n", dest); + (void) printf("src_addr %s\n", src); +} + +printdludqosreq(dlp) +union DL_primitives *dlp; +{ + (void) printf("DL_UDQOS_REQ: qos_length %d qos_offset %d\n", + dlp->udqos_req.dl_qos_length, + dlp->udqos_req.dl_qos_offset); +} + +/* + * Return string. + */ +addrtostring(addr, length, s) +u_char *addr; +u_long length; +u_char *s; +{ + int i; + + for (i = 0; i < length; i++) { + (void) sprintf((char*) s, "%x:", addr[i] & 0xff); + s = s + strlen((char*)s); + } + if (length) + *(--s) = '\0'; +} + +/* + * Return length + */ +stringtoaddr(sp, addr) +char *sp; +char *addr; +{ + int n = 0; + char *p; + int val; + + p = sp; + while (p = strtok(p, ":")) { + if (sscanf(p, "%x", &val) != 1) + err("stringtoaddr: invalid input string: %s", sp); + if (val > 0xff) + err("stringtoaddr: invalid input string: %s", sp); + *addr++ = val; + n++; + p = NULL; + } + + return (n); +} + + +static char +hexnibble(c) +char c; +{ + static char hextab[] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f' + }; + + return (hextab[c & 0x0f]); +} + +char* +dlprim(prim) +u_long prim; +{ + static char primbuf[80]; + + switch ((int)prim) { + CASERET(DL_INFO_REQ); + CASERET(DL_INFO_ACK); + CASERET(DL_ATTACH_REQ); + CASERET(DL_DETACH_REQ); + CASERET(DL_BIND_REQ); + CASERET(DL_BIND_ACK); + CASERET(DL_UNBIND_REQ); + CASERET(DL_OK_ACK); + CASERET(DL_ERROR_ACK); + CASERET(DL_SUBS_BIND_REQ); + CASERET(DL_SUBS_BIND_ACK); + CASERET(DL_UNITDATA_REQ); + CASERET(DL_UNITDATA_IND); + CASERET(DL_UDERROR_IND); + CASERET(DL_UDQOS_REQ); + CASERET(DL_CONNECT_REQ); + CASERET(DL_CONNECT_IND); + CASERET(DL_CONNECT_RES); + CASERET(DL_CONNECT_CON); + CASERET(DL_TOKEN_REQ); + CASERET(DL_TOKEN_ACK); + CASERET(DL_DISCONNECT_REQ); + CASERET(DL_DISCONNECT_IND); + CASERET(DL_RESET_REQ); + CASERET(DL_RESET_IND); + CASERET(DL_RESET_RES); + CASERET(DL_RESET_CON); + default: + (void) sprintf(primbuf, "unknown primitive 0x%x", prim); + return (primbuf); + } +} + + +char* +dlstate(state) +u_long state; +{ + static char statebuf[80]; + + switch (state) { + CASERET(DL_UNATTACHED); + CASERET(DL_ATTACH_PENDING); + CASERET(DL_DETACH_PENDING); + CASERET(DL_UNBOUND); + CASERET(DL_BIND_PENDING); + CASERET(DL_UNBIND_PENDING); + CASERET(DL_IDLE); + CASERET(DL_UDQOS_PENDING); + CASERET(DL_OUTCON_PENDING); + CASERET(DL_INCON_PENDING); + CASERET(DL_CONN_RES_PENDING); + CASERET(DL_DATAXFER); + CASERET(DL_USER_RESET_PENDING); + CASERET(DL_PROV_RESET_PENDING); + CASERET(DL_RESET_RES_PENDING); + CASERET(DL_DISCON8_PENDING); + CASERET(DL_DISCON9_PENDING); + CASERET(DL_DISCON11_PENDING); + CASERET(DL_DISCON12_PENDING); + CASERET(DL_DISCON13_PENDING); + CASERET(DL_SUBS_BIND_PND); + default: + (void) sprintf(statebuf, "unknown state 0x%x", state); + return (statebuf); + } +} + +char* +dlerrno(errno) +u_long errno; +{ + static char errnobuf[80]; + + switch (errno) { + CASERET(DL_ACCESS); + CASERET(DL_BADADDR); + CASERET(DL_BADCORR); + CASERET(DL_BADDATA); + CASERET(DL_BADPPA); + CASERET(DL_BADPRIM); + CASERET(DL_BADQOSPARAM); + CASERET(DL_BADQOSTYPE); + CASERET(DL_BADSAP); + CASERET(DL_BADTOKEN); + CASERET(DL_BOUND); + CASERET(DL_INITFAILED); + CASERET(DL_NOADDR); + CASERET(DL_NOTINIT); + CASERET(DL_OUTSTATE); + CASERET(DL_SYSERR); + CASERET(DL_UNSUPPORTED); + CASERET(DL_UNDELIVERABLE); + CASERET(DL_NOTSUPPORTED); + CASERET(DL_TOOMANY); + CASERET(DL_NOTENAB); + CASERET(DL_BUSY); + CASERET(DL_NOAUTO); + CASERET(DL_NOXIDAUTO); + CASERET(DL_NOTESTAUTO); + CASERET(DL_XIDAUTO); + CASERET(DL_TESTAUTO); + CASERET(DL_PENDING); + + default: + (void) sprintf(errnobuf, "unknown dlpi errno 0x%x", errno); + return (errnobuf); + } +} + +char* +dlpromisclevel(level) +u_long level; +{ + static char levelbuf[80]; + + switch (level) { + CASERET(DL_PROMISC_PHYS); + CASERET(DL_PROMISC_SAP); + CASERET(DL_PROMISC_MULTI); + default: + (void) sprintf(levelbuf, "unknown promisc level 0x%x", level); + return (levelbuf); + } +} + +char* +dlservicemode(servicemode) +u_long servicemode; +{ + static char servicemodebuf[80]; + + switch (servicemode) { + CASERET(DL_CODLS); + CASERET(DL_CLDLS); + CASERET(DL_CODLS|DL_CLDLS); + default: + (void) sprintf(servicemodebuf, + "unknown provider service mode 0x%x", servicemode); + return (servicemodebuf); + } +} + +char* +dlstyle(style) +long style; +{ + static char stylebuf[80]; + + switch (style) { + CASERET(DL_STYLE1); + CASERET(DL_STYLE2); + default: + (void) sprintf(stylebuf, "unknown provider style 0x%x", style); + return (stylebuf); + } +} + +char* +dlmactype(media) +u_long media; +{ + static char mediabuf[80]; + + switch (media) { + CASERET(DL_CSMACD); + CASERET(DL_TPB); + CASERET(DL_TPR); + CASERET(DL_METRO); + CASERET(DL_ETHER); + CASERET(DL_HDLC); + CASERET(DL_CHAR); + CASERET(DL_CTCA); + default: + (void) sprintf(mediabuf, "unknown media type 0x%x", media); + return (mediabuf); + } +} + +/*VARARGS1*/ +err(fmt, a1, a2, a3, a4) +char *fmt; +char *a1, *a2, *a3, *a4; +{ + (void) fprintf(stderr, fmt, a1, a2, a3, a4); + (void) fprintf(stderr, "\n"); + (void) exit(1); +} + +syserr(s) +char *s; +{ + (void) perror(s); + exit(1); +} + +strioctl(fd, cmd, timout, len, dp) +int fd; +int cmd; +int timout; +int len; +char *dp; +{ + struct strioctl sioc; + int rc; + + sioc.ic_cmd = cmd; + sioc.ic_timout = timout; + sioc.ic_len = len; + sioc.ic_dp = dp; + rc = ioctl(fd, I_STR, &sioc); + + if (rc < 0) + return (rc); + else + return (sioc.ic_len); +} diff --git a/contrib/ipfilter/ipsend/dltest.h b/contrib/ipfilter/ipsend/dltest.h new file mode 100644 index 000000000000..4c32c30eb1bc --- /dev/null +++ b/contrib/ipfilter/ipsend/dltest.h @@ -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(); diff --git a/contrib/ipfilter/ipsend/in_var.h b/contrib/ipfilter/ipsend/in_var.h new file mode 100644 index 000000000000..63980ef304e3 --- /dev/null +++ b/contrib/ipfilter/ipsend/in_var.h @@ -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*/ diff --git a/contrib/ipfilter/ipsend/ip.c b/contrib/ipfilter/ipsend/ip.c new file mode 100644 index 000000000000..2c7f7ff3e019 --- /dev/null +++ b/contrib/ipfilter/ipsend/ip.c @@ -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 *)ð, 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 *)ð, 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); + } +} diff --git a/contrib/ipfilter/ipsend/ip_compat.h b/contrib/ipfilter/ipsend/ip_compat.h new file mode 100644 index 000000000000..c38fa59ed3c7 --- /dev/null +++ b/contrib/ipfilter/ipsend/ip_compat.h @@ -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 diff --git a/contrib/ipfilter/ipsend/ip_var.h b/contrib/ipfilter/ipsend/ip_var.h new file mode 100644 index 000000000000..92eb38a0befc --- /dev/null +++ b/contrib/ipfilter/ipsend/ip_var.h @@ -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*/ diff --git a/contrib/ipfilter/ipsend/ipresend.c b/contrib/ipfilter/ipsend/ipresend.c new file mode 100644 index 000000000000..6fd91bf4ff10 --- /dev/null +++ b/contrib/ipfilter/ipsend/ipresend.c @@ -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 = ðerf; + 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); +} diff --git a/contrib/ipfilter/ipsend/ipsend.c b/contrib/ipfilter/ipsend/ipsend.c new file mode 100644 index 000000000000..e45d3ee73adc --- /dev/null +++ b/contrib/ipfilter/ipsend/ipsend.c @@ -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); +} diff --git a/contrib/ipfilter/ipsend/ipsopt.c b/contrib/ipfilter/ipsend/ipsopt.c new file mode 100644 index 000000000000..75c4f1627a8e --- /dev/null +++ b/contrib/ipfilter/ipsend/ipsopt.c @@ -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; +} diff --git a/contrib/ipfilter/ipsend/iptest.c b/contrib/ipfilter/ipsend/iptest.c new file mode 100644 index 000000000000..c5d48fa83420 --- /dev/null +++ b/contrib/ipfilter/ipsend/iptest.c @@ -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; +} diff --git a/contrib/ipfilter/ipsend/iptests.c b/contrib/ipfilter/ipsend/iptests.c new file mode 100644 index 000000000000..b9da7b2ba82e --- /dev/null +++ b/contrib/ipfilter/ipsend/iptests.c @@ -0,0 +1,1296 @@ +/* + * (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 ? + */ +#if !defined(lint) && defined(LIBC_SCCS) +static char sccsid[] = "%W% %G% (C)1995 Darren Reed"; +#endif +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/param.h> +#if !defined(solaris) +# define _KERNEL +# define KERNEL +# include <sys/file.h> +# undef _KERNEL +# undef KERNEL +# include <nlist.h> +# include <sys/user.h> +# include <sys/proc.h> +#endif +#include <kvm.h> +#include <sys/socket.h> +#include <sys/socketvar.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 <netinet/in_systm.h> +#include <sys/socket.h> +#include <net/if.h> +#include <net/route.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netinet/ip.h> +#include <netinet/tcp.h> +#include <netinet/udp.h> +#include <netinet/ip_icmp.h> +#include <netinet/if_ether.h> +#include <netinet/ip_var.h> +#include <netinet/in_pcb.h> +#include <netinet/tcp_timer.h> +#include <netinet/tcp_var.h> +#include "ip_compat.h" +#ifdef linux +#include "tcpip.h" +#else +#include <netinet/tcpip.h> +# if defined(__SVR4) || defined(__svr4__) +#include <sys/sysmacros.h> +# endif +#endif + +#define PAUSE() tv.tv_sec = 0; tv.tv_usec = 10000; \ + (void) select(0, NULL, NULL, NULL, &tv) + +extern int send_ip(), send_tcp(), send_udp(), send_icmp(), send_ether(); +extern int initdevice(), kmemcpy(); +extern u_short chksum(); +extern struct tcpcb *find_tcp(); + +void ip_test1(dev, mtu, ip, gwip, ptest) +char *dev; +int mtu; +ip_t *ip; +struct in_addr gwip; +int ptest; +{ + struct timeval tv; + udphdr_t *u; + int nfd, i, len, id = getpid(); + + ip->ip_hl = sizeof(*ip) >> 2; + ip->ip_v = IPVERSION; + ip->ip_tos = 0; + ip->ip_off = 0; + ip->ip_ttl = 60; + ip->ip_p = IPPROTO_UDP; + ip->ip_sum = 0; + u = (udphdr_t *)(ip + 1); + u->uh_sport = 1; + u->uh_dport = 9; + u->uh_sum = 0; + u->uh_ulen = sizeof(*u) + 4; + ip->ip_len = sizeof(*ip) + u->uh_ulen; + len = ip->ip_len; + nfd = initdevice(dev, u->uh_sport, 1); + + u->uh_sport = htons(u->uh_sport); + u->uh_dport = htons(u->uh_dport); + u->uh_ulen = htons(u->uh_ulen); + if (!ptest || (ptest == 1)) { + /* + * Part1: hl < len + */ + ip->ip_id = 0; + printf("1.1. sending packets with ip_hl < ip_len\n"); + for (i = 0; i < ((sizeof(*ip) + u->uh_ulen) >> 2); i++) { + ip->ip_hl = i >> 2; + (void) send_ip(nfd, 1500, ip, gwip, 1); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + putchar('\n'); + } + + if (!ptest || (ptest == 2)) { + /* + * Part2: hl > len + */ + ip->ip_id = 0; + printf("1.2. sending packets with ip_hl > ip_len\n"); + for (; i < ((sizeof(*ip) * 2 + u->uh_ulen) >> 2); i++) { + ip->ip_hl = i >> 2; + (void) send_ip(nfd, 1500, ip, gwip, 1); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + putchar('\n'); + } + + if (!ptest || (ptest == 3)) { + /* + * Part3: v < 4 + */ + ip->ip_id = 0; + printf("1.3. ip_v < 4\n"); + ip->ip_hl = sizeof(*ip) >> 2; + for (i = 0; i < 4; i++) { + ip->ip_v = i; + (void) send_ip(nfd, 1500, ip, gwip, 1); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + putchar('\n'); + } + + if (!ptest || (ptest == 4)) { + /* + * Part4: v > 4 + */ + ip->ip_id = 0; + printf("1.4. ip_v > 4\n"); + for (i = 5; i < 16; i++) { + ip->ip_v = i; + (void) send_ip(nfd, 1500, ip, gwip, 1); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + putchar('\n'); + } + + if (!ptest || (ptest == 5)) { + /* + * Part5: len < packet + */ + ip->ip_id = 0; + ip->ip_v = IPVERSION; + i = ip->ip_len + 1; + ip->ip_len = htons(ip->ip_len); + ip->ip_off = htons(ip->ip_off); + printf("1.5.0 ip_len < packet size (size++, long packets)\n"); + for (; i < (ntohs(ip->ip_len) * 2); i++) { + ip->ip_id = htons(id++); + ip->ip_sum = 0; + ip->ip_sum = chksum(ip, ip->ip_hl << 2); + (void) send_ether(nfd, ip, i, gwip); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + putchar('\n'); + printf("1.5.1 ip_len < packet size (ip_len-, short packets)\n"); + for (i = len; i > 0; i--) { + ip->ip_id = htons(id++); + ip->ip_len = htons(i); + ip->ip_sum = 0; + ip->ip_sum = chksum(ip, ip->ip_hl << 2); + (void) send_ether(nfd, ip, len, gwip); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + putchar('\n'); + } + + if (!ptest || (ptest == 6)) { + /* + * Part6: len > packet + */ + ip->ip_id = 0; + printf("1.6.0 ip_len > packet size (increase ip_len)\n"); + for (i = len + 1; i < (len * 2); i++) { + ip->ip_id = htons(id++); + ip->ip_len = htons(i); + ip->ip_sum = 0; + ip->ip_sum = chksum(ip, ip->ip_hl << 2); + (void) send_ether(nfd, ip, len, gwip); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + putchar('\n'); + ip->ip_len = htons(len); + printf("1.6.1 ip_len > packet size (size--, short packets)\n"); + for (i = len; i > 0; i--) { + ip->ip_id = htons(id++); + ip->ip_sum = 0; + ip->ip_sum = chksum(ip, ip->ip_hl << 2); + (void) send_ether(nfd, ip, i, gwip); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + putchar('\n'); + } + + if (!ptest || (ptest == 7)) { + /* + * Part7: 0 length fragment + */ + printf("1.7.0 Zero length fragments (ip_off = 0x2000)\n"); + ip->ip_id = 0; + ip->ip_len = sizeof(*ip); + ip->ip_off = htons(IP_MF); + (void) send_ip(nfd, mtu, ip, gwip, 1); + fflush(stdout); + PAUSE(); + + printf("1.7.1 Zero length fragments (ip_off = 0x3000)\n"); + ip->ip_id = 0; + ip->ip_len = sizeof(*ip); + ip->ip_off = htons(IP_MF); + (void) send_ip(nfd, mtu, ip, gwip, 1); + fflush(stdout); + PAUSE(); + + printf("1.7.2 Zero length fragments (ip_off = 0xa000)\n"); + ip->ip_id = 0; + ip->ip_len = sizeof(*ip); + ip->ip_off = htons(0xa000); + (void) send_ip(nfd, mtu, ip, gwip, 1); + fflush(stdout); + PAUSE(); + + printf("1.7.3 Zero length fragments (ip_off = 0x0100)\n"); + ip->ip_id = 0; + ip->ip_len = sizeof(*ip); + ip->ip_off = htons(0x0100); + (void) send_ip(nfd, mtu, ip, gwip, 1); + fflush(stdout); + PAUSE(); + } + + if (!ptest || (ptest == 8)) { + struct timeval tv; + + gettimeofday(&tv, NULL); + srand(tv.tv_sec ^ getpid() ^ tv.tv_usec); + /* + * Part8.1: 63k packet + 1k fragment at offset 0x1ffe + * Mark it as being ICMP (so it doesn't get junked), but + * don't bother about the ICMP header, we're not worrying + * about that here. + */ + ip->ip_p = IPPROTO_ICMP; + ip->ip_off = IP_MF; + u->uh_dport = htons(9); + ip->ip_id = htons(id++); + printf("1.8.1 63k packet + 1k fragment at offset 0x1ffe\n"); + ip->ip_len = 768 + 20 + 8; + (void) send_ip(nfd, mtu, ip, gwip, 1); + printf("%d\r", i); + + ip->ip_len = MIN(768 + 20, mtu - 68); + i = 512; + for (; i < (63 * 1024 + 768); i += 768) { + ip->ip_off = IP_MF | (i >> 3); + (void) send_ip(nfd, mtu, ip, gwip, 1); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + ip->ip_len = 896 + 20; + ip->ip_off = (i >> 3); + (void) send_ip(nfd, mtu, ip, gwip, 1); + printf("%d\r", i); + putchar('\n'); + fflush(stdout); + + /* + * Part8.2: 63k packet + 1k fragment at offset 0x1ffe + * Mark it as being ICMP (so it doesn't get junked), but + * don't bother about the ICMP header, we're not worrying + * about that here. (Lossage here) + */ + ip->ip_p = IPPROTO_ICMP; + ip->ip_off = IP_MF; + u->uh_dport = htons(9); + ip->ip_id = htons(id++); + printf("1.8.2 63k packet + 1k fragment at offset 0x1ffe\n"); + ip->ip_len = 768 + 20 + 8; + if ((rand() & 0x1f) != 0) { + (void) send_ip(nfd, mtu, ip, gwip, 1); + printf("%d\r", i); + } else + printf("skip 0\n"); + + ip->ip_len = MIN(768 + 20, mtu - 68); + i = 512; + for (; i < (63 * 1024 + 768); i += 768) { + ip->ip_off = IP_MF | (i >> 3); + if ((rand() & 0x1f) != 0) { + (void) send_ip(nfd, mtu, ip, gwip, 1); + printf("%d\r", i); + } else + printf("skip %d\n", i); + fflush(stdout); + PAUSE(); + } + ip->ip_len = 896 + 20; + ip->ip_off = (i >> 3); + if ((rand() & 0x1f) != 0) { + (void) send_ip(nfd, mtu, ip, gwip, 1); + printf("%d\r", i); + } else + printf("skip\n"); + putchar('\n'); + fflush(stdout); + + /* + * Part8.3: 33k packet - test for not dealing with -ve length + * Mark it as being ICMP (so it doesn't get junked), but + * don't bother about the ICMP header, we're not worrying + * about that here. + */ + ip->ip_p = IPPROTO_ICMP; + ip->ip_off = IP_MF; + u->uh_dport = htons(9); + ip->ip_id = htons(id++); + printf("1.8.3 33k packet\n"); + ip->ip_len = 768 + 20 + 8; + (void) send_ip(nfd, mtu, ip, gwip, 1); + printf("%d\r", i); + + ip->ip_len = MIN(768 + 20, mtu - 68); + i = 512; + for (; i < (32 * 1024 + 768); i += 768) { + ip->ip_off = IP_MF | (i >> 3); + (void) send_ip(nfd, mtu, ip, gwip, 1); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + ip->ip_len = 896 + 20; + ip->ip_off = (i >> 3); + (void) send_ip(nfd, mtu, ip, gwip, 1); + printf("%d\r", i); + putchar('\n'); + fflush(stdout); + } + + ip->ip_len = len; + ip->ip_off = 0; + if (!ptest || (ptest == 9)) { + /* + * Part9: off & 0x8000 == 0x8000 + */ + ip->ip_id = 0; + ip->ip_off = 0x8000; + printf("1.9. ip_off & 0x8000 == 0x8000\n"); + (void) send_ip(nfd, mtu, ip, gwip, 1); + fflush(stdout); + PAUSE(); + } + + ip->ip_off = 0; + + if (!ptest || (ptest == 10)) { + /* + * Part10: ttl = 255 + */ + ip->ip_id = 0; + ip->ip_ttl = 255; + printf("1.10.0 ip_ttl = 255\n"); + (void) send_ip(nfd, mtu, ip, gwip, 1); + fflush(stdout); + PAUSE(); + + ip->ip_ttl = 128; + printf("1.10.1 ip_ttl = 128\n"); + (void) send_ip(nfd, mtu, ip, gwip, 1); + fflush(stdout); + PAUSE(); + + ip->ip_ttl = 0; + printf("1.10.2 ip_ttl = 0\n"); + (void) send_ip(nfd, mtu, ip, gwip, 1); + fflush(stdout); + PAUSE(); + } + + (void) close(nfd); +} + + +void ip_test2(dev, mtu, ip, gwip, ptest) +char *dev; +int mtu; +ip_t *ip; +struct in_addr gwip; +int ptest; +{ + struct timeval tv; + int nfd; + u_char *s; + + s = (u_char *)(ip + 1); + nfd = initdevice(dev, 1, 1); + + ip->ip_hl = 6; + ip->ip_len = ip->ip_hl << 2; + s[IPOPT_OPTVAL] = IPOPT_NOP; + s++; + if (!ptest || (ptest == 1)) { + /* + * Test 1: option length > packet length, + * header length == packet length + */ + s[IPOPT_OPTVAL] = IPOPT_TS; + s[IPOPT_OLEN] = 4; + s[IPOPT_OFFSET] = IPOPT_MINOFF; + ip->ip_p = IPPROTO_IP; + printf("2.1 option length > packet length\n"); + (void) send_ip(nfd, mtu, ip, gwip, 1); + fflush(stdout); + PAUSE(); + } + + ip->ip_hl = 7; + ip->ip_len = ip->ip_hl << 2; + if (!ptest || (ptest == 1)) { + /* + * Test 2: options have length = 0 + */ + printf("2.2.1 option length = 0, RR\n"); + s[IPOPT_OPTVAL] = IPOPT_RR; + s[IPOPT_OLEN] = 0; + (void) send_ip(nfd, mtu, ip, gwip, 1); + fflush(stdout); + PAUSE(); + + printf("2.2.2 option length = 0, TS\n"); + s[IPOPT_OPTVAL] = IPOPT_TS; + s[IPOPT_OLEN] = 0; + (void) send_ip(nfd, mtu, ip, gwip, 1); + fflush(stdout); + PAUSE(); + + printf("2.2.3 option length = 0, SECURITY\n"); + s[IPOPT_OPTVAL] = IPOPT_SECURITY; + s[IPOPT_OLEN] = 0; + (void) send_ip(nfd, mtu, ip, gwip, 1); + fflush(stdout); + PAUSE(); + + printf("2.2.4 option length = 0, LSRR\n"); + s[IPOPT_OPTVAL] = IPOPT_LSRR; + s[IPOPT_OLEN] = 0; + (void) send_ip(nfd, mtu, ip, gwip, 1); + fflush(stdout); + PAUSE(); + + printf("2.2.5 option length = 0, SATID\n"); + s[IPOPT_OPTVAL] = IPOPT_SATID; + s[IPOPT_OLEN] = 0; + (void) send_ip(nfd, mtu, ip, gwip, 1); + fflush(stdout); + PAUSE(); + + printf("2.2.6 option length = 0, SSRR\n"); + s[IPOPT_OPTVAL] = IPOPT_SSRR; + s[IPOPT_OLEN] = 0; + (void) send_ip(nfd, mtu, ip, gwip, 1); + fflush(stdout); + PAUSE(); + } + + (void) close(nfd); +} + + +/* + * test 3 (ICMP) + */ +void ip_test3(dev, mtu, ip, gwip, ptest) +char *dev; +int mtu; +ip_t *ip; +struct in_addr gwip; +int ptest; +{ + static int ict1[10] = { 8, 9, 10, 13, 14, 15, 16, 17, 18, 0 }; + static int ict2[8] = { 3, 9, 10, 13, 14, 17, 18, 0 }; + struct timeval tv; + struct icmp *icp; + int nfd, i; + + ip->ip_hl = sizeof(*ip) >> 2; + ip->ip_v = IPVERSION; + ip->ip_tos = 0; + ip->ip_off = 0; + ip->ip_ttl = 60; + ip->ip_p = IPPROTO_ICMP; + ip->ip_sum = 0; + ip->ip_len = sizeof(*ip) + sizeof(*icp); + icp = (struct icmp *)((char *)ip + (ip->ip_hl << 2)); + nfd = initdevice(dev, 1, 1); + + if (!ptest || (ptest == 1)) { + /* + * Type 0 - 31, 255, code = 0 + */ + bzero((char *)icp, sizeof(*icp)); + for (i = 0; i < 32; i++) { + icp->icmp_type = i; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.1.%d ICMP type %d code 0 (all 0's)\r", i, i); + } + icp->icmp_type = 255; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.1.%d ICMP type %d code 0 (all 0's)\r", i, 255); + putchar('\n'); + } + + if (!ptest || (ptest == 2)) { + /* + * Type 3, code = 0 - 31 + */ + icp->icmp_type = 3; + for (i = 0; i < 32; i++) { + icp->icmp_code = i; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.2.%d ICMP type 3 code %d (all 0's)\r", i, i); + } + } + + if (!ptest || (ptest == 3)) { + /* + * Type 4, code = 0,127,128,255 + */ + icp->icmp_type = 4; + icp->icmp_code = 0; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.3.1 ICMP type 4 code 0 (all 0's)\r"); + icp->icmp_code = 127; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.3.2 ICMP type 4 code 127 (all 0's)\r"); + icp->icmp_code = 128; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.3.3 ICMP type 4 code 128 (all 0's)\r"); + icp->icmp_code = 255; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.3.4 ICMP type 4 code 255 (all 0's)\r"); + } + + if (!ptest || (ptest == 4)) { + /* + * Type 5, code = 0,127,128,255 + */ + icp->icmp_type = 5; + icp->icmp_code = 0; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.4.1 ICMP type 5 code 0 (all 0's)\r"); + icp->icmp_code = 127; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.4.2 ICMP type 5 code 127 (all 0's)\r"); + icp->icmp_code = 128; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.4.3 ICMP type 5 code 128 (all 0's)\r"); + icp->icmp_code = 255; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.4.4 ICMP type 5 code 255 (all 0's)\r"); + } + + if (!ptest || (ptest == 5)) { + /* + * Type 8-10;13-18, code - 0,127,128,255 + */ + for (i = 0; ict1[i]; i++) { + icp->icmp_type = ict1[i]; + icp->icmp_code = 0; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.5.%d ICMP type 5 code 0 (all 0's)\r", + i * 4); + icp->icmp_code = 127; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.5.%d ICMP type 5 code 127 (all 0's)\r", + i * 4 + 1); + icp->icmp_code = 128; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.5.%d ICMP type 5 code 128 (all 0's)\r", + i * 4 + 2); + icp->icmp_code = 255; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.5.%d ICMP type 5 code 255 (all 0's)\r", + i * 4 + 3); + } + putchar('\n'); + } + + if (!ptest || (ptest == 6)) { + /* + * Type 12, code - 0,127,128,129,255 + */ + icp->icmp_type = 12; + icp->icmp_code = 0; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.6.1 ICMP type 12 code 0 (all 0's)\r"); + icp->icmp_code = 127; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.6.2 ICMP type 12 code 127 (all 0's)\r"); + icp->icmp_code = 128; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.6.3 ICMP type 12 code 128 (all 0's)\r"); + icp->icmp_code = 129; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.6.4 ICMP type 12 code 129 (all 0's)\r"); + icp->icmp_code = 255; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.6.5 ICMP type 12 code 255 (all 0's)\r"); + putchar('\n'); + } + + if (!ptest || (ptest == 7)) { + /* + * Type 3;9-10;13-14;17-18 - shorter packets + */ + ip->ip_len = sizeof(*ip) + sizeof(*icp) / 2; + for (i = 0; ict2[i]; i++) { + icp->icmp_type = ict1[i]; + icp->icmp_code = 0; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.5.%d ICMP type %d code 0 (all 0's)\r", + i * 4, icp->icmp_type); + icp->icmp_code = 127; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.5.%d ICMP type %d code 127 (all 0's)\r", + i * 4 + 1, icp->icmp_type); + icp->icmp_code = 128; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.5.%d ICMP type %d code 128 (all 0's)\r", + i * 4 + 2, icp->icmp_type); + icp->icmp_code = 255; + (void) send_icmp(nfd, mtu, ip, gwip); + PAUSE(); + printf("3.5.%d ICMP type %d code 127 (all 0's)\r", + i * 4 + 3, icp->icmp_type); + } + putchar('\n'); + } +} + + +/* Perform test 4 (UDP) */ + +void ip_test4(dev, mtu, ip, gwip, ptest) +char *dev; +int mtu; +ip_t *ip; +struct in_addr gwip; +int ptest; +{ + struct timeval tv; + struct udphdr *u; + int nfd, i; + + + ip->ip_hl = sizeof(*ip) >> 2; + ip->ip_v = IPVERSION; + ip->ip_tos = 0; + ip->ip_off = 0; + ip->ip_ttl = 60; + ip->ip_p = IPPROTO_UDP; + ip->ip_sum = 0; + u = (udphdr_t *)((char *)ip + (ip->ip_hl << 2)); + u->uh_sport = 1; + u->uh_dport = 1; + u->uh_ulen = sizeof(*u) + 4; + nfd = initdevice(dev, u->uh_sport, 1); + + if (!ptest || (ptest == 1)) { + /* + * Test 1. ulen > packet + */ + u->uh_ulen = sizeof(*u) + 4; + ip->ip_len = (ip->ip_hl << 2) + u->uh_ulen; + printf("4.1 UDP uh_ulen > packet size - short packets\n"); + for (i = u->uh_ulen * 2; i > sizeof(*u) + 4; i--) { + u->uh_ulen = i; + (void) send_udp(nfd, 1500, ip, gwip); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + putchar('\n'); + } + + if (!ptest || (ptest == 2)) { + /* + * Test 2. ulen < packet + */ + u->uh_ulen = sizeof(*u) + 4; + ip->ip_len = (ip->ip_hl << 2) + u->uh_ulen; + printf("4.2 UDP uh_ulen < packet size - short packets\n"); + for (i = u->uh_ulen * 2; i > sizeof(*u) + 4; i--) { + ip->ip_len = i; + (void) send_udp(nfd, 1500, ip, gwip); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + putchar('\n'); + } + + if (!ptest || (ptest == 3)) { + /* + * Test 3: sport = 0, sport = 1, sport = 32767 + * sport = 32768, sport = 65535 + */ + u->uh_ulen = sizeof(*u) + 4; + ip->ip_len = (ip->ip_hl << 2) + u->uh_ulen; + printf("4.3.1 UDP sport = 0\n"); + u->uh_sport = 0; + (void) send_udp(nfd, 1500, ip, gwip); + printf("0\n"); + fflush(stdout); + PAUSE(); + printf("4.3.2 UDP sport = 1\n"); + u->uh_sport = 1; + (void) send_udp(nfd, 1500, ip, gwip); + printf("1\n"); + fflush(stdout); + PAUSE(); + printf("4.3.3 UDP sport = 32767\n"); + u->uh_sport = 32767; + (void) send_udp(nfd, 1500, ip, gwip); + printf("32767\n"); + fflush(stdout); + PAUSE(); + printf("4.3.4 UDP sport = 32768\n"); + u->uh_sport = 32768; + (void) send_udp(nfd, 1500, ip, gwip); + printf("32768\n"); + putchar('\n'); + fflush(stdout); + PAUSE(); + printf("4.3.5 UDP sport = 65535\n"); + u->uh_sport = 65535; + (void) send_udp(nfd, 1500, ip, gwip); + printf("65535\n"); + fflush(stdout); + PAUSE(); + } + + if (!ptest || (ptest == 4)) { + /* + * Test 4: dport = 0, dport = 1, dport = 32767 + * dport = 32768, dport = 65535 + */ + u->uh_ulen = sizeof(*u) + 4; + u->uh_sport = 1; + ip->ip_len = (ip->ip_hl << 2) + u->uh_ulen; + printf("4.4.1 UDP dport = 0\n"); + u->uh_dport = 0; + (void) send_udp(nfd, 1500, ip, gwip); + printf("0\n"); + fflush(stdout); + PAUSE(); + printf("4.4.2 UDP dport = 1\n"); + u->uh_dport = 1; + (void) send_udp(nfd, 1500, ip, gwip); + printf("1\n"); + fflush(stdout); + PAUSE(); + printf("4.4.3 UDP dport = 32767\n"); + u->uh_dport = 32767; + (void) send_udp(nfd, 1500, ip, gwip); + printf("32767\n"); + fflush(stdout); + PAUSE(); + printf("4.4.4 UDP dport = 32768\n"); + u->uh_dport = 32768; + (void) send_udp(nfd, 1500, ip, gwip); + printf("32768\n"); + fflush(stdout); + PAUSE(); + printf("4.4.5 UDP dport = 65535\n"); + u->uh_dport = 65535; + (void) send_udp(nfd, 1500, ip, gwip); + printf("65535\n"); + fflush(stdout); + PAUSE(); + } + + if (!ptest || (ptest == 4)) { + /* + * Test 5: sizeof(struct ip) <= MTU <= sizeof(struct udphdr) + + * sizeof(struct ip) + */ + printf("4.5 UDP 20 <= MTU <= 32\n"); + for (i = sizeof(*ip); i <= u->uh_ulen; i++) { + (void) send_udp(nfd, i, ip, gwip); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + putchar('\n'); + } +} + + +/* Perform test 5 (TCP) */ + +void ip_test5(dev, mtu, ip, gwip, ptest) +char *dev; +int mtu; +ip_t *ip; +struct in_addr gwip; +int ptest; +{ + struct timeval tv; + tcphdr_t *t; + int nfd, i; + + t = (tcphdr_t *)((char *)ip + (ip->ip_hl << 2)); + t->th_x2 = 0; + t->th_off = 0; + t->th_sport = 1; + t->th_dport = 1; + t->th_win = 4096; + t->th_urp = 0; + t->th_sum = 0; + t->th_seq = 1; + t->th_ack = 0; + nfd = initdevice(dev, t->th_sport, 1); + + if (!ptest || (ptest == 1)) { + /* + * Test 1: flags variations, 0 - 3f + */ + t->th_off = sizeof(*t) >> 2; + printf("5.1 Test TCP flag combinations\n"); + for (i = 0; i <= (TH_URG|TH_ACK|TH_PUSH|TH_RST|TH_SYN|TH_FIN); + i++) { + t->th_flags = i; + (void) send_tcp(nfd, mtu, ip, gwip); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + putchar('\n'); + } + + if (!ptest || (ptest == 2)) { + t->th_flags = TH_SYN; + /* + * Test 2: seq = 0, seq = 1, seq = 0x7fffffff, seq=0x80000000, + * seq = 0xa000000, seq = 0xffffffff + */ + printf("5.2.1 TCP seq = 0\n"); + t->th_seq = 0; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.2.2 TCP seq = 1\n"); + t->th_seq = 1; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.2.3 TCP seq = 0x7fffffff\n"); + t->th_seq = 0x7fffffff; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.2.4 TCP seq = 0x80000000\n"); + t->th_seq = 0x80000000; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.2.5 TCP seq = 0xc0000000\n"); + t->th_seq = 0xc0000000; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.2.6 TCP seq = 0xffffffff\n"); + t->th_seq = 0xffffffff; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + } + + if (!ptest || (ptest == 3)) { + t->th_flags = TH_ACK; + /* + * Test 3: ack = 0, ack = 1, ack = 0x7fffffff, ack = 0x8000000 + * ack = 0xa000000, ack = 0xffffffff + */ + printf("5.3.1 TCP ack = 0\n"); + t->th_ack = 0; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.3.2 TCP ack = 1\n"); + t->th_ack = 1; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.3.3 TCP ack = 0x7fffffff\n"); + t->th_ack = 0x7fffffff; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.3.4 TCP ack = 0x80000000\n"); + t->th_ack = 0x80000000; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.3.5 TCP ack = 0xc0000000\n"); + t->th_ack = 0xc0000000; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.3.6 TCP ack = 0xffffffff\n"); + t->th_ack = 0xffffffff; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + } + + if (!ptest || (ptest == 4)) { + t->th_flags = TH_SYN; + /* + * Test 4: win = 0, win = 32768, win = 65535 + */ + printf("5.4.1 TCP win = 0\n"); + t->th_seq = 0; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.4.2 TCP win = 32768\n"); + t->th_seq = 0x7fff; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.4.3 TCP win = 65535\n"); + t->th_win = 0xffff; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + } + +#if !defined(linux) && !defined(__SVR4) && !defined(__svr4__) + { + struct tcpcb *t, tcb; + struct tcpiphdr ti; + struct sockaddr_in sin; + int fd, slen; + + bzero((char *)&sin, sizeof(sin)); + + for (i = 1; i < 63; i++) { + fd = socket(AF_INET, SOCK_STREAM, 0); + sin.sin_addr.s_addr = ip->ip_dst.s_addr; + sin.sin_port = htons(i); + if (!connect(fd, (struct sockaddr *)&sin, sizeof(sin))) + break; + } + + if (i == 63) { + printf("Couldn't open a TCP socket between ports 1 and 63\n"); + printf("to host %s for test 5 and 6 - skipping.\n", + inet_ntoa(ip->ip_dst)); + goto skip_five_and_six; + } + + bcopy((char *)ip, (char *)&ti, sizeof(*ip)); + ti.ti_dport = i; + slen = sizeof(sin); + if (!getsockname(fd, (struct sockaddr *)&sin, &slen)) + ti.ti_sport = sin.sin_port; + if (!(t = find_tcp(fd, &ti))) { + printf("Can't find PCB\n"); + goto skip_five_and_six; + } + 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 (!ptest || (ptest == 5)) { + /* + * Test 5: urp + */ + printf("5.1 TCP Urgent pointer\n"); + ti.ti_urp = 1; + (void) send_tcp(nfd, mtu, ip, gwip); + PAUSE(); + ti.ti_urp = 0x7fff; + (void) send_tcp(nfd, mtu, ip, gwip); + PAUSE(); + ti.ti_urp = 0x8000; + (void) send_tcp(nfd, mtu, ip, gwip); + PAUSE(); + ti.ti_urp = 0xffff; + (void) send_tcp(nfd, mtu, ip, gwip); + PAUSE(); + } + + if (!ptest || (ptest == 6)) { + /* + * Test 6: data offset, off = 0, off is inside, off is outside + */ + printf("6.1 TCP off = 0-15, len = 40\n"); + for (i = 0; i < 16; i++) { + ti.ti_off = ntohs(i); + (void) send_tcp(nfd, mtu, ip, gwip); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + putchar('\n'); + } + + (void) close(fd); + } +skip_five_and_six: +#endif + t->th_seq = 1; + t->th_ack = 1; + + if (!ptest || (ptest == 7)) { + t->th_off = 0; + t->th_flags = TH_SYN; + /* + * Test 7: sport = 0, sport = 1, sport = 32767 + * sport = 32768, sport = 65535 + */ + printf("5.7.1 TCP sport = 0\n"); + t->th_sport = 0; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.7.2 TCP sport = 1\n"); + t->th_sport = 1; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.7.3 TCP sport = 32767\n"); + t->th_sport = 32767; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.7.4 TCP sport = 32768\n"); + t->th_sport = 32768; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.7.5 TCP sport = 65535\n"); + t->th_sport = 65535; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + } + + if (!ptest || (ptest == 8)) { + t->th_sport = 1; + /* + * Test 8: dport = 0, dport = 1, dport = 32767 + * dport = 32768, dport = 65535 + */ + printf("5.8.1 TCP dport = 0\n"); + t->th_dport = 0; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.8.2 TCP dport = 1\n"); + t->th_dport = 1; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.8.3 TCP dport = 32767\n"); + t->th_dport = 32767; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.8.4 TCP dport = 32768\n"); + t->th_dport = 32768; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + + printf("5.8.5 TCP dport = 65535\n"); + t->th_dport = 65535; + (void) send_tcp(nfd, mtu, ip, gwip); + fflush(stdout); + PAUSE(); + } + /* TCP options header checking */ + /* 0 length options, etc */ +} + + +/* Perform test 6 (exhaust mbuf test) */ + +void ip_test6(dev, mtu, ip, gwip, ptest) +char *dev; +int mtu; +ip_t *ip; +struct in_addr gwip; +int ptest; +{ + struct timeval tv; + udphdr_t *u; + int nfd, i, j, k; + + ip->ip_v = IPVERSION; + ip->ip_tos = 0; + ip->ip_off = 0; + ip->ip_ttl = 60; + ip->ip_p = IPPROTO_UDP; + ip->ip_sum = 0; + u = (udphdr_t *)(ip + 1); + u->uh_sport = 1; + u->uh_dport = 9; + u->uh_sum = 0; + + nfd = initdevice(dev, u->uh_sport, 1); + u->uh_sport = htons(u->uh_sport); + u->uh_dport = htons(u->uh_dport); + u->uh_ulen = 7168; + + for (i = 0; i < 128; i++) { + /* + * First send the entire packet in 768 byte chunks. + */ + ip->ip_len = sizeof(*ip) + 768 + sizeof(*u); + ip->ip_hl = sizeof(*ip) >> 2; + ip->ip_off = IP_MF; + (void) send_ip(nfd, 1500, ip, gwip, 1); + printf("%d %d\r", i, 0); + fflush(stdout); + PAUSE(); + /* + * And again using 128 byte chunks. + */ + ip->ip_len = sizeof(*ip) + 128 + sizeof(*u); + ip->ip_off = IP_MF; + (void) send_ip(nfd, 1500, ip, gwip, 1); + printf("%d %d\r", i, 0); + fflush(stdout); + PAUSE(); + + for (j = 768; j < 3584; j += 768) { + ip->ip_len = sizeof(*ip) + 768; + ip->ip_off = IP_MF|(j>>3); + (void) send_ip(nfd, 1500, ip, gwip, 1); + printf("%d %d\r", i, j); + fflush(stdout); + PAUSE(); + + ip->ip_len = sizeof(*ip) + 128; + for (k = j - 768; k < j; k += 128) { + ip->ip_off = IP_MF|(k>>3); + (void) send_ip(nfd, 1500, ip, gwip, 1); + printf("%d %d\r", i, k); + fflush(stdout); + PAUSE(); + } + } + } + putchar('\n'); +} + + +/* Perform test 7 (random packets) */ + +static u_long tbuf[64]; + +void ip_test7(dev, mtu, ip, gwip, ptest) +char *dev; +int mtu; +ip_t *ip; +struct in_addr gwip; +int ptest; +{ + ip_t *pip; + struct timeval tv; + int nfd, i, j; + u_char *s; + + nfd = initdevice(dev, 0, 1); + pip = (ip_t *)tbuf; + + srand(time(NULL) ^ (getpid() * getppid())); + + printf("7. send 1024 random IP packets.\n"); + + for (i = 0; i < 512; i++) { + for (s = (u_char *)pip, j = 0; j < sizeof(tbuf); j++, s++) + *s = (rand() >> 13) & 0xff; + pip->ip_v = IPVERSION; + bcopy((char *)&ip->ip_dst, (char *)&pip->ip_dst, + sizeof(struct in_addr)); + pip->ip_sum = 0; + pip->ip_len &= 0xff; + (void) send_ip(nfd, mtu, pip, gwip, 0); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + putchar('\n'); + + for (i = 0; i < 512; i++) { + for (s = (u_char *)pip, j = 0; j < sizeof(tbuf); j++, s++) + *s = (rand() >> 13) & 0xff; + pip->ip_v = IPVERSION; + pip->ip_off &= 0xc000; + bcopy((char *)&ip->ip_dst, (char *)&pip->ip_dst, + sizeof(struct in_addr)); + pip->ip_sum = 0; + pip->ip_len &= 0xff; + (void) send_ip(nfd, mtu, pip, gwip, 0); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + putchar('\n'); +} diff --git a/contrib/ipfilter/ipsend/larp.c b/contrib/ipfilter/ipsend/larp.c new file mode 100644 index 000000000000..1eb4b2fe3e7a --- /dev/null +++ b/contrib/ipfilter/ipsend/larp.c @@ -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; +} diff --git a/contrib/ipfilter/ipsend/linux.h b/contrib/ipfilter/ipsend/linux.h new file mode 100644 index 000000000000..7eb382b4b7e1 --- /dev/null +++ b/contrib/ipfilter/ipsend/linux.h @@ -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" diff --git a/contrib/ipfilter/ipsend/lsock.c b/contrib/ipfilter/ipsend/lsock.c new file mode 100644 index 000000000000..89b6ab7e4e32 --- /dev/null +++ b/contrib/ipfilter/ipsend/lsock.c @@ -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; +} diff --git a/contrib/ipfilter/ipsend/resend.c b/contrib/ipfilter/ipsend/resend.c new file mode 100644 index 000000000000..59ed75ef082c --- /dev/null +++ b/contrib/ipfilter/ipsend/resend.c @@ -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; +} diff --git a/contrib/ipfilter/ipsend/sbpf.c b/contrib/ipfilter/ipsend/sbpf.c new file mode 100644 index 000000000000..5eb9d9b1f97d --- /dev/null +++ b/contrib/ipfilter/ipsend/sbpf.c @@ -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; +} diff --git a/contrib/ipfilter/ipsend/sdlpi.c b/contrib/ipfilter/ipsend/sdlpi.c new file mode 100644 index 000000000000..eabd61eb7344 --- /dev/null +++ b/contrib/ipfilter/ipsend/sdlpi.c @@ -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; +} diff --git a/contrib/ipfilter/ipsend/slinux.c b/contrib/ipfilter/ipsend/slinux.c new file mode 100644 index 000000000000..1767dfeb9ba2 --- /dev/null +++ b/contrib/ipfilter/ipsend/slinux.c @@ -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; +} + + +/* |