This is a low-level network debugging utility that utilizes raw packet i/o to construct and deconstruct tcp, udp, ipv4, arp, and icmp packets over ethernet.
net/tcp.h
- Committer:
- etherealflaim
- Date:
- 2010-10-12
- Revision:
- 3:c32d9660b888
- Parent:
- 2:e8e09adc41fc
- Child:
- 6:66c4cd9073aa
File content as of revision 3:c32d9660b888:
#ifndef TCP_H #define TCP_H #include "net.h" /// \file TCP Segment #define IPPROTO_TCP 0x06 /// TCP Segment memory map typedef struct { u16 source_port; ///< Source port (1-65535) u16 destination_port; ///< Destination port (1-65535) u32 sequence_number; ///< TCP Sequence number (initial one if SYN set) u32 acknowledge_number; ///< TCP Acknowledge number (valid if ACK set) unsigned data_offset_bytes_div4:4; ///< Length of this header (20) divided by 4 (should be 5) unsigned unused_0:4; ///< Unused, should be zero unsigned fin:1; ///< connection FINished (no more data from sender) unsigned syn:1; ///< SYNchronize sequence numbers unsigned rst:1; ///< ReSeT the connection unsigned psh:1; ///< PuSH to receiving application unsigned ack:1; ///< ACKnowledge fiend is significant unsigned urg:1; ///< URGent field is significant unsigned ece:1; ///< ECn Echo unsigned cwr:1; ///< Congestion Window Reduced u16 window_size; ///< TCP Maxumum window size (8192 is good) u16 checksum; ///< TCP checksum (computed with pseudo header) u16 urgent_pointer; ///< Urgent pointer (valid if URG set) /// Memory map for data if no options are set unsigned char data[]; } TCP_SegmentHeader; /// Convert from wire to host or host to wire endianness inline void fix_endian_tcp(TCP_SegmentHeader *segment) { segment->unused_0 ^= segment->data_offset_bytes_div4; segment->data_offset_bytes_div4 ^= segment->unused_0; segment->unused_0 ^= segment->data_offset_bytes_div4; fix_endian_u16(&segment->source_port); fix_endian_u16(&segment->destination_port); fix_endian_u16(&segment->window_size); // No fixing checksums fix_endian_u16(&segment->urgent_pointer); fix_endian_u32(&segment->sequence_number); fix_endian_u32(&segment->acknowledge_number); } /// Print the TCP segment header inline void print_tcp(TCP_SegmentHeader *segment) { main_log.printf("TCP Segment:"); main_log.printf(" Source: PORT %d", segment->source_port); main_log.printf(" Dest: PORT %d", segment->destination_port); main_log.printf(" TCP Seqno: 0x%08X", segment->sequence_number); main_log.printf(" TCP Ackno: 0x%08X", segment->acknowledge_number); main_log.printf(" Header: %d bytes", segment->data_offset_bytes_div4*4); if (segment->cwr) main_log.printf(" Flag: CWR"); if (segment->ece) main_log.printf(" Flag: ECE"); if (segment->urg) main_log.printf(" Flag: URG"); if (segment->ack) main_log.printf(" Flag: ACK"); if (segment->psh) main_log.printf(" Flag: PSH"); if (segment->rst) main_log.printf(" Flag: RST"); if (segment->syn) main_log.printf(" Flag: SYN"); if (segment->fin) main_log.printf(" Flag: FIN"); } /// Compute the pseudo header checksum with the given source, destination, and length inline u16 pseudo_header_checksum(IP_Address source, IP_Address destination, u16 length) { struct { IP_Address src, dst; u8 zeros; u8 proto; u16 length; } pseudoheader = {source, destination, 0, IPPROTO_TCP, length}; fix_endian_u16(&pseudoheader.length); return checksum(&pseudoheader, sizeof(pseudoheader)); } #endif