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