*/
#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.
-****************************************************************************/
-
-uint16_t get_sockaddr_port(const struct sockaddr_storage *pss)
-{
- uint16_t port = 0;
-
- if (pss->ss_family != AF_INET) {
-#if defined(HAVE_IPV6)
- /* IPv6 */
- const struct sockaddr_in6 *sa6 =
- (const struct sockaddr_in6 *)pss;
- port = ntohs(sa6->sin6_port);
-#endif
- } else {
- const struct sockaddr_in *sa =
- (const struct sockaddr_in *)pss;
- port = ntohs(sa->sin_port);
- }
- return port;
-}
-
-/****************************************************************************
- Print out an IPv4 or IPv6 address from a struct sockaddr_storage.
-****************************************************************************/
-
-static char *print_sockaddr_len(char *dest,
- size_t destlen,
- const struct sockaddr *psa,
- socklen_t psalen)
-{
- if (destlen > 0) {
- dest[0] = '\0';
- }
- (void)sys_getnameinfo(psa,
- psalen,
- dest, destlen,
- NULL, 0,
- NI_NUMERICHOST);
- return dest;
-}
-
-/****************************************************************************
- Print out an IPv4 or IPv6 address from a struct sockaddr_storage.
-****************************************************************************/
-
-char *print_sockaddr(char *dest,
- size_t destlen,
- const struct sockaddr_storage *psa)
-{
- return print_sockaddr_len(dest, destlen, (struct sockaddr *)psa,
- sizeof(struct sockaddr_storage));
-}
-
-/****************************************************************************
- Print out a canonical IPv4 or IPv6 address from a struct sockaddr_storage.
-****************************************************************************/
-
-char *print_canonical_sockaddr(TALLOC_CTX *ctx,
- const struct sockaddr_storage *pss)
-{
- char addr[INET6_ADDRSTRLEN];
- char *dest = NULL;
- int ret;
-
- /* Linux getnameinfo() man pages says port is unitialized if
- service name is NULL. */
-
- ret = sys_getnameinfo((const struct sockaddr *)pss,
- sizeof(struct sockaddr_storage),
- addr, sizeof(addr),
- NULL, 0,
- NI_NUMERICHOST);
- if (ret != 0) {
- return NULL;
- }
-
- if (pss->ss_family != AF_INET) {
-#if defined(HAVE_IPV6)
- dest = talloc_asprintf(ctx, "[%s]", addr);
-#else
- return NULL;
-#endif
- } else {
- dest = talloc_asprintf(ctx, "%s", addr);
- }
-
- return dest;
-}
-
-/****************************************************************************
- Return the string of an IP address (IPv4 or IPv6).
-****************************************************************************/
-
-static const char *get_socket_addr(int fd, char *addr_buf, size_t addr_len)
-{
- struct sockaddr_storage sa;
- socklen_t length = sizeof(sa);
-
- /* Ok, returning a hard coded IPv4 address
- * is bogus, but it's just as bogus as a
- * zero IPv6 address. No good choice here.
- */
-
- strlcpy(addr_buf, "0.0.0.0", addr_len);
-
- if (fd == -1) {
- return addr_buf;
- }
-
- if (getsockname(fd, (struct sockaddr *)&sa, &length) < 0) {
- DEBUG(0,("getsockname failed. Error was %s\n",
- strerror(errno) ));
- return addr_buf;
- }
-
- 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)
-{
- struct sockaddr_storage sa;
- socklen_t length = sizeof(sa);
-
- if (fd == -1) {
- return -1;
- }
-
- if (getsockname(fd, (struct sockaddr *)&sa, &length) < 0) {
- DEBUG(0,("getpeername failed. Error was %s\n",
- strerror(errno) ));
- return -1;
- }
-
-#if defined(HAVE_IPV6)
- if (sa.ss_family == AF_INET6) {
- return ntohs(((struct sockaddr_in6 *)&sa)->sin6_port);
- }
-#endif
- if (sa.ss_family == AF_INET) {
- return ntohs(((struct sockaddr_in *)&sa)->sin_port);
- }
- return -1;
-}
-#endif
-
-const char *client_name(int fd)
-{
- return get_peer_name(fd,false);
-}
+#include "system/filesys.h"
+#include "memcache.h"
+#include "../lib/async_req/async_sock.h"
+#include "../lib/util/select.h"
+#include "lib/socket/interfaces.h"
+#include "../lib/util/tevent_unix.h"
+#include "../lib/util/tevent_ntstatus.h"
+#include "../lib/tsocket/tsocket.h"
const char *client_addr(int fd, char *addr, size_t addrlen)
{
return get_peer_addr(fd,addr,addrlen);
}
-const char *client_socket_addr(int fd, char *addr, size_t addr_len)
-{
- return get_socket_addr(fd, addr, addr_len);
-}
-
#if 0
/* Not currently used. JRA. */
int client_socket_port(int fd)
}
#endif
-/****************************************************************************
- Accessor functions to make thread-safe code easier later...
-****************************************************************************/
-
-void set_smb_read_error(enum smb_read_errors *pre,
- enum smb_read_errors newerr)
-{
- if (pre) {
- *pre = newerr;
- }
-}
-
-void cond_set_smb_read_error(enum smb_read_errors *pre,
- enum smb_read_errors newerr)
-{
- if (pre && *pre == SMB_READ_OK) {
- *pre = newerr;
- }
-}
-
/****************************************************************************
Determine if a file descriptor is in fact a socket.
****************************************************************************/
return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
}
-enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
-
-typedef struct smb_socket_option {
- const char *name;
- int level;
- int option;
- int value;
- int opttype;
-} smb_socket_option;
-
-static const smb_socket_option socket_options[] = {
- {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
- {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
- {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
-#ifdef TCP_NODELAY
- {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},
-#endif
-#ifdef TCP_KEEPCNT
- {"TCP_KEEPCNT", IPPROTO_TCP, TCP_KEEPCNT, 0, OPT_INT},
-#endif
-#ifdef TCP_KEEPIDLE
- {"TCP_KEEPIDLE", IPPROTO_TCP, TCP_KEEPIDLE, 0, OPT_INT},
-#endif
-#ifdef TCP_KEEPINTVL
- {"TCP_KEEPINTVL", IPPROTO_TCP, TCP_KEEPINTVL, 0, OPT_INT},
-#endif
-#ifdef IPTOS_LOWDELAY
- {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON},
-#endif
-#ifdef IPTOS_THROUGHPUT
- {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON},
-#endif
-#ifdef SO_REUSEPORT
- {"SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT, 0, OPT_BOOL},
-#endif
-#ifdef SO_SNDBUF
- {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT},
-#endif
-#ifdef SO_RCVBUF
- {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT},
-#endif
-#ifdef SO_SNDLOWAT
- {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT},
-#endif
-#ifdef SO_RCVLOWAT
- {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT},
-#endif
-#ifdef SO_SNDTIMEO
- {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT},
-#endif
-#ifdef SO_RCVTIMEO
- {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
-#endif
-#ifdef TCP_FASTACK
- {"TCP_FASTACK", IPPROTO_TCP, TCP_FASTACK, 0, OPT_INT},
-#endif
- {NULL,0,0,0,0}};
-
-/****************************************************************************
- Print socket options.
-****************************************************************************/
-
-static void print_socket_options(int s)
-{
- int value;
- socklen_t vlen = 4;
- const smb_socket_option *p = &socket_options[0];
-
- /* wrapped in if statement to prevent streams
- * leak in SCO Openserver 5.0 */
- /* reported on samba-technical --jerry */
- if ( DEBUGLEVEL >= 5 ) {
- DEBUG(5,("Socket options:\n"));
- for (; p->name != NULL; p++) {
- if (getsockopt(s, p->level, p->option,
- (void *)&value, &vlen) == -1) {
- DEBUGADD(5,("\tCould not test socket option %s.\n",
- p->name));
- } else {
- DEBUGADD(5,("\t%s = %d\n",
- p->name,value));
- }
- }
- }
- }
-
-/****************************************************************************
- Set user socket options.
-****************************************************************************/
-
-void set_socket_options(int fd, const char *options)
-{
- TALLOC_CTX *ctx = talloc_stackframe();
- char *tok;
-
- while (next_token_talloc(ctx, &options, &tok," \t,")) {
- int ret=0,i;
- int value = 1;
- char *p;
- bool got_value = false;
-
- if ((p = strchr_m(tok,'='))) {
- *p = 0;
- value = atoi(p+1);
- got_value = true;
- }
-
- for (i=0;socket_options[i].name;i++)
- if (strequal(socket_options[i].name,tok))
- break;
-
- if (!socket_options[i].name) {
- DEBUG(0,("Unknown socket option %s\n",tok));
- continue;
- }
-
- switch (socket_options[i].opttype) {
- case OPT_BOOL:
- case OPT_INT:
- ret = setsockopt(fd,socket_options[i].level,
- socket_options[i].option,
- (char *)&value,sizeof(int));
- break;
-
- case OPT_ON:
- if (got_value)
- DEBUG(0,("syntax error - %s "
- "does not take a value\n",tok));
-
- {
- int on = socket_options[i].value;
- ret = setsockopt(fd,socket_options[i].level,
- socket_options[i].option,
- (char *)&on,sizeof(int));
- }
- break;
- }
-
- if (ret != 0) {
- /* be aware that some systems like Solaris return
- * EINVAL to a setsockopt() call when the client
- * sent a RST previously - no need to worry */
- DEBUG(2,("Failed to set socket option %s (Error %s)\n",
- tok, strerror(errno) ));
- }
- }
-
- TALLOC_FREE(ctx);
- print_socket_options(fd);
-}
-
/****************************************************************************
Read from a socket.
****************************************************************************/
}
/****************************************************************************
- 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)
{
- fd_set fds;
- int selrtn;
+ int pollrtn;
ssize_t readret;
size_t nread = 0;
- struct timeval timeout;
- char addr[INET6_ADDRSTRLEN];
/* 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) {
- if (fd == get_client_fd()) {
- /* Try and give an error message
- * saying what client failed. */
- DEBUG(0,("read_socket_with_timeout: "
- "client %s read error = %s.\n",
- get_peer_addr(fd,addr,sizeof(addr)),
- strerror(errno) ));
- } else {
- DEBUG(0,("read_socket_with_timeout: "
- "read error = %s.\n",
- strerror(errno) ));
- }
return map_nt_error_from_unix(errno);
}
nread += readret;
system performance will suffer severely as
select always returns true on disk files */
- /* Set initial timeout */
- timeout.tv_sec = (time_t)(time_out / 1000);
- timeout.tv_usec = (long)(1000 * (time_out % 1000));
-
for (nread=0; nread < mincnt; ) {
- FD_ZERO(&fds);
- FD_SET(fd,&fds);
+ int revents;
- selrtn = sys_select_intr(fd+1,&fds,NULL,NULL,&timeout);
+ pollrtn = poll_intr_one_fd(fd, POLLIN|POLLHUP, time_out,
+ &revents);
/* Check if error */
- if (selrtn == -1) {
- /* 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 "
- "read for client %s. select error = %s.\n",
- get_peer_addr(fd,addr,sizeof(addr)),
- strerror(errno) ));
- } else {
- DEBUG(0,("read_socket_with_timeout: timeout "
- "read. select error = %s.\n",
- strerror(errno) ));
- }
+ if (pollrtn == -1) {
return map_nt_error_from_unix(errno);
}
/* Did we timeout ? */
- if (selrtn == 0) {
- DEBUG(10,("read_socket_with_timeout: timeout read. "
+ if ((pollrtn == 0) ||
+ ((revents & (POLLIN|POLLHUP|POLLERR)) == 0)) {
+ 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) {
- /* 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 "
- "read to client %s. read error = %s.\n",
- get_peer_addr(fd,addr,sizeof(addr)),
- strerror(errno) ));
- } else {
- DEBUG(0,("read_socket_with_timeout: timeout "
- "read. read error = %s.\n",
- strerror(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)
* discarding elements.
*/
- iov_copy = (struct iovec *)TALLOC_MEMDUP(
+ iov_copy = (struct iovec *)talloc_memdup(
talloc_tos(), orig_iov, sizeof(struct iovec) * iovcnt);
if (iov_copy == NULL) {
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 = discard_const_p(void, buffer);
iov.iov_len = N;
-
- ret = write_data_iov(fd, &iov, 1);
- if (ret >= 0) {
- return ret;
- }
-
- if (fd == get_client_fd()) {
- char addr[INET6_ADDRSTRLEN];
- /*
- * Try and give an error message saying what client failed.
- */
- DEBUG(0, ("write_data: write failure in writing to client %s. "
- "Error %s\n", get_peer_addr(fd,addr,sizeof(addr)),
- strerror(errno)));
- } else {
- DEBUG(0,("write_data: write failure. Error = %s\n",
- strerror(errno) ));
- }
-
- return -1;
+ return write_data_iov(fd, &iov, 1);
}
/****************************************************************************
{
unsigned char buf[4];
- buf[0] = SMBkeepalive;
+ buf[0] = NBSSkeepalive;
buf[1] = buf[2] = buf[3] = 0;
return(write_data(client,(char *)buf,4) == 4);
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 = smb_len(inbuf);
msg_type = CVAL(inbuf,0);
- if (msg_type == SMBkeepalive) {
+ if (msg_type == NBSSkeepalive) {
DEBUG(5,("Got keepalive packet\n"));
}
return NT_STATUS_OK;
}
-/****************************************************************************
- Read 4 bytes of a smb packet and return the smb length of the packet.
- Store the result in the buffer. This version of the function will
- never return a session keepalive (length of zero).
- Timeout is in milliseconds.
-****************************************************************************/
-
-NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
- size_t *len)
-{
- uint8_t msgtype = SMBkeepalive;
-
- while (msgtype == SMBkeepalive) {
- NTSTATUS status;
-
- status = read_smb_length_return_keepalive(fd, inbuf, timeout,
- len);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- msgtype = CVAL(inbuf, 0);
- }
-
- DEBUG(10,("read_smb_length: got smb length of %lu\n",
- (unsigned long)len));
-
- return NT_STATUS_OK;
-}
-
/****************************************************************************
Read an smb from a fd.
The timeout is in milliseconds.
status = read_smb_length_return_keepalive(fd,buffer,timeout,&len);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("receive_smb_raw: %s!\n", nt_errstr(status)));
+ DEBUG(0, ("read_fd_with_timeout failed, read "
+ "error = %s.\n", nt_errstr(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)) {
+ DEBUG(0, ("read_fd_with_timeout failed, read error = "
+ "%s.\n", nt_errstr(status)));
return status;
}
#endif /* SO_REUSEPORT */
}
+#ifdef HAVE_IPV6
+ /*
+ * As IPV6_V6ONLY is the default on some systems,
+ * we better try to be consistent and always use it.
+ *
+ * This also avoids using IPv4 via AF_INET6 sockets
+ * and makes sure %I never resolves to a '::ffff:192.168.0.1'
+ * string.
+ */
+ if (sock.ss_family == AF_INET6) {
+ int val = 1;
+ int ret;
+
+ ret = setsockopt(res, IPPROTO_IPV6, IPV6_V6ONLY,
+ (const void *)&val, sizeof(val));
+ if (ret == -1) {
+ if(DEBUGLVL(0)) {
+ dbgtext("open_socket_in(): IPV6_ONLY failed: ");
+ dbgtext("%s\n", strerror(errno));
+ }
+ close(res);
+ return -1;
+ }
+ }
+#endif
+
/* now we've got a socket - we need to bind it */
if (bind(res, (struct sockaddr *)&sock, slen) == -1 ) {
- if( DEBUGLVL(dlevel) && (port == SMB_PORT1 ||
- port == SMB_PORT2 || port == NMB_PORT) ) {
+ if( DEBUGLVL(dlevel) && (port == NMB_PORT ||
+ port == NBT_SMB_PORT ||
+ port == TCP_SMB_PORT) ) {
char addr[INET6_ADDRSTRLEN];
print_sockaddr(addr, sizeof(addr),
&sock);
struct open_socket_out_state {
int fd;
- struct event_context *ev;
+ struct tevent_context *ev;
struct sockaddr_storage ss;
socklen_t salen;
uint16_t port;
- int wait_nsec;
+ int wait_usec;
};
-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 tevent_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;
state->ss = *pss;
state->port = port;
- state->wait_nsec = 10000;
+ state->wait_usec = 10000;
state->salen = -1;
state->fd = socket(state->ss.ss_family, SOCK_STREAM, 0);
}
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_msec(timeout))) {
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));
subreq = async_connect_send(state, state->ev, state->fd,
(struct sockaddr *)&state->ss,
- state->salen);
+ state->salen, NULL, NULL, NULL);
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_usec))) {
+ 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_status(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);
- NTSTATUS status;
+ 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;
- status = async_connect_recv(subreq, &sys_errno);
+ ret = async_connect_recv(subreq, &sys_errno);
TALLOC_FREE(subreq);
- if (NT_STATUS_IS_OK(status)) {
- async_req_done(req);
+ if (ret == 0) {
+ tevent_req_done(req);
return;
}
- if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)
- || (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
*/
- if (state->wait_nsec < 250000) {
- state->wait_nsec *= 1.5;
+ if (state->wait_usec < 250000) {
+ state->wait_usec *= 1.5;
}
subreq = async_connect_send(state, state->ev, state->fd,
(struct sockaddr *)&state->ss,
- state->salen);
- if (async_req_nomem(subreq, req)) {
+ state->salen, NULL, NULL, NULL);
+ 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, NT_STATUS_NO_MEMORY);
+ if (!tevent_req_set_endtime(
+ subreq, state->ev,
+ timeval_current_ofs_usec(state->wait_usec))) {
+ 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, map_nt_error_from_unix(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);
+ struct open_socket_out_state *state =
+ tevent_req_data(req, struct open_socket_out_state);
NTSTATUS status;
- if (async_req_is_error(req, &status)) {
+ if (tevent_req_is_nterror(req, &status)) {
return status;
}
*pfd = state->fd;
return NT_STATUS_OK;
}
+/**
+* @brief open a socket
+*
+* @param pss a struct sockaddr_storage defining the address to connect to
+* @param port to connect to
+* @param timeout in MILLISECONDS
+* @param pfd file descriptor returned
+*
+* @return NTSTATUS code
+*/
NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port,
int timeout, int *pfd)
{
TALLOC_CTX *frame = talloc_stackframe();
- struct event_context *ev;
- struct async_req *req;
+ struct tevent_context *ev;
+ struct tevent_req *req;
NTSTATUS status = NT_STATUS_NO_MEMORY;
- ev = event_context_init(frame);
+ ev = samba_tevent_context_init(frame);
if (ev == NULL) {
goto fail;
}
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);
}
struct open_socket_out_defer_state {
- struct event_context *ev;
+ struct tevent_context *ev;
struct sockaddr_storage ss;
uint16_t port;
int timeout;
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 tevent_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_status(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);
- NTSTATUS status;
+ 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;
- status = async_wait_recv(subreq);
+ ret = tevent_wakeup_recv(subreq);
TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- async_req_error(req, status);
+ if (!ret) {
+ 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_error(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_error(req, &status)) {
+ if (tevent_req_is_nterror(req, &status)) {
return status;
}
*pfd = state->fd;
return NT_STATUS_OK;
}
-/*******************************************************************
- Create an outgoing TCP socket to the first addr that connects.
-
- This is for simultaneous connection attempts to port 445 and 139 of a host
- or for simultatneous connection attempts to multiple DCs at once. We return
- a socket fd of the first successful connection.
-
- @param[in] addrs list of Internet addresses and ports to connect to
- @param[in] num_addrs number of address/port pairs in the addrs list
- @param[in] timeout time after which we stop waiting for a socket connection
- to succeed, given in milliseconds
- @param[out] fd_index the entry in addrs which we successfully connected to
- @param[out] fd fd of the open and connected socket
- @return true on a successful connection, false if all connection attempts
- failed or we timed out
-*******************************************************************/
-
-bool open_any_socket_out(struct sockaddr_storage *addrs, int num_addrs,
- int timeout, int *fd_index, int *fd)
-{
- int i, resulting_index, res;
- int *sockets;
- bool good_connect;
-
- fd_set r_fds, wr_fds;
- struct timeval tv;
- int maxfd;
-
- int connect_loop = 10000; /* 10 milliseconds */
-
- timeout *= 1000; /* convert to microseconds */
-
- sockets = SMB_MALLOC_ARRAY(int, num_addrs);
-
- if (sockets == NULL)
- return false;
-
- resulting_index = -1;
-
- for (i=0; i<num_addrs; i++)
- sockets[i] = -1;
-
- for (i=0; i<num_addrs; i++) {
- sockets[i] = socket(addrs[i].ss_family, SOCK_STREAM, 0);
- if (sockets[i] < 0)
- goto done;
- set_blocking(sockets[i], false);
- }
-
- connect_again:
- good_connect = false;
-
- for (i=0; i<num_addrs; i++) {
- const struct sockaddr * a =
- (const struct sockaddr *)&(addrs[i]);
-
- if (sockets[i] == -1)
- continue;
-
- if (sys_connect(sockets[i], a) == 0) {
- /* Rather unlikely as we are non-blocking, but it
- * might actually happen. */
- resulting_index = i;
- goto done;
- }
-
- if (errno == EINPROGRESS || errno == EALREADY ||
-#ifdef EISCONN
- errno == EISCONN ||
-#endif
- errno == EAGAIN || errno == EINTR) {
- /* These are the error messages that something is
- progressing. */
- good_connect = true;
- } else if (errno != 0) {
- /* There was a direct error */
- close(sockets[i]);
- sockets[i] = -1;
- }
- }
-
- if (!good_connect) {
- /* All of the connect's resulted in real error conditions */
- goto done;
- }
-
- /* Lets see if any of the connect attempts succeeded */
-
- maxfd = 0;
- FD_ZERO(&wr_fds);
- FD_ZERO(&r_fds);
-
- for (i=0; i<num_addrs; i++) {
- if (sockets[i] == -1)
- continue;
- FD_SET(sockets[i], &wr_fds);
- FD_SET(sockets[i], &r_fds);
- if (sockets[i]>maxfd)
- maxfd = sockets[i];
- }
-
- tv.tv_sec = 0;
- tv.tv_usec = connect_loop;
-
- res = sys_select_intr(maxfd+1, &r_fds, &wr_fds, NULL, &tv);
-
- if (res < 0)
- goto done;
-
- if (res == 0)
- goto next_round;
-
- for (i=0; i<num_addrs; i++) {
-
- if (sockets[i] == -1)
- continue;
-
- /* Stevens, Network Programming says that if there's a
- * successful connect, the socket is only writable. Upon an
- * error, it's both readable and writable. */
-
- if (FD_ISSET(sockets[i], &r_fds) &&
- FD_ISSET(sockets[i], &wr_fds)) {
- /* readable and writable, so it's an error */
- close(sockets[i]);
- sockets[i] = -1;
- continue;
- }
-
- if (!FD_ISSET(sockets[i], &r_fds) &&
- FD_ISSET(sockets[i], &wr_fds)) {
- /* Only writable, so it's connected */
- resulting_index = i;
- goto done;
- }
- }
-
- next_round:
-
- timeout -= connect_loop;
- if (timeout <= 0)
- goto done;
- connect_loop *= 1.5;
- if (connect_loop > timeout)
- connect_loop = timeout;
- goto connect_again;
-
- done:
- for (i=0; i<num_addrs; i++) {
- if (i == resulting_index)
- continue;
- if (sockets[i] >= 0)
- close(sockets[i]);
- }
-
- if (resulting_index >= 0) {
- *fd_index = resulting_index;
- *fd = sockets[*fd_index];
- set_blocking(*fd, true);
- }
-
- free(sockets);
-
- return (resulting_index >= 0);
-}
/****************************************************************************
Open a connected UDP socket to host on port
**************************************************************************/
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;
+ socklen_t salen;
- 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);
+ }
+ salen = sizeof(struct sockaddr_in6);
+ } else
+#endif
+ if (ss.ss_family == AF_INET) {
+ struct sockaddr_in *psa;
+ psa = (struct sockaddr_in *)&ss;
+ psa->sin_port = htons(port);
+ salen = sizeof(struct sockaddr_in);
+ } else {
+ DEBUG(1, ("unknown socket family %d", ss.ss_family));
+ close(res);
+ return -1;
+ }
- if (sys_connect(res,(struct sockaddr *)&sock_out)) {
+ if (connect(res, (struct sockaddr *)&ss, salen)) {
close(res);
return -1;
}
}
if (getpeername(fd, (struct sockaddr *)pss, plength) < 0) {
- DEBUG(0,("getpeername failed. Error was %s\n",
- strerror(errno) ));
+ int level = (errno == ENOTCONN) ? 2 : 0;
+ DEBUG(level, ("getpeername failed. Error was %s\n",
+ strerror(errno)));
return addr_buf;
}
continue;
}
if (sockaddr_equal((const struct sockaddr *)res->ai_addr,
- (struct sockaddr *)pss)) {
+ (const struct sockaddr *)pss)) {
freeaddrinfo(ailist);
return true;
}
}
/*******************************************************************
- Return the DNS name of the remote end of a socket.
-******************************************************************/
+ Return the IP addr of the remote end of a socket as a string.
+ ******************************************************************/
-const char *get_peer_name(int fd, bool force_lookup)
+const char *get_peer_addr(int fd, char *addr, size_t addr_len)
+{
+ return get_peer_addr_internal(fd, addr, addr_len, NULL, NULL);
+}
+
+int get_remote_hostname(const struct tsocket_address *remote_address,
+ char **name,
+ TALLOC_CTX *mem_ctx)
{
- struct name_addr_pair nc;
- char addr_buf[INET6_ADDRSTRLEN];
- struct sockaddr_storage ss;
- socklen_t length = sizeof(ss);
- const char *p;
- int ret;
char name_buf[MAX_DNS_NAME_LENGTH];
char tmp_name[MAX_DNS_NAME_LENGTH];
+ struct name_addr_pair nc;
+ struct sockaddr_storage ss;
+ ssize_t len;
+ int rc;
+
+ if (!lp_hostname_lookups()) {
+ nc.name = tsocket_address_inet_addr_string(remote_address,
+ mem_ctx);
+ if (nc.name == NULL) {
+ return -1;
+ }
+
+ len = tsocket_address_bsd_sockaddr(remote_address,
+ (struct sockaddr *) &nc.ss,
+ sizeof(struct sockaddr_storage));
+ if (len < 0) {
+ return -1;
+ }
- /* reverse lookups can be *very* expensive, and in many
- situations won't work because many networks don't link dhcp
- with dns. To avoid the delay we avoid the lookup if
- possible */
- if (!lp_hostname_lookups() && (force_lookup == false)) {
- length = sizeof(nc.ss);
- nc.name = get_peer_addr_internal(fd, addr_buf, sizeof(addr_buf),
- (struct sockaddr *)&nc.ss, &length);
store_nc(&nc);
lookup_nc(&nc);
- return nc.name ? nc.name : "UNKNOWN";
+
+ if (nc.name == NULL) {
+ *name = talloc_strdup(mem_ctx, "UNKNOWN");
+ } else {
+ *name = talloc_strdup(mem_ctx, nc.name);
+ }
+ return 0;
}
lookup_nc(&nc);
- memset(&ss, '\0', sizeof(ss));
- p = get_peer_addr_internal(fd, addr_buf, sizeof(addr_buf), (struct sockaddr *)&ss, &length);
+ ZERO_STRUCT(ss);
- /* it might be the same as the last one - save some DNS work */
- if (sockaddr_equal((struct sockaddr *)&ss, (struct sockaddr *)&nc.ss)) {
- return nc.name ? nc.name : "UNKNOWN";
+ len = tsocket_address_bsd_sockaddr(remote_address,
+ (struct sockaddr *) &ss,
+ sizeof(struct sockaddr_storage));
+ if (len < 0) {
+ return -1;
}
- /* Not the same. We need to lookup. */
- if (fd == -1) {
- return "UNKNOWN";
+ /* it might be the same as the last one - save some DNS work */
+ if (sockaddr_equal((struct sockaddr *)&ss, (struct sockaddr *)&nc.ss)) {
+ if (nc.name == NULL) {
+ *name = talloc_strdup(mem_ctx, "UNKNOWN");
+ } else {
+ *name = talloc_strdup(mem_ctx, nc.name);
+ }
+ return 0;
}
/* Look up the remote host name. */
- ret = sys_getnameinfo((struct sockaddr *)&ss,
- length,
- name_buf,
- sizeof(name_buf),
- NULL,
- 0,
- 0);
-
- if (ret) {
- DEBUG(1,("get_peer_name: getnameinfo failed "
- "for %s with error %s\n",
- p,
- gai_strerror(ret)));
+ rc = sys_getnameinfo((struct sockaddr *) &ss,
+ len,
+ name_buf,
+ sizeof(name_buf),
+ NULL,
+ 0,
+ 0);
+ if (rc < 0) {
+ char *p;
+
+ p = tsocket_address_inet_addr_string(remote_address, mem_ctx);
+ if (p == NULL) {
+ return -1;
+ }
+
+ DEBUG(1,("getnameinfo failed for %s with error %s\n",
+ p,
+ gai_strerror(rc)));
strlcpy(name_buf, p, sizeof(name_buf));
+
+ TALLOC_FREE(p);
} else {
- if (!matchname(name_buf, (struct sockaddr *)&ss, length)) {
- DEBUG(0,("Matchname failed on %s %s\n",name_buf,p));
- strlcpy(name_buf,"UNKNOWN",sizeof(name_buf));
+ if (!matchname(name_buf, (struct sockaddr *)&ss, len)) {
+ DEBUG(0,("matchname failed on %s\n", name_buf));
+ strlcpy(name_buf, "UNKNOWN", sizeof(name_buf));
}
}
- /* can't pass the same source and dest strings in when you
- use --enable-developer or the clobber_region() call will
- get you */
-
strlcpy(tmp_name, name_buf, sizeof(tmp_name));
alpha_strcpy(name_buf, tmp_name, "_-.", sizeof(name_buf));
if (strstr(name_buf,"..")) {
store_nc(&nc);
lookup_nc(&nc);
- return nc.name ? nc.name : "UNKNOWN";
-}
-/*******************************************************************
- Return the IP addr of the remote end of a socket as a string.
- ******************************************************************/
+ if (nc.name == NULL) {
+ *name = talloc_strdup(mem_ctx, "UNKOWN");
+ } else {
+ *name = talloc_strdup(mem_ctx, nc.name);
+ }
-const char *get_peer_addr(int fd, char *addr, size_t addr_len)
-{
- return get_peer_addr_internal(fd, addr, addr_len, NULL, NULL);
+ return 0;
}
/*******************************************************************
{
#ifdef HAVE_UNIXSOCKET
struct sockaddr_un sunaddr;
- struct stat st;
- int sock;
+ bool ok;
+ int sock = -1;
mode_t old_umask;
char *path = NULL;
old_umask = umask(0);
- /* Create the socket directory or reuse the existing one */
-
- if (lstat(socket_dir, &st) == -1) {
- if (errno == ENOENT) {
- /* Create directory */
- if (mkdir(socket_dir, dir_perms) == -1) {
- DEBUG(0, ("error creating socket directory "
- "%s: %s\n", socket_dir,
- strerror(errno)));
- goto out_umask;
- }
- } else {
- DEBUG(0, ("lstat failed on socket directory %s: %s\n",
- socket_dir, strerror(errno)));
- goto out_umask;
- }
- } else {
- /* Check ownership and permission on existing directory */
- if (!S_ISDIR(st.st_mode)) {
- DEBUG(0, ("socket directory %s isn't a directory\n",
- socket_dir));
- goto out_umask;
- }
- if ((st.st_uid != sec_initial_uid()) ||
- ((st.st_mode & 0777) != dir_perms)) {
- DEBUG(0, ("invalid permissions on socket directory "
- "%s\n", socket_dir));
- goto out_umask;
- }
+ ok = directory_create_or_exist_strict(socket_dir,
+ sec_initial_uid(),
+ dir_perms);
+ if (!ok) {
+ goto out_close;
}
/* Create the socket file */
-
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock == -1) {
goto out_close;
}
- if (listen(sock, 5) == -1) {
- DEBUG(0, ("listen failed on pipe socket %s: %s\n", path,
- strerror(errno)));
- goto out_close;
- }
-
SAFE_FREE(path);
umask(old_umask);
if (sock != -1)
close(sock);
-out_umask:
umask(old_umask);
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 (is_zero_addr(&ss)) {
+ return false;
+ }
+
+ if (ismyaddr((struct sockaddr *)&ss) ||
+ is_loopback_addr((struct sockaddr *)&ss)) {
+ return true;
+ }
+
+ 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;
}
/* Optimize for the common case */
- if (strequal(servername, global_myname())) {
+ if (strequal(servername, lp_netbios_name())) {
return true;
}
return true;
}
- /* Handle possible CNAME records - convert to an IP addr. */
- 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)) {
- print_sockaddr(addr,
- sizeof(addr),
- &ss);
- servername = addr;
- }
- }
-
/* 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;
- }
+ /* Handle possible CNAME records - convert to an IP addr. list. */
+ {
+ /* Use DNS to resolve the name, check all addresses. */
+ struct addrinfo *p = NULL;
+ struct addrinfo *res = NULL;
- if (is_zero_addr((struct sockaddr *)&ss) ||
- is_loopback_addr((struct sockaddr *)&ss)) {
+ if (!interpret_string_addr_internal(&res,
+ servername,
+ AI_ADDRCONFIG)) {
return false;
}
- 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);
+ 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);
+ if (is_my_ipaddr(addr)) {
+ freeaddrinfo(res);
return true;
}
}
- TALLOC_FREE(nics);
+ freeaddrinfo(res);
}
/* No match */
return false;
}
+
+struct getaddrinfo_state {
+ const char *node;
+ const char *service;
+ const struct addrinfo *hints;
+ struct addrinfo *res;
+ int ret;
+};
+
+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;
+ }
+
+ 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;
+}
+
+int poll_one_fd(int fd, int events, int timeout, int *revents)
+{
+ struct pollfd *fds;
+ int ret;
+ int saved_errno;
+
+ fds = talloc_zero_array(talloc_tos(), struct pollfd, 1);
+ if (fds == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ fds[0].fd = fd;
+ fds[0].events = events;
+
+ ret = poll(fds, 1, timeout);
+
+ /*
+ * Assign whatever poll did, even in the ret<=0 case.
+ */
+ *revents = fds[0].revents;
+ saved_errno = errno;
+ TALLOC_FREE(fds);
+ errno = saved_errno;
+
+ return ret;
+}
+
+int poll_intr_one_fd(int fd, int events, int timeout, int *revents)
+{
+ struct pollfd pfd;
+ int ret;
+
+ pfd.fd = fd;
+ pfd.events = events;
+
+ ret = sys_poll_intr(&pfd, 1, timeout);
+ if (ret <= 0) {
+ *revents = 0;
+ return ret;
+ }
+ *revents = pfd.revents;
+ return 1;
+}