amq_subr.c revision 51069
197403Sobrien/* 297403Sobrien * Copyright (c) 1997-1998 Erez Zadok 3169691Skan * Copyright (c) 1990 Jan-Simon Pendry 497403Sobrien * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 597403Sobrien * Copyright (c) 1990 The Regents of the University of California. 697403Sobrien * All rights reserved. 797403Sobrien * 897403Sobrien * This code is derived from software contributed to Berkeley by 997403Sobrien * Jan-Simon Pendry at Imperial College, London. 1097403Sobrien * 1197403Sobrien * Redistribution and use in source and binary forms, with or without 1297403Sobrien * modification, are permitted provided that the following conditions 1397403Sobrien * are met: 1497403Sobrien * 1. Redistributions of source code must retain the above copyright 1597403Sobrien * notice, this list of conditions and the following disclaimer. 1697403Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1797403Sobrien * notice, this list of conditions and the following disclaimer in the 18169691Skan * documentation and/or other materials provided with the distribution. 1997403Sobrien * 3. All advertising materials mentioning features or use of this software 2097403Sobrien * must display the following acknowledgment: 2197403Sobrien * This product includes software developed by the University of 2297403Sobrien * California, Berkeley and its contributors. 2397403Sobrien * 4. Neither the name of the University nor the names of its contributors 2497403Sobrien * may be used to endorse or promote products derived from this software 2597403Sobrien * without specific prior written permission. 2697403Sobrien * 2797403Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2897403Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2997403Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30169691Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31169691Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32169691Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33169691Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3497403Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3597403Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3697403Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3797403Sobrien * SUCH DAMAGE. 38132720Skan * 39132720Skan * %W% (Berkeley) %G% 4097403Sobrien * 4197403Sobrien * $Id: amq_subr.c,v 1.3 1999/01/13 20:03:54 obrien Exp $ 4297403Sobrien * 4397403Sobrien */ 4497403Sobrien/* 4597403Sobrien * Auxiliary routines for amq tool 46169691Skan */ 47169691Skan 4897403Sobrien#ifdef HAVE_CONFIG_H 4997403Sobrien# include <config.h> 5097403Sobrien#endif /* HAVE_CONFIG_H */ 5197403Sobrien#include <am_defs.h> 5297403Sobrien#include <amd.h> 5397403Sobrien 5497403Sobrien/* forward definitions */ 5597403Sobrienbool_t xdr_amq_mount_tree_node(XDR *xdrs, amq_mount_tree *objp); 5697403Sobrienbool_t xdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp); 5797403Sobrien 5897403Sobrien 5997403Sobrienvoidp 6097403Sobrienamqproc_null_1_svc(voidp argp, struct svc_req *rqstp) 6197403Sobrien{ 6297403Sobrien static char res; 6397403Sobrien 6497403Sobrien return (voidp) &res; 6597403Sobrien} 6697403Sobrien 6797403Sobrien 6897403Sobrien/* 6997403Sobrien * Return a sub-tree of mounts 7097403Sobrien */ 7197403Sobrienamq_mount_tree_p * 7297403Sobrienamqproc_mnttree_1_svc(voidp argp, struct svc_req *rqstp) 7397403Sobrien{ 7497403Sobrien static am_node *mp; 7597403Sobrien 7697403Sobrien mp = find_ap(*(char **) argp); 7797403Sobrien return (amq_mount_tree_p *) ∓ 7897403Sobrien} 7997403Sobrien 8097403Sobrien 8197403Sobrien/* 8297403Sobrien * Unmount a single node 8397403Sobrien */ 8497403Sobrienvoidp 8597403Sobrienamqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp) 8697403Sobrien{ 8797403Sobrien static char res; 8897403Sobrien am_node *mp = find_ap(*(char **) argp); 8997403Sobrien 9097403Sobrien if (mp) 9197403Sobrien forcibly_timeout_mp(mp); 9297403Sobrien 9397403Sobrien return (voidp) &res; 9497403Sobrien} 9597403Sobrien 9697403Sobrien 9797403Sobrien/* 9897403Sobrien * Return global statistics 9997403Sobrien */ 10097403Sobrienamq_mount_stats * 10197403Sobrienamqproc_stats_1_svc(voidp argp, struct svc_req *rqstp) 10297403Sobrien{ 10397403Sobrien return (amq_mount_stats *) &amd_stats; 10497403Sobrien} 10597403Sobrien 10697403Sobrien 10797403Sobrien/* 10897403Sobrien * Return the entire tree of mount nodes 10997403Sobrien */ 11097403Sobrienamq_mount_tree_list * 11197403Sobrienamqproc_export_1_svc(voidp argp, struct svc_req *rqstp) 11297403Sobrien{ 11397403Sobrien static amq_mount_tree_list aml; 11497403Sobrien 11597403Sobrien aml.amq_mount_tree_list_val = (amq_mount_tree_p *) &exported_ap[0]; 11697403Sobrien aml.amq_mount_tree_list_len = 1; /* XXX */ 11797403Sobrien 11897403Sobrien return &aml; 11997403Sobrien} 12097403Sobrien 12197403Sobrien 12297403Sobrienint * 12397403Sobrienamqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp) 12497403Sobrien{ 12597403Sobrien static int rc; 12697403Sobrien amq_setopt *opt = (amq_setopt *) argp; 12797403Sobrien 12897403Sobrien rc = 0; 12997403Sobrien 13097403Sobrien switch (opt->as_opt) { 13197403Sobrien 13297403Sobrien case AMOPT_DEBUG: 13397403Sobrien#ifdef DEBUG 13497403Sobrien if (debug_option(opt->as_str)) 13597403Sobrien#endif /* DEBUG */ 13697403Sobrien rc = EINVAL; 13797403Sobrien break; 13897403Sobrien 13997403Sobrien case AMOPT_LOGFILE: 14097403Sobrien if (gopt.logfile && opt->as_str 14197403Sobrien && STREQ(gopt.logfile, opt->as_str)) { 14297403Sobrien if (switch_to_logfile(opt->as_str, orig_umask)) 14397403Sobrien rc = EINVAL; 14497403Sobrien } else { 14597403Sobrien rc = EACCES; 146169691Skan } 147169691Skan break; 148132720Skan 149 case AMOPT_XLOG: 150 if (switch_option(opt->as_str)) 151 rc = EINVAL; 152 break; 153 154 case AMOPT_FLUSHMAPC: 155 if (amd_state == Run) { 156 plog(XLOG_INFO, "amq says flush cache"); 157 do_mapc_reload = 0; 158 flush_nfs_fhandle_cache((fserver *) 0); 159 flush_srvr_nfs_cache(); 160 } 161 break; 162 } 163 164 return &rc; 165} 166 167 168amq_mount_info_list * 169amqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp) 170{ 171 return (amq_mount_info_list *) &mfhead; /* XXX */ 172} 173 174#ifdef ENABLE_AMQ_MOUNT 175/* 176 * This is code that is vulnerable to IP spoofing attacks. Unless you 177 * absolutely need it, I suggest you do not enable it 178 * (using configure --enable-amq-mount) 179 */ 180static int 181ok_security(struct svc_req *rqstp) 182{ 183 struct sockaddr_in *sin = (struct sockaddr_in *) NULL; 184 185 if ((sin = amu_svc_getcaller(rqstp->rq_xprt)) == NULL) { 186 plog(XLOG_ERROR, "amu_svc_getcaller returned NULL"); 187 return(0); /* assume security is therefore not OK */ 188 } 189 190 if (ntohs(sin->sin_port) >= 1024 || 191 !(sin->sin_addr.s_addr == htonl(0x7f000001) || 192 sin->sin_addr.s_addr == myipaddr.s_addr)) { 193 char dq[20]; 194 plog(XLOG_INFO, "AMQ request from %s.%d DENIED", 195 inet_dquad(dq, sin->sin_addr.s_addr), 196 ntohs(sin->sin_port)); 197 return (0); 198 } 199 200 return (1); 201} 202 203 204int * 205amqproc_mount_1_svc(voidp argp, struct svc_req *rqstp) 206{ 207 static int rc = EINVAL; 208 char s[AMQ_STRLEN]; 209 char *cp; 210 char dq[20]; 211 struct sockaddr_in *sin; 212 213 if ((sin = amu_svc_getcaller(rqstp->rq_xprt)) == NULL) { 214 plog(XLOG_ERROR, "amu_svc_getcaller returned NULL"); 215 return &rc; 216 } 217 218 strncpy(s, *(amq_string *) argp, AMQ_STRLEN-1); 219 s[AMQ_STRLEN-1] = '\0'; /* null terminate, to be sure */ 220 plog(XLOG_ERROR, 221 "amq requested mount of %s from %s.%d", 222 s, inet_dquad(dq, sin->sin_addr.s_addr), 223 ntohs(sin->sin_port)); 224 225 /* 226 * Minimalist security check. 227 */ 228 if (!ok_security(rqstp)) { 229 rc = EACCES; 230 return &rc; 231 } 232 /* 233 * Find end of key 234 */ 235 for (cp = (char *) s; *cp && (!isascii(*cp) || !isspace(*cp)); cp++) ; 236 237 if (!*cp) { 238 plog(XLOG_INFO, "amqproc_mount: Invalid arguments"); 239 rc = EINVAL; 240 return &rc; 241 } 242 *cp++ = '\0'; 243 244 /* 245 * Find start of value 246 */ 247 while (*cp && isascii(*cp) && isspace(*cp)) 248 cp++; 249 250 root_newmap(s, cp, (char *) 0, NULL); 251 rc = mount_auto_node(s, (voidp) root_node); 252 if (rc < 0) 253 return 0; 254 return &rc; 255} 256 257#else /* not ENABLE_AMQ_MOUNT */ 258 259int * 260amqproc_mount_1_svc(voidp argp, struct svc_req *rqstp) 261{ 262 static int rc; 263 char *s = *(amq_string *) argp; 264 265 plog(XLOG_ERROR, "amq requested mount of %s, but code is disabled", s); 266 267 rc = EINVAL; 268 return &rc; 269} 270#endif /* not ENABLE_AMQ_MOUNT */ 271 272 273amq_string * 274amqproc_getvers_1_svc(voidp argp, struct svc_req *rqstp) 275{ 276 static amq_string res; 277 278 res = get_version_string(); 279 return &res; 280} 281 282 283/* get PID of remote amd */ 284int * 285amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp) 286{ 287 static int res; 288 289 res = getpid(); 290 return &res; 291} 292 293 294/* 295 * XDR routines. 296 */ 297 298 299bool_t 300xdr_amq_setopt(XDR *xdrs, amq_setopt *objp) 301{ 302 if (!xdr_enum(xdrs, (enum_t *) & objp->as_opt)) { 303 return (FALSE); 304 } 305 if (!xdr_string(xdrs, &objp->as_str, AMQ_STRLEN)) { 306 return (FALSE); 307 } 308 return (TRUE); 309} 310 311 312/* 313 * More XDR routines - Should be used for OUTPUT ONLY. 314 */ 315bool_t 316xdr_amq_mount_tree_node(XDR *xdrs, amq_mount_tree *objp) 317{ 318 am_node *mp = (am_node *) objp; 319 long mtime; 320 321 if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_info)) { 322 return (FALSE); 323 } 324 if (!xdr_amq_string(xdrs, &mp->am_path)) { 325 return (FALSE); 326 } 327 if (!xdr_amq_string(xdrs, mp->am_link ? &mp->am_link : &mp->am_mnt->mf_mount)) { 328 return (FALSE); 329 } 330 if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_ops->fs_type)) { 331 return (FALSE); 332 } 333 mtime = mp->am_stats.s_mtime; 334 if (!xdr_long(xdrs, &mtime)) { 335 return (FALSE); 336 } 337 if (!xdr_u_short(xdrs, &mp->am_stats.s_uid)) { 338 return (FALSE); 339 } 340 if (!xdr_int(xdrs, &mp->am_stats.s_getattr)) { 341 return (FALSE); 342 } 343 if (!xdr_int(xdrs, &mp->am_stats.s_lookup)) { 344 return (FALSE); 345 } 346 if (!xdr_int(xdrs, &mp->am_stats.s_readdir)) { 347 return (FALSE); 348 } 349 if (!xdr_int(xdrs, &mp->am_stats.s_readlink)) { 350 return (FALSE); 351 } 352 if (!xdr_int(xdrs, &mp->am_stats.s_statfs)) { 353 return (FALSE); 354 } 355 return (TRUE); 356} 357 358 359bool_t 360xdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp) 361{ 362 am_node *mp = (am_node *) objp; 363 364 if (!xdr_amq_mount_tree_node(xdrs, objp)) { 365 return (FALSE); 366 } 367 if (!xdr_pointer(xdrs, (char **) &mp->am_osib, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { 368 return (FALSE); 369 } 370 if (!xdr_pointer(xdrs, (char **) &mp->am_child, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { 371 return (FALSE); 372 } 373 return (TRUE); 374} 375 376 377bool_t 378xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp) 379{ 380 am_node *mp = (am_node *) objp; 381 am_node *mnil = 0; 382 383 if (!xdr_amq_mount_tree_node(xdrs, objp)) { 384 return (FALSE); 385 } 386 if (!xdr_pointer(xdrs, (char **) &mnil, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { 387 return (FALSE); 388 } 389 if (!xdr_pointer(xdrs, (char **) &mp->am_child, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) { 390 return (FALSE); 391 } 392 return (TRUE); 393} 394 395 396bool_t 397xdr_amq_mount_tree_p(XDR *xdrs, amq_mount_tree_p *objp) 398{ 399 if (!xdr_pointer(xdrs, (char **) objp, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) { 400 return (FALSE); 401 } 402 return (TRUE); 403} 404 405 406bool_t 407xdr_amq_mount_stats(XDR *xdrs, amq_mount_stats *objp) 408{ 409 if (!xdr_int(xdrs, &objp->as_drops)) { 410 return (FALSE); 411 } 412 if (!xdr_int(xdrs, &objp->as_stale)) { 413 return (FALSE); 414 } 415 if (!xdr_int(xdrs, &objp->as_mok)) { 416 return (FALSE); 417 } 418 if (!xdr_int(xdrs, &objp->as_merr)) { 419 return (FALSE); 420 } 421 if (!xdr_int(xdrs, &objp->as_uerr)) { 422 return (FALSE); 423 } 424 return (TRUE); 425} 426 427 428 429bool_t 430xdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp) 431{ 432 if (!xdr_array(xdrs, 433 (char **) &objp->amq_mount_tree_list_val, 434 (u_int *) &objp->amq_mount_tree_list_len, 435 ~0, 436 sizeof(amq_mount_tree_p), 437 (XDRPROC_T_TYPE) xdr_amq_mount_tree_p)) { 438 return (FALSE); 439 } 440 return (TRUE); 441} 442 443 444 445/* 446 * Compute length of list 447 */ 448bool_t 449xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead) 450{ 451 mntfs *mf; 452 u_int len = 0; 453 454 for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) { 455 if (!(mf->mf_ops->fs_flags & FS_AMQINFO)) 456 continue; 457 len++; 458 } 459 xdr_u_int(xdrs, &len); 460 461 /* 462 * Send individual data items 463 */ 464 for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) { 465 int up; 466 if (!(mf->mf_ops->fs_flags & FS_AMQINFO)) 467 continue; 468 469 if (!xdr_amq_string(xdrs, &mf->mf_ops->fs_type)) { 470 return (FALSE); 471 } 472 if (!xdr_amq_string(xdrs, &mf->mf_mount)) { 473 return (FALSE); 474 } 475 if (!xdr_amq_string(xdrs, &mf->mf_info)) { 476 return (FALSE); 477 } 478 if (!xdr_amq_string(xdrs, &mf->mf_server->fs_host)) { 479 return (FALSE); 480 } 481 if (!xdr_int(xdrs, &mf->mf_error)) { 482 return (FALSE); 483 } 484 if (!xdr_int(xdrs, &mf->mf_refc)) { 485 return (FALSE); 486 } 487 if (mf->mf_server->fs_flags & FSF_ERROR) 488 up = 0; 489 else 490 switch (mf->mf_server->fs_flags & (FSF_DOWN | FSF_VALID)) { 491 case FSF_DOWN | FSF_VALID: 492 up = 0; 493 break; 494 case FSF_VALID: 495 up = 1; 496 break; 497 default: 498 up = -1; 499 break; 500 } 501 if (!xdr_int(xdrs, &up)) { 502 return (FALSE); 503 } 504 } 505 return (TRUE); 506} 507 508 509bool_t 510xdr_pri_free(XDRPROC_T_TYPE xdr_args, caddr_t args_ptr) 511{ 512 XDR xdr; 513 514 xdr.x_op = XDR_FREE; 515 return ((*xdr_args) (&xdr, (caddr_t *) args_ptr)); 516} 517