Home | History | Annotate | Line # | Download | only in amd
      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 */
     52 bool_t xdr_amq_mount_tree_node(XDR *xdrs, amq_mount_tree *objp);
     53 bool_t xdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp);
     54 
     55 
     56 voidp
     57 amqproc_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  */
     68 amq_mount_tree_p *
     69 amqproc_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  */
     81 int *
     82 amqproc_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  */
     97 int *
     98 amqproc_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  */
    108 amq_sync_umnt *
    109 amqproc_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  */
    131 amq_sync_umnt *
    132 amqproc_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  */
    149 amq_mount_stats *
    150 amqproc_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  */
    159 amq_mount_tree_list *
    160 amqproc_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 
    173 int *
    174 amqproc_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 
    217 amq_mount_info_list *
    218 amqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp)
    219 {
    220   return (amq_mount_info_list *) ((void *)&mfhead);	/* XXX */
    221 }
    222 
    223 extern qelem map_list_head;
    224 amq_map_info_list *
    225 amqproc_getmapinfo_1_svc(voidp argp, struct svc_req *rqstp)
    226 {
    227   return (amq_map_info_list *) ((void *)&map_list_head);	/* XXX */
    228 }
    229 
    230 amq_string *
    231 amqproc_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 */
    241 int *
    242 amqproc_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  */
    260 amq_string *
    261 amqproc_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 
    314 bool_t
    315 xdr_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  */
    330 bool_t
    331 xdr_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 
    374 bool_t
    375 xdr_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 
    398 bool_t
    399 xdr_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 
    423 bool_t
    424 xdr_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 
    433 bool_t
    434 xdr_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 
    456 bool_t
    457 xdr_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 
    471 bool_t
    472 xdr_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 
    526 bool_t
    527 xdr_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 
    593 bool_t
    594 xdr_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