diff --git a/README.md b/README.md index 61634d00e4..7e9acb6900 100644 --- a/README.md +++ b/README.md @@ -79,9 +79,9 @@ Compile for Windows XP/7/8: 2. Open Visual Studio solution in bin/win32 3. For invoking opener type in command line: - OpENer ipaddress subnetmask gateway domainname hostaddress macaddress + OpENer interface_index - e.g. OpENer 192.168.0.2 255.255.255.0 192.168.0.1 test.com testdevice 00 15 C5 BF D0 87 + e.g. OpENer 3 Directory structure: -------------------- diff --git a/source/src/ports/WIN32/CMakeLists.txt b/source/src/ports/WIN32/CMakeLists.txt index f56f44c57a..097b39bbe7 100755 --- a/source/src/ports/WIN32/CMakeLists.txt +++ b/source/src/ports/WIN32/CMakeLists.txt @@ -18,4 +18,4 @@ add_library( ${PLATFORMLIBNAME} ${PLATFORM_SPEC_SRC}) add_executable(OpENer main.c) -target_link_libraries( OpENer PLATFORM_GENERIC ${PLATFORMLIBNAME} CIP SAMPLE_APP ENET_ENCAP ws2_32 ${OpENer_CIP_OBJECTS} ) +target_link_libraries( OpENer PLATFORM_GENERIC ${PLATFORMLIBNAME} CIP Utils SAMPLE_APP ENET_ENCAP ws2_32 ${OpENer_CIP_OBJECTS} ) diff --git a/source/src/ports/WIN32/main.c b/source/src/ports/WIN32/main.c index 3ce02ac77d..f07e69c439 100644 --- a/source/src/ports/WIN32/main.c +++ b/source/src/ports/WIN32/main.c @@ -31,30 +31,24 @@ int g_end_stack = 0; /******************************************************************************/ int main(int argc, char *arg[]) { - EipUint8 acMyMACAddress[6]; EipUint16 nUniqueConnectionID; - if (argc != 12) { + if (argc != 2) { printf("Wrong number of command line parameters!\n"); printf("The correct command line parameters are:\n"); printf( - "./OpENer ipaddress subnetmask gateway domainname hostaddress macaddress\n"); + "./OpENer index\n"); printf( - " e.g. ./OpENer 192.168.0.2 255.255.255.0 192.168.0.1 test.com testdevice 00 15 C5 BF D0 87\n"); + " e.g. ./OpENer index\n"); exit(0); } else { + DoublyLinkedListInitialize(&connection_list, + CipConnectionObjectListArrayAllocator, + CipConnectionObjectListArrayFree); /* fetch Internet address info from the platform */ - ConfigureNetworkInterface(arg[1], arg[2], arg[3]); - ConfigureDomainName(arg[4]); - ConfigureHostName(arg[5]); - - acMyMACAddress[0] = (EipUint8) strtoul(arg[6], NULL, 16); - acMyMACAddress[1] = (EipUint8) strtoul(arg[7], NULL, 16); - acMyMACAddress[2] = (EipUint8) strtoul(arg[8], NULL, 16); - acMyMACAddress[3] = (EipUint8) strtoul(arg[9], NULL, 16); - acMyMACAddress[4] = (EipUint8) strtoul(arg[10], NULL, 16); - acMyMACAddress[5] = (EipUint8) strtoul(arg[11], NULL, 16); - ConfigureMacAddress(acMyMACAddress); + ConfigureDomainName(atoi(arg[1])); + ConfigureHostName(atoi(arg[1])); + ConfigureIpMacAddress(atoi(arg[1])); } /*for a real device the serial number should be unique per device */ diff --git a/source/src/ports/WIN32/networkconfig.c b/source/src/ports/WIN32/networkconfig.c index dc832de31a..a7ba8001c4 100644 --- a/source/src/ports/WIN32/networkconfig.c +++ b/source/src/ports/WIN32/networkconfig.c @@ -3,7 +3,7 @@ * All rights reserved. * ******************************************************************************/ - +#define WIN32_LEAN_AND_MEAN #include "ciptcpipinterface.h" #include "networkconfig.h" #include "cipcommon.h" @@ -11,52 +11,216 @@ #include "opener_api.h" #include "trace.h" #include +#include +#include +#include +#include +#include +#include +#include -EipStatus ConfigureNetworkInterface(const char *ip_address, - const char *subnet_mask, - const char *gateway) { +#define WORKING_BUFFER_SIZE 15000 +#define MAX_TRIES 3 - interface_configuration_.ip_address = inet_addr(ip_address); - interface_configuration_.network_mask = inet_addr(subnet_mask); - interface_configuration_.gateway = inet_addr(gateway); +#pragma comment(lib, "IPHLPAPI.lib") +#pragma comment(lib, "Ws2_32.lib") - /* calculate the CIP multicast address. The multicast address is calculated, not input*/ - EipUint32 host_id = ntohl(interface_configuration_.ip_address) - & ~ntohl(interface_configuration_.network_mask); /* see CIP spec 3-5.3 for multicast address algorithm*/ - host_id -= 1; - host_id &= 0x3ff; - g_multicast_configuration.starting_multicast_address = htonl( - ntohl( inet_addr("239.192.1.0") ) + (host_id << 5) ); +void ConfigureIpMacAddress(const CipUint interface_index) { + + PIP_ADAPTER_INFO pAdapterInfo; + PIP_ADAPTER_INFO pAdapter = NULL; + CipDword dwRetVal = 0; + + CipUdint ulOutBufLen = sizeof(IP_ADAPTER_INFO); + pAdapterInfo = (IP_ADAPTER_INFO *)CipCalloc(1,sizeof(IP_ADAPTER_INFO)); + if (pAdapterInfo == NULL) { + printf("Error allocating memory needed to call GetAdaptersinfo\n"); + return 1; + } + // Make an initial call to GetAdaptersInfo to get + // the necessary size into the ulOutBufLen variable + if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { + CipFree(pAdapterInfo); + pAdapterInfo = (IP_ADAPTER_INFO *)CipCalloc(ulOutBufLen,sizeof(CipUdint)); + if (pAdapterInfo == NULL) { + printf("Error allocating memory needed to call GetAdaptersinfo\n"); + return 1; + } + } - return kEipStatusOk; -} -void ConfigureMacAddress(const EipUint8 *const mac_address) { - memcpy( &g_ethernet_link.physical_address, mac_address, - sizeof(g_ethernet_link.physical_address) ); + if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { + pAdapter = pAdapterInfo; + while (pAdapter) { + if (pAdapter->Index == interface_index) { + for (int i = 0; i < 6; i++) { + memcpy(&g_ethernet_link.physical_address, pAdapter->Address, + 6*sizeof(CipUsint)); + } + interface_configuration_.ip_address = inet_addr(pAdapter->IpAddressList.IpAddress.String); + interface_configuration_.network_mask = inet_addr(pAdapter->IpAddressList.IpMask.String); + interface_configuration_.gateway = inet_addr(pAdapter->GatewayList.IpAddress.String); + + CipUdint host_id = ntohl(interface_configuration_.ip_address) + & ~ntohl(interface_configuration_.network_mask); /* see CIP spec 3-5.3 for multicast address algorithm*/ + host_id -= 1; + host_id &= 0x3ff; + + g_multicast_configuration.starting_multicast_address = htonl( + ntohl(inet_addr("239.192.1.0")) + (host_id << 5)); + } + pAdapter = pAdapter->Next; + } + } + else { + printf("GetAdaptersInfo failed with error: %d\n", dwRetVal); + + } + CipFree(pAdapterInfo); + CipFree(pAdapter); } -void ConfigureDomainName(const char *domain_name) { - if (NULL != interface_configuration_.domain_name.string) { - /* if the string is already set to a value we have to free the resources - * before we can set the new value in order to avoid memory leaks. - */ - CipFree(interface_configuration_.domain_name.string); - } - interface_configuration_.domain_name.length = strlen(domain_name); - if (interface_configuration_.domain_name.length) { - interface_configuration_.domain_name.string = (EipByte *) CipCalloc( - interface_configuration_.domain_name.length + 1, sizeof(EipInt8) ); - strcpy(interface_configuration_.domain_name.string, domain_name); - } else { - interface_configuration_.domain_name.string = NULL; - } +void ConfigureDomainName(const CipUint interface_index) { + + CipDword dwSize = 0; + int i = 0; + // Set the flags to pass to GetAdaptersAddresses + CipUdint flags = GAA_FLAG_INCLUDE_PREFIX; + CipDword dwRetVal = 0; + // default to unspecified address family (both) + CipUdint family = AF_UNSPEC; + + LPVOID lpMsgBuf = NULL; + + PIP_ADAPTER_ADDRESSES pAddresses = NULL; + PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; + IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL; + CipUdint outBufLen = 0; + CipUdint tries = 0; + + family = AF_INET; + // Allocate a 15 KB buffer to start with. + outBufLen = WORKING_BUFFER_SIZE; + + do { + + pAddresses = (IP_ADAPTER_ADDRESSES *)CipCalloc(1,outBufLen); + if (pAddresses == NULL) { + printf + ("Memory allocation failed for IP_ADAPTER_ADDRESSES struct\n"); + exit(1); + } + + dwRetVal = + GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen); + + if (dwRetVal == ERROR_BUFFER_OVERFLOW) { + CipFree(pAddresses); + pAddresses = NULL; + } + else { + break; + } + + tries++; + + } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (tries < MAX_TRIES)); + + if (dwRetVal == NO_ERROR) { + // If successful, output some information from the data we received + pCurrAddresses = pAddresses; + while (pCurrAddresses) { + if (interface_index == pCurrAddresses->IfIndex) { + pDnServer = pCurrAddresses->FirstDnsServerAddress; + if (pDnServer) { + for (i = 0; pDnServer != NULL; i++) + pDnServer = pDnServer->Next; + } + + char pStringBuf[INET_ADDRSTRLEN]; + if (i != 0) { + + if (NULL != interface_configuration_.domain_name.string) { + /* if the string is already set to a value we have to free the resources + * before we can set the new value in order to avoid memory leaks. + */ + CipFree(interface_configuration_.domain_name.string); + } + interface_configuration_.domain_name.length = strlen(pCurrAddresses->DnsSuffix); + if (interface_configuration_.domain_name.length) { + interface_configuration_.domain_name.string = (CipByte *)CipCalloc( + interface_configuration_.domain_name.length + 1, sizeof(CipUsint)); + strcpy(interface_configuration_.domain_name.string, pCurrAddresses->DnsSuffix); + } + else { + interface_configuration_.domain_name.string = NULL; + } + + InetNtop(AF_INET, pCurrAddresses->FirstDnsServerAddress->Address.lpSockaddr->sa_data + 2, interface_configuration_.name_server, sizeof(interface_configuration_.name_server)); + InetNtop(AF_INET, pCurrAddresses->FirstDnsServerAddress->Next->Address.lpSockaddr->sa_data + 2, interface_configuration_.name_server_2, sizeof(interface_configuration_.name_server_2)); + } + else interface_configuration_.domain_name.length = 0; + + } + pCurrAddresses = pCurrAddresses->Next; + } + } + else { + OPENER_TRACE_INFO("Call to GetAdaptersAddresses failed with error: %d\n", + dwRetVal); + if (dwRetVal == ERROR_NO_DATA) + OPENER_TRACE_INFO("\tNo addresses were found for the requested parameters\n"); + else { + + if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + // Default language + (LPTSTR)& lpMsgBuf, 0, NULL)) { + OPENER_TRACE_INFO("\tError: %s", lpMsgBuf); + CipFree(lpMsgBuf); + if (pAddresses) + CipFree(pAddresses); + exit(1); + } + } + } + + if (pAddresses) { + CipFree(pAddresses); + } + + } -void ConfigureHostName(const char *const RESTRICT hostname) { - if (NULL != hostname_.string) { +void ConfigureHostName(const CipUint interface_index) { + CipWord wVersionRequested; + WSADATA wsaData; + int err; + + /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */ + wVersionRequested = MAKEWORD(2, 2); + + err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) { + /* Tell the user that we could not find a usable */ + /* Winsock DLL. */ + printf("WSAStartup failed with error: %d\n", err); + return 1; + } + + char hostname[256] = ""; + int status = 0; + status = gethostname(hostname, sizeof(hostname)); + + WSACleanup(); + + + + + if (NULL != hostname_.string) { /* if the string is already set to a value we have to free the resources * before we can set the new value in order to avoid memory leaks. */ @@ -64,8 +228,8 @@ void ConfigureHostName(const char *const RESTRICT hostname) { } hostname_.length = strlen(hostname); if (hostname_.length) { - hostname_.string = (EipByte *) CipCalloc( hostname_.length + 1, - sizeof(EipByte) ); + hostname_.string = (CipByte *) CipCalloc( hostname_.length + 1, + sizeof(CipByte) ); strcpy(hostname_.string, hostname); } else { hostname_.string = NULL; diff --git a/source/src/ports/WIN32/networkhandler.c b/source/src/ports/WIN32/networkhandler.c index d8001dd7f5..8e5128584f 100644 --- a/source/src/ports/WIN32/networkhandler.c +++ b/source/src/ports/WIN32/networkhandler.c @@ -45,8 +45,8 @@ int SetSocketToNonBlocking(int socket_handle) { return ioctlsocket(socket_handle, FIONBIO, &iMode); } -void SetQosOnSocket(int socket, +int SetQosOnSocket(int socket, CipUsint qos_value) { CipUsint set_tos = qos_value; - setsockopt(socket, IPPROTO_IP, IP_TOS, &set_tos, sizeof(set_tos) ); + return setsockopt(socket, IPPROTO_IP, IP_TOS, &set_tos, sizeof(set_tos) ); } diff --git a/source/src/ports/WIN32/networkhandler.h b/source/src/ports/WIN32/networkhandler.h index ab70717a6c..ac238f9bf9 100644 --- a/source/src/ports/WIN32/networkhandler.h +++ b/source/src/ports/WIN32/networkhandler.h @@ -34,7 +34,7 @@ MicroSeconds GetMicroSeconds(void); */ MilliSeconds GetMilliSeconds(void); -void SetQosOnSocket(int socket, +int SetQosOnSocket(int socket, CipUsint qos_value); #endif /*NETWORKHANDLER_H_*/