#include "includes.h"
#include "system/filesys.h"
-#include "memcache.h"
+#include "../lib/util/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_name(int fd)
-{
- return get_peer_name(fd,false);
-}
+#include "lib/util/sys_rw.h"
+#include "lib/util/sys_rw_data.h"
const char *client_addr(int fd, char *addr, size_t addrlen)
{
}
#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.
****************************************************************************/
on socket calls.
****************************************************************************/
-NTSTATUS read_data(int fd, char *buffer, size_t N)
+NTSTATUS read_data_ntstatus(int fd, char *buffer, size_t N)
{
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)
-{
- int i;
- size_t to_send;
- ssize_t thistime;
- size_t sent;
- struct iovec *iov_copy, *iov;
-
- to_send = 0;
- for (i=0; i<iovcnt; i++) {
- to_send += orig_iov[i].iov_len;
- }
-
- thistime = sys_writev(fd, orig_iov, iovcnt);
- if ((thistime <= 0) || (thistime == to_send)) {
- return thistime;
- }
- sent = thistime;
-
- /*
- * We could not send everything in one call. Make a copy of iov that
- * we can mess with. We keep a copy of the array start in iov_copy for
- * the TALLOC_FREE, because we're going to modify iov later on,
- * discarding elements.
- */
-
- iov_copy = (struct iovec *)talloc_memdup(
- talloc_tos(), orig_iov, sizeof(struct iovec) * iovcnt);
-
- if (iov_copy == NULL) {
- errno = ENOMEM;
- return -1;
- }
- iov = iov_copy;
-
- while (sent < to_send) {
- /*
- * We have to discard "thistime" bytes from the beginning
- * iov array, "thistime" contains the number of bytes sent
- * via writev last.
- */
- while (thistime > 0) {
- if (thistime < iov[0].iov_len) {
- char *new_base =
- (char *)iov[0].iov_base + thistime;
- iov[0].iov_base = (void *)new_base;
- iov[0].iov_len -= thistime;
- break;
- }
- thistime -= iov[0].iov_len;
- iov += 1;
- iovcnt -= 1;
- }
-
- thistime = sys_writev(fd, iov, iovcnt);
- if (thistime <= 0) {
- break;
- }
- sent += thistime;
- }
-
- TALLOC_FREE(iov_copy);
- return sent;
-}
-
-/****************************************************************************
- 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)
-{
- struct iovec iov;
-
- iov.iov_base = discard_const_p(void, buffer);
- iov.iov_len = N;
- return write_data_iov(fd, &iov, 1);
-}
-
/****************************************************************************
Send a keepalive packet (rfc1002).
****************************************************************************/
{
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);
*len = smb_len(inbuf);
msg_type = CVAL(inbuf,0);
- if (msg_type == SMBkeepalive) {
+ if (msg_type == NBSSkeepalive) {
DEBUG(5,("Got keepalive packet\n"));
}
/* 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_usec;
+ struct tevent_req *connect_subreq;
};
static void open_socket_out_connected(struct tevent_req *subreq);
-static int open_socket_out_state_destructor(struct open_socket_out_state *s)
+static void open_socket_out_cleanup(struct tevent_req *req,
+ enum tevent_req_state req_state)
{
- if (s->fd != -1) {
- close(s->fd);
+ struct open_socket_out_state *state =
+ tevent_req_data(req, struct open_socket_out_state);
+
+ /*
+ * Make sure that the async_connect_send subreq has a chance to reset
+ * fcntl before the socket goes away.
+ */
+ TALLOC_FREE(state->connect_subreq);
+
+ if (req_state == TEVENT_REQ_DONE) {
+ /*
+ * we keep the socket open for the caller to use
+ */
+ return;
+ }
+
+ if (state->fd != -1) {
+ close(state->fd);
+ state->fd = -1;
}
- return 0;
}
/****************************************************************************
**************************************************************************/
struct tevent_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
+ struct tevent_context *ev,
const struct sockaddr_storage *pss,
uint16_t port,
int timeout)
{
char addr[INET6_ADDRSTRLEN];
- struct tevent_req *result, *subreq;
+ struct tevent_req *result;
struct open_socket_out_state *state;
NTSTATUS status;
status = map_nt_error_from_unix(errno);
goto post_status;
}
- talloc_set_destructor(state, open_socket_out_state_destructor);
+
+ tevent_req_set_cleanup_fn(result, open_socket_out_cleanup);
if (!tevent_req_set_endtime(
result, ev, timeval_current_ofs_msec(timeout))) {
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);
- if ((subreq == NULL)
+ state->connect_subreq = async_connect_send(
+ state, state->ev, state->fd, (struct sockaddr *)&state->ss,
+ state->salen, NULL, NULL, NULL);
+ if ((state->connect_subreq == NULL)
|| !tevent_req_set_endtime(
- subreq, state->ev,
+ state->connect_subreq, state->ev,
timeval_current_ofs(0, state->wait_usec))) {
goto fail;
}
- tevent_req_set_callback(subreq, open_socket_out_connected, result);
+ tevent_req_set_callback(state->connect_subreq,
+ open_socket_out_connected, result);
return result;
post_status:
ret = async_connect_recv(subreq, &sys_errno);
TALLOC_FREE(subreq);
+ state->connect_subreq = NULL;
if (ret == 0) {
tevent_req_done(req);
return;
subreq = async_connect_send(state, state->ev, state->fd,
(struct sockaddr *)&state->ss,
- state->salen);
+ state->salen, NULL, NULL, NULL);
if (tevent_req_nomem(subreq, req)) {
return;
}
tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
return;
}
+ state->connect_subreq = subreq;
tevent_req_set_callback(subreq, open_socket_out_connected, req);
return;
}
NTSTATUS status;
if (tevent_req_is_nterror(req, &status)) {
+ tevent_req_received(req);
return status;
}
*pfd = state->fd;
state->fd = -1;
+ tevent_req_received(req);
return NT_STATUS_OK;
}
int timeout, int *pfd)
{
TALLOC_CTX *frame = talloc_stackframe();
- struct event_context *ev;
+ 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;
}
}
struct open_socket_out_defer_state {
- struct event_context *ev;
+ struct tevent_context *ev;
struct sockaddr_storage ss;
uint16_t port;
int timeout;
static void open_socket_out_defer_connected(struct tevent_req *subreq);
struct tevent_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
+ struct tevent_context *ev,
struct timeval wait_time,
const struct sockaddr_storage *pss,
uint16_t port,
{
struct sockaddr_storage ss;
int res;
+ socklen_t salen;
if (!interpret_string_addr(&ss, host, 0)) {
DEBUG(10,("open_udp_socket: can't resolve name %s\n",
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);
- }
+ 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 *)&ss)) {
+ if (connect(res, (struct sockaddr *)&ss, salen)) {
close(res);
return -1;
}
data_blob_free(&tmp);
}
-/*******************************************************************
- Return the DNS name of the remote end of a socket.
-******************************************************************/
-
-const char *get_peer_name(int fd, bool force_lookup)
-{
- 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];
-
- /* 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";
- }
-
- lookup_nc(&nc);
-
- memset(&ss, '\0', sizeof(ss));
- p = get_peer_addr_internal(fd, addr_buf, sizeof(addr_buf), (struct sockaddr *)&ss, &length);
-
- /* 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";
- }
-
- /* Not the same. We need to lookup. */
- if (fd == -1) {
- return "UNKNOWN";
- }
-
- /* 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)));
- strlcpy(name_buf, p, sizeof(name_buf));
- } 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));
- }
- }
-
- strlcpy(tmp_name, name_buf, sizeof(tmp_name));
- alpha_strcpy(name_buf, tmp_name, "_-.", sizeof(name_buf));
- if (strstr(name_buf,"..")) {
- strlcpy(name_buf, "UNKNOWN", sizeof(name_buf));
- }
-
- nc.name = name_buf;
- nc.ss = ss;
-
- 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.
******************************************************************/
char tmp_name[MAX_DNS_NAME_LENGTH];
struct name_addr_pair nc;
struct sockaddr_storage ss;
- socklen_t len;
+ ssize_t len;
int rc;
if (!lp_hostname_lookups()) {
gai_strerror(rc)));
strlcpy(name_buf, p, sizeof(name_buf));
- talloc_free(p);
+ TALLOC_FREE(p);
} else {
if (!matchname(name_buf, (struct sockaddr *)&ss, len)) {
DEBUG(0,("matchname failed on %s\n", name_buf));
lookup_nc(&nc);
if (nc.name == NULL) {
- *name = talloc_strdup(mem_ctx, "UNKOWN");
+ *name = talloc_strdup(mem_ctx, "UNKNOWN");
} else {
*name = talloc_strdup(mem_ctx, nc.name);
}
{
#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()) {
- DEBUG(0, ("invalid ownership on directory "
- "'%s'\n", socket_dir));
- umask(old_umask);
- goto out_umask;
- }
- if ((st.st_mode & 0777) != dir_perms) {
- DEBUG(0, ("invalid permissions on directory "
- "'%s': has 0%o should be 0%o\n", socket_dir,
- (st.st_mode & 0777), dir_perms));
- umask(old_umask);
- 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;
static void getaddrinfo_do(void *private_data)
{
struct getaddrinfo_state *state =
- (struct getaddrinfo_state *)private_data;
+ talloc_get_type_abort(private_data, struct getaddrinfo_state);
state->ret = getaddrinfo(state->node, state->service, state->hints,
&state->res);
int poll_one_fd(int fd, int events, int timeout, int *revents)
{
- struct pollfd *fds;
+ struct pollfd pfd;
int ret;
- int saved_errno;
- fds = talloc_zero_array(talloc_tos(), struct pollfd, 2);
- if (fds == NULL) {
- errno = ENOMEM;
- return -1;
- }
- fds[0].fd = fd;
- fds[0].events = events;
+ pfd.fd = fd;
+ pfd.events = events;
- ret = sys_poll(fds, 1, timeout);
+ ret = poll(&pfd, 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;
+ *revents = pfd.revents;
return ret;
}