- use dig before gethostbyname to resolve host names
This commit is contained in:
119
ascon.c
119
ascon.c
@ -17,75 +17,62 @@
|
||||
static double lastClose = 0; /* time of last close operation */
|
||||
static AsconProtocol *protocols = NULL;
|
||||
|
||||
long parse_dotted_adr(const char *dottedadr) {
|
||||
int ip[4];
|
||||
int i;
|
||||
|
||||
if (sscanf(dottedadr, "%d.%d.%d.%d", ip, ip+1, ip+2, ip+3) != 4) return 0;
|
||||
for (i=0; i<3; i++) {
|
||||
if (ip[i] < 0 || ip[i] > 255) return 0;
|
||||
}
|
||||
return ip[0] + (ip[1] << 8) + (ip[2] << 16) + (ip[3] << 24);
|
||||
}
|
||||
static int MakeSocketAdr(
|
||||
struct sockaddr *sockaddrPtr, /* socket address */
|
||||
char *hostname, /* name or ip of host. NULL implies INADDR_ANY */
|
||||
int port, /* port number */
|
||||
char dotted_ip[16]) { /* resolved ip adr */
|
||||
/*
|
||||
Workaround for the following case:
|
||||
switching off and on a LakeShore 336 does acquire a new address,
|
||||
but the value in the cache (for gethostbyname) is not updated.
|
||||
node: dig seems to be recommended over nslookup
|
||||
*/
|
||||
|
||||
long ns_lookup(char *hostname) {
|
||||
struct hostent *hostent; /* Host database entry */
|
||||
struct sockaddr_in *sadr = (struct sockaddr_in *)sockaddrPtr;
|
||||
FILE *fil;
|
||||
char line[256];
|
||||
long ipadr;
|
||||
int l;
|
||||
|
||||
ipadr = parse_dotted_adr(hostname);
|
||||
if (ipadr) return ipadr;
|
||||
snprintf(line, sizeof line, "timeout 1 nslookup %s", hostname);
|
||||
fil = popen(line, "r");
|
||||
if (fil == NULL) {
|
||||
(void) memset(sadr, 0, sizeof(*sadr));
|
||||
if (dotted_ip) { /* default value: failure */
|
||||
dotted_ip[0] = 0;
|
||||
}
|
||||
sadr->sin_family = AF_INET;
|
||||
sadr->sin_port = htons((unsigned short)port);
|
||||
if (hostname == NULL) {
|
||||
/* do not need to copy, as INADDR_ANY is all zero bytes */
|
||||
return 1;
|
||||
}
|
||||
if (inet_pton(AF_INET, hostname, &sadr->sin_addr) == 1) {
|
||||
/* resolved as dotted numbers notation */
|
||||
return 1;
|
||||
}
|
||||
hostent = gethostbyname(hostname);
|
||||
if (hostent == 0) {
|
||||
/* we assume that when gethostname gets no entry, dig will also fail.
|
||||
That way, dig will not be called repeatedly for no reason */
|
||||
return 0;
|
||||
}
|
||||
while (fgets(line, sizeof(line), fil) != NULL) {
|
||||
if (strncmp(line, "Address: ", 9) == 0) {
|
||||
ipadr = parse_dotted_adr(line+9);
|
||||
if (ipadr) {
|
||||
fclose(fil);
|
||||
return ipadr;
|
||||
}
|
||||
/* copy the address: in case dig fails, we use the cached value */
|
||||
memcpy(&sadr->sin_addr, hostent->h_addr_list[0], 4);
|
||||
/* we use hostent->h_name instead of hostname here, as this has already
|
||||
the proper domain added */
|
||||
snprintf(line, sizeof line, "timeout 1 dig +short %s", hostent->h_name);
|
||||
fil = popen(line, "r");
|
||||
if (fil != NULL) {
|
||||
if (fgets(line, sizeof(line), fil) != NULL) {
|
||||
l = strlen(line);
|
||||
if (line[l-1] <= ' ') line[l-1] = 0; /* strip off newline */
|
||||
/* silently ignore return value, if it fails, we take the cached value */
|
||||
inet_pton(AF_INET, line, &sadr->sin_addr);
|
||||
}
|
||||
fclose(fil);
|
||||
}
|
||||
fclose(fil);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Based on CreateSocketAdress from John Ousterhout
|
||||
Use ns_lookup instead of gethostbyname, as the latter uses a cache, which
|
||||
is not sufficient in some cases (switching off and on a LakeShore 336 does
|
||||
acquire a new address, but the value in the cache is not updates)
|
||||
*/
|
||||
|
||||
static int MakeSocketAdress(struct sockaddr_in *sockaddrPtr, /* Socket address */
|
||||
char *host, /* Host. NULL implies INADDR_ANY */
|
||||
int port)
|
||||
{ /* Port number */
|
||||
struct hostent *hostent; /* Host database entry */
|
||||
struct in_addr addr; /* For 64/32 bit madness */
|
||||
|
||||
(void) memset((char *) sockaddrPtr, '\0', sizeof(struct sockaddr_in));
|
||||
sockaddrPtr->sin_family = AF_INET;
|
||||
sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF));
|
||||
if (host == NULL) {
|
||||
addr.s_addr = INADDR_ANY;
|
||||
} else {
|
||||
addr.s_addr = ns_lookup(host);
|
||||
if (addr.s_addr == 0) { /* try gethostbyname only if ns_lookup failed */
|
||||
hostent = gethostbyname(host);
|
||||
if (hostent == NULL) return 0; /* error */
|
||||
memcpy((char *) &addr,
|
||||
(char *) hostent->h_addr_list[0], (size_t) hostent->h_length);
|
||||
}
|
||||
if (dotted_ip) {
|
||||
inet_ntop(AF_INET, &sadr->sin_addr, dotted_ip, 16);
|
||||
}
|
||||
/*
|
||||
* There is a rumor that this assignment may require care on
|
||||
* some 64 bit machines, we do not believe it.
|
||||
*/
|
||||
sockaddrPtr->sin_addr.s_addr = addr.s_addr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -140,7 +127,7 @@ static void AsconConnect(Ascon * a)
|
||||
/* input state: AsconConnectStart
|
||||
output state: AsconFailed or AsconConnecting */
|
||||
int ret;
|
||||
struct sockaddr_in adr;
|
||||
struct sockaddr adr;
|
||||
char *colon;
|
||||
int port;
|
||||
int oldopts;
|
||||
@ -184,17 +171,15 @@ static void AsconConnect(Ascon * a)
|
||||
return;
|
||||
}
|
||||
*colon = '\0';
|
||||
ret = MakeSocketAdress(&adr, a->hostport, port);
|
||||
ret = MakeSocketAdr(&adr, a->hostport, port, a->ip);
|
||||
*colon = ':';
|
||||
if (ret == 0) {
|
||||
a->ip = 0;
|
||||
AsconError(a, "bad host specification", 0);
|
||||
return;
|
||||
}
|
||||
a->ip = adr.sin_addr.s_addr;
|
||||
oldopts = fcntl(a->fd, F_GETFL, 0);
|
||||
fcntl(a->fd, F_SETFL, oldopts | O_NONBLOCK);
|
||||
ret = connect(a->fd, (struct sockaddr *) &adr, sizeof(struct sockaddr_in));
|
||||
ret = connect(a->fd, &adr, sizeof(struct sockaddr_in));
|
||||
if (ret < 0) {
|
||||
switch (errno) {
|
||||
case EINPROGRESS:
|
||||
@ -891,10 +876,10 @@ char *AsconHostport(Ascon *a)
|
||||
return a->hostport;
|
||||
}
|
||||
|
||||
unsigned long AsconIP(Ascon *a)
|
||||
char *AsconIP(Ascon *a)
|
||||
{
|
||||
if (a==NULL) {
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
return a->ip;
|
||||
}
|
||||
|
4
ascon.h
4
ascon.h
@ -112,9 +112,9 @@ char *AsconHostport(Ascon *a);
|
||||
/**
|
||||
* \brief return IP address
|
||||
* \param a The Ascon to query
|
||||
* \return the IP address
|
||||
* \return the IP address (dotted numbers)
|
||||
*/
|
||||
unsigned long AsconIP(Ascon *a);
|
||||
char *AsconIP(Ascon *a);
|
||||
|
||||
/**
|
||||
* \brief set or get timeout
|
||||
|
2
ascon.i
2
ascon.i
@ -65,7 +65,7 @@ struct Ascon {
|
||||
char *sendTerminator; /**< terminator for sending messages */
|
||||
char *replyTerminator; /**< (std) terminator list for reply. NULL is the special case CR, LF or CR/LF */
|
||||
char *hostport; /**< host:port to connect */
|
||||
in_addr_t ip; /**< the ip address */
|
||||
char ip[16]; /**< the ip address (dotted numbers) */
|
||||
pDynString errmsg; /**< error message */
|
||||
double start; /**< unix time when read was started */
|
||||
int noResponse; /**< no response expected */
|
||||
|
2
devser.c
2
devser.c
@ -580,7 +580,7 @@ char *DevHostport(DevSer *devser) {
|
||||
return AsconHostport(devser->ascon);
|
||||
}
|
||||
|
||||
unsigned long DevIP(DevSer *devser) {
|
||||
char *DevIP(DevSer *devser) {
|
||||
return AsconIP(devser->ascon);
|
||||
}
|
||||
|
||||
|
4
devser.h
4
devser.h
@ -206,9 +206,9 @@ char *DevHostport(DevSer *devser);
|
||||
/**
|
||||
* \brief return IP address
|
||||
* \param a The device serializer to query
|
||||
* \return the IP address
|
||||
* \return the IP address (dotted numbers)
|
||||
*/
|
||||
unsigned long DevIP(DevSer *devser);
|
||||
char *DevIP(DevSer *devser);
|
||||
|
||||
/**
|
||||
* \brief return status of device server ("offline", "unconnected", "")
|
||||
|
@ -1742,15 +1742,9 @@ static int SctIpAddress(pSICSOBJ ccmd, SConnection * con,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
SctController *c;
|
||||
uint32_t ip;
|
||||
|
||||
c = (SctController *) ccmd->pPrivate;
|
||||
ip = DevIP(c->devser);
|
||||
SCPrintf(con, eValue, "%d.%d.%d.%d",
|
||||
(int)(ip & 0xff),
|
||||
(int)((ip >> 8) & 0xff),
|
||||
(int)((ip >> 16) & 0xff),
|
||||
(int)((ip >> 24) & 0xff));
|
||||
SCPrintf(con, eValue, "%s", DevIP(c->devser));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user