/* * Copyright (C) 1995, 1997-1999 Jeffrey A. Uphoff * Modified by Olaf Kirch, Oct. 1996. * Modified by Lon Hohberger, Oct. 2000. * * NSM for Linux. */ #ifdef HAVE_CONFIG_H #include #endif #include #include "rpcmisc.h" #include "statd.h" #include "notlist.h" /* Callback notify list. */ /* notify_list *cbnl = NULL; ... never used */ /* * Services SM_NOTIFY requests. * * When NLM uses an SM_MON request to tell statd to monitor a remote, * the request contains a "mon_name" argument. This is usually the * "caller_name" argument of an NLMPROC_LOCK request. On Linux, the * NLM can send statd the remote's IP address instead of its * caller_name. The NSM protocol does not allow both the remote's * caller_name and it's IP address to be sent in the same SM_MON * request. * * The remote's caller_name is useful because it makes it simple * to identify rebooting remotes by matching the "mon_name" argument * they sent via an SM_NOTIFY request. * * The caller_name string may not be a fully qualified domain name, * or even registered in the DNS database, however. Having the * remote's IP address is useful because then there is no ambiguity * about where to send an SM_NOTIFY after the local system reboots. * * Without the actual caller_name, however, statd must use an * heuristic to match an incoming SM_NOTIFY request to one of the * hosts it is currently monitoring. The incoming mon_name in an * SM_NOTIFY address is converted to a list of IP addresses using * DNS. Each mon_name on statd's monitor list is also converted to * an address list, and the two lists are checked to see if there is * a matching address. * * There are some risks to this strategy: * * 1. The external DNS database is not reliable. It can change * over time, or the forward and reverse mappings could be * inconsistent. * * 2. If statd's monitor list becomes substantial, finding a match * can generate a not inconsequential amount of DNS traffic. * * 3. statd is a single-threaded service. When DNS becomes slow or * unresponsive, statd also becomes slow or unresponsive. * * 4. If the remote does not have a DNS entry at all (or if the * remote can resolve itself, but the local host can't resolve * the remote's hostname), the remote cannot be monitored, and * therefore NLM locking cannot be provided for that host. * * 5. Local DNS resolution can produce different results for the * mon_name than the results the remote might see for the same * query, especially if the remote did not send a caller_name * or mon_name that is a fully qualified domain name. * * Note that a caller_name is passed from NFS client to server, * but the client never knows what mon_name the server might use * to notify it of a reboot. On Linux, the client extracts the * server's name from the devname it was passed by the mount * command. This is often not a fully-qualified domain name. */ void * sm_notify_1_svc(struct stat_chge *argp, struct svc_req *rqstp) { notify_list *lp, *call; static char *result = NULL; struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); char ip_addr[INET6_ADDRSTRLEN]; xlog(D_CALL, "Received SM_NOTIFY from %s, state: %d", argp->mon_name, argp->state); /* quick check - don't bother if we're not monitoring anyone */ if (rtnl == NULL) { xlog_warn("SM_NOTIFY from %s while not monitoring any hosts", argp->mon_name); return ((void *) &result); } if (!statd_present_address(sap, ip_addr, sizeof(ip_addr))) { xlog_warn("Unrecognized sender address"); return ((void *) &result); } /* okir change: statd doesn't remove the remote host from its * internal monitor list when receiving an SM_NOTIFY call from * it. Lockd will want to continue monitoring the remote host * until it issues an SM_UNMON call. */ for (lp = rtnl ; lp ; lp = lp->next) if (NL_STATE(lp) != argp->state && (statd_matchhostname(argp->mon_name, lp->dns_name) || statd_matchhostname(ip_addr, lp->dns_name))) { NL_STATE(lp) = argp->state; call = nlist_clone(lp); nlist_insert(¬ify, call); } return ((void *) &result); }