X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/e49147e56ea8973e235400ea9c84cd3205b0dce5..de2934965c2c685270d123aa2e4fd0088511803c:/librb/src/commio.c diff --git a/librb/src/commio.c b/librb/src/commio.c index 21bc226e..a131b7eb 100644 --- a/librb/src/commio.c +++ b/librb/src/commio.c @@ -21,8 +21,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA * - * $Id: commio.c 26254 2008-12-10 04:04:38Z androsyn $ */ + #include #include #include @@ -69,9 +69,7 @@ int rb_maxconnections = 0; static PF rb_connect_timeout; static PF rb_connect_tryconnect; -#ifdef RB_IPV6 static void mangle_mapped_sockaddr(struct sockaddr *in); -#endif #ifndef HAVE_SOCKETPAIR static int rb_inet_socketpair(int d, int type, int protocol, rb_platform_fd_t sv[2]); @@ -110,6 +108,16 @@ free_fds(void) 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); } @@ -336,11 +344,14 @@ rb_accept_tryaccept(rb_fde_t *F, void *data) { struct rb_sockaddr_storage st; rb_fde_t *new_F; - rb_socklen_t addrlen = sizeof(st); + rb_socklen_t addrlen; int new_fd; while(1) { + memset(&st, 0, sizeof(st)); + addrlen = sizeof(st); + new_fd = accept(F->fd, (struct sockaddr *)&st, &addrlen); rb_get_errno(); if(new_fd < 0) @@ -369,9 +380,7 @@ rb_accept_tryaccept(rb_fde_t *F, void *data) rb_close(new_F); } -#ifdef RB_IPV6 mangle_mapped_sockaddr((struct sockaddr *)&st); -#endif if(F->accept->precb != NULL) { @@ -410,10 +419,10 @@ rb_accept_tcp(rb_fde_t *F, ACPRE * precb, ACCB * callback, void *data) /* * 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. @@ -423,7 +432,7 @@ rb_accept_tcp(rb_fde_t *F, ACPRE * precb, ACCB * callback, void *data) */ 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; @@ -442,7 +451,7 @@ rb_connect_tcp(rb_fde_t *F, struct sockaddr *dest, * 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); @@ -695,7 +704,6 @@ rb_socket(int family, int sock_type, int proto, const char *note) if(rb_unlikely(fd < 0)) return NULL; /* errno will be passed through, yay.. */ -#if defined(RB_IPV6) && defined(IPV6_V6ONLY) /* * Make sure we can take both IPv4 and IPv6 connections * on an AF_INET6 socket @@ -703,7 +711,7 @@ rb_socket(int family, int sock_type, int proto, const char *note) 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)); @@ -711,7 +719,6 @@ rb_socket(int family, int sock_type, int proto, const char *note) return NULL; } } -#endif F = rb_open(fd, RB_FD_SOCKET, note); if(F == NULL) @@ -736,15 +743,11 @@ rb_socket(int family, int sock_type, int proto, const char *note) * If a sockaddr_storage is AF_INET6 but is a mapped IPv4 * socket manged the sockaddr. */ -#ifdef RB_IPV6 static void mangle_mapped_sockaddr(struct sockaddr *in) { struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)in; - if(in->sa_family == AF_INET) - return; - if(in->sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&in6->sin6_addr)) { struct sockaddr_in in4; @@ -754,9 +757,7 @@ mangle_mapped_sockaddr(struct sockaddr *in) in4.sin_addr.s_addr = ((uint32_t *)&in6->sin6_addr)[3]; memcpy(in, &in4, sizeof(struct sockaddr_in)); } - return; } -#endif /* * rb_listen() - listen on a port @@ -886,17 +887,8 @@ rb_close(rb_fde_t *F) 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); } @@ -970,7 +962,7 @@ rb_fd_ssl(rb_fde_t *F) return 0; } -int +rb_platform_fd_t rb_get_fd(rb_fde_t *F) { if(F == NULL) @@ -1180,9 +1172,7 @@ inetntoa(const char *in) */ static const char *inet_ntop4(const unsigned char *src, char *dst, unsigned int size); -#ifdef RB_IPV6 static const char *inet_ntop6(const unsigned char *src, char *dst, unsigned int size); -#endif /* const char * * inet_ntop4(src, dst, size) @@ -1209,7 +1199,6 @@ inet_ntop4(const unsigned char *src, char *dst, unsigned int size) * author: * Paul Vixie, 1996. */ -#ifdef RB_IPV6 static const char * inet_ntop6(const unsigned char *src, char *dst, unsigned int size) { @@ -1314,27 +1303,24 @@ inet_ntop6(const unsigned char *src, char *dst, unsigned int size) } return memcpy(dst, tmp, tp - tmp); } -#endif int rb_inet_pton_sock(const char *src, struct sockaddr *dst) { 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_PORT(dst, 0); 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_PORT(dst, 0); SET_SS_LEN(dst, sizeof(struct sockaddr_in6)); return 1; } -#endif return 0; } @@ -1345,16 +1331,11 @@ rb_inet_ntop_sock(struct sockaddr *src, char *dst, unsigned int size) { case AF_INET: return (rb_inet_ntop(AF_INET, &((struct sockaddr_in *)src)->sin_addr, dst, size)); - break; -#ifdef RB_IPV6 case AF_INET6: return (rb_inet_ntop (AF_INET6, &((struct sockaddr_in6 *)src)->sin6_addr, dst, size)); - break; -#endif default: return NULL; - break; } } @@ -1373,7 +1354,6 @@ rb_inet_ntop(int af, const void *src, char *dst, unsigned int size) { case AF_INET: return (inet_ntop4(src, dst, size)); -#ifdef RB_IPV6 case AF_INET6: if(IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src) || IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)src)) @@ -1382,9 +1362,6 @@ rb_inet_ntop(int af, const void *src, char *dst, unsigned int size) s6_addr[12], dst, size)); else return (inet_ntop6(src, dst, size)); - - -#endif default: return (NULL); } @@ -1460,7 +1437,6 @@ inet_pton4(const char *src, unsigned char *dst) return (1); } -#ifdef RB_IPV6 /* int * inet_pton6(src, dst) * convert presentation level address to network order binary form. @@ -1573,7 +1549,7 @@ inet_pton6(const char *src, unsigned char *dst) memcpy(dst, tmp, IN6ADDRSZ); return (1); } -#endif + int rb_inet_pton(int af, const char *src, void *dst) { @@ -1581,7 +1557,6 @@ rb_inet_pton(int af, const char *src, void *dst) { case AF_INET: return (inet_pton4(src, dst)); -#ifdef RB_IPV6 case AF_INET6: /* Somebody might have passed as an IPv4 address this is sick but it works */ if(inet_pton4(src, dst)) @@ -1592,7 +1567,6 @@ rb_inet_pton(int af, const char *src, void *dst) } else return (inet_pton6(src, dst)); -#endif default: return (-1); } @@ -2096,7 +2070,6 @@ rb_setup_fd(rb_fde_t *F) } - int rb_ignore_errno(int error) { @@ -2223,6 +2196,7 @@ rb_send_fd_buf(rb_fde_t *xF, rb_fde_t **F, int count, void *data, size_t datasiz if(count > 0) { + size_t ucount = (size_t)count; int len = CMSG_SPACE(sizeof(int) * count); char buf[len]; @@ -2233,7 +2207,7 @@ rb_send_fd_buf(rb_fde_t *xF, rb_fde_t **F, int count, void *data, size_t datasiz 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]); } @@ -2242,7 +2216,7 @@ rb_send_fd_buf(rb_fde_t *xF, rb_fde_t **F, int count, void *data, size_t datasiz } 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) @@ -2257,5 +2231,30 @@ rb_send_fd_buf(rb_fde_t *xF, rb_fde_t **F, int count, void *data, size_t datasiz errno = ENOSYS; return -1; } -#endif -#endif +#endif /* _WIN32 */ +#endif /* defined(HAVE_SENDMSG) && !defined(WIN32) */ + +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; +}