Subject: lib/13082: clnt_control option CLGET_SVC_ADDR does not work with rpc vc transport
To: None <gnats-bugs@gnats.netbsd.org>
From: Jean-Luc Richier <Jean-Luc.Richier@imag.fr>
List: netbsd-bugs
Date: 06/01/2001 18:20:12
>Number:         13082
>Category:       lib
>Synopsis:       clnt_control option CLGET_SVC_ADDR does not work with rpc vc transport
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Jun 01 09:28:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Jean-Luc Richier
>Release:        NetBSD 1.5
>Organization:
IMAG
>Environment:
System: NetBSD oban.imag.fr 1.5 NetBSD 1.5 (IPv6) #24: Fri Apr 20 17:36:52 MEST 2001 richier@oban.imag.fr:/usr/src/sys/arch/sparc/compile/IPv6 sparc


>Description:
    In the RPC libc code, the control call which allows clients to
    find the address of the server (clnt_control(clnt, CLGET_SVC_ADDR, ..)
    return an incorrect value.
    Bug was detected in NetBSD1.5, and in still in the NetBSD-current source

>How-To-Repeat:
    Consider the code at the end, which allows to test rpc calls (unicast or
    not) on different transports, compile it (cc -o tstrpc tstrpc.c)
    - on udp: it works:
    % tstrpc tuna.imag.fr
    response from: tuna.imag.fr
    - on tcp there is an error
    % tstrpc -t tuna.imag.fr
    incorrect response

     test program tstrpc.c:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <rpc/rpc.h>

#define RPCBPROC_NULL 0
char *transp;

int
reply(caddr_t replyp, struct netbuf *raddrp, struct netconfig *nconf)
{
	char host[NI_MAXHOST];
	struct sockaddr *sock = raddrp->buf;

	if (getnameinfo(sock, sock->sa_len, host, sizeof (host), NULL, 0, 0))
		printf("incorrect response\n");
	else
		printf("response from: %s\n", host);
	return(0);
}

void
onehost(char *host)
{
        CLIENT *clnt;
	struct netbuf addr;
	struct timeval tv;

        if ((clnt = clnt_create(host, RPCBPROG, RPCBVERS, transp)) == NULL)
                errx(1, "%s", clnt_spcreateerror(""));

	tv.tv_sec = 15;
	tv.tv_usec = 0;
	if (clnt_call(clnt, RPCBPROC_NULL, xdr_void, NULL, xdr_void, NULL, tv)
			!= RPC_SUCCESS)
                errx(1, "%s", clnt_sperror(clnt, ""));
	clnt_control(clnt, CLGET_SVC_ADDR, (char *)&addr);
	reply(NULL, &addr, NULL);
}

void
allhosts()
{
	enum clnt_stat clnt_stat;

	clnt_stat = rpc_broadcast(RPCBPROG, RPCBVERS, RPCBPROC_NULL,
				   xdr_void, NULL, xdr_void, NULL,
				   (resultproc_t)reply, transp);
	if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT)
		errx(1, "%s", clnt_sperrno(clnt_stat));
}

int
main(int argc, char *argv[])
{
        int ch;

	transp = "udp";
        while ((ch = getopt(argc, argv, "ut")) != -1)
	        switch (ch) {
                case 't':
                        transp = "tcp";
                        break;
                case 'u':
                        transp = "udp";
                        break;
                default:
                        errx(1, "tstrpc -[u|t] ...");
                }
	if (argc == optind)
		allhosts();
	else for (; optind < argc; optind++)
		onehost(argv[optind]);
        exit(0);
}

>Fix:

     The problem is in lib/libc/rpc/clnt_vc.c, an incorrect reference.
     To correct:

*** /usr/src/lib/libc/rpc/clnt_vc.c.DIST	Fri Jul 14 18:48:12 2000
--- /usr/src/lib/libc/rpc/clnt_vc.c	Fri Jun  1 18:05:33 2001
***************
*** 263,269 ****
  	ct->ct_addr.buf = malloc(raddr->maxlen);
  	if (ct->ct_addr.buf == NULL)
  		goto fooy;
! 	memcpy(ct->ct_addr.buf, &raddr->buf, raddr->len);
  	ct->ct_addr.len = raddr->maxlen;
  	ct->ct_addr.maxlen = raddr->maxlen;
  
--- 263,269 ----
  	ct->ct_addr.buf = malloc(raddr->maxlen);
  	if (ct->ct_addr.buf == NULL)
  		goto fooy;
! 	memcpy(ct->ct_addr.buf, raddr->buf, raddr->len);
  	ct->ct_addr.len = raddr->maxlen;
  	ct->ct_addr.maxlen = raddr->maxlen;
  

>Release-Note:
>Audit-Trail:
>Unformatted: