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