PERFORCE change 146109 for review

Rui Paulo rpaulo at FreeBSD.org
Mon Jul 28 12:32:43 UTC 2008


http://perforce.freebsd.org/chv.cgi?CH=146109

Change 146109 by rpaulo at rpaulo_epsilon on 2008/07/28 12:31:58

	Move helper.c contents into handler.c
	Implement TCP option processing.
	Add more SEQ/ACK validation.
	Remove some const qualifiers.
	Dump some RFC1323 variables.

Affected files ...

.. //depot/projects/soc2008/rpaulo-tcpad/Makefile#12 edit
.. //depot/projects/soc2008/rpaulo-tcpad/debug.h#5 edit
.. //depot/projects/soc2008/rpaulo-tcpad/dumper.c#10 edit
.. //depot/projects/soc2008/rpaulo-tcpad/handler.c#16 edit
.. //depot/projects/soc2008/rpaulo-tcpad/helper.c#4 delete
.. //depot/projects/soc2008/rpaulo-tcpad/helper.h#2 delete
.. //depot/projects/soc2008/rpaulo-tcpad/linkhdr.c#9 edit
.. //depot/projects/soc2008/rpaulo-tcpad/linkhdr.h#3 edit
.. //depot/projects/soc2008/rpaulo-tcpad/verify.c#4 edit
.. //depot/projects/soc2008/rpaulo-tcpad/verify.h#3 edit

Differences ...

==== //depot/projects/soc2008/rpaulo-tcpad/Makefile#12 (text+ko) ====

@@ -1,7 +1,7 @@
-# $P4: //depot/projects/soc2008/rpaulo-tcpad/Makefile#11 $
+# $P4: //depot/projects/soc2008/rpaulo-tcpad/Makefile#12 $
 
 PROG=tcpad
-SRCS=main.c device.c linkhdr.c handler.c helper.c dumper.c timer.c verify.c
+SRCS=main.c device.c linkhdr.c handler.c dumper.c timer.c verify.c
 CFLAGS+=-DDEBUG -ggdb
 CFLAGS+=-DDUMPER_PATH=\"dumpfiles\"
 WARNS=5

==== //depot/projects/soc2008/rpaulo-tcpad/debug.h#5 (text+ko) ====

@@ -23,7 +23,7 @@
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
- * $P4: //depot/projects/soc2008/rpaulo-tcpad/debug.h#4 $
+ * $P4: //depot/projects/soc2008/rpaulo-tcpad/debug.h#5 $
  */
 
 #ifndef _DEBUG_H_
@@ -37,6 +37,7 @@
 #define DEBUG_DUMP	0x004
 #define DEBUG_LINK	0x008
 #define DEBUG_SEQ	0x010
+#define DEBUG_TOPTS	0x020
 #define DEBUG_ALL	0xfff
 
 #define DPRINTF(level, ...) do {			\

==== //depot/projects/soc2008/rpaulo-tcpad/dumper.c#10 (text+ko) ====

@@ -23,7 +23,7 @@
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
- * $P4: //depot/projects/soc2008/rpaulo-tcpad/dumper.c#9 $
+ * $P4: //depot/projects/soc2008/rpaulo-tcpad/dumper.c#10 $
  */
 
 #include <assert.h>
@@ -33,8 +33,13 @@
 #include <stdlib.h>
 #include <stdarg.h>
 #include <unistd.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/socketvar.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/tcp_var.h>
 #include <arpa/inet.h>
-#include <sys/queue.h>
 #include <pcap.h>
 
 #include "tcpad.h"
@@ -87,12 +92,14 @@
 		snprintf(path, sizeof(path), "%s/dump%d.txt", DUMPER_PATH, i);
 		if (access(path, F_OK) != 0)
 			break;
+		/* XXX: race [1] */
 	}
 	if (i == 3000) {
 		fprintf(stderr, "%s: %s is full!\n", __func__, DUMPER_PATH);
 		return;
 	}
 
+	/* XXX: race [1] */
 	fp = fopen(path, "w");
 	if (fp == NULL) {
 		warn("failure to open dump file: %s", path);
@@ -111,7 +118,8 @@
 	    pcap_dump((u_char *)pd, &dp->pheader, dp->headers);
 	pcap_dump_close(pd);
 
-	fprintf(fp, "tcpad (TCP Anomaly Detector) version xx.xx\n\n");
+	fprintf(fp, "tcpad (TCP Anomaly Detector) version "
+	    TCPAD_VERSION "\n\n");
 	fprintf(fp, "Related pcap file:\t%s\n", cappath);
 	fprintf(fp, "Error message:\t\t");
 	va_start(ap, fmt);
@@ -123,7 +131,7 @@
 	fprintf(fp, "%18s |\n", inet_ntoa(cp->dv4addr));
 	fprintf(fp, "TCP Port:\t| %18d | %18d |\n", cp->sport, cp->dport);
 	fprintf(fp, "\n");
-#define DUMPER_TPFIELD(cp, field, name)			do {		\
+#define DUMPER_TPFIELD(cp, field, name)	do {				\
 	fprintf(fp, "%s:\t", name);					\
 	if (strlen(name) < 7)						\
 		fprintf(fp, "\t");					\
@@ -149,6 +157,10 @@
 	DUMPER_TPFIELD(cp, rcv_nxt, "RCV.NXT");
 	DUMPER_TPFIELD(cp, rcv_wnd, "RCV.WND");
 	DUMPER_TPFIELD(cp, rcv_up, "RCV.UP");
+
+	fprintf(fp, "\nRFC 1323 variables:\n");
+	DUMPER_TPFIELD(cp, snd_scale, "SND.SCALE");
+	DUMPER_TPFIELD(cp, rcv_scale, "RCV.SCALE");
 #undef DUMPER_TPFIELD
 	fclose(fp);
 }

==== //depot/projects/soc2008/rpaulo-tcpad/handler.c#16 (text+ko) ====

@@ -23,23 +23,19 @@
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
- * $P4: //depot/projects/soc2008/rpaulo-tcpad/handler.c#15 $
+ * $P4: //depot/projects/soc2008/rpaulo-tcpad/handler.c#16 $
  */
 
-#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/queue.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
+#include <sys/socketvar.h>
 #include <netinet/ip.h>
 #include <netinet/tcp.h>
-#include <netinet/tcp_fsm.h>
-#include <netinet/tcp_seq.h>
-#include <arpa/inet.h>
+#include <netinet/tcp_var.h>
 #include <pcap.h>
 
 #include "tcpad.h"
@@ -47,44 +43,97 @@
 #include "linkhdr.h"
 #include "handler.h"
 #include "dumper.h"
-#include "helper.h"
-#include "debug.h"
+
+static struct tcpc *
+find_conn(struct in_addr ipsrc, struct in_addr ipdst, unsigned short
+    sport, unsigned short dport)
+{
+	struct tcpc *cp;
+
+	LIST_FOREACH(cp, &tcpchead, entries) {
+		if (memcmp(&cp->sv4addr, &ipsrc, sizeof(struct in_addr)) == 0 &&
+		    memcmp(&cp->dv4addr, &ipdst, sizeof(struct in_addr)) == 0 &&
+		    cp->sport == sport && cp->dport == dport) {
+			return (cp);
+		}
+	}
+	return (NULL);
+}
 
 void
 tcpad_pcaphandler(unsigned char *user, const struct pcap_pkthdr *ph,
     const unsigned char *bytes)
 {
-	const struct ip *ip;
-	const struct tcphdr *th;
-	struct tcphdr tcp;
+	struct ip *ip;
+	struct tcphdr *th;
 	int linkhlen;
 	struct tcpc *cp, *rcp;
+	unsigned char *wirepkt;
+	unsigned char *inetpkt;
+	int added;
+	unsigned char topts[40];
+
+	/* XXX: make sure the packet is a valid TCP packet */
 
 	linkhlen = (int)*user;
-	ip = (const struct ip *)linkhdr_remove(bytes, linkhlen);
-	th = (const struct tcphdr *)linkhdr_remove(bytes,
-	    linkhlen + sizeof(struct ip));
+	wirepkt = malloc(snaplen);
+	memcpy(wirepkt, bytes, snaplen);
+	inetpkt = linkhdr_remove(wirepkt, linkhlen);
+	ip = (struct ip *)inetpkt;
+	th = (struct tcphdr *)(inetpkt + sizeof(struct ip));
+	memcpy(topts, (inetpkt + sizeof(struct ip) + sizeof(struct tcphdr)),
+	    sizeof(topts));
+
+	/* Local endpoint */
+	cp = find_conn(ip->ip_src, ip->ip_dst, ntohs(th->th_sport),
+	    ntohs(th->th_dport));
 
-	memcpy(&tcp, th, sizeof(tcp));
+	/* Remote endpoint */
+	rcp = find_conn(ip->ip_dst, ip->ip_src, ntohs(th->th_dport),
+	    ntohs(th->th_sport));
 
-	tcp.th_seq = ntohl(tcp.th_seq);
-	tcp.th_ack = ntohl(tcp.th_ack);
-	tcp.th_win = ntohs(tcp.th_win);
-	tcp.th_urp = ntohs(tcp.th_urp);
-	tcp.th_sport = ntohs(tcp.th_sport);
-	tcp.th_dport = ntohs(tcp.th_dport);
+	/*
+	 * Erase the data in the TCP packet.
+	 * XXX: This breaks the checksum.
+	 *
+	 * Pun intended :-)
+	 */
+	memset((inetpkt + sizeof(struct ip) + th->th_off * 4), 'R',
+	    snaplen - (sizeof(struct ip) + th->th_off * 4) - 2);
 
-	/* Local endpoint */
-	cp = find_conn(ip->ip_src, ip->ip_dst, tcp.th_sport,
-	    tcp.th_dport);
+	added = 0;
+	if (cp && cp->pktshead) {
+		added = 1;
+		dumper_addpkt(cp, ph, wirepkt);
+	}
 
-	/* Remote endpoint */
-	rcp = find_conn(ip->ip_dst, ip->ip_src, tcp.th_dport,
-	    tcp.th_sport);
+	/* 
+	 * We can only do this here because we need to save the bytes in
+	 * network order (above call to dumper_addpkt()).
+	 */
+	th->th_seq = ntohl(th->th_seq);
+	th->th_ack = ntohl(th->th_ack);
+	th->th_win = ntohs(th->th_win);
+	th->th_urp = ntohs(th->th_urp);
+	th->th_sport = ntohs(th->th_sport);
+	th->th_dport = ntohs(th->th_dport);
 
-	if (cp && cp->pktshead)
+	cp = tcpad_verify_output(cp, rcp, ip, th, topts);
+	/*
+	 * If we didn't add the packet it was a SYN packet and a connection
+	 * structure was created. Now that we have one, add the packet to the
+	 * dumper.
+	 */
+	if (!added && cp && cp->pktshead) {
+		/*
+		 * We can't use wirepkt buffer because we changed some TCP
+		 * fields to host order. Let's hope there was no sensitive
+		 * data with the SYN. (Pratically all TCP/IP stacks nowadays
+		 * don't send data with the SYN anyway).
+		 */
 		dumper_addpkt(cp, ph, bytes);
+	}
+	tcpad_verify_input(rcp, cp, ip, th, topts);
 
-	cp = tcpad_verify_output(cp, rcp, ip, &tcp);
-	tcpad_verify_input(rcp, cp, ip, &tcp);
+	free(wirepkt);
 }

==== //depot/projects/soc2008/rpaulo-tcpad/linkhdr.c#9 (text+ko) ====

@@ -23,7 +23,7 @@
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
- * $P4: //depot/projects/soc2008/rpaulo-tcpad/linkhdr.c#8 $
+ * $P4: //depot/projects/soc2008/rpaulo-tcpad/linkhdr.c#9 $
  */
 
 #include <sys/types.h>
@@ -77,8 +77,8 @@
 }
 
 
-const unsigned char *
-linkhdr_remove(const unsigned char *bytes, unsigned int skip)
+unsigned char *
+linkhdr_remove(unsigned char *bytes, unsigned int skip)
 {
 	/* XXX: more computation needed for some interfaces, e.g.: SLIP, 
 	  PPP, etc. */

==== //depot/projects/soc2008/rpaulo-tcpad/linkhdr.h#3 (text+ko) ====

@@ -23,14 +23,14 @@
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
- * $P4: //depot/projects/soc2008/rpaulo-tcpad/linkhdr.h#2 $
+ * $P4: //depot/projects/soc2008/rpaulo-tcpad/linkhdr.h#3 $
  */
 
 #ifndef _LINKHDR_H_
 #define _LINKHDR_H_
 
 int	linkhdr_headerlen(int dlt);
-const unsigned char *
-	linkhdr_remove(const unsigned char *bytes, unsigned int skip);
+unsigned char *
+	linkhdr_remove(unsigned char *bytes, unsigned int skip);
 
 #endif /* _LINKHDR_H_ */

==== //depot/projects/soc2008/rpaulo-tcpad/verify.c#4 (text+ko) ====

@@ -23,7 +23,7 @@
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
- * $P4: //depot/projects/soc2008/rpaulo-tcpad/verify.c#3 $
+ * $P4: //depot/projects/soc2008/rpaulo-tcpad/verify.c#4 $
  */
 
 #include <stdio.h>
@@ -32,12 +32,12 @@
 #include <time.h>
 #include <sys/queue.h>
 #include <sys/types.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
+#include <sys/socketvar.h>
 #include <netinet/ip.h>
 #include <netinet/tcp.h>
 #include <netinet/tcp_fsm.h>
 #include <netinet/tcp_seq.h>
+#include <netinet/tcp_var.h>
 #include <arpa/inet.h>
 #include <pcap.h>
 
@@ -46,9 +46,13 @@
 #include "dumper.h"
 #include "verify.h"
 
+
+static void	tcpad_verify_topts(const unsigned char *topts, struct tcpcb *tp,
+    int flags, int direction);
+
 struct tcpc *
 tcpad_verify_output(struct tcpc *cp, struct tcpc *rcp, const struct ip *ip,
-    const struct tcphdr *th)
+    const struct tcphdr *th, const unsigned char *topts)
 {
 	unsigned int tlen;
 	struct tcpcb *tp;
@@ -73,17 +77,19 @@
 	    !(th->th_flags & TH_RST) && !(th->th_flags & TH_FIN)) {
 		if (cp) {
 			if (th->th_seq != tp->iss) {
-				dumper_error(cp, "connection already being "
-				    "tracked");
+				if (tp->t_state != TCPS_TIME_WAIT) {
+					dumper_error(cp, "connection already "
+					    "being tracked");
+				}
 				dumper_free(cp);
 				LIST_REMOVE(cp, entries);
 				free(cp);
-				return NULL;
 			} else
 				/* It's a SYN retransmit. */
-				return cp;
+				return (cp);
 		}
 
+
 		cp = malloc(sizeof(*cp));
 		memset(cp, 0, sizeof(*cp));
 		tp = &cp->tcb;
@@ -104,8 +110,13 @@
 		    tp);
 		tp->t_state = TCPS_SYN_SENT;
 		tp->iss = th->th_seq;
+		tp->snd_una = tp->iss;
 		tp->snd_nxt = tp->iss + 1;
 		tp->snd_wnd = th->th_win;
+		tp->snd_wl1 = th->th_seq;
+		tp->snd_wl2 = th->th_ack;
+		tcpad_verify_topts(topts, tp, th->th_flags,
+		    TCPAD_VERIFY_DIRECTION_OUT);
 	}
 	/*
 	 * SYNcronize and ACKnowledge sequence numbers.
@@ -113,9 +124,19 @@
 	else if ((th->th_flags & TH_SYN) && (th->th_flags & TH_ACK)) {
 		switch (tp->t_state) {
 		case TCPS_SYN_RECEIVED:
+			/* 
+			 * tcpcb was already created in the input routine
+			 * when the SYN was transmitted. Fill the remaining
+			 * values.
+			 */
 			tp->iss = th->th_seq;
+			tp->snd_una = tp->iss;
 			tp->snd_nxt = tp->iss + 1;
 			tp->snd_wnd = th->th_win;
+			tp->snd_wl1 = th->th_seq;
+			tp->snd_wl2 = th->th_ack;
+			tcpad_verify_topts(topts, tp, th->th_flags,
+			    TCPAD_VERIFY_DIRECTION_OUT);
 			break;
 		}
 
@@ -124,21 +145,24 @@
 	 * ReSeT. ;-)
 	 */
 	else if (th->th_flags & TH_RST) {
-		if (cp == NULL) return NULL;
+		/* Ignore unknown RSTs */
+		if (cp == NULL)
+			return (NULL);
 
 		switch (tp->t_state) {
 		case TCPS_SYN_RECEIVED:
-			if (SEQ_GEQ(th->th_ack, tp->rcv_nxt)) {
-				DPRINTF(DEBUG_FSM, "FSM transition: %p "
-				    "SYN_RECEIVED -> CLOSED\n", tp);
-				LIST_REMOVE(cp, entries);
-				free(cp);
-			} else {
-                                dumper_error(cp, "RST: ACK < snd_nxt");
-                                LIST_REMOVE(cp, entries);
-                                free(cp);
-
-			}
+			/*
+			 * XXX: We received a RST for a SYN. This end
+			 * was not really in SYN_RECEIVED state, but this
+			 * is a side-effect of creating both virtual endpoints
+			 * when we see a SYN on the wire.
+			 *
+			 * Leave the ACK validation to the input routine.
+			 */
+			DPRINTF(DEBUG_FSM, "FSM transition: %p "
+			    "SYN_RECEIVED -> CLOSED\n", tp);
+			LIST_REMOVE(cp, entries);
+			free(cp);
 			break;
 		}
 	}
@@ -146,6 +170,9 @@
 	 * FINish.
 	 */
 	else if ((th->th_flags & TH_FIN) && (th->th_flags & TH_ACK)) {
+		if (cp == NULL)
+			return (NULL);
+
 		switch (tp->t_state) {
 		case TCPS_ESTABLISHED:
 			tp->t_state = TCPS_FIN_WAIT_1;
@@ -161,6 +188,19 @@
 
 	}
 	else if (th->th_flags & TH_ACK) {
+		if (cp == NULL)
+			return (NULL);
+
+		switch (tp->t_state) {
+		case TCPS_ESTABLISHED:
+			if (th->th_seq != tp->snd_nxt)
+				printf("wrong seq %u %u\n", th->th_seq,
+				    tp->snd_nxt);
+			if (th->th_ack != tp->rcv_nxt)
+				printf("wrong ack %u %u\n", th->th_ack,
+				    tp->rcv_nxt);
+			break;
+		}
 	}
 
 	return (cp);
@@ -169,7 +209,7 @@
 
 struct tcpc *
 tcpad_verify_input(struct tcpc *cp, struct tcpc *rcp, const struct ip *ip,
-    const struct tcphdr *th)
+    const struct tcphdr *th, const unsigned char *topts)
 {
 	struct tcpcb *tp;
 	unsigned int tlen;
@@ -212,6 +252,8 @@
 		tp->irs = th->th_seq;
 		tp->rcv_nxt = tp->irs + 1;
 		tp->rcv_wnd = th->th_win;
+		tcpad_verify_topts(topts, tp, th->th_flags,
+		    TCPAD_VERIFY_DIRECTION_IN);
 	}
 	/*
 	 * SYNcronize and ACKnowledge sequence numbers.
@@ -219,18 +261,29 @@
 	else if ((th->th_flags & TH_SYN) && (th->th_flags & TH_ACK)) {
 		switch (tp->t_state) {
 		case TCPS_SYN_SENT:
-			if (th->th_ack != tp->iss + 1) {
-				dumper_error(cp, "ACK != ISS + 1");
+			if (SEQ_LEQ(th->th_ack, tp->iss) ||
+			    SEQ_GT(th->th_ack, tp->snd_nxt)) {
+				dumper_error(cp, "SEG.ACK =< ISS or "
+				    "SEG.ACK > SND.NXT");
 				dumper_free(cp);
 				LIST_REMOVE(cp, entries);
 				free(cp);
 				return (NULL);
 			}
-			DPRINTF(DEBUG_FSM, "FSM transition: %p SYN_SENT -> "
-			    "ESTABLISHED\n", tp);
-			tp->t_state = TCPS_ESTABLISHED;
+			tp->irs = th->th_seq;
+			tp->rcv_nxt = th->th_seq + 1;
 			tp->rcv_wnd = th->th_win;
-			tp->irs = th->th_seq;
+			tp->snd_una = th->th_ack;
+			if (SEQ_GT(tp->snd_una, tp->iss)) {
+				tp->t_state = TCPS_ESTABLISHED;
+				DPRINTF(DEBUG_FSM, "FSM transition: %p "
+				    "SYN_SENT -> ESTABLISHED\n", tp);
+			} else {
+				dumper_error(cp, "SYN not acked");
+				dumper_free(cp);
+				LIST_REMOVE(cp, entries);
+				free(cp);
+			}
 			break;
 		default:
 			dumper_error(cp, "SYN/ACK received, state != SYN_SENT");
@@ -247,11 +300,14 @@
 	 * ReSeT. ;-)
 	 */
 	else if (th->th_flags & TH_RST) {
-		if (cp == NULL) return NULL;
+		/* Ignore unknown RSTs */
+		if (cp == NULL)
+			return (NULL);
 
 		switch (tp->t_state) {
 		case TCPS_SYN_SENT:
-			if (SEQ_GEQ(th->th_ack, tp->snd_nxt)) {
+			if (SEQ_GEQ(th->th_ack, tp->snd_una) &&
+			    SEQ_LEQ(th->th_ack, tp->snd_nxt)) {
 				DPRINTF(DEBUG_FSM, "FSM transition: %p "
 				    "SYN_SENT -> CLOSED\n", tp);
 				dumper_free(cp);
@@ -263,12 +319,18 @@
                                 LIST_REMOVE(cp, entries);
 				free(cp);
 			}
+			break;
+		default:
+			dumper_error(cp, "RST with no known state");
 		}
 	}
 	/*
 	 * FINish.
 	 */
 	else if ((th->th_flags & TH_FIN) && (th->th_flags & TH_ACK)) {
+		if (cp == NULL)
+			return (NULL);
+
 		switch (tp->t_state) {
 		case TCPS_ESTABLISHED:
 			tp->t_state = TCPS_CLOSE_WAIT;
@@ -281,16 +343,30 @@
 			    "FIN_WAIT_2 -> TIME_WAIT\n", tp);
 			break;
 		default:
+			if (cp)
+				dumper_error(cp, "FIN with no known state");
 			break;
 		}
 	}
 	
 	else if (th->th_flags & TH_ACK) {
+		if (cp == NULL)
+			return (NULL);
+
 		switch (tp->t_state) {
 		case TCPS_SYN_RECEIVED:
-			tp->t_state = TCPS_ESTABLISHED;	
-			DPRINTF(DEBUG_FSM, "FSM transition: %p SYN_RECEIVED "
-			    "-> ESTABLISHED\n", tp);
+			if (SEQ_GEQ(th->th_ack, tp->snd_una) &&
+			    SEQ_LEQ(th->th_ack, tp->snd_nxt)) {
+				tp->t_state = TCPS_ESTABLISHED;	
+				DPRINTF(DEBUG_FSM, "FSM transition: %p "
+				    "SYN_RECEIVED -> ESTABLISHED\n", tp);
+			} else {
+				dumper_error(cp, "ACK < SND.UNA or "
+				    "ACK > SND.NXT");
+				dumper_free(cp);
+				LIST_REMOVE(cp, entries);
+				free(cp);
+			}
 			break;
 		case TCPS_FIN_WAIT_1:
 			tp->t_state = TCPS_FIN_WAIT_2;
@@ -309,8 +385,136 @@
 			LIST_REMOVE(cp, entries);
 			free(cp);
 			break;
+		case TCPS_ESTABLISHED:
+			/* SEQ processing */
+			if (tlen == 0) {
+				if (tp->rcv_wnd == 0) {
+					if (th->th_seq != tp->rcv_nxt) {
+						dumper_error(cp, "SEQ.SEQ != "
+						    "RCV.NXT");
+						dumper_free(cp);
+						LIST_REMOVE(cp, entries);
+						free(cp);
+					}
+				} else {
+					if (SEQ_LT(th->th_seq, tp->rcv_nxt) ||
+					    SEQ_GEQ(th->th_seq, tp->rcv_nxt +
+						tp->rcv_wnd)) {
+						dumper_error(cp, "SEQ.SEQ < "
+						    "RCV.NXT or SEG.SEQ >= "
+						    "RCV.NXT + RCV.WND");
+						dumper_free(cp);
+					}
+				}
+			} else {
+				if (tp->rcv_wnd == 0) {
+					dumper_error(cp, "SEG.LEN > 0 and "
+					    "RCV.WND == 0");
+					dumper_free(cp);
+					LIST_REMOVE(cp, entries);
+					free(cp);
+					return (NULL);
+				} else {
+					if (SEQ_LT(th->th_seq + tlen,
+						tp->rcv_nxt) ||
+					    SEQ_GEQ(th->th_seq + tlen,
+						tp->rcv_nxt + tp->rcv_wnd))
+						printf("strange seq\n");
+
+
+				}
+
+			}
+			/* ACK processing */
+			if (SEQ_GEQ(th->th_ack, tp->snd_una) &&
+			    SEQ_LEQ(th->th_ack, tp->snd_nxt)) {
+				tp->snd_una = th->th_ack;
+				/* update send window */
+				if (SEQ_LT(tp->snd_wl1, th->th_seq) ||
+				    (tp->snd_wl1 == th->th_seq &&
+				     SEQ_LEQ(tp->snd_wl2, th->th_ack))) {
+					tp->snd_wnd = th->th_win;
+					tp->snd_wl1 = th->th_seq;
+					tp->snd_wl2 = th->th_ack;
+				}
+			}
+			break;
+		default:
+			if (cp)
+				dumper_error(cp, "ACK with no known state");
 		}
 	}
 
 	return (cp);
 }
+
+
+static void
+tcpad_verify_topts(const unsigned char *topts, struct tcpcb *tp, int flags,
+    int direction)
+{
+	int i;
+
+	for (i = 0; i < 40; i++) {
+		switch (topts[i]) {
+		case TCPOPT_EOL:
+			DPRINTF(DEBUG_TOPTS, "EOL option found\n");
+			i = 40;
+			break;
+		case TCPOPT_NOP:
+			DPRINTF(DEBUG_TOPTS, "NOP option found\n");
+			break;
+		case TCPOPT_MAXSEG:
+			if (i < 34 && topts[i+1] == TCPOLEN_MAXSEG) {
+				uint16_t mss;
+
+				memcpy(&mss, topts+i+2, 2);
+				mss = ntohs(mss);
+				DPRINTF(DEBUG_TOPTS, "MSS option "
+				    "found: %d\n", mss);
+
+				if (direction == TCPAD_VERIFY_DIRECTION_OUT &&
+				    (flags & (TH_SYN|TH_ACK)) == TH_SYN) {
+						tp->t_maxseg = mss;
+				}
+
+			}
+			i += 3;
+			break;
+		case TCPOPT_WINDOW:
+			if (i < 35 && topts[i+1] == TCPOLEN_WINDOW) {
+				uint8_t wscale;
+				memcpy(&wscale, topts+i+2, 1);
+				DPRINTF(DEBUG_TOPTS, "WSCALE option "
+				    "found: %d\n", wscale);
+				if (direction == TCPAD_VERIFY_DIRECTION_IN)
+					tp->rcv_scale = wscale;
+				else
+					tp->snd_scale = wscale;
+			}
+			i += 2;
+			break;
+		case TCPOPT_TIMESTAMP:
+			if (i < 29 && topts[i+1] == TCPOLEN_TIMESTAMP) {
+				uint32_t tsval;
+				uint32_t tsecr;
+				memcpy(&tsval, topts+i+2, 4);
+				memcpy(&tsecr, topts+i+6, 4);
+				DPRINTF(DEBUG_TOPTS, "TIMESTAMP option "
+				    "found: %u %u\n", tsval, tsecr);
+			}
+			i += 9;
+			break;
+		case TCPOPT_SACK_PERMITTED:
+			DPRINTF(DEBUG_TOPTS, "SACK_PERM option found\n");
+			i += 1;
+			break;
+		case TCPOPT_SACK:
+			DPRINTF(DEBUG_TOPTS, "SACK option found\n");
+			i += 1;
+			break;
+		default:
+			DPRINTF(DEBUG_TOPTS, "unkown option: %d\n", topts[i]);
+		}
+	}
+}

==== //depot/projects/soc2008/rpaulo-tcpad/verify.h#3 (text+ko) ====

@@ -23,10 +23,13 @@
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
- * $P4: //depot/projects/soc2008/rpaulo-tcpad/verify.h#2 $
+ * $P4: //depot/projects/soc2008/rpaulo-tcpad/verify.h#3 $
  */
 
+#define TCPAD_VERIFY_DIRECTION_IN	0
+#define TCPAD_VERIFY_DIRECTION_OUT	1
+
 struct tcpc *	tcpad_verify_output(struct tcpc *cp, struct tcpc *rcp,
-    const struct ip *ip, const struct tcphdr *th);
+    const struct ip *ip, const struct tcphdr *th, const unsigned char *topts);
 struct tcpc *	tcpad_verify_input(struct tcpc *cp, struct tcpc *rcp,
-    const struct ip *ip, const struct tcphdr *th);
+    const struct ip *ip, const struct tcphdr *th, const unsigned char *topts);


More information about the p4-projects mailing list