static void notify_deferred_opens(struct share_mode_lock *lck) { int i; if (!should_notify_deferred_opens()) { return; } for (i=0; i<lck->num_share_modes; i++) { struct share_mode_entry *e = &lck->share_modes[i]; if (!is_deferred_open_entry(e)) { continue; } if (procid_is_me(&e->pid)) { /* * We need to notify ourself to retry the open. Do * this by finding the queued SMB record, moving it to * the head of the queue and changing the wait time to * zero. */ schedule_deferred_open_smb_message(e->op_mid); } else { char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; share_mode_entry_to_message(msg, e); messaging_send_buf(smbd_messaging_context(), e->pid, MSG_SMB_OPEN_RETRY, (uint8 *)msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE); } } }
/** * Respond to a POOL_USAGE message by sending back string form of memory * usage stats. **/ static void msg_pool_usage(struct messaging_context *msg_ctx, void *private_data, uint32_t msg_type, struct server_id src, DATA_BLOB *data) { struct msg_pool_usage_state state; SMB_ASSERT(msg_type == MSG_REQ_POOL_USAGE); DEBUG(2,("Got POOL_USAGE\n")); state.mem_ctx = talloc_init("msg_pool_usage"); if (!state.mem_ctx) { return; } state.len = 0; state.buflen = 512; state.s = NULL; talloc_report_depth_cb(NULL, 0, -1, msg_pool_usage_helper, &state); if (!state.s) { talloc_destroy(state.mem_ctx); return; } messaging_send_buf(msg_ctx, src, MSG_POOL_USAGE, (uint8 *)state.s, strlen(state.s)+1); talloc_destroy(state.mem_ctx); }
struct blocking_lock_record *blocking_lock_cancel_smb1(files_struct *fsp, uint64_t smblctx, uint64_t offset, uint64_t count, enum brl_flavour lock_flav, unsigned char locktype, NTSTATUS err) { struct smbd_server_connection *sconn = fsp->conn->sconn; char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE]; struct blocking_lock_record *blr; if (!sconn->smb1.locks.blocking_lock_cancel_state) { /* Register our message. */ messaging_register(sconn->msg_ctx, sconn, MSG_SMB_BLOCKING_LOCK_CANCEL, process_blocking_lock_cancel_message); sconn->smb1.locks.blocking_lock_cancel_state = True; } for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) { if (fsp == blr->fsp && smblctx == blr->smblctx && offset == blr->offset && count == blr->count && lock_flav == blr->lock_flav) { break; } } if (!blr) { return NULL; } /* Check the flags are right. */ if (blr->req->cmd == SMBlockingX && (locktype & LOCKING_ANDX_LARGE_FILES) != (CVAL(blr->req->vwv+3, 0) & LOCKING_ANDX_LARGE_FILES)) { return NULL; } /* Move to cancelled queue. */ DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr); DLIST_ADD(sconn->smb1.locks.blocking_lock_cancelled_queue, blr); /* Create the message. */ memcpy(msg, &blr, sizeof(blr)); memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS)); messaging_send_buf(sconn->msg_ctx, messaging_server_id(sconn->msg_ctx), MSG_SMB_BLOCKING_LOCK_CANCEL, (uint8 *)&msg, sizeof(msg)); return blr; }
static void winbind_msg_validate_cache(struct messaging_context *msg_ctx, void *private_data, uint32_t msg_type, struct server_id server_id, DATA_BLOB *data) { uint8 ret; pid_t child_pid; struct sigaction act; struct sigaction oldact; DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache " "message.\n")); /* * call the validation code from a child: * so we don't block the main winbindd and the validation * code can safely use fork/waitpid... */ CatchChild(); child_pid = sys_fork(); if (child_pid == -1) { DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n", strerror(errno))); return; } if (child_pid != 0) { /* parent */ DEBUG(5, ("winbind_msg_validate_cache: child created with " "pid %d.\n", (int)child_pid)); return; } /* child */ /* install default SIGCHLD handler: validation code uses fork/waitpid */ ZERO_STRUCT(act); act.sa_handler = SIG_DFL; #ifdef SA_RESTART /* We *want* SIGALRM to interrupt a system call. */ act.sa_flags = SA_RESTART; #endif sigemptyset(&act.sa_mask); sigaddset(&act.sa_mask,SIGCHLD); sigaction(SIGCHLD,&act,&oldact); ret = (uint8)winbindd_validate_cache_nobackup(); DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret)); messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret, (size_t)1); _exit(0); }
static void smb_tell_num_children(struct messaging_context *ctx, void *data, uint32_t msg_type, struct server_id srv_id, DATA_BLOB *msg_data) { uint8_t buf[sizeof(uint32_t)]; if (am_parent) { SIVAL(buf, 0, am_parent->num_children); messaging_send_buf(ctx, srv_id, MSG_SMB_NUM_CHILDREN, buf, sizeof(buf)); } }
static void winbind_msg_validate_cache(struct messaging_context *msg_ctx, void *private_data, uint32_t msg_type, struct server_id server_id, DATA_BLOB *data) { uint8 ret; pid_t child_pid; NTSTATUS status; DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache " "message.\n")); /* * call the validation code from a child: * so we don't block the main winbindd and the validation * code can safely use fork/waitpid... */ child_pid = sys_fork(); if (child_pid == -1) { DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n", strerror(errno))); return; } if (child_pid != 0) { /* parent */ DEBUG(5, ("winbind_msg_validate_cache: child created with " "pid %d.\n", (int)child_pid)); return; } /* child */ status = winbindd_reinit_after_fork(NULL, NULL); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n", nt_errstr(status))); _exit(0); } /* install default SIGCHLD handler: validation code uses fork/waitpid */ CatchSignal(SIGCHLD, SIG_DFL); ret = (uint8)winbindd_validate_cache_nobackup(); DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret)); messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret, (size_t)1); _exit(0); }
static void cleanup_timeout_fn(struct event_context *event_ctx, struct timed_event *te, struct timeval now, void *private_data) { struct timed_event **cleanup_te = (struct timed_event **)private_data; DEBUG(1,("Cleaning up brl and lock database after unclean shutdown\n")); message_send_all(smbd_messaging_context(), MSG_SMB_UNLOCK, NULL, 0, NULL); messaging_send_buf(smbd_messaging_context(), procid_self(), MSG_SMB_BRL_VALIDATE, NULL, 0); /* mark the cleanup as having been done */ (*cleanup_te) = NULL; }
/* * helper function used by the kernel oplock backends to post the break message */ void break_kernel_oplock(struct messaging_context *msg_ctx, files_struct *fsp) { uint8_t msg[MSG_SMB_KERNEL_BREAK_SIZE]; /* Put the kernel break info into the message. */ push_file_id_24((char *)msg, &fsp->file_id); SIVAL(msg,24,fsp->fh->gen_id); /* Don't need to be root here as we're only ever sending to ourselves. */ messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx), MSG_SMB_KERNEL_BREAK, msg, MSG_SMB_KERNEL_BREAK_SIZE); }
static void cleanup_timeout_fn(struct tevent_context *event_ctx, struct tevent_timer *te, struct timeval now, void *private_data) { struct smbd_parent_context *parent = talloc_get_type_abort(private_data, struct smbd_parent_context); parent->cleanup_te = NULL; DEBUG(1,("Cleaning up brl and lock database after unclean shutdown\n")); message_send_all(parent->msg_ctx, MSG_SMB_UNLOCK, NULL, 0, NULL); messaging_send_buf(parent->msg_ctx, messaging_server_id(parent->msg_ctx), MSG_SMB_BRL_VALIDATE, NULL, 0); }
static bool send_message(struct messaging_context *msg_ctx, struct server_id pid, int msg_type, const void *buf, int len) { bool ret; int n_sent = 0; if (procid_to_pid(&pid) != 0) return NT_STATUS_IS_OK( messaging_send_buf(msg_ctx, pid, msg_type, (const uint8 *)buf, len)); ret = message_send_all(msg_ctx, msg_type, buf, len, &n_sent); DEBUG(10,("smbcontrol/send_message: broadcast message to " "%d processes\n", n_sent)); return ret; }
static int smbd_parent_ctdb_reconfigured( uint32_t src_vnn, uint32_t dst_vnn, uint64_t dst_srvid, const uint8_t *msg, size_t msglen, void *private_data) { struct messaging_context *msg_ctx = talloc_get_type_abort( private_data, struct messaging_context); DEBUG(10, ("Got %s message\n", (dst_srvid == CTDB_SRVID_RECONFIGURE) ? "cluster reconfigure" : "SAMBA_NOTIFY")); /* * Someone from the family died, validate our locks */ messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx), MSG_SMB_BRL_VALIDATE, NULL, 0); return 0; }
/**************************************************************************** receive a request profile level message ****************************************************************************/ static void reqprofile_message(struct messaging_context *msg_ctx, void *private_data, uint32_t msg_type, struct server_id src, DATA_BLOB *data) { int level; level = 1; if (smbprofile_state.config.do_count) { level += 2; } if (smbprofile_state.config.do_times) { level += 4; } DEBUG(1,("INFO: Received REQ_PROFILELEVEL message from PID %u\n", (unsigned int)procid_to_pid(&src))); messaging_send_buf(msg_ctx, src, MSG_PROFILELEVEL, (uint8 *)&level, sizeof(level)); }
int main(int argc, char *argv[]) { struct tevent_context *evt_ctx; struct messaging_context *msg_ctx; pid_t pid; int i, n; char buf[12]; int ret; load_case_tables(); setup_logging(argv[0], DEBUG_STDOUT); lp_load(get_dyn_CONFIGFILE(),False,False,False,True); if (!(evt_ctx = tevent_context_init(NULL)) || !(msg_ctx = messaging_init(NULL, procid_self(), evt_ctx))) { fprintf(stderr, "could not init messaging context\n"); exit(1); } if (argc != 3) { fprintf(stderr, "%s: Usage - %s pid count\n", argv[0], argv[0]); exit(1); } pid = atoi(argv[1]); n = atoi(argv[2]); messaging_register(msg_ctx, NULL, MSG_PONG, pong_message); for (i=0;i<n;i++) { messaging_send(msg_ctx, pid_to_procid(pid), MSG_PING, &data_blob_null); } while (pong_count < i) { ret = tevent_loop_once(evt_ctx); if (ret != 0) { break; } } /* Now test that the duplicate filtering code works. */ pong_count = 0; strlcpy(buf, "1234567890", sizeof(buf)); for (i=0;i<n;i++) { messaging_send(msg_ctx, messaging_server_id(msg_ctx), MSG_PING, &data_blob_null); messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx), MSG_PING,(uint8 *)buf, 11); } for (i=0;i<n;i++) { ret = tevent_loop_once(evt_ctx); if (ret != 0) { break; } } if (pong_count != 2) { fprintf(stderr, "Duplicate filter failed (%d).\n", pong_count); } /* Speed testing */ pong_count = 0; { struct timeval tv = timeval_current(); size_t timelimit = n; size_t ping_count = 0; printf("Sending pings for %d seconds\n", (int)timelimit); while (timeval_elapsed(&tv) < timelimit) { if(NT_STATUS_IS_OK(messaging_send_buf( msg_ctx, pid_to_procid(pid), MSG_PING, (uint8 *)buf, 11))) ping_count++; if(NT_STATUS_IS_OK(messaging_send( msg_ctx, pid_to_procid(pid), MSG_PING, &data_blob_null))) ping_count++; while (ping_count > pong_count + 20) { ret = tevent_loop_once(evt_ctx); if (ret != 0) { break; } } } printf("waiting for %d remaining replies (done %d)\n", (int)(ping_count - pong_count), pong_count); while (timeval_elapsed(&tv) < 30 && pong_count < ping_count) { ret = tevent_loop_once(evt_ctx); if (ret != 0) { break; } } if (ping_count != pong_count) { fprintf(stderr, "ping test failed! received %d, sent " "%d\n", pong_count, (int)ping_count); } printf("ping rate of %.0f messages/sec\n", (ping_count+pong_count)/timeval_elapsed(&tv)); } return (0); }
static void notify_deferred_opens(struct smbd_server_connection *sconn, struct share_mode_lock *lck) { uint32_t i, num_deferred; struct share_mode_entry *deferred; if (!should_notify_deferred_opens()) { return; } num_deferred = 0; for (i=0; i<lck->data->num_share_modes; i++) { if (is_deferred_open_entry(&lck->data->share_modes[i])) { num_deferred += 1; } } if (num_deferred == 0) { return; } deferred = talloc_array(talloc_tos(), struct share_mode_entry, num_deferred); if (deferred == NULL) { return; } num_deferred = 0; for (i=0; i<lck->data->num_share_modes; i++) { struct share_mode_entry *e = &lck->data->share_modes[i]; if (is_deferred_open_entry(e)) { deferred[num_deferred] = *e; num_deferred += 1; } } /* * We need to sort the notifications by initial request time. Imagine * two opens come in asyncronously, both conflicting with the open we * just close here. If we don't sort the notifications, the one that * came in last might get the response before the one that came in * first. This is demonstrated with the smbtorture4 raw.mux test. * * As long as we had the UNUSED_SHARE_MODE_ENTRY, we happened to * survive this particular test. Without UNUSED_SHARE_MODE_ENTRY, we * shuffle the share mode entries around a bit, so that we do not * survive raw.mux anymore. * * We could have kept the ordering in del_share_mode, but as the * ordering was never formalized I think it is better to do it here * where it is necessary. */ qsort(deferred, num_deferred, sizeof(struct share_mode_entry), compare_share_mode_times); for (i=0; i<num_deferred; i++) { struct share_mode_entry *e = &deferred[i]; if (procid_is_me(&e->pid)) { /* * We need to notify ourself to retry the open. Do * this by finding the queued SMB record, moving it to * the head of the queue and changing the wait time to * zero. */ schedule_deferred_open_message_smb(sconn, e->op_mid); } else { char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE]; share_mode_entry_to_message(msg, e); messaging_send_buf(sconn->msg_ctx, e->pid, MSG_SMB_OPEN_RETRY, (uint8 *)msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE); } } TALLOC_FREE(deferred); }
int main(int argc, char *argv[]) { struct tevent_context *evt_ctx; struct messaging_context *msg_ctx; pid_t pid; int i, n; char buf[12]; int ret; TALLOC_CTX *frame = talloc_stackframe(); load_case_tables(); setup_logging(argv[0], DEBUG_STDOUT); lp_load_global(get_dyn_CONFIGFILE()); if (!(evt_ctx = samba_tevent_context_init(NULL)) || !(msg_ctx = messaging_init(NULL, evt_ctx))) { fprintf(stderr, "could not init messaging context\n"); TALLOC_FREE(frame); exit(1); } if (argc != 3) { fprintf(stderr, "%s: Usage - %s pid count\n", argv[0], argv[0]); TALLOC_FREE(frame); exit(1); } pid = atoi(argv[1]); n = atoi(argv[2]); messaging_register(msg_ctx, NULL, MSG_PONG, pong_message); for (i=0;i<n;i++) { messaging_send(msg_ctx, pid_to_procid(pid), MSG_PING, &data_blob_null); } while (pong_count < i) { ret = tevent_loop_once(evt_ctx); if (ret != 0) { break; } } /* Ensure all messages get through to ourselves. */ pong_count = 0; strlcpy(buf, "1234567890", sizeof(buf)); for (i=0;i<n;i++) { messaging_send(msg_ctx, messaging_server_id(msg_ctx), MSG_PING, &data_blob_null); messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx), MSG_PING,(uint8 *)buf, 11); } /* * We have to loop at least 2 times for * each message as local ping messages are * handled by an immediate callback, that * has to be dispatched, which sends a pong * message, which also has to be dispatched. * Above we sent 2*n messages, which means * we have to dispatch 4*n times. */ while (pong_count < n*2) { ret = tevent_loop_once(evt_ctx); if (ret != 0) { break; } } if (pong_count != 2*n) { fprintf(stderr, "Message count failed (%d).\n", pong_count); } /* Speed testing */ pong_count = 0; { struct timeval tv = timeval_current(); size_t timelimit = n; size_t ping_count = 0; printf("Sending pings for %d seconds\n", (int)timelimit); while (timeval_elapsed(&tv) < timelimit) { if(NT_STATUS_IS_OK(messaging_send_buf( msg_ctx, pid_to_procid(pid), MSG_PING, (uint8 *)buf, 11))) ping_count++; if(NT_STATUS_IS_OK(messaging_send( msg_ctx, pid_to_procid(pid), MSG_PING, &data_blob_null))) ping_count++; while (ping_count > pong_count + 20) { ret = tevent_loop_once(evt_ctx); if (ret != 0) { break; } } } printf("waiting for %d remaining replies (done %d)\n", (int)(ping_count - pong_count), pong_count); while (timeval_elapsed(&tv) < 30 && pong_count < ping_count) { ret = tevent_loop_once(evt_ctx); if (ret != 0) { break; } } if (ping_count != pong_count) { fprintf(stderr, "ping test failed! received %d, sent " "%d\n", pong_count, (int)ping_count); } printf("ping rate of %.0f messages/sec\n", (ping_count+pong_count)/timeval_elapsed(&tv)); } TALLOC_FREE(frame); return (0); }
static void print_notify_send_messages_to_printer(struct messaging_context *msg_ctx, const char *printer, unsigned int timeout) { char *buf; struct notify_queue *pq, *pq_next; size_t msg_count = 0, offset = 0; size_t num_pids = 0; size_t i; pid_t *pid_list = NULL; struct timeval end_time = timeval_zero(); /* Count the space needed to send the messages. */ for (pq = notify_queue_head; pq; pq = pq->next) { if (strequal(printer, pq->msg->printer)) { if (!flatten_message(pq)) { DEBUG(0,("print_notify_send_messages: Out of memory\n")); talloc_free_children(send_ctx); num_messages = 0; return; } offset += (pq->buflen + 4); msg_count++; } } offset += 4; /* For count. */ buf = (char *)TALLOC(send_ctx, offset); if (!buf) { DEBUG(0,("print_notify_send_messages: Out of memory\n")); talloc_free_children(send_ctx); num_messages = 0; return; } offset = 0; SIVAL(buf,offset,msg_count); offset += 4; for (pq = notify_queue_head; pq; pq = pq_next) { pq_next = pq->next; if (strequal(printer, pq->msg->printer)) { SIVAL(buf,offset,pq->buflen); offset += 4; memcpy(buf + offset, pq->buf, pq->buflen); offset += pq->buflen; /* Remove from list. */ DLIST_REMOVE(notify_queue_head, pq); } } DEBUG(5, ("print_notify_send_messages_to_printer: sending %lu print notify message%s to printer %s\n", (unsigned long)msg_count, msg_count != 1 ? "s" : "", printer)); /* * Get the list of PID's to send to. */ if (!print_notify_pid_list(printer, send_ctx, &num_pids, &pid_list)) return; if (timeout != 0) { end_time = timeval_current_ofs(timeout, 0); } for (i = 0; i < num_pids; i++) { messaging_send_buf(msg_ctx, pid_to_procid(pid_list[i]), MSG_PRINTER_NOTIFY2 | MSG_FLAG_LOWPRIORITY, (uint8 *)buf, offset); if ((timeout != 0) && timeval_expired(&end_time)) { break; } } }
bool rename_share_filename(struct messaging_context *msg_ctx, struct share_mode_lock *lck, const char *servicepath, uint32_t orig_name_hash, uint32_t new_name_hash, const struct smb_filename *smb_fname_dst) { struct share_mode_data *d = lck->data; size_t sp_len; size_t bn_len; size_t sn_len; size_t msg_len; char *frm = NULL; int i; bool strip_two_chars = false; bool has_stream = smb_fname_dst->stream_name != NULL; struct server_id self_pid = messaging_server_id(msg_ctx); DEBUG(10, ("rename_share_filename: servicepath %s newname %s\n", servicepath, smb_fname_dst->base_name)); /* * rename_internal_fsp() and rename_internals() add './' to * head of newname if newname does not contain a '/'. */ if (smb_fname_dst->base_name[0] && smb_fname_dst->base_name[1] && smb_fname_dst->base_name[0] == '.' && smb_fname_dst->base_name[1] == '/') { strip_two_chars = true; } d->servicepath = talloc_strdup(d, servicepath); d->base_name = talloc_strdup(d, smb_fname_dst->base_name + (strip_two_chars ? 2 : 0)); d->stream_name = talloc_strdup(d, smb_fname_dst->stream_name); if (d->base_name == NULL || (has_stream && d->stream_name == NULL) || d->servicepath == NULL) { DEBUG(0, ("rename_share_filename: talloc failed\n")); return False; } d->modified = True; sp_len = strlen(d->servicepath); bn_len = strlen(d->base_name); sn_len = has_stream ? strlen(d->stream_name) : 0; msg_len = MSG_FILE_RENAMED_MIN_SIZE + sp_len + 1 + bn_len + 1 + sn_len + 1; /* Set up the name changed message. */ frm = talloc_array(d, char, msg_len); if (!frm) { return False; } push_file_id_24(frm, &d->id); DEBUG(10,("rename_share_filename: msg_len = %u\n", (unsigned int)msg_len )); strlcpy(&frm[24], d->servicepath ? d->servicepath : "", sp_len+1); strlcpy(&frm[24 + sp_len + 1], d->base_name ? d->base_name : "", bn_len+1); strlcpy(&frm[24 + sp_len + 1 + bn_len + 1], d->stream_name ? d->stream_name : "", sn_len+1); /* Send the messages. */ for (i=0; i<d->num_share_modes; i++) { struct share_mode_entry *se = &d->share_modes[i]; if (!is_valid_share_mode_entry(se)) { continue; } /* If this is a hardlink to the inode with a different name, skip this. */ if (se->name_hash != orig_name_hash) { continue; } se->name_hash = new_name_hash; /* But not to ourselves... */ if (serverid_equal(&se->pid, &self_pid)) { continue; } if (share_mode_stale_pid(d, i)) { continue; } DEBUG(10,("rename_share_filename: sending rename message to " "pid %s file_id %s sharepath %s base_name %s " "stream_name %s\n", procid_str_static(&se->pid), file_id_string_tos(&d->id), d->servicepath, d->base_name, has_stream ? d->stream_name : "")); messaging_send_buf(msg_ctx, se->pid, MSG_SMB_FILE_RENAME, (uint8 *)frm, msg_len); } return True; }
bool cli_send_mailslot(struct messaging_context *msg_ctx, bool unique, const char *mailslot, uint16 priority, char *buf, int len, const char *srcname, int src_type, const char *dstname, int dest_type, const struct sockaddr_storage *dest_ss) { struct packet_struct p; struct dgram_packet *dgram = &p.packet.dgram; char *ptr, *p2; char tmp[4]; pid_t nmbd_pid; char addr[INET6_ADDRSTRLEN]; if ((nmbd_pid = pidfile_pid("nmbd")) == 0) { DEBUG(3, ("No nmbd found\n")); return False; } if (dest_ss->ss_family != AF_INET) { DEBUG(3, ("cli_send_mailslot: can't send to IPv6 address.\n")); return false; } memset((char *)&p, '\0', sizeof(p)); /* * Next, build the DGRAM ... */ /* DIRECT GROUP or UNIQUE datagram. */ dgram->header.msg_type = unique ? 0x10 : 0x11; dgram->header.flags.node_type = M_NODE; dgram->header.flags.first = True; dgram->header.flags.more = False; dgram->header.dgm_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) + ((unsigned)sys_getpid()%(unsigned)100); /* source ip is filled by nmbd */ dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */ dgram->header.packet_offset = 0; make_nmb_name(&dgram->source_name,srcname,src_type); make_nmb_name(&dgram->dest_name,dstname,dest_type); ptr = &dgram->data[0]; /* Setup the smb part. */ ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */ memcpy(tmp,ptr,4); if (smb_size + 17*2 + strlen(mailslot) + 1 + len > MAX_DGRAM_SIZE) { DEBUG(0, ("cli_send_mailslot: Cannot write beyond end of packet\n")); return False; } cli_set_message(ptr,17,strlen(mailslot) + 1 + len,True); memcpy(ptr,tmp,4); SCVAL(ptr,smb_com,SMBtrans); SSVAL(ptr,smb_vwv1,len); SSVAL(ptr,smb_vwv11,len); SSVAL(ptr,smb_vwv12,70 + strlen(mailslot)); SSVAL(ptr,smb_vwv13,3); SSVAL(ptr,smb_vwv14,1); SSVAL(ptr,smb_vwv15,priority); SSVAL(ptr,smb_vwv16,2); p2 = smb_buf(ptr); fstrcpy(p2,mailslot); p2 = skip_string(ptr,MAX_DGRAM_SIZE,p2); if (!p2) { return False; } memcpy(p2,buf,len); p2 += len; dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */ p.packet_type = DGRAM_PACKET; p.ip = ((const struct sockaddr_in *)dest_ss)->sin_addr; p.timestamp = time(NULL); DEBUG(4,("send_mailslot: Sending to mailslot %s from %s ", mailslot, nmb_namestr(&dgram->source_name))); print_sockaddr(addr, sizeof(addr), dest_ss); DEBUGADD(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name), addr)); return NT_STATUS_IS_OK(messaging_send_buf(msg_ctx, pid_to_procid(nmbd_pid), MSG_SEND_PACKET, (uint8 *)&p, sizeof(p))); }