Hi,

the client side (nagios-nrpe-plugin) is pretty straightforward. I've attached my patch I'm using locally. I'm not an experienced C programmer and it is far from perfect, but it works for me.

* Might contain security bugs, memory leaks, you name it
* can one assume that getaddrinfo() is available on all (Debian) platforms nowadays? I have never done any automake stuff, and the code would probably become a bit messy doing that.
* one should probably code -4/-6 flags
* haven't done any testing on IPv4-only hosts (without loaded IPv6)

The server side is probably a lot trickier, especially in daemon mode.

* one has to open/listen to two sockets, one for IPv6 and one for IPv4 nowadays. I'm not sure whether this is even possible without an additional fork()
* server_address might not be too easy
* allowed_hosts is probably really hard

I am ignoring all those challenges and running nrpe from xinetd, which works fine. I doubt this will be good enough for Debian mainline though.

Bernhard
 src/utils.c |   76 +++++++++++++++++++++++++++++-----------------------------
 1 files changed, 38 insertions(+), 38 deletions(-)

diff --git a/src/utils.c b/src/utils.c
index 48d7e58..1b368a0 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -121,45 +121,46 @@ int my_tcp_connect(char *host_name,int port,int *sd){
 
 /* opens a tcp or udp connection to a remote host */
 int my_connect(char *host_name,int port,int *sd,char *proto){
-	struct sockaddr_in servaddr;
-	struct hostent *hp;
-	struct protoent *ptrp;
-	int result;
+	struct addrinfo hints, *res, *res0;
+	int result, lasterr;
+	char portstr[6];
 
-	bzero((char *)&servaddr,sizeof(servaddr));
-	servaddr.sin_family=AF_INET;
-	servaddr.sin_port=htons(port);
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = PF_UNSPEC;
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_flags = AI_NUMERICSERV;
 
-	/* try to bypass using a DNS lookup if this is just an IP address */
-	if(!my_inet_aton(host_name,&servaddr.sin_addr)){
+	sprintf(portstr, "%d", port);
 
-		/* else do a DNS lookup */
-		hp=gethostbyname((const char *)host_name);
-		if(hp==NULL){
-			printf("Invalid host name '%s'\n",host_name);
-			return STATE_UNKNOWN;
-		        }
+	result = getaddrinfo(host_name, portstr, &hints, &res0);
+	if (result != 0){
+		printf("Invalid host name '%s'\n",host_name);
+		return STATE_UNKNOWN;
+		}
 
-		memcpy(&servaddr.sin_addr,hp->h_addr,hp->h_length);
-	        }
+	for (res=res0; res; res=res->ai_next){
+		*sd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+		if(*sd<0){
+			printf("Socket creation failed\n");
+			freeaddrinfo(res0);
+			return STATE_UNKNOWN;
+	        	}
 
-	/* map transport protocol name to protocol number */
-	if(((ptrp=getprotobyname(proto)))==NULL){
-		printf("Cannot map \"%s\" to protocol number\n",proto);
-		return STATE_UNKNOWN;
-	        }
+		/* open a connection */
+		result=connect(*sd,res->ai_addr,res->ai_addrlen);
+		if(result<0){
+			lasterr=errno;
+			continue;
+	        	}
+		else {
+			break;
+			}
+		}
 
-	/* create a socket */
-	*sd=socket(PF_INET,(!strcmp(proto,"udp"))?SOCK_DGRAM:SOCK_STREAM,ptrp->p_proto);
-	if(*sd<0){
-		printf("Socket creation failed\n");
-		return STATE_UNKNOWN;
-	        }
+	freeaddrinfo(res0);
 
-	/* open a connection */
-	result=connect(*sd,(struct sockaddr *)&servaddr,sizeof(servaddr));
-	if(result<0){
-		switch(errno){  
+	if (result<0) {
+		switch(lasterr){  
 		case ECONNREFUSED:
 			printf("Connection refused by host\n");
 			break;
@@ -171,12 +172,11 @@ int my_connect(char *host_name,int port,int *sd,char *proto){
 			break;
 		default:
 			printf("Connection refused or timed out\n");
-		        }
-
+			}
 		return STATE_CRITICAL;
-	        }
-
-	return STATE_OK;
+		}
+	else
+		return STATE_OK;
         }
 
 

Reply via email to