int main(int argc, char **argv) { int c; int port = 0; int state = 0, sflag = 0; char mon_client[STR_SIZE], mflag = 0; char remote_addr_s[STR_SIZE], rflag = 0; char local_addr_s[STR_SIZE], lflag = 0; notify arg; CLIENT *clnt; struct netbuf *buf; char port_str[20]; struct sockaddr_in local_addr; int fd; while ((c = getopt(argc, argv, "p:r:m:l:s:")) != EOF) switch (c) { case 'p': port = atoi(optarg); break; case 's': state = atoi(optarg); sflag = 1; break; case 'm': if (strlen(optarg) >= STR_SIZE) { fprintf(stderr, ERR_MSG1, "monitor host"); exit(1); } strcpy(mon_client, optarg); mflag = 1; break; case 'r': if (strlen(optarg) >= STR_SIZE) { fprintf(stderr, ERR_MSG1, "remote address"); exit(1); } strcpy(remote_addr_s, optarg); rflag = 1; break; case 'l': if (strlen(optarg) >= STR_SIZE) { fprintf(stderr, ERR_MSG1, "local address"); exit(1); } strcpy(local_addr_s, optarg); lflag = 1; break; case '?': default: fprintf(stderr, USAGE, argv[0]); exit(1); break; } if ((sflag + lflag + mflag + rflag) != 4) { fprintf(stderr, USAGE, argv[0]); exit(1); } /* create a udp socket */ fd = socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_UDP); if (fd < 0) { fprintf(stderr, "socket call failed. errno=%d\n", errno); exit(1); } /* set up the sockaddr for local endpoint */ memset(&local_addr, 0, sizeof(struct sockaddr_in)); local_addr.sin_family = PF_INET; local_addr.sin_port = htons(port); local_addr.sin_addr.s_addr = inet_addr(local_addr_s); if (bind(fd, (struct sockaddr *)&local_addr, sizeof(struct sockaddr)) < 0) { fprintf(stderr, "bind call failed. errno=%d\n", errno); exit(1); } /* find the port for SM service of the remote server */ buf = rpcb_find_mapped_addr( "udp", SM_PROG, SM_VERS, remote_addr_s); /* handle error here, for example, * client side blocking rpc call */ if (buf == NULL) { close(fd); exit(1); } /* convert port to string format */ sprintf(port_str, "%d", htons(((struct sockaddr_in *) buf->buf)->sin_port)); clnt = clnt_dg_ncreate(fd, buf, SM_PROG, SM_VERS, 0, 0); arg.my_name = mon_client; arg.state = state; nsm_notify_1(&arg, clnt); /* free resources */ gsh_free(buf->buf); gsh_free(buf); clnt_destroy(clnt); close(fd); return 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; }