|
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 // This file implements the CIPv4ProtocolIf class, which handles the transmission |
|
15 // of IPv4 data to and from the TCP/IP stack. |
|
16 // |
|
17 // |
|
18 |
|
19 /** |
|
20 @file |
|
21 */ |
|
22 |
|
23 #include <etelpckt.h> |
|
24 #include <in_iface.h> |
|
25 #include "RawIPNifMain.h" |
|
26 #include "IPv4ProtocolIf.h" |
|
27 #ifdef WCDMA_STUB |
|
28 #include <UMTSNifControlIf.h> |
|
29 #endif |
|
30 #define LOG_IP_ADDRESS(desc,addr) _LOG_L2C5(_L8(" " desc " = %d.%d.%d.%d from context"), \ |
|
31 addr >> 24, (addr >> 16) & 0xFF, (addr >> 8) & 0xFF, addr & 0xFF); |
|
32 |
|
33 CIPv4ProtocolIf::CIPv4ProtocolIf(CRawIPNifMain& aNifMain, CBttLogger* aTheLogger) |
|
34 /** |
|
35 * Constructor |
|
36 */ |
|
37 : CProtocolIfBase(aNifMain,aTheLogger), |
|
38 iTheLogger(aTheLogger), |
|
39 iSpeedMetric(KDefaultSpeedMetric) |
|
40 { |
|
41 } |
|
42 |
|
43 CIPv4ProtocolIf::~CIPv4ProtocolIf() |
|
44 /** |
|
45 * Destructor |
|
46 */ |
|
47 { |
|
48 } |
|
49 |
|
50 void CIPv4ProtocolIf::BindL(TAny* aId) |
|
51 /** |
|
52 * Binds protocol to the Nif |
|
53 * |
|
54 * @param aId A point the the protocol(TCP/IP) |
|
55 */ |
|
56 { |
|
57 _LOG_L1C2(_L8("CIPv4ProtocolIf::BindL [aId=%X]"), aId); |
|
58 |
|
59 CProtocolIfBase::BindL(aId); // Call the superclass's method. |
|
60 iNotify = iNifMain.Notify(); |
|
61 } |
|
62 |
|
63 TInt CIPv4ProtocolIf::Control(TUint aLevel, TUint aName, TDes8& aOption, |
|
64 TAny* /*aSource*/) |
|
65 /** |
|
66 * The main function called by the TCP/IP protocol to control the interface. |
|
67 * Can perform a variety of general IP tasks (such as getting IP config) |
|
68 * and "3G" specific tasks (such as deleting the context). |
|
69 * |
|
70 * @param aLevel The level of the interface to control - always KSOLInterface |
|
71 * @param aName The command to perform |
|
72 * @param aOption Data to be input/output as a result of the command |
|
73 * @param aSource The source of the command (unused) |
|
74 * @return Standard error codes |
|
75 */ |
|
76 { |
|
77 _LOG_L1C3(_L8("CIPv4ProtocolIf::Control [aLevel=%d, aName=%d]"), |
|
78 aLevel, aName); |
|
79 |
|
80 if (aLevel == KSOLInterface) |
|
81 { |
|
82 switch (aName) |
|
83 { |
|
84 // General IP configuration commands are below this point. |
|
85 |
|
86 case KSoIfInfo: |
|
87 // Gets information about the interface, such as name and MTU. |
|
88 return WriteIfInfo(aOption); |
|
89 |
|
90 case KSoIfConfig: |
|
91 // Gets interface configuration, eg. IP address and DNS servers. |
|
92 return WriteIfConfig(aOption); |
|
93 |
|
94 case KSoIfGetConnectionInfo: |
|
95 // Gets IAP and network information. |
|
96 return WriteConnectionInfo(aOption); |
|
97 |
|
98 case KSoIfHardwareAddr: |
|
99 // unsupported because we don't have a h/w address |
|
100 case KSoIfCompareAddr: |
|
101 // this never actually appears to be called |
|
102 break; |
|
103 |
|
104 // 3G-specific configuration commands are below this point. |
|
105 #ifdef WCDMA_STUB |
|
106 case KRegisterEventHandler: |
|
107 // Raw IP NIF Events are not supported |
|
108 case KContextSetEvents: |
|
109 // Raw IP NIF Events are not supported |
|
110 break; |
|
111 |
|
112 case KContextCreate: |
|
113 // We don't support creating new secondary contexts. |
|
114 break; |
|
115 |
|
116 case KContextDelete: |
|
117 // Deletes the primary PDP context. This will shut down the Nif. |
|
118 return DeleteContext(aOption); |
|
119 |
|
120 case KContextActivate: |
|
121 // If the IPv4 interface is up, then the context will already have |
|
122 // been activated. So this command should fail with |
|
123 // KErrAlreadyExists |
|
124 { |
|
125 TUint8* ptr = CONST_CAST(TUint8*, aOption.Ptr()); |
|
126 TContextParameters* contextParams = |
|
127 REINTERPRET_CAST(TContextParameters*, ptr); |
|
128 |
|
129 if (contextParams->iContextInfo.iContextId != |
|
130 STATIC_CAST(TInt8, GetNifMain().GetBcaController()->Nsapi())) |
|
131 { |
|
132 contextParams->iReasonCode = KErrNotFound; |
|
133 } |
|
134 else |
|
135 { |
|
136 contextParams->iContextInfo.iStatus = |
|
137 GetNifMain().GetContextStatus(); |
|
138 contextParams->iReasonCode = KErrAlreadyExists; |
|
139 } |
|
140 return KErrNone; |
|
141 } |
|
142 |
|
143 case KNifSetDefaultQoS: |
|
144 case KContextQoSSet: |
|
145 // Setting the QoS is meaningless over GPRS, so we just return that |
|
146 // we don't support these operations. |
|
147 break; |
|
148 |
|
149 case KContextTFTModify: |
|
150 // As we only have one primary context, we don't support anything |
|
151 // to do with traffic flow templates, which are used by secondary |
|
152 // contexts. |
|
153 break; |
|
154 |
|
155 case KContextModifyActive: |
|
156 // This command is only valid aftermodifying TFT/QoS parameters. |
|
157 // As we don't support any of these operations, |
|
158 // this command is never valid. |
|
159 break; |
|
160 #endif |
|
161 default: |
|
162 break; |
|
163 } |
|
164 } |
|
165 return KErrNotSupported; |
|
166 } |
|
167 |
|
168 TInt CIPv4ProtocolIf::WriteIfConfig(TDes8& aIfConfig) |
|
169 /** |
|
170 * Writes the configuration of the interface (eg. IP address, DNS servers) |
|
171 * into the supplied descriptor. |
|
172 * |
|
173 * @param aIfConfig Will contain the interface configuration |
|
174 * @return KErrNotSupported if an incorrect structure is passed, |
|
175 * otherwise KErrNone |
|
176 */ |
|
177 { |
|
178 _LOG_L1C1(_L8("CIPv4ProtocolIf::WriteIfConfig")); |
|
179 |
|
180 if (aIfConfig.Length() != sizeof(TSoInetIfConfig)) |
|
181 { |
|
182 return KErrArgument; |
|
183 } |
|
184 |
|
185 TUint8* ptr = CONST_CAST(TUint8*, aIfConfig.Ptr()); |
|
186 TSoInetIfConfig* config = REINTERPRET_CAST(TSoInetIfConfig*, ptr); |
|
187 |
|
188 if (config->iFamily != KAfInet) |
|
189 { |
|
190 return KErrNotSupported; |
|
191 } |
|
192 |
|
193 TInetAddr::Cast(config->iConfig.iAddress).SetAddress(iSettings.iLocalAddr); |
|
194 TInetAddr::Cast(config->iConfig.iNetMask).SetAddress(iSettings.iNetMask); |
|
195 TInetAddr::Cast(config->iConfig.iBrdAddr). |
|
196 SetAddress(iSettings.iBroadcastAddr); |
|
197 TInetAddr::Cast(config->iConfig.iDefGate).SetAddress(iSettings.iDefGateway); |
|
198 TInetAddr::Cast(config->iConfig.iNameSer1). |
|
199 SetAddress(iSettings.iPrimaryDns); |
|
200 TInetAddr::Cast(config->iConfig.iNameSer2). |
|
201 SetAddress(iSettings.iSecondaryDns); |
|
202 |
|
203 return KErrNone; |
|
204 } |
|
205 |
|
206 TInt CIPv4ProtocolIf::WriteIfInfo(TDes8& aIfInfo) |
|
207 /** |
|
208 * Writes information about the interface into the supplied descriptor. |
|
209 * |
|
210 * @param aIfInfo Will contain the interface information |
|
211 * @return KErrArgument if an incorrect structure is passed, otherwise KErrNone |
|
212 */ |
|
213 { |
|
214 _LOG_L1C1(_L8("CIPv4ProtocolIf::WriteIfInfo")); |
|
215 |
|
216 if (aIfInfo.Length() != sizeof(TSoIfInfo)) |
|
217 { |
|
218 return KErrArgument; |
|
219 } |
|
220 |
|
221 TSoIfInfo* info = (TSoIfInfo*) aIfInfo.Ptr(); |
|
222 info->iFeatures = KIfCanBroadcast | KIfCanMulticast; |
|
223 info->iSpeedMetric = iSpeedMetric; |
|
224 info->iMtu = KDefaultMtu; |
|
225 WriteIfName(info->iName); |
|
226 |
|
227 return KErrNone; |
|
228 } |
|
229 |
|
230 TInt CIPv4ProtocolIf::WriteConnectionInfo(TDes8& aConnectionInfo) |
|
231 /** |
|
232 * Writes information about the IAP and network we're associated with. This |
|
233 * is used to route data in a multi-homing environment. |
|
234 * |
|
235 * @param aConnectionInfo Will contain the connection information |
|
236 * @return Standard CommDB error codes |
|
237 */ |
|
238 { |
|
239 _LOG_L1C1(_L8("CIPv4ProtocolIf::WriteConnectionInfo")); |
|
240 |
|
241 TSoIfConnectionInfo* connectionInfo = |
|
242 (TSoIfConnectionInfo*) aConnectionInfo.Ptr(); |
|
243 |
|
244 TInt err; |
|
245 // Append the 2 commdb filed into this descriptor |
|
246 TBuf<2*KCommsDbSvrMaxColumnNameLength+1> fieldName; |
|
247 |
|
248 fieldName.Copy(TPtrC(IAP)); |
|
249 fieldName.Append(KSlashChar); |
|
250 fieldName.Append(TPtrC(COMMDB_ID)); |
|
251 err = GetNifMain().GetAgent()->ReadInt(fieldName, connectionInfo->iIAPId); |
|
252 if (err != KErrNone) |
|
253 { |
|
254 return err; |
|
255 } |
|
256 |
|
257 fieldName.Copy(TPtrC(IAP)); |
|
258 fieldName.Append(KSlashChar); |
|
259 fieldName.Append(TPtrC(IAP_NETWORK)); |
|
260 err = GetNifMain().GetAgent()->ReadInt(fieldName, connectionInfo->iNetworkId); |
|
261 if (err != KErrNone) |
|
262 { |
|
263 return err; |
|
264 } |
|
265 |
|
266 return KErrNone; |
|
267 } |
|
268 #ifdef WCDMA_STUB |
|
269 |
|
270 TInt CIPv4ProtocolIf::DeleteContext(TDes8& aContextParameters) |
|
271 /** |
|
272 * Deletes a context. As the NIF is responsible for one primary context, |
|
273 * this is equivalent to closing down the NIF. |
|
274 * |
|
275 * @param aContextParameters Parameters of the context to delete |
|
276 * @return KErrArgument if an incorrect structure is passed, otherwise KErrNone |
|
277 */ |
|
278 { |
|
279 _LOG_L1C1(_L8("CIPv4ProtocolIf::DeleteContext")); |
|
280 |
|
281 if (aContextParameters.Length() != sizeof(TContextParameters)) |
|
282 { |
|
283 return KErrArgument; |
|
284 } |
|
285 |
|
286 TUint8* ptr = CONST_CAST(TUint8*, aContextParameters.Ptr()); |
|
287 TContextParameters* params = REINTERPRET_CAST(TContextParameters*, ptr); |
|
288 |
|
289 if (params->iContextInfo.iContextId != |
|
290 STATIC_CAST(TInt8, GetNifMain().GetBcaController()->Nsapi())) |
|
291 { |
|
292 params->iReasonCode = KErrBadName; |
|
293 } |
|
294 else |
|
295 { |
|
296 params->iReasonCode = KErrNone; |
|
297 GetNifMain().Stop(KErrNone, MNifIfNotify::EDisconnect); |
|
298 } |
|
299 |
|
300 return KErrNone; |
|
301 } |
|
302 |
|
303 #endif |
|
304 |
|
305 void CIPv4ProtocolIf::ReadCommDbGprsSettingsL() |
|
306 /** |
|
307 * Reads GPRS IP settings from CommDB via the agent. |
|
308 */ |
|
309 { |
|
310 _LOG_L1C1(_L8("CIPv4ProtocolIf::ReadCommDbGprsSettings")); |
|
311 |
|
312 // Read the IP address settings from CommDB. |
|
313 ReadIPv4SettingL(TPtrC(GPRS_IP_ADDR), iSettings.iLocalAddr); |
|
314 ReadIPv4SettingL(TPtrC(GPRS_IP_NETMASK), iSettings.iNetMask); |
|
315 ReadIPv4SettingL(TPtrC(GPRS_IP_NAME_SERVER1), iSettings.iPrimaryDns); |
|
316 ReadIPv4SettingL(TPtrC(GPRS_IP_NAME_SERVER2), iSettings.iSecondaryDns); |
|
317 ReadIPv4SettingL(TPtrC(GPRS_IP_GATEWAY), iSettings.iDefGateway); |
|
318 |
|
319 // Read whether to get the gateway IP address from the server. |
|
320 _BTT_LEAVEIFERROR(GetNifMain().GetAgent()->ReadBool( |
|
321 TPtrC(GPRS_IP_ADDR_FROM_SERVER), |
|
322 iSettings.iGetGatewayFromServer)); |
|
323 |
|
324 // Read whether to get the DNS addresses from the server. |
|
325 _BTT_LEAVEIFERROR(GetNifMain().GetAgent()->ReadBool( |
|
326 TPtrC(GPRS_IP_DNS_ADDR_FROM_SERVER), |
|
327 iSettings.iGetDnsFromServer)); |
|
328 |
|
329 // Because CommDB doesn't define a Broadcast Address field, we must |
|
330 // calculate the broadcast address. This is based on the localAddr |
|
331 // and the netMask. |
|
332 TInetAddr localAddr(iSettings.iLocalAddr, 0); |
|
333 TInetAddr netMask(iSettings.iNetMask, 0); |
|
334 TInetAddr broadcast; |
|
335 broadcast.SubNetBroadcast(localAddr, netMask); |
|
336 iSettings.iBroadcastAddr = broadcast.Address(); |
|
337 } |
|
338 |
|
339 void CIPv4ProtocolIf::UpdateContextConfigL(const |
|
340 RPacketContext::TContextConfigGPRS& |
|
341 aConfig) |
|
342 /** |
|
343 * Called when the context has been activated to set our IP address and get |
|
344 * any other required settings from CommDB. |
|
345 * |
|
346 * @param aConfig The new context config |
|
347 */ |
|
348 { |
|
349 _LOG_L1C1(_L8("CIPv4ProtocolIf::UpdateContextConfig")); |
|
350 |
|
351 // Get the settings which are stored in CommDB. |
|
352 ReadCommDbGprsSettingsL(); |
|
353 |
|
354 // Get our IP address from the GPRS context config. |
|
355 TInetAddr address; |
|
356 |
|
357 TBuf<RPacketContext::KMaxPDPAddressLength> tempAddr; |
|
358 tempAddr.Copy(aConfig.iPdpAddress); |
|
359 TInt ret = address.Input(tempAddr); |
|
360 |
|
361 // We've got our IP address! Let's save it. |
|
362 if (ret == KErrNone) |
|
363 { |
|
364 iSettings.iLocalAddr = address.Address(); |
|
365 LOG_IP_ADDRESS("Got local IP address", iSettings.iLocalAddr); |
|
366 } |
|
367 else |
|
368 { |
|
369 _LOG_L2C2(_L8("Couldn't get IP address from GPRS config (err: %d)"), |
|
370 ret); |
|
371 |
|
372 // Don't leave on this error: we may still be OK if we read some |
|
373 // settings from CommDB. |
|
374 } |
|
375 |
|
376 // @todo - is this correct. We can only get the DNS addresses |
|
377 // from the TSY using the iProtocolConfigOption data. Yet a client could |
|
378 // access those DNS config details without knowing about the state of the |
|
379 // iSettings.iGetDnsFromServer flag. |
|
380 |
|
381 if ((iSettings.iGetDnsFromServer) || |
|
382 ((iSettings.iPrimaryDns == 0) && |
|
383 (iSettings.iSecondaryDns == 0)) ) |
|
384 { |
|
385 TBuf<RPacketContext::KMaxPDPAddressLength> tempAddr; |
|
386 tempAddr.Copy(aConfig.iProtocolConfigOption.iDnsAddresses.iPrimaryDns); |
|
387 ret = address.Input(tempAddr); |
|
388 |
|
389 if (ret == KErrNone) |
|
390 { |
|
391 iSettings.iPrimaryDns = address.Address(); |
|
392 LOG_IP_ADDRESS("Got primary DNS", iSettings.iPrimaryDns); |
|
393 } |
|
394 else |
|
395 { |
|
396 _LOG_L2C2(_L8("Couldn't get primary DNS address from GPRS config (err: %d)"), |
|
397 ret); |
|
398 |
|
399 // Don't leave on this error: we may still be OK if we read some |
|
400 // settings from CommDB. |
|
401 } |
|
402 |
|
403 tempAddr.Copy(aConfig.iProtocolConfigOption.iDnsAddresses.iSecondaryDns); |
|
404 ret = address.Input(tempAddr); |
|
405 |
|
406 if (ret == KErrNone) |
|
407 { |
|
408 iSettings.iSecondaryDns = address.Address(); |
|
409 LOG_IP_ADDRESS("Got secondary DNS", iSettings.iPrimaryDns); |
|
410 } |
|
411 else |
|
412 { |
|
413 _LOG_L2C2(_L8("Couldn't get secondary DNS address from GPRS config (err: %d)"), |
|
414 ret); |
|
415 |
|
416 // Don't leave on this error: we may still be OK if we read some |
|
417 // settings from CommDB. |
|
418 } |
|
419 } |
|
420 else |
|
421 { |
|
422 LOG_IP_ADDRESS("Using CommDB DNS address - Primary ", iSettings.iPrimaryDns); |
|
423 LOG_IP_ADDRESS(" - Secondary ", iSettings.iSecondaryDns); |
|
424 } |
|
425 |
|
426 |
|
427 // TProtocolConfigOptionV2::iMiscBuffer is not the correct way to pass a gateway |
|
428 // address - data needs to be passed in TLV format but there are no TLV content tags |
|
429 // defined for a gateway address and any UMTS/GPRS hardware which claims to be able |
|
430 // to supply this address is erroneous (3gpp standard 24.008, section 10.5.6.3). |
|
431 // This misuse of iMiscBuffer was preventing other correctly formed parameters from |
|
432 // being passed (INC113612). |
|
433 /* if (iSettings.iGetGatewayFromServer) |
|
434 { |
|
435 tempAddr.Copy(aConfig.iProtocolConfigOption.iMiscBuffer); |
|
436 ret = address.Input(tempAddr); |
|
437 |
|
438 if (ret == KErrNone) |
|
439 { |
|
440 iSettings.iDefGateway = address.Address(); |
|
441 LOG_IP_ADDRESS("Got default gateway", iSettings.iDefGateway); |
|
442 } |
|
443 else |
|
444 { |
|
445 _LOG_L2C2(_L8("Couldn't get default gateway from GPRS config (err: %d)"), |
|
446 ret); |
|
447 } |
|
448 }*/ |
|
449 } |
|
450 |
|
451 void CIPv4ProtocolIf::UpdateConnectionSpeed(TUint aConnectionSpeed) |
|
452 /** |
|
453 * Sets the speed metric to return to TCP/IP, based on what the TSY tells us. |
|
454 * |
|
455 * @param aConnectionSpeed Our connection speed |
|
456 */ |
|
457 { |
|
458 _LOG_L1C1(_L8("CIPv4ProtocolIf::UpdateConnectionSpeed")); |
|
459 |
|
460 iSpeedMetric = aConnectionSpeed; |
|
461 } |
|
462 |
|
463 void CIPv4ProtocolIf::ReadIPv4SettingL(const TDesC& aFieldName, |
|
464 TUint32& aIpAddr) |
|
465 /** |
|
466 * Reads an IPv4 address from CommDB, via the TRP agent. It leaves if an error |
|
467 * other than KErrNotFound occurs. |
|
468 * |
|
469 * @param aFieldName The name of the field to read |
|
470 * @param aIpAddr Will contain the IP address |
|
471 */ |
|
472 { |
|
473 #ifdef __BTT_LOGGING__ |
|
474 TBuf8<256> debugBuffer; |
|
475 debugBuffer.Copy(aFieldName); |
|
476 _LOG_L1C2(_L8("CIPv4ProtocolIf::ReadIp4Setting [aFieldName=%S]"), |
|
477 &debugBuffer); |
|
478 #endif |
|
479 |
|
480 TBuf<KCommsDbSvrMaxFieldLength> name; |
|
481 TInetAddr ip4Addr; |
|
482 |
|
483 TInt ret = GetNifMain().GetAgent()->ReadDes(aFieldName, name); |
|
484 |
|
485 if (ret == KErrNone) |
|
486 { |
|
487 // We've successfully read an IP address, so convert it into a number. |
|
488 ip4Addr.Input(name); |
|
489 aIpAddr = ip4Addr.Address(); |
|
490 } |
|
491 else |
|
492 { |
|
493 // We couldn't get the IP address, so set it to 0.0.0.0. Note that we |
|
494 // only leave here if we got a more serious error than "not found". |
|
495 aIpAddr = 0; |
|
496 if (ret != KErrNotFound) |
|
497 { |
|
498 _BTT_LEAVEIFERROR(ret); |
|
499 } |
|
500 } |
|
501 } |
|
502 |
|
503 TInt CIPv4ProtocolIf::Send(RMBufChain& aPdu, TAny* aSource) |
|
504 /** |
|
505 * Called by the protocol to send an outgoing IP packet to the network. |
|
506 * |
|
507 * @param aPdu The outgoing packet |
|
508 * @param aSource The source of the packet |
|
509 * @return Standard error codes |
|
510 */ |
|
511 { |
|
512 _LOG_L1C1(_L8("CIPv4ProtocolIf::Send")); |
|
513 |
|
514 #ifdef __BTT_LOGGING__ |
|
515 LogPacket(aPdu); |
|
516 #endif |
|
517 |
|
518 // Return <0: an error occurred |
|
519 // Return 0: no error, but don't send any more packets |
|
520 |
|
521 return GetNifMain().SendPacket(aPdu, aSource, KIp4FrameType); |
|
522 } |
|
523 |
|
524 void CIPv4ProtocolIf::Info(TNifIfInfo& aInfo) const |
|
525 /** |
|
526 * Called by the protocol to get information about the NIF. |
|
527 * |
|
528 * @param aInfo Will contain NIF information |
|
529 */ |
|
530 { |
|
531 _LOG_L1C1(_L8("CIPv4ProtocolIf::Info")); |
|
532 |
|
533 // The parent class sets everything except the name... |
|
534 CProtocolIfBase::Info(aInfo); |
|
535 // ...which we set here. |
|
536 WriteIfName(aInfo.iName); |
|
537 } |
|
538 |
|
539 TInt CIPv4ProtocolIf::Notification(TAgentToNifEventType /*aEvent*/, |
|
540 void* /*aInfo*/) |
|
541 /** |
|
542 * The Nif will ignore any notification sent |
|
543 * |
|
544 * @param aEvent Not used |
|
545 * @param aInfo Not used |
|
546 */ |
|
547 { |
|
548 _LOG_L1C1(_L8("CIPv4ProtocolIf::Notification")); |
|
549 |
|
550 return KErrNone; |
|
551 } |
|
552 |
|
553 void CIPv4ProtocolIf::StartSending(CProtocolBase* aProtocol) |
|
554 /** |
|
555 * Indicates to the protocol layer that the NIF is ready to send packets. |
|
556 * |
|
557 * @param aProtocol A pointer to a protocol |
|
558 */ |
|
559 { |
|
560 _LOG_L1C2(_L8("CIPv4ProtocolIf::StartSending [aProtocol=%X]"), aProtocol); |
|
561 |
|
562 CProtocolIfBase::StartSending(aProtocol); |
|
563 } |
|
564 |
|
565 TBool CIPv4ProtocolIf::WantsProtocol(TUint16 aProtocolCode) |
|
566 /** |
|
567 * Indicates the type of protocol implemented by this class. |
|
568 * |
|
569 * @param aProtocolCode The protocol type |
|
570 */ |
|
571 { |
|
572 _LOG_L1C2(_L8("CIPv4ProtocolIf::WantsProtocol [aProtocolCode=%X]"), |
|
573 aProtocolCode); |
|
574 |
|
575 #ifdef RAWIP_HEADER_APPENDED_TO_PACKETS |
|
576 return ((aProtocolCode & 0x00FF) == KIp4FrameType); |
|
577 #else |
|
578 (void) aProtocolCode; // disable compiler warning |
|
579 return ETrue; |
|
580 #endif // RAWIP_HEADER_APPENDED_TO_PACKETS |
|
581 } |
|
582 |
|
583 void CIPv4ProtocolIf::Process(RMBufChain& aPdu) |
|
584 /** |
|
585 * Called when an incoming IP packet has arrived. Send packets up to the |
|
586 * TCP/IP stack. |
|
587 * |
|
588 * @param aPdu The incoming packet |
|
589 */ |
|
590 { |
|
591 _LOG_L1C1(_L8("CIPv4ProtocolIf::Process")); |
|
592 |
|
593 #ifdef __BTT_LOGGING__ |
|
594 LogPacket(aPdu); |
|
595 #endif |
|
596 |
|
597 // Pass incoming packets up to the protocol, unless it hasn't |
|
598 // been bound yet. |
|
599 if (iProtocol) |
|
600 { |
|
601 _LOG_L1C1(_L8("CIPv4ProtocolIf: Packet Sent to TCP/IP Protocol!!!")); |
|
602 iProtocol->Process(aPdu, reinterpret_cast<CProtocolBase*>(this)); |
|
603 } |
|
604 else |
|
605 { |
|
606 _LOG_L2C1(_L8("WARNING: dumping incoming packet, no protocol bound")); |
|
607 aPdu.Free(); |
|
608 } |
|
609 } |
|
610 |
|
611 #ifdef __BTT_LOGGING__ |
|
612 void CIPv4ProtocolIf::LogPacket(const RMBufChain& aPacket) |
|
613 /** |
|
614 * Logs packet information into log file. |
|
615 * |
|
616 * @param aPacket The packet |
|
617 */ |
|
618 { |
|
619 _LOG_L1C1(_L8("CIPv4ProtocolIf::LogPacket")); |
|
620 |
|
621 TInt mBufLength = aPacket.Length() - aPacket.First()->Length(); |
|
622 |
|
623 _LOG_L3C2(_L8("Analysis of %d byte packet:"), mBufLength); |
|
624 |
|
625 //Note: All the constants used on this method are a pragmatic guess of the |
|
626 //IP header fields. The only porpose of this method is logging. |
|
627 |
|
628 if (mBufLength < 20) |
|
629 { |
|
630 _LOG_L3C2(_L8(" -doesn't appear to be a valid IPv4 packet (length=%d)") |
|
631 , mBufLength); |
|
632 return; |
|
633 } |
|
634 |
|
635 // Get a pointer to the packet's payload. |
|
636 const TUint8* payloadPtr = aPacket.First()->Next()->Ptr(); |
|
637 |
|
638 if ((payloadPtr[0] & 0xF0) != 0x40) |
|
639 { |
|
640 _LOG_L3C2(_L8(" - doesn't appear to be an IPv4 packet (version=0x%X)"), |
|
641 (payloadPtr[0] & 0xF0) >> 4); |
|
642 return; |
|
643 } |
|
644 |
|
645 if ((payloadPtr[0] & 0xF) != 0x5) |
|
646 { |
|
647 _LOG_L3C2(_L8(" - doesn't have a standard IP header (length=0x%X)"), |
|
648 payloadPtr[0] & 0xF); |
|
649 return; |
|
650 } |
|
651 |
|
652 _LOG_L3C5(_L8(" - src addr: %d.%d.%d.%d"), payloadPtr[12], payloadPtr[13], |
|
653 payloadPtr[14], payloadPtr[15]); |
|
654 _LOG_L3C5(_L8(" - dst addr: %d.%d.%d.%d"), payloadPtr[16], payloadPtr[17], |
|
655 payloadPtr[18], payloadPtr[19]); |
|
656 |
|
657 if (payloadPtr[9] == 0x06) |
|
658 { |
|
659 _LOG_L3C1(_L8(" - appears to be a TCP packet")); |
|
660 if (mBufLength < 40) |
|
661 { |
|
662 _LOG_L3C2(_L8(" - but is too short (length=0x%X)"), mBufLength); |
|
663 return; |
|
664 } |
|
665 _LOG_L3C3(_L8(" - src port: %d, dst port: %d"), |
|
666 (payloadPtr[20] << 8) + payloadPtr[21], |
|
667 (payloadPtr[22] << 8) + payloadPtr[23]); |
|
668 _LOG_L3C3(_L8(" - seq #: 0x%08X, ack #: 0x%08X"), |
|
669 (payloadPtr[24] << 24) + (payloadPtr[25] << 16) + |
|
670 (payloadPtr[26] << 8) + payloadPtr[27], |
|
671 (payloadPtr[28] << 24) + (payloadPtr[29] << 16) + |
|
672 (payloadPtr[30] << 8) + payloadPtr[31]); |
|
673 |
|
674 TBuf8<100> flagsSet; |
|
675 flagsSet.Copy(_L8(" - flags set: ")); |
|
676 |
|
677 // Write description of payload's flags to "flagsSet" |
|
678 if (payloadPtr[33] & 0x01) |
|
679 { |
|
680 flagsSet.Append(_L8("FIN ")); |
|
681 } |
|
682 if (payloadPtr[33] & 0x02) |
|
683 { |
|
684 flagsSet.Append(_L8("SYN ")); |
|
685 } |
|
686 if (payloadPtr[33] & 0x04) |
|
687 { |
|
688 flagsSet.Append(_L8("RST ")); |
|
689 } |
|
690 if (payloadPtr[33] & 0x08) |
|
691 { |
|
692 flagsSet.Append(_L8("PSH ")); |
|
693 } |
|
694 if (payloadPtr[33] & 0x10) |
|
695 { |
|
696 flagsSet.Append(_L8("ACK ")); |
|
697 } |
|
698 if (payloadPtr[33] & 0x20) |
|
699 { |
|
700 flagsSet.Append(_L8("URG ")); |
|
701 } |
|
702 _LOG_L3C1(flagsSet); |
|
703 |
|
704 TInt dataOffset = payloadPtr[32] >> 2; // in bytes |
|
705 if ((dataOffset > 0) && (mBufLength > dataOffset + 30)) |
|
706 { |
|
707 TBuf8<100> data; |
|
708 data.Copy(_L8(" - data begins: ")); |
|
709 for (TInt i = dataOffset + 20; i < dataOffset + 100; i++) |
|
710 { |
|
711 // We skip some bytes at the end of the MBuf, as they're junk. |
|
712 if (i >= (mBufLength - 10)) |
|
713 { |
|
714 break; |
|
715 } |
|
716 if (TChar(payloadPtr[i]).IsPrint()) |
|
717 { |
|
718 data.Append(TChar(payloadPtr[i])); |
|
719 } |
|
720 else |
|
721 { |
|
722 data.Append(TChar('?')); |
|
723 } |
|
724 } |
|
725 _LOG_L3C1(data); |
|
726 } |
|
727 } |
|
728 else if (payloadPtr[9] == 0x01) |
|
729 { |
|
730 _LOG_L3C1(_L8(" - appears to be an ICMP packet")); |
|
731 if (mBufLength < 24) |
|
732 { |
|
733 _LOG_L3C2(_L8(" - but is too short (length=0x%X)"), mBufLength); |
|
734 return; |
|
735 } |
|
736 |
|
737 if (payloadPtr[20] == 0x8) |
|
738 { |
|
739 _LOG_L3C1(_L8(" - is an echo request")); |
|
740 } |
|
741 else if (payloadPtr[20] == 0x0) |
|
742 { |
|
743 _LOG_L3C1(_L8(" - is an echo reply")); |
|
744 } |
|
745 else |
|
746 { |
|
747 _LOG_L3C2(_L8(" - unknown type (0x%02X)"), payloadPtr[20]); |
|
748 return; |
|
749 } |
|
750 |
|
751 if (mBufLength >= 28) |
|
752 { |
|
753 _LOG_L3C3(_L8(" - ID: 0x%04X, seq #: 0x%04X"), |
|
754 (payloadPtr[24] << 8) + payloadPtr[25], |
|
755 (payloadPtr[26] << 8) + payloadPtr[27]); |
|
756 } |
|
757 } |
|
758 else if (payloadPtr[9] == 0x11) |
|
759 { |
|
760 _LOG_L3C1(_L8(" - appears to be a UDP packet")); |
|
761 if (mBufLength < 28) |
|
762 { |
|
763 _LOG_L3C2(_L8(" - but is too short (length=0x%X)"), mBufLength); |
|
764 return; |
|
765 } |
|
766 _LOG_L3C3(_L8(" - src port: %d, dst port: %d"), |
|
767 (payloadPtr[20] << 8) + payloadPtr[21], |
|
768 (payloadPtr[22] << 8) + payloadPtr[23]); |
|
769 } |
|
770 else |
|
771 { |
|
772 _LOG_L3C2(_L8(" - appears to be for an unknown protocol (0x%X)"), |
|
773 payloadPtr[9]); |
|
774 } |
|
775 } |
|
776 #endif // __BTT_LOGGING__ |