|
1 /* |
|
2 * Copyright (c) 1995-2007 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 /** |
|
20 @internalTechnology |
|
21 @file |
|
22 |
|
23 Implementation of the Netcards.exe adapter selection application. |
|
24 This version writes settings to an ethernet.ini file only. Those settings |
|
25 should be either copied into epoc.ini (EKA2) or extracted into correct setup |
|
26 files: ethermac.dat and etherdriver.dat (EKA1) using an appropriate tool. |
|
27 */ |
|
28 |
|
29 /* |
|
30 * Desired design of maximum size and alignment. |
|
31 * These are implementation specific. |
|
32 */ |
|
33 #define _SS_MAXSIZE 128 // Maximum size. |
|
34 #define _SS_ALIGNSIZE (sizeof(__int64)) // Desired alignment. |
|
35 |
|
36 /* |
|
37 * Definitions used for sockaddr_storage structure paddings design. |
|
38 */ |
|
39 /** |
|
40 * This version of netcards.c has been written to work and run on Windows 2000 |
|
41 * and Windows XP. It has been compiled against both WinPCap 4.0. |
|
42 * |
|
43 * We identify the version of the compiler from the macros set by E32PLAT.pm |
|
44 * and if .NET assume that winsock2 will be used (although this is not needed). |
|
45 */ |
|
46 |
|
47 #define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof (short)) |
|
48 #define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (short) + _SS_PAD1SIZE \ |
|
49 + _SS_ALIGNSIZE)) |
|
50 |
|
51 struct sockaddr_storage { |
|
52 short ss_family; // Address family. |
|
53 char __ss_pad1[_SS_PAD1SIZE]; // 6 byte pad, this is to make |
|
54 // implementation specific pad up to |
|
55 // alignment field that follows explicit |
|
56 // in the data structure. |
|
57 __int64 __ss_align; // Field to force desired structure. |
|
58 char __ss_pad2[_SS_PAD2SIZE]; // 112 byte pad to achieve desired size; |
|
59 // _SS_MAXSIZE value minus size of |
|
60 // ss_family, __ss_pad1, and |
|
61 // __ss_align fields is 112. |
|
62 }; |
|
63 |
|
64 // Forward declare struct _RPC_ASYNC_STATE, to avoid a warning in rpcasync.h |
|
65 struct _RPC_ASYNC_STATE; |
|
66 |
|
67 // include WinPcap |
|
68 // The dance with warnings is necessary to avoid warnings such as |
|
69 // |
|
70 // \MSVC6\VC98\include\qos.h(236) : warning C4201: nonstandard extension used : |
|
71 // nameless struct/union |
|
72 // |
|
73 // when we compile at warning level 4. |
|
74 // |
|
75 |
|
76 #pragma warning(disable:4514) |
|
77 #pragma warning(push,3) |
|
78 #include "pcap.h" |
|
79 #pragma warning(pop) |
|
80 |
|
81 //other includes |
|
82 #include "packet32.h" |
|
83 #include "ntddndis.h" |
|
84 #include <windows.h> |
|
85 |
|
86 #include <stdio.h> |
|
87 #include <malloc.h> |
|
88 #include <conio.h> |
|
89 |
|
90 |
|
91 #define EPOC_INI_FILE "ethernet.ini" |
|
92 |
|
93 #define EPOC_INI_FILE_TEMP "__temp__ethernet__.ini" |
|
94 |
|
95 #define ETHER_NIF_ENTRY "ETHER_NIF" |
|
96 #define ETHER_MAC_ENTRY "ETHER_MAC" |
|
97 #define ETHER_SPEED_ENTRY "ETHER_SPEED" |
|
98 |
|
99 #define MAX_VALUE 80 |
|
100 #define MAX_LINE 100 |
|
101 #define MAX_OID_DATA 256 |
|
102 |
|
103 #define MAX_ADAPTER_LEN 1024 |
|
104 #define MAX_ADAPTERS 10 |
|
105 |
|
106 #define OID_802_3_CURRENT_ADDRESS 0x01010102 |
|
107 |
|
108 |
|
109 // |
|
110 // Global list of supported adapter names. |
|
111 // |
|
112 char AdapterList[MAX_ADAPTERS][MAX_ADAPTER_LEN]; |
|
113 |
|
114 |
|
115 // |
|
116 // Replace or write new 'value' for 'entry' in epoc.ini file |
|
117 // returns 0 if ok, negative value if sth wrong |
|
118 // |
|
119 int replace_in_inifile(char * entry, char* value, BOOL valUnicode ); |
|
120 |
|
121 |
|
122 // |
|
123 // Gets the adapter speed and mac address. Returns 0 if no mac is available, |
|
124 // otherwise returns non-zero if successful. |
|
125 // |
|
126 int get_adapter_speed_and_mac(char* adapterName, UINT* speed, unsigned char* mac); |
|
127 |
|
128 // |
|
129 // Main entry point. |
|
130 // |
|
131 int main(int argc, char* argv[]) |
|
132 { |
|
133 char err[PCAP_ERRBUF_SIZE + 1]; |
|
134 |
|
135 |
|
136 // string that contains a list of the network adapters |
|
137 pcap_if_t *adapterlist, *adapter; |
|
138 |
|
139 int adapters=0, adapterToUse, i; |
|
140 UINT speed_Mbps = 0; |
|
141 unsigned char mac[6]; |
|
142 |
|
143 FILE *inifile; |
|
144 |
|
145 char speed_value[10]; |
|
146 char *MAC_value = malloc( 13*sizeof(char) ); |
|
147 char *temp2 = malloc( 13*sizeof(char) ); |
|
148 int interfaceArg = 0; |
|
149 int MACmode = 0; |
|
150 |
|
151 if ( argc>1 && argv[1] ) |
|
152 { |
|
153 interfaceArg = atoi(argv[1])%10; |
|
154 MACmode = atoi(argv[1])/10; //used for set ethernet/WLAN MAC address |
|
155 } |
|
156 //printf("interfaceArg=%d, MACmode=%d\n", interfaceArg, MACmode); |
|
157 |
|
158 // |
|
159 // Obtain the name of the adapters installed on this machine. |
|
160 // |
|
161 // The result of this function is obtained querying the registry, |
|
162 // and therefore the format of the result in Windows NTx is different |
|
163 // from the one in Windows 9x. Windows 9x uses the ASCII encoding method |
|
164 // to store a string, while Windows NTx uses UNICODE. |
|
165 // |
|
166 // In addition different versions of PCAP vary this behaviour meaning |
|
167 // that the returned data cannot be assumed to be one format or the |
|
168 // other - in other words we must check it ourselves. |
|
169 // |
|
170 printf("\nAdapters installed:\n"); |
|
171 |
|
172 if(pcap_findalldevs(&adapterlist, err) < 0) |
|
173 { |
|
174 printf("Error - pcap_findalldevs: %s\n", err); |
|
175 return (1); |
|
176 } |
|
177 for(adapter = adapterlist; adapter; adapter = adapter->next) |
|
178 { |
|
179 memcpy(AdapterList[adapters], adapter->name, strlen(adapter->name)); |
|
180 if(get_adapter_speed_and_mac(AdapterList[adapters], &speed_Mbps, mac)) |
|
181 { |
|
182 printf("\n%3d - %s\n", adapters+1, AdapterList[adapters]); |
|
183 adapters++; |
|
184 } |
|
185 else |
|
186 { |
|
187 printf("\nN/A - %s\n",AdapterList[adapters]); |
|
188 } |
|
189 printf(" %s\n", adapter->description); |
|
190 } |
|
191 printf("\n"); |
|
192 |
|
193 if (adapters>1) |
|
194 { |
|
195 if((interfaceArg>adapters)||(interfaceArg<1) ) |
|
196 { |
|
197 do |
|
198 { |
|
199 printf("Select the number of the adapter to use : "); |
|
200 scanf("%d",&adapterToUse); |
|
201 if (adapterToUse > adapters || adapterToUse < 1) |
|
202 { |
|
203 printf("\nThe number must be between 1 and %d\n",adapters); |
|
204 } |
|
205 } while (adapterToUse > adapters || adapterToUse < 1); |
|
206 } |
|
207 else |
|
208 { |
|
209 adapterToUse = interfaceArg; |
|
210 } |
|
211 } |
|
212 else |
|
213 { |
|
214 adapterToUse = adapters; |
|
215 } |
|
216 |
|
217 MAC_value[0] = '\0'; |
|
218 temp2[0] = '\0'; |
|
219 speed_value[0] = '\0'; |
|
220 |
|
221 // |
|
222 // Open the adapter if available... |
|
223 // |
|
224 if (adapterToUse > 0 && adapterToUse <= adapters) |
|
225 { |
|
226 printf("\nUsing adapter %d\n", adapterToUse); |
|
227 |
|
228 if (get_adapter_speed_and_mac(AdapterList[adapterToUse-1], &speed_Mbps, mac)) |
|
229 { |
|
230 if (speed_Mbps == 0) |
|
231 { |
|
232 printf("Could not read Ethernet card's speed\n"); |
|
233 } |
|
234 |
|
235 printf("Physical address read: %02x:%02x:%02x:%02x:%02x:%02x\n", |
|
236 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); |
|
237 |
|
238 if(MACmode == 0) //ethernet MAC |
|
239 { |
|
240 mac[0] += 2; // changing address from global to local |
|
241 } |
|
242 |
|
243 for( i=0; i<6; i++ ) |
|
244 { |
|
245 strcpy( temp2, MAC_value); |
|
246 if( mac[i] > 15 ) |
|
247 { |
|
248 // has 2 hex digits |
|
249 sprintf( MAC_value, "%s%x", temp2, mac[i]); |
|
250 } |
|
251 else |
|
252 { |
|
253 sprintf( MAC_value, "%s0%x", temp2, mac[i]); |
|
254 } |
|
255 } |
|
256 } |
|
257 else |
|
258 { |
|
259 printf("Problem with opening adapter (packet.lib issue)\n"); |
|
260 return (1); |
|
261 } |
|
262 } |
|
263 else |
|
264 { |
|
265 printf("\nNo supported adapters found\n"); |
|
266 } |
|
267 |
|
268 // |
|
269 // Write the settings to the INI file... |
|
270 // |
|
271 printf("Writing settings to %s.\n\n", EPOC_INI_FILE); |
|
272 |
|
273 inifile = fopen(EPOC_INI_FILE, "a"); // to create if does exist |
|
274 if ( NULL != inifile ) |
|
275 { |
|
276 fclose(inifile); |
|
277 } |
|
278 else |
|
279 { |
|
280 printf("Can't create or access %s.\n\n", EPOC_INI_FILE); |
|
281 return (1); |
|
282 } |
|
283 |
|
284 if ( 0 != replace_in_inifile( ETHER_NIF_ENTRY, AdapterList[adapterToUse-1], FALSE ) ) |
|
285 { |
|
286 printf("Couldn't write adapter name to %s file\n", EPOC_INI_FILE); |
|
287 return (1); |
|
288 } |
|
289 |
|
290 |
|
291 if ( 0 != replace_in_inifile( ETHER_MAC_ENTRY, MAC_value, FALSE ) ) |
|
292 { |
|
293 printf("Couldn't write MAC address to %s file\n", EPOC_INI_FILE); |
|
294 return (1); |
|
295 } |
|
296 |
|
297 |
|
298 if( 0 != speed_Mbps ) |
|
299 { |
|
300 sprintf( speed_value, "%dMbps", speed_Mbps); |
|
301 } |
|
302 |
|
303 if ( 0 != replace_in_inifile( ETHER_SPEED_ENTRY, speed_value, FALSE ) ) |
|
304 { |
|
305 printf("Couldn't write speed value to %s file\n", EPOC_INI_FILE); |
|
306 return (1); |
|
307 } |
|
308 |
|
309 //printf("Netcards has written settings to %s.\n\n", EPOC_INI_FILE); |
|
310 free(MAC_value); |
|
311 free(temp2); |
|
312 pcap_freealldevs(adapterlist); |
|
313 |
|
314 return (0); |
|
315 } // main |
|
316 |
|
317 |
|
318 int get_adapter_speed_and_mac(char* adapterName, UINT* speed, unsigned char* mac) |
|
319 { |
|
320 LPADAPTER lpAdapter; |
|
321 int retVal = 0; |
|
322 |
|
323 // |
|
324 // Open the adapter and get the speed and MAC address... |
|
325 // |
|
326 lpAdapter = PacketOpenAdapter(adapterName); |
|
327 |
|
328 if (lpAdapter) |
|
329 { |
|
330 PPACKET_OID_DATA pOidData = malloc(sizeof(PACKET_OID_DATA) + MAX_OID_DATA); |
|
331 |
|
332 // |
|
333 // Get the link speed first. We use this method rather than call |
|
334 // PacketGetNetType() as it works better with PCAP3.1... |
|
335 // |
|
336 pOidData->Oid = OID_GEN_LINK_SPEED; |
|
337 pOidData->Length = MAX_OID_DATA; |
|
338 |
|
339 if (PacketRequest(lpAdapter, FALSE , pOidData)) |
|
340 { |
|
341 *speed = *((UINT*)pOidData->Data) / 10000; // OID is in 100 bps units. |
|
342 } |
|
343 else |
|
344 { |
|
345 *speed = 0; |
|
346 } |
|
347 |
|
348 // |
|
349 // Check the adapter is 802.3 based, cable connected and has a MAC address. |
|
350 // |
|
351 pOidData->Oid = OID_GEN_MEDIA_IN_USE; |
|
352 pOidData->Length = MAX_OID_DATA; |
|
353 |
|
354 if (PacketRequest(lpAdapter, FALSE , pOidData) && |
|
355 *((UINT*)pOidData->Data) == NdisMedium802_3) |
|
356 { |
|
357 pOidData->Oid = OID_GEN_MEDIA_CONNECT_STATUS; |
|
358 pOidData->Length = MAX_OID_DATA; |
|
359 |
|
360 if (PacketRequest(lpAdapter, FALSE , pOidData) && |
|
361 *((UINT*)pOidData->Data) == NdisMediaStateConnected) |
|
362 { |
|
363 pOidData->Oid = OID_802_3_CURRENT_ADDRESS; |
|
364 pOidData->Length = MAX_OID_DATA; |
|
365 |
|
366 if (PacketRequest(lpAdapter, FALSE , pOidData)) |
|
367 { |
|
368 mac[0] = pOidData->Data[0]; |
|
369 mac[1] = pOidData->Data[1]; |
|
370 mac[2] = pOidData->Data[2]; |
|
371 mac[3] = pOidData->Data[3]; |
|
372 mac[4] = pOidData->Data[4]; |
|
373 mac[5] = pOidData->Data[5]; |
|
374 |
|
375 retVal = 1; |
|
376 } |
|
377 } |
|
378 } |
|
379 |
|
380 free(pOidData); |
|
381 |
|
382 PacketCloseAdapter(lpAdapter); |
|
383 } |
|
384 |
|
385 return retVal; |
|
386 } // get_adapter_speed_and_mac |
|
387 |
|
388 |
|
389 int replace_in_inifile(char * entry_str, char* value, BOOL valUnicode) |
|
390 { |
|
391 int err = 0; // 0 - ok, negative sth wrong |
|
392 |
|
393 int replaced = 0; |
|
394 int len = strlen(entry_str); |
|
395 |
|
396 FILE * file; |
|
397 FILE * tmp_file; |
|
398 |
|
399 char* s = malloc(MAX_LINE); |
|
400 char *line = malloc(MAX_LINE); |
|
401 |
|
402 if ( NULL == (tmp_file = fopen(EPOC_INI_FILE_TEMP, "w")) ) |
|
403 { |
|
404 printf( "Could not create '%s'\n", EPOC_INI_FILE_TEMP ); |
|
405 return -1; |
|
406 } |
|
407 |
|
408 if ( NULL == (file = fopen(EPOC_INI_FILE, "r+")) ) |
|
409 { |
|
410 fclose( tmp_file ); |
|
411 remove( EPOC_INI_FILE_TEMP ); |
|
412 printf( "Could not open '%s'\n", EPOC_INI_FILE ); |
|
413 return -1; |
|
414 } |
|
415 |
|
416 rewind(file); |
|
417 |
|
418 |
|
419 while( fgets(line, MAX_LINE, file) != NULL) |
|
420 { |
|
421 if (sscanf( line, "%s", s ) > 0) // to trim blank chars |
|
422 { |
|
423 s[len] = '\0'; |
|
424 if( 0 == strcmp(entry_str, s)) |
|
425 { |
|
426 fprintf(tmp_file, "%s=", entry_str); |
|
427 |
|
428 if( valUnicode ) |
|
429 { |
|
430 fwprintf(tmp_file, L"%s\n", value); |
|
431 } |
|
432 else |
|
433 { |
|
434 fprintf(tmp_file, "%s\n", value); |
|
435 } |
|
436 |
|
437 replaced = 1; |
|
438 } |
|
439 else |
|
440 { |
|
441 if( EOF == fputs(line, tmp_file) ) |
|
442 { |
|
443 err = -1; |
|
444 break; |
|
445 } |
|
446 } |
|
447 } |
|
448 } |
|
449 |
|
450 free(line); |
|
451 free(s); |
|
452 |
|
453 if( (0 == replaced) && (0 == err) ) |
|
454 { |
|
455 // no entry encountered - add new |
|
456 if( 0 != fseek( tmp_file, 0, SEEK_END ) ) |
|
457 { |
|
458 err = -1; |
|
459 } |
|
460 |
|
461 fprintf( tmp_file, "\n%s=", entry_str); |
|
462 if ( valUnicode ) |
|
463 { |
|
464 fwprintf( tmp_file, L"%s\n", value); |
|
465 } |
|
466 else |
|
467 { |
|
468 fprintf( tmp_file, "%s\n", value); |
|
469 } |
|
470 } |
|
471 |
|
472 |
|
473 if ( 0 != fclose(file ) ) |
|
474 { |
|
475 printf( "Could not close %s file\n", EPOC_INI_FILE ); |
|
476 return -1; |
|
477 } |
|
478 |
|
479 if ( 0 != fclose( tmp_file ) ) |
|
480 { |
|
481 printf( "Could not close %s file\n", EPOC_INI_FILE_TEMP ); |
|
482 return -1; |
|
483 } |
|
484 |
|
485 |
|
486 if( remove( EPOC_INI_FILE ) == -1 ) |
|
487 { |
|
488 printf( "Could not overwrite %s file\n", EPOC_INI_FILE ); |
|
489 return -1; |
|
490 } |
|
491 |
|
492 if( rename( EPOC_INI_FILE_TEMP, EPOC_INI_FILE ) != 0 ) |
|
493 { |
|
494 printf( "\nCould not rename '%s' to '%s'\n", EPOC_INI_FILE_TEMP, EPOC_INI_FILE ); |
|
495 return -1; |
|
496 } |
|
497 |
|
498 return 0; |
|
499 } // replace_in_inifile |