diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index a9698ec90..80c2a76e5 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -13,6 +13,13 @@ +

Improvements to aToIPAddr()

+ +

The libCom routine aToIPAddr() and the vxWorks implementation of the +associated hostToIPAddr() function have been modified to be able to look up +hostnames that begin with one or more digits. The epicsSockResolveTest program +was added to check this functionality.

+

Added osdFindSymbol for Windows

Dirk Zimoch implemented the epicsLoadLibrary(), epicsLoadError() and diff --git a/src/libCom/misc/aToIPAddr.c b/src/libCom/misc/aToIPAddr.c index c5d53bc30..04809bffe 100644 --- a/src/libCom/misc/aToIPAddr.c +++ b/src/libCom/misc/aToIPAddr.c @@ -1,11 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* * rational replacement for inet_addr() @@ -13,49 +12,25 @@ * author: Jeff Hill */ #include -#include -#include #include #define epicsExportSharedSymbols #include "osiSock.h" - -#ifndef NELEMENTS -#define NELEMENTS(A) (sizeof(A)/sizeof(A[0])) -#endif /*NELEMENTS*/ - -/* - * addrArrayToUL () - */ -static int addrArrayToUL (const unsigned short *pAddr, unsigned nElements, struct in_addr *pIpAddr) -{ - unsigned i; - unsigned long addr = 0ul; - - for ( i=0u; i < nElements; i++ ) { - if ( pAddr[i] > 0xff ) { - return -1; - } - addr <<= 8; - addr |= pAddr[i]; - } - pIpAddr->s_addr = htonl ( addr ); - - return 0; -} +#include "epicsStdlib.h" /* * initIPAddr() * !! ipAddr should be passed in in network byte order !! * !! port is passed in in host byte order !! */ -static int initIPAddr (struct in_addr ipAddr, unsigned short port, struct sockaddr_in *pIP) +static int initIPAddr (struct in_addr ipAddr, unsigned short port, + struct sockaddr_in *pIP) { - memset (pIP, '\0', sizeof(*pIP)); - pIP->sin_family = AF_INET; - pIP->sin_port = htons(port); - pIP->sin_addr = ipAddr; - return 0; + memset(pIP, '\0', sizeof(*pIP)); + pIP->sin_family = AF_INET; + pIP->sin_port = htons(port); + pIP->sin_addr = ipAddr; + return 0; } /* @@ -69,68 +44,46 @@ static int initIPAddr (struct in_addr ipAddr, unsigned short port, struct sockad * "pAddrString" does not contain an address of the form * "n.n.n.n:p" */ -epicsShareFunc int epicsShareAPI - aToIPAddr(const char *pAddrString, unsigned short defaultPort, struct sockaddr_in *pIP) +epicsShareFunc int epicsShareAPI +aToIPAddr(const char *pAddrString, unsigned short defaultPort, + struct sockaddr_in *pIP) { - int status; - unsigned short addr[4]; - unsigned long rawAddr; - char hostName[512]; /* !! change n elements here requires change in format below !! */ - unsigned short port; - struct in_addr ina; + int status; + char hostName[512]; /* !! change n elements here requires change in format below !! */ + char *endp; + unsigned int port; + unsigned long numaddr; + struct in_addr ina; - /* - * dotted ip addresses - */ - status = sscanf (pAddrString, " %hu.%hu.%hu.%hu:%hu", - addr, addr+1u, addr+2u, addr+3u, &port); - if (status>0) { - if (status>=4) { - if ( addrArrayToUL ( addr, NELEMENTS ( addr ), &ina ) < 0 ) { - return -1; - } - if (status==4) { - port = defaultPort; - } - return initIPAddr (ina, port, pIP); - } - else { - return -1; - } - } - - /* - * IP address as a raw number - */ - status = sscanf ( pAddrString, " %lu:%hu", &rawAddr, &port ); - if (status>=1) { - if ( rawAddr > 0xffffffff ) { - return -1; - } - if ( status == 1 ) { - port = defaultPort; - } - ina.s_addr = htonl ( rawAddr ); - return initIPAddr ( ina, port, pIP ); - } - - /* - * check for a valid host name before giving up - */ - status = sscanf ( pAddrString, " %511[^:]:%hu", hostName, &port ); - if ( status >= 1 ) { - if ( status == 1 ) { - port = defaultPort; - } - status = hostToIPAddr ( hostName, &ina ); - if ( status == 0 ) { - return initIPAddr ( ina, port, pIP ); - } - else { - return -1; - } - } - else { + /* + * Scan for a port number + */ + status = sscanf( pAddrString, " %511[^:]:%u", hostName, &port ); + if ( status == 0 ) { return -1; } + if ( status == 1 ) { + port = defaultPort; + } + else if (status == 2 && port > 65535) { + return -1; + } + + /* + * Look for a valid host name or dotted quad + */ + status = hostToIPAddr( hostName, &ina ); + if ( status == 0 ) { + return initIPAddr( ina, port, pIP ); + } + + /* + * Try the IP address as a decimal integer + */ + numaddr = strtoul( hostName, &endp, 10 ); + if (*endp) + return -1; + + ina.s_addr = htonl( numaddr ); + return initIPAddr( ina, port, pIP ); } diff --git a/src/libCom/osi/os/vxWorks/osdSock.c b/src/libCom/osi/os/vxWorks/osdSock.c index dd6bab973..13798803b 100644 --- a/src/libCom/osi/os/vxWorks/osdSock.c +++ b/src/libCom/osi/os/vxWorks/osdSock.c @@ -27,7 +27,7 @@ int osiSockAttach() { - return 1; + return 1; } void osiSockRelease() @@ -112,27 +112,25 @@ epicsShareFunc unsigned epicsShareAPI ipAddrToHostName /* * hostToIPAddr () */ -epicsShareFunc int epicsShareAPI hostToIPAddr - (const char *pHostName, struct in_addr *pIPA) +epicsShareFunc int epicsShareAPI +hostToIPAddr(const char *pHostName, struct in_addr *pIPA) { - int addr; + int addr; - addr = hostGetByName ((char *)pHostName); - if (addr==ERROR) { - addr = inet_addr ((char *)pHostName); - if (addr==ERROR) { - /* - * return indicating an error - */ - return -1; - } + addr = hostGetByName((char *)pHostName); + if (addr != ERROR) { + pIPA->s_addr = (unsigned long) addr; + } + else if (inet_aton((char *)pHostName, pIPA) == ERROR) { + /* + * return indicating an error + */ + return -1; } - pIPA->s_addr = (unsigned long) addr; - - /* - * success - */ - return 0; + /* + * success + */ + return 0; } diff --git a/src/libCom/test/Makefile b/src/libCom/test/Makefile index 9bf92f528..ef89f3875 100644 --- a/src/libCom/test/Makefile +++ b/src/libCom/test/Makefile @@ -47,6 +47,11 @@ epicsStdioTest_SRCS += epicsStdioTest.c testHarness_SRCS += epicsStdioTest.c TESTS += epicsStdioTest +TESTPROD_HOST += epicsSockResolveTest +epicsSockResolveTest_SRCS += epicsSockResolveTest.c +testHarness_SRCS += epicsSockResolveTest.c +TESTS += epicsSockResolveTest + TESTPROD_HOST += epicsStringTest epicsStringTest_SRCS += epicsStringTest.c testHarness_SRCS += epicsStringTest.c diff --git a/src/libCom/test/epicsRunLibComTests.c b/src/libCom/test/epicsRunLibComTests.c index 80ddbf3b3..7a6da1e66 100644 --- a/src/libCom/test/epicsRunLibComTests.c +++ b/src/libCom/test/epicsRunLibComTests.c @@ -38,6 +38,7 @@ int macEnvExpandTest(void); int ringPointerTest(void); int ringBytesTest(void); int blockingSockTest(void); +int epicsSockResolveTest(void); int taskwdTest(void); int epicsExitTest(void); @@ -94,6 +95,8 @@ void epicsRunLibComTests(void) runTest(ringBytesTest); runTest(blockingSockTest); + + runTest(epicsSockResolveTest); runTest(taskwdTest); diff --git a/src/libCom/test/epicsSockResolveTest.c b/src/libCom/test/epicsSockResolveTest.c new file mode 100644 index 000000000..166a29b90 --- /dev/null +++ b/src/libCom/test/epicsSockResolveTest.c @@ -0,0 +1,92 @@ +/*************************************************************************\ +* Copyright (c) 2012 Brookhaven Science Associates as Operator of +* Brookhaven National Lab. +* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. +\*************************************************************************/ + +#include "dbDefs.h" +#include "osiSock.h" + +#include "epicsUnitTest.h" +#include "testMain.h" + +#define DEFAULT_PORT 4000 + +typedef struct { + const char *input; + unsigned long IP; + unsigned short port; +} testData; + +static testData okdata[] = { + {"127.0.0.1", 0x7f000001, DEFAULT_PORT}, + {"127.0.0.1:42", 0x7f000001, 42}, + {"localhost", 0x7f000001, DEFAULT_PORT}, + {"localhost:42", 0x7f000001, 42}, + {"2424", 2424, DEFAULT_PORT}, + {"2424:42", 2424, 42}, + {"255.255.255.255", 0xffffffff, DEFAULT_PORT}, + {"255.255.255.255:65535", 0xffffffff, 65535}, +}; + +static const char * baddata[] = { + "127.0.0.hi", + "127.0.0.hi:42", + "16invalidhostname", + "16invalidhostname:42", + "256.255.255.255", + "255.256.255.255", + "255.255.256.255", + "255.255.255.256", + "255.255.255.255:65536", +}; + +MAIN(epicsSockResolveTest) +{ + int i; + + testPlan(3*NELEMENTS(okdata) + NELEMENTS(baddata)); + + { + struct in_addr addr; + + if (hostToIPAddr("obviously.invalid.host", &addr) == 0) { + testAbort("hostToIPAddr() is broken, testing not possible"); + } + } + + testDiag("Tests of aToIPAddr"); + + for (i=0; i %d", + okdata[i].input, DEFAULT_PORT, ret); + if (ret) { + testSkip(2, " aToIPAddr() failed"); + } + else { + testOk(addr.sin_addr.s_addr == htonl(okdata[i].IP), " IP correct"); + testOk(addr.sin_port == htons(okdata[i].port), " Port correct"); + } + } + + for (i=0; i %d", + baddata[i], DEFAULT_PORT, ret); + if (ret==0) { + testDiag(" IP=0x%lx, port=%d", + (unsigned long) ntohl(addr.sin_addr.s_addr), + ntohs(addr.sin_port)); + } + } + + return testDone(); +}