00001 // $Id: TCPPacket.cc 1792 2011-06-09 15:49:59Z tho $ 00002 // 00003 // Copyright (C) 2009 00004 // Fraunhofer (FOKUS) 00005 // Competence Center NETwork research (NET), St. Augustin, GERMANY 00006 // Dennis Goslar <dennis.goslar@inf.hochschule-bonn-rhein-sieg.de> 00007 // 00008 // This program is free software; you can redistribute it and/or modify 00009 // it under the terms of the GNU General Public License as published by 00010 // the Free Software Foundation; either version 2 of the License, or 00011 // (at your option) any later version. 00012 // 00013 // This program is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 // GNU General Public License for more details. 00017 // 00018 // You should have received a copy of the GNU General Public License 00019 // along with this program; if not, write to the 00020 // Free Software Foundation, Inc., 00021 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00022 00026 #include "TCPPacket.hh" 00027 //#include "TCPPacket.ih" 00028 00029 // Custom includes 00030 #include <iomanip> 00031 #include <boost/io/ios_state.hpp> 00032 #include <senf/Utils/IpChecksum.hh> 00033 #include "IPv6Packet.hh" 00034 00035 #define prefix_ 00036 //-///////////////////////////////////////////////////////////////////////////////////////////////// 00037 00038 namespace { 00039 SENF_PACKET_REGISTRY_REGISTER( senf::IpTypes, 6, senf::TCPPacket); 00040 } 00041 00042 //-///////////////////////////////////////////////////////////////////////////////////////////////// 00043 // senf::TCPPacketParser 00044 00045 prefix_ boost::uint16_t senf::TCPPacketParser::calcChecksum() 00046 const 00047 { 00048 IpChecksum summer; 00049 // first on to the awkward part: the IP pseudo header 00050 IPv4Packet ipv4 (packet().rfind<IPv4Packet>(nothrow)); 00051 if (ipv4) { 00052 // Pseudo header defined in RFC793 00053 // begin 00054 summer.feed( ipv4->source().i(), 00055 ipv4->source().i() + IPv4Packet::Parser::source_t::fixed_bytes ); 00057 summer.feed( ipv4->destination().i(), 00058 ipv4->destination().i() + IPv4PacketParser::destination_t::fixed_bytes ); 00059 // include zero byte 00060 summer.feed( 0u ); 00063 summer.feed( 6u ); 00064 00065 // feed 1st byte and 2nd byte from field tcp length 00066 summer.feed(boost::uint16_t(data().size()) & 0xff00); 00067 summer.feed(boost::uint16_t(data().size()) & 0x00ff); 00068 // end pseudo header 00069 } 00070 else { 00071 // Pseudo header defined in RFC2460 00072 IPv6Packet ipv6 (packet().rfind<IPv6Packet>(nothrow)); 00073 if (ipv6) { 00074 summer.feed( ipv6->source().i(), 00075 ipv6->source().i() + IPv6Packet::Parser::source_t::fixed_bytes ); 00077 // The destination used here must be the *final* destination ... 00078 summer.feed( ipv6->destination().i(), 00079 ipv6->destination().i() + IPv6PacketParser::destination_t::fixed_bytes ); 00080 // This is a simplification. The value is really 32bit to support UDP Jumbograms 00081 // (RFC2147). However, skipping an even number of 0 bytes does not change the checksum 00082 // RFC2460 specifies, that this must always be 6, not the value used in the ipv6 00083 // header 00084 // feed 1st byte and 2nd byte from field tcp length 00085 summer.feed(boost::uint16_t(data().size()) & 0xff00); 00086 summer.feed(boost::uint16_t(data().size()) & 0x00ff); 00087 // include zero byte 00088 summer.feed( 0u ); 00089 // add TCP protocol number 00090 summer.feed( 6u ); 00091 } 00092 } 00093 00094 // since header are 16 / even 32bit aligned we don't have to care for padding. since IpChecksum 00095 // cares for padding at the final summing we don't have to care is the payload is 16nbit-aligned, too. 00096 00097 // iterate till checksum field and skip 2 bytes, 00098 // iterate over rest of tcp header and tcp payload 00099 summer.feed( i(), i()+16 ); 00100 summer.feed( i()+18, data().end() ); 00101 00102 boost::uint16_t rv (summer.sum()); 00103 return rv ? rv : 0xffffu; 00104 00105 } 00106 00107 //-///////////////////////////////////////////////////////////////////////////////////////////////// 00108 // senf::TCPPacketType 00109 00110 prefix_ void senf::TCPPacketType::dump(packet p, std::ostream & os) 00111 { 00112 boost::io::ios_all_saver ias(os); 00113 os << "TCP:\n" 00114 << senf::fieldName("source port") << p->source() << "\n" 00115 << senf::fieldName("destination port") << p->destination() << "\n" 00116 << senf::fieldName("sequence number") << p->sequencenumber() << "\n" 00117 << senf::fieldName("acknowledgment number") << p->acknowledgmentnumber() << "\n" 00118 << senf::fieldName("data offset") << p->dataoffset() << "\n" 00119 << senf::fieldName("urgent flag") << p->urgf() << "\n" 00120 << senf::fieldName("ack flag") << p->ackf() << "\n" 00121 << senf::fieldName("push flag") << p->pshf() << "\n" 00122 << senf::fieldName("reset flag") << p->rstf() << "\n" 00123 << senf::fieldName("syn flag") << p->synf() << "\n" 00124 << senf::fieldName("fin flag") << p->finf() << "\n" 00125 << senf::fieldName("window size") << p->window() << "\n" 00126 << senf::fieldName("checksum") 00127 << "0x" << std::hex << std::setw(4) << std::setfill('0') << std::right << p->checksum() << "\n" 00128 << senf::fieldName("urgent pointer") << p->urgentpointer() << "\n"; 00129 } 00130 00131 prefix_ void senf::TCPPacketType::finalize(packet p) 00132 { 00133 p->dataoffset() << p.size(); 00134 p->checksum() << p->calcChecksum(); 00135 } 00136 00137 //-///////////////////////////////////////////////////////////////////////////////////////////////// 00138 #undef prefix_ 00139 00140 00141 // Local Variables: 00142 // mode: c++ 00143 // fill-column: 100 00144 // c-file-style: "senf" 00145 // indent-tabs-mode: nil 00146 // ispell-local-dictionary: "american" 00147 // compile-command: "scons -u test" 00148 // comment-column: 40 00149 // End: