138494Sobrien/* 2174313Sobrien * Copyright (c) 1997-2006 Erez Zadok 338494Sobrien * Copyright (c) 1990 Jan-Simon Pendry 438494Sobrien * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 538494Sobrien * Copyright (c) 1990 The Regents of the University of California. 638494Sobrien * All rights reserved. 738494Sobrien * 838494Sobrien * This code is derived from software contributed to Berkeley by 938494Sobrien * Jan-Simon Pendry at Imperial College, London. 1038494Sobrien * 1138494Sobrien * Redistribution and use in source and binary forms, with or without 1238494Sobrien * modification, are permitted provided that the following conditions 1338494Sobrien * are met: 1438494Sobrien * 1. Redistributions of source code must retain the above copyright 1538494Sobrien * notice, this list of conditions and the following disclaimer. 1638494Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1738494Sobrien * notice, this list of conditions and the following disclaimer in the 1838494Sobrien * documentation and/or other materials provided with the distribution. 1938494Sobrien * 3. All advertising materials mentioning features or use of this software 2042633Sobrien * must display the following acknowledgment: 2138494Sobrien * This product includes software developed by the University of 2238494Sobrien * California, Berkeley and its contributors. 2338494Sobrien * 4. Neither the name of the University nor the names of its contributors 2438494Sobrien * may be used to endorse or promote products derived from this software 2538494Sobrien * without specific prior written permission. 2638494Sobrien * 2738494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2838494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2938494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3038494Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3138494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3238494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3338494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3438494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3538494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3638494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3738494Sobrien * SUCH DAMAGE. 3838494Sobrien * 3938494Sobrien * 40174313Sobrien * File: am-utils/amd/amq_subr.c 4138494Sobrien * 4238494Sobrien */ 4338494Sobrien/* 4442633Sobrien * Auxiliary routines for amq tool 4538494Sobrien */ 4638494Sobrien 4738494Sobrien#ifdef HAVE_CONFIG_H 4838494Sobrien# include <config.h> 4938494Sobrien#endif /* HAVE_CONFIG_H */ 5038494Sobrien#include <am_defs.h> 5138494Sobrien#include <amd.h> 5238494Sobrien 5338494Sobrien/* forward definitions */ 5438494Sobrienbool_t xdr_amq_mount_tree_node(XDR *xdrs, amq_mount_tree *objp); 5538494Sobrienbool_t xdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp); 5638494Sobrien 5738494Sobrien 5838494Sobrienvoidp 5938494Sobrienamqproc_null_1_svc(voidp argp, struct svc_req *rqstp) 6038494Sobrien{ 6138494Sobrien static char res; 6238494Sobrien 6338494Sobrien return (voidp) &res; 6438494Sobrien} 6538494Sobrien 6638494Sobrien 6738494Sobrien/* 6838494Sobrien * Return a sub-tree of mounts 6938494Sobrien */ 7038494Sobrienamq_mount_tree_p * 7138494Sobrienamqproc_mnttree_1_svc(voidp argp, struct svc_req *rqstp) 7238494Sobrien{ 7338494Sobrien static am_node *mp; 7438494Sobrien 7538494Sobrien mp = find_ap(*(char **) argp); 76131706Smbr return (amq_mount_tree_p *) ((void *)&mp); 7738494Sobrien} 7838494Sobrien 7938494Sobrien 8038494Sobrien/* 8138494Sobrien * Unmount a single node 8238494Sobrien */ 8338494Sobrienvoidp 8438494Sobrienamqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp) 8538494Sobrien{ 8638494Sobrien static char res; 8738494Sobrien am_node *mp = find_ap(*(char **) argp); 8838494Sobrien 8938494Sobrien if (mp) 9038494Sobrien forcibly_timeout_mp(mp); 9138494Sobrien 9238494Sobrien return (voidp) &res; 9338494Sobrien} 9438494Sobrien 9538494Sobrien 9638494Sobrien/* 9738494Sobrien * Return global statistics 9838494Sobrien */ 9938494Sobrienamq_mount_stats * 10038494Sobrienamqproc_stats_1_svc(voidp argp, struct svc_req *rqstp) 10138494Sobrien{ 102131706Smbr return (amq_mount_stats *) ((void *)&amd_stats); 10338494Sobrien} 10438494Sobrien 10538494Sobrien 10638494Sobrien/* 10738494Sobrien * Return the entire tree of mount nodes 10838494Sobrien */ 10938494Sobrienamq_mount_tree_list * 11038494Sobrienamqproc_export_1_svc(voidp argp, struct svc_req *rqstp) 11138494Sobrien{ 11238494Sobrien static amq_mount_tree_list aml; 113174313Sobrien static am_node *mp; 11438494Sobrien 115174313Sobrien mp = get_exported_ap(0); 116174313Sobrien aml.amq_mount_tree_list_val = (amq_mount_tree_p *) ((void *) &mp); 11738494Sobrien aml.amq_mount_tree_list_len = 1; /* XXX */ 11838494Sobrien 11938494Sobrien return &aml; 12038494Sobrien} 12138494Sobrien 12238494Sobrien 12338494Sobrienint * 12438494Sobrienamqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp) 12538494Sobrien{ 12638494Sobrien static int rc; 12738494Sobrien amq_setopt *opt = (amq_setopt *) argp; 12838494Sobrien 12938494Sobrien rc = 0; 13038494Sobrien 13138494Sobrien switch (opt->as_opt) { 13238494Sobrien 13338494Sobrien case AMOPT_DEBUG: 13438494Sobrien if (debug_option(opt->as_str)) 13538494Sobrien rc = EINVAL; 13638494Sobrien break; 13738494Sobrien 13838494Sobrien case AMOPT_LOGFILE: 13938494Sobrien if (gopt.logfile && opt->as_str 14038494Sobrien && STREQ(gopt.logfile, opt->as_str)) { 141174313Sobrien if (switch_to_logfile(opt->as_str, orig_umask, 0)) 14238494Sobrien rc = EINVAL; 14338494Sobrien } else { 14438494Sobrien rc = EACCES; 14538494Sobrien } 14638494Sobrien break; 14738494Sobrien 14838494Sobrien case AMOPT_XLOG: 14938494Sobrien if (switch_option(opt->as_str)) 15038494Sobrien rc = EINVAL; 15138494Sobrien break; 15238494Sobrien 15338494Sobrien case AMOPT_FLUSHMAPC: 15438494Sobrien if (amd_state == Run) { 15538494Sobrien plog(XLOG_INFO, "amq says flush cache"); 15638494Sobrien do_mapc_reload = 0; 157174313Sobrien flush_nfs_fhandle_cache((fserver *) NULL); 158174313Sobrien flush_srvr_nfs_cache((fserver *) NULL); 15938494Sobrien } 16038494Sobrien break; 16138494Sobrien } 16238494Sobrien 16338494Sobrien return &rc; 16438494Sobrien} 16538494Sobrien 16638494Sobrien 16738494Sobrienamq_mount_info_list * 16838494Sobrienamqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp) 16938494Sobrien{ 170174313Sobrien return (amq_mount_info_list *) ((void *)&mfhead); /* XXX */ 17138494Sobrien} 17238494Sobrien 17338494Sobrien 17438494Sobrienamq_string * 17538494Sobrienamqproc_getvers_1_svc(voidp argp, struct svc_req *rqstp) 17638494Sobrien{ 17738494Sobrien static amq_string res; 17838494Sobrien 17938494Sobrien res = get_version_string(); 18038494Sobrien return &res; 18138494Sobrien} 18238494Sobrien 18338494Sobrien 18438494Sobrien/* get PID of remote amd */ 18538494Sobrienint * 18638494Sobrienamqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp) 18738494Sobrien{ 18838494Sobrien static int res; 18938494Sobrien 19038494Sobrien res = getpid(); 19138494Sobrien return &res; 19238494Sobrien} 19338494Sobrien 19438494Sobrien 19538494Sobrien/* 196174313Sobrien * Process PAWD string of remote pawd tool. 197174313Sobrien * 198174313Sobrien * We repeat the resolution of the string until the resolved string resolves 199174313Sobrien * to itself. This ensures that we follow path resolutions through all 200174313Sobrien * possible Amd mount points until we reach some sort of convergence. To 201174313Sobrien * prevent possible infinite loops, we break out of this loop if the strings 202174313Sobrien * do not converge after MAX_PAWD_TRIES times. 203174313Sobrien */ 204174313Sobrienamq_string * 205174313Sobrienamqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp) 206174313Sobrien{ 207174313Sobrien static amq_string res; 208174313Sobrien#define MAX_PAWD_TRIES 10 209174313Sobrien int index, len, maxagain = MAX_PAWD_TRIES; 210174313Sobrien am_node *mp; 211174313Sobrien char *mountpoint; 212174313Sobrien char *dir = *(char **) argp; 213174313Sobrien static char tmp_buf[MAXPATHLEN]; 214174313Sobrien char prev_buf[MAXPATHLEN]; 215174313Sobrien 216174313Sobrien tmp_buf[0] = prev_buf[0] = '\0'; /* default is empty string: no match */ 217174313Sobrien do { 218174313Sobrien for (mp = get_first_exported_ap(&index); 219174313Sobrien mp; 220174313Sobrien mp = get_next_exported_ap(&index)) { 221174313Sobrien if (STREQ(mp->am_mnt->mf_ops->fs_type, "toplvl")) 222174313Sobrien continue; 223174313Sobrien if (STREQ(mp->am_mnt->mf_ops->fs_type, "auto")) 224174313Sobrien continue; 225174313Sobrien mountpoint = (mp->am_link ? mp->am_link : mp->am_mnt->mf_mount); 226174313Sobrien len = strlen(mountpoint); 227174313Sobrien if (len == 0) 228174313Sobrien continue; 229174313Sobrien if (!NSTREQ(mountpoint, dir, len)) 230174313Sobrien continue; 231174313Sobrien if (dir[len] != '\0' && dir[len] != '/') 232174313Sobrien continue; 233174313Sobrien xstrlcpy(tmp_buf, mp->am_path, sizeof(tmp_buf)); 234174313Sobrien xstrlcat(tmp_buf, &dir[len], sizeof(tmp_buf)); 235174313Sobrien break; 236174313Sobrien } /* end of "for" loop */ 237174313Sobrien /* once tmp_buf and prev_buf are equal, break out of "do" loop */ 238174313Sobrien if (STREQ(tmp_buf, prev_buf)) 239174313Sobrien break; 240174313Sobrien else 241174313Sobrien xstrlcpy(prev_buf, tmp_buf, sizeof(prev_buf)); 242174313Sobrien } while (--maxagain); 243174313Sobrien /* check if we couldn't resolve the string after MAX_PAWD_TRIES times */ 244174313Sobrien if (maxagain <= 0) 245174313Sobrien plog(XLOG_WARNING, "path \"%s\" did not resolve after %d tries", 246174313Sobrien tmp_buf, MAX_PAWD_TRIES); 247174313Sobrien 248174313Sobrien res = tmp_buf; 249174313Sobrien return &res; 250174313Sobrien} 251174313Sobrien 252174313Sobrien 253174313Sobrien/* 25438494Sobrien * XDR routines. 25538494Sobrien */ 25638494Sobrien 25738494Sobrien 25838494Sobrienbool_t 25938494Sobrienxdr_amq_setopt(XDR *xdrs, amq_setopt *objp) 26038494Sobrien{ 261174313Sobrien if (!xdr_enum(xdrs, (enum_t *) ((voidp) &objp->as_opt))) { 26238494Sobrien return (FALSE); 26338494Sobrien } 26438494Sobrien if (!xdr_string(xdrs, &objp->as_str, AMQ_STRLEN)) { 26538494Sobrien return (FALSE); 26638494Sobrien } 26738494Sobrien return (TRUE); 26838494Sobrien} 26938494Sobrien 27038494Sobrien 27138494Sobrien/* 27238494Sobrien * More XDR routines - Should be used for OUTPUT ONLY. 27338494Sobrien */ 27438494Sobrienbool_t 27538494Sobrienxdr_amq_mount_tree_node(XDR *xdrs, amq_mount_tree *objp) 27638494Sobrien{ 27738494Sobrien am_node *mp = (am_node *) objp; 27838790Sobrien long mtime; 27938494Sobrien 28038494Sobrien if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_info)) { 28138494Sobrien return (FALSE); 28238494Sobrien } 28338494Sobrien if (!xdr_amq_string(xdrs, &mp->am_path)) { 28438494Sobrien return (FALSE); 28538494Sobrien } 28638494Sobrien if (!xdr_amq_string(xdrs, mp->am_link ? &mp->am_link : &mp->am_mnt->mf_mount)) { 28738494Sobrien return (FALSE); 28838494Sobrien } 28938494Sobrien if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_ops->fs_type)) { 29038494Sobrien return (FALSE); 29138494Sobrien } 29238790Sobrien mtime = mp->am_stats.s_mtime; 29338790Sobrien if (!xdr_long(xdrs, &mtime)) { 29438494Sobrien return (FALSE); 29538494Sobrien } 29638494Sobrien if (!xdr_u_short(xdrs, &mp->am_stats.s_uid)) { 29738494Sobrien return (FALSE); 29838494Sobrien } 29938494Sobrien if (!xdr_int(xdrs, &mp->am_stats.s_getattr)) { 30038494Sobrien return (FALSE); 30138494Sobrien } 30238494Sobrien if (!xdr_int(xdrs, &mp->am_stats.s_lookup)) { 30338494Sobrien return (FALSE); 30438494Sobrien } 30538494Sobrien if (!xdr_int(xdrs, &mp->am_stats.s_readdir)) { 30638494Sobrien return (FALSE); 30738494Sobrien } 30838494Sobrien if (!xdr_int(xdrs, &mp->am_stats.s_readlink)) { 30938494Sobrien return (FALSE); 31038494Sobrien } 31138494Sobrien if (!xdr_int(xdrs, &mp->am_stats.s_statfs)) { 31238494Sobrien return (FALSE); 31338494Sobrien } 31438494Sobrien return (TRUE); 31538494Sobrien} 31638494Sobrien 31738494Sobrien 31838494Sobrienbool_t 31938494Sobrienxdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp) 32038494Sobrien{ 32138494Sobrien am_node *mp = (am_node *) objp; 32238494Sobrien 32338494Sobrien if (!xdr_amq_mount_tree_node(xdrs, objp)) { 32438494Sobrien return (FALSE); 32538494Sobrien } 326174313Sobrien if (!xdr_pointer(xdrs, 327174313Sobrien (char **) ((voidp) &mp->am_osib), 328174313Sobrien sizeof(amq_mount_tree), 329174313Sobrien (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { 33038494Sobrien return (FALSE); 33138494Sobrien } 332174313Sobrien if (!xdr_pointer(xdrs, 333174313Sobrien (char **) ((voidp) &mp->am_child), 334174313Sobrien sizeof(amq_mount_tree), 335174313Sobrien (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { 33638494Sobrien return (FALSE); 33738494Sobrien } 33838494Sobrien return (TRUE); 33938494Sobrien} 34038494Sobrien 34138494Sobrien 34238494Sobrienbool_t 34338494Sobrienxdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp) 34438494Sobrien{ 34538494Sobrien am_node *mp = (am_node *) objp; 346174313Sobrien am_node *mnil = NULL; 34738494Sobrien 34838494Sobrien if (!xdr_amq_mount_tree_node(xdrs, objp)) { 34938494Sobrien return (FALSE); 35038494Sobrien } 351174313Sobrien if (!xdr_pointer(xdrs, 352174313Sobrien (char **) ((voidp) &mnil), 353174313Sobrien sizeof(amq_mount_tree), 354174313Sobrien (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { 35538494Sobrien return (FALSE); 35638494Sobrien } 357174313Sobrien if (!xdr_pointer(xdrs, 358174313Sobrien (char **) ((voidp) &mp->am_child), 359174313Sobrien sizeof(amq_mount_tree), 360174313Sobrien (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { 36138494Sobrien return (FALSE); 36238494Sobrien } 36338494Sobrien return (TRUE); 36438494Sobrien} 36538494Sobrien 36638494Sobrien 36738494Sobrienbool_t 36838494Sobrienxdr_amq_mount_tree_p(XDR *xdrs, amq_mount_tree_p *objp) 36938494Sobrien{ 37038494Sobrien if (!xdr_pointer(xdrs, (char **) objp, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) { 37138494Sobrien return (FALSE); 37238494Sobrien } 37338494Sobrien return (TRUE); 37438494Sobrien} 37538494Sobrien 37638494Sobrien 37738494Sobrienbool_t 37838494Sobrienxdr_amq_mount_stats(XDR *xdrs, amq_mount_stats *objp) 37938494Sobrien{ 38038494Sobrien if (!xdr_int(xdrs, &objp->as_drops)) { 38138494Sobrien return (FALSE); 38238494Sobrien } 38338494Sobrien if (!xdr_int(xdrs, &objp->as_stale)) { 38438494Sobrien return (FALSE); 38538494Sobrien } 38638494Sobrien if (!xdr_int(xdrs, &objp->as_mok)) { 38738494Sobrien return (FALSE); 38838494Sobrien } 38938494Sobrien if (!xdr_int(xdrs, &objp->as_merr)) { 39038494Sobrien return (FALSE); 39138494Sobrien } 39238494Sobrien if (!xdr_int(xdrs, &objp->as_uerr)) { 39338494Sobrien return (FALSE); 39438494Sobrien } 39538494Sobrien return (TRUE); 39638494Sobrien} 39738494Sobrien 39838494Sobrien 39938494Sobrien 40038494Sobrienbool_t 40138494Sobrienxdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp) 40238494Sobrien{ 40338494Sobrien if (!xdr_array(xdrs, 404174313Sobrien (char **) ((voidp) &objp->amq_mount_tree_list_val), 40538494Sobrien (u_int *) &objp->amq_mount_tree_list_len, 40638494Sobrien ~0, 40738494Sobrien sizeof(amq_mount_tree_p), 40838494Sobrien (XDRPROC_T_TYPE) xdr_amq_mount_tree_p)) { 40938494Sobrien return (FALSE); 41038494Sobrien } 41138494Sobrien return (TRUE); 41238494Sobrien} 41338494Sobrien 41438494Sobrien 41538494Sobrien 41638494Sobrien/* 41738494Sobrien * Compute length of list 41838494Sobrien */ 41938494Sobrienbool_t 42038494Sobrienxdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead) 42138494Sobrien{ 42238494Sobrien mntfs *mf; 42338494Sobrien u_int len = 0; 42438494Sobrien 42538494Sobrien for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) { 426174313Sobrien if (!(mf->mf_fsflags & FS_AMQINFO)) 42738494Sobrien continue; 42838494Sobrien len++; 42938494Sobrien } 43038494Sobrien xdr_u_int(xdrs, &len); 43138494Sobrien 43238494Sobrien /* 43338494Sobrien * Send individual data items 43438494Sobrien */ 43538494Sobrien for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) { 43638494Sobrien int up; 437174313Sobrien if (!(mf->mf_fsflags & FS_AMQINFO)) 43838494Sobrien continue; 43938494Sobrien 44038494Sobrien if (!xdr_amq_string(xdrs, &mf->mf_ops->fs_type)) { 44138494Sobrien return (FALSE); 44238494Sobrien } 44338494Sobrien if (!xdr_amq_string(xdrs, &mf->mf_mount)) { 44438494Sobrien return (FALSE); 44538494Sobrien } 44638494Sobrien if (!xdr_amq_string(xdrs, &mf->mf_info)) { 44738494Sobrien return (FALSE); 44838494Sobrien } 44938494Sobrien if (!xdr_amq_string(xdrs, &mf->mf_server->fs_host)) { 45038494Sobrien return (FALSE); 45138494Sobrien } 45238494Sobrien if (!xdr_int(xdrs, &mf->mf_error)) { 45338494Sobrien return (FALSE); 45438494Sobrien } 45538494Sobrien if (!xdr_int(xdrs, &mf->mf_refc)) { 45638494Sobrien return (FALSE); 45738494Sobrien } 458174313Sobrien if (FSRV_ERROR(mf->mf_server) || FSRV_ISDOWN(mf->mf_server)) 45938494Sobrien up = 0; 460174313Sobrien else if (FSRV_ISUP(mf->mf_server)) 461174313Sobrien up = 1; 46238494Sobrien else 463174313Sobrien up = -1; 46438494Sobrien if (!xdr_int(xdrs, &up)) { 46538494Sobrien return (FALSE); 46638494Sobrien } 46738494Sobrien } 46838494Sobrien return (TRUE); 46938494Sobrien} 47038494Sobrien 47138494Sobrien 47238494Sobrienbool_t 47338494Sobrienxdr_pri_free(XDRPROC_T_TYPE xdr_args, caddr_t args_ptr) 47438494Sobrien{ 47538494Sobrien XDR xdr; 47638494Sobrien 47738494Sobrien xdr.x_op = XDR_FREE; 47838494Sobrien return ((*xdr_args) (&xdr, (caddr_t *) args_ptr)); 47938494Sobrien} 480