Print this page
195 Need replacement for nfs/lockd+klm
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Jeremy Jones <jeremy@delphix.com>
Reviewed by: Jeff Biseda <jbiseda@delphix.com>

@@ -23,10 +23,11 @@
  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 /*
  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
 /*        All Rights Reserved   */
 

@@ -57,10 +58,12 @@
 #include <arpa/inet.h>
 #include <netdb.h>
 #include <netdir.h>
 #include <synch.h>
 #include <thread.h>
+#include <ifaddrs.h>
+#include <errno.h>
 #include <assert.h>
 #include "sm_statd.h"
 
 static int local_state;         /* fake local sm state */
                                 /* client name-to-address translation table */

@@ -87,13 +90,11 @@
 extern int self_check(char *hostname);
 extern struct lifconf *getmyaddrs(void);
 
 /* ARGSUSED */
 void
-sm_status(namep, resp)
-        sm_name *namep;
-        sm_stat_res *resp;
+sm_stat_svc(sm_name *namep, sm_stat_res *resp)
 {
 
         if (debug)
                 (void) printf("proc sm_stat: mon_name = %s\n",
                                 namep->mon_name);

@@ -102,13 +103,11 @@
         resp->state = LOCAL_STATE;
 }
 
 /* ARGSUSED */
 void
-sm_mon(monp, resp)
-        mon *monp;
-        sm_stat_res *resp;
+sm_mon_svc(mon *monp, sm_stat_res *resp)
 {
         mon_id *monidp;
         monidp = &monp->mon_id;
 
         rw_rdlock(&thr_rwlock);

@@ -130,13 +129,11 @@
         rw_unlock(&thr_rwlock);
 }
 
 /* ARGSUSED */
 void
-sm_unmon(monidp, resp)
-        mon_id *monidp;
-        sm_stat *resp;
+sm_unmon_svc(mon_id *monidp, sm_stat *resp)
 {
         rw_rdlock(&thr_rwlock);
         if (debug) {
                 (void) printf(
                         "proc sm_unmon: mon_name = %s, [%s, %d, %d, %d]\n",

@@ -152,13 +149,11 @@
         rw_unlock(&thr_rwlock);
 }
 
 /* ARGSUSED */
 void
-sm_unmon_all(myidp, resp)
-        my_id *myidp;
-        sm_stat *resp;
+sm_unmon_all_svc(my_id *myidp, sm_stat *resp)
 {
         rw_rdlock(&thr_rwlock);
         if (debug)
                 (void) printf("proc sm_unmon_all: [%s, %d, %d, %d]\n",
                 myidp->my_name,

@@ -172,12 +167,11 @@
 
 /*
  * Notifies lockd specified by name that state has changed for this server.
  */
 void
-sm_notify(ntfp)
-        stat_chge *ntfp;
+sm_notify_svc(stat_chge *ntfp)
 {
         rw_rdlock(&thr_rwlock);
         if (debug)
                 (void) printf("sm_notify: %s state =%d\n",
                         ntfp->mon_name, ntfp->state);

@@ -185,12 +179,11 @@
         rw_unlock(&thr_rwlock);
 }
 
 /* ARGSUSED */
 void
-sm_simu_crash(myidp)
-        void *myidp;
+sm_simu_crash_svc(void *myidp)
 {
         int i;
         struct mon_entry *monitor_q;
         int found = 0;
 

@@ -725,11 +718,10 @@
 thr_send_notice(void *arg)
 {
         moninfo_t *minfop;
 
         minfop = (moninfo_t *)arg;
-
         if (statd_call_lockd(&minfop->id, minfop->state) == -1) {
                 if (debug && minfop->id.mon_id.mon_name)
                         (void) printf("problem with notifying %s failure, "
                             "give up\n", minfop->id.mon_id.mon_name);
         } else {

@@ -757,20 +749,20 @@
         mon *monp;
         int state;
 {
         enum clnt_stat clnt_stat;
         struct timeval tottimeout;
-        struct status stat;
+        struct sm_status stat;
         my_id *my_idp;
         char *mon_name;
         int i;
         int rc = 0;
         CLIENT *clnt;
 
         mon_name = monp->mon_id.mon_name;
         my_idp = &monp->mon_id.my_id;
-        (void) memset(&stat, 0, sizeof (struct status));
+        (void) memset(&stat, 0, sizeof (stat));
         stat.mon_name = mon_name;
         stat.state = state;
         for (i = 0; i < 16; i++) {
                 stat.priv[i] = monp->priv[i];
         }

@@ -779,16 +771,18 @@
                         stat.mon_name, stat.state);
 
         tottimeout.tv_sec = SM_RPC_TIMEOUT;
         tottimeout.tv_usec = 0;
 
-        if ((clnt = create_client(my_idp->my_name, my_idp->my_prog,
-                my_idp->my_vers, &tottimeout)) == (CLIENT *) NULL) {
+        clnt = create_client(my_idp->my_name, my_idp->my_prog, my_idp->my_vers,
+            "ticotsord", &tottimeout);
+        if (clnt == NULL) {
                         return (-1);
         }
 
-        clnt_stat = clnt_call(clnt, my_idp->my_proc, xdr_status, (char *)&stat,
+        clnt_stat = clnt_call(clnt, my_idp->my_proc,
+                                xdr_sm_status, (char *)&stat,
                                 xdr_void, NULL, tottimeout);
         if (debug) {
                 (void) printf("clnt_stat=%s(%d)\n",
                         clnt_sperrno(clnt_stat), clnt_stat);
         }

@@ -806,25 +800,39 @@
 
 /*
  * Client handle created.
  */
 CLIENT *
-create_client(host, prognum, versnum, utimeout)
-        char    *host;
-        int     prognum;
-        int     versnum;
-        struct timeval  *utimeout;
+create_client(char *host, int prognum, int versnum, char *netid,
+    struct timeval *utimeout)
 {
         int             fd;
         struct timeval  timeout;
         CLIENT          *client;
         struct t_info   tinfo;
 
-        if ((client = clnt_create_timed(host, prognum, versnum,
-                        "netpath", utimeout)) == NULL) {
+        if (netid == NULL) {
+                client = clnt_create_timed(host, prognum, versnum,
+                    "netpath", utimeout);
+        } else {
+                struct netconfig *nconf;
+
+                nconf = getnetconfigent(netid);
+                if (nconf == NULL) {
                 return (NULL);
         }
+
+                client = clnt_tp_create_timed(host, prognum, versnum, nconf,
+                    utimeout);
+
+                freenetconfigent(nconf);
+        }
+
+        if (client == NULL) {
+                return (NULL);
+        }
+
         (void) CLNT_CONTROL(client, CLGET_FD, (caddr_t)&fd);
         if (t_getinfo(fd, &tinfo) != -1) {
                 if (tinfo.servtype == T_CLTS) {
                         /*
                          * Set time outs for connectionless case

@@ -1298,6 +1306,75 @@
                     memcmp(dst1, dst2, len) == 0) {
                         return (0);
                 }
         }
         return (1);
+}
+
+/*
+ * Add IP address strings to the host_name list.
+ */
+void
+merge_ips(void)
+{
+        struct ifaddrs *ifap, *cifap;
+        int error;
+
+        error = getifaddrs(&ifap);
+        if (error) {
+                syslog(LOG_WARNING, "getifaddrs error: '%s'",
+                    strerror(errno));
+                return;
+        }
+
+        for (cifap = ifap; cifap != NULL; cifap = cifap->ifa_next) {
+                struct sockaddr *sa = cifap->ifa_addr;
+                char addr_str[INET6_ADDRSTRLEN];
+                void *addr = NULL;
+
+                switch (sa->sa_family) {
+                case AF_INET: {
+                        struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+
+                        /* Skip loopback addresses. */
+                        if (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) {
+                                continue;
+                        }
+
+                        addr = &sin->sin_addr;
+                        break;
+                }
+
+                case AF_INET6: {
+                        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+
+                        /* Skip loopback addresses. */
+                        if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) {
+                                continue;
+                        }
+
+                        addr = &sin6->sin6_addr;
+                        break;
+                }
+
+                default:
+                        syslog(LOG_WARNING, "Unknown address family %d for "
+                            "interface %s", sa->sa_family, cifap->ifa_name);
+                        continue;
+                }
+
+                if (inet_ntop(sa->sa_family, addr, addr_str, sizeof (addr_str))
+                    == NULL) {
+                        syslog(LOG_WARNING, "Failed to convert address into "
+                            "string representation for interface '%s' "
+                            "address family %d", cifap->ifa_name,
+                            sa->sa_family);
+                        continue;
+                }
+
+                if (!in_host_array(addr_str)) {
+                        add_to_host_array(addr_str);
+                }
+        }
+
+        freeifaddrs(ifap);
 }