#include #include #include #include #include "ip.h" #include "main.h" #include "tcp.h" #include "util.h" #include "vars.h" int tcpconns = 0; static const char *tcp_ports[65536]; static const char *portcache(int port) { if (! tcp_ports[port]) { struct servent *sp; sp = getservbyport(port,"tcp"); if (sp) { char *tmp; tmp = malloc(1+strlen(sp->s_name)+1); sprintf(tmp,"=%s",sp->s_name); tcp_ports[port] = tmp; } else { tcp_ports[port] = ""; } } return(tcp_ports[port]); } void dump_tcp(void) { unsigned short int th_sport; unsigned short int th_dport; unsigned long int th_seq; unsigned long int th_ack; unsigned char th_off; unsigned char th_flags; unsigned short int th_win; unsigned short int th_sum; unsigned short int th_urp; int tcp_optlen; need(20,"minimum TCP header"); printx(pkt,2); th_sport = get16(0); printf("th_sport [%d%s]\n",th_sport,portcache(th_sport)); consume(2); printx(pkt,2); th_dport = get16(0); printf("th_dport [%d%s]\n",th_dport,portcache(th_dport)); consume(2); printx(pkt,4); th_seq = get32(0); printf("th_seq\n"); consume(4); printx(pkt,4); th_ack = get32(0); printf("th_ack\n"); consume(4); printx(pkt,1); th_off = get8(0) >> 4; printf("th_off=%d\n",th_off); if (th_off < 5) { printf("*** Claimed header size too small\n"); dumpabort(); } if (get8(0) & 0x0f) { printf("*** Reserved bit(s) set\n"); dumpabort(); } consume(1); printx(pkt,1); th_flags = get8(0); printf("th_flags "); { static struct { int bit; const char *name; } flags[] = { { 0x20, "URG" }, { 0x10, "ACK" }, { 0x08, "PSH" }, { 0x04, "RST" }, { 0x02, "SYN" }, { 0x01, "FIN" } }; int i; char c; c = '['; for (i=0;i<(sizeof(flags)/sizeof(flags[0]));i++) { if (th_flags & flags[i].bit) { printf("%c%s",c,flags[i].name); c = '|'; } } if (c == '[') printf("["); } printf("]\n"); if (th_flags & 0xc0) { printf("*** Reserved bit(s) set\n"); dumpabort(); } consume(1); printx(pkt,2); th_win = get16(0); printf("th_win [%d]\n",th_win); consume(2); printx(pkt,2); th_sum = get16(0); printf("th_sum\n"); consume(2); printx(pkt,2); th_urp = get16(0); printf("th_urp [%d]\n",th_urp); consume(2); tcp_optlen = (th_off - 5) * 4; need(tcp_optlen,"TCP options"); while (tcp_optlen > 0) { int n; switch (get8(0)) { case 0x00: n = 1; printx(pkt,1); printf("TCP option: end-of-list\n"); break; case 0x01: n = 1; printx(pkt,1); printf("TCP option: No-op\n"); break; case 0x02: n = get8(1); if (n > tcp_optlen) { printx(pkt,2); printf("...\n*** MSS option extends past end of options\n"); n = tcp_optlen; } else { printx(pkt,n); if (n != 4) { printf("TCP option: MSS (bad length)\n"); } else { unsigned short int mss; mss = get16(2); printf("TCP option: MSS=%d\n",mss); } } break; case 0x03: n = get8(1); if (n > tcp_optlen) { printx(pkt,2); printf("...\n*** WS option extends past end of options\n"); n = tcp_optlen; } else { printx(pkt,n); if (n != 3) { printf("TCP option: WS (bad length)\n"); } else { unsigned char scl; scl = get8(2); printf("TCP option: WS=%d (factor %d)\n",scl,1< tcp_optlen) { printx(pkt,2); printf("...\n*** SACK-OK option extends past end of options\n"); n = tcp_optlen; } else { printx(pkt,n); if (n != 2) { printf("TCP option: SACK-OK (bad length)\n"); } else { printf("TCP option: SACK-OK\n"); } } break; case 0x08: n = get8(1); if (n > tcp_optlen) { printx(pkt,2); printf("...\n*** TS option extends past end of options\n"); n = tcp_optlen; } else { printx(pkt,n); if (n != 10) { printf("TCP option: TS (bad length)\n"); } else { unsigned long int val; unsigned long int ech; val = get32(2); ech = get32(6); printf("TCP option: TS val=%08lx",val); if (th_flags & 0x10/*ACK*/) printf(" ech=%08lx",ech); printf("\n"); } } break; default: n = tcp_optlen; need(n,"TCP option flush"); printx(pkt,n); printf("Unrecognized TCP option(s)\n"); break; } consume(n); tcp_optlen -= n; } if (tcpconns && (pktleft > 0)) { int i; printf("=TCP= %lu.%lu.%lu.%lu/%d -> %lu.%lu.%lu.%lu/%d %08lx %d:",ip_src>>24,(ip_src>>16)&0xff,(ip_src>>8)&0xff,ip_src&0xff,th_sport,ip_dst>>24,(ip_dst>>16)&0xff,(ip_dst>>8)&0xff,ip_dst&0xff,th_dport,th_seq,pktleft); for (i=0;i