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