#include "includes.h"
-/*******************************************************************
- Map a text hostname or IP address (IPv4 or IPv6) into a
- struct sockaddr_storage.
-******************************************************************/
-
-bool interpret_string_addr(struct sockaddr_storage *pss,
- const char *str,
- int flags)
-{
- struct addrinfo *res = NULL;
-#if defined(HAVE_IPV6)
- char addr[INET6_ADDRSTRLEN];
- unsigned int scope_id = 0;
-
- if (strchr_m(str, ':')) {
- char *p = strchr_m(str, '%');
-
- /*
- * Cope with link-local.
- * This is IP:v6:addr%ifname.
- */
-
- if (p && (p > str) && ((scope_id = if_nametoindex(p+1)) != 0)) {
- strlcpy(addr, str,
- MIN(PTR_DIFF(p,str)+1,
- sizeof(addr)));
- str = addr;
- }
- }
-#endif
-
- zero_sockaddr(pss);
-
- if (!interpret_string_addr_internal(&res, str, flags|AI_ADDRCONFIG)) {
- return false;
- }
- if (!res) {
- return false;
- }
- /* Copy the first sockaddr. */
- memcpy(pss, res->ai_addr, res->ai_addrlen);
-
-#if defined(HAVE_IPV6)
- if (pss->ss_family == AF_INET6 && scope_id) {
- struct sockaddr_in6 *ps6 = (struct sockaddr_in6 *)pss;
- if (IN6_IS_ADDR_LINKLOCAL(&ps6->sin6_addr) &&
- ps6->sin6_scope_id == 0) {
- ps6->sin6_scope_id = scope_id;
- }
- }
-#endif
-
- freeaddrinfo(res);
- return true;
-}
-
-/*******************************************************************
- Set an address to INADDR_ANY.
-******************************************************************/
-
-void zero_sockaddr(struct sockaddr_storage *pss)
-{
- memset(pss, '\0', sizeof(*pss));
- /* Ensure we're at least a valid sockaddr-storage. */
- pss->ss_family = AF_INET;
-}
-
/****************************************************************************
Get a port number in host byte order from a sockaddr_storage.
****************************************************************************/
return print_sockaddr_len(addr_buf, addr_len, (struct sockaddr *)&sa, length);
}
-#if 0
-/* Not currently used. JRA. */
/****************************************************************************
Return the port number we've bound to on a socket.
****************************************************************************/
-static int get_socket_port(int fd)
+int get_socket_port(int fd)
{
struct sockaddr_storage sa;
socklen_t length = sizeof(sa);
}
return -1;
}
-#endif
const char *client_name(int fd)
{
#endif
#ifdef TCP_FASTACK
{"TCP_FASTACK", IPPROTO_TCP, TCP_FASTACK, 0, OPT_INT},
+#endif
+#ifdef TCP_QUICKACK
+ {"TCP_QUICKACK", IPPROTO_TCP, TCP_QUICKACK, 0, OPT_BOOL},
#endif
{NULL,0,0,0,0}};
}
/****************************************************************************
- Read data from a socket with a timout in msec.
+ Read data from a file descriptor with a timout in msec.
mincount = if timeout, minimum to read before returning
maxcount = number to be read.
time_out = timeout in milliseconds
+ NB. This can be called with a non-socket fd, don't change
+ sys_read() to sys_recv() or other socket call.
****************************************************************************/
-NTSTATUS read_socket_with_timeout(int fd, char *buf,
+NTSTATUS read_fd_with_timeout(int fd, char *buf,
size_t mincnt, size_t maxcnt,
unsigned int time_out,
size_t *size_ret)
size_t nread = 0;
struct timeval timeout;
char addr[INET6_ADDRSTRLEN];
+ int save_errno;
/* just checking .... */
if (maxcnt <= 0)
readret = sys_read(fd, buf + nread, maxcnt - nread);
if (readret == 0) {
- DEBUG(5,("read_socket_with_timeout: "
+ DEBUG(5,("read_fd_with_timeout: "
"blocking read. EOF from client.\n"));
return NT_STATUS_END_OF_FILE;
}
if (readret == -1) {
+ save_errno = errno;
if (fd == get_client_fd()) {
/* Try and give an error message
* saying what client failed. */
- DEBUG(0,("read_socket_with_timeout: "
+ DEBUG(0,("read_fd_with_timeout: "
"client %s read error = %s.\n",
get_peer_addr(fd,addr,sizeof(addr)),
- strerror(errno) ));
+ strerror(save_errno) ));
} else {
- DEBUG(0,("read_socket_with_timeout: "
+ DEBUG(0,("read_fd_with_timeout: "
"read error = %s.\n",
- strerror(errno) ));
+ strerror(save_errno) ));
}
- return map_nt_error_from_unix(errno);
+ return map_nt_error_from_unix(save_errno);
}
nread += readret;
}
timeout.tv_usec = (long)(1000 * (time_out % 1000));
for (nread=0; nread < mincnt; ) {
+ if (fd < 0 || fd >= FD_SETSIZE) {
+ errno = EBADF;
+ return map_nt_error_from_unix(EBADF);
+ }
+
FD_ZERO(&fds);
FD_SET(fd,&fds);
/* Check if error */
if (selrtn == -1) {
+ save_errno = errno;
/* something is wrong. Maybe the socket is dead? */
if (fd == get_client_fd()) {
/* Try and give an error message saying
* what client failed. */
- DEBUG(0,("read_socket_with_timeout: timeout "
+ DEBUG(0,("read_fd_with_timeout: timeout "
"read for client %s. select error = %s.\n",
get_peer_addr(fd,addr,sizeof(addr)),
- strerror(errno) ));
+ strerror(save_errno) ));
} else {
- DEBUG(0,("read_socket_with_timeout: timeout "
+ DEBUG(0,("read_fd_with_timeout: timeout "
"read. select error = %s.\n",
- strerror(errno) ));
+ strerror(save_errno) ));
}
- return map_nt_error_from_unix(errno);
+ return map_nt_error_from_unix(save_errno);
}
/* Did we timeout ? */
if (selrtn == 0) {
- DEBUG(10,("read_socket_with_timeout: timeout read. "
+ DEBUG(10,("read_fd_with_timeout: timeout read. "
"select timed out.\n"));
return NT_STATUS_IO_TIMEOUT;
}
if (readret == 0) {
/* we got EOF on the file descriptor */
- DEBUG(5,("read_socket_with_timeout: timeout read. "
+ DEBUG(5,("read_fd_with_timeout: timeout read. "
"EOF from client.\n"));
return NT_STATUS_END_OF_FILE;
}
if (readret == -1) {
+ save_errno = errno;
/* the descriptor is probably dead */
if (fd == get_client_fd()) {
/* Try and give an error message
* saying what client failed. */
- DEBUG(0,("read_socket_with_timeout: timeout "
+ DEBUG(0,("read_fd_with_timeout: timeout "
"read to client %s. read error = %s.\n",
get_peer_addr(fd,addr,sizeof(addr)),
- strerror(errno) ));
+ strerror(save_errno) ));
} else {
- DEBUG(0,("read_socket_with_timeout: timeout "
+ DEBUG(0,("read_fd_with_timeout: timeout "
"read. read error = %s.\n",
- strerror(errno) ));
+ strerror(save_errno) ));
}
return map_nt_error_from_unix(errno);
}
}
/****************************************************************************
- Read data from the client, reading exactly N bytes.
+ Read data from an fd, reading exactly N bytes.
+ NB. This can be called with a non-socket fd, don't add dependencies
+ on socket calls.
****************************************************************************/
NTSTATUS read_data(int fd, char *buffer, size_t N)
{
- return read_socket_with_timeout(fd, buffer, N, N, 0, NULL);
+ return read_fd_with_timeout(fd, buffer, N, N, 0, NULL);
}
/****************************************************************************
Write all data from an iov array
+ NB. This can be called with a non-socket fd, don't add dependencies
+ on socket calls.
****************************************************************************/
ssize_t write_data_iov(int fd, const struct iovec *orig_iov, int iovcnt)
if (thistime < iov[0].iov_len) {
char *new_base =
(char *)iov[0].iov_base + thistime;
- iov[0].iov_base = new_base;
+ iov[0].iov_base = (void *)new_base;
iov[0].iov_len -= thistime;
break;
}
/****************************************************************************
Write data to a fd.
+ NB. This can be called with a non-socket fd, don't add dependencies
+ on socket calls.
****************************************************************************/
ssize_t write_data(int fd, const char *buffer, size_t N)
ssize_t ret;
struct iovec iov;
- iov.iov_base = CONST_DISCARD(char *, buffer);
+ iov.iov_base = CONST_DISCARD(void *, buffer);
iov.iov_len = N;
ret = write_data_iov(fd, &iov, 1);
int msg_type;
NTSTATUS status;
- status = read_socket_with_timeout(fd, inbuf, 4, 4, timeout, NULL);
+ status = read_fd_with_timeout(fd, inbuf, 4, 4, timeout, NULL);
if (!NT_STATUS_IS_OK(status)) {
return status;
len = MIN(len,maxlen);
}
- status = read_socket_with_timeout(
+ status = read_fd_with_timeout(
fd, buffer+4, len, len, timeout, &len);
if (!NT_STATUS_IS_OK(status)) {
int wait_nsec;
};
-static void open_socket_out_connected(struct async_req *subreq);
+static void open_socket_out_connected(struct tevent_req *subreq);
static int open_socket_out_state_destructor(struct open_socket_out_state *s)
{
Create an outgoing socket. timeout is in milliseconds.
**************************************************************************/
-struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- const struct sockaddr_storage *pss,
- uint16_t port,
- int timeout)
+struct tevent_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ const struct sockaddr_storage *pss,
+ uint16_t port,
+ int timeout)
{
char addr[INET6_ADDRSTRLEN];
- struct async_req *result, *subreq;
+ struct tevent_req *result, *subreq;
struct open_socket_out_state *state;
NTSTATUS status;
- if (!async_req_setup(mem_ctx, &result, &state,
- struct open_socket_out_state)) {
+ result = tevent_req_create(mem_ctx, &state,
+ struct open_socket_out_state);
+ if (result == NULL) {
return NULL;
}
state->ev = ev;
}
talloc_set_destructor(state, open_socket_out_state_destructor);
- if (!async_req_set_timeout(result, ev, timeval_set(0, timeout*1000))) {
+ if (!tevent_req_set_endtime(
+ result, ev, timeval_current_ofs(0, timeout*1000))) {
goto fail;
}
state->salen = sizeof(struct sockaddr_in);
}
+ if (pss->ss_family == AF_UNIX) {
+ state->salen = sizeof(struct sockaddr_un);
+ }
+
print_sockaddr(addr, sizeof(addr), &state->ss);
DEBUG(3,("Connecting to %s at port %u\n", addr, (unsigned int)port));
(struct sockaddr *)&state->ss,
state->salen);
if ((subreq == NULL)
- || !async_req_set_timeout(subreq, state->ev,
- timeval_set(0, state->wait_nsec))) {
- status = NT_STATUS_NO_MEMORY;
- goto post_status;
+ || !tevent_req_set_endtime(
+ subreq, state->ev,
+ timeval_current_ofs(0, state->wait_nsec))) {
+ goto fail;
}
- subreq->async.fn = open_socket_out_connected;
- subreq->async.priv = result;
+ tevent_req_set_callback(subreq, open_socket_out_connected, result);
return result;
post_status:
- if (!async_post_ntstatus(result, ev, status)) {
- goto fail;
- }
- return result;
+ tevent_req_nterror(result, status);
+ return tevent_req_post(result, ev);
fail:
TALLOC_FREE(result);
return NULL;
}
-static void open_socket_out_connected(struct async_req *subreq)
+static void open_socket_out_connected(struct tevent_req *subreq)
{
- struct async_req *req = talloc_get_type_abort(
- subreq->async.priv, struct async_req);
- struct open_socket_out_state *state = talloc_get_type_abort(
- req->private_data, struct open_socket_out_state);
- int err;
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq, struct tevent_req);
+ struct open_socket_out_state *state =
+ tevent_req_data(req, struct open_socket_out_state);
+ int ret;
int sys_errno;
- err = async_connect_recv(subreq, &sys_errno);
+ ret = async_connect_recv(subreq, &sys_errno);
TALLOC_FREE(subreq);
- if (err == 0) {
- async_req_done(req);
+ if (ret == 0) {
+ tevent_req_done(req);
return;
}
- if ((sys_errno == ETIME)
- || (sys_errno == EINPROGRESS)
- || (sys_errno == EALREADY)
- || (sys_errno == EAGAIN)) {
+ if (
+#ifdef ETIMEDOUT
+ (sys_errno == ETIMEDOUT) ||
+#endif
+ (sys_errno == EINPROGRESS) ||
+ (sys_errno == EALREADY) ||
+ (sys_errno == EAGAIN)) {
/*
* retry
subreq = async_connect_send(state, state->ev, state->fd,
(struct sockaddr *)&state->ss,
state->salen);
- if (async_req_nomem(subreq, req)) {
+ if (tevent_req_nomem(subreq, req)) {
return;
}
- if (!async_req_set_timeout(subreq, state->ev,
- timeval_set(0, state->wait_nsec))) {
- async_req_error(req, ENOMEM);
+ if (!tevent_req_set_endtime(
+ subreq, state->ev,
+ timeval_current_ofs(0, state->wait_nsec))) {
+ tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
return;
}
- subreq->async.fn = open_socket_out_connected;
- subreq->async.priv = req;
+ tevent_req_set_callback(subreq, open_socket_out_connected, req);
return;
}
#ifdef EISCONN
if (sys_errno == EISCONN) {
- async_req_done(req);
+ tevent_req_done(req);
return;
}
#endif
/* real error */
- async_req_error(req, sys_errno);
+ tevent_req_nterror(req, map_nt_error_from_unix(sys_errno));
}
-NTSTATUS open_socket_out_recv(struct async_req *req, int *pfd)
+NTSTATUS open_socket_out_recv(struct tevent_req *req, int *pfd)
{
- struct open_socket_out_state *state = talloc_get_type_abort(
- req->private_data, struct open_socket_out_state);
- int err;
+ struct open_socket_out_state *state =
+ tevent_req_data(req, struct open_socket_out_state);
+ NTSTATUS status;
- if (async_req_is_errno(req, &err)) {
- return map_nt_error_from_unix(err);
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
}
*pfd = state->fd;
state->fd = -1;
{
TALLOC_CTX *frame = talloc_stackframe();
struct event_context *ev;
- struct async_req *req;
+ struct tevent_req *req;
NTSTATUS status = NT_STATUS_NO_MEMORY;
ev = event_context_init(frame);
if (req == NULL) {
goto fail;
}
- while (req->state < ASYNC_REQ_DONE) {
- event_loop_once(ev);
+ if (!tevent_req_poll(req, ev)) {
+ status = NT_STATUS_INTERNAL_ERROR;
+ goto fail;
}
-
status = open_socket_out_recv(req, pfd);
fail:
TALLOC_FREE(frame);
int fd;
};
-static void open_socket_out_defer_waited(struct async_req *subreq);
-static void open_socket_out_defer_connected(struct async_req *subreq);
+static void open_socket_out_defer_waited(struct tevent_req *subreq);
+static void open_socket_out_defer_connected(struct tevent_req *subreq);
-struct async_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct timeval wait_time,
- const struct sockaddr_storage *pss,
- uint16_t port,
- int timeout)
+struct tevent_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct timeval wait_time,
+ const struct sockaddr_storage *pss,
+ uint16_t port,
+ int timeout)
{
- struct async_req *result, *subreq;
+ struct tevent_req *req, *subreq;
struct open_socket_out_defer_state *state;
- NTSTATUS status;
- if (!async_req_setup(mem_ctx, &result, &state,
- struct open_socket_out_defer_state)) {
+ req = tevent_req_create(mem_ctx, &state,
+ struct open_socket_out_defer_state);
+ if (req == NULL) {
return NULL;
}
state->ev = ev;
state->port = port;
state->timeout = timeout;
- subreq = async_wait_send(state, ev, wait_time);
+ subreq = tevent_wakeup_send(
+ state, ev,
+ timeval_current_ofs(wait_time.tv_sec, wait_time.tv_usec));
if (subreq == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto post_status;
- }
- subreq->async.fn = open_socket_out_defer_waited;
- subreq->async.priv = result;
- return result;
-
- post_status:
- if (!async_post_ntstatus(result, ev, status)) {
goto fail;
}
- return result;
+ tevent_req_set_callback(subreq, open_socket_out_defer_waited, req);
+ return req;
fail:
- TALLOC_FREE(result);
+ TALLOC_FREE(req);
return NULL;
}
-static void open_socket_out_defer_waited(struct async_req *subreq)
+static void open_socket_out_defer_waited(struct tevent_req *subreq)
{
- struct async_req *req = talloc_get_type_abort(
- subreq->async.priv, struct async_req);
- struct open_socket_out_defer_state *state = talloc_get_type_abort(
- req->private_data, struct open_socket_out_defer_state);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct open_socket_out_defer_state *state = tevent_req_data(
+ req, struct open_socket_out_defer_state);
bool ret;
- ret = async_wait_recv(subreq);
+ ret = tevent_wakeup_recv(subreq);
TALLOC_FREE(subreq);
if (!ret) {
- async_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
return;
}
subreq = open_socket_out_send(state, state->ev, &state->ss,
state->port, state->timeout);
- if (async_req_nomem(subreq, req)) {
+ if (tevent_req_nomem(subreq, req)) {
return;
}
- subreq->async.fn = open_socket_out_defer_connected;
- subreq->async.priv = req;
+ tevent_req_set_callback(subreq, open_socket_out_defer_connected, req);
}
-static void open_socket_out_defer_connected(struct async_req *subreq)
+static void open_socket_out_defer_connected(struct tevent_req *subreq)
{
- struct async_req *req = talloc_get_type_abort(
- subreq->async.priv, struct async_req);
- struct open_socket_out_defer_state *state = talloc_get_type_abort(
- req->private_data, struct open_socket_out_defer_state);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct open_socket_out_defer_state *state = tevent_req_data(
+ req, struct open_socket_out_defer_state);
NTSTATUS status;
status = open_socket_out_recv(subreq, &state->fd);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
- async_req_nterror(req, status);
+ tevent_req_nterror(req, status);
return;
}
- async_req_done(req);
+ tevent_req_done(req);
}
-NTSTATUS open_socket_out_defer_recv(struct async_req *req, int *pfd)
+NTSTATUS open_socket_out_defer_recv(struct tevent_req *req, int *pfd)
{
- struct open_socket_out_defer_state *state = talloc_get_type_abort(
- req->private_data, struct open_socket_out_defer_state);
+ struct open_socket_out_defer_state *state = tevent_req_data(
+ req, struct open_socket_out_defer_state);
NTSTATUS status;
- if (async_req_is_nterror(req, &status)) {
+ if (tevent_req_is_nterror(req, &status)) {
return status;
}
*pfd = state->fd;
for (i=0; i<num_addrs; i++) {
sockets[i] = socket(addrs[i].ss_family, SOCK_STREAM, 0);
- if (sockets[i] < 0)
+ if (sockets[i] < 0 || sockets[i] >= FD_SETSIZE)
goto done;
set_blocking(sockets[i], false);
}
FD_ZERO(&r_fds);
for (i=0; i<num_addrs; i++) {
- if (sockets[i] == -1)
+ if (sockets[i] < 0 || sockets[i] >= FD_SETSIZE) {
+ /* This cannot happen - ignore if so. */
continue;
+ }
FD_SET(sockets[i], &wr_fds);
FD_SET(sockets[i], &r_fds);
if (sockets[i]>maxfd)
for (i=0; i<num_addrs; i++) {
- if (sockets[i] == -1)
+ if (sockets[i] < 0 || sockets[i] >= FD_SETSIZE) {
+ /* This cannot happen - ignore if so. */
continue;
+ }
/* Stevens, Network Programming says that if there's a
* successful connect, the socket is only writable. Upon an
int open_udp_socket(const char *host, int port)
{
- int type = SOCK_DGRAM;
- struct sockaddr_in sock_out;
+ struct sockaddr_storage ss;
int res;
- struct in_addr addr;
- addr = interpret_addr2(host);
+ if (!interpret_string_addr(&ss, host, 0)) {
+ DEBUG(10,("open_udp_socket: can't resolve name %s\n",
+ host));
+ return -1;
+ }
- res = socket(PF_INET, type, 0);
+ res = socket(ss.ss_family, SOCK_DGRAM, 0);
if (res == -1) {
return -1;
}
- memset((char *)&sock_out,'\0',sizeof(sock_out));
- putip((char *)&sock_out.sin_addr,(char *)&addr);
- sock_out.sin_port = htons(port);
- sock_out.sin_family = PF_INET;
+#if defined(HAVE_IPV6)
+ if (ss.ss_family == AF_INET6) {
+ struct sockaddr_in6 *psa6;
+ psa6 = (struct sockaddr_in6 *)&ss;
+ psa6->sin6_port = htons(port);
+ if (psa6->sin6_scope_id == 0
+ && IN6_IS_ADDR_LINKLOCAL(&psa6->sin6_addr)) {
+ setup_linklocal_scope_id(
+ (struct sockaddr *)&ss);
+ }
+ }
+#endif
+ if (ss.ss_family == AF_INET) {
+ struct sockaddr_in *psa;
+ psa = (struct sockaddr_in *)&ss;
+ psa->sin_port = htons(port);
+ }
- if (sys_connect(res,(struct sockaddr *)&sock_out)) {
+ if (sys_connect(res,(struct sockaddr *)&ss)) {
close(res);
return -1;
}
return (const char *)tmp.data;
}
+/************************************************************
+ Is this my ip address ?
+************************************************************/
+
+static bool is_my_ipaddr(const char *ipaddr_str)
+{
+ struct sockaddr_storage ss;
+ struct iface_struct *nics;
+ int i, n;
+
+ if (!interpret_string_addr(&ss, ipaddr_str, AI_NUMERICHOST)) {
+ return false;
+ }
+
+ if (ismyaddr((struct sockaddr *)&ss)) {
+ return true;
+ }
+
+ if (is_zero_addr((struct sockaddr *)&ss) ||
+ is_loopback_addr((struct sockaddr *)&ss)) {
+ return false;
+ }
+
+ n = get_interfaces(talloc_tos(), &nics);
+ for (i=0; i<n; i++) {
+ if (sockaddr_equal((struct sockaddr *)&nics[i].ip, (struct sockaddr *)&ss)) {
+ TALLOC_FREE(nics);
+ return true;
+ }
+ }
+ TALLOC_FREE(nics);
+ return false;
+}
+
/************************************************************
Is this my name ?
************************************************************/
bool is_myname_or_ipaddr(const char *s)
{
TALLOC_CTX *ctx = talloc_tos();
- char addr[INET6_ADDRSTRLEN];
char *name = NULL;
const char *dnsname;
char *servername = NULL;
return true;
}
- /* Handle possible CNAME records - convert to an IP addr. */
+ /* Handle possible CNAME records - convert to an IP addr. list. */
if (!is_ipaddress(servername)) {
- /* Use DNS to resolve the name, but only the first address */
- struct sockaddr_storage ss;
- if (interpret_string_addr(&ss, servername, 0)) {
+ /* Use DNS to resolve the name, check all addresses. */
+ struct addrinfo *p = NULL;
+ struct addrinfo *res = NULL;
+
+ if (!interpret_string_addr_internal(&res,
+ servername,
+ AI_ADDRCONFIG)) {
+ return false;
+ }
+
+ for (p = res; p; p = p->ai_next) {
+ char addr[INET6_ADDRSTRLEN];
+ struct sockaddr_storage ss;
+
+ ZERO_STRUCT(ss);
+ memcpy(&ss, p->ai_addr, p->ai_addrlen);
print_sockaddr(addr,
sizeof(addr),
&ss);
- servername = addr;
+ if (is_my_ipaddr(addr)) {
+ freeaddrinfo(res);
+ return true;
+ }
}
+ freeaddrinfo(res);
}
/* Maybe its an IP address? */
if (is_ipaddress(servername)) {
- struct sockaddr_storage ss;
- struct iface_struct *nics;
- int i, n;
+ return is_my_ipaddr(servername);
+ }
- if (!interpret_string_addr(&ss, servername, AI_NUMERICHOST)) {
- return false;
- }
+ /* No match */
+ return false;
+}
- if (is_zero_addr((struct sockaddr *)&ss) ||
- is_loopback_addr((struct sockaddr *)&ss)) {
- return false;
- }
+struct getaddrinfo_state {
+ const char *node;
+ const char *service;
+ const struct addrinfo *hints;
+ struct addrinfo *res;
+ int ret;
+};
- nics = TALLOC_ARRAY(ctx, struct iface_struct,
- MAX_INTERFACES);
- if (!nics) {
- return false;
- }
- n = get_interfaces(nics, MAX_INTERFACES);
- for (i=0; i<n; i++) {
- if (sockaddr_equal((struct sockaddr *)&nics[i].ip, (struct sockaddr *)&ss)) {
- TALLOC_FREE(nics);
- return true;
- }
- }
- TALLOC_FREE(nics);
+static void getaddrinfo_do(void *private_data);
+static void getaddrinfo_done(struct tevent_req *subreq);
+
+struct tevent_req *getaddrinfo_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct fncall_context *ctx,
+ const char *node,
+ const char *service,
+ const struct addrinfo *hints)
+{
+ struct tevent_req *req, *subreq;
+ struct getaddrinfo_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct getaddrinfo_state);
+ if (req == NULL) {
+ return NULL;
}
- /* No match */
- return false;
+ state->node = node;
+ state->service = service;
+ state->hints = hints;
+
+ subreq = fncall_send(state, ev, ctx, getaddrinfo_do, state);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, getaddrinfo_done, req);
+ return req;
+}
+
+static void getaddrinfo_do(void *private_data)
+{
+ struct getaddrinfo_state *state =
+ (struct getaddrinfo_state *)private_data;
+
+ state->ret = getaddrinfo(state->node, state->service, state->hints,
+ &state->res);
+}
+
+static void getaddrinfo_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ int ret, err;
+
+ ret = fncall_recv(subreq, &err);
+ TALLOC_FREE(subreq);
+ if (ret == -1) {
+ tevent_req_error(req, err);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+int getaddrinfo_recv(struct tevent_req *req, struct addrinfo **res)
+{
+ struct getaddrinfo_state *state = tevent_req_data(
+ req, struct getaddrinfo_state);
+ int err;
+
+ if (tevent_req_is_unix_error(req, &err)) {
+ switch(err) {
+ case ENOMEM:
+ return EAI_MEMORY;
+ default:
+ return EAI_FAIL;
+ }
+ }
+ if (state->ret == 0) {
+ *res = state->res;
+ }
+ return state->ret;
}