*** dp_if.c.old	Fri Sep  2 23:28:00 1994
--- dp_if.c	Tue Oct  4 01:30:17 1994
***************
*** 648,653 ****
--- 648,1405 ----
      }
  }
  
+ #define	INFILT  1
+ 
+ /* 
+  *
+ 
+ infilt-0.5 -- Anti-copyright (A) 1994 Henry Strickland 
+ 			<strick@yak.net>
+ 			<strick@netcom.com>
+ 
+ This package (named infilt-0.5) is a patch to the file dp_if.c 
+ in the dp-2.3 DialupPPP package.  It adds "firewall-style" 
+ packet filtering for a host using a "dp" interface to connect 
+ it to the internet.
+ 
+ The filter will drop incoming packets considered dangerous.  The
+ packets are dropped after they are shown to the Network Interface Tap
+ ("nit" or "snit") but before they are queued as IP packets to the
+ operating system.  Thus "tcpdump" will still see the packets (it reads
+ them on "snit"), but they will not be processed any further (they 
+ will not be delivered to programs on this host, or forwarded to
+ other hosts.)
+ 
+ Packets leaving the host through the "dp" interface are unaffected.
+ This package does the same filtering regardless of the source and
+ destination IP addresses of the packets, and regardless of which dp%d
+ interface they are arriving on.
+ 
+ New functionality:  TCP window and mss clamping.  Both ingoing
+ and outcoming TCP packets will have their TCP "window" slot and
+ "mss" option reduced if they exceed configurable values
+ infilt_tcp_mss_max and infilt_tcp_window_max.
+ 
+ I place these diffs in the public domain.  
+ Remember that other copyrights apply to the original dp-2.3 source.
+ 
+ BECAUSE THE PROGRAM IS AVAILBLE FREE OF CHARGE, THERE IS NO
+ WARRANTY FOR THE PROGRAM.  See "infile.doc" for more information.
+ 
+ 
+  *
+  */
+ 
+ #ifdef INFILT
+ 
+ #include <netinet/ip_icmp.h>
+ #include <netinet/udp.h>
+ #include <netinet/tcp.h>
+ 
+ #define	INFILT_LIST_LEN	99
+ 
+ #define	INFILT_OK	0
+ #define	INFILT_DROP	1
+ #define	INFILT_DEAD	2
+ 
+ 
+ int     infilt_enable=1;   /* 0 to turn the whole infilt thing off */
+ int     infilt_debug=2;   /* 1 is normal, 2 prints zapped packets, more for debugging */
+ 
+ int     infilt_clear_options=1;
+ int     infilt_kill_options=1;
+ 
+ int	infilt_udp_dport_min= 65536;	/* drop UDP packets to port smaller than this */
+ int	infilt_tcp_dport_min= 65536;	/* drop TCP packets to port smaller than this */
+ 
+ int	infilt_tcp_mss_max= 65536;  	/* by default dont change MSS */
+ int	infilt_tcp_window_max= 65536;	/* by default dont change window */
+ 
+ int	infilt_tcp_no_window_max[INFILT_LIST_LEN];	/* do not enforce tcp_window_max on these ports */
+ 
+ int	infilt_icmp_type_zap[INFILT_LIST_LEN];	/* drop ICMP packets of these types */
+ 
+ int	infilt_udp_dport_ok[INFILT_LIST_LEN];	/* exceptions < dport_min */
+ int	infilt_udp_dport_zap[INFILT_LIST_LEN];	/* exceptions >= dport_min */
+ 
+ int	infilt_tcp_dport_ok[INFILT_LIST_LEN];	/* exceptions < dport_min */
+ int	infilt_tcp_dport_zap[INFILT_LIST_LEN];	/* exceptions >= dport_min */
+ 
+ #define INFILT_LOG0   if ( 1                 ) log
+ #define INFILT_LOG1   if ( infilt_debug      ) log
+ #define INFILT_LOG2   if ( infilt_debug >= 2 ) log
+ #define INFILT_LOG3   if ( infilt_debug >= 3 ) log
+ #define INFILT_LOG8   if ( infilt_debug >= 8 ) log
+ 
+ #define	IP_SRC_ADDR \
+ 	255&((unsigned char*)(&ip->ip_src.s_addr))[0], \
+ 	255&((unsigned char*)(&ip->ip_src.s_addr))[1], \
+ 	255&((unsigned char*)(&ip->ip_src.s_addr))[2], \
+ 	255&((unsigned char*)(&ip->ip_src.s_addr))[3]
+ #define	IP_DST_ADDR \
+ 	255&((unsigned char*)(&ip->ip_dst.s_addr))[0], \
+ 	255&((unsigned char*)(&ip->ip_dst.s_addr))[1], \
+ 	255&((unsigned char*)(&ip->ip_dst.s_addr))[2], \
+ 	255&((unsigned char*)(&ip->ip_dst.s_addr))[3]
+ 
+ 
+ #define	PPP_OVERHEAD sizeof(struct ppp_header)
+ #define MP (*mbuf_ptr)
+ 
+ char infilt_hexchar[] = "0123456789abcdef";
+ 
+ void
+ infilt_print_mbuf(p,s)
+   struct mbuf* p;
+   char* s;
+ {
+   char buf[99];
+   int i, j, k;
+   while (p) {
+     INFILT_LOG2(LOG_DEBUG, "infilt_print_mbuf: ---- off=%d len=%d t=%d ---- %s\n",  
+ 			p->m_off, p->m_len, p->m_type, s );
+ 
+     for ( i=0; i<p->m_len; i+=32 ) {
+ 	k= 0;
+ 	buf[k++]= '=';
+ 	buf[k++]= '=';
+ 	buf[k++]= ' ';
+ 	for ( j=0; j<32; j++ ) {
+ 		if ( i+j >= p->m_len ) break;
+ 		buf[k++]= infilt_hexchar[ 15 & ((mtod(p,char*) [i+j])>>4) ];
+ 		buf[k++]= infilt_hexchar[ 15 & ((mtod(p,char*) [i+j])>>0) ];
+ 		if ( (j&3)==3 ) buf[k++]= ' ';
+ 		if ( (j&15)==15 ) buf[k++]= ' ';
+ 	}
+ 	buf[k++]= '\n';
+ 	buf[k++]= '\0';
+ 	INFILT_LOG2(LOG_DEBUG, buf);
+     }
+     s="--";
+     p= p->m_next;
+   }
+   INFILT_LOG2(LOG_DEBUG, "---------------\n");
+ }
+ 
+ 
+ 
+ #define	INFILT_TCP_CANNOT_CHECKSUM 0xFFFFFFFF
+ 
+   unsigned long
+ infilt_tcp_checksum(mp, overhead)
+   struct mbuf* mp;
+   int overhead;
+ {
+     /*
+      *  this cannot be called on fragmented packets,
+      *  becasue the entire tcp data is not there to be checksummed, duh. 
+      */
+     struct mbuf* orig_mp= mp;
+     long ip_size= mp->m_len - overhead;
+     struct ip* ip= (struct ip*) (mtod(mp, u_char*)+overhead);
+     struct tcphdr* tcp= (struct tcphdr*) ((long*)ip+ip->ip_hl);
+     unsigned short* usp= (unsigned short*)NULL;
+     unsigned long check= 0;
+     unsigned long hold_check_field= tcp->th_sum;
+     unsigned long tcp_length= 0;
+     unsigned long before_tcp= 0; /* bytes before TCP header */
+     long i=0, j=0;
+     int k=0;
+     unsigned char* bytep= (unsigned char*)NULL;
+ 
+     /* quick hack: ignore size checks and pullups */
+ 
+     /* first sum the pseudo header:
+                      +--------+--------+--------+--------+
+                      |           Source Address          |
+                      +--------+--------+--------+--------+
+                      |         Destination Address       |
+                      +--------+--------+--------+--------+
+                      |  zero  |  PTCL  |    TCP Length   |
+                      +--------+--------+--------+--------+
+     */
+ 
+     /* tcp_length = IP_LEN - ip-header-size. */
+     before_tcp= (u_char*)tcp - mtod(mp, u_char*);
+     tcp_length = ( (unsigned) ip->ip_len - 4*ip->ip_hl);
+ 
+     /* ohno: use the big endian assumption! */ 
+     check += 0xFFFF & ((unsigned short*)(&ip->ip_src))[0];
+     check += 0xFFFF & ((unsigned short*)(&ip->ip_src))[1];
+     check += 0xFFFF & ((unsigned short*)(&ip->ip_dst))[0];
+     check += 0xFFFF & ((unsigned short*)(&ip->ip_dst))[1];
+     check += 0x00FF & ip->ip_p;
+     check += 0xFFFF & tcp_length;
+ 
+     /* now the TCP stuff */
+ 
+     /* let i count how many bytes remain in this chunk */
+     /* let j count how many more data bytes are required */
+     /* let bytep point to the bytes */  
+     /* let k be 0 on even, or 1 on odd */
+ 
+     j= tcp_length;
+     i= mp->m_len - before_tcp;
+     k= 0;
+     bytep= (unsigned char*)tcp;
+     tcp->th_sum= 0; /* temporarily */
+     while (j) {
+ 	if (i==0) {
+ 		if (mp->m_next) {
+ 			mp= mp->m_next;
+ 			i= mp->m_len;
+ 			bytep= mtod(mp, u_char*);
+ 		} else {
+ 			INFILT_LOG0(LOG_ERR, "infilt_tcp_checksum: exhausted mp");
+     			tcp->th_sum= hold_check_field; /* restore */
+ 			return INFILT_TCP_CANNOT_CHECKSUM;
+ 		}
+ 	}
+ 	if (i==0) {
+ 			INFILT_LOG0(LOG_ERR, "infilt_tcp_checksum: double i==0");
+     			tcp->th_sum= hold_check_field; /* restore */
+ 			return INFILT_TCP_CANNOT_CHECKSUM;
+ 	}
+ 	if (k) {
+ 		check += (*bytep++);
+ 		k= 0;
+ 	} else {
+ 		check += (*bytep++)<<8;
+ 		k= 1;
+ 	}
+ 	--j;
+ 	--i;
+     }
+     tcp->th_sum= hold_check_field; /* restore */
+ 
+     check = (check&0xFFFF) + ((check>>16)&0xFFFF);  /* add in the carry */
+     check = (check&0xFFFF) + ((check>>16)&0xFFFF);  /* add in the carry */
+     check = (check&0xFFFF) + ((check>>16)&0xFFFF);  /* add the carry dammit */
+ 
+     check = ~check;                 /* ones comp */
+     check &= 0xFFFF;                /* mask to short */
+ 
+     return check;
+ }
+ 
+   void
+ infilt_tcp_clamp(mbuf_ptr, overhead)
+   struct mbuf** mbuf_ptr;
+   int overhead;
+ {
+     /*
+      *  clamp the WINDOW and MSS values to some maximum value.
+      * 
+      *  this cannot be called on fragmented packets,
+      *  becasue the entire tcp data is not there to be checksummed, duh. 
+      */
+     struct ip* ip= (struct ip*)NULL;
+     struct tcphdr* tcp= (struct tcphdr*)NULL;
+ 
+     unsigned long check= 0;
+     int needs_new_checksum= 0;
+ 
+     unsigned long total_length= 0;	/* sum of all mbuf lengths */
+     unsigned long min_length= 0;	/* cannot work without this much */
+     unsigned long target_length= 0; 	/* covers most cases */
+     struct mbuf* tmp= MP;
+     int i=0;
+ 
+     if ( !infilt_enable ) return;    /* the big red switch */
+ 
+     /* calculate total_length of all mbufs */
+     while (tmp) {
+ 	total_length += tmp->m_len;
+ 	tmp= tmp->m_next;
+     }
+ 
+     /***************************************************************/
+     /***************************************************************/
+ 
+     min_length= overhead + 5*4 /*IP*/ + 5*4 /*TCP*/;
+     if ( total_length < min_length ) return;  /* too short to bother */
+ 
+     target_length= min_length + 1*4 /* one tcp option word */;
+     if ( total_length < target_length ) target_length= total_length;
+ 
+     if ( MP->m_len < target_length ) {
+ 	MP= (m_pullup(MP, target_length ));
+ 	if (!MP) {
+ 			INFILT_LOG0(LOG_WARNING,
+                         "infilt_tcp: TRAGIC: cannot m_pullup %d", 
+ 			target_length
+                 	);
+ 	   return;
+ 	}
+     }
+ 
+     /* now that we have an IP header, check for TCP packet */
+ 
+     ip= (struct ip*) (mtod(MP, u_char*)+overhead);
+ 
+     if ( ip->ip_v != IPVERSION /*4*/ ) return;   /* not IP */
+     if ( ip->ip_hl < 5 ) return;   /* not big enuf */
+     if ( ip->ip_off&0x2FFF ) return;	/* cannot change fragments */
+     if ( ip->ip_p != IPPROTO_TCP /*6*/ ) return; /* not tcp */
+ 
+     /***************************************************************/
+ 
+     /* in most cases, that should do it.  But in case of other
+      *   IP options, try now to make it bigger.
+      */
+ 
+     min_length= overhead + 4*ip->ip_hl + 5*4 /*TCP*/;
+ 
+     if ( total_length < min_length ) return;  /* too short to bother */
+ 
+     target_length= min_length + 1*4 /* one tcp option word */;
+     if ( total_length < target_length ) target_length= total_length;
+ 
+     if ( MP->m_len < target_length ) {
+ 	MP= (m_pullup(MP, target_length ));
+ 	if (!MP) {
+ 			INFILT_LOG0(LOG_WARNING,
+                         "infilt_tcp: TRAGIC 2: cannot m_pullup %d", 
+ 			target_length
+                 	);
+ 	   return;
+ 	}
+     }
+ 
+     /***************************************************************/
+ 
+     ip= (struct ip*) (mtod(MP, u_char*)+overhead);
+     tcp= (struct tcphdr*) ((long*)ip+ip->ip_hl);
+ 
+     /* we're not going to repeat that again -- 
+      *  instead we assume that MSS option comes first.
+      */
+ 
+     /***************************************************************/
+     /***************************************************************/
+ 
+     check = infilt_tcp_checksum(MP, overhead);
+ 
+     if ( check == INFILT_TCP_CANNOT_CHECKSUM ) {
+ 			INFILT_LOG1(LOG_NOTICE,
+                     	"infilt_tcp_clamp: cannot checksum... %d\n",
+ 			tcp->th_sum
+ 			);
+ 			infilt_print_mbuf(MP, "infilt_tcp_clamp");
+ 	return;
+     }
+ 
+     if ( tcp->th_win > infilt_tcp_window_max ) {
+ 
+ 	/* look for exception ports, that have no window max */
+ 
+ 	for ( i=0; infilt_tcp_no_window_max[i]; i++ ) {
+ 		if ( tcp->th_dport == infilt_tcp_no_window_max[i] ) break;
+ 		if ( tcp->th_sport == infilt_tcp_no_window_max[i] ) break;
+ 	}
+ 
+ 	/* if we broke, infilt_tcp_no_window_max[i] is nonzero */
+ 	/* if infilt_tcp_no_window_max[i] is zero, we want to fix it */
+ 
+ 	if ( ! infilt_tcp_no_window_max[i] ) {
+ 
+ 			INFILT_LOG3(LOG_NOTICE,
+                     	"infilt_tcp_clamp: CHANGING th_win from %d to %d / %x(%d)>%x(%d)\n",
+ 			tcp->th_win, infilt_tcp_window_max,
+ 			ip->ip_src, tcp->th_sport, ip->ip_dst, tcp->th_dport
+ 			);
+ 		tcp->th_win= infilt_tcp_window_max;
+ 		needs_new_checksum= 1;
+ 	}
+     }
+ 
+ 
+     if ( tcp->th_off > 5 ) {
+ 
+ 	/* has TCP options...
+ 	 * MSS (2) should be the first option, 
+ 	 *  at offset 20, length 4,
+ 	 *  since it's the only useful option 
+ 	 */
+ 
+ 	unsigned char* cp= (unsigned char*) tcp; 
+ 	if ( cp[20]==2 && cp[21]==4 ) {
+ 	    unsigned long the_mss= (cp[22]<<8) + cp[23];
+ 	    if ( the_mss > infilt_tcp_mss_max ) {
+ 
+ 			INFILT_LOG3(LOG_NOTICE,
+                     	"infilt_tcp_clamp: CHANGING tcp MSS from %d to %d / %x(%d)->%x(%d)\n",
+ 			the_mss, infilt_tcp_mss_max,
+ 			ip->ip_src, tcp->th_sport, ip->ip_dst, tcp->th_dport
+ 			);
+ 
+ 		cp[22]= infilt_tcp_mss_max>>8;
+ 		cp[23]= infilt_tcp_mss_max;
+ 		needs_new_checksum= 1;
+ 	    }
+ 	}
+     }
+ 
+     if ( needs_new_checksum ) {
+ 	tcp->th_sum= infilt_tcp_checksum(MP, overhead);
+     }
+ 
+     return;
+ }
+ 
+ int  /* return INFILT_DROP to drop, INFILT_OK to keep */
+ infilt_tcp(mbuf_ptr)
+   struct mbuf** mbuf_ptr;
+ {
+     long ip_size= MP->m_len - PPP_OVERHEAD; 
+     struct ip* ip= (struct ip*) (mtod(MP, u_char*)+PPP_OVERHEAD);
+     struct tcphdr* tcp= (struct tcphdr*) ((long*)ip+ip->ip_hl);
+     int* p;
+ 
+ 
+     if ( ip_size < ip->ip_hl*4 + sizeof *tcp ) {
+ 	   		INFILT_LOG1(LOG_NOTICE, 
+ 			"infilt_tcp: %d.%d.%d.%d -> %d.%d.%d.%d m_pullup %d %d\n", 
+ 			IP_SRC_ADDR, IP_DST_ADDR, ip_size, ip->ip_hl*4 + sizeof *tcp 
+ 			);
+ 			infilt_print_mbuf(*mbuf_ptr, "infilt_tcp before pullup" );
+ 	MP= (m_pullup(MP, ip->ip_hl*4 + sizeof *tcp + PPP_OVERHEAD));
+ 	if (!MP) {
+ 		/*
+ 		 *   if cannot pullup ... is it already freed?
+ 		 *       it seems so....
+ 		 */
+ 			INFILT_LOG0(LOG_WARNING, 
+ 			"infilt_tcp: cannot m_pullup %d",
+ 			ip->ip_hl*4 + sizeof *tcp + PPP_OVERHEAD
+ 			);
+ 		return INFILT_DEAD;
+ 	}
+ 			infilt_print_mbuf(*mbuf_ptr, "infilt_tcp after pullup" );
+ 	ip_size= MP->m_len - PPP_OVERHEAD;
+ 	ip= (struct ip*) (mtod(MP, u_char*)+PPP_OVERHEAD);
+ 	tcp= (struct tcphdr*) ((long*)ip+ip->ip_hl);
+     }
+ 
+     if ( ip_size < ip->ip_hl*4 + sizeof *tcp  ) {
+ 			INFILT_LOG0(LOG_ERR, 
+ 			"infilt_tcp: %d.%d.%d.%d -> %d.%d.%d.%d NOTREACHED ip_size %d\n", 
+ 			IP_SRC_ADDR, IP_DST_ADDR, ip_size
+ 			);
+ 	/* drop tiny packets here,
+ 	 *   so that packets cannot evade inspection by being
+ 	 *   fragmented with a tiny first frament
+ 	 */
+ 	return INFILT_DROP;
+     } else { 
+ 
+     infilt_tcp_clamp(mbuf_ptr, PPP_OVERHEAD);
+ 
+        if ( tcp->th_dport >= infilt_tcp_dport_min ) {
+ 	   /* meets minimum -- pass unless zapped */
+ 	   for ( p=infilt_tcp_dport_zap; *p; p++ ) {
+ 		if ( *p == tcp->th_dport ) {
+ 		    	INFILT_LOG1(LOG_NOTICE, 
+ 			"infilt_tcp: %d.%d.%d.%d -> %d.%d.%d.%d zap %d\n", 
+ 			IP_SRC_ADDR, IP_DST_ADDR, tcp->th_dport 
+ 			);
+ 		    return INFILT_DROP;
+ 		}
+ 	   }
+ 	} else {
+ 	   /* below minimum -- drop unless ok */
+ 	   for ( p=infilt_tcp_dport_ok; *p; p++ ) {
+ 		if ( *p == tcp->th_dport ) {
+ 		    	INFILT_LOG8(LOG_DEBUG, 
+ 			"infilt_tcp: %d.%d.%d.%d -> %d.%d.%d.%d ok %d\n", 
+ 			IP_SRC_ADDR, IP_DST_ADDR, tcp->th_dport 
+ 			);
+ 		    return INFILT_OK;
+ 		}
+ 	   }
+ 	   		INFILT_LOG1(LOG_NOTICE, 
+ 			"infilt_tcp: %d.%d.%d.%d -> %d.%d.%d.%d ZAP %d\n", 
+ 			IP_SRC_ADDR, IP_DST_ADDR, tcp->th_dport 
+ 			);
+ 	   return INFILT_DROP;
+ 	}
+     }
+     			INFILT_LOG8(LOG_DEBUG, 
+ 			"infilt_tcp: %d.%d.%d.%d -> %d.%d.%d.%d OK %d\n", 
+ 			IP_SRC_ADDR, IP_DST_ADDR, tcp->th_dport );
+     return INFILT_OK;
+ }
+ 
+ int  /* return INFILT_DROP to drop, INFILT_OK to keep */
+ infilt_udp(mbuf_ptr)
+   struct mbuf** mbuf_ptr;
+ {
+     long ip_size= MP->m_len - PPP_OVERHEAD; 
+     struct ip* ip= (struct ip*) (mtod(MP, u_char*)+PPP_OVERHEAD);
+     struct udphdr* udp= (struct udphdr*) ((long*)ip+ip->ip_hl);
+     int* p;
+ 
+ 
+     if ( ip_size < ip->ip_hl*4 + sizeof *udp ) {
+ 	   		INFILT_LOG1(LOG_NOTICE, 
+ 			"infilt_tcp: %d.%d.%d.%d -> %d.%d.%d.%d m_pullup %d %d\n", 
+ 			IP_SRC_ADDR, IP_DST_ADDR, ip_size, ip->ip_hl*4 + sizeof *udp );
+ 			infilt_print_mbuf(*mbuf_ptr, "infilt_tcp before pullup" );
+ 	MP= (m_pullup(MP, ip->ip_hl*4 + sizeof *udp + PPP_OVERHEAD));
+ 	if (!MP) {
+ 		/*
+ 		 *   if cannot pullup ... is it already freed?
+ 		 *       it seems so....
+ 		 */
+ 			INFILT_LOG0(LOG_WARNING, 
+ 			"infilt_udp: cannot m_pullup %d",
+ 			ip->ip_hl*4 + sizeof *udp + PPP_OVERHEAD
+ 			);
+ 		return INFILT_DEAD;
+ 	}
+ 			infilt_print_mbuf(*mbuf_ptr, "infilt_udp after pullup" );
+ 	ip_size= MP->m_len - PPP_OVERHEAD;
+ 	ip= (struct ip*) (mtod(MP, u_char*)+PPP_OVERHEAD);
+ 	udp= (struct udphdr*) ((long*)ip+ip->ip_hl);
+     }
+ 
+ 
+     if ( ip_size < ip->ip_hl*4 + sizeof *udp  ) {
+ 			INFILT_LOG0(LOG_ERR, 
+ 	   		"infilt_udp: %d.%d.%d.%d -> %d.%d.%d.%d NOTREACHED ip_size %d\n", 
+ 	   		IP_SRC_ADDR, IP_DST_ADDR, ip_size
+ 			);
+ 	/* drop tiny packets here,
+ 	 *   so that packets cannot evade inspection by being
+ 	 *   fragmented with a tiny first frament
+ 	 */
+ 	return INFILT_DROP;
+     } else { 
+        if ( udp->uh_dport >= infilt_udp_dport_min ) {
+ 	   /* meets minimum -- pass unless zapped */
+ 	   for ( p= infilt_udp_dport_zap; *p; p++ ) {
+ 		if ( *p == udp->uh_dport ) {
+ 		   	INFILT_LOG1(LOG_NOTICE, 
+ 			"infilt_udp: %d.%d.%d.%d -> %d.%d.%d.%d zap %d\n", 
+ 			IP_SRC_ADDR, IP_DST_ADDR, udp->uh_dport 
+ 			);
+ 		    return INFILT_DROP;
+ 		}
+ 	   }
+ 	} else {
+ 	   /* below minimum -- drop unless ok */
+ 	   for ( p= infilt_udp_dport_ok; *p; p++ ) {
+ 		if ( *p == udp->uh_dport ) {
+ 		    	INFILT_LOG8(LOG_DEBUG, 
+ 			"infilt_udp: %d.%d.%d.%d -> %d.%d.%d.%d ok %d\n", 
+ 			IP_SRC_ADDR, IP_DST_ADDR, udp->uh_dport 
+ 			);
+ 		    return INFILT_OK;
+ 		}
+ 	   }
+ 	   		INFILT_LOG1(LOG_NOTICE, 
+ 			"infilt_udp: %d.%d.%d.%d -> %d.%d.%d.%d ZAP %d\n", 
+ 			IP_SRC_ADDR, IP_DST_ADDR, udp->uh_dport 
+ 			);
+ 	   return INFILT_DROP;
+ 	}
+     }
+     INFILT_LOG8(LOG_DEBUG, 
+ 		"infilt_udp: %d.%d.%d.%d -> %d.%d.%d.%d OK %d\n", 
+ 		IP_SRC_ADDR, IP_DST_ADDR, udp->uh_dport );
+     return INFILT_OK;
+ }
+ 
+ int  /* return INFILT_DROP to drop, INFILT_OK to keep */
+ infilt_icmp(mbuf_ptr)
+   struct mbuf** mbuf_ptr;
+ {
+     long ip_size= MP->m_len - PPP_OVERHEAD; 
+     struct ip* ip= (struct ip*) (mtod(MP, u_char*)+PPP_OVERHEAD);
+     struct icmp* icmp= (struct icmp*) ((long*)ip+ip->ip_hl);
+     int* p= infilt_icmp_type_zap;
+ 
+ 
+     /* don't require full "sizeof *icmp" for ip_size */
+     if ( ip_size < ip->ip_hl*4 + sizeof icmp->icmp_type ) {
+ 	   		INFILT_LOG1(LOG_NOTICE, 
+ 			"infilt_icmp: %d.%d.%d.%d -> %d.%d.%d.%d m_pullup %d %d\n", 
+ 			IP_SRC_ADDR, IP_DST_ADDR, ip_size, ip->ip_hl*4 + sizeof icmp->icmp_type 
+ 			);
+ 			infilt_print_mbuf(*mbuf_ptr, "infilt_icmp before pullup" );
+ 	MP= (m_pullup(MP, ip->ip_hl*4 + sizeof icmp->icmp_type + PPP_OVERHEAD));
+ 	if (!MP) {
+ 		/*
+ 		 *   if cannot pullup ... is it already freed?
+ 		 *       it seems so....
+ 		 */
+ 			INFILT_LOG0(LOG_WARNING, 
+ 			"infilt_icmp: cannot m_pullup %d",
+ 			ip->ip_hl*4 + sizeof icmp->icmp_type + PPP_OVERHEAD
+ 			);
+ 		return INFILT_DEAD;
+ 	}
+ 			infilt_print_mbuf(*mbuf_ptr, "infilt_icmp after pullup" );
+ 	ip_size= MP->m_len - PPP_OVERHEAD;
+ 	ip= (struct ip*) (mtod(MP, u_char*)+PPP_OVERHEAD);
+ 	icmp= (struct icmp*) ((long*)ip+ip->ip_hl);
+     }
+ 
+ 
+     if ( ip_size < ip->ip_hl*4 + sizeof icmp->icmp_type  ) {
+ 			INFILT_LOG0(LOG_ERR, 
+ 	   		"infilt_icmp: %d.%d.%d.%d -> %d.%d.%d.%d NOTREACHED ip_size %d\n", 
+ 	   		IP_SRC_ADDR, IP_DST_ADDR, ip_size
+ 			);
+ 	/* drop tiny packets here,
+ 	 *   so that packets cannot evade inspection by being
+ 	 *   fragmented with a tiny first frament
+ 	 */
+ 	return INFILT_DROP;
+     } else { 
+ 	for ( ; *p; p++ ) {
+ 		if ( *p == icmp->icmp_type ) {
+ 		    	INFILT_LOG1(LOG_NOTICE, 
+ 			"infilt_icmp: %d.%d.%d.%d -> %d.%d.%d.%d zap %d\n", 
+ 			IP_SRC_ADDR, IP_DST_ADDR, icmp->icmp_type 
+ 			);
+ 		    return INFILT_DROP;
+ 		}
+ 	}
+     }
+     			INFILT_LOG8(LOG_DEBUG, 
+ 			"infilt_icmp: %d.%d.%d.%d -> %d.%d.%d.%d OK %d\n", 
+ 			IP_SRC_ADDR, IP_DST_ADDR, icmp->icmp_type 
+ 			);
+     return INFILT_OK;
+ }
+ 
+ 
+ int  /* return INFILT_DROP to drop, INFILT_OK to keep */
+ infilt(mbuf_ptr)
+   struct mbuf** mbuf_ptr;
+ {
+     register j;
+     long ip_size= MP->m_len - PPP_OVERHEAD; 
+     struct ip* ip= (struct ip*) (mtod(MP, u_char*)+PPP_OVERHEAD);
+     int status= INFILT_OK;
+ 
+     if ( ! infilt_enable ) return INFILT_OK;  /* quick cutoff */
+ 
+     if ( ip_size < sizeof *ip ) {
+ 	   		INFILT_LOG1(LOG_NOTICE, 
+ 			"infilt: %d.%d.%d.%d -> %d.%d.%d.%d m_pullup %d %d\n", 
+ 			IP_SRC_ADDR, IP_DST_ADDR, ip_size, sizeof *ip );
+ 			infilt_print_mbuf(*mbuf_ptr, "infilt before pullup" );
+ 	MP= (m_pullup(MP, sizeof(struct ip)+PPP_OVERHEAD));
+ 	if (!MP) {
+ 		/*
+ 		 *   if cannot pullup ... is it already freed?
+ 		 *       it seems so....
+ 		 */
+ 			INFILT_LOG0(LOG_WARNING, 
+ 			"infilt: cannot m_pullup %d",
+ 			sizeof(struct ip)+PPP_OVERHEAD
+ 			);
+ 		return INFILT_DEAD;
+ 	}
+ 			infilt_print_mbuf(*mbuf_ptr, "infilt after pullup" );
+ 	ip_size= MP->m_len - PPP_OVERHEAD;
+ 	ip= (struct ip*) (mtod(MP, u_char*)+PPP_OVERHEAD);
+     }
+ 
+     if ( ip_size < sizeof *ip ) {
+ 	/* should not happen, after sucessful pullup */
+ 			INFILT_LOG0(LOG_ERR, "infilt: NOTREACHED ip_size %d", ip_size);
+ 			infilt_print_mbuf(*mbuf_ptr, "infilt NOTREACHED ip_size" );
+ 	return INFILT_DROP;
+     } else if ( ip->ip_v != IPVERSION ) {
+ 			INFILT_LOG0(LOG_WARNING, "infilt: BAD ip_version %d", ip->ip_v );
+ 			infilt_print_mbuf(*mbuf_ptr, "infilt BAD ip_version" );
+ 	return INFILT_DROP;
+     } else { 
+ 	if ( infilt_kill_options && ip->ip_hl>5 ) {
+ 			INFILT_LOG1(LOG_NOTICE, 
+ 		    	"infilt: %d.%d.%d.%d -> %d.%d.%d.%d KILL ip_option %d",
+ 		    	IP_SRC_ADDR, IP_DST_ADDR, 
+ 		    	255 & *(unsigned char*)(5+(long*)ip) /* first option */
+ 			);
+ 			infilt_print_mbuf(*mbuf_ptr, "infilt KILL ip_option" );
+ 		return INFILT_DROP;
+ 	}
+ 
+ 	if ( infilt_clear_options && ip->ip_hl>5 ) {
+ 
+ 	   /* ZERO OUT THE IP HEADER OPTIONS */
+ 
+ 	   /* calculate old header checksum */
+ 	   unsigned long check= 0;
+ 	   for (j=0; j<ip->ip_hl*2; j++ ) {
+ 		/* add shorts, but skip the checksum itself (index 5) */ 
+ 		if ( j!=5 ) check += ((unsigned short*)ip)[j];
+ 	   }
+ 	   check += ((check>>16)&0xFFFF);  /* add in the carry */
+ 	   check += ((check>>16)&0xFFFF);  /* add in the carry */
+ 	   check = ~check;		   /* ones comp */
+ 	   check &= 0xFFFF;		   /* mask to short */ 
+ 
+ 	   if ( check != (unsigned short) ip->ip_sum ) {
+ 			INFILT_LOG1(LOG_NOTICE, 
+ 		    	"infilt: %d.%d.%d.%d -> %d.%d.%d.%d BAD ip_sum %d %d",
+ 		    	IP_SRC_ADDR, IP_DST_ADDR, check, ip->ip_sum
+ 			);
+ 			infilt_print_mbuf(*mbuf_ptr, "infilt BAD ip_sum" );
+ 		return INFILT_DROP; /* drop bad checksums! */
+ 	   }
+ 
+ 	   /* now zero the options */
+ 
+ 	   for (j=5; j<ip->ip_hl && j<16; j++ ) {
+ 		((unsigned long*)(ip))[j]= 0; /* clear 32 bit words */
+ 	   }
+ 
+ 	   /* calculate new header checksum */
+ 	   check= 0;
+ 	   for (j=0; j<ip->ip_hl*2; j++ ) {
+ 		/* add shorts, but skip the checksum itself (index 5) */ 
+ 		if ( j!=5 ) check += ((unsigned short*)ip)[j];
+ 	   }
+ 	   check += ((check>>16)&0xFFFF);  /* add in the carry */
+ 	   check += ((check>>16)&0xFFFF);  /* add in the carry */
+ 	   check = ~check;		   /* ones comp */
+ 	   check &= 0xFFFF;		   /* mask to short */ 
+ 
+ 	   ip->ip_sum= check;   /* insert new checksum into packet */
+ 
+ 	}
+ 
+ 	if ( ip->ip_off & 0x1FFF ) {
+ 	   /* allow later fragments to pass -- they'll be dropped
+ 	    * later if the first fragment is dropped.
+ 	    */
+ 	   status= INFILT_OK;
+ 	} else {
+ 	   /* do filtering on first fragment or on unfragmented packets */
+            switch ( ip->ip_p ) {
+ 	      case IPPROTO_ICMP:  status= infilt_icmp(mbuf_ptr);  break;
+ 	      case IPPROTO_TCP:	  status= infilt_tcp(mbuf_ptr);  break;
+ 	      case IPPROTO_UDP:	  status= infilt_udp(mbuf_ptr);  break;
+ 	      default:		  infilt_print_mbuf(*mbuf_ptr, 
+ 					"infilt default ip_p" );
+ 				  break;
+ 	   }
+ 	}
+ 
+     }
+ 
+     if ( status != INFILT_OK ) infilt_print_mbuf(*mbuf_ptr, "infilt status not OK" );
+     return status;
+ }
+ 
+ #endif /* INFILT */
+ 
+ 
+ 
  static int
  dp_if_rsrv(q)
  queue_t	*q;
***************
*** 664,669 ****
--- 1416,1424 ----
      struct mbuf	*mb1, *mb2,*mbtail;
      int	len,xlen,count,s;
      u_char	*rptr;
+ #ifdef INFILT
+     int drop_it= 0;
+ #endif
  
      p = (PII *) q->q_ptr;
  
***************
*** 820,830 ****
  #define	IPADJ	sizeof(struct ppp_header)
  	dp_active(p, (struct ip *)(mtod(mb1, u_char *) + IPADJ),
  		  mb1->m_len - IPADJ, 0);
  	s = splimp();
! 	if (IF_QFULL(&ipintrq)) {
  	    IF_DROP(&ipintrq);
  	    p->pii_ifnet.if_ierrors++;
! 	    m_freem(mb1);
  	}
  	else {
  	    IF_ENQUEUE(&ipintrq, mb1);
--- 1575,1593 ----
  #define	IPADJ	sizeof(struct ppp_header)
  	dp_active(p, (struct ip *)(mtod(mb1, u_char *) + IPADJ),
  		  mb1->m_len - IPADJ, 0);
+ #ifdef INFILT
+ 	drop_it= infilt(&mb1);
+ #endif
  	s = splimp();
! #ifdef INFILT
! 	if (drop_it || IF_QFULL(&ipintrq)) 
! #else
! 	if (IF_QFULL(&ipintrq)) 
! #endif
! 	{
  	    IF_DROP(&ipintrq);
  	    p->pii_ifnet.if_ierrors++;
! 	    if (mb1) m_freem(mb1);
  	}
  	else {
  	    IF_ENQUEUE(&ipintrq, mb1);
***************
*** 917,922 ****
--- 1680,1689 ----
      switch (dst->sa_family) {
  #ifdef	INET
       case AF_INET:
+ #ifdef INFILT
+ 	infilt_tcp_clamp(&m0, 0);
+ 	if ( ! m0 ) goto getout;
+ #endif
  #ifdef PPP_SNIT
  	if (ifp->if_flags & IFF_PROMISC) {
  	    struct mbuf *m = m0;
