Files
epics-base/modules/libcom/src/misc/aToIPAddr.c
2020-08-14 10:04:56 -07:00

198 lines
5.0 KiB
C

/*************************************************************************\
* Copyright (c) 2013 LANS LLC, as Operator of
* Los Alamos National Laboratory.
* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* SPDX-License-Identifier: EPICS
* 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()
*
* author: Jeff Hill
*/
#include <stdio.h>
#include <string.h>
#include "epicsTypes.h"
#include "osiSock.h"
#ifndef NELEMENTS
#define NELEMENTS(A) (sizeof(A)/sizeof(A[0]))
#endif /*NELEMENTS*/
/*
* addrArrayToUL ()
*/
static int addrArrayToUL ( const unsigned *pAddr,
unsigned nElements, struct in_addr *pIpAddr )
{
unsigned i;
epicsUInt32 addr = 0ul;
for ( i=0u; i < nElements; i++ ) {
if ( pAddr[i] > 0xff ) {
return -1;
}
addr <<= 8;
addr |= ( epicsUInt32 ) pAddr[i];
}
pIpAddr->s_addr = htonl ( addr );
return 0;
}
/*
* 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 port,
struct sockaddr_in *pIP )
{
if ( port > 0xffff ) {
return -1;
}
{
epicsUInt16 port_16 = (epicsUInt16) port;
memset (pIP, '\0', sizeof(*pIP));
pIP->sin_family = AF_INET;
pIP->sin_port = htons(port_16);
pIP->sin_addr = ipAddr;
}
return 0;
}
/*
* rational replacement for inet_addr()
* which allows the limited broadcast address
* 255.255.255.255, allows the user
* to specify a port number, and allows also a
* named host to be specified.
*
* Sets the port number to "defaultPort" only if
* "pAddrString" does not contain an address of the form
* "n.n.n.n:p or host:p"
*/
LIBCOM_API int epicsStdCall
aToIPAddr( const char *pAddrString, unsigned short defaultPort,
struct sockaddr_in *pIP )
{
int status;
unsigned addr[4];
unsigned long rawAddr;
/*
* !! change n elements here requires change in format below !!
*/
char hostName[512];
char dummy[8];
unsigned port;
struct in_addr ina;
if ( pAddrString == NULL ) {
return -1;
}
/*
* dotted ip addresses
*/
status = sscanf ( pAddrString, " %u . %u . %u . %u %7s ",
addr, addr+1u, addr+2u, addr+3u, dummy );
if ( status == 4 ) {
if ( addrArrayToUL ( addr, NELEMENTS ( addr ), & ina ) < 0 ) {
return -1;
}
port = defaultPort;
return initIPAddr ( ina, port, pIP );
}
/*
* dotted ip addresses and port
*/
status = sscanf ( pAddrString, " %u . %u . %u . %u : %u %7s",
addr, addr+1u, addr+2u, addr+3u, &port, dummy );
if ( status >= 5 ) {
if ( status > 5 ) {
/*
* valid at the start but detritus on the end
*/
return -1;
}
if ( addrArrayToUL ( addr, NELEMENTS ( addr ), &ina ) < 0 ) {
return -1;
}
return initIPAddr ( ina, port, pIP );
}
/*
* IP address as a raw number
*/
status = sscanf ( pAddrString, " %lu %7s ", &rawAddr, dummy );
if ( status == 1 ) {
if ( rawAddr > 0xffffffff ) {
return -1;
}
port = defaultPort;
{
epicsUInt32 rawAddr_32 = ( epicsUInt32 ) rawAddr;
ina.s_addr = htonl ( rawAddr_32 );
return initIPAddr ( ina, port, pIP );
}
}
/*
* IP address as a raw number, and port
*/
status = sscanf ( pAddrString, " %lu : %u %7s ", &rawAddr, &port, dummy );
if ( status >= 2 ) {
if ( status > 2 ) {
/*
* valid at the start but detritus on the end
*/
return -1;
}
if ( rawAddr > 0xffffffff ) {
return -1;
}
{
epicsUInt32 rawAddr_32 = ( epicsUInt32 ) rawAddr;
ina.s_addr = htonl ( rawAddr_32 );
return initIPAddr ( ina, port, pIP );
}
}
/*
* host name string
*/
status = sscanf ( pAddrString, " %511[^:] %s ", hostName, dummy );
if ( status == 1 ) {
port = defaultPort;
status = hostToIPAddr ( hostName, &ina );
if ( status == 0 ) {
return initIPAddr ( ina, port, pIP );
}
}
/*
* host name string, and port
*/
status = sscanf ( pAddrString, " %511[^:] : %u %s ", hostName,
&port, dummy );
if ( status >= 2 ) {
if ( status > 2 ) {
/*
* valid at the start but detritus on the end
*/
return -1;
}
status = hostToIPAddr ( hostName, &ina );
if ( status == 0 ) {
return initIPAddr ( ina, port, pIP );
}
}
return -1;
}