static NTSTATUS ipv6_tcp_connect(struct socket_context *sock, const struct socket_address *my_address, const struct socket_address *srv_address, uint32_t flags) { int ret; if (my_address && my_address->sockaddr) { ret = bind(sock->fd, my_address->sockaddr, my_address->sockaddrlen); if (ret == -1) { return map_nt_error_from_unix_common(errno); } } else if (my_address) { struct in6_addr my_ip; my_ip = interpret_addr6(my_address->addr); if (memcmp(&my_ip, &in6addr_any, sizeof(my_ip)) || my_address->port != 0) { struct sockaddr_in6 my_addr; ZERO_STRUCT(my_addr); my_addr.sin6_addr = my_ip; my_addr.sin6_port = htons(my_address->port); my_addr.sin6_family = PF_INET6; ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr)); if (ret == -1) { return map_nt_error_from_unix_common(errno); } } } if (srv_address->sockaddr) { ret = connect(sock->fd, srv_address->sockaddr, srv_address->sockaddrlen); } else { struct in6_addr srv_ip; struct sockaddr_in6 srv_addr; srv_ip = interpret_addr6(srv_address->addr); if (memcmp(&srv_ip, &in6addr_any, sizeof(srv_ip)) == 0) { return NT_STATUS_BAD_NETWORK_NAME; } ZERO_STRUCT(srv_addr); srv_addr.sin6_addr = srv_ip; srv_addr.sin6_port = htons(srv_address->port); srv_addr.sin6_family = PF_INET6; ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr)); } if (ret == -1) { return map_nt_error_from_unix_common(errno); } return ip_connect_complete(sock, flags); }
static NTSTATUS ipv6_sendto(struct socket_context *sock, const DATA_BLOB *blob, size_t *sendlen, const struct socket_address *dest_addr) { ssize_t len; if (dest_addr->sockaddr) { len = sendto(sock->fd, blob->data, blob->length, 0, dest_addr->sockaddr, dest_addr->sockaddrlen); } else { struct sockaddr_in6 srv_addr; struct in6_addr addr; ZERO_STRUCT(srv_addr); addr = interpret_addr6(dest_addr->addr); if (addr.s6_addr == 0) { return NT_STATUS_HOST_UNREACHABLE; } srv_addr.sin6_addr = addr; srv_addr.sin6_port = htons(dest_addr->port); srv_addr.sin6_family = PF_INET6; *sendlen = 0; len = sendto(sock->fd, blob->data, blob->length, 0, (struct sockaddr *)&srv_addr, sizeof(srv_addr)); } if (len == -1) { return map_nt_error_from_unix_common(errno); } *sendlen = len; return NT_STATUS_OK; }
static NTSTATUS ipv6_listen(struct socket_context *sock, const struct socket_address *my_address, int queue_size, uint32_t flags) { struct sockaddr_in6 my_addr; struct in6_addr ip_addr; int ret; socket_set_option(sock, "SO_REUSEADDR=1", NULL); if (my_address->sockaddr) { ret = bind(sock->fd, my_address->sockaddr, my_address->sockaddrlen); } else { int one = 1; ip_addr = interpret_addr6(my_address->addr); ZERO_STRUCT(my_addr); my_addr.sin6_addr = ip_addr; my_addr.sin6_port = htons(my_address->port); my_addr.sin6_family = PF_INET6; fix_scope_id(&my_addr, my_address->addr); /* when binding on ipv6 we always want to only bind on v6 */ ret = setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void *)&one, sizeof(one)); if (ret != -1) { ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr)); } } if (ret == -1) { return map_nt_error_from_unix_common(errno); } if (sock->type == SOCKET_TYPE_STREAM) { ret = listen(sock->fd, queue_size); if (ret == -1) { return map_nt_error_from_unix_common(errno); } } if (!(flags & SOCKET_FLAG_BLOCK)) { ret = set_blocking(sock->fd, false); if (ret == -1) { return map_nt_error_from_unix_common(errno); } } sock->state= SOCKET_STATE_SERVER_LISTEN; return NT_STATUS_OK; }
static NTSTATUS ipv6_listen(struct socket_context *sock, const struct socket_address *my_address, int queue_size, uint32_t flags) { struct sockaddr_in6 my_addr; struct in6_addr ip_addr; int ret; socket_set_option(sock, "SO_REUSEADDR=1", NULL); if (my_address->sockaddr) { ret = bind(sock->fd, my_address->sockaddr, my_address->sockaddrlen); } else { ip_addr = interpret_addr6(my_address->addr); ZERO_STRUCT(my_addr); my_addr.sin6_addr = ip_addr; my_addr.sin6_port = htons(my_address->port); my_addr.sin6_family = PF_INET6; ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr)); } if (ret == -1) { return map_nt_error_from_unix(errno); } if (sock->type == SOCKET_TYPE_STREAM) { ret = listen(sock->fd, queue_size); if (ret == -1) { return map_nt_error_from_unix(errno); } } if (!(flags & SOCKET_FLAG_BLOCK)) { ret = set_blocking(sock->fd, false); if (ret == -1) { return map_nt_error_from_unix(errno); } } sock->state= SOCKET_STATE_SERVER_LISTEN; return NT_STATUS_OK; }