diff --git a/contrib/ipfilter/FWTK/FWTK.sed b/contrib/ipfilter/FWTK/FWTK.sed new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/contrib/ipfilter/FWTK/ftp-gw.diff b/contrib/ipfilter/FWTK/ftp-gw.diff index 075e6eb2fdb8..715d2a76735b 100644 --- a/contrib/ipfilter/FWTK/ftp-gw.diff +++ b/contrib/ipfilter/FWTK/ftp-gw.diff @@ -1,237 +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 $"; + static char RcsId[] = "$Header: /devel/CVS/IP-Filter/FWTK/ftp-gw.diff,v 2.0.2.2 1997/02/23 10:38:35 darrenr Exp $"; #include #include #include #include #include #include - extern int errno; - extern char *sys_errlist[]; #include #include #include #include #include #include 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 $"; + static char RcsId[] = "$Header: /devel/CVS/IP-Filter/FWTK/ftp-gw.diff,v 2.0.2.2 1997/02/23 10:38:35 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 #include #include + #include + #include #include #include #include #include #include #include #include #include #include + #include 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/fwtk_transparent.diff b/contrib/ipfilter/FWTK/fwtk_transparent.diff index 4fe58087e4fe..6a5c37666ee7 100644 --- a/contrib/ipfilter/FWTK/fwtk_transparent.diff +++ b/contrib/ipfilter/FWTK/fwtk_transparent.diff @@ -1,1025 +1,1025 @@ diff -cr ../TIS.orig/fwtk/Makefile.config.linux fwtk/Makefile.config.linux *** ../TIS.orig/fwtk/Makefile.config.linux Sat Sep 7 05:58:21 1996 --- fwtk/Makefile.config.linux Sun Feb 2 05:48:01 1997 *************** *** 13,19 **** # Your C compiler (eg, "cc" or "gcc") ! CC= cc # program to use for installation -- this may or may not preserve --- 13,19 ---- # Your C compiler (eg, "cc" or "gcc") ! CC= gcc # program to use for installation -- this may or may not preserve *************** *** 24,37 **** # Defines for your operating system # ! DEFINES=-DLINUX #DEFINES=-DSYSV -DSOLARIS # Options for your compiler (eg, "-g" for debugging, "-O" for # optimizing, or "-g -O" for both under GCC) #COPT= -g -traditional $(DEFINES) ! COPT= -g $(DEFINES) ! #COPT= -O $(DEFINES) # Version of "make" you want to use #MAKE= gnumake --- 24,37 ---- # Defines for your operating system # ! DEFINES=-DLINUX -DUSE_IP_FILTER #DEFINES=-DSYSV -DSOLARIS # Options for your compiler (eg, "-g" for debugging, "-O" for # optimizing, or "-g -O" for both under GCC) #COPT= -g -traditional $(DEFINES) ! #COPT= -g $(DEFINES) ! COPT= -O $(DEFINES) # Version of "make" you want to use #MAKE= gnumake *************** *** 44,50 **** # Destination directory for installation of binaries ! DEST= /usr/local/etc # Destination directory for installation of man pages --- 44,50 ---- # Destination directory for installation of binaries ! DEST= /usr/local/sbin # Destination directory for installation of man pages *************** *** 72,78 **** # or -Bstatic for static binaries under SunOS 4.1.x) #LDFL= -Bstatic #LDFL= ! LDFL= -g # Location of the fwtk sources [For #include by any external tools needing it] --- 72,79 ---- # or -Bstatic for static binaries under SunOS 4.1.x) #LDFL= -Bstatic #LDFL= ! #LDFL= -g ! LDFL= -O # Location of the fwtk sources [For #include by any external tools needing it] *************** *** 81,87 **** # Location of X libraries for X-gw ! XLIBDIR=/usr/X11/lib #XLIBDIR=/usr/local/X11R5/lib # X Libraries --- 82,88 ---- # Location of X libraries for X-gw ! XLIBDIR=/usr/X11R6/lib #XLIBDIR=/usr/local/X11R5/lib # X Libraries *************** *** 96,102 **** #XLIBS = -L$(XLIBDIR) -lXaw -lXmu -lXt -lXext -lX11 # Location of X include files ! XINCLUDE=/usr/X11/include #XINCLUDE=/usr/local/X11R5/include # Objects to include in libfwall for SYSV --- 97,103 ---- #XLIBS = -L$(XLIBDIR) -lXaw -lXmu -lXt -lXext -lX11 # Location of X include files ! XINCLUDE=/usr/X11R6/include #XINCLUDE=/usr/local/X11R5/include # Objects to include in libfwall for SYSV diff -cr ../TIS.orig/fwtk/Makefile.config.solaris fwtk/Makefile.config.solaris *** ../TIS.orig/fwtk/Makefile.config.solaris Sat Sep 7 06:14:13 1996 --- fwtk/Makefile.config.solaris Sun Feb 2 06:09:19 1997 *************** *** 11,30 **** # - # RcsId: "$Header: /devel/CVS/IP-Filter/FWTK/fwtk_transparent.diff,v 2.0.1.1 1997/02/19 13:02:37 darrenr Exp $" + # RcsId: "$Header: /devel/CVS/IP-Filter/FWTK/fwtk_transparent.diff,v 2.0.2.1 1997/02/23 10:38:36 darrenr Exp $" # Your C compiler (eg, "cc" or "gcc") ! CC= cc # program to use for installation -- this may or may not preserve # old versions (or whatever). assumes that it takes parameters: # copy source dest ! CP= cp # Defines for your operating system # ! DEFINES=-DSYSV -DSOLARIS #DEFINES=-DSYSV -DSOLARIS -Dgethostbyname=res_gethostbyname \ -Dgethostbyaddr=res_gethostbyaddr -Dgetnetbyname=res_getnetbyname \ --- 11,34 ---- # - # RcsId: "$Header: /devel/CVS/IP-Filter/FWTK/fwtk_transparent.diff,v 2.0.1.1 1997/02/19 13:02:37 darrenr Exp $" + # RcsId: "$Header: /devel/CVS/IP-Filter/FWTK/fwtk_transparent.diff,v 2.0.2.1 1997/02/23 10:38:36 darrenr Exp $" + # + # Path to sources of ip_filter (ip_nat.h required in lib/hnam.c) + # + IPFPATH=/src/unpacked/firewall/ip_fil3.1.5 # Your C compiler (eg, "cc" or "gcc") ! CC= gcc # program to use for installation -- this may or may not preserve # old versions (or whatever). assumes that it takes parameters: # copy source dest ! CP= /usr/ucb/install -c -s # Defines for your operating system # ! DEFINES=-DSYSV -DSOLARIS -DUSE_IP_FILTER -I$(IPFPATH) #DEFINES=-DSYSV -DSOLARIS -Dgethostbyname=res_gethostbyname \ -Dgethostbyaddr=res_gethostbyaddr -Dgetnetbyname=res_getnetbyname \ *************** *** 45,52 **** # Your ranlib utility (use "touch" if you don't have ranlib) ! RANLIB= ranlib ! #RANLIB= touch # Destination directory for installation of binaries --- 49,56 ---- # Your ranlib utility (use "touch" if you don't have ranlib) ! # RANLIB= ranlib ! RANLIB= touch # Destination directory for installation of binaries diff -cr ../TIS.orig/fwtk/firewall.h fwtk/firewall.h *** ../TIS.orig/fwtk/firewall.h Sun Sep 8 05:55:26 1996 --- fwtk/firewall.h Sun Feb 2 05:23:33 1997 *************** *** 47,53 **** system. */ #ifndef PERMFILE ! #define PERMFILE "/usr/local/etc/netperm-table" #endif /* --- 47,53 ---- system. */ #ifndef PERMFILE ! #define PERMFILE "/etc/fwtk/netperm-table" #endif /* *************** *** 67,73 **** /* Choose a system logging facility for the firewall toolkit. */ #ifndef LFAC ! #define LFAC LOG_DAEMON #endif --- 67,73 ---- /* Choose a system logging facility for the firewall toolkit. */ #ifndef LFAC ! #define LFAC LOG_LOCAL5 #endif *************** *** 215,220 **** #define PERM_ALLOW 01 #define PERM_DENY 02 ! #define _INCL_FWALL_H #endif --- 215,222 ---- #define PERM_ALLOW 01 #define PERM_DENY 02 ! #ifdef USE_IP_FILTER ! extern char *getdsthost(int, int*); ! #endif #define _INCL_FWALL_H #endif diff -cr ../TIS.orig/fwtk/ftp-gw/ftp-gw.c fwtk/ftp-gw/ftp-gw.c *** ../TIS.orig/fwtk/ftp-gw/ftp-gw.c Fri Sep 6 18:55:05 1996 --- fwtk/ftp-gw/ftp-gw.c Sat Feb 1 06:49:13 1997 *************** *** 50,55 **** --- 50,59 ---- #ifndef FTPPORT #define FTPPORT 21 #endif + #ifdef USE_IP_FILTER + static int do_transparent=0; + static int connectdest(); + #endif static Cfg *confp; static char **validests = (char **)0; *************** *** 170,175 **** --- 174,182 ---- char xuf[1024]; char huf[128]; char *passuser = (char *)0; /* passed user as av */ + #ifdef USE_IP_FILTER + char *psychic, *hotline; + #endif #ifndef LOG_DAEMON openlog("ftp-gw",LOG_PID); *************** *** 313,320 **** } } else timeout = 60*60; - /* display a welcome file or message */ if(passuser == (char *)0) { if((cf = cfg_get("welcome-msg",confp)) != (Cfg *)0) { --- 320,330 ---- } } else timeout = 60*60; + #ifdef USE_IP_FILTER + psychic=getdsthost(0,NULL); + if(psychic) { do_transparent++; } + #endif /* display a welcome file or message */ if(passuser == (char *)0) { if((cf = cfg_get("welcome-msg",confp)) != (Cfg *)0) { *************** *** 322,327 **** --- 332,345 ---- syslog(LLEV,"fwtkcfgerr: welcome-msg must have one parameter, line %d",cf->ln); exit(1); } + #ifdef USE_IP_FILTER + if(do_transparent) { + if(sayfile2(0,cf->argv[0],220)) { + syslog(LLEV,"fwtksyserr: cannot display welcome %s: %m",cf->argv[0]); + exit(1); + } + } else + #endif /* USE_IP_FILTER */ 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); } --- 350,361 ---- if(authallflg) if(say(0,"220-Proxy first requires authentication")) exit(1); ! #ifdef USE_IP_FILTER ! if(do_transparent) ! sprintf(xuf,"220-%s FTP proxy (Version %s) ready.",huf,FWTK_VERSION_MINOR); ! else ! #endif ! sprintf(xuf,"220 %s FTP proxy (Version %s) ready.",huf,FWTK_VERSION_MINOR); if(say(0,xuf)) exit(1); } *************** *** 352,358 **** if(cmd_user(2,fakav,"user internal")) exit(1); } ! /* main loop */ while(1) { FD_ZERO(&rdy); --- 375,386 ---- if(cmd_user(2,fakav,"user internal")) exit(1); } ! #ifdef USE_IP_FILTER ! if(do_transparent) { ! connectdest(psychic,21); ! } ! #endif ! /* main loop */ while(1) { FD_ZERO(&rdy); *************** *** 676,681 **** --- 704,719 ---- return(sayn(0,noad,sizeof(noad)-1)); } + #ifdef USE_IP_FILTER + 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)); + } + #endif if(*dest == '\0') dest = "localhost"; *************** *** 717,723 **** char ebuf[512]; strcpy(ebuf,buf); ! sprintf(buf,"521 %s: %s",dest,ebuf); rfd = -1; return(say(0,buf)); } --- 755,766 ---- char ebuf[512]; strcpy(ebuf,buf); ! #ifdef USE_IP_FILTER ! if(do_transparent) { ! sprintf(buf,"521 %s,%d: %s",dest,ntohs(port),ebuf); ! } else ! #endif ! sprintf(buf,"521 %s: %s",dest,ebuf); rfd = -1; return(say(0,buf)); } *************** *** 1874,1876 **** --- 1917,2036 ---- dup(nread); } #endif + + #ifdef USE_IP_FILTER + 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; + } + + + /* 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); + } + + #endif /* USE_IP_FILTER */ diff -cr ../TIS.orig/fwtk/http-gw/http-gw.c fwtk/http-gw/http-gw.c *** ../TIS.orig/fwtk/http-gw/http-gw.c Mon Sep 9 20:40:53 1996 --- fwtk/http-gw/http-gw.c Sun Feb 2 06:41:18 1997 *************** *** 27,32 **** --- 27,35 ---- static char http_buffer[8192]; static char reason[8192]; static int checkBrowserType = 1; + #ifdef USE_IP_FILTER + static int do_transparent=0; + #endif static void do_logging() { char *proto = "GOPHER"; *************** *** 422,427 **** --- 425,441 ---- /*(NOT A SPECIAL FORM)*/ if((rem_type & TYPE_LOCAL)== 0){ + #ifdef USE_IP_FILTER + 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)); + } + } + + #endif /* USE_IP_FILTER */ /* See if it can be forwarded */ if( can_forward(buf)){ *************** *** 1513,1518 **** --- 1527,1537 ---- parse_vec[0], parse_vec[1], ourname, ourport); + } + #ifdef USE_IP_FILTER + 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]); + #endif /* USE_IP_FILTER */ }else{ sprintf(new_reply,"%s\tgopher://%s:%s/%c%s\t%s\t%u", parse_vec[0], parse_vec[2], diff -cr ../TIS.orig/fwtk/lib/hnam.c fwtk/lib/hnam.c *** ../TIS.orig/fwtk/lib/hnam.c Sat Nov 5 00:30:19 1994 --- fwtk/lib/hnam.c Sat Feb 1 08:17:46 1997 *************** *** 20,25 **** --- 20,37 ---- extern char *inet_ntoa(); + #if defined(USE_IP_FILTER) + #include + #ifndef LINUX + #include "ip_nat.h" + #endif + #if defined(SOLARIS) + #include + #include + #include + #include + #endif + #endif /* IP_FILTER */ #include "firewall.h" *************** *** 45,47 **** --- 57,158 ---- bcopy(hp->h_addr,&sin.sin_addr,hp->h_length); return(inet_ntoa(sin.sin_addr)); } + + + + #ifdef USE_IP_FILTER + 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; + static char buf[255], hostbuf[255]; + #if defined(__FreeBSD__) || defined(SOLARIS) + struct sockaddr_in rsin; + struct natlookup natlookup; + int natfd; + #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 + + #if defined(__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 + + #if defined(SOLARIS) /* for Solaris */ + /* The basis for this block of code is Darren Reed's + * patches to the TIS ftwk's ftp-gw. + * modified for Solaris from Michael Kutzner, Michael.Kutzner@paderlinx.de + */ + memset((char*)&sin, 0, sizeof(sin)); + memset((char*)&rsin, 0, 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); + } + #endif /* USE_IP_FILTER */ diff -cr ../TIS.orig/fwtk/plug-gw/plug-gw.c fwtk/plug-gw/plug-gw.c *** ../TIS.orig/fwtk/plug-gw/plug-gw.c Thu Sep 5 21:36:33 1996 --- fwtk/plug-gw/plug-gw.c Sun Feb 2 04:50:40 1997 *************** *** 38,44 **** static int timeout = PROXY_TIMEOUT; static char **validdests = (char **)0; static Cfg *confp; ! main(ac,av) int ac; char *av[]; --- 38,46 ---- static int timeout = PROXY_TIMEOUT; static char **validdests = (char **)0; static Cfg *confp; ! #ifdef USE_IP_FILTER ! static int do_transparent=0; ! #endif main(ac,av) int ac; char *av[]; *************** *** 189,201 **** static char buf[1024 * 4]; void (*op)(); char *dhost = NULL; char hostport[1024 * 4]; char *ptr; int state = 0; int ssl_plug = 0; ! struct timeval timo; if(c->flags & PERM_DENY) { if (p == -1) syslog(LLEV,"deny host=%s/%s port=any",rhost,raddr); --- 191,215 ---- static char buf[1024 * 4]; void (*op)(); char *dhost = NULL; + char *transhost = NULL; char hostport[1024 * 4]; char *ptr; int state = 0; int ssl_plug = 0; ! #ifdef USE_IP_FILTER ! int pport; ! #endif struct timeval timo; + #ifdef USE_IP_FILTER + /* Transparent plug-gw is probably a bad idea, but hey .. */ + transhost=getdsthost(0,&pport); + if(transhost) { + do_transparent++; + portid=pport; + } + #endif + if(c->flags & PERM_DENY) { if (p == -1) syslog(LLEV,"deny host=%s/%s port=any",rhost,raddr); *************** *** 223,229 **** privport = 1; continue; } ! if (!strcmp(av[x], "-port")) { if (++x >= ac) { syslog(LLEV,"fwtkcfgerr: -port takes an argument, line %d",c->ln); --- 237,248 ---- privport = 1; continue; } ! #ifdef USE_IP_FILTER ! if (!strcmp(av[x],"-all-destinations")) { ! dhost = transhost; ! continue; ! } ! #endif if (!strcmp(av[x], "-port")) { if (++x >= ac) { syslog(LLEV,"fwtkcfgerr: -port takes an argument, line %d",c->ln); diff -cr ../TIS.orig/fwtk/rlogin-gw/rlogin-gw.c fwtk/rlogin-gw/rlogin-gw.c *** ../TIS.orig/fwtk/rlogin-gw/rlogin-gw.c Fri Sep 6 18:56:33 1996 --- fwtk/rlogin-gw/rlogin-gw.c Sun Feb 2 06:26:04 1997 *************** *** 40,46 **** extern char *maphostname(); ! static int cmd_quit(); static int cmd_help(); static int cmd_connect(); --- 40,48 ---- extern char *maphostname(); ! #ifdef USE_IP_FILTER ! static int do_transparent=0; ! #endif static int cmd_quit(); static int cmd_help(); static int cmd_connect(); *************** *** 120,125 **** --- 122,130 ---- static char *tokav[56]; int tokac; struct timeval timo; + #ifdef USE_IP_FILTER + char *psychic; + #endif #ifndef LOG_NDELAY openlog("rlogin-gw",LOG_PID); *************** *** 186,192 **** } ! if((cf = cfg_get("directory",confp)) != (Cfg *)0) { if(cf->argc != 1) { syslog(LLEV,"fwtkcfgerr: chroot must have one parameter, line %d",cf->ln); --- 191,204 ---- } ! #ifdef USE_IP_FILTER ! psychic=getdsthost(0,NULL); ! if(psychic) { ! do_transparent++; ! strncpy(dest,psychic,511); ! dest[511]='\0'; ! } ! #endif /* USE_IP_FILTER */ if((cf = cfg_get("directory",confp)) != (Cfg *)0) { if(cf->argc != 1) { syslog(LLEV,"fwtkcfgerr: chroot must have one parameter, line %d",cf->ln); *************** *** 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,281 ---- } /* if present a host name, chop and save username and hostname */ if((p = index(rusername,'@')) != (char *)0) { char *namp; + dest[0] = '\0'; *p++ = '\0'; if(*p == '\0') p = "localhost"; *************** *** 532,539 **** --- 544,557 ---- sprintf(ebuf,"Trying %s@%s...",rusername,namp); else sprintf(ebuf,"Trying %s...",namp); + #ifdef USE_IP_FILTER + if(!do_transparent) { + #endif if(say(0,ebuf)) return(1); + #ifdef USE_IP_FILTER + } + #endif } 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 -cr ../TIS.orig/fwtk/tn-gw/tn-gw.c fwtk/tn-gw/tn-gw.c *** ../TIS.orig/fwtk/tn-gw/tn-gw.c Fri Sep 6 18:55:48 1996 --- fwtk/tn-gw/tn-gw.c Sun Feb 2 06:06:33 1997 *************** *** 97,102 **** --- 97,106 ---- static int timeout = PROXY_TIMEOUT; static char timed_out_msg[] = "\r\nConnection closed due to inactivity"; + #ifdef USE_IP_FILTER + static int do_transparent=0; + #endif + typedef struct { char *name; char *hmsg; *************** *** 140,145 **** --- 144,153 ---- char tokbuf[BSIZ]; char *tokav[56]; int tokac; + #ifdef USE_IP_FILTER + int port; + char *psychic; + #endif #ifndef LOG_DAEMON openlog("tn-gw",LOG_PID); *************** *** 307,313 **** exit(1); } } ! while (argc > 1) { argc--; argv++; --- 315,349 ---- exit(1); } } ! #ifdef USE_IP_FILTER ! 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; ! } ! ! ! } ! } ! ! #endif /* USE_IP_FILTER */ while (argc > 1) { argc--; argv++; *************** *** 870,877 **** 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]); --- 906,920 ---- syslog(LLEV,"permit host=%s/%s destination=%s",rladdr,riaddr,namp); sprintf(ebuf,"Trying %s port %d...",namp,port); ! #ifdef USE_IP_FILTER ! if(!do_transparent) { ! sprintf(ebuf,"Trying %s port %d...",namp,port); ! #endif ! if(say(0,ebuf)) ! return(1); ! #ifdef USE_IP_FILTER ! } ! #endif } 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); } --- 946,959 ---- syslog(LLEV,"connected host=%s/%s destination=%s",rladdr,riaddr,av[1]); strncpy(dest,av[1], 511); ! #ifdef USE_IP_FILTER ! if(!do_transparent) { ! sprintf(buf, "Connected to %s.", dest); ! say(0, buf); ! } ! #else say(0, buf); + #endif return(2); } diff -cr ../TIS.orig/fwtk/x-gw/socket.c fwtk/x-gw/socket.c *** ../TIS.orig/fwtk/x-gw/socket.c Sat Sep 7 05:16:35 1996 --- fwtk/x-gw/socket.c Sun Feb 2 05:26:44 1997 *************** *** 212,218 **** case AF_UNIX: un_name = (struct sockaddr_un *)addr; len = sizeof(un_name->sun_family) + sizeof(un_name->sun_path) ! #ifdef SCM_RIGHTS /* 4.3BSD Reno and later */ + sizeof(un_name->sun_len) + 1 #endif ; --- 212,218 ---- case AF_UNIX: un_name = (struct sockaddr_un *)addr; len = sizeof(un_name->sun_family) + sizeof(un_name->sun_path) ! #if defined(SCM_RIGHTS) && !defined(LINUX)/* 4.3BSD Reno and later */ + sizeof(un_name->sun_len) + 1 #endif ; Only in fwtk/x-gw: socket.c.bak diff --git a/contrib/ipfilter/FreeBSD-2.2/in_proto.c.diffs b/contrib/ipfilter/FreeBSD-2.2/in_proto.c.diffs new file mode 100644 index 000000000000..dfebbe8f9472 --- /dev/null +++ b/contrib/ipfilter/FreeBSD-2.2/in_proto.c.diffs @@ -0,0 +1,16 @@ +*** in_proto.c.orig Wed Apr 2 19:50:00 1997 +--- in_proto.c Wed Apr 2 19:51:21 1997 +*************** +*** 89,94 **** +--- 89,99 ---- + void eoninput(), eonctlinput(), eonprotoinit(); + #endif /* EON */ + ++ #if defined(IPFILTER) && !defined(IPFILTER_LKM) ++ void iplinit(); ++ #define ip_init iplinit ++ #endif ++ + extern struct domain inetdomain; + + struct protosw inetsw[] = { diff --git a/contrib/ipfilter/FreeBSD-2.2/ip_input.c.diffs b/contrib/ipfilter/FreeBSD-2.2/ip_input.c.diffs new file mode 100644 index 000000000000..1339e012512e --- /dev/null +++ b/contrib/ipfilter/FreeBSD-2.2/ip_input.c.diffs @@ -0,0 +1,32 @@ +*** ip_input.c.orig Wed Apr 2 19:41:44 1997 +--- /sys/netinet/ip_input.c Wed Apr 2 19:28:53 1997 +*************** +*** 74,79 **** +--- 74,82 ---- + #ifdef IPFIREWALL + #include + #endif ++ #if defined(IPFILTER_LKM) || defined(IPFILTER) ++ int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif + + int rsvp_on = 0; + static int ip_rsvp_on; +*************** +*** 310,316 **** +--- 313,327 ---- + * - Wrap: fake packet's addr/port + * - Encapsulate: put it in another IP and send out. + */ ++ #if defined(IPFILTER_LKM) || defined(IPFILTER) ++ if (fr_checkp) { ++ struct mbuf *m1 = m; + ++ if ((*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m1) || !m1) ++ return; ++ ip = mtod(m = m1, struct ip *); ++ } ++ #endif + #ifdef COMPAT_IPFW + if (ip_fw_chk_ptr) { + int action; diff --git a/contrib/ipfilter/FreeBSD-2.2/ip_output.c.diffs b/contrib/ipfilter/FreeBSD-2.2/ip_output.c.diffs new file mode 100644 index 000000000000..3f53ac72caf5 --- /dev/null +++ b/contrib/ipfilter/FreeBSD-2.2/ip_output.c.diffs @@ -0,0 +1,69 @@ +*** ip_output.c.orig Wed Apr 2 19:41:48 1997 +--- /sys/netinet/ip_output.c Wed Apr 2 19:38:19 1997 +*************** +*** 67,72 **** +--- 67,76 ---- + #else + #undef COMPAT_IPFW + #endif ++ #if defined(IPFILTER_LKM) || defined(IPFILTER) ++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); ++ #endif ++ + + u_short ip_id; + +*************** +*** 75,81 **** + __P((struct ifnet *, struct mbuf *, struct sockaddr_in *)); + static int ip_getmoptions + __P((int, struct ip_moptions *, struct mbuf **)); +! static int ip_optcopy __P((struct ip *, struct ip *)); + static int ip_pcbopts __P((struct mbuf **, struct mbuf *)); + static int ip_setmoptions + __P((int, struct ip_moptions **, struct mbuf *)); +--- 79,85 ---- + __P((struct ifnet *, struct mbuf *, struct sockaddr_in *)); + static int ip_getmoptions + __P((int, struct ip_moptions *, struct mbuf **)); +! int ip_optcopy __P((struct ip *, struct ip *)); + static int ip_pcbopts __P((struct mbuf **, struct mbuf *)); + static int ip_setmoptions + __P((int, struct ip_moptions **, struct mbuf *)); +*************** +*** 338,344 **** +--- 342,358 ---- + * - Wrap: fake packet's addr/port + * - Encapsulate: put it in another IP and send out. + */ ++ #if defined(IPFILTER_LKM) || defined(IPFILTER) ++ if (fr_checkp) { ++ struct mbuf *m1 = m; + ++ if ((*fr_checkp)(ip, hlen, ifp, 1, &m1)) ++ error = EHOSTUNREACH; ++ if (error || !m1) ++ goto done; ++ ip = mtod(m = m1, struct ip *); ++ } ++ #endif + #ifdef COMPAT_IPFW + if (ip_nat_ptr && !(*ip_nat_ptr)(&ip, &m, ifp, IP_NAT_OUT)) { + error = EACCES; +*************** +*** 559,565 **** + * Copy options from ip to jp, + * omitting those not copied during fragmentation. + */ +! static int + ip_optcopy(ip, jp) + struct ip *ip, *jp; + { +--- 573,579 ---- + * Copy options from ip to jp, + * omitting those not copied during fragmentation. + */ +! int + ip_optcopy(ip, jp) + struct ip *ip, *jp; + { diff --git a/contrib/ipfilter/FreeBSD-2.2/minstall b/contrib/ipfilter/FreeBSD-2.2/minstall new file mode 100755 index 000000000000..832b68e81a63 --- /dev/null +++ b/contrib/ipfilter/FreeBSD-2.2/minstall @@ -0,0 +1,38 @@ +#!/bin/csh -f +# +set dir=`pwd` +set karch=`uname -m` +if ( -d /sys/arch/$karch ) set archdir="/sys/arch/$karch" +if ( -d /sys/$karch ) set archdir="/sys/$karch" +set confdir="$archdir/conf" + +if ( $dir =~ */FreeBSD-2.2 ) cd .. +echo "Patching ip_input.c, ip_output.c and in_proto.c" +cat FreeBSD-2.2/ip_{in,out}put.c.diffs FreeBSD-2.2/in_proto.c.diffs | \ +(cd /sys/netinet; patch) + +set config=`(cd $confdir; /bin/ls -1t [0-9A-Z_]*) | head -1` +echo -n "Kernel configuration to update [$config] " +set newconfig=$< +if ( "$newconfig" != "" ) then + set config="$confdir/$newconfig" +else + set newconfig=$config +endif +echo "Re-config'ing $newconfig..." +if ( -f $confdir/$newconfig ) then + mv $confdir/$newconfig $confdir/$newconfig.bak +endif +if ( -d $archdir/../compile/$newconfig ) then + set bak=".bak" + set dot=0 + while ( -d $archdir/../compile/${newconfig}${bak} ) + set bak=".bak."$dot + set dot=`expr 1 + $dot` + end + mv $archdir/../compile/$newconfig $archdir/../compile/${newconfig}$bak +endif +awk '{print $0;if($2=="INET"){print"options IPFILTER_LKM\noptions IPFILTER_LOG"}}' \ + $confdir/$newconfig.bak > $confdir/$newconfig +echo 'You will now need to run "config" and build a new kernel.' +exit 0 diff --git a/contrib/ipfilter/FreeBSD-2.2/unminstall b/contrib/ipfilter/FreeBSD-2.2/unminstall new file mode 100755 index 000000000000..abb263114a3e --- /dev/null +++ b/contrib/ipfilter/FreeBSD-2.2/unminstall @@ -0,0 +1,36 @@ +#!/bin/csh -f +# +set dir=`pwd` +set karch=`uname -m` +if ( -d /sys/arch/$karch ) set archdir="/sys/arch/$karch" +if ( -d /sys/$karch ) set archdir="/sys/$karch" +set confdir="$archdir/conf" + +if ( $dir =~ */FreeBSD ) cd .. +echo "Unpatching ip_input.c, ip_output.c and in_proto.c" +cat FreeBSD/ip_{in,out}put.c.diffs FreeBSD/in_proto.c.diffs | \ +(cd /sys/netinet; patch -R) + +set config=`(cd $confdir; /bin/ls -1t [0-9A-Z_]*) | head -1` +echo -n "Kernel configuration to update [$config] " +set newconfig=$< +if ( "$newconfig" != "" ) then + set config="$confdir/$newconfig" +else + set newconfig=$config +endif +if ( -f $confdir/$newconfig ) then + mv $confdir/$newconfig $confdir/$newconfig.bak +endif +if ( -d $archdir/../compile/$newconfig ) then + set bak=".bak" + set dot=0 + while ( -d $archdir/../compile/${newconfig}.${bak} ) + set bak=".bak.$dot" + set dot=`expr 1 + $dot` + end + mv $archdir/../compile/$newconfig $archdir/../compile/${newconfig}.$bak +endif +grep -v IPFILTER $confdir/$newconfig.bak > $confdir/$newconfig +echo 'You will now need to run "config" and build a new kernel.' +exit 0 diff --git a/contrib/ipfilter/HISTORY b/contrib/ipfilter/HISTORY index 41c94d120394..425aa2432bfb 100644 --- a/contrib/ipfilter/HISTORY +++ b/contrib/ipfilter/HISTORY @@ -1,576 +1,659 @@ # # 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.2alpha4 2/4/97 - Released + +Some compiler warnings cleaned up. + +FreeBSD-2.2 patches for LKM completed. + +3.2alpha3 31/3/97 - Released + +ipmon changes: -N for reading NAT logfile, -S for reading state logfile. +-a for reading all. -n now toggles hostname resolution. + +Add logging of new state entries and expiration of old state entries. +count log successes and failures. + +Add logging of new NAT entries and expiration of old NAT entries. +count log successes and failures. + +Use u_quad_t for records of bytes & packets where kept +(IP Accounting: fr_hits, fr_bytes; IP state: is_pkts, is_bytes). + +Fixup use of CPU and DCPU in Makefiles. + +Fix broken 0/32 NAT mapping. Carl Makin + +3.2alpha2 + +Implement mapping to 0/32 as being an alias for automatically using the +interface's first IP address. + +Implement separate minor devices for both NAT and IP state code. + +Fully prototype all functions. + +Fix Makefile problem due to attempt to fix Sun compiling problems. + +3.1.10 23/3/97 - Released + +ipfstat -a requires a -i or -o command line option too. Print an error +when not present rather than attempt to do something. + +patch updates for SunOS4 for kernel compiling. +patch for ipmon -s (flush's syslog file which isn't good). Andrew J. Schorr + + +too many people hit their heads hard when compiling code into the kernel +that doesn't let any packets through. (fil.c - IPF_NOMATCH) + +icmp-type parsing doesn't return any errors when it isn't constructed +correctly. Neil Readwin + +Using "-conf" with modload on SunOS4 doesn't work. +Timothy Demarest + +Need to define ARCH in makefile for SunOS4 building. "make sunos4" +in INSTALL.SunOS is incorrect. James R Grinter +[all SunOS targets now run buildsunos] + +NAT lookups are still incorrect, matching non-TCP/UDP with TCP/UDP +information. ArkanoiD + +Need to check for __FreeBSD_version being 199511 rather than 199607 +in mln_ipl.c. Eric Feillant + +3.1.9 8/3/97 - Released + +fixed incorrect lookup of active NAT entries. + +patch for ip_deq() wrong for pre 2.1.6 FreeBSD. +fyeung@fyeung8.netific.com (Francis Yeung) + +check for out with return-rst/return-icmp at wrong place - Erkki Ritoniemi +(erkki@vlsi.fi) + +text_readip returns the interface pointer pointing to text on stack - +Neil Readwin + +fix from Pradeep Krishnan for printout rules "with not opt sec". + +3.1.8 18/2/97 - Released + +Diffs for ip_output.c and ip_input.c updated to fix bug with fastroute and +compiling warnings about reuse of m0. + prevent use of return-rst and return-icmp with rules blocking packets going out, preventing panics in certain situations. loop forms in frag cache table - Yury Pshenychny should use SPLNET/SPLX around expire routines in NAT/frag/state code. redeclared malloc in 44arp.c - 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 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 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 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 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 "" 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 (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 . Man page problems reported and fixed by Carson Gaspar . 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 Added patches for FreeBSD 1, and added two new switches (-E, -D) to ipf, along with a new ioctl, SIOCFRENB. From: Dieter Dworkin Muller 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 . 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 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 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/INSTALL.FreeBSD b/contrib/ipfilter/INST.FreeBSD-2.2 similarity index 57% copy from contrib/ipfilter/INSTALL.FreeBSD copy to contrib/ipfilter/INST.FreeBSD-2.2 index 3910f4d47577..400963d416bb 100644 --- a/contrib/ipfilter/INSTALL.FreeBSD +++ b/contrib/ipfilter/INST.FreeBSD-2.2 @@ -1,41 +1,53 @@ To build a kernel for use with the loadable kernel module, follow these steps: - 1. do "make bsd" + 1. do "make freebsd22" 2. do "make install-bsd" (probably has to be done as root) - 3. run "FreeBSD/minstall" as root + 3. run "FreeBSD-2.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" +*** KERNEL INSTALL CURRENTLY UNSUPPORTED *** + 1. do "make freebsd22" 2. do "make install-bsd" (probably has to be done as root) - 3. run "FreeBSD/kinstall" as root + 3. run "FreeBSD-2.2/kinstall" as root 4. build a new kernel - 5. create /dev/ipl with "mknod /dev/ipl c 20 0". + 5a) For FreeBSD 2.2 (or later) + create devices for IP Filter as follows: + mknod /dev/ipl c 79 0 + mknod /dev/ipnat c 79 1 + mknod /dev/ipstate c 79 2 + + 5b) For versions prior to FreeBSD 2.2: + create devices for IP Filter as follows (assuming it was + installed into the device table as char dev 20): + mknod /dev/ipl c 20 0 + mknod /dev/ipnat c 20 1 + mknod /dev/ipstate c 20 2 6. install and reboot with the new kernel Darren Reed darrenr@cyber.com.au diff --git a/contrib/ipfilter/INSTALL.FreeBSD b/contrib/ipfilter/INSTALL.FreeBSD index 3910f4d47577..fc35ecb34a0c 100644 --- a/contrib/ipfilter/INSTALL.FreeBSD +++ b/contrib/ipfilter/INSTALL.FreeBSD @@ -1,41 +1,48 @@ +*** IF you are using FreeBSD 2.2 or later, see the file "INST.FreeBSD-2.2" *** + + 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". + 5. create devices for IP Filter as follows (assuming it was + installed into the device table as char dev 20): + mknod /dev/ipl c 20 0 + mknod /dev/ipnat c 20 1 + mknod /dev/ipstate c 20 2 6. install and reboot with the new kernel Darren Reed darrenr@cyber.com.au diff --git a/contrib/ipfilter/INSTALL.SunOS b/contrib/ipfilter/INSTALL.SunOS index 836d1214589a..64392fdf3119 100644 --- a/contrib/ipfilter/INSTALL.SunOS +++ b/contrib/ipfilter/INSTALL.SunOS @@ -1,36 +1,36 @@ To install as a Loadable Kernel Module (LKM): - 1. do a "make sunos4" in this directory + 1. do a "make solaris" 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 + 1. do a "make solaris" 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/Makefile b/contrib/ipfilter/Makefile index 258074aa301a..9c83fc4ead02 100644 --- a/contrib/ipfilter/Makefile +++ b/contrib/ipfilter/Makefile @@ -1,158 +1,170 @@ # # (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.5 1997/02/16 06:17:04 darrenr Exp $ +# $Id: Makefile,v 2.0.2.7 1997/04/02 12:23:14 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 +#To test prototyping +#CC=gcc -Wstrict-prototypes -Wmissing-prototypes -Werror CC=gcc DEBUG=-g CFLAGS=-I$$(TOP) -DCPU=`uname -m` +CPU=`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=-DIPF_DEFAULT_PASS=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)" + "SOLARIS2=$(SOLARIS2)" "DEBUG=$(DEBUG)" "DCPU=$(CPU)" # ########## ########## ########## ########## ########## ########## ########## # 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 ..) +freebsd22 freebsd30: + -if [ ! -d BSD/$(CPU) ] ; then mkdir BSD/$(CPU); fi + @if [ ! -f `uname -v|sed -e 's@^.*:\(/[^: ]*\).*@\1@'`/ioconf.h ] ; then \ + echo "Can't find ioconf.h"; \ + exit 1;\ + fi + rm -f BSD/$(CPU)/ioconf.h + ln -s `uname -v|sed -e 's@^.*:\(/[^: ]*\).*@\1@'`/ioconf.h BSD/$(CPU) + make bsd + +bsd netbsd freebsd freebsd20 freebsd21: + -if [ ! -d BSD/$(CPU) ] ; then mkdir BSD/$(CPU); fi + -rm -f BSD/$(CPU)/Makefile BSD/$(CPU)/Makefile.ipsend + -ln -s ../Makefile BSD/$(CPU)/Makefile + -ln -s ../Makefile.ipsend BSD/$(CPU)/Makefile.ipsend + (cd BSD/$(CPU); make build "TOP=../.." $(MFLAGS); cd ..) + (cd BSD/$(CPU); 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 ..) + -if [ ! -d BSD/$(CPU) ] ; then mkdir BSD/$(CPU); fi + -rm -f BSD/$(CPU)/Makefile BSD/$(CPU)/Makefile.ipsend + -ln -s ../Makefile BSD/$(CPU)/Makefile + -ln -s ../Makefile.ipsend BSD/$(CPU)/Makefile.ipsend + (cd BSD/$(CPU); make build "TOP=../.." $(MFLAGS) LKM= ; cd ..) + (cd BSD/$(CPU); 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 +sunos4 solaris1: + (cd SunOS4; make build TOP=.. $(MFLAGS); cd ..) + (cd SunOS4; make -f Makefile.ipsend TOP=.. $(MFLAGS); cd ..) + +sunos5 solaris2: + (cd SunOS5/$(CPU); make build TOP=../.. $(MFLAGS) "SOLARIS2=$(SOLARIS2)" "CPU=-Dsparc -D__sparc__"; cd ..) + (cd SunOS5/$(CPU); make -f Makefile.ipsend TOP=../.. $(MFLAGS); cd ..) + +sunos5x86 solaris2x86: + (cd SunOS5/$(CPU); make build TOP=../.. $(MFLAGS) "SOLARIS2=$(SOLARIS2)" "CPU=-Di86pc -Di386 -D__i386__"; cd ..) + (cd SunOS5/$(CPU); make -f Makefile.ipsend TOP=../.. $(MFLAGS); cd ..) + install-bsd: bsd - (cd BSD/$(DCPU); $(MAKE) "TOP=../.." install) + (cd BSD/$(CPU); $(MAKE) "CPU=$(CPU) TOP=../.." install) install-sunos4: solaris - (cd SunOS4; $(MAKE) "TOP=.." install) + (cd SunOS4; $(MAKE) "CPU=$(CPU) TOP=.." install) install-sunos5: solaris - (cd SunOS5; $(MAKE) "TOP=.." install) + (cd SunOS5; $(MAKE) "CPU=$(CPU) 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/NAT.FreeBSD b/contrib/ipfilter/NAT.FreeBSD new file mode 100644 index 000000000000..996b009ab1bf --- /dev/null +++ b/contrib/ipfilter/NAT.FreeBSD @@ -0,0 +1,104 @@ +These are Instructions for Configuring A FreeBSD Box For NAT +After you have installed IpFilter. + +You will need to change three files: + +/etc/rc.local +/etc/sysconfig +/etc/natrules + +You will have to: + +1) Load the kernel module +2) Make the ipnat rules +3) Load the ipnat rules +4) Enable routing between interfaces +5) Add static routes for the subnet ranges +6) Configure your network interfaces +7) reboot the computer for the changes to take effect. + +The FAQ was written by Chris Coleman +This was tested using ipfilter 3.1.4 and FreeBSD 2.1.6-RELEASE +_________________________________________________________ +1) Loading the Kernel Module + +If you are using a Kernal Loadable Module you need to edit your +/etc/rc.local file and load the module at boot time. +use the line: + + modload /lkm/if_ipl.o + +If you are not loading a kernel module, skip this step. +_________________________________________________________ +2) Setting up the NAT Rules + +Make a file called /etc/natrules +put in the rules that you need for your system. + +If you want to use the whole 10 Network. Try: + +map fpx0 10.0.0.0/8 -> 208.8.0.1/32 portmap tcp/udp 10000:65000 + +_________________________________________________________ +Here is an explaination of each part of the command: + +map starts the command. + +fpx0 is the interface with the real internet address. + +10.0.0.0 is the subnet you want to use. + +/8 is the subnet mask. ie 255.0.0.0 + +208.8.0.1 is the real ip address that you use. + +/32 is the subnet mask 255.255.255.255, ie only use this ip address. + +portmap tcp/udp 10000:65000 + tells it to use the ports to redirect the tcp/udp calls through + + +The one line should work for the whole network. +_________________________________________________________ +3) Loading the NAT Rules: + +The NAT Rules will need to be loaded every time the computer +reboots. + +In your /etc/rc.local put the line: + +ipnat -f /etc/natrules + +To check and see if it is loaded, as root type + ipnat -ls +_________________________________________________________ +4) Enable Routing between interfaces. + +Tell the kernel to route these addresses. + +in the rc.local file put the line: + +sysctl -w net.inet.ip.forwarding=1 + +_________________________________________________________ +5) Static Routes to Subnet Ranges + +Now you have to add a static routes for the subnet ranges. +Edit your /etc/sysconfig to add them at bootup. + +static_routes="foo" +route_foo="10.0.0.0 -netmask 0xf0000000 -interface 10.0.0.1" + + +_________________________________________________________ +6) Make sure that you have your interfaces configured. + +I have two Intel Ether Express Pro B cards. +One is on 208.8.0.1 The other is on 10.0.0.1 + +You need to configure these in the /etc/sysconfig + +network_interfaces="fxp0 fxp1" +ifconfig_fxp0="inet 208.8.0.1 netmask 255.255.255.0" +ifconfig_fxp1="inet 10.0.0.1 netmask 255.0.0.0" +_________________________________________________________ diff --git a/contrib/ipfilter/buildsunos b/contrib/ipfilter/buildsunos index dd2aa38a36ca..5e396695455d 100755 --- a/contrib/ipfilter/buildsunos +++ b/contrib/ipfilter/buildsunos @@ -1,23 +1,23 @@ #! /bin/sh -# $Id: buildsunos,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp $ +# $Id: buildsunos,v 2.0.2.3 1997/03/30 15:37:34 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} + make ${1+"$@"} sunos5x86 SOLARIS2="-DSOLARIS2=$solrev" CPU=${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} +make ${1+"$@"} sunos$rev SOLARIS2="-DSOLARIS2=$solrev" CPU=${cpu} exit $? diff --git a/contrib/ipfilter/etc/etc.sed b/contrib/ipfilter/etc/etc.sed new file mode 100644 index 000000000000..b14fc74851d7 --- /dev/null +++ b/contrib/ipfilter/etc/etc.sed @@ -0,0 +1,2 @@ + Æ . Ä..'! CVS + protocols diff --git a/contrib/ipfilter/fil.c b/contrib/ipfilter/fil.c index 9f953614e42d..32b6068dfecb 100644 --- a/contrib/ipfilter/fil.c +++ b/contrib/ipfilter/fil.c @@ -1,772 +1,779 @@ /* * (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.7 1997/02/18 10:53:47 darrenr Exp $"; +static char rcsid[] = "$Id: fil.c,v 2.0.2.7 1997/04/02 12:23:15 darrenr Exp $"; #endif #include #include #include +#include #include #include #if defined(_KERNEL) || defined(KERNEL) # include #else # include # include #endif #include #if !defined(__SVR4) && !defined(__svr4__) # include #else # include # include # include #endif #include #include #include #ifdef sun # include #endif #include #include #include #include #include #include #include #include #include -#include "ip_fil.h" #include "ip_compat.h" +#include "ip_fil.h" #include "ip_nat.h" #include "ip_frag.h" #include "ip_state.h" #ifndef MIN #define MIN(a,b) (((a)<(b))?(a):(b)) #endif #ifndef _KERNEL -#include "ipf.h" +# include "ipf.h" +# include "ipt.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) +# 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, m) +# define SEND_RESET(ip, qif, q, if) send_reset(ip, if) +# define IPLLOG(a, c, d, e) ipllog() # if SOLARIS +# define ICMP_ERROR(b, ip, t, c, if, src) icmp_error(ip) # 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(); +# define ICMP_ERROR(b, ip, t, c, if, src) icmp_error(b, ip, if) # 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 +#else /* #ifndef _KERNEL */ +# 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) +# define IPLLOG(a, c, d, e) ipllog(a, IPL_LOGIPF, c, d, e) +# if SOLARIS +extern kmutex_t ipf_mutex; +# define SEND_RESET(ip, qif, q, if) send_reset(ip, qif, q) # define ICMP_ERROR(b, ip, t, c, if, src) \ - icmp_error(mtod(b, ip_t *), t, c, if, src) + icmp_error(b, ip, t, c, if, src) # else -# define ICMP_ERROR(b, ip, t, c, if, src) \ +# define FR_SCANLIST(p, ip, fi, m) fr_scanlist(p, ip, fi, m) +# define SEND_RESET(ip, qif, q, if) send_reset((struct tcpiphdr *)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 #endif #ifndef IPF_LOGGING #define IPF_LOGGING 0 #endif #ifdef IPF_DEFAULT_PASS #define IPF_NOMATCH (IPF_DEFAULT_PASS|FR_NOMATCH) #else -#define IPF_NOMATCH (FR_NOMATCH) +#define IPF_NOMATCH (FR_PASS|FR_NOMATCH) #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 = IPF_LOGGING, fr_active = 0; fr_info_t frcache[2]; +static void fr_makefrip __P((int, ip_t *, fr_info_t *)); +static int fr_tcpudpchk __P((frentry_t *, fr_info_t *)); +static int fr_scanlist __P((int, ip_t *, fr_info_t *, void *)); + /* * 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) +static 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) +static 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) +static 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)) + if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp) 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)) + 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; + fr->fr_bytes += (U_QUAD_T)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 -) +, mp) +char *mp; #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; +#ifndef _KERNEL + char *mc = mp, *m = mp; +#endif -#if !defined(__SVR4) && !defined(__svr4__) && defined(_KERNEL) +#ifdef _KERNEL +# if !defined(__SVR4) && !defined(__svr4__) 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) +# endif +# if SOLARIS mblk_t *mc = NULL, *m = qif->qf_m; +# endif #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 = IPF_NOMATCH; if ((fin->fin_fr = ipfilter[out][fr_active])) pass = FR_SCANLIST(IPF_NOMATCH, ip, fin, m); bcopy((char *)fin, (char *)fc, FI_CSIZE); if (pass & FR_NOMATCH) frstats[out].fr_nom++; } 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) + if (fr && fr->fr_func && !(pass & FR_CALLNOW)) 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)) { + 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 ? * WARNING: ICMP error packets AND TCP RST packets should * ONLY be sent in repsonse to incoming packets. Sending them * in response to outbound packets can result in a panic on * some operating systems. */ if (!out) { #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 = *mp = 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) + if (SEND_RESET(ip, qif, q, ifp) == 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; } 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) +int fr_copytolog(dev, buf, len) +int dev; char *buf; int len; { - int clen, tail; + register char *bufp = iplbuf[dev], *tp = iplt[dev], *hp = iplh[dev]; + register int clen, tail; - tail = (iplh >= iplt) ? (iplbuf + IPLLOGSIZE - iplh) : (iplt - iplh); + tail = (hp >= tp) ? (bufp + IPLLOGSIZE - hp) : (tp - hp); clen = MIN(tail, len); - bcopy(buf, iplh, clen); + bcopy(buf, hp, clen); len -= clen; tail -= clen; - iplh += clen; + hp += clen; buf += clen; - if (iplh == iplbuf + IPLLOGSIZE) { - iplh = iplbuf; - tail = iplt - iplh; + if (hp == bufp + IPLLOGSIZE) { + hp = bufp; + tail = tp - hp; } if (len && tail) { clen = MIN(tail, len); - bcopy(buf, iplh, clen); + bcopy(buf, hp, clen); len -= clen; - iplh += clen; + hp += clen; } + iplh[dev] = hp; return len; } #endif diff --git a/contrib/ipfilter/fils.c b/contrib/ipfilter/fils.c index 249611b25343..ca6abe0cdb09 100644 --- a/contrib/ipfilter/fils.c +++ b/contrib/ipfilter/fils.c @@ -1,366 +1,387 @@ /* * (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 #include #if !defined(__SVR4) && !defined(__svr4__) #include #endif #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include "ip_fil.h" -#include "ip_compat.h" -#include "ip_nat.h" -#include "ip_frag.h" -#include "ip_state.h" #include #include #include +#include "ip_compat.h" +#include "ip_fil.h" #include "ipf.h" +#include "ip_nat.h" +#include "ip_frag.h" +#include "ip_state.h" #include "kmem.h" #ifdef __NetBSD__ #include #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 $"; +static char rcsid[] = "$Id: fils.c,v 2.0.2.7 1997/04/02 12:23:16 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(); +extern int main __P((int, char *[])); +static void showstats __P((int, friostat_t *)); +static void showfrstates __P((int, ipfrstat_t *)); +static void showlist __P((friostat_t *)); +static void showipstates __P((int, ips_stat_t *)); +static void Usage __P((char *)); + -void Usage(name) +static void Usage(name) char *name; { fprintf(stderr, "Usage: %s [-afhIiosv] [-d ]\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 { + FPRINTF(stderr, "No -i or -o given with -a\n"); + return; + } } 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)) +#ifdef USE_QUAD_T + PRINTF("%qd ", fp->fr_hits); +#else PRINTF("%ld ", fp->fr_hits); +#endif if (opts & (OPT_ACCNT|OPT_VERBOSE)) +#ifdef USE_QUAD_T + PRINTF("%qd ", fp->fr_bytes); +#else PRINTF("%ld ", fp->fr_bytes); +#endif 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) + if (kmemcpy((char *)&ips, (u_long)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", + PRINTF("%s age %ld 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]); + PRINTF("\tpkts %ld bytes %ld", + ips.is_pkts, ips.is_bytes); 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), + PRINTF(" %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, + PRINTF(" %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], + if (kmemcpy((char *)&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 index 91faec3eeed7..3a91e7a5dd7c 100644 --- a/contrib/ipfilter/inet_addr.c +++ b/contrib/ipfilter/inet_addr.c @@ -1,182 +1,191 @@ /* * ++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 $"; +static char rcsid[] = "$Id: inet_addr.c,v 2.0.2.3 1997/03/27 13:45:00 darrenr Exp $"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include +#ifndef __P +# ifdef __STDC__ +# define __P(x) x +# else +# define __P(x) () +# endif +#endif +int inet_aton __P((const char *, struct in_addr *)); + /* * 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 index 5a36cc318ad6..c1fbfce0cebe 100644 --- a/contrib/ipfilter/ip_compat.h +++ b/contrib/ipfilter/ip_compat.h @@ -1,342 +1,387 @@ /* * (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 $ + * $Id: ip_compat.h,v 2.0.2.6 1997/04/02 12:23:17 darrenr Exp $ */ #ifndef __IP_COMPAT_H_ #define __IP_COMPAT_H__ +#ifndef __P +# ifdef __STDC__ +# define __P(x) x +# else +# define __P(x) () +# endif +#endif + #ifndef SOLARIS #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) #endif + #if SOLARIS -#define MTYPE(m) ((m)->b_datap->db_type) +# define MTYPE(m) ((m)->b_datap->db_type) +# include +# include +/* + * because Solaris 2 defines these in two places :-/ + */ +# undef IPOPT_EOL +# undef IPOPT_NOP +# undef IPOPT_LSRR +# undef IPOPT_RR +# undef IPOPT_SSRR +# ifndef _KERNEL +# define _KERNEL +# undef RES_INIT +# include +# include +# include +# undef _KERNEL +# else +# include +# include +# include +# endif #endif #define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h))) #ifndef IP_OFFMASK #define IP_OFFMASK 0x1fff #endif +#if BSD > 199306 +# define USE_QUAD_T +# define U_QUAD_T u_quad_t +#else +# define U_QUAD_T u_long +#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 */ +#ifdef __FreeBSD__ +# include +# if defined(IPFILTER_LKM) && !defined(ACTUALLY_LKM_NOT_KERNEL) +# define ACTUALLY_LKM_NOT_KERNEL +# endif +#endif + /* * Build some macros and #defines to enable the same code to compile anywhere * Well, that's the idea, anyway :-) */ -#ifdef _KERNEL +#if defined(_KERNEL) || defined(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) +extern ill_t *get_unit __P((char *)); # define GETUNIT(n) get_unit((n)) # else # include # 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)(); + int (*qf_inp) __P((queue_t *, mblk_t *)); + int (*qf_outp) __P((queue_t *, mblk_t *)); 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 KMALLOC(a,b,c) (a) = (b)kmem_alloc((c), KM_NOSLEEP) # define GET_MINOR(x) getminor(x) # else -# define KMALLOC(x) new_kmem_alloc((x), KMEM_NOSLEEP) +# define KMALLOC(a,b,c) (a) = (b)new_kmem_alloc((c), KMEM_NOSLEEP) # endif /* __svr4__ */ # endif /* sun && !linux */ # ifndef GET_MINOR # define GET_MINOR(x) minor(x) # endif # if BSD >= 199306 || defined(__FreeBSD__) # include -# if !defined(__FreeBSD__) +# if !defined(__FreeBSD__) || (defined (__FreeBSD__) && __FreeBSD__>=3) # include # include extern vm_map_t kmem_map; # else # include # endif /* __FreeBSD__ */ /* -** # define KMALLOC(x) kmem_alloc(kmem_map, (x)) -** # define KFREE(x) kmem_free(kmem_map, (vm_offset_t)(x), \ +# define KMALLOC(a,b,c) (a) = (b)kmem_alloc(kmem_map, (c)) +# 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 KMALLOC(a, b, c) MALLOC((a), b, (c), M_PFIL, M_NOWAIT) # define KFREE(x) FREE((x), M_PFIL) # else -# define KMALLOC(x) malloc((x), M_TEMP, M_NOWAIT) +# define KMALLOC(a, b, c) MALLOC((a), b, (c), 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 +# define MUTEX_ENTER(x) ; +# define MUTEX_EXIT(x) ; +# define SPLNET(x) ; +# undef SPLX +# define SPLX(x) ; +# define KMALLOC(a,b,c) (a) = (b)malloc(c) +# define KFREE(x) free(x) +# define GETUNIT(x) get_unit(x) +# define IRCOPY(a,b,c) bcopy((a), (b), (c)) +# define IWCOPY(a,b,c) bcopy((a), (b), (c)) #endif /* KERNEL */ #ifdef linux # define ICMP_UNREACH ICMP_DEST_UNREACH # 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 KMALLOC(a,b,c) (a) = (b)kmalloc((c), 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 index fec484670f4b..353d7a6e8ec7 100644 --- a/contrib/ipfilter/ip_fil.c +++ b/contrib/ipfilter/ip_fil.c @@ -1,887 +1,1099 @@ /* * (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.7 1997/02/19 12:45:02 darrenr Exp $"; +static char rcsid[] = "$Id: ip_fil.c,v 2.0.2.6 1997/04/02 12:23:19 darrenr Exp $"; #endif +#ifndef SOLARIS +#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) +#endif + +#ifdef __FreeBSD__ +#include +#endif +#ifndef _KERNEL +#include +#include +#endif #include #include #include #include #include +#include +#ifdef _KERNEL #include +#endif #include +#if !SOLARIS +#include #include +#else +#define bcmp memcmp +#define bzero(a,b) memset(a,0,b) +#define bcopy(a,b,c) memcpy(b,a,c) +#include +#endif #include #include #include #ifdef sun #include #endif #include #include #include #include #include #include #include #include #include #include #include -#include "ip_fil.h" #include "ip_compat.h" +#include "ip_fil.h" #include "ip_frag.h" #include "ip_nat.h" #include "ip_state.h" #ifndef MIN #define MIN(a,b) (((a)<(b))?(a):(b)) #endif extern fr_flags, fr_active; extern struct protosw inetsw[]; -extern int (*fr_checkp)(); #if BSD < 199306 -extern int ipfr_slowtimer(); -static int (*fr_saveslowtimo)(); +static int (*fr_saveslowtimo) __P((void)); extern int tcp_ttl; #else -extern void ipfr_slowtimer(); -static void (*fr_saveslowtimo)(); +static void (*fr_saveslowtimo) __P((void)); #endif int ipl_inited = 0; int ipl_unreach = ICMP_UNREACH_FILTER; -int send_reset(); + +#ifndef _KERNEL +#include "ipt.h" +static struct ifnet **ifneta = NULL; +static int nifs = 0; +struct ifnet *get_unit __P((char *)); +#endif #ifdef IPFILTER_LOG -# define LOGSIZE 8192 -int ipllog(); -char iplbuf[LOGSIZE]; -caddr_t iplh = iplbuf, iplt = iplbuf; -static int iplused = 0; +char iplbuf[3][IPLLOGSIZE]; +caddr_t iplh[3], iplt[3]; +int iplused[3] = {0,0,0}; #endif /* IPFILTER_LOG */ -static void frflush(); -static int frrequest(); -static int (*fr_savep)() = NULL; +static void frflush __P((caddr_t)); +static int frrequest __P((int, caddr_t, int)); +static void frzerostats __P((caddr_t)); +#ifdef _KERNEL +static int (*fr_savep) __P((struct ip *, int, struct ifnet *, + int, struct mbuf **)); +#else +void init_ifp __P((void)); +static int (*fr_savep) __P((struct ip *, int, struct ifnet *, + int, char *)); +static int no_output __P((struct ifnet *, struct mbuf *, + struct sockaddr *, struct rtentry *)); +static int write_output __P((struct ifnet *, struct mbuf *, + struct sockaddr *, struct rtentry *)); +#endif + -#if _BSDI_VERSION >= 199501 +#if (_BSDI_VERSION >= 199510) && defined(_KERNEL) # include # include -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 */ +#endif /* _BSDI_VERSION >= 199510 && _KERNEL */ + -#ifdef IPFILTER_LKM +#ifdef _KERNEL +# ifdef IPFILTER_LKM int iplidentify(s) char *s; { if (strcmp(s, "ipl") == 0) return 1; return 0; } -#endif /* IPFILTER_LKM */ +# endif /* IPFILTER_LKM */ int iplattach() { - int s; + int s, i; 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; + + /* + * Set log buffer pointers for each of the log buffers + */ + for (i = 0; i <= 2; i++) { + iplh[i] = iplbuf[i]; + iplt[i] = iplbuf[i]; + } 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; } +#if defined(IPFILTER_LKM) || defined(IPFILTER) fr_checkp = fr_savep; +#endif inetsw[0].pr_slowtimo = fr_saveslowtimo; frflush((caddr_t)&i); ipl_inited = 0; ipfr_unload(); ip_natunload(); fr_stateunload(); SPLX(s); return 0; } +#endif /* _KERNEL */ 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 +#if ((_BSDI_VERSION >= 199510) || (BSD >= 199506)) && defined(_KERNEL) , p) struct proc *p; #else ) #endif dev_t dev; int cmd; caddr_t data; int mode; { int error = 0, s, unit; +#ifdef _KERNEL unit = minor(dev); - if (unit != 0) + if ((2 < unit) || (unit < 0)) return ENXIO; +#endif SPLNET(s); switch (cmd) { case FIONREAD : #ifdef IPFILTER_LOG - *(int *)data = iplused; + *(int *)data = iplused[unit]; #endif break; -#ifndef IPFILTER_LKM +#if !defined(IPFILTER_LKM) && defined(_KERNEL) 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; + *(int *)data = iplused[unit]; + iplh[unit] = iplt[unit] = iplbuf[unit]; + iplused[unit] = 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; + frentry_t frd; frdest_t *fdp; - struct frentry frd; int error = 0, in; - fp = &fr; + fp = &frd; 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; + bzero((char *)frcache, sizeof(frcache[0]) * 2); + 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)))) { + KMALLOC(f, frentry_t *, sizeof(*f)); + if (f != NULL) { 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) +#ifdef _KERNEL /* * routines below for saving IP headers to buffer */ int iplopen(dev, flags -#if _BSDI_VERSION >= 199501 +#if ((_BSDI_VERSION >= 199510) || (BSD >= 199506)) && defined(_KERNEL) , devtype, p) int devtype; struct proc *p; -#else +# else ) -#endif +# endif dev_t dev; int flags; { u_int min = minor(dev); - if (min) + if (2 < min) min = ENXIO; + else + min = 0; return min; } int iplclose(dev, flags -#if _BSDI_VERSION >= 199501 +#if ((_BSDI_VERSION >= 199510) || (BSD >= 199506)) && defined(_KERNEL) , devtype, p) int devtype; struct proc *p; -#else +# else ) -#endif +# endif dev_t dev; int flags; { u_int min = minor(dev); - if (min) + if (2 < min) min = ENXIO; + else + min = 0; 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 int ret, s, unit; register size_t sz, sx; int error; + unit = minor(dev); + if ((2 < unit) || (unit < 0)) + return ENXIO; + if (!uio->uio_resid) return 0; - while (!iplused) { - error = SLEEP(iplbuf, "ipl sleep"); + + while (!iplused[unit]) { + error = SLEEP(iplbuf[unit], "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 = MIN(uio->uio_resid, iplused[unit]); + if (iplh[unit] < iplt[unit]) + sz = MIN(sz, IPLLOGSIZE - (iplt[unit] - iplbuf[unit])); 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 (!(ret = UIOMOVE(iplt[unit], sz, UIO_READ, uio))) { + iplt[unit] += sz; + iplused[unit] -= sz; + if ((iplh[unit] < iplt[unit]) && (iplt[unit] == iplbuf[unit] + IPLLOGSIZE)) + iplt[unit] = iplbuf[unit]; + + if (sx && !(ret = UIOMOVE(iplt[unit], sx, UIO_READ, uio))) { + iplt[unit] += sx; + iplused[unit] -= sx; + if ((iplh[unit] < iplt[unit]) && (iplt[unit] == iplbuf[unit] + IPLLOGSIZE)) + iplt[unit] = iplbuf[unit]; } - if (!iplused) /* minimise wrapping around the end */ - iplh = iplt = iplbuf; + if (!iplused[unit]) /* minimise wrapping around the end */ + iplh[unit] = iplt[unit] = iplbuf[unit]; } SPLX(s); return ret; } # endif /* IPFILTER_LOG */ -#endif /* linux */ -#ifdef IPFILTER_LOG -int ipllog(flags, ip, fin, m) +# ifdef IPFILTER_LOG +int ipllog(flags, dev, ip, fin, m) u_int flags; +int dev; 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) + if (iplused[dev] + len > IPLLOGSIZE) return 0; - iplused += len; + iplused[dev] += len; -# ifdef sun +# ifdef sun uniqtime(&iplci); -# endif -# if BSD >= 199306 || defined(__FreeBSD__) +# endif +# if BSD >= 199306 || defined(__FreeBSD__) microtime((struct timeval *)&iplci); -# endif +# 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 +# endif + if (iplh[dev] == iplbuf[dev] + IPLLOGSIZE) + iplh[dev] = iplbuf[dev]; + /* * Gauranteed to succeed from above */ - (void) fr_copytolog(&iplci, sizeof(iplci)); + (void) fr_copytolog(dev, (char *)&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)) + if (fr_copytolog(dev, mtod(m, char *), hlen)) break; } - wakeup(iplbuf); + wakeup(iplbuf[dev]); return 1; } -#endif /* IPFILTER_LOG */ +# 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 +# if BSD < 199306 m = m_get(M_DONTWAIT, MT_HEADER); -#else +# else m = m_gethdr(M_DONTWAIT, MT_HEADER); m->m_data += max_linkhdr; -#endif +# endif if (m == NULL) return -1; if (ti->ti_flags & TH_SYN) tlen = 1; m->m_len = sizeof (struct tcpiphdr); -#if BSD >= 199306 +# if BSD >= 199306 m->m_pkthdr.len = sizeof (struct tcpiphdr); m->m_pkthdr.rcvif = (struct ifnet *)0; -#endif +# 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 +# if BSD < 199306 ip->ip_ttl = tcp_ttl; -#else +# else ip->ip_ttl = ip_defttl; -#endif +# endif /* * extra 0 in case of multicast */ (void) ip_output(m, (struct mbuf *)0, 0, 0, 0); return 0; } -#ifndef IPFILTER_LKM -void iplinit() +# ifndef IPFILTER_LKM +# if BSD < 199306 +int +# else +void +# endif +iplinit() { (void) iplattach(); ip_init(); } -#endif +# 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; #ifdef __bsdi__ dst->sin_len = sizeof(*dst); #endif #if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) # ifdef RTF_CLONING rtalloc_ign(ro, RTF_CLONING); -# else +# else rtalloc_ign(ro, RTF_PRCLONING); -# endif -#else +# endif +# else rtalloc(ro); -#endif +# 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 +# ifndef sparc ip->ip_id = htons(ip->ip_id); ip->ip_len = htons(ip->ip_len); ip->ip_off = htons(ip->ip_off); -#endif +# endif if (!ip->ip_sum) ip->ip_sum = in_cksum(m, hlen); -#if BSD >= 199306 +# if BSD >= 199306 error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, ro->ro_rt); -#else +# else error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst); -#endif +# 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 +# if BSD >= 199306 m->m_data += max_linkhdr; -#else +# else m->m_off = MMAXOFF - hlen; -#endif +# 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 +# ifndef sparc mhip->ip_off = htons((u_short)mhip->ip_off); -#endif +# 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 +# if BSD >= 199306 error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, ro->ro_rt); -#else +# else error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst); -#endif +# endif else m_freem(m); } } done: if (ro->ro_rt) { RTFREE(ro->ro_rt); } return; bad: m_freem(m); goto done; } +#else /* #ifdef _KERNEL */ + + +static int no_output __P((struct ifnet *ifp, struct mbuf *m, + struct sockaddr *s, struct rtentry *rt)) +{ + return 0; +} + + +# ifdef __STDC__ +static int write_output __P((struct ifnet *ifp, struct mbuf *m, + struct sockaddr *s, struct rtentry *rt)) +{ + ip_t *ip = (ip_t *)m; +# else +static int write_output(ifp, ip) +struct ifnet *ifp; +ip_t *ip; +{ +# endif + FILE *fp; + char fname[32]; + +#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) + sprintf(fname, "/tmp/%s", ifp->if_xname); + if ((fp = fopen(fname, "a"))) { + fclose(fp); + } +#else + sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); + if ((fp = fopen(fname, "a"))) { + fwrite((char *)ip, ntohs(ip->ip_len), 1, fp); + fclose(fp); + } +#endif +} + + +struct ifnet *get_unit(name) +char *name; +{ + struct ifnet *ifp, **ifa; +#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) + for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { + if (!strcmp(name, ifp->if_xname)) + return ifp; + } +#else + char ifname[32], *s; + + for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { + (void) sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit); + if (!strcmp(name, ifname)) + return ifp; + } +#endif + + if (!ifneta) { + ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2); + ifneta[1] = NULL; + ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp)); + nifs = 1; + } else { + nifs++; + ifneta = (struct ifnet **)realloc(ifneta, + (nifs + 1) * sizeof(*ifa)); + ifneta[nifs] = NULL; + ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp)); + } + ifp = ifneta[nifs - 1]; + +#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) + strncpy(ifp->if_xname, name, sizeof(ifp->if_xname)); +#else + for (s = name; *s && !isdigit(*s); s++) + ; + if (*s && isdigit(*s)) { + ifp->if_unit = atoi(s); + ifp->if_name = (char *)malloc(s - name + 1); + strncpy(ifp->if_name, name, s - name); + ifp->if_name[s - name] = '\0'; + } else { + ifp->if_name = strdup(name); + ifp->if_unit = -1; + } +#endif + ifp->if_output = no_output; + return ifp; +} + + +void init_ifp() +{ + FILE *fp; + struct ifnet *ifp, **ifa; + char fname[32]; +#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) + for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { + ifp->if_output = write_output; + sprintf(fname, "/tmp/%s", ifp->if_xname); + if ((fp = fopen(fname, "w"))) + fclose(fp); + } +#else + + for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { + ifp->if_output = write_output; + sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); + if ((fp = fopen(fname, "w"))) + fclose(fp); + } +#endif +} + + +void ipfr_fastroute(ip, fin, fdp) +ip_t *ip; +fr_info_t *fin; +frdest_t *fdp; +{ + struct ifnet *ifp = fdp->fd_ifp; + + if (!ifp) + return; /* no routing table out here */ + + ip->ip_len = htons((u_short)ip->ip_len); + ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); + ip->ip_sum = 0; + (*ifp->if_output)(ifp, (void *)ip, NULL, 0); +} + + +void ipllog() +{ + verbose("l"); +} + + +int send_reset(ip, ifp) +ip_t *ip; +struct ifnet *ifp; +{ + verbose("- TCP RST sent\n"); + return 0; +} + + +int icmp_error(ip, ifp) +ip_t *ip; +struct ifnet *ifp; +{ + verbose("- TCP RST sent\n"); + return 0; +} +#endif /* _KERNEL */ diff --git a/contrib/ipfilter/ip_fil.h b/contrib/ipfilter/ip_fil.h index 389a161bc2df..f6acda702e88 100644 --- a/contrib/ipfilter/ip_fil.h +++ b/contrib/ipfilter/ip_fil.h @@ -1,293 +1,370 @@ /* * (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 $ + * $Id: ip_fil.h,v 2.0.2.9 1997/04/02 12:23:20 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 -# include -# ifdef _KERNEL -# include -/* - * because Solaris 2 defines these in two places :-/ - */ -#undef IPOPT_EOL -#undef IPOPT_NOP -#undef IPOPT_LSRR -#undef IPOPT_RR -#undef IPOPT_SSRR -# include + +#ifndef __P +# ifdef __STDC__ +# define __P(x) x +# else +# define __P(x) () # 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*/ + /* + * There are only incremented when a packet matches this rule and + * it is the last match + */ + U_QUAD_T fr_hits; + U_QUAD_T fr_bytes; /* * 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 */ + int (*fr_func) __P((int, struct ip *, fr_info_t *)); /* 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]; +/* + * Device filenames. Use ipf on Solaris2 because ipl is already a name used + * by something else. + */ +#ifndef IPL_NAME +# if SOLARIS +# define IPL_NAME "/dev/ipf" +# else +# define IPL_NAME "/dev/ipl" +# endif +#endif +#define IPL_NAT "/dev/ipnat" +#define IPL_STATE "/dev/ipstate" +#define IPL_LOGIPF 0 /* Minor device #'s for accessing logs */ +#define IPL_LOGNAT 1 +#define IPL_LOGSTATE 2 -#ifdef _KERNEL +#if !defined(CDEV_MAJOR) && defined (__FreeBSD_version) && \ + (__FreeBSD_version >= 220000) +# define CDEV_MAJOR 79 +#endif -extern struct frentry *ipfilter[2][2], *ipacct[2][2]; -extern struct filterstats frstats[]; +#ifndef _KERNEL +extern int fr_check __P((struct ip *, int, struct ifnet *, int, char *)); +extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, + int, char *)); +extern int send_reset __P((struct ip *, struct ifnet *)); +extern int icmp_error __P((struct ip *, struct ifnet *)); +extern void ipllog __P((void)); +extern void ipfr_fastroute __P((struct ip *, fr_info_t *, frdest_t *)); +#else # if SOLARIS -extern int ipfsync(); +extern int fr_check __P((struct ip *, int, struct ifnet *, int, qif_t *, + queue_t *, mblk_t **)); +extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, + int, qif_t *, queue_t *, mblk_t *)); +extern int icmp_error __P((queue_t *, ip_t *, int, int, qif_t *, + struct in_addr)); +# else +extern int fr_check __P((struct ip *, int, struct ifnet *, int, + struct mbuf **)); +extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, + struct mbuf **)); +extern int send_reset __P((struct tcpiphdr *)); +extern int ipllog __P((u_int, int, struct ip *, fr_info_t *, struct mbuf *)); +extern void ipfr_fastroute __P((struct mbuf *, fr_info_t *, frdest_t *)); # endif +#endif +extern int fr_copytolog __P((int, char *, int)); +extern int ipl_unreach; +extern fr_info_t frcache[]; +extern char *iplh[3], *iplt[3]; +extern char iplbuf[3][IPLLOGSIZE]; +extern int iplused[3]; +extern struct frentry *ipfilter[2][2], *ipacct[2][2]; +extern struct filterstats frstats[]; + +#ifndef _KERNEL +extern int iplioctl __P((dev_t, int, caddr_t, int)); +extern int iplopen __P((dev_t, int)); +extern int iplclose __P((dev_t, int)); +#else +extern int iplattach __P((void)); +extern int ipldetach __P((void)); +# if SOLARIS +extern int iplioctl __P((dev_t, int, int, int, cred_t *, int *)); +extern int iplopen __P((dev_t *, int, int, cred_t *)); +extern int iplclose __P((dev_t, int, int, cred_t *)); +extern int ipfsync __P((void)); +# ifdef IPFILTER_LOG +extern int iplread __P((dev_t, struct uio *, cred_t *)); +# endif +# else +# ifdef IPFILTER_LKM +extern int iplidentify __P((char *)); +# endif +# if (_BSDI_VERSION >= 199510) || (__FreeBSD_version >= 199612) +extern int iplioctl __P((dev_t, int, caddr_t, int, struct proc *)); +extern int iplopen __P((dev_t, int, int, struct proc *)); +extern int iplclose __P((dev_t, int, int, struct proc *)); +# else +extern int iplioctl __P((dev_t, int, caddr_t, int)); +extern int iplopen __P((dev_t, int)); +extern int iplclose __P((dev_t, int)); +# endif /* (_BSDI_VERSION >= 199510) */ +# ifdef IPFILTER_LOG +# if BSD >= 199306 +extern int iplread __P((dev_t, struct uio *, int)); +# else +extern int iplread __P((dev_t, struct uio *)); +# endif /* BSD >= 199306 */ +# else +# define iplread noread +# endif /* IPFILTER_LOG */ +# endif /* SOLARIS */ #endif /* _KERNEL */ #endif /* __IP_FIL_H__ */ diff --git a/contrib/ipfilter/ip_frag.c b/contrib/ipfilter/ip_frag.c index 7ed97ceb56fd..59dac40b23fa 100644 --- a/contrib/ipfilter/ip_frag.c +++ b/contrib/ipfilter/ip_frag.c @@ -1,277 +1,292 @@ /* * (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.2 1997/02/16 06:17:35 darrenr Exp $"; +static char rcsid[] = "$Id: ip_frag.c,v 2.0.2.5 1997/04/02 12:23:21 darrenr Exp $"; #endif #if !defined(_KERNEL) && !defined(KERNEL) # include # include #endif #include #include #include +#include #include +#if defined(__FreeBSD__) && (__FreeBSD__ >= 3) +#include +#include +#include +#else #include +#endif #include #include #include -#ifdef _KERNEL +#ifdef _KERNEL # include #endif #if !defined(__SVR4) && !defined(__svr4__) # include #else # include # include # include # include #endif #include #ifdef sun #include #endif #include #include #include #include #include #include #include #include #include -#include "ip_fil.h" #include "ip_compat.h" +#include "ip_fil.h" #include "ip_frag.h" #include "ip_nat.h" #include "ip_state.h" ipfr_t *ipfr_heads[IPFT_SIZE]; ipfrstat_t ipfr_stats; u_long ipfr_inuse = 0, 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 +#ifdef __FreeBSD__ +# if BSD < 199306 +int ipfr_slowtimer __P((void)); +# else +void ipfr_slowtimer __P((void)); +# endif +#endif /* __FreeBSD__ */ 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)))) { + KMALLOC(fr, ipfr_t *, sizeof(*fr)); + if (fr == NULL) { 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); 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 +# if (BSD >= 199306) || SOLARIS void ipfr_slowtimer() +# else +int 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 index a356785e528c..28b314c72aff 100644 --- a/contrib/ipfilter/ip_frag.h +++ b/contrib/ipfilter/ip_frag.h @@ -1,47 +1,51 @@ /* * (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 $ + * $Id: ip_frag.h,v 2.0.2.4 1997/03/27 13:45:09 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 +extern ipfrstat_t *ipfr_fragstats __P((void)); +extern int ipfr_newfrag __P((ip_t *, fr_info_t *, int)); +extern int ipfr_knownfrag __P((ip_t *, fr_info_t *)); +extern void ipfr_unload __P((void)); +#if (BSD >= 199306) || SOLARIS +extern void ipfr_slowtimer __P((void)); +#else +extern int ipfr_slowtimer __P((void)); +#endif #endif /* __IP_FIL_H__ */ diff --git a/contrib/ipfilter/ip_nat.c b/contrib/ipfilter/ip_nat.c index ee59a6cda1dd..7e0e38177089 100644 --- a/contrib/ipfilter/ip_nat.c +++ b/contrib/ipfilter/ip_nat.c @@ -1,895 +1,996 @@ /* * (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.11 1997/02/16 06:26:47 darrenr Exp $"; +static char rcsid[] = "$Id: ip_nat.c,v 2.0.2.8 1997/04/02 12:23:23 darrenr Exp $"; +#endif + +#if defined(__FreeBSD__) && defined(KERNEL) +#define _KERNEL #endif #if !defined(_KERNEL) && !defined(KERNEL) # include # include # include #endif #include #include #include +#include #include #include #include #include #include -#ifdef _KERNEL +#ifdef _KERNEL # include #endif #if !defined(__SVR4) && !defined(__svr4__) # include #else # include # include # include # include #endif #include #ifdef sun #include #endif #include #include #include #include #ifdef RFC1825 #include #include extern struct ifnet vpnif; #endif #include #include #include #include #include -#include "ip_fil.h" #include "ip_compat.h" +#include "ip_fil.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(); +static int flush_nattable __P((void)), clear_natlist __P((void)); +static void nattable_sync __P((void)), nat_delete __P((struct nat *)); +static nat_t *nat_new __P((ipnat_t *, ip_t *, fr_info_t *, u_short, int)); +static void fix_outcksum __P((u_short *, u_long)); +static void fix_incksum __P((u_short *, u_long)); -void fix_outcksum(sp, n) +static 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) +static 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, s; /* * For add/delete, look to see if the NAT entry is already present */ MUTEX_ENTER(&ipf_nat); SPLNET(s); 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)))) { + KMALLOC(n, ipnat_t *, sizeof(*n)); + if (n == NULL) { 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; } SPLX(s); 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) +static 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)))) + KMALLOC(nat, nat_t *, sizeof(*nat)); + if (nat == NULL) return NULL; bzero((char *)nat, sizeof(*nat)); + nat->nat_flags = flags; /* * Search the current table for a match. */ if (direction == NAT_OUTBOUND) { +#if SOLARIS + ill_t *ill = fin->fin_ifp; +#else + struct ifnet *ifp = fin->fin_ifp; +#endif /* * 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 (!in.s_addr && (np->in_outmsk == 0xffffffff)) { +#if SOLARIS + in.s_addr = ill->ill_ipif->ipif_local_addr; +#else + struct ifaddr *ifa; + struct sockaddr_in *sin; + + ifa = ifp->if_addrlist; +# if BSD < 199306 + sin = (struct sockaddr_in *)&ifa->ifa_addr; +# else + sin = (struct sockaddr_in *)ifa->ifa_addr; + while (sin && ifa && + sin->sin_family != AF_INET) { + ifa = ifa->ifa_next; + sin = (struct sockaddr_in *)ifa->ifa_addr; + } + if (!ifa) + sin = NULL; + if (!sin) { + KFREE(nat); + return NULL; + } +# endif + in = sin->sin_addr; + in.s_addr = ntohl(in.s_addr); +#endif + } 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))) + flags == nat->nat_flags && (!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))) + flags == nat->nat_flags && (!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))) + flags == nat->nat_flags && (!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 + * If it's a redirection, then we don't want * to create new outgoing port stuff. * Redirections are only for incoming * connections. */ + if (np->in_redir == NAT_REDIRECT) + continue; if (!(nat = nat_new(np, ip, fin, nflags, NAT_OUTBOUND))) break; +#ifdef IPFILTER_LOG + nat_log(nat, (u_short)np->in_redir); +#endif } 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); + fr_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 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 (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; - } + if (!(nat = nat_new(np, ip, fin, nflags, + NAT_INBOUND))) + break; +#ifdef IPFILTER_LOG + nat_log(nat, (u_short)np->in_redir); +#endif } 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); + fr_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() { int s; MUTEX_ENTER(&ipf_nat); SPLNET(s); (void) clear_natlist(); (void) flush_nattable(); SPLX(s) 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; int s; MUTEX_ENTER(&ipf_nat); SPLNET(s); for (natp = &nat_instances; (nat = *natp); ) { if (--nat->nat_age) { natp = &nat->nat_next; continue; } *natp = nat->nat_next; +#ifdef IPFILTER_LOG + nat_log(nat, NL_EXPIRE); +#endif nat_delete(nat); nat_stats.ns_expire++; } SPLX(s); MUTEX_EXIT(&ipf_nat); } + + +#ifdef IPFILTER_LOG +void nat_log(nat, type) +struct nat *nat; +u_short type; +{ + struct ipnat *np; + struct natlog natl; + int rulen; + + if (iplused[IPL_LOGNAT] + sizeof(natl) > IPLLOGSIZE) { + nat_stats.ns_logfail++; + return; + } + + if (iplh[IPL_LOGNAT] == iplbuf[IPL_LOGNAT] + IPLLOGSIZE) + iplh[IPL_LOGNAT] = iplbuf[IPL_LOGNAT]; + +# ifdef sun + uniqtime(&natl); +# endif +# if BSD >= 199306 || defined(__FreeBSD__) + microtime((struct timeval *)&natl); +# endif + natl.nl_origport = nat->nat_oport; + natl.nl_outport = nat->nat_outport; + natl.nl_inport = nat->nat_inport; + natl.nl_origip = nat->nat_oip; + natl.nl_outip = nat->nat_outip; + natl.nl_inip = nat->nat_inip; + natl.nl_type = type; + natl.nl_rule = -1; + if (nat->nat_ptr) { + for (rulen = 0, np = nat_list; np; np = np->in_next, rulen++) + if (np == nat->nat_ptr) { + natl.nl_rule = rulen; + break; + } + } + + if (!fr_copytolog(IPL_LOGNAT, (char *)&natl, sizeof(natl))) { + iplused[IPL_LOGNAT] += sizeof(natl); + nat_stats.ns_logged++; + } else + nat_stats.ns_logfail++; + wakeup(iplbuf[IPL_LOGNAT]); +} +#endif diff --git a/contrib/ipfilter/ip_nat.h b/contrib/ipfilter/ip_nat.h index d64183ac3920..bf435e08e3b3 100644 --- a/contrib/ipfilter/ip_nat.h +++ b/contrib/ipfilter/ip_nat.h @@ -1,118 +1,149 @@ /* * (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 $ + * $Id: ip_nat.h,v 2.0.2.6 1997/03/31 10:05:30 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_age; + int nat_flags; 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; + u_long ns_logged; + u_long ns_logfail; 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 + +typedef struct natlog { + struct timeval nl_tv; + struct in_addr nl_origip; + struct in_addr nl_outip; + struct in_addr nl_inip; + u_short nl_origport; + u_short nl_outport; + u_short nl_inport; + u_short nl_type; + int nl_rule; +} natlog_t; + + +#define NL_NEWMAP NAT_MAP +#define NL_NEWRDR NAT_REDIRECT +#define NL_EXPIRE 0xffff + + 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(); +extern int nat_ioctl __P((caddr_t, int, int)); +extern nat_t *nat_outlookup __P((int, struct in_addr, u_short, + struct in_addr, u_short)); +extern nat_t *nat_inlookup __P((int, struct in_addr, u_short, + struct in_addr, u_short)); +extern nat_t *nat_lookupredir __P((natlookup_t *)); +extern nat_t *nat_lookupmapip __P((int, struct in_addr, u_short, + struct in_addr, u_short)); + +extern int ip_natout __P((ip_t *, int, fr_info_t *)); +extern int ip_natin __P((ip_t *, int, fr_info_t *)); +extern void ip_natunload __P((void)), ip_natexpire __P((void)); +extern void nat_log __P((struct nat *, u_short)); #endif /* __IP_NAT_H__ */ diff --git a/contrib/ipfilter/ip_sfil.c b/contrib/ipfilter/ip_sfil.c index debc512707d6..5d0e8fe3a896 100644 --- a/contrib/ipfilter/ip_sfil.c +++ b/contrib/ipfilter/ip_sfil.c @@ -1,731 +1,745 @@ /* * (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 $"; +static char rcsid[] = "$Id: ip_sfil.c,v 2.0.2.3 1997/03/27 13:45:13 darrenr Exp $"; #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include "ip_fil.h" #include "ip_compat.h" +#include "ip_fil.h" #include "ip_state.h" #include "ip_frag.h" #include "ip_nat.h" #include #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(); +int send_reset __P((struct tcpiphdr *, qif_t *, queue_t *)); +u_short ipf_cksum __P((u_short *, int)); +static void frzerostats __P((caddr_t)); #ifdef IPFILTER_LOG -int ipllog(); -static void frflush(); -char iplbuf[IPLLOGSIZE]; -caddr_t iplh = iplbuf, iplt = iplbuf; -static int iplused = 0; +int ipllog __P((u_int, int, ip_t *, fr_info_t *, mblk_t *)); +static void frflush __P((caddr_t)); +char iplbuf[3][IPLLOGSIZE]; +caddr_t iplh[3], iplt[3]; +static int iplused[3] = {0, 0, 0}; #endif /* IPFILTER_LOG */ -static int frrequest(); +static int frrequest __P((int, caddr_t, int)); 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() +int iplattach __P((void)) { + int i; + + for (i = 0; i <= 2; i++) { + iplt[i] = iplbuf[i]; + iplh[i] = iplbuf[i]; + } + 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 data; int mode; cred_t *cp; int *rp; { - int error = 0; + int error = 0, unit; + + unit = getminor(dev); switch (cmd) { case SIOCFRENB : { u_int enable; if (!(mode & FWRITE)) return EPERM; - IRCOPY(data, (caddr_t)&enable, sizeof(enable)); + IRCOPY((caddr_t)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)); + IRCOPY((caddr_t)data, (caddr_t)&fr_flags, sizeof(fr_flags)); mutex_exit(&ipf_mutex); break; case SIOCGETFF : - IWCOPY((caddr_t)&fr_flags, data, sizeof(fr_flags)); + IWCOPY((caddr_t)&fr_flags, (caddr_t)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); + error = frrequest(cmd, (caddr_t)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); + error = frrequest(cmd, (caddr_t)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)); + IWCOPY((caddr_t)&fio, (caddr_t)data, sizeof(fio)); break; } case SIOCFRZST : if (!(mode & FWRITE)) return EPERM; - frzerostats(data); + frzerostats((caddr_t)data); break; #ifdef IPFILTER_LOG case SIOCIPFFL : if (!(mode & FWRITE)) return EPERM; mutex_enter(&ipf_mutex); - frflush(data); + frflush((caddr_t)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; + IWCOPY((caddr_t)&iplused[unit], (caddr_t)data, + sizeof(iplused[unit])); + iplh[unit] = iplt[unit] = iplbuf[unit]; + iplused[unit] = 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); + error = nat_ioctl((caddr_t)data, cmd, mode); break; case SIOCGFRST : - IWCOPY((caddr_t)ipfr_fragstats(), data, sizeof(ipfrstat_t)); + IWCOPY((caddr_t)ipfr_fragstats(), (caddr_t)data, + sizeof(ipfrstat_t)); break; case SIOCGIPST : - IWCOPY((caddr_t)fr_statetstats(), data, sizeof(ips_stat_t)); + IWCOPY((caddr_t)fr_statetstats(), (caddr_t)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)))) { + KMALLOC(f, frentry_t *, sizeof(*f)); + if (f != NULL) { 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; + min = (2 < min || min < 0) ? ENXIO : 0; 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; + min = (2 < min || min < 0) ? ENXIO : 0; 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; + int error, used, usedo, copied, unit; + + unit = getminor(dev); 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) { + while (!iplused[unit]) { error = cv_wait_sig(&iplwait, &ipl_mutex); if (!error) { mutex_exit(&ipl_mutex); return EINTR; } } - h = iplh; - t = iplt; - used = iplused; + h = iplh[unit]; + t = iplt[unit]; + used = iplused[unit]; 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); + sz = MIN(sz, IPLLOGSIZE + iplbuf[unit] - t); if (!(ret = uiomove(t, sz, UIO_READ, uio))) { t += sz; sx -= sz; used -= sz; - if ((h < t) && (t >= iplbuf + IPLLOGSIZE)) - t = iplbuf; + if ((h < t) && (t >= iplbuf[unit] + IPLLOGSIZE)) + t = iplbuf[unit]; 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; + iplused[unit] -= copied; - if (!iplused) /* minimise wrapping around the end */ - iplh = iplt = iplbuf; + if (!iplused[unit]) /* minimise wrapping around the end */ + iplh[unit] = iplt[unit] = iplbuf[unit]; else { - iplt += copied; - if (iplt >= iplbuf + IPLLOGSIZE) - iplt -= IPLLOGSIZE; - if (iplt == iplbuf + IPLLOGSIZE) - iplt = iplbuf; + iplt[unit] += copied; + if (iplt[unit] >= iplbuf[unit] + IPLLOGSIZE) + iplt[unit] -= IPLLOGSIZE; + if (iplt[unit] == iplbuf[unit] + IPLLOGSIZE) + iplt[unit] = iplbuf[unit]; } mutex_exit(&ipl_mutex); return ret; } -int ipllog(flags, ip, fin, m) +int ipllog(flags, dev, ip, fin, m) u_int flags; +int dev; 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) { + if ((iplused[dev] + len) > IPLLOGSIZE) { mutex_exit(&ipl_mutex); return 0; } - iplused += len; + iplused[dev] += 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)); + (void) fr_copytolog(dev, (char *)&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)) + if (fr_copytolog(dev, 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); + icmp->icmp_cksum = ipf_cksum((u_short *)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 index 2643ce95a633..edd05b85280d 100644 --- a/contrib/ipfilter/ip_state.c +++ b/contrib/ipfilter/ip_state.c @@ -1,542 +1,604 @@ /* * (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.3 1997/02/16 06:18:36 darrenr Exp $"; +static char rcsid[] = "$Id: ip_state.c,v 2.0.2.6 1997/04/02 12:23:24 darrenr Exp $"; #endif #if !defined(_KERNEL) && !defined(KERNEL) # include # include #endif #include #include #include +#include #include +#if defined(__FreeBSD__) && (__FreeBSD__ >= 3) +#include +#include +#include +#else #include +#endif #include #include #include -#ifdef _KERNEL +#ifdef _KERNEL # include #endif #if !defined(__SVR4) && !defined(__svr4__) # include #else # include # include # include # include #endif #include #ifdef sun #include #endif #include #include #include #include #include #include #include #include #include #include -#include "ip_fil.h" #include "ip_compat.h" +#include "ip_fil.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); + fr_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)))) { + KMALLOC(is, ipstate_t *, sizeof(*is)); + if (is == NULL) { 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; + is->is_pkts = 1; + is->is_bytes = ip->ip_len; if (pass & FR_LOGFIRST) is->is_pass &= ~(FR_LOGFIRST|FR_LOG); ips_num++; +#ifdef IPFILTER_LOG + ipstate_log(is, ISL_NEW); +#endif 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 +int fr_tcpstate(is, fin, ip, tcp, sport) 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++; + is->is_pkts++; + is->is_bytes += ip->ip_len; /* * Nearing end of connection, start timeout. */ - set_tcp_age(&is->is_age, is->is_state, ip, fin, - tcp->th_sport == is->is_sport); + fr_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; + u_int hv, hlen, pass; 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; + is->is_pkts++; + is->is_bytes += ip->ip_len; 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 + return pass; } } 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_pkts++; + is->is_bytes += ip->ip_len; is->is_age = fr_udptimeout; + pass = is->is_pass; MUTEX_EXIT(&ipf_state); - return is->is_pass; + return 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; int s; MUTEX_ENTER(&ipf_state); SPLNET(s); for (i = 0; i < IPSTATE_SIZE; i++) for (isp = &ips_table[i]; (is = *isp); ) { *isp = is->is_next; KFREE(is); } SPLX(s); 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; int s; MUTEX_ENTER(&ipf_state); SPLNET(s); 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++; +#ifdef IPFILTER_LOG + ipstate_log(is, ISL_EXPIRE); +#endif KFREE(is); ips_num--; } else isp = &is->is_next; SPLX(s); 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; +void fr_tcp_age(age, state, ip, fin, dir) +u_long *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; } } + + +#ifdef IPFILTER_LOG +void ipstate_log(is, type) +struct ipstate *is; +u_short type; +{ + struct ipslog ipsl; + + if (iplused[IPL_LOGSTATE] + sizeof(ipsl) > IPLLOGSIZE) { + ips_stats.iss_logfail++; + return; + } + + if (iplh[IPL_LOGSTATE] == iplbuf[IPL_LOGSTATE] + IPLLOGSIZE) + iplh[IPL_LOGSTATE] = iplbuf[IPL_LOGSTATE]; + +# ifdef sun + uniqtime(&ipsl); +# endif +# if BSD >= 199306 || defined(__FreeBSD__) + microtime((struct timeval *)&ipsl); +# endif + ipsl.isl_pkts = is->is_pkts; + ipsl.isl_bytes = is->is_bytes; + ipsl.isl_src = is->is_src; + ipsl.isl_dst = is->is_dst; + ipsl.isl_p = is->is_p; + ipsl.isl_flags = is->is_flags; + ipsl.isl_type = type; + if (ipsl.isl_p == IPPROTO_TCP || ipsl.isl_p == IPPROTO_UDP) { + ipsl.isl_sport = is->is_sport; + ipsl.isl_dport = is->is_dport; + } else if (ipsl.isl_p == IPPROTO_ICMP) + ipsl.isl_itype = is->is_icmp.ics_type; + else { + ipsl.isl_ps.isl_filler[0] = 0; + ipsl.isl_ps.isl_filler[1] = 0; + } + + if (!fr_copytolog(IPL_LOGSTATE, (char *)&ipsl, sizeof(ipsl))) { + iplused[IPL_LOGSTATE] += sizeof(ipsl); + ips_stats.iss_logged++; + } else + ips_stats.iss_logfail++; + wakeup(iplbuf[IPL_LOGSTATE]); +} +#endif diff --git a/contrib/ipfilter/ip_state.h b/contrib/ipfilter/ip_state.h index ee30b986d844..33395fc7021c 100644 --- a/contrib/ipfilter/ip_state.h +++ b/contrib/ipfilter/ip_state.h @@ -1,86 +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_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 $ + * $Id: ip_state.h,v 2.0.2.5 1997/03/31 10:05:32 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_long is_age; u_int is_pass; + U_QUAD_T is_pkts; + U_QUAD_T is_bytes; 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 ipslog { + struct timeval isl_tv; + U_QUAD_T isl_pkts; + U_QUAD_T isl_bytes; + struct in_addr isl_src; + struct in_addr isl_dst; + u_char isl_p; + u_char isl_flags; + u_short isl_type; + union { + u_short isl_filler[2]; + u_short isl_ports[2]; + u_short isl_icmp; + } isl_ps; +} ipslog_t; + +#define isl_sport isl_ps.isl_ports[0] +#define isl_dport isl_ps.isl_ports[1] +#define isl_itype isl_ps.isl_icmp + +#define ISL_NEW 0 +#define ISL_EXPIRE 0xffff + + 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; + u_long iss_logged; + u_long iss_logfail; 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 +extern int fr_tcpstate __P((ipstate_t *, fr_info_t *, ip_t *, + tcphdr_t *, u_short)); +extern ips_stat_t *fr_statetstats __P((void)); +extern int fr_addstate __P((ip_t *, fr_info_t *, u_int)); +extern int fr_checkstate __P((ip_t *, fr_info_t *)); +extern void fr_timeoutstate __P((void)); +extern void fr_tcp_age __P((u_long *, u_char *, ip_t *, fr_info_t *, int)); +extern void fr_stateunload __P((void)); +extern void ipstate_log __P((struct ipstate *, u_short)); #endif /* __IP_STATE_H__ */ diff --git a/contrib/ipfilter/ipf.c b/contrib/ipfilter/ipf.c index da6baa244648..d4747a1d8353 100644 --- a/contrib/ipfilter/ipf.c +++ b/contrib/ipfilter/ipf.c @@ -1,434 +1,445 @@ /* * (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 #include #include #include #include #if !defined(__SVR4) && !defined(__GNUC__) #include #endif -#if !defined(__SVR4) && defined(__GNUC__) -extern char *index(); -#endif #include #include #include #include -#include #include #include #include #include #include #include #include -#include "ip_fil.h" #include #include #include +#include "ip_compat.h" +#include "ip_fil.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 $"; +static char rcsid[] = "$Id: ipf.c,v 2.0.2.5 1997/03/31 10:05:33 darrenr Exp $"; #endif #if SOLARIS -void frsync(), blockunknown(); +static void frsync __P((void)); +static void blockunknown __P((void)); +#endif +#if !defined(__SVR4) && defined(__GNUC__) +extern char *index __P((const char *, int)); #endif -void zerostats(); extern char *optarg; +void zerostats __P((void)); +int main __P((int, char *[])); + int opts = 0; static int fd = -1; -static void procfile(), flushfilter(), set_state(); -static void packetlogon(), swapactive(), showstats(); -static char *getline(); +static void procfile __P((char *, char *)), flushfilter __P((char *)); +static void set_state __P((u_int)), showstats __P((friostat_t *)); +static void packetlogon __P((char *)), swapactive __P((void)); +static int opendevice __P((void)); +static char *getline __P((char *, size_t, FILE *)); 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); + set_state((u_int)1); break; case 'D' : - set_state(0); + set_state((u_int)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; + add = (u_int)fr->fr_hits ? SIOCINIFR : + SIOCADIFR; else - add = fr->fr_hits ? SIOCINAFR : SIOCADAFR; + add = (u_int)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 { +#ifdef USE_QUAD_T + printf("hits %qd bytes %qd ", +#else printf("hits %ld bytes %ld ", +#endif 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() +static 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() +static 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 index 3ac76fc288e5..4d35281dfc45 100644 --- a/contrib/ipfilter/ipf.h +++ b/contrib/ipfilter/ipf.h @@ -1,67 +1,81 @@ /* * (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 $ + * $Id: ipf.h,v 2.0.2.4 1997/03/27 13:45:18 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 +#define OPT_SAVEOUT 0x20000 -extern struct frentry *parse(); +#ifndef __P +# ifdef __STDC__ +# define __P(x) x +# else +# define __P(x) () +# endif +#endif + +extern struct frentry *parse __P((char *)); + +extern void printfr __P((struct frentry *)); +extern void binprint __P((struct frentry *)), initparse __P((void)); +extern u_short portnum __P((char *)); -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(); +extern u_long buildopts __P((char *, char *)); +extern u_long hostnum __P((char *, int *)); +extern u_long optname __P((char ***, u_short *)); +extern void printpacket __P((struct ip *)); #if SOLARIS -extern int inet_aton(); +extern int inet_aton __P((const char *, struct in_addr *)); #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 index 2c4cc0f0d21b..13e85577de6b 100644 --- a/contrib/ipfilter/ipft_ef.c +++ b/contrib/ipfilter/ipft_ef.c @@ -1,148 +1,150 @@ /* * (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 #include #if !defined(__SVR4) && !defined(__GNUC__) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 $"; +static char rcsid[] = "$Id: ipft_ef.c,v 2.0.2.3 1997/03/10 08:10:24 darrenr Exp $"; #endif -static int etherf_open(), etherf_close(), etherf_readip(); +static int etherf_open __P((char *)); +static int etherf_close __P((void)); +static int etherf_readip __P((char *, int, char **, int *)); 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 index 26dbc83d15a4..e57eedae7d5c 100644 --- a/contrib/ipfilter/ipft_hx.c +++ b/contrib/ipfilter/ipft_hx.c @@ -1,140 +1,163 @@ /* * (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 #include #include #include #if !defined(__SVR4) && !defined(__svr4__) #include #else #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 $"; +static char rcsid[] = "$Id: ipft_hx.c,v 2.0.2.3 1997/03/10 08:10:25 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(); +static int hex_open __P((char *)); +static int hex_close __P((void)); +static int hex_readip __P((char *, int, char **, int *)); +static char *readhex __P((char *, char *)); 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; + register char *s, *t, *u; 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); + + /* + * interpret start of line as possibly "[ifname]" or + * "[in/out,ifname]". + */ + *ifn = NULL; + *dir = 0; + if ((*buf == '[') && (s = index(line, ']'))) { + t = buf + 1; + if (t - s > 0) { + if ((u = index(t, ',')) && (u < s)) { + u++; + *ifn = u; + if (*t == 'i') + *dir = 0; + else if (*t == 'o') + *dir = 1; + } else + *ifn = t; + *s++ = '\0'; + } + } else + s = line; + ip = (struct ip *)readhex(s, (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 index 3d3d8879bd80..5b8967a534a2 100644 --- a/contrib/ipfilter/ipft_pc.c +++ b/contrib/ipfilter/ipft_pc.c @@ -1,224 +1,228 @@ /* * (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 #include #if !defined(__SVR4) && !defined(__GNUC__) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 $"; +static char rcsid[] = "$Id: ipft_pc.c,v 2.0.2.3 1997/03/10 08:10:26 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 pcap_open __P((char *)); +static int pcap_close __P((void)); +static int pcap_readip __P((char *, int, char **, int *)); +static void swap_hdr __P((pcaphdr_t *)); +static int pcap_read_rec __P((struct pcap_pkthdr *)); 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 index 3185b56157dc..e8c098a63787 100644 --- a/contrib/ipfilter/ipft_sn.c +++ b/contrib/ipfilter/ipft_sn.c @@ -1,206 +1,209 @@ /* * (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 #include #if !defined(__SVR4) && !defined(__GNUC__) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 $"; +static char rcsid[] = "$Id: ipft_sn.c,v 2.0.2.3 1997/03/10 08:10:29 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 snoop_open __P((char *)); +static int snoop_close __P((void)); +static int snoop_readip __P((char *, int, char **, int *)); static int sfd = -1, s_type = -1; +static int snoop_read_rec __P((struct snooppkt *)); 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 index ecd2badae454..ef39bf0e1dee 100644 --- a/contrib/ipfilter/ipft_td.c +++ b/contrib/ipfilter/ipft_td.c @@ -1,184 +1,187 @@ /* * (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 #include #if !defined(__SVR4) && !defined(__GNUC__) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 $"; +static char rcsid[] = "$Id: ipft_td.c,v 2.0.2.3 1997/03/10 08:10:30 darrenr Exp $"; #endif -static int tcpd_open(), tcpd_close(), tcpd_readip(); +static int tcpd_open __P((char *)); +static int tcpd_close __P((void)); +static int tcpd_readip __P((char *, int, char **, int *)); +static int count_dots __P((char *)); 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 index 0522f96cfae5..cce9af7baec5 100644 --- a/contrib/ipfilter/ipft_tx.c +++ b/contrib/ipfilter/ipft_tx.c @@ -1,338 +1,342 @@ /* * (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 #include #include #include #if !defined(__SVR4) && !defined(__svr4__) #include #else #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 $"; +static char rcsid[] = "$Id: ipft_tx.c,v 2.0.2.3 1997/03/10 08:10:31 darrenr Exp $"; #endif extern int opts; -extern u_long buildopts(); +extern u_long buildopts __P((char *, char *)); static char *tx_proto = ""; -static int text_open(), text_close(), text_readip(), parseline(); +static int text_open __P((char *)), text_close __P((void)); +static int text_readip __P((char *, int, char **, int *)); +static int parseline __P((char *, struct ip *, char **, int *)); 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(); +static u_long tx_hostnum __P((char *, int *)); +static u_short tx_portnum __P((char *)); /* * 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 (!parseline(line, (struct ip *)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; + if (*ifn) + free(*ifn); 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++; + *ifn = strdup(*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 index 9a2e43d995d2..1057a58936dd 100644 --- a/contrib/ipfilter/ipl.h +++ b/contrib/ipfilter/ipl.h @@ -1,16 +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" +#define IPL_VERSION "IP Filter v3.2alpha4" #endif diff --git a/contrib/ipfilter/ipmon.c b/contrib/ipfilter/ipmon.c index 2ea34efb1874..cb71ff7e782c 100644 --- a/contrib/ipfilter/ipmon.c +++ b/contrib/ipfilter/ipmon.c @@ -1,582 +1,902 @@ /* * (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 -#include #include -#include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include #if !defined(__SVR4) && !defined(__svr4__) +#include #include -#include #else #include #endif -#include +#include +#include +#include +#include +#include +#include #include -#include - -#include +#include #include #include +#include #include +#include +#include +#include +#include + +#include +#include +#include + #include #include #include #include -#include -#include + #include +#include + +#include "ip_compat.h" +#include "ip_fil.h" +#include "ip_nat.h" +#include "ip_state.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 $"; +static char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-1996 Darren Reed"; +static char rcsid[] = "$Id: ipmon.c,v 2.0.2.6 1997/04/02 12:23:27 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 +static void usage __P((char *)); +static void print_ipflog __P((FILE *, char *, int)); +static void print_natlog __P((FILE *, char *, int)); +static void print_statelog __P((FILE *, char *, int)); +static void dumphex __P((FILE *, u_char *, int)); +static void printiplci __P((struct ipl_ci *)); +static void resynclog __P((int, struct ipl_ci *, FILE *)); +static int read_ipflog __P((int, int *, char *, int, FILE *)); +static int read_natlog __P((int, int *, char *, int, FILE *)); +static int read_statelog __P((int, int *, char *, int, FILE *)); +char *hostname __P((int, struct in_addr)); +char *portname __P((int, char *, u_short)); +int main __P((int, char *[])); + +static int (*readfunc[3]) __P((int, int *, char *, int, FILE *)) = + { read_ipflog, read_natlog, read_statelog }; +static void (*printfunc[3]) __P((FILE *, char *, int)) = + { print_ipflog, print_natlog, print_statelog }; + + +#define OPT_SYSLOG 0x001 +#define OPT_RESOLVE 0x002 +#define OPT_HEXBODY 0x004 +#define OPT_VERBOSE 0x008 +#define OPT_HEXHDR 0x010 +#define OPT_TAIL 0x020 +#define OPT_ALL 0x040 +#define OPT_NAT 0x080 +#define OPT_STATE 0x100 #ifndef LOGFAC #define LOGFAC LOG_LOCAL0 #endif -void printiplci(icp) +static 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) +static int read_natlog(fd, lenp, buf, bufsize, log) +int fd, bufsize, *lenp; +char *buf; +FILE *log; +{ + int len, avail = 0, want = sizeof(struct natlog); + + *lenp = 0; + + if (ioctl(fd, FIONREAD, &avail) == -1) { + perror("ioctl(FIONREAD"); + return 1; + } + + if (avail < want) + return 2; + + while (want) { + len = read(fd, buf, want); + if (len > 0) + want -= len; + else + break; + } + + if (!want) { + *lenp = sizeof(struct natlog); + return 0; + } + return !len ? 2 : -1; +} + + +static int read_statelog(fd, lenp, buf, bufsize, log) +int fd, bufsize, *lenp; +char *buf; +FILE *log; +{ + int len, avail = 0, want = sizeof(struct ipslog); + + *lenp = 0; + + if (ioctl(fd, FIONREAD, &avail) == -1) { + perror("ioctl(FIONREAD"); + return 1; + } + + if (avail < want) + return 2; + + while (want) { + len = read(fd, buf, want); + if (len > 0) + want -= len; + else + break; + } + + if (!want) { + *lenp = sizeof(struct ipslog); + return 0; + } + return !len ? 2 : -1; +} + + +static int read_ipflog(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); + syslog(LOG_INFO, "Out of sync! (1,%lx)\n", now); else - fprintf(log, "Out of sync! (1,%x)\n", now); + fprintf(log, "Out of sync! (1,%lx)\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) +static void print_natlog(log, buf, blen) +FILE *log; +char *buf; +int blen; +{ + struct natlog *nl = (struct natlog *)buf; + char *t = line; + struct tm *tm; + int res; + + res = (opts & OPT_RESOLVE) ? 1 : 0; + tm = localtime((time_t *)&nl->nl_tv.tv_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); + } + (void) sprintf(t, "%02d:%02d:%02d.%-.6ld @%hd ", + tm->tm_hour, tm->tm_min, tm->tm_sec, nl->nl_tv.tv_usec, + nl->nl_rule); + t += strlen(t); + + if (nl->nl_type == NL_NEWMAP) + strcpy(t, "NAT:MAP "); + else if (nl->nl_type == NL_NEWRDR) + strcpy(t, "NAT:RDR "); + else if (nl->nl_type == ISL_EXPIRE) + strcpy(t, "NAT:EXPIRE "); + else + sprintf(t, "Type: %d ", nl->nl_type); + t += strlen(t); + + (void) sprintf(t, "%s,%s <- -> ", hostname(res, nl->nl_inip), + portname(res, NULL, nl->nl_inport)); + t += strlen(t); + (void) sprintf(t, "%s,%s ", hostname(res, nl->nl_outip), + portname(res, NULL, nl->nl_outport)); + t += strlen(t); + (void) sprintf(t, "[%s,%s]", hostname(res, nl->nl_origip), + portname(res, NULL, nl->nl_origport)); + t += strlen(t); + + *t++ = '\n'; + *t++ = '\0'; + if (opts & OPT_SYSLOG) + syslog(LOG_INFO, "%s", line); + else + (void) fprintf(log, "%s", line); +} + + +static void print_statelog(log, buf, blen) +FILE *log; +char *buf; +int blen; +{ + struct ipslog *sl = (struct ipslog *)buf; + struct protoent *pr; + char *t = line, *proto, pname[6]; + struct tm *tm; + int res; + + res = (opts & OPT_RESOLVE) ? 1 : 0; + tm = localtime((time_t *)&sl->isl_tv.tv_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); + } + (void) sprintf(t, "%02d:%02d:%02d.%-.6ld ", + tm->tm_hour, tm->tm_min, tm->tm_sec, sl->isl_tv.tv_usec); + t += strlen(t); + + if (sl->isl_type == ISL_NEW) + strcpy(t, "STATE:NEW "); + else if (sl->isl_type == ISL_EXPIRE) + strcpy(t, "STATE:EXPIRE "); + else + sprintf(t, "Type: %d ", sl->isl_type); + t += strlen(t); + + pr = getprotobynumber((int)sl->isl_p); + if (!pr) { + proto = pname; + sprintf(proto, "%d", (u_int)sl->isl_p); + } else + proto = pr->p_name; + + if (sl->isl_p == IPPROTO_TCP || sl->isl_p == IPPROTO_UDP) { + (void) sprintf(t, "%s,%s -> ", + hostname(res, sl->isl_src), + portname(res, proto, sl->isl_sport)); + t += strlen(t); + (void) sprintf(t, "%s,%s PR %s ", + hostname(res, sl->isl_dst), + portname(res, proto, sl->isl_dport), proto); + } else if (sl->isl_p == IPPROTO_ICMP) { + (void) sprintf(t, "%s -> ", hostname(res, sl->isl_src)); + t += strlen(t); + (void) sprintf(t, "%s PR icmp %d ", + hostname(res, sl->isl_dst), sl->isl_itype); + } + t += strlen(t); + if (sl->isl_type != ISL_NEW) { +#ifdef USE_QUAD_T + (void) sprintf(t, "Pkts %qd Bytes %qd", +#else + (void) sprintf(t, "Pkts %ld Bytes %ld", +#endif + sl->isl_pkts, sl->isl_bytes); + t += strlen(t); + } + + *t++ = '\n'; + *t++ = '\0'; + if (opts & OPT_SYSLOG) + syslog(LOG_INFO, "%s", line); + else + (void) fprintf(log, "%s", line); +} + + +static void print_ipflog(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); + dumphex(log, (u_char *)ip, lp->plen + lp->hlen); +} + + +void static usage(prog) +char *prog; +{ + fprintf(stderr, "%s: [-NFhstvxX] [-f ]\n", prog); + exit(1); +} + + +void flushlogs(file, log) +char *file; +FILE *log; +{ + int fd, flushed = 0; + + if ((fd = open(file, O_RDWR)) == -1) { + (void) fprintf(stderr, "%s: ", file); + perror("open"); + exit(-1); + } + + if (ioctl(fd, SIOCIPFFB, &flushed) == 0) { + printf("%d bytes flushed from log buffer\n", + flushed); + fflush(stdout); + } else + perror("SIOCIPFFB"); + (void) close(fd); + + 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); + } } + int main(argc, argv) int argc; char *argv[]; { + struct stat stat; FILE *log = NULL; - int fd = -1, flushed = 0, doread, n; + int fd[3] = {-1, -1, -1}, flushed = 0, doread, n, i, nfd = 1; + int tr, nr, regular; + int fdt[3] = {IPL_LOGIPF, IPL_LOGNAT, IPL_LOGSTATE}; char buf[512], c, *iplfile = IPL_NAME; extern int optind; extern char *optarg; - while ((c = getopt(argc, argv, "Nf:FsvxX")) != -1) + while ((c = getopt(argc, argv, "?af:FhnNsStvxX")) != -1) switch (c) { + case 'a' : + opts |= OPT_ALL; + nfd = 3; + break; 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 (!(opts & OPT_ALL)) + flushlogs(iplfile, log); + else { + flushlogs(IPL_NAME, log); + flushlogs(IPL_NAT, log); + flushlogs(IPL_STATE, log); } - if (ioctl(fd, SIOCIPFFB, &flushed) == 0) { - printf("%d bytes flushed from log buffer\n", - flushed); - fflush(stdout); - } else - perror("SIOCIPFFB"); break; - case 'N' : + case 'n' : opts |= OPT_RESOLVE; break; + case 'N' : + opts |= OPT_NAT; + fdt[0] = IPL_LOGNAT; + readfunc[0] = read_natlog; + printfunc[0] = print_natlog; + break; case 's' : openlog(argv[0], LOG_NDELAY|LOG_PID, LOGFAC); opts |= OPT_SYSLOG; break; + case 'S' : + opts |= OPT_STATE; + fdt[0] = IPL_LOGSTATE; + readfunc[0] = read_statelog; + printfunc[0] = print_statelog; + break; + case 't' : + opts |= OPT_TAIL; + break; case 'v' : opts |= OPT_VERBOSE; break; case 'x' : opts |= OPT_HEXBODY; break; case 'X' : opts |= OPT_HEXHDR; break; + default : + case 'h' : + case '?' : + usage(argv[0]); } - if ((fd == -1) && (fd = open(iplfile, O_RDONLY)) == -1) { - (void) fprintf(stderr, "%s: ", IPL_NAME); + if ((fd[0] == -1) && (fd[0] = open(iplfile, O_RDONLY)) == -1) { + (void) fprintf(stderr, "%s: ", iplfile); perror("open"); exit(-1); } + if ((opts & OPT_ALL)) { + if ((fd[1] = open(IPL_NAT, O_RDONLY)) == -1) { + (void) fprintf(stderr, "%s: ", IPL_NAT); + perror("open"); + exit(-1); + } + if ((fd[2] = open(IPL_STATE, O_RDONLY)) == -1) { + (void) fprintf(stderr, "%s: ", IPL_STATE); + 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); + if (fstat(fd[0], &stat) == -1) { + fprintf(stderr, "%s :", iplfile); + perror("fstat"); + exit(-1); } - 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; + regular = !S_ISCHR(stat.st_mode); + + for (doread = 1; doread; ) { + nr = 0; + + for (i = 0; i < nfd; i++) { + tr = 0; + if (!regular) { + if (ioctl(fd[i], FIONREAD, &tr) == -1) { + perror("ioctl(FIONREAD)"); + exit(-1); + } + } else { + tr = (lseek(fd[i], 0, SEEK_CUR) < + stat.st_size); + if (!tr && !(opts & OPT_TAIL)) + doread = 0; + } + if (!tr) + continue; + nr += tr; + + tr = (*readfunc[i])(fd[i], &n, buf, sizeof(buf), log); + switch (tr) + { + 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 : + if (n > 0) { + (*printfunc[i])(log, buf, n); + if (!(opts & OPT_SYSLOG)) + fflush(log); + } + break; + } } + if (!nr && regular && (opts & OPT_TAIL)) + sleep(1); + } exit(0); /* NOTREACHED */ } diff --git a/contrib/ipfilter/ipnat.c b/contrib/ipfilter/ipnat.c index d7592284de14..8c731e370284 100644 --- a/contrib/ipfilter/ipnat.c +++ b/contrib/ipfilter/ipnat.c @@ -1,692 +1,707 @@ /* * (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 #include #include #if !defined(__SVR4) && !defined(__svr4__) #include #else #include #endif #include +#include #include #include #include #include #include #include #if defined(sun) && (defined(__svr4__) || defined(__SVR4)) # include # include #endif #include #include #include #include #include -#include "ip_compat.h" #include #include #include #include -#include "ip_nat.h" #include +#include "ip_compat.h" +#include "ip_fil.h" +#include "ip_nat.h" +#include "kmem.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.8 1997/02/16 21:23:40 darrenr Exp $"; +static char rcsid[] = "$Id: ipnat.c,v 2.0.2.6 1997/04/02 12:23:29 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(); +ipnat_t *parse __P((char *)); +u_long hostnum __P((char *, int *)); +u_long hostmask __P((char *)); +u_short portnum __P((char *, char *)); +void dostats __P((int, int)), flushtable __P((int, int)); +void printnat __P((ipnat_t *, int, void *)); +void parsefile __P((int, char *, int)); +void usage __P((char *)); +int countbits __P((u_long)); +char *getnattype __P((ipnat_t *)); +int main __P((int, char*[])); #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%p %u %x %u %x %d\n", (u_int)np->in_ifp, + printf("\t%p %u %x %u %p %d\n", 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%p %u %s %d %x\n", (u_int)np->in_ifp, + printf("\t%p %u %s %d %x\n", 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))) + if (ipnat && kmemcpy((char *)&ipnatbuff, (long)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 %p list %p\n", - (u_int)ns.ns_table, (u_int)ns.ns_list); + printf("table %p list %p\n", ns.ns_table, 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))) { + if (kmemcpy((char *)&ipn, (long)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)) { + if (kmemcpy((char *)nt[0], (long)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))) + if (kmemcpy((char *)&nat, (long)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, + printf(" %ld %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/ipsd.sed b/contrib/ipfilter/ipsd/ipsd.sed new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/contrib/ipfilter/ipsend/44arp.c b/contrib/ipfilter/ipsend/44arp.c index aa428593b57e..f46bc55430b9 100644 --- a/contrib/ipfilter/ipsend/44arp.c +++ b/contrib/ipfilter/ipsend/44arp.c @@ -1,95 +1,100 @@ /* * Based upon 4.4BSD's /usr/sbin/arp */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include +#include +#include +#include "ipsend.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 *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/arp.c b/contrib/ipfilter/ipsend/arp.c index 47f6fce3e397..e010b9b93946 100644 --- a/contrib/ipfilter/ipsend/arp.c +++ b/contrib/ipfilter/ipsend/arp.c @@ -1,119 +1,122 @@ /* * 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 #include #include #include #include #include #include #include #include #include +#include +#include +#include +#include "ipsend.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/ip.c b/contrib/ipfilter/ipsend/ip.c index 2c7f7ff3e019..1b0822221a74 100644 --- a/contrib/ipfilter/ipsend/ip.c +++ b/contrib/ipfilter/ipsend/ip.c @@ -1,346 +1,341 @@ /* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef linux #include #include -#include -#endif -#include "ip_compat.h" -#ifdef linux -#include "tcpip.h" #endif +#include "ipsend.h" 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) + else if (arp((char *)&gwip, (char *)&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) + else if (arp((char *)&gwip, (char *)&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); + ip->ip_sum = chksum((u_short *)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); + ip->ip_sum = chksum((u_short *)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)); + ti->ti_sum = chksum((u_short *)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)); + ti->ti_sum = chksum((u_short *)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)); + ic->icmp_cksum = chksum((u_short *)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/ipresend.c b/contrib/ipfilter/ipsend/ipresend.c index 6fd91bf4ff10..9402104a6d22 100644 --- a/contrib/ipfilter/ipsend/ipresend.c +++ b/contrib/ipfilter/ipsend/ipresend.c @@ -1,165 +1,162 @@ /* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef linux #include -#include #endif -#include "ip_compat.h" -#ifdef linux -#include -#include "tcpip.h" -#endif -#include "ipt.h" +#include "ipsend.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) +static void usage __P((char *)); +int main __P((int, char **)); + + +static 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 index e45d3ee73adc..4c37557abcd7 100644 --- a/contrib/ipfilter/ipsend/ipsend.c +++ b/contrib/ipfilter/ipsend/ipsend.c @@ -1,350 +1,347 @@ /* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef linux #include -#include #endif -#include "ip_compat.h" -#ifdef linux -#include -#include "tcpip.h" -#endif -#include "ipt.h" +#include "ipsend.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) +static void usage __P((char *)); +static void do_icmp __P((ip_t *, char *)); +int main __P((int, char **)); + + +static 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); + return send_packets(dev, mtu, (ip_t *)ti, gwip); } diff --git a/contrib/ipfilter/ipsend/ipsend.h b/contrib/ipfilter/ipsend/ipsend.h new file mode 100644 index 000000000000..362e273aa02a --- /dev/null +++ b/contrib/ipfilter/ipsend/ipsend.h @@ -0,0 +1,64 @@ +/* + * ipsend.h (C) 1997 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. + * + */ +#ifndef __P +# ifdef __STDC__ +# define __P(x) x +# else +# define __P(x) () +# endif +#endif + +#include "ip_compat.h" +#ifdef linux +#include +#endif +#include "tcpip.h" +#include "ipt.h" + +extern int resolve __P((char *, char *)); +extern int arp __P((char *, char *)); +extern u_short chksum __P((u_short *, int)); +extern int send_ether __P((int, char *, int, struct in_addr)); +extern int send_ip __P((int, int, ip_t *, struct in_addr, int)); +extern int send_tcp __P((int, int, ip_t *, struct in_addr)); +extern int send_udp __P((int, int, ip_t *, struct in_addr)); +extern int send_icmp __P((int, int, ip_t *, struct in_addr)); +extern int send_packet __P((int, int, ip_t *, struct in_addr)); +extern int send_packets __P((char *, int, ip_t *, struct in_addr)); +extern u_short seclevel __P((char *)); +extern u_long optname __P((char *, char *)); +extern int initdevice __P((char *, int, int)); +extern int sendip __P((int, char *, int)); +#ifdef linux +extern struct sock *find_tcp __P((int, struct tcpiphdr *)); +#else +extern struct tcpcb *find_tcp __P((int, struct tcpiphdr *)); +#endif +extern int ip_resend __P((char *, int, struct ipread *, struct in_addr, char *)); + +extern void ip_test1 __P((char *, int, ip_t *, struct in_addr, int)); +extern void ip_test2 __P((char *, int, ip_t *, struct in_addr, int)); +extern void ip_test3 __P((char *, int, ip_t *, struct in_addr, int)); +extern void ip_test4 __P((char *, int, ip_t *, struct in_addr, int)); +extern void ip_test5 __P((char *, int, ip_t *, struct in_addr, int)); +extern void ip_test6 __P((char *, int, ip_t *, struct in_addr, int)); +extern void ip_test7 __P((char *, int, ip_t *, struct in_addr, int)); +extern int do_socket __P((char *, int, struct tcpiphdr *, struct in_addr)); + +extern int openkmem __P((void)); +extern int kmemcpy __P((char *, void *, int)); + +#define KMCPY(a,b,c) kmemcpy((char *)(a), (void *)(b), (int)(c)) diff --git a/contrib/ipfilter/ipsend/ipsend.sed b/contrib/ipfilter/ipsend/ipsend.sed new file mode 100644 index 000000000000..774c0e24e3df --- /dev/null +++ b/contrib/ipfilter/ipsend/ipsend.sed @@ -0,0 +1,3 @@ +0Æ . Ä,..+ CVS0Í +.cvsignore0Î44arp.c0Ï Crashable0ÐMakefile0Ñarp.c0Ò +dlcommon.c0Ódltest.h0Ôin_var.h0Õip.c0Ö ip_compat.h0×ip_var.h0Ø diff --git a/contrib/ipfilter/ipsend/ipsopt.c b/contrib/ipfilter/ipsend/ipsopt.c index 75c4f1627a8e..8313559bc45e 100644 --- a/contrib/ipfilter/ipsend/ipsopt.c +++ b/contrib/ipfilter/ipsend/ipsopt.c @@ -1,111 +1,125 @@ /* * (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 #include #include #include #include #include #include #include #include "ip_compat.h" + +#ifndef __P +# ifdef __STDC__ +# define __P(x) x +# else +# define __P(x) () +# endif +#endif + + 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 __P((char *)); +u_long optname __P((char *, char *)); + + 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 index c5d48fa83420..00b51fb40d45 100644 --- a/contrib/ipfilter/ipsend/iptest.c +++ b/contrib/ipfilter/ipsend/iptest.c @@ -1,211 +1,214 @@ /* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef linux #include -#include #endif -#include "ip_compat.h" #ifdef linux #include -#include "tcpip.h" #endif -#include "ipt.h" +#include "ipsend.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 +static void usage __P((char *)); +int main __P((int, char **)); + -void usage(prog) -char *prog; +static 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; +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); + ip_test1(dev, mtu, (ip_t *)ti, gwip, pointtest); + break; case 2 : - return ip_test2(dev, mtu, ti, gwip, pointtest); + ip_test2(dev, mtu, (ip_t *)ti, gwip, pointtest); + break; case 3 : - return ip_test3(dev, mtu, ti, gwip, pointtest); + ip_test3(dev, mtu, (ip_t *)ti, gwip, pointtest); + break; case 4 : - return ip_test4(dev, mtu, ti, gwip, pointtest); + ip_test4(dev, mtu, (ip_t *)ti, gwip, pointtest); + break; case 5 : - return ip_test5(dev, mtu, ti, gwip, pointtest); + ip_test5(dev, mtu, (ip_t *)ti, gwip, pointtest); + break; case 6 : - return ip_test6(dev, mtu, ti, gwip, pointtest); + ip_test6(dev, mtu, (ip_t *)ti, gwip, pointtest); + break; case 7 : - return ip_test7(dev, mtu, ti, gwip, pointtest); + ip_test7(dev, mtu, (ip_t *)ti, gwip, pointtest); + break; default : break; } return 0; } diff --git a/contrib/ipfilter/ipsend/iptests.c b/contrib/ipfilter/ipsend/iptests.c index b9da7b2ba82e..4de99c4727f5 100644 --- a/contrib/ipfilter/ipsend/iptests.c +++ b/contrib/ipfilter/ipsend/iptests.c @@ -1,1296 +1,1288 @@ /* * (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 #include #include #include #include #include #include #if !defined(solaris) # define _KERNEL # define KERNEL # include # undef _KERNEL # undef KERNEL # include # include # include #endif #include #include #include #ifdef sun #include #include #endif #if BSD >= 199103 #include #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include "ip_compat.h" -#ifdef linux -#include "tcpip.h" -#else -#include # if defined(__SVR4) || defined(__svr4__) #include # endif -#endif +#include "ipsend.h" + #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); + ip->ip_sum = chksum((u_short *)ip, ip->ip_hl << 2); + (void) send_ether(nfd, (char *)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); + ip->ip_sum = chksum((u_short *)ip, ip->ip_hl << 2); + (void) send_ether(nfd, (char *)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); + ip->ip_sum = chksum((u_short *)ip, ip->ip_hl << 2); + (void) send_ether(nfd, (char *)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); + ip->ip_sum = chksum((u_short *)ip, ip->ip_hl << 2); + (void) send_ether(nfd, (char *)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)); + KMCPY(&tcb, 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/lsock.c b/contrib/ipfilter/ipsend/lsock.c index 89b6ab7e4e32..5cc3122b75bc 100644 --- a/contrib/ipfilter/ipsend/lsock.c +++ b/contrib/ipfilter/ipsend/lsock.c @@ -1,261 +1,257 @@ /* * 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 #include #include #include #include #include #include #include #include #include #include #include #define __KERNEL__ #if LINUX >= 0200 # undef UINT_MAX # undef INT_MAX # undef ULONG_MAX # undef LONG_MAX # include #endif #include #if LINUX >= 0200 #include "linux/netdevice.h" #include "net/sock.h" #endif #undef __KERNEL__ #include #include #include #include #include #include #include #include #include #if LINUX < 0103 #include #endif -#include "ip_compat.h" -#include "tcpip.h" +#include "ipsend.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) + if (KMCPY(&nproc, 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) + if (KMCPY(&v, 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) + if (KMCPY(pp, 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) + if (KMCPY((proc + n), 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) + if (KMCPY(o, 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) + if (KMCPY(f, 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) + if (KMCPY(i, 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)); + KMCPY(&sk, 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 index 59ed75ef082c..84d3215ac18e 100644 --- a/contrib/ipfilter/ipsend/resend.c +++ b/contrib/ipfilter/ipsend/resend.c @@ -1,130 +1,124 @@ /* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef linux #include -#include #include #endif -#include "ip_compat.h" -#ifdef linux -#include -#include "tcpip.h" -#endif -#include "ipt.h" +#include "ipsend.h" static u_char buf[65536]; /* 1 big packet */ +static void printpacket __P((ip_t *)); -extern int initdevice(), arp(), sendip(); -void printpacket(ip) +static 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) + if (sendip(wfd, (char *)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 index 5eb9d9b1f97d..dd781ab4145c 100644 --- a/contrib/ipfilter/ipsend/sbpf.c +++ b/contrib/ipfilter/ipsend/sbpf.c @@ -1,136 +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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if BSD < 199103 #include #endif #include #include #include #include #include #include #include #include #include #include #include -#include +#include "ipsend.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 index eabd61eb7344..94d71ae9e864 100644 --- a/contrib/ipfilter/ipsend/sdlpi.c +++ b/contrib/ipfilter/ipsend/sdlpi.c @@ -1,130 +1,129 @@ /* * (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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include -#include "ip_compat.h" +#include "ipsend.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 index 1767dfeb9ba2..7e4c7bf7d069 100644 --- a/contrib/ipfilter/ipsend/slinux.c +++ b/contrib/ipfilter/ipsend/slinux.c @@ -1,94 +1,93 @@ /* * (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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include "ip_compat.h" -#include "tcpip.h" +#include "ipsend.h" #if !defined(lint) && defined(LIBC_SCCS) static char sccsid[] = "@(#)slinux.c 1.2 8/25/95"; #endif #define CHUNKSIZE 8192 #define BUFSPACE (4*CHUNKSIZE) /* * Be careful to only include those defined in the flags option for the * interface are included in the header size. */ static int timeout; static char *eth_dev = NULL; int initdevice(dev, sport, tout) char *dev; int sport, tout; { int fd; eth_dev = strdup(dev); if ((fd = socket(AF_INET, SOCK_PACKET, htons(ETHERTYPE_IP))) == -1) { perror("socket(SOCK_PACKET)"); exit(-1); } return fd; } /* * output an IP packet onto a fd opened for /dev/nit */ int sendip(fd, pkt, len) int fd, len; char *pkt; { struct sockaddr s; struct ifreq ifr; strncpy(ifr.ifr_name, eth_dev, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) { perror("SIOCGIFHWADDR"); return -1; } bcopy(ifr.ifr_hwaddr.sa_data, pkt + 6, 6); s.sa_family = ETHERTYPE_IP; strncpy(s.sa_data, eth_dev, sizeof(s.sa_data)); if (sendto(fd, pkt, len, 0, &s, sizeof(s)) == -1) { perror("send"); return -1; } return len; } diff --git a/contrib/ipfilter/ipsend/snit.c b/contrib/ipfilter/ipsend/snit.c index d02219267398..e738fdb5ccd4 100644 --- a/contrib/ipfilter/ipsend/snit.c +++ b/contrib/ipfilter/ipsend/snit.c @@ -1,160 +1,161 @@ /* * (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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include + +#include "ipsend.h" #if !defined(lint) && defined(LIBC_SCCS) static char snitid[] = "@(#)snit.c 1.5 1/11/96 (C)1995 Darren Reed"; #endif #define CHUNKSIZE 8192 #define BUFSPACE (4*CHUNKSIZE) /* * Be careful to only include those defined in the flags option for the * interface are included in the header size. */ #define BUFHDR_SIZE (sizeof(struct nit_bufhdr)) #define NIT_HDRSIZE (BUFHDR_SIZE) static int timeout; int initdevice(device, sport, tout) char *device; int sport, tout; { struct strioctl si; struct timeval to; struct ifreq ifr; int fd; if ((fd = open("/dev/nit", O_RDWR)) < 0) { perror("/dev/nit"); exit(-1); } /* * arrange to get messages from the NIT STREAM and use NIT_BUF option */ ioctl(fd, I_SRDOPT, (char*)RMSGD); ioctl(fd, I_PUSH, "nbuf"); /* * set the timeout */ timeout = tout; si.ic_timout = 1; to.tv_sec = 1; to.tv_usec = 0; si.ic_cmd = NIOCSTIME; si.ic_len = sizeof(to); si.ic_dp = (char*)&to; if (ioctl(fd, I_STR, (char*)&si) == -1) { perror("ioctl: NIT timeout"); exit(-1); } /* * request the interface */ strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' '; si.ic_cmd = NIOCBIND; si.ic_len = sizeof(ifr); si.ic_dp = (char*)𝔦 if (ioctl(fd, I_STR, (char*)&si) == -1) { perror(ifr.ifr_name); exit(1); } return fd; } /* * output an IP packet onto a fd opened for /dev/nit */ int sendip(fd, pkt, len) int fd, len; char *pkt; { struct sockaddr sk, *sa = &sk; struct strbuf cbuf, *cp = &cbuf, dbuf, *dp = &dbuf; /* * For ethernet, need at least 802.3 header and IP header. */ if (len < (sizeof(sa->sa_data) + sizeof(struct ip))) return -1; /* * to avoid any output processing for IP, say we're not. */ sa->sa_family = AF_UNSPEC; bcopy(pkt, sa->sa_data, sizeof(sa->sa_data)); pkt += sizeof(sa->sa_data); len -= sizeof(sa->sa_data); /* * construct NIT STREAMS messages, first control then data. */ cp->len = sizeof(*sa); cp->maxlen = sizeof(*sa); cp->buf = (char *)sa; dp->buf = pkt; dp->len = len; dp->maxlen = dp->len; if (putmsg(fd, cp, dp, 0) == -1) { perror("putmsg"); return -1; } if (ioctl(fd, I_FLUSH, FLUSHW) == -1) { perror("I_FLUSH"); return -1; } return len; } diff --git a/contrib/ipfilter/ipsend/sock.c b/contrib/ipfilter/ipsend/sock.c index 58949c50d608..b75342691440 100644 --- a/contrib/ipfilter/ipsend/sock.c +++ b/contrib/ipfilter/ipsend/sock.c @@ -1,370 +1,372 @@ /* * sock.c (C) 1995 Darren Reed * * The author provides this program as-is, with no gaurantee for its * suitability for any specific purpose. The author takes no responsibility * for the misuse/abuse of this program and provides it for the sole purpose * of testing packet filter policies. This file maybe distributed freely * providing it is not modified and that this notice remains in tact. */ #if !defined(lint) && defined(LIBC_SCCS) static char sccsid[] = "@(#)sock.c 1.2 1/11/96 (C)1995 Darren Reed"; #endif #include #include #include #include #include #include #include #include #include #include #include #include #define _KERNEL #define KERNEL #include #undef _KERNEL #undef KERNEL #include #include #include #include #include #include #ifdef sun #include #include #endif #if BSD >= 199103 #include #include #include #endif #include #include #include #include #include #include #include #include #include #include #include -#include +#include "ipsend.h" int nproc; struct proc *proc; -extern int initdevice(), send_tcp(); - #ifndef KMEM # ifdef _PATH_KMEM # define KMEM _PATH_KMEM # endif #endif #ifndef KERNEL # ifdef _PATH_UNIX # define KERNEL _PATH_UNIX # endif #endif #ifndef KMEM # define KMEM "/dev/kmem" #endif #ifndef KERNEL # define KERNEL "/vmunix" #endif + +#if BSD < 199103 +static struct proc *getproc __P((void)); +#else +static struct kinfo_proc *getproc __P((void)); +#endif + + int kmemcpy(buf, pos, n) char *buf; -off_t pos; +void *pos; int n; { static int kfd = -1; if (kfd == -1) kfd = open(KMEM, O_RDONLY); - if (lseek(kfd, pos, SEEK_SET) == -1) + 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] = { { "_proc" }, { "_nproc" }, { NULL } }; #if BSD < 199103 -struct proc *getproc() +static struct proc *getproc() { struct proc *p; pid_t pid = getpid(); int siz, n; n = nlist(KERNEL, names); if (n != 0) { fprintf(stderr, "nlist(%#x) == %d\n", names, n); return NULL; } - if (kmemcpy((char *)&nproc, (off_t)names[1].n_value, - sizeof(nproc)) == -1) + if (KMCPY(&nproc, names[1].n_value, sizeof(nproc)) == -1) { fprintf(stderr, "read nproc (%#x)\n", names[1].n_value); return NULL; } siz = nproc * sizeof(struct proc); - if (kmemcpy((char *)&p, (off_t)names[0].n_value, sizeof(p)) == -1) + if (KMCPY(&p, names[0].n_value, sizeof(p)) == -1) { fprintf(stderr, "read(%#x,%#x,%d) proc\n", names[0].n_value, &p, sizeof(p)); return NULL; } proc = (struct proc *)malloc(siz); - if (kmemcpy((char *)proc, (off_t)p, siz) == -1) + if (KMCPY(proc, p, siz) == -1) { fprintf(stderr, "read(%#x,%#x,%d) proc\n", p, proc, siz); return NULL; } p = proc; for (n = nproc; n; n--, p++) if (p->p_pid == pid) break; if (!n) return NULL; return p; } struct tcpcb *find_tcp(fd, ti) int fd; struct tcpiphdr *ti; { struct tcpcb *t; struct inpcb *i; struct socket *s; struct user *up; struct proc *p; struct file *f, **o; if (!(p = getproc())) return NULL; up = (struct user *)malloc(sizeof(*up)); - if (kmemcpy((char *)up, (off_t)p->p_uarea, sizeof(*up)) == -1) + if (KMCPY(up, p->p_uarea, sizeof(*up)) == -1) { fprintf(stderr, "read(%#x,%#x) failed\n", p, p->p_uarea); return NULL; } o = (struct file **)calloc(1, sizeof(*o) * (up->u_lastfile + 1)); - if (kmemcpy((char *)o, (off_t)up->u_ofile, - (up->u_lastfile + 1) * sizeof(*o)) == -1) + if (KMCPY(o, up->u_ofile, (up->u_lastfile + 1) * sizeof(*o)) == -1) { fprintf(stderr, "read(%#x,%#x,%d) - u_ofile - failed\n", up->u_ofile_arr, o, sizeof(*o)); return NULL; } f = (struct file *)calloc(1, sizeof(*f)); - if (kmemcpy((char *)f, (off_t)o[fd], sizeof(*f)) == -1) + if (KMCPY(f, o[fd], sizeof(*f)) == -1) { fprintf(stderr, "read(%#x,%#x,%d) - o[fd] - failed\n", up->u_ofile_arr[fd], f, sizeof(*f)); return NULL; } s = (struct socket *)calloc(1, sizeof(*s)); - if (kmemcpy((char *)s, (off_t)f->f_data, sizeof(*s)) == -1) + if (KMCPY(s, f->f_data, sizeof(*s)) == -1) { fprintf(stderr, "read(%#x,%#x,%d) - f_data - failed\n", o[fd], s, sizeof(*s)); return NULL; } i = (struct inpcb *)calloc(1, sizeof(*i)); - if (kmemcpy((char *)i, (off_t)s->so_pcb, sizeof(*i)) == -1) + if (KMCPY(i, s->so_pcb, sizeof(*i)) == -1) { fprintf(stderr, "kvm_read(%#x,%#x,%d) - so_pcb - failed\n", s->so_pcb, i, sizeof(*i)); return NULL; } t = (struct tcpcb *)calloc(1, sizeof(*t)); - if (kmemcpy((char *)t, (off_t)i->inp_ppcb, sizeof(*t)) == -1) + if (KMCPY(t, i->inp_ppcb, sizeof(*t)) == -1) { fprintf(stderr, "read(%#x,%#x,%d) - inp_ppcb - failed\n", i->inp_ppcb, t, sizeof(*t)); return NULL; } return (struct tcpcb *)i->inp_ppcb; } #else -struct kinfo_proc *getproc() +static struct kinfo_proc *getproc() { static struct kinfo_proc kp; pid_t pid = getpid(); int n, mib[4]; mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PID; mib[3] = pid; n = 1; if (sysctl(mib, 4, &kp, &n, NULL, 0) == -1) { perror("sysctl"); return NULL; } return &kp; } struct tcpcb *find_tcp(tfd, ti) int tfd; struct tcpiphdr *ti; { struct tcpcb *t; struct inpcb *i; struct socket *s; struct filedesc *fd; struct kinfo_proc *p; struct file *f, **o; if (!(p = getproc())) return NULL; fd = (struct filedesc *)malloc(sizeof(*fd)); - if (kmemcpy((char *)fd, (void *)p->kp_proc.p_fd, sizeof(*fd)) == -1) + if (KMCPY(fd, p->kp_proc.p_fd, sizeof(*fd)) == -1) { fprintf(stderr, "read(%#lx,%#lx) failed\n", (u_long)p, (u_long)p->kp_proc.p_fd); return NULL; } o = (struct file **)calloc(1, sizeof(*o) * (fd->fd_lastfile + 1)); - if (kmemcpy((char *)o, (void *)fd->fd_ofiles, - (fd->fd_lastfile + 1) * sizeof(*o)) == -1) + if (KMCPY(o, fd->fd_ofiles, (fd->fd_lastfile + 1) * sizeof(*o)) == -1) { fprintf(stderr, "read(%#lx,%#lx,%d) - u_ofile - failed\n", (u_long)fd->fd_ofiles, (u_long)o, sizeof(*o)); return NULL; } f = (struct file *)calloc(1, sizeof(*f)); - if (kmemcpy((char *)f, (void *)o[tfd], sizeof(*f)) == -1) + if (KMCPY(f, o[tfd], sizeof(*f)) == -1) { fprintf(stderr, "read(%#lx,%#lx,%d) - o[tfd] - failed\n", (u_long)o[tfd], (u_long)f, sizeof(*f)); return NULL; } s = (struct socket *)calloc(1, sizeof(*s)); - if (kmemcpy((char *)s, (void *)f->f_data, sizeof(*s)) == -1) + if (KMCPY(s, f->f_data, sizeof(*s)) == -1) { fprintf(stderr, "read(%#lx,%#lx,%d) - f_data - failed\n", (u_long)f->f_data, (u_long)s, sizeof(*s)); return NULL; } i = (struct inpcb *)calloc(1, sizeof(*i)); - if (kmemcpy((char *)i, (void *)s->so_pcb, sizeof(*i)) == -1) + if (KMCPY(i, s->so_pcb, sizeof(*i)) == -1) { fprintf(stderr, "kvm_read(%#lx,%#lx,%d) - so_pcb - failed\n", (u_long)s->so_pcb, (u_long)i, sizeof(*i)); return NULL; } t = (struct tcpcb *)calloc(1, sizeof(*t)); - if (kmemcpy((char *)t, (void *)i->inp_ppcb, sizeof(*t)) == -1) + if (KMCPY(t, i->inp_ppcb, sizeof(*t)) == -1) { fprintf(stderr, "read(%#lx,%#lx,%d) - inp_ppcb - failed\n", (u_long)i->inp_ppcb, (u_long)t, sizeof(*t)); return NULL; } return (struct tcpcb *)i->inp_ppcb; } #endif /* BSD < 199301 */ -int do_socket(dev, mtu, ti, gwip, flags) +int do_socket(dev, mtu, ti, gwip) char *dev; int mtu; struct tcpiphdr *ti; struct in_addr gwip; -int flags; { struct sockaddr_in rsin, lsin; struct tcpcb *t, tcb; int fd, nfd, len; printf("Dest. Port: %d\n", ti->ti_dport); fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) { perror("socket"); return -1; } if (fcntl(fd, F_SETFL, FNDELAY) == -1) { perror("fcntl"); return -1; } bzero((char *)&lsin, sizeof(lsin)); lsin.sin_family = AF_INET; bcopy((char *)&ti->ti_src, (char *)&lsin.sin_addr, sizeof(struct in_addr)); if (bind(fd, (struct sockaddr *)&lsin, sizeof(lsin)) == -1) { perror("bind"); return -1; } len = sizeof(lsin); (void) getsockname(fd, (struct sockaddr *)&lsin, &len); ti->ti_sport = lsin.sin_port; printf("sport %d\n", ntohs(lsin.sin_port)); - nfd = initdevice(dev, ntohs(lsin.sin_port)); + nfd = initdevice(dev, ntohs(lsin.sin_port), 1); if (!(t = find_tcp(fd, ti))) return -1; bzero((char *)&rsin, sizeof(rsin)); rsin.sin_family = AF_INET; bcopy((char *)&ti->ti_dst, (char *)&rsin.sin_addr, sizeof(struct in_addr)); rsin.sin_port = ti->ti_dport; if (connect(fd, (struct sockaddr *)&rsin, sizeof(rsin)) == -1 && errno != EINPROGRESS) { perror("connect"); return -1; } - kmemcpy((char*)&tcb, (void *)t, sizeof(tcb)); + KMCPY(&tcb, t, sizeof(tcb)); ti->ti_win = tcb.rcv_adv; ti->ti_seq = tcb.snd_nxt - 1; ti->ti_ack = tcb.rcv_nxt; - if (send_tcp(nfd, mtu, ti, gwip, TH_SYN) == -1) + if (send_tcp(nfd, mtu, (ip_t *)ti, gwip) == -1) return -1; (void)write(fd, "Hello World\n", 12); sleep(2); close(fd); return 0; } diff --git a/contrib/ipfilter/ipt.c b/contrib/ipfilter/ipt.c index b934c2fbae74..1e0f3e4464f0 100644 --- a/contrib/ipfilter/ipt.c +++ b/contrib/ipfilter/ipt.c @@ -1,199 +1,202 @@ /* * (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 #include #include #if !defined(__SVR4) && !defined(__svr4__) #include #else #include +#include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include "ip_fil.h" #include #include #include #include +#include +#include "ip_compat.h" +#include "ip_fil.h" #include "ipf.h" #include "ipt.h" -#include #if !defined(lint) && defined(LIBC_SCCS) static char sccsid[] = "@(#)ipt.c 1.19 6/3/96 (C) 1993-1996 Darren Reed"; -static char rcsid[] = "$Id: ipt.c,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $"; +static char rcsid[] = "$Id: ipt.c,v 2.0.2.4 1997/04/02 12:23:30 darrenr Exp $"; #endif -extern int fr_check(); extern char *optarg; -extern struct frentry *ipfilter[2][2]; -extern struct ipread snoop, etherf, tcpd, pcap, iptext, iphex; -extern void debug(), verbose(); - -struct frentry *ft_in = NULL, *ft_out = NULL; +extern struct frentry *ipfilter[2][2]; +extern struct ipread snoop, etherf, tcpd, pcap, iptext, iphex; +extern struct ifnet *get_unit __P((char *)); +extern void init_ifp __P((void)); int opts = 0; +int main __P((int, char *[])); int main(argc,argv) int argc; char *argv[]; { struct ipread *r = &iptext; - struct frentry *f; struct ip *ip; u_long buf[64]; + struct ifnet *ifp; char c; char *rules = NULL, *datain = NULL, *iface = NULL; int fd, i, dir = 0; - while ((c = getopt(argc, argv, "bdEHi:I:Pr:STvX")) != -1) + while ((c = getopt(argc, argv, "bdEHi:I:oPr:STvX")) != -1) switch (c) { case 'b' : opts |= OPT_BRIEF; break; case 'd' : opts |= OPT_DEBUG; break; case 'i' : datain = optarg; break; case 'I' : iface = optarg; break; + case 'o' : + opts |= OPT_SAVEOUT; + break; case 'r' : rules = optarg; break; case 'v' : opts |= OPT_VERBOSE; break; case 'E' : r = ðerf; break; case 'H' : r = &iphex; break; case 'P' : r = &pcap; break; case 'S' : r = &snoop; break; case 'T' : r = &tcpd; break; case 'X' : r = &iptext; break; } if (!rules) { (void)fprintf(stderr,"no rule file present\n"); exit(-1); } initparse(); if (rules) { struct frentry *fr; char line[513], *s; FILE *fp; if (!strcmp(rules, "-")) fp = stdin; else if (!(fp = fopen(rules, "r"))) { (void)fprintf(stderr, "couldn't open %s\n", rules); exit(-1); } if (!(opts & OPT_BRIEF)) (void)printf("opening rule file \"%s\"\n", rules); while (fgets(line, sizeof(line)-1, fp)) { /* * treat both CR and LF as EOL */ if ((s = index(line, '\n'))) *s = '\0'; if ((s = index(line, '\r'))) *s = '\0'; /* * # is comment marker, everything after is a ignored */ if ((s = index(line, '#'))) *s = '\0'; if (!*line) continue; if (!(fr = parse(line))) continue; - f = (struct frentry *)malloc(sizeof(*f)); - if (fr->fr_flags & FR_INQUE) { - if (!ft_in) - ft_in = ipfilter[0][0] = f; - else - ft_in->fr_next = f, ft_in = f; - } else if (fr->fr_flags & FR_OUTQUE) { - if (!ft_out) - ft_out = ipfilter[1][0] = f; - else - ft_out->fr_next = f, ft_out = f; - } - bcopy((char *)fr, (char *)f, sizeof(*fr)); + /* fake an `ioctl' call :) */ + i = iplioctl(0, SIOCADDFR, (caddr_t)fr, FWRITE|FREAD); + if (opts & OPT_DEBUG) + fprintf(stderr, + "iplioctl(SIOCADDFR,%x,1) = %d\n", i); } (void)fclose(fp); } + if (opts & OPT_SAVEOUT) + init_ifp(); + if (datain) fd = (*r->r_open)(datain); else fd = (*r->r_open)("-"); if (fd < 0) exit(-1); ip = (struct ip *)buf; - while ((i = (*r->r_readip)(buf, sizeof(buf), &iface, &dir)) > 0) { + while ((i = (*r->r_readip)((char *)buf, sizeof(buf), + &iface, &dir)) > 0) { + ifp = iface ? get_unit(iface) : NULL; ip->ip_off = ntohs(ip->ip_off); ip->ip_len = ntohs(ip->ip_len); - switch (fr_check(ip, ip->ip_hl << 2, iface, dir)) + switch (fr_check(ip, ip->ip_hl << 2, ifp, dir, (char *)buf)) { case -1 : (void)printf("block"); break; case 0 : (void)printf("pass"); break; case 1 : (void)printf("nomatch"); break; } if (!(opts & OPT_BRIEF)) { putchar(' '); - printpacket(buf); + printpacket((struct ip *)buf); printf("--------------"); } + if (dir && ifp && ip->ip_v) + (*ifp->if_output)(ifp, (void *)buf, NULL, 0); putchar('\n'); dir = 0; } (*r->r_close)(); return 0; } diff --git a/contrib/ipfilter/ipt.h b/contrib/ipfilter/ipt.h index be481cabb481..e91190ba81bf 100644 --- a/contrib/ipfilter/ipt.h +++ b/contrib/ipfilter/ipt.h @@ -1,16 +1,25 @@ /* * (C)opyright 1993,1994,1995 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given * to the original author and the contributors. - * $Id: ipt.h,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $ + * $Id: ipt.h,v 2.0.2.4 1997/03/27 13:45:23 darrenr Exp $ */ #include +#ifdef __STDC__ +#include +#else +#include +#endif + struct ipread { - int (*r_open)(); - int (*r_close)(); - int (*r_readip)(); + int (*r_open) __P((char *)); + int (*r_close) __P((void)); + int (*r_readip) __P((char *, int, char **, int *)); }; + +extern void debug __P((char *, ...)); +extern void verbose __P((char *, ...)); diff --git a/contrib/ipfilter/kmem.c b/contrib/ipfilter/kmem.c index 33345807e914..33b6595fe90e 100644 --- a/contrib/ipfilter/kmem.c +++ b/contrib/ipfilter/kmem.c @@ -1,68 +1,67 @@ /* * (C)opyright 1993,1994,1995 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given * to the original author and the contributors. */ /* * kmemcpy() - copies n bytes from kernel memory into user buffer. * returns 0 on success, -1 on error. */ #include #include #include #include #include #include - -#define KMEM "/dev/kmem" +#include "kmem.h" #if !defined(lint) && defined(LIBC_SCCS) static char sccsid[] = "@(#)kmem.c 1.4 1/12/96 (C) 1992 Darren Reed"; -static char rcsid[] = "$Id: kmem.c,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $"; +static char rcsid[] = "$Id: kmem.c,v 2.0.2.3 1997/03/10 08:10:37 darrenr Exp $"; #endif static int kmemfd = -1; int openkmem() { if ((kmemfd = open(KMEM,O_RDONLY)) == -1) { perror("kmeminit:open"); return -1; } return kmemfd; } int kmemcpy(buf, pos, n) register char *buf; long pos; register int n; { register int r; if (!n) return 0; if (kmemfd == -1) if (openkmem() == -1) return -1; if (lseek(kmemfd, pos, 0) == -1) { perror("kmemcpy:lseek"); return -1; } while ((r = read(kmemfd, buf, n)) < n) if (r <= 0) { perror("kmemcpy:read"); return -1; } else { buf += r; n -= r; } return 0; } diff --git a/contrib/ipfilter/kmem.h b/contrib/ipfilter/kmem.h index 18c1c238aba8..38d64304bddf 100644 --- a/contrib/ipfilter/kmem.h +++ b/contrib/ipfilter/kmem.h @@ -1,12 +1,21 @@ /* * (C)opyright 1993,1994,1995 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given * to the original author and the contributors. - * $Id: kmem.h,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $ + * $Id: kmem.h,v 2.0.2.3 1997/03/10 08:10:38 darrenr Exp $ */ -extern int openkmem(); -extern int kmemcpy(); +#ifndef __P +# ifdef __STDC__ +# define __P(x) x +# else +# define __P(x) () +# endif +#endif +extern int openkmem __P((void)); +extern int kmemcpy __P((char *, long, int)); + +#define KMEM "/dev/kmem" diff --git a/contrib/ipfilter/linux.h b/contrib/ipfilter/linux.h index f4d3bda7d344..3f28724318da 100644 --- a/contrib/ipfilter/linux.h +++ b/contrib/ipfilter/linux.h @@ -1,19 +1,19 @@ /* * (C)opyright 1993,1994,1995 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given * to the original author and the contributors. The author accepts no * responsibility and is not changed in any way. * * I hate legaleese, don't you ? - * $Id: linux.h,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $ + * $Id: linux.h,v 2.0.2.2 1997/02/23 10:38:08 darrenr Exp $ */ #include #ifdef MODULE #include #include #endif /* MODULE */ #include "ip_compat.h" diff --git a/contrib/ipfilter/man/ipf.4 b/contrib/ipfilter/man/ipf.4 index ff17f4f7e33b..ebeacebb0b16 100644 --- a/contrib/ipfilter/man/ipf.4 +++ b/contrib/ipfilter/man/ipf.4 @@ -1,184 +1,183 @@ .TH IPF 4 .SH NAME ipf \- packet filtering kernel interface .SH SYNOPSIS #include .SH IOCTLS .PP To add and delete rules to the filter list, three 'basic' ioctls are provided for use. The ioctl's are called as: .LP .nf ioctl(fd, SIOCADDFR, struct frentry *) ioctl(fd, SIOCDELFR, struct frentry *) ioctl(fd, SIOCIPFFL, int *) .fi .PP However, the full complement is as follows: .LP .nf ioctl(fd, SIOCADAFR, struct frentry *) (same as SUICADDFR) ioctl(fd, SIOCRMAFR, struct frentry *) (same as SUICDELFR) ioctl(fd, SIOCADIFR, struct frentry *) ioctl(fd, SIOCRMIFR, struct frentry *) ioctl(fd, SIOCINAFR, struct frentry *) ioctl(fd, SIOCINIFR, struct frentry *) ioctl(fd, SIOCIPFFL, int *) .fi .PP The variations, SIOCADAFR vs. SIOCADIFR, allow operation on the two lists, active and inactive, respectively. All of these ioctl's are implemented as being routing ioctls and thus the same rules for the various routing ioctls and the file descriptor are employed, mainly being that the fd must be that of the device associated with the module (i.e., /dev/ipl). .LP .PP The three groups of ioctls above perform adding rules to the end of the list (SIOCAD*), deletion of rules from any place in the list (SIOCRM*) and insertion of a rule into the list (SIOCIN*). The rule place into which it is inserted is stored in the "fr_hits" field, below. .LP .nf typedef struct frentry { struct frentry *fr_next; struct ifnet *fr_ifa; u_long fr_hits; u_long fr_bytes; /* this is only incremented when a packet */ /* stops matching on this rule */ /* * Fields after this may not change whilst in the kernel. */ struct fr_ip fr_ip; struct fr_ip fr_mip; u_char fr_tcpfm; /* tcp flags mask */ u_char fr_tcpf; /* tcp flags */ u_short fr_icmpm; /* data for ICMP packets (mask) */ u_short fr_icmp; u_char fr_scmp; /* data for port comparisons */ u_char fr_dcmp; u_short fr_dport; u_short fr_sport; u_short fr_stop; /* top port for <> and >< */ u_short fr_dtop; /* top port for <> and >< */ u_long fr_flags; /* per-rule flags && options (see below) */ int (*fr_func)(); /* call this function */ char fr_icode; /* return ICMP code */ char fr_ifname[IFNAMSIZ]; struct frdest fr_tif; /* "to" interface */ struct frdest fr_dif; /* duplicate packet interfaces */ } frentry_t; .fi .PP When adding a new rule, all unused fields (in the filter rule) should be initialised to be zero. To insert a rule, at a particular position in the filter list, the number of the rule which it is to be inserted before must be put in the "fr_hits" field (the first rule is number 0). .LP .PP Flags which are recognised in fr_pass: .nf FR_BLOCK 0x00001 /* do not allow packet to pass */ FR_PASS 0x00002 /* allow packet to pass */ FR_OUTQUE 0x00004 /* outgoing packets */ FR_INQUE 0x00008 /* ingoing packets */ FR_LOG 0x00010 /* Log */ FR_LOGP 0x00011 /* Log-pass */ FR_LOGB 0x00012 /* Log-fail */ FR_LOGBODY 0x00020 /* log the body of packets too */ FR_LOGFIRST 0x00040 /* log only the first packet to match */ FR_RETRST 0x00080 /* return a TCP RST packet if blocked */ FR_RETICMP 0x00100 /* return an ICMP packet if blocked */ FR_NOMATCH 0x00200 /* no match occured */ FR_ACCOUNT 0x00400 /* count packet bytes */ FR_KEEPFRAG 0x00800 FR_KEEPSTATE 0x01000 /* keep packet flow state information */ FR_INACTIVE 0x02000 FR_QUICK 0x04000 /* quick-match and return */ FR_FASTROUTE 0x08000 - FR_CALLFUNC 0x10000 - FR_CALLNOW 0x20000 - FR_DUP 0x40000 /* duplicate the packet (not Solaris2) + FR_CALLNOW 0x10000 + FR_DUP 0x20000 /* duplicate the packet (not Solaris2) .fi .PP Values for fr_scomp and fr_dcomp (source and destination port value comparisons) : .LP .nf FR_NONE 0 FR_EQUAL 1 FR_NEQUAL 2 FR_LESST 3 FR_GREATERT 4 FR_LESSTE 5 FR_GREATERTE 6 FR_OUTRANGE 7 FR_INRANGE 8 .fi .PP The third ioctl, SIOCIPFFL, flushes either the input filter list, the output filter list or both and it returns the number of filters removed from the list(s). The values which it will take and recognise are FR_INQUE and FR_OUTQUE (see above). \fBGeneral Logging Flags\fP There are two flags which can be set to log packets independantly of the rules used. These allow for packets which are either passed or blocked to be logged. To set (and clear)/get these flags, two ioctls are provided: .IP SIOCSETFF 16 Takes an unsigned integer as the parameter. The flags are then set to those provided (clearing/setting all in one). .nf FF_LOGPASS 1 FF_LOGBLOCK 2 .fi .IP SIOCGETFF 16 Takes a pointer to an unsigned integer as the parameter. A copy of the flags currently in used is copied to user space. .LP \fBFilter statistics\fP Statistics on the various operations performed by this package on packets is kept inside the kernel. These statistics apply to packets traversing through the kernel. To retrieve this structure, use this ioctl: .nf ioctl(fd, SIOCGETFS, struct friostat *) struct friostat { struct filterstats f_st[2]; struct frentry *f_fin; struct frentry *f_fout; }; struct filterstats { u_long fr_pass; /* packets allowed */ u_long fr_block; /* packets denied */ u_long fr_nom; /* packets which don't match any rule */ u_long fr_ppkl; /* packets allowed and logged */ u_long fr_bpkl; /* packets denied and logged */ u_long fr_npkl; /* packets unmatched and logged */ u_long fr_pkl; /* packets logged */ u_long fr_skip; /* packets to be logged but buffer full */ u_long fr_ret; /* packets for which a return is sent */ u_long fr_acct; /* packets for which counting was performed */ u_long fr_bnfr; /* bad attempts to allocate fragment state */ u_long fr_nfr; /* new fragment state kept */ u_long fr_cfr; /* add new fragment state but complete pkt */ u_long fr_bads; /* bad attempts to allocate packet state */ u_long fr_ads; /* new packet state kept */ u_long fr_chit; /* cached hit */ #if SOLARIS u_long fr_bad; /* bad IP packets to the filter */ u_long fr_notip; /* packets passed through no on ip queue */ u_long fr_drop; /* packets dropped - no info for them! */ #endif }; .fi .SH SEE ALSO ipfstat(1), ipf(1), ipf(5) diff --git a/contrib/ipfilter/man/ipfilter.5 b/contrib/ipfilter/man/ipfilter.5 new file mode 100644 index 000000000000..03a87a5f4548 --- /dev/null +++ b/contrib/ipfilter/man/ipfilter.5 @@ -0,0 +1,7 @@ +.TH IPFILTER 1 +.SH NAME +IP FIlter +.SH DESCRIPTION +.PP +.SH SEE ALSO +ipf(1), ipf(1), ipf(5), ipnat(1), ipnat(5) diff --git a/contrib/ipfilter/man/ipmon.8 b/contrib/ipfilter/man/ipmon.8 index 11ac23aa7031..e793352a60e5 100644 --- a/contrib/ipfilter/man/ipmon.8 +++ b/contrib/ipfilter/man/ipmon.8 @@ -1,56 +1,65 @@ .TH ipmon 8 .SH NAME ipmon \- monitors /dev/ipl for logged packets .SH SYNOPSIS .B ipmon [ -.B \-sfN +.B \-asfnSN ] [ ] .SH DESCRIPTION .LP \fBipmon\fP opens \fB/dev/ipl\fP for reading and awaits data to be saved from the packet filter. The binary data read from the device is reprinted in human readable for, however, IP#'s are not mapped back to hostnames, nor are ports mapped back to service names. The output goes to standard output by default or a filename, if given on the command line. Should the \fB\-s\fP option be used, output is instead sent to \fBsyslogd(8)\fP. Messages sent via syslog have the day, month and year removed from the message, but the time (including microseconds), as recorded in the log, is still included. .SH OPTIONS .TP .B \-s Packet information read in will be sent through syslogd rather than saved to a file. The following levels are used: .IP .B LOG_INFO \- packets logged using the "log" keyword as the action rather than pass or block. .IP .B LOG_NOTICE \- packets logged which are also passed .IP .B LOG_WARNING \- packets logged which are also blocked .IP .B LOG_ERR \- packets which have been logged and which can be considered "short". .TP +.B \-a +Open all of the device logfiles for reading log entries from. +.TP .B \-f Flush the current packet log buffer. The number of bytes flushed is displayed, even should the result be zero. .TP -.B \-N +.B \-n IP addresses and port numbers will be mapped, where possible, back into hostnames and service names. +.TP +.B \-N +Treat the logfile as being composed of NAT log records. +.TP +.B \-S +Treat the logfile as being composed of state log records. .SH DIAGNOSTICS \fBipmon\fP expects data that it reads to be consistant with how it should be saved and will abort if it fails an assertion which detects an anomoly in the recorded data. .SH FILES /dev/ipl .SH SEE ALSO ipf(1), ipfstat(1) .SH BUGS diff --git a/contrib/ipfilter/man/man.sed b/contrib/ipfilter/man/man.sed new file mode 100644 index 000000000000..0be8dab0dc7b --- /dev/null +++ b/contrib/ipfilter/man/man.sed @@ -0,0 +1 @@ +DF . Ä..– CVSD~MakefileDipf.1D€ipf.4Dipf.5D‚ diff --git a/contrib/ipfilter/misc.c b/contrib/ipfilter/misc.c index dc6e92cf646c..c0e415c94c97 100644 --- a/contrib/ipfilter/misc.c +++ b/contrib/ipfilter/misc.c @@ -1,85 +1,102 @@ /* * (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 #include #include #if !defined(__SVR4) && !defined(__svr4__) #include #else #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include "ip_fil.h" #include #include #include +#include "ip_compat.h" +#include "ip_fil.h" #include "ipf.h" #include "ipt.h" #if !defined(lint) && defined(LIBC_SCCS) static char sccsid[] = "@(#)misc.c 1.3 2/4/96 (C) 1995 Darren Reed"; -static char rcsid[] = "$Id: misc.c,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $"; +static char rcsid[] = "$Id: misc.c,v 2.0.2.5 1997/03/31 10:05:36 darrenr Exp $"; #endif -void debug(), verbose(); - extern int opts; void printpacket(ip) struct ip *ip; { struct tcphdr *tcp; tcp = (struct tcphdr *)((char *)ip + (ip->ip_hl << 2)); printf("ip %d(%d) %d ", ip->ip_len, ip->ip_hl << 2, ip->ip_p); if (ip->ip_off & 0x1fff) printf("@%d", ip->ip_off << 3); (void)printf(" %s", inet_ntoa(ip->ip_src)); if (!(ip->ip_off & 0x1fff)) if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) (void)printf(",%d", ntohs(tcp->th_sport)); (void)printf(" > "); (void)printf("%s", inet_ntoa(ip->ip_dst)); if (!(ip->ip_off & 0x1fff)) if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) (void)printf(",%d", ntohs(tcp->th_dport)); putchar('\n'); } -void verbose(fmt, p1, p2, p3, p4, p5, p6, p7, p8, p9) -char *fmt, *p1, *p2, *p3, *p4, *p5, *p6, *p7,*p8,*p9; +#ifdef __STDC__ +void verbose(char *fmt, ...) +#else +void verbose(fmt, va_alist) +char *fmt; +va_dcl +#endif { + va_list pvar; + + va_start(pvar, fmt); if (opts & OPT_VERBOSE) - printf(fmt, p1, p2, p3, p4, p5, p6, p7, p8, p9); + vprintf(fmt, pvar); + va_end(pvar); } -void debug(fmt, p1, p2, p3, p4, p5, p6, p7, p8, p9) -char *fmt, *p1, *p2, *p3, *p4, *p5, *p6, *p7,*p8,*p9; +#ifdef __STDC__ +void debug(char *fmt, ...) +#else +void debug(fmt, va_alist) +char *fmt; +va_dcl +#endif { + va_list pvar; + + va_start(pvar, fmt); if (opts & OPT_DEBUG) - printf(fmt, p1, p2, p3, p4, p5, p6, p7, p8, p9); + vprintf(fmt, pvar); + va_end(pvar); } diff --git a/contrib/ipfilter/mln_ipl.c b/contrib/ipfilter/mln_ipl.c index 08a9c367381c..068a9ff39dde 100644 --- a/contrib/ipfilter/mln_ipl.c +++ b/contrib/ipfilter/mln_ipl.c @@ -1,237 +1,374 @@ /* * (C)opyright 1993,1994,1995 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given * to the original author and the contributors. */ /* * 29/12/94 Added code from Marc Huber to allow it to allocate * its own major char number! Way cool patch! */ #include /* * Post NetBSD 1.2 has the PFIL interface for packet filters. This turns * on those hooks. We don't need any special mods with this! */ #if (defined(NetBSD) && (NetBSD > 199609) && (NetBSD <= 1991011)) || \ (defined(NetBSD1_2) && NetBSD1_2 > 1) # define NETBSD_PF #endif #if defined(__FreeBSD__) && (__FreeBSD__ > 1) # include +# ifdef IPFILTER_LKM +# define ACTUALLY_LKM_NOT_KERNEL +# endif #endif #include +#if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000) +# include +# include +# ifdef DEVFS +# include +# endif /*DEVFS*/ +#endif #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__NetBSD__) || (defined(__FreeBSD_version) && \ - (__FreeBSD_version >= 199607)) + (__FreeBSD_version >= 199511)) #include #include #include #include +#include +#include +#include +#include #endif #ifndef __NetBSD__ #include #endif #include #include "ipl.h" +#include "ip_compat.h" #include "ip_fil.h" #ifndef IPL_NAME #define IPL_NAME "/dev/ipl" #endif +#define IPL_NAT "/dev/ipnat" +#define IPL_STATE "/dev/ipstate" + #if !defined(VOP_LEASE) && defined(LEASE_CHECK) #define VOP_LEASE LEASE_CHECK #endif #ifndef MIN #define MIN(a,b) (((a)<(b))?(a):(b)) #endif -extern int lkmenodev(), lkmexists(), lkmdispatch(); +extern int lkmenodev __P((void)); + -extern int iplattach(), iplopen(), iplclose(), iplioctl(), ipldetach(); #ifdef NETBSD_PF #include #endif -#ifdef IPFILTER_LOG -extern int iplread(); -#else -#ifdef NETBSD_PF -#define iplread enodev -#else -#define iplread nodev -#endif +#ifndef IPFILTER_LOG +# ifdef NETBSD_PF +# define iplread enodev +# else +# define iplread nodev +# endif #endif -extern int iplidentify(); #ifdef NETBSD_PF int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)) = NULL; #endif -static int ipl_unload(), ipl_load(); +static int ipl_unload __P((void)); +static int ipl_load __P((void)); +static int ipl_remove __P((void)); +int xxxinit __P((struct lkm_table *, int, int)); + + #if (defined(NetBSD1_0) && (NetBSD1_0 > 1)) || \ (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199511)) struct cdevsw ipldevsw = { iplopen, /* open */ iplclose, /* close */ iplread, /* read */ 0, /* write */ iplioctl, /* ioctl */ 0, /* stop */ 0, /* tty */ 0, /* select */ 0, /* mmap */ NULL /* strategy */ }; #else struct cdevsw ipldevsw = { iplopen, /* open */ iplclose, /* close */ iplread, /* read */ (void *)nullop, /* write */ iplioctl, /* ioctl */ (void *)nullop, /* stop */ (void *)nullop, /* reset */ (void *)NULL, /* tty */ (void *)nullop, /* select */ (void *)nullop, /* mmap */ NULL /* strategy */ }; #endif -static struct cdevsw cdev_sav; + +#if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000) int ipl_major = 0; MOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipldevsw); -extern int vd_unuseddev(); extern struct cdevsw cdevsw[]; +extern int vd_unuseddev __P((void)); extern int nchrdev; +#else +int ipl_major = CDEV_MAJOR; + +static struct cdevsw ipl_cdevsw = { + iplopen, iplclose, iplread, nowrite, /* 79 */ + iplioctl, nostop, noreset, nodevtotty, + noselect, nommap, nostrategy, "ipl", + NULL, -1 +}; +#endif + + static int iplaction(lkmtp, cmd) struct lkm_table *lkmtp; int cmd; { - int i; + int i = ipl_major; struct lkm_dev *args = lkmtp->private.lkm_dev; int err = 0; switch (cmd) { case LKM_E_LOAD : if (lkmexists(lkmtp)) return EEXIST; +#if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000) for (i = 0; i < nchrdev; i++) if (cdevsw[i].d_open == lkmenodev || cdevsw[i].d_open == iplopen) break; if (i == nchrdev) { printf("IP Filter: No free cdevsw slots\n"); return ENODEV; } ipl_major = i; args->lkm_offset = i; /* slot in cdevsw[] */ +#endif printf("IP Filter: loaded into slot %d\n", ipl_major); return ipl_load(); + break; case LKM_E_UNLOAD : printf("IP Filter: unloaded from slot %d\n", ipl_major); return ipl_unload(); case LKM_E_STAT : break; default: err = EIO; break; } return 0; } -static int ipl_remove() +static int ipl_remove __P((void)) { struct nameidata nd; int error; NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, IPL_NAME, curproc); if ((error = namei(&nd))) return (error); VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE); VOP_LOCK(nd.ni_vp); VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE); - return VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); + (void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); + + NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, IPL_NAT, curproc); + if ((error = namei(&nd))) + return (error); + VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE); + VOP_LOCK(nd.ni_vp); + VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE); + (void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); + + NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, IPL_STATE, curproc); + if ((error = namei(&nd))) + return (error); + VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE); + VOP_LOCK(nd.ni_vp); + VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE); + (void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); } static int ipl_unload() { - int error; + int error = 0; error = ipldetach(); #ifdef NETBSD_PF pfil_remove_hook(fr_check, PFIL_IN|PFIL_OUT); #endif if (!error) error = ipl_remove(); return error; } static int ipl_load() { struct nameidata nd; struct vattr vattr; - int error, fmode = S_IFCHR|0600; + int error = 0, fmode = S_IFCHR|0600; error = iplattach(); #ifdef NETBSD_PF pfil_add_hook(fr_check, PFIL_IN|PFIL_OUT); #endif if (error) return error; (void) ipl_remove(); - error = 0; + NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, IPL_NAME, curproc); if (error = namei(&nd)) return error; if (nd.ni_vp != NULL) { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == nd.ni_vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); vrele(nd.ni_vp); return (EEXIST); } VATTR_NULL(&vattr); vattr.va_type = VCHR; vattr.va_mode = (fmode & 07777); vattr.va_rdev = ipl_major<<8; VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE); - return VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); + error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); + if (error) + return error; + + NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, IPL_NAT, curproc); + if (error = namei(&nd)) + return error; + if (nd.ni_vp != NULL) { + VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); + if (nd.ni_dvp == nd.ni_vp) + vrele(nd.ni_dvp); + else + vput(nd.ni_dvp); + vrele(nd.ni_vp); + return (EEXIST); + } + VATTR_NULL(&vattr); + vattr.va_type = VCHR; + vattr.va_mode = (fmode & 07777); + vattr.va_rdev = (ipl_major<<8)|1; + VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE); + error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); + if (error) + return error; + + NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, IPL_STATE, curproc); + if (error = namei(&nd)) + return error; + if (nd.ni_vp != NULL) { + VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); + if (nd.ni_dvp == nd.ni_vp) + vrele(nd.ni_dvp); + else + vput(nd.ni_dvp); + vrele(nd.ni_vp); + return (EEXIST); + } + VATTR_NULL(&vattr); + vattr.va_type = VCHR; + vattr.va_mode = (fmode & 07777); + vattr.va_rdev = (ipl_major<<8)|2; + VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE); + error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); + if (error) + return error; + return 0; } +#if defined(__FreeBSD_version) && (__FreeBSD_version < 220000) int xxxinit(lkmtp, cmd, ver) struct lkm_table *lkmtp; int cmd, ver; { DISPATCH(lkmtp, cmd, ver, iplaction, iplaction, iplaction); } +#else +#include +#include + +MOD_DECL(if_ipl); + +static struct lkm_dev _module = { + LM_DEV, + LKM_VERSION, + IPL_VERSION, + CDEV_MAJOR, + LM_DT_CHAR, + (void *)&ipl_cdevsw +}; + +int if_ipl(lkmtp, cmd, ver) +struct lkm_table *lkmtp; +int cmd, ver; +{ + DISPATCH(lkmtp, cmd, ver, iplaction, iplaction, iplaction); +} + +/* +static ipl_devsw_installed = 0; + +static void ipl_drvinit __P((void *unused)) +{ + dev_t dev; + + if( ! ipl_devsw_installed ) { + dev = makedev(CDEV_MAJOR,0); + cdevsw_add(&dev, &ipl_cdevsw,NULL); + ipl_devsw_installed = 1; + } +} + +SYSINIT(ipldev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ipl_drvinit,NULL) +*/ +#endif /* __FreeBSD__ */ diff --git a/contrib/ipfilter/mls_ipl.c b/contrib/ipfilter/mls_ipl.c index 22e2db9af3b5..ba89346c4160 100644 --- a/contrib/ipfilter/mls_ipl.c +++ b/contrib/ipfilter/mls_ipl.c @@ -1,174 +1,223 @@ /* * (C)opyright 1993,1994,1995 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given * to the original author and the contributors. */ /* * 29/12/94 Added code from Marc Huber to allow it to allocate * its own major char number! Way cool patch! */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(sun4c) || defined(sun4m) # include #endif #include "ipl.h" +#include "ip_compat.h" + #if !defined(lint) && defined(LIBC_SCCS) static char sccsid[] = "@(#)mls_ipl.c 2.6 10/15/95 (C) 1993-1995 Darren Reed"; -static char rcsid[] = "$Id: mls_ipl.c,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $"; +static char rcsid[] = "$Id: mls_ipl.c,v 2.0.2.3 1997/03/27 13:45:26 darrenr Exp $"; #endif #ifndef IPL_NAME #define IPL_NAME "/dev/ipl" #endif - -extern int iplattach(), iplopen(), iplclose(), iplioctl(), ipldetach(); +#define IPL_NAT "/dev/ipnat" +#define IPL_STATE "/dev/ipstate" + +extern int iplattach __P((void)); +extern int iplopen __P((void)); +extern int iplclose __P((void)); +extern int iplioctl __P((void)); +extern int ipldetach __P((void)); #ifdef IPFILTER_LOG -extern int iplread(); +extern int iplread __P((void)); #else #define iplread nulldev #endif -extern int nulldev(), iplidentify(), errno; +extern int nulldev __P((void)); +extern int iplidentify __P((void)); +extern int errno; + +extern int nodev __P((void)); + +static int unload __P((void)); +static int ipl_attach __P((void)); +int xxxinit __P((u_int, struct vddrv *, caddr_t, struct vdstat *)); -static int unload(), ipl_attach(); struct cdevsw ipldevsw = { iplopen, iplclose, iplread, nulldev, iplioctl, nulldev, nulldev, nulldev, 0, nulldev, }; struct dev_ops ipl_ops = { 1, iplidentify, iplattach, iplopen, iplclose, iplread, NULL, /* write */ NULL, /* strategy */ NULL, /* dump */ 0, /* psize */ iplioctl, NULL, /* reset */ NULL /* mmap */ }; int ipl_major = 0; #ifdef sun4m struct vdldrv vd = { VDMAGIC_PSEUDO, IPL_VERSION, &ipl_ops, NULL, &ipldevsw, 0, 0, NULL, NULL, NULL, 0, 1, }; #else /* sun4m */ struct vdldrv vd = { VDMAGIC_PSEUDO, /* magic */ IPL_VERSION, #ifdef sun4c &ipl_ops, /* dev_ops */ #else NULL, /* struct mb_ctlr *mb_ctlr */ NULL, /* struct mb_driver *mb_driver */ NULL, /* struct mb_device *mb_device */ 0, /* num ctlrs */ 1, /* numdevs */ #endif /* sun4c */ NULL, /* bdevsw */ &ipldevsw, /* cdevsw */ 0, /* block major */ 0, /* char major */ }; #endif /* sun4m */ -extern int vd_unuseddev(); +extern int vd_unuseddev __P((void)); extern struct cdevsw cdevsw[]; extern int nchrdev; -xxxinit(fc, vdp, vdi, vds) +xxxinit(fc, vdp, data, vds) u_int fc; struct vddrv *vdp; -caddr_t vdi; +caddr_t data; struct vdstat *vds; { + struct vdioctl_load *vdi = (struct vdioctl_load *)data; + switch (fc) { case VDLOAD: - while (ipl_major < nchrdev && - cdevsw[ipl_major].d_open != vd_unuseddev) - ipl_major++; - if (ipl_major == nchrdev) - return ENODEV; - vd.Drv_charmajor = ipl_major; + { + struct vdconf *vdc; + if (vdi && vdi->vdi_userconf) + for (vdc = vdi->vdi_userconf; vdc->vdc_type; vdc++) + if (vdc->vdc_type == VDCCHARMAJOR) { + ipl_major = vdc->vdc_data; + break; + } + + if (!ipl_major) { + while (ipl_major < nchrdev && + cdevsw[ipl_major].d_open != vd_unuseddev) + ipl_major++; + if (ipl_major == nchrdev) + return ENODEV; + } vdp->vdd_vdtab = (struct vdlinkage *)&vd; + vd.Drv_charmajor = ipl_major; return ipl_attach(); + } case VDUNLOAD: return unload(); case VDSTAT: return 0; default: return EIO; } } static int unload() { int err; err = ipldetach(); if (!err) (void) vn_remove(IPL_NAME, UIO_SYSSPACE, FILE); return err; } static int ipl_attach() { struct vnode *vp; struct vattr vattr; int error = 0, fmode = S_IFCHR|0600; error = iplattach(); if (error) return error; (void) vn_remove(IPL_NAME, UIO_SYSSPACE, FILE); vattr_null(&vattr); vattr.va_type = MFTOVT(fmode); vattr.va_mode = (fmode & 07777); vattr.va_rdev = ipl_major<<8; error = vn_create(IPL_NAME, UIO_SYSSPACE, &vattr, EXCL, 0, &vp); + if (error == 0) + VN_RELE(vp); + + (void) vn_remove(IPL_NAT, UIO_SYSSPACE, FILE); + vattr_null(&vattr); + vattr.va_type = MFTOVT(fmode); + vattr.va_mode = (fmode & 07777); + vattr.va_rdev = (ipl_major<<8)|1; + + error = vn_create(IPL_NAT, UIO_SYSSPACE, &vattr, EXCL, 0, &vp); + if (error == 0) + VN_RELE(vp); + + (void) vn_remove(IPL_STATE, UIO_SYSSPACE, FILE); + vattr_null(&vattr); + vattr.va_type = MFTOVT(fmode); + vattr.va_mode = (fmode & 07777); + vattr.va_rdev = (ipl_major<<8)|2; + + error = vn_create(IPL_STATE, UIO_SYSSPACE, &vattr, EXCL, 0, &vp); if (error == 0) VN_RELE(vp); return error; } diff --git a/contrib/ipfilter/opt.c b/contrib/ipfilter/opt.c index 4576b554d632..e52f7bc3674d 100644 --- a/contrib/ipfilter/opt.c +++ b/contrib/ipfilter/opt.c @@ -1,134 +1,135 @@ /* * (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 #include #include #include #include #include #include #include #include #include #include #include #include "ip_compat.h" #include "ipf.h" #if !defined(lint) && defined(LIBC_SCCS) static char sccsid[] = "@(#)opt.c 1.8 4/10/96 (C) 1993-1995 Darren Reed"; -static char rcsid[] = "$Id: opt.c,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $"; +static char rcsid[] = "$Id: opt.c,v 2.0.2.3 1997/03/10 08:10:40 darrenr Exp $"; #endif extern int opts; struct ipopt_names ionames[] ={ { IPOPT_NOP, 0x000001, 1, "nop" }, { IPOPT_RR, 0x000002, 7, "rr" }, /* 1 route */ { IPOPT_ZSU, 0x000004, 3, "zsu" }, { IPOPT_MTUP, 0x000008, 3, "mtup" }, { IPOPT_MTUR, 0x000010, 3, "mtur" }, { IPOPT_ENCODE, 0x000020, 3, "encode" }, { IPOPT_TS, 0x000040, 8, "ts" }, /* 1 TS */ { IPOPT_TR, 0x000080, 3, "tr" }, { IPOPT_SECURITY,0x000100, 11, "sec" }, { IPOPT_SECURITY,0x000100, 11, "sec-class" }, { IPOPT_LSRR, 0x000200, 7, "lsrr" }, /* 1 route */ { IPOPT_E_SEC, 0x000400, 3, "e-sec" }, { IPOPT_CIPSO, 0x000800, 3, "cipso" }, { IPOPT_SATID, 0x001000, 4, "satid" }, { IPOPT_SSRR, 0x002000, 7, "ssrr" }, /* 1 route */ { IPOPT_ADDEXT, 0x004000, 3, "addext" }, { IPOPT_VISA, 0x008000, 3, "visa" }, { IPOPT_IMITD, 0x010000, 3, "imitd" }, { IPOPT_EIP, 0x020000, 3, "eip" }, { IPOPT_FINN, 0x040000, 3, "finn" }, { 0, 0, 0, (char *)NULL } /* must be last */ }; struct ipopt_names secclass[] = { { IPSO_CLASS_RES4, 0x01, 0, "reserv-4" }, { IPSO_CLASS_TOPS, 0x02, 0, "topsecret" }, { IPSO_CLASS_SECR, 0x04, 0, "secret" }, { IPSO_CLASS_RES3, 0x08, 0, "reserv-3" }, { IPSO_CLASS_CONF, 0x10, 0, "confid" }, { IPSO_CLASS_UNCL, 0x20, 0, "unclass" }, { IPSO_CLASS_RES2, 0x40, 0, "reserv-2" }, { IPSO_CLASS_RES1, 0x80, 0, "reserv-1" }, { 0, 0, 0, NULL } /* must be last */ }; +static u_char seclevel __P((char *)); static u_char seclevel(slevel) char *slevel; { struct ipopt_names *so; for (so = secclass; 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 (u_char)so->on_value; } u_long buildopts(cp, op) char *cp, *op; { struct ipopt_names *io; u_char 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-class")) { lvl = seclevel(t); *(op - 1) = lvl; } op += io->on_siz - 3; if (len & 3) { *op++ = IPOPT_NOP; len++; } } if (opts & OPT_DEBUG) fprintf(stderr, "bo: %s %d %#x: %d\n", io->on_name, io->on_value, io->on_bit, len); 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/parse.c b/contrib/ipfilter/parse.c index 023605399d73..432fb99a4052 100644 --- a/contrib/ipfilter/parse.c +++ b/contrib/ipfilter/parse.c @@ -1,1258 +1,1277 @@ /* * (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 #include #if !defined(__SVR4) && !defined(__svr4__) #include #else #include #endif #include #include #include #include #include #include #include #include #include #include #include -#include "ip_fil.h" #include #include #include #include -#include "ipf.h" #include +#include "ip_compat.h" +#include "ip_fil.h" +#include "ipf.h" #if !defined(lint) && defined(LIBC_SCCS) static char sccsid[] ="@(#)parse.c 1.44 6/5/96 (C) 1993-1996 Darren Reed"; -static char rcsid[] = "$Id: parse.c,v 2.0.1.2 1997/02/17 13:59:44 darrenr Exp $"; +static char rcsid[] = "$Id: parse.c,v 2.0.2.5 1997/03/31 10:05:38 darrenr Exp $"; #endif extern struct ipopt_names ionames[], secclass[]; extern int opts; -extern int gethostname(); -u_long hostnum(), optname(); -u_short portnum(); -u_char tcp_flags(); -struct frentry *parse(); -void binprint(), printfr(); -int addicmp(), extras(), hostmask(), ports(), icmpcode(), addkeep(); -int to_interface(); +u_short portnum __P((char *)); +u_char tcp_flags __P((char *, u_char *)); +int addicmp __P((char ***, struct frentry *)); +int extras __P((char ***, struct frentry *)); +char ***seg; +u_long *sa, *msk; +u_short *pp, *tp; +u_char *cp; + +int hostmask __P((char ***, u_long *, u_long *, u_short *, u_char *, + u_short *)); +int ports __P((char ***, u_short *, u_char *, u_short *)); +int icmpcode __P((char *)), addkeep __P((char ***, struct frentry *)); +int to_interface __P((frdest_t *, char *)); +void print_toif __P((char *, frdest_t *)); +void optprint __P((u_short, u_short, u_long, u_long)); +int countbits __P((u_long)); +char *portname __P((int, int)); char *proto = NULL; char flagset[] = "FSRPAU"; u_char flags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH, TH_ACK, TH_URG }; static char thishost[64]; void initparse() { gethostname(thishost, sizeof(thishost)); thishost[sizeof(thishost) - 1] = '\0'; } /* parse() * * parse a line read from the input filter rule file */ struct frentry *parse(line) char *line; { static struct frentry fil; struct protoent *p = NULL; char *cps[31], **cpp; u_char ch; int i, cnt = 1; while (*line && isspace(*line)) line++; if (!*line) return NULL; bzero((char *)&fil, sizeof(fil)); fil.fr_mip.fi_v = 0xf; fil.fr_ip.fi_v = 4; /* * break line up into max of 20 segments */ if (opts & OPT_DEBUG) fprintf(stderr, "parse [%s]\n", line); for (i = 0, *cps = strtok(line, " \b\t\r\n"); cps[i] && i < 30; cnt++) cps[++i] = strtok(NULL, " \b\t\r\n"); cps[i] = NULL; if (cnt < 3) { (void)fprintf(stderr,"not enough segments in line\n"); return NULL; } cpp = cps; if (**cpp == '@') - fil.fr_hits = atoi(*cpp++ + 1) + 1; + fil.fr_hits = (U_QUAD_T)atoi(*cpp++ + 1) + 1; if (!strcasecmp("block", *cpp)) { fil.fr_flags = FR_BLOCK; if (!strncasecmp(*(cpp+1), "return-icmp", 11)) { fil.fr_flags |= FR_RETICMP; cpp++; if (*(*cpp + 11) == '(') { fil.fr_icode = icmpcode(*cpp + 12); if (fil.fr_icode == -1) { fprintf(stderr, "uncrecognised icmp code %s\n", *cpp + 12); return NULL; } } } else if (!strncasecmp(*(cpp+1), "return-rst", 10)) { fil.fr_flags |= FR_RETRST; cpp++; } } else if (!strcasecmp("count", *cpp)) { fil.fr_flags = FR_ACCOUNT; } else if (!strcasecmp("pass", *cpp)) { fil.fr_flags = FR_PASS; } else if (!strcasecmp("log", *cpp)) { fil.fr_flags = FR_LOG; if (!strcasecmp(*(cpp+1), "body")) { fil.fr_flags |= FR_LOGBODY; cpp++; } if (!strcasecmp(*(cpp+1), "first")) { fil.fr_flags |= FR_LOGFIRST; cpp++; } } else { /* * Doesn't start with one of the action words */ (void)fprintf(stderr, "unknown keyword (%s)\n", *cpp); return NULL; } cpp++; - if (!strcasecmp("in", *cpp)) { + if (!strcasecmp("in", *cpp)) fil.fr_flags |= FR_INQUE; + else if (!strcasecmp("out", *cpp)) { + fil.fr_flags |= FR_OUTQUE; if (fil.fr_flags & FR_RETICMP) { (void)fprintf(stderr, "Can only use return-icmp with 'in'\n"); return NULL; } else if (fil.fr_flags & FR_RETRST) { (void)fprintf(stderr, "Can only use return-rst with 'in'\n"); return NULL; } - } else if (!strcasecmp("out", *cpp)) - fil.fr_flags |= FR_OUTQUE; - else { + } else { (void)fprintf(stderr, "missing 'in'/'out' keyword (%s)\n", *cpp); return NULL; } if (!*++cpp) return NULL; if (!strcasecmp("log", *cpp)) { cpp++; if (fil.fr_flags & FR_PASS) fil.fr_flags |= FR_LOGP; else if (fil.fr_flags & FR_BLOCK) fil.fr_flags |= FR_LOGB; if (!strcasecmp(*cpp, "body")) { fil.fr_flags |= FR_LOGBODY; cpp++; } if (!strcasecmp(*cpp, "first")) { fil.fr_flags |= FR_LOGFIRST; cpp++; } if (!strcasecmp(*cpp, "or-block")) { if (!(fil.fr_flags & FR_PASS)) { (void)fprintf(stderr, "or-block must be used with pass\n"); return NULL; } fil.fr_flags |= FR_LOGORBLOCK; cpp++; } } if (!strcasecmp("quick", *cpp)) { cpp++; fil.fr_flags |= FR_QUICK; } *fil.fr_ifname = '\0'; if (*cpp && !strcasecmp(*cpp, "on")) { if (!*++cpp) { (void)fprintf(stderr, "interface name missing\n"); return NULL; } (void)strncpy(fil.fr_ifname, *cpp, IFNAMSIZ-1); fil.fr_ifname[IFNAMSIZ-1] = '\0'; cpp++; if (!*cpp) { if (fil.fr_flags & FR_RETRST) { (void)fprintf(stderr, "%s can only be used with TCP\n", "return-rst"); return NULL; } return &fil; } if (*cpp) { if (!strcasecmp(*cpp, "dup-to") && *(cpp + 1)) { cpp++; if (to_interface(&fil.fr_dif, *cpp)) return NULL; cpp++; } if (!strcasecmp(*cpp, "to") && *(cpp + 1)) { cpp++; if (to_interface(&fil.fr_tif, *cpp)) return NULL; cpp++; } else if (!strcasecmp(*cpp, "fastroute")) { fil.fr_flags |= FR_FASTROUTE; cpp++; } } } if (*cpp && !strcasecmp(*cpp, "tos")) { if (!*++cpp) { (void)fprintf(stderr, "tos missing value\n"); return NULL; } fil.fr_tos = strtol(*cpp, NULL, 0); fil.fr_mip.fi_tos = 0xff; cpp++; } if (*cpp && !strcasecmp(*cpp, "ttl")) { if (!*++cpp) { (void)fprintf(stderr, "ttl missing hopcount value\n"); return NULL; } fil.fr_ttl = atoi(*cpp); fil.fr_mip.fi_ttl = 0xff; cpp++; } /* * check for "proto " only decode udp/tcp/icmp as protoname */ proto = NULL; if (*cpp && !strcasecmp(*cpp, "proto")) { if (!*++cpp) { (void)fprintf(stderr, "protocol name missing\n"); return NULL; } if (!strcasecmp(*cpp, "tcp/udp")) { fil.fr_ip.fi_fl |= FI_TCPUDP; fil.fr_mip.fi_fl |= FI_TCPUDP; } else { if (!(p = getprotobyname(*cpp)) && !isdigit(**cpp)) { (void)fprintf(stderr, "unknown protocol (%s)\n", *cpp); return NULL; } if (p) fil.fr_proto = p->p_proto; else if (isdigit(**cpp)) fil.fr_proto = atoi(*cpp); fil.fr_mip.fi_p = 0xff; } proto = *cpp; if (fil.fr_proto != IPPROTO_TCP && fil.fr_flags & FR_RETRST) { (void)fprintf(stderr, "%s can only be used with TCP\n", "return-rst"); return NULL; } if (!*++cpp) return &fil; } if (fil.fr_proto != IPPROTO_TCP && fil.fr_flags & FR_RETRST) { (void)fprintf(stderr, "%s can only be used with TCP\n", "return-rst"); return NULL; } /* * get the from host and bit mask to use against packets */ if (!*cpp) { fprintf(stderr, "missing source specification\n"); return NULL; } if (!strcasecmp(*cpp, "all")) { cpp++; if (!*cpp) return &fil; } else { if (strcasecmp(*cpp, "from")) { (void)fprintf(stderr, "unexpected keyword (%s) - from\n", *cpp); return NULL; } if (!*++cpp) { (void)fprintf(stderr, "missing host after from\n"); return NULL; } ch = 0; - if (hostmask(&cpp, &fil.fr_src, &fil.fr_smsk, - &fil.fr_sport, &ch, &fil.fr_stop)) { + if (hostmask(&cpp, (u_long *)&fil.fr_src, + (u_long *)&fil.fr_smsk, &fil.fr_sport, &ch, + &fil.fr_stop)) { (void)fprintf(stderr, "bad host (%s)\n", *cpp); return NULL; } fil.fr_scmp = ch; if (!*cpp) { (void)fprintf(stderr, "missing to fields\n"); return NULL; } /* * do the same for the to field (destination host) */ if (strcasecmp(*cpp, "to")) { (void)fprintf(stderr, "unexpected keyword (%s) - to\n", *cpp); return NULL; } if (!*++cpp) { (void)fprintf(stderr, "missing host after to\n"); return NULL; } ch = 0; - if (hostmask(&cpp, &fil.fr_dst, &fil.fr_dmsk, - &fil.fr_dport, &ch, &fil.fr_dtop)) { + if (hostmask(&cpp, (u_long *)&fil.fr_dst, + (u_long *)&fil.fr_dmsk, &fil.fr_dport, &ch, + &fil.fr_dtop)) { (void)fprintf(stderr, "bad host (%s)\n", *cpp); return NULL; } fil.fr_dcmp = ch; } /* * check some sanity, make sure we don't have icmp checks with tcp * or udp or visa versa. */ if (fil.fr_proto && (fil.fr_dcmp || fil.fr_scmp) && fil.fr_proto != IPPROTO_TCP && fil.fr_proto != IPPROTO_UDP) { (void)fprintf(stderr, "port operation on non tcp/udp\n"); return NULL; } if (fil.fr_icmp && fil.fr_proto != IPPROTO_ICMP) { (void)fprintf(stderr, "icmp comparisons on wrong protocol\n"); return NULL; } if (!*cpp) return &fil; if (*cpp && !strcasecmp(*cpp, "flags")) { if (!*++cpp) { (void)fprintf(stderr, "no flags present\n"); return NULL; } fil.fr_tcpf = tcp_flags(*cpp, &fil.fr_tcpfm); cpp++; } /* * extras... */ if (*cpp && (!strcasecmp(*cpp, "with") || !strcasecmp(*cpp, "and"))) if (extras(&cpp, &fil)) return NULL; /* * icmp types for use with the icmp protocol */ if (*cpp && !strcasecmp(*cpp, "icmp-type")) { if (fil.fr_proto != IPPROTO_ICMP) { (void)fprintf(stderr, "icmp with wrong protocol (%d)\n", fil.fr_proto); return NULL; } if (addicmp(&cpp, &fil)) return NULL; fil.fr_icmp = htons(fil.fr_icmp); fil.fr_icmpm = htons(fil.fr_icmpm); } /* * Keep something... */ while (*cpp && !strcasecmp(*cpp, "keep")) if (addkeep(&cpp, &fil)) return NULL; /* * leftovers...yuck */ if (*cpp && **cpp) { fprintf(stderr, "unknown words at end: ["); for (; *cpp; cpp++) (void)fprintf(stderr, "%s ", *cpp); (void)fprintf(stderr, "]\n"); return NULL; } /* * lazy users... */ if (!fil.fr_proto && (fil.fr_dcmp || fil.fr_scmp || fil.fr_tcpf)) { (void)fprintf(stderr, "no protocol given for TCP/UDP comparisons\n"); return NULL; } /* if ((fil.fr_flags & FR_KEEPFRAG) && (!(fil.fr_ip.fi_fl & FI_FRAG) || !(fil.fr_ip.fi_fl & FI_FRAG))) { (void)fprintf(stderr, "must use 'with frags' with 'keep frags'\n"); return NULL; } */ return &fil; } int to_interface(fdp, to) frdest_t *fdp; char *to; { int r = 0; char *s; s = index(to, ':'); fdp->fd_ifp = NULL; if (s) { *s++ = '\0'; fdp->fd_ip.s_addr = hostnum(s, &r); if (r == -1) return -1; } (void) strncpy(fdp->fd_ifname, to, sizeof(fdp->fd_ifname) - 1); fdp->fd_ifname[sizeof(fdp->fd_ifname) - 1] = '\0'; return 0; } void print_toif(tag, fdp) char *tag; frdest_t *fdp; { (void)printf("%s %s%s", tag, fdp->fd_ifname, (fdp->fd_ifp || (int)fdp->fd_ifp == -1) ? "" : "(!)"); if (fdp->fd_ip.s_addr) (void)printf(":%s", inet_ntoa(fdp->fd_ip)); putchar(' '); } /* * returns false if neither "hostmask/num" or "hostmask mask addr" are * found in the line segments */ int hostmask(seg, sa, msk, pp, cp, tp) char ***seg; u_long *sa, *msk; u_short *pp, *tp; u_char *cp; { char *s; int bits = -1, resolved; /* * is it possibly hostname/num ? */ if ((s = index(**seg, '/'))) { *s++ = '\0'; if (!isdigit(*s)) return -1; if (index(s, '.')) *msk = inet_addr(s); if (!index(s, '.') && !index(s, 'x')) { /* * set x most significant bits */ for (bits = atoi(s); bits; bits--) { *msk /= 2; *msk |= ntohl(inet_addr("128.0.0.0")); } *msk = htonl(*msk); } else { if (inet_aton(s, (struct in_addr *)msk) == -1) return -1; } *sa = hostnum(**seg, &resolved) & *msk; if (resolved == -1) return -1; (*seg)++; return ports(seg, pp, cp, tp); } /* * look for extra segments if "mask" found in right spot */ if (*(*seg+1) && *(*seg+2) && !strcasecmp(*(*seg+1), "mask")) { *sa = hostnum(**seg, &resolved); if (resolved == -1) return -1; (*seg)++; (*seg)++; if (inet_aton(**seg, (struct in_addr *)msk) == -1) return -1; (*seg)++; *sa &= *msk; return ports(seg, pp, cp, tp); } if (**seg) { *sa = hostnum(**seg, &resolved); if (resolved == -1) return -1; (*seg)++; *msk = (*sa ? inet_addr("255.255.255.255") : 0L); *sa &= *msk; return ports(seg, pp, cp, tp); } return -1; } /* * 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 (!strcasecmp("", host)) host = thishost; 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; } /* * check for possible presence of the port fields in the line */ int ports(seg, pp, cp, tp) char ***seg; u_short *pp, *tp; u_char *cp; { int comp = -1; if (!*seg || !**seg || !***seg) return 0; if (!strcasecmp(**seg, "port") && *(*seg + 1) && *(*seg + 2)) { (*seg)++; if (isdigit(***seg) && *(*seg + 2)) { *pp = portnum(**seg); (*seg)++; if (!strcmp(**seg, "<>")) comp = FR_OUTRANGE; else if (!strcmp(**seg, "><")) comp = FR_INRANGE; (*seg)++; *tp = portnum(**seg); } else if (!strcmp(**seg, "=") || !strcasecmp(**seg, "eq")) comp = FR_EQUAL; else if (!strcmp(**seg, "!=") || !strcasecmp(**seg, "ne")) comp = FR_NEQUAL; else if (!strcmp(**seg, "<") || !strcasecmp(**seg, "lt")) comp = FR_LESST; else if (!strcmp(**seg, ">") || !strcasecmp(**seg, "gt")) comp = FR_GREATERT; else if (!strcmp(**seg, "<=") || !strcasecmp(**seg, "le")) comp = FR_LESSTE; else if (!strcmp(**seg, ">=") || !strcasecmp(**seg, "ge")) comp = FR_GREATERTE; else { (void)fprintf(stderr,"unknown comparator (%s)\n", **seg); return -1; } if (comp != FR_OUTRANGE && comp != FR_INRANGE) { (*seg)++; *pp = portnum(**seg); } *cp = comp; (*seg)++; } return 0; } /* * find the port number given by the name, either from getservbyname() or * straight atoi() */ u_short portnum(name) char *name; { struct servent *sp, *sp2; u_short p1 = 0; if (isdigit(*name)) return (u_short)atoi(name); if (!proto) proto = "tcp/udp"; if (strcasecmp(proto, "tcp/udp")) { sp = getservbyname(name, 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); } u_char tcp_flags(flgs, mask) char *flgs; u_char *mask; { u_char tcpf = 0, tcpfm = 0, *fp = &tcpf; char *s, *t; for (s = flgs; *s; s++) { if (*s == '/' && fp == &tcpf) { fp = &tcpfm; continue; } if (!(t = index(flagset, *s))) { (void)fprintf(stderr, "unknown flag (%c)\n", *s); return 0; } *fp |= flags[t - flagset]; } if (!tcpfm) tcpfm = 0xff; *mask = tcpfm; return tcpf; } /* * deal with extra bits on end of the line */ int extras(cp, fr) char ***cp; struct frentry *fr; { u_short secmsk; u_long opts; int notopt; char oflags; opts = 0; secmsk = 0; notopt = 0; (*cp)++; if (!**cp) return -1; while (**cp && (!strncasecmp(**cp, "ipopt", 5) || !strncasecmp(**cp, "not", 3) || !strncasecmp(**cp, "opt", 4) || !strncasecmp(**cp, "frag", 3) || !strncasecmp(**cp, "no", 2) || !strncasecmp(**cp, "short", 5))) { if (***cp == 'n' || ***cp == 'N') { notopt = 1; (*cp)++; continue; } else if (***cp == 'i' || ***cp == 'I') { if (!notopt) fr->fr_ip.fi_fl |= FI_OPTIONS; fr->fr_mip.fi_fl |= FI_OPTIONS; goto nextopt; } else if (***cp == 'f' || ***cp == 'F') { if (!notopt) fr->fr_ip.fi_fl |= FI_FRAG; fr->fr_mip.fi_fl |= FI_FRAG; goto nextopt; } else if (***cp == 'o' || ***cp == 'O') { if (!*(*cp + 1)) { (void)fprintf(stderr, "opt missing arguements\n"); return -1; } (*cp)++; if (!(opts = optname(cp, &secmsk))) return -1; oflags = FI_OPTIONS; } else if (***cp == 's' || ***cp == 'S') { if (fr->fr_tcpf) { (void) fprintf(stderr, "short cannot be used with TCP flags\n"); return -1; } if (!notopt) fr->fr_ip.fi_fl |= FI_SHORT; fr->fr_mip.fi_fl |= FI_SHORT; goto nextopt; } else return -1; if (!notopt || !opts) fr->fr_mip.fi_fl |= oflags; if (notopt) if (!secmsk) fr->fr_mip.fi_optmsk |= opts; else fr->fr_mip.fi_optmsk |= (opts & ~0x0100); else fr->fr_mip.fi_optmsk |= opts; fr->fr_mip.fi_secmsk |= secmsk; if (notopt) { fr->fr_ip.fi_fl &= (~oflags & 0xf); fr->fr_ip.fi_optmsk &= ~opts; fr->fr_ip.fi_secmsk &= ~secmsk; } else { fr->fr_ip.fi_fl |= oflags; fr->fr_ip.fi_optmsk |= opts; fr->fr_ip.fi_secmsk |= secmsk; } nextopt: notopt = 0; opts = 0; oflags = 0; secmsk = 0; (*cp)++; } return 0; } u_long optname(cp, sp) char ***cp; u_short *sp; { struct ipopt_names *io, *so; u_long msk = 0; u_short smsk = 0; char *s; int sec = 0; for (s = strtok(**cp, ","); s; s = strtok(NULL, ",")) { for (io = ionames; io->on_name; io++) if (!strcasecmp(s, io->on_name)) { msk |= io->on_bit; break; } if (!io->on_name) { fprintf(stderr, "unknown IP option name %s\n", s); return 0; } if (!strcasecmp(s, "sec-class")) sec = 1; } if (sec && !*(*cp + 1)) { fprintf(stderr, "missing security level after sec-class\n"); return 0; } if (sec) { (*cp)++; for (s = strtok(**cp, ","); s; s = strtok(NULL, ",")) { for (so = secclass; so->on_name; so++) if (!strcasecmp(s, so->on_name)) { smsk |= so->on_bit; break; } if (!so->on_name) { fprintf(stderr, "no such security level: %s\n", s); return 0; } } if (smsk) *sp = smsk; } return msk; } void optprint(secmsk, secbits, optmsk, optbits) u_short secmsk, secbits; u_long optmsk, optbits; { struct ipopt_names *io, *so; char *s; int secflag = 0; s = " opt "; for (io = ionames; io->on_name; io++) if ((io->on_bit & optmsk) && ((io->on_bit & optmsk) == (io->on_bit & optbits))) { if ((io->on_value != IPOPT_SECURITY) || (!secmsk && !secbits)) { printf("%s%s", s, io->on_name); if (io->on_value == IPOPT_SECURITY) io++; s = ","; } else secflag = 1; } if (secmsk & secbits) { printf("%ssec-class", s); s = " "; for (so = secclass; so->on_name; so++) if ((secmsk & so->on_bit) && ((so->on_bit & secmsk) == (so->on_bit & secbits))) { printf("%s%s", s, so->on_name); s = ","; } } if ((optmsk && (optmsk != optbits)) || (secmsk && (secmsk != secbits))) { s = " "; printf(" not opt"); if (optmsk != optbits) { for (io = ionames; io->on_name; io++) if ((io->on_bit & optmsk) && ((io->on_bit & optmsk) != (io->on_bit & optbits))) { if ((io->on_value != IPOPT_SECURITY) || (!secmsk && !secbits)) { printf("%s%s", s, io->on_name); s = ","; + if (io->on_value == + IPOPT_SECURITY) + io++; } else io++; } } if (secmsk != secbits) { printf("%ssec-class", s); s = " "; for (so = secclass; so->on_name; so++) if ((so->on_bit & secmsk) && ((so->on_bit & secmsk) != (so->on_bit & secbits))) { printf("%s%s", s, so->on_name); s = ","; } } } } char *icmptypes[] = { "echorep", (char *)NULL, (char *)NULL, "unreach", "squench", "redir", (char *)NULL, (char *)NULL, "echo", (char *)NULL, (char *)NULL, "timex", "paramprob", "timest", "timestrep", "inforeq", "inforep", "maskreq", "maskrep", "END" }; /* * set the icmp field to the correct type if "icmp" word is found */ int addicmp(cp, fp) char ***cp; struct frentry *fp; { char **t; int i; (*cp)++; if (!**cp) return -1; if (!fp->fr_proto) /* to catch lusers */ fp->fr_proto = IPPROTO_ICMP; if (isdigit(***cp)) { i = atoi(**cp); (*cp)++; } else { for (t = icmptypes, i = 0; ; t++, i++) { if (!*t) continue; if (!strcasecmp("END", *t)) { i = -1; break; } if (!strcasecmp(*t, **cp)) break; } - if (i == -1) + if (i == -1) { + (void)fprintf(stderr, + "Invalid icmp-type (%s) specified\n", **cp); return -1; + } } fp->fr_icmp = (u_short)(i << 8); fp->fr_icmpm = (u_short)0xff00; (*cp)++; if (!**cp) return 0; if (**cp && strcasecmp("code", **cp)) return 0; (*cp)++; if (isdigit(***cp)) { i = atoi(**cp); fp->fr_icmp |= (u_short)i; fp->fr_icmpm = (u_short)0xffff; (*cp)++; return 0; } return -1; } #define MAX_ICMPCODE 12 char *icmpcodes[] = { "net-unr", "host-unr", "proto-unr", "port-unr", "needfrag", "srcfail", "net-unk", "host-unk", "isolate", "net-prohib", "host-prohib", "net-tos", "host-tos", NULL }; /* * Return the number for the associated ICMP unreachable code. */ int icmpcode(str) char *str; { char *s; int i, len; if (!(s = strrchr(str, ')'))) return -1; *s = '\0'; if (isdigit(*str)) return atoi(str); len = strlen(str); for (i = 0; icmpcodes[i]; i++) if (!strncasecmp(str, icmpcodes[i], MIN(len, strlen(icmpcodes[i])) )) return i; return -1; } /* * set the icmp field to the correct type if "icmp" word is found */ int addkeep(cp, fp) char ***cp; struct frentry *fp; { if (fp->fr_proto != IPPROTO_TCP && fp->fr_proto != IPPROTO_UDP && fp->fr_proto != IPPROTO_ICMP && !(fp->fr_ip.fi_fl & FI_TCPUDP)) { (void)fprintf(stderr, "Can only use keep with UDP/ICMP/TCP\n"); return -1; } (*cp)++; if (**cp && strcasecmp(**cp, "state") && strcasecmp(**cp, "frags")) { (void)fprintf(stderr, "Unrecognised state keyword \"%s\"\n", **cp); return -1; } if (***cp == 's' || ***cp == 'S') fp->fr_flags |= FR_KEEPSTATE; else if (***cp == 'f' || ***cp == 'F') fp->fr_flags |= FR_KEEPFRAG; (*cp)++; return 0; } /* * count consecutive 1's in bit mask. If the mask generated by counting * consecutive 1's is different to that passed, return -1, else return # * 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; } char *portname(pr, port) int pr, port; { static char buf[32]; struct protoent *p = NULL; struct servent *sv = NULL, *sv1 = NULL; if (pr == -1) { if ((sv = getservbyport(port, "tcp"))) { strncpy(buf, sv->s_name, sizeof(buf)-1); buf[sizeof(buf)-1] = '\0'; sv1 = getservbyport(port, "udp"); sv = strncasecmp(buf, sv->s_name, strlen(buf)) ? NULL : sv1; } if (sv) return buf; } else if (pr && (p = getprotobynumber(pr))) { if ((sv = getservbyport(port, p->p_name))) { strncpy(buf, sv->s_name, sizeof(buf)-1); buf[sizeof(buf)-1] = '\0'; return buf; } } (void) sprintf(buf, "%d", port); return buf; } /* * print the filter structure in a useful way */ void printfr(fp) struct frentry *fp; { static char *pcmp1[] = { "*", "=", "!=", "<", ">", "<=", ">=", "<>", "><"}; struct protoent *p; int ones = 0, pr; char *s; u_char *t; if (fp->fr_flags & FR_PASS) { (void)printf("pass"); } else if (fp->fr_flags & FR_BLOCK) { (void)printf("block"); if (fp->fr_flags & FR_RETICMP) { (void)printf(" return-icmp"); if (fp->fr_icode) if (fp->fr_icode <= MAX_ICMPCODE) printf("(%s)", icmpcodes[(int)fp->fr_icode]); else printf("(%d)", fp->fr_icode); } if (fp->fr_flags & FR_RETRST) (void)printf(" return-rst"); } else if ((fp->fr_flags & FR_LOGMASK) == FR_LOG) { (void)printf("log"); if (fp->fr_flags & FR_LOGBODY) (void)printf(" body"); if (fp->fr_flags & FR_LOGFIRST) (void)printf(" first"); } else if (fp->fr_flags & FR_ACCOUNT) (void)printf("count"); if (fp->fr_flags & FR_OUTQUE) (void)printf(" out "); else (void)printf(" in "); if (((fp->fr_flags & FR_LOGB) == FR_LOGB) || ((fp->fr_flags & FR_LOGP) == FR_LOGP)) { (void)printf("log "); if (fp->fr_flags & FR_LOGBODY) (void)printf("body "); if (fp->fr_flags & FR_LOGFIRST) (void)printf("first "); if (fp->fr_flags & FR_LOGORBLOCK) (void)printf("or-block "); } if (fp->fr_flags & FR_QUICK) (void)printf("quick "); if (*fp->fr_ifname) { (void)printf("on %s%s ", fp->fr_ifname, (fp->fr_ifa || (int)fp->fr_ifa == -1) ? "" : "(!)"); if (*fp->fr_dif.fd_ifname) print_toif("dup-to", &fp->fr_dif); if (*fp->fr_tif.fd_ifname) print_toif("to", &fp->fr_tif); if (fp->fr_flags & FR_FASTROUTE) (void)printf("fastroute "); } if (fp->fr_mip.fi_tos) (void)printf("tos %#x ", fp->fr_tos); if (fp->fr_mip.fi_ttl) (void)printf("ttl %d ", fp->fr_ttl); if (fp->fr_ip.fi_fl & FI_TCPUDP) { (void)printf("proto tcp/udp "); pr = -1; } else if ((pr = fp->fr_mip.fi_p)) { if ((p = getprotobynumber(fp->fr_proto))) (void)printf("proto %s ", p->p_name); else (void)printf("proto %d ", fp->fr_proto); } if (!fp->fr_src.s_addr & !fp->fr_smsk.s_addr) (void)printf("from any "); else { (void)printf("from %s", inet_ntoa(fp->fr_src)); if ((ones = countbits(fp->fr_smsk.s_addr)) == -1) (void)printf("/%s ", inet_ntoa(fp->fr_smsk)); else (void)printf("/%d ", ones); } if (fp->fr_scmp) if (fp->fr_scmp == FR_INRANGE || fp->fr_scmp == FR_OUTRANGE) (void)printf("port %d %s %d ", fp->fr_sport, pcmp1[fp->fr_scmp], fp->fr_stop); else (void)printf("port %s %s ", pcmp1[fp->fr_scmp], portname(pr, fp->fr_sport)); if (!fp->fr_dst.s_addr & !fp->fr_dmsk.s_addr) (void)printf("to any"); else { (void)printf("to %s", inet_ntoa(fp->fr_dst)); if ((ones = countbits(fp->fr_dmsk.s_addr)) == -1) (void)printf("/%s", inet_ntoa(fp->fr_dmsk)); else (void)printf("/%d", ones); } if (fp->fr_dcmp) { if (fp->fr_dcmp == FR_INRANGE || fp->fr_dcmp == FR_OUTRANGE) (void)printf(" port %d %s %d", fp->fr_dport, pcmp1[fp->fr_dcmp], fp->fr_dtop); else (void)printf(" port %s %s", pcmp1[fp->fr_dcmp], portname(pr, fp->fr_dport)); } if ((fp->fr_ip.fi_fl & ~FI_TCPUDP) || (fp->fr_mip.fi_fl & ~FI_TCPUDP) || fp->fr_ip.fi_optmsk || fp->fr_mip.fi_optmsk || fp->fr_ip.fi_secmsk || fp->fr_mip.fi_secmsk) { (void)printf(" with"); if (fp->fr_ip.fi_optmsk || fp->fr_mip.fi_optmsk || fp->fr_ip.fi_secmsk || fp->fr_mip.fi_secmsk) optprint(fp->fr_mip.fi_secmsk, fp->fr_ip.fi_secmsk, fp->fr_mip.fi_optmsk, fp->fr_ip.fi_optmsk); else if (fp->fr_mip.fi_fl & FI_OPTIONS) { if (!(fp->fr_ip.fi_fl & FI_OPTIONS)) (void)printf(" not"); (void)printf(" ipopt"); } if (fp->fr_mip.fi_fl & FI_SHORT) { if (!(fp->fr_ip.fi_fl & FI_SHORT)) (void)printf(" not"); (void)printf(" short"); } if (fp->fr_mip.fi_fl & FI_FRAG) { if (!(fp->fr_ip.fi_fl & FI_FRAG)) (void)printf(" not"); (void)printf(" frag"); } } if (fp->fr_proto == IPPROTO_ICMP && fp->fr_icmpm) { int type = fp->fr_icmp, code; type = ntohs(fp->fr_icmp); code = type & 0xff; type /= 256; if (type < (sizeof(icmptypes) / sizeof(char *)) && icmptypes[type]) (void)printf(" icmp-type %s", icmptypes[type]); else (void)printf(" icmp-type %d", type); if (code) (void)printf(" code %d", code); } if (fp->fr_proto == IPPROTO_TCP && (fp->fr_tcpf || fp->fr_tcpfm)) { (void)printf(" flags "); for (s = flagset, t = flags; *s; s++, t++) if (fp->fr_tcpf & *t) (void)putchar(*s); if (fp->fr_tcpfm) { (void)putchar('/'); for (s = flagset, t = flags; *s; s++, t++) if (fp->fr_tcpfm & *t) (void)putchar(*s); } } if (fp->fr_flags & FR_KEEPSTATE) printf(" keep state"); if (fp->fr_flags & FR_KEEPFRAG) printf(" keep frags"); (void)putchar('\n'); } void binprint(fp) struct frentry *fp; { int i = sizeof(*fp), j = 0; u_char *s; for (s = (u_char *)fp; i; i--, s++) { j++; (void)printf("%02x ",*s); if (j == 16) { (void)printf("\n"); j = 0; } } putchar('\n'); (void)fflush(stdout); } diff --git a/contrib/ipfilter/pcap.h b/contrib/ipfilter/pcap.h index c909297a4d01..1eee3c692852 100644 --- a/contrib/ipfilter/pcap.h +++ b/contrib/ipfilter/pcap.h @@ -1,35 +1,35 @@ /* * (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. - * $Id: pcap.h,v 2.0.1.1 1997/01/09 15:14:45 darrenr Exp $ + * $Id: pcap.h,v 2.0.2.2 1997/02/23 10:38:17 darrenr Exp $ */ /* * This header file is constructed to match the version described by * PCAP_VERSION_MAJ. * * The structure largely derives from libpcap which wouldn't include * nicely without bpf. */ typedef struct pcap_filehdr { u_int pc_id; u_short pc_v_maj; u_short pc_v_min; u_int pc_zone; u_int pc_sigfigs; u_int pc_slen; u_int pc_type; } pcaphdr_t; #define TCPDUMP_MAGIC 0xa1b2c3d4 #define PCAP_VERSION_MAJ 2 typedef struct pcap_pkthdr { struct timeval ph_ts; u_int ph_clen; u_int ph_len; } pcappkt_t; diff --git a/contrib/ipfilter/relay.c b/contrib/ipfilter/relay.c index 9a181a1a83b7..d6acd1070f58 100644 --- a/contrib/ipfilter/relay.c +++ b/contrib/ipfilter/relay.c @@ -1,179 +1,180 @@ /* * Sample program to be used as a transparent proxy. * * Must be executed with permission enough to do an ioctl on /dev/ipl * or equivalent. This is just a sample and is only alpha quality. * - Darren Reed (8 April 1996) */ #include #include #include #include +#include #include #include #include #include #include #include #include "ip_nat.h" #define RELAY_BUFSZ 8192 char ibuff[RELAY_BUFSZ]; char obuff[RELAY_BUFSZ]; int relay(ifd, ofd, rfd) int ifd, ofd, rfd; { fd_set rfds, wfds; char *irh, *irt, *rrh, *rrt; char *iwh, *iwt, *rwh, *rwt; int nfd, n, rw; irh = irt = ibuff; iwh = iwt = obuff; nfd = ifd; if (nfd < ofd) nfd = ofd; if (nfd < rfd) nfd = rfd; while (1) { FD_ZERO(&rfds); FD_ZERO(&wfds); if (irh > irt) FD_SET(rfd, &wfds); if (irh < (ibuff + RELAY_BUFSZ)) FD_SET(ifd, &rfds); if (iwh > iwt) FD_SET(ofd, &wfds); if (iwh < (obuff + RELAY_BUFSZ)) FD_SET(rfd, &rfds); switch ((n = select(nfd + 1, &rfds, &wfds, NULL, NULL))) { case -1 : case 0 : return -1; default : if (FD_ISSET(ifd, &rfds)) { rw = read(ifd, irh, ibuff + RELAY_BUFSZ - irh); if (rw == -1) return -1; if (rw == 0) return 0; irh += rw; n--; } if (n && FD_ISSET(ofd, &wfds)) { rw = write(ofd, iwt, iwh - iwt); if (rw == -1) return -1; iwt += rw; n--; } if (n && FD_ISSET(rfd, &rfds)) { rw = read(rfd, iwh, obuff + RELAY_BUFSZ - iwh); if (rw == -1) return -1; if (rw == 0) return 0; iwh += rw; n--; } if (n && FD_ISSET(rfd, &wfds)) { rw = write(rfd, irt, irh - irt); if (rw == -1) return -1; irt += rw; n--; } if (irh == irt) irh = irt = ibuff; if (iwh == iwt) iwh = iwt = obuff; } } } main(argc, argv) int argc; char *argv[]; { struct sockaddr_in sin; natlookup_t nl; int fd, sl = sizeof(sl), se; openlog(argv[0], LOG_PID|LOG_NDELAY, LOG_DAEMON); if ((fd = open("/dev/ipl", O_RDONLY)) == -1) { se = errno; perror("open"); errno = se; syslog(LOG_ERR, "open: %m\n"); exit(-1); } bzero(&sin, sizeof(sin)); sin.sin_family = AF_INET; sl = sizeof(sin); if (getsockname(0, (struct sockaddr *)&sin, &sl) == -1) { se = errno; perror("getsockname"); errno = se; syslog(LOG_ERR, "getsockname: %m\n"); exit(-1); } else { nl.nl_inip.s_addr = sin.sin_addr.s_addr; nl.nl_inport = sin.sin_port; } bzero(&sin, sizeof(sin)); sin.sin_family = AF_INET; sl = sizeof(sin); if (getpeername(0, (struct sockaddr *)&sin, &sl) == -1) { se = errno; perror("getpeername"); errno = se; syslog(LOG_ERR, "getpeername: %m\n"); exit(-1); } else { nl.nl_outip.s_addr = sin.sin_addr.s_addr; nl.nl_outport = sin.sin_port; } if (ioctl(fd, SIOCGNATL, &nl) == -1) { se = errno; perror("ioctl"); errno = se; syslog(LOG_ERR, "ioctl: %m\n"); exit(-1); } sin.sin_port = nl.nl_inport; sin.sin_addr = nl.nl_inip; sl = sizeof(sin); fd = socket(AF_INET, SOCK_STREAM, 0); if (connect(fd, (struct sockaddr *)&sin, sl) == -1) { se = errno; perror("connect"); errno = se; syslog(LOG_ERR, "connect: %m\n"); exit(-1); } (void) ioctl(fd, F_SETFL, ioctl(fd, F_GETFL, 0)|O_NONBLOCK); (void) ioctl(0, F_SETFL, ioctl(fd, F_GETFL, 0)|O_NONBLOCK); (void) ioctl(1, F_SETFL, ioctl(fd, F_GETFL, 0)|O_NONBLOCK); syslog(LOG_NOTICE, "connected to %s,%d\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); if (relay(0, 1, fd) == -1) { se = errno; perror("relay"); errno = se; syslog(LOG_ERR, "relay: %m\n"); exit(-1); } exit(0); } diff --git a/contrib/ipfilter/rules/rules.sed b/contrib/ipfilter/rules/rules.sed new file mode 100644 index 000000000000..050d9b6ab710 --- /dev/null +++ b/contrib/ipfilter/rules/rules.sed @@ -0,0 +1,5 @@ +WÆ . Ä..'& CVSWÜ example.1WÝ +example.10WÞ +example.11Wß +example.12Wà +example.13Wá example.2Wâ example.3Wã example.4Wä example.5Wå example.6Wæ example.7Wç example.8Wè example.9Wé diff --git a/contrib/ipfilter/snoop.h b/contrib/ipfilter/snoop.h index fdebcef370a8..e257be5ec24d 100644 --- a/contrib/ipfilter/snoop.h +++ b/contrib/ipfilter/snoop.h @@ -1,42 +1,42 @@ /* * (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 RFC (1761) from Sun. - * $Id: snoop.h,v 2.0.1.1 1997/01/09 15:14:45 darrenr Exp $ + * $Id: snoop.h,v 2.0.2.2 1997/02/23 10:38:19 darrenr Exp $ */ struct snoophdr { char s_id[8]; int s_v; int s_type; }; #define SNOOP_VERSION 2 #define SDL_8023 0 #define SDL_8024 1 #define SDL_8025 2 #define SDL_8026 3 #define SDL_ETHER 4 #define SDL_HDLC 5 #define SDL_CHSYNC 6 #define SDL_IBMCC 7 #define SDL_FDDI 8 #define SDL_OTHER 9 #define SDL_MAX 9 struct snooppkt { int sp_olen; int sp_ilen; int sp_plen; int sp_drop; int sp_sec; int sp_usec; }; diff --git a/contrib/ipfilter/solaris.c b/contrib/ipfilter/solaris.c index 73db28fddc6f..8f158fca2174 100644 --- a/contrib/ipfilter/solaris.c +++ b/contrib/ipfilter/solaris.c @@ -1,1018 +1,1044 @@ /* * (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. */ /* #pragma ident "@(#)solaris.c 1.12 6/5/96 (C) 1995 Darren Reed"*/ -#pragma ident "$Id: solaris.c,v 2.0.1.4 1997/02/08 06:38:30 darrenr Exp $"; +#pragma ident "$Id: solaris.c,v 2.0.2.3 1997/03/27 13:45:28 darrenr Exp $"; #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include "ipl.h" -#include "ip_fil.h" -#include "ip_compat.h" #include #include -#include +#include "ip_compat.h" +#include "ipl.h" +#include "ip_fil.h" char _depends_on[] = "drv/ip"; -extern int iplopen(), iplclose(), iplread(), iplioctl(); -extern int iplattach(), ipldetach(); -extern void copyout_mblk(), copyin_mblk(); +extern void copyout_mblk __P((mblk_t *, int, char *, int)); +extern void copyin_mblk __P((mblk_t *, int, char *, int)); -int solattach(), soldetach(); +int solattach __P((void)); +int soldetach __P((void)); extern struct filterstats frstats[]; extern kmutex_t ipl_mutex, ipf_mutex, ipfs_mutex; extern int fr_flags; static qif_t *qif_head = NULL; -static int ipl_getinfo(), ipl_probe(), ipl_identify(), ipl_attach(); -static int ipl_detach(); +static int ipl_getinfo __P((dev_info_t *, ddi_info_cmd_t, + void *, void **)); +static int ipl_probe __P((dev_info_t *)); +static int ipl_identify __P((dev_info_t *)); +static int ipl_attach __P((dev_info_t *, ddi_attach_cmd_t)); +static int ipl_detach __P((dev_info_t *, ddi_detach_cmd_t)); +static qif_t *qif_from_queue __P((queue_t *)); +static int fr_qin __P((queue_t *, mblk_t *)); +static int fr_qout __P((queue_t *, mblk_t *)); +static void fr_donotip __P((int, qif_t *, queue_t *, mblk_t *, + mblk_t *, ip_t *, int)); +void printire __P((ire_t *)); +int ipfr_fastroute __P((qif_t *, ip_t *, mblk_t *, mblk_t **, + fr_info_t *, frdest_t *)); +int fr_precheck __P((mblk_t **, queue_t *, qif_t *, int)); + static struct cb_ops ipl_cb_ops = { iplopen, iplclose, nodev, /* strategy */ nodev, /* print */ nodev, /* dump */ iplread, nodev, /* write */ iplioctl, /* ioctl */ nodev, /* devmap */ nodev, /* mmap */ nodev, /* segmap */ nochpoll, /* poll */ ddi_prop_op, NULL, D_MTSAFE }; static struct dev_ops ipl_ops = { DEVO_REV, 0, ipl_getinfo, ipl_identify, ipl_probe, ipl_attach, ipl_detach, nodev, /* reset */ &ipl_cb_ops, (struct bus_ops *)0 }; extern struct mod_ops mod_driverops; static struct modldrv iplmod = { &mod_driverops, IPL_VERSION, &ipl_ops }; static struct modlinkage modlink1 = { MODREV_1, &iplmod, 0 }; static dev_info_t *ipf_dev_info = NULL; int _init() { #ifdef IPFDEBUG cmn_err(CE_NOTE, "IP Filter: ipf_init()"); #endif return mod_install(&modlink1); } int _fini(void) { #ifdef IPFDEBUG cmn_err(CE_NOTE, "IP Filter: ipf_fini()"); #endif return mod_remove(&modlink1); } int _info(struct modinfo *modinfop) { #ifdef IPFDEBUG cmn_err(CE_NOTE, "IP Filter: ipf_info(%x)", modinfop); #endif return mod_info(&modlink1, modinfop); } static int ipl_probe(dev_info_t *dip) { #ifdef IPFDEBUG cmn_err(CE_NOTE, "IP Filter: ipl_probe(%x)", dip); #endif return DDI_PROBE_SUCCESS; } static int ipl_identify(dev_info_t *dip) { #ifdef IPFDEBUG cmn_err(CE_NOTE, "IP Filter: ipl_identify(%x)", dip); #endif if (strcmp(ddi_get_name(dip), "ipf") == 0) return (DDI_IDENTIFIED); return (DDI_NOT_IDENTIFIED); } -static int ipl_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) +static int ipl_attach(dip, cmd) +dev_info_t *dip; +ddi_attach_cmd_t cmd; { int instance; #ifdef IPFDEBUG cmn_err(CE_NOTE, "IP Filter: ipl_attach(%x,%x)", dip, cmd); #endif switch (cmd) { case DDI_ATTACH: instance = ddi_get_instance(dip); #ifdef IPFDEBUG cmn_err(CE_NOTE, "IP Filter: attach ipf instace %d", instance); #endif if (ddi_create_minor_node(dip, "ipf", S_IFCHR, instance, DDI_PSEUDO, 0) == DDI_FAILURE) { ddi_remove_minor_node(dip, NULL); goto attach_failed; } + if (ddi_create_minor_node(dip, "ipnat", S_IFCHR, instance, + DDI_PSEUDO, 1) == DDI_FAILURE) { + ddi_remove_minor_node(dip, NULL); + goto attach_failed; + } + if (ddi_create_minor_node(dip, "ipstate", S_IFCHR, instance, + DDI_PSEUDO, 2) == DDI_FAILURE) { + ddi_remove_minor_node(dip, NULL); + goto attach_failed; + } ipf_dev_info = dip; sync(); /* * Initialize mutex's */ iplattach(); solattach(); cmn_err(CE_CONT, "IP Filter: attaching complete.\n"); return (DDI_SUCCESS); default: return (DDI_FAILURE); } attach_failed: /* * Use our own detach routine to toss * away any stuff we allocated above. */ (void) ipl_detach(dip, DDI_DETACH); return (DDI_FAILURE); } static int ipl_detach(dip, cmd) dev_info_t *dip; ddi_detach_cmd_t cmd; { int instance; #ifdef IPFDEBUG cmn_err(CE_NOTE, "IP Filter: ipl_detach(%x,%x)", dip, cmd); #endif switch (cmd) { case DDI_DETACH: /* * Undo what we did in ipl_attach, freeing resources * and removing things we installed. The system * framework guarantees we are not active with this devinfo * node in any other entry points at this time. */ ddi_prop_remove_all(dip); instance = ddi_get_instance(dip); ddi_remove_minor_node(dip, NULL); sync(); if (!soldetach()) { cmn_err(CE_CONT, "IP Filter: detached\n"); return (DDI_SUCCESS); } default: return (DDI_FAILURE); } } static int ipl_getinfo(dip, infocmd, arg, result) dev_info_t *dip; ddi_info_cmd_t infocmd; void *arg, **result; { int error = DDI_FAILURE; #ifdef IPFDEBUG cmn_err(CE_NOTE, "IP Filter: ipl_getinfo(%x,%x)", dip, infocmd); #endif switch (infocmd) { case DDI_INFO_DEVT2DEVINFO: *result = ipf_dev_info; error = DDI_SUCCESS; break; case DDI_INFO_DEVT2INSTANCE: *result = (void *)getminor((dev_t) arg); error = DDI_SUCCESS; break; default: break; } return (error); } /* * find the filter structure setup for this queue */ -qif_t *qif_from_queue(q) +static qif_t *qif_from_queue(q) queue_t *q; { qif_t *qif; for (qif = qif_head; qif; qif = qif->qf_next) if ((qif->qf_iptr == q->q_ptr) || (qif->qf_optr == q->q_ptr)) break; return qif; } /* * OK, this is pretty scrappy code, but then it's essentially just here for * debug purposes and that's it. Packets should not normally come through * here, and if they do, well, we would like to see as much information as * possible about them and what they claim to hold. */ void fr_donotip(out, qif, q, m, mt, ip, off) int out; qif_t *qif; queue_t *q; mblk_t *m, *mt; ip_t *ip; int off; { u_char *s, outb[256], *t; int i; outb[0] = '\0'; outb[1] = '\0'; outb[2] = '\0'; outb[3] = '\0'; s = ip ? (u_char *)ip : outb; if (!ip && (m == mt) && m->b_cont && (MTYPE(m) != M_DATA)) m = m->b_cont; printf("!IP %s:%d %x %x %x %d %x %x %x %d %d %x\n%02x%02x%02x%02x\n", qif ? qif->qf_name : "?", out, q, q ? q->q_ptr : NULL, q ? q->q_qinfo : NULL, mt->b_wptr - mt->b_rptr, m, mt, m->b_rptr, m->b_wptr - m->b_rptr, off, ip, *s, *(s+1), *(s+2), *(s+3)); if (m != mt) { i = 0; t = outb; s = mt->b_rptr; sprintf(t, "%d:", MTYPE(mt)); t += strlen(t); for (; (i < 100) && (s < mt->b_wptr); i++) { sprintf(t, "%02x%s", *s++, ((i & 3) == 3) ? " " : ""); t += ((i & 3) == 3) ? 3 : 2; } *t++ = '\n'; *t = '\0'; printf("%s", outb); } i = 0; t = outb; s = m->b_rptr; sprintf(t, "%d:", MTYPE(m)); t += strlen(t); for (; (i < 100) && (s < m->b_wptr); i++) { sprintf(t, "%02x%s", *s++, ((i & 3) == 3) ? " " : ""); t += ((i & 3) == 3) ? 3 : 2; } *t++ = '\n'; *t = '\0'; printf("%s", outb); } /* * find the first data mblk, if present, in the chain we're processing. Also * make a few sanity checks to try prevent the filter from causing a panic - * none of the nice IP sanity checks (including checksumming) should have been * done yet - dangerous! */ int fr_precheck(mp, q, qif, out) mblk_t **mp; queue_t *q; qif_t *qif; int out; { u_long lbuf[48]; mblk_t *m, *mp1, *mt = *mp; register ip_t *ip; int iphlen, hlen, len, err, mlen, off, synced = 0; #ifndef sparc u_short __iplen, __ipoff; #endif tryagain: /* * If there is only M_DATA for a packet going out, then any header * information (which would otherwise appear in an M_PROTO mblk before * the M_DATA) is prepended before the IP header. We need to set the * offset to account for this. - see MMM */ off = (out) ? qif->qf_hl : 0; /* * Find the first data block, count the data blocks in this chain and * the total amount of data. */ for (m = mt; m && (MTYPE(m) != M_DATA); m = m->b_cont) off = 0; /* Any non-M_DATA cancels the offset */ if (!m) return 0; /* No data blocks */ ip = (ip_t *)(m->b_rptr + off); /* MMM */ /* * We might have a 1st data block which is really M_PROTO, i.e. it is * only big enough for the link layer header */ while ((u_char *)ip >= m->b_wptr) { len = (u_char *)ip - m->b_wptr; if (!(m = m->b_cont)) return 0; /* not enough data for IP */ ip = (ip_t *)(m->b_rptr + len); } if ((off = (u_char *)ip - m->b_rptr)) m->b_rptr = (u_char *)ip; mlen = msgdsize(m); /* * Ok, the IP header isn't on a 32bit aligned address. To get around * this, we copy the data to an aligned buffer and work with that. */ if (!OK_32PTR(ip)) { len = MIN(mlen, sizeof(ip_t)); - copyout_mblk(m, 0, lbuf, len); + copyout_mblk(m, 0, (char *)lbuf, len); frstats[out].fr_pull[0]++; ip = (ip_t *)lbuf; } else len = m->b_wptr - (u_char *)ip; if (ip->ip_v != IPVERSION) { m->b_rptr -= off; if (!synced) { synced = 1; ipfsync(); goto tryagain; } fr_donotip(out, qif, q, m, mt, ip, off); frstats[out].fr_notip++; return (fr_flags & FF_BLOCKNONIP) ? -1 : 0; } hlen = iphlen = ip->ip_hl << 2; /* * Make hlen the total size of the IP header plus TCP/UDP/ICMP header * (if it is one of these three). */ if (!(ip->ip_off & 0x1fff)) switch (ip->ip_p) { case IPPROTO_TCP : hlen += sizeof(tcphdr_t); break; case IPPROTO_UDP : hlen += sizeof(udphdr_t); break; case IPPROTO_ICMP : hlen += sizeof(icmphdr_t); break; default : break; } /* * If we don't have enough data in the mblk or we haven't yet copied * enough (above), then copy some more. */ if ((hlen > len)) { len = MIN(hlen, sizeof(lbuf)); len = MIN(mlen, len); - copyout_mblk(m, 0, lbuf, len); + copyout_mblk(m, 0, (char *)lbuf, len); frstats[out].fr_pull[0]++; ip = (ip_t *)lbuf; } #ifndef sparc __iplen = ip->ip_len; ip->ip_len = ntohs(__iplen); __ipoff = ip->ip_off; ip->ip_off = ntohs(__ipoff); #endif if ((iphlen < sizeof(ip_t)) || (iphlen > (u_short)ip->ip_len) || (mlen < (u_short)ip->ip_len)) { /* * Bad IP packet or not enough data/data length mismatches */ m->b_rptr -= off; frstats[out].fr_bad++; return -1; } qif->qf_m = m; qif->qf_len = len; - err = fr_check(ip, iphlen, qif->qf_ill, out, qif, q, mp); + err = fr_check(ip, iphlen, (struct ifnet *)qif->qf_ill, out, qif, + q, mp); /* * Copy back the ip header data if it was changed, we haven't yet * freed the message and we aren't going to drop the packet. */ #ifndef sparc if (*mp) { ip->ip_len = __iplen; ip->ip_off = __ipoff; } #endif if (err == 1) { if (*mp && (ip == (ip_t *)lbuf)) { - copyin_mblk(m, 0, lbuf, len); + copyin_mblk(m, 0, (char *)lbuf, len); frstats[out].fr_pull[1]++; } err = 0; } m->b_rptr -= off; return err; } -int fr_qin(q, mb) +static int fr_qin(q, mb) queue_t *q; mblk_t *mb; { - int (*pnext)(), type, synced = 0; + int (*pnext) __P((queue_t *, mblk_t *)), type, synced = 0; qif_t qfb, *qif; again: mutex_enter(&ipfs_mutex); while (!(qif = qif_from_queue(q))) { for (qif = qif_head; qif; qif = qif->qf_next) if (qif->qf_rqinfo == q->q_qinfo && qif->qf_inp) { pnext = qif->qf_inp; mutex_exit(&ipfs_mutex); frstats[0].fr_notip++; if (!synced) { ipfsync(); synced = 1; goto again; } /* fr_donotip(0, NULL, q, mb, mb, NULL, 0); */ return (*pnext)(q, mb); } mutex_exit(&ipfs_mutex); if (!synced) { ipfsync(); synced = 1; goto again; } cmn_err(CE_WARN, "IP Filter: dropped: fr_qin(%x,%x): type %x qif %x", q, mb, MTYPE(mb), qif); cmn_err(CE_CONT, "info %x next %x ptr %x fsrv %x bsrv %x\n", q->q_qinfo, q->q_next, q->q_ptr, q->q_nfsrv, q->q_nbsrv); cmn_err(CE_CONT, "IP Filter: info: putp %x srvp %x info %x\n", q->q_qinfo->qi_putp, q->q_qinfo->qi_srvp, q->q_qinfo->qi_infop); frstats[0].fr_drop++; freemsg(mb); return 0; } /* * So we can be more re-entrant. */ bcopy((char *)qif, (char *)&qfb, sizeof(*qif)); mutex_exit(&ipfs_mutex); qif = &qfb; pnext = qif->qf_inp; type = MTYPE(mb); if (type == M_DATA || type == M_PROTO || type == M_PCPROTO) if (fr_precheck(&mb, q, qif, 0)) { if (mb) freemsg(mb); return 0; } if (mb) { if (pnext) return (*pnext)(q, mb); cmn_err(CE_WARN, "IP Filter: inp NULL: qif %x %s q %x info %x", qif, qif->qf_name, q, q->q_qinfo); freemsg(mb); } return 0; } -int fr_qout(q, mb) +static int fr_qout(q, mb) queue_t *q; mblk_t *mb; { - int (*pnext)(), type, synced = 0; + int (*pnext) __P((queue_t *, mblk_t *)), type, synced = 0; qif_t qfb, *qif; again: mutex_enter(&ipfs_mutex); if (!(qif = qif_from_queue(q))) { for (qif = qif_head; qif; qif = qif->qf_next) if (qif->qf_wqinfo == q->q_qinfo && qif->qf_outp) { pnext = qif->qf_outp; mutex_exit(&ipfs_mutex); frstats[1].fr_notip++; if (!synced) { ipfsync(); synced = 1; goto again; } /* fr_donotip(0, NULL, q, mb, mb, NULL, 0); */ return (*pnext)(q, mb); } mutex_exit(&ipfs_mutex); if (!synced) { ipfsync(); synced = 1; goto again; } cmn_err(CE_WARN, "IP Filter: dropped: fr_qout(%x,%x): type %x: qif %x", q, mb, MTYPE(mb), qif); cmn_err(CE_CONT, "info %x next %x ptr %x fsrv %x bsrv %x\n", q->q_qinfo, q->q_next, q->q_ptr, q->q_nfsrv, q->q_nbsrv); cmn_err(CE_CONT, "IP Filter: info: putp %x srvp %x info %x\n", q->q_qinfo->qi_putp, q->q_qinfo->qi_srvp, q->q_qinfo->qi_infop); if (q->q_nfsrv) cmn_err(CE_CONT, "nfsrv: info %x next %x ptr %x\n", q->q_nfsrv->q_qinfo, q->q_nfsrv->q_next, q->q_nfsrv->q_ptr); if (q->q_nbsrv) cmn_err(CE_CONT, "nbsrv: info %x next %x ptr %x\n", q->q_nbsrv->q_qinfo, q->q_nbsrv->q_next, q->q_nbsrv->q_ptr); frstats[1].fr_drop++; freemsg(mb); return 0; } /* * So we can be more re-entrant. */ bcopy((char *)qif, (char *)&qfb, sizeof(*qif)); mutex_exit(&ipfs_mutex); qif = &qfb; pnext = qif->qf_outp; type = MTYPE(mb); if (type == M_DATA || type == M_PROTO || type == M_PCPROTO) if (fr_precheck(&mb, q, qif, 1)) { if (mb) freemsg(mb); return 0; } if (mb) { if (pnext) return (*pnext)(q, mb); cmn_err(CE_WARN, "IP Filter: outp NULL: qif %x %s q %x info %x", qif, qif->qf_name, q, q->q_qinfo); freemsg(mb); } return 0; } /* * attach the packet filter to each interface that is defined as having an * IP address associated with it and save some of the info. for that struct * so we're not out of date as soon as te ill disappears - but we must sync * to be correct! */ int solattach() { queue_t *in, *out; qif_t *qif, *qf2; ill_t *il; for (il = ill_g_head; il; il = il->ill_next) { in = il->ill_rq; if (!in || !il->ill_wq) continue; out = il->ill_wq->q_next; mutex_enter(&ipfs_mutex); /* * Look for entry already setup for this device */ for (qif = qif_head; qif; qif = qif->qf_next) if (qif->qf_iptr == in->q_ptr && qif->qf_optr == out->q_ptr) break; if (qif) { mutex_exit(&ipfs_mutex); continue; } #ifdef IPFDEBUG cmn_err(CE_NOTE, "IP Filter: il %x ipt %x opt %x ipu %x opu %x i %x/%x", il, in->q_ptr, out->q_ptr, in->q_qinfo->qi_putp, out->q_qinfo->qi_putp, out->q_qinfo, in->q_qinfo); #endif - qif = (qif_t *)KMALLOC(sizeof(*qif)); + KMALLOC(qif, qif_t *, sizeof(*qif)); if (in->q_qinfo->qi_putp == fr_qin) { for (qf2 = qif_head; qf2; qf2 = qf2->qf_next) if (qf2->qf_rqinfo == in->q_qinfo) { qif->qf_inp = qf2->qf_inp; break; } if (!qf2) { #ifdef IPFDEBUG cmn_err(CE_WARN, "IP Filter: rq:%s put %x qi %x", il->ill_name, in->q_qinfo->qi_putp, in->q_qinfo); #endif mutex_exit(&ipfs_mutex); KFREE(qif); continue; } } else qif->qf_inp = in->q_qinfo->qi_putp; if (out->q_qinfo->qi_putp == fr_qout) { for (qf2 = qif_head; qf2; qf2 = qf2->qf_next) if (qf2->qf_wqinfo == out->q_qinfo) { qif->qf_outp = qf2->qf_outp; break; } if (!qf2) { #ifdef IPFDEBUG cmn_err(CE_WARN, "IP Filter: wq:%s put %x qi %x", il->ill_name, out->q_qinfo->qi_putp, out->q_qinfo); #endif mutex_exit(&ipfs_mutex); KFREE(qif); continue; } } else qif->qf_outp = out->q_qinfo->qi_putp; qif->qf_ill = il; qif->qf_iptr = in->q_ptr; qif->qf_optr = out->q_ptr; qif->qf_hl = il->ill_hdr_length; strncpy(qif->qf_name, il->ill_name, sizeof(qif->qf_name)); qif->qf_name[sizeof(qif->qf_name) - 1] = '\0'; qif->qf_wqinfo = out->q_qinfo; qif->qf_rqinfo = in->q_qinfo; qif->qf_next = qif_head; qif_head = qif; in->q_qinfo->qi_putp = fr_qin; out->q_qinfo->qi_putp = fr_qout; mutex_exit(&ipfs_mutex); cmn_err(CE_CONT, "IP Filter: attach to [%s,%d]\n", qif->qf_name, il->ill_ppa); } if (!qif_head) { cmn_err(CE_CONT, "IP Filter: not attached to any interfaces\n"); return -1; } return 0; } /* * look for bad consistancies between the list of interfaces the filter knows * about and those which are currently configured. */ int ipfsync() { register struct frentry *f, **fp; register qif_t *qif, **qp; register ill_t *il; mutex_enter(&ipfs_mutex); for (qp = &qif_head; (qif = *qp); ) { for (il = ill_g_head; il; il = il->ill_next) if ((qif->qf_ill == il) && !strcmp(qif->qf_name, il->ill_name)) { mblk_t *m = il->ill_hdr_mp; qif->qf_hl = il->ill_hdr_length; if (m && qif->qf_hl != (m->b_wptr - m->b_rptr)) printf("ILL Header Length Mismatch\n"); break; } if (il) { qp = &qif->qf_next; continue; } cmn_err(CE_CONT, "IP Filter: detaching [%s]\n", qif->qf_name); *qp = qif->qf_next; /* * Delete any rules directly associated with this interface */ mutex_enter(&ipf_mutex); for (fp = &ipfilter[0][0]; (f = *fp); ) if ((void *)f->fr_ifa == (void *)qif->qf_ill) { *fp = f->fr_next; KFREE(f); } else fp = &f->fr_next; for (fp = &ipfilter[1][0]; (f = *fp); ) if ((void *)f->fr_ifa == (void *)qif->qf_ill) { *fp = f->fr_next; KFREE(f); } else fp = &f->fr_next; mutex_exit(&ipf_mutex); KFREE(qif); qif = *qp; } mutex_exit(&ipfs_mutex); return solattach(); } /* * unhook the IP filter from all defined interfaces with IP addresses */ int soldetach() { queue_t *in, *out; qif_t *qif, *qf2, **qp; ill_t *il; mutex_enter(&ipfs_mutex); /* * Make two passes, first get rid of all the unknown devices, next * unlink known devices. */ for (qp = &qif_head; (qif = *qp); ) { for (il = ill_g_head; il; il = il->ill_next) if (qif->qf_ill == il) break; if (il) { qp = &qif->qf_next; continue; } cmn_err(CE_CONT, "IP Filter: removing [%s]\n", qif->qf_name); *qp = qif->qf_next; KFREE(qif); } while ((qif = qif_head)) { qif_head = qif->qf_next; for (il = ill_g_head; il; il = il->ill_next) if (qif->qf_ill == il) break; if (il) { in = il->ill_rq; out = il->ill_wq->q_next; printf("IP Filter: detaching [%s,%d]\n", qif->qf_name, il->ill_ppa); in->q_qinfo->qi_putp = qif->qf_inp; /* * and change back if something is still interested * in filtering (read side) on this interface. */ for (qf2 = qif_head; qf2; qf2 = qf2->qf_next) if (qf2->qf_rqinfo == in->q_qinfo) { in->q_qinfo->qi_putp = fr_qin; break; } /* * and the write queue... */ out->q_qinfo->qi_putp = qif->qf_outp; for (qf2 = qif_head; qf2; qf2 = qf2->qf_next) if (qf2->qf_wqinfo == out->q_qinfo) { out->q_qinfo->qi_putp = fr_qout; break; } } KFREE(qif); } mutex_exit(&ipfs_mutex); return ipldetach(); } -printire(ire) +void printire(ire) ire_t *ire; { printf("ire: ll_hdr_mp %x rfq %x stq %x src_addr %x max_frag %d\n", ire->ire_ll_hdr_mp, ire->ire_rfq, ire->ire_stq, ire->ire_src_addr, ire->ire_max_frag); printf("ire: mask %x addr %x gateway_addr %x type %d\n", ire->ire_mask, ire->ire_addr, ire->ire_gateway_addr, ire->ire_type); printf("ire: ll_hdr_length %d ll_hdr_saved_mp %x\n", ire->ire_ll_hdr_length, ire->ire_ll_hdr_saved_mp); } int ipfr_fastroute(qf, ip, mb, mpp, fin, fdp) qif_t *qf; ip_t *ip; mblk_t *mb, **mpp; fr_info_t *fin; frdest_t *fdp; { mblk_t *mp = NULL; struct in_addr dst; ire_t *ir, *dir; int hlen = 0; u_char *s; queue_t *q = NULL; #ifndef sparc u_short __iplen, __ipoff; /* * If this is a duplicate mblk then we want ip to point at that * data, not the original, if and only if it is already pointing at * the current mblk data. */ if (ip == (ip_t *)qf->qf_m->b_rptr && qf->qf_m != mb) ip = (ip_t *)mb->b_rptr; /* * In fr_precheck(), we modify ip_len and ip_off in an aligned data * area. However, we only need to change it back if we didn't copy * the IP header data out. */ __iplen = (u_short)ip->ip_len, __ipoff = (u_short)ip->ip_off; ip->ip_len = htons(__iplen); ip->ip_off = htons(__ipoff); #endif if (ip != (ip_t *)mb->b_rptr) { - copyin_mblk(mb, 0, ip, qf->qf_len); + copyin_mblk(mb, 0, (char *)ip, qf->qf_len); frstats[fin->fin_out].fr_pull[1]++; } /* * If there is another M_PROTO, we don't want it */ if (*mpp != mb) { (*mpp)->b_cont = NULL; freemsg(*mpp); } ir = (ire_t *)fdp->fd_ifp; if (fdp->fd_ip.s_addr) dst = fdp->fd_ip; else dst = fin->fin_fi.fi_dst; if (dir = ire_lookup(dst.s_addr)) if (!dir->ire_ll_hdr_mp || !dir->ire_ll_hdr_length) dir = NULL; if (!ir) ir = dir; if (ir && dir) { if ((mp = dir->ire_ll_hdr_mp)) { hlen = dir->ire_ll_hdr_length; s = mb->b_rptr; if (hlen && (s - mb->b_datap->db_base) >= hlen) { s -= hlen; mb->b_rptr = (u_char *)s; bcopy((char *)mp->b_rptr, (char *)s, hlen); } else { mblk_t *mp2; mp2 = copyb(mp); if (!mp2) goto bad_fastroute; mp2->b_cont = mb; mb = mp2; } } if (ir->ire_stq) q = ir->ire_stq; else if (ir->ire_rfq) q = WR(ir->ire_rfq); if (q) { putnext(q, mb); return 0; } } bad_fastroute: return -1; } void copyout_mblk(m, off, buf, len) mblk_t *m; int off, len; char *buf; { char *s, *bp = buf; int mlen, olen, clen; for (; m && len; m = m->b_cont) { if (MTYPE(m) != M_DATA) continue; s = m->b_rptr; mlen = (char *)m->b_wptr - s; olen = MIN(off, mlen); if ((olen == mlen) || (olen < off)) { off -= olen; continue; } else if (olen) { off -= olen; s += olen; mlen -= olen; } clen = MIN(mlen, len); bcopy(s, bp, clen); len -= clen; bp += clen; } } void copyin_mblk(m, off, buf, len) mblk_t *m; int off, len; char *buf; { char *s, *bp = buf; int mlen, olen, clen; for (; m && len; m = m->b_cont) { if (MTYPE(m) != M_DATA) continue; s = m->b_rptr; mlen = (char *)m->b_wptr - s; olen = MIN(off, mlen); if ((olen == mlen) || (olen < off)) { off -= olen; continue; } else if (olen) { off -= olen; s += olen; mlen -= olen; } clen = MIN(mlen, len); bcopy(bp, s, clen); len -= clen; bp += clen; } } diff --git a/contrib/ipfilter/test/expected/expected.sed b/contrib/ipfilter/test/expected/expected.sed new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/contrib/ipfilter/test/input/input.sed b/contrib/ipfilter/test/input/input.sed new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/contrib/ipfilter/test/regress/regress.sed b/contrib/ipfilter/test/regress/regress.sed new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/contrib/ipfilter/test/test.sed b/contrib/ipfilter/test/test.sed new file mode 100644 index 000000000000..3ce0cb16415e --- /dev/null +++ b/contrib/ipfilter/test/test.sed @@ -0,0 +1,6 @@ + Ç . Ä..0þ CVSGexpected0ÇinputDG$regress +  +.cvsignore +!Makefile +"dotest +#hextest diff --git a/contrib/ipfilter/todo b/contrib/ipfilter/todo index f1664c02c0f5..3914bef42457 100644 --- a/contrib/ipfilter/todo +++ b/contrib/ipfilter/todo @@ -1,19 +1,27 @@ * automatically use the interface's IP# for NAT rather than any specific IP# + - Done. Use "0/32" as destination address/mask. Uses first interface IP# + set for an interface. * use fr_tcpstate() with NAT code for increased NAT usage security or even fr_checkstate() * use minor devices for controlling access to alternate parts of IP Filter such as filtering, accounting, state, NAT, etc. * see if the Solaris2 and dynamic plumb/unplumb problem is solvable time permitting: * load balancing across interfaces * record buffering for TCP/UDP * modular application proxying * invesitgate making logging better + +* add reverse nat (similar to rdr) to map addresses going in both directions + +* add 'tail' switch to ipmon + (this might just be some changes to rdr). In 1:1 relationships maybe make + it an option.