libCom: Back-ported aToIPAddr fix from 3.15 branch.

Cherry-picked 3.15 revno 12398 with some changes.
This commit is contained in:
Andrew Johnson
2013-06-07 17:03:55 -05:00
parent 93449dccb8
commit ef5d88d3e5
6 changed files with 173 additions and 115 deletions

View File

@@ -13,6 +13,13 @@
<!-- Insert new items immediately below here ... -->
<h3>Improvements to aToIPAddr()</h3>
<p>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.</p>
<h4>Added osdFindSymbol for Windows</h4>
<p>Dirk Zimoch implemented the epicsLoadLibrary(), epicsLoadError() and

View File

@@ -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 <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#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 );
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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<NELEMENTS(okdata); i++) {
struct sockaddr_in addr;
int ret;
ret = aToIPAddr(okdata[i].input, DEFAULT_PORT, &addr);
testOk(ret==0, "aToIPAddr(\"%s\", %u) -> %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<NELEMENTS(baddata); i++) {
struct sockaddr_in addr;
int ret;
ret = aToIPAddr(baddata[i], DEFAULT_PORT, &addr);
testOk(ret!=0, "aToIPAddr(\"%s\", %u) -> %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();
}