Date: Mon, 28 Jul 2008 12:32:42 GMT From: Rui Paulo <rpaulo@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 146109 for review Message-ID: <200807281232.m6SCWgOp097000@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=146109 Change 146109 by rpaulo@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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200807281232.m6SCWgOp097000>