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