Sponge
CS144's user-space TCP library
tcp_over_ip.cc
Go to the documentation of this file.
1 #include "tcp_over_ip.hh"
2 
3 #include "ipv4_datagram.hh"
4 #include "ipv4_header.hh"
5 #include "parser.hh"
6 
7 #include <arpa/inet.h>
8 #include <stdexcept>
9 #include <unistd.h>
10 #include <utility>
11 
12 using namespace std;
13 
26 optional<TCPSegment> TCPOverIPv4Adapter::unwrap_tcp_in_ip(const InternetDatagram &ip_dgram) {
27  // is the IPv4 datagram for us?
28  // Note: it's valid to bind to address "0" (INADDR_ANY) and reply from actual address contacted
29  if (not listening() and (ip_dgram.header().dst != config().source.ipv4_numeric())) {
30  return {};
31  }
32 
33  // is the IPv4 datagram from our peer?
34  if (not listening() and (ip_dgram.header().src != config().destination.ipv4_numeric())) {
35  return {};
36  }
37 
38  // does the IPv4 datagram claim that its payload is a TCP segment?
39  if (ip_dgram.header().proto != IPv4Header::PROTO_TCP) {
40  return {};
41  }
42 
43  // is the payload a valid TCP segment?
44  TCPSegment tcp_seg;
45  if (ParseResult::NoError != tcp_seg.parse(ip_dgram.payload(), ip_dgram.header().pseudo_cksum())) {
46  return {};
47  }
48 
49  // is the TCP segment for us?
50  if (tcp_seg.header().dport != config().source.port()) {
51  return {};
52  }
53 
54  // should we target this source addr/port (and use its destination addr as our source) in reply?
55  if (listening()) {
56  if (tcp_seg.header().syn and not tcp_seg.header().rst) {
57  config_mutable().source = {inet_ntoa({htobe32(ip_dgram.header().dst)}), config().source.port()};
58  config_mutable().destination = {inet_ntoa({htobe32(ip_dgram.header().src)}), tcp_seg.header().sport};
59  set_listening(false);
60  } else {
61  return {};
62  }
63  }
64 
65  // is the TCP segment from our peer?
66  if (tcp_seg.header().sport != config().destination.port()) {
67  return {};
68  }
69 
70  return tcp_seg;
71 }
72 
76  // set the port numbers in the TCP segment
77  seg.header().sport = config().source.port();
78  seg.header().dport = config().destination.port();
79 
80  // create an Internet Datagram and set its addresses and length
81  InternetDatagram ip_dgram;
82  ip_dgram.header().src = config().source.ipv4_numeric();
83  ip_dgram.header().dst = config().destination.ipv4_numeric();
84  ip_dgram.header().len = ip_dgram.header().hlen * 4 + seg.header().doff * 4 + seg.payload().size();
85 
86  // set payload, calculating TCP checksum using information from IP header
87  ip_dgram.payload() = seg.serialize(ip_dgram.header().pseudo_cksum());
88 
89  return ip_dgram;
90 }
ParseResult::NoError
@ NoError
Success.
tcp_over_ip.hh
TCPHeader::rst
bool rst
rst flag
Definition: tcp_header.hh:45
TCPSegment::serialize
BufferList serialize(const uint32_t datagram_layer_checksum=0) const
Serialize the segment to a string.
Definition: tcp_segment.cc:30
ipv4_header.hh
IPv4Header::src
uint32_t src
src address
Definition: ipv4_header.hh:45
IPv4Datagram
IPv4 Internet datagram
Definition: ipv4_datagram.hh:8
TCPOverIPv4Adapter::wrap_tcp_in_ip
InternetDatagram wrap_tcp_in_ip(TCPSegment &seg)
Definition: tcp_over_ip.cc:75
TCPHeader::dport
uint16_t dport
destination port
Definition: tcp_header.hh:38
ipv4_datagram.hh
IPv4Header::dst
uint32_t dst
Definition: ipv4_header.hh:46
TCPHeader::syn
bool syn
syn flag
Definition: tcp_header.hh:46
IPv4Header::PROTO_TCP
static constexpr uint8_t PROTO_TCP
Protocol number for tcp.
Definition: ipv4_header.hh:11
TCPSegment::parse
ParseResult parse(const Buffer buffer, const uint32_t datagram_layer_checksum=0)
Parse the segment from a string.
Definition: tcp_segment.cc:12
TCPHeader::sport
uint16_t sport
source port
Definition: tcp_header.hh:37
IPv4Header::pseudo_cksum
uint32_t pseudo_cksum() const
pseudo-header's contribution to the TCP checksum
Definition: ipv4_header.cc:125
TCPHeader::doff
uint8_t doff
data offset
Definition: tcp_header.hh:41
IPv4Header::hlen
uint8_t hlen
header length (multiples of 32 bits)
Definition: ipv4_header.hh:35
std
IPv4Header::len
uint16_t len
total length of packet
Definition: ipv4_header.hh:37
Buffer::size
size_t size() const
Size of the string.
Definition: buffer.hh:41
TCPSegment::payload
const Buffer & payload() const
Definition: tcp_segment.hh:27
TCPOverIPv4Adapter::unwrap_tcp_in_ip
std::optional< TCPSegment > unwrap_tcp_in_ip(const InternetDatagram &ip_dgram)
Definition: tcp_over_ip.cc:26
IPv4Header::proto
uint8_t proto
protocol field
Definition: ipv4_header.hh:43
TCPSegment
TCP segment
Definition: tcp_segment.hh:10
IPv4Datagram::header
const IPv4Header & header() const
Definition: ipv4_datagram.hh:22
TCPSegment::header
const TCPHeader & header() const
Definition: tcp_segment.hh:24
parser.hh
IPv4Datagram::payload
const BufferList & payload() const
Definition: ipv4_datagram.hh:25