/* setup the inotify handle - called the first time a watch is added on this context */ static NTSTATUS inotify_setup(struct sys_notify_context *ctx) { struct inotify_private *in; if (!lp_parm_bool(-1, "notify", "inotify", True)) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } in = talloc(ctx, struct inotify_private); NT_STATUS_HAVE_NO_MEMORY(in); in->fd = inotify_init(); if (in->fd == -1) { DEBUG(0,("Failed to init inotify - %s\n", strerror(errno))); talloc_free(in); return map_nt_error_from_unix(errno); } in->ctx = ctx; in->watches = NULL; in->broken_inotify = False; ctx->private_data = in; talloc_set_destructor(in, inotify_destructor); /* add a event waiting for the inotify fd to be readable */ event_add_fd(ctx->ev, in, in->fd, EVENT_FD_READ, inotify_handler, in); return NT_STATUS_OK; }
static void onefs_init_cbrl(void) { static bool init_done = false; static int cbrl_event_fd; static struct fd_event *cbrl_fde; if (init_done) return; DEBUG(10, ("onefs_init_cbrl\n")); /* Register the event channel for CBRL. */ cbrl_event_fd = cbrl_event_register(); if (cbrl_event_fd == -1) { DEBUG(0, ("cbrl_event_register failed: %s\n", strerror(errno))); return; } DEBUG(10, ("cbrl_event_fd = %d\n", cbrl_event_fd)); /* Register the CBRL event_fd with samba's event system */ cbrl_fde = event_add_fd(smbd_event_context(), NULL, cbrl_event_fd, EVENT_FD_READ, onefs_cbrl_events_handler, NULL); init_done = true; return; }
Conn_t * conn_add(ConnType_t type, int fd, LecId_t pvc_lecid) { Conn_t *tmp; LecId_t lecid = 0; if (type != CT_MAIN && type != CT_PVC_CD) { /* Find next available LECID */ for (tmp = connlist; tmp != NULL; tmp = tmp->next){ if (lecid < tmp->lecid) { lecid = tmp->lecid; } } lecid++; } else if (type == CT_MAIN) { lecid = 0; } else /* PVC */ lecid = pvc_lecid; tmp = (Conn_t *)mem_alloc(&conn_unit, sizeof(Conn_t)); memset(tmp, 0, sizeof(*tmp)); tmp->fd = fd; tmp->state = CS_IDLE; tmp->lecid = lecid; tmp->type = type; tmp->next = connlist; tmp->timer = timer_new(&conn_unit); tmp->proxy = BL_FALSE; connlist = tmp; event_add_fd(fd, tmp); return tmp; }
/* initialise a nbt_dgram_socket. The event_ctx is optional, if provided then operations will use that event context */ struct nbt_dgram_socket *nbt_dgram_socket_init(TALLOC_CTX *mem_ctx, struct tevent_context *event_ctx, struct smb_iconv_convenience *iconv_convenience) { struct nbt_dgram_socket *dgmsock; NTSTATUS status; dgmsock = talloc(mem_ctx, struct nbt_dgram_socket); if (dgmsock == NULL) goto failed; dgmsock->event_ctx = event_ctx; if (dgmsock->event_ctx == NULL) goto failed; status = socket_create("ip", SOCKET_TYPE_DGRAM, &dgmsock->sock, 0); if (!NT_STATUS_IS_OK(status)) goto failed; socket_set_option(dgmsock->sock, "SO_BROADCAST", "1"); talloc_steal(dgmsock, dgmsock->sock); dgmsock->fde = event_add_fd(dgmsock->event_ctx, dgmsock, socket_get_fd(dgmsock->sock), 0, dgm_socket_handler, dgmsock); dgmsock->send_queue = NULL; dgmsock->incoming.handler = NULL; dgmsock->mailslot_handlers = NULL; dgmsock->iconv_convenience = iconv_convenience; return dgmsock; failed: talloc_free(dgmsock); return NULL; }
/* create a transport structure based on an established socket */ struct smbcli_transport *smbcli_transport_init(struct smbcli_socket *sock, TALLOC_CTX *parent_ctx, bool primary, struct smbcli_options *options) { struct smbcli_transport *transport; transport = talloc_zero(parent_ctx, struct smbcli_transport); if (!transport) return NULL; if (primary) { transport->socket = talloc_steal(transport, sock); } else { transport->socket = talloc_reference(transport, sock); } transport->negotiate.protocol = PROTOCOL_NT1; transport->options = *options; transport->negotiate.max_xmit = transport->options.max_xmit; /* setup the stream -> packet parser */ transport->packet = packet_init(transport); if (transport->packet == NULL) { talloc_free(transport); return NULL; } packet_set_private(transport->packet, transport); packet_set_socket(transport->packet, transport->socket->sock); packet_set_callback(transport->packet, smbcli_transport_finish_recv); packet_set_full_request(transport->packet, packet_full_request_nbt); packet_set_error_handler(transport->packet, smbcli_transport_error); packet_set_event_context(transport->packet, transport->socket->event.ctx); packet_set_nofree(transport->packet); packet_set_initial_read(transport->packet, 4); smbcli_init_signing(transport); ZERO_STRUCT(transport->called); /* take over event handling from the socket layer - it only handles events up until we are connected */ talloc_free(transport->socket->event.fde); transport->socket->event.fde = event_add_fd(transport->socket->event.ctx, transport->socket->sock, socket_get_fd(transport->socket->sock), EVENT_FD_READ, smbcli_transport_event_handler, transport); packet_set_fde(transport->packet, transport->socket->event.fde); packet_set_serialise(transport->packet); talloc_set_destructor(transport, transport_destructor); return transport; }
/* initialise a wrepl_socket from an already existing connection */ struct wrepl_socket *wrepl_socket_merge(TALLOC_CTX *mem_ctx, struct tevent_context *event_ctx, struct socket_context *sock, struct packet_context *pack) { struct wrepl_socket *wrepl_socket; wrepl_socket = talloc_zero(mem_ctx, struct wrepl_socket); if (wrepl_socket == NULL) goto failed; wrepl_socket->event.ctx = talloc_reference(wrepl_socket, event_ctx); if (wrepl_socket->event.ctx == NULL) goto failed; wrepl_socket->sock = sock; talloc_steal(wrepl_socket, wrepl_socket->sock); wrepl_socket->request_timeout = WREPL_SOCKET_REQUEST_TIMEOUT; wrepl_socket->event.fde = event_add_fd(wrepl_socket->event.ctx, wrepl_socket, socket_get_fd(wrepl_socket->sock), EVENT_FD_READ, wrepl_handler, wrepl_socket); if (wrepl_socket->event.fde == NULL) { goto failed; } wrepl_socket->packet = pack; talloc_steal(wrepl_socket, wrepl_socket->packet); packet_set_private(wrepl_socket->packet, wrepl_socket); packet_set_socket(wrepl_socket->packet, wrepl_socket->sock); packet_set_callback(wrepl_socket->packet, wrepl_finish_recv); packet_set_full_request(wrepl_socket->packet, packet_full_request_u32); packet_set_error_handler(wrepl_socket->packet, wrepl_error); packet_set_event_context(wrepl_socket->packet, wrepl_socket->event.ctx); packet_set_fde(wrepl_socket->packet, wrepl_socket->event.fde); packet_set_serialise(wrepl_socket->packet); talloc_set_destructor(wrepl_socket, wrepl_socket_destructor); return wrepl_socket; failed: talloc_free(wrepl_socket); return NULL; }
struct kernel_oplocks *irix_init_kernel_oplocks(struct smbd_server_connection *sconn) { struct kernel_oplocks *_ctx; struct irix_oplocks_context *ctx; int pfd[2]; if (!irix_oplocks_available()) return NULL; _ctx = talloc_zero(sconn, struct kernel_oplocks); if (!_ctx) { return NULL; } ctx = talloc_zero(_ctx, struct irix_oplocks_context); if (!ctx) { talloc_free(_ctx); return NULL; } _ctx->ops = &irix_koplocks; _ctx->private_data = ctx; ctx->ctx = _ctx; ctx->sconn = sconn; if(pipe(pfd) != 0) { talloc_free(_ctx); DEBUG(0,("setup_kernel_oplock_pipe: Unable to create pipe. " "Error was %s\n", strerror(errno) )); return False; } ctx->read_fd = pfd[0]; ctx->write_fd = pfd[1]; ctx->read_fde = event_add_fd(sconn->ev_ctx, ctx, ctx->read_fd, EVENT_FD_READ, irix_oplocks_read_fde_handler, ctx); return _ctx; }
/* * State transition functions */ static int join(Conn_t *conn) { int timeout; int rfd; Debug_unit(&conn_unit, "Join called"); dump_conn(conn); timeout = get_var_int(&conn_unit, "S4"); timer_alarm(&conn_unit, conn->timer, (unsigned)timeout, conn); rfd=atm_connect_back(get_var_addr(&conn_unit, "S1"), conn, CONTROL_DISTRIBUTE); if (rfd<0) { conn_remove(conn); return 0; } conn->sfd=rfd; event_add_fd(rfd, conn); return 1; }
/* setup the fd used by the queue */ int ctdb_queue_set_fd(struct ctdb_queue *queue, int fd) { queue->fd = fd; talloc_free(queue->fde); queue->fde = NULL; if (fd != -1) { queue->fde = event_add_fd(queue->ctdb->ev, queue, fd, EVENT_FD_READ, queue_io_handler, queue); if (queue->fde == NULL) { return -1; } tevent_fd_set_auto_close(queue->fde); if (queue->out_queue) { EVENT_FD_WRITEABLE(queue->fde); } } return 0; }
/* listen on our own address */ int ctdb_tcp_listen(struct ctdb_context *ctdb) { struct ctdb_tcp *ctcp = talloc_get_type(ctdb->private_data, struct ctdb_tcp); ctdb_sock_addr sock; int sock_size; int one = 1; struct tevent_fd *fde; /* we can either auto-bind to the first available address, or we can use a specified address */ if (!ctdb->address.address) { return ctdb_tcp_listen_automatic(ctdb); } ZERO_STRUCT(sock); if (ctdb_tcp_get_address(ctdb, ctdb->address.address, &sock) != 0) { goto failed; } switch (sock.sa.sa_family) { case AF_INET: sock.ip.sin_port = htons(ctdb->address.port); sock_size = sizeof(sock.ip); break; case AF_INET6: sock.ip6.sin6_port = htons(ctdb->address.port); sock_size = sizeof(sock.ip6); break; default: DEBUG(DEBUG_ERR, (__location__ " unknown family %u\n", sock.sa.sa_family)); goto failed; } #ifdef HAVE_SOCK_SIN_LEN sock.ip.sin_len = sock_size; #endif ctcp->listen_fd = socket(sock.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); if (ctcp->listen_fd == -1) { ctdb_set_error(ctdb, "socket failed\n"); return -1; } set_close_on_exec(ctcp->listen_fd); if (setsockopt(ctcp->listen_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one)) == -1) { DEBUG(DEBUG_WARNING, ("Failed to set REUSEADDR on fd - %s\n", strerror(errno))); } if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, sock_size) != 0) { DEBUG(DEBUG_ERR,(__location__ " Failed to bind() to socket. %s(%d)\n", strerror(errno), errno)); goto failed; } if (listen(ctcp->listen_fd, 10) == -1) { goto failed; } fde = event_add_fd(ctdb->ev, ctcp, ctcp->listen_fd, EVENT_FD_READ, ctdb_listen_event, ctdb); tevent_fd_set_auto_close(fde); return 0; failed: if (ctcp->listen_fd != -1) { close(ctcp->listen_fd); } ctcp->listen_fd = -1; return -1; }
/* automatically find which address to listen on */ static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb) { struct ctdb_tcp *ctcp = talloc_get_type(ctdb->private_data, struct ctdb_tcp); ctdb_sock_addr sock; int lock_fd, i; const char *lock_path = VARDIR "/run/ctdb/.socket_lock"; struct flock lock; int one = 1; int sock_size; struct tevent_fd *fde; /* If there are no nodes, then it won't be possible to find * the first one. Log a failure and short circuit the whole * process. */ if (ctdb->num_nodes == 0) { DEBUG(DEBUG_CRIT,("No nodes available to attempt bind to - is the nodes file empty?\n")); return -1; } /* in order to ensure that we don't get two nodes with the same adddress, we must make the bind() and listen() calls atomic. The SO_REUSEADDR setsockopt only prevents double binds if the first socket is in LISTEN state */ lock_fd = open(lock_path, O_RDWR|O_CREAT, 0666); if (lock_fd == -1) { DEBUG(DEBUG_CRIT,("Unable to open %s\n", lock_path)); return -1; } lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 1; lock.l_pid = 0; if (fcntl(lock_fd, F_SETLKW, &lock) != 0) { DEBUG(DEBUG_CRIT,("Unable to lock %s\n", lock_path)); close(lock_fd); return -1; } for (i=0; i < ctdb->num_nodes; i++) { if (ctdb->nodes[i]->flags & NODE_FLAGS_DELETED) { continue; } ZERO_STRUCT(sock); if (ctdb_tcp_get_address(ctdb, ctdb->nodes[i]->address.address, &sock) != 0) { continue; } switch (sock.sa.sa_family) { case AF_INET: sock.ip.sin_port = htons(ctdb->nodes[i]->address.port); sock_size = sizeof(sock.ip); break; case AF_INET6: sock.ip6.sin6_port = htons(ctdb->nodes[i]->address.port); sock_size = sizeof(sock.ip6); break; default: DEBUG(DEBUG_ERR, (__location__ " unknown family %u\n", sock.sa.sa_family)); continue; } #ifdef HAVE_SOCK_SIN_LEN sock.ip.sin_len = sock_size; #endif ctcp->listen_fd = socket(sock.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); if (ctcp->listen_fd == -1) { ctdb_set_error(ctdb, "socket failed\n"); continue; } set_close_on_exec(ctcp->listen_fd); if (setsockopt(ctcp->listen_fd,SOL_SOCKET,SO_REUSEADDR, (char *)&one,sizeof(one)) == -1) { DEBUG(DEBUG_WARNING, ("Failed to set REUSEADDR on fd - %s\n", strerror(errno))); } if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, sock_size) == 0) { break; } if (errno == EADDRNOTAVAIL) { DEBUG(DEBUG_DEBUG,(__location__ " Failed to bind() to socket. %s(%d)\n", strerror(errno), errno)); } else { DEBUG(DEBUG_ERR,(__location__ " Failed to bind() to socket. %s(%d)\n", strerror(errno), errno)); } } if (i == ctdb->num_nodes) { DEBUG(DEBUG_CRIT,("Unable to bind to any of the node addresses - giving up\n")); goto failed; } ctdb->address.address = talloc_strdup(ctdb, ctdb->nodes[i]->address.address); ctdb->address.port = ctdb->nodes[i]->address.port; ctdb->name = talloc_asprintf(ctdb, "%s:%u", ctdb->address.address, ctdb->address.port); ctdb->pnn = ctdb->nodes[i]->pnn; DEBUG(DEBUG_INFO,("ctdb chose network address %s:%u pnn %u\n", ctdb->address.address, ctdb->address.port, ctdb->pnn)); if (listen(ctcp->listen_fd, 10) == -1) { goto failed; } fde = event_add_fd(ctdb->ev, ctcp, ctcp->listen_fd, EVENT_FD_READ, ctdb_listen_event, ctdb); tevent_fd_set_auto_close(fde); close(lock_fd); return 0; failed: close(lock_fd); if (ctcp->listen_fd != -1) { close(ctcp->listen_fd); ctcp->listen_fd = -1; } return -1; }
/* called when we should try and establish a tcp connection to a node */ void ctdb_tcp_node_connect(struct event_context *ev, struct timed_event *te, struct timeval t, void *private_data) { struct ctdb_node *node = talloc_get_type(private_data, struct ctdb_node); struct ctdb_tcp_node *tnode = talloc_get_type(node->private_data, struct ctdb_tcp_node); struct ctdb_context *ctdb = node->ctdb; ctdb_sock_addr sock_in; int sockin_size; int sockout_size; ctdb_sock_addr sock_out; ctdb_tcp_stop_connection(node); ZERO_STRUCT(sock_out); #ifdef HAVE_SOCK_SIN_LEN sock_out.ip.sin_len = sizeof(sock_out); #endif if (ctdb_tcp_get_address(ctdb, node->address.address, &sock_out) != 0) { return; } switch (sock_out.sa.sa_family) { case AF_INET: sock_out.ip.sin_port = htons(node->address.port); break; case AF_INET6: sock_out.ip6.sin6_port = htons(node->address.port); break; default: DEBUG(DEBUG_ERR, (__location__ " unknown family %u\n", sock_out.sa.sa_family)); return; } tnode->fd = socket(sock_out.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); if (tnode->fd == -1) { DEBUG(DEBUG_ERR, (__location__ "Failed to create socket\n")); return; } set_nonblocking(tnode->fd); set_close_on_exec(tnode->fd); DEBUG(DEBUG_DEBUG, (__location__ " Created TCP SOCKET FD:%d\n", tnode->fd)); /* Bind our side of the socketpair to the same address we use to listen * on incoming CTDB traffic. * We must specify this address to make sure that the address we expose to * the remote side is actually routable in case CTDB traffic will run on * a dedicated non-routeable network. */ ZERO_STRUCT(sock_in); if (ctdb_tcp_get_address(ctdb, ctdb->address.address, &sock_in) != 0) { DEBUG(DEBUG_ERR, (__location__ " Failed to find our address. Failing bind.\n")); close(tnode->fd); return; } /* AIX libs check to see if the socket address and length arguments are consistent with each other on calls like connect(). Can not get by with just sizeof(sock_in), need sizeof(sock_in.ip). */ switch (sock_in.sa.sa_family) { case AF_INET: sockin_size = sizeof(sock_in.ip); sockout_size = sizeof(sock_out.ip); break; case AF_INET6: sockin_size = sizeof(sock_in.ip6); sockout_size = sizeof(sock_out.ip6); break; default: DEBUG(DEBUG_ERR, (__location__ " unknown family %u\n", sock_in.sa.sa_family)); close(tnode->fd); return; } #ifdef HAVE_SOCK_SIN_LEN sock_in.ip.sin_len = sockin_size; sock_out.ip.sin_len = sockout_size; #endif if (bind(tnode->fd, (struct sockaddr *)&sock_in, sockin_size) == -1) { DEBUG(DEBUG_ERR, (__location__ "Failed to bind socket %s(%d)\n", strerror(errno), errno)); close(tnode->fd); return; } if (connect(tnode->fd, (struct sockaddr *)&sock_out, sockout_size) != 0 && errno != EINPROGRESS) { ctdb_tcp_stop_connection(node); tnode->connect_te = event_add_timed(ctdb->ev, tnode, timeval_current_ofs(1, 0), ctdb_tcp_node_connect, node); return; } /* non-blocking connect - wait for write event */ tnode->connect_fde = event_add_fd(node->ctdb->ev, tnode, tnode->fd, EVENT_FD_WRITE|EVENT_FD_READ, ctdb_node_connect_write, node); /* don't give it long to connect - retry in one second. This ensures that we find a node is up quickly (tcp normally backs off a syn reply delay by quite a lot) */ tnode->connect_te = event_add_timed(ctdb->ev, tnode, timeval_current_ofs(1, 0), ctdb_tcp_node_connect, node); }