Example #1
0
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);
        }
    }
}
Example #2
0
/**
 * 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);
}
Example #3
0
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;
}
Example #4
0
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);
}
Example #5
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));
	}
}
Example #6
0
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);
}
Example #7
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;
}
Example #8
0
/*
 * 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);
}
Example #9
0
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);
}
Example #10
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;
}
Example #11
0
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;
}
Example #12
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));
}
Example #13
0
 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);
}
Example #14
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);
}
Example #16
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;
		}
	}
}
Example #17
0
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;
}
Example #18
0
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)));
}