xref: /onnv-gate/usr/src/cmd/fs.d/nfs/statd/sm_proc.c (revision 1:475eb30342f9)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
23*1Sgt29601  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
300Sstevel@tonic-gate /*
310Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
320Sstevel@tonic-gate  * The Regents of the University of California
330Sstevel@tonic-gate  * All Rights Reserved
340Sstevel@tonic-gate  *
350Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
360Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
370Sstevel@tonic-gate  * contributors.
380Sstevel@tonic-gate  */
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
410Sstevel@tonic-gate 
420Sstevel@tonic-gate #include <stdio.h>
430Sstevel@tonic-gate #include <sys/types.h>
440Sstevel@tonic-gate #include <stdlib.h>
450Sstevel@tonic-gate #include <unistd.h>
460Sstevel@tonic-gate #include <string.h>
470Sstevel@tonic-gate #include <syslog.h>
480Sstevel@tonic-gate #include <rpc/rpc.h>
490Sstevel@tonic-gate #include <rpcsvc/sm_inter.h>
500Sstevel@tonic-gate #include <rpcsvc/nsm_addr.h>
510Sstevel@tonic-gate #include <memory.h>
520Sstevel@tonic-gate #include <net/if.h>
530Sstevel@tonic-gate #include <sys/sockio.h>
540Sstevel@tonic-gate #include <sys/socket.h>
550Sstevel@tonic-gate #include <netinet/in.h>
560Sstevel@tonic-gate #include <arpa/inet.h>
570Sstevel@tonic-gate #include <netdb.h>
580Sstevel@tonic-gate #include <netdir.h>
590Sstevel@tonic-gate #include <synch.h>
600Sstevel@tonic-gate #include <thread.h>
610Sstevel@tonic-gate #include <assert.h>
620Sstevel@tonic-gate #include "sm_statd.h"
630Sstevel@tonic-gate 
640Sstevel@tonic-gate static int local_state;		/* fake local sm state */
650Sstevel@tonic-gate 				/* client name-to-address translation table */
660Sstevel@tonic-gate static name_addr_entry_t *name_addr = NULL;
670Sstevel@tonic-gate 
680Sstevel@tonic-gate 
690Sstevel@tonic-gate #define	LOGHOST "loghost"
700Sstevel@tonic-gate 
710Sstevel@tonic-gate static void delete_mon(char *mon_name, my_id *my_idp);
720Sstevel@tonic-gate static void insert_mon(mon *monp);
730Sstevel@tonic-gate static void pr_mon(char *);
740Sstevel@tonic-gate static int statd_call_lockd(mon *monp, int state);
750Sstevel@tonic-gate static int hostname_eq(char *host1, char *host2);
760Sstevel@tonic-gate static char *get_system_id(char *hostname);
770Sstevel@tonic-gate static void add_aliases(struct hostent *phost);
780Sstevel@tonic-gate static void *thr_send_notice(void *);
790Sstevel@tonic-gate static void delete_onemon(char *mon_name, my_id *my_idp,
800Sstevel@tonic-gate 				mon_entry **monitor_q);
810Sstevel@tonic-gate static void send_notice(char *mon_name, int state);
820Sstevel@tonic-gate static void add_to_host_array(char *host);
830Sstevel@tonic-gate static int in_host_array(char *host);
840Sstevel@tonic-gate static void pr_name_addr(name_addr_entry_t *name_addr);
850Sstevel@tonic-gate 
860Sstevel@tonic-gate extern int self_check(char *hostname);
870Sstevel@tonic-gate extern struct lifconf *getmyaddrs(void);
880Sstevel@tonic-gate 
890Sstevel@tonic-gate /* ARGSUSED */
900Sstevel@tonic-gate void
sm_status(namep,resp)910Sstevel@tonic-gate sm_status(namep, resp)
920Sstevel@tonic-gate 	sm_name *namep;
930Sstevel@tonic-gate 	sm_stat_res *resp;
940Sstevel@tonic-gate {
950Sstevel@tonic-gate 
960Sstevel@tonic-gate 	if (debug)
970Sstevel@tonic-gate 		(void) printf("proc sm_stat: mon_name = %s\n",
980Sstevel@tonic-gate 				namep->mon_name);
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	resp->res_stat = stat_succ;
1010Sstevel@tonic-gate 	resp->state = LOCAL_STATE;
1020Sstevel@tonic-gate }
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate /* ARGSUSED */
1050Sstevel@tonic-gate void
sm_mon(monp,resp)1060Sstevel@tonic-gate sm_mon(monp, resp)
1070Sstevel@tonic-gate 	mon *monp;
1080Sstevel@tonic-gate 	sm_stat_res *resp;
1090Sstevel@tonic-gate {
1100Sstevel@tonic-gate 	mon_id *monidp;
1110Sstevel@tonic-gate 	monidp = &monp->mon_id;
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 	rw_rdlock(&thr_rwlock);
1140Sstevel@tonic-gate 	if (debug) {
1150Sstevel@tonic-gate 		(void) printf("proc sm_mon: mon_name = %s, id = %d\n",
1160Sstevel@tonic-gate 		monidp->mon_name, * ((int *)monp->priv));
1170Sstevel@tonic-gate 		pr_mon(monp->mon_id.mon_name);
1180Sstevel@tonic-gate 	}
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	/* only monitor other hosts */
1210Sstevel@tonic-gate 	if (self_check(monp->mon_id.mon_name) == 0) {
1220Sstevel@tonic-gate 		/* store monitor request into monitor_q */
1230Sstevel@tonic-gate 		insert_mon(monp);
1240Sstevel@tonic-gate 	}
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 	pr_mon(monp->mon_id.mon_name);
1270Sstevel@tonic-gate 	resp->res_stat = stat_succ;
1280Sstevel@tonic-gate 	resp->state = local_state;
1290Sstevel@tonic-gate 	rw_unlock(&thr_rwlock);
1300Sstevel@tonic-gate }
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate /* ARGSUSED */
1330Sstevel@tonic-gate void
sm_unmon(monidp,resp)1340Sstevel@tonic-gate sm_unmon(monidp, resp)
1350Sstevel@tonic-gate 	mon_id *monidp;
1360Sstevel@tonic-gate 	sm_stat *resp;
1370Sstevel@tonic-gate {
1380Sstevel@tonic-gate 	rw_rdlock(&thr_rwlock);
1390Sstevel@tonic-gate 	if (debug) {
1400Sstevel@tonic-gate 		(void) printf(
1410Sstevel@tonic-gate 			"proc sm_unmon: mon_name = %s, [%s, %d, %d, %d]\n",
1420Sstevel@tonic-gate 			monidp->mon_name, monidp->my_id.my_name,
1430Sstevel@tonic-gate 			monidp->my_id.my_prog, monidp->my_id.my_vers,
1440Sstevel@tonic-gate 			monidp->my_id.my_proc);
1450Sstevel@tonic-gate 		pr_mon(monidp->mon_name);
1460Sstevel@tonic-gate 	}
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 	delete_mon(monidp->mon_name, &monidp->my_id);
1490Sstevel@tonic-gate 	pr_mon(monidp->mon_name);
1500Sstevel@tonic-gate 	resp->state = local_state;
1510Sstevel@tonic-gate 	rw_unlock(&thr_rwlock);
1520Sstevel@tonic-gate }
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate /* ARGSUSED */
1550Sstevel@tonic-gate void
sm_unmon_all(myidp,resp)1560Sstevel@tonic-gate sm_unmon_all(myidp, resp)
1570Sstevel@tonic-gate 	my_id *myidp;
1580Sstevel@tonic-gate 	sm_stat *resp;
1590Sstevel@tonic-gate {
1600Sstevel@tonic-gate 	rw_rdlock(&thr_rwlock);
1610Sstevel@tonic-gate 	if (debug)
1620Sstevel@tonic-gate 		(void) printf("proc sm_unmon_all: [%s, %d, %d, %d]\n",
1630Sstevel@tonic-gate 		myidp->my_name,
1640Sstevel@tonic-gate 		myidp->my_prog, myidp->my_vers,
1650Sstevel@tonic-gate 		myidp->my_proc);
1660Sstevel@tonic-gate 	delete_mon((char *)NULL, myidp);
1670Sstevel@tonic-gate 	pr_mon(NULL);
1680Sstevel@tonic-gate 	resp->state = local_state;
1690Sstevel@tonic-gate 	rw_unlock(&thr_rwlock);
1700Sstevel@tonic-gate }
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate /*
1730Sstevel@tonic-gate  * Notifies lockd specified by name that state has changed for this server.
1740Sstevel@tonic-gate  */
1750Sstevel@tonic-gate void
sm_notify(ntfp)1760Sstevel@tonic-gate sm_notify(ntfp)
1770Sstevel@tonic-gate 	stat_chge *ntfp;
1780Sstevel@tonic-gate {
1790Sstevel@tonic-gate 	rw_rdlock(&thr_rwlock);
1800Sstevel@tonic-gate 	if (debug)
1810Sstevel@tonic-gate 		(void) printf("sm_notify: %s state =%d\n",
1820Sstevel@tonic-gate 			ntfp->mon_name, ntfp->state);
1830Sstevel@tonic-gate 	send_notice(ntfp->mon_name, ntfp->state);
1840Sstevel@tonic-gate 	rw_unlock(&thr_rwlock);
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate /* ARGSUSED */
1880Sstevel@tonic-gate void
sm_simu_crash(myidp)1890Sstevel@tonic-gate sm_simu_crash(myidp)
1900Sstevel@tonic-gate 	void *myidp;
1910Sstevel@tonic-gate {
1920Sstevel@tonic-gate 	int i;
1930Sstevel@tonic-gate 	struct mon_entry *monitor_q;
1940Sstevel@tonic-gate 	int found = 0;
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 	/* Only one crash should be running at a time. */
1970Sstevel@tonic-gate 	mutex_lock(&crash_lock);
1980Sstevel@tonic-gate 	if (debug)
1990Sstevel@tonic-gate 		(void) printf("proc sm_simu_crash\n");
2000Sstevel@tonic-gate 	if (in_crash) {
2010Sstevel@tonic-gate 		cond_wait(&crash_finish, &crash_lock);
2020Sstevel@tonic-gate 		mutex_unlock(&crash_lock);
2030Sstevel@tonic-gate 		return;
2040Sstevel@tonic-gate 	} else {
2050Sstevel@tonic-gate 		in_crash = 1;
2060Sstevel@tonic-gate 	}
2070Sstevel@tonic-gate 	mutex_unlock(&crash_lock);
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate 	for (i = 0; i < MAX_HASHSIZE; i++) {
2100Sstevel@tonic-gate 		mutex_lock(&mon_table[i].lock);
2110Sstevel@tonic-gate 		monitor_q = mon_table[i].sm_monhdp;
2120Sstevel@tonic-gate 		if (monitor_q != (struct mon_entry *)NULL) {
2130Sstevel@tonic-gate 			mutex_unlock(&mon_table[i].lock);
2140Sstevel@tonic-gate 			found = 1;
2150Sstevel@tonic-gate 			break;
2160Sstevel@tonic-gate 		}
2170Sstevel@tonic-gate 		mutex_unlock(&mon_table[i].lock);
2180Sstevel@tonic-gate 	}
2190Sstevel@tonic-gate 	/*
2200Sstevel@tonic-gate 	 * If there are entries found in the monitor table,
2210Sstevel@tonic-gate 	 * initiate a crash, else zero out the in_crash variable.
2220Sstevel@tonic-gate 	 */
2230Sstevel@tonic-gate 	if (found) {
2240Sstevel@tonic-gate 		mutex_lock(&crash_lock);
2250Sstevel@tonic-gate 		die = 1;
2260Sstevel@tonic-gate 		/* Signal sm_retry() thread if sleeping. */
2270Sstevel@tonic-gate 		cond_signal(&retrywait);
2280Sstevel@tonic-gate 		mutex_unlock(&crash_lock);
2290Sstevel@tonic-gate 		rw_wrlock(&thr_rwlock);
2300Sstevel@tonic-gate 		sm_crash();
2310Sstevel@tonic-gate 		rw_unlock(&thr_rwlock);
2320Sstevel@tonic-gate 	} else {
2330Sstevel@tonic-gate 		mutex_lock(&crash_lock);
2340Sstevel@tonic-gate 		in_crash = 0;
2350Sstevel@tonic-gate 		mutex_unlock(&crash_lock);
2360Sstevel@tonic-gate 	}
2370Sstevel@tonic-gate }
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate /* ARGSUSED */
2400Sstevel@tonic-gate void
nsmaddrproc1_reg(regargs,regresp)2410Sstevel@tonic-gate nsmaddrproc1_reg(regargs, regresp)
2420Sstevel@tonic-gate 	reg1args *regargs;
2430Sstevel@tonic-gate 	reg1res  *regresp;
2440Sstevel@tonic-gate {
2450Sstevel@tonic-gate 	nsm_addr_res status;
2460Sstevel@tonic-gate 	name_addr_entry_t *entry;
2470Sstevel@tonic-gate 	char *tmp_n_bytes;
2480Sstevel@tonic-gate 	addr_entry_t *addr;
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	rw_rdlock(&thr_rwlock);
2510Sstevel@tonic-gate 	if (debug) {
2520Sstevel@tonic-gate 		int i;
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 		(void) printf("nap1_reg: fam= %d, name= %s, len= %d\n",
2550Sstevel@tonic-gate 				regargs->family,
2560Sstevel@tonic-gate 				regargs->name,
2570Sstevel@tonic-gate 				regargs->address.n_len);
2580Sstevel@tonic-gate 		(void) printf("address is: ");
2590Sstevel@tonic-gate 		for (i = 0; i < regargs->address.n_len; i++) {
2600Sstevel@tonic-gate 			(void) printf("%d.",
2610Sstevel@tonic-gate 				(unsigned char)regargs->address.n_bytes[i]);
2620Sstevel@tonic-gate 		}
2630Sstevel@tonic-gate 		(void) printf("\n");
2640Sstevel@tonic-gate 	}
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	/*
2670Sstevel@tonic-gate 	 * Locate the entry with the name in the NSM_ADDR_REG request if
2680Sstevel@tonic-gate 	 * it exists.  If it doesn't, create a new entry to hold this name.
2690Sstevel@tonic-gate 	 * The first time through this code, name_addr starts out as NULL.
2700Sstevel@tonic-gate 	 */
2710Sstevel@tonic-gate 	mutex_lock(&name_addrlock);
2720Sstevel@tonic-gate 	for (entry = name_addr; entry; entry = entry->next) {
2730Sstevel@tonic-gate 		if (strcmp(regargs->name, entry->name) == 0) {
2740Sstevel@tonic-gate 			if (debug) {
2750Sstevel@tonic-gate 				(void) printf("nap1_reg: matched name %s\n",
2760Sstevel@tonic-gate 						entry->name);
2770Sstevel@tonic-gate 			}
2780Sstevel@tonic-gate 			break;
2790Sstevel@tonic-gate 		}
2800Sstevel@tonic-gate 	}
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate 	if (entry == NULL) {
2830Sstevel@tonic-gate 		entry = (name_addr_entry_t *)malloc(sizeof (*entry));
2840Sstevel@tonic-gate 		if (entry == NULL) {
2850Sstevel@tonic-gate 			if (debug) {
2860Sstevel@tonic-gate 				(void) printf(
2870Sstevel@tonic-gate 				"nsmaddrproc1_reg: no memory for entry\n");
2880Sstevel@tonic-gate 			}
2890Sstevel@tonic-gate 			status = nsm_addr_fail;
2900Sstevel@tonic-gate 			goto done;
2910Sstevel@tonic-gate 		}
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 		entry->name = strdup(regargs->name);
2940Sstevel@tonic-gate 		if (entry->name == NULL) {
2950Sstevel@tonic-gate 			if (debug) {
2960Sstevel@tonic-gate 				(void) printf(
2970Sstevel@tonic-gate 				"nsmaddrproc1_reg: no memory for name\n");
2980Sstevel@tonic-gate 			}
2990Sstevel@tonic-gate 			free(entry);
3000Sstevel@tonic-gate 			status = nsm_addr_fail;
3010Sstevel@tonic-gate 			goto done;
3020Sstevel@tonic-gate 		}
3030Sstevel@tonic-gate 		entry->addresses = NULL;
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate 		/*
3060Sstevel@tonic-gate 		 * Link the new entry onto the *head* of the name_addr
3070Sstevel@tonic-gate 		 * table.
3080Sstevel@tonic-gate 		 *
3090Sstevel@tonic-gate 		 * Note: there is code below in the address maintenance
3100Sstevel@tonic-gate 		 * section that assumes this behavior.
3110Sstevel@tonic-gate 		 */
3120Sstevel@tonic-gate 		entry->next = name_addr;
3130Sstevel@tonic-gate 		name_addr = entry;
3140Sstevel@tonic-gate 	}
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate 	/*
3170Sstevel@tonic-gate 	 * Try to match the address in the request; if it doesn't match,
3180Sstevel@tonic-gate 	 * add it to the entry's address list.
3190Sstevel@tonic-gate 	 */
3200Sstevel@tonic-gate 	for (addr = entry->addresses; addr; addr = addr->next) {
3210Sstevel@tonic-gate 		if (addr->family == (sa_family_t)regargs->family &&
3220Sstevel@tonic-gate 		    addr->ah.n_len == regargs->address.n_len &&
3230Sstevel@tonic-gate 		    memcmp(addr->ah.n_bytes, regargs->address.n_bytes,
3240Sstevel@tonic-gate 			addr->ah.n_len) == 0) {
3250Sstevel@tonic-gate 			if (debug) {
3260Sstevel@tonic-gate 				int i;
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 				(void) printf("nap1_reg: matched addr ");
3290Sstevel@tonic-gate 				for (i = 0; i < addr->ah.n_len; i++) {
3300Sstevel@tonic-gate 					(void) printf("%d.",
3310Sstevel@tonic-gate 					(unsigned char)addr->ah.n_bytes[i]);
3320Sstevel@tonic-gate 				}
3330Sstevel@tonic-gate 				(void) printf(" family %d for name %s\n",
3340Sstevel@tonic-gate 						addr->family,
3350Sstevel@tonic-gate 						entry->name);
3360Sstevel@tonic-gate 			}
3370Sstevel@tonic-gate 			break;
3380Sstevel@tonic-gate 		}
3390Sstevel@tonic-gate 	}
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	if (addr == NULL) {
3420Sstevel@tonic-gate 		addr = (addr_entry_t *)malloc(sizeof (*addr));
3430Sstevel@tonic-gate 		tmp_n_bytes = (char *)malloc(regargs->address.n_len);
3440Sstevel@tonic-gate 		if (addr == NULL || tmp_n_bytes == NULL) {
3450Sstevel@tonic-gate 			if (debug) {
3460Sstevel@tonic-gate 				(void) printf(
3470Sstevel@tonic-gate 					"nap1_reg: no memory for addr\n");
3480Sstevel@tonic-gate 			}
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate 			/*
3510Sstevel@tonic-gate 			 * If this name entry was just newly made in the
3520Sstevel@tonic-gate 			 * table, back it out now that we can't register
3530Sstevel@tonic-gate 			 * an address with it anyway.
3540Sstevel@tonic-gate 			 *
3550Sstevel@tonic-gate 			 * Note: we are making an assumption about how
3560Sstevel@tonic-gate 			 * names are added to (the head of) name_addr here.
3570Sstevel@tonic-gate 			 */
3580Sstevel@tonic-gate 			if (entry == name_addr && entry->addresses == NULL) {
3590Sstevel@tonic-gate 				name_addr = name_addr->next;
3600Sstevel@tonic-gate 				free(entry->name);
3610Sstevel@tonic-gate 				free(entry);
3620Sstevel@tonic-gate 				if (tmp_n_bytes)
3630Sstevel@tonic-gate 					free(tmp_n_bytes);
3640Sstevel@tonic-gate 				if (addr)
3650Sstevel@tonic-gate 					free(addr);
3660Sstevel@tonic-gate 				status = nsm_addr_fail;
3670Sstevel@tonic-gate 				goto done;
3680Sstevel@tonic-gate 			}
3690Sstevel@tonic-gate 		}
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate 		/*
3720Sstevel@tonic-gate 		 * Note:  this check for address family assumes that we
3730Sstevel@tonic-gate 		 *	  will get something different here someday for
3740Sstevel@tonic-gate 		 *	  other supported address types, such as IPv6.
3750Sstevel@tonic-gate 		 */
3760Sstevel@tonic-gate 		addr->ah.n_len = regargs->address.n_len;
3770Sstevel@tonic-gate 		addr->ah.n_bytes = tmp_n_bytes;
3780Sstevel@tonic-gate 		addr->family = regargs->family;
3790Sstevel@tonic-gate 		if (debug) {
3800Sstevel@tonic-gate 			if ((addr->family != AF_INET) && \
3810Sstevel@tonic-gate 				(addr->family != AF_INET6)) {
3820Sstevel@tonic-gate 				(void) printf(
3830Sstevel@tonic-gate 					"nap1_reg: unknown addr family %d\n",
3840Sstevel@tonic-gate 					addr->family);
3850Sstevel@tonic-gate 			}
3860Sstevel@tonic-gate 		}
3870Sstevel@tonic-gate 		(void) memcpy(addr->ah.n_bytes, regargs->address.n_bytes,
3880Sstevel@tonic-gate 				addr->ah.n_len);
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 		addr->next = entry->addresses;
3910Sstevel@tonic-gate 		entry->addresses = addr;
3920Sstevel@tonic-gate 	}
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate 	status = nsm_addr_succ;
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate done:
3970Sstevel@tonic-gate 	regresp->status = status;
3980Sstevel@tonic-gate 	if (debug) {
3990Sstevel@tonic-gate 		pr_name_addr(name_addr);
4000Sstevel@tonic-gate 	}
4010Sstevel@tonic-gate 	mutex_unlock(&name_addrlock);
4020Sstevel@tonic-gate 	rw_unlock(&thr_rwlock);
4030Sstevel@tonic-gate }
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate /*
4060Sstevel@tonic-gate  * Insert an entry into the monitor_q.  Space for the entry is allocated
4070Sstevel@tonic-gate  * here.  It is then filled in from the information passed in.
4080Sstevel@tonic-gate  */
4090Sstevel@tonic-gate static void
insert_mon(monp)4100Sstevel@tonic-gate insert_mon(monp)
4110Sstevel@tonic-gate 	mon *monp;
4120Sstevel@tonic-gate {
4130Sstevel@tonic-gate 	mon_entry *new, *found;
4140Sstevel@tonic-gate 	my_id *my_idp, *nl_idp;
4150Sstevel@tonic-gate 	mon_entry *monitor_q;
4160Sstevel@tonic-gate 	unsigned int hash;
4170Sstevel@tonic-gate 	name_addr_entry_t *entry;
4180Sstevel@tonic-gate 	addr_entry_t *addr;
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 	/* Allocate entry for new */
4210Sstevel@tonic-gate 	if ((new = (mon_entry *) malloc(sizeof (mon_entry))) == 0) {
4220Sstevel@tonic-gate 		syslog(LOG_ERR,
4230Sstevel@tonic-gate 			"statd: insert_mon: malloc error on mon %s (id=%d)\n",
4240Sstevel@tonic-gate 			monp->mon_id.mon_name, * ((int *)monp->priv));
4250Sstevel@tonic-gate 		return;
4260Sstevel@tonic-gate 	}
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate 	/* Initialize and copy contents of monp to new */
4290Sstevel@tonic-gate 	(void) memset(new, 0, sizeof (mon_entry));
4300Sstevel@tonic-gate 	(void) memcpy(&new->id, monp, sizeof (mon));
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 	/* Allocate entry for new mon_name */
4330Sstevel@tonic-gate 	if ((new->id.mon_id.mon_name = strdup(monp->mon_id.mon_name)) == 0) {
4340Sstevel@tonic-gate 		syslog(LOG_ERR,
4350Sstevel@tonic-gate 			"statd: insert_mon: malloc error on mon %s (id=%d)\n",
4360Sstevel@tonic-gate 			monp->mon_id.mon_name, * ((int *)monp->priv));
4370Sstevel@tonic-gate 		free(new);
4380Sstevel@tonic-gate 		return;
4390Sstevel@tonic-gate 	}
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 	/* Allocate entry for new my_name */
4430Sstevel@tonic-gate 	if ((new->id.mon_id.my_id.my_name =
4440Sstevel@tonic-gate 		strdup(monp->mon_id.my_id.my_name)) == 0) {
4450Sstevel@tonic-gate 		syslog(LOG_ERR,
4460Sstevel@tonic-gate 			"statd: insert_mon: malloc error on mon %s (id=%d)\n",
4470Sstevel@tonic-gate 			monp->mon_id.mon_name, * ((int *)monp->priv));
4480Sstevel@tonic-gate 		free(new->id.mon_id.mon_name);
4490Sstevel@tonic-gate 		free(new);
4500Sstevel@tonic-gate 		return;
4510Sstevel@tonic-gate 	}
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate 	if (debug)
4540Sstevel@tonic-gate 		(void) printf("add_mon(%x) %s (id=%d)\n",
4550Sstevel@tonic-gate 		(int)new, new->id.mon_id.mon_name, * ((int *)new->id.priv));
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate 	/*
4580Sstevel@tonic-gate 	 * Record the name, and all addresses which have been registered
4590Sstevel@tonic-gate 	 * for this name, in the filesystem name space.
4600Sstevel@tonic-gate 	 */
4610Sstevel@tonic-gate 	record_name(new->id.mon_id.mon_name, 1);
4620Sstevel@tonic-gate 	if (regfiles_only == 0) {
4630Sstevel@tonic-gate 		mutex_lock(&name_addrlock);
4640Sstevel@tonic-gate 		for (entry = name_addr; entry; entry = entry->next) {
4650Sstevel@tonic-gate 			if (strcmp(new->id.mon_id.mon_name, entry->name) != 0) {
4660Sstevel@tonic-gate 				continue;
4670Sstevel@tonic-gate 			}
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate 			for (addr = entry->addresses; addr; addr = addr->next) {
4700Sstevel@tonic-gate 				record_addr(new->id.mon_id.mon_name,
4710Sstevel@tonic-gate 						addr->family, &addr->ah);
4720Sstevel@tonic-gate 			}
4730Sstevel@tonic-gate 			break;
4740Sstevel@tonic-gate 		}
4750Sstevel@tonic-gate 		mutex_unlock(&name_addrlock);
4760Sstevel@tonic-gate 	}
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 	SMHASH(new->id.mon_id.mon_name, hash);
4790Sstevel@tonic-gate 	mutex_lock(&mon_table[hash].lock);
4800Sstevel@tonic-gate 	monitor_q = mon_table[hash].sm_monhdp;
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate 	/* If mon_table hash list is empty. */
4830Sstevel@tonic-gate 	if (monitor_q == (struct mon_entry *)NULL) {
4840Sstevel@tonic-gate 		if (debug)
4850Sstevel@tonic-gate 			(void) printf("\nAdding to monitor_q hash %d\n", hash);
4860Sstevel@tonic-gate 		new->nxt = new->prev = (mon_entry *)NULL;
4870Sstevel@tonic-gate 		mon_table[hash].sm_monhdp = new;
4880Sstevel@tonic-gate 		mutex_unlock(&mon_table[hash].lock);
4890Sstevel@tonic-gate 		return;
4900Sstevel@tonic-gate 	} else {
4910Sstevel@tonic-gate 		found = 0;
4920Sstevel@tonic-gate 		my_idp = &new->id.mon_id.my_id;
4930Sstevel@tonic-gate 		while (monitor_q != (mon_entry *)NULL)  {
4940Sstevel@tonic-gate 			/*
4950Sstevel@tonic-gate 			 * This list is searched sequentially for the
4960Sstevel@tonic-gate 			 * tuple (hostname, prog, vers, proc). The tuples
4970Sstevel@tonic-gate 			 * are inserted in the beginning of the monitor_q,
4980Sstevel@tonic-gate 			 * if the hostname is not already present in the list.
4990Sstevel@tonic-gate 			 * If the hostname is found in the list, the incoming
5000Sstevel@tonic-gate 			 * tuple is inserted just after all the tuples with the
5010Sstevel@tonic-gate 			 * same hostname. However, if the tuple matches exactly
5020Sstevel@tonic-gate 			 * with an entry in the list, space allocated for the
5030Sstevel@tonic-gate 			 * new entry is released and nothing is inserted in the
5040Sstevel@tonic-gate 			 * list.
5050Sstevel@tonic-gate 			 */
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate 			if (str_cmp_unqual_hostname(
5080Sstevel@tonic-gate 				monitor_q->id.mon_id.mon_name,
5090Sstevel@tonic-gate 				new->id.mon_id.mon_name) == 0) {
5100Sstevel@tonic-gate 				/* found */
5110Sstevel@tonic-gate 				nl_idp = &monitor_q->id.mon_id.my_id;
5120Sstevel@tonic-gate 				if ((str_cmp_unqual_hostname(my_idp->my_name,
5130Sstevel@tonic-gate 					nl_idp->my_name) == 0) &&
5140Sstevel@tonic-gate 					my_idp->my_prog == nl_idp->my_prog &&
5150Sstevel@tonic-gate 					my_idp->my_vers == nl_idp->my_vers &&
5160Sstevel@tonic-gate 					my_idp->my_proc == nl_idp->my_proc) {
5170Sstevel@tonic-gate 					/*
5180Sstevel@tonic-gate 					 * already exists an identical one,
5190Sstevel@tonic-gate 					 * release the space allocated for the
5200Sstevel@tonic-gate 					 * mon_entry
5210Sstevel@tonic-gate 					 */
5220Sstevel@tonic-gate 					free(new->id.mon_id.mon_name);
5230Sstevel@tonic-gate 					free(new->id.mon_id.my_id.my_name);
5240Sstevel@tonic-gate 					free(new);
5250Sstevel@tonic-gate 					mutex_unlock(&mon_table[hash].lock);
5260Sstevel@tonic-gate 					return;
5270Sstevel@tonic-gate 				} else {
5280Sstevel@tonic-gate 					/*
5290Sstevel@tonic-gate 					 * mark the last callback that is
5300Sstevel@tonic-gate 					 * not matching; new is inserted
5310Sstevel@tonic-gate 					 * after this
5320Sstevel@tonic-gate 					 */
5330Sstevel@tonic-gate 					found = monitor_q;
5340Sstevel@tonic-gate 				}
5350Sstevel@tonic-gate 			} else if (found)
5360Sstevel@tonic-gate 				break;
5370Sstevel@tonic-gate 			monitor_q = monitor_q->nxt;
5380Sstevel@tonic-gate 		}
5390Sstevel@tonic-gate 		if (found) {
5400Sstevel@tonic-gate 			/*
5410Sstevel@tonic-gate 			 * insert just after the entry having matching tuple.
5420Sstevel@tonic-gate 			 */
5430Sstevel@tonic-gate 			new->nxt = found->nxt;
5440Sstevel@tonic-gate 			new->prev = found;
5450Sstevel@tonic-gate 			if (found->nxt != (mon_entry *)NULL)
5460Sstevel@tonic-gate 				found->nxt->prev = new;
5470Sstevel@tonic-gate 			found->nxt = new;
5480Sstevel@tonic-gate 		} else {
5490Sstevel@tonic-gate 			/*
5500Sstevel@tonic-gate 			 * not found, insert in front of list.
5510Sstevel@tonic-gate 			 */
5520Sstevel@tonic-gate 			new->nxt = mon_table[hash].sm_monhdp;
5530Sstevel@tonic-gate 			new->prev = (mon_entry *) NULL;
5540Sstevel@tonic-gate 			if (new->nxt != (mon_entry *) NULL)
5550Sstevel@tonic-gate 				new->nxt->prev = new;
5560Sstevel@tonic-gate 			mon_table[hash].sm_monhdp = new;
5570Sstevel@tonic-gate 		}
5580Sstevel@tonic-gate 		mutex_unlock(&mon_table[hash].lock);
5590Sstevel@tonic-gate 		return;
5600Sstevel@tonic-gate 	}
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate /*
5640Sstevel@tonic-gate  * Deletes a specific monitor name or deletes all monitors with same id
5650Sstevel@tonic-gate  * in hash table.
5660Sstevel@tonic-gate  */
5670Sstevel@tonic-gate static void
delete_mon(mon_name,my_idp)5680Sstevel@tonic-gate delete_mon(mon_name, my_idp)
5690Sstevel@tonic-gate 	char *mon_name;
5700Sstevel@tonic-gate 	my_id *my_idp;
5710Sstevel@tonic-gate {
5720Sstevel@tonic-gate 	unsigned int hash;
5730Sstevel@tonic-gate 
5740Sstevel@tonic-gate 	if (mon_name != (char *)NULL) {
5750Sstevel@tonic-gate 		record_name(mon_name, 0);
5760Sstevel@tonic-gate 		SMHASH(mon_name, hash);
5770Sstevel@tonic-gate 		mutex_lock(&mon_table[hash].lock);
5780Sstevel@tonic-gate 		delete_onemon(mon_name, my_idp, &mon_table[hash].sm_monhdp);
5790Sstevel@tonic-gate 		mutex_unlock(&mon_table[hash].lock);
5800Sstevel@tonic-gate 	} else {
5810Sstevel@tonic-gate 		for (hash = 0; hash < MAX_HASHSIZE; hash++) {
5820Sstevel@tonic-gate 			mutex_lock(&mon_table[hash].lock);
5830Sstevel@tonic-gate 			delete_onemon(mon_name, my_idp,
5840Sstevel@tonic-gate 					&mon_table[hash].sm_monhdp);
5850Sstevel@tonic-gate 			mutex_unlock(&mon_table[hash].lock);
5860Sstevel@tonic-gate 		}
5870Sstevel@tonic-gate 	}
5880Sstevel@tonic-gate }
5890Sstevel@tonic-gate 
5900Sstevel@tonic-gate /*
5910Sstevel@tonic-gate  * Deletes a monitor in list.
5920Sstevel@tonic-gate  * IF mon_name is NULL, delete all mon_names that have the same id,
5930Sstevel@tonic-gate  * else delete specific monitor.
5940Sstevel@tonic-gate  */
5950Sstevel@tonic-gate void
delete_onemon(mon_name,my_idp,monitor_q)5960Sstevel@tonic-gate delete_onemon(mon_name, my_idp, monitor_q)
5970Sstevel@tonic-gate 	char *mon_name;
5980Sstevel@tonic-gate 	my_id *my_idp;
5990Sstevel@tonic-gate 	mon_entry **monitor_q;
6000Sstevel@tonic-gate {
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 	mon_entry *next, *nl;
6030Sstevel@tonic-gate 	my_id *nl_idp;
6040Sstevel@tonic-gate 
6050Sstevel@tonic-gate 	next = *monitor_q;
6060Sstevel@tonic-gate 	while ((nl = next) != (struct mon_entry *)NULL) {
6070Sstevel@tonic-gate 		next = next->nxt;
6080Sstevel@tonic-gate 		if (mon_name == (char *)NULL || (mon_name != (char *)NULL &&
6090Sstevel@tonic-gate 			str_cmp_unqual_hostname(nl->id.mon_id.mon_name,
6100Sstevel@tonic-gate 			mon_name) == 0)) {
6110Sstevel@tonic-gate 			nl_idp = &nl->id.mon_id.my_id;
6120Sstevel@tonic-gate 			if ((str_cmp_unqual_hostname(my_idp->my_name,
6130Sstevel@tonic-gate 					nl_idp->my_name) == 0) &&
6140Sstevel@tonic-gate 				my_idp->my_prog == nl_idp->my_prog &&
6150Sstevel@tonic-gate 				my_idp->my_vers == nl_idp->my_vers &&
6160Sstevel@tonic-gate 				my_idp->my_proc == nl_idp->my_proc) {
6170Sstevel@tonic-gate 				/* found */
6180Sstevel@tonic-gate 				if (debug)
6190Sstevel@tonic-gate 					(void) printf("delete_mon(%x): %s\n",
6200Sstevel@tonic-gate 							(int)nl, mon_name ?
6210Sstevel@tonic-gate 							mon_name : "<NULL>");
6220Sstevel@tonic-gate 				/*
6230Sstevel@tonic-gate 				 * Remove the monitor name from the
6240Sstevel@tonic-gate 				 * record_q, if id matches.
6250Sstevel@tonic-gate 				 */
6260Sstevel@tonic-gate 				record_name(nl->id.mon_id.mon_name, 0);
6270Sstevel@tonic-gate 				/* if nl is not the first entry on list */
6280Sstevel@tonic-gate 				if (nl->prev != (struct mon_entry *)NULL)
6290Sstevel@tonic-gate 					nl->prev->nxt = nl->nxt;
6300Sstevel@tonic-gate 				else {
6310Sstevel@tonic-gate 					*monitor_q = nl->nxt;
6320Sstevel@tonic-gate 				}
6330Sstevel@tonic-gate 				if (nl->nxt != (struct mon_entry *)NULL)
6340Sstevel@tonic-gate 					nl->nxt->prev = nl->prev;
6350Sstevel@tonic-gate 				free(nl->id.mon_id.mon_name);
6360Sstevel@tonic-gate 				free(nl_idp->my_name);
6370Sstevel@tonic-gate 				free(nl);
6380Sstevel@tonic-gate 			}
6390Sstevel@tonic-gate 		} /* end of if mon */
6400Sstevel@tonic-gate 	}
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate }
6430Sstevel@tonic-gate /*
6440Sstevel@tonic-gate  * Notify lockd of host specified by mon_name that the specified state
6450Sstevel@tonic-gate  * has changed.
6460Sstevel@tonic-gate  */
6470Sstevel@tonic-gate static void
send_notice(mon_name,state)6480Sstevel@tonic-gate send_notice(mon_name, state)
6490Sstevel@tonic-gate 	char *mon_name;
6500Sstevel@tonic-gate 	int state;
6510Sstevel@tonic-gate {
6520Sstevel@tonic-gate 	struct mon_entry *next;
6530Sstevel@tonic-gate 	mon_entry *monitor_q;
6540Sstevel@tonic-gate 	unsigned int hash;
6550Sstevel@tonic-gate 	moninfo_t *minfop;
6560Sstevel@tonic-gate 	mon *monp;
6570Sstevel@tonic-gate 
6580Sstevel@tonic-gate 	SMHASH(mon_name, hash);
6590Sstevel@tonic-gate 	mutex_lock(&mon_table[hash].lock);
6600Sstevel@tonic-gate 	monitor_q = mon_table[hash].sm_monhdp;
6610Sstevel@tonic-gate 
6620Sstevel@tonic-gate 	next = monitor_q;
6630Sstevel@tonic-gate 	while (next != (struct mon_entry *)NULL) {
6640Sstevel@tonic-gate 		if (hostname_eq(next->id.mon_id.mon_name, mon_name)) {
6650Sstevel@tonic-gate 			monp = &next->id;
6660Sstevel@tonic-gate 			/*
6670Sstevel@tonic-gate 			 * Prepare the minfop structure to pass to
6680Sstevel@tonic-gate 			 * thr_create(). This structure is a copy of
6690Sstevel@tonic-gate 			 * mon info and state.
6700Sstevel@tonic-gate 			 */
6710Sstevel@tonic-gate 			if ((minfop =
6720Sstevel@tonic-gate 				(moninfo_t *)xmalloc(sizeof (moninfo_t))) !=
6730Sstevel@tonic-gate 				(moninfo_t *)NULL) {
6740Sstevel@tonic-gate 				(void) memcpy(&minfop->id, monp, sizeof (mon));
6750Sstevel@tonic-gate 				/* Allocate entry for mon_name */
6760Sstevel@tonic-gate 				if ((minfop->id.mon_id.mon_name =
6770Sstevel@tonic-gate 					strdup(monp->mon_id.mon_name)) == 0) {
6780Sstevel@tonic-gate 					syslog(LOG_ERR,
6790Sstevel@tonic-gate 			"statd: send_notice: malloc error on mon %s (id=%d)\n",
6800Sstevel@tonic-gate 						monp->mon_id.mon_name,
6810Sstevel@tonic-gate 						* ((int *)monp->priv));
6820Sstevel@tonic-gate 					free(minfop);
6830Sstevel@tonic-gate 					continue;
6840Sstevel@tonic-gate 				}
6850Sstevel@tonic-gate 				/* Allocate entry for my_name */
6860Sstevel@tonic-gate 				if ((minfop->id.mon_id.my_id.my_name =
6870Sstevel@tonic-gate 				strdup(monp->mon_id.my_id.my_name)) == 0) {
6880Sstevel@tonic-gate 					syslog(LOG_ERR,
6890Sstevel@tonic-gate 			"statd: send_notice: malloc error on mon %s (id=%d)\n",
6900Sstevel@tonic-gate 						monp->mon_id.mon_name,
6910Sstevel@tonic-gate 						* ((int *)monp->priv));
6920Sstevel@tonic-gate 					free(minfop->id.mon_id.mon_name);
6930Sstevel@tonic-gate 					free(minfop);
6940Sstevel@tonic-gate 					continue;
6950Sstevel@tonic-gate 				}
6960Sstevel@tonic-gate 				minfop->state = state;
6970Sstevel@tonic-gate 				/*
6980Sstevel@tonic-gate 				 * Create detached threads to process each host
6990Sstevel@tonic-gate 				 * to notify.  If error, print out msg, free
7000Sstevel@tonic-gate 				 * resources and continue.
7010Sstevel@tonic-gate 				 */
7020Sstevel@tonic-gate 				if (thr_create(NULL, NULL, thr_send_notice,
7030Sstevel@tonic-gate 						(void *)minfop, THR_DETACHED,
7040Sstevel@tonic-gate 						NULL)) {
7050Sstevel@tonic-gate 				    syslog(LOG_ERR,
7060Sstevel@tonic-gate 		"statd: unable to create thread to send_notice to %s.\n",
7070Sstevel@tonic-gate 					mon_name);
7080Sstevel@tonic-gate 				    free(minfop->id.mon_id.mon_name);
7090Sstevel@tonic-gate 				    free(minfop->id.mon_id.my_id.my_name);
7100Sstevel@tonic-gate 				    free(minfop);
7110Sstevel@tonic-gate 				    continue;
7120Sstevel@tonic-gate 				}
7130Sstevel@tonic-gate 			}
7140Sstevel@tonic-gate 		}
7150Sstevel@tonic-gate 		next = next->nxt;
7160Sstevel@tonic-gate 	}
7170Sstevel@tonic-gate 	mutex_unlock(&mon_table[hash].lock);
7180Sstevel@tonic-gate }
7190Sstevel@tonic-gate 
7200Sstevel@tonic-gate /*
7210Sstevel@tonic-gate  * Work thread created to do the actual statd_call_lockd
7220Sstevel@tonic-gate  */
7230Sstevel@tonic-gate static void *
thr_send_notice(void * arg)7240Sstevel@tonic-gate thr_send_notice(void *arg)
7250Sstevel@tonic-gate {
7260Sstevel@tonic-gate 	moninfo_t *minfop;
7270Sstevel@tonic-gate 
7280Sstevel@tonic-gate 	minfop = (moninfo_t *)arg;
7290Sstevel@tonic-gate 
7300Sstevel@tonic-gate 	if (statd_call_lockd(&minfop->id, minfop->state) == -1) {
7310Sstevel@tonic-gate 		if (debug && minfop->id.mon_id.mon_name)
7320Sstevel@tonic-gate 			(void) printf(
7330Sstevel@tonic-gate 		"problem with notifying %s failure, give up\n",
7340Sstevel@tonic-gate 			minfop->id.mon_id.mon_name);
7350Sstevel@tonic-gate 	} else {
7360Sstevel@tonic-gate 		if (debug)
7370Sstevel@tonic-gate 			(void) printf(
7380Sstevel@tonic-gate 		"send_notice: %s, %d notified.\n",
7390Sstevel@tonic-gate 		minfop->id.mon_id.mon_name, minfop->state);
7400Sstevel@tonic-gate 	}
7410Sstevel@tonic-gate 
7420Sstevel@tonic-gate 	free(minfop->id.mon_id.mon_name);
7430Sstevel@tonic-gate 	free(minfop->id.mon_id.my_id.my_name);
7440Sstevel@tonic-gate 	free(minfop);
7450Sstevel@tonic-gate 
7460Sstevel@tonic-gate 	thr_exit((void *) 0);
7470Sstevel@tonic-gate #ifdef lint
7480Sstevel@tonic-gate 	/*NOTREACHED*/
7490Sstevel@tonic-gate 	return ((void *)0);
7500Sstevel@tonic-gate #endif
7510Sstevel@tonic-gate }
7520Sstevel@tonic-gate 
7530Sstevel@tonic-gate /*
7540Sstevel@tonic-gate  * Contact lockd specified by monp.
7550Sstevel@tonic-gate  */
7560Sstevel@tonic-gate static int
statd_call_lockd(monp,state)7570Sstevel@tonic-gate statd_call_lockd(monp, state)
7580Sstevel@tonic-gate 	mon *monp;
7590Sstevel@tonic-gate 	int state;
7600Sstevel@tonic-gate {
7610Sstevel@tonic-gate 	enum clnt_stat clnt_stat;
7620Sstevel@tonic-gate 	struct timeval tottimeout;
7630Sstevel@tonic-gate 	struct status stat;
7640Sstevel@tonic-gate 	my_id *my_idp;
7650Sstevel@tonic-gate 	char *mon_name;
7660Sstevel@tonic-gate 	int i;
7670Sstevel@tonic-gate 	int rc = 0;
7680Sstevel@tonic-gate 	CLIENT *clnt;
7690Sstevel@tonic-gate 
7700Sstevel@tonic-gate 	mon_name = monp->mon_id.mon_name;
7710Sstevel@tonic-gate 	my_idp = &monp->mon_id.my_id;
7720Sstevel@tonic-gate 	(void) memset(&stat, 0, sizeof (struct status));
7730Sstevel@tonic-gate 	stat.mon_name = mon_name;
7740Sstevel@tonic-gate 	stat.state = state;
7750Sstevel@tonic-gate 	for (i = 0; i < 16; i++) {
7760Sstevel@tonic-gate 		stat.priv[i] = monp->priv[i];
7770Sstevel@tonic-gate 	}
7780Sstevel@tonic-gate 	if (debug)
7790Sstevel@tonic-gate 		(void) printf("statd_call_lockd: %s state = %d\n",
7800Sstevel@tonic-gate 			stat.mon_name, stat.state);
7810Sstevel@tonic-gate 
782*1Sgt29601 	tottimeout.tv_sec = SM_RPC_TIMEOUT;
783*1Sgt29601 	tottimeout.tv_usec = 0;
784*1Sgt29601 
7850Sstevel@tonic-gate 	if ((clnt = create_client(my_idp->my_name, my_idp->my_prog,
786*1Sgt29601 		my_idp->my_vers, &tottimeout)) == (CLIENT *) NULL) {
7870Sstevel@tonic-gate 			return (-1);
7880Sstevel@tonic-gate 	}
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate 	clnt_stat = clnt_call(clnt, my_idp->my_proc, xdr_status, (char *)&stat,
7910Sstevel@tonic-gate 				xdr_void, NULL, tottimeout);
7920Sstevel@tonic-gate 	if (debug) {
7930Sstevel@tonic-gate 		(void) printf("clnt_stat=%s(%d)\n",
7940Sstevel@tonic-gate 			clnt_sperrno(clnt_stat), clnt_stat);
7950Sstevel@tonic-gate 	}
7960Sstevel@tonic-gate 	if (clnt_stat != (int)RPC_SUCCESS) {
7970Sstevel@tonic-gate 		syslog(LOG_WARNING,
7980Sstevel@tonic-gate 			"statd: cannot talk to lockd at %s, %s(%d)\n",
7990Sstevel@tonic-gate 			my_idp->my_name, clnt_sperrno(clnt_stat), clnt_stat);
8000Sstevel@tonic-gate 		rc = -1;
8010Sstevel@tonic-gate 	}
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate 	clnt_destroy(clnt);
8040Sstevel@tonic-gate 	return (rc);
8050Sstevel@tonic-gate 
8060Sstevel@tonic-gate }
8070Sstevel@tonic-gate 
8080Sstevel@tonic-gate /*
8090Sstevel@tonic-gate  * Client handle created.
8100Sstevel@tonic-gate  */
8110Sstevel@tonic-gate CLIENT *
create_client(host,prognum,versnum,utimeout)812*1Sgt29601 create_client(host, prognum, versnum, utimeout)
8130Sstevel@tonic-gate 	char	*host;
8140Sstevel@tonic-gate 	int	prognum;
8150Sstevel@tonic-gate 	int	versnum;
816*1Sgt29601 	struct timeval	*utimeout;
8170Sstevel@tonic-gate {
8180Sstevel@tonic-gate 	int		fd;
8190Sstevel@tonic-gate 	struct timeval	timeout;
8200Sstevel@tonic-gate 	CLIENT		*client;
8210Sstevel@tonic-gate 	struct t_info	tinfo;
8220Sstevel@tonic-gate 
823*1Sgt29601 	if ((client = clnt_create_timed(host, prognum, versnum,
824*1Sgt29601 			"netpath", utimeout)) == NULL) {
8250Sstevel@tonic-gate 		return (NULL);
8260Sstevel@tonic-gate 	}
8270Sstevel@tonic-gate 	(void) CLNT_CONTROL(client, CLGET_FD, (caddr_t)&fd);
8280Sstevel@tonic-gate 	if (t_getinfo(fd, &tinfo) != -1) {
8290Sstevel@tonic-gate 		if (tinfo.servtype == T_CLTS) {
8300Sstevel@tonic-gate 			/*
8310Sstevel@tonic-gate 			 * Set time outs for connectionless case
8320Sstevel@tonic-gate 			 */
8330Sstevel@tonic-gate 			timeout.tv_usec = 0;
8340Sstevel@tonic-gate 			timeout.tv_sec = SM_CLTS_TIMEOUT;
8350Sstevel@tonic-gate 			(void) CLNT_CONTROL(client,
8360Sstevel@tonic-gate 				CLSET_RETRY_TIMEOUT, (caddr_t)&timeout);
8370Sstevel@tonic-gate 		}
8380Sstevel@tonic-gate 	} else
8390Sstevel@tonic-gate 		return (NULL);
8400Sstevel@tonic-gate 
8410Sstevel@tonic-gate 	return (client);
8420Sstevel@tonic-gate }
8430Sstevel@tonic-gate 
8440Sstevel@tonic-gate /*
8450Sstevel@tonic-gate  * ONLY for debugging.
8460Sstevel@tonic-gate  * Debug messages which prints out the monitor table information.
8470Sstevel@tonic-gate  * If name is specified, just print out the hash list corresponding
8480Sstevel@tonic-gate  * to name, otherwise print out the entire monitor table.
8490Sstevel@tonic-gate  */
8500Sstevel@tonic-gate static void
pr_mon(name)8510Sstevel@tonic-gate pr_mon(name)
8520Sstevel@tonic-gate 	char *name;
8530Sstevel@tonic-gate {
8540Sstevel@tonic-gate 	mon_entry *nl;
8550Sstevel@tonic-gate 	int hash;
8560Sstevel@tonic-gate 
8570Sstevel@tonic-gate 	if (!debug)
8580Sstevel@tonic-gate 		return;
8590Sstevel@tonic-gate 
8600Sstevel@tonic-gate 	/* print all */
8610Sstevel@tonic-gate 	if (name == NULL) {
8620Sstevel@tonic-gate 		for (hash = 0; hash < MAX_HASHSIZE; hash++) {
8630Sstevel@tonic-gate 			mutex_lock(&mon_table[hash].lock);
8640Sstevel@tonic-gate 			nl = mon_table[hash].sm_monhdp;
8650Sstevel@tonic-gate 			if (nl == (struct mon_entry *)NULL) {
8660Sstevel@tonic-gate 				(void) printf(
8670Sstevel@tonic-gate 					"*****monitor_q = NULL hash %d\n",
8680Sstevel@tonic-gate 					hash);
8690Sstevel@tonic-gate 				mutex_unlock(&mon_table[hash].lock);
8700Sstevel@tonic-gate 				continue;
8710Sstevel@tonic-gate 			}
8720Sstevel@tonic-gate 			(void) printf("*****monitor_q:\n ");
8730Sstevel@tonic-gate 			while (nl != (mon_entry *)NULL) {
8740Sstevel@tonic-gate 				(void) printf("%s:(%x), ",
8750Sstevel@tonic-gate 					nl->id.mon_id.mon_name, (int)nl);
8760Sstevel@tonic-gate 				nl = nl->nxt;
8770Sstevel@tonic-gate 			}
8780Sstevel@tonic-gate 			mutex_unlock(&mon_table[hash].lock);
8790Sstevel@tonic-gate 			(void) printf("\n");
8800Sstevel@tonic-gate 		}
8810Sstevel@tonic-gate 	} else { /* print one hash list */
8820Sstevel@tonic-gate 		SMHASH(name, hash);
8830Sstevel@tonic-gate 		mutex_lock(&mon_table[hash].lock);
8840Sstevel@tonic-gate 		nl = mon_table[hash].sm_monhdp;
8850Sstevel@tonic-gate 		if (nl == (struct mon_entry *)NULL) {
8860Sstevel@tonic-gate 			(void) printf("*****monitor_q = NULL hash %d\n", hash);
8870Sstevel@tonic-gate 		} else {
8880Sstevel@tonic-gate 			(void) printf("*****monitor_q:\n ");
8890Sstevel@tonic-gate 			while (nl != (mon_entry *)NULL) {
8900Sstevel@tonic-gate 				(void) printf("%s:(%x), ",
8910Sstevel@tonic-gate 					nl->id.mon_id.mon_name, (int)nl);
8920Sstevel@tonic-gate 				nl = nl->nxt;
8930Sstevel@tonic-gate 			}
8940Sstevel@tonic-gate 			(void) printf("\n");
8950Sstevel@tonic-gate 		}
8960Sstevel@tonic-gate 		mutex_unlock(&mon_table[hash].lock);
8970Sstevel@tonic-gate 	}
8980Sstevel@tonic-gate }
8990Sstevel@tonic-gate 
9000Sstevel@tonic-gate /*
9010Sstevel@tonic-gate  * Only for debugging.
9020Sstevel@tonic-gate  * Dump the host name-to-address translation table passed in `name_addr'.
9030Sstevel@tonic-gate  */
9040Sstevel@tonic-gate static void
pr_name_addr(name_addr_entry_t * name_addr)9050Sstevel@tonic-gate pr_name_addr(name_addr_entry_t *name_addr)
9060Sstevel@tonic-gate {
9070Sstevel@tonic-gate 	name_addr_entry_t *entry;
9080Sstevel@tonic-gate 	addr_entry_t *addr;
9090Sstevel@tonic-gate 	struct in_addr ipv4_addr;
9100Sstevel@tonic-gate 	char *ipv6_addr;
9110Sstevel@tonic-gate 	char abuf[INET6_ADDRSTRLEN];
9120Sstevel@tonic-gate 
9130Sstevel@tonic-gate 	assert(MUTEX_HELD(&name_addrlock));
9140Sstevel@tonic-gate 	(void) printf("name-to-address translation table:\n");
9150Sstevel@tonic-gate 	for (entry = name_addr; entry != NULL; entry = entry->next) {
9160Sstevel@tonic-gate 		(void) printf("\t%s: ",
9170Sstevel@tonic-gate 				(entry->name ? entry->name : "(null)"));
9180Sstevel@tonic-gate 		for (addr = entry->addresses; addr; addr = addr->next) {
9190Sstevel@tonic-gate 			switch (addr->family) {
9200Sstevel@tonic-gate 				case AF_INET:
9210Sstevel@tonic-gate 					ipv4_addr = *(struct in_addr *)addr->ah.
9220Sstevel@tonic-gate n_bytes;
9230Sstevel@tonic-gate 					(void) printf(" %s (fam %d)",
9240Sstevel@tonic-gate 							inet_ntoa(ipv4_addr),
9250Sstevel@tonic-gate 							addr->family);
9260Sstevel@tonic-gate 					break;
9270Sstevel@tonic-gate 				case AF_INET6:
9280Sstevel@tonic-gate 					ipv6_addr = (char *)addr->ah.n_bytes;
9290Sstevel@tonic-gate 					(void) printf(" %s (fam %d)",
9300Sstevel@tonic-gate 							inet_ntop(addr->family,
9310Sstevel@tonic-gate ipv6_addr, abuf, sizeof (abuf)), addr->family);
9320Sstevel@tonic-gate 					break;
9330Sstevel@tonic-gate 				default:
9340Sstevel@tonic-gate 					return;
9350Sstevel@tonic-gate 			}
9360Sstevel@tonic-gate 		}
9370Sstevel@tonic-gate 		printf("\n");
9380Sstevel@tonic-gate 	}
9390Sstevel@tonic-gate }
9400Sstevel@tonic-gate 
9410Sstevel@tonic-gate /*
9420Sstevel@tonic-gate  * Statd has trouble dealing with hostname aliases because two
9430Sstevel@tonic-gate  * different aliases for the same machine don't match each other
9440Sstevel@tonic-gate  * when using strcmp.  To deal with this, the hostnames must be
9450Sstevel@tonic-gate  * translated into some sort of universal identifier.  These
9460Sstevel@tonic-gate  * identifiers can be compared.  Universal network addresses are
9470Sstevel@tonic-gate  * currently used for this identifier because it is general and
9480Sstevel@tonic-gate  * easy to do.  Other schemes are possible and this routine
9490Sstevel@tonic-gate  * could be converted if required.
9500Sstevel@tonic-gate  *
9510Sstevel@tonic-gate  * If it can't find an address for some reason, 0 is returned.
9520Sstevel@tonic-gate  */
9530Sstevel@tonic-gate static int
hostname_eq(char * host1,char * host2)9540Sstevel@tonic-gate hostname_eq(char *host1, char *host2)
9550Sstevel@tonic-gate {
9560Sstevel@tonic-gate 	char *sysid1;
9570Sstevel@tonic-gate 	char *sysid2;
9580Sstevel@tonic-gate 	int rv;
9590Sstevel@tonic-gate 
9600Sstevel@tonic-gate 	sysid1 = get_system_id(host1);
9610Sstevel@tonic-gate 	sysid2 = get_system_id(host2);
9620Sstevel@tonic-gate 	if ((sysid1 == NULL) || (sysid2 == NULL))
9630Sstevel@tonic-gate 		rv = 0;
9640Sstevel@tonic-gate 	else
9650Sstevel@tonic-gate 		rv = (strcmp(sysid1, sysid2) == 0);
9660Sstevel@tonic-gate 	free(sysid1);
9670Sstevel@tonic-gate 	free(sysid2);
9680Sstevel@tonic-gate 	return (rv);
9690Sstevel@tonic-gate }
9700Sstevel@tonic-gate 
9710Sstevel@tonic-gate /*
9720Sstevel@tonic-gate  * Convert a hostname character string into its network address.
9730Sstevel@tonic-gate  * A network address is found by searching through all the entries
9740Sstevel@tonic-gate  * in /etc/netconfig and doing a netdir_getbyname() for each inet
9750Sstevel@tonic-gate  * entry found.  The netbuf structure returned is converted into
9760Sstevel@tonic-gate  * a universal address format.
9770Sstevel@tonic-gate  *
9780Sstevel@tonic-gate  * If a NULL hostname is given, then the name of the current host
9790Sstevel@tonic-gate  * is used.  If the hostname doesn't map to an address, a NULL
9800Sstevel@tonic-gate  * pointer is returned.
9810Sstevel@tonic-gate  *
9820Sstevel@tonic-gate  * N.B. the character string returned is allocated in taddr2uaddr()
9830Sstevel@tonic-gate  * and should be freed by the caller using free().
9840Sstevel@tonic-gate  */
9850Sstevel@tonic-gate static char *
get_system_id(char * hostname)9860Sstevel@tonic-gate get_system_id(char *hostname)
9870Sstevel@tonic-gate {
9880Sstevel@tonic-gate 	void *hp;
9890Sstevel@tonic-gate 	struct netconfig *ncp;
9900Sstevel@tonic-gate 	struct nd_hostserv service;
9910Sstevel@tonic-gate 	struct nd_addrlist *addrs;
9920Sstevel@tonic-gate 	char *uaddr;
9930Sstevel@tonic-gate 	int rv;
9940Sstevel@tonic-gate 
9950Sstevel@tonic-gate 	if (hostname == NULL)
9960Sstevel@tonic-gate 		service.h_host = HOST_SELF;
9970Sstevel@tonic-gate 	else
9980Sstevel@tonic-gate 		service.h_host = hostname;
9990Sstevel@tonic-gate 	service.h_serv = NULL;
10000Sstevel@tonic-gate 	hp = setnetconfig();
10010Sstevel@tonic-gate 	if (hp == (void *) NULL) {
10020Sstevel@tonic-gate 		return (NULL);
10030Sstevel@tonic-gate 	}
10040Sstevel@tonic-gate 	while ((ncp = getnetconfig(hp)) != (struct netconfig *)NULL) {
10050Sstevel@tonic-gate 		if ((strcmp(ncp->nc_protofmly, NC_INET) == 0) ||
10060Sstevel@tonic-gate 			(strcmp(ncp->nc_protofmly, NC_INET6) == 0)) {
10070Sstevel@tonic-gate 			addrs = NULL;
10080Sstevel@tonic-gate 			rv = netdir_getbyname(ncp, &service, &addrs);
10090Sstevel@tonic-gate 			if (rv != 0) {
10100Sstevel@tonic-gate 				continue;
10110Sstevel@tonic-gate 			}
10120Sstevel@tonic-gate 			if (addrs) {
10130Sstevel@tonic-gate 				uaddr = taddr2uaddr(ncp, addrs->n_addrs);
10140Sstevel@tonic-gate 				netdir_free(addrs, ND_ADDRLIST);
10150Sstevel@tonic-gate 				endnetconfig(hp);
10160Sstevel@tonic-gate 				return (uaddr);
10170Sstevel@tonic-gate 			}
10180Sstevel@tonic-gate 		}
10190Sstevel@tonic-gate 		else
10200Sstevel@tonic-gate 			continue;
10210Sstevel@tonic-gate 	}
10220Sstevel@tonic-gate 	endnetconfig(hp);
10230Sstevel@tonic-gate 	return (NULL);
10240Sstevel@tonic-gate }
10250Sstevel@tonic-gate 
10260Sstevel@tonic-gate void
merge_hosts(void)10270Sstevel@tonic-gate merge_hosts(void)
10280Sstevel@tonic-gate {
10290Sstevel@tonic-gate 	struct lifconf *lifc = NULL;
10300Sstevel@tonic-gate 	int sock = -1;
10310Sstevel@tonic-gate 	struct lifreq *lifrp;
10320Sstevel@tonic-gate 	struct lifreq lifr;
10330Sstevel@tonic-gate 	int n;
10340Sstevel@tonic-gate 	struct sockaddr_in *sin;
10350Sstevel@tonic-gate 	struct sockaddr_in6 *sin6;
10360Sstevel@tonic-gate 	struct sockaddr_storage *sa;
10370Sstevel@tonic-gate 	int af;
10380Sstevel@tonic-gate 	struct hostent *phost;
10390Sstevel@tonic-gate 	char *addr;
10400Sstevel@tonic-gate 	size_t alen;
10410Sstevel@tonic-gate 	int errnum;
10420Sstevel@tonic-gate 
10430Sstevel@tonic-gate 	/*
10440Sstevel@tonic-gate 	 * This function will enumerate all the interfaces for
10450Sstevel@tonic-gate 	 * this platform, then get the hostent for each i/f.
10460Sstevel@tonic-gate 	 * With the hostent structure, we can get all of the
10470Sstevel@tonic-gate 	 * aliases for the i/f. Then we'll merge all the aliases
10480Sstevel@tonic-gate 	 * with the existing host_name[] list to come up with
10490Sstevel@tonic-gate 	 * all of the known names for each interface. This solves
10500Sstevel@tonic-gate 	 * the problem of a multi-homed host not knowing which
10510Sstevel@tonic-gate 	 * name to publish when statd is started. All the aliases
10520Sstevel@tonic-gate 	 * will be stored in the array, host_name.
10530Sstevel@tonic-gate 	 *
10540Sstevel@tonic-gate 	 * NOTE: Even though we will use all of the aliases we
10550Sstevel@tonic-gate 	 * can get from the i/f hostent, the receiving statd
10560Sstevel@tonic-gate 	 * will still need to handle aliases with hostname_eq.
10570Sstevel@tonic-gate 	 * This is because the sender's aliases may not match
10580Sstevel@tonic-gate 	 * those of the receiver.
10590Sstevel@tonic-gate 	 */
10600Sstevel@tonic-gate 	lifc = getmyaddrs();
10610Sstevel@tonic-gate 	if (lifc == (struct lifconf *)NULL) {
10620Sstevel@tonic-gate 		goto finish;
10630Sstevel@tonic-gate 	}
10640Sstevel@tonic-gate 	lifrp = lifc->lifc_req;
10650Sstevel@tonic-gate 	for (n = lifc->lifc_len / sizeof (struct lifreq); n > 0; n--, lifrp++) {
10660Sstevel@tonic-gate 
10670Sstevel@tonic-gate 		(void) strncpy(lifr.lifr_name, lifrp->lifr_name,
10680Sstevel@tonic-gate 				sizeof (lifr.lifr_name));
10690Sstevel@tonic-gate 
10700Sstevel@tonic-gate 		af = lifrp->lifr_addr.ss_family;
10710Sstevel@tonic-gate 		sock = socket(af, SOCK_DGRAM, 0);
10720Sstevel@tonic-gate 		if (sock == -1) {
10730Sstevel@tonic-gate 			syslog(LOG_ERR, "statd: socket failed\n");
10740Sstevel@tonic-gate 			goto finish;
10750Sstevel@tonic-gate 		}
10760Sstevel@tonic-gate 
10770Sstevel@tonic-gate 		/* If it's the loopback interface, ignore */
10780Sstevel@tonic-gate 		if (ioctl(sock, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
10790Sstevel@tonic-gate 			syslog(LOG_ERR,
10800Sstevel@tonic-gate 				"statd: SIOCGLIFFLAGS failed, error: %m\n");
10810Sstevel@tonic-gate 			goto finish;
10820Sstevel@tonic-gate 		}
10830Sstevel@tonic-gate 		if (lifr.lifr_flags & IFF_LOOPBACK)
10840Sstevel@tonic-gate 			continue;
10850Sstevel@tonic-gate 
10860Sstevel@tonic-gate 		if (ioctl(sock, SIOCGLIFADDR, (caddr_t)&lifr) < 0) {
10870Sstevel@tonic-gate 			syslog(LOG_ERR,
10880Sstevel@tonic-gate 				"statd: SIOCGLIFADDR failed, error: %m\n");
10890Sstevel@tonic-gate 			goto finish;
10900Sstevel@tonic-gate 		}
10910Sstevel@tonic-gate 		sa = (struct sockaddr_storage *)&(lifr.lifr_addr);
10920Sstevel@tonic-gate 
10930Sstevel@tonic-gate 		if (sa->ss_family == AF_INET) {
10940Sstevel@tonic-gate 			sin = (struct sockaddr_in *)&lifr.lifr_addr;
10950Sstevel@tonic-gate 			addr = (char *)(&sin->sin_addr);
10960Sstevel@tonic-gate 			alen = sizeof (struct in_addr);
10970Sstevel@tonic-gate 		} else if (sa->ss_family == AF_INET6) {
10980Sstevel@tonic-gate 			sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
10990Sstevel@tonic-gate 			addr = (char *)(&sin6->sin6_addr);
11000Sstevel@tonic-gate 			alen = sizeof (struct in6_addr);
11010Sstevel@tonic-gate 		} else {
11020Sstevel@tonic-gate 			syslog(LOG_WARNING,
11030Sstevel@tonic-gate 			    "unexpected address family (%d)",
11040Sstevel@tonic-gate 			    sa->ss_family);
11050Sstevel@tonic-gate 			continue;
11060Sstevel@tonic-gate 		}
11070Sstevel@tonic-gate 
11080Sstevel@tonic-gate 		phost = getipnodebyaddr(addr, alen, sa->ss_family, &errnum);
11090Sstevel@tonic-gate 
11100Sstevel@tonic-gate 		if (phost)
11110Sstevel@tonic-gate 			add_aliases(phost);
11120Sstevel@tonic-gate 	}
11130Sstevel@tonic-gate 	/*
11140Sstevel@tonic-gate 	 * Now, just in case we didn't get them all byaddr,
11150Sstevel@tonic-gate 	 * let's look by name.
11160Sstevel@tonic-gate 	 */
11170Sstevel@tonic-gate 	phost = getipnodebyname(hostname, AF_INET6, AI_ALL, &errnum);
11180Sstevel@tonic-gate 
11190Sstevel@tonic-gate 	if (phost)
11200Sstevel@tonic-gate 		add_aliases(phost);
11210Sstevel@tonic-gate 
11220Sstevel@tonic-gate finish:
11230Sstevel@tonic-gate 	if (sock != -1)
11240Sstevel@tonic-gate 		(void) close(sock);
11250Sstevel@tonic-gate 	if (lifc) {
11260Sstevel@tonic-gate 		free(lifc->lifc_buf);
11270Sstevel@tonic-gate 		free(lifc);
11280Sstevel@tonic-gate 	}
11290Sstevel@tonic-gate }
11300Sstevel@tonic-gate 
11310Sstevel@tonic-gate /*
11320Sstevel@tonic-gate  * add_aliases traverses a hostent alias list, compares
11330Sstevel@tonic-gate  * the aliases to the contents of host_name, and if an
11340Sstevel@tonic-gate  * alias is not already present, adds it to host_name[].
11350Sstevel@tonic-gate  */
11360Sstevel@tonic-gate 
11370Sstevel@tonic-gate static void
add_aliases(struct hostent * phost)11380Sstevel@tonic-gate add_aliases(struct hostent *phost)
11390Sstevel@tonic-gate {
11400Sstevel@tonic-gate 	char **aliases;
11410Sstevel@tonic-gate 
11420Sstevel@tonic-gate 	if (!in_host_array(phost->h_name)) {
11430Sstevel@tonic-gate 		add_to_host_array(phost->h_name);
11440Sstevel@tonic-gate 	}
11450Sstevel@tonic-gate 
11460Sstevel@tonic-gate 	if (phost->h_aliases == NULL)
11470Sstevel@tonic-gate 		return;			/* no aliases to register */
11480Sstevel@tonic-gate 
11490Sstevel@tonic-gate 	for (aliases = phost->h_aliases; *aliases != NULL; aliases++) {
11500Sstevel@tonic-gate 		if (!in_host_array(*aliases)) {
11510Sstevel@tonic-gate 			add_to_host_array(*aliases);
11520Sstevel@tonic-gate 		}
11530Sstevel@tonic-gate 	}
11540Sstevel@tonic-gate }
11550Sstevel@tonic-gate 
11560Sstevel@tonic-gate /*
11570Sstevel@tonic-gate  * in_host_array checks if the given hostname exists in the host_name
11580Sstevel@tonic-gate  * array. Returns 0 if the host doesn't exist, and 1 if it does exist
11590Sstevel@tonic-gate  */
11600Sstevel@tonic-gate static int
in_host_array(char * host)11610Sstevel@tonic-gate in_host_array(char *host)
11620Sstevel@tonic-gate {
11630Sstevel@tonic-gate 	int i;
11640Sstevel@tonic-gate 
11650Sstevel@tonic-gate 	if (debug)
11660Sstevel@tonic-gate 		(void) printf("%s ", host);
11670Sstevel@tonic-gate 
11680Sstevel@tonic-gate 	if ((strcmp(hostname, host) == 0) || (strcmp(LOGHOST, host) == 0))
11690Sstevel@tonic-gate 		return (1);
11700Sstevel@tonic-gate 
11710Sstevel@tonic-gate 	for (i = 0; i < addrix; i++) {
11720Sstevel@tonic-gate 		if (strcmp(host_name[i], host) == 0)
11730Sstevel@tonic-gate 			return (1);
11740Sstevel@tonic-gate 	}
11750Sstevel@tonic-gate 
11760Sstevel@tonic-gate 	return (0);
11770Sstevel@tonic-gate }
11780Sstevel@tonic-gate 
11790Sstevel@tonic-gate /*
11800Sstevel@tonic-gate  * add_to_host_array adds a hostname to the host_name array. But if
11810Sstevel@tonic-gate  * the array is already full, then it first reallocates the array with
11820Sstevel@tonic-gate  * HOST_NAME_INCR extra elements. If the realloc fails, then it does
11830Sstevel@tonic-gate  * nothing and leaves host_name the way it was previous to the call.
11840Sstevel@tonic-gate  */
11850Sstevel@tonic-gate static void
add_to_host_array(char * host)11860Sstevel@tonic-gate add_to_host_array(char *host) {
11870Sstevel@tonic-gate 
11880Sstevel@tonic-gate 	void *new_block = NULL;
11890Sstevel@tonic-gate 
11900Sstevel@tonic-gate 	/* Make sure we don't overrun host_name. */
11910Sstevel@tonic-gate 	if (addrix >= host_name_count) {
11920Sstevel@tonic-gate 		host_name_count += HOST_NAME_INCR;
11930Sstevel@tonic-gate 		new_block = realloc((void *)host_name,
11940Sstevel@tonic-gate 				    host_name_count*sizeof (char *));
11950Sstevel@tonic-gate 		if (new_block != NULL)
11960Sstevel@tonic-gate 			host_name = new_block;
11970Sstevel@tonic-gate 		else {
11980Sstevel@tonic-gate 			host_name_count -= HOST_NAME_INCR;
11990Sstevel@tonic-gate 			return;
12000Sstevel@tonic-gate 		}
12010Sstevel@tonic-gate 	}
12020Sstevel@tonic-gate 
12030Sstevel@tonic-gate 	if ((host_name[addrix] = strdup(host)) != NULL)
12040Sstevel@tonic-gate 		addrix++;
12050Sstevel@tonic-gate }
12060Sstevel@tonic-gate 
12070Sstevel@tonic-gate /*
12080Sstevel@tonic-gate  * Compares the unqualified hostnames for hosts. Returns 0 if the
12090Sstevel@tonic-gate  * names match, and 1 if the names fail to match.
12100Sstevel@tonic-gate  */
12110Sstevel@tonic-gate int
str_cmp_unqual_hostname(char * rawname1,char * rawname2)12120Sstevel@tonic-gate str_cmp_unqual_hostname(char *rawname1, char *rawname2)
12130Sstevel@tonic-gate {
12140Sstevel@tonic-gate 	size_t unq_len1, unq_len2;
12150Sstevel@tonic-gate 	char *domain;
12160Sstevel@tonic-gate 
12170Sstevel@tonic-gate 	if (debug) {
12180Sstevel@tonic-gate 		(void) printf("str_cmp_unqual: rawname1= %s, rawname2= %s\n",
12190Sstevel@tonic-gate 				rawname1, rawname2);
12200Sstevel@tonic-gate 	}
12210Sstevel@tonic-gate 
12220Sstevel@tonic-gate 	unq_len1 = strcspn(rawname1, ".");
12230Sstevel@tonic-gate 	unq_len2 = strcspn(rawname2, ".");
12240Sstevel@tonic-gate 	domain = strchr(rawname1, '.');
12250Sstevel@tonic-gate 	if (domain != NULL) {
12260Sstevel@tonic-gate 		if ((strncmp(rawname1, SM_ADDR_IPV4, unq_len1) == 0) ||
12270Sstevel@tonic-gate 			(strncmp(rawname1, SM_ADDR_IPV6, unq_len1) == 0))
12280Sstevel@tonic-gate 		return (1);
12290Sstevel@tonic-gate 	}
12300Sstevel@tonic-gate 
12310Sstevel@tonic-gate 	if ((unq_len1 == unq_len2) &&
12320Sstevel@tonic-gate 			(strncmp(rawname1, rawname2, unq_len1) == 0)) {
12330Sstevel@tonic-gate 		return (0);
12340Sstevel@tonic-gate 	}
12350Sstevel@tonic-gate 
12360Sstevel@tonic-gate 	return (1);
12370Sstevel@tonic-gate }
12380Sstevel@tonic-gate 
12390Sstevel@tonic-gate /*
12400Sstevel@tonic-gate  * Compares <family>.<address-specifier> ASCII names for hosts.  Returns
12410Sstevel@tonic-gate  * 0 if the addresses match, and 1 if the addresses fail to match.
12420Sstevel@tonic-gate  * If the args are indeed specifiers, they should look like this:
12430Sstevel@tonic-gate  *
12440Sstevel@tonic-gate  *	ipv4.192.9.200.1 or ipv6.::C009:C801
12450Sstevel@tonic-gate  */
12460Sstevel@tonic-gate int
str_cmp_address_specifier(char * specifier1,char * specifier2)12470Sstevel@tonic-gate str_cmp_address_specifier(char *specifier1, char *specifier2)
12480Sstevel@tonic-gate {
12490Sstevel@tonic-gate 	size_t unq_len1, unq_len2;
12500Sstevel@tonic-gate 	char *rawaddr1, *rawaddr2;
12510Sstevel@tonic-gate 	int af1, af2, len;
12520Sstevel@tonic-gate 
12530Sstevel@tonic-gate 	if (debug) {
12540Sstevel@tonic-gate 		(void) printf("str_cmp_addr: specifier1= %s, specifier2= %s\n",
12550Sstevel@tonic-gate 				specifier1, specifier2);
12560Sstevel@tonic-gate 	}
12570Sstevel@tonic-gate 
12580Sstevel@tonic-gate 	/*
12590Sstevel@tonic-gate 	 * Verify that:
12600Sstevel@tonic-gate 	 *	1. The family tokens match;
12610Sstevel@tonic-gate 	 *	2. The IP addresses following the `.' are legal; and
12620Sstevel@tonic-gate 	 *	3. These addresses match.
12630Sstevel@tonic-gate 	 */
12640Sstevel@tonic-gate 	unq_len1 = strcspn(specifier1, ".");
12650Sstevel@tonic-gate 	unq_len2 = strcspn(specifier2, ".");
12660Sstevel@tonic-gate 	rawaddr1 = strchr(specifier1, '.');
12670Sstevel@tonic-gate 	rawaddr2 = strchr(specifier2, '.');
12680Sstevel@tonic-gate 
12690Sstevel@tonic-gate 	if (strncmp(specifier1, SM_ADDR_IPV4, unq_len1) == 0) {
12700Sstevel@tonic-gate 		af1 = AF_INET;
12710Sstevel@tonic-gate 		len = 4;
12720Sstevel@tonic-gate 	} else if (strncmp(specifier1, SM_ADDR_IPV6, unq_len1) == 0) {
12730Sstevel@tonic-gate 		af1 = AF_INET6;
12740Sstevel@tonic-gate 		len = 16;
12750Sstevel@tonic-gate 	}
12760Sstevel@tonic-gate 	else
12770Sstevel@tonic-gate 		return (1);
12780Sstevel@tonic-gate 
12790Sstevel@tonic-gate 	if (strncmp(specifier2, SM_ADDR_IPV4, unq_len2) == 0)
12800Sstevel@tonic-gate 		af2 = AF_INET;
12810Sstevel@tonic-gate 	else if (strncmp(specifier2, SM_ADDR_IPV6, unq_len2) == 0)
12820Sstevel@tonic-gate 		af2 = AF_INET6;
12830Sstevel@tonic-gate 	else
12840Sstevel@tonic-gate 		return (1);
12850Sstevel@tonic-gate 
12860Sstevel@tonic-gate 	if (af1 != af2)
12870Sstevel@tonic-gate 		return (1);
12880Sstevel@tonic-gate 
12890Sstevel@tonic-gate 	if (rawaddr1 != NULL && rawaddr2 != NULL) {
12900Sstevel@tonic-gate 		char dst1[16];
12910Sstevel@tonic-gate 		char dst2[16];
12920Sstevel@tonic-gate 		++rawaddr1;
12930Sstevel@tonic-gate 		++rawaddr2;
12940Sstevel@tonic-gate 
12950Sstevel@tonic-gate 		if (inet_pton(af1, rawaddr1, dst1) == 1 &&
12960Sstevel@tonic-gate 			inet_pton(af2, rawaddr1, dst2) == 1 &&
12970Sstevel@tonic-gate 			memcmp(dst1, dst2, len) == 0) {
12980Sstevel@tonic-gate 			return (0);
12990Sstevel@tonic-gate 		}
13000Sstevel@tonic-gate 	}
13010Sstevel@tonic-gate 	return (1);
13020Sstevel@tonic-gate }
1303