X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fstatd%2Frmtcall.c;h=7684b3b51eb142b3c7f18e760868cd0575521729;hp=911a93236937245b2f9505faf9e6795c71ce623c;hb=c481a5416e5b937541205da23cde15cdabf106c1;hpb=af93e0306d87bba3f703386fd6390e9bf8e76816 diff --git a/utils/statd/rmtcall.c b/utils/statd/rmtcall.c index 911a932..7684b3b 100644 --- a/utils/statd/rmtcall.c +++ b/utils/statd/rmtcall.c @@ -20,12 +20,15 @@ * it won't if it's worth its money). */ -#include "config.h" +#ifdef HAVE_CONFIG_H +#include +#endif #include #include #include #include +#include #include #include #include @@ -34,6 +37,9 @@ #include #include #include +#ifdef HAVE_IFADDRS_H +#include +#endif /* HAVE_IFADDRS_H */ #include "sm_inter.h" #include "statd.h" #include "notlist.h" @@ -65,15 +71,78 @@ statd_get_socket(int port) memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; - sin.sin_port = port; + sin.sin_addr.s_addr = INADDR_ANY; + /* + * If a local hostname is given (-n option to statd), bind to the address + * specified. This is required to support clients that ignore the mon_name in + * the statd protocol but use the source address from the request packet. + */ + if (MY_NAME) { + struct hostent *hp = gethostbyname(MY_NAME); + if (hp) + sin.sin_addr = *(struct in_addr *) hp->h_addr; + } + if (port != 0) { + sin.sin_port = htons(port); + if (bind(sockfd, &sin, sizeof(sin)) == 0) + goto out_success; + note(N_CRIT, "statd: failed to bind to outgoing port, %d\n" + " falling back on randomly chosen port\n", port); + } if (bindresvport(sockfd, &sin) < 0) { dprintf(N_WARNING, "process_hosts: can't bind to reserved port\n"); } - +out_success: return sockfd; } +#ifdef HAVE_IFADDRS_H +/* + * Using the NL_ADDR(lp), reset (if needed) the hostname + * that will be put in the SM_NOTIFY to the hostname + * that is associated with the network interface + * that was monitored + */ +static void +reset_my_name(notify_list *lp) +{ + struct ifaddrs *ifa = NULL, *ifap; + struct in_addr netaddr, tmp; + struct sockaddr_in *sin, *nsin; + struct hostent *hp; + + netaddr.s_addr = inet_netof(NL_ADDR(lp)); + if (getifaddrs(&ifa) >= 0) { + for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) { + if (!(ifap->ifa_flags & IFF_UP)) + continue; + + note(N_DEBUG, "ifa_name %s\n", ifap->ifa_name); + if (ifap->ifa_addr == NULL) + continue; + if (ifap->ifa_addr->sa_family != AF_INET) + continue; + + sin = (struct sockaddr_in *)ifap->ifa_addr; + nsin = (struct sockaddr_in *)ifap->ifa_netmask; + tmp.s_addr = sin->sin_addr.s_addr & nsin->sin_addr.s_addr; + if (memcmp(&tmp.s_addr, &netaddr.s_addr, sizeof(netaddr.s_addr))) + continue; + hp = gethostbyaddr((char *)&sin->sin_addr, + sizeof(sin->sin_addr), AF_INET); + if (hp == NULL) + continue; + if (strcmp(NL_MY_NAME(lp), hp->h_name)) { + free(NL_MY_NAME(lp)); + NL_MY_NAME(lp)= strdup(hp->h_name); + note(N_DEBUG, "NL_MY_NAME %s\n", NL_MY_NAME(lp)); + } + } + } + return; +} +#endif /* HAVE_IFADDRS_H */ /* * Try to resolve host name for notify/callback request * @@ -283,6 +352,7 @@ process_entry(int sockfd, notify_list *lp) { struct sockaddr_in sin; struct status new_status; + stat_chge new_stat; xdrproc_t func; void *objp; u_int32_t proc, vers, prog; @@ -309,9 +379,20 @@ process_entry(int sockfd, notify_list *lp) /* Use source address for notify replies */ sin.sin_addr = lp->addr; - + /* + * Unless a static hostname has been defined + * set the NL_MY_NAME(lp) hostname to the + * one associated with the network interface + */ +#ifdef HAVE_IFADDRS_H + if (!(run_mode & STATIC_HOSTNAME)) + reset_my_name(lp); +#endif /* HAVE_IFADDRS_H */ func = (xdrproc_t) xdr_stat_chge; - objp = &SM_stat_chge; + new_stat.state = MY_STATE; + new_stat.mon_name = NL_MY_NAME(lp); + + objp = &new_stat; break; case NOTIFY_CALLBACK: prog = NL_MY_PROG(lp);