diff --git a/include/libbb.h b/include/libbb.h index dd23c704d..742d04031 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -316,7 +316,10 @@ int xconnect_stream(const len_and_sockaddr *lsa); /* Return malloc'ed len_and_sockaddr with socket address of host:port * Currently will return IPv4 or IPv6 sockaddrs only * (depending on host), but in theory nothing prevents e.g. - * UNIX socket address being returned, IPX sockaddr etc... */ + * UNIX socket address being returned, IPX sockaddr etc... + * On error does bb_error_msg and returns NULL */ +len_and_sockaddr* host2sockaddr(const char *host, int port); +/* Versions which die on error */ len_and_sockaddr* xhost2sockaddr(const char *host, int port); #if ENABLE_FEATURE_IPV6 /* Same, useful if you want to force family (e.g. IPv6) */ diff --git a/libbb/xconnect.c b/libbb/xconnect.c index e5bdaac38..c3ccc470b 100644 --- a/libbb/xconnect.c +++ b/libbb/xconnect.c @@ -164,8 +164,9 @@ USE_FEATURE_IPV6(sa_family_t af,) hint.ai_flags = ai_flags & ~DIE_ON_ERROR; rc = getaddrinfo(host, NULL, &hint, &result); if (rc || !result) { + bb_error_msg("bad address '%s'", org_host); if (ai_flags & DIE_ON_ERROR) - bb_error_msg_and_die("bad address '%s'", org_host); + sleep_and_die(); goto ret; } r = xmalloc(offsetof(len_and_sockaddr, sa) + result->ai_addrlen); @@ -187,6 +188,11 @@ len_and_sockaddr* xhost_and_af2sockaddr(const char *host, int port, sa_family_t } #endif +len_and_sockaddr* host2sockaddr(const char *host, int port) +{ + return str2sockaddr(host, port, AF_UNSPEC, 0); +} + len_and_sockaddr* xhost2sockaddr(const char *host, int port) { return str2sockaddr(host, port, AF_UNSPEC, DIE_ON_ERROR); diff --git a/util-linux/mount.c b/util-linux/mount.c index 702c0338a..567514ccb 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -687,6 +687,8 @@ get_mountport(struct sockaddr_in *server_addr, static struct pmap p = {0, 0, 0, 0}; server_addr->sin_port = PMAPPORT; +/* glibc 2.4 (still) has pmap_getmaps(struct sockaddr_in *). + * I understand it like "IPv6 for this is not 100% ready" */ pmap = pmap_getmaps(server_addr); if (version > MAX_NFSPROT) @@ -1396,8 +1398,9 @@ static int singlemount(struct mntent *mp, int ignore_busy) && (mp->mnt_fsname[0]=='/' || mp->mnt_fsname[0]=='\\') && mp->mnt_fsname[0]==mp->mnt_fsname[1] ) { - struct hostent *he; - char ip[32], *s; + len_and_sockaddr *lsa; + char *ip, *dotted; + char *s; rc = 1; // Replace '/' with '\' and verify that unc points to "//server/share". @@ -1408,29 +1411,34 @@ static int singlemount(struct mntent *mp, int ignore_busy) // get server IP s = strrchr(mp->mnt_fsname, '\\'); - if (s == mp->mnt_fsname+1) goto report_error; + if (s <= mp->mnt_fsname+1) goto report_error; *s = '\0'; - he = gethostbyname(mp->mnt_fsname+2); + lsa = host2sockaddr(mp->mnt_fsname+2, 0); *s = '\\'; - if (!he) goto report_error; + if (!lsa) goto report_error; - // Insert ip=... option into string flags. (NOTE: Add IPv6 support.) + // insert ip=... option into string flags. - sprintf(ip, "ip=%d.%d.%d.%d", he->h_addr[0], he->h_addr[1], - he->h_addr[2], he->h_addr[3]); + dotted = xmalloc_sockaddr2dotted_noport(&lsa->sa, lsa->len); + ip = xasprintf("ip=%s", dotted); parse_mount_options(ip, &filteropts); // compose new unc '\\server-ip\share' + // (s => slash after hostname) - mp->mnt_fsname = xasprintf("\\\\%s%s", ip+3, - strchr(mp->mnt_fsname+2,'\\')); + mp->mnt_fsname = xasprintf("\\\\%s%s", dotted, s); // lock is required vfsflags |= MS_MANDLOCK; mp->mnt_type = (char*)"cifs"; rc = mount_it_now(mp, vfsflags, filteropts); - if (ENABLE_FEATURE_CLEAN_UP) free(mp->mnt_fsname); + if (ENABLE_FEATURE_CLEAN_UP) { + free(mp->mnt_fsname); + free(ip); + free(dotted); + free(lsa); + } goto report_error; } @@ -1508,8 +1516,9 @@ static int singlemount(struct mntent *mp, int ignore_busy) } } -report_error: - if (ENABLE_FEATURE_CLEAN_UP) free(filteropts); + report_error: + if (ENABLE_FEATURE_CLEAN_UP) + free(filteropts); if (rc && errno == EBUSY && ignore_busy) rc = 0; if (rc < 0)