amq_subr.c revision 1.1
1/* $NetBSD: amq_subr.c,v 1.1 2008/09/19 20:07:15 christos Exp $ */ 2 3/* 4 * Copyright (c) 1997-2007 Erez Zadok 5 * Copyright (c) 1990 Jan-Simon Pendry 6 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 7 * Copyright (c) 1990 The Regents of the University of California. 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to Berkeley by 11 * Jan-Simon Pendry at Imperial College, London. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgment: 23 * This product includes software developed by the University of 24 * California, Berkeley and its contributors. 25 * 4. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * 42 * File: am-utils/amd/amq_subr.c 43 * 44 */ 45/* 46 * Auxiliary routines for amq tool 47 */ 48 49#ifdef HAVE_CONFIG_H 50# include <config.h> 51#endif /* HAVE_CONFIG_H */ 52#include <am_defs.h> 53#include <amd.h> 54 55/* forward definitions */ 56bool_t xdr_amq_mount_tree_node(XDR *xdrs, amq_mount_tree *objp); 57bool_t xdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp); 58 59 60voidp 61amqproc_null_1_svc(voidp argp, struct svc_req *rqstp) 62{ 63 static char res; 64 65 return (voidp) &res; 66} 67 68 69/* 70 * Return a sub-tree of mounts 71 */ 72amq_mount_tree_p * 73amqproc_mnttree_1_svc(voidp argp, struct svc_req *rqstp) 74{ 75 static am_node *mp; 76 77 mp = find_ap(*(char **) argp); 78 return (amq_mount_tree_p *) ((void *)&mp); 79} 80 81 82/* 83 * Unmount a single node 84 */ 85voidp 86amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp) 87{ 88 static char res; 89 am_node *mp = find_ap(*(char **) argp); 90 91 if (mp) 92 forcibly_timeout_mp(mp); 93 94 return (voidp) &res; 95} 96 97 98/* 99 * Return global statistics 100 */ 101amq_mount_stats * 102amqproc_stats_1_svc(voidp argp, struct svc_req *rqstp) 103{ 104 return (amq_mount_stats *) ((void *)&amd_stats); 105} 106 107 108/* 109 * Return the entire tree of mount nodes 110 */ 111amq_mount_tree_list * 112amqproc_export_1_svc(voidp argp, struct svc_req *rqstp) 113{ 114 static amq_mount_tree_list aml; 115 static am_node *mp; 116 117 mp = get_exported_ap(0); 118 aml.amq_mount_tree_list_val = (amq_mount_tree_p *) ((void *) &mp); 119 aml.amq_mount_tree_list_len = 1; /* XXX */ 120 121 return &aml; 122} 123 124 125int * 126amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp) 127{ 128 static int rc; 129 amq_setopt *opt = (amq_setopt *) argp; 130 131 rc = 0; 132 133 switch (opt->as_opt) { 134 135 case AMOPT_DEBUG: 136 if (debug_option(opt->as_str)) 137 rc = EINVAL; 138 break; 139 140 case AMOPT_LOGFILE: 141 if (gopt.logfile && opt->as_str 142 && STREQ(gopt.logfile, opt->as_str)) { 143 if (switch_to_logfile(opt->as_str, orig_umask, 0)) 144 rc = EINVAL; 145 } else { 146 rc = EACCES; 147 } 148 break; 149 150 case AMOPT_XLOG: 151 if (switch_option(opt->as_str)) 152 rc = EINVAL; 153 break; 154 155 case AMOPT_FLUSHMAPC: 156 if (amd_state == Run) { 157 plog(XLOG_INFO, "amq says flush cache"); 158 do_mapc_reload = 0; 159 flush_nfs_fhandle_cache((fserver *) NULL); 160 flush_srvr_nfs_cache((fserver *) NULL); 161 } 162 break; 163 } 164 165 return &rc; 166} 167 168 169amq_mount_info_list * 170amqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp) 171{ 172 return (amq_mount_info_list *) ((void *)&mfhead); /* XXX */ 173} 174 175 176amq_string * 177amqproc_getvers_1_svc(voidp argp, struct svc_req *rqstp) 178{ 179 static amq_string res; 180 181 res = get_version_string(); 182 return &res; 183} 184 185 186/* get PID of remote amd */ 187int * 188amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp) 189{ 190 static int res; 191 192 res = getpid(); 193 return &res; 194} 195 196 197/* 198 * Process PAWD string of remote pawd tool. 199 * 200 * We repeat the resolution of the string until the resolved string resolves 201 * to itself. This ensures that we follow path resolutions through all 202 * possible Amd mount points until we reach some sort of convergence. To 203 * prevent possible infinite loops, we break out of this loop if the strings 204 * do not converge after MAX_PAWD_TRIES times. 205 */ 206amq_string * 207amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp) 208{ 209 static amq_string res; 210#define MAX_PAWD_TRIES 10 211 int index, len, maxagain = MAX_PAWD_TRIES; 212 am_node *mp; 213 char *mountpoint; 214 char *dir = *(char **) argp; 215 static char tmp_buf[MAXPATHLEN]; 216 char prev_buf[MAXPATHLEN]; 217 218 tmp_buf[0] = prev_buf[0] = '\0'; /* default is empty string: no match */ 219 do { 220 for (mp = get_first_exported_ap(&index); 221 mp; 222 mp = get_next_exported_ap(&index)) { 223 if (STREQ(mp->am_mnt->mf_ops->fs_type, "toplvl")) 224 continue; 225 if (STREQ(mp->am_mnt->mf_ops->fs_type, "auto")) 226 continue; 227 mountpoint = (mp->am_link ? mp->am_link : mp->am_mnt->mf_mount); 228 len = strlen(mountpoint); 229 if (len == 0) 230 continue; 231 if (!NSTREQ(mountpoint, dir, len)) 232 continue; 233 if (dir[len] != '\0' && dir[len] != '/') 234 continue; 235 xstrlcpy(tmp_buf, mp->am_path, sizeof(tmp_buf)); 236 xstrlcat(tmp_buf, &dir[len], sizeof(tmp_buf)); 237 break; 238 } /* end of "for" loop */ 239 /* once tmp_buf and prev_buf are equal, break out of "do" loop */ 240 if (STREQ(tmp_buf, prev_buf)) 241 break; 242 else 243 xstrlcpy(prev_buf, tmp_buf, sizeof(prev_buf)); 244 } while (--maxagain); 245 /* check if we couldn't resolve the string after MAX_PAWD_TRIES times */ 246 if (maxagain <= 0) 247 plog(XLOG_WARNING, "path \"%s\" did not resolve after %d tries", 248 tmp_buf, MAX_PAWD_TRIES); 249 250 res = tmp_buf; 251 return &res; 252} 253 254 255/* 256 * XDR routines. 257 */ 258 259 260bool_t 261xdr_amq_setopt(XDR *xdrs, amq_setopt *objp) 262{ 263 if (!xdr_enum(xdrs, (enum_t *) ((voidp) &objp->as_opt))) { 264 return (FALSE); 265 } 266 if (!xdr_string(xdrs, &objp->as_str, AMQ_STRLEN)) { 267 return (FALSE); 268 } 269 return (TRUE); 270} 271 272 273/* 274 * More XDR routines - Should be used for OUTPUT ONLY. 275 */ 276bool_t 277xdr_amq_mount_tree_node(XDR *xdrs, amq_mount_tree *objp) 278{ 279 am_node *mp = (am_node *) objp; 280 long mtime; 281 282 if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_info)) { 283 return (FALSE); 284 } 285 if (!xdr_amq_string(xdrs, &mp->am_path)) { 286 return (FALSE); 287 } 288 if (!xdr_amq_string(xdrs, mp->am_link ? &mp->am_link : &mp->am_mnt->mf_mount)) { 289 return (FALSE); 290 } 291 if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_ops->fs_type)) { 292 return (FALSE); 293 } 294 mtime = mp->am_stats.s_mtime; 295 if (!xdr_long(xdrs, &mtime)) { 296 return (FALSE); 297 } 298 if (!xdr_u_short(xdrs, &mp->am_stats.s_uid)) { 299 return (FALSE); 300 } 301 if (!xdr_int(xdrs, &mp->am_stats.s_getattr)) { 302 return (FALSE); 303 } 304 if (!xdr_int(xdrs, &mp->am_stats.s_lookup)) { 305 return (FALSE); 306 } 307 if (!xdr_int(xdrs, &mp->am_stats.s_readdir)) { 308 return (FALSE); 309 } 310 if (!xdr_int(xdrs, &mp->am_stats.s_readlink)) { 311 return (FALSE); 312 } 313 if (!xdr_int(xdrs, &mp->am_stats.s_statfs)) { 314 return (FALSE); 315 } 316 return (TRUE); 317} 318 319 320bool_t 321xdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp) 322{ 323 am_node *mp = (am_node *) objp; 324 325 if (!xdr_amq_mount_tree_node(xdrs, objp)) { 326 return (FALSE); 327 } 328 if (!xdr_pointer(xdrs, 329 (char **) ((voidp) &mp->am_osib), 330 sizeof(amq_mount_tree), 331 (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { 332 return (FALSE); 333 } 334 if (!xdr_pointer(xdrs, 335 (char **) ((voidp) &mp->am_child), 336 sizeof(amq_mount_tree), 337 (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { 338 return (FALSE); 339 } 340 return (TRUE); 341} 342 343 344bool_t 345xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp) 346{ 347 am_node *mp = (am_node *) objp; 348 am_node *mnil = NULL; 349 350 if (!xdr_amq_mount_tree_node(xdrs, objp)) { 351 return (FALSE); 352 } 353 if (!xdr_pointer(xdrs, 354 (char **) ((voidp) &mnil), 355 sizeof(amq_mount_tree), 356 (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { 357 return (FALSE); 358 } 359 if (!xdr_pointer(xdrs, 360 (char **) ((voidp) &mp->am_child), 361 sizeof(amq_mount_tree), 362 (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { 363 return (FALSE); 364 } 365 return (TRUE); 366} 367 368 369bool_t 370xdr_amq_mount_tree_p(XDR *xdrs, amq_mount_tree_p *objp) 371{ 372 if (!xdr_pointer(xdrs, (char **) objp, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) { 373 return (FALSE); 374 } 375 return (TRUE); 376} 377 378 379bool_t 380xdr_amq_mount_stats(XDR *xdrs, amq_mount_stats *objp) 381{ 382 if (!xdr_int(xdrs, &objp->as_drops)) { 383 return (FALSE); 384 } 385 if (!xdr_int(xdrs, &objp->as_stale)) { 386 return (FALSE); 387 } 388 if (!xdr_int(xdrs, &objp->as_mok)) { 389 return (FALSE); 390 } 391 if (!xdr_int(xdrs, &objp->as_merr)) { 392 return (FALSE); 393 } 394 if (!xdr_int(xdrs, &objp->as_uerr)) { 395 return (FALSE); 396 } 397 return (TRUE); 398} 399 400 401 402bool_t 403xdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp) 404{ 405 if (!xdr_array(xdrs, 406 (char **) ((voidp) &objp->amq_mount_tree_list_val), 407 (u_int *) &objp->amq_mount_tree_list_len, 408 ~0, 409 sizeof(amq_mount_tree_p), 410 (XDRPROC_T_TYPE) xdr_amq_mount_tree_p)) { 411 return (FALSE); 412 } 413 return (TRUE); 414} 415 416 417 418/* 419 * Compute length of list 420 */ 421bool_t 422xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead) 423{ 424 mntfs *mf; 425 u_int len = 0; 426 427 for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) { 428 if (!(mf->mf_fsflags & FS_AMQINFO)) 429 continue; 430 len++; 431 } 432 xdr_u_int(xdrs, &len); 433 434 /* 435 * Send individual data items 436 */ 437 for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) { 438 int up; 439 if (!(mf->mf_fsflags & FS_AMQINFO)) 440 continue; 441 442 if (!xdr_amq_string(xdrs, &mf->mf_ops->fs_type)) { 443 return (FALSE); 444 } 445 if (!xdr_amq_string(xdrs, &mf->mf_mount)) { 446 return (FALSE); 447 } 448 if (!xdr_amq_string(xdrs, &mf->mf_info)) { 449 return (FALSE); 450 } 451 if (!xdr_amq_string(xdrs, &mf->mf_server->fs_host)) { 452 return (FALSE); 453 } 454 if (!xdr_int(xdrs, &mf->mf_error)) { 455 return (FALSE); 456 } 457 if (!xdr_int(xdrs, &mf->mf_refc)) { 458 return (FALSE); 459 } 460 if (FSRV_ERROR(mf->mf_server) || FSRV_ISDOWN(mf->mf_server)) 461 up = 0; 462 else if (FSRV_ISUP(mf->mf_server)) 463 up = 1; 464 else 465 up = -1; 466 if (!xdr_int(xdrs, &up)) { 467 return (FALSE); 468 } 469 } 470 return (TRUE); 471} 472 473 474bool_t 475xdr_pri_free(XDRPROC_T_TYPE xdr_args, caddr_t args_ptr) 476{ 477 XDR xdr; 478 479 xdr.x_op = XDR_FREE; 480 return ((*xdr_args) (&xdr, (caddr_t *) args_ptr)); 481} 482