Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 12 May 1996 14:40:24 -0500 (CDT)
From:      Alex Nash <alex@zen.nash.org>
To:        FreeBSD-gnats-submit@freebsd.org
Cc:        phk@freebsd.org
Subject:   kern/1192: Kernel IPFW
Message-ID:  <199605121940.OAA00723@zen.nash.org>
Resent-Message-ID: <199605121950.MAA10412@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         1192
>Category:       kern
>Synopsis:       various ipfw.[ch] changes (see below)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun May 12 12:50:02 PDT 1996
>Last-Modified:
>Originator:     Alex Nash
>Organization:
>Release:        FreeBSD 2.1-STABLE i386
>Environment:

-current and -stable systems that use ipfw.

>Description:

ip_fw.h:

  A constant used by the ipfw program was missing from the -stable
  branch.

ip_fw.c:

  Added IPFIREWALL_VERBOSE_LIMIT option that prevents denial-of-service
  attacks by flooding a system with IPFW log messages.  This option
  is OFF by default.

  Added the ability to clear the accounting record of a single chain
  entry.  (An update to the ipfw program has been submitted separately
  to accomodate this.)

  Changed the boot up messages to indicate the logging level and
  limit (if enabled).

  Moved the majority of code out of the ipfw_load (module load)
  routine and instead issue a call to ipfw_init which does the same
  thing (sans the splnet() issued at the beginning of ipfw_load).

  WARNING: The new sysctl int has not been tested or even compiled!

LINT:

  Expanded the explanation of the IPFIREWALL_VERBOSE option.

  Added IPFIREWALL_VERBOSE_LIMIT.

>How-To-Repeat:

N/A

>Fix:
	
--- sys/netinet/ip_fw.h	Sun May 12 12:51:26 1996
***************
*** 105,110 ****
--- 105,111 ----
  #define IP_FW_TCPF_PSH		TH_PUSH
  #define IP_FW_TCPF_ACK		TH_ACK
  #define IP_FW_TCPF_URG		TH_URG
+ #define IP_FW_TCPF_ESTAB	0x40
  
  /*
   * New IP firewall options for [gs]etsockopt at the RAW IP level.



--- sys/netinet/ip_fw.c	Sun May 12 12:27:06 1996
***************
*** 41,46 ****
--- 41,51 ----
  #else
  static int fw_verbose = 0;
  #endif
+ #ifdef IPFIREWALL_VERBOSE_LIMIT
+ static int fw_verbose_limit = IPFIREWALL_VERBOSE_LIMIT;
+ #else
+ static int fw_verbose_limit = 0;
+ #endif
  
  
  LIST_HEAD (ip_fw_head, ip_fw_chain) ip_fw_chain;
***************
*** 49,54 ****
--- 54,60 ----
  SYSCTL_NODE(net_inet_ip, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");
  SYSCTL_INT(net_inet_ip_fw, OID_AUTO, debug, CTLFLAG_RW, &fw_debug, 0, "");
  SYSCTL_INT(net_inet_ip_fw, OID_AUTO, verbose, CTLFLAG_RW, &fw_verbose, 0, "");
+ SYSCTL_INT(net_inet_ip_fw, OID_AUTO, verbose_limit, CTLFLAG_RW, &fw_verbose_limit, 0, "");
  #endif
  
  #define dprintf(a)	if (!fw_debug); else printf a
***************
*** 68,74 ****
  static int	port_match __P((u_short *portptr, int nports, u_short port,
  				int range_flag));
  static int	tcpflg_match __P((struct tcphdr *tcp, struct ip_fw *f));
! static void	ipfw_report __P((char *txt, int rule, struct ip *ip));
  
  static int (*old_chk_ptr)(struct mbuf *, struct ip *,struct ifnet *, int dir);
  static int (*old_ctl_ptr)(int,struct mbuf **);
--- 74,80 ----
  static int	port_match __P((u_short *portptr, int nports, u_short port,
  				int range_flag));
  static int	tcpflg_match __P((struct tcphdr *tcp, struct ip_fw *f));
! static void	ipfw_report __P((char *txt, int rule, struct ip *ip, int counter));
  
  static int (*old_chk_ptr)(struct mbuf *, struct ip *,struct ifnet *, int dir);
  static int (*old_ctl_ptr)(int,struct mbuf **);
***************
*** 179,191 ****
  }
  
  static void
! ipfw_report(char *txt, int rule, struct ip *ip)
  {
  	struct tcphdr *tcp = (struct tcphdr *) ((u_long *) ip + ip->ip_hl);
  	struct udphdr *udp = (struct udphdr *) ((u_long *) ip + ip->ip_hl);
  	struct icmp *icmp = (struct icmp *) ((u_long *) ip + ip->ip_hl);
  	if (!fw_verbose)
  		return;
  	printf("ipfw: %d %s ",rule, txt);
  	switch (ip->ip_p) {
  	case IPPROTO_TCP:
--- 185,199 ----
  }
  
  static void
! ipfw_report(char *txt, int rule, struct ip *ip, int counter)
  {
  	struct tcphdr *tcp = (struct tcphdr *) ((u_long *) ip + ip->ip_hl);
  	struct udphdr *udp = (struct udphdr *) ((u_long *) ip + ip->ip_hl);
  	struct icmp *icmp = (struct icmp *) ((u_long *) ip + ip->ip_hl);
  	if (!fw_verbose)
  		return;
+ 	if (fw_verbose_limit != 0 && counter > fw_verbose_limit)
+ 		return;
  	printf("ipfw: %d %s ",rule, txt);
  	switch (ip->ip_p) {
  	case IPPROTO_TCP:
***************
*** 246,252 ****
  	 * we're not going to pass it...
  	 */
  	if ((ip->ip_off & IP_OFFMASK) == 1) {
! 		ipfw_report("Refuse", -1, ip);
  		m_freem(m);
  		return 0;
  	}
--- 254,263 ----
  	 * we're not going to pass it...
  	 */
  	if ((ip->ip_off & IP_OFFMASK) == 1) {
! 		static int frag_counter = 0;
! 
! 		++frag_counter;
! 		ipfw_report("Refuse", -1, ip, frag_counter);
  		m_freem(m);
  		return 0;
  	}
***************
*** 398,408 ****
  		f->fw_bcnt+=ip->ip_len;
  		if (f->fw_flg & IP_FW_F_PRN) {
  			if (f->fw_flg & IP_FW_F_ACCEPT)
! 				ipfw_report("Accept", f->fw_number, ip);
  			else if (f->fw_flg & IP_FW_F_COUNT)
! 				ipfw_report("Count", f->fw_number, ip);
  			else
! 				ipfw_report("Deny", f->fw_number, ip);
  		}
  		if (f->fw_flg & IP_FW_F_ACCEPT)
  			return 1;
--- 409,419 ----
  		f->fw_bcnt+=ip->ip_len;
  		if (f->fw_flg & IP_FW_F_PRN) {
  			if (f->fw_flg & IP_FW_F_ACCEPT)
! 				ipfw_report("Accept", f->fw_number, ip, f->fw_pcnt);
  			else if (f->fw_flg & IP_FW_F_COUNT)
! 				ipfw_report("Count", f->fw_number, ip, f->fw_pcnt);
  			else
! 				ipfw_report("Deny", f->fw_number, ip, f->fw_pcnt);
  		}
  		if (f->fw_flg & IP_FW_F_ACCEPT)
  			return 1;
***************
*** 518,523 ****
--- 529,563 ----
  	return (EINVAL);
  }
  
+ static int
+ zero_entry(m)
+ 	struct mbuf *m;
+ {
+ 	struct ip_fw *frwl;
+ 	struct ip_fw_chain *fcp;
+ 	int s;
+ 
+ 	if (m) {
+ 		frwl = check_ipfw_struct(m);
+ 
+ 		if (!frwl)
+ 			return(EINVAL);
+ 	}
+ 	else
+ 		frwl = NULL;
+ 
+ 	/*
+ 	 *	It's possible to insert multiple chain entries with the
+ 	 *	same number, so we don't stop after finding the first
+ 	 *	match if zeroing a specific entry.
+ 	 */
+ 	s = splnet();
+ 	for (fcp = ip_fw_chain.lh_first; fcp; fcp = fcp->chain.le_next)
+ 		if (!frwl || frwl->fw_number == fcp->rule->fw_number)
+ 			fcp->rule->fw_bcnt = fcp->rule->fw_pcnt = 0;
+ 	splx(s);
+ }
+ 
  static struct ip_fw *
  check_ipfw_struct(m)
  	struct mbuf *m;
***************
*** 600,612 ****
  		return (0);
  	}
  	if (stage == IP_FW_ZERO) {
! 		int s = splnet();
! 		struct ip_fw_chain *fcp;
! 		for (fcp = ip_fw_chain.lh_first; fcp; fcp = fcp->chain.le_next)
! 			fcp->rule->fw_bcnt = fcp->rule->fw_pcnt = 0;
! 		splx(s);
  		if (m) (void)m_free(m);
! 		return (0);
  	}
  	if (m == NULL) {
  		printf("ip_fw_ctl:  NULL mbuf ptr\n");
--- 640,648 ----
  		return (0);
  	}
  	if (stage == IP_FW_ZERO) {
! 		error = zero_entry(m);
  		if (m) (void)m_free(m);
! 		return (error);
  	}
  	if (m == NULL) {
  		printf("ip_fw_ctl:  NULL mbuf ptr\n");
***************
*** 647,653 ****
  	deny.fw_number = (u_short)-1;
  	add_entry(&ip_fw_chain, &deny);
  	
! 	printf("IP firewall initialized\n");
  }
  
  #ifdef ACTUALLY_LKM_NOT_KERNEL
--- 683,697 ----
  	deny.fw_number = (u_short)-1;
  	add_entry(&ip_fw_chain, &deny);
  	
! 	printf("IP firewall initialized, ");
! #ifndef IPFIREWALL_VERBOSE
! 	printf("logging disabled\n");
! #else
! 	if (fw_verbose_limit == 0)
! 		printf("unlimited logging\n");
! 	else
! 		printf("logging limited to %d packets/entry\n", fw_verbose_limit);
! #endif
  }
  
  #ifdef ACTUALLY_LKM_NOT_KERNEL
***************
*** 662,682 ****
  ipfw_load(struct lkm_table *lkmtp, int cmd)
  {
  	int s=splnet();
- 	struct ip_fw deny;
  
          old_chk_ptr = ip_fw_chk_ptr;
          old_ctl_ptr = ip_fw_ctl_ptr;
- 	ip_fw_chk_ptr = ip_fw_chk;
- 	ip_fw_ctl_ptr = ip_fw_ctl;
- 
- 	LIST_INIT(&ip_fw_chain);
- 	bzero(&deny, sizeof deny);
- 	deny.fw_flg = IP_FW_F_ALL;
- 	deny.fw_number = (u_short)-1;
- 	add_entry(&ip_fw_chain, &deny);
  
  	splx(s);
- 	printf("IP firewall loaded\n");
  	return 0;
  }
  
--- 706,717 ----
  ipfw_load(struct lkm_table *lkmtp, int cmd)
  {
  	int s=splnet();
  
          old_chk_ptr = ip_fw_chk_ptr;
          old_ctl_ptr = ip_fw_ctl_ptr;
  
+ 	ip_fw_init();
  	splx(s);
  	return 0;
  }


--- sys/i386/conf/LINT        Sat May 11 08:28:06 1996
***************
*** 185,192 ****
  # with mrouted(8).
  #
  # IPFIREWALL enables support for IP firewall construction, in
! # conjunction with the `ipfw' program.  IPFIREWALL_VERBOSE does
! # the obvious thing.
  #
  # ARP_PROXYALL enables global proxy ARP.  Beware!  This can burn
  # your house down!  See netinet/if_ether.c for the gory details.
--- 185,193 ----
  # with mrouted(8).
  #
  # IPFIREWALL enables support for IP firewall construction, in
! # conjunction with the `ipfw' program.  IPFIREWALL_VERBOSE prints
! # logged packets on the console.  IPFIREWALL_VERBOSE_LIMIT limits
! # the number of times a matching entry can print.
  #
  # ARP_PROXYALL enables global proxy ARP.  Beware!  This can burn
  # your house down!  See netinet/if_ether.c for the gory details.
***************
*** 198,203 ****
--- 199,205 ----
  options         IPFIREWALL              #firewall
  options         IPFIREWALL_VERBOSE      #print information about
                                        # dropped packets
+ options               "IPFIREWALL_VERBOSE_LIMIT=100" # limit verbosity
  options               ARP_PROXYALL            # global proxy ARP
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199605121940.OAA00723>