[ previous ] [ next ] [ threads ]
 
 From:  Manuel Kasper <mk at neon1 dot net>
 To:  m0n0wall dash dev at lists dot m0n0 dot ch
 Subject:  ipnat MSS patch
 Date:  Sat, 17 Apr 2004 23:54:05 +0200
(again, this time without application/octet-stream...)

Here's my patch to enable MSS clamping in ipnat regardless of any NAT
rules; details about its usage are included in the attachment.

I'd appreciate feedback from kernel hackers...

- Manuel
MSS clamping patch for ipnat
by Manuel Kasper <mk at neon1 dot net>
04/17/2004

This patch for ipfilter on FreeBSD 4.9 adds two sysctls that can be used to do 
MSS clamping regardless of any ipnat rules (i.e. to clamp the MSS when no NAT is 
required). It even works with an empty ipnat ruleset. If a matching NAT rule 
with the mssclamp keyword is found, the MSS given in that rule is honored; 
otherwise, the default (as set with the sysctl) is applied.

net.inet.ipf.fr_mssclamp
	set to the desired MSS (usually MTU - 40), or 0 to disable

net.inet.ipf.fr_mssif
	set to the interface name on which MSS clamping should take place
	(empty string = disable)

Example (PPPoE with MPD):

sysctl net.inet.ipf.fr_mssif=ng0
sysctl net.inet.ipf.fr_mssclamp=1452

This patch is against ipfilter 3.4.33, so make sure to install that first
(FreeBSD 4.9 comes with buggy ipfilter 3.4.31).


--- sys/contrib/ipfilter/netinet/ip_nat.c.orig	Wed Feb 11 16:16:22 2004
+++ sys/contrib/ipfilter/netinet/ip_nat.c	Sat Apr 17 20:59:53 2004
@@ -126,6 +126,9 @@
 ipnat_t	**rdr_rules = NULL;
 hostmap_t	**maptable  = NULL;
 
+int	fr_mssclamp = 0;
+char fr_mssif[IFNAMSIZ] = "";
+
 u_long	fr_defnatage = DEF_NAT_AGE,
 	fr_defnaticmpage = 6;		/* 3 seconds */
 natstat_t nat_stats;
@@ -2374,8 +2377,10 @@
 	void *sifp;
 	u_32_t iph;
 	nat_t *nat;
+	int clamped = 0;
+	int retval = 0;
 
-	if (nat_list == NULL || (fr_nat_lock))
+	if (fr_nat_lock)
 		return 0;
 
 	if ((fr = fin->fin_fr) && !(fr->fr_flags & FR_DUP) &&
@@ -2399,6 +2404,9 @@
 	}
 
 	ipa = fin->fin_saddr;
+	
+	if (nat_list == NULL)
+		goto ip_natout_mss;
 
 	READ_ENTER(&ipf_nat);
 
@@ -2554,9 +2562,11 @@
                                  * only deal IPv4 for now.
                                  */
                                 if (nat->nat_mssclamp &&
-                                    (tcp->th_flags & TH_SYN) != 0)
+                                    (tcp->th_flags & TH_SYN) != 0) {
                                         nat_mssclamp(tcp, nat->nat_mssclamp,
 						     fin, csump);
+						     			clamped = 1;
+						 }
 
 				MUTEX_EXIT(&nat->nat_lock);
 			} else if (fin->fin_p == IPPROTO_UDP) {
@@ -2586,13 +2596,29 @@
 		} else
 			i = 1;
 		ATOMIC_INCL(nat_stats.ns_mapped[1]);
-		RWLOCK_EXIT(&ipf_nat);	/* READ */
-		fin->fin_ifp = sifp;
-		return i;
+		retval = i;
 	}
 	RWLOCK_EXIT(&ipf_nat);			/* READ/WRITE */
+	
+ip_natout_mss:
+	/* Handle MSS clamping, if necessary */
+	if (!clamped && (fr_mssclamp > 0) && (fr_mssif[0] != 0) &&
+		(fin->fin_off == 0) && !(fin->fin_fl & FI_SHORT) &&
+		(fin->fin_p == IPPROTO_TCP)) {
+		
+		if ((tcp->th_flags & TH_SYN) != 0) {
+		
+			/* Does the interface name match? */
+			char tmpifn[IFNAMSIZ];
+			snprintf(tmpifn, IFNAMSIZ, "%s%d", ifp->if_name, ifp->if_unit);
+			
+			if (strncmp(tmpifn, fr_mssif, IFNAMSIZ) == 0)
+				nat_mssclamp(tcp, fr_mssclamp, fin, &tcp->th_sum);
+		}
+	}
+	
 	fin->fin_ifp = sifp;
-	return 0;
+	return retval;
 }
 
 
@@ -2614,8 +2640,10 @@
 	int i, icmpset = 0;
 	nat_t *nat;
 	u_32_t iph;
+	int clamped = 0;
+	int retval = 0;
 
-	if ((nat_list == NULL) || (ip->ip_v != 4) || (fr_nat_lock))
+	if ((ip->ip_v != 4) || (fr_nat_lock))
 		return 0;
 
 	if ((fin->fin_off == 0) && !(fin->fin_fl & FI_SHORT)) {
@@ -2633,6 +2661,9 @@
 	in = fin->fin_dst;
 	/* make sure the source address is to be redirected */
 	src = fin->fin_src;
+	
+	if (nat_list == NULL)
+		goto ip_natin_mss;
 
 	READ_ENTER(&ipf_nat);
 
@@ -2775,9 +2806,11 @@
                                  * only deal IPv4 for now.
                                  */
                                 if (nat->nat_mssclamp &&
-                                    (tcp->th_flags & TH_SYN) != 0)
+                                    (tcp->th_flags & TH_SYN) != 0) {
                                         nat_mssclamp(tcp, nat->nat_mssclamp,
 						     fin, csump);
+						     			clamped = 1;
+						 }
 
 				MUTEX_EXIT(&nat->nat_lock);
 			} else if (fin->fin_p == IPPROTO_UDP) {
@@ -2797,11 +2830,28 @@
 			}
 		}
 		ATOMIC_INCL(nat_stats.ns_mapped[0]);
-		RWLOCK_EXIT(&ipf_nat);			/* READ */
-		return 1;
+		retval = 1;
 	}
 	RWLOCK_EXIT(&ipf_nat);			/* READ/WRITE */
-	return 0;
+	
+ip_natin_mss:
+	/* Handle MSS clamping, if necessary */
+	if (!clamped && (fr_mssclamp > 0) && (fr_mssif[0] != 0) &&
+		(fin->fin_off == 0) && !(fin->fin_fl & FI_SHORT) &&
+		(fin->fin_p == IPPROTO_TCP)) {
+		
+		if ((tcp->th_flags & TH_SYN) != 0) {
+		
+			/* Does the interface name match? */
+			char tmpifn[IFNAMSIZ];
+			snprintf(tmpifn, IFNAMSIZ, "%s%d", ifp->if_name, ifp->if_unit);
+			
+			if (strncmp(tmpifn, fr_mssif, IFNAMSIZ) == 0)
+				nat_mssclamp(tcp, fr_mssclamp, fin, &tcp->th_sum);
+		}
+	}
+	
+	return retval;
 }
 
 
--- sys/contrib/ipfilter/netinet/ip_nat.h.orig	Wed Feb 11 16:16:37 2004
+++ sys/contrib/ipfilter/netinet/ip_nat.h	Sat Apr 17 20:45:37 2004
@@ -302,6 +302,8 @@
 extern	void	ip_natsync __P((void *));
 extern	u_long	fr_defnatage;
 extern	u_long	fr_defnaticmpage;
+extern	int		fr_mssclamp;
+extern	char	fr_mssif[];
 extern	nat_t	**nat_table[2];
 extern	nat_t	*nat_instances;
 extern	ipnat_t	**nat_rules;
--- sys/contrib/ipfilter/netinet/mlf_ipl.c.orig	Tue Jun  4 16:51:31 2002
+++ sys/contrib/ipfilter/netinet/mlf_ipl.c	Sat Apr 17 20:45:42 2004
@@ -131,6 +131,10 @@
 	   &fr_defaultauthage, 0, "");
 SYSCTL_INT(_net_inet_ipf, OID_AUTO, ippr_ftp_pasvonly, CTLFLAG_RW,
 	   &ippr_ftp_pasvonly, 0, "");
+SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_mssclamp, CTLFLAG_RW,
+	   &fr_mssclamp, 0, "");
+SYSCTL_STRING(_net_inet_ipf, OID_AUTO, fr_mssif, CTLFLAG_RW,
+	   fr_mssif, IFNAMSIZ, "");
 #endif
 
 #ifdef DEVFS
--- sys/contrib/ipfilter/netinet/mlfk_ipl.c.orig	Mon Aug 27 23:14:04 2001
+++ sys/contrib/ipfilter/netinet/mlfk_ipl.c	Sat Apr 17 20:45:44 2004
@@ -102,6 +102,10 @@
 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &fr_minttl, 0, "");
 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_minttllog, CTLFLAG_RW,
 	   &fr_minttllog, 0, "");
+SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_mssclamp, CTLFLAG_RW,
+	   &fr_mssclamp, 0, "");
+SYSCTL_STRING(_net_inet_ipf, OID_AUTO, fr_mssif, CTLFLAG_RW,
+	   fr_mssif, IFNAMSIZ, "");
 
 #define CDEV_MAJOR 79
 static struct cdevsw ipl_cdevsw = {