Author: jelmer Date: 2007-04-24 13:55:04 +0000 (Tue, 24 Apr 2007) New Revision: 22503
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=22503 Log: Add support for dgram to socket_ipv6. No tests yet... Modified: branches/SAMBA_4_0/ branches/SAMBA_4_0/source/lib/socket/socket_ipv6.c Changeset: Property changes on: branches/SAMBA_4_0 ___________________________________________________________________ Name: bzr:merge ...skipped... Modified: branches/SAMBA_4_0/source/lib/socket/socket_ipv6.c =================================================================== --- branches/SAMBA_4_0/source/lib/socket/socket_ipv6.c 2007-04-24 12:56:23 UTC (rev 22502) +++ branches/SAMBA_4_0/source/lib/socket/socket_ipv6.c 2007-04-24 13:55:04 UTC (rev 22503) @@ -190,7 +190,12 @@ struct sockaddr_in cli_addr; socklen_t cli_addr_len = sizeof(cli_addr); int new_fd; + + if (sock->type != SOCKET_TYPE_STREAM) { + return NT_STATUS_INVALID_PARAMETER; + } + new_fd = accept(sock->fd, (struct sockaddr *)&cli_addr, &cli_addr_len); if (new_fd == -1) { return map_nt_error_from_unix(errno); @@ -249,6 +254,62 @@ return NT_STATUS_OK; } +static NTSTATUS ipv6_recvfrom(struct socket_context *sock, void *buf, + size_t wantlen, size_t *nread, + TALLOC_CTX *addr_ctx, struct socket_address **_src) +{ + ssize_t gotlen; + struct sockaddr_in6 *from_addr; + socklen_t from_len = sizeof(*from_addr); + struct socket_address *src; + struct hostent *he; + + src = talloc(addr_ctx, struct socket_address); + if (!src) { + return NT_STATUS_NO_MEMORY; + } + + src->family = sock->backend_name; + + from_addr = talloc(src, struct sockaddr_in6); + if (!from_addr) { + talloc_free(src); + return NT_STATUS_NO_MEMORY; + } + + src->sockaddr = (struct sockaddr *)from_addr; + + *nread = 0; + + gotlen = recvfrom(sock->fd, buf, wantlen, 0, + src->sockaddr, &from_len); + if (gotlen == 0) { + talloc_free(src); + return NT_STATUS_END_OF_FILE; + } else if (gotlen == -1) { + talloc_free(src); + return map_nt_error_from_unix(errno); + } + + src->sockaddrlen = from_len; + + he = gethostbyaddr((void *)&from_addr->sin6_addr, sizeof(from_addr->sin6_addr), AF_INET6); + if (he == NULL) { + talloc_free(src); + return NT_STATUS_INTERNAL_ERROR; + } + src->addr = talloc_strdup(src, he->h_name); + if (src->addr == NULL) { + talloc_free(src); + return NT_STATUS_NO_MEMORY; + } + src->port = ntohs(from_addr->sin6_port); + + *nread = gotlen; + *_src = src; + return NT_STATUS_OK; +} + static NTSTATUS ipv6_tcp_send(struct socket_context *sock, const DATA_BLOB *blob, size_t *sendlen) { @@ -266,6 +327,42 @@ return NT_STATUS_OK; } +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(errno); + } + + *sendlen = len; + + return NT_STATUS_OK; +} + static NTSTATUS ipv6_tcp_set_option(struct socket_context *sock, const char *option, const char *val) { set_socket_options(sock->fd, option); @@ -410,6 +507,8 @@ .fn_listen = ipv6_tcp_listen, .fn_accept = ipv6_tcp_accept, .fn_recv = ipv6_tcp_recv, + .fn_recvfrom = ipv6_recvfrom, + .fn_sendto = ipv6_sendto, .fn_send = ipv6_tcp_send, .fn_close = ipv6_tcp_close, .fn_pending = ipv6_pending, @@ -425,8 +524,5 @@ const struct socket_ops *socket_ipv6_ops(enum socket_type type) { - if (type != SOCKET_TYPE_STREAM) { - return NULL; - } return &ipv6_tcp_ops; }