This adds basic IPv6 support to libnfs.
Since libnfs currently only support PORTMAPPER protocol up to version 2
the IPv6 support only works if the server runs Both MOUNT and NFS protocols
on the same ports for IPv6 as for IPv4.
To get full IPv6 support we need to add support for PORTMAPPER version 3
and use it for discovery when using IPv6
#include "win32_errnowrapper.h"
#endif
#include "win32_errnowrapper.h"
#endif
static int rpc_reconnect_requeue(struct rpc_context *rpc);
static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_storage *s);
static int rpc_reconnect_requeue(struct rpc_context *rpc);
static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_storage *s);
if (rpc->tcp_syncnt != RPC_PARAM_UNDEFINED) {
set_tcp_sockopt(rpc->fd, TCP_SYNCNT, rpc->tcp_syncnt);
}
if (rpc->tcp_syncnt != RPC_PARAM_UNDEFINED) {
set_tcp_sockopt(rpc->fd, TCP_SYNCNT, rpc->tcp_syncnt);
}
+#endif
+ break;
+ case AF_INET6:
+ socksize = sizeof(struct sockaddr_in6);
+ rpc->fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+#ifdef HAVE_NETINET_TCP_H
+ if (rpc->tcp_syncnt != RPC_PARAM_UNDEFINED) {
+ set_tcp_sockopt(rpc->fd, TCP_SYNCNT, rpc->tcp_syncnt);
+ }
* binding will usually succeed.
*/
{
* binding will usually succeed.
*/
{
- struct sockaddr_in sin;
+ struct sockaddr_storage ss;
static int portOfs = 0;
const int firstPort = 512; /* >= 512 according to Sun docs */
const int portCount = IPPORT_RESERVED - firstPort;
static int portOfs = 0;
const int firstPort = 512; /* >= 512 according to Sun docs */
const int portCount = IPPORT_RESERVED - firstPort;
/* skip well-known ports */
if (!getservbyport(port, "tcp")) {
/* skip well-known ports */
if (!getservbyport(port, "tcp")) {
- memset(&sin, 0, sizeof(sin));
- sin.sin_port = port;
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = 0;
+ memset(&ss, 0, sizeof(ss));
+
+ switch (s->ss_family) {
+ case AF_INET:
+ ((struct sockaddr_in *)&ss)->sin_port = port;
+ ((struct sockaddr_in *)&ss)->sin_family = AF_INET;
+#ifdef HAVE_SOCKADDR_LEN
+ ((struct sockaddr_in *)&ss)->sin_len = sizeof(struct sockaddr_in);
+#endif
+ break;
+ case AF_INET6:
+ ((struct sockaddr_in6 *)&ss)->sin6_port = port;
+ ((struct sockaddr_in6 *)&ss)->sin6_family = AF_INET6;
+#ifdef HAVE_SOCKADDR_LEN
+ ((struct sockaddr_in6 *)&ss)->sin6_len = sizeof(struct sockaddr_in);
+#endif
+ break;
+ }
- rc = bind(rpc->fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in));
+ rc = bind(rpc->fd, (struct sockaddr *)&ss, socksize);
#if !defined(WIN32)
/* we got EACCES, so don't try again */
if (rc != 0 && errno == EACCES)
#if !defined(WIN32)
/* we got EACCES, so don't try again */
if (rc != 0 && errno == EACCES)
int rpc_connect_async(struct rpc_context *rpc, const char *server, int port, rpc_cb cb, void *private_data)
{
int rpc_connect_async(struct rpc_context *rpc, const char *server, int port, rpc_cb cb, void *private_data)
{
- struct sockaddr_in *sin = (struct sockaddr_in *)&rpc->s;
+ struct addrinfo *ai = NULL;
assert(rpc->magic == RPC_CONTEXT_MAGIC);
assert(rpc->magic == RPC_CONTEXT_MAGIC);
- sin->sin_family = AF_INET;
- sin->sin_port = htons(port);
- if (inet_pton(AF_INET, server, &sin->sin_addr) != 1) {
- rpc_set_error(rpc, "Not a valid server ip address");
+ if (getaddrinfo(server, NULL, NULL, &ai) != 0) {
+ rpc_set_error(rpc, "Invalid address:%s. "
+ "Can not resolv into IPv4/v6 structure.", server);
- switch (rpc->s.ss_family) {
+ switch (ai->ai_family) {
+ ((struct sockaddr_in *)&rpc->s)->sin_family = ai->ai_family;
+ ((struct sockaddr_in *)&rpc->s)->sin_port = htons(port);
+#ifdef HAVE_SOCKADDR_LEN
+ ((struct sockaddr_in *)&rpc->s)->sin_len = sizeof(struct sockaddr_in);
+#endif
+ break;
+ case AF_INET6:
+ ((struct sockaddr_in6 *)&rpc->s)->sin6_family = ai->ai_family;
+ ((struct sockaddr_in6 *)&rpc->s)->sin6_port = htons(port);
- sin->sin_len = sizeof(struct sockaddr_in);
+ ((struct sockaddr_in6 *)&rpc->s)->sin6_len = sizeof(struct sockaddr_in6);
rpc->connect_cb = cb;
rpc->connect_data = private_data;
rpc->connect_cb = cb;
rpc->connect_data = private_data;
if (rpc_connect_sockaddr_async(rpc, &rpc->s) != 0) {
return -1;
}
if (rpc_connect_sockaddr_async(rpc, &rpc->s) != 0) {
return -1;
}