williamr@2
|
1 |
// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
|
williamr@2
|
2 |
// All rights reserved.
|
williamr@2
|
3 |
// This component and the accompanying materials are made available
|
williamr@2
|
4 |
// under the terms of the License "Symbian Foundation License v1.0" to Symbian Foundation members and "Symbian Foundation End User License Agreement v1.0" to non-members
|
williamr@2
|
5 |
// which accompanies this distribution, and is available
|
williamr@2
|
6 |
// at the URL "http://www.symbianfoundation.org/legal/licencesv10.html".
|
williamr@2
|
7 |
//
|
williamr@2
|
8 |
// Initial Contributors:
|
williamr@2
|
9 |
// Nokia Corporation - initial contribution.
|
williamr@2
|
10 |
//
|
williamr@2
|
11 |
// Contributors:
|
williamr@2
|
12 |
//
|
williamr@2
|
13 |
// Description:
|
williamr@2
|
14 |
// in_pkt.h - packet handling routines
|
williamr@2
|
15 |
// Generic packet handling utility for mapping packet handling to the RMBufChain.
|
williamr@2
|
16 |
//
|
williamr@2
|
17 |
|
williamr@2
|
18 |
|
williamr@2
|
19 |
|
williamr@2
|
20 |
/**
|
williamr@2
|
21 |
@file in_pkt.h
|
williamr@2
|
22 |
@publishedAll
|
williamr@2
|
23 |
@released
|
williamr@2
|
24 |
*/
|
williamr@2
|
25 |
|
williamr@2
|
26 |
#ifndef __IN_PKT_H__
|
williamr@2
|
27 |
#define __IN_PKT_H__
|
williamr@2
|
28 |
|
williamr@2
|
29 |
#include <nifmbuf.h>
|
williamr@2
|
30 |
#include "ip6_hdr.h" // ..should eventually be <inet/ip6_hdr.h>? -- msa
|
williamr@2
|
31 |
#include "ip4_hdr.h"
|
williamr@2
|
32 |
|
williamr@2
|
33 |
#define TPACKETHEAD_FRAGMENT 1 ///< Enable iFragment in TPacketHead
|
williamr@2
|
34 |
|
williamr@2
|
35 |
/**
|
williamr@2
|
36 |
TScopeType is only provided so that "magic" constants can be
|
williamr@2
|
37 |
avoided in the source code. However, the max value cannot be changed
|
williamr@2
|
38 |
to anything from 0xF. The scope type is assumed to be 4 bits long
|
williamr@2
|
39 |
in many occasions.
|
williamr@2
|
40 |
|
williamr@2
|
41 |
The value of the scope type is directly bound the the IPv6 Scope
|
williamr@2
|
42 |
level - 1. This can be done, as IPv6 Scope level 0 is not legal
|
williamr@2
|
43 |
(or usable) in any context within the stack.
|
williamr@2
|
44 |
This allows our non-standard network scope (= 0x10) to
|
williamr@2
|
45 |
be coded internally in 4 bits (as 0xF).
|
williamr@2
|
46 |
|
williamr@2
|
47 |
@publishedAll
|
williamr@2
|
48 |
@released
|
williamr@2
|
49 |
@since v7.0s
|
williamr@2
|
50 |
*/
|
williamr@2
|
51 |
enum TScopeType
|
williamr@2
|
52 |
{
|
williamr@2
|
53 |
EScopeType_IF = 0x0, ///< (= #KIp6AddrScopeNodeLocal - 1), id is interface index
|
williamr@2
|
54 |
EScopeType_IAP = 0x1, ///< (= #KIp6AddrScopeLinkLocal - 1). id is IAP number
|
williamr@2
|
55 |
EScopeType_GLOBAL = 0xD,///< (= #KIp6AddrScopeGlobal - 1). id is global scope id
|
williamr@2
|
56 |
//
|
williamr@2
|
57 |
// no symbols defined for types 2..14 (they are also valid)
|
williamr@2
|
58 |
//
|
williamr@2
|
59 |
EScopeType_NET = 0xF ///< (= #KIp6AddrScopeNetwork - 1), id is network number (must be the last entry)
|
williamr@2
|
60 |
};
|
williamr@2
|
61 |
|
williamr@2
|
62 |
//
|
williamr@2
|
63 |
// TIpHeader
|
williamr@2
|
64 |
// *********
|
williamr@2
|
65 |
class TIpHeader
|
williamr@2
|
66 |
/**
|
williamr@2
|
67 |
A simple help class that uses a union to merge handling of either an IPv4 or
|
williamr@2
|
68 |
an IPv6 header.
|
williamr@2
|
69 |
@since v7.0
|
williamr@2
|
70 |
@publishedAll
|
williamr@2
|
71 |
@released
|
williamr@2
|
72 |
*/
|
williamr@2
|
73 |
{
|
williamr@2
|
74 |
public:
|
williamr@2
|
75 |
/**
|
williamr@2
|
76 |
Gets the minimum header length.
|
williamr@2
|
77 |
|
williamr@2
|
78 |
IPv6 header is longer than minimum IPv4 header, thus
|
williamr@2
|
79 |
returned value is for IPv4. This function only defined
|
williamr@2
|
80 |
because it is required when this class is used as template
|
williamr@2
|
81 |
parameter in TInet6Packet.
|
williamr@2
|
82 |
|
williamr@2
|
83 |
@return Minimum IPv4 header length
|
williamr@2
|
84 |
*/
|
williamr@2
|
85 |
inline static TInt MinHeaderLength() {return TInet6HeaderIP4::MinHeaderLength(); }
|
williamr@2
|
86 |
/**
|
williamr@2
|
87 |
Gets the maximum header length.
|
williamr@2
|
88 |
|
williamr@2
|
89 |
IPv6 header always shorter than maximum IPv4 header, thus
|
williamr@2
|
90 |
returned value is for IPv4. This function is only defined
|
williamr@2
|
91 |
because "header mapping" classes are expected to have it.
|
williamr@2
|
92 |
|
williamr@2
|
93 |
@return Maximum IPv4 header length
|
williamr@2
|
94 |
*/
|
williamr@2
|
95 |
inline static TInt MaxHeaderLength() {return TInet6HeaderIP4::MaxHeaderLength(); }
|
williamr@2
|
96 |
|
williamr@2
|
97 |
union
|
williamr@2
|
98 |
{
|
williamr@2
|
99 |
TInet6HeaderIP4 ip4;
|
williamr@2
|
100 |
TInet6HeaderIP ip6;
|
williamr@2
|
101 |
};
|
williamr@2
|
102 |
};
|
williamr@2
|
103 |
|
williamr@2
|
104 |
|
williamr@2
|
105 |
// RMBufPacketPeek
|
williamr@2
|
106 |
// ***************
|
williamr@2
|
107 |
class RMBufPacketPeek : public RMBufChain
|
williamr@2
|
108 |
/**
|
williamr@2
|
109 |
Extends RMBufChain to add functions to read packet data as a descriptor
|
williamr@2
|
110 |
and as an IP header.
|
williamr@2
|
111 |
|
williamr@2
|
112 |
The RMBufChain is assumed to contain the raw packet, without
|
williamr@2
|
113 |
the info block prepended (e.g. if this class is used for RMBufPacketBase
|
williamr@2
|
114 |
derived handle, it must be in "unpacked" state).
|
williamr@2
|
115 |
|
williamr@2
|
116 |
@since v7.0
|
williamr@2
|
117 |
@publishedAll
|
williamr@2
|
118 |
@released
|
williamr@2
|
119 |
*/
|
williamr@2
|
120 |
{
|
williamr@2
|
121 |
public:
|
williamr@2
|
122 |
IMPORT_C TPtr8 Access(TInt aSize, TUint aOffset = 0);
|
williamr@2
|
123 |
IMPORT_C TIpHeader *GetIpHeader();
|
williamr@2
|
124 |
};
|
williamr@2
|
125 |
|
williamr@2
|
126 |
// TPacketHead
|
williamr@2
|
127 |
// ***********
|
williamr@2
|
128 |
class TPacketHead
|
williamr@2
|
129 |
/**
|
williamr@2
|
130 |
Storage for some precomputed information for an outbound packet flow.
|
williamr@2
|
131 |
|
williamr@2
|
132 |
The outbound TPacketHead is part of the flow context (CFlowContext).
|
williamr@2
|
133 |
|
williamr@2
|
134 |
The CFlowContext::Connect initializes the content from the parameters
|
williamr@2
|
135 |
of the flow (TFlowInfo) and runs the connection process.. The connection
|
williamr@2
|
136 |
process (MIp6Hook::OpenL and MFlowHook::ReadyL phases) completes the
|
williamr@2
|
137 |
information. After this, as long as the flow is connected, the content
|
williamr@2
|
138 |
is mostly frozen and <b>must not be modified by anyone</b>.
|
williamr@2
|
139 |
|
williamr@2
|
140 |
When there is a need to change any flow information, the changes must
|
williamr@2
|
141 |
be done to the flow parameters (and not to TPacketHead). The change of
|
williamr@2
|
142 |
flow parameters also sets the CFlowContext::iChanged flag, and this
|
williamr@2
|
143 |
eventually causes a new CFlowContext::Connect, which re-initializes
|
williamr@2
|
144 |
the TPacketHead with the new information.
|
williamr@2
|
145 |
|
williamr@2
|
146 |
For each field in the TPacketHead, the hook writer must follow the
|
williamr@2
|
147 |
basic rule (only for fields that it intends to change):
|
williamr@2
|
148 |
|
williamr@2
|
149 |
- if some field is changed in MIp6Hook::OpenL, then the previous
|
williamr@2
|
150 |
value should be restored in the MFlowHook::ReadyL.
|
williamr@2
|
151 |
- an exeception: the hook must omit the restore, if the
|
williamr@2
|
152 |
previous value was unspecified value (for example, the source
|
williamr@2
|
153 |
address).
|
williamr@2
|
154 |
- the content of #iPacket (and #iOffset) are special: they cannot
|
williamr@2
|
155 |
be modified in the MIp6Hook::OpenL phase. A hook can
|
williamr@2
|
156 |
modify them only in the MFlowHook::ReadyL phase. And, if the hook
|
williamr@2
|
157 |
is adding an IP header for tunneling, it must save the current content
|
williamr@2
|
158 |
of these fields in the ReadyL function, and then clear out the fields
|
williamr@2
|
159 |
(it must make the iPacket empty and zero iOffset). The hook must add
|
williamr@2
|
160 |
the saved iPacket content below the added tunnel header in
|
williamr@2
|
161 |
MFlowHook::ApplyL .
|
williamr@2
|
162 |
|
williamr@2
|
163 |
@since v7.0
|
williamr@2
|
164 |
@publishedAll
|
williamr@2
|
165 |
@released
|
williamr@2
|
166 |
*/
|
williamr@2
|
167 |
{
|
williamr@2
|
168 |
public:
|
williamr@2
|
169 |
IMPORT_C TBool ExtHdrGet(TInt aType, TInt& aOfs, TInt& aLen);
|
williamr@2
|
170 |
IMPORT_C TBool ExtHdrGetOrPrependL(TInt aType, TInt& aOfs, TInt& aLen);
|
williamr@2
|
171 |
IMPORT_C TBool ExtHdrGetOrAppendL(TInt aType, TInt& aOfs, TInt& aLen);
|
williamr@2
|
172 |
IMPORT_C void AddDestinationOptionL(const TPtrC8& aOption, TUint8 aAlign=0, TUint8 aModulo=4);
|
williamr@2
|
173 |
IMPORT_C void AddDestinationOptionL(const TUint8* aOption, TUint8 aLen, TUint8 aAlign=0, TUint8 aModulo=4);
|
williamr@2
|
174 |
|
williamr@2
|
175 |
public:
|
williamr@2
|
176 |
/**
|
williamr@2
|
177 |
"Virtual" IP header. The IPv6 header stucture is used, but the same
|
williamr@2
|
178 |
format is <b>also</b> used for the IPv4 destinations (Version() == 4,
|
williamr@2
|
179 |
even though the header format is still IPv6!)
|
williamr@2
|
180 |
|
williamr@2
|
181 |
This header is initialized in the beginning of the OpenL phase
|
williamr@2
|
182 |
as follows:
|
williamr@2
|
183 |
@li Version = 0
|
williamr@2
|
184 |
@li Traffic Class, copied from the flow iOptions.iTrafficClass
|
williamr@2
|
185 |
@li Flow Label = 0
|
williamr@2
|
186 |
@li Payload Length = 0 (dummy field, not used)
|
williamr@2
|
187 |
@li Next Header, copied from the flow iProtocol
|
williamr@2
|
188 |
@li Hop Limit, copied from the flow iOptions.iHopLimit
|
williamr@2
|
189 |
@li Src Address, copied from the flow Local Address (usually unspecified)
|
williamr@2
|
190 |
@li Dst Address, copied from the flow Remote Address
|
williamr@2
|
191 |
|
williamr@2
|
192 |
At beginning of the ReadyL phase (= at end of OpenL), the destination
|
williamr@2
|
193 |
address (and iDstId) are used to find a route on the interface. Depending
|
williamr@2
|
194 |
on whether this address is IPv4 (mapped) or IPv6, the Version field is set
|
williamr@2
|
195 |
accordingly to either 4 or 6.
|
williamr@2
|
196 |
|
williamr@2
|
197 |
After succesfull completion of the ReadyL, this used for *each* packet
|
williamr@2
|
198 |
which needs an IP header to be generated on send. The Version() determines
|
williamr@2
|
199 |
whether IPv4 or IPv6 frame is to be generated (this is the initial
|
williamr@2
|
200 |
header in the packet, *before* running outbound ApplyL hooks):
|
williamr@2
|
201 |
|
williamr@2
|
202 |
@verbatim
|
williamr@2
|
203 |
IPv6 IPv4
|
williamr@2
|
204 |
Version == 6 ==4
|
williamr@2
|
205 |
Traffic Class used as is used as TOS
|
williamr@2
|
206 |
Flow Label used as is ignored
|
williamr@2
|
207 |
Payload Length ignored ignored
|
williamr@2
|
208 |
Next Header used as is used as Protocol
|
williamr@2
|
209 |
Hop Limit used as is used as TTL
|
williamr@2
|
210 |
Src Address used as is used as IPv4 mapped
|
williamr@2
|
211 |
Dst Address used as is used as IPv4 mapped
|
williamr@2
|
212 |
@endverbatim
|
williamr@2
|
213 |
*/
|
williamr@2
|
214 |
TInet6HeaderIP ip6;
|
williamr@2
|
215 |
/**
|
williamr@2
|
216 |
Contains the scope id associated with the destination address
|
williamr@2
|
217 |
which is stored in #ip6 Dst Address. This id and address must
|
williamr@2
|
218 |
always be considered as a unit. Logically, any change changes
|
williamr@2
|
219 |
both values.
|
williamr@2
|
220 |
|
williamr@2
|
221 |
iDstId is initialized from the flow context TFlowInfo::iRemote.Scope() at
|
williamr@2
|
222 |
beginning of the flow connect phase. If application does not define
|
williamr@2
|
223 |
this scope id, then the system will attempt to choose a default value
|
williamr@2
|
224 |
at beginning of the connect phase. If the default cannot be determined,
|
williamr@2
|
225 |
the flow is put into pending state (and no connect happens).
|
williamr@2
|
226 |
|
williamr@2
|
227 |
@par MIp6Hook::OpenL
|
williamr@2
|
228 |
On entry to the OpenL, the iDstId is always non-zero and destination
|
williamr@2
|
229 |
address is specified. If a hook changes the destination address in
|
williamr@2
|
230 |
OpenL method, it must provide the correct id value
|
williamr@2
|
231 |
which goes with the new destination. If it cannot do this, it
|
williamr@2
|
232 |
must either abort the connect by leaving with an error state, or it
|
williamr@2
|
233 |
can leave with PENDING (> 0) status to signal there is no route
|
williamr@2
|
234 |
for the new destination.
|
williamr@2
|
235 |
If the stack cannot find suitable interface for the destination, then
|
williamr@2
|
236 |
it aborts the connect phase, and the flow is placed into holding state.
|
williamr@2
|
237 |
|
williamr@2
|
238 |
@note
|
williamr@2
|
239 |
Only a tunneling hook can safely change the destination
|
williamr@2
|
240 |
address (a use of routing header can also be a kind of
|
williamr@2
|
241 |
tunneling).
|
williamr@2
|
242 |
|
williamr@2
|
243 |
@par MFlowHook::ReadyL
|
williamr@2
|
244 |
If the hook changed the destination address (or id) in the OpenL,
|
williamr@2
|
245 |
the ReadyL must restore the original values back.
|
williamr@2
|
246 |
|
williamr@2
|
247 |
*/
|
williamr@2
|
248 |
TUint32 iDstId;
|
williamr@2
|
249 |
/**
|
williamr@2
|
250 |
Contains the scope id associated with the source address
|
williamr@2
|
251 |
which is stored in #ip6 Src address. This is defined when the source
|
williamr@2
|
252 |
address is defined, and otherwise undefined.
|
williamr@2
|
253 |
|
williamr@2
|
254 |
iSrcId is initialized from TFlowInfo::iLocal.Scope() at beginning of the
|
williamr@2
|
255 |
flow connect phase. If application defines the source address,
|
williamr@2
|
256 |
but does not specify this scope id, then the system chooses
|
williamr@2
|
257 |
the id based on the interface defined by the source address.
|
williamr@2
|
258 |
If scope and address are both specified, they must match the
|
williamr@2
|
259 |
selected interface.
|
williamr@2
|
260 |
|
williamr@2
|
261 |
@par MIp6Hook::OpenL
|
williamr@2
|
262 |
On entry to the OpenL, the iSrcId (and source address) may be
|
williamr@2
|
263 |
undefined (#iSourceSet = 0). If defined (iSourceSet = 1), then
|
williamr@2
|
264 |
both address and iSrcId are defined (iSrcId != 0). A hook may
|
williamr@2
|
265 |
force a reselection of the source just by zeroing the
|
williamr@2
|
266 |
iSourceSet.
|
williamr@2
|
267 |
|
williamr@2
|
268 |
@par MFlowHook::ReadyL
|
williamr@2
|
269 |
If the hook changed the source address (or id) in the OpenL,
|
williamr@2
|
270 |
the ReadyL must restore the original values back, but only
|
williamr@2
|
271 |
if the original value was defined (#iSourceSet = 1 in OpenL).
|
williamr@2
|
272 |
*/
|
williamr@2
|
273 |
TUint32 iSrcId;
|
williamr@2
|
274 |
/**
|
williamr@2
|
275 |
The source address has been set.
|
williamr@2
|
276 |
|
williamr@2
|
277 |
This bit indicates whether the value stored in #ip6 src field
|
williamr@2
|
278 |
and #iSrcId is to be used as a source address as is.
|
williamr@2
|
279 |
|
williamr@2
|
280 |
Initialized from TFlowInfo::iLocalSet, which tells whether user
|
williamr@2
|
281 |
specified tbe source address or not (e.g used RSocket Bind method).
|
williamr@2
|
282 |
The stack checks the value after each MIp6Hook::OpenL call, and
|
williamr@2
|
283 |
if the flag is set, the source in ip6 is used as is. If the flag
|
williamr@2
|
284 |
is zero, then the stack performs the normal source address selection
|
williamr@2
|
285 |
based on the current destination address (#iSrcId and destination
|
williamr@2
|
286 |
address).
|
williamr@2
|
287 |
|
williamr@2
|
288 |
@par MIp6Hook::OpenL
|
williamr@2
|
289 |
On entry, this flag is always set and source address is defined.
|
williamr@2
|
290 |
A hook may clear this flag, if it wants the
|
williamr@2
|
291 |
stack choose the source address based on current destination.
|
williamr@2
|
292 |
The clearing operation is normally needed only by a tunneling
|
williamr@2
|
293 |
hook.
|
williamr@2
|
294 |
|
williamr@2
|
295 |
@note
|
williamr@2
|
296 |
If the hook specifies the source address, it must be either
|
williamr@2
|
297 |
a valid source address for the interface or unspecified
|
williamr@2
|
298 |
address.
|
williamr@2
|
299 |
|
williamr@2
|
300 |
@par MFlowHook::ReadyL
|
williamr@2
|
301 |
Upon entry to the ReadyL, the source address is always fully
|
williamr@2
|
302 |
known (the hook can assume that #iSrcId and the #ip6 source
|
williamr@2
|
303 |
addresses are valid).
|
williamr@2
|
304 |
If the source address was set before the OpenL, then this
|
williamr@2
|
305 |
must restore the original value (along with the #iSrcId
|
williamr@2
|
306 |
and source address).
|
williamr@2
|
307 |
*/
|
williamr@2
|
308 |
TUint iSourceSet:1;
|
williamr@2
|
309 |
#ifdef TPACKETHEAD_FRAGMENT
|
williamr@2
|
310 |
/**
|
williamr@2
|
311 |
The fragment processing alredy done.
|
williamr@2
|
312 |
|
williamr@2
|
313 |
This bit is meaningful only in OpenL phase. If already set,
|
williamr@2
|
314 |
then some ealier hook has requested that the packet must
|
williamr@2
|
315 |
be fragmented to fit the mtu.
|
williamr@2
|
316 |
|
williamr@2
|
317 |
A tunneling hook can set this bit in OpenL, if it needs
|
williamr@2
|
318 |
the fragmenting to happen before the ApplyL is called (e.g.
|
williamr@2
|
319 |
the fragments are tunneled instead of fragmenting the
|
williamr@2
|
320 |
tunneling).
|
williamr@2
|
321 |
|
williamr@2
|
322 |
This bit can only be set or left as is. It cannot be cleared
|
williamr@2
|
323 |
once set.
|
williamr@2
|
324 |
*/
|
williamr@2
|
325 |
TUint iFragment:1;
|
williamr@2
|
326 |
#endif
|
williamr@2
|
327 |
/**
|
williamr@2
|
328 |
Selector info, the upper layer protocol.
|
williamr@2
|
329 |
|
williamr@2
|
330 |
iProtocol has the same value as ip6.NextHeader() when iPacket is empty,
|
williamr@2
|
331 |
and otherwise it is the same as NextHeader() of the last extension
|
williamr@2
|
332 |
header in the iPacket.
|
williamr@2
|
333 |
|
williamr@2
|
334 |
The values of the other selector fields: #iIcmpType, #iIcmpCode
|
williamr@2
|
335 |
#iSrcPort and #iDstPort depend on iProtocol. Whenever iProtocol
|
williamr@2
|
336 |
is changed, the other fields must be updated accordingly.
|
williamr@2
|
337 |
|
williamr@2
|
338 |
@par MIp6Hook::OpenL
|
williamr@2
|
339 |
Because iPacket cannot be modified during the OpenL phase, the
|
williamr@2
|
340 |
content of this field and the Next Header (protocol) field in
|
williamr@2
|
341 |
the #ip6 pseudoheader must always be the same. This field should
|
williamr@2
|
342 |
be considered as <b>read-only</b>, unless the hook intends to
|
williamr@2
|
343 |
apply IP-in-IP tunneling, in which case the hook <b>must</b>
|
williamr@2
|
344 |
change the value to the appropriate tunneling protocol
|
williamr@2
|
345 |
(#KProtocolInet6Ipip or #KProtocolInetIpip).
|
williamr@2
|
346 |
|
williamr@2
|
347 |
@par MFlowHook::ReadyL
|
williamr@2
|
348 |
Only a tunneling hook needs to restore the value here to match
|
williamr@2
|
349 |
the original upper layer protocol. See #iPacket for
|
williamr@2
|
350 |
more detailed information.
|
williamr@2
|
351 |
*/
|
williamr@2
|
352 |
TUint8 iProtocol;
|
williamr@2
|
353 |
/**
|
williamr@2
|
354 |
Selector field whose value depends on #iProtocol.
|
williamr@2
|
355 |
|
williamr@2
|
356 |
If this field does not have meaning with the protocol,
|
williamr@2
|
357 |
the field content should be set to ZERO.
|
williamr@2
|
358 |
*/
|
williamr@2
|
359 |
TUint8 iIcmpType;
|
williamr@2
|
360 |
/**
|
williamr@2
|
361 |
Selector field whose value depends on #iProtocol.
|
williamr@2
|
362 |
|
williamr@2
|
363 |
If this field does not have meaning with the protocol,
|
williamr@2
|
364 |
the field content should be set to ZERO.
|
williamr@2
|
365 |
*/
|
williamr@2
|
366 |
TUint8 iIcmpCode;
|
williamr@2
|
367 |
/**
|
williamr@2
|
368 |
Selector field whose value depends on #iProtocol.
|
williamr@2
|
369 |
|
williamr@2
|
370 |
If this field does not have meaning with the protocol,
|
williamr@2
|
371 |
the field content should be set to ZERO.
|
williamr@2
|
372 |
*/
|
williamr@2
|
373 |
TUint16 iSrcPort;
|
williamr@2
|
374 |
/**
|
williamr@2
|
375 |
Selector field whose value depends on #iProtocol.
|
williamr@2
|
376 |
|
williamr@2
|
377 |
If this field does not have meaning with the protocol,
|
williamr@2
|
378 |
the field content should be set to ZERO.
|
williamr@2
|
379 |
*/
|
williamr@2
|
380 |
TUint16 iDstPort;
|
williamr@2
|
381 |
/**
|
williamr@2
|
382 |
The amount of pre-computed IPv6 extension headers in iPacket which
|
williamr@2
|
383 |
are copied to the beginning of each outgoing packet
|
williamr@2
|
384 |
|
williamr@2
|
385 |
If iOffset > 0, then #iPacket includes that much of extension
|
williamr@2
|
386 |
headers that are copied in front of each packet.
|
williamr@2
|
387 |
*/
|
williamr@2
|
388 |
TInt iOffset;
|
williamr@2
|
389 |
/**
|
williamr@2
|
390 |
Pre-computed extension headers for all packets in this flow.
|
williamr@2
|
391 |
|
williamr@2
|
392 |
These can only be added in the ReadyL phase. If any of the
|
williamr@2
|
393 |
ReadyL's adds extension headers into this, it must take care
|
williamr@2
|
394 |
of maintaining the correct Next Header in the virtual IP header
|
williamr@2
|
395 |
(and the original upper layer protocol must be placed in the
|
williamr@2
|
396 |
next header of the last extension header added.
|
williamr@2
|
397 |
|
williamr@2
|
398 |
Stack copies the content of this to each outgoing packet, just below
|
williamr@2
|
399 |
the IP header, before running the ApplyL functions of the outbound
|
williamr@2
|
400 |
flow hooks.
|
williamr@2
|
401 |
|
williamr@2
|
402 |
@par MIp6Hook::OpenL
|
williamr@2
|
403 |
The iPacket <b>must not</b> be modified during the OpenL phase.
|
williamr@2
|
404 |
|
williamr@2
|
405 |
@par MFlowHook::ReadyL
|
williamr@2
|
406 |
A non-tunneling hook may add extension headers into the current
|
williamr@2
|
407 |
iPacket. A tunneling hook has more complex requirements:
|
williamr@2
|
408 |
it must save the current iPacket and #iOffset and initialize
|
williamr@2
|
409 |
iOffset = 0, and iPacket as empty.
|
williamr@2
|
410 |
|
williamr@2
|
411 |
@par MFlowHook::ApplyL
|
williamr@2
|
412 |
When a tunneling hook adds the tunneling IP header, it
|
williamr@2
|
413 |
must also copy the saved iPacket below the added IP header.
|
williamr@2
|
414 |
*/
|
williamr@2
|
415 |
RMBufPacketPeek iPacket;
|
williamr@2
|
416 |
/**
|
williamr@2
|
417 |
The received packet which caused an ICMP error reply to be sent.
|
williamr@2
|
418 |
|
williamr@2
|
419 |
This is only used for ICMP error repply flows, and should be
|
williamr@2
|
420 |
ignored by others -- mainly for IPSEC hook. The packet, if
|
williamr@2
|
421 |
present, is in unpacked state.
|
williamr@2
|
422 |
*/
|
williamr@2
|
423 |
RMBufPacketBase iIcmp;
|
williamr@2
|
424 |
/**
|
williamr@2
|
425 |
The current destination interface.
|
williamr@2
|
426 |
|
williamr@2
|
427 |
This is ONLY used during connect/OpenL phase.
|
williamr@2
|
428 |
|
williamr@2
|
429 |
The value is maintained by the stack, and is intended as
|
williamr@2
|
430 |
read-only information for the hooks that have a use for
|
williamr@2
|
431 |
it (for example, IPSEC implementing VPN specific policies).
|
williamr@2
|
432 |
|
williamr@2
|
433 |
A hook must not modify this value (the stack will recompute
|
williamr@2
|
434 |
the value after each OpenL, based on the possibly changed
|
williamr@2
|
435 |
address parameters in the TPacketHead)
|
williamr@2
|
436 |
|
williamr@2
|
437 |
@par MIp6Hook::OpenL
|
williamr@2
|
438 |
<b>read-only</b>
|
williamr@2
|
439 |
@par MFlowHook::ReadyL
|
williamr@2
|
440 |
<b>read-only</b>
|
williamr@2
|
441 |
*/
|
williamr@2
|
442 |
TUint32 iInterfaceIndex;
|
williamr@2
|
443 |
};
|
williamr@2
|
444 |
|
williamr@2
|
445 |
class TInet6PacketBase
|
williamr@2
|
446 |
/**
|
williamr@2
|
447 |
* Thin base class for the TInet6Packet.
|
williamr@2
|
448 |
*/
|
williamr@2
|
449 |
{
|
williamr@2
|
450 |
public:
|
williamr@2
|
451 |
enum TAlign
|
williamr@2
|
452 |
{
|
williamr@2
|
453 |
EAlign1 = 0, ///< Align to byte (no align requirement)
|
williamr@2
|
454 |
EAlign2 = 1, ///< Align to 2 byte unit (even address)
|
williamr@2
|
455 |
EAlign4 = 3, ///< Align to 4 byte unit
|
williamr@2
|
456 |
EAlign8 = 7 ///< Align to 8 byte unit
|
williamr@2
|
457 |
};
|
williamr@2
|
458 |
|
williamr@2
|
459 |
/**
|
williamr@2
|
460 |
Constructor.
|
williamr@2
|
461 |
|
williamr@2
|
462 |
@param aAlign The align requirement.
|
williamr@2
|
463 |
*/
|
williamr@2
|
464 |
TInet6PacketBase(TAlign aAlign) : iLength(0), iAlign(aAlign) {}
|
williamr@2
|
465 |
|
williamr@2
|
466 |
/**
|
williamr@2
|
467 |
Length of the mapped region.
|
williamr@2
|
468 |
|
williamr@2
|
469 |
The real mapped length as computed by the Access function.
|
williamr@2
|
470 |
If access returned non-NULL, the following is always TRUE:
|
williamr@2
|
471 |
|
williamr@2
|
472 |
@li aMin <= iLength
|
williamr@2
|
473 |
*/
|
williamr@2
|
474 |
TInt iLength;
|
williamr@2
|
475 |
|
williamr@2
|
476 |
IMPORT_C TUint8 *Access(RMBufChain &aPacket, TInt aOffset, TInt aSize, TInt aMin);
|
williamr@2
|
477 |
|
williamr@2
|
478 |
inline void SetAlign(TAlign aAlign)
|
williamr@2
|
479 |
/**
|
williamr@2
|
480 |
* Changes the align requirement.
|
williamr@2
|
481 |
*
|
williamr@2
|
482 |
* @param aAlign The new align requirement.
|
williamr@2
|
483 |
*/
|
williamr@2
|
484 |
{
|
williamr@2
|
485 |
iAlign = aAlign;
|
williamr@2
|
486 |
}
|
williamr@2
|
487 |
protected:
|
williamr@2
|
488 |
/**
|
williamr@2
|
489 |
The align requirement.
|
williamr@2
|
490 |
*/
|
williamr@2
|
491 |
TAlign iAlign;
|
williamr@2
|
492 |
};
|
williamr@2
|
493 |
|
williamr@2
|
494 |
// TInet6Packet template
|
williamr@2
|
495 |
// *********************
|
williamr@2
|
496 |
template <class T>
|
williamr@2
|
497 |
class TInet6Packet : public TInet6PacketBase
|
williamr@2
|
498 |
/**
|
williamr@2
|
499 |
Encapsulates an IPv6 packet header as a section of an RMBufChain.
|
williamr@2
|
500 |
|
williamr@2
|
501 |
The T template parameter should represent a packet header type. It should
|
williamr@2
|
502 |
support static functions MaxHeaderLength() and MinHeaderLength() that return
|
williamr@2
|
503 |
TInt values for maximum and minimum header lengths respectively.
|
williamr@2
|
504 |
|
williamr@2
|
505 |
@publishedAll
|
williamr@2
|
506 |
@released
|
williamr@2
|
507 |
@since v7.0
|
williamr@2
|
508 |
*/
|
williamr@2
|
509 |
{
|
williamr@2
|
510 |
public:
|
williamr@2
|
511 |
TInet6Packet(TAlign aAlign = EAlign4) : TInet6PacketBase(aAlign), iHdr(NULL)
|
williamr@2
|
512 |
/**
|
williamr@2
|
513 |
Default constructor.
|
williamr@2
|
514 |
|
williamr@2
|
515 |
Construct an empty mapping. To be usable, the Set() function
|
williamr@2
|
516 |
must be used.
|
williamr@2
|
517 |
*/
|
williamr@2
|
518 |
{}
|
williamr@2
|
519 |
TInet6Packet(RMBufChain &aPacket) : TInet6PacketBase(EAlign4)
|
williamr@2
|
520 |
/**
|
williamr@2
|
521 |
Constructor specifying a RMBufChain object.
|
williamr@2
|
522 |
|
williamr@2
|
523 |
Verify and arrange it so that a class T can be mapped
|
williamr@2
|
524 |
to a contiguous octets from the beginning of the RMBufChain
|
williamr@2
|
525 |
content, and set iHdr to point this area.
|
williamr@2
|
526 |
|
williamr@2
|
527 |
If this is not possible, iHdr is initialized to NULL.
|
williamr@2
|
528 |
|
williamr@2
|
529 |
@param aPacket
|
williamr@2
|
530 |
Packet containing the header T at offset = 0
|
williamr@2
|
531 |
*/
|
williamr@2
|
532 |
{
|
williamr@2
|
533 |
iHdr = (T *)Access(aPacket, 0, T::MaxHeaderLength(), T::MinHeaderLength());
|
williamr@2
|
534 |
}
|
williamr@2
|
535 |
|
williamr@2
|
536 |
TInet6Packet(RMBufChain &aPacket, TInt aOffset, TAlign aAlign = EAlign4) : TInet6PacketBase(aAlign)
|
williamr@2
|
537 |
/**
|
williamr@2
|
538 |
Constructor specifying a RMBufChain object and an offset.
|
williamr@2
|
539 |
|
williamr@2
|
540 |
Verify and arrange it so that a class T can be mapped
|
williamr@2
|
541 |
to a contiguous octets starting at specified offset of
|
williamr@2
|
542 |
the RMBufChain content, and set iHdr to point this area.
|
williamr@2
|
543 |
|
williamr@2
|
544 |
If this is not possible, iHdr is initialized to NULL.
|
williamr@2
|
545 |
|
williamr@2
|
546 |
@param aPacket
|
williamr@2
|
547 |
Packet containing the header T at aOffset
|
williamr@2
|
548 |
@param aOffset
|
williamr@2
|
549 |
Offset of the header to be mapped.
|
williamr@2
|
550 |
@param aAlign
|
williamr@2
|
551 |
The alignement requirement.
|
williamr@2
|
552 |
*/
|
williamr@2
|
553 |
{
|
williamr@2
|
554 |
iHdr = (T *)Access(aPacket, aOffset, T::MaxHeaderLength(), T::MinHeaderLength());
|
williamr@2
|
555 |
}
|
williamr@2
|
556 |
|
williamr@2
|
557 |
void Set(RMBufChain &aPacket, TInt aOffset, TInt aSize)
|
williamr@2
|
558 |
/**
|
williamr@2
|
559 |
Sets the packet header from a specified RMBufChain object.
|
williamr@2
|
560 |
|
williamr@2
|
561 |
Verify and arrange it so that a aSize octets can be mapped
|
williamr@2
|
562 |
to a contiguous octets starting at specified offset of
|
williamr@2
|
563 |
the RMBufChain content, and set iHdr to point this area.
|
williamr@2
|
564 |
|
williamr@2
|
565 |
If this is not possible, iHdr is initialized to NULL.
|
williamr@2
|
566 |
|
williamr@2
|
567 |
Note that this differs from the contructors: the required
|
williamr@2
|
568 |
size is a parameter, and not determined by the T::MinHeaderLength().
|
williamr@2
|
569 |
However, the "T* iHdr" is set to point the start of the requested
|
williamr@2
|
570 |
area. It's a responsibility of the user of this method to know
|
williamr@2
|
571 |
whether using this pointer is safe with the specified size parameter.
|
williamr@2
|
572 |
|
williamr@2
|
573 |
@param aPacket
|
williamr@2
|
574 |
Packet containing the header T at aOffset
|
williamr@2
|
575 |
@param aOffset
|
williamr@2
|
576 |
Offset (position) of the header to be mapped
|
williamr@2
|
577 |
@param aSize
|
williamr@2
|
578 |
Length of required contiguous memory
|
williamr@2
|
579 |
*/
|
williamr@2
|
580 |
{
|
williamr@2
|
581 |
iHdr = (T *)Access(aPacket, aOffset, aSize, aSize);
|
williamr@2
|
582 |
}
|
williamr@2
|
583 |
|
williamr@2
|
584 |
inline T& operator()()
|
williamr@2
|
585 |
{
|
williamr@2
|
586 |
return *iHdr;
|
williamr@2
|
587 |
}
|
williamr@2
|
588 |
/**
|
williamr@2
|
589 |
The pointer to the mapped region (if non-NULL). If NULL,
|
williamr@2
|
590 |
then there is no mapping, and iLength == 0.
|
williamr@2
|
591 |
*/
|
williamr@2
|
592 |
T *iHdr;
|
williamr@2
|
593 |
};
|
williamr@2
|
594 |
|
williamr@2
|
595 |
|
williamr@2
|
596 |
// TPacketPoker
|
williamr@2
|
597 |
// ************
|
williamr@2
|
598 |
class TPacketPoker
|
williamr@2
|
599 |
/**
|
williamr@2
|
600 |
Provides a utility for linear scanning of a chain of RMBuf objects (an RMBufChain).
|
williamr@2
|
601 |
|
williamr@2
|
602 |
An object of this type maintains a current point in the RMBufChain. This point
|
williamr@2
|
603 |
can only move forward, and a leave occurs if the point advances beyond the
|
williamr@2
|
604 |
end of the chain.
|
williamr@2
|
605 |
|
williamr@2
|
606 |
Any pointers and aligns arranged before the current point, remain valid: for
|
williamr@2
|
607 |
example, you can save a reference and advance the pointer, and the reference
|
williamr@2
|
608 |
remains usable.
|
williamr@2
|
609 |
|
williamr@2
|
610 |
If instead you need to go to a single specified offset, then use
|
williamr@2
|
611 |
RMBufChain::Goto() or RMBufPacketPeek::Access().
|
williamr@2
|
612 |
|
williamr@2
|
613 |
@post
|
williamr@2
|
614 |
A Generic implementation assert:
|
williamr@2
|
615 |
after construct, iTail == 0 iff iCurrent == 0 (all scanned), or
|
williamr@2
|
616 |
in other words: as long as there are bytes after current point,
|
williamr@2
|
617 |
iTail will be non-zero (and More() returns ETrue).
|
williamr@2
|
618 |
All methods maintain this invariant or leave, if impossible.
|
williamr@2
|
619 |
|
williamr@2
|
620 |
Some other utility methods, not directly related to scanning, are also included.
|
williamr@2
|
621 |
@since v7.0
|
williamr@2
|
622 |
@publishedAll
|
williamr@2
|
623 |
@released
|
williamr@2
|
624 |
*/
|
williamr@2
|
625 |
{
|
williamr@2
|
626 |
public:
|
williamr@2
|
627 |
IMPORT_C TPacketPoker(RMBufChain &aChain);
|
williamr@2
|
628 |
|
williamr@2
|
629 |
inline void SkipL(TInt aSize)
|
williamr@2
|
630 |
/**
|
williamr@2
|
631 |
Moves the current point forward a specified number of bytes.
|
williamr@2
|
632 |
|
williamr@2
|
633 |
@param aSize Number of bytes to move forward
|
williamr@2
|
634 |
@leave KErrEof
|
williamr@2
|
635 |
if the request cannot be satisfied.
|
williamr@2
|
636 |
*/
|
williamr@2
|
637 |
{ if (aSize < iTail) { iTail -= aSize; iOffset += aSize; } else OverL(aSize); }
|
williamr@2
|
638 |
|
williamr@2
|
639 |
inline TUint8 *Ptr() const
|
williamr@2
|
640 |
/**
|
williamr@2
|
641 |
Raw pointer to the current point (can be invalid, if iTail = 0).
|
williamr@2
|
642 |
|
williamr@2
|
643 |
@note Internal "unsafe" method
|
williamr@2
|
644 |
*/
|
williamr@2
|
645 |
{return iCurrent->Ptr() + iOffset; }
|
williamr@2
|
646 |
|
williamr@2
|
647 |
inline TUint8 *ReferenceL(TInt aSize = 1)
|
williamr@2
|
648 |
/**
|
williamr@2
|
649 |
Gets a pointer to the current point, such that
|
williamr@2
|
650 |
at least the specified minimum number of bytes can be read.
|
williamr@2
|
651 |
|
williamr@2
|
652 |
@param aSize
|
williamr@2
|
653 |
Specified minimum number of bytes to be read through
|
williamr@2
|
654 |
the returned pointer.
|
williamr@2
|
655 |
@return Raw data pointer
|
williamr@2
|
656 |
@leave KErrEof
|
williamr@2
|
657 |
if the request cannot be satisfied.
|
williamr@2
|
658 |
*/
|
williamr@2
|
659 |
{ if (iTail >= aSize) return Ptr(); else return AdjustL(aSize); }
|
williamr@2
|
660 |
|
williamr@2
|
661 |
inline TUint8 *ReferenceAndSkipL(TInt aSize)
|
williamr@2
|
662 |
/**
|
williamr@2
|
663 |
Gets a pointer to the current point, such that at least the
|
williamr@2
|
664 |
specified minimum number of bytes can be read,
|
williamr@2
|
665 |
and moves the point the specified number of bytes forward.
|
williamr@2
|
666 |
|
williamr@2
|
667 |
@param aSize
|
williamr@2
|
668 |
Specified minimum number of bytes to be read through the returned
|
williamr@2
|
669 |
pointer, and the number of bytes to move forward
|
williamr@2
|
670 |
@return
|
williamr@2
|
671 |
Raw data pointer
|
williamr@2
|
672 |
@leave KErrEof
|
williamr@2
|
673 |
if the request cannot be satisfied.
|
williamr@2
|
674 |
*/
|
williamr@2
|
675 |
{ TUint8 *x = ReferenceL(aSize); SkipL(aSize); return x; }
|
williamr@2
|
676 |
|
williamr@2
|
677 |
inline TInt Remainder() const
|
williamr@2
|
678 |
/**
|
williamr@2
|
679 |
Gets the length of the contiguous space after the current point.
|
williamr@2
|
680 |
|
williamr@2
|
681 |
@return Length after the current point
|
williamr@2
|
682 |
*/
|
williamr@2
|
683 |
{ return iTail; }
|
williamr@2
|
684 |
|
williamr@2
|
685 |
inline TBool AtBegin() const
|
williamr@2
|
686 |
/**
|
williamr@2
|
687 |
Tests whether the current point is at the beginning of an RMBuf.
|
williamr@2
|
688 |
|
williamr@2
|
689 |
@return ETrue if current point is at the beginning
|
williamr@2
|
690 |
*/
|
williamr@2
|
691 |
{ return iOffset == 0; }
|
williamr@2
|
692 |
|
williamr@2
|
693 |
inline TBool More() const
|
williamr@2
|
694 |
/**
|
williamr@2
|
695 |
Tests whether there is more data to scan.
|
williamr@2
|
696 |
|
williamr@2
|
697 |
@return ETrue if there is more data to scan
|
williamr@2
|
698 |
*/
|
williamr@2
|
699 |
{ return iTail > 0; }
|
williamr@2
|
700 |
|
williamr@2
|
701 |
IMPORT_C static TBool IsExtensionHeader(TInt aProtocolId);
|
williamr@2
|
702 |
private:
|
williamr@2
|
703 |
IMPORT_C void OverL(TInt aSize);
|
williamr@2
|
704 |
IMPORT_C TUint8 *AdjustL(TInt aSize);
|
williamr@2
|
705 |
/** The RMBuf of the current point. */
|
williamr@2
|
706 |
RMBuf *iCurrent;
|
williamr@2
|
707 |
/** The offset of the current point in the RMBuf. */
|
williamr@2
|
708 |
TInt iOffset;
|
williamr@2
|
709 |
/** Remaining bytes starting from the current point in the RMBuf. */
|
williamr@2
|
710 |
TInt iTail;
|
williamr@2
|
711 |
};
|
williamr@2
|
712 |
|
williamr@2
|
713 |
#endif
|