1/* $NetBSD: amq_subr.c,v 1.5 2022/08/24 05:01:13 christos Exp $ */ 2 3/* 4 * Copyright (c) 1997-2014 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. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * 38 * File: am-utils/amd/amq_subr.c 39 * 40 */ 41/* 42 * Auxiliary routines for amq tool 43 */ 44 45#ifdef HAVE_CONFIG_H 46# include <config.h> 47#endif /* HAVE_CONFIG_H */ 48#include <am_defs.h> 49#include <amd.h> 50 51/* forward definitions */ 52bool_t xdr_amq_mount_tree_node(XDR *xdrs, amq_mount_tree *objp); 53bool_t xdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp); 54 55 56voidp 57amqproc_null_1_svc(voidp argp, struct svc_req *rqstp) 58{ 59 static char res; 60 61 return (voidp) &res; 62} 63 64 65/* 66 * Return a sub-tree of mounts 67 */ 68amq_mount_tree_p * 69amqproc_mnttree_1_svc(voidp argp, struct svc_req *rqstp) 70{ 71 static am_node *mp; 72 73 mp = find_ap(*(char **) argp); 74 return (amq_mount_tree_p *) ((void *)&mp); 75} 76 77 78/* 79 * Unmount a single node 80 */ 81int * 82amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp) 83{ 84 static int res = AMQ_UMNT_OK; 85 am_node *mp = find_ap(*(char **) argp); 86 87 if (mp) 88 forcibly_timeout_mp(mp); 89 90 return &res; 91} 92 93 94/* 95 * Synchronously unmount a single node - parent side. 96 */ 97int * 98amqproc_sync_umnt_1_svc_parent(voidp argp, struct svc_req *rqstp) 99{ 100 amqproc_umnt_1_svc(argp, rqstp); 101 return NULL; 102} 103 104 105/* 106 * Synchronously unmount a single node - child side. 107 */ 108amq_sync_umnt * 109amqproc_sync_umnt_1_svc_child(voidp argp, struct svc_req *rqstp) 110{ 111 static amq_sync_umnt rv; 112 amq_sync_umnt buf; 113 ssize_t n; 114 115 am_node *mp = find_ap(*(char **) argp); 116 117 memset(&rv, 0, sizeof(rv)); 118 rv.au_etype = AMQ_UMNT_READ; 119 if (mp && mp->am_fd[0] >= 0) { 120 n = read(mp->am_fd[0], &buf, sizeof(buf)); 121 if (n == sizeof(buf)) 122 rv = buf; 123 } 124 return &rv; 125} 126 127 128/* 129 * Synchronously unmount a single node - use if we can't fork (asynchronous). 130 */ 131amq_sync_umnt * 132amqproc_sync_umnt_1_svc_async(voidp argp, struct svc_req *rqstp) 133{ 134 static amq_sync_umnt rv; 135 136 memset(&rv, 0, sizeof(rv)); 137 rv.au_etype = AMQ_UMNT_FORK; 138 rv.au_errno = errno; 139 140 amqproc_umnt_1_svc(argp, rqstp); 141 142 return &rv; 143} 144 145 146/* 147 * Return global statistics 148 */ 149amq_mount_stats * 150amqproc_stats_1_svc(voidp argp, struct svc_req *rqstp) 151{ 152 return (amq_mount_stats *) ((void *)&amd_stats); 153} 154 155 156/* 157 * Return the entire tree of mount nodes 158 */ 159amq_mount_tree_list * 160amqproc_export_1_svc(voidp argp, struct svc_req *rqstp) 161{ 162 static amq_mount_tree_list aml; 163 static am_node *mp; 164 165 mp = get_exported_ap(0); 166 aml.amq_mount_tree_list_val = (amq_mount_tree_p *) ((void *) &mp); 167 aml.amq_mount_tree_list_len = 1; /* XXX */ 168 169 return &aml; 170} 171 172 173int * 174amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp) 175{ 176 static int rc; 177 amq_setopt *opt = (amq_setopt *) argp; 178 179 rc = 0; 180 181 switch (opt->as_opt) { 182 183 case AMOPT_DEBUG: 184 if (debug_option(opt->as_str)) 185 rc = EINVAL; 186 break; 187 188 case AMOPT_LOGFILE: 189 if (gopt.logfile && opt->as_str 190 && STREQ(gopt.logfile, opt->as_str)) { 191 if (switch_to_logfile(opt->as_str, orig_umask, 0)) 192 rc = EINVAL; 193 } else { 194 rc = EACCES; 195 } 196 break; 197 198 case AMOPT_XLOG: 199 if (switch_option(opt->as_str)) 200 rc = EINVAL; 201 break; 202 203 case AMOPT_FLUSHMAPC: 204 if (amd_state == Run) { 205 plog(XLOG_INFO, "amq says flush cache"); 206 do_mapc_reload = 0; 207 flush_nfs_fhandle_cache((fserver *) NULL); 208 flush_srvr_nfs_cache((fserver *) NULL); 209 } 210 break; 211 } 212 213 return &rc; 214} 215 216 217amq_mount_info_list * 218amqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp) 219{ 220 return (amq_mount_info_list *) ((void *)&mfhead); /* XXX */ 221} 222 223extern qelem map_list_head; 224amq_map_info_list * 225amqproc_getmapinfo_1_svc(voidp argp, struct svc_req *rqstp) 226{ 227 return (amq_map_info_list *) ((void *)&map_list_head); /* XXX */ 228} 229 230amq_string * 231amqproc_getvers_1_svc(voidp argp, struct svc_req *rqstp) 232{ 233 static amq_string res; 234 235 res = get_version_string(); 236 return &res; 237} 238 239 240/* get PID of remote amd */ 241int * 242amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp) 243{ 244 static int res; 245 246 res = getpid(); 247 return &res; 248} 249 250 251/* 252 * Process PAWD string of remote pawd tool. 253 * 254 * We repeat the resolution of the string until the resolved string resolves 255 * to itself. This ensures that we follow path resolutions through all 256 * possible Amd mount points until we reach some sort of convergence. To 257 * prevent possible infinite loops, we break out of this loop if the strings 258 * do not converge after MAX_PAWD_TRIES times. 259 */ 260amq_string * 261amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp) 262{ 263 static amq_string res; 264#define MAX_PAWD_TRIES 10 265 int index, len, maxagain = MAX_PAWD_TRIES; 266 am_node *mp; 267 char *mountpoint; 268 char *dir = *(char **) argp; 269 static char tmp_buf[MAXPATHLEN]; 270 char prev_buf[MAXPATHLEN]; 271 272 tmp_buf[0] = prev_buf[0] = '\0'; /* default is empty string: no match */ 273 do { 274 for (mp = get_first_exported_ap(&index); 275 mp; 276 mp = get_next_exported_ap(&index)) { 277 if (STREQ(mp->am_al->al_mnt->mf_ops->fs_type, "toplvl")) 278 continue; 279 if (STREQ(mp->am_al->al_mnt->mf_ops->fs_type, "auto")) 280 continue; 281 mountpoint = (mp->am_link ? mp->am_link : mp->am_al->al_mnt->mf_mount); 282 len = strlen(mountpoint); 283 if (len == 0) 284 continue; 285 if (!NSTREQ(mountpoint, dir, len)) 286 continue; 287 if (dir[len] != '\0' && dir[len] != '/') 288 continue; 289 xstrlcpy(tmp_buf, mp->am_path, sizeof(tmp_buf)); 290 xstrlcat(tmp_buf, &dir[len], sizeof(tmp_buf)); 291 break; 292 } /* end of "for" loop */ 293 /* once tmp_buf and prev_buf are equal, break out of "do" loop */ 294 if (STREQ(tmp_buf, prev_buf)) 295 break; 296 else 297 xstrlcpy(prev_buf, tmp_buf, sizeof(prev_buf)); 298 } while (--maxagain); 299 /* check if we couldn't resolve the string after MAX_PAWD_TRIES times */ 300 if (maxagain <= 0) 301 plog(XLOG_WARNING, "path \"%s\" did not resolve after %d tries", 302 tmp_buf, MAX_PAWD_TRIES); 303 304 res = tmp_buf; 305 return &res; 306} 307 308 309/* 310 * XDR routines. 311 */ 312 313 314bool_t 315xdr_amq_setopt(XDR *xdrs, amq_setopt *objp) 316{ 317 if (!xdr_enum(xdrs, (enum_t *) ((voidp) &objp->as_opt))) { 318 return (FALSE); 319 } 320 if (!xdr_string(xdrs, &objp->as_str, AMQ_STRLEN)) { 321 return (FALSE); 322 } 323 return (TRUE); 324} 325 326 327/* 328 * More XDR routines - Should be used for OUTPUT ONLY. 329 */ 330bool_t 331xdr_amq_mount_tree_node(XDR *xdrs, amq_mount_tree *objp) 332{ 333 am_node *mp = (am_node *) objp; 334 longlong_t mtime; 335 336 if (!xdr_amq_string(xdrs, &mp->am_al->al_mnt->mf_info)) { 337 return (FALSE); 338 } 339 if (!xdr_amq_string(xdrs, &mp->am_path)) { 340 return (FALSE); 341 } 342 if (!xdr_amq_string(xdrs, mp->am_link ? &mp->am_link : &mp->am_al->al_mnt->mf_mount)) { 343 return (FALSE); 344 } 345 if (!xdr_amq_string(xdrs, &mp->am_al->al_mnt->mf_ops->fs_type)) { 346 return (FALSE); 347 } 348 mtime = mp->am_stats.s_mtime; 349 if (!xdr_longlong_t(xdrs, &mtime)) { 350 return (FALSE); 351 } 352 if (!xdr_u_short(xdrs, &mp->am_stats.s_uid)) { 353 return (FALSE); 354 } 355 if (!xdr_int(xdrs, &mp->am_stats.s_getattr)) { 356 return (FALSE); 357 } 358 if (!xdr_int(xdrs, &mp->am_stats.s_lookup)) { 359 return (FALSE); 360 } 361 if (!xdr_int(xdrs, &mp->am_stats.s_readdir)) { 362 return (FALSE); 363 } 364 if (!xdr_int(xdrs, &mp->am_stats.s_readlink)) { 365 return (FALSE); 366 } 367 if (!xdr_int(xdrs, &mp->am_stats.s_statfs)) { 368 return (FALSE); 369 } 370 return (TRUE); 371} 372 373 374bool_t 375xdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp) 376{ 377 am_node *mp = (am_node *) objp; 378 379 if (!xdr_amq_mount_tree_node(xdrs, objp)) { 380 return (FALSE); 381 } 382 if (!xdr_pointer(xdrs, 383 (char **) ((voidp) &mp->am_osib), 384 sizeof(amq_mount_tree), 385 (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { 386 return (FALSE); 387 } 388 if (!xdr_pointer(xdrs, 389 (char **) ((voidp) &mp->am_child), 390 sizeof(amq_mount_tree), 391 (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { 392 return (FALSE); 393 } 394 return (TRUE); 395} 396 397 398bool_t 399xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp) 400{ 401 am_node *mp = (am_node *) objp; 402 am_node *mnil = NULL; 403 404 if (!xdr_amq_mount_tree_node(xdrs, objp)) { 405 return (FALSE); 406 } 407 if (!xdr_pointer(xdrs, 408 (char **) ((voidp) &mnil), 409 sizeof(amq_mount_tree), 410 (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { 411 return (FALSE); 412 } 413 if (!xdr_pointer(xdrs, 414 (char **) ((voidp) &mp->am_child), 415 sizeof(amq_mount_tree), 416 (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { 417 return (FALSE); 418 } 419 return (TRUE); 420} 421 422 423bool_t 424xdr_amq_mount_tree_p(XDR *xdrs, amq_mount_tree_p *objp) 425{ 426 if (!xdr_pointer(xdrs, (char **) objp, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) { 427 return (FALSE); 428 } 429 return (TRUE); 430} 431 432 433bool_t 434xdr_amq_mount_stats(XDR *xdrs, amq_mount_stats *objp) 435{ 436 if (!xdr_int(xdrs, &objp->as_drops)) { 437 return (FALSE); 438 } 439 if (!xdr_int(xdrs, &objp->as_stale)) { 440 return (FALSE); 441 } 442 if (!xdr_int(xdrs, &objp->as_mok)) { 443 return (FALSE); 444 } 445 if (!xdr_int(xdrs, &objp->as_merr)) { 446 return (FALSE); 447 } 448 if (!xdr_int(xdrs, &objp->as_uerr)) { 449 return (FALSE); 450 } 451 return (TRUE); 452} 453 454 455 456bool_t 457xdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp) 458{ 459 if (!xdr_array(xdrs, 460 (char **) ((voidp) &objp->amq_mount_tree_list_val), 461 (u_int *) &objp->amq_mount_tree_list_len, 462 ~0, 463 sizeof(amq_mount_tree_p), 464 (XDRPROC_T_TYPE) xdr_amq_mount_tree_p)) { 465 return (FALSE); 466 } 467 return (TRUE); 468} 469 470 471bool_t 472xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead) 473{ 474 mntfs *mf; 475 u_int len = 0; 476 477 /* 478 * Compute length of list 479 */ 480 for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) { 481 if (!(mf->mf_fsflags & FS_AMQINFO)) 482 continue; 483 len++; 484 } 485 xdr_u_int(xdrs, &len); 486 487 /* 488 * Send individual data items 489 */ 490 for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) { 491 int up; 492 if (!(mf->mf_fsflags & FS_AMQINFO)) 493 continue; 494 495 if (!xdr_amq_string(xdrs, &mf->mf_ops->fs_type)) { 496 return (FALSE); 497 } 498 if (!xdr_amq_string(xdrs, &mf->mf_mount)) { 499 return (FALSE); 500 } 501 if (!xdr_amq_string(xdrs, &mf->mf_info)) { 502 return (FALSE); 503 } 504 if (!xdr_amq_string(xdrs, &mf->mf_server->fs_host)) { 505 return (FALSE); 506 } 507 if (!xdr_int(xdrs, &mf->mf_error)) { 508 return (FALSE); 509 } 510 if (!xdr_int(xdrs, &mf->mf_refc)) { 511 return (FALSE); 512 } 513 if (FSRV_ERROR(mf->mf_server) || FSRV_ISDOWN(mf->mf_server)) 514 up = 0; 515 else if (FSRV_ISUP(mf->mf_server)) 516 up = 1; 517 else 518 up = -1; 519 if (!xdr_int(xdrs, &up)) { 520 return (FALSE); 521 } 522 } 523 return (TRUE); 524} 525 526bool_t 527xdr_amq_map_info_qelem(XDR *xdrs, qelem *qhead) 528{ 529 mnt_map *m; 530 u_int len = 0; 531 int x; 532 char *n; 533 longlong_t modify; 534 535 /* 536 * Compute length of list 537 */ 538 ITER(m, mnt_map, qhead) { 539 len++; 540 } 541 542 if (!xdr_u_int(xdrs, &len)) 543 return (FALSE); 544 545 /* 546 * Send individual data items 547 */ 548 ITER(m, mnt_map, qhead) { 549 if (!xdr_amq_string(xdrs, &m->map_name)) { 550 return (FALSE); 551 } 552 553 n = m->wildcard ? m->wildcard : ""; 554 if (!xdr_amq_string(xdrs, &n)) { 555 return (FALSE); 556 } 557 558 modify = m->modify; 559 if (!xdr_longlong_t(xdrs, &modify)) { 560 return (FALSE); 561 } 562 563 x = m->flags; 564 if (!xdr_int(xdrs, &x)) { 565 return (FALSE); 566 } 567 568 x = m->nentries; 569 if (!xdr_int(xdrs, &x)) { 570 return (FALSE); 571 } 572 573 x = m->reloads; 574 if (!xdr_int(xdrs, &x)) { 575 return (FALSE); 576 } 577 578 if (!xdr_int(xdrs, &m->refc)) { 579 return (FALSE); 580 } 581 582 if (m->isup) 583 x = (*m->isup)(m, m->map_name); 584 else 585 x = -1; 586 if (!xdr_int(xdrs, &x)) { 587 return (FALSE); 588 } 589 } 590 return (TRUE); 591} 592 593bool_t 594xdr_pri_free(XDRPROC_T_TYPE xdr_args, caddr_t args_ptr) 595{ 596 XDR xdr; 597 598 xdr.x_op = XDR_FREE; 599 return ((*xdr_args) (&xdr, (caddr_t *) args_ptr)); 600} 601