switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Packets / DefaultBundle / TCPPacket.cc
1 // $Id$
2 //
3 // Copyright (C) 2009
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26
27 /** \file
28     \brief TCPPacket non-inline non-template implementation */
29
30 #include "TCPPacket.hh"
31 //#include "TCPPacket.ih"
32
33 // Custom includes
34 #include <iomanip>
35 #include <boost/io/ios_state.hpp>
36 #include <senf/Utils/IpChecksum.hh>
37 #include "IPv6Packet.hh"
38
39 #define prefix_
40 //-/////////////////////////////////////////////////////////////////////////////////////////////////
41
42 namespace {
43     SENF_PACKET_REGISTRY_REGISTER( senf::IpTypes, 6, senf::TCPPacket);
44 }
45
46 //-/////////////////////////////////////////////////////////////////////////////////////////////////
47 // senf::TCPPacketParser
48
49 prefix_ boost::uint16_t senf::TCPPacketParser::calcChecksum()
50     const
51 {
52     IpChecksum summer;
53     // first on to the awkward part: the IP pseudo header
54     IPv4Packet ipv4 (packet().rfind<IPv4Packet>(nothrow));
55     if (ipv4) {
56         // Pseudo header defined in RFC793
57         // begin
58         summer.feed( ipv4->source().i(),
59                      ipv4->source().i() + IPv4Packet::Parser::source_t::fixed_bytes );
60         ///\fixme What about a hop-by-hop routing option? Which destination is used in IPv4 ?
61         summer.feed( ipv4->destination().i(),
62                      ipv4->destination().i() + IPv4PacketParser::destination_t::fixed_bytes );
63         // include zero byte
64         summer.feed( 0u );
65         ///\fixme May there be another header between the IPv4 header and TCP? if so, we
66         /// need to hack the correct protocol number here ...
67         summer.feed( 6u );
68
69         // feed 1st byte and 2nd byte from field tcp length
70         summer.feed(boost::uint16_t(data().size()) & 0xff00);
71         summer.feed(boost::uint16_t(data().size()) & 0x00ff);
72         // end pseudo header
73     }
74     else {
75     // Pseudo header defined in RFC2460
76         IPv6Packet ipv6 (packet().rfind<IPv6Packet>(nothrow));
77         if (ipv6) {
78             summer.feed( ipv6->source().i(),
79                          ipv6->source().i() + IPv6Packet::Parser::source_t::fixed_bytes );
80             ///\todo Implement routing header support
81             // The destination used here must be the *final* destination ...
82             summer.feed( ipv6->destination().i(),
83                          ipv6->destination().i() + IPv6PacketParser::destination_t::fixed_bytes );
84             // This is a simplification. The value is really 32bit to support UDP Jumbograms
85             // (RFC2147). However, skipping an even number of 0 bytes does not change the checksum
86             // RFC2460 specifies, that this must always be 6, not the value used in the ipv6
87             // header
88             // feed 1st byte and 2nd byte from field tcp length
89             summer.feed(boost::uint16_t(data().size()) & 0xff00);
90             summer.feed(boost::uint16_t(data().size()) & 0x00ff);
91             // include zero byte
92             summer.feed( 0u );
93             // add TCP protocol number
94             summer.feed( 6u );
95         }
96     }
97
98     // since header are 16 / even 32bit aligned we don't have to care for padding. since IpChecksum
99     // cares for padding at the final summing we don't have to care is the payload is 16nbit-aligned, too.
100
101     // iterate till checksum field and skip 2 bytes,
102     // iterate over rest of tcp header and tcp payload
103     summer.feed( i(), i()+16 );
104     summer.feed( i()+18, data().end() );
105
106     boost::uint16_t rv (summer.sum());
107     return rv ? rv : 0xffffu;
108
109 }
110
111 //-/////////////////////////////////////////////////////////////////////////////////////////////////
112 // senf::TCPPacketType
113
114 prefix_ void senf::TCPPacketType::dump(packet p, std::ostream & os)
115 {
116     boost::io::ios_all_saver ias(os);
117     os << "TCP:\n"
118        << senf::fieldName("source port")               << p->source() << "\n"
119        << senf::fieldName("destination port")          << p->destination() << "\n"
120        << senf::fieldName("sequence number")           << p->sequencenumber() << "\n"
121        << senf::fieldName("acknowledgment number")     << p->acknowledgmentnumber() << "\n"
122        << senf::fieldName("data offset")               << p->dataoffset() << "\n"
123        << senf::fieldName("urgent flag")               << p->urgf() << "\n"
124        << senf::fieldName("ack flag")                  << p->ackf() << "\n"
125        << senf::fieldName("push flag")                 << p->pshf() << "\n"
126        << senf::fieldName("reset flag")                << p->rstf() << "\n"
127        << senf::fieldName("syn flag")                  << p->synf() << "\n"
128        << senf::fieldName("fin flag")                  << p->finf() << "\n"
129        << senf::fieldName("window size")               << p->window() << "\n"
130        << senf::fieldName("checksum")
131        << "0x" << std::hex << std::setw(4) << std::setfill('0') << std::right << p->checksum() << "\n"
132        << senf::fieldName("urgent pointer")            << p->urgentpointer() << "\n";
133 }
134
135 prefix_ void senf::TCPPacketType::finalize(packet p)
136 {
137     p->dataoffset() << p.size();
138     p->checksum() << p->calcChecksum();
139 }
140
141 //-/////////////////////////////////////////////////////////////////////////////////////////////////
142 #undef prefix_
143
144 \f
145 // Local Variables:
146 // mode: c++
147 // fill-column: 100
148 // c-file-style: "senf"
149 // indent-tabs-mode: nil
150 // ispell-local-dictionary: "american"
151 // compile-command: "scons -u test"
152 // comment-column: 40
153 // End: