os/kernelhwsrv/kerneltest/e32utils/netcards/netcards.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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