|
1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // Name : CIcmpV6Receiver.cpp |
|
15 // Part of : ConnectionMgr |
|
16 // Version : SIP/4.0 |
|
17 // Destination Unreachable Message: |
|
18 // 0 1 2 3 |
|
19 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
|
20 // | Type | Code | Checksum | |
|
21 // | Unused | |
|
22 // | As much of invoking packet | |
|
23 // + as will fit without the ICMPv6 packet + |
|
24 // | exceeding the minimum IPv6 MTU [IPv6] | |
|
25 // IPv6 Header Format: |
|
26 // 0 1 2 3 |
|
27 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
|
28 // |Version| Traffic Class | Flow Label | |
|
29 // | Payload Length | Next Header | Hop Limit | |
|
30 // + Source Address + |
|
31 // + Destination Address + |
|
32 // Extension Header Format: |
|
33 // | Next Header | Hdr Ext Len | | |
|
34 // . type-specific data (variable length) . |
|
35 // User datagram: |
|
36 // 0 7 8 15 16 23 24 31 |
|
37 // | Source | Destination | |
|
38 // | Port | Port | |
|
39 // | Length | Checksum | |
|
40 // | data octets ... |
|
41 // In the code the data is located in 8-bit pieces. |
|
42 // |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 #include <ip6_hdr.h> |
|
48 #include <icmp6_hdr.h> |
|
49 #include <udp_hdr.h> |
|
50 #include <ext_hdr.h> |
|
51 #include <in_sock.h> |
|
52 #include "CIcmpV6Receiver.h" |
|
53 #include "MIcmpReceiver.h" |
|
54 #include "CSipConnection.h" |
|
55 #include "CommonConsts.h" |
|
56 #include "SipLogs.h" |
|
57 |
|
58 |
|
59 // ----------------------------------------------------------------------------- |
|
60 // CIcmpV6Receiver::NewL |
|
61 // ----------------------------------------------------------------------------- |
|
62 // |
|
63 CIcmpV6Receiver* CIcmpV6Receiver::NewL(MIcmpErrorObserver& aObserver, |
|
64 RSocketServ& aServer) |
|
65 { |
|
66 CIcmpV6Receiver* self = new (ELeave) CIcmpV6Receiver(); |
|
67 CleanupStack::PushL(self); |
|
68 self->ConstructL(aObserver, aServer); |
|
69 CleanupStack::Pop(); |
|
70 return self; |
|
71 } |
|
72 |
|
73 // ----------------------------------------------------------------------------- |
|
74 // CIcmpV6Receiver::CIcmpV6Receiver |
|
75 // ----------------------------------------------------------------------------- |
|
76 // |
|
77 CIcmpV6Receiver::CIcmpV6Receiver() : CActive( CActive::EPriorityStandard ) |
|
78 { |
|
79 } |
|
80 |
|
81 // ----------------------------------------------------------------------------- |
|
82 // CIcmpV6Receiver::ConstructL |
|
83 // ----------------------------------------------------------------------------- |
|
84 // |
|
85 void CIcmpV6Receiver::ConstructL(MIcmpErrorObserver& aObserver, |
|
86 RSocketServ& aServer) |
|
87 { |
|
88 CActiveScheduler::Add(this); |
|
89 iObserver = &aObserver; |
|
90 iServer = &aServer; |
|
91 |
|
92 // Start |
|
93 User::LeaveIfError(iSocket.Open(*iServer, KAfInet, KSockDatagram, |
|
94 KProtocolInet6Icmp)); |
|
95 Receive(); |
|
96 } |
|
97 |
|
98 // ----------------------------------------------------------------------------- |
|
99 // CIcmpV6Receiver::~CIcmpV6Receiver |
|
100 // ----------------------------------------------------------------------------- |
|
101 // |
|
102 CIcmpV6Receiver::~CIcmpV6Receiver() |
|
103 { |
|
104 Cancel(); |
|
105 iSocket.Close(); |
|
106 } |
|
107 |
|
108 // ----------------------------------------------------------------------------- |
|
109 // CIcmpV6Receiver::RunL |
|
110 // ----------------------------------------------------------------------------- |
|
111 // |
|
112 void CIcmpV6Receiver::RunL() |
|
113 { |
|
114 if(iStatus == KErrNone) |
|
115 { |
|
116 CheckError(); |
|
117 Receive(); |
|
118 } |
|
119 } |
|
120 |
|
121 // Disabled PC-Lint warning for "Suspicious pointer-to-pointer conversion |
|
122 // (area too small))". It was caused by TUin8* to TInet6xxx typecasts and could |
|
123 // not be avoided otherwise. |
|
124 /*lint -e826 */ |
|
125 |
|
126 // ----------------------------------------------------------------------------- |
|
127 // CIcmpV6Receiver::CheckError |
|
128 // ----------------------------------------------------------------------------- |
|
129 // |
|
130 void CIcmpV6Receiver::CheckError() |
|
131 { |
|
132 const TUint KDestinationUnreachable = 1; |
|
133 |
|
134 // Pointer to ICMP header |
|
135 TInet6HeaderICMP* icmpPtr = ( TInet6HeaderICMP* ) iData.Ptr(); |
|
136 |
|
137 // Pointer to IPv6 header |
|
138 TInet6HeaderIP* ipv6Ptr = ( TInet6HeaderIP* )( iData.Ptr() + 8 ); |
|
139 // Get the whole length of the header in bytes |
|
140 TUint32 payloadLength = ipv6Ptr->PayloadLength(); |
|
141 TUint32 offset = 0; |
|
142 |
|
143 // Pointer to IPv6 extension header |
|
144 TInet6HeaderExtension* extPtr = |
|
145 ( TInet6HeaderExtension* )( iData.Ptr() + 14 ); |
|
146 // Get the extension header length in bytes |
|
147 TUint32 extHdrLength = extPtr->HeaderLength(); |
|
148 |
|
149 // Pointer to UDP data |
|
150 TInet6HeaderUDP* udpPtr = ( TInet6HeaderUDP* )( ipv6Ptr->EndPtr() ); |
|
151 |
|
152 // Error message type |
|
153 TUint32 error = icmpPtr->Type(); |
|
154 if( error == KDestinationUnreachable ) |
|
155 { |
|
156 TUint32 nextHeader = 0; |
|
157 do // Search the correct header, if there are extension headers |
|
158 { |
|
159 nextHeader = extPtr->NextHeader(); |
|
160 if( nextHeader == KProtocolInetUdp ) |
|
161 { |
|
162 // Get the destination port number |
|
163 iAddress.SetPort( udpPtr->DstPort() ); |
|
164 |
|
165 // Set the destination address |
|
166 iAddress.SetAddress( ipv6Ptr->DstAddr() ); |
|
167 |
|
168 __SIP_INT_LOG1( "ICMP error", error ) |
|
169 __SIP_ADDR_LOG( "ICMP error address", iAddress ) |
|
170 |
|
171 iObserver->IcmpError( iAddress ); |
|
172 } |
|
173 else |
|
174 { |
|
175 // Step to next header |
|
176 if( offset < payloadLength ) |
|
177 { |
|
178 extPtr = extPtr + extHdrLength; |
|
179 offset = offset + extHdrLength; |
|
180 } |
|
181 } |
|
182 // Loop until UDP datagram is found. If it is not found, |
|
183 // get out of here and do nothing. |
|
184 } while ((nextHeader != KProtocolInetUdp) && (offset < payloadLength)); |
|
185 } |
|
186 } |
|
187 |
|
188 // ----------------------------------------------------------------------------- |
|
189 // CIcmpV6Receiver::DoCancel |
|
190 // ----------------------------------------------------------------------------- |
|
191 // |
|
192 void CIcmpV6Receiver::DoCancel() |
|
193 { |
|
194 iSocket.CancelRecv(); |
|
195 } |
|
196 |
|
197 // ----------------------------------------------------------------------------- |
|
198 // CIcmpV6Receiver::Receive |
|
199 // ----------------------------------------------------------------------------- |
|
200 // |
|
201 void CIcmpV6Receiver::Receive() |
|
202 { |
|
203 if(!IsActive()) |
|
204 { |
|
205 iSocket.Recv( iData, 0, iStatus ); |
|
206 SetActive(); |
|
207 } |
|
208 } |