diff --git a/ascon.c b/ascon.c index 09440e99..8bcdb39e 100644 --- a/ascon.c +++ b/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; } diff --git a/ascon.h b/ascon.h index 9d457da6..d32130eb 100644 --- a/ascon.h +++ b/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 diff --git a/ascon.i b/ascon.i index f4da9ad9..41f42e12 100644 --- a/ascon.i +++ b/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 */ diff --git a/devser.c b/devser.c index 05d9101c..705514fd 100644 --- a/devser.c +++ b/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); } diff --git a/devser.h b/devser.h index 9ea76805..50ea45f9 100644 --- a/devser.h +++ b/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", "") diff --git a/scriptcontext.c b/scriptcontext.c index 77d5eebf..fb5c6596 100644 --- a/scriptcontext.c +++ b/scriptcontext.c @@ -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; }