svn commit: r187122 - user/piso/sys/netinet

Paolo Pisati piso at FreeBSD.org
Mon Jan 12 15:17:12 PST 2009


Author: piso
Date: Mon Jan 12 23:17:12 2009
New Revision: 187122
URL: http://svn.freebsd.org/changeset/base/187122

Log:
  In case of fragments, reassemble the packet before passing it to libalias.

Modified:
  user/piso/sys/netinet/ip_fw_nat.c

Modified: user/piso/sys/netinet/ip_fw_nat.c
==============================================================================
--- user/piso/sys/netinet/ip_fw_nat.c	Mon Jan 12 22:53:26 2009	(r187121)
+++ user/piso/sys/netinet/ip_fw_nat.c	Mon Jan 12 23:17:12 2009	(r187122)
@@ -252,7 +252,7 @@ ipfw_nat(struct ip_fw_args *args, struct
 	struct mbuf *mcl;
 	struct ip *ip;
 	/* XXX - libalias duct tape */
-	int ldt, retval;
+	int ldt, retval, off;
 	char *c;
 
 	ldt = 0;
@@ -261,7 +261,51 @@ ipfw_nat(struct ip_fw_args *args, struct
 	    NULL)
 		goto badnat;
 	ip = mtod(mcl, struct ip *);
-	if (args->eh == NULL) {
+	/* 
+	 * In case of fragments, reassemble the packet 
+	 * before passing it to libalias.
+	 */
+	off = (args->eh == NULL) ? ip->ip_off : ntohs(ip->ip_off);
+	if (off & (IP_MF | IP_OFFMASK)) {
+		struct mbuf *reass;
+
+		/* 
+		 * Ip_reass() expects len & off in host byte order:
+		 * fix them in case we come from layer2.
+		 */
+		if (args->eh != NULL) {
+			ip->ip_len = ntohs(ip->ip_len);
+			ip->ip_off = ntohs(ip->ip_off);
+		}
+
+		/* Reassemble packet. */
+		reass = ip_reass(mcl);
+
+		/*
+		 * IP header checksum fixup after reassembly and leave header
+		 * in network byte order.
+		 */
+		if (reass != NULL) {
+			int hlen;
+			
+			ip = mtod(reass, struct ip *);
+			hlen = ip->ip_hl << 2;
+			ip->ip_len = htons(ip->ip_len);
+			ip->ip_off = htons(ip->ip_off);
+			ip->ip_sum = 0;
+			if (hlen == sizeof(struct ip))
+				ip->ip_sum = in_cksum_hdr(ip);
+			else
+				ip->ip_sum = in_cksum(reass, hlen);
+			if ((mcl = m_megapullup(reass, reass->m_pkthdr.len)) ==
+			    NULL)
+				goto badnat;
+			ip = mtod(mcl, struct ip *);
+		} else {
+			mcl = NULL;
+			goto badnat;
+		}
+	} else if (args->eh == NULL) {
 		ip->ip_len = htons(ip->ip_len);
 		ip->ip_off = htons(ip->ip_off);
 	}


More information about the svn-src-user mailing list