1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 
21 #include "udp-header.h"
22 #include "ns3/address-utils.h"
23 
24 namespace ns3 {
25 
26 NS_OBJECT_ENSURE_REGISTERED (UdpHeader);
27 
28 /* The magic values below are used only for debugging.
29  * They can be used to easily detect memory corruption
30  * problems so you can see the patterns in memory.
31  */
UdpHeader()32 UdpHeader::UdpHeader ()
33   : m_sourcePort (0xfffd),
34     m_destinationPort (0xfffd),
35     m_payloadSize (0),
36     m_checksum (0),
37     m_calcChecksum (false),
38     m_goodChecksum (true)
39 {
40 }
~UdpHeader()41 UdpHeader::~UdpHeader ()
42 {
43   m_sourcePort = 0xfffe;
44   m_destinationPort = 0xfffe;
45   m_payloadSize = 0xfffe;
46 }
47 
48 void
EnableChecksums(void)49 UdpHeader::EnableChecksums (void)
50 {
51   m_calcChecksum = true;
52 }
53 
54 void
SetDestinationPort(uint16_t port)55 UdpHeader::SetDestinationPort (uint16_t port)
56 {
57   m_destinationPort = port;
58 }
59 void
SetSourcePort(uint16_t port)60 UdpHeader::SetSourcePort (uint16_t port)
61 {
62   m_sourcePort = port;
63 }
64 uint16_t
GetSourcePort(void) const65 UdpHeader::GetSourcePort (void) const
66 {
67   return m_sourcePort;
68 }
69 uint16_t
GetDestinationPort(void) const70 UdpHeader::GetDestinationPort (void) const
71 {
72   return m_destinationPort;
73 }
74 void
InitializeChecksum(Address source,Address destination,uint8_t protocol)75 UdpHeader::InitializeChecksum (Address source,
76                                Address destination,
77                                uint8_t protocol)
78 {
79   m_source = source;
80   m_destination = destination;
81   m_protocol = protocol;
82 }
83 void
InitializeChecksum(Ipv4Address source,Ipv4Address destination,uint8_t protocol)84 UdpHeader::InitializeChecksum (Ipv4Address source,
85                                Ipv4Address destination,
86                                uint8_t protocol)
87 {
88   m_source = source;
89   m_destination = destination;
90   m_protocol = protocol;
91 }
92 void
InitializeChecksum(Ipv6Address source,Ipv6Address destination,uint8_t protocol)93 UdpHeader::InitializeChecksum (Ipv6Address source,
94                                Ipv6Address destination,
95                                uint8_t protocol)
96 {
97   m_source = source;
98   m_destination = destination;
99   m_protocol = protocol;
100 }
101 uint16_t
CalculateHeaderChecksum(uint16_t size) const102 UdpHeader::CalculateHeaderChecksum (uint16_t size) const
103 {
104   Buffer buf = Buffer ((2 * Address::MAX_SIZE) + 8);
105   buf.AddAtStart ((2 * Address::MAX_SIZE) + 8);
106   Buffer::Iterator it = buf.Begin ();
107   uint32_t hdrSize = 0;
108 
109   WriteTo (it, m_source);
110   WriteTo (it, m_destination);
111   if (Ipv4Address::IsMatchingType (m_source))
112     {
113       it.WriteU8 (0); /* protocol */
114       it.WriteU8 (m_protocol); /* protocol */
115       it.WriteU8 (size >> 8); /* length */
116       it.WriteU8 (size & 0xff); /* length */
117       hdrSize = 12;
118     }
119   else if (Ipv6Address::IsMatchingType (m_source))
120     {
121       it.WriteU16 (0);
122       it.WriteU8 (size >> 8); /* length */
123       it.WriteU8 (size & 0xff); /* length */
124       it.WriteU16 (0);
125       it.WriteU8 (0);
126       it.WriteU8 (m_protocol); /* protocol */
127       hdrSize = 40;
128     }
129 
130   it = buf.Begin ();
131   /* we don't CompleteChecksum ( ~ ) now */
132   return ~(it.CalculateIpChecksum (hdrSize));
133 }
134 
135 bool
IsChecksumOk(void) const136 UdpHeader::IsChecksumOk (void) const
137 {
138   return m_goodChecksum;
139 }
140 
141 void
ForceChecksum(uint16_t checksum)142 UdpHeader::ForceChecksum (uint16_t checksum)
143 {
144   m_checksum = checksum;
145 }
146 
147 void
ForcePayloadSize(uint16_t payloadSize)148 UdpHeader::ForcePayloadSize (uint16_t payloadSize)
149 {
150   m_payloadSize = payloadSize;
151 }
152 
153 TypeId
GetTypeId(void)154 UdpHeader::GetTypeId (void)
155 {
156   static TypeId tid = TypeId ("ns3::UdpHeader")
157     .SetParent<Header> ()
158     .SetGroupName ("Internet")
159     .AddConstructor<UdpHeader> ()
160   ;
161   return tid;
162 }
163 TypeId
GetInstanceTypeId(void) const164 UdpHeader::GetInstanceTypeId (void) const
165 {
166   return GetTypeId ();
167 }
168 void
Print(std::ostream & os) const169 UdpHeader::Print (std::ostream &os) const
170 {
171   os << "length: " << m_payloadSize + GetSerializedSize ()
172      << " "
173      << m_sourcePort << " > " << m_destinationPort
174   ;
175 }
176 
177 uint32_t
GetSerializedSize(void) const178 UdpHeader::GetSerializedSize (void) const
179 {
180   return 8;
181 }
182 
183 void
Serialize(Buffer::Iterator start) const184 UdpHeader::Serialize (Buffer::Iterator start) const
185 {
186   Buffer::Iterator i = start;
187 
188   i.WriteHtonU16 (m_sourcePort);
189   i.WriteHtonU16 (m_destinationPort);
190   if (m_payloadSize == 0)
191     {
192       i.WriteHtonU16 (start.GetSize ());
193     }
194   else
195     {
196       i.WriteHtonU16 (m_payloadSize);
197     }
198 
199   if ( m_checksum == 0)
200     {
201       i.WriteU16 (0);
202 
203       if (m_calcChecksum)
204         {
205           uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
206           i = start;
207           uint16_t checksum = i.CalculateIpChecksum (start.GetSize (), headerChecksum);
208 
209           i = start;
210           i.Next (6);
211           i.WriteU16 (checksum);
212         }
213     }
214   else
215     {
216       i.WriteU16 (m_checksum);
217     }
218 }
219 uint32_t
Deserialize(Buffer::Iterator start)220 UdpHeader::Deserialize (Buffer::Iterator start)
221 {
222   Buffer::Iterator i = start;
223   m_sourcePort = i.ReadNtohU16 ();
224   m_destinationPort = i.ReadNtohU16 ();
225   m_payloadSize = i.ReadNtohU16 () - GetSerializedSize ();
226   m_checksum = i.ReadU16 ();
227 
228   if (m_calcChecksum)
229     {
230       uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
231       i = start;
232       uint16_t checksum = i.CalculateIpChecksum (start.GetSize (), headerChecksum);
233 
234       m_goodChecksum = (checksum == 0);
235     }
236 
237   return GetSerializedSize ();
238 }
239 
240 uint16_t
GetChecksum()241 UdpHeader::GetChecksum ()
242 {
243   return m_checksum;
244 }
245 
246 } // namespace ns3
247