#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);
if (count < 0) {
rpc_set_error(rpc, "Failed recvfrom: %s", strerror(errno));
free(buf);
+ return -1;
}
if (rpc_process_pdu(rpc, buf, count) != 0) {
rpc_set_error(rpc, "Invalid/garbage pdu received from server. Ignoring PDU");
pdu_size = rpc_get_pdu_size(rpc->inbuf);
if (rpc->insize < pdu_size) {
unsigned char *buf;
-
+
buf = malloc(pdu_size);
if (buf == NULL) {
rpc_set_error(rpc, "Failed to allocate buffer of %d bytes for pdu, errno:%d. Closing socket.", pdu_size, errno);
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);
+ }
#endif
break;
default:
* 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;
/* 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));
- rc = bind(rpc->fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in));
+ 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 *)&ss, socksize);
#if !defined(WIN32)
/* we got EACCES, so don't try again */
if (rc != 0 && errno == EACCES)
if (connect(rpc->fd, (struct sockaddr *)s, socksize) != 0 && errno != EINPROGRESS) {
rpc_set_error(rpc, "connect() to server failed. %s(%d)", strerror(errno), errno);
return -1;
- }
+ }
return 0;
-}
+}
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);
rpc->auto_reconnect = 0;
- 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);
return -1;
- }
-
+ }
- switch (rpc->s.ss_family) {
+ switch (ai->ai_family) {
case AF_INET:
+ ((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);
#ifdef HAVE_SOCKADDR_LEN
- sin->sin_len = sizeof(struct sockaddr_in);
+ ((struct sockaddr_in6 *)&rpc->s)->sin6_len = sizeof(struct sockaddr_in6);
#endif
break;
}
rpc->connect_cb = cb;
rpc->connect_data = private_data;
+ freeaddrinfo(ai);
+
if (rpc_connect_sockaddr_async(rpc, &rpc->s) != 0) {
return -1;
}
return 0;
-}
+}
int rpc_disconnect(struct rpc_context *rpc, char *error)
{
sprintf(service, "%d", port);
if (getaddrinfo(addr, service, NULL, &ai) != 0) {
rpc_set_error(rpc, "Invalid address:%s. "
- "Can not resolv into IPv4/v6 structure.");
+ "Can not resolv into IPv4/v6 structure.", addr);
return -1;
}
case AF_INET:
rpc->fd = socket(ai->ai_family, SOCK_DGRAM, 0);
if (rpc->fd == -1) {
- rpc_set_error(rpc, "Failed to create UDP socket: %s", strerror(errno));
+ rpc_set_error(rpc, "Failed to create UDP socket: %s", strerror(errno));
freeaddrinfo(ai);
return -1;
}
if (bind(rpc->fd, (struct sockaddr *)ai->ai_addr, sizeof(struct sockaddr_in)) != 0) {
- rpc_set_error(rpc, "Failed to bind to UDP socket: %s",strerror(errno));
+ rpc_set_error(rpc, "Failed to bind to UDP socket: %s",strerror(errno));
freeaddrinfo(ai);
return -1;
}
sprintf(service, "%d", port);
if (getaddrinfo(addr, service, NULL, &ai) != 0) {
rpc_set_error(rpc, "Invalid address:%s. "
- "Can not resolv into IPv4/v6 structure.");
+ "Can not resolv into IPv4/v6 structure.", addr);
return -1;
}
}
return i;
}
+
+void rpc_set_fd(struct rpc_context *rpc, int fd)
+{
+ assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
+ rpc->fd = fd;
+}