|
1 // Copyright (c) 2006-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 // inet.cpp - inet protocol base |
|
15 // |
|
16 |
|
17 #include <in_pkt.h> |
|
18 #include <ext_hdr.h> |
|
19 #include <comms-infras/nifif.h> |
|
20 #include <comms-infras/nifif_internal.h> |
|
21 #include "inet.h" |
|
22 #include "networkinfo.h" |
|
23 #include "inet6log.h" |
|
24 |
|
25 // |
|
26 // CProtocolInet6Base |
|
27 // |
|
28 // |
|
29 |
|
30 CProtocolInet6Base::CProtocolInet6Base() |
|
31 { |
|
32 // Nothing here -- rely on CBase zero fill! |
|
33 } |
|
34 |
|
35 void CProtocolInet6Base::InitL(TDesC& /*aTag*/) |
|
36 { |
|
37 #ifdef _LOG |
|
38 // Fetch the protocol name for logging purposes |
|
39 TServerProtocolDesc info; |
|
40 Identify(&info); |
|
41 iName = info.iName; |
|
42 #endif |
|
43 } |
|
44 |
|
45 void CProtocolInet6Base::BindL(CProtocolBase* /*aProtocol*/, TUint /*aId*/) |
|
46 { |
|
47 Panic(EInet6Panic_NotSupported); |
|
48 } |
|
49 |
|
50 void CProtocolInet6Base::Unbind(CProtocolBase* /*aProtocol*/, TUint /*aId*/) |
|
51 { |
|
52 } |
|
53 |
|
54 void CProtocolInet6Base::StartL() |
|
55 { |
|
56 } |
|
57 |
|
58 // |
|
59 // *NOTE* |
|
60 // In the INET6 stack the Error upcall is passed up from the drivers |
|
61 // but, it does not require any actions by default (doing something |
|
62 // here is only useful for protocols modules that want to know about |
|
63 // changes in the interfaces and possibly doing there own |
|
64 // reconfiguring after this (for example, 6to4). |
|
65 // |
|
66 // In INET6 the interface manager takes care of notifying individual |
|
67 // flows about the interface changes that affect them. -- msa |
|
68 // |
|
69 // This here is required, because the base CProtocolBase::Error() |
|
70 // calls Panic. A similar consideration applies to the StartSending(), |
|
71 // but as the CProtocolBase::StartSending() is already a NOP, nothing |
|
72 // needs to be done here. |
|
73 // |
|
74 void CProtocolInet6Base::Error(TInt /*anError*/, CProtocolBase* /*aSourceProtocol*/) |
|
75 { |
|
76 } |
|
77 |
|
78 |
|
79 CProtocolInet6Base::~CProtocolInet6Base() |
|
80 { |
|
81 // All SAP's should have been detached from this by now! |
|
82 ASSERT(iSapCount == 0); |
|
83 } |
|
84 |
|
85 |
|
86 // |
|
87 // SAP counting |
|
88 // |
|
89 void CProtocolInet6Base::IncSAPs() |
|
90 { |
|
91 iSapCount++; |
|
92 } |
|
93 |
|
94 void CProtocolInet6Base::DecSAPs() |
|
95 { |
|
96 ASSERT(iSapCount > 0); |
|
97 iSapCount--; |
|
98 } |
|
99 |
|
100 // |
|
101 // SAP database routines |
|
102 // |
|
103 void CProtocolInet6Base::BindProvider(CProviderInet6Base* aSAP) |
|
104 { |
|
105 #ifdef _LOG |
|
106 TBuf<50> local; aSAP->iFlow.FlowContext()->LocalAddr().OutputWithScope(local); |
|
107 TBuf<50> remote; aSAP->iFlow.FlowContext()->RemoteAddr().OutputWithScope(remote); |
|
108 Log::Printf(_L("\t%S SAP[%u] BindProvider({%S,%d} <--> {%S,%d})"), |
|
109 &ProtocolName(), (TInt)aSAP, |
|
110 &local, aSAP->iFlow.FlowContext()->LocalPort(), &remote, aSAP->iFlow.FlowContext()->RemotePort()); |
|
111 #endif |
|
112 |
|
113 TUint key = ProviderHashKey(aSAP->iFlow.FlowContext()->LocalPort()); |
|
114 aSAP->iNextSAP = iSAP[key]; |
|
115 iSAP[key] = aSAP; |
|
116 } |
|
117 |
|
118 void CProtocolInet6Base::QueueBindProvider(CProviderInet6Base* aSAP) |
|
119 { |
|
120 #ifdef _LOG |
|
121 TBuf<50> local; aSAP->iFlow.FlowContext()->LocalAddr().OutputWithScope(local); |
|
122 TBuf<50> remote; aSAP->iFlow.FlowContext()->RemoteAddr().OutputWithScope(remote); |
|
123 Log::Printf(_L("\t%S SAP[%u] QueueBindProvider(): {%S,%d} <--> {%S,%d}"), |
|
124 &ProtocolName(), (TInt)this, |
|
125 &local, aSAP->iFlow.FlowContext()->LocalPort(), &remote, aSAP->iFlow.FlowContext()->RemotePort()); |
|
126 #endif |
|
127 |
|
128 TUint key = ProviderHashKey(aSAP->iFlow.FlowContext()->LocalPort()); |
|
129 CProviderInet6Base **sap = &iSAP[key]; |
|
130 while (*sap != NULL) |
|
131 sap = &(*sap)->iNextSAP; |
|
132 *sap = aSAP; |
|
133 } |
|
134 |
|
135 void CProtocolInet6Base::UnbindProvider(CProviderInet6Base* aSAP) |
|
136 { |
|
137 CProviderInet6Base **sapPtr; |
|
138 TUint key; |
|
139 |
|
140 if (aSAP->iFlow.FlowContext() == NULL) |
|
141 return; |
|
142 |
|
143 key = ProviderHashKey(aSAP->iFlow.FlowContext()->LocalPort()); |
|
144 for (sapPtr = &iSAP[key]; *sapPtr != NULL; sapPtr = &((*sapPtr)->iNextSAP)) |
|
145 if (*sapPtr == aSAP) |
|
146 { |
|
147 #ifdef _LOG |
|
148 TBuf<50> local; aSAP->iFlow.FlowContext()->LocalAddr().OutputWithScope(local); |
|
149 TBuf<50> remote; aSAP->iFlow.FlowContext()->RemoteAddr().OutputWithScope(remote); |
|
150 Log::Printf(_L("\t%S SAP[%u] UnbindProvider({%S,%d} <--> {%S,%d})"), |
|
151 &ProtocolName(), (TInt)aSAP, |
|
152 &local, aSAP->iFlow.FlowContext()->LocalPort(), &remote, aSAP->iFlow.FlowContext()->RemotePort()); |
|
153 #endif |
|
154 *sapPtr = (*sapPtr)->iNextSAP; |
|
155 aSAP->iNextSAP = NULL; |
|
156 return; |
|
157 } |
|
158 } |
|
159 |
|
160 CProviderInet6Base* CProtocolInet6Base::LocateProvider(TUint aPort) |
|
161 { |
|
162 CProviderInet6Base *sap; |
|
163 TUint key = ProviderHashKey(aPort); |
|
164 |
|
165 for (sap = iSAP[key]; sap != NULL; sap = sap->iNextSAP) |
|
166 if (sap->iFlow.FlowContext()->LocalPort() == aPort) |
|
167 return sap; |
|
168 |
|
169 return NULL; |
|
170 } |
|
171 |
|
172 void CProviderInet6Base::InitL() |
|
173 { |
|
174 TInt err = iFlow.Open(iProtocol->NetworkService()); |
|
175 if (err != KErrNone) |
|
176 User::Leave(err); |
|
177 |
|
178 iFlow.SetNotify(this); |
|
179 |
|
180 iLastError.iStatus = KErrNone; |
|
181 iLastError.iErrType = 0; |
|
182 iLastError.iErrCode = 0; |
|
183 iErrorMask = 0; |
|
184 } |
|
185 |
|
186 void CProviderInet6Base::Start() |
|
187 { |
|
188 #if 0 |
|
189 // XXX - Setting socket write buffer to 1024 seems to seriously |
|
190 // hamper TCP performance over loopback. Default is 4096 and 2048 |
|
191 // also works ok. Have to look at this later. -ML |
|
192 TVersion v = RNif::Version(); |
|
193 TUint32 ver = (v.iMajor << 24) | (v.iMinor << 16) | v.iBuild; |
|
194 if (ver >= 0x01000044) |
|
195 Nif::SetSocketState(ENifBuffers1024, this); |
|
196 #endif |
|
197 } |
|
198 |
|
199 |
|
200 // |
|
201 // CProviderInet6Base |
|
202 // |
|
203 // |
|
204 |
|
205 CProviderInet6Base::CProviderInet6Base(CProtocolInet6Base* aProtocol) : iProtocol(aProtocol) |
|
206 { |
|
207 LOG(Log::Printf(_L("\t%S SAP[%u] New"), &ProtocolName(), (TInt)this)); |
|
208 iNextSAP = NULL; |
|
209 iProtocol->Open(); |
|
210 iProtocol->IncSAPs(); |
|
211 if (iIsUser == 0) |
|
212 { |
|
213 iProtocol->NetworkService()->IncUsers(); |
|
214 iIsUser = 1; |
|
215 } |
|
216 } |
|
217 |
|
218 CProviderInet6Base::~CProviderInet6Base() |
|
219 { |
|
220 ((CProtocolInet6Base*)iProtocol)->UnbindProvider(this); |
|
221 CFlowContext *flow = iFlow.FlowContext(); |
|
222 if (flow) |
|
223 { |
|
224 TPckgBuf< TInt > opt(0); // Currently there is no use for the option parameter |
|
225 flow->SetOption(KSOLProvider, KSoFlowClosing, opt); |
|
226 } |
|
227 iFlow.Close(); |
|
228 if (iIsUser == 1) |
|
229 { |
|
230 iProtocol->NetworkService()->DecUsers(); |
|
231 iIsUser = 0; |
|
232 } |
|
233 iProtocol->DecSAPs(); |
|
234 LOG(Log::Printf(_L("\t%S SAP[%u] Deleted"), &ProtocolName(), (TInt)this)); |
|
235 iProtocol->Close(); |
|
236 } |
|
237 |
|
238 |
|
239 void CProviderInet6Base::ActiveOpen() |
|
240 { |
|
241 Panic(EInet6Panic_NotSupported); |
|
242 } |
|
243 |
|
244 |
|
245 TInt CProviderInet6Base::PassiveOpen(TUint /*aQueSize*/) |
|
246 { |
|
247 Panic(EInet6Panic_NotSupported); |
|
248 return 0; |
|
249 } |
|
250 |
|
251 |
|
252 void CProviderInet6Base::ActiveOpen(const TDesC8& /*aConnectionData*/) |
|
253 { |
|
254 Panic(EInet6Panic_NotSupported); |
|
255 } |
|
256 |
|
257 |
|
258 TInt CProviderInet6Base::PassiveOpen(TUint /*aQueSize*/,const TDesC8& /*aConnectionData*/) |
|
259 { |
|
260 Panic(EInet6Panic_NotSupported); |
|
261 return 0; |
|
262 } |
|
263 |
|
264 void CProviderInet6Base::Shutdown(TCloseType /*option*/,const TDesC8& /*aDisconnectionData*/) |
|
265 { |
|
266 Panic(EInet6Panic_NotSupported); |
|
267 } |
|
268 |
|
269 // *NOTE* |
|
270 // Why are level KSoInetIfCtrl and KSoInetRtCtrl handled at this |
|
271 // level? Why not just let iProtocol->SetOption() handle them (as |
|
272 // would be logical)? The reason is KSoInetEnum*/KSoInetNext*, which |
|
273 // need a SAP specific context, and that is *NOT* provided by the |
|
274 // iProtocol->SetOption interface. However, only these options are |
|
275 // handled here, rest of the KSoInetRtCtrl/KSoInetIfCtrl are passed |
|
276 // to the protocol -- msa |
|
277 // |
|
278 TInt CProviderInet6Base::SetOption(TUint aLevel, TUint aName, const TDesC8& aOption) |
|
279 { |
|
280 if (aLevel == KSolInetIp) |
|
281 { |
|
282 // Prefetch the option parameter (error return is ignored, |
|
283 // if the option is not implemented at this level). |
|
284 TInt val; |
|
285 const TInt ret = GetOptionInt(aOption, val); |
|
286 |
|
287 switch (aName) |
|
288 { |
|
289 case KSoHeaderIncluded: |
|
290 case KSoRawMode: |
|
291 // *note* Need to arrange KErrNotSupported for TCP! -- msa |
|
292 |
|
293 // Implementation of setting HeaderIncluded and RawMode options |
|
294 if (ret != KErrNone) |
|
295 return ret; |
|
296 // [The raw/headerincluded logic here is unnecessarily convoluted. |
|
297 // In EPOC they could be handled independently, as there is no |
|
298 // special priviledges required for setting the raw mode either. |
|
299 // But, because it is specified to work in this way, sigh ... |
|
300 // -- msa] |
|
301 // |
|
302 // Only allow setting of iHeaderIncluded when iRawMode is set |
|
303 // Clearing is always allowed. |
|
304 // When iRawMode==0, then *ALWAYS* iHeaderIncluded == 0 |
|
305 if (aName == KSoRawMode) |
|
306 { |
|
307 if (val) |
|
308 iRawMode = 1; |
|
309 else |
|
310 { |
|
311 iRawMode = 0; |
|
312 iHeaderIncluded = 0; |
|
313 } |
|
314 } |
|
315 else if (val == 0) |
|
316 iHeaderIncluded = 0; |
|
317 else if (iRawMode) |
|
318 { |
|
319 iHeaderIncluded = 1; |
|
320 } |
|
321 else |
|
322 return KErrNotSupported; // attempted to set KSoHeaderIncluded without Raw mode |
|
323 #ifdef _LOG |
|
324 Log::Printf(_L("SetOpt\t%S SAP[%u] RawMode=%d HeaderInclude=%d"), |
|
325 &ProtocolName(), (TInt)this, iRawMode, iHeaderIncluded); |
|
326 #endif |
|
327 return KErrNone; |
|
328 |
|
329 case KSoUserSocket: |
|
330 if (ret != KErrNone) |
|
331 return ret; |
|
332 #ifdef _LOG |
|
333 Log::Printf(_L("SetOpt\t%S SAP[%u] KSoUserSocket %d -> %d"), |
|
334 &ProtocolName(), (TInt)this, iIsUser, val); |
|
335 #endif |
|
336 if ((TUint)val == iIsUser) |
|
337 return KErrNone; // No change in state |
|
338 else if (val == 0) |
|
339 { |
|
340 iProtocol->NetworkService()->DecUsers(); |
|
341 iIsUser = 0; |
|
342 return KErrNone; |
|
343 } |
|
344 else if (val == 1) |
|
345 { |
|
346 iProtocol->NetworkService()->IncUsers(); |
|
347 iIsUser = 1; |
|
348 return KErrNone; |
|
349 } |
|
350 else |
|
351 return KErrArgument; |
|
352 default: |
|
353 // For now, give generic LOG here, but should really log at each implementation -- msa |
|
354 LOG(Log::Printf(_L("SetOpt\t%S SAP[%u] level=KSolInetIp name=%d"), &ProtocolName(), (TInt)this, aName)); |
|
355 break; |
|
356 } |
|
357 } |
|
358 else if (aLevel == KSolInetIfCtrl) |
|
359 { |
|
360 if (aName == STATIC_CAST(TUint, KSoInetEnumInterfaces)) // See *NOTE* above! |
|
361 { |
|
362 iInterfaceIndex = 0; |
|
363 LOG(Log::Printf(_L("SetOpt\t%S SAP[%u] KSoInetEnumInterfaces"), &ProtocolName(), (TInt)this)); |
|
364 return KErrNone; |
|
365 } |
|
366 } |
|
367 else if (aLevel == KSolInetRtCtrl) |
|
368 { |
|
369 if (aName == STATIC_CAST(TUint, KSoInetEnumRoutes)) // See *NOTE* above! |
|
370 { |
|
371 iRouteIndex = 0; |
|
372 LOG(Log::Printf(_L("SetOpt\t%S SAP[%u] KSoInetEnumRoutes"), &ProtocolName(), (TInt)this)); |
|
373 return KErrNone; |
|
374 } |
|
375 } |
|
376 else if (aLevel == KNifOptLevel) |
|
377 { |
|
378 return KErrNotSupported; |
|
379 } |
|
380 if (iFlow.FlowContext()) |
|
381 { |
|
382 const TInt ret = iFlow.FlowContext()->SetOption(aLevel, aName, aOption); |
|
383 if (ret != KErrNotSupported) |
|
384 return ret; |
|
385 } |
|
386 return iProtocol->Interfacer()->SetOption(aLevel, aName, aOption, *this); |
|
387 } |
|
388 |
|
389 TInt CProviderInet6Base::GetOption(TUint aLevel, TUint aName, TDes8& aOption) const |
|
390 { |
|
391 LOG(Log::Printf(_L("GetOpt\t%S SAP[%u] level=%x, name=%x, len=%d"), &iProtocol->ProtocolName(), (TInt)this, aLevel, aName, aOption.Length());) |
|
392 if (aLevel == KSolInetIp) |
|
393 switch (aName) |
|
394 { |
|
395 case KSoInetLastError: |
|
396 if (STATIC_CAST(TUint, aOption.MaxLength()) >= sizeof(iLastError)) |
|
397 { |
|
398 aOption.SetLength(sizeof(TSoInetLastErr)); |
|
399 aOption.Copy((TUint8*)&iLastError, sizeof(iLastError)); |
|
400 return KErrNone; |
|
401 } |
|
402 return KErrTooBig; |
|
403 |
|
404 case KSoHeaderIncluded: |
|
405 return SetOptionInt(aOption, iHeaderIncluded); |
|
406 case KSoRawMode: |
|
407 return SetOptionInt(aOption, iRawMode); |
|
408 case KSoUserSocket: |
|
409 return SetOptionInt(aOption, iIsUser != 0); |
|
410 |
|
411 default: |
|
412 break; |
|
413 } |
|
414 else if (aLevel == KSolInetIfCtrl && aName == STATIC_CAST(TUint, KSoInetNextInterface)) // See *NOTE* above! |
|
415 { |
|
416 TSoInetInterfaceInfo& opt = *(TSoInetInterfaceInfo*)aOption.Ptr(); |
|
417 if (STATIC_CAST(TUint, aOption.MaxLength()) < sizeof(TSoInetInterfaceInfo)) |
|
418 return KErrTooBig; |
|
419 (void) new (&opt) TSoInetInterfaceInfo; // Make sure descriptors are correct. |
|
420 aOption.SetLength(sizeof(TSoInetInterfaceInfo)); |
|
421 ((CProviderInet6Base *)this)->iInterfaceIndex = iProtocol->Interfacer()->InterfaceInfo(iInterfaceIndex, opt); |
|
422 if (iInterfaceIndex > 0) |
|
423 return KErrNone; |
|
424 else |
|
425 return KErrNotFound; |
|
426 } |
|
427 else if (aLevel == KSolInetRtCtrl && aName == STATIC_CAST(TUint, KSoInetNextRoute)) // See *NOTE* above! |
|
428 { |
|
429 TSoInetRouteInfo& opt = *(TSoInetRouteInfo*)aOption.Ptr(); |
|
430 if (STATIC_CAST(TUint, aOption.MaxLength()) < sizeof(TSoInetRouteInfo)) |
|
431 return KErrTooBig; |
|
432 aOption.SetLength(sizeof(TSoInetRouteInfo)); |
|
433 (void) new (&opt) TSoInetRouteInfo; // Make sure descriptors are correct. |
|
434 ((CProviderInet6Base *)this)->iRouteIndex = iProtocol->Interfacer()->RouteInfo(iRouteIndex, opt); |
|
435 if (iRouteIndex > 0) |
|
436 return KErrNone; |
|
437 else |
|
438 return KErrNotFound; |
|
439 } |
|
440 else if (aLevel == KNifOptLevel) |
|
441 { |
|
442 return KErrNotSupported; |
|
443 } |
|
444 // |
|
445 // if none of the above "supported", falls here... |
|
446 // |
|
447 CFlowContext *flow = iFlow.FlowContext(); |
|
448 if (flow) |
|
449 { |
|
450 const TInt ret = flow->GetOption(aLevel, aName, aOption); |
|
451 if (ret != KErrNotSupported) |
|
452 return ret; |
|
453 } |
|
454 return iProtocol->Interfacer()->GetOption(aLevel, aName, aOption, *((CProviderInet6Base *)this)); |
|
455 } |
|
456 |
|
457 void CProviderInet6Base::Ioctl(TUint aLevel, TUint aName, TDes8* /*anOption*/) |
|
458 { |
|
459 LOG(Log::Printf(_L("Ioctl\t%S SAP[%u] %x, %x)"), &ProtocolName(), (TInt)this, aLevel, aName)); |
|
460 if (aLevel == KSolInetIp && aName == KIoctlInetLastError) |
|
461 { |
|
462 TPckg<TSoInetLastErr> lastError(iLastError); |
|
463 iSocket->IoctlComplete(&lastError); |
|
464 } |
|
465 else |
|
466 Error(KErrNotSupported, MSocketNotify::EErrorIoctl); |
|
467 } |
|
468 |
|
469 void CProviderInet6Base::CancelIoctl(TUint aLevel, TUint aName) |
|
470 { |
|
471 #ifdef _LOG |
|
472 Log::Printf(_L("CancelIoctl\t%S SAP[%u] %x, %x)"), &ProtocolName(), (TInt)this, aLevel, aName); |
|
473 #else |
|
474 (void)aLevel; // silence compiler warning |
|
475 (void)aName; // silence compiler warning |
|
476 #endif |
|
477 // Error call removed. Fixes defect IP/76. -MikaL |
|
478 //Error(KErrNotSupported); |
|
479 } |
|
480 |
|
481 |
|
482 void CProviderInet6Base::Process(RMBufChain& /*aPacket*/, CProtocolBase* /*aSourceProtocol*/) |
|
483 { |
|
484 Panic(EInet6Panic_NotSupported); |
|
485 } |
|
486 |
|
487 // |
|
488 // Error report routine. |
|
489 // |
|
490 // Soft errors are not immediately reported to the socket server. |
|
491 // A soft error is indicated by a zero aOperationMask. |
|
492 // |
|
493 // The socket error can be cleared by calling this routing with |
|
494 // aError == KErrNone. |
|
495 // |
|
496 void CProviderInet6Base::Error(TInt aError, TUint aOperationMask) |
|
497 { |
|
498 if (aError <= KErrNone && !FatalState()) |
|
499 { |
|
500 iLastError.iStatus = aError; |
|
501 if (aError == KErrNone) |
|
502 iErrorMask = aOperationMask; |
|
503 else |
|
504 iErrorMask |= aOperationMask; |
|
505 if (iSocket && aOperationMask) |
|
506 { |
|
507 LOG(Log::Printf(_L("\t%S SAP[%u] Error %d, mask %b"), |
|
508 &ProtocolName(), (TInt)this, aError, aOperationMask)); |
|
509 iSocket->Error(aError, aOperationMask); |
|
510 } |
|
511 else |
|
512 { |
|
513 LOG(Log::Printf(_L("\t%S SAP[%u] Error %d, mask %b pending"), |
|
514 &ProtocolName(), (TInt)this, aError, aOperationMask)); |
|
515 } |
|
516 } |
|
517 else |
|
518 { |
|
519 LOG(Log::Printf(_L("\t%S SAP[%u] Error %d, mask %b ignored"), |
|
520 &ProtocolName(), (TInt) this, aError, aOperationMask)); |
|
521 } |
|
522 } |
|
523 |
|
524 void CProviderInet6Base::SaveIcmpError(TInt aType, TInt aCode, const TInetAddr& aSrcAddr, |
|
525 const TInetAddr& aDstAddr, const TInetAddr& aErrAddr) |
|
526 { |
|
527 iLastError.iErrType = aType; |
|
528 iLastError.iErrCode = aCode; |
|
529 iLastError.iSrcAddr = aSrcAddr; |
|
530 iLastError.iDstAddr = aDstAddr; |
|
531 iLastError.iErrAddr = aErrAddr; |
|
532 } |
|
533 |
|
534 void CProviderInet6Base::CanSend() |
|
535 { |
|
536 if(iSocket && /*iFlow.Status() == EFlow_READY && */!FatalState()) |
|
537 { |
|
538 LOG(Log::Printf(_L("\t%S SAP[%u] CanSend() Flow UNBLOCKED"), &ProtocolName(), (TInt)this)); |
|
539 iSocket->CanSend(); |
|
540 } |
|
541 } |
|
542 |
|
543 void CProviderInet6Base::NoBearer(const TDesC8& aConnectionParams) |
|
544 { |
|
545 if(iSocket) |
|
546 { |
|
547 LOG(Log::Printf(_L("\t%S SAP[%u] NoBearer()"), &ProtocolName(), (TInt)this)); |
|
548 iSocket->NoBearer(aConnectionParams); |
|
549 } |
|
550 } |
|
551 |
|
552 void CProviderInet6Base::Bearer(const TDesC8 &aConnectionInfo) |
|
553 { |
|
554 if(iSocket) |
|
555 { |
|
556 LOG(Log::Printf(_L("\t%S SAP[%u] Bearer()"), &ProtocolName(), (TInt)this)); |
|
557 iSocket->Bearer(aConnectionInfo); |
|
558 } |
|
559 } |
|
560 |
|
561 TInt CProviderInet6Base::CheckPolicy(const TSecurityPolicy& aPolicy, const char *aDiagnostic) |
|
562 { |
|
563 return iSecurityChecker ? iSecurityChecker->CheckPolicy(aPolicy, aDiagnostic) : KErrDisconnected; |
|
564 } |
|
565 |
|
566 TInt CProviderInet6Base::SecurityCheck(MProvdSecurityChecker *aSecurityChecker) |
|
567 { |
|
568 iSecurityChecker = aSecurityChecker; |
|
569 iHasNetworkServices = CheckPolicy(KPolicyNetworkServices, 0) == KErrNone; |
|
570 return KErrNone; |
|
571 } |
|
572 |
|
573 TInt CProviderInet6Base::GetOptionInt(const TDesC8 &anOption, TInt &aVal) |
|
574 { |
|
575 if (STATIC_CAST(TUint, anOption.Length()) < sizeof(aVal)) |
|
576 return KErrTooBig; |
|
577 Mem::Copy(&aVal, anOption.Ptr(), sizeof(aVal)); |
|
578 return KErrNone; |
|
579 } |
|
580 |
|
581 TInt CProviderInet6Base::SetOptionInt(TDes8 &anOption, TInt aVal) |
|
582 { |
|
583 if (STATIC_CAST(TUint, anOption.MaxLength()) < sizeof(aVal)) |
|
584 return KErrTooBig; |
|
585 anOption.SetLength(sizeof(aVal)); |
|
586 anOption.Copy((TUint8*)&aVal, sizeof(aVal)); |
|
587 return KErrNone; |
|
588 } |
|
589 |
|
590 TInt CProviderInet6Base::Write(RMBufChain& aData, TUint aOptions, TSockAddr* aToAddr) |
|
591 { |
|
592 RMBufSendPacket packet; |
|
593 packet.Assign(aData); // *beware!* It is legal for aData to be EMPTY! |
|
594 #ifdef _LOG |
|
595 TBuf<70> tmp(_L("NULL")); |
|
596 #endif |
|
597 |
|
598 TInt offset = 0; |
|
599 RMBufSendInfo* info = NULL; |
|
600 TInt err(0); |
|
601 // Allocate the info block for the packet. |
|
602 info = packet.NewInfo(); |
|
603 // Because many RMBufChain methods do not handle the empty |
|
604 // chain "logically", must make sure the chain has at least |
|
605 // one RMBuf in it (without no content). Allocate one and |
|
606 // make its content empty. |
|
607 if (info) |
|
608 { |
|
609 if (packet.IsEmpty()) |
|
610 { |
|
611 err = packet.Alloc(0); // <-- *WARNING* Assumed to allocate single RMBuf |
|
612 if (err == KErrNone) |
|
613 { |
|
614 packet.First()->AdjustStart(packet.Length()); |
|
615 info->iLength = 0; |
|
616 } |
|
617 } |
|
618 else |
|
619 info->iLength = packet.Length(); |
|
620 } |
|
621 else |
|
622 err = KErrNoMBufs; // The info allocation was not successful |
|
623 |
|
624 |
|
625 if(err < 0) |
|
626 { |
|
627 // Treat all leaves in above as no MBufs. |
|
628 LOG(Log::Printf(_L("Write\t%S SAP[%u] No Mbufs (%d)"), &ProtocolName(), (TInt)this, err)); |
|
629 err = KErrNoMBufs; |
|
630 goto notify_error; |
|
631 } |
|
632 |
|
633 #ifdef _LOG |
|
634 if (aToAddr) |
|
635 TInetAddr::Cast(*aToAddr).OutputWithScope(tmp); |
|
636 Log::Printf(_L("Write\t%S SAP[%u] len=%d, opt=%x, to=%S"), &ProtocolName(), (TInt)this, info->iLength, aOptions, &tmp); |
|
637 #endif |
|
638 |
|
639 // |
|
640 // Initialize the info |
|
641 // |
|
642 TInetAddr::Cast(info->iSrcAddr).Init(0); |
|
643 info->iSrcAddr.SetPort(0); |
|
644 TInetAddr::Cast(info->iDstAddr).Init(0); |
|
645 info->iDstAddr.SetPort(0); |
|
646 // |
|
647 // Get the protocol number to use. |
|
648 // iProtocolId must be NON-ZERO for anything else, except |
|
649 // for IP/IP6 raw sockets. Only those sockets have specified |
|
650 // that the protocol number can be given in port field! |
|
651 info->iProtocol = iProtocolId != 0 ? iProtocolId : |
|
652 aToAddr != NULL ? aToAddr->Port() : 0; |
|
653 info->iFlags = aOptions & (KIpHeaderIncluded | KIpDontFragment); |
|
654 if (iHeaderIncluded) |
|
655 info->iFlags |= KIpHeaderIncluded; |
|
656 (void)new (&info->iFlow) RFlowContext(); |
|
657 |
|
658 // |
|
659 // Prepare iDstAddr from aToAddr, if specified |
|
660 // |
|
661 if (aToAddr) |
|
662 { |
|
663 info->iDstAddr = *aToAddr; // Copy as is, including port, flow label and scope. |
|
664 if (info->iDstAddr.Family() != KAfInet6) |
|
665 TInetAddr::Cast(info->iDstAddr).ConvertToV4Mapped(); |
|
666 } |
|
667 // |
|
668 // Prepare from included header, if present |
|
669 // |
|
670 err = KErrNotSupported; |
|
671 if (info->iFlags & KIpHeaderIncluded) |
|
672 { |
|
673 // The packet starts with an IPv4 or IPv6 header. |
|
674 TInt next_header = info->iProtocol; |
|
675 TIpHeader *const ip = ((RMBufPacketPeek &)packet).GetIpHeader(); |
|
676 if (!ip) |
|
677 { |
|
678 LOG(Log::Printf(_L("\t%S SAP[%u] HeaderIncluded, short/bad IP header"), &ProtocolName(), (TInt)this)); |
|
679 goto notify_error; |
|
680 } |
|
681 switch (ip->ip4.Version()) |
|
682 { |
|
683 case 4: |
|
684 offset = ip->ip4.HeaderLength(); |
|
685 // If protocol is ZERO in header, default to aProtocol. This is |
|
686 // a backward compatibility issue. Applications should not rely |
|
687 // on this. If they are providing the IPv4 header, they SHOULD |
|
688 // ALSO fill the proper protocol number in there. |
|
689 if (!ip->ip4.Protocol()) |
|
690 ip->ip4.SetProtocol(next_header); |
|
691 else |
|
692 next_header = ip->ip4.Protocol(); |
|
693 TInetAddr::Cast(info->iSrcAddr).SetV4MappedAddress(ip->ip4.SrcAddr()); |
|
694 if (aToAddr) |
|
695 ip->ip4.SetDstAddr(TInetAddr::Cast(info->iDstAddr).Address()); |
|
696 else |
|
697 TInetAddr::Cast(info->iDstAddr).SetV4MappedAddress(ip->ip4.DstAddr()); |
|
698 info->iProtocol = KProtocolInetIp; |
|
699 break; |
|
700 case 6: |
|
701 offset = ip->ip6.HeaderLength(); |
|
702 // Note: ZERO NextHeader() does not cause default processing. In |
|
703 // IPv6 ZERO is the Hop-by-Hop extension header and potentially |
|
704 // provided by the application. |
|
705 next_header = ip->ip6.NextHeader(); |
|
706 TInetAddr::Cast(info->iSrcAddr).SetAddress(ip->ip6.SrcAddr()); |
|
707 if (aToAddr) |
|
708 ip->ip6.SetDstAddr(TInetAddr::Cast(info->iDstAddr).Ip6Address()); |
|
709 else |
|
710 TInetAddr::Cast(info->iDstAddr).SetAddress(ip->ip6.DstAddr()); |
|
711 info->iProtocol = KProtocolInet6Ip; |
|
712 break; |
|
713 default: |
|
714 LOG(Log::Printf(_L("\t%S SAP[%u] HeaderIncluded, bad IP version (= %d)"), &ProtocolName(), (TInt)this, (TInt)ip->ip4.Version())); |
|
715 goto notify_error; |
|
716 } |
|
717 // |
|
718 // Need to locate the upper layer header |
|
719 // |
|
720 while (info->iProtocol != next_header) |
|
721 { |
|
722 TInet6Packet<TInet6HeaderExtension> hdr(packet, offset); |
|
723 if (hdr.iHdr == NULL || !TPacketPoker::IsExtensionHeader(next_header)) |
|
724 { |
|
725 LOG(Log::Printf(_L("\t%S SAP[%u] HeaderIncluded, unknown extension hdr (= %d)"), &ProtocolName(), (TInt)this, next_header)); |
|
726 goto notify_error; |
|
727 } |
|
728 offset += hdr.iHdr->HeaderLength(); |
|
729 next_header = hdr.iHdr->NextHeader(); |
|
730 } |
|
731 } |
|
732 |
|
733 iFlow.SetProtocol(info->iProtocol); |
|
734 err = DoWrite(packet, *info, aOptions, offset); |
|
735 if (err == KErrNone) |
|
736 { |
|
737 // If packet is Empty, assume DoWrite handled it, and |
|
738 // don't send it to the protocol. |
|
739 if (!packet.IsEmpty()) |
|
740 { |
|
741 packet.Pack(); |
|
742 iProtocol->Send(packet); |
|
743 } |
|
744 goto packet_done; |
|
745 } |
|
746 // DoWrite indicated problem: |
|
747 // err > 0, flow cannot receive packet |
|
748 // err < 0, some error condition |
|
749 // |
|
750 notify_error: |
|
751 if (err >= 0) |
|
752 err = 0; // Return 0 to indicate that packet has not been accepted |
|
753 else if (err != KErrNoMBufs) |
|
754 { |
|
755 // |
|
756 // Cannot send the packet, report error and drop packet. |
|
757 // |
|
758 Error(err, MSocketNotify::EErrorSend); |
|
759 goto packet_done; |
|
760 } |
|
761 else |
|
762 { |
|
763 if (iSynchSend == 0) |
|
764 { |
|
765 // Out of buffer space (KErrNoMBufs). If iSynchSend is not set, just |
|
766 // drop the packet silently, |
|
767 LOG(Log::Printf(_L("\t%S SAP[%u] Dropping packet for KErrNoMBufs"), &ProtocolName(), (TInt)this)); |
|
768 goto packet_done; |
|
769 } |
|
770 LOG(Log::Printf(_L("\t%S SAP[%u] Blocking for KErrNoMBufs"), &ProtocolName(), (TInt)this)); |
|
771 } |
|
772 |
|
773 // note: err == 0 or KErrNoMBufs! |
|
774 aData.Assign(packet); // Try to return original chain (approximately correct only |
|
775 // if DoWrite does not add anything to the chain!) |
|
776 packet.Free(); // Need to release info! |
|
777 return err; |
|
778 packet_done: |
|
779 // Packet has been sent or dropped |
|
780 packet.Free(); // Cleanup, not always needed (does nothing then). |
|
781 return 1; // Return 1 to indicate that packet has been accepted |
|
782 } |
|
783 |
|
784 TUint CProviderInet6Base::Write(const TDesC8& aDesc, TUint aOptions, TSockAddr* aAddr) |
|
785 { |
|
786 LOG(Log::Printf(_L("Write\t%S SAP[%u] Desclen=%d, opt=%x)"), &ProtocolName(), (TInt)this, aDesc.Length(), aOptions)); |
|
787 RMBufChain data; |
|
788 if (aDesc.Length() > 0) |
|
789 { |
|
790 TRAPD(err, data.CreateL(aDesc)); |
|
791 if (err != KErrNone) |
|
792 { |
|
793 data.Free(); // just to be sure.. |
|
794 return 1; |
|
795 } |
|
796 } |
|
797 const TInt ret = Write(data, aOptions, aAddr) != 0; // Return 0 or 1 only. |
|
798 data.Free(); |
|
799 return ret; |
|
800 } |