* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
- * $Id: commio.c 26254 2008-12-10 04:04:38Z androsyn $
*/
+
#include <librb_config.h>
#include <rb_lib.h>
#include <commio-int.h>
#endif
#ifndef HAVE_SOCKETPAIR
-static int rb_inet_socketpair(int d, int type, int protocol, int sv[2]);
+static int rb_inet_socketpair(int d, int type, int protocol, rb_platform_fd_t sv[2]);
static int rb_inet_socketpair_udp(rb_fde_t **newF1, rb_fde_t **newF2);
#endif
RB_DLINK_FOREACH_SAFE(ptr, next, closed_list.head)
{
F = ptr->data;
+
+ number_fd--;
+
+#ifdef _WIN32
+ if(F->type & (RB_FD_SOCKET | RB_FD_PIPE))
+ closesocket(F->fd);
+ else
+#endif
+ close(F->fd);
+
rb_dlinkDelete(ptr, &closed_list);
rb_bh_free(fd_heap, F);
}
/*
* void rb_connect_tcp(rb_platform_fd_t fd, struct sockaddr *dest,
- * struct sockaddr *clocal, int socklen,
+ * struct sockaddr *clocal,
* CNCB *callback, void *data, int timeout)
* Input: An fd to connect with, a host and port to connect to,
- * a local sockaddr to connect from + length(or NULL to use the
+ * a local sockaddr to connect from (or NULL to use the
* default), a callback, the data to pass into the callback, the
* address family.
* Output: None.
*/
void
rb_connect_tcp(rb_fde_t *F, struct sockaddr *dest,
- struct sockaddr *clocal, int socklen, CNCB * callback, void *data, int timeout)
+ struct sockaddr *clocal, CNCB * callback, void *data, int timeout)
{
if(F == NULL)
return;
* virtual host IP, for completeness.
* -- adrian
*/
- if((clocal != NULL) && (bind(F->fd, clocal, socklen) < 0))
+ if((clocal != NULL) && (bind(F->fd, clocal, GET_SS_LEN(clocal)) < 0))
{
/* Failure, call the callback with RB_ERR_BIND */
rb_connect_callback(F, RB_ERR_BIND);
int
rb_socketpair(int family, int sock_type, int proto, rb_fde_t **F1, rb_fde_t **F2, const char *note)
{
- int nfd[2];
+ rb_platform_fd_t nfd[2];
if(number_fd >= rb_maxconnections)
{
errno = ENFILE;
if(family == AF_INET6)
{
int off = 1;
- if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)) == -1)
+ if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void *) &off, sizeof(off)) == -1)
{
rb_lib_log("rb_socket: Could not set IPV6_V6ONLY option to 1 on FD %d: %s",
fd, strerror(errno));
ClearFDOpen(F);
}
- number_fd--;
-
-#ifdef _WIN32
- if(type & (RB_FD_SOCKET | RB_FD_PIPE))
- {
- closesocket(fd);
- return;
- }
- else
-#endif
- close(fd);
+ if(type & RB_FD_LISTEN)
+ shutdown(fd, SHUT_RDWR);
}
return 0;
}
-int
+rb_platform_fd_t
rb_get_fd(rb_fde_t *F)
{
if(F == NULL)
{
if(rb_inet_pton(AF_INET, src, &((struct sockaddr_in *)dst)->sin_addr))
{
- ((struct sockaddr_in *)dst)->sin_port = 0;
- ((struct sockaddr_in *)dst)->sin_family = AF_INET;
+ SET_SS_FAMILY(dst, AF_INET);
SET_SS_LEN(dst, sizeof(struct sockaddr_in));
return 1;
}
#ifdef RB_IPV6
else if(rb_inet_pton(AF_INET6, src, &((struct sockaddr_in6 *)dst)->sin6_addr))
{
- ((struct sockaddr_in6 *)dst)->sin6_port = 0;
- ((struct sockaddr_in6 *)dst)->sin6_family = AF_INET6;
+ SET_SS_FAMILY(dst, AF_INET6);
SET_SS_LEN(dst, sizeof(struct sockaddr_in6));
return 1;
}
#endif
+ SET_SS_PORT(dst, 0);
return 0;
}
}
-
int
rb_ignore_errno(int error)
{
if(count > 0)
{
+ size_t ucount = (size_t)count;
int len = CMSG_SPACE(sizeof(int) * count);
char buf[len];
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * count);
- for(unsigned int i = 0; i < count; i++)
+ for(size_t i = 0; i < ucount; i++)
{
((int *)CMSG_DATA(cmsg))[i] = rb_get_fd(F[i]);
}
}
return sendmsg(rb_get_fd(xF), &msg, MSG_NOSIGNAL);
}
-#else
+#else /* defined(HAVE_SENDMSG) && !defined(WIN32) */
#ifndef _WIN32
int
rb_recv_fd_buf(rb_fde_t *F, void *data, size_t datasize, rb_fde_t **xF, int nfds)
errno = ENOSYS;
return -1;
}
-#endif
-#endif
+#endif /* _WIN32 */
+#endif /* defined(HAVE_SENDMSG) && !defined(WIN32) */
+
+#ifdef RB_IPV6
+int
+rb_ipv4_from_ipv6(const struct sockaddr_in6 *restrict ip6, struct sockaddr_in *restrict ip4)
+{
+ int i;
+
+ if (!memcmp(ip6->sin6_addr.s6_addr, "\x20\x02", 2))
+ {
+ /* 6to4 and similar */
+ memcpy(&ip4->sin_addr, ip6->sin6_addr.s6_addr + 2, 4);
+ }
+ else if (!memcmp(ip6->sin6_addr.s6_addr, "\x20\x01\x00\x00", 4))
+ {
+ /* Teredo */
+ for (i = 0; i < 4; i++)
+ ((uint8_t *)&ip4->sin_addr)[i] = 0xFF ^
+ ip6->sin6_addr.s6_addr[12 + i];
+ }
+ else
+ return 0;
+ SET_SS_LEN(ip4, sizeof(struct sockaddr_in));
+ ip4->sin_family = AF_INET;
+ ip4->sin_port = 0;
+ return 1;
+}
+#else
+int
+rb_ipv4_from_ipv6(const struct sockaddr_in6 *restrict ip6, struct sockaddr_in *restrict ip4)
+{
+ return 0;
+}
+#endif /* RB_IPV6 */