|
1 // Copyright (c) 2004-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 // engine.cpp - IP administration tool engine |
|
15 // |
|
16 |
|
17 #include <eikenv.h> |
|
18 #include "ipadm.h" |
|
19 #include "engine.h" |
|
20 |
|
21 #include "uniload.h" |
|
22 |
|
23 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS |
|
24 #include <in_sock_internal.h> |
|
25 #endif |
|
26 |
|
27 #ifndef __SECURE_DATA__ |
|
28 #define DEFAULT_ROUTES_FILE _L("C:\\Data\\IpAdm\\route.ini") |
|
29 #else |
|
30 #define DEFAULT_ROUTES_FILE _L("route.ini") |
|
31 #endif |
|
32 |
|
33 LOCAL_C void AppendInterfaceStatus(TDes& buf, const TInt aStatus) |
|
34 { |
|
35 switch (aStatus) |
|
36 { |
|
37 case EIfPending: buf.Append(_L("PEND ")); break; |
|
38 case EIfUp: break; |
|
39 case EIfBusy: buf.Append(_L("BUSY ")); break; |
|
40 case EIfDown: buf.Append(_L("DOWN ")); break; |
|
41 default: buf.Append(_L("???? ")); break; |
|
42 } |
|
43 } |
|
44 |
|
45 LOCAL_C void AppendInterfaceName(TDes& buf, const TName& aName) |
|
46 { |
|
47 if (aName.Length() > 0) |
|
48 { |
|
49 buf.Append(aName); |
|
50 } |
|
51 else |
|
52 { |
|
53 buf.Append(_L("default")); |
|
54 } |
|
55 } |
|
56 |
|
57 LOCAL_C void AppendRouteType(TDes& buf, const TInt aType) |
|
58 { |
|
59 switch (aType) |
|
60 { |
|
61 case ERtNormal: buf.Append(_L(" ")); break; |
|
62 case ERtUser: buf.Append(_L("u ")); break; |
|
63 case ERtIcmpAdd: buf.Append(_L("- ")); break; // for IPv6, this is ND entry |
|
64 case ERtIcmpDel: buf.Append(_L("d ")); break; |
|
65 default: buf.Append(_L("? ")); break; |
|
66 } |
|
67 } |
|
68 |
|
69 LOCAL_C void AppendRouteState(TDes& buf, const TInt aState) |
|
70 { |
|
71 switch (aState) |
|
72 { |
|
73 case ERtNone: buf.Append(_L("NONE ")); break; |
|
74 case ERtPending: buf.Append(_L("PEND ")); break; |
|
75 case ERtBusy: buf.Append(_L("BUSY ")); break; |
|
76 case ERtReady: break; |
|
77 case ERtDown: buf.Append(_L("DOWN ")); break; |
|
78 default: buf.Append(_L("???? ")); break; |
|
79 } |
|
80 } |
|
81 |
|
82 // |
|
83 // |
|
84 // Just count the number of rightmost zeroes in an IPv6 address |
|
85 // and return (128 - count). |
|
86 // |
|
87 LOCAL_C TInt MaskLength(const TIp6Addr &aAddr) |
|
88 { |
|
89 TInt count = 0; |
|
90 for (TInt i = sizeof(aAddr.u.iAddr8) / sizeof(aAddr.u.iAddr8[0]); --i >= 0; ) |
|
91 { |
|
92 if (aAddr.u.iAddr8[i]) |
|
93 { |
|
94 TUint8 nonZeroByte = aAddr.u.iAddr8[i]; |
|
95 while ((nonZeroByte & 1) == 0) |
|
96 { |
|
97 count += 1; |
|
98 nonZeroByte >>= 1; |
|
99 } |
|
100 break; |
|
101 } |
|
102 count += 8; |
|
103 } |
|
104 return 128-count; |
|
105 } |
|
106 |
|
107 |
|
108 LOCAL_C TInt MaskLength(TUint32 aAddr) |
|
109 { |
|
110 TInt count = 0; |
|
111 // obviously, this is "brute force" counting |
|
112 while (aAddr & 0x80000000) |
|
113 { |
|
114 count++; |
|
115 aAddr <<= 1; |
|
116 } |
|
117 return count; |
|
118 } |
|
119 |
|
120 |
|
121 // TRawAddr |
|
122 // ********* |
|
123 // Lightweight internal help class for handling the link layer addresses |
|
124 // |
|
125 class TRawAddr : public TSockAddr |
|
126 { |
|
127 public: |
|
128 |
|
129 void Output(TDes& aBuf) const |
|
130 { |
|
131 TUint8* p = (TUint8*)UserPtr(); |
|
132 TInt len = ((TSockAddr *)this)->GetUserLen(); //lint !e1773 // it's a kludge but works anyway |
|
133 |
|
134 aBuf.SetLength(0); |
|
135 if (len == 0) |
|
136 return; |
|
137 if (aBuf.MaxLength() < len * 4) |
|
138 { |
|
139 aBuf.Fill('*', aBuf.MaxLength()); |
|
140 return; |
|
141 } |
|
142 if (len == 0) |
|
143 return; |
|
144 for (;;) |
|
145 { |
|
146 aBuf.AppendFormat(_L("%02X"), *p++ & 0xFF); |
|
147 if (--len == 0) |
|
148 break; |
|
149 aBuf.Append(TChar(':')); |
|
150 } |
|
151 } |
|
152 |
|
153 inline static TRawAddr& Cast(const TSockAddr& aAddr) |
|
154 { |
|
155 return *((TRawAddr *)&aAddr); //lint !e1773 // standard way to implement Cast |
|
156 } |
|
157 inline static TRawAddr& Cast(const TSockAddr* aAddr) |
|
158 { |
|
159 return *((TRawAddr *)aAddr); //lint !e1773 // standard way to implement Cast |
|
160 } |
|
161 }; |
|
162 |
|
163 // |
|
164 CIpAdmEngine::~CIpAdmEngine() |
|
165 { |
|
166 // |
|
167 // Ordering is important... Do not close iSS before |
|
168 // all sockets associated with it have been closed! |
|
169 // |
|
170 iFS.Close(); |
|
171 iSS.Close(); |
|
172 } |
|
173 |
|
174 void CIpAdmEngine::ConstructL() |
|
175 { |
|
176 // |
|
177 // Start Socket Reader activity |
|
178 // |
|
179 CheckResultL(_L("Active Scheduler"), CActiveScheduler::Current() == NULL); |
|
180 CheckResultL(_L("Connect to File server"), iFS.Connect()); |
|
181 CheckResultL(_L("Connect to Socket server"), iSS.Connect()); |
|
182 } |
|
183 |
|
184 |
|
185 LOCAL_C void AppendIpAddress(TDes &buf, const TDesC &aLabel, const TInetAddr &aAddr, TInt aSkip = 1) |
|
186 { |
|
187 if (aSkip && aAddr.IsUnspecified()) |
|
188 return; |
|
189 TBuf<64> out; |
|
190 buf.Append(aLabel); |
|
191 #ifdef HURRICANE_INSOCK |
|
192 aAddr.Output(out); |
|
193 #else |
|
194 aAddr.OutputWithScope(out); |
|
195 #endif |
|
196 buf.Append(out); |
|
197 } |
|
198 |
|
199 LOCAL_C void AppendRawAddress(TDes &buf, const TDesC &aLabel, const TSockAddr &aAddr) |
|
200 { |
|
201 if (aAddr.Family() == KAFUnspec) |
|
202 return; |
|
203 TBuf<100> out; |
|
204 buf.Append(aLabel); |
|
205 TRawAddr::Cast(aAddr).Output(out); |
|
206 buf.Append(out); |
|
207 } |
|
208 |
|
209 LOCAL_C void AppendIpMask(TDes &buf, const TInetAddr &aAddr) |
|
210 { |
|
211 if (aAddr.Family() == KAfInet6) |
|
212 buf.AppendFormat(_L("/%d"), MaskLength(aAddr.Ip6Address())); |
|
213 else |
|
214 buf.AppendFormat(_L("/%d"), MaskLength(aAddr.Address())); |
|
215 } |
|
216 |
|
217 void CIpAdmEngine::Show(TInt /*aVersion*/, const TSoInetInterfaceInfo &aInfo) |
|
218 { |
|
219 TBuf<1000> buf; |
|
220 buf = _L("if "); |
|
221 AppendInterfaceStatus(buf, aInfo.iState); |
|
222 AppendInterfaceName(buf, aInfo.iName); |
|
223 AppendIpAddress(buf, _L(" addr="), (const TInetAddr &)aInfo.iAddress, 0); |
|
224 AppendIpMask(buf, (const TInetAddr &)aInfo.iNetMask); |
|
225 AppendIpAddress(buf, _L(" bcast="), (const TInetAddr &)aInfo.iBrdAddr); |
|
226 AppendIpAddress(buf, _L(" gw="), (const TInetAddr &)aInfo.iDefGate); |
|
227 AppendIpAddress(buf, _L(" ns1="), (const TInetAddr &)aInfo.iNameSer1); |
|
228 AppendIpAddress(buf, _L(" ns2="), (const TInetAddr &)aInfo.iNameSer2); |
|
229 AppendRawAddress(buf, _L(" hwa="), aInfo.iHwAddr); |
|
230 buf.AppendFormat(_L(" Mtu=%d, SM=%d, F=%x"), aInfo.iMtu, aInfo.iSpeedMetric, (TUint)aInfo.iFeatures); |
|
231 ShowText(buf); |
|
232 } |
|
233 |
|
234 void CIpAdmEngine::Show(TInt /*aVersion*/, const TSoInetRouteInfo &aInfo) |
|
235 { |
|
236 TBuf<1000> buf; |
|
237 buf = _L("rt"); |
|
238 AppendRouteType(buf, aInfo.iType); |
|
239 AppendRouteState(buf, aInfo.iState); |
|
240 AppendIpAddress(buf, _L(""), (const TInetAddr &)aInfo.iDstAddr, 0); |
|
241 AppendIpMask(buf, (const TInetAddr &)aInfo.iNetMask); |
|
242 // the iIfAddr is actually the src address to be used for this route destination |
|
243 AppendIpAddress(buf, _L(" src="), (const TInetAddr &)aInfo.iIfAddr); |
|
244 if (aInfo.iGateway.Family() == KAfInet6 || aInfo.iGateway.Family() == KAfInet) |
|
245 AppendIpAddress(buf, _L(" gw="), (const TInetAddr &)aInfo.iGateway); |
|
246 else |
|
247 AppendRawAddress(buf, _L(" hwa="), aInfo.iGateway); |
|
248 buf.AppendFormat(_L(" M=%d"), aInfo.iMetric); |
|
249 ShowText(buf); |
|
250 } |
|
251 |
|
252 void CIpAdmEngine::ListInterfaces(TInt aVersion, const TDesC &aProtocol) |
|
253 { |
|
254 RSocket socket; |
|
255 |
|
256 if (CheckResult(aProtocol, socket.Open(iSS, aProtocol)) != KErrNone) |
|
257 return; |
|
258 if (socket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl) == KErrNone) |
|
259 { |
|
260 TPckgBuf<TSoInetInterfaceInfo> opt; |
|
261 while (socket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, opt) == KErrNone) |
|
262 Show(aVersion, opt()); |
|
263 } |
|
264 socket.Close(); |
|
265 } |
|
266 |
|
267 void CIpAdmEngine::ListRoutes(TInt aVersion, const TDesC &aProtocol) |
|
268 { |
|
269 RSocket socket; |
|
270 |
|
271 if (CheckResult(aProtocol, socket.Open(iSS, aProtocol)) != KErrNone) |
|
272 return; |
|
273 if (socket.SetOpt(KSoInetEnumRoutes, KSolInetRtCtrl) == KErrNone) |
|
274 { |
|
275 TPckgBuf<TSoInetRouteInfo> opt; |
|
276 while (socket.GetOpt(KSoInetNextRoute, KSolInetRtCtrl, opt) == KErrNone) |
|
277 Show(aVersion, opt()); |
|
278 } |
|
279 socket.Close(); |
|
280 } |
|
281 |
|
282 class TParser : public TLex |
|
283 { |
|
284 public: |
|
285 TParser(const TDesC &aStr); |
|
286 void NextToken(); |
|
287 int SkipSpaceAndMark(); |
|
288 TInt ParameterValue(const TDesC &aKey, TInt &aValue, const TInt aDefault = 0); |
|
289 TInt ParameterValue(const TDesC &aKey, TInetAddr &aValue); |
|
290 TLexMark iLine; |
|
291 TLexMark iCurrent; |
|
292 TPtrC iLastLine; |
|
293 TPtrC Line(); |
|
294 inline void MarkLine() { iCurrent = iLine; iOpen = 1; } |
|
295 TPtrC iToken; |
|
296 TInt iOpen; |
|
297 TInt iFirst; // Non-zero, if next token is first in line |
|
298 }; |
|
299 |
|
300 #pragma warning (disable:4097) |
|
301 TParser::TParser(const TDesC &aStr) : TLex(aStr), iLine(), iCurrent(), iLastLine(), iToken(), iOpen(0), iFirst(1) |
|
302 { |
|
303 Mark(iLine); |
|
304 MarkLine(); |
|
305 } |
|
306 #pragma warning (default:4097) |
|
307 |
|
308 // |
|
309 // Return current line as a descriptor |
|
310 // (and skip to the next line, if not fully parsed) |
|
311 // |
|
312 TPtrC TParser::Line() |
|
313 { |
|
314 if (iOpen) |
|
315 { |
|
316 // Line not fully parsed yet, search to the EOL |
|
317 while (!Eos()) |
|
318 { |
|
319 TChar ch = Get(); |
|
320 if (ch == '\n' || ch == '\r') |
|
321 { |
|
322 iLastLine.Set(MarkedToken(iCurrent)); |
|
323 iOpen = 0; |
|
324 Mark(iLine); |
|
325 break; |
|
326 } |
|
327 } |
|
328 } |
|
329 return iLastLine; |
|
330 } |
|
331 // |
|
332 // Skip white space and mark, including comments! |
|
333 // |
|
334 int TParser::SkipSpaceAndMark() |
|
335 { |
|
336 TChar ch; |
|
337 TInt comment = 0; |
|
338 TInt newline = 0; |
|
339 |
|
340 while (!Eos()) |
|
341 { |
|
342 ch = Get(); |
|
343 if (ch =='\n') |
|
344 { |
|
345 comment = 0; |
|
346 newline = 1; |
|
347 if (iOpen) |
|
348 { |
|
349 iLastLine.Set(MarkedToken(iCurrent)); |
|
350 iOpen = 0; |
|
351 } |
|
352 Mark(iLine); |
|
353 } |
|
354 else if (comment || ch == '#') |
|
355 comment = 1; |
|
356 else if (!ch.IsSpace()) |
|
357 { |
|
358 UnGet(); |
|
359 break; |
|
360 } |
|
361 } |
|
362 Mark(); |
|
363 return newline; |
|
364 } |
|
365 |
|
366 // |
|
367 // Extract Next token and return |
|
368 // |
|
369 void TParser::NextToken() |
|
370 { |
|
371 if (SkipSpaceAndMark()) |
|
372 iFirst = 1; // New line! |
|
373 if (Eos()) |
|
374 { |
|
375 iFirst = -1; |
|
376 return; |
|
377 } |
|
378 while (!Eos()) |
|
379 { |
|
380 TChar ch = Peek(); |
|
381 if (ch == '#' || ch.IsSpace()) |
|
382 break; |
|
383 Inc(); |
|
384 } |
|
385 iToken.Set(MarkedToken()); |
|
386 iFirst = SkipSpaceAndMark(); |
|
387 } |
|
388 |
|
389 TInt TParser::ParameterValue(const TDesC &aKey, TInt &aValue, const TInt aDefault) |
|
390 { |
|
391 if (aKey.Compare(iToken) != 0) |
|
392 return KErrNotFound; // Doesn't match, do nothing |
|
393 // |
|
394 // When the keyword matches, return is always KErrNone |
|
395 // (caller must deduce errors by aDefault. |
|
396 // |
|
397 if (iFirst) |
|
398 aValue = aDefault; |
|
399 else if (Val(aValue) == KErrNone) |
|
400 iFirst = SkipSpaceAndMark(); |
|
401 else |
|
402 aValue = aDefault; |
|
403 return KErrNone; |
|
404 } |
|
405 |
|
406 TInt TParser::ParameterValue(const TDesC &aKey, TInetAddr &aValue) |
|
407 { |
|
408 if (aKey.Compare(iToken) != 0) |
|
409 return KErrNotFound; // Doesn't match, do nothing |
|
410 // |
|
411 // When the keyword matches, return is always KErrNone |
|
412 // (caller must deduce errors by aDefault. |
|
413 // |
|
414 if (!iFirst) |
|
415 { |
|
416 NextToken(); |
|
417 if (aValue.Input(iToken) == KErrNone) |
|
418 return KErrNone; |
|
419 } |
|
420 aValue.SetFamily(0); |
|
421 return KErrNone; |
|
422 } |
|
423 |
|
424 |
|
425 void CIpAdmEngine::AddRoutes(const TDesC &aProtocol) |
|
426 { |
|
427 TInt err = KErrNone; |
|
428 RSocket socket; |
|
429 |
|
430 if (CheckResult(aProtocol, socket.Open(iSS, aProtocol)) != KErrNone) |
|
431 return; |
|
432 |
|
433 HBufC *buf = NULL; |
|
434 #ifndef __DATA_CAGING__ |
|
435 TRAP(err, buf = UnicodeLoad::LoadL(iFS, DEFAULT_ROUTES_FILE)); |
|
436 if (CheckResult(DEFAULT_ROUTES_FILE, err)) |
|
437 #else // __DATA_CAGING__ |
|
438 // get private path |
|
439 TFileName filename; |
|
440 RFs theFS; |
|
441 |
|
442 theFS.Connect(); |
|
443 theFS.PrivatePath(filename); |
|
444 theFS.Close(); |
|
445 filename.Append(DEFAULT_ROUTES_FILE); |
|
446 |
|
447 TRAP(err, buf = UnicodeLoad::LoadL(iFS, filename)); |
|
448 if (CheckResult(filename, err)) |
|
449 #endif // __DATA_CAGING__ |
|
450 { |
|
451 socket.Close(); |
|
452 return; |
|
453 } |
|
454 //lint -save -e613 Trapped above |
|
455 TParser inifile(*buf); //lint -restore |
|
456 TInt route_count = 0; |
|
457 TInt if_count = 0; |
|
458 while (!err) |
|
459 { |
|
460 // Skip until first token in line |
|
461 while (inifile.iFirst == 0) |
|
462 inifile.NextToken(); |
|
463 if (inifile.iFirst < 0) |
|
464 break; |
|
465 |
|
466 // |
|
467 // The route file is a simple list of lines with following format |
|
468 // |
|
469 inifile.NextToken(); |
|
470 inifile.MarkLine(); |
|
471 if ((inifile.iToken.Compare(_L("route-add")) == 0)) |
|
472 { |
|
473 // route-add destination netmask metric gateway interface |
|
474 // |
|
475 // all except the "metric" are assumed to be addresses |
|
476 // |
|
477 TPckgBuf<TSoInetRouteInfo> opt; |
|
478 opt().iType = ERtUser; |
|
479 opt().iState = ERtReady; |
|
480 opt().iIfAddr.SetFamily(KAFUnspec); |
|
481 for (int i = 0; !err && inifile.iFirst == 0; ++i) |
|
482 { |
|
483 switch (i) |
|
484 { |
|
485 case 0: // Destination |
|
486 inifile.NextToken(); |
|
487 err = (TInetAddr::Cast(opt().iDstAddr)).Input(inifile.iToken); |
|
488 break; |
|
489 case 1: // Netmask |
|
490 inifile.NextToken(); |
|
491 err = (TInetAddr::Cast(opt().iNetMask)).Input(inifile.iToken); |
|
492 break; |
|
493 case 2: // metric |
|
494 err = inifile.Val(opt().iMetric); |
|
495 break; |
|
496 case 3: // Gateway |
|
497 inifile.NextToken(); |
|
498 if (inifile.iToken.Compare(_L("-")) == 0) |
|
499 opt().iGateway.SetFamily(KAFUnspec); |
|
500 else |
|
501 err = (TInetAddr::Cast(opt().iGateway)).Input(inifile.iToken); |
|
502 break; |
|
503 case 4: // Interface |
|
504 inifile.NextToken(); |
|
505 if (inifile.iToken.Compare(_L("-")) == 0) |
|
506 opt().iIfAddr.SetFamily(KAFUnspec); |
|
507 else |
|
508 err = (TInetAddr::Cast(opt().iIfAddr)).Input(inifile.iToken); |
|
509 break; |
|
510 default: |
|
511 inifile.NextToken(); |
|
512 break; |
|
513 } |
|
514 inifile.SkipSpaceAndMark(); |
|
515 } |
|
516 if (err) |
|
517 { |
|
518 ShowText(_L("Syntax error on line")); |
|
519 ShowText(inifile.Line()); |
|
520 break; |
|
521 } |
|
522 else if (CheckResult(inifile.Line(), socket.SetOpt(KSoInetAddRoute, KSolInetRtCtrl, opt)) == KErrNone) |
|
523 route_count++; |
|
524 } |
|
525 else if ((inifile.iToken.Compare(_L("ifconfig")) == 0)) |
|
526 { |
|
527 // |
|
528 // For now only simple format |
|
529 // |
|
530 // ifconfig interface [address [remote]] [parameters] |
|
531 // |
|
532 // perameters can be |
|
533 // |
|
534 // prefix n netmask (ip4)/prefix (ip6) [default 32/128]. This *IS* not same |
|
535 // as Unix ifconfig. Here the value tells whether a "single address" |
|
536 // or netmask/prefix configuration is to be performed. |
|
537 // |
|
538 // *NOTE* prefix splits the bits in the address into two sections: (prefix,id) |
|
539 // if prefix part is non-ZERO, it will be added as if router had sent |
|
540 // RA with prefix option with L=1, A=1 |
|
541 // if id part is non-ZERO, it will be processed as interface id (alias |
|
542 // keyword will control whether this is primary or additional). |
|
543 // |
|
544 // *NOTE* prefix 128 => id part is zero length, assumed ZERO |
|
545 // prefix 0 => prefix part is zero length, and treated as ZERO |
|
546 // |
|
547 // *NOTE* If configuring for single address, do not specify prefix! |
|
548 // |
|
549 // alias specify additional network address ([address] required) |
|
550 // 'alias' is not present, but [address] is, then the primary |
|
551 // network address is configured. |
|
552 // delete remove specified network address |
|
553 // down mark interface down |
|
554 // up mark interface up |
|
555 // metric n set metric to n |
|
556 // mtu n set MTU to n |
|
557 // ns1 address nameserver 1 address |
|
558 // ns2 address nameserver 2 address |
|
559 // proxy speficy address as proxy |
|
560 // anycast specify address as anycast |
|
561 // |
|
562 |
|
563 TPckgBuf<TSoInet6InterfaceInfo> opt; |
|
564 #if 1 |
|
565 opt().iDoState = 0; |
|
566 opt().iDoId = 0; |
|
567 opt().iDoPrefix = 0; |
|
568 opt().iDoAnycast = 0; |
|
569 #ifndef HURRICANE_INSOCK |
|
570 opt().iDoProxy = 0; |
|
571 #endif |
|
572 opt().iAlias = 0; |
|
573 opt().iDelete = 0; |
|
574 opt().iAddress.SetFamily(0); |
|
575 opt().iDefGate.SetFamily(0); |
|
576 opt().iNetMask.SetFamily(0); |
|
577 opt().iNameSer1.SetFamily(0); |
|
578 opt().iNameSer2.SetFamily(0); |
|
579 opt().iMtu = 0; |
|
580 opt().iSpeedMetric = 0; |
|
581 #else |
|
582 // unfortunately, this does not work.. "has initialized data" in MARM compile! |
|
583 static const TSoInet6InterfaceInfo init_opt; |
|
584 opt() = init_opt; |
|
585 #endif |
|
586 TInt prefix = -1; |
|
587 for (int i = 0; !err && inifile.iFirst == 0; ++i) |
|
588 { |
|
589 inifile.NextToken(); |
|
590 switch (i) |
|
591 { |
|
592 case 0: // Interface Name |
|
593 opt().iName = inifile.iToken; |
|
594 opt().iTag = inifile.iToken; |
|
595 break; |
|
596 case 1: // Address |
|
597 if ((TInetAddr::Cast(opt().iAddress)).Input(inifile.iToken) != KErrNone) |
|
598 { |
|
599 i = 2; // We won't have remote address either! |
|
600 goto parameters; //lint !e801 // no clean way to do it without goto |
|
601 } |
|
602 break; |
|
603 case 2: // Remote Address |
|
604 if ((TInetAddr::Cast(opt().iDefGate)).Input(inifile.iToken) == KErrNone) |
|
605 break; |
|
606 //lint -fallthrough |
|
607 default: |
|
608 parameters: |
|
609 if (opt().iDoState == 0) |
|
610 { |
|
611 if (inifile.iToken.Compare(_L("down")) == 0) |
|
612 { |
|
613 opt().iState = EIfDown; |
|
614 opt().iDoState = 1; |
|
615 break; |
|
616 } |
|
617 if (inifile.iToken.Compare(_L("up")) == 0) |
|
618 { |
|
619 opt().iState = EIfUp; |
|
620 opt().iDoState = 1; |
|
621 break; |
|
622 } |
|
623 } |
|
624 if (opt().iDoAnycast == 0 && |
|
625 #ifndef HURRICANE_INSOCK |
|
626 opt().iDoProxy == 0 && |
|
627 #endif |
|
628 prefix < 0) |
|
629 { |
|
630 // Only one of 'proxy' or 'anycast' can be present. Also, prefix must not |
|
631 // be present. |
|
632 if (inifile.iToken.Compare(_L("anycast")) == 0) |
|
633 { |
|
634 opt().iDoAnycast = 1; |
|
635 break; |
|
636 } |
|
637 else if (inifile.iToken.Compare(_L("proxy")) == 0) |
|
638 { |
|
639 #ifndef HURRICANE_INSOCK |
|
640 opt().iDoProxy = 1; |
|
641 #endif |
|
642 break; |
|
643 } |
|
644 } |
|
645 if (opt().iNameSer1.Family() == 0 && inifile.ParameterValue(_L("ns1"), opt().iNameSer1) == KErrNone) |
|
646 break; |
|
647 if (opt().iNameSer2.Family() == 0 && inifile.ParameterValue(_L("ns2"), opt().iNameSer2) == KErrNone) |
|
648 break; |
|
649 if (opt().iDelete == 0 && inifile.iToken.Compare(_L("delete")) == 0) |
|
650 { |
|
651 opt().iDelete = 1; |
|
652 break; |
|
653 } |
|
654 if (opt().iAlias == 0 && inifile.iToken.Compare(_L("alias")) == 0) |
|
655 { |
|
656 opt().iAlias = 1; |
|
657 break; |
|
658 } |
|
659 if (opt().iMtu == 0 && inifile.ParameterValue(_L("mtu"), opt().iMtu) == KErrNone) |
|
660 break; |
|
661 if (opt().iSpeedMetric == 0 && inifile.ParameterValue(_L("metric"), opt().iSpeedMetric) == KErrNone) |
|
662 break; |
|
663 if (opt().iDoAnycast == 0 && |
|
664 #ifndef HURRICANE_INSOCK |
|
665 opt().iDoProxy == 0 && |
|
666 #endif |
|
667 prefix < 0 && |
|
668 inifile.ParameterValue(_L("prefix"), prefix, 129) == KErrNone) |
|
669 { |
|
670 // prefix == 129, if value is missing => Error |
|
671 if (prefix > 128) |
|
672 err = KErrArgument; |
|
673 break; |
|
674 } |
|
675 err = KErrGeneral; |
|
676 break; |
|
677 } |
|
678 inifile.SkipSpaceAndMark(); |
|
679 } |
|
680 if (!err) |
|
681 { |
|
682 // Munge the prefix information into TSoInet6InterfaceInfo |
|
683 if (prefix < 0) |
|
684 { |
|
685 // No prefix present, iNetMask is left unspecified, |
|
686 // request "single address" processing (prefix = 128) |
|
687 opt().iDoId = 1; |
|
688 opt().iDoPrefix = 1; |
|
689 } |
|
690 else if (opt().iAddress.Family() == KAfInet && prefix <= 32) |
|
691 { |
|
692 // IPv4 processing -- defines the netmask |
|
693 const TUint32 mask = ~0UL << (32 - prefix); |
|
694 const TUint32 addr = opt().iAddress.Address(); |
|
695 TInetAddr::Cast(opt().iNetMask).SetAddress(mask); |
|
696 if (mask & addr) |
|
697 opt().iDoPrefix = 1; |
|
698 if ((~mask) & addr) |
|
699 opt().iDoId = 1; |
|
700 } |
|
701 else if (opt().iAddress.Family() == KAfInet6 && prefix <= 128) |
|
702 { |
|
703 // IPv6 processing |
|
704 TInetAddr p; |
|
705 // Is Prefix part all zeroes? |
|
706 p.Prefix(TInetAddr::Cast(opt().iAddress), prefix); |
|
707 if (!p.Ip6Address().IsUnspecified()) |
|
708 opt().iDoPrefix = 1; |
|
709 TInetAddr::Cast(opt().iNetMask).PrefixMask(prefix); |
|
710 // Is Id part all zeroes? |
|
711 p.SetAddress(TInetAddr::Cast(opt().iAddress).Ip6Address()); |
|
712 const TIp6Addr addr = p.Ip6Address(); |
|
713 const TIp6Addr mask = TInetAddr::Cast(opt().iNetMask).Ip6Address(); |
|
714 if ((addr.u.iAddr32[0] & ~mask.u.iAddr32[0]) != 0 || |
|
715 (addr.u.iAddr32[1] & ~mask.u.iAddr32[1]) != 0 || |
|
716 (addr.u.iAddr32[2] & ~mask.u.iAddr32[2]) != 0 || |
|
717 (addr.u.iAddr32[3] & ~mask.u.iAddr32[3]) != 0) |
|
718 opt().iDoId = 1; |
|
719 } |
|
720 else |
|
721 { |
|
722 // incorrect of prefix value |
|
723 err = KErrArgument; |
|
724 } |
|
725 } |
|
726 if (err) |
|
727 { |
|
728 ShowText(_L("Syntax error on line")); |
|
729 ShowText(inifile.Line()); |
|
730 break; |
|
731 } |
|
732 else if (CheckResult(inifile.Line(), socket.SetOpt(KSoInetConfigInterface, KSolInetIfCtrl, opt)) == KErrNone) |
|
733 if_count++; |
|
734 } |
|
735 #ifndef HURRICANE_INSOCK |
|
736 else if ((inifile.iToken.Compare(_L("setscope")) == 0)) |
|
737 { |
|
738 // |
|
739 // For now only simple format |
|
740 // |
|
741 // setscope interface interface2 level |
|
742 // |
|
743 // perameters can be |
|
744 // |
|
745 // interface the name of the interface to be change |
|
746 // interface2 the name of the interface to used as a source for the scope values |
|
747 // scope the scope of the join point [2..16] |
|
748 |
|
749 TPckgBuf<TSoInetIfQuery> opt1; |
|
750 TPckgBuf<TSoInetIfQuery> opt2; |
|
751 TInt scope = -1; |
|
752 TInt i = 0; |
|
753 for (i = 0; !err && inifile.iFirst == 0; ++i) |
|
754 { |
|
755 inifile.NextToken(); |
|
756 switch (i) |
|
757 { |
|
758 case 0: // Interface Name (to modify) |
|
759 opt1().iName = inifile.iToken; |
|
760 err = CheckResult(inifile.iToken, socket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, opt1)); |
|
761 break; |
|
762 case 1: // Interface Name (the source) |
|
763 opt2().iName = inifile.iToken; |
|
764 err = CheckResult(inifile.iToken, socket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, opt2)); |
|
765 break; |
|
766 case 2: // Scope Level |
|
767 err = inifile.ParameterValue(_L("level"), scope); |
|
768 break; |
|
769 default: |
|
770 err = KErrArgument; |
|
771 break; |
|
772 } |
|
773 inifile.SkipSpaceAndMark(); |
|
774 } |
|
775 if (err || scope < 2 || scope > 16) |
|
776 { |
|
777 ShowText(_L("Syntax error on line")); |
|
778 ShowText(inifile.Line()); |
|
779 break; |
|
780 } |
|
781 // |
|
782 // Build a new scope id vector |
|
783 // |
|
784 scope -= 1; // scope array is indexed from 0 |
|
785 #if 0 |
|
786 for (i = 0; ++i < scope;) |
|
787 opt1().iZone[i] = ~opt1().iZone[0]; |
|
788 for ( ;scope < STATIC_CAST(TInt, sizeof(opt1().iZone) / sizeof(opt1().iZone[0])); ++scope) |
|
789 opt1().iZone[scope] = opt2().iZone[scope]; |
|
790 #else |
|
791 opt1().iZone[scope] = opt2().iZone[scope]; |
|
792 #endif |
|
793 opt1().iIndex = opt1().iZone[0]; |
|
794 err = CheckResult(inifile.Line(), socket.SetOpt(KSoInetIfQuerySetScope, KSolInetIfQuery, opt1)); |
|
795 } |
|
796 #endif |
|
797 } |
|
798 delete buf; |
|
799 TBuf<80> text; |
|
800 text.Format(_L("Added %d routes, configured %d interfaces"), route_count, if_count); |
|
801 ShowText(text); |
|
802 socket.Close(); |
|
803 } |
|
804 |
|
805 void CIpAdmEngine::HandleCommandL(TInt aCommand) |
|
806 { |
|
807 switch (aCommand) |
|
808 { |
|
809 case EIpAdmInterfaces: |
|
810 ListInterfaces(4,_L("udp")); |
|
811 // ListInterfaces(6,_L("udp6")); |
|
812 break; |
|
813 case EIpAdmRoutes: |
|
814 ListRoutes(4, _L("udp")); |
|
815 // ListRoutes(6, _L("udp6")); |
|
816 break; |
|
817 case EIpAdmAddRoutes: |
|
818 AddRoutes(_L("udp")); |
|
819 break; |
|
820 default: |
|
821 break; |
|
822 } |
|
823 } |
|
824 |
|
825 |
|
826 // |
|
827 // CIpAdmEngine::CheckResult |
|
828 // Output success or fail message, returns the error code |
|
829 // |
|
830 TInt CIpAdmEngine::CheckResult(const TDesC &aText, TInt aResult) |
|
831 { |
|
832 if (aResult == KErrNone) |
|
833 return KErrNone; |
|
834 |
|
835 TBuf<100> err; |
|
836 CEikonEnv::Static()->GetErrorText(err, aResult); |
|
837 |
|
838 TBuf<200> str(aText); |
|
839 str.AppendFormat(_L(" returned with [%s] "), err.PtrZ()); |
|
840 iAppView->Write(str); |
|
841 |
|
842 return aResult; |
|
843 } |
|
844 // |
|
845 // CIpAdmEngine::CheckResultL |
|
846 // Output success or fail message, and Leave if the code is not |
|
847 // KErrNone. |
|
848 // |
|
849 void CIpAdmEngine::CheckResultL(const TDesC &aText, TInt aResult) |
|
850 { |
|
851 if (CheckResult(aText, aResult) != KErrNone) |
|
852 User::Leave(aResult); |
|
853 } |
|
854 |
|
855 void CIpAdmEngine::ShowText(const TDesC &aText) |
|
856 { |
|
857 iAppView->Write(aText); |
|
858 } |
|
859 |