diff options
Diffstat (limited to 'Src/Modules/tcp.c')
-rw-r--r-- | Src/Modules/tcp.c | 141 |
1 files changed, 107 insertions, 34 deletions
diff --git a/Src/Modules/tcp.c b/Src/Modules/tcp.c index 847bb6fc5..d1d4e5002 100644 --- a/Src/Modules/tcp.c +++ b/Src/Modules/tcp.c @@ -135,6 +135,79 @@ 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 */ @@ -238,23 +311,25 @@ tcp_close(Tcp_session sess) /**/ mod_export int -tcp_connect(Tcp_session sess, struct addrinfo *zai) +tcp_connect(Tcp_session sess, char *addrp, struct hostent *zhost, int d_port) { int salen; #ifdef SUPPORT_IPV6 - if (zai->ai_family==AF_INET6) { - memcpy(&(sess->peer.in6.sin6_addr), zai->ai_addr, zai->ai_addrlen); + if (zhost->h_addrtype==AF_INET6) { + memcpy(&(sess->peer.in6.sin6_addr), addrp, zhost->h_length); + sess->peer.in6.sin6_port = d_port; 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 = zai->ai_family; + sess->peer.in6.sin6_family = zhost->h_addrtype; salen = sizeof(struct sockaddr_in6); } else #endif /* SUPPORT_IPV6 */ { - memcpy(&(sess->peer.in.sin_addr), zai->ai_addr, zai->ai_addrlen); - sess->peer.in.sin_family = zai->ai_family; + 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; salen = sizeof(struct sockaddr_in); } @@ -264,13 +339,12 @@ tcp_connect(Tcp_session sess, struct addrinfo *zai) static int bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func)) { - int err=1, destport, force=0, verbose=0, test=0, targetfd=0; + int herrno, err=1, destport, force=0, verbose=0, test=0, targetfd=0; ZSOCKLEN_T len; - char *desthost, *localname, *remotename; - char zthostname[1025], ztpeername[1025]; + char **addrp, *desthost, *localname, *remotename; + struct hostent *zthost = NULL, *ztpeer = NULL; struct servent *srv; Tcp_session sess = NULL; - struct addrinfo *zhostlist, *zai; if (OPT_ISSET(ops,'f')) force = 1; @@ -487,16 +561,16 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func)) if (sess->fd != -1) { - if (getnameinfo((const struct sockaddr *)&(sess->sock.in.sin_addr), sizeof(struct sockaddr_in), zthostname, 1025, NULL, 0, 0)) + zthost = gethostbyaddr((const void *)&(sess->sock.in.sin_addr), sizeof(sess->sock.in.sin_addr), AF_INET); + if (zthost) + localname = zthost->h_name; + else 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) @@ -528,21 +602,20 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func)) destport = htons(23); } else { - struct addrinfo hints; - - 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); - } + 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; } sess = tcp_socket(PF_INET, SOCK_STREAM, 0, 0); @@ -564,11 +637,11 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func)) return 1; } - for (zai = zhostlist; err && zai; zai = zai->ai_next) { - if (zai->ai_addrlen != 4) + for (addrp = zthost->h_addr_list; err && *addrp; addrp++) { + if (zthost->h_length != 4) zwarnnam(nam, "address length mismatch"); do { - err = tcp_connect(sess, zai); + err = tcp_connect(sess, *addrp, zthost, destport); } while (err && errno == EINTR && !errflag); } |