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
58452SJohn.Wren.Kennedy@Sun.COM * Common Development and Distribution License (the "License").
68452SJohn.Wren.Kennedy@Sun.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
218452SJohn.Wren.Kennedy@Sun.COM
220Sstevel@tonic-gate /*
23*11053SSurya.Prakki@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #include <unistd.h>
280Sstevel@tonic-gate #include <sys/types.h>
290Sstevel@tonic-gate #include <sys/socket.h>
300Sstevel@tonic-gate #include <netinet/in.h>
310Sstevel@tonic-gate #include <arpa/inet.h>
320Sstevel@tonic-gate #include <thread.h>
330Sstevel@tonic-gate #include "meta.h"
340Sstevel@tonic-gate #include "mdmn_subr.h"
350Sstevel@tonic-gate
360Sstevel@tonic-gate extern int mdmn_init_set(set_t setno, int todo);
370Sstevel@tonic-gate
380Sstevel@tonic-gate uint_t mdmn_busy[MD_MAXSETS][MD_MN_NCLASSES];
390Sstevel@tonic-gate mutex_t mdmn_busy_mutex[MD_MAXSETS];
400Sstevel@tonic-gate cond_t mdmn_busy_cv[MD_MAXSETS];
410Sstevel@tonic-gate
420Sstevel@tonic-gate
430Sstevel@tonic-gate /* the wakeup table for the initiator's side */
440Sstevel@tonic-gate mdmn_wti_t mdmn_initiator_table[MD_MAXSETS][MD_MN_NCLASSES];
450Sstevel@tonic-gate
460Sstevel@tonic-gate /* the wakeup table for the master */
470Sstevel@tonic-gate mdmn_wtm_t mdmn_master_table[MD_MAXSETS][MD_MN_NCLASSES];
480Sstevel@tonic-gate
490Sstevel@tonic-gate /* List of licensed ip addresses */
500Sstevel@tonic-gate licensed_ip_t licensed_nodes[NNODES];
510Sstevel@tonic-gate
520Sstevel@tonic-gate /* speed up the search for licensed ip addresses */
530Sstevel@tonic-gate md_mn_nodeid_t maxlicnodes = 0; /* 0 is not a valid node ID */
540Sstevel@tonic-gate
550Sstevel@tonic-gate /*
560Sstevel@tonic-gate * Check if a given set/class combination is currently in use
570Sstevel@tonic-gate * If in use, returns TRUE
580Sstevel@tonic-gate * Otherwise returns FALSE
590Sstevel@tonic-gate *
600Sstevel@tonic-gate * Must be called with mdmn_busy_mutex held
610Sstevel@tonic-gate */
620Sstevel@tonic-gate bool_t
mdmn_is_class_busy(set_t setno,md_mn_msgclass_t class)630Sstevel@tonic-gate mdmn_is_class_busy(set_t setno, md_mn_msgclass_t class)
640Sstevel@tonic-gate {
650Sstevel@tonic-gate if (mdmn_busy[setno][class] & MDMN_BUSY) {
660Sstevel@tonic-gate return (TRUE);
670Sstevel@tonic-gate } else {
680Sstevel@tonic-gate return (FALSE);
690Sstevel@tonic-gate }
700Sstevel@tonic-gate }
710Sstevel@tonic-gate
720Sstevel@tonic-gate /*
730Sstevel@tonic-gate * Mark a given set/class combination as currently in use
740Sstevel@tonic-gate * If the class was already in use, returns FALSE
750Sstevel@tonic-gate * Otherwise returns TRUE
760Sstevel@tonic-gate *
770Sstevel@tonic-gate * So mdmn_mark_class_busy can be used like
780Sstevel@tonic-gate * if (mdmn_mark_class_busy(setno, class) == FALSE)
790Sstevel@tonic-gate * failure;
800Sstevel@tonic-gate * else
810Sstevel@tonic-gate * success;
820Sstevel@tonic-gate *
830Sstevel@tonic-gate * Must be called with mdmn_busy_mutex held
840Sstevel@tonic-gate */
850Sstevel@tonic-gate bool_t
mdmn_mark_class_busy(set_t setno,md_mn_msgclass_t class)860Sstevel@tonic-gate mdmn_mark_class_busy(set_t setno, md_mn_msgclass_t class)
870Sstevel@tonic-gate {
880Sstevel@tonic-gate if (mdmn_busy[setno][class] & MDMN_BUSY) {
890Sstevel@tonic-gate return (FALSE);
900Sstevel@tonic-gate } else {
910Sstevel@tonic-gate mdmn_busy[setno][class] |= MDMN_BUSY;
920Sstevel@tonic-gate commd_debug(MD_MMV_MISC, "busy: set=%d, class=%d\n",
930Sstevel@tonic-gate setno, class);
940Sstevel@tonic-gate return (TRUE);
950Sstevel@tonic-gate }
960Sstevel@tonic-gate }
970Sstevel@tonic-gate
980Sstevel@tonic-gate /*
990Sstevel@tonic-gate * Mark a given set/class combination as currently available
1000Sstevel@tonic-gate * Always succeeds, thus void.
1010Sstevel@tonic-gate *
1020Sstevel@tonic-gate * If this class is marked MDMN_SUSPEND_ALL, we are in the middle of
1030Sstevel@tonic-gate * draining all classes of this set.
1040Sstevel@tonic-gate * We have to mark class+1 as MDMN_SUSPEND_ALL too.
1050Sstevel@tonic-gate * If class+2 wasn't busy, we proceed with class+2, and so on
1060Sstevel@tonic-gate * If any class is busy, we return.
1070Sstevel@tonic-gate * Then the drain process will be continued by the mdmn_mark_class_unbusy() of
1080Sstevel@tonic-gate * that busy class
1090Sstevel@tonic-gate */
1100Sstevel@tonic-gate void
mdmn_mark_class_unbusy(set_t setno,md_mn_msgclass_t class)1110Sstevel@tonic-gate mdmn_mark_class_unbusy(set_t setno, md_mn_msgclass_t class)
1120Sstevel@tonic-gate {
1130Sstevel@tonic-gate commd_debug(MD_MMV_MISC, "unbusy: set=%d, class=%d\n", setno, class);
1140Sstevel@tonic-gate mdmn_busy[setno][class] &= ~MDMN_BUSY;
1150Sstevel@tonic-gate /* something changed, inform threads waiting for that */
116*11053SSurya.Prakki@Sun.COM (void) cond_signal(&mdmn_busy_cv[setno]);
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate if ((mdmn_busy[setno][class] & MDMN_SUSPEND_ALL) == 0) {
1190Sstevel@tonic-gate return;
1200Sstevel@tonic-gate }
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate while (++class < MD_MN_NCLASSES) {
1230Sstevel@tonic-gate commd_debug(MD_MMV_MISC,
1240Sstevel@tonic-gate "unbusy: suspending set=%d, class=%d\n", setno, class);
1250Sstevel@tonic-gate if (mdmn_mark_class_suspended(setno, class, MDMN_SUSPEND_ALL)
1260Sstevel@tonic-gate == MDMNE_SET_NOT_DRAINED) {
1270Sstevel@tonic-gate break;
1280Sstevel@tonic-gate }
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate }
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate
1340Sstevel@tonic-gate /*
1350Sstevel@tonic-gate * Check if a given set/class combination is locked.
1360Sstevel@tonic-gate */
1370Sstevel@tonic-gate bool_t
mdmn_is_class_locked(set_t setno,md_mn_msgclass_t class)1380Sstevel@tonic-gate mdmn_is_class_locked(set_t setno, md_mn_msgclass_t class)
1390Sstevel@tonic-gate {
1400Sstevel@tonic-gate if (mdmn_busy[setno][class] & MDMN_LOCKED) {
1410Sstevel@tonic-gate return (TRUE);
1420Sstevel@tonic-gate } else {
1430Sstevel@tonic-gate return (FALSE);
1440Sstevel@tonic-gate }
1450Sstevel@tonic-gate }
1460Sstevel@tonic-gate
1470Sstevel@tonic-gate /*
1480Sstevel@tonic-gate * Mark a given set/class combination as locked.
1490Sstevel@tonic-gate * No checking is done here, so routine can be void.
1500Sstevel@tonic-gate * Locking a locked set/class is ok.
1510Sstevel@tonic-gate *
1520Sstevel@tonic-gate * Must be called with mdmn_busy_mutex held
1530Sstevel@tonic-gate */
1540Sstevel@tonic-gate void
mdmn_mark_class_locked(set_t setno,md_mn_msgclass_t class)1550Sstevel@tonic-gate mdmn_mark_class_locked(set_t setno, md_mn_msgclass_t class)
1560Sstevel@tonic-gate {
1570Sstevel@tonic-gate mdmn_busy[setno][class] |= MDMN_LOCKED;
1580Sstevel@tonic-gate }
1590Sstevel@tonic-gate
1600Sstevel@tonic-gate /*
1610Sstevel@tonic-gate * Mark a given set/class combination as unlocked.
1620Sstevel@tonic-gate * No checking is done here, so routine can be void.
1630Sstevel@tonic-gate * Unlocking a unlocked set/class is ok.
1640Sstevel@tonic-gate *
1650Sstevel@tonic-gate * Must be called with mdmn_busy_mutex held
1660Sstevel@tonic-gate */
1670Sstevel@tonic-gate void
mdmn_mark_class_unlocked(set_t setno,md_mn_msgclass_t class)1680Sstevel@tonic-gate mdmn_mark_class_unlocked(set_t setno, md_mn_msgclass_t class)
1690Sstevel@tonic-gate {
1700Sstevel@tonic-gate mdmn_busy[setno][class] &= ~MDMN_LOCKED;
1710Sstevel@tonic-gate }
1720Sstevel@tonic-gate
1730Sstevel@tonic-gate /*
1740Sstevel@tonic-gate * Suspend a set/class combination
1750Sstevel@tonic-gate *
1760Sstevel@tonic-gate * If called during draining all classes of a set susptype is MDMN_SUSPEND_ALL.
1770Sstevel@tonic-gate * If only one class is about to be drained susptype is MDMN_SUSPEND_1.
1780Sstevel@tonic-gate *
1790Sstevel@tonic-gate * Returns:
1800Sstevel@tonic-gate * MDMNE_ACK if there are no outstanding messages
1810Sstevel@tonic-gate * MDMNE_SET_NOT_DRAINED otherwise
1820Sstevel@tonic-gate *
1830Sstevel@tonic-gate * Must be called with mdmn_busy_mutex held for this set.
1840Sstevel@tonic-gate */
1850Sstevel@tonic-gate int
mdmn_mark_class_suspended(set_t setno,md_mn_msgclass_t class,uint_t susptype)1860Sstevel@tonic-gate mdmn_mark_class_suspended(set_t setno, md_mn_msgclass_t class, uint_t susptype)
1870Sstevel@tonic-gate {
1880Sstevel@tonic-gate /*
1890Sstevel@tonic-gate * We use the mdmn_busy array to mark this set is suspended.
1900Sstevel@tonic-gate */
1910Sstevel@tonic-gate mdmn_busy[setno][class] |= susptype;
1920Sstevel@tonic-gate
1930Sstevel@tonic-gate /*
1940Sstevel@tonic-gate * If there are outstanding messages for this set/class we
1950Sstevel@tonic-gate * return MDMNE_SET_NOT_DRAINED, otherwise we return MDMNE_ACK
1960Sstevel@tonic-gate */
1970Sstevel@tonic-gate if (mdmn_is_class_busy(setno, class) == TRUE) {
1980Sstevel@tonic-gate return (MDMNE_SET_NOT_DRAINED);
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate return (MDMNE_ACK);
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate /*
2040Sstevel@tonic-gate * Resume operation for a set/class combination after it was
2050Sstevel@tonic-gate * previously suspended
2060Sstevel@tonic-gate *
2070Sstevel@tonic-gate * If called from mdmn_comm_resume_svc_1 to resume _one_ specific class
2080Sstevel@tonic-gate * then susptype will be MDMN_SUSPEND_1
2090Sstevel@tonic-gate * Otherwise to resume all classes of one set,
2100Sstevel@tonic-gate * then susptype equals (MDMN_SUSPEND_ALL | MDMN_SUSPEND_1)
2110Sstevel@tonic-gate *
2120Sstevel@tonic-gate * Always succeeds, thus void.
2130Sstevel@tonic-gate *
2140Sstevel@tonic-gate * Must be called with mdmn_busy_mutex held for this set.
2150Sstevel@tonic-gate */
2160Sstevel@tonic-gate void
mdmn_mark_class_resumed(set_t setno,md_mn_msgclass_t class,uint_t susptype)2170Sstevel@tonic-gate mdmn_mark_class_resumed(set_t setno, md_mn_msgclass_t class, uint_t susptype)
2180Sstevel@tonic-gate {
2190Sstevel@tonic-gate /* simply the reverse operation to mdmn_mark_set_drained() */
2200Sstevel@tonic-gate mdmn_busy[setno][class] &= ~susptype;
2210Sstevel@tonic-gate }
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate /*
2240Sstevel@tonic-gate * Check if a drain command was issued for this set/class combination.
2250Sstevel@tonic-gate *
2260Sstevel@tonic-gate * Must be called with mdmn_busy_mutex held for this set.
2270Sstevel@tonic-gate */
2280Sstevel@tonic-gate bool_t
mdmn_is_class_suspended(set_t setno,md_mn_msgclass_t class)2290Sstevel@tonic-gate mdmn_is_class_suspended(set_t setno, md_mn_msgclass_t class)
2300Sstevel@tonic-gate {
2310Sstevel@tonic-gate if (mdmn_busy[setno][class] & (MDMN_SUSPEND_ALL | MDMN_SUSPEND_1)) {
2320Sstevel@tonic-gate return (TRUE);
2330Sstevel@tonic-gate } else {
2340Sstevel@tonic-gate return (FALSE);
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate }
2370Sstevel@tonic-gate
2380Sstevel@tonic-gate /*
2390Sstevel@tonic-gate * Put a result into the wakeup table for the master
2400Sstevel@tonic-gate * It's ensured that the msg id from the master_table entry and from
2410Sstevel@tonic-gate * result are matching
2420Sstevel@tonic-gate */
2430Sstevel@tonic-gate void
mdmn_set_master_table_res(set_t setno,md_mn_msgclass_t class,md_mn_result_t * res)2440Sstevel@tonic-gate mdmn_set_master_table_res(set_t setno, md_mn_msgclass_t class,
2450Sstevel@tonic-gate md_mn_result_t *res)
2460Sstevel@tonic-gate {
2470Sstevel@tonic-gate mdmn_master_table[setno][class].wtm_result = res;
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate void
mdmn_set_master_table_id(set_t setno,md_mn_msgclass_t class,md_mn_msgid_t * id)2500Sstevel@tonic-gate mdmn_set_master_table_id(set_t setno, md_mn_msgclass_t class, md_mn_msgid_t *id)
2510Sstevel@tonic-gate {
2520Sstevel@tonic-gate MSGID_COPY(id, &(mdmn_master_table[setno][class].wtm_id));
2530Sstevel@tonic-gate }
2540Sstevel@tonic-gate
2550Sstevel@tonic-gate void
mdmn_set_master_table_addr(set_t setno,md_mn_msgclass_t class,md_mn_nodeid_t nid)2560Sstevel@tonic-gate mdmn_set_master_table_addr(set_t setno, md_mn_msgclass_t class,
2570Sstevel@tonic-gate md_mn_nodeid_t nid)
2580Sstevel@tonic-gate {
2590Sstevel@tonic-gate mdmn_master_table[setno][class].wtm_addr = nid;
2600Sstevel@tonic-gate }
2610Sstevel@tonic-gate
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate md_mn_result_t *
mdmn_get_master_table_res(set_t setno,md_mn_msgclass_t class)2640Sstevel@tonic-gate mdmn_get_master_table_res(set_t setno, md_mn_msgclass_t class)
2650Sstevel@tonic-gate {
2660Sstevel@tonic-gate return (mdmn_master_table[setno][class].wtm_result);
2670Sstevel@tonic-gate }
2680Sstevel@tonic-gate
2690Sstevel@tonic-gate void
mdmn_get_master_table_id(set_t setno,md_mn_msgclass_t class,md_mn_msgid_t * id)2700Sstevel@tonic-gate mdmn_get_master_table_id(set_t setno, md_mn_msgclass_t class, md_mn_msgid_t *id)
2710Sstevel@tonic-gate {
2720Sstevel@tonic-gate MSGID_COPY(&(mdmn_master_table[setno][class].wtm_id), id);
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate
2750Sstevel@tonic-gate cond_t *
mdmn_get_master_table_cv(set_t setno,md_mn_msgclass_t class)2760Sstevel@tonic-gate mdmn_get_master_table_cv(set_t setno, md_mn_msgclass_t class)
2770Sstevel@tonic-gate {
2780Sstevel@tonic-gate return (&(mdmn_master_table[setno][class].wtm_cv));
2790Sstevel@tonic-gate }
2800Sstevel@tonic-gate
2810Sstevel@tonic-gate mutex_t *
mdmn_get_master_table_mx(set_t setno,md_mn_msgclass_t class)2820Sstevel@tonic-gate mdmn_get_master_table_mx(set_t setno, md_mn_msgclass_t class)
2830Sstevel@tonic-gate {
2840Sstevel@tonic-gate return (&(mdmn_master_table[setno][class].wtm_mx));
2850Sstevel@tonic-gate }
2860Sstevel@tonic-gate
2870Sstevel@tonic-gate md_mn_nodeid_t
mdmn_get_master_table_addr(set_t setno,md_mn_msgclass_t class)2880Sstevel@tonic-gate mdmn_get_master_table_addr(set_t setno, md_mn_msgclass_t class)
2890Sstevel@tonic-gate {
2900Sstevel@tonic-gate return (mdmn_master_table[setno][class].wtm_addr);
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate /* here come the functions dealing with the wakeup table for the initiators */
2960Sstevel@tonic-gate
2970Sstevel@tonic-gate
2980Sstevel@tonic-gate void
mdmn_register_initiator_table(set_t setno,md_mn_msgclass_t class,md_mn_msg_t * msg,SVCXPRT * transp)2990Sstevel@tonic-gate mdmn_register_initiator_table(set_t setno, md_mn_msgclass_t class,
3000Sstevel@tonic-gate md_mn_msg_t *msg, SVCXPRT *transp)
3010Sstevel@tonic-gate {
3020Sstevel@tonic-gate uint_t nnodes = set_descriptor[setno]->sd_mn_numnodes;
3030Sstevel@tonic-gate time_t timeout = mdmn_get_timeout(msg->msg_type);
3040Sstevel@tonic-gate
3050Sstevel@tonic-gate
3060Sstevel@tonic-gate MSGID_COPY(&(msg->msg_msgid),
3070Sstevel@tonic-gate &(mdmn_initiator_table[setno][class].wti_id));
3080Sstevel@tonic-gate mdmn_initiator_table[setno][class].wti_transp = transp;
3090Sstevel@tonic-gate mdmn_initiator_table[setno][class].wti_args = (char *)msg;
3100Sstevel@tonic-gate
3110Sstevel@tonic-gate /*
3120Sstevel@tonic-gate * as the point in time where we want to be guaranteed to be woken up
3130Sstevel@tonic-gate * again, we chose the
3140Sstevel@tonic-gate * current time + nnodes times the timeout value for the message type
3150Sstevel@tonic-gate */
3160Sstevel@tonic-gate mdmn_initiator_table[setno][class].wti_time =
3170Sstevel@tonic-gate time((time_t *)NULL) + (nnodes * timeout);
3180Sstevel@tonic-gate }
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate /*
3210Sstevel@tonic-gate * If the set/class combination is currently busy, return MDMNE_CLASS_BUSY
3220Sstevel@tonic-gate * Otherwise return MDMNE_ACK
3230Sstevel@tonic-gate */
3240Sstevel@tonic-gate int
mdmn_check_initiator_table(set_t setno,md_mn_msgclass_t class)3250Sstevel@tonic-gate mdmn_check_initiator_table(set_t setno, md_mn_msgclass_t class)
3260Sstevel@tonic-gate {
3270Sstevel@tonic-gate if ((mdmn_initiator_table[setno][class].wti_id.mid_nid == ~0u) &&
3280Sstevel@tonic-gate (mdmn_initiator_table[setno][class].wti_transp == (SVCXPRT *)NULL))
3290Sstevel@tonic-gate return (MDMNE_ACK);
3300Sstevel@tonic-gate return (MDMNE_CLASS_BUSY);
3310Sstevel@tonic-gate }
3320Sstevel@tonic-gate
3330Sstevel@tonic-gate /*
3340Sstevel@tonic-gate * Remove an entry from the initiator table entirely,
3350Sstevel@tonic-gate * This must be done with mutex held.
3360Sstevel@tonic-gate */
3370Sstevel@tonic-gate void
mdmn_unregister_initiator_table(set_t setno,md_mn_msgclass_t class)3380Sstevel@tonic-gate mdmn_unregister_initiator_table(set_t setno, md_mn_msgclass_t class)
3390Sstevel@tonic-gate {
3400Sstevel@tonic-gate mdmn_initiator_table[setno][class].wti_id.mid_nid = ~0u;
3410Sstevel@tonic-gate mdmn_initiator_table[setno][class].wti_id.mid_time = 0LL;
3420Sstevel@tonic-gate mdmn_initiator_table[setno][class].wti_transp = (SVCXPRT *)NULL;
3430Sstevel@tonic-gate mdmn_initiator_table[setno][class].wti_args = (char *)0;
3440Sstevel@tonic-gate mdmn_initiator_table[setno][class].wti_time = (time_t)0;
3450Sstevel@tonic-gate }
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate void
mdmn_get_initiator_table_id(set_t setno,md_mn_msgclass_t class,md_mn_msgid_t * mid)3480Sstevel@tonic-gate mdmn_get_initiator_table_id(set_t setno, md_mn_msgclass_t class,
3490Sstevel@tonic-gate md_mn_msgid_t *mid)
3500Sstevel@tonic-gate {
3510Sstevel@tonic-gate MSGID_COPY(&(mdmn_initiator_table[setno][class].wti_id), mid);
3520Sstevel@tonic-gate }
3530Sstevel@tonic-gate
3540Sstevel@tonic-gate SVCXPRT *
mdmn_get_initiator_table_transp(set_t setno,md_mn_msgclass_t class)3550Sstevel@tonic-gate mdmn_get_initiator_table_transp(set_t setno, md_mn_msgclass_t class)
3560Sstevel@tonic-gate {
3570Sstevel@tonic-gate return (mdmn_initiator_table[setno][class].wti_transp);
3580Sstevel@tonic-gate }
3590Sstevel@tonic-gate
3600Sstevel@tonic-gate char *
mdmn_get_initiator_table_args(set_t setno,md_mn_msgclass_t class)3610Sstevel@tonic-gate mdmn_get_initiator_table_args(set_t setno, md_mn_msgclass_t class)
3620Sstevel@tonic-gate {
3630Sstevel@tonic-gate return (mdmn_initiator_table[setno][class].wti_args);
3640Sstevel@tonic-gate }
3650Sstevel@tonic-gate
3660Sstevel@tonic-gate mutex_t *
mdmn_get_initiator_table_mx(set_t setno,md_mn_msgclass_t class)3670Sstevel@tonic-gate mdmn_get_initiator_table_mx(set_t setno, md_mn_msgclass_t class)
3680Sstevel@tonic-gate {
3690Sstevel@tonic-gate return (&(mdmn_initiator_table[setno][class].wti_mx));
3700Sstevel@tonic-gate }
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate time_t
mdmn_get_initiator_table_time(set_t setno,md_mn_msgclass_t class)3730Sstevel@tonic-gate mdmn_get_initiator_table_time(set_t setno, md_mn_msgclass_t class)
3740Sstevel@tonic-gate {
3750Sstevel@tonic-gate return (mdmn_initiator_table[setno][class].wti_time);
3760Sstevel@tonic-gate }
3770Sstevel@tonic-gate
3780Sstevel@tonic-gate extern uint_t md_commd_global_verb; /* global bitmask for debug classes */
3790Sstevel@tonic-gate extern FILE *commdout; /* debug output file for the commd */
3800Sstevel@tonic-gate extern hrtime_t __savetime;
3810Sstevel@tonic-gate
3820Sstevel@tonic-gate
3830Sstevel@tonic-gate /*
3840Sstevel@tonic-gate * Print debug messages to the terminal or to syslog
3850Sstevel@tonic-gate * commd_debug(MD_MMV_SYSLOG,....) is always printed (and always via syslog),
3860Sstevel@tonic-gate * even if md_commd_global_verb is zero.
3870Sstevel@tonic-gate *
3880Sstevel@tonic-gate * Otherwise the correct bit must be set in the bitmask md_commd_global_verb
3890Sstevel@tonic-gate */
3900Sstevel@tonic-gate void
commd_debug(uint_t debug_class,const char * message,...)3910Sstevel@tonic-gate commd_debug(uint_t debug_class, const char *message, ...)
3920Sstevel@tonic-gate {
3930Sstevel@tonic-gate va_list ap;
3940Sstevel@tonic-gate
3950Sstevel@tonic-gate /* Is this a message for syslog? */
3960Sstevel@tonic-gate if (debug_class == MD_MMV_SYSLOG) {
3970Sstevel@tonic-gate
3980Sstevel@tonic-gate va_start(ap, message);
3990Sstevel@tonic-gate (void) vsyslog(LOG_WARNING, message, ap);
4000Sstevel@tonic-gate va_end(ap);
4010Sstevel@tonic-gate } else {
4020Sstevel@tonic-gate /* Is this debug_class set in the global verbosity state? */
4030Sstevel@tonic-gate if ((md_commd_global_verb & debug_class) == 0) {
4040Sstevel@tonic-gate return;
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate /* Is our output file already functioning? */
4070Sstevel@tonic-gate if (commdout == NULL) {
4080Sstevel@tonic-gate return;
4090Sstevel@tonic-gate }
4100Sstevel@tonic-gate /* Are timestamps activated ? */
4110Sstevel@tonic-gate if (md_commd_global_verb & MD_MMV_TIMESTAMP) {
4120Sstevel@tonic-gate /* print time since last TRESET in usecs */
413*11053SSurya.Prakki@Sun.COM (void) fprintf(commdout, "[%s]",
4140Sstevel@tonic-gate meta_print_hrtime(gethrtime() - __savetime));
4150Sstevel@tonic-gate }
4160Sstevel@tonic-gate /* Now print the real message */
4170Sstevel@tonic-gate va_start(ap, message);
4180Sstevel@tonic-gate (void) vfprintf(commdout, message, ap);
4190Sstevel@tonic-gate va_end(ap);
4200Sstevel@tonic-gate }
4210Sstevel@tonic-gate }
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate
4240Sstevel@tonic-gate void
dump_hex(uint_t debug_class,unsigned int * x,int cnt)4250Sstevel@tonic-gate dump_hex(uint_t debug_class, unsigned int *x, int cnt)
4260Sstevel@tonic-gate {
4270Sstevel@tonic-gate cnt /= sizeof (unsigned int);
4280Sstevel@tonic-gate while (cnt--) {
4290Sstevel@tonic-gate commd_debug(debug_class, "0x%8x ", *x++);
4300Sstevel@tonic-gate if (cnt % 4)
4310Sstevel@tonic-gate continue;
4320Sstevel@tonic-gate commd_debug(debug_class, "\n");
4330Sstevel@tonic-gate }
4340Sstevel@tonic-gate commd_debug(debug_class, "\n");
4350Sstevel@tonic-gate }
4360Sstevel@tonic-gate
4370Sstevel@tonic-gate /* debug output: dump a message */
4380Sstevel@tonic-gate void
dump_msg(uint_t dbc,char * prefix,md_mn_msg_t * msg)4390Sstevel@tonic-gate dump_msg(uint_t dbc, char *prefix, md_mn_msg_t *msg)
4400Sstevel@tonic-gate {
4410Sstevel@tonic-gate commd_debug(dbc, "%s &msg = 0x%x\n", prefix, (int)msg);
4420Sstevel@tonic-gate commd_debug(dbc, "%s ID = (%d, 0x%llx-%d)\n", prefix,
4430Sstevel@tonic-gate MSGID_ELEMS(msg->msg_msgid));
4440Sstevel@tonic-gate commd_debug(dbc, "%s sender = %d\n", prefix, msg->msg_sender);
4450Sstevel@tonic-gate commd_debug(dbc, "%s flags = 0x%x\n", prefix, msg->msg_flags);
4460Sstevel@tonic-gate commd_debug(dbc, "%s setno = %d\n", prefix, msg->msg_setno);
4478452SJohn.Wren.Kennedy@Sun.COM commd_debug(dbc, "%s recipient = %d\n", prefix, msg->msg_recipient);
4480Sstevel@tonic-gate commd_debug(dbc, "%s type = %d\n", prefix, msg->msg_type);
4490Sstevel@tonic-gate commd_debug(dbc, "%s size = %d\n", prefix, msg->msg_event_size);
4500Sstevel@tonic-gate if (msg->msg_event_size) {
4510Sstevel@tonic-gate commd_debug(dbc, "%s data =\n", prefix);
4520Sstevel@tonic-gate dump_hex(dbc, (unsigned int *)(void *)msg->msg_event_data,
4530Sstevel@tonic-gate msg->msg_event_size);
4540Sstevel@tonic-gate }
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate
4570Sstevel@tonic-gate /* debug output: dump a result structure */
4580Sstevel@tonic-gate void
dump_result(uint_t dbc,char * prefix,md_mn_result_t * res)4590Sstevel@tonic-gate dump_result(uint_t dbc, char *prefix, md_mn_result_t *res)
4600Sstevel@tonic-gate {
4610Sstevel@tonic-gate commd_debug(dbc, "%s &res = 0x%x\n", prefix, (int)res);
4620Sstevel@tonic-gate commd_debug(dbc, "%s ID = (%d, 0x%llx-%d)\n", prefix,
4630Sstevel@tonic-gate MSGID_ELEMS(res->mmr_msgid));
4640Sstevel@tonic-gate commd_debug(dbc, "%s setno = %d\n", prefix, res->mmr_setno);
4650Sstevel@tonic-gate commd_debug(dbc, "%s type = %d\n", prefix, res->mmr_msgtype);
4660Sstevel@tonic-gate commd_debug(dbc, "%s flags = 0x%x\n", prefix, res->mmr_flags);
4670Sstevel@tonic-gate commd_debug(dbc, "%s comm_state= %d\n", prefix, res->mmr_comm_state);
4680Sstevel@tonic-gate commd_debug(dbc, "%s exitval = %d\n", prefix, res->mmr_exitval);
4690Sstevel@tonic-gate commd_debug(dbc, "%s out_size = %d\n", prefix, res->mmr_out_size);
4700Sstevel@tonic-gate if (res->mmr_out_size)
4710Sstevel@tonic-gate commd_debug(dbc, "%s out = %s\n", prefix, res->mmr_out);
4720Sstevel@tonic-gate commd_debug(dbc, "%s err_size = %d\n", prefix, res->mmr_err_size);
4730Sstevel@tonic-gate if (res->mmr_err_size)
4740Sstevel@tonic-gate commd_debug(dbc, "%s err = %s\n", prefix, res->mmr_err);
4750Sstevel@tonic-gate }
4760Sstevel@tonic-gate
4770Sstevel@tonic-gate
4780Sstevel@tonic-gate /*
4790Sstevel@tonic-gate * Here we find out, where to store or find the results for a given msg.
4800Sstevel@tonic-gate *
4810Sstevel@tonic-gate * Per set we have a pointer to a three dimensional array:
4820Sstevel@tonic-gate * mct[set] -> mct_mce[NNODES][MD_MN_NCLASSES][MAX_SUBMESSAGES]
4830Sstevel@tonic-gate * So, for every possible node and for every possible class we can store
4840Sstevel@tonic-gate * MAX_SUBMESSAGES results.
4850Sstevel@tonic-gate * the way to find the correct index is
4860Sstevel@tonic-gate * submessage +
4870Sstevel@tonic-gate * class * MAX_SUBMESSAGES +
4880Sstevel@tonic-gate * nodeid * MAX_SUBMESSAGES * MD_MN_NCLASSES.
4890Sstevel@tonic-gate *
4900Sstevel@tonic-gate * To find the correct address the index has to be multiplied
4910Sstevel@tonic-gate * by the size of one entry.
4920Sstevel@tonic-gate */
4930Sstevel@tonic-gate static md_mn_mce_t *
mdmn_get_mce_by_msg(md_mn_msg_t * msg)4940Sstevel@tonic-gate mdmn_get_mce_by_msg(md_mn_msg_t *msg)
4950Sstevel@tonic-gate {
4960Sstevel@tonic-gate set_t setno = msg->msg_setno;
4970Sstevel@tonic-gate int nodeid = msg->msg_msgid.mid_nid;
4980Sstevel@tonic-gate int submsg = msg->msg_msgid.mid_smid;
4990Sstevel@tonic-gate int mct_index;
5000Sstevel@tonic-gate off_t mct_offset;
5010Sstevel@tonic-gate md_mn_msgclass_t class;
5020Sstevel@tonic-gate
5030Sstevel@tonic-gate if (mct[setno] != NULL) {
5040Sstevel@tonic-gate if (mdmn_init_set(setno, MDMN_SET_MCT) != 0) {
5050Sstevel@tonic-gate return ((md_mn_mce_t *)MDMN_MCT_ERROR);
5060Sstevel@tonic-gate }
5070Sstevel@tonic-gate }
5080Sstevel@tonic-gate
5090Sstevel@tonic-gate if (submsg == 0) {
5100Sstevel@tonic-gate class = mdmn_get_message_class(msg->msg_type);
5110Sstevel@tonic-gate } else {
5120Sstevel@tonic-gate class = msg->msg_msgid.mid_oclass;
5130Sstevel@tonic-gate }
5140Sstevel@tonic-gate
5158452SJohn.Wren.Kennedy@Sun.COM mct_index = submsg + class * MAX_SUBMESSAGES +
5168452SJohn.Wren.Kennedy@Sun.COM nodeid * MAX_SUBMESSAGES * MD_MN_NCLASSES;
5170Sstevel@tonic-gate
5180Sstevel@tonic-gate mct_offset = mct_index * sizeof (md_mn_mce_t);
5190Sstevel@tonic-gate
5200Sstevel@tonic-gate /* LINTED Pointer alignment */
5210Sstevel@tonic-gate return ((md_mn_mce_t *)((caddr_t)(mct[setno]) + mct_offset));
5220Sstevel@tonic-gate
5230Sstevel@tonic-gate /*
5240Sstevel@tonic-gate * the lint clean version would be:
5250Sstevel@tonic-gate * return (&(mct[setno]->mct_mce[0][0][0]) + mct_index);
5260Sstevel@tonic-gate * :-)
5270Sstevel@tonic-gate */
5280Sstevel@tonic-gate }
5290Sstevel@tonic-gate
5300Sstevel@tonic-gate /*
5310Sstevel@tonic-gate * mdmn_mark_completion(msg, result, flag)
5320Sstevel@tonic-gate * Stores the result of this message into the mmaped memory MCT[setno]
5330Sstevel@tonic-gate * In case the same message comes along a second time we will know that
5340Sstevel@tonic-gate * this message has already been processed and we can deliver the
5350Sstevel@tonic-gate * results immediately.
5360Sstevel@tonic-gate *
5370Sstevel@tonic-gate * Before a message handler is called, the message in the MCT is flagged
5380Sstevel@tonic-gate * as currently being processed (flag == MDMN_MCT_IN_PROGRESS).
5390Sstevel@tonic-gate * This we need so we don't start a second handler for the same message.
5400Sstevel@tonic-gate *
5410Sstevel@tonic-gate * After a message handler is completed, this routine is called with
5420Sstevel@tonic-gate * flag == MDMN_MCT_DONE and the appropriate result that we store in the MCT.
5430Sstevel@tonic-gate * As MCT[setno] is memory mapped to disks, this information is persistent
5440Sstevel@tonic-gate * even across a crash of the commd.
5450Sstevel@tonic-gate * It doesn't have to be persistent across a reboot, though.
5460Sstevel@tonic-gate *
5470Sstevel@tonic-gate * Returns MDMN_MCT_DONE in case of success
5480Sstevel@tonic-gate * Returns MDMN_MCT_ERROR in case of error creating the mct
5490Sstevel@tonic-gate */
5500Sstevel@tonic-gate int
mdmn_mark_completion(md_mn_msg_t * msg,md_mn_result_t * result,uint_t flag)5510Sstevel@tonic-gate mdmn_mark_completion(md_mn_msg_t *msg, md_mn_result_t *result, uint_t flag)
5520Sstevel@tonic-gate {
5530Sstevel@tonic-gate md_mn_mce_t *mce;
5540Sstevel@tonic-gate uint_t offset_in_page;
5550Sstevel@tonic-gate
5560Sstevel@tonic-gate mce = mdmn_get_mce_by_msg(msg);
5570Sstevel@tonic-gate if (mce == (md_mn_mce_t *)-1) {
5580Sstevel@tonic-gate return (MDMN_MCT_ERROR);
5590Sstevel@tonic-gate }
5600Sstevel@tonic-gate offset_in_page = (uint_t)(caddr_t)mce % sysconf(_SC_PAGESIZE);
5610Sstevel@tonic-gate
562*11053SSurya.Prakki@Sun.COM (void) memset(mce, 0, sizeof (md_mn_mce_t));
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate MSGID_COPY(&msg->msg_msgid, &mce->mce_result.mmr_msgid);
5650Sstevel@tonic-gate if (flag == MDMN_MCT_IN_PROGRESS) {
5660Sstevel@tonic-gate mce->mce_flags = MDMN_MCT_IN_PROGRESS;
5670Sstevel@tonic-gate goto mmc_out;
5680Sstevel@tonic-gate }
5690Sstevel@tonic-gate
5700Sstevel@tonic-gate /*
5710Sstevel@tonic-gate * In case the message flags indicate that the result should not be
5720Sstevel@tonic-gate * stored in the MCT, we return a MDMN_MCT_NOT_DONE,
5730Sstevel@tonic-gate * so the message will be processed at any rate,
5740Sstevel@tonic-gate * even if we process this message twice.
5750Sstevel@tonic-gate * this makes sense if the result of the message is a dynamic status
5760Sstevel@tonic-gate * and might have changed meanwhile.
5770Sstevel@tonic-gate */
5780Sstevel@tonic-gate if (msg->msg_flags & MD_MSGF_NO_MCT) {
5790Sstevel@tonic-gate return (MDMN_MCT_DONE);
5800Sstevel@tonic-gate }
5810Sstevel@tonic-gate
5820Sstevel@tonic-gate /* This msg is no longer in progress */
5830Sstevel@tonic-gate mce->mce_flags = MDMN_MCT_DONE;
5840Sstevel@tonic-gate
5850Sstevel@tonic-gate mce->mce_result.mmr_msgtype = result->mmr_msgtype;
5860Sstevel@tonic-gate mce->mce_result.mmr_setno = result->mmr_setno;
5870Sstevel@tonic-gate mce->mce_result.mmr_flags = result->mmr_flags;
5880Sstevel@tonic-gate mce->mce_result.mmr_sender = result->mmr_sender;
5890Sstevel@tonic-gate mce->mce_result.mmr_failing_node = result->mmr_failing_node;
5900Sstevel@tonic-gate mce->mce_result.mmr_comm_state = result->mmr_comm_state;
5910Sstevel@tonic-gate mce->mce_result.mmr_exitval = result->mmr_exitval;
5920Sstevel@tonic-gate
5930Sstevel@tonic-gate /* if mmr_exitval is zero, we store stdout, otherwise stderr */
5940Sstevel@tonic-gate if (result->mmr_exitval == 0) {
5950Sstevel@tonic-gate if (result->mmr_out_size > 0) {
596*11053SSurya.Prakki@Sun.COM (void) memcpy(mce->mce_data, result->mmr_out,
5970Sstevel@tonic-gate result->mmr_out_size);
5980Sstevel@tonic-gate mce->mce_result.mmr_out_size = result->mmr_out_size;
5990Sstevel@tonic-gate }
6000Sstevel@tonic-gate } else {
6010Sstevel@tonic-gate if (result->mmr_err_size > 0) {
6020Sstevel@tonic-gate mce->mce_result.mmr_err_size = result->mmr_err_size;
603*11053SSurya.Prakki@Sun.COM (void) memcpy(mce->mce_data, result->mmr_err,
6040Sstevel@tonic-gate result->mmr_err_size);
6050Sstevel@tonic-gate }
6060Sstevel@tonic-gate }
6070Sstevel@tonic-gate
6080Sstevel@tonic-gate dump_result(MD_MMV_PROC_S, "mdmn_mark_completion1", result);
6090Sstevel@tonic-gate
6100Sstevel@tonic-gate mmc_out:
6110Sstevel@tonic-gate /* now flush this entry to disk */
612*11053SSurya.Prakki@Sun.COM (void) msync((caddr_t)mce - offset_in_page,
6130Sstevel@tonic-gate sizeof (md_mn_mce_t) + offset_in_page, MS_SYNC);
6140Sstevel@tonic-gate return (MDMN_MCT_DONE);
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate
6170Sstevel@tonic-gate /*
6180Sstevel@tonic-gate * mdmn_check_completion(msg, resultp)
6190Sstevel@tonic-gate * checks if msg has already been processed on this node, and if so copies
6200Sstevel@tonic-gate * the stored result to resultp.
6210Sstevel@tonic-gate *
6220Sstevel@tonic-gate * returns MDMN_MCT_DONE and the result filled out acurately in case the
6230Sstevel@tonic-gate * msg has already been processed before
6240Sstevel@tonic-gate * returns MDMN_MCT_NOT_DONE if the message has not been processed before
6250Sstevel@tonic-gate * returns MDMN_MCT_IN_PROGRESS if the message is currently being processed
6260Sstevel@tonic-gate * This can only occur on a slave node.
6270Sstevel@tonic-gate * return MDMN_MCT_ERROR in case of error creating the mct
6280Sstevel@tonic-gate */
6290Sstevel@tonic-gate int
mdmn_check_completion(md_mn_msg_t * msg,md_mn_result_t * result)6300Sstevel@tonic-gate mdmn_check_completion(md_mn_msg_t *msg, md_mn_result_t *result)
6310Sstevel@tonic-gate {
6320Sstevel@tonic-gate md_mn_mce_t *mce;
6330Sstevel@tonic-gate size_t outsize;
6340Sstevel@tonic-gate size_t errsize;
6350Sstevel@tonic-gate
6360Sstevel@tonic-gate mce = mdmn_get_mce_by_msg(msg);
6370Sstevel@tonic-gate if (mce == (md_mn_mce_t *)MDMN_MCT_ERROR) {
6380Sstevel@tonic-gate return (MDMN_MCT_ERROR); /* what to do in that case ? */
6390Sstevel@tonic-gate }
6400Sstevel@tonic-gate if (MSGID_CMP(&(msg->msg_msgid), &(mce->mce_result.mmr_msgid))) {
6410Sstevel@tonic-gate /* is the message completed, or in progress? */
6420Sstevel@tonic-gate if (mce->mce_flags & MDMN_MCT_IN_PROGRESS) {
6430Sstevel@tonic-gate return (MDMN_MCT_IN_PROGRESS);
6440Sstevel@tonic-gate }
6450Sstevel@tonic-gate /*
6460Sstevel@tonic-gate * See comment on MD_MSGF_NO_MCT above, if this flag is set
6470Sstevel@tonic-gate * for a message no result was stored and so the message has
6480Sstevel@tonic-gate * to be processed no matter if this is the 2nd time then.
6490Sstevel@tonic-gate */
6500Sstevel@tonic-gate if (msg->msg_flags & MD_MSGF_NO_MCT) {
6510Sstevel@tonic-gate return (MDMN_MCT_NOT_DONE);
6520Sstevel@tonic-gate }
6530Sstevel@tonic-gate
6540Sstevel@tonic-gate /* Paranoia check: mce_flags must be MDMN_MCT_DONE here */
6550Sstevel@tonic-gate if ((mce->mce_flags & MDMN_MCT_DONE) == 0) {
6560Sstevel@tonic-gate commd_debug(MD_MMV_ALL,
6570Sstevel@tonic-gate "mdmn_check_completion: msg not done and not in "
6580Sstevel@tonic-gate "progress! ID = (%d, 0x%llx-%d)\n",
6590Sstevel@tonic-gate MSGID_ELEMS(msg->msg_msgid));
6600Sstevel@tonic-gate return (MDMN_MCT_NOT_DONE);
6610Sstevel@tonic-gate }
6620Sstevel@tonic-gate /*
6630Sstevel@tonic-gate * Already processed.
6640Sstevel@tonic-gate * Copy saved results data;
6650Sstevel@tonic-gate * return only a pointer to any output.
6660Sstevel@tonic-gate */
6670Sstevel@tonic-gate MSGID_COPY(&(mce->mce_result.mmr_msgid), &result->mmr_msgid);
6680Sstevel@tonic-gate result->mmr_msgtype = mce->mce_result.mmr_msgtype;
6690Sstevel@tonic-gate result->mmr_setno = mce->mce_result.mmr_setno;
6700Sstevel@tonic-gate result->mmr_flags = mce->mce_result.mmr_flags;
6710Sstevel@tonic-gate result->mmr_sender = mce->mce_result.mmr_sender;
6720Sstevel@tonic-gate result->mmr_failing_node = mce->mce_result.mmr_failing_node;
6730Sstevel@tonic-gate result->mmr_comm_state = mce->mce_result.mmr_comm_state;
6740Sstevel@tonic-gate result->mmr_exitval = mce->mce_result.mmr_exitval;
6750Sstevel@tonic-gate result->mmr_err = NULL;
6760Sstevel@tonic-gate result->mmr_out = NULL;
6770Sstevel@tonic-gate outsize = result->mmr_out_size = mce->mce_result.mmr_out_size;
6780Sstevel@tonic-gate errsize = result->mmr_err_size = mce->mce_result.mmr_err_size;
6790Sstevel@tonic-gate /*
6800Sstevel@tonic-gate * if the exit val is zero only stdout was stored (if any)
6810Sstevel@tonic-gate * otherwise only stderr was stored (if any)
6820Sstevel@tonic-gate */
6830Sstevel@tonic-gate if (result->mmr_exitval == 0) {
6840Sstevel@tonic-gate if (outsize != 0) {
6850Sstevel@tonic-gate result->mmr_out = Zalloc(outsize);
686*11053SSurya.Prakki@Sun.COM (void) memcpy(result->mmr_out, mce->mce_data,
687*11053SSurya.Prakki@Sun.COM outsize);
6880Sstevel@tonic-gate }
6890Sstevel@tonic-gate } else {
6900Sstevel@tonic-gate if (errsize != 0) {
6910Sstevel@tonic-gate result->mmr_err = Zalloc(errsize);
692*11053SSurya.Prakki@Sun.COM (void) memcpy(result->mmr_err, mce->mce_data,
693*11053SSurya.Prakki@Sun.COM errsize);
6940Sstevel@tonic-gate }
6950Sstevel@tonic-gate }
6960Sstevel@tonic-gate commd_debug(MD_MMV_MISC,
6978452SJohn.Wren.Kennedy@Sun.COM "mdmn_check_completion: msg already processed \n");
6980Sstevel@tonic-gate dump_result(MD_MMV_MISC, "mdmn_check_completion", result);
6990Sstevel@tonic-gate return (MDMN_MCT_DONE);
7000Sstevel@tonic-gate }
7010Sstevel@tonic-gate commd_debug(MD_MMV_MISC,
7028452SJohn.Wren.Kennedy@Sun.COM "mdmn_check_completion: msg not yet processed\n");
7030Sstevel@tonic-gate return (MDMN_MCT_NOT_DONE);
7040Sstevel@tonic-gate }
7050Sstevel@tonic-gate
7060Sstevel@tonic-gate
7070Sstevel@tonic-gate
7080Sstevel@tonic-gate /*
7090Sstevel@tonic-gate * check_license(rqstp, chknid)
7100Sstevel@tonic-gate *
7110Sstevel@tonic-gate * Is this RPC request sent from a licensed host?
7120Sstevel@tonic-gate *
7130Sstevel@tonic-gate * If chknid is non-zero, the caller of check_license() knows the ID of
7140Sstevel@tonic-gate * the sender. Then we check just the one entry of licensed_nodes[]
7150Sstevel@tonic-gate *
7160Sstevel@tonic-gate * If chknid is zero, the sender is not known. In that case the sender must be
7170Sstevel@tonic-gate * the local node.
7180Sstevel@tonic-gate *
7190Sstevel@tonic-gate * If the host is licensed, return TRUE, else return FALSE
7200Sstevel@tonic-gate */
7210Sstevel@tonic-gate bool_t
check_license(struct svc_req * rqstp,md_mn_nodeid_t chknid)7220Sstevel@tonic-gate check_license(struct svc_req *rqstp, md_mn_nodeid_t chknid)
7230Sstevel@tonic-gate {
7240Sstevel@tonic-gate char buf[INET6_ADDRSTRLEN];
7250Sstevel@tonic-gate void *caller = NULL;
7260Sstevel@tonic-gate in_addr_t caller_ipv4;
7270Sstevel@tonic-gate in6_addr_t caller_ipv6;
7280Sstevel@tonic-gate struct sockaddr *ca;
7290Sstevel@tonic-gate
7300Sstevel@tonic-gate
7310Sstevel@tonic-gate ca = (struct sockaddr *)(void *)svc_getrpccaller(rqstp->rq_xprt)->buf;
7320Sstevel@tonic-gate
7330Sstevel@tonic-gate if (ca->sa_family == AF_INET) {
7340Sstevel@tonic-gate caller_ipv4 =
7350Sstevel@tonic-gate ((struct sockaddr_in *)(void *)ca)->sin_addr.s_addr;
7360Sstevel@tonic-gate caller = (void *)&caller_ipv4;
7370Sstevel@tonic-gate
7380Sstevel@tonic-gate if (chknid == 0) {
7390Sstevel@tonic-gate /* check against local node */
7400Sstevel@tonic-gate if (caller_ipv4 == htonl(INADDR_LOOPBACK)) {
7410Sstevel@tonic-gate return (TRUE);
7420Sstevel@tonic-gate
7430Sstevel@tonic-gate }
7440Sstevel@tonic-gate } else {
7450Sstevel@tonic-gate /* check against one specific node */
7460Sstevel@tonic-gate if ((caller_ipv4 == licensed_nodes[chknid].lip_ipv4) &&
7470Sstevel@tonic-gate (licensed_nodes[chknid].lip_family == AF_INET)) {
7480Sstevel@tonic-gate return (TRUE);
7490Sstevel@tonic-gate } else {
7500Sstevel@tonic-gate commd_debug(MD_MMV_MISC,
7510Sstevel@tonic-gate "Bad attempt from %x ln[%d]=%x\n",
7520Sstevel@tonic-gate caller_ipv4, chknid,
7530Sstevel@tonic-gate licensed_nodes[chknid].lip_ipv4);
7540Sstevel@tonic-gate }
7550Sstevel@tonic-gate }
7560Sstevel@tonic-gate } else if (ca->sa_family == AF_INET6) {
7570Sstevel@tonic-gate caller_ipv6 = ((struct sockaddr_in6 *)(void *)ca)->sin6_addr;
7580Sstevel@tonic-gate caller = (void *)&caller_ipv6;
7590Sstevel@tonic-gate
7600Sstevel@tonic-gate if (chknid == 0) {
7610Sstevel@tonic-gate /* check against local node */
7620Sstevel@tonic-gate if (IN6_IS_ADDR_LOOPBACK(&caller_ipv6)) {
7630Sstevel@tonic-gate return (TRUE);
7640Sstevel@tonic-gate
7650Sstevel@tonic-gate }
7660Sstevel@tonic-gate } else {
7670Sstevel@tonic-gate /* check against one specific node */
7680Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(&caller_ipv6,
7690Sstevel@tonic-gate &(licensed_nodes[chknid].lip_ipv6)) &&
7700Sstevel@tonic-gate (licensed_nodes[chknid].lip_family == AF_INET6)) {
7710Sstevel@tonic-gate return (TRUE);
7720Sstevel@tonic-gate }
7730Sstevel@tonic-gate }
7740Sstevel@tonic-gate }
7750Sstevel@tonic-gate /* if we are here, we were contacted by an unlicensed node */
7760Sstevel@tonic-gate commd_debug(MD_MMV_SYSLOG,
7770Sstevel@tonic-gate "Bad attempt to contact rpc.mdcommd from %s\n",
7780Sstevel@tonic-gate caller ?
7790Sstevel@tonic-gate inet_ntop(ca->sa_family, caller, buf, INET6_ADDRSTRLEN) :
7800Sstevel@tonic-gate "unknown");
7810Sstevel@tonic-gate
7820Sstevel@tonic-gate return (FALSE);
7830Sstevel@tonic-gate }
7840Sstevel@tonic-gate
7850Sstevel@tonic-gate /*
7860Sstevel@tonic-gate * Add a node to the list of licensed nodes.
7870Sstevel@tonic-gate *
7880Sstevel@tonic-gate * Only IPv4 is currently supported.
7890Sstevel@tonic-gate * for IPv6, we need to change md_mnnode_desc.
7900Sstevel@tonic-gate */
7910Sstevel@tonic-gate void
add_license(md_mnnode_desc * node)7920Sstevel@tonic-gate add_license(md_mnnode_desc *node)
7930Sstevel@tonic-gate {
7940Sstevel@tonic-gate md_mn_nodeid_t nid = node->nd_nodeid;
7950Sstevel@tonic-gate char buf[INET6_ADDRSTRLEN];
7960Sstevel@tonic-gate
7970Sstevel@tonic-gate /*
7980Sstevel@tonic-gate * If this node is not yet licensed, do it now.
7990Sstevel@tonic-gate * For now only IPv4 addresses are supported.
8000Sstevel@tonic-gate */
8010Sstevel@tonic-gate commd_debug(MD_MMV_MISC, "add_lic(%s): ln[%d]=%s, lnc[%d]=%d\n",
8020Sstevel@tonic-gate node->nd_priv_ic, nid,
8030Sstevel@tonic-gate inet_ntop(AF_INET, (void *)&licensed_nodes[nid].lip_ipv4,
8040Sstevel@tonic-gate buf, INET6_ADDRSTRLEN), nid, licensed_nodes[nid].lip_cnt);
8050Sstevel@tonic-gate
8060Sstevel@tonic-gate if (licensed_nodes[nid].lip_ipv4 == (in_addr_t)0) {
8070Sstevel@tonic-gate licensed_nodes[nid].lip_family = AF_INET; /* IPv4 */
8080Sstevel@tonic-gate licensed_nodes[nid].lip_ipv4 = inet_addr(node->nd_priv_ic);
8090Sstevel@tonic-gate /* keep track of the last entry for faster search */
8100Sstevel@tonic-gate if (nid > maxlicnodes)
8110Sstevel@tonic-gate maxlicnodes = nid;
8120Sstevel@tonic-gate
8130Sstevel@tonic-gate }
8140Sstevel@tonic-gate /* in any case bump up the reference count */
8150Sstevel@tonic-gate licensed_nodes[nid].lip_cnt++;
8160Sstevel@tonic-gate }
8170Sstevel@tonic-gate
8180Sstevel@tonic-gate /*
8190Sstevel@tonic-gate * lower the reference count for one node.
8200Sstevel@tonic-gate * If that drops to zero, remove the node from the list of licensed nodes
8210Sstevel@tonic-gate *
8220Sstevel@tonic-gate * Only IPv4 is currently supported.
8230Sstevel@tonic-gate * for IPv6, we need to change md_mnnode_desc.
8240Sstevel@tonic-gate */
8250Sstevel@tonic-gate void
rem_license(md_mnnode_desc * node)8260Sstevel@tonic-gate rem_license(md_mnnode_desc *node)
8270Sstevel@tonic-gate {
8280Sstevel@tonic-gate md_mn_nodeid_t nid = node->nd_nodeid;
8290Sstevel@tonic-gate char buf[INET6_ADDRSTRLEN];
8300Sstevel@tonic-gate
8310Sstevel@tonic-gate commd_debug(MD_MMV_MISC, "rem_lic(%s): ln[%d]=%s, lnc[%d]=%d\n",
8320Sstevel@tonic-gate node->nd_priv_ic, nid,
8330Sstevel@tonic-gate inet_ntop(AF_INET, (void *)&licensed_nodes[nid].lip_ipv4, buf,
8340Sstevel@tonic-gate INET6_ADDRSTRLEN), nid, licensed_nodes[nid].lip_cnt);
8350Sstevel@tonic-gate
8360Sstevel@tonic-gate assert(licensed_nodes[nid].lip_cnt > 0);
8370Sstevel@tonic-gate
8380Sstevel@tonic-gate /*
8390Sstevel@tonic-gate * If this was the last reference to that node, it's license expires
8400Sstevel@tonic-gate * For now only IPv4 addresses are supported.
8410Sstevel@tonic-gate */
8420Sstevel@tonic-gate if (--licensed_nodes[nid].lip_cnt == 0) {
8430Sstevel@tonic-gate licensed_nodes[nid].lip_ipv4 = (in_addr_t)0;
8440Sstevel@tonic-gate }
8450Sstevel@tonic-gate }
846