00001 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ 00002 /* 00003 * Copyright (c) 2005 INRIA 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation; 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 * 00018 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr> 00019 */ 00020 00021 #include "ns3/assert.h" 00022 #include "ns3/log.h" 00023 #include "ns3/header.h" 00024 #include "ipv4-header.h" 00025 00026 NS_LOG_COMPONENT_DEFINE ("Ipv4Header"); 00027 00028 namespace ns3 { 00029 00030 NS_OBJECT_ENSURE_REGISTERED (Ipv4Header); 00031 00032 Ipv4Header::Ipv4Header () 00033 : m_calcChecksum (false), 00034 m_payloadSize (0), 00035 m_identification (0), 00036 m_tos (0), 00037 m_ttl (0), 00038 m_protocol (0), 00039 m_flags (0), 00040 m_fragmentOffset (0), 00041 m_checksum(0), 00042 m_goodChecksum (true) 00043 {} 00044 00045 void 00046 Ipv4Header::EnableChecksum (void) 00047 { 00048 m_calcChecksum = true; 00049 } 00050 00051 void 00052 Ipv4Header::SetPayloadSize (uint16_t size) 00053 { 00054 m_payloadSize = size; 00055 } 00056 uint16_t 00057 Ipv4Header::GetPayloadSize (void) const 00058 { 00059 return m_payloadSize; 00060 } 00061 00062 uint16_t 00063 Ipv4Header::GetIdentification (void) const 00064 { 00065 return m_identification; 00066 } 00067 void 00068 Ipv4Header::SetIdentification (uint16_t identification) 00069 { 00070 m_identification = identification; 00071 } 00072 00073 00074 00075 void 00076 Ipv4Header::SetTos (uint8_t tos) 00077 { 00078 m_tos = tos; 00079 } 00080 uint8_t 00081 Ipv4Header::GetTos (void) const 00082 { 00083 return m_tos; 00084 } 00085 void 00086 Ipv4Header::SetMoreFragments (void) 00087 { 00088 m_flags |= MORE_FRAGMENTS; 00089 } 00090 void 00091 Ipv4Header::SetLastFragment (void) 00092 { 00093 m_flags &= ~MORE_FRAGMENTS; 00094 } 00095 bool 00096 Ipv4Header::IsLastFragment (void) const 00097 { 00098 return !(m_flags & MORE_FRAGMENTS); 00099 } 00100 00101 void 00102 Ipv4Header::SetDontFragment (void) 00103 { 00104 m_flags |= DONT_FRAGMENT; 00105 } 00106 void 00107 Ipv4Header::SetMayFragment (void) 00108 { 00109 m_flags &= ~DONT_FRAGMENT; 00110 } 00111 bool 00112 Ipv4Header::IsDontFragment (void) const 00113 { 00114 return (m_flags & DONT_FRAGMENT); 00115 } 00116 00117 void 00118 Ipv4Header::SetFragmentOffset (uint16_t offset) 00119 { 00120 NS_ASSERT (!(offset & (~0x3fff))); 00121 m_fragmentOffset = offset; 00122 } 00123 uint16_t 00124 Ipv4Header::GetFragmentOffset (void) const 00125 { 00126 NS_ASSERT (!(m_fragmentOffset & (~0x3fff))); 00127 return m_fragmentOffset; 00128 } 00129 00130 void 00131 Ipv4Header::SetTtl (uint8_t ttl) 00132 { 00133 m_ttl = ttl; 00134 } 00135 uint8_t 00136 Ipv4Header::GetTtl (void) const 00137 { 00138 return m_ttl; 00139 } 00140 00141 uint8_t 00142 Ipv4Header::GetProtocol (void) const 00143 { 00144 return m_protocol; 00145 } 00146 void 00147 Ipv4Header::SetProtocol (uint8_t protocol) 00148 { 00149 m_protocol = protocol; 00150 } 00151 00152 void 00153 Ipv4Header::SetSource (Ipv4Address source) 00154 { 00155 m_source = source; 00156 } 00157 Ipv4Address 00158 Ipv4Header::GetSource (void) const 00159 { 00160 return m_source; 00161 } 00162 00163 void 00164 Ipv4Header::SetDestination (Ipv4Address dst) 00165 { 00166 m_destination = dst; 00167 } 00168 Ipv4Address 00169 Ipv4Header::GetDestination (void) const 00170 { 00171 return m_destination; 00172 } 00173 00174 00175 bool 00176 Ipv4Header::IsChecksumOk (void) const 00177 { 00178 return m_goodChecksum; 00179 } 00180 00181 TypeId 00182 Ipv4Header::GetTypeId (void) 00183 { 00184 static TypeId tid = TypeId ("ns3::Ipv4Header") 00185 .SetParent<Header> () 00186 .AddConstructor<Ipv4Header> () 00187 ; 00188 return tid; 00189 } 00190 TypeId 00191 Ipv4Header::GetInstanceTypeId (void) const 00192 { 00193 return GetTypeId (); 00194 } 00195 void 00196 Ipv4Header::Print (std::ostream &os) const 00197 { 00198 // ipv4, right ? 00199 std::string flags; 00200 if (m_flags == 0) 00201 { 00202 flags = "none"; 00203 } 00204 else if (m_flags & MORE_FRAGMENTS && 00205 m_flags & DONT_FRAGMENT) 00206 { 00207 flags = "MF|DF"; 00208 } 00209 else if (m_flags & DONT_FRAGMENT) 00210 { 00211 flags = "DF"; 00212 } 00213 else if (m_flags & MORE_FRAGMENTS) 00214 { 00215 flags = "MF"; 00216 } 00217 else 00218 { 00219 flags = "XX"; 00220 } 00221 os << "tos 0x" << std::hex << m_tos << std::dec << " " 00222 << "ttl " << m_ttl << " " 00223 << "id " << m_identification << " " 00224 << "protocol " << m_protocol << " " 00225 << "offset " << m_fragmentOffset << " " 00226 << "flags [" << flags << "] " 00227 << "length: " << (m_payloadSize + 5 * 4) 00228 << " " 00229 << m_source << " > " << m_destination 00230 ; 00231 } 00232 uint32_t 00233 Ipv4Header::GetSerializedSize (void) const 00234 { 00235 return 5 * 4; 00236 } 00237 00238 void 00239 Ipv4Header::Serialize (Buffer::Iterator start) const 00240 { 00241 Buffer::Iterator i = start; 00242 00243 uint8_t verIhl = (4 << 4) | (5); 00244 i.WriteU8 (verIhl); 00245 i.WriteU8 (m_tos); 00246 i.WriteHtonU16 (m_payloadSize + 5*4); 00247 i.WriteHtonU16 (m_identification); 00248 uint32_t fragmentOffset = m_fragmentOffset / 8; 00249 uint8_t flagsFrag = (fragmentOffset >> 8) & 0x1f; 00250 if (m_flags & DONT_FRAGMENT) 00251 { 00252 flagsFrag |= (1<<6); 00253 } 00254 if (m_flags & MORE_FRAGMENTS) 00255 { 00256 flagsFrag |= (1<<5); 00257 } 00258 i.WriteU8 (flagsFrag); 00259 uint8_t frag = fragmentOffset & 0xff; 00260 i.WriteU8 (frag); 00261 i.WriteU8 (m_ttl); 00262 i.WriteU8 (m_protocol); 00263 i.WriteHtonU16 (0); 00264 i.WriteHtonU32 (m_source.Get ()); 00265 i.WriteHtonU32 (m_destination.Get ()); 00266 00267 if (m_calcChecksum) 00268 { 00269 i = start; 00270 uint16_t checksum = i.CalculateIpChecksum(20); 00271 NS_LOG_LOGIC ("checksum=" <<checksum); 00272 i = start; 00273 i.Next (10); 00274 i.WriteU16 (checksum); 00275 } 00276 } 00277 uint32_t 00278 Ipv4Header::Deserialize (Buffer::Iterator start) 00279 { 00280 Buffer::Iterator i = start; 00281 uint8_t verIhl = i.ReadU8 (); 00282 uint8_t ihl = verIhl & 0x0f; 00283 uint16_t headerSize = ihl * 4; 00284 NS_ASSERT ((verIhl >> 4) == 4); 00285 m_tos = i.ReadU8 (); 00286 uint16_t size = i.ReadNtohU16 (); 00287 m_payloadSize = size - headerSize; 00288 m_identification = i.ReadNtohU16 (); 00289 uint8_t flags = i.ReadU8 (); 00290 m_flags = 0; 00291 if (flags & (1<<6)) 00292 { 00293 m_flags |= DONT_FRAGMENT; 00294 } 00295 if (flags & (1<<5)) 00296 { 00297 m_flags |= MORE_FRAGMENTS; 00298 } 00299 i.Prev (); 00300 m_fragmentOffset = i.ReadU8 () & 0x1f; 00301 m_fragmentOffset <<= 8; 00302 m_fragmentOffset |= i.ReadU8 (); 00303 m_fragmentOffset <<= 3; 00304 m_ttl = i.ReadU8 (); 00305 m_protocol = i.ReadU8 (); 00306 m_checksum = i.ReadU16(); 00307 /* i.Next (2); // checksum */ 00308 m_source.Set (i.ReadNtohU32 ()); 00309 m_destination.Set (i.ReadNtohU32 ()); 00310 00311 if (m_calcChecksum) 00312 { 00313 i = start; 00314 uint16_t checksum = i.CalculateIpChecksum(headerSize); 00315 NS_LOG_LOGIC ("checksum=" <<checksum); 00316 00317 m_goodChecksum = (checksum == 0); 00318 } 00319 return GetSerializedSize (); 00320 } 00321 00322 }; // namespace ns3