mount: (try to) support cifs with IPv6
No binary (build failed)
—
(log yok)
| @@ -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) */ | |
| @@ -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); | |
| @@ -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) | |