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