From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15032 invoked from network); 11 Jul 2007 00:37:26 -0000 X-Spam-Checker-Version: SpamAssassin 3.2.1 (2007-05-02) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.2.1 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by ns1.primenet.com.au with SMTP; 11 Jul 2007 00:37:26 -0000 Received-SPF: none (ns1.primenet.com.au: domain at sunsite.dk does not designate permitted sender hosts) Received: (qmail 68304 invoked from network); 11 Jul 2007 00:37:20 -0000 Received: from sunsite.dk (130.225.247.90) by a.mx.sunsite.dk with SMTP; 11 Jul 2007 00:37:20 -0000 Received: (qmail 24791 invoked by alias); 11 Jul 2007 00:37:16 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 23670 Received: (qmail 24782 invoked from network); 11 Jul 2007 00:37:15 -0000 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by sunsite.dk with SMTP; 11 Jul 2007 00:37:15 -0000 Received: (qmail 67962 invoked from network); 11 Jul 2007 00:37:15 -0000 Received: from acolyte.scowler.net (216.254.112.45) by a.mx.sunsite.dk with SMTP; 11 Jul 2007 00:37:08 -0000 Received: by acolyte.scowler.net (Postfix, from userid 1000) id 883AD5C3C6; Tue, 10 Jul 2007 20:37:07 -0400 (EDT) Date: Tue, 10 Jul 2007 20:37:07 -0400 From: Clint Adams To: zsh-workers@sunsite.dk Subject: Re: using getaddrinfo/getnameinfo Message-ID: <20070711003707.GA21928@scowler.net> Mail-Followup-To: zsh-workers@sunsite.dk References: <20070523195532.GA7139@scowler.net> <070523192537.ZM7842@torch.brasslantern.com> <20070526012545.GA14364@scowler.net> <070526112459.ZM29419@torch.brasslantern.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <070526112459.ZM29419@torch.brasslantern.com> User-Agent: Mutt/1.5.16 (2007-06-11) On Sat, May 26, 2007 at 11:24:59AM -0700, Bart Schaefer wrote: > Create zget* wrapper functions, put the #ifdef's in there, and change > the calls scattered elsewhere to use the zget variants. I gave this a shot, but my plan proved to be a nightmare to execute. I also noticed that I repressed 17404. > It might very well be, but zsh compiles on some pretty crufty OSs/hardware. There's the don't-compile-modules-on-crufty-systems approach, though it is a regression of sorts: --- a/Src/Modules/tcp.c +++ b/Src/Modules/tcp.c @@ -135,79 +135,6 @@ zsh_inet_pton(int af, char const *src, void *dst) /**/ #endif /* !HAVE_INET_PTON */ -/**/ -#ifndef HAVE_GETIPNODEBYNAME - -/**/ -# ifndef HAVE_GETHOSTBYNAME2 - -/**/ -mod_export struct hostent * -zsh_gethostbyname2(char const *name, int af) -{ - if (af != AF_INET) { - h_errno = NO_RECOVERY; - return NULL; - } - return gethostbyname(name); -} - -/**/ -#else /* !HAVE_GETHOSTBYNAME2 */ - -/**/ -# define zsh_gethostbyname2 gethostbyname2 - -/**/ -# endif /* !HAVE_GETHOSTBYNAME2 */ - -/* note: this is not a complete implementation. If ignores the flags, - and does not provide the memory allocation of the standard interface. - Each returned structure will overwrite the previous one. */ - -/**/ -mod_export struct hostent * -zsh_getipnodebyname(char const *name, int af, UNUSED(int flags), int *errorp) -{ - static struct hostent ahe; - static char nbuf[16]; - static char *addrlist[] = { nbuf, NULL }; -# ifdef SUPPORT_IPV6 - static char pbuf[INET6_ADDRSTRLEN]; -# else - static char pbuf[INET_ADDRSTRLEN]; -# endif - struct hostent *he; - if (zsh_inet_pton(af, name, nbuf) == 1) { - zsh_inet_ntop(af, nbuf, pbuf, sizeof(pbuf)); - ahe.h_name = pbuf; - ahe.h_aliases = addrlist+1; - ahe.h_addrtype = af; - ahe.h_length = (af == AF_INET) ? 4 : 16; - ahe.h_addr_list = addrlist; - return &ahe; - } - he = zsh_gethostbyname2(name, af); - if (!he) - *errorp = h_errno; - return he; -} - -/**/ -mod_export void -freehostent(UNUSED(struct hostent *ptr)) -{ -} - -/**/ -#else /* !HAVE_GETIPNODEBYNAME */ - -/**/ -# define zsh_getipnodebyname getipnodebyname - -/**/ -#endif /* !HAVE_GETIPNODEBYNAME */ - LinkList ztcp_sessions; /* "allocate" a tcp_session */ @@ -311,25 +238,23 @@ tcp_close(Tcp_session sess) /**/ mod_export int -tcp_connect(Tcp_session sess, char *addrp, struct hostent *zhost, int d_port) +tcp_connect(Tcp_session sess, struct addrinfo *zai) { int salen; #ifdef SUPPORT_IPV6 - if (zhost->h_addrtype==AF_INET6) { - memcpy(&(sess->peer.in6.sin6_addr), addrp, zhost->h_length); - sess->peer.in6.sin6_port = d_port; + if (zai->ai_family==AF_INET6) { + memcpy(&(sess->peer.in6.sin6_addr), zai->ai_addr, zai->ai_addrlen); sess->peer.in6.sin6_flowinfo = 0; # ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID sess->peer.in6.sin6_scope_id = 0; # endif - sess->peer.in6.sin6_family = zhost->h_addrtype; + sess->peer.in6.sin6_family = zai->ai_family; salen = sizeof(struct sockaddr_in6); } else #endif /* SUPPORT_IPV6 */ { - memcpy(&(sess->peer.in.sin_addr), addrp, zhost->h_length); - sess->peer.in.sin_port = d_port; - sess->peer.in.sin_family = zhost->h_addrtype; + memcpy(&(sess->peer.in.sin_addr), zai->ai_addr, zai->ai_addrlen); + sess->peer.in.sin_family = zai->ai_family; salen = sizeof(struct sockaddr_in); } @@ -339,12 +264,13 @@ tcp_connect(Tcp_session sess, char *addrp, struct hostent *zhost, int d_port) static int bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func)) { - int herrno, err=1, destport, force=0, verbose=0, test=0, targetfd=0; + int err=1, destport, force=0, verbose=0, test=0, targetfd=0; ZSOCKLEN_T len; - char **addrp, *desthost, *localname, *remotename; - struct hostent *zthost = NULL, *ztpeer = NULL; + char *desthost, *localname, *remotename; + char zthostname[1025], ztpeername[1025]; struct servent *srv; Tcp_session sess = NULL; + struct addrinfo *zhostlist, *zai; if (OPT_ISSET(ops,'f')) force = 1; @@ -561,16 +487,16 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func)) if (sess->fd != -1) { - zthost = gethostbyaddr((const void *)&(sess->sock.in.sin_addr), sizeof(sess->sock.in.sin_addr), AF_INET); - if (zthost) - localname = zthost->h_name; - else + if (getnameinfo((const struct sockaddr *)&(sess->sock.in.sin_addr), sizeof(struct sockaddr_in), zthostname, 1025, NULL, 0, 0)) localname = ztrdup(inet_ntoa(sess->sock.in.sin_addr)); - ztpeer = gethostbyaddr((const void *)&(sess->peer.in.sin_addr), sizeof(sess->peer.in.sin_addr), AF_INET); - if (ztpeer) - remotename = ztpeer->h_name; else + localname = (char *)&zthostname; + + if (getnameinfo((const struct sockaddr *)&(sess->peer.in.sin_addr), sizeof(struct sockaddr_in), ztpeername, 1025, NULL, 0, 0)) remotename = ztrdup(inet_ntoa(sess->peer.in.sin_addr)); + else + remotename = (char *)&ztpeername; + if (OPT_ISSET(ops,'L')) { int schar; if (sess->flags & ZTCP_ZFTP) @@ -602,20 +528,21 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func)) destport = htons(23); } else { + struct addrinfo hints; - srv = getservbyname(args[1],"tcp"); - if (srv) - destport = srv->s_port; - else - destport = htons(atoi(args[1])); - } - - desthost = ztrdup(args[0]); - - zthost = zsh_getipnodebyname(desthost, AF_INET, 0, &herrno); - if (!zthost || errflag) { - zwarnnam(nam, "host resolution failure: %s", desthost); - return 1; + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = PF_INET; + + desthost = ztrdup(args[0]); + + if(getaddrinfo(desthost, args[1], &hints, &zhostlist)) { + zwarnnam(nam, "host resolution failure: %s", desthost); + return 1; + } + else { + destport = ntohs(((struct sockaddr_in *)(&zhostlist->ai_addr))->sin_port); + } } sess = tcp_socket(PF_INET, SOCK_STREAM, 0, 0); @@ -637,11 +564,11 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func)) return 1; } - for (addrp = zthost->h_addr_list; err && *addrp; addrp++) { - if (zthost->h_length != 4) + for (zai = zhostlist; err && zai; zai = zai->ai_next) { + if (zai->ai_addrlen != 4) zwarnnam(nam, "address length mismatch"); do { - err = tcp_connect(sess, *addrp, zthost, destport); + err = tcp_connect(sess, zai); } while (err && errno == EINTR && !errflag); } diff --git a/Src/Modules/tcp.mdd b/Src/Modules/tcp.mdd index 69fd4d6..d2bac21 100644 --- a/Src/Modules/tcp.mdd +++ b/Src/Modules/tcp.mdd @@ -1,6 +1,7 @@ name=zsh/net/tcp -link=dynamic +link=`if test x$ac_cv_func_getaddrinfo; then echo dynamic; else echo no; fi` load=no + functions='Functions/TCP/*' objects="tcp.o" diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c index af48e80..9f810f9 100644 --- a/Src/Modules/zftp.c +++ b/Src/Modules/zftp.c @@ -1697,12 +1697,12 @@ zftp_open(char *name, char **args, int flags) { struct protoent *zprotop; struct servent *zservp; - struct hostent *zhostp; + struct addrinfo *zai; char **addrp, *fname, *tmpptr, *portnam = "ftp"; char *hostnam, *hostsuffix; int err, tmout, port = -1; ZSOCKLEN_T len; - int herrno, af, hlen; + int af, hlen; if (!*args) { if (zfsess->userparams) @@ -1806,21 +1806,20 @@ zftp_open(char *name, char **args, int flags) #endif { off_t tcp_port; + struct addrinfo hints, *hostlist; + int gai_err; - zhostp = zsh_getipnodebyname(hostnam, af, 0, &herrno); - if (!zhostp || errflag) { - /* should use herror() here if available, but maybe - * needs configure test. on AIX it's present but not - * in headers. - * - * on the other hand, herror() is obsolete - */ + hints.ai_family = af; + + gai_err = getaddrinfo(hostnam, NULL, &hints, &hostlist); + + if (errflag || gai_err) { FAILED(); - zwarnnam(name, "host not found: %s", hostnam); + zwarnnam(name, "host lookup failure: %s", gai_strerror(gai_err)); alarm(0); return 1; } - zfsetparam("ZFTP_HOST", ztrdup(zhostp->h_name), ZFPM_READONLY); + zfsetparam("ZFTP_HOST", ztrdup(hostlist->ai_canonname), ZFPM_READONLY); /* careful with pointer types */ #if defined(HAVE_NTOHS) && defined(HAVE_HTONS) tcp_port = (off_t)ntohs((unsigned short)zservp->s_port); @@ -1845,7 +1844,6 @@ zftp_open(char *name, char **args, int flags) tcp_close(zfsess->control); zfsess->control = NULL; } - freehostent(zhostp); zfunsetparam("ZFTP_HOST"); zfunsetparam("ZFTP_PORT"); FAILED(); @@ -1864,17 +1862,16 @@ zftp_open(char *name, char **args, int flags) err = 1; /* try all possible IP's */ - for (addrp = zhostp->h_addr_list; err && *addrp; addrp++) { - if(hlen != zhostp->h_length) + for (zai = hostlist; err && zai; zai = zai->ai_next) { + if(hlen != zai->ai_addrlen) zwarnnam(name, "address length mismatch"); do { - err = tcp_connect(zfsess->control, *addrp, zhostp, zservp->s_port); + err = tcp_connect(zfsess->control, zai); } while (err && errno == EINTR && !errflag); /* you can check whether it's worth retrying here */ } if (err) { - freehostent(zhostp); zfclose(0); FAILED(); zwarnnam(name, "connect failed: %e", errno); @@ -1895,7 +1892,6 @@ zftp_open(char *name, char **args, int flags) zsh_inet_ntop(af, *addrp, pbuf, sizeof(pbuf)); zfsetparam("ZFTP_IP", ztrdup(pbuf), ZFPM_READONLY); } - freehostent(zhostp); /* now we can talk to the control connection */ zcfinish = 0; diff --git a/Src/Modules/zftp.mdd b/Src/Modules/zftp.mdd index e96b367..f86056c 100644 --- a/Src/Modules/zftp.mdd +++ b/Src/Modules/zftp.mdd @@ -1,5 +1,5 @@ name=zsh/zftp -link=dynamic +link=`if test x$ac_cv_func_getaddrinfo; then echo dynamic; else echo no; fi` load=no functions='Functions/Zftp/*' diff --git a/configure.ac b/configure.ac index a3556d1..9a0cfae 100644 --- a/configure.ac +++ b/configure.ac @@ -1116,7 +1116,7 @@ AC_CHECK_FUNCS(strftime strptime mktime timelocal \ waitpid wait3 \ sigaction sigblock sighold sigrelse sigsetmask sigprocmask \ killpg setpgid setpgrp tcsetpgrp tcgetattr nice \ - gethostname gethostbyname2 getipnodebyname \ + gethostname getaddrinfo getnameinfo \ inet_aton inet_pton inet_ntop \ getlogin getpwent getpwnam getpwuid getgrgid getgrnam \ initgroups nis_list \