sl@0: /* sl@0: * Copyright (c) 1995-2007 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * sl@0: */ sl@0: sl@0: sl@0: /** sl@0: @internalTechnology sl@0: @file sl@0: sl@0: Implementation of the Netcards.exe adapter selection application. sl@0: This version writes settings to an ethernet.ini file only. Those settings sl@0: should be either copied into epoc.ini (EKA2) or extracted into correct setup sl@0: files: ethermac.dat and etherdriver.dat (EKA1) using an appropriate tool. sl@0: */ sl@0: sl@0: /* sl@0: * Desired design of maximum size and alignment. sl@0: * These are implementation specific. sl@0: */ sl@0: #define _SS_MAXSIZE 128 // Maximum size. sl@0: #define _SS_ALIGNSIZE (sizeof(__int64)) // Desired alignment. sl@0: sl@0: /* sl@0: * Definitions used for sockaddr_storage structure paddings design. sl@0: */ sl@0: /** sl@0: * This version of netcards.c has been written to work and run on Windows 2000 sl@0: * and Windows XP. It has been compiled against both WinPCap 4.0. sl@0: * sl@0: * We identify the version of the compiler from the macros set by E32PLAT.pm sl@0: * and if .NET assume that winsock2 will be used (although this is not needed). sl@0: */ sl@0: sl@0: #define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof (short)) sl@0: #define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (short) + _SS_PAD1SIZE \ sl@0: + _SS_ALIGNSIZE)) sl@0: sl@0: struct sockaddr_storage { sl@0: short ss_family; // Address family. sl@0: char __ss_pad1[_SS_PAD1SIZE]; // 6 byte pad, this is to make sl@0: // implementation specific pad up to sl@0: // alignment field that follows explicit sl@0: // in the data structure. sl@0: __int64 __ss_align; // Field to force desired structure. sl@0: char __ss_pad2[_SS_PAD2SIZE]; // 112 byte pad to achieve desired size; sl@0: // _SS_MAXSIZE value minus size of sl@0: // ss_family, __ss_pad1, and sl@0: // __ss_align fields is 112. sl@0: }; sl@0: sl@0: // Forward declare struct _RPC_ASYNC_STATE, to avoid a warning in rpcasync.h sl@0: struct _RPC_ASYNC_STATE; sl@0: sl@0: // include WinPcap sl@0: // The dance with warnings is necessary to avoid warnings such as sl@0: // sl@0: // \MSVC6\VC98\include\qos.h(236) : warning C4201: nonstandard extension used : sl@0: // nameless struct/union sl@0: // sl@0: // when we compile at warning level 4. sl@0: // sl@0: sl@0: #pragma warning(disable:4514) sl@0: #pragma warning(push,3) sl@0: #include "pcap.h" sl@0: #pragma warning(pop) sl@0: sl@0: //other includes sl@0: #include "packet32.h" sl@0: #include "ntddndis.h" sl@0: #include sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: sl@0: #define EPOC_INI_FILE "ethernet.ini" sl@0: sl@0: #define EPOC_INI_FILE_TEMP "__temp__ethernet__.ini" sl@0: sl@0: #define ETHER_NIF_ENTRY "ETHER_NIF" sl@0: #define ETHER_MAC_ENTRY "ETHER_MAC" sl@0: #define ETHER_SPEED_ENTRY "ETHER_SPEED" sl@0: sl@0: #define MAX_VALUE 80 sl@0: #define MAX_LINE 100 sl@0: #define MAX_OID_DATA 256 sl@0: sl@0: #define MAX_ADAPTER_LEN 1024 sl@0: #define MAX_ADAPTERS 10 sl@0: sl@0: #define OID_802_3_CURRENT_ADDRESS 0x01010102 sl@0: sl@0: sl@0: // sl@0: // Global list of supported adapter names. sl@0: // sl@0: char AdapterList[MAX_ADAPTERS][MAX_ADAPTER_LEN]; sl@0: sl@0: sl@0: // sl@0: // Replace or write new 'value' for 'entry' in epoc.ini file sl@0: // returns 0 if ok, negative value if sth wrong sl@0: // sl@0: int replace_in_inifile(char * entry, char* value, BOOL valUnicode ); sl@0: sl@0: sl@0: // sl@0: // Gets the adapter speed and mac address. Returns 0 if no mac is available, sl@0: // otherwise returns non-zero if successful. sl@0: // sl@0: int get_adapter_speed_and_mac(char* adapterName, UINT* speed, unsigned char* mac); sl@0: sl@0: // sl@0: // Main entry point. sl@0: // sl@0: int main(int argc, char* argv[]) sl@0: { sl@0: char err[PCAP_ERRBUF_SIZE + 1]; sl@0: sl@0: sl@0: // string that contains a list of the network adapters sl@0: pcap_if_t *adapterlist, *adapter; sl@0: sl@0: int adapters=0, adapterToUse, i; sl@0: UINT speed_Mbps = 0; sl@0: unsigned char mac[6]; sl@0: sl@0: FILE *inifile; sl@0: sl@0: char speed_value[10]; sl@0: char *MAC_value = malloc( 13*sizeof(char) ); sl@0: char *temp2 = malloc( 13*sizeof(char) ); sl@0: int interfaceArg = 0; sl@0: int MACmode = 0; sl@0: sl@0: if ( argc>1 && argv[1] ) sl@0: { sl@0: interfaceArg = atoi(argv[1])%10; sl@0: MACmode = atoi(argv[1])/10; //used for set ethernet/WLAN MAC address sl@0: } sl@0: //printf("interfaceArg=%d, MACmode=%d\n", interfaceArg, MACmode); sl@0: sl@0: // sl@0: // Obtain the name of the adapters installed on this machine. sl@0: // sl@0: // The result of this function is obtained querying the registry, sl@0: // and therefore the format of the result in Windows NTx is different sl@0: // from the one in Windows 9x. Windows 9x uses the ASCII encoding method sl@0: // to store a string, while Windows NTx uses UNICODE. sl@0: // sl@0: // In addition different versions of PCAP vary this behaviour meaning sl@0: // that the returned data cannot be assumed to be one format or the sl@0: // other - in other words we must check it ourselves. sl@0: // sl@0: printf("\nAdapters installed:\n"); sl@0: sl@0: if(pcap_findalldevs(&adapterlist, err) < 0) sl@0: { sl@0: printf("Error - pcap_findalldevs: %s\n", err); sl@0: return (1); sl@0: } sl@0: for(adapter = adapterlist; adapter; adapter = adapter->next) sl@0: { sl@0: memcpy(AdapterList[adapters], adapter->name, strlen(adapter->name)); sl@0: if(get_adapter_speed_and_mac(AdapterList[adapters], &speed_Mbps, mac)) sl@0: { sl@0: printf("\n%3d - %s\n", adapters+1, AdapterList[adapters]); sl@0: adapters++; sl@0: } sl@0: else sl@0: { sl@0: printf("\nN/A - %s\n",AdapterList[adapters]); sl@0: } sl@0: printf(" %s\n", adapter->description); sl@0: } sl@0: printf("\n"); sl@0: sl@0: if (adapters>1) sl@0: { sl@0: if((interfaceArg>adapters)||(interfaceArg<1) ) sl@0: { sl@0: do sl@0: { sl@0: printf("Select the number of the adapter to use : "); sl@0: scanf("%d",&adapterToUse); sl@0: if (adapterToUse > adapters || adapterToUse < 1) sl@0: { sl@0: printf("\nThe number must be between 1 and %d\n",adapters); sl@0: } sl@0: } while (adapterToUse > adapters || adapterToUse < 1); sl@0: } sl@0: else sl@0: { sl@0: adapterToUse = interfaceArg; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: adapterToUse = adapters; sl@0: } sl@0: sl@0: MAC_value[0] = '\0'; sl@0: temp2[0] = '\0'; sl@0: speed_value[0] = '\0'; sl@0: sl@0: // sl@0: // Open the adapter if available... sl@0: // sl@0: if (adapterToUse > 0 && adapterToUse <= adapters) sl@0: { sl@0: printf("\nUsing adapter %d\n", adapterToUse); sl@0: sl@0: if (get_adapter_speed_and_mac(AdapterList[adapterToUse-1], &speed_Mbps, mac)) sl@0: { sl@0: if (speed_Mbps == 0) sl@0: { sl@0: printf("Could not read Ethernet card's speed\n"); sl@0: } sl@0: sl@0: printf("Physical address read: %02x:%02x:%02x:%02x:%02x:%02x\n", sl@0: mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); sl@0: sl@0: if(MACmode == 0) //ethernet MAC sl@0: { sl@0: mac[0] += 2; // changing address from global to local sl@0: } sl@0: sl@0: for( i=0; i<6; i++ ) sl@0: { sl@0: strcpy( temp2, MAC_value); sl@0: if( mac[i] > 15 ) sl@0: { sl@0: // has 2 hex digits sl@0: sprintf( MAC_value, "%s%x", temp2, mac[i]); sl@0: } sl@0: else sl@0: { sl@0: sprintf( MAC_value, "%s0%x", temp2, mac[i]); sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { sl@0: printf("Problem with opening adapter (packet.lib issue)\n"); sl@0: return (1); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: printf("\nNo supported adapters found\n"); sl@0: } sl@0: sl@0: // sl@0: // Write the settings to the INI file... sl@0: // sl@0: printf("Writing settings to %s.\n\n", EPOC_INI_FILE); sl@0: sl@0: inifile = fopen(EPOC_INI_FILE, "a"); // to create if does exist sl@0: if ( NULL != inifile ) sl@0: { sl@0: fclose(inifile); sl@0: } sl@0: else sl@0: { sl@0: printf("Can't create or access %s.\n\n", EPOC_INI_FILE); sl@0: return (1); sl@0: } sl@0: sl@0: if ( 0 != replace_in_inifile( ETHER_NIF_ENTRY, AdapterList[adapterToUse-1], FALSE ) ) sl@0: { sl@0: printf("Couldn't write adapter name to %s file\n", EPOC_INI_FILE); sl@0: return (1); sl@0: } sl@0: sl@0: sl@0: if ( 0 != replace_in_inifile( ETHER_MAC_ENTRY, MAC_value, FALSE ) ) sl@0: { sl@0: printf("Couldn't write MAC address to %s file\n", EPOC_INI_FILE); sl@0: return (1); sl@0: } sl@0: sl@0: sl@0: if( 0 != speed_Mbps ) sl@0: { sl@0: sprintf( speed_value, "%dMbps", speed_Mbps); sl@0: } sl@0: sl@0: if ( 0 != replace_in_inifile( ETHER_SPEED_ENTRY, speed_value, FALSE ) ) sl@0: { sl@0: printf("Couldn't write speed value to %s file\n", EPOC_INI_FILE); sl@0: return (1); sl@0: } sl@0: sl@0: //printf("Netcards has written settings to %s.\n\n", EPOC_INI_FILE); sl@0: free(MAC_value); sl@0: free(temp2); sl@0: pcap_freealldevs(adapterlist); sl@0: sl@0: return (0); sl@0: } // main sl@0: sl@0: sl@0: int get_adapter_speed_and_mac(char* adapterName, UINT* speed, unsigned char* mac) sl@0: { sl@0: LPADAPTER lpAdapter; sl@0: int retVal = 0; sl@0: sl@0: // sl@0: // Open the adapter and get the speed and MAC address... sl@0: // sl@0: lpAdapter = PacketOpenAdapter(adapterName); sl@0: sl@0: if (lpAdapter) sl@0: { sl@0: PPACKET_OID_DATA pOidData = malloc(sizeof(PACKET_OID_DATA) + MAX_OID_DATA); sl@0: sl@0: // sl@0: // Get the link speed first. We use this method rather than call sl@0: // PacketGetNetType() as it works better with PCAP3.1... sl@0: // sl@0: pOidData->Oid = OID_GEN_LINK_SPEED; sl@0: pOidData->Length = MAX_OID_DATA; sl@0: sl@0: if (PacketRequest(lpAdapter, FALSE , pOidData)) sl@0: { sl@0: *speed = *((UINT*)pOidData->Data) / 10000; // OID is in 100 bps units. sl@0: } sl@0: else sl@0: { sl@0: *speed = 0; sl@0: } sl@0: sl@0: // sl@0: // Check the adapter is 802.3 based, cable connected and has a MAC address. sl@0: // sl@0: pOidData->Oid = OID_GEN_MEDIA_IN_USE; sl@0: pOidData->Length = MAX_OID_DATA; sl@0: sl@0: if (PacketRequest(lpAdapter, FALSE , pOidData) && sl@0: *((UINT*)pOidData->Data) == NdisMedium802_3) sl@0: { sl@0: pOidData->Oid = OID_GEN_MEDIA_CONNECT_STATUS; sl@0: pOidData->Length = MAX_OID_DATA; sl@0: sl@0: if (PacketRequest(lpAdapter, FALSE , pOidData) && sl@0: *((UINT*)pOidData->Data) == NdisMediaStateConnected) sl@0: { sl@0: pOidData->Oid = OID_802_3_CURRENT_ADDRESS; sl@0: pOidData->Length = MAX_OID_DATA; sl@0: sl@0: if (PacketRequest(lpAdapter, FALSE , pOidData)) sl@0: { sl@0: mac[0] = pOidData->Data[0]; sl@0: mac[1] = pOidData->Data[1]; sl@0: mac[2] = pOidData->Data[2]; sl@0: mac[3] = pOidData->Data[3]; sl@0: mac[4] = pOidData->Data[4]; sl@0: mac[5] = pOidData->Data[5]; sl@0: sl@0: retVal = 1; sl@0: } sl@0: } sl@0: } sl@0: sl@0: free(pOidData); sl@0: sl@0: PacketCloseAdapter(lpAdapter); sl@0: } sl@0: sl@0: return retVal; sl@0: } // get_adapter_speed_and_mac sl@0: sl@0: sl@0: int replace_in_inifile(char * entry_str, char* value, BOOL valUnicode) sl@0: { sl@0: int err = 0; // 0 - ok, negative sth wrong sl@0: sl@0: int replaced = 0; sl@0: int len = strlen(entry_str); sl@0: sl@0: FILE * file; sl@0: FILE * tmp_file; sl@0: sl@0: char* s = malloc(MAX_LINE); sl@0: char *line = malloc(MAX_LINE); sl@0: sl@0: if ( NULL == (tmp_file = fopen(EPOC_INI_FILE_TEMP, "w")) ) sl@0: { sl@0: printf( "Could not create '%s'\n", EPOC_INI_FILE_TEMP ); sl@0: return -1; sl@0: } sl@0: sl@0: if ( NULL == (file = fopen(EPOC_INI_FILE, "r+")) ) sl@0: { sl@0: fclose( tmp_file ); sl@0: remove( EPOC_INI_FILE_TEMP ); sl@0: printf( "Could not open '%s'\n", EPOC_INI_FILE ); sl@0: return -1; sl@0: } sl@0: sl@0: rewind(file); sl@0: sl@0: sl@0: while( fgets(line, MAX_LINE, file) != NULL) sl@0: { sl@0: if (sscanf( line, "%s", s ) > 0) // to trim blank chars sl@0: { sl@0: s[len] = '\0'; sl@0: if( 0 == strcmp(entry_str, s)) sl@0: { sl@0: fprintf(tmp_file, "%s=", entry_str); sl@0: sl@0: if( valUnicode ) sl@0: { sl@0: fwprintf(tmp_file, L"%s\n", value); sl@0: } sl@0: else sl@0: { sl@0: fprintf(tmp_file, "%s\n", value); sl@0: } sl@0: sl@0: replaced = 1; sl@0: } sl@0: else sl@0: { sl@0: if( EOF == fputs(line, tmp_file) ) sl@0: { sl@0: err = -1; sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: free(line); sl@0: free(s); sl@0: sl@0: if( (0 == replaced) && (0 == err) ) sl@0: { sl@0: // no entry encountered - add new sl@0: if( 0 != fseek( tmp_file, 0, SEEK_END ) ) sl@0: { sl@0: err = -1; sl@0: } sl@0: sl@0: fprintf( tmp_file, "\n%s=", entry_str); sl@0: if ( valUnicode ) sl@0: { sl@0: fwprintf( tmp_file, L"%s\n", value); sl@0: } sl@0: else sl@0: { sl@0: fprintf( tmp_file, "%s\n", value); sl@0: } sl@0: } sl@0: sl@0: sl@0: if ( 0 != fclose(file ) ) sl@0: { sl@0: printf( "Could not close %s file\n", EPOC_INI_FILE ); sl@0: return -1; sl@0: } sl@0: sl@0: if ( 0 != fclose( tmp_file ) ) sl@0: { sl@0: printf( "Could not close %s file\n", EPOC_INI_FILE_TEMP ); sl@0: return -1; sl@0: } sl@0: sl@0: sl@0: if( remove( EPOC_INI_FILE ) == -1 ) sl@0: { sl@0: printf( "Could not overwrite %s file\n", EPOC_INI_FILE ); sl@0: return -1; sl@0: } sl@0: sl@0: if( rename( EPOC_INI_FILE_TEMP, EPOC_INI_FILE ) != 0 ) sl@0: { sl@0: printf( "\nCould not rename '%s' to '%s'\n", EPOC_INI_FILE_TEMP, EPOC_INI_FILE ); sl@0: return -1; sl@0: } sl@0: sl@0: return 0; sl@0: } // replace_in_inifile