xref: /titanic_50/usr/src/cmd/fs.d/nfs/statd/sm_proc.c (revision 98573c1925f3692d1e8ea9eb018cb915fc0becc5)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
22*98573c19SMarcel Telka 
23*98573c19SMarcel Telka /*
24*98573c19SMarcel Telka  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
25*98573c19SMarcel Telka  */
26*98573c19SMarcel Telka 
277c478bd9Sstevel@tonic-gate /*
28a6f0fae9Sgt29601  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
297c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
307c478bd9Sstevel@tonic-gate  */
31b17f03d7SMarcel Telka /*
32bbaa8b60SDan Kruchinin  * Copyright (c) 2012 by Delphix. All rights reserved.
33b17f03d7SMarcel Telka  */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
367c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /*
397c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
407c478bd9Sstevel@tonic-gate  * The Regents of the University of California
417c478bd9Sstevel@tonic-gate  * All Rights Reserved
427c478bd9Sstevel@tonic-gate  *
437c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
447c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
457c478bd9Sstevel@tonic-gate  * contributors.
467c478bd9Sstevel@tonic-gate  */
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate #include <stdio.h>
497c478bd9Sstevel@tonic-gate #include <sys/types.h>
507c478bd9Sstevel@tonic-gate #include <stdlib.h>
517c478bd9Sstevel@tonic-gate #include <unistd.h>
527c478bd9Sstevel@tonic-gate #include <string.h>
537c478bd9Sstevel@tonic-gate #include <syslog.h>
547c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
557c478bd9Sstevel@tonic-gate #include <rpcsvc/sm_inter.h>
567c478bd9Sstevel@tonic-gate #include <rpcsvc/nsm_addr.h>
577c478bd9Sstevel@tonic-gate #include <memory.h>
587c478bd9Sstevel@tonic-gate #include <net/if.h>
597c478bd9Sstevel@tonic-gate #include <sys/sockio.h>
607c478bd9Sstevel@tonic-gate #include <sys/socket.h>
617c478bd9Sstevel@tonic-gate #include <netinet/in.h>
627c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
637c478bd9Sstevel@tonic-gate #include <netdb.h>
647c478bd9Sstevel@tonic-gate #include <netdir.h>
657c478bd9Sstevel@tonic-gate #include <synch.h>
667c478bd9Sstevel@tonic-gate #include <thread.h>
67bbaa8b60SDan Kruchinin #include <ifaddrs.h>
68bbaa8b60SDan Kruchinin #include <errno.h>
697c478bd9Sstevel@tonic-gate #include <assert.h>
707c478bd9Sstevel@tonic-gate #include "sm_statd.h"
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate static int local_state;		/* fake local sm state */
737c478bd9Sstevel@tonic-gate 				/* client name-to-address translation table */
747c478bd9Sstevel@tonic-gate static name_addr_entry_t *name_addr = NULL;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate #define	LOGHOST "loghost"
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate static void delete_mon(char *mon_name, my_id *my_idp);
807c478bd9Sstevel@tonic-gate static void insert_mon(mon *monp);
817c478bd9Sstevel@tonic-gate static void pr_mon(char *);
827c478bd9Sstevel@tonic-gate static int statd_call_lockd(mon *monp, int state);
837c478bd9Sstevel@tonic-gate static int hostname_eq(char *host1, char *host2);
847c478bd9Sstevel@tonic-gate static char *get_system_id(char *hostname);
857c478bd9Sstevel@tonic-gate static void add_aliases(struct hostent *phost);
867c478bd9Sstevel@tonic-gate static void *thr_send_notice(void *);
877c478bd9Sstevel@tonic-gate static void delete_onemon(char *mon_name, my_id *my_idp,
887c478bd9Sstevel@tonic-gate 				mon_entry **monitor_q);
897c478bd9Sstevel@tonic-gate static void send_notice(char *mon_name, int state);
907c478bd9Sstevel@tonic-gate static void add_to_host_array(char *host);
917c478bd9Sstevel@tonic-gate static int in_host_array(char *host);
927c478bd9Sstevel@tonic-gate static void pr_name_addr(name_addr_entry_t *name_addr);
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate extern int self_check(char *hostname);
957c478bd9Sstevel@tonic-gate extern struct lifconf *getmyaddrs(void);
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate /* ARGSUSED */
987c478bd9Sstevel@tonic-gate void
sm_stat_svc(sm_name * namep,sm_stat_res * resp)99bbaa8b60SDan Kruchinin sm_stat_svc(sm_name *namep, sm_stat_res *resp)
1007c478bd9Sstevel@tonic-gate {
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	if (debug)
1037c478bd9Sstevel@tonic-gate 		(void) printf("proc sm_stat: mon_name = %s\n",
1047c478bd9Sstevel@tonic-gate 		    namep->mon_name);
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	resp->res_stat = stat_succ;
1077c478bd9Sstevel@tonic-gate 	resp->state = LOCAL_STATE;
1087c478bd9Sstevel@tonic-gate }
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate /* ARGSUSED */
1117c478bd9Sstevel@tonic-gate void
sm_mon_svc(mon * monp,sm_stat_res * resp)112bbaa8b60SDan Kruchinin sm_mon_svc(mon *monp, sm_stat_res *resp)
1137c478bd9Sstevel@tonic-gate {
1147c478bd9Sstevel@tonic-gate 	mon_id *monidp;
1157c478bd9Sstevel@tonic-gate 	monidp = &monp->mon_id;
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	rw_rdlock(&thr_rwlock);
1187c478bd9Sstevel@tonic-gate 	if (debug) {
1197c478bd9Sstevel@tonic-gate 		(void) printf("proc sm_mon: mon_name = %s, id = %d\n",
1207c478bd9Sstevel@tonic-gate 		    monidp->mon_name, *((int *)monp->priv));
1217c478bd9Sstevel@tonic-gate 		pr_mon(monp->mon_id.mon_name);
1227c478bd9Sstevel@tonic-gate 	}
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	/* only monitor other hosts */
1257c478bd9Sstevel@tonic-gate 	if (self_check(monp->mon_id.mon_name) == 0) {
1267c478bd9Sstevel@tonic-gate 		/* store monitor request into monitor_q */
1277c478bd9Sstevel@tonic-gate 		insert_mon(monp);
1287c478bd9Sstevel@tonic-gate 	}
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	pr_mon(monp->mon_id.mon_name);
1317c478bd9Sstevel@tonic-gate 	resp->res_stat = stat_succ;
1327c478bd9Sstevel@tonic-gate 	resp->state = local_state;
1337c478bd9Sstevel@tonic-gate 	rw_unlock(&thr_rwlock);
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate /* ARGSUSED */
1377c478bd9Sstevel@tonic-gate void
sm_unmon_svc(mon_id * monidp,sm_stat * resp)138bbaa8b60SDan Kruchinin sm_unmon_svc(mon_id *monidp, sm_stat *resp)
1397c478bd9Sstevel@tonic-gate {
1407c478bd9Sstevel@tonic-gate 	rw_rdlock(&thr_rwlock);
1417c478bd9Sstevel@tonic-gate 	if (debug) {
1427c478bd9Sstevel@tonic-gate 		(void) printf(
1437c478bd9Sstevel@tonic-gate 		    "proc sm_unmon: mon_name = %s, [%s, %d, %d, %d]\n",
1447c478bd9Sstevel@tonic-gate 		    monidp->mon_name, monidp->my_id.my_name,
1457c478bd9Sstevel@tonic-gate 		    monidp->my_id.my_prog, monidp->my_id.my_vers,
1467c478bd9Sstevel@tonic-gate 		    monidp->my_id.my_proc);
1477c478bd9Sstevel@tonic-gate 		pr_mon(monidp->mon_name);
1487c478bd9Sstevel@tonic-gate 	}
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	delete_mon(monidp->mon_name, &monidp->my_id);
1517c478bd9Sstevel@tonic-gate 	pr_mon(monidp->mon_name);
1527c478bd9Sstevel@tonic-gate 	resp->state = local_state;
1537c478bd9Sstevel@tonic-gate 	rw_unlock(&thr_rwlock);
1547c478bd9Sstevel@tonic-gate }
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate /* ARGSUSED */
1577c478bd9Sstevel@tonic-gate void
sm_unmon_all_svc(my_id * myidp,sm_stat * resp)158bbaa8b60SDan Kruchinin sm_unmon_all_svc(my_id *myidp, sm_stat *resp)
1597c478bd9Sstevel@tonic-gate {
1607c478bd9Sstevel@tonic-gate 	rw_rdlock(&thr_rwlock);
1617c478bd9Sstevel@tonic-gate 	if (debug)
1627c478bd9Sstevel@tonic-gate 		(void) printf("proc sm_unmon_all: [%s, %d, %d, %d]\n",
1637c478bd9Sstevel@tonic-gate 		    myidp->my_name,
1647c478bd9Sstevel@tonic-gate 		    myidp->my_prog, myidp->my_vers,
1657c478bd9Sstevel@tonic-gate 		    myidp->my_proc);
166*98573c19SMarcel Telka 	delete_mon(NULL, myidp);
1677c478bd9Sstevel@tonic-gate 	pr_mon(NULL);
1687c478bd9Sstevel@tonic-gate 	resp->state = local_state;
1697c478bd9Sstevel@tonic-gate 	rw_unlock(&thr_rwlock);
1707c478bd9Sstevel@tonic-gate }
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate /*
1737c478bd9Sstevel@tonic-gate  * Notifies lockd specified by name that state has changed for this server.
1747c478bd9Sstevel@tonic-gate  */
1757c478bd9Sstevel@tonic-gate void
sm_notify_svc(stat_chge * ntfp)176bbaa8b60SDan Kruchinin sm_notify_svc(stat_chge *ntfp)
1777c478bd9Sstevel@tonic-gate {
1787c478bd9Sstevel@tonic-gate 	rw_rdlock(&thr_rwlock);
1797c478bd9Sstevel@tonic-gate 	if (debug)
1807c478bd9Sstevel@tonic-gate 		(void) printf("sm_notify: %s state =%d\n",
1817c478bd9Sstevel@tonic-gate 		    ntfp->mon_name, ntfp->state);
1827c478bd9Sstevel@tonic-gate 	send_notice(ntfp->mon_name, ntfp->state);
1837c478bd9Sstevel@tonic-gate 	rw_unlock(&thr_rwlock);
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate /* ARGSUSED */
1877c478bd9Sstevel@tonic-gate void
sm_simu_crash_svc(void * myidp)188bbaa8b60SDan Kruchinin sm_simu_crash_svc(void *myidp)
1897c478bd9Sstevel@tonic-gate {
1907c478bd9Sstevel@tonic-gate 	int i;
1917c478bd9Sstevel@tonic-gate 	struct mon_entry *monitor_q;
1927c478bd9Sstevel@tonic-gate 	int found = 0;
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	if (debug)
1957c478bd9Sstevel@tonic-gate 		(void) printf("proc sm_simu_crash\n");
196*98573c19SMarcel Telka 
197*98573c19SMarcel Telka 	/* Only one crash should be running at a time. */
198*98573c19SMarcel Telka 	mutex_lock(&crash_lock);
199*98573c19SMarcel Telka 	if (in_crash != 0) {
2007c478bd9Sstevel@tonic-gate 		mutex_unlock(&crash_lock);
2017c478bd9Sstevel@tonic-gate 		return;
2027c478bd9Sstevel@tonic-gate 	}
203*98573c19SMarcel Telka 	in_crash = 1;
2047c478bd9Sstevel@tonic-gate 	mutex_unlock(&crash_lock);
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	for (i = 0; i < MAX_HASHSIZE; i++) {
2077c478bd9Sstevel@tonic-gate 		mutex_lock(&mon_table[i].lock);
2087c478bd9Sstevel@tonic-gate 		monitor_q = mon_table[i].sm_monhdp;
209*98573c19SMarcel Telka 		if (monitor_q != NULL) {
2107c478bd9Sstevel@tonic-gate 			mutex_unlock(&mon_table[i].lock);
2117c478bd9Sstevel@tonic-gate 			found = 1;
2127c478bd9Sstevel@tonic-gate 			break;
2137c478bd9Sstevel@tonic-gate 		}
2147c478bd9Sstevel@tonic-gate 		mutex_unlock(&mon_table[i].lock);
2157c478bd9Sstevel@tonic-gate 	}
2167c478bd9Sstevel@tonic-gate 	/*
2177c478bd9Sstevel@tonic-gate 	 * If there are entries found in the monitor table,
2187c478bd9Sstevel@tonic-gate 	 * initiate a crash, else zero out the in_crash variable.
2197c478bd9Sstevel@tonic-gate 	 */
2207c478bd9Sstevel@tonic-gate 	if (found) {
2217c478bd9Sstevel@tonic-gate 		mutex_lock(&crash_lock);
2227c478bd9Sstevel@tonic-gate 		die = 1;
223*98573c19SMarcel Telka 		/* Signal sm_try() thread if sleeping. */
2247c478bd9Sstevel@tonic-gate 		cond_signal(&retrywait);
2257c478bd9Sstevel@tonic-gate 		mutex_unlock(&crash_lock);
2267c478bd9Sstevel@tonic-gate 		rw_wrlock(&thr_rwlock);
2277c478bd9Sstevel@tonic-gate 		sm_crash();
2287c478bd9Sstevel@tonic-gate 		rw_unlock(&thr_rwlock);
2297c478bd9Sstevel@tonic-gate 	} else {
2307c478bd9Sstevel@tonic-gate 		mutex_lock(&crash_lock);
2317c478bd9Sstevel@tonic-gate 		in_crash = 0;
2327c478bd9Sstevel@tonic-gate 		mutex_unlock(&crash_lock);
2337c478bd9Sstevel@tonic-gate 	}
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate /* ARGSUSED */
2377c478bd9Sstevel@tonic-gate void
nsmaddrproc1_reg(reg1args * regargs,reg1res * regresp)238*98573c19SMarcel Telka nsmaddrproc1_reg(reg1args *regargs, reg1res *regresp)
2397c478bd9Sstevel@tonic-gate {
2407c478bd9Sstevel@tonic-gate 	nsm_addr_res status;
2417c478bd9Sstevel@tonic-gate 	name_addr_entry_t *entry;
2427c478bd9Sstevel@tonic-gate 	char *tmp_n_bytes;
2437c478bd9Sstevel@tonic-gate 	addr_entry_t *addr;
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	rw_rdlock(&thr_rwlock);
2467c478bd9Sstevel@tonic-gate 	if (debug) {
2477c478bd9Sstevel@tonic-gate 		int i;
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 		(void) printf("nap1_reg: fam= %d, name= %s, len= %d\n",
250*98573c19SMarcel Telka 		    regargs->family, regargs->name, regargs->address.n_len);
2517c478bd9Sstevel@tonic-gate 		(void) printf("address is: ");
2527c478bd9Sstevel@tonic-gate 		for (i = 0; i < regargs->address.n_len; i++) {
2537c478bd9Sstevel@tonic-gate 			(void) printf("%d.",
2547c478bd9Sstevel@tonic-gate 			    (unsigned char)regargs->address.n_bytes[i]);
2557c478bd9Sstevel@tonic-gate 		}
2567c478bd9Sstevel@tonic-gate 		(void) printf("\n");
2577c478bd9Sstevel@tonic-gate 	}
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	/*
2607c478bd9Sstevel@tonic-gate 	 * Locate the entry with the name in the NSM_ADDR_REG request if
2617c478bd9Sstevel@tonic-gate 	 * it exists.  If it doesn't, create a new entry to hold this name.
2627c478bd9Sstevel@tonic-gate 	 * The first time through this code, name_addr starts out as NULL.
2637c478bd9Sstevel@tonic-gate 	 */
2647c478bd9Sstevel@tonic-gate 	mutex_lock(&name_addrlock);
2657c478bd9Sstevel@tonic-gate 	for (entry = name_addr; entry; entry = entry->next) {
2667c478bd9Sstevel@tonic-gate 		if (strcmp(regargs->name, entry->name) == 0) {
2677c478bd9Sstevel@tonic-gate 			if (debug) {
2687c478bd9Sstevel@tonic-gate 				(void) printf("nap1_reg: matched name %s\n",
2697c478bd9Sstevel@tonic-gate 				    entry->name);
2707c478bd9Sstevel@tonic-gate 			}
2717c478bd9Sstevel@tonic-gate 			break;
2727c478bd9Sstevel@tonic-gate 		}
2737c478bd9Sstevel@tonic-gate 	}
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	if (entry == NULL) {
2767c478bd9Sstevel@tonic-gate 		entry = (name_addr_entry_t *)malloc(sizeof (*entry));
2777c478bd9Sstevel@tonic-gate 		if (entry == NULL) {
2787c478bd9Sstevel@tonic-gate 			if (debug) {
2797c478bd9Sstevel@tonic-gate 				(void) printf(
2807c478bd9Sstevel@tonic-gate 				"nsmaddrproc1_reg: no memory for entry\n");
2817c478bd9Sstevel@tonic-gate 			}
2827c478bd9Sstevel@tonic-gate 			status = nsm_addr_fail;
2837c478bd9Sstevel@tonic-gate 			goto done;
2847c478bd9Sstevel@tonic-gate 		}
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 		entry->name = strdup(regargs->name);
2877c478bd9Sstevel@tonic-gate 		if (entry->name == NULL) {
2887c478bd9Sstevel@tonic-gate 			if (debug) {
2897c478bd9Sstevel@tonic-gate 				(void) printf(
2907c478bd9Sstevel@tonic-gate 				"nsmaddrproc1_reg: no memory for name\n");
2917c478bd9Sstevel@tonic-gate 			}
2927c478bd9Sstevel@tonic-gate 			free(entry);
2937c478bd9Sstevel@tonic-gate 			status = nsm_addr_fail;
2947c478bd9Sstevel@tonic-gate 			goto done;
2957c478bd9Sstevel@tonic-gate 		}
2967c478bd9Sstevel@tonic-gate 		entry->addresses = NULL;
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 		/*
2997c478bd9Sstevel@tonic-gate 		 * Link the new entry onto the *head* of the name_addr
3007c478bd9Sstevel@tonic-gate 		 * table.
3017c478bd9Sstevel@tonic-gate 		 *
3027c478bd9Sstevel@tonic-gate 		 * Note: there is code below in the address maintenance
3037c478bd9Sstevel@tonic-gate 		 * section that assumes this behavior.
3047c478bd9Sstevel@tonic-gate 		 */
3057c478bd9Sstevel@tonic-gate 		entry->next = name_addr;
3067c478bd9Sstevel@tonic-gate 		name_addr = entry;
3077c478bd9Sstevel@tonic-gate 	}
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	/*
3107c478bd9Sstevel@tonic-gate 	 * Try to match the address in the request; if it doesn't match,
3117c478bd9Sstevel@tonic-gate 	 * add it to the entry's address list.
3127c478bd9Sstevel@tonic-gate 	 */
3137c478bd9Sstevel@tonic-gate 	for (addr = entry->addresses; addr; addr = addr->next) {
3147c478bd9Sstevel@tonic-gate 		if (addr->family == (sa_family_t)regargs->family &&
3157c478bd9Sstevel@tonic-gate 		    addr->ah.n_len == regargs->address.n_len &&
3167c478bd9Sstevel@tonic-gate 		    memcmp(addr->ah.n_bytes, regargs->address.n_bytes,
3177c478bd9Sstevel@tonic-gate 		    addr->ah.n_len) == 0) {
3187c478bd9Sstevel@tonic-gate 			if (debug) {
3197c478bd9Sstevel@tonic-gate 				int i;
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 				(void) printf("nap1_reg: matched addr ");
3227c478bd9Sstevel@tonic-gate 				for (i = 0; i < addr->ah.n_len; i++) {
3237c478bd9Sstevel@tonic-gate 					(void) printf("%d.",
3247c478bd9Sstevel@tonic-gate 					    (unsigned char)addr->ah.n_bytes[i]);
3257c478bd9Sstevel@tonic-gate 				}
3267c478bd9Sstevel@tonic-gate 				(void) printf(" family %d for name %s\n",
327*98573c19SMarcel Telka 				    addr->family, entry->name);
3287c478bd9Sstevel@tonic-gate 			}
3297c478bd9Sstevel@tonic-gate 			break;
3307c478bd9Sstevel@tonic-gate 		}
3317c478bd9Sstevel@tonic-gate 	}
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	if (addr == NULL) {
3347c478bd9Sstevel@tonic-gate 		addr = (addr_entry_t *)malloc(sizeof (*addr));
3357c478bd9Sstevel@tonic-gate 		tmp_n_bytes = (char *)malloc(regargs->address.n_len);
3367c478bd9Sstevel@tonic-gate 		if (addr == NULL || tmp_n_bytes == NULL) {
3377c478bd9Sstevel@tonic-gate 			if (debug) {
338*98573c19SMarcel Telka 				(void) printf("nap1_reg: no memory for addr\n");
3397c478bd9Sstevel@tonic-gate 			}
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 			/*
3427c478bd9Sstevel@tonic-gate 			 * If this name entry was just newly made in the
3437c478bd9Sstevel@tonic-gate 			 * table, back it out now that we can't register
3447c478bd9Sstevel@tonic-gate 			 * an address with it anyway.
3457c478bd9Sstevel@tonic-gate 			 *
3467c478bd9Sstevel@tonic-gate 			 * Note: we are making an assumption about how
3477c478bd9Sstevel@tonic-gate 			 * names are added to (the head of) name_addr here.
3487c478bd9Sstevel@tonic-gate 			 */
3497c478bd9Sstevel@tonic-gate 			if (entry == name_addr && entry->addresses == NULL) {
3507c478bd9Sstevel@tonic-gate 				name_addr = name_addr->next;
3517c478bd9Sstevel@tonic-gate 				free(entry->name);
3527c478bd9Sstevel@tonic-gate 				free(entry);
3537c478bd9Sstevel@tonic-gate 				if (tmp_n_bytes)
3547c478bd9Sstevel@tonic-gate 					free(tmp_n_bytes);
3557c478bd9Sstevel@tonic-gate 				if (addr)
3567c478bd9Sstevel@tonic-gate 					free(addr);
3577c478bd9Sstevel@tonic-gate 				status = nsm_addr_fail;
3587c478bd9Sstevel@tonic-gate 				goto done;
3597c478bd9Sstevel@tonic-gate 			}
3607c478bd9Sstevel@tonic-gate 		}
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 		/*
3637c478bd9Sstevel@tonic-gate 		 * Note:  this check for address family assumes that we
3647c478bd9Sstevel@tonic-gate 		 *	  will get something different here someday for
3657c478bd9Sstevel@tonic-gate 		 *	  other supported address types, such as IPv6.
3667c478bd9Sstevel@tonic-gate 		 */
3677c478bd9Sstevel@tonic-gate 		addr->ah.n_len = regargs->address.n_len;
3687c478bd9Sstevel@tonic-gate 		addr->ah.n_bytes = tmp_n_bytes;
3697c478bd9Sstevel@tonic-gate 		addr->family = regargs->family;
3707c478bd9Sstevel@tonic-gate 		if (debug) {
371*98573c19SMarcel Telka 			if ((addr->family != AF_INET) &&
3727c478bd9Sstevel@tonic-gate 			    (addr->family != AF_INET6)) {
3737c478bd9Sstevel@tonic-gate 				(void) printf(
3747c478bd9Sstevel@tonic-gate 				    "nap1_reg: unknown addr family %d\n",
3757c478bd9Sstevel@tonic-gate 				    addr->family);
3767c478bd9Sstevel@tonic-gate 			}
3777c478bd9Sstevel@tonic-gate 		}
3787c478bd9Sstevel@tonic-gate 		(void) memcpy(addr->ah.n_bytes, regargs->address.n_bytes,
3797c478bd9Sstevel@tonic-gate 		    addr->ah.n_len);
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 		addr->next = entry->addresses;
3827c478bd9Sstevel@tonic-gate 		entry->addresses = addr;
3837c478bd9Sstevel@tonic-gate 	}
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	status = nsm_addr_succ;
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate done:
3887c478bd9Sstevel@tonic-gate 	regresp->status = status;
3897c478bd9Sstevel@tonic-gate 	if (debug) {
3907c478bd9Sstevel@tonic-gate 		pr_name_addr(name_addr);
3917c478bd9Sstevel@tonic-gate 	}
3927c478bd9Sstevel@tonic-gate 	mutex_unlock(&name_addrlock);
3937c478bd9Sstevel@tonic-gate 	rw_unlock(&thr_rwlock);
3947c478bd9Sstevel@tonic-gate }
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate /*
3977c478bd9Sstevel@tonic-gate  * Insert an entry into the monitor_q.  Space for the entry is allocated
3987c478bd9Sstevel@tonic-gate  * here.  It is then filled in from the information passed in.
3997c478bd9Sstevel@tonic-gate  */
4007c478bd9Sstevel@tonic-gate static void
insert_mon(mon * monp)401*98573c19SMarcel Telka insert_mon(mon *monp)
4027c478bd9Sstevel@tonic-gate {
4037c478bd9Sstevel@tonic-gate 	mon_entry *new, *found;
4047c478bd9Sstevel@tonic-gate 	my_id *my_idp, *nl_idp;
4057c478bd9Sstevel@tonic-gate 	mon_entry *monitor_q;
4067c478bd9Sstevel@tonic-gate 	unsigned int hash;
4077c478bd9Sstevel@tonic-gate 	name_addr_entry_t *entry;
4087c478bd9Sstevel@tonic-gate 	addr_entry_t *addr;
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	/* Allocate entry for new */
4117c478bd9Sstevel@tonic-gate 	if ((new = (mon_entry *) malloc(sizeof (mon_entry))) == 0) {
4127c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR,
4137c478bd9Sstevel@tonic-gate 		    "statd: insert_mon: malloc error on mon %s (id=%d)\n",
4147c478bd9Sstevel@tonic-gate 		    monp->mon_id.mon_name, *((int *)monp->priv));
4157c478bd9Sstevel@tonic-gate 		return;
4167c478bd9Sstevel@tonic-gate 	}
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	/* Initialize and copy contents of monp to new */
4197c478bd9Sstevel@tonic-gate 	(void) memset(new, 0, sizeof (mon_entry));
4207c478bd9Sstevel@tonic-gate 	(void) memcpy(&new->id, monp, sizeof (mon));
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 	/* Allocate entry for new mon_name */
4237c478bd9Sstevel@tonic-gate 	if ((new->id.mon_id.mon_name = strdup(monp->mon_id.mon_name)) == 0) {
4247c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR,
4257c478bd9Sstevel@tonic-gate 		    "statd: insert_mon: malloc error on mon %s (id=%d)\n",
4267c478bd9Sstevel@tonic-gate 		    monp->mon_id.mon_name, *((int *)monp->priv));
4277c478bd9Sstevel@tonic-gate 		free(new);
4287c478bd9Sstevel@tonic-gate 		return;
4297c478bd9Sstevel@tonic-gate 	}
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	/* Allocate entry for new my_name */
4337c478bd9Sstevel@tonic-gate 	if ((new->id.mon_id.my_id.my_name =
4347c478bd9Sstevel@tonic-gate 	    strdup(monp->mon_id.my_id.my_name)) == 0) {
4357c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR,
4367c478bd9Sstevel@tonic-gate 		    "statd: insert_mon: malloc error on mon %s (id=%d)\n",
4377c478bd9Sstevel@tonic-gate 		    monp->mon_id.mon_name, *((int *)monp->priv));
4387c478bd9Sstevel@tonic-gate 		free(new->id.mon_id.mon_name);
4397c478bd9Sstevel@tonic-gate 		free(new);
4407c478bd9Sstevel@tonic-gate 		return;
4417c478bd9Sstevel@tonic-gate 	}
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	if (debug)
4447c478bd9Sstevel@tonic-gate 		(void) printf("add_mon(%x) %s (id=%d)\n",
4457c478bd9Sstevel@tonic-gate 		    (int)new, new->id.mon_id.mon_name, *((int *)new->id.priv));
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 	/*
4487c478bd9Sstevel@tonic-gate 	 * Record the name, and all addresses which have been registered
4497c478bd9Sstevel@tonic-gate 	 * for this name, in the filesystem name space.
4507c478bd9Sstevel@tonic-gate 	 */
4517c478bd9Sstevel@tonic-gate 	record_name(new->id.mon_id.mon_name, 1);
4527c478bd9Sstevel@tonic-gate 	if (regfiles_only == 0) {
4537c478bd9Sstevel@tonic-gate 		mutex_lock(&name_addrlock);
4547c478bd9Sstevel@tonic-gate 		for (entry = name_addr; entry; entry = entry->next) {
4557c478bd9Sstevel@tonic-gate 			if (strcmp(new->id.mon_id.mon_name, entry->name) != 0) {
4567c478bd9Sstevel@tonic-gate 				continue;
4577c478bd9Sstevel@tonic-gate 			}
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 			for (addr = entry->addresses; addr; addr = addr->next) {
4607c478bd9Sstevel@tonic-gate 				record_addr(new->id.mon_id.mon_name,
4617c478bd9Sstevel@tonic-gate 				    addr->family, &addr->ah);
4627c478bd9Sstevel@tonic-gate 			}
4637c478bd9Sstevel@tonic-gate 			break;
4647c478bd9Sstevel@tonic-gate 		}
4657c478bd9Sstevel@tonic-gate 		mutex_unlock(&name_addrlock);
4667c478bd9Sstevel@tonic-gate 	}
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	SMHASH(new->id.mon_id.mon_name, hash);
4697c478bd9Sstevel@tonic-gate 	mutex_lock(&mon_table[hash].lock);
4707c478bd9Sstevel@tonic-gate 	monitor_q = mon_table[hash].sm_monhdp;
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 	/* If mon_table hash list is empty. */
473*98573c19SMarcel Telka 	if (monitor_q == NULL) {
4747c478bd9Sstevel@tonic-gate 		if (debug)
4757c478bd9Sstevel@tonic-gate 			(void) printf("\nAdding to monitor_q hash %d\n", hash);
476*98573c19SMarcel Telka 		new->nxt = new->prev = NULL;
4777c478bd9Sstevel@tonic-gate 		mon_table[hash].sm_monhdp = new;
4787c478bd9Sstevel@tonic-gate 		mutex_unlock(&mon_table[hash].lock);
4797c478bd9Sstevel@tonic-gate 		return;
4807c478bd9Sstevel@tonic-gate 	} else {
4817c478bd9Sstevel@tonic-gate 		found = 0;
4827c478bd9Sstevel@tonic-gate 		my_idp = &new->id.mon_id.my_id;
483*98573c19SMarcel Telka 		while (monitor_q != NULL)  {
4847c478bd9Sstevel@tonic-gate 			/*
4857c478bd9Sstevel@tonic-gate 			 * This list is searched sequentially for the
4867c478bd9Sstevel@tonic-gate 			 * tuple (hostname, prog, vers, proc). The tuples
4877c478bd9Sstevel@tonic-gate 			 * are inserted in the beginning of the monitor_q,
4887c478bd9Sstevel@tonic-gate 			 * if the hostname is not already present in the list.
4897c478bd9Sstevel@tonic-gate 			 * If the hostname is found in the list, the incoming
4907c478bd9Sstevel@tonic-gate 			 * tuple is inserted just after all the tuples with the
4917c478bd9Sstevel@tonic-gate 			 * same hostname. However, if the tuple matches exactly
4927c478bd9Sstevel@tonic-gate 			 * with an entry in the list, space allocated for the
4937c478bd9Sstevel@tonic-gate 			 * new entry is released and nothing is inserted in the
4947c478bd9Sstevel@tonic-gate 			 * list.
4957c478bd9Sstevel@tonic-gate 			 */
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 			if (str_cmp_unqual_hostname(
4987c478bd9Sstevel@tonic-gate 			    monitor_q->id.mon_id.mon_name,
4997c478bd9Sstevel@tonic-gate 			    new->id.mon_id.mon_name) == 0) {
5007c478bd9Sstevel@tonic-gate 				/* found */
5017c478bd9Sstevel@tonic-gate 				nl_idp = &monitor_q->id.mon_id.my_id;
5027c478bd9Sstevel@tonic-gate 				if ((str_cmp_unqual_hostname(my_idp->my_name,
5037c478bd9Sstevel@tonic-gate 				    nl_idp->my_name) == 0) &&
5047c478bd9Sstevel@tonic-gate 				    my_idp->my_prog == nl_idp->my_prog &&
5057c478bd9Sstevel@tonic-gate 				    my_idp->my_vers == nl_idp->my_vers &&
5067c478bd9Sstevel@tonic-gate 				    my_idp->my_proc == nl_idp->my_proc) {
5077c478bd9Sstevel@tonic-gate 					/*
5087c478bd9Sstevel@tonic-gate 					 * already exists an identical one,
5097c478bd9Sstevel@tonic-gate 					 * release the space allocated for the
5107c478bd9Sstevel@tonic-gate 					 * mon_entry
5117c478bd9Sstevel@tonic-gate 					 */
5127c478bd9Sstevel@tonic-gate 					free(new->id.mon_id.mon_name);
5137c478bd9Sstevel@tonic-gate 					free(new->id.mon_id.my_id.my_name);
5147c478bd9Sstevel@tonic-gate 					free(new);
5157c478bd9Sstevel@tonic-gate 					mutex_unlock(&mon_table[hash].lock);
5167c478bd9Sstevel@tonic-gate 					return;
5177c478bd9Sstevel@tonic-gate 				} else {
5187c478bd9Sstevel@tonic-gate 					/*
5197c478bd9Sstevel@tonic-gate 					 * mark the last callback that is
5207c478bd9Sstevel@tonic-gate 					 * not matching; new is inserted
5217c478bd9Sstevel@tonic-gate 					 * after this
5227c478bd9Sstevel@tonic-gate 					 */
5237c478bd9Sstevel@tonic-gate 					found = monitor_q;
5247c478bd9Sstevel@tonic-gate 				}
5257c478bd9Sstevel@tonic-gate 			} else if (found)
5267c478bd9Sstevel@tonic-gate 				break;
5277c478bd9Sstevel@tonic-gate 			monitor_q = monitor_q->nxt;
5287c478bd9Sstevel@tonic-gate 		}
5297c478bd9Sstevel@tonic-gate 		if (found) {
5307c478bd9Sstevel@tonic-gate 			/*
5317c478bd9Sstevel@tonic-gate 			 * insert just after the entry having matching tuple.
5327c478bd9Sstevel@tonic-gate 			 */
5337c478bd9Sstevel@tonic-gate 			new->nxt = found->nxt;
5347c478bd9Sstevel@tonic-gate 			new->prev = found;
535*98573c19SMarcel Telka 			if (found->nxt != NULL)
5367c478bd9Sstevel@tonic-gate 				found->nxt->prev = new;
5377c478bd9Sstevel@tonic-gate 			found->nxt = new;
5387c478bd9Sstevel@tonic-gate 		} else {
5397c478bd9Sstevel@tonic-gate 			/*
5407c478bd9Sstevel@tonic-gate 			 * not found, insert in front of list.
5417c478bd9Sstevel@tonic-gate 			 */
5427c478bd9Sstevel@tonic-gate 			new->nxt = mon_table[hash].sm_monhdp;
5437c478bd9Sstevel@tonic-gate 			new->prev = (mon_entry *) NULL;
5447c478bd9Sstevel@tonic-gate 			if (new->nxt != (mon_entry *) NULL)
5457c478bd9Sstevel@tonic-gate 				new->nxt->prev = new;
5467c478bd9Sstevel@tonic-gate 			mon_table[hash].sm_monhdp = new;
5477c478bd9Sstevel@tonic-gate 		}
5487c478bd9Sstevel@tonic-gate 		mutex_unlock(&mon_table[hash].lock);
5497c478bd9Sstevel@tonic-gate 		return;
5507c478bd9Sstevel@tonic-gate 	}
5517c478bd9Sstevel@tonic-gate }
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate /*
5547c478bd9Sstevel@tonic-gate  * Deletes a specific monitor name or deletes all monitors with same id
5557c478bd9Sstevel@tonic-gate  * in hash table.
5567c478bd9Sstevel@tonic-gate  */
5577c478bd9Sstevel@tonic-gate static void
delete_mon(char * mon_name,my_id * my_idp)558*98573c19SMarcel Telka delete_mon(char *mon_name, my_id *my_idp)
5597c478bd9Sstevel@tonic-gate {
5607c478bd9Sstevel@tonic-gate 	unsigned int hash;
5617c478bd9Sstevel@tonic-gate 
562*98573c19SMarcel Telka 	if (mon_name != NULL) {
5637c478bd9Sstevel@tonic-gate 		record_name(mon_name, 0);
5647c478bd9Sstevel@tonic-gate 		SMHASH(mon_name, hash);
5657c478bd9Sstevel@tonic-gate 		mutex_lock(&mon_table[hash].lock);
5667c478bd9Sstevel@tonic-gate 		delete_onemon(mon_name, my_idp, &mon_table[hash].sm_monhdp);
5677c478bd9Sstevel@tonic-gate 		mutex_unlock(&mon_table[hash].lock);
5687c478bd9Sstevel@tonic-gate 	} else {
5697c478bd9Sstevel@tonic-gate 		for (hash = 0; hash < MAX_HASHSIZE; hash++) {
5707c478bd9Sstevel@tonic-gate 			mutex_lock(&mon_table[hash].lock);
5717c478bd9Sstevel@tonic-gate 			delete_onemon(mon_name, my_idp,
5727c478bd9Sstevel@tonic-gate 			    &mon_table[hash].sm_monhdp);
5737c478bd9Sstevel@tonic-gate 			mutex_unlock(&mon_table[hash].lock);
5747c478bd9Sstevel@tonic-gate 		}
5757c478bd9Sstevel@tonic-gate 	}
5767c478bd9Sstevel@tonic-gate }
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate /*
5797c478bd9Sstevel@tonic-gate  * Deletes a monitor in list.
5807c478bd9Sstevel@tonic-gate  * IF mon_name is NULL, delete all mon_names that have the same id,
5817c478bd9Sstevel@tonic-gate  * else delete specific monitor.
5827c478bd9Sstevel@tonic-gate  */
5837c478bd9Sstevel@tonic-gate void
delete_onemon(char * mon_name,my_id * my_idp,mon_entry ** monitor_q)584*98573c19SMarcel Telka delete_onemon(char *mon_name, my_id *my_idp, mon_entry **monitor_q)
5857c478bd9Sstevel@tonic-gate {
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	mon_entry *next, *nl;
5887c478bd9Sstevel@tonic-gate 	my_id *nl_idp;
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 	next = *monitor_q;
591*98573c19SMarcel Telka 	while ((nl = next) != NULL) {
5927c478bd9Sstevel@tonic-gate 		next = next->nxt;
593*98573c19SMarcel Telka 		if (mon_name == NULL || (mon_name != NULL &&
5947c478bd9Sstevel@tonic-gate 		    str_cmp_unqual_hostname(nl->id.mon_id.mon_name,
5957c478bd9Sstevel@tonic-gate 		    mon_name) == 0)) {
5967c478bd9Sstevel@tonic-gate 			nl_idp = &nl->id.mon_id.my_id;
5977c478bd9Sstevel@tonic-gate 			if ((str_cmp_unqual_hostname(my_idp->my_name,
5987c478bd9Sstevel@tonic-gate 			    nl_idp->my_name) == 0) &&
5997c478bd9Sstevel@tonic-gate 			    my_idp->my_prog == nl_idp->my_prog &&
6007c478bd9Sstevel@tonic-gate 			    my_idp->my_vers == nl_idp->my_vers &&
6017c478bd9Sstevel@tonic-gate 			    my_idp->my_proc == nl_idp->my_proc) {
6027c478bd9Sstevel@tonic-gate 				/* found */
6037c478bd9Sstevel@tonic-gate 				if (debug)
6047c478bd9Sstevel@tonic-gate 					(void) printf("delete_mon(%x): %s\n",
6057c478bd9Sstevel@tonic-gate 					    (int)nl, mon_name ?
6067c478bd9Sstevel@tonic-gate 					    mon_name : "<NULL>");
6077c478bd9Sstevel@tonic-gate 				/*
6087c478bd9Sstevel@tonic-gate 				 * Remove the monitor name from the
6097c478bd9Sstevel@tonic-gate 				 * record_q, if id matches.
6107c478bd9Sstevel@tonic-gate 				 */
6117c478bd9Sstevel@tonic-gate 				record_name(nl->id.mon_id.mon_name, 0);
6127c478bd9Sstevel@tonic-gate 				/* if nl is not the first entry on list */
613*98573c19SMarcel Telka 				if (nl->prev != NULL)
6147c478bd9Sstevel@tonic-gate 					nl->prev->nxt = nl->nxt;
6157c478bd9Sstevel@tonic-gate 				else {
6167c478bd9Sstevel@tonic-gate 					*monitor_q = nl->nxt;
6177c478bd9Sstevel@tonic-gate 				}
618*98573c19SMarcel Telka 				if (nl->nxt != NULL)
6197c478bd9Sstevel@tonic-gate 					nl->nxt->prev = nl->prev;
6207c478bd9Sstevel@tonic-gate 				free(nl->id.mon_id.mon_name);
6217c478bd9Sstevel@tonic-gate 				free(nl_idp->my_name);
6227c478bd9Sstevel@tonic-gate 				free(nl);
6237c478bd9Sstevel@tonic-gate 			}
6247c478bd9Sstevel@tonic-gate 		} /* end of if mon */
6257c478bd9Sstevel@tonic-gate 	}
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate }
6287c478bd9Sstevel@tonic-gate /*
6297c478bd9Sstevel@tonic-gate  * Notify lockd of host specified by mon_name that the specified state
6307c478bd9Sstevel@tonic-gate  * has changed.
6317c478bd9Sstevel@tonic-gate  */
6327c478bd9Sstevel@tonic-gate static void
send_notice(char * mon_name,int state)633*98573c19SMarcel Telka send_notice(char *mon_name, int state)
6347c478bd9Sstevel@tonic-gate {
6357c478bd9Sstevel@tonic-gate 	struct mon_entry *next;
6367c478bd9Sstevel@tonic-gate 	mon_entry *monitor_q;
6377c478bd9Sstevel@tonic-gate 	unsigned int hash;
6387c478bd9Sstevel@tonic-gate 	moninfo_t *minfop;
6397c478bd9Sstevel@tonic-gate 	mon *monp;
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	SMHASH(mon_name, hash);
6427c478bd9Sstevel@tonic-gate 	mutex_lock(&mon_table[hash].lock);
6437c478bd9Sstevel@tonic-gate 	monitor_q = mon_table[hash].sm_monhdp;
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 	next = monitor_q;
646*98573c19SMarcel Telka 	while (next != NULL) {
6477c478bd9Sstevel@tonic-gate 		if (hostname_eq(next->id.mon_id.mon_name, mon_name)) {
6487c478bd9Sstevel@tonic-gate 			monp = &next->id;
6497c478bd9Sstevel@tonic-gate 			/*
6507c478bd9Sstevel@tonic-gate 			 * Prepare the minfop structure to pass to
6517c478bd9Sstevel@tonic-gate 			 * thr_create(). This structure is a copy of
6527c478bd9Sstevel@tonic-gate 			 * mon info and state.
6537c478bd9Sstevel@tonic-gate 			 */
6547c478bd9Sstevel@tonic-gate 			if ((minfop =
655*98573c19SMarcel Telka 			    (moninfo_t *)xmalloc(sizeof (moninfo_t))) != NULL) {
6567c478bd9Sstevel@tonic-gate 				(void) memcpy(&minfop->id, monp, sizeof (mon));
6577c478bd9Sstevel@tonic-gate 				/* Allocate entry for mon_name */
6587c478bd9Sstevel@tonic-gate 				if ((minfop->id.mon_id.mon_name =
6597c478bd9Sstevel@tonic-gate 				    strdup(monp->mon_id.mon_name)) == 0) {
660*98573c19SMarcel Telka 					syslog(LOG_ERR, "statd: send_notice: "
661*98573c19SMarcel Telka 					    "malloc error on mon %s (id=%d)\n",
6627c478bd9Sstevel@tonic-gate 					    monp->mon_id.mon_name,
6637c478bd9Sstevel@tonic-gate 					    *((int *)monp->priv));
6647c478bd9Sstevel@tonic-gate 					free(minfop);
6657c478bd9Sstevel@tonic-gate 					continue;
6667c478bd9Sstevel@tonic-gate 				}
6677c478bd9Sstevel@tonic-gate 				/* Allocate entry for my_name */
6687c478bd9Sstevel@tonic-gate 				if ((minfop->id.mon_id.my_id.my_name =
6697c478bd9Sstevel@tonic-gate 				    strdup(monp->mon_id.my_id.my_name)) == 0) {
670*98573c19SMarcel Telka 					syslog(LOG_ERR, "statd: send_notice: "
671*98573c19SMarcel Telka 					    "malloc error on mon %s (id=%d)\n",
6727c478bd9Sstevel@tonic-gate 					    monp->mon_id.mon_name,
6737c478bd9Sstevel@tonic-gate 					    *((int *)monp->priv));
6747c478bd9Sstevel@tonic-gate 					free(minfop->id.mon_id.mon_name);
6757c478bd9Sstevel@tonic-gate 					free(minfop);
6767c478bd9Sstevel@tonic-gate 					continue;
6777c478bd9Sstevel@tonic-gate 				}
6787c478bd9Sstevel@tonic-gate 				minfop->state = state;
6797c478bd9Sstevel@tonic-gate 				/*
6807c478bd9Sstevel@tonic-gate 				 * Create detached threads to process each host
6817c478bd9Sstevel@tonic-gate 				 * to notify.  If error, print out msg, free
6827c478bd9Sstevel@tonic-gate 				 * resources and continue.
6837c478bd9Sstevel@tonic-gate 				 */
6847c478bd9Sstevel@tonic-gate 				if (thr_create(NULL, NULL, thr_send_notice,
685*98573c19SMarcel Telka 				    minfop, THR_DETACHED, NULL)) {
686*98573c19SMarcel Telka 					syslog(LOG_ERR, "statd: unable to "
687*98573c19SMarcel Telka 					    "create thread to send_notice to "
688*98573c19SMarcel Telka 					    "%s.\n", mon_name);
6897c478bd9Sstevel@tonic-gate 					free(minfop->id.mon_id.mon_name);
6907c478bd9Sstevel@tonic-gate 					free(minfop->id.mon_id.my_id.my_name);
6917c478bd9Sstevel@tonic-gate 					free(minfop);
6927c478bd9Sstevel@tonic-gate 					continue;
6937c478bd9Sstevel@tonic-gate 				}
6947c478bd9Sstevel@tonic-gate 			}
6957c478bd9Sstevel@tonic-gate 		}
6967c478bd9Sstevel@tonic-gate 		next = next->nxt;
6977c478bd9Sstevel@tonic-gate 	}
6987c478bd9Sstevel@tonic-gate 	mutex_unlock(&mon_table[hash].lock);
6997c478bd9Sstevel@tonic-gate }
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate /*
7027c478bd9Sstevel@tonic-gate  * Work thread created to do the actual statd_call_lockd
7037c478bd9Sstevel@tonic-gate  */
7047c478bd9Sstevel@tonic-gate static void *
thr_send_notice(void * arg)7057c478bd9Sstevel@tonic-gate thr_send_notice(void *arg)
7067c478bd9Sstevel@tonic-gate {
7077c478bd9Sstevel@tonic-gate 	moninfo_t *minfop;
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate 	minfop = (moninfo_t *)arg;
7107c478bd9Sstevel@tonic-gate 	if (statd_call_lockd(&minfop->id, minfop->state) == -1) {
7117c478bd9Sstevel@tonic-gate 		if (debug && minfop->id.mon_id.mon_name)
712b17f03d7SMarcel Telka 			(void) printf("problem with notifying %s failure, "
713b17f03d7SMarcel Telka 			    "give up\n", minfop->id.mon_id.mon_name);
7147c478bd9Sstevel@tonic-gate 	} else {
7157c478bd9Sstevel@tonic-gate 		if (debug)
716b17f03d7SMarcel Telka 			(void) printf("send_notice: %s, %d notified.\n",
7177c478bd9Sstevel@tonic-gate 			    minfop->id.mon_id.mon_name, minfop->state);
7187c478bd9Sstevel@tonic-gate 	}
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate 	free(minfop->id.mon_id.mon_name);
7217c478bd9Sstevel@tonic-gate 	free(minfop->id.mon_id.my_id.my_name);
7227c478bd9Sstevel@tonic-gate 	free(minfop);
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate 	thr_exit((void *) 0);
7257c478bd9Sstevel@tonic-gate #ifdef lint
7267c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
7277c478bd9Sstevel@tonic-gate 	return ((void *)0);
7287c478bd9Sstevel@tonic-gate #endif
7297c478bd9Sstevel@tonic-gate }
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate /*
7327c478bd9Sstevel@tonic-gate  * Contact lockd specified by monp.
7337c478bd9Sstevel@tonic-gate  */
7347c478bd9Sstevel@tonic-gate static int
statd_call_lockd(mon * monp,int state)735*98573c19SMarcel Telka statd_call_lockd(mon *monp, int state)
7367c478bd9Sstevel@tonic-gate {
7377c478bd9Sstevel@tonic-gate 	enum clnt_stat clnt_stat;
7387c478bd9Sstevel@tonic-gate 	struct timeval tottimeout;
739bbaa8b60SDan Kruchinin 	struct sm_status stat;
7407c478bd9Sstevel@tonic-gate 	my_id *my_idp;
7417c478bd9Sstevel@tonic-gate 	char *mon_name;
7427c478bd9Sstevel@tonic-gate 	int i;
7437c478bd9Sstevel@tonic-gate 	int rc = 0;
7447c478bd9Sstevel@tonic-gate 	CLIENT *clnt;
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate 	mon_name = monp->mon_id.mon_name;
7477c478bd9Sstevel@tonic-gate 	my_idp = &monp->mon_id.my_id;
748bbaa8b60SDan Kruchinin 	(void) memset(&stat, 0, sizeof (stat));
7497c478bd9Sstevel@tonic-gate 	stat.mon_name = mon_name;
7507c478bd9Sstevel@tonic-gate 	stat.state = state;
7517c478bd9Sstevel@tonic-gate 	for (i = 0; i < 16; i++) {
7527c478bd9Sstevel@tonic-gate 		stat.priv[i] = monp->priv[i];
7537c478bd9Sstevel@tonic-gate 	}
7547c478bd9Sstevel@tonic-gate 	if (debug)
7557c478bd9Sstevel@tonic-gate 		(void) printf("statd_call_lockd: %s state = %d\n",
7567c478bd9Sstevel@tonic-gate 		    stat.mon_name, stat.state);
7577c478bd9Sstevel@tonic-gate 
758a6f0fae9Sgt29601 	tottimeout.tv_sec = SM_RPC_TIMEOUT;
759a6f0fae9Sgt29601 	tottimeout.tv_usec = 0;
760a6f0fae9Sgt29601 
761bbaa8b60SDan Kruchinin 	clnt = create_client(my_idp->my_name, my_idp->my_prog, my_idp->my_vers,
762bbaa8b60SDan Kruchinin 	    "ticotsord", &tottimeout);
763bbaa8b60SDan Kruchinin 	if (clnt == NULL) {
7647c478bd9Sstevel@tonic-gate 		return (-1);
7657c478bd9Sstevel@tonic-gate 	}
7667c478bd9Sstevel@tonic-gate 
767*98573c19SMarcel Telka 	clnt_stat = clnt_call(clnt, my_idp->my_proc, xdr_sm_status,
768*98573c19SMarcel Telka 	    (char *)&stat, xdr_void, NULL, tottimeout);
7697c478bd9Sstevel@tonic-gate 	if (debug) {
7707c478bd9Sstevel@tonic-gate 		(void) printf("clnt_stat=%s(%d)\n",
7717c478bd9Sstevel@tonic-gate 		    clnt_sperrno(clnt_stat), clnt_stat);
7727c478bd9Sstevel@tonic-gate 	}
7737c478bd9Sstevel@tonic-gate 	if (clnt_stat != (int)RPC_SUCCESS) {
7747c478bd9Sstevel@tonic-gate 		syslog(LOG_WARNING,
7757c478bd9Sstevel@tonic-gate 		    "statd: cannot talk to lockd at %s, %s(%d)\n",
7767c478bd9Sstevel@tonic-gate 		    my_idp->my_name, clnt_sperrno(clnt_stat), clnt_stat);
7777c478bd9Sstevel@tonic-gate 		rc = -1;
7787c478bd9Sstevel@tonic-gate 	}
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate 	clnt_destroy(clnt);
7817c478bd9Sstevel@tonic-gate 	return (rc);
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate }
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate /*
7867c478bd9Sstevel@tonic-gate  * Client handle created.
7877c478bd9Sstevel@tonic-gate  */
7887c478bd9Sstevel@tonic-gate CLIENT *
create_client(char * host,int prognum,int versnum,char * netid,struct timeval * utimeout)789bbaa8b60SDan Kruchinin create_client(char *host, int prognum, int versnum, char *netid,
790bbaa8b60SDan Kruchinin     struct timeval *utimeout)
7917c478bd9Sstevel@tonic-gate {
7927c478bd9Sstevel@tonic-gate 	int		fd;
7937c478bd9Sstevel@tonic-gate 	struct timeval	timeout;
7947c478bd9Sstevel@tonic-gate 	CLIENT		*client;
7957c478bd9Sstevel@tonic-gate 	struct t_info	tinfo;
7967c478bd9Sstevel@tonic-gate 
797bbaa8b60SDan Kruchinin 	if (netid == NULL) {
798bbaa8b60SDan Kruchinin 		client = clnt_create_timed(host, prognum, versnum,
799bbaa8b60SDan Kruchinin 		    "netpath", utimeout);
800bbaa8b60SDan Kruchinin 	} else {
801bbaa8b60SDan Kruchinin 		struct netconfig *nconf;
802bbaa8b60SDan Kruchinin 
803bbaa8b60SDan Kruchinin 		nconf = getnetconfigent(netid);
804bbaa8b60SDan Kruchinin 		if (nconf == NULL) {
8057c478bd9Sstevel@tonic-gate 			return (NULL);
8067c478bd9Sstevel@tonic-gate 		}
807bbaa8b60SDan Kruchinin 
808bbaa8b60SDan Kruchinin 		client = clnt_tp_create_timed(host, prognum, versnum, nconf,
809bbaa8b60SDan Kruchinin 		    utimeout);
810bbaa8b60SDan Kruchinin 
811bbaa8b60SDan Kruchinin 		freenetconfigent(nconf);
812bbaa8b60SDan Kruchinin 	}
813bbaa8b60SDan Kruchinin 
814bbaa8b60SDan Kruchinin 	if (client == NULL) {
815bbaa8b60SDan Kruchinin 		return (NULL);
816bbaa8b60SDan Kruchinin 	}
817bbaa8b60SDan Kruchinin 
8187c478bd9Sstevel@tonic-gate 	(void) CLNT_CONTROL(client, CLGET_FD, (caddr_t)&fd);
8197c478bd9Sstevel@tonic-gate 	if (t_getinfo(fd, &tinfo) != -1) {
8207c478bd9Sstevel@tonic-gate 		if (tinfo.servtype == T_CLTS) {
8217c478bd9Sstevel@tonic-gate 			/*
8227c478bd9Sstevel@tonic-gate 			 * Set time outs for connectionless case
8237c478bd9Sstevel@tonic-gate 			 */
8247c478bd9Sstevel@tonic-gate 			timeout.tv_usec = 0;
8257c478bd9Sstevel@tonic-gate 			timeout.tv_sec = SM_CLTS_TIMEOUT;
8267c478bd9Sstevel@tonic-gate 			(void) CLNT_CONTROL(client,
8277c478bd9Sstevel@tonic-gate 			    CLSET_RETRY_TIMEOUT, (caddr_t)&timeout);
8287c478bd9Sstevel@tonic-gate 		}
8297c478bd9Sstevel@tonic-gate 	} else
8307c478bd9Sstevel@tonic-gate 		return (NULL);
8317c478bd9Sstevel@tonic-gate 
8327c478bd9Sstevel@tonic-gate 	return (client);
8337c478bd9Sstevel@tonic-gate }
8347c478bd9Sstevel@tonic-gate 
8357c478bd9Sstevel@tonic-gate /*
8367c478bd9Sstevel@tonic-gate  * ONLY for debugging.
8377c478bd9Sstevel@tonic-gate  * Debug messages which prints out the monitor table information.
8387c478bd9Sstevel@tonic-gate  * If name is specified, just print out the hash list corresponding
8397c478bd9Sstevel@tonic-gate  * to name, otherwise print out the entire monitor table.
8407c478bd9Sstevel@tonic-gate  */
8417c478bd9Sstevel@tonic-gate static void
pr_mon(char * name)842*98573c19SMarcel Telka pr_mon(char *name)
8437c478bd9Sstevel@tonic-gate {
8447c478bd9Sstevel@tonic-gate 	mon_entry *nl;
8457c478bd9Sstevel@tonic-gate 	int hash;
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate 	if (!debug)
8487c478bd9Sstevel@tonic-gate 		return;
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 	/* print all */
8517c478bd9Sstevel@tonic-gate 	if (name == NULL) {
8527c478bd9Sstevel@tonic-gate 		for (hash = 0; hash < MAX_HASHSIZE; hash++) {
8537c478bd9Sstevel@tonic-gate 			mutex_lock(&mon_table[hash].lock);
8547c478bd9Sstevel@tonic-gate 			nl = mon_table[hash].sm_monhdp;
855*98573c19SMarcel Telka 			if (nl == NULL) {
8567c478bd9Sstevel@tonic-gate 				(void) printf(
857*98573c19SMarcel Telka 				    "*****monitor_q = NULL hash %d\n", hash);
8587c478bd9Sstevel@tonic-gate 				mutex_unlock(&mon_table[hash].lock);
8597c478bd9Sstevel@tonic-gate 				continue;
8607c478bd9Sstevel@tonic-gate 			}
8617c478bd9Sstevel@tonic-gate 			(void) printf("*****monitor_q:\n ");
862*98573c19SMarcel Telka 			while (nl != NULL) {
8637c478bd9Sstevel@tonic-gate 				(void) printf("%s:(%x), ",
8647c478bd9Sstevel@tonic-gate 				    nl->id.mon_id.mon_name, (int)nl);
8657c478bd9Sstevel@tonic-gate 				nl = nl->nxt;
8667c478bd9Sstevel@tonic-gate 			}
8677c478bd9Sstevel@tonic-gate 			mutex_unlock(&mon_table[hash].lock);
8687c478bd9Sstevel@tonic-gate 			(void) printf("\n");
8697c478bd9Sstevel@tonic-gate 		}
8707c478bd9Sstevel@tonic-gate 	} else { /* print one hash list */
8717c478bd9Sstevel@tonic-gate 		SMHASH(name, hash);
8727c478bd9Sstevel@tonic-gate 		mutex_lock(&mon_table[hash].lock);
8737c478bd9Sstevel@tonic-gate 		nl = mon_table[hash].sm_monhdp;
874*98573c19SMarcel Telka 		if (nl == NULL) {
8757c478bd9Sstevel@tonic-gate 			(void) printf("*****monitor_q = NULL hash %d\n", hash);
8767c478bd9Sstevel@tonic-gate 		} else {
8777c478bd9Sstevel@tonic-gate 			(void) printf("*****monitor_q:\n ");
878*98573c19SMarcel Telka 			while (nl != NULL) {
8797c478bd9Sstevel@tonic-gate 				(void) printf("%s:(%x), ",
8807c478bd9Sstevel@tonic-gate 				    nl->id.mon_id.mon_name, (int)nl);
8817c478bd9Sstevel@tonic-gate 				nl = nl->nxt;
8827c478bd9Sstevel@tonic-gate 			}
8837c478bd9Sstevel@tonic-gate 			(void) printf("\n");
8847c478bd9Sstevel@tonic-gate 		}
8857c478bd9Sstevel@tonic-gate 		mutex_unlock(&mon_table[hash].lock);
8867c478bd9Sstevel@tonic-gate 	}
8877c478bd9Sstevel@tonic-gate }
8887c478bd9Sstevel@tonic-gate 
8897c478bd9Sstevel@tonic-gate /*
8907c478bd9Sstevel@tonic-gate  * Only for debugging.
8917c478bd9Sstevel@tonic-gate  * Dump the host name-to-address translation table passed in `name_addr'.
8927c478bd9Sstevel@tonic-gate  */
8937c478bd9Sstevel@tonic-gate static void
pr_name_addr(name_addr_entry_t * name_addr)8947c478bd9Sstevel@tonic-gate pr_name_addr(name_addr_entry_t *name_addr)
8957c478bd9Sstevel@tonic-gate {
8967c478bd9Sstevel@tonic-gate 	name_addr_entry_t *entry;
8977c478bd9Sstevel@tonic-gate 	addr_entry_t *addr;
8987c478bd9Sstevel@tonic-gate 	struct in_addr ipv4_addr;
8997c478bd9Sstevel@tonic-gate 	char *ipv6_addr;
9007c478bd9Sstevel@tonic-gate 	char abuf[INET6_ADDRSTRLEN];
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate 	assert(MUTEX_HELD(&name_addrlock));
9037c478bd9Sstevel@tonic-gate 	(void) printf("name-to-address translation table:\n");
9047c478bd9Sstevel@tonic-gate 	for (entry = name_addr; entry != NULL; entry = entry->next) {
9057c478bd9Sstevel@tonic-gate 		(void) printf("\t%s: ",
9067c478bd9Sstevel@tonic-gate 		    (entry->name ? entry->name : "(null)"));
9077c478bd9Sstevel@tonic-gate 		for (addr = entry->addresses; addr; addr = addr->next) {
9087c478bd9Sstevel@tonic-gate 			switch (addr->family) {
9097c478bd9Sstevel@tonic-gate 			case AF_INET:
910b17f03d7SMarcel Telka 				ipv4_addr = *(struct in_addr *)addr->ah.n_bytes;
9117c478bd9Sstevel@tonic-gate 				(void) printf(" %s (fam %d)",
912b17f03d7SMarcel Telka 				    inet_ntoa(ipv4_addr), addr->family);
9137c478bd9Sstevel@tonic-gate 				break;
9147c478bd9Sstevel@tonic-gate 			case AF_INET6:
9157c478bd9Sstevel@tonic-gate 				ipv6_addr = (char *)addr->ah.n_bytes;
9167c478bd9Sstevel@tonic-gate 				(void) printf(" %s (fam %d)",
917b17f03d7SMarcel Telka 				    inet_ntop(addr->family, ipv6_addr, abuf,
918b17f03d7SMarcel Telka 				    sizeof (abuf)), addr->family);
9197c478bd9Sstevel@tonic-gate 				break;
9207c478bd9Sstevel@tonic-gate 			default:
9217c478bd9Sstevel@tonic-gate 				return;
9227c478bd9Sstevel@tonic-gate 			}
9237c478bd9Sstevel@tonic-gate 		}
9247c478bd9Sstevel@tonic-gate 		printf("\n");
9257c478bd9Sstevel@tonic-gate 	}
9267c478bd9Sstevel@tonic-gate }
9277c478bd9Sstevel@tonic-gate 
9287c478bd9Sstevel@tonic-gate /*
929b17f03d7SMarcel Telka  * First, try to compare the hostnames as strings.  If the hostnames does not
930b17f03d7SMarcel Telka  * match we might deal with the hostname aliases.  In this case two different
931b17f03d7SMarcel Telka  * aliases for the same machine don't match each other when using strcmp.  To
932b17f03d7SMarcel Telka  * deal with this, the hostnames must be translated into some sort of universal
933b17f03d7SMarcel Telka  * identifier.  These identifiers can be compared.  Universal network addresses
934b17f03d7SMarcel Telka  * are currently used for this identifier because it is general and easy to do.
935b17f03d7SMarcel Telka  * Other schemes are possible and this routine could be converted if required.
9367c478bd9Sstevel@tonic-gate  *
9377c478bd9Sstevel@tonic-gate  * If it can't find an address for some reason, 0 is returned.
9387c478bd9Sstevel@tonic-gate  */
9397c478bd9Sstevel@tonic-gate static int
hostname_eq(char * host1,char * host2)9407c478bd9Sstevel@tonic-gate hostname_eq(char *host1, char *host2)
9417c478bd9Sstevel@tonic-gate {
9427c478bd9Sstevel@tonic-gate 	char *sysid1;
9437c478bd9Sstevel@tonic-gate 	char *sysid2;
9447c478bd9Sstevel@tonic-gate 	int rv;
9457c478bd9Sstevel@tonic-gate 
946b17f03d7SMarcel Telka 	/* Compare hostnames as strings */
947b17f03d7SMarcel Telka 	if (host1 != NULL && host2 != NULL && strcmp(host1, host2) == 0)
948b17f03d7SMarcel Telka 		return (1);
949b17f03d7SMarcel Telka 
950b17f03d7SMarcel Telka 	/* Try harder if hostnames do not match */
9517c478bd9Sstevel@tonic-gate 	sysid1 = get_system_id(host1);
9527c478bd9Sstevel@tonic-gate 	sysid2 = get_system_id(host2);
9537c478bd9Sstevel@tonic-gate 	if ((sysid1 == NULL) || (sysid2 == NULL))
9547c478bd9Sstevel@tonic-gate 		rv = 0;
9557c478bd9Sstevel@tonic-gate 	else
9567c478bd9Sstevel@tonic-gate 		rv = (strcmp(sysid1, sysid2) == 0);
9577c478bd9Sstevel@tonic-gate 	free(sysid1);
9587c478bd9Sstevel@tonic-gate 	free(sysid2);
9597c478bd9Sstevel@tonic-gate 	return (rv);
9607c478bd9Sstevel@tonic-gate }
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate /*
9637c478bd9Sstevel@tonic-gate  * Convert a hostname character string into its network address.
9647c478bd9Sstevel@tonic-gate  * A network address is found by searching through all the entries
9657c478bd9Sstevel@tonic-gate  * in /etc/netconfig and doing a netdir_getbyname() for each inet
9667c478bd9Sstevel@tonic-gate  * entry found.  The netbuf structure returned is converted into
9677c478bd9Sstevel@tonic-gate  * a universal address format.
9687c478bd9Sstevel@tonic-gate  *
9697c478bd9Sstevel@tonic-gate  * If a NULL hostname is given, then the name of the current host
9707c478bd9Sstevel@tonic-gate  * is used.  If the hostname doesn't map to an address, a NULL
9717c478bd9Sstevel@tonic-gate  * pointer is returned.
9727c478bd9Sstevel@tonic-gate  *
9737c478bd9Sstevel@tonic-gate  * N.B. the character string returned is allocated in taddr2uaddr()
9747c478bd9Sstevel@tonic-gate  * and should be freed by the caller using free().
9757c478bd9Sstevel@tonic-gate  */
9767c478bd9Sstevel@tonic-gate static char *
get_system_id(char * hostname)9777c478bd9Sstevel@tonic-gate get_system_id(char *hostname)
9787c478bd9Sstevel@tonic-gate {
9797c478bd9Sstevel@tonic-gate 	void *hp;
9807c478bd9Sstevel@tonic-gate 	struct netconfig *ncp;
9817c478bd9Sstevel@tonic-gate 	struct nd_hostserv service;
9827c478bd9Sstevel@tonic-gate 	struct nd_addrlist *addrs;
9837c478bd9Sstevel@tonic-gate 	char *uaddr;
9847c478bd9Sstevel@tonic-gate 	int rv;
9857c478bd9Sstevel@tonic-gate 
9867c478bd9Sstevel@tonic-gate 	if (hostname == NULL)
9877c478bd9Sstevel@tonic-gate 		service.h_host = HOST_SELF;
9887c478bd9Sstevel@tonic-gate 	else
9897c478bd9Sstevel@tonic-gate 		service.h_host = hostname;
9907c478bd9Sstevel@tonic-gate 	service.h_serv = NULL;
9917c478bd9Sstevel@tonic-gate 	hp = setnetconfig();
9927c478bd9Sstevel@tonic-gate 	if (hp == (void *) NULL) {
9937c478bd9Sstevel@tonic-gate 		return (NULL);
9947c478bd9Sstevel@tonic-gate 	}
995*98573c19SMarcel Telka 	while ((ncp = getnetconfig(hp)) != NULL) {
9967c478bd9Sstevel@tonic-gate 		if ((strcmp(ncp->nc_protofmly, NC_INET) == 0) ||
9977c478bd9Sstevel@tonic-gate 		    (strcmp(ncp->nc_protofmly, NC_INET6) == 0)) {
9987c478bd9Sstevel@tonic-gate 			addrs = NULL;
9997c478bd9Sstevel@tonic-gate 			rv = netdir_getbyname(ncp, &service, &addrs);
10007c478bd9Sstevel@tonic-gate 			if (rv != 0) {
10017c478bd9Sstevel@tonic-gate 				continue;
10027c478bd9Sstevel@tonic-gate 			}
10037c478bd9Sstevel@tonic-gate 			if (addrs) {
10047c478bd9Sstevel@tonic-gate 				uaddr = taddr2uaddr(ncp, addrs->n_addrs);
10057c478bd9Sstevel@tonic-gate 				netdir_free(addrs, ND_ADDRLIST);
10067c478bd9Sstevel@tonic-gate 				endnetconfig(hp);
10077c478bd9Sstevel@tonic-gate 				return (uaddr);
10087c478bd9Sstevel@tonic-gate 			}
10097c478bd9Sstevel@tonic-gate 		}
10107c478bd9Sstevel@tonic-gate 		else
10117c478bd9Sstevel@tonic-gate 			continue;
10127c478bd9Sstevel@tonic-gate 	}
10137c478bd9Sstevel@tonic-gate 	endnetconfig(hp);
10147c478bd9Sstevel@tonic-gate 	return (NULL);
10157c478bd9Sstevel@tonic-gate }
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate void
merge_hosts(void)10187c478bd9Sstevel@tonic-gate merge_hosts(void)
10197c478bd9Sstevel@tonic-gate {
10207c478bd9Sstevel@tonic-gate 	struct lifconf *lifc = NULL;
10217c478bd9Sstevel@tonic-gate 	int sock = -1;
10227c478bd9Sstevel@tonic-gate 	struct lifreq *lifrp;
10237c478bd9Sstevel@tonic-gate 	struct lifreq lifr;
10247c478bd9Sstevel@tonic-gate 	int n;
10257c478bd9Sstevel@tonic-gate 	struct sockaddr_in *sin;
10267c478bd9Sstevel@tonic-gate 	struct sockaddr_in6 *sin6;
10277c478bd9Sstevel@tonic-gate 	struct sockaddr_storage *sa;
10287c478bd9Sstevel@tonic-gate 	int af;
10297c478bd9Sstevel@tonic-gate 	struct hostent *phost;
10307c478bd9Sstevel@tonic-gate 	char *addr;
10317c478bd9Sstevel@tonic-gate 	size_t alen;
10327c478bd9Sstevel@tonic-gate 	int errnum;
10337c478bd9Sstevel@tonic-gate 
10347c478bd9Sstevel@tonic-gate 	/*
10357c478bd9Sstevel@tonic-gate 	 * This function will enumerate all the interfaces for
10367c478bd9Sstevel@tonic-gate 	 * this platform, then get the hostent for each i/f.
10377c478bd9Sstevel@tonic-gate 	 * With the hostent structure, we can get all of the
10387c478bd9Sstevel@tonic-gate 	 * aliases for the i/f. Then we'll merge all the aliases
10397c478bd9Sstevel@tonic-gate 	 * with the existing host_name[] list to come up with
10407c478bd9Sstevel@tonic-gate 	 * all of the known names for each interface. This solves
10417c478bd9Sstevel@tonic-gate 	 * the problem of a multi-homed host not knowing which
10427c478bd9Sstevel@tonic-gate 	 * name to publish when statd is started. All the aliases
10437c478bd9Sstevel@tonic-gate 	 * will be stored in the array, host_name.
10447c478bd9Sstevel@tonic-gate 	 *
10457c478bd9Sstevel@tonic-gate 	 * NOTE: Even though we will use all of the aliases we
10467c478bd9Sstevel@tonic-gate 	 * can get from the i/f hostent, the receiving statd
10477c478bd9Sstevel@tonic-gate 	 * will still need to handle aliases with hostname_eq.
10487c478bd9Sstevel@tonic-gate 	 * This is because the sender's aliases may not match
10497c478bd9Sstevel@tonic-gate 	 * those of the receiver.
10507c478bd9Sstevel@tonic-gate 	 */
10517c478bd9Sstevel@tonic-gate 	lifc = getmyaddrs();
1052*98573c19SMarcel Telka 	if (lifc == NULL) {
10537c478bd9Sstevel@tonic-gate 		goto finish;
10547c478bd9Sstevel@tonic-gate 	}
10557c478bd9Sstevel@tonic-gate 	lifrp = lifc->lifc_req;
10567c478bd9Sstevel@tonic-gate 	for (n = lifc->lifc_len / sizeof (struct lifreq); n > 0; n--, lifrp++) {
10577c478bd9Sstevel@tonic-gate 
10587c478bd9Sstevel@tonic-gate 		(void) strncpy(lifr.lifr_name, lifrp->lifr_name,
10597c478bd9Sstevel@tonic-gate 		    sizeof (lifr.lifr_name));
10607c478bd9Sstevel@tonic-gate 
10617c478bd9Sstevel@tonic-gate 		af = lifrp->lifr_addr.ss_family;
10627c478bd9Sstevel@tonic-gate 		sock = socket(af, SOCK_DGRAM, 0);
10637c478bd9Sstevel@tonic-gate 		if (sock == -1) {
10647c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "statd: socket failed\n");
10657c478bd9Sstevel@tonic-gate 			goto finish;
10667c478bd9Sstevel@tonic-gate 		}
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate 		/* If it's the loopback interface, ignore */
10697c478bd9Sstevel@tonic-gate 		if (ioctl(sock, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
10707c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
10717c478bd9Sstevel@tonic-gate 			    "statd: SIOCGLIFFLAGS failed, error: %m\n");
10727c478bd9Sstevel@tonic-gate 			goto finish;
10737c478bd9Sstevel@tonic-gate 		}
10747c478bd9Sstevel@tonic-gate 		if (lifr.lifr_flags & IFF_LOOPBACK)
10757c478bd9Sstevel@tonic-gate 			continue;
10767c478bd9Sstevel@tonic-gate 
10777c478bd9Sstevel@tonic-gate 		if (ioctl(sock, SIOCGLIFADDR, (caddr_t)&lifr) < 0) {
10787c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
10797c478bd9Sstevel@tonic-gate 			    "statd: SIOCGLIFADDR failed, error: %m\n");
10807c478bd9Sstevel@tonic-gate 			goto finish;
10817c478bd9Sstevel@tonic-gate 		}
10827c478bd9Sstevel@tonic-gate 		sa = (struct sockaddr_storage *)&(lifr.lifr_addr);
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate 		if (sa->ss_family == AF_INET) {
10857c478bd9Sstevel@tonic-gate 			sin = (struct sockaddr_in *)&lifr.lifr_addr;
10867c478bd9Sstevel@tonic-gate 			addr = (char *)(&sin->sin_addr);
10877c478bd9Sstevel@tonic-gate 			alen = sizeof (struct in_addr);
10887c478bd9Sstevel@tonic-gate 		} else if (sa->ss_family == AF_INET6) {
10897c478bd9Sstevel@tonic-gate 			sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
10907c478bd9Sstevel@tonic-gate 			addr = (char *)(&sin6->sin6_addr);
10917c478bd9Sstevel@tonic-gate 			alen = sizeof (struct in6_addr);
10927c478bd9Sstevel@tonic-gate 		} else {
10937c478bd9Sstevel@tonic-gate 			syslog(LOG_WARNING,
10947c478bd9Sstevel@tonic-gate 			    "unexpected address family (%d)",
10957c478bd9Sstevel@tonic-gate 			    sa->ss_family);
10967c478bd9Sstevel@tonic-gate 			continue;
10977c478bd9Sstevel@tonic-gate 		}
10987c478bd9Sstevel@tonic-gate 
10997c478bd9Sstevel@tonic-gate 		phost = getipnodebyaddr(addr, alen, sa->ss_family, &errnum);
11007c478bd9Sstevel@tonic-gate 
11017c478bd9Sstevel@tonic-gate 		if (phost)
11027c478bd9Sstevel@tonic-gate 			add_aliases(phost);
11037c478bd9Sstevel@tonic-gate 	}
11047c478bd9Sstevel@tonic-gate 	/*
11057c478bd9Sstevel@tonic-gate 	 * Now, just in case we didn't get them all byaddr,
11067c478bd9Sstevel@tonic-gate 	 * let's look by name.
11077c478bd9Sstevel@tonic-gate 	 */
11087c478bd9Sstevel@tonic-gate 	phost = getipnodebyname(hostname, AF_INET6, AI_ALL, &errnum);
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate 	if (phost)
11117c478bd9Sstevel@tonic-gate 		add_aliases(phost);
11127c478bd9Sstevel@tonic-gate 
11137c478bd9Sstevel@tonic-gate finish:
11147c478bd9Sstevel@tonic-gate 	if (sock != -1)
11157c478bd9Sstevel@tonic-gate 		(void) close(sock);
11167c478bd9Sstevel@tonic-gate 	if (lifc) {
11177c478bd9Sstevel@tonic-gate 		free(lifc->lifc_buf);
11187c478bd9Sstevel@tonic-gate 		free(lifc);
11197c478bd9Sstevel@tonic-gate 	}
11207c478bd9Sstevel@tonic-gate }
11217c478bd9Sstevel@tonic-gate 
11227c478bd9Sstevel@tonic-gate /*
11237c478bd9Sstevel@tonic-gate  * add_aliases traverses a hostent alias list, compares
11247c478bd9Sstevel@tonic-gate  * the aliases to the contents of host_name, and if an
11257c478bd9Sstevel@tonic-gate  * alias is not already present, adds it to host_name[].
11267c478bd9Sstevel@tonic-gate  */
11277c478bd9Sstevel@tonic-gate 
11287c478bd9Sstevel@tonic-gate static void
add_aliases(struct hostent * phost)11297c478bd9Sstevel@tonic-gate add_aliases(struct hostent *phost)
11307c478bd9Sstevel@tonic-gate {
11317c478bd9Sstevel@tonic-gate 	char **aliases;
11327c478bd9Sstevel@tonic-gate 
11337c478bd9Sstevel@tonic-gate 	if (!in_host_array(phost->h_name)) {
11347c478bd9Sstevel@tonic-gate 		add_to_host_array(phost->h_name);
11357c478bd9Sstevel@tonic-gate 	}
11367c478bd9Sstevel@tonic-gate 
11377c478bd9Sstevel@tonic-gate 	if (phost->h_aliases == NULL)
11387c478bd9Sstevel@tonic-gate 		return;			/* no aliases to register */
11397c478bd9Sstevel@tonic-gate 
11407c478bd9Sstevel@tonic-gate 	for (aliases = phost->h_aliases; *aliases != NULL; aliases++) {
11417c478bd9Sstevel@tonic-gate 		if (!in_host_array(*aliases)) {
11427c478bd9Sstevel@tonic-gate 			add_to_host_array(*aliases);
11437c478bd9Sstevel@tonic-gate 		}
11447c478bd9Sstevel@tonic-gate 	}
11457c478bd9Sstevel@tonic-gate }
11467c478bd9Sstevel@tonic-gate 
11477c478bd9Sstevel@tonic-gate /*
11487c478bd9Sstevel@tonic-gate  * in_host_array checks if the given hostname exists in the host_name
11497c478bd9Sstevel@tonic-gate  * array. Returns 0 if the host doesn't exist, and 1 if it does exist
11507c478bd9Sstevel@tonic-gate  */
11517c478bd9Sstevel@tonic-gate static int
in_host_array(char * host)11527c478bd9Sstevel@tonic-gate in_host_array(char *host)
11537c478bd9Sstevel@tonic-gate {
11547c478bd9Sstevel@tonic-gate 	int i;
11557c478bd9Sstevel@tonic-gate 
11567c478bd9Sstevel@tonic-gate 	if (debug)
11577c478bd9Sstevel@tonic-gate 		(void) printf("%s ", host);
11587c478bd9Sstevel@tonic-gate 
11597c478bd9Sstevel@tonic-gate 	if ((strcmp(hostname, host) == 0) || (strcmp(LOGHOST, host) == 0))
11607c478bd9Sstevel@tonic-gate 		return (1);
11617c478bd9Sstevel@tonic-gate 
11627c478bd9Sstevel@tonic-gate 	for (i = 0; i < addrix; i++) {
11637c478bd9Sstevel@tonic-gate 		if (strcmp(host_name[i], host) == 0)
11647c478bd9Sstevel@tonic-gate 			return (1);
11657c478bd9Sstevel@tonic-gate 	}
11667c478bd9Sstevel@tonic-gate 
11677c478bd9Sstevel@tonic-gate 	return (0);
11687c478bd9Sstevel@tonic-gate }
11697c478bd9Sstevel@tonic-gate 
11707c478bd9Sstevel@tonic-gate /*
11717c478bd9Sstevel@tonic-gate  * add_to_host_array adds a hostname to the host_name array. But if
11727c478bd9Sstevel@tonic-gate  * the array is already full, then it first reallocates the array with
11737c478bd9Sstevel@tonic-gate  * HOST_NAME_INCR extra elements. If the realloc fails, then it does
11747c478bd9Sstevel@tonic-gate  * nothing and leaves host_name the way it was previous to the call.
11757c478bd9Sstevel@tonic-gate  */
11767c478bd9Sstevel@tonic-gate static void
add_to_host_array(char * host)11777c478bd9Sstevel@tonic-gate add_to_host_array(char *host) {
11787c478bd9Sstevel@tonic-gate 
11797c478bd9Sstevel@tonic-gate 	void *new_block = NULL;
11807c478bd9Sstevel@tonic-gate 
11817c478bd9Sstevel@tonic-gate 	/* Make sure we don't overrun host_name. */
11827c478bd9Sstevel@tonic-gate 	if (addrix >= host_name_count) {
11837c478bd9Sstevel@tonic-gate 		host_name_count += HOST_NAME_INCR;
11847c478bd9Sstevel@tonic-gate 		new_block = realloc((void *)host_name,
11857c478bd9Sstevel@tonic-gate 				    host_name_count*sizeof (char *));
11867c478bd9Sstevel@tonic-gate 		if (new_block != NULL)
11877c478bd9Sstevel@tonic-gate 			host_name = new_block;
11887c478bd9Sstevel@tonic-gate 		else {
11897c478bd9Sstevel@tonic-gate 			host_name_count -= HOST_NAME_INCR;
11907c478bd9Sstevel@tonic-gate 			return;
11917c478bd9Sstevel@tonic-gate 		}
11927c478bd9Sstevel@tonic-gate 	}
11937c478bd9Sstevel@tonic-gate 
11947c478bd9Sstevel@tonic-gate 	if ((host_name[addrix] = strdup(host)) != NULL)
11957c478bd9Sstevel@tonic-gate 		addrix++;
11967c478bd9Sstevel@tonic-gate }
11977c478bd9Sstevel@tonic-gate 
11987c478bd9Sstevel@tonic-gate /*
11997c478bd9Sstevel@tonic-gate  * Compares the unqualified hostnames for hosts. Returns 0 if the
12007c478bd9Sstevel@tonic-gate  * names match, and 1 if the names fail to match.
12017c478bd9Sstevel@tonic-gate  */
12027c478bd9Sstevel@tonic-gate int
str_cmp_unqual_hostname(char * rawname1,char * rawname2)12037c478bd9Sstevel@tonic-gate str_cmp_unqual_hostname(char *rawname1, char *rawname2)
12047c478bd9Sstevel@tonic-gate {
12057c478bd9Sstevel@tonic-gate 	size_t unq_len1, unq_len2;
12067c478bd9Sstevel@tonic-gate 	char *domain;
12077c478bd9Sstevel@tonic-gate 
12087c478bd9Sstevel@tonic-gate 	if (debug) {
12097c478bd9Sstevel@tonic-gate 		(void) printf("str_cmp_unqual: rawname1= %s, rawname2= %s\n",
12107c478bd9Sstevel@tonic-gate 		    rawname1, rawname2);
12117c478bd9Sstevel@tonic-gate 	}
12127c478bd9Sstevel@tonic-gate 
12137c478bd9Sstevel@tonic-gate 	unq_len1 = strcspn(rawname1, ".");
12147c478bd9Sstevel@tonic-gate 	unq_len2 = strcspn(rawname2, ".");
12157c478bd9Sstevel@tonic-gate 	domain = strchr(rawname1, '.');
12167c478bd9Sstevel@tonic-gate 	if (domain != NULL) {
12177c478bd9Sstevel@tonic-gate 		if ((strncmp(rawname1, SM_ADDR_IPV4, unq_len1) == 0) ||
12187c478bd9Sstevel@tonic-gate 		    (strncmp(rawname1, SM_ADDR_IPV6, unq_len1) == 0))
12197c478bd9Sstevel@tonic-gate 		return (1);
12207c478bd9Sstevel@tonic-gate 	}
12217c478bd9Sstevel@tonic-gate 
12227c478bd9Sstevel@tonic-gate 	if ((unq_len1 == unq_len2) &&
12237c478bd9Sstevel@tonic-gate 	    (strncmp(rawname1, rawname2, unq_len1) == 0)) {
12247c478bd9Sstevel@tonic-gate 		return (0);
12257c478bd9Sstevel@tonic-gate 	}
12267c478bd9Sstevel@tonic-gate 
12277c478bd9Sstevel@tonic-gate 	return (1);
12287c478bd9Sstevel@tonic-gate }
12297c478bd9Sstevel@tonic-gate 
12307c478bd9Sstevel@tonic-gate /*
12317c478bd9Sstevel@tonic-gate  * Compares <family>.<address-specifier> ASCII names for hosts.  Returns
12327c478bd9Sstevel@tonic-gate  * 0 if the addresses match, and 1 if the addresses fail to match.
12337c478bd9Sstevel@tonic-gate  * If the args are indeed specifiers, they should look like this:
12347c478bd9Sstevel@tonic-gate  *
12357c478bd9Sstevel@tonic-gate  *	ipv4.192.9.200.1 or ipv6.::C009:C801
12367c478bd9Sstevel@tonic-gate  */
12377c478bd9Sstevel@tonic-gate int
str_cmp_address_specifier(char * specifier1,char * specifier2)12387c478bd9Sstevel@tonic-gate str_cmp_address_specifier(char *specifier1, char *specifier2)
12397c478bd9Sstevel@tonic-gate {
12407c478bd9Sstevel@tonic-gate 	size_t unq_len1, unq_len2;
12417c478bd9Sstevel@tonic-gate 	char *rawaddr1, *rawaddr2;
12427c478bd9Sstevel@tonic-gate 	int af1, af2, len;
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate 	if (debug) {
12457c478bd9Sstevel@tonic-gate 		(void) printf("str_cmp_addr: specifier1= %s, specifier2= %s\n",
12467c478bd9Sstevel@tonic-gate 		    specifier1, specifier2);
12477c478bd9Sstevel@tonic-gate 	}
12487c478bd9Sstevel@tonic-gate 
12497c478bd9Sstevel@tonic-gate 	/*
12507c478bd9Sstevel@tonic-gate 	 * Verify that:
12517c478bd9Sstevel@tonic-gate 	 *	1. The family tokens match;
12527c478bd9Sstevel@tonic-gate 	 *	2. The IP addresses following the `.' are legal; and
12537c478bd9Sstevel@tonic-gate 	 *	3. These addresses match.
12547c478bd9Sstevel@tonic-gate 	 */
12557c478bd9Sstevel@tonic-gate 	unq_len1 = strcspn(specifier1, ".");
12567c478bd9Sstevel@tonic-gate 	unq_len2 = strcspn(specifier2, ".");
12577c478bd9Sstevel@tonic-gate 	rawaddr1 = strchr(specifier1, '.');
12587c478bd9Sstevel@tonic-gate 	rawaddr2 = strchr(specifier2, '.');
12597c478bd9Sstevel@tonic-gate 
12607c478bd9Sstevel@tonic-gate 	if (strncmp(specifier1, SM_ADDR_IPV4, unq_len1) == 0) {
12617c478bd9Sstevel@tonic-gate 		af1 = AF_INET;
12627c478bd9Sstevel@tonic-gate 		len = 4;
12637c478bd9Sstevel@tonic-gate 	} else if (strncmp(specifier1, SM_ADDR_IPV6, unq_len1) == 0) {
12647c478bd9Sstevel@tonic-gate 		af1 = AF_INET6;
12657c478bd9Sstevel@tonic-gate 		len = 16;
12667c478bd9Sstevel@tonic-gate 	}
12677c478bd9Sstevel@tonic-gate 	else
12687c478bd9Sstevel@tonic-gate 		return (1);
12697c478bd9Sstevel@tonic-gate 
12707c478bd9Sstevel@tonic-gate 	if (strncmp(specifier2, SM_ADDR_IPV4, unq_len2) == 0)
12717c478bd9Sstevel@tonic-gate 		af2 = AF_INET;
12727c478bd9Sstevel@tonic-gate 	else if (strncmp(specifier2, SM_ADDR_IPV6, unq_len2) == 0)
12737c478bd9Sstevel@tonic-gate 		af2 = AF_INET6;
12747c478bd9Sstevel@tonic-gate 	else
12757c478bd9Sstevel@tonic-gate 		return (1);
12767c478bd9Sstevel@tonic-gate 
12777c478bd9Sstevel@tonic-gate 	if (af1 != af2)
12787c478bd9Sstevel@tonic-gate 		return (1);
12797c478bd9Sstevel@tonic-gate 
12807c478bd9Sstevel@tonic-gate 	if (rawaddr1 != NULL && rawaddr2 != NULL) {
12817c478bd9Sstevel@tonic-gate 		char dst1[16];
12827c478bd9Sstevel@tonic-gate 		char dst2[16];
12837c478bd9Sstevel@tonic-gate 		++rawaddr1;
12847c478bd9Sstevel@tonic-gate 		++rawaddr2;
12857c478bd9Sstevel@tonic-gate 
12867c478bd9Sstevel@tonic-gate 		if (inet_pton(af1, rawaddr1, dst1) == 1 &&
12877c478bd9Sstevel@tonic-gate 		    inet_pton(af2, rawaddr1, dst2) == 1 &&
12887c478bd9Sstevel@tonic-gate 		    memcmp(dst1, dst2, len) == 0) {
12897c478bd9Sstevel@tonic-gate 			return (0);
12907c478bd9Sstevel@tonic-gate 		}
12917c478bd9Sstevel@tonic-gate 	}
12927c478bd9Sstevel@tonic-gate 	return (1);
12937c478bd9Sstevel@tonic-gate }
1294bbaa8b60SDan Kruchinin 
1295bbaa8b60SDan Kruchinin /*
1296bbaa8b60SDan Kruchinin  * Add IP address strings to the host_name list.
1297bbaa8b60SDan Kruchinin  */
1298bbaa8b60SDan Kruchinin void
merge_ips(void)1299bbaa8b60SDan Kruchinin merge_ips(void)
1300bbaa8b60SDan Kruchinin {
1301bbaa8b60SDan Kruchinin 	struct ifaddrs *ifap, *cifap;
1302bbaa8b60SDan Kruchinin 	int error;
1303bbaa8b60SDan Kruchinin 
1304bbaa8b60SDan Kruchinin 	error = getifaddrs(&ifap);
1305bbaa8b60SDan Kruchinin 	if (error) {
1306bbaa8b60SDan Kruchinin 		syslog(LOG_WARNING, "getifaddrs error: '%s'",
1307bbaa8b60SDan Kruchinin 		    strerror(errno));
1308bbaa8b60SDan Kruchinin 		return;
1309bbaa8b60SDan Kruchinin 	}
1310bbaa8b60SDan Kruchinin 
1311bbaa8b60SDan Kruchinin 	for (cifap = ifap; cifap != NULL; cifap = cifap->ifa_next) {
1312bbaa8b60SDan Kruchinin 		struct sockaddr *sa = cifap->ifa_addr;
1313bbaa8b60SDan Kruchinin 		char addr_str[INET6_ADDRSTRLEN];
1314bbaa8b60SDan Kruchinin 		void *addr = NULL;
1315bbaa8b60SDan Kruchinin 
1316bbaa8b60SDan Kruchinin 		switch (sa->sa_family) {
1317bbaa8b60SDan Kruchinin 		case AF_INET: {
1318bbaa8b60SDan Kruchinin 			struct sockaddr_in *sin = (struct sockaddr_in *)sa;
1319bbaa8b60SDan Kruchinin 
1320bbaa8b60SDan Kruchinin 			/* Skip loopback addresses. */
1321bbaa8b60SDan Kruchinin 			if (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) {
1322bbaa8b60SDan Kruchinin 				continue;
1323bbaa8b60SDan Kruchinin 			}
1324bbaa8b60SDan Kruchinin 
1325bbaa8b60SDan Kruchinin 			addr = &sin->sin_addr;
1326bbaa8b60SDan Kruchinin 			break;
1327bbaa8b60SDan Kruchinin 		}
1328bbaa8b60SDan Kruchinin 
1329bbaa8b60SDan Kruchinin 		case AF_INET6: {
1330bbaa8b60SDan Kruchinin 			struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
1331bbaa8b60SDan Kruchinin 
1332bbaa8b60SDan Kruchinin 			/* Skip loopback addresses. */
1333bbaa8b60SDan Kruchinin 			if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) {
1334bbaa8b60SDan Kruchinin 				continue;
1335bbaa8b60SDan Kruchinin 			}
1336bbaa8b60SDan Kruchinin 
1337bbaa8b60SDan Kruchinin 			addr = &sin6->sin6_addr;
1338bbaa8b60SDan Kruchinin 			break;
1339bbaa8b60SDan Kruchinin 		}
1340bbaa8b60SDan Kruchinin 
1341bbaa8b60SDan Kruchinin 		default:
1342bbaa8b60SDan Kruchinin 			syslog(LOG_WARNING, "Unknown address family %d for "
1343bbaa8b60SDan Kruchinin 			    "interface %s", sa->sa_family, cifap->ifa_name);
1344bbaa8b60SDan Kruchinin 			continue;
1345bbaa8b60SDan Kruchinin 		}
1346bbaa8b60SDan Kruchinin 
1347bbaa8b60SDan Kruchinin 		if (inet_ntop(sa->sa_family, addr, addr_str, sizeof (addr_str))
1348bbaa8b60SDan Kruchinin 		    == NULL) {
1349bbaa8b60SDan Kruchinin 			syslog(LOG_WARNING, "Failed to convert address into "
1350bbaa8b60SDan Kruchinin 			    "string representation for interface '%s' "
1351bbaa8b60SDan Kruchinin 			    "address family %d", cifap->ifa_name,
1352bbaa8b60SDan Kruchinin 			    sa->sa_family);
1353bbaa8b60SDan Kruchinin 			continue;
1354bbaa8b60SDan Kruchinin 		}
1355bbaa8b60SDan Kruchinin 
1356bbaa8b60SDan Kruchinin 		if (!in_host_array(addr_str)) {
1357bbaa8b60SDan Kruchinin 			add_to_host_array(addr_str);
1358bbaa8b60SDan Kruchinin 		}
1359bbaa8b60SDan Kruchinin 	}
1360bbaa8b60SDan Kruchinin 
1361bbaa8b60SDan Kruchinin 	freeifaddrs(ifap);
1362bbaa8b60SDan Kruchinin }
1363