Beispiel #1
0
bool nsm_connect()
{
	struct utsname utsname;

	if (nsm_clnt != NULL)
		return true;

	if (uname(&utsname) == -1) {
		LogCrit(COMPONENT_NLM,
			"uname failed with errno %d (%s)",
			errno, strerror(errno));
		return false;
	}

	nodename = gsh_strdup(utsname.nodename);
	if (nodename == NULL) {
		LogCrit(COMPONENT_NLM,
			"failed to allocate memory for nodename");
		return false;
	}

	nsm_clnt = gsh_clnt_create("localhost", SM_PROG, SM_VERS, "tcp");

	if (nsm_clnt == NULL) {
		LogCrit(COMPONENT_NLM, "failed to connect to statd");
		gsh_free(nodename);
		nodename = NULL;
	}

	/* split auth (for authnone, idempotent) */
	nsm_auth = authnone_create();

	return nsm_clnt != NULL;
}
Beispiel #2
0
/* Client routine  to send the asynchrnous response,
 * key is used to wait for a response
 */
int nlm_send_async(int proc, state_nlm_client_t *host, void *inarg, void *key)
{
	struct timeval tout = { 0, 10 };
	int retval, retry;
	struct timeval start, now;
	struct timespec timeout;

	for (retry = 1; retry <= MAX_ASYNC_RETRY; retry++) {
		if (host->slc_callback_clnt == NULL) {
			LogFullDebug(COMPONENT_NLM,
				     "gsh_clnt_create %s",
				     host->slc_nsm_client->ssc_nlm_caller_name);

			if (host->slc_client_type == XPRT_TCP) {
				int fd;
				struct sockaddr_in6 server_addr;
				struct netbuf *buf, local_buf;
				struct addrinfo *result;
				struct addrinfo hints;
				char port_str[20];

				fd = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
				if (fd < 0)
					return -1;

				memcpy(&server_addr,
				       &(host->slc_server_addr),
				       sizeof(struct sockaddr_in6));
				server_addr.sin6_port = 0;

				if (bind(fd,
					 (struct sockaddr *)&server_addr,
					  sizeof(server_addr)) == -1) {
					LogMajor(COMPONENT_NLM, "Cannot bind");
					close(fd);
					return -1;
				}

				buf = rpcb_find_mapped_addr(
				     (char *) xprt_type_to_str(
							host->slc_client_type),
				     NLMPROG, NLM4_VERS,
				     host->slc_nsm_client->ssc_nlm_caller_name);
				/* handle error here, for example,
				 * client side blocking rpc call
				 */
				if (buf == NULL) {
					LogMajor(COMPONENT_NLM,
						 "Cannot create NLM async %s connection to client %s",
						 xprt_type_to_str(
							host->slc_client_type),
						 host->slc_nsm_client->
						 ssc_nlm_caller_name);
					close(fd);
					return -1;
				}

				memset(&hints, 0, sizeof(struct addrinfo));
				hints.ai_family = AF_INET6;	/* only INET6 */
				hints.ai_socktype = SOCK_STREAM; /* TCP */
				hints.ai_protocol = 0;	/* Any protocol */
				hints.ai_canonname = NULL;
				hints.ai_addr = NULL;
				hints.ai_next = NULL;

				/* convert port to string format */
				sprintf(port_str, "%d",
					htons(((struct sockaddr_in *)
						buf->buf)->sin_port));

				/* buf with inet is only needed for the port */
				gsh_free(buf->buf);
				gsh_free(buf);

				/* get the IPv4 mapped IPv6 address */
				getaddrinfo(host->slc_nsm_client->
					    ssc_nlm_caller_name,
					    port_str,
					    &hints,
					    &result);

				/* setup the netbuf with in6 address */
				local_buf.buf = result->ai_addr;
				local_buf.len = local_buf.maxlen =
				    result->ai_addrlen;

				host->slc_callback_clnt =
				    clnt_vc_ncreate(fd, &local_buf, NLMPROG,
						    NLM4_VERS, 0, 0);
				freeaddrinfo(result);
			} else {

				host->slc_callback_clnt = gsh_clnt_create(
				    host->slc_nsm_client->ssc_nlm_caller_name,
				    NLMPROG,
				    NLM4_VERS,
				    (char *) xprt_type_to_str(
						host->slc_client_type));
			}

			if (host->slc_callback_clnt == NULL) {
				LogMajor(COMPONENT_NLM,
					 "Cannot create NLM async %s connection to client %s",
					 xprt_type_to_str(host->
							  slc_client_type),
					 host->slc_nsm_client->
					 ssc_nlm_caller_name);
				return -1;
			}

			/* split auth (for authnone, idempotent) */
			host->slc_callback_auth = authnone_create();
		}

		PTHREAD_MUTEX_lock(&nlm_async_resp_mutex);
		resp_key = key;
		PTHREAD_MUTEX_unlock(&nlm_async_resp_mutex);

		LogFullDebug(COMPONENT_NLM, "About to make clnt_call");

		retval = clnt_call(host->slc_callback_clnt,
				   host->slc_callback_auth,
				   proc,
				   nlm_reply_proc[proc],
				   inarg,
				   (xdrproc_t) xdr_void,
				   NULL,
				   tout);

		LogFullDebug(COMPONENT_NLM, "Done with clnt_call");

		if (retval == RPC_TIMEDOUT || retval == RPC_SUCCESS) {
			retval = RPC_SUCCESS;
			break;
		}

		LogCrit(COMPONENT_NLM,
			"NLM async Client procedure call %d failed with return code %d %s",
			proc, retval,
			clnt_sperror(host->slc_callback_clnt, ""));

		gsh_clnt_destroy(host->slc_callback_clnt);
		host->slc_callback_clnt = NULL;

		if (retry == MAX_ASYNC_RETRY) {
			LogMajor(COMPONENT_NLM,
				 "NLM async Client exceeded retry count %d",
				 MAX_ASYNC_RETRY);
			PTHREAD_MUTEX_lock(&nlm_async_resp_mutex);
			resp_key = NULL;
			PTHREAD_MUTEX_unlock(&nlm_async_resp_mutex);
			return retval;
		}
	}

	PTHREAD_MUTEX_lock(&nlm_async_resp_mutex);

	if (resp_key != NULL) {
		/* Wait for 5 seconds or a signal */
		gettimeofday(&start, NULL);
		gettimeofday(&now, NULL);
		timeout.tv_sec = 5 + start.tv_sec;
		timeout.tv_nsec = 0;

		LogFullDebug(COMPONENT_NLM,
			     "About to wait for signal for key %p", resp_key);

		while (resp_key != NULL && now.tv_sec < (start.tv_sec + 5)) {
			int rc;
			rc = pthread_cond_timedwait(&nlm_async_resp_cond,
						    &nlm_async_resp_mutex,
						    &timeout);
			LogFullDebug(COMPONENT_NLM,
				     "pthread_cond_timedwait returned %d",
				     rc);
			gettimeofday(&now, NULL);
		}
		LogFullDebug(COMPONENT_NLM, "Done waiting");
	}

	PTHREAD_MUTEX_unlock(&nlm_async_resp_mutex);

	return retval;
}