From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 85979 invoked by alias); 29 Dec 2017 13:30:41 -0000 Mailing-List: contact cygwin-help@cygwin.com; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner@cygwin.com Mail-Followup-To: cygwin@cygwin.com Received: (qmail 85966 invoked by uid 89); 29 Dec 2017 13:30:40 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.8 required=5.0 tests=AWL,BAYES_00,CYGWIN_OWNER_BODY,GIT_PATCH_2,KAM_INFOUSMEBIZ,KAM_LAZY_DOMAIN_SECURITY,KAM_SHORT,RCVD_IN_DNSWL_NONE autolearn=no version=3.3.2 spammy=compliment, H*MI:local, firewall, connections X-HELO: mailrelay.dillinger.de Received: from mailrelayb.dillinger.de (HELO mailrelay.dillinger.de) (212.184.64.29) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 29 Dec 2017 13:30:37 +0000 Received: from mailrelaya2.dillinger.de (mailrelaya [192.168.175.11]) by lin254mailrelayb.dillinger.de (Postfix) with ESMTP id 45D5AA316 for ; Fri, 29 Dec 2017 14:30:35 +0100 (CET) Received: from lin275.int.shsservices.de (lin275 [172.18.32.6]) by mailrelaya2.dillinger.de (Postfix) with ESMTP id CCDED24230E for ; Fri, 29 Dec 2017 14:39:19 +0100 (CET) Received: from RESW103.resdom01.local (resw103.dillinger.de [172.18.22.103]) by lin275.int.shsservices.de (Postfix) with ESMTP id 397B3F3AFA for ; Fri, 29 Dec 2017 14:30:35 +0100 (CET) Received: from RESW102.resdom01.local ([fe80::a883:3db9:4459:1159]) by RESW103.resdom01.local ([fe80::a480:c1ef:e5bb:a91b%15]) with mapi id 14.03.0279.002; Fri, 29 Dec 2017 14:30:35 +0100 From: "PAULUS, Raimund, TI-ABN" To: "cygwin@cygwin.com" Subject: Re: AW: RPC clnt_create() adress already in use Date: Sat, 30 Dec 2017 18:39:00 -0000 Message-ID: <59D90AF8D70E9740907BACDE2BCB520836CCDAED@RESW102.resdom01.local> Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-IsSubscribed: yes X-SW-Source: 2017-12/txt/msg00277.txt.bz2 Hello Mark, you wrote: "Just so I understand more fully: you are compiling with those options on C= ygwin?" Answer: yes you wrote: "The idea there is to use a different port on each run of the program. If = you're looping around and reaching that code again with port=3D=3D0, then y= es you'll get the same port number=20 each time because getpid() is not changing." Answer: That's correct. But you can see, the following bind() is embedded in a loop= : if the bind() would work correctly, it would deliver res < 0 because errn= o =3D EADDRINUSE. In this case=20 the port would be incremented and the next loop pass is made. This would ha= ppen till an unused port is found or all ports are used. I think, the probl= em here is, bind() does not=20 deliver the correct return value. Therefore my two approaches. you wrote: "I don't know enough to set up an RPC test bed to try your client program=20 locally. *Unless* it's sufficient to run your client program and aim at th= e=20 local machine even though it has no RPC server listening. If that would=20 demonstrate your issue, let me know and I'll have another look. Otherwise,= I=20 would need to set up an RPC server on my Cygwin machine. If you've done th= at on=20 your Cygwin machine, what are the steps? I think I can follow Unix-style=20 instructions but will have to allow for Windows Firewall so if you've done = this=20 already on Cygwin your procedure would help a lot." Answer: To make a connection the RPC server must be running. My RPC server is runni= ng on a linux machine since several years. I know, it is reliable and i wou= ld not have an additional possible error source. I didn't do anything with the Windows firewall. I found a simple RPC example here: https://www.unf.edu/~sahuja/cnt5505/rpce= xample.html. I did some minimal changes to better show the problem (client uses tcp inst= ead udp, connection establishment in a loop). I could reproduce the problem= in this example. Here the sources and the compile directives: date.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D /* * Please do not edit this file. * It was generated using rpcgen. */ #ifndef _DATE_H_RPCGEN #define _DATE_H_RPCGEN #include #ifdef __cplusplus extern "C" { #endif #define DATEPROG 0x3012225 #define DATEVERS 1 #if defined(__STDC__) || defined(__cplusplus) #define BINDATE 1 extern long * bindate_1(void *, CLIENT *); extern long * bindate_1_svc(void *, struct svc_req *); extern int dateprog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t); #else /* K&R C */ #define BINDATE 1 extern long * bindate_1(); extern long * bindate_1_svc(); extern int dateprog_1_freeresult (); #endif /* K&R C */ #ifdef __cplusplus } #endif #endif /* !_DATE_H_RPCGEN */ date_client.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D /* * Please do not edit this file. * It was generated using rpcgen. */ #include /* for memset */ #include "date.h" /* Default timeout can be changed using clnt_control() */ static struct timeval TIMEOUT =3D { 25, 0 }; long * bindate_1(void *argp, CLIENT *clnt) { static long clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); if (clnt_call (clnt, BINDATE, (xdrproc_t) xdr_void, (caddr_t) argp, (xdrproc_t) xdr_long, (caddr_t) &clnt_res, TIMEOUT) !=3D RPC_SUCCESS) { return (NULL); } return (&clnt_res); } date_svc.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D /* * Please do not edit this file. * It was generated using rpcgen. */ #include "date.h" #include #include #include #include #include #include #include #ifndef SIG_PF #define SIG_PF void(*)(int) #endif static void dateprog_1(struct svc_req *rqstp, register SVCXPRT *transp) { union { int fill; } argument; char *result; xdrproc_t _xdr_argument, _xdr_result; char *(*local)(char *, struct svc_req *); switch (rqstp->rq_proc) { case NULLPROC: (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *= )NULL); return; case BINDATE: _xdr_argument =3D (xdrproc_t) xdr_void; _xdr_result =3D (xdrproc_t) xdr_long; local =3D (char *(*)(char *, struct svc_req *)) bindate_1_s= vc; break; default: svcerr_noproc (transp); return; } memset ((char *)&argument, 0, sizeof (argument)); if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &arg= ument)) { svcerr_decode (transp); return; } result =3D (*local)((char *)&argument, rqstp); if (result !=3D NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_res= ult, result)) { svcerr_systemerr (transp); } if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &ar= gument)) { fprintf (stderr, "%s", "unable to free arguments"); exit (1); } return; } int main (int argc, char **argv) { register SVCXPRT *transp; pmap_unset (DATEPROG, DATEVERS); transp =3D svctcp_create(RPC_ANYSOCK, 0, 0); if (transp =3D=3D NULL) { fprintf (stderr, "%s", "cannot create tcp service."); exit(1); } if (!svc_register(transp, DATEPROG, DATEVERS, dateprog_1, IPPROTO_U= DP)) { fprintf (stderr, "%s", "unable to register (DATEPROG, DATEV= ERS, udp)."); exit(1); } transp =3D svctcp_create(RPC_ANYSOCK, 0, 0); if (transp =3D=3D NULL) { fprintf (stderr, "%s", "cannot create tcp service."); exit(1); } if (!svc_register(transp, DATEPROG, DATEVERS, dateprog_1, IPPROTO_T= CP)) { fprintf (stderr, "%s", "unable to register (DATEPROG, DATEV= ERS, tcp)."); exit(1); } svc_run (); fprintf (stderr, "%s", "svc_run returned"); exit (1); /* NOTREACHED */ } dateproc.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D /*********************************************************************/ /* dateproc.c - remote procedures; called by server stub */ #include #include #include #include "date.h" /* return the binary date and time */ /* In Linux: long * bindate_1_svc(void* arg1, struct svc_req *arg2) { */ /* In Dec Unix: long * bindate_1() { */ long * bindate_1_svc(void* arg1, struct svc_req *arg2) { static long timeval; /* must be static */ timeval =3D time((long *) 0); return (&timeval); } rdate.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D /****************************************************************/ /* rdate.c - client program for remote date service */ #include #include #include #include #include #include "date.h" int main(int argc, char *argv[]) { CLIENT *cl; char *server; long *lres; if (argc !=3D 2) { fprintf(stderr, "usage: %s hostname\n", argv[0]); exit(1); } server =3D argv[1]; int i; for(i=3D0; i< 100; i++) { /* create client handle */ if ((cl =3D clnt_create(server, DATEPROG, DATEVERS, "tcp")) =3D=3D NULL) { /* couldn't establish connection with server */ printf("can't establish connection with host %s\n", server); exit(2); } /* first call the remote procedure bindate() */ if (( lres =3D bindate_1(NULL, cl)) =3D=3D NULL){ printf(" remote procedure bindate() failure\n"); exit(3); } printf("Loop %d: time on host %s =3D %ld =3D=3D %s", i, server, *lres, ctime(lres)); clnt_destroy(cl); /* done with handle */ sleep(1); } return 0; } **************************************************** Commands: gcc -c date_clnt.c gcc -c date_svc.c gcc -c dateproc.c gcc -c rdate.c gcc -o client date_clnt.o rdate.o gcc -o server date_svc.o dateproc.o for Cygwin gcc -I/usr/include/tirpc -c date_clnt.c gcc -I/usr/include/tirpc -c date_svc.c gcc -I/usr/include/tirpc -c dateproc.c gcc -I/usr/include/tirpc -c rdate.c gcc -o client date_clnt.o rdate.o -ltirpc gcc -o server date_svc.o dateproc.o -ltirpc I hope this will help Raimund -----Urspr=FCngliche Nachricht----- Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com] Im Auftrag vo= n Mark Geisert Gesendet: Mittwoch, 27. Dezember 2017 10:39 An: cygwin@cygwin.com Betreff: Re: RPC clnt_create() adress already in use Hi Raimund, Comments embedded below... PAULUS, Raimund, TI-ABN wrote: > Hello Mark, > > in my earlier tests the lib and header files for tirpc was still there fr= om the Cygwin-installation. I think, this could influence the results of th= e tests. > Therefore i removed these files. From now on i used only the downloaded f= iles from sourceforge (https://sourceforge.net/projects/libtirpc/files/libt= irpc/). I tested libtirpc-0.3.2, libtirpc-1.0.1 and libtirpc-1.0.2. The res= ults for all releases are the same. > > I needed the following sources: > > auth_none.c, auth_unix.c, authunix_prot.c, bindresvport.c, clnt_bcast.c, = clnt_dg.c, clnt_generic.c, clnt_perror.c, clnt_vc.c, debug.c, getnetconfig.= c, getnetpath.c, mt_misc.c, rpc_callmsg.c, rpc_commondata.c, rpc_generic.c,= rpc_prot.c, rpcb_clnt.c, rpcb_prot.c, xdr.c, xdr_array.c, xdr_float.c, xdr= _reference.c, xdr_rec.c, xdr_mem.c > > I had to change the following (already mentioned earlier): > > clnt_bcast.c > (because POLLRDNORM, POLLRDBAND are already defined in /usr/include/sys/p= oll.h) : > > --> #ifndef POLLRDNORM > # define POLLRDNORM 0x040 /* Normal data may be read. */ > # define POLLRDBAND 0x080 /* Priority data may be read. */ > --> #endif Not only does /usr/include/sys/poll.h already define them, they're defined = with different values. Could be a red flag or a red herring; don't know ye= t. > xdr.h (typedefs where missed): > > #include > > --> typedef __uint64_t u_quad_t; > --> typedef __int64_t quad_t; > > > My compile-flags: -D_GNU_SOURCE -D__GLIBC__ -D__linux__ Just so I understand more fully: you are compiling with those options on Cy= gwin? > If i build my test program with the sources above, the behavior is the sa= me as with the Cygwin-libtirpc: the first RPC-connection is ok, the next ca= ll to clnt_create() delivers the error EADDRINUSE. > > The test program on a Linux-box works perfectly. With "netstat -n" you ca= n see each connection from the client to the server creates a new pair of p= orts. On the server-side the pair is always the same (ports 111, 907). On t= he client-side however the ports differ from one connection to the other. W= hen the connections are closed the ports remain in state TIME_WAIT. After a= while they disappear. > > If the RPC-client (Cygwin) is running on a Windows-box, "netstat -n" show= s the pair of ports for the first connection. The next connection attempt (= clnt_create()) delivers: EADDRINUSE. > > In the sources you can see the following: > > clnt_create() calls the function bindresvport_sa() (in bindresvport.c). H= ere the port for the connection is determined: > > if (port =3D=3D 0) { > port =3D (getpid() % NPORTS) + STARTPORT; } The idea there is to use a different port on each run of the program. If y= ou're looping around and reaching that code again with port=3D=3D0, then ye= s you'll get the same port number each time because getpid() is not changin= g. > > and the socket is bound to the port: > > res =3D bind(sd, sa, salen); > > If this part is executed multiple times (loop) the port is always the sam= e. The function bind() doesn't deliver an error (res =3D 0, maybe bind() do= esn't work correctly?). Therefore the error is not detected until the call = of connect() in function clnt_vc_create() (in clnt_vc.c). But here you can= not correct the port. > > I tried the following: > > The call of setsockopt(., SO_REUSEADDR, .) before bind() doesn't change a= nything. The error still occurs. > > I found 2 approaches to avoid the error: > > 1. Before the call to bind() set the port to 0 (port =3D 0). The followin= g bind() searches an unused port. > > 2. Set the port to 0 (port =3D 0). Do not call bind(). Later the call to = connect() searches an unused port. > > I tested the two methods and the behavior was the same as the Linux-clien= t. It obviously works correctly. But i'm not a network specialist and i do= n't know, if it's the best solution for the problem. > > > Subsequently I downloaded the Cygwin-sources for libtirpc-0.3.2 and libti= rpc-1.0.1. And here again, with the changes mentioned in the two approaches= the RPC-connection works perfectly. The only difference her is: a connecti= on does not create a pair of ports but only a single port (netstat -n). I must compliment you; you are being very specific and detailed about what= =20 you're doing on the client end of the RPC connection. But as I said in my = last=20 email, I don't know specifics about RPC implementation; I sort of know gene= rally=20 what RPC can do. I don't know enough to set up an RPC test bed to try your client program=20 locally. *Unless* it's sufficient to run your client program and aim at th= e=20 local machine even though it has no RPC server listening. If that would=20 demonstrate your issue, let me know and I'll have another look. Otherwise,= I=20 would need to set up an RPC server on my Cygwin machine. If you've done th= at on=20 your Cygwin machine, what are the steps? I think I can follow Unix-style=20 instructions but will have to allow for Windows Firewall so if you've done = this=20 already on Cygwin your procedure would help a lot. Thanks, ..mark -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple