示例#1
0
int main(int argc, char *argv[]) {
	/* a request */
	request_t request = {{0}};

	/* resolving hints */
	struct addrinfo hints = {0};

	/* the address of a client */
	struct sockaddr client_address = {0};

	/* the daemon data */
	daemon_t daemon_data = {{{0}}};

	/* the request size */
	ssize_t size = 0;

	/* the client address size */
	socklen_t address_size = 0;

	/* the exit code */
	int exit_code = EXIT_FAILURE;

	/* a received signal */
	int received_signal = 0;

	/* child process ID */
	pid_t pid = 0;

	/* the local address */
	struct addrinfo *address = NULL;

	/* the file path */
	const char *path = NULL;

	/* the transfer mode */
	const char *mode = NULL;

	/* make sure the number of command-line arguments is valid */
	if (1 != argc) {
		PRINT(USAGE);
		goto end;
	}

	/* resolve the local address */
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_DGRAM;
	hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG | AI_V4MAPPED;
	if (0 != getaddrinfo(NULL, LISTENING_PORT, &hints, &address)) {
		goto end;
	}

	/* create a socket */
	daemon_data.fd = socket(address->ai_family,
	                        address->ai_socktype,
	                        address->ai_protocol);
	if (-1 == daemon_data.fd) {
		goto free_address;
	}

	/* set the socket timeout */
	if (false == _set_timeout(daemon_data.fd)) {
		goto end;
	}

	/* bind the socket */
	if (-1 == bind(daemon_data.fd, address->ai_addr, address->ai_addrlen)) {
		goto close_socket;
	}

	/* open the system log*/
	openlog("tftpd", LOG_NDELAY, LOG_DAEMON);

	/* initialize the daemon */
	if (false == daemon_init(&daemon_data, SERVER_ROOT, DAEMON_USER)) {
		goto close_log;
	}

	do {
		/* wait for a request */
		if (false == daemon_wait(&daemon_data, &received_signal)) {
			break;
		}

		/* if the received signal is a termination one, report success */
		if (SIGTERM == received_signal) {
			break;
		}

		/* receive the request */
		address_size = sizeof(client_address);
		size = recvfrom(daemon_data.fd,
		                (void *) request.data,
		                sizeof(request.data),
		                0,
		                &client_address,
		                &address_size);
		switch (size) {
			case 0:
				/* if it was nothing but a scan, ignore it */
				continue;

			case (-1):
				goto close_log;
		}

		/* make sure the request isn't too small */
		if (MIN_REQUEST_SIZE > size) {
			continue;
		}

		/* make sure the request is valid */
		request.header.opcode = ntohs(request.header.opcode);
		switch (request.header.opcode) {
			case PACKET_TYPE_RRQ:
			case PACKET_TYPE_WRQ:
				break;

			default:
				continue;
		}

		/* locate the path */
		path = (const char *) &request.data[sizeof(uint16_t)];

		/* make sure the path is null-terminated */
		mode = memchr((const void *) path, '\0', 1 + NAME_MAX);
		if (NULL == mode) {
			continue;
		}

		/* skip the null byte */
		++mode;

		/* spawn a child process */
		pid = fork();
		switch (pid) {
			case (-1):
				goto close_log;

			case 0:
				/* handle the request */
				if (false == _handle_request(path,
				                             mode,
				                             request.header.opcode,
				                             address,
				                             &client_address,
				                             address_size)) {
					goto close_log;
				}
				goto success;
		}
	} while (1);

success:
	/* report success */
	exit_code = EXIT_SUCCESS;

close_log:
	/* close the system log */
	closelog();

close_socket:
	/* close the socket */
	(void) close(daemon_data.fd);

free_address:
	/* free the local address */
	freeaddrinfo(address);

end:
	return exit_code;
}
示例#2
0
文件: req.c 项目: VURM/slurm
static void *
_handle_accept(void *arg)
{
	/*struct request_params *param = (struct request_params *)arg;*/
	int fd = ((struct request_params *)arg)->fd;
	slurmd_job_t *job = ((struct request_params *)arg)->job;
	int req;
	int len;
	Buf buffer;
	void *auth_cred;
	int rc;
	uid_t uid;
	gid_t gid;

	debug3("Entering _handle_accept (new thread)");
	xfree(arg);

	safe_read(fd, &req, sizeof(int));
	if (req != REQUEST_CONNECT) {
		error("First message must be REQUEST_CONNECT");
		goto fail;
	}

	safe_read(fd, &len, sizeof(int));
	buffer = init_buf(len);
	safe_read(fd, get_buf_data(buffer), len);

	/* Unpack and verify the auth credential */
	auth_cred = g_slurm_auth_unpack(buffer);
	if (auth_cred == NULL) {
		error("Unpacking authentication credential: %s",
		      g_slurm_auth_errstr(g_slurm_auth_errno(NULL)));
		free_buf(buffer);
		goto fail;
	}
	rc = g_slurm_auth_verify(auth_cred, NULL, 2, NULL);
	if (rc != SLURM_SUCCESS) {
		error("Verifying authentication credential: %s",
		      g_slurm_auth_errstr(g_slurm_auth_errno(auth_cred)));
		(void) g_slurm_auth_destroy(auth_cred);
		free_buf(buffer);
		goto fail;
	}

	/* Get the uid & gid from the credential, then destroy it. */
	uid = g_slurm_auth_get_uid(auth_cred, NULL);
	gid = g_slurm_auth_get_gid(auth_cred, NULL);
	debug3("  Identity: uid=%d, gid=%d", uid, gid);
	g_slurm_auth_destroy(auth_cred);
	free_buf(buffer);

	rc = SLURM_SUCCESS;
	safe_write(fd, &rc, sizeof(int));

	while (1) {
		rc = _handle_request(fd, job, uid, gid);
		if (rc != SLURM_SUCCESS)
			break;
	}

	if (close(fd) == -1)
		error("Closing accepted fd: %m");

	pthread_mutex_lock(&message_lock);
	message_connections--;
	pthread_cond_signal(&message_cond);
	pthread_mutex_unlock(&message_lock);

	debug3("Leaving  _handle_accept");
	return NULL;

fail:
	rc = SLURM_FAILURE;
	safe_write(fd, &rc, sizeof(int));
rwfail:
	if (close(fd) == -1)
		error("Closing accepted fd after error: %m");
	debug("Leaving  _handle_accept on an error");
	return NULL;
}