/* move a call from an existing linked list to the specified list. This prevents bugs where we forget to remove the call from a previous list when moving it. */ static void dcesrv_call_set_list(struct dcesrv_call_state *call, enum dcesrv_call_list list) { switch (call->list) { case DCESRV_LIST_NONE: break; case DCESRV_LIST_CALL_LIST: DLIST_REMOVE(call->conn->call_list, call); break; case DCESRV_LIST_FRAGMENTED_CALL_LIST: DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call); break; case DCESRV_LIST_PENDING_CALL_LIST: DLIST_REMOVE(call->conn->pending_call_list, call); break; } call->list = list; switch (list) { case DCESRV_LIST_NONE: break; case DCESRV_LIST_CALL_LIST: DLIST_ADD_END(call->conn->call_list, call); break; case DCESRV_LIST_FRAGMENTED_CALL_LIST: DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call); break; case DCESRV_LIST_PENDING_CALL_LIST: DLIST_ADD_END(call->conn->pending_call_list, call); break; } }
/* a client has asked to register a unique name that someone else owns. We need to ask each of the current owners if they still want it. If they do then reject the registration, otherwise allow it */ static void wins_register_wack(struct nbt_name_socket *nbtsock, struct nbt_name_packet *packet, struct winsdb_record *rec, struct socket_address *src, enum wrepl_name_type new_type) { struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); struct wins_server *winssrv = iface->nbtsrv->winssrv; struct nbtd_wins_wack_state *s; struct composite_context *c_req; uint32_t ttl; s = talloc_zero(nbtsock, struct nbtd_wins_wack_state); if (s == NULL) goto failed; /* package up the state variables for this wack request */ s->winssrv = winssrv; s->nbtsock = nbtsock; s->iface = iface; s->request_packet = talloc_steal(s, packet); s->rec = talloc_steal(s, rec); s->reg_address = packet->additional[0].rdata.netbios.addresses[0].ipaddr; s->new_type = new_type; s->src = socket_address_copy(s, src); if (s->src == NULL) goto failed; s->io.in.nbtd_server = iface->nbtsrv; s->io.in.nbt_port = lpcfg_nbt_port(iface->nbtsrv->task->lp_ctx); s->io.in.event_ctx = iface->nbtsrv->task->event_ctx; s->io.in.name = rec->name; s->io.in.num_addresses = winsdb_addr_list_length(rec->addresses); s->io.in.addresses = winsdb_addr_string_list(s, rec->addresses); if (s->io.in.addresses == NULL) goto failed; DLIST_ADD_END(iface->wack_queue, s); talloc_set_destructor(s, nbtd_wins_wack_state_destructor); /* * send a WACK to the client, specifying the maximum time it could * take to check with the owner, plus some slack */ ttl = 5 + 4 * winsdb_addr_list_length(rec->addresses); nbtd_wack_reply(nbtsock, packet, src, ttl); /* * send the challenge to the old addresses */ c_req = wins_challenge_send(s, &s->io); if (c_req == NULL) goto failed; c_req->async.fn = wack_wins_challenge_handler; c_req->async.private_data = s; return; failed: talloc_free(s); nbtd_name_registration_reply(nbtsock, packet, src, NBT_RCODE_SVR); }
/** * Search an entry as specified via file name. If found, moved entry * to the end of the list, too * @param fname file name * @return a pointer to the found entry or NULL * */ struct lrufiles_struct *lrufiles_search(pstring fname) { struct lrufiles_struct *curr, *tmp = NULL; DEBUG(10, ("search for '%s' in lrufiles\n", fname)); /* search backwards */ curr = LrufilesEnd; while ( curr != NULL ) { if ( StrCaseCmp(fname, curr->fname) == 0 ) { DEBUG(10, ("file '%s' matched\n", fname)); /* match ... */ /* move to end of list */ DLIST_REMOVE(Lrufiles, curr); #if (SMB_VFS_INTERFACE_VERSION >= 21) DLIST_ADD_END(Lrufiles, curr, struct lrufiles_struct *); #else DLIST_ADD_END(Lrufiles, curr, tmp); #endif LrufilesEnd = curr; /* return it */ return curr; } curr = curr->prev; } /* not found */ DEBUG(10, ("file '%s' not matched\n", fname)); return NULL; }
static NTSTATUS make_auth_context_text_list(struct auth_context **auth_context, char **text_list) { auth_methods *list = NULL; auth_methods *t = NULL; auth_methods *tmp; NTSTATUS nt_status; if (!text_list) { DEBUG(2,("make_auth_context_text_list: No auth method list!?\n")); return NT_STATUS_UNSUCCESSFUL; } if (!NT_STATUS_IS_OK(nt_status = make_auth_context(auth_context))) return nt_status; for (;*text_list; text_list++) { if (load_auth_module(*auth_context, *text_list, &t)) { DLIST_ADD_END(list, t, tmp); } } (*auth_context)->auth_method_list = list; return nt_status; }
/* queue a datagram for send */ NTSTATUS nbt_dgram_send(struct nbt_dgram_socket *dgmsock, struct nbt_dgram_packet *packet, struct socket_address *dest) { struct nbt_dgram_request *req; NTSTATUS status = NT_STATUS_NO_MEMORY; enum ndr_err_code ndr_err; req = talloc(dgmsock, struct nbt_dgram_request); if (req == NULL) goto failed; req->dest = dest; if (talloc_reference(req, dest) == NULL) goto failed; ndr_err = ndr_push_struct_blob(&req->encoded, req, packet, (ndr_push_flags_fn_t)ndr_push_nbt_dgram_packet); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); goto failed; } DLIST_ADD_END(dgmsock->send_queue, req); TEVENT_FD_WRITEABLE(dgmsock->fde); return NT_STATUS_OK; failed: talloc_free(req); return status; }
/* * Lock record / db depending on type */ static struct lock_request *ctdb_lock_internal(struct ctdb_context *ctdb, struct ctdb_db_context *ctdb_db, TDB_DATA key, uint32_t priority, void (*callback)(void *, bool), void *private_data, enum lock_type type, bool auto_mark) { struct lock_context *lock_ctx = NULL; struct lock_request *request; if (callback == NULL) { DEBUG(DEBUG_WARNING, ("No callback function specified, not locking\n")); return NULL; } #if 0 /* Disable this optimization to ensure first-in-first-out fair * scheduling of lock requests */ /* get a context for this key - search only the pending contexts, * current contexts might in the middle of processing callbacks */ lock_ctx = find_lock_context(ctdb->lock_pending, ctdb_db, key, priority, type); #endif /* No existing context, create one */ if (lock_ctx == NULL) { lock_ctx = talloc_zero(ctdb, struct lock_context); if (lock_ctx == NULL) { DEBUG(DEBUG_ERR, ("Failed to create a new lock context\n")); return NULL; } lock_ctx->type = type; lock_ctx->ctdb = ctdb; lock_ctx->ctdb_db = ctdb_db; lock_ctx->key.dsize = key.dsize; if (key.dsize > 0) { lock_ctx->key.dptr = talloc_memdup(lock_ctx, key.dptr, key.dsize); } else { lock_ctx->key.dptr = NULL; } lock_ctx->priority = priority; lock_ctx->auto_mark = auto_mark; lock_ctx->child = -1; lock_ctx->block_child = -1; DLIST_ADD_END(ctdb->lock_pending, lock_ctx, NULL); ctdb->lock_num_pending++; CTDB_INCREMENT_STAT(ctdb, locks.num_pending); if (ctdb_db) { CTDB_INCREMENT_DB_STAT(ctdb_db, locks.num_pending); } /* Start the timer when we activate the context */ lock_ctx->start_time = timeval_current(); }
/** * Adds a new entry, or if the entry already exists, mtime and infected values * are updated * @param fname the file name * @param mtime time the file was last modified * @param infected marks a file as infected or not infected * @return returns a pointer of the new entry, the updated entry or NULL * if no memory could be allocated * */ struct lrufiles_struct *lrufiles_add(pstring fname, time_t mtime, bool infected) { struct lrufiles_struct *new_entry, *tmp, *found = NULL; /* check if lru file access was disabled by setting the corresponding value in the configuration file to zero (or below zero) */ if ( lrufiles_max_entries <= 0 ) { DEBUG(1, ("lru files feature is disabled, do nothing\n")); /* do nothing, simply return NULL */ return NULL; } DEBUG(10, ("file '%s' should be added\n", fname)); /* check if file has already been added */ found = lrufiles_search(fname); if ( found != NULL ) { /* has already been added, update mtime and infected only */ DEBUG(10, ("file '%s' in list, update mtime and infected\n", fname)); found->mtime = mtime; found->infected = infected; /* FIXME hm, should we updated it or not?! */ /* found->time_added = time(NULL); */ return found; } else { DEBUG(10, ("alloc space for file entry '%s'\n", fname)); new_entry = (struct lrufiles_struct *)malloc(sizeof(*new_entry)); if (!new_entry) return NULL; ZERO_STRUCTP(new_entry); pstrcpy(new_entry->fname, fname); new_entry->mtime = mtime; new_entry->infected = infected; new_entry->time_added = time(NULL); /* reached maximum? */ if ( lrufiles_count == lrufiles_max_entries ) { DEBUG(10, ("lru maximum reached '%d'\n", lrufiles_count)); /* remove the first one - it really removes only the first one */ tmp = Lrufiles; DEBUG(10, ("removing first entry...")); lrufiles_delete_p(tmp); } DEBUG(10, ("adding new entry to list...\n")); #if (SMB_VFS_INTERFACE_VERSION >= 21) DLIST_ADD_END(Lrufiles, new_entry, struct lrufiles_struct *); #else DLIST_ADD_END(Lrufiles, new_entry, tmp); #endif LrufilesEnd = new_entry; lrufiles_count++; DEBUG(10, ("entry '%s' added, count '%d'\n", fname, lrufiles_count)); return new_entry; } }
/** * Add a child testsuite to a testsuite. */ bool torture_suite_add_suite(struct torture_suite *suite, struct torture_suite *child) { if (child == NULL) return false; DLIST_ADD_END(suite->children, child); /* FIXME: Check for duplicates and return false if the * added suite already exists as a child */ return true; }
int iscsi_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { if (iscsi == NULL) { printf("trying to queue to NULL context\n"); return -1; } if (pdu == NULL) { printf("trying to queue NULL pdu\n"); return -2; } DLIST_ADD_END(iscsi->outqueue, pdu, NULL); return 0; }
/** * Add a new testcase */ bool torture_suite_init_tcase(struct torture_suite *suite, struct torture_tcase *tcase, const char *name) { tcase->name = talloc_strdup(tcase, name); tcase->description = NULL; tcase->setup = NULL; tcase->teardown = NULL; tcase->fixture_persistent = true; tcase->tests = NULL; DLIST_ADD_END(suite->testcases, tcase); return true; }
/* return a dcerpc fault */ NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32_t fault_code) { struct ncacn_packet pkt; struct data_blob_list_item *rep; uint8_t zeros[4]; NTSTATUS status; /* setup a bind_ack */ dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx)); pkt.auth_length = 0; pkt.call_id = call->pkt.call_id; pkt.ptype = DCERPC_PKT_FAULT; pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; pkt.u.fault.alloc_hint = 0; pkt.u.fault.context_id = 0; pkt.u.fault.cancel_count = 0; pkt.u.fault.status = fault_code; ZERO_STRUCT(zeros); pkt.u.fault._pad = data_blob_const(zeros, sizeof(zeros)); rep = talloc(call, struct data_blob_list_item); if (!rep) { return NT_STATUS_NO_MEMORY; } status = ncacn_push_auth(&rep->blob, call, &pkt, NULL); if (!NT_STATUS_IS_OK(status)) { return status; } dcerpc_set_frag_length(&rep->blob, rep->blob.length); DLIST_ADD_END(call->replies, rep); dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST); if (call->conn->call_list && call->conn->call_list->replies) { if (call->conn->transport.report_output_data) { call->conn->transport.report_output_data(call->conn); } } return NT_STATUS_OK; }
struct torture_test *torture_tcase_add_simple_test(struct torture_tcase *tcase, const char *name, bool (*run) (struct torture_context *test, void *tcase_data)) { struct torture_test *test; test = talloc(tcase, struct torture_test); test->name = talloc_strdup(test, name); test->description = NULL; test->run = wrap_test_with_simple_test; test->fn = run; test->data = NULL; test->dangerous = false; DLIST_ADD_END(tcase->tests, test); return test; }
static BOOL push_queued_message(char *buf, int msg_len, struct timeval request_time, struct timeval end_time, char *private_data, size_t private_len) { struct pending_message_list *tmp_msg; struct pending_message_list *msg; msg = TALLOC_ZERO_P(NULL, struct pending_message_list); if(msg == NULL) { DEBUG(0,("push_message: malloc fail (1)\n")); return False; } msg->buf = data_blob_talloc(msg, buf, msg_len); if(msg->buf.data == NULL) { DEBUG(0,("push_message: malloc fail (2)\n")); TALLOC_FREE(msg); return False; } msg->request_time = request_time; msg->end_time = end_time; if (private_data) { msg->private_data = data_blob_talloc(msg, private_data, private_len); if (msg->private_data.data == NULL) { DEBUG(0,("push_message: malloc fail (3)\n")); TALLOC_FREE(msg); return False; } } DLIST_ADD_END(deferred_open_queue, msg, tmp_msg); DEBUG(10,("push_message: pushed message length %u on " "deferred_open_queue\n", (unsigned int)msg_len)); return True; }
struct torture_tcase *torture_suite_add_simple_test( struct torture_suite *suite, const char *name, bool (*run) (struct torture_context *test)) { struct torture_test *test; struct torture_tcase *tcase; tcase = torture_suite_add_tcase(suite, name); test = talloc(tcase, struct torture_test); test->name = talloc_strdup(test, name); test->description = NULL; test->run = wrap_simple_test; test->fn = run; test->dangerous = false; DLIST_ADD_END(tcase->tests, test); return tcase; }
static int iscsi_write_to_socket(struct iscsi_context *iscsi) { ssize_t count; if (iscsi == NULL) { printf("trying to write to socket for NULL context\n"); return -1; } if (iscsi->fd == -1) { printf("trying to write but not connected\n"); return -2; } while (iscsi->outqueue != NULL) { ssize_t total; total = iscsi->outqueue->outdata.size; total = (total +3) & 0xfffffffc; count = write(iscsi->fd, iscsi->outqueue->outdata.data + iscsi->outqueue->written, total - iscsi->outqueue->written); if (count == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { printf("socket would block, return from write to socket\n"); return 0; } printf("Error when writing to socket :%d\n", errno); return -3; } iscsi->outqueue->written += count; if (iscsi->outqueue->written == total) { struct iscsi_pdu *pdu = iscsi->outqueue; DLIST_REMOVE(iscsi->outqueue, pdu); DLIST_ADD_END(iscsi->waitpdu, pdu, NULL); } } return 0; }
static NTSTATUS make_auth_context_text_list(TALLOC_CTX *mem_ctx, struct auth_context **auth_context, char **text_list) { auth_methods *list = NULL; auth_methods *t, *method = NULL; NTSTATUS nt_status; if (!text_list) { DEBUG(2,("make_auth_context_text_list: No auth method list!?\n")); return NT_STATUS_UNSUCCESSFUL; } nt_status = make_auth_context(mem_ctx, auth_context); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } for (;*text_list; text_list++) { if (load_auth_module(*auth_context, *text_list, &t)) { DLIST_ADD_END(list, t); } } (*auth_context)->auth_method_list = list; /* Look for the first module to provide a prepare_gensec and * make_auth4_context hook, and set that if provided */ for (method = (*auth_context)->auth_method_list; method; method = method->next) { if (method->prepare_gensec && method->make_auth4_context) { (*auth_context)->prepare_gensec = method->prepare_gensec; (*auth_context)->make_auth4_context = method->make_auth4_context; break; } } return NT_STATUS_OK; }
/**************************************************************************** add an interface to the linked list of interfaces ****************************************************************************/ static void add_interface(TALLOC_CTX *mem_ctx, const struct iface_struct *ifs, struct interface **interfaces, bool enable_ipv6) { char addr[INET6_ADDRSTRLEN]; struct interface *iface; if (iface_list_find(*interfaces, (const struct sockaddr *)&ifs->ip, false)) { DEBUG(3,("add_interface: not adding duplicate interface %s\n", print_sockaddr(addr, sizeof(addr), &ifs->ip) )); return; } if (!(ifs->flags & (IFF_BROADCAST|IFF_LOOPBACK))) { DEBUG(3,("not adding non-broadcast interface %s\n", ifs->name )); return; } if (!enable_ipv6 && ifs->ip.ss_family != AF_INET) { return; } iface = talloc(*interfaces == NULL ? mem_ctx : *interfaces, struct interface); if (iface == NULL) return; ZERO_STRUCTPN(iface); iface->name = talloc_strdup(iface, ifs->name); if (!iface->name) { SAFE_FREE(iface); return; } iface->flags = ifs->flags; iface->ip = ifs->ip; iface->netmask = ifs->netmask; iface->bcast = ifs->bcast; /* keep string versions too, to avoid people tripping over the implied static in inet_ntoa() */ print_sockaddr(addr, sizeof(addr), &iface->ip); DEBUG(4,("added interface %s ip=%s ", iface->name, addr)); iface->ip_s = talloc_strdup(iface, addr); print_sockaddr(addr, sizeof(addr), &iface->bcast); DEBUG(4,("bcast=%s ", addr)); iface->bcast_s = talloc_strdup(iface, addr); print_sockaddr(addr, sizeof(addr), &iface->netmask); DEBUG(4,("netmask=%s\n", addr)); iface->nmask_s = talloc_strdup(iface, addr); /* this needs to be a ADD_END, as some tests (such as the spoolss notify test) depend on the interfaces ordering */ DLIST_ADD_END(*interfaces, iface, NULL); }
/* Add a trusted domain out of a trusted domain cache entry */ static struct winbindd_domain * add_trusted_domain_from_tdc(const struct winbindd_tdc_domain *tdc) { struct winbindd_domain *domain; const char *alternative_name = NULL; const char **ignored_domains, **dom; int role = lp_server_role(); const char *domain_name = tdc->domain_name; const struct dom_sid *sid = &tdc->sid; if (is_null_sid(sid)) { sid = NULL; } ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL); for (dom=ignored_domains; dom && *dom; dom++) { if (gen_fnmatch(*dom, domain_name) == 0) { DEBUG(2,("Ignoring domain '%s'\n", domain_name)); return NULL; } } /* use alt_name if available to allow DNS lookups */ if (tdc->dns_name && *tdc->dns_name) { alternative_name = tdc->dns_name; } /* We can't call domain_list() as this function is called from init_domain_list() and we'll get stuck in a loop. */ for (domain = _domain_list; domain; domain = domain->next) { if (strequal(domain_name, domain->name) || strequal(domain_name, domain->alt_name)) { break; } if (alternative_name) { if (strequal(alternative_name, domain->name) || strequal(alternative_name, domain->alt_name)) { break; } } if (sid != NULL) { if (dom_sid_equal(sid, &domain->sid)) { break; } } } if (domain != NULL) { /* * We found a match on domain->name or * domain->alt_name. Possibly update the SID * if the stored SID was the NULL SID * and return the matching entry. */ if ((sid != NULL) && dom_sid_equal(&domain->sid, &global_sid_NULL)) { sid_copy( &domain->sid, sid ); } return domain; } /* Create new domain entry */ domain = talloc_zero(NULL, struct winbindd_domain); if (domain == NULL) { return NULL; } domain->children = talloc_zero_array(domain, struct winbindd_child, lp_winbind_max_domain_connections()); if (domain->children == NULL) { TALLOC_FREE(domain); return NULL; } domain->name = talloc_strdup(domain, domain_name); if (domain->name == NULL) { TALLOC_FREE(domain); return NULL; } if (alternative_name) { domain->alt_name = talloc_strdup(domain, alternative_name); if (domain->alt_name == NULL) { TALLOC_FREE(domain); return NULL; } } domain->backend = NULL; domain->internal = is_internal_domain(sid); domain->sequence_number = DOM_SEQUENCE_NONE; domain->last_seq_check = 0; domain->initialized = false; domain->online = is_internal_domain(sid); domain->check_online_timeout = 0; domain->dc_probe_pid = (pid_t)-1; if (sid != NULL) { sid_copy(&domain->sid, sid); } domain->domain_flags = tdc->trust_flags; domain->domain_type = tdc->trust_type; domain->domain_trust_attribs = tdc->trust_attribs; /* Is this our primary domain ? */ if (strequal(domain_name, get_global_sam_name()) && (role != ROLE_DOMAIN_MEMBER)) { domain->primary = true; } else if (strequal(domain_name, lp_workgroup()) && (role == ROLE_DOMAIN_MEMBER)) { domain->primary = true; } if (domain->primary) { if (role == ROLE_ACTIVE_DIRECTORY_DC) { domain->active_directory = true; } if (lp_security() == SEC_ADS) { domain->active_directory = true; } } else if (!domain->internal) { if (domain->domain_type == LSA_TRUST_TYPE_UPLEVEL) { domain->active_directory = true; } } /* Link to domain list */ DLIST_ADD_END(_domain_list, domain); wcache_tdc_add_domain( domain ); setup_domain_child(domain); DEBUG(2, ("Added domain %s %s %s\n", domain->name, domain->alt_name, !is_null_sid(&domain->sid) ? sid_string_dbg(&domain->sid) : "")); return domain; }
static bool nb_do_createx(struct ftable *f, const char *fname, unsigned int create_options, unsigned int create_disposition, int handle, NTSTATUS status, bool retry) { union smb_open io; uint32_t desired_access; NTSTATUS ret; TALLOC_CTX *mem_ctx; unsigned int flags = 0; mem_ctx = talloc_init("raw_open"); if (create_options & NTCREATEX_OPTIONS_DIRECTORY) { desired_access = SEC_FILE_READ_DATA; } else { desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA | SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_ATTRIBUTE; flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK | NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK; } io.ntcreatex.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.flags = flags; io.ntcreatex.in.root_fid.fnum = 0; io.ntcreatex.in.access_mask = desired_access; io.ntcreatex.in.file_attr = 0; io.ntcreatex.in.alloc_size = 0; io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE; io.ntcreatex.in.open_disposition = create_disposition; io.ntcreatex.in.create_options = create_options; io.ntcreatex.in.impersonation = 0; io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; if (retry) { /* Reopening after a disconnect. */ io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; } else if (f != NULL && f->cp.create_disposition == NTCREATEX_DISP_CREATE && NT_STATUS_IS_OK(status)) { /* Reopening after nb_createx() error. */ io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; } ret = smb_raw_open(c->tree, mem_ctx, &io); talloc_free(mem_ctx); if (!check_status("NTCreateX", status, ret)) return false; if (!NT_STATUS_IS_OK(ret)) return true; if (f == NULL) { f = talloc (NULL, struct ftable); f->locks = NULL; nb_set_createx_params(f, fname, create_options, create_disposition, handle); DLIST_ADD_END(ftable, f); }
static void send_spoolss_notify2_msg(struct tevent_context *ev, struct messaging_context *msg_ctx, SPOOLSS_NOTIFY_MSG *msg) { struct notify_queue *pnqueue, *tmp_ptr; /* * Ensure we only have one job total_bytes and job total_pages for * each job. There is no point in sending multiple messages that match * as they will just cause flickering updates in the client. */ if ((num_messages < 100) && (msg->type == JOB_NOTIFY_TYPE) && (msg->field == JOB_NOTIFY_FIELD_TOTAL_BYTES || msg->field == JOB_NOTIFY_FIELD_TOTAL_PAGES )) { for (tmp_ptr = notify_queue_head; tmp_ptr; tmp_ptr = tmp_ptr->next) { if (tmp_ptr->msg->type == msg->type && tmp_ptr->msg->field == msg->field && tmp_ptr->msg->id == msg->id && tmp_ptr->msg->flags == msg->flags && strequal(tmp_ptr->msg->printer, msg->printer)) { DEBUG(5,("send_spoolss_notify2_msg: replacing message 0x%02x/0x%02x for " "printer %s in notify_queue\n", msg->type, msg->field, msg->printer)); tmp_ptr->msg = msg; return; } } } /* Store the message on the pending queue. */ pnqueue = talloc(send_ctx, struct notify_queue); if (!pnqueue) { DEBUG(0,("send_spoolss_notify2_msg: Out of memory.\n")); return; } /* allocate a new msg structure and copy the fields */ if ( !(pnqueue->msg = talloc(send_ctx, SPOOLSS_NOTIFY_MSG)) ) { DEBUG(0,("send_spoolss_notify2_msg: talloc() of size [%lu] failed!\n", (unsigned long)sizeof(SPOOLSS_NOTIFY_MSG))); return; } copy_notify2_msg(pnqueue->msg, msg); GetTimeOfDay(&pnqueue->tv); pnqueue->buf = NULL; pnqueue->buflen = 0; DEBUG(5, ("send_spoolss_notify2_msg: appending message 0x%02x/0x%02x for printer %s \ to notify_queue_head\n", msg->type, msg->field, msg->printer)); /* * Note we add to the end of the list to ensure * the messages are sent in the order they were received. JRA. */ DLIST_ADD_END(notify_queue_head, pnqueue); num_messages++; if ((notify_event == NULL) && (ev != NULL)) { /* Add an event for 1 second's time to send this queue. */ notify_event = tevent_add_timer( ev, NULL, timeval_current_ofs(1,0), print_notify_event_send_messages, msg_ctx); } }
static struct tevent_queue_entry *tevent_queue_add_internal( struct tevent_queue *queue, struct tevent_context *ev, struct tevent_req *req, tevent_queue_trigger_fn_t trigger, void *private_data, bool allow_direct) { struct tevent_queue_entry *e; e = talloc_zero(req, struct tevent_queue_entry); if (e == NULL) { return NULL; } e->queue = queue; e->req = req; e->ev = ev; e->trigger = trigger; e->private_data = private_data; /* * if there is no trigger, it is just a blocker */ if (trigger == NULL) { e->triggered = true; } if (queue->length > 0) { /* * if there are already entries in the * queue do not optimize. */ allow_direct = false; } if (req->async.fn != NULL) { /* * If the caller wants to optimize for the * empty queue case, call the trigger only * if there is no callback defined for the * request yet. */ allow_direct = false; } DLIST_ADD_END(queue->list, e); queue->length++; talloc_set_destructor(e, tevent_queue_entry_destructor); if (!queue->running) { return e; } if (queue->list->triggered) { return e; } /* * If allowed we directly call the trigger * avoiding possible delays caused by * an immediate event. */ if (allow_direct) { queue->list->triggered = true; queue->list->trigger(queue->list->req, queue->list->private_data); return e; } tevent_schedule_immediate(queue->immediate, queue->list->ev, tevent_queue_immediate_trigger, queue); return e; }
BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num, uint16 lock_pid, SMB_BIG_UINT offset, SMB_BIG_UINT count) { static BOOL set_lock_msg; blocking_lock_record *blr, *tmp; BOOL my_lock_ctx = False; NTSTATUS status; if(in_chained_smb() ) { DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n")); return False; } /* * Now queue an entry on the blocking lock queue. We setup * the expiration time here. */ if((blr = SMB_MALLOC_P(blocking_lock_record)) == NULL) { DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" )); return False; } if((blr->inbuf = (char *)SMB_MALLOC(length)) == NULL) { DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" )); SAFE_FREE(blr); return False; } blr->com_type = CVAL(inbuf,smb_com); blr->fsp = get_fsp_from_pkt(inbuf); blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; blr->lock_num = lock_num; blr->lock_pid = lock_pid; blr->offset = offset; blr->count = count; memcpy(blr->inbuf, inbuf, length); blr->length = length; /* Add a pending lock record for this. */ status = brl_lock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, lock_pid, sys_getpid(), blr->fsp->conn->cnum, offset, count, PENDING_LOCK, &my_lock_ctx); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); free_blocking_lock_record(blr); return False; } DLIST_ADD_END(blocking_lock_queue, blr, tmp); /* Ensure we'll receive messages when this is unlocked. */ if (!set_lock_msg) { message_register(MSG_SMB_UNLOCK, received_unlock_msg); set_lock_msg = True; } DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with expiry time %d (+%d) \ for fnum = %d, name = %s\n", length, (int)blr->expire_time, lock_timeout, blr->fsp->fnum, blr->fsp->fsp_name )); /* Push the MID of this packet on the signing queue. */ srv_defer_sign_response(SVAL(inbuf,smb_mid)); return True; }
static struct aio_open_private_data *create_private_open_data(const files_struct *fsp, int flags, mode_t mode) { struct aio_open_private_data *opd = talloc_zero(NULL, struct aio_open_private_data); const char *fname = NULL; if (!opd) { return NULL; } opd->jobid = aio_pthread_open_jobid++; opd->dir_fd = -1; opd->ret_fd = -1; opd->ret_errno = EINPROGRESS; opd->flags = flags; opd->mode = mode; opd->mid = fsp->mid; opd->in_progress = true; opd->sconn = fsp->conn->sconn; opd->initial_allocation_size = fsp->initial_allocation_size; /* Copy our current credentials. */ opd->ux_tok = copy_unix_token(opd, get_current_utok(fsp->conn)); if (opd->ux_tok == NULL) { TALLOC_FREE(opd); return NULL; } /* * Copy the parent directory name and the * relative path within it. */ if (parent_dirname(opd, fsp->fsp_name->base_name, &opd->dname, &fname) == false) { TALLOC_FREE(opd); return NULL; } opd->fname = talloc_strdup(opd, fname); if (opd->fname == NULL) { TALLOC_FREE(opd); return NULL; } #if defined(O_DIRECTORY) opd->dir_fd = open(opd->dname, O_RDONLY|O_DIRECTORY); #else opd->dir_fd = open(opd->dname, O_RDONLY); #endif if (opd->dir_fd == -1) { TALLOC_FREE(opd); return NULL; } talloc_set_destructor(opd, opd_destructor); DLIST_ADD_END(open_pd_list, opd); return opd; }
_PUBLIC_ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call) { struct ndr_push *push; NTSTATUS status; DATA_BLOB stub; uint32_t total_length, chunk_size; struct dcesrv_connection_context *context = call->context; size_t sig_size = 0; /* call the reply function */ status = context->iface->reply(call, call, call->r); if (!NT_STATUS_IS_OK(status)) { return dcesrv_fault(call, call->fault_code); } /* form the reply NDR */ push = ndr_push_init_ctx(call); NT_STATUS_HAVE_NO_MEMORY(push); /* carry over the pointer count to the reply in case we are using full pointer. See NDR specification for full pointers */ push->ptr_count = call->ndr_pull->ptr_count; if (lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx)) { push->flags |= LIBNDR_FLAG_BIGENDIAN; } status = context->iface->ndr_push(call, call, push, call->r); if (!NT_STATUS_IS_OK(status)) { return dcesrv_fault(call, call->fault_code); } stub = ndr_push_blob(push); total_length = stub.length; /* we can write a full max_recv_frag size, minus the dcerpc request header size */ chunk_size = call->conn->cli_max_recv_frag; chunk_size -= DCERPC_REQUEST_LENGTH; if (call->conn->auth_state.auth_info && call->conn->auth_state.gensec_security) { size_t max_payload = chunk_size; max_payload -= DCERPC_AUTH_TRAILER_LENGTH; max_payload -= (max_payload % DCERPC_AUTH_PAD_ALIGNMENT); sig_size = gensec_sig_size(call->conn->auth_state.gensec_security, max_payload); if (sig_size) { chunk_size -= DCERPC_AUTH_TRAILER_LENGTH; chunk_size -= sig_size; } } chunk_size -= (chunk_size % DCERPC_AUTH_PAD_ALIGNMENT); do { uint32_t length; struct data_blob_list_item *rep; struct ncacn_packet pkt; rep = talloc(call, struct data_blob_list_item); NT_STATUS_HAVE_NO_MEMORY(rep); length = MIN(chunk_size, stub.length); /* form the dcerpc response packet */ dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx)); pkt.auth_length = 0; pkt.call_id = call->pkt.call_id; pkt.ptype = DCERPC_PKT_RESPONSE; pkt.pfc_flags = 0; if (stub.length == total_length) { pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST; } if (length == stub.length) { pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST; } pkt.u.response.alloc_hint = stub.length; pkt.u.response.context_id = call->pkt.u.request.context_id; pkt.u.response.cancel_count = 0; pkt.u.response._pad.data = call->pkt.u.request._pad.data; pkt.u.response._pad.length = call->pkt.u.request._pad.length; pkt.u.response.stub_and_verifier.data = stub.data; pkt.u.response.stub_and_verifier.length = length; if (!dcesrv_auth_response(call, &rep->blob, sig_size, &pkt)) { return dcesrv_fault(call, DCERPC_FAULT_OTHER); } dcerpc_set_frag_length(&rep->blob, rep->blob.length); DLIST_ADD_END(call->replies, rep); stub.data += length; stub.length -= length; } while (stub.length != 0); /* move the call from the pending to the finished calls list */ dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST); if (call->conn->call_list && call->conn->call_list->replies) { if (call->conn->transport.report_output_data) { call->conn->transport.report_output_data(call->conn); } } return NT_STATUS_OK; }
/* queue a packet for sending */ int ctdb_queue_send(struct ctdb_queue *queue, uint8_t *data, uint32_t length) { struct ctdb_queue_pkt *pkt; uint32_t length2, full_length; if (queue->alignment) { /* enforce the length and alignment rules from the tcp packet allocator */ length2 = (length+(queue->alignment-1)) & ~(queue->alignment-1); *(uint32_t *)data = length2; } else { length2 = length; } if (length2 != length) { memset(data+length, 0, length2-length); } full_length = length2; /* if the queue is empty then try an immediate write, avoiding queue overhead. This relies on non-blocking sockets */ if (queue->out_queue == NULL && queue->fd != -1 && !(queue->ctdb->flags & CTDB_FLAG_TORTURE)) { ssize_t n = write(queue->fd, data, length2); if (n == -1 && errno != EAGAIN && errno != EWOULDBLOCK) { talloc_free(queue->fde); queue->fde = NULL; queue->fd = -1; tevent_schedule_immediate(queue->im, queue->ctdb->ev, queue_dead, queue); /* yes, we report success, as the dead node is handled via a separate event */ return 0; } if (n > 0) { data += n; length2 -= n; } if (length2 == 0) return 0; } pkt = talloc(queue, struct ctdb_queue_pkt); CTDB_NO_MEMORY(queue->ctdb, pkt); pkt->data = talloc_memdup(pkt, data, length2); CTDB_NO_MEMORY(queue->ctdb, pkt->data); pkt->length = length2; pkt->full_length = full_length; if (queue->out_queue == NULL && queue->fd != -1) { EVENT_FD_WRITEABLE(queue->fde); } DLIST_ADD_END(queue->out_queue, pkt, NULL); queue->out_queue_length++; if (queue->ctdb->tunable.verbose_memory_names != 0) { struct ctdb_req_header *hdr = (struct ctdb_req_header *)pkt->data; switch (hdr->operation) { case CTDB_REQ_CONTROL: { struct ctdb_req_control *c = (struct ctdb_req_control *)hdr; talloc_set_name(pkt, "ctdb_queue_pkt: %s control opcode=%u srvid=%llu datalen=%u", queue->name, (unsigned)c->opcode, (unsigned long long)c->srvid, (unsigned)c->datalen); break; } case CTDB_REQ_MESSAGE: { struct ctdb_req_message *m = (struct ctdb_req_message *)hdr; talloc_set_name(pkt, "ctdb_queue_pkt: %s message srvid=%llu datalen=%u", queue->name, (unsigned long long)m->srvid, (unsigned)m->datalen); break; } default: talloc_set_name(pkt, "ctdb_queue_pkt: %s operation=%u length=%u src=%u dest=%u", queue->name, (unsigned)hdr->operation, (unsigned)hdr->length, (unsigned)hdr->srcnode, (unsigned)hdr->destnode); break; } } return 0; }
/* * Schedule a new lock child process * Set up callback handler and timeout handler */ static void ctdb_lock_schedule(struct ctdb_context *ctdb) { struct lock_context *lock_ctx, *next_ctx, *active_ctx; int ret; TALLOC_CTX *tmp_ctx; const char *helper = BINDIR "/ctdb_lock_helper"; static const char *prog = NULL; char **args; if (prog == NULL) { const char *t; t = getenv("CTDB_LOCK_HELPER"); if (t != NULL) { prog = talloc_strdup(ctdb, t); } else { prog = talloc_strdup(ctdb, helper); } CTDB_NO_MEMORY_VOID(ctdb, prog); } if (ctdb->lock_pending == NULL) { return; } /* Find a lock context with requests */ lock_ctx = ctdb->lock_pending; while (lock_ctx != NULL) { next_ctx = lock_ctx->next; if (! lock_ctx->req_queue) { DEBUG(DEBUG_INFO, ("Removing lock context without lock requests\n")); DLIST_REMOVE(ctdb->lock_pending, lock_ctx); ctdb->lock_num_pending--; CTDB_DECREMENT_STAT(ctdb, locks.num_pending); if (lock_ctx->ctdb_db) { CTDB_DECREMENT_DB_STAT(lock_ctx->ctdb_db, locks.num_pending); } talloc_free(lock_ctx); } else { active_ctx = find_lock_context(ctdb->lock_current, lock_ctx->ctdb_db, lock_ctx->key, lock_ctx->priority, lock_ctx->type); if (active_ctx == NULL) { if (lock_ctx->ctdb_db == NULL || lock_ctx->ctdb_db->lock_num_current < MAX_LOCK_PROCESSES_PER_DB) { /* Found a lock context with lock requests */ break; } } /* There is already a child waiting for the * same key. So don't schedule another child * just yet. */ } lock_ctx = next_ctx; } if (lock_ctx == NULL) { return; } lock_ctx->child = -1; ret = pipe(lock_ctx->fd); if (ret != 0) { DEBUG(DEBUG_ERR, ("Failed to create pipe in ctdb_lock_schedule\n")); return; } set_close_on_exec(lock_ctx->fd[0]); /* Create data for child process */ tmp_ctx = talloc_new(lock_ctx); if (tmp_ctx == NULL) { DEBUG(DEBUG_ERR, ("Failed to allocate memory for helper args\n")); close(lock_ctx->fd[0]); close(lock_ctx->fd[1]); return; } /* Create arguments for lock helper */ args = lock_helper_args(tmp_ctx, lock_ctx, lock_ctx->fd[1]); if (args == NULL) { DEBUG(DEBUG_ERR, ("Failed to create lock helper args\n")); close(lock_ctx->fd[0]); close(lock_ctx->fd[1]); talloc_free(tmp_ctx); return; } lock_ctx->child = vfork(); if (lock_ctx->child == (pid_t)-1) { DEBUG(DEBUG_ERR, ("Failed to create a child in ctdb_lock_schedule\n")); close(lock_ctx->fd[0]); close(lock_ctx->fd[1]); talloc_free(tmp_ctx); return; } /* Child process */ if (lock_ctx->child == 0) { ret = execv(prog, args); if (ret < 0) { DEBUG(DEBUG_ERR, ("Failed to execute helper %s (%d, %s)\n", prog, errno, strerror(errno))); } _exit(1); } /* Parent process */ ctdb_track_child(ctdb, lock_ctx->child); close(lock_ctx->fd[1]); talloc_set_destructor(lock_ctx, ctdb_lock_context_destructor); talloc_free(tmp_ctx); /* Set up timeout handler */ lock_ctx->ttimer = tevent_add_timer(ctdb->ev, lock_ctx, timeval_current_ofs(10, 0), ctdb_lock_timeout_handler, (void *)lock_ctx); if (lock_ctx->ttimer == NULL) { ctdb_kill(ctdb, lock_ctx->child, SIGKILL); lock_ctx->child = -1; talloc_set_destructor(lock_ctx, NULL); close(lock_ctx->fd[0]); return; } /* Set up callback */ lock_ctx->tfd = tevent_add_fd(ctdb->ev, lock_ctx, lock_ctx->fd[0], EVENT_FD_READ, ctdb_lock_handler, (void *)lock_ctx); if (lock_ctx->tfd == NULL) { TALLOC_FREE(lock_ctx->ttimer); ctdb_kill(ctdb, lock_ctx->child, SIGKILL); lock_ctx->child = -1; talloc_set_destructor(lock_ctx, NULL); close(lock_ctx->fd[0]); return; } tevent_fd_set_auto_close(lock_ctx->tfd); /* Move the context from pending to current */ DLIST_REMOVE(ctdb->lock_pending, lock_ctx); ctdb->lock_num_pending--; DLIST_ADD_END(ctdb->lock_current, lock_ctx, NULL); if (lock_ctx->ctdb_db) { lock_ctx->ctdb_db->lock_num_current++; CTDB_INCREMENT_STAT(lock_ctx->ctdb, locks.num_current); CTDB_INCREMENT_DB_STAT(lock_ctx->ctdb_db, locks.num_current); } }