/* * All we want to know about a TCP packet, in one place. * Compare with Linux's SKB structure. */ #include #include // This structure is suboptimal. The buffer be just a pointer, // managed with malloc() as needed (or, better yet, obtained // from a special heap for packets; see BSD's mbuf structure, // see https://www.openbsd.org/papers/asiabsdcon08-network.pdf // or https://www.youtube.com/watch?v=V85It0dGUF4). typedef struct pkt { struct pkt *next; // linked list of all packets struct pkt *prev; int invalid; // packet could not be received, ignore it char buf[IP_MAXPACKET]; // buffer holding the packet's raw bytes int len; // length of raw packet struct iphdr *ip; // points to packet's IP header in buf // (for us, same as buf's address, but viewed as // a different type) struct tcphdr *tcp; // points to packet's TCP header in buf int sockfd; // the raw socket used to receive or send struct sockaddr_in sin; // and its sockaddr struct. socklen_t clilen; // and its length char *payload; // TCP segment payload int payload_sz; // and its size uint32_t seq; // this packet's TCP segment's SEQ uint32_t ack; // and ACK to send back with it int rto_fd; // retransmission timout timer int polled_slot; // in pollfd array, same as fd } pkt_t; #define IS_SYN(p) ((p)->tcp->syn && !(p)->tcp->ack) #define IS_ACK(p) ((p)->tcp->ack && !(p)->tcp->syn && \ !(p)->tcp->rst && !(p)->tcp->fin) #define IS_RST(p) ((p)->tcp->rst) #define IS_FIN(p) ((p)->tcp->fin && !(p)->tcp->ack) #define IS_FINACK(p) ((p)->tcp->fin && (p)->tcp->ack) #define GET_ACK(p) (ntohl((p)->tcp->ack_seq)) char *tcp_states[] = { "NO_SUCH_STATE", "TCP_ESTABLISHED", "TCP_SYN_SENT", "TCP_SYN_RECV", "TCP_FIN_WAIT1", "TCP_FIN_WAIT2", "TCP_TIME_WAIT", "TCP_CLOSE", "TCP_CLOSE_WAIT", "TCP_LAST_ACK", "TCP_LISTEN", "TCP_CLOSING" }; #define ADDR2A(n) (inet_ntoa(*(struct in_addr *)&(n))) typedef struct { uint8_t kind; uint8_t size; } tcp_option_t;