138494Sobrien/*
2174313Sobrien * Copyright (c) 1997-2006 Erez Zadok
338494Sobrien * Copyright (c) 1990 Jan-Simon Pendry
438494Sobrien * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
538494Sobrien * Copyright (c) 1990 The Regents of the University of California.
638494Sobrien * All rights reserved.
738494Sobrien *
838494Sobrien * This code is derived from software contributed to Berkeley by
938494Sobrien * Jan-Simon Pendry at Imperial College, London.
1038494Sobrien *
1138494Sobrien * Redistribution and use in source and binary forms, with or without
1238494Sobrien * modification, are permitted provided that the following conditions
1338494Sobrien * are met:
1438494Sobrien * 1. Redistributions of source code must retain the above copyright
1538494Sobrien *    notice, this list of conditions and the following disclaimer.
1638494Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1738494Sobrien *    notice, this list of conditions and the following disclaimer in the
1838494Sobrien *    documentation and/or other materials provided with the distribution.
1938494Sobrien * 3. All advertising materials mentioning features or use of this software
2042633Sobrien *    must display the following acknowledgment:
2138494Sobrien *      This product includes software developed by the University of
2238494Sobrien *      California, Berkeley and its contributors.
2338494Sobrien * 4. Neither the name of the University nor the names of its contributors
2438494Sobrien *    may be used to endorse or promote products derived from this software
2538494Sobrien *    without specific prior written permission.
2638494Sobrien *
2738494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2838494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2938494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3038494Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3138494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3238494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3338494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3438494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3538494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3638494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3738494Sobrien * SUCH DAMAGE.
3838494Sobrien *
3938494Sobrien *
40174313Sobrien * File: am-utils/amd/amq_subr.c
4138494Sobrien *
4238494Sobrien */
4338494Sobrien/*
4442633Sobrien * Auxiliary routines for amq tool
4538494Sobrien */
4638494Sobrien
4738494Sobrien#ifdef HAVE_CONFIG_H
4838494Sobrien# include <config.h>
4938494Sobrien#endif /* HAVE_CONFIG_H */
5038494Sobrien#include <am_defs.h>
5138494Sobrien#include <amd.h>
5238494Sobrien
5338494Sobrien/* forward definitions */
5438494Sobrienbool_t xdr_amq_mount_tree_node(XDR *xdrs, amq_mount_tree *objp);
5538494Sobrienbool_t xdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp);
5638494Sobrien
5738494Sobrien
5838494Sobrienvoidp
5938494Sobrienamqproc_null_1_svc(voidp argp, struct svc_req *rqstp)
6038494Sobrien{
6138494Sobrien  static char res;
6238494Sobrien
6338494Sobrien  return (voidp) &res;
6438494Sobrien}
6538494Sobrien
6638494Sobrien
6738494Sobrien/*
6838494Sobrien * Return a sub-tree of mounts
6938494Sobrien */
7038494Sobrienamq_mount_tree_p *
7138494Sobrienamqproc_mnttree_1_svc(voidp argp, struct svc_req *rqstp)
7238494Sobrien{
7338494Sobrien  static am_node *mp;
7438494Sobrien
7538494Sobrien  mp = find_ap(*(char **) argp);
76131706Smbr  return (amq_mount_tree_p *) ((void *)&mp);
7738494Sobrien}
7838494Sobrien
7938494Sobrien
8038494Sobrien/*
8138494Sobrien * Unmount a single node
8238494Sobrien */
8338494Sobrienvoidp
8438494Sobrienamqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp)
8538494Sobrien{
8638494Sobrien  static char res;
8738494Sobrien  am_node *mp = find_ap(*(char **) argp);
8838494Sobrien
8938494Sobrien  if (mp)
9038494Sobrien    forcibly_timeout_mp(mp);
9138494Sobrien
9238494Sobrien  return (voidp) &res;
9338494Sobrien}
9438494Sobrien
9538494Sobrien
9638494Sobrien/*
9738494Sobrien * Return global statistics
9838494Sobrien */
9938494Sobrienamq_mount_stats *
10038494Sobrienamqproc_stats_1_svc(voidp argp, struct svc_req *rqstp)
10138494Sobrien{
102131706Smbr  return (amq_mount_stats *) ((void *)&amd_stats);
10338494Sobrien}
10438494Sobrien
10538494Sobrien
10638494Sobrien/*
10738494Sobrien * Return the entire tree of mount nodes
10838494Sobrien */
10938494Sobrienamq_mount_tree_list *
11038494Sobrienamqproc_export_1_svc(voidp argp, struct svc_req *rqstp)
11138494Sobrien{
11238494Sobrien  static amq_mount_tree_list aml;
113174313Sobrien  static am_node *mp;
11438494Sobrien
115174313Sobrien  mp = get_exported_ap(0);
116174313Sobrien  aml.amq_mount_tree_list_val = (amq_mount_tree_p *) ((void *) &mp);
11738494Sobrien  aml.amq_mount_tree_list_len = 1;	/* XXX */
11838494Sobrien
11938494Sobrien  return &aml;
12038494Sobrien}
12138494Sobrien
12238494Sobrien
12338494Sobrienint *
12438494Sobrienamqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp)
12538494Sobrien{
12638494Sobrien  static int rc;
12738494Sobrien  amq_setopt *opt = (amq_setopt *) argp;
12838494Sobrien
12938494Sobrien  rc = 0;
13038494Sobrien
13138494Sobrien  switch (opt->as_opt) {
13238494Sobrien
13338494Sobrien  case AMOPT_DEBUG:
13438494Sobrien    if (debug_option(opt->as_str))
13538494Sobrien      rc = EINVAL;
13638494Sobrien    break;
13738494Sobrien
13838494Sobrien  case AMOPT_LOGFILE:
13938494Sobrien    if (gopt.logfile && opt->as_str
14038494Sobrien	&& STREQ(gopt.logfile, opt->as_str)) {
141174313Sobrien      if (switch_to_logfile(opt->as_str, orig_umask, 0))
14238494Sobrien	rc = EINVAL;
14338494Sobrien    } else {
14438494Sobrien      rc = EACCES;
14538494Sobrien    }
14638494Sobrien    break;
14738494Sobrien
14838494Sobrien  case AMOPT_XLOG:
14938494Sobrien    if (switch_option(opt->as_str))
15038494Sobrien      rc = EINVAL;
15138494Sobrien    break;
15238494Sobrien
15338494Sobrien  case AMOPT_FLUSHMAPC:
15438494Sobrien    if (amd_state == Run) {
15538494Sobrien      plog(XLOG_INFO, "amq says flush cache");
15638494Sobrien      do_mapc_reload = 0;
157174313Sobrien      flush_nfs_fhandle_cache((fserver *) NULL);
158174313Sobrien      flush_srvr_nfs_cache((fserver *) NULL);
15938494Sobrien    }
16038494Sobrien    break;
16138494Sobrien  }
16238494Sobrien
16338494Sobrien  return &rc;
16438494Sobrien}
16538494Sobrien
16638494Sobrien
16738494Sobrienamq_mount_info_list *
16838494Sobrienamqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp)
16938494Sobrien{
170174313Sobrien  return (amq_mount_info_list *) ((void *)&mfhead);	/* XXX */
17138494Sobrien}
17238494Sobrien
17338494Sobrien
17438494Sobrienamq_string *
17538494Sobrienamqproc_getvers_1_svc(voidp argp, struct svc_req *rqstp)
17638494Sobrien{
17738494Sobrien  static amq_string res;
17838494Sobrien
17938494Sobrien  res = get_version_string();
18038494Sobrien  return &res;
18138494Sobrien}
18238494Sobrien
18338494Sobrien
18438494Sobrien/* get PID of remote amd */
18538494Sobrienint *
18638494Sobrienamqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp)
18738494Sobrien{
18838494Sobrien  static int res;
18938494Sobrien
19038494Sobrien  res = getpid();
19138494Sobrien  return &res;
19238494Sobrien}
19338494Sobrien
19438494Sobrien
19538494Sobrien/*
196174313Sobrien * Process PAWD string of remote pawd tool.
197174313Sobrien *
198174313Sobrien * We repeat the resolution of the string until the resolved string resolves
199174313Sobrien * to itself.  This ensures that we follow path resolutions through all
200174313Sobrien * possible Amd mount points until we reach some sort of convergence.  To
201174313Sobrien * prevent possible infinite loops, we break out of this loop if the strings
202174313Sobrien * do not converge after MAX_PAWD_TRIES times.
203174313Sobrien */
204174313Sobrienamq_string *
205174313Sobrienamqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp)
206174313Sobrien{
207174313Sobrien  static amq_string res;
208174313Sobrien#define MAX_PAWD_TRIES 10
209174313Sobrien  int index, len, maxagain = MAX_PAWD_TRIES;
210174313Sobrien  am_node *mp;
211174313Sobrien  char *mountpoint;
212174313Sobrien  char *dir = *(char **) argp;
213174313Sobrien  static char tmp_buf[MAXPATHLEN];
214174313Sobrien  char prev_buf[MAXPATHLEN];
215174313Sobrien
216174313Sobrien  tmp_buf[0] = prev_buf[0] = '\0'; /* default is empty string: no match */
217174313Sobrien  do {
218174313Sobrien    for (mp = get_first_exported_ap(&index);
219174313Sobrien	 mp;
220174313Sobrien	 mp = get_next_exported_ap(&index)) {
221174313Sobrien      if (STREQ(mp->am_mnt->mf_ops->fs_type, "toplvl"))
222174313Sobrien	continue;
223174313Sobrien      if (STREQ(mp->am_mnt->mf_ops->fs_type, "auto"))
224174313Sobrien	continue;
225174313Sobrien      mountpoint = (mp->am_link ? mp->am_link : mp->am_mnt->mf_mount);
226174313Sobrien      len = strlen(mountpoint);
227174313Sobrien      if (len == 0)
228174313Sobrien	continue;
229174313Sobrien      if (!NSTREQ(mountpoint, dir, len))
230174313Sobrien	continue;
231174313Sobrien      if (dir[len] != '\0' && dir[len] != '/')
232174313Sobrien	continue;
233174313Sobrien      xstrlcpy(tmp_buf, mp->am_path, sizeof(tmp_buf));
234174313Sobrien      xstrlcat(tmp_buf, &dir[len], sizeof(tmp_buf));
235174313Sobrien      break;
236174313Sobrien    } /* end of "for" loop */
237174313Sobrien    /* once tmp_buf and prev_buf are equal, break out of "do" loop */
238174313Sobrien    if (STREQ(tmp_buf, prev_buf))
239174313Sobrien      break;
240174313Sobrien    else
241174313Sobrien      xstrlcpy(prev_buf, tmp_buf, sizeof(prev_buf));
242174313Sobrien  } while (--maxagain);
243174313Sobrien  /* check if we couldn't resolve the string after MAX_PAWD_TRIES times */
244174313Sobrien  if (maxagain <= 0)
245174313Sobrien    plog(XLOG_WARNING, "path \"%s\" did not resolve after %d tries",
246174313Sobrien	 tmp_buf, MAX_PAWD_TRIES);
247174313Sobrien
248174313Sobrien  res = tmp_buf;
249174313Sobrien  return &res;
250174313Sobrien}
251174313Sobrien
252174313Sobrien
253174313Sobrien/*
25438494Sobrien * XDR routines.
25538494Sobrien */
25638494Sobrien
25738494Sobrien
25838494Sobrienbool_t
25938494Sobrienxdr_amq_setopt(XDR *xdrs, amq_setopt *objp)
26038494Sobrien{
261174313Sobrien  if (!xdr_enum(xdrs, (enum_t *) ((voidp) &objp->as_opt))) {
26238494Sobrien    return (FALSE);
26338494Sobrien  }
26438494Sobrien  if (!xdr_string(xdrs, &objp->as_str, AMQ_STRLEN)) {
26538494Sobrien    return (FALSE);
26638494Sobrien  }
26738494Sobrien  return (TRUE);
26838494Sobrien}
26938494Sobrien
27038494Sobrien
27138494Sobrien/*
27238494Sobrien * More XDR routines  - Should be used for OUTPUT ONLY.
27338494Sobrien */
27438494Sobrienbool_t
27538494Sobrienxdr_amq_mount_tree_node(XDR *xdrs, amq_mount_tree *objp)
27638494Sobrien{
27738494Sobrien  am_node *mp = (am_node *) objp;
27838790Sobrien  long mtime;
27938494Sobrien
28038494Sobrien  if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_info)) {
28138494Sobrien    return (FALSE);
28238494Sobrien  }
28338494Sobrien  if (!xdr_amq_string(xdrs, &mp->am_path)) {
28438494Sobrien    return (FALSE);
28538494Sobrien  }
28638494Sobrien  if (!xdr_amq_string(xdrs, mp->am_link ? &mp->am_link : &mp->am_mnt->mf_mount)) {
28738494Sobrien    return (FALSE);
28838494Sobrien  }
28938494Sobrien  if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_ops->fs_type)) {
29038494Sobrien    return (FALSE);
29138494Sobrien  }
29238790Sobrien  mtime = mp->am_stats.s_mtime;
29338790Sobrien  if (!xdr_long(xdrs, &mtime)) {
29438494Sobrien    return (FALSE);
29538494Sobrien  }
29638494Sobrien  if (!xdr_u_short(xdrs, &mp->am_stats.s_uid)) {
29738494Sobrien    return (FALSE);
29838494Sobrien  }
29938494Sobrien  if (!xdr_int(xdrs, &mp->am_stats.s_getattr)) {
30038494Sobrien    return (FALSE);
30138494Sobrien  }
30238494Sobrien  if (!xdr_int(xdrs, &mp->am_stats.s_lookup)) {
30338494Sobrien    return (FALSE);
30438494Sobrien  }
30538494Sobrien  if (!xdr_int(xdrs, &mp->am_stats.s_readdir)) {
30638494Sobrien    return (FALSE);
30738494Sobrien  }
30838494Sobrien  if (!xdr_int(xdrs, &mp->am_stats.s_readlink)) {
30938494Sobrien    return (FALSE);
31038494Sobrien  }
31138494Sobrien  if (!xdr_int(xdrs, &mp->am_stats.s_statfs)) {
31238494Sobrien    return (FALSE);
31338494Sobrien  }
31438494Sobrien  return (TRUE);
31538494Sobrien}
31638494Sobrien
31738494Sobrien
31838494Sobrienbool_t
31938494Sobrienxdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp)
32038494Sobrien{
32138494Sobrien  am_node *mp = (am_node *) objp;
32238494Sobrien
32338494Sobrien  if (!xdr_amq_mount_tree_node(xdrs, objp)) {
32438494Sobrien    return (FALSE);
32538494Sobrien  }
326174313Sobrien  if (!xdr_pointer(xdrs,
327174313Sobrien		   (char **) ((voidp) &mp->am_osib),
328174313Sobrien		   sizeof(amq_mount_tree),
329174313Sobrien		   (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
33038494Sobrien    return (FALSE);
33138494Sobrien  }
332174313Sobrien  if (!xdr_pointer(xdrs,
333174313Sobrien		   (char **) ((voidp) &mp->am_child),
334174313Sobrien		   sizeof(amq_mount_tree),
335174313Sobrien		   (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
33638494Sobrien    return (FALSE);
33738494Sobrien  }
33838494Sobrien  return (TRUE);
33938494Sobrien}
34038494Sobrien
34138494Sobrien
34238494Sobrienbool_t
34338494Sobrienxdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp)
34438494Sobrien{
34538494Sobrien  am_node *mp = (am_node *) objp;
346174313Sobrien  am_node *mnil = NULL;
34738494Sobrien
34838494Sobrien  if (!xdr_amq_mount_tree_node(xdrs, objp)) {
34938494Sobrien    return (FALSE);
35038494Sobrien  }
351174313Sobrien  if (!xdr_pointer(xdrs,
352174313Sobrien		   (char **) ((voidp) &mnil),
353174313Sobrien		   sizeof(amq_mount_tree),
354174313Sobrien		   (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
35538494Sobrien    return (FALSE);
35638494Sobrien  }
357174313Sobrien  if (!xdr_pointer(xdrs,
358174313Sobrien		   (char **) ((voidp) &mp->am_child),
359174313Sobrien		   sizeof(amq_mount_tree),
360174313Sobrien		   (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
36138494Sobrien    return (FALSE);
36238494Sobrien  }
36338494Sobrien  return (TRUE);
36438494Sobrien}
36538494Sobrien
36638494Sobrien
36738494Sobrienbool_t
36838494Sobrienxdr_amq_mount_tree_p(XDR *xdrs, amq_mount_tree_p *objp)
36938494Sobrien{
37038494Sobrien  if (!xdr_pointer(xdrs, (char **) objp, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
37138494Sobrien    return (FALSE);
37238494Sobrien  }
37338494Sobrien  return (TRUE);
37438494Sobrien}
37538494Sobrien
37638494Sobrien
37738494Sobrienbool_t
37838494Sobrienxdr_amq_mount_stats(XDR *xdrs, amq_mount_stats *objp)
37938494Sobrien{
38038494Sobrien  if (!xdr_int(xdrs, &objp->as_drops)) {
38138494Sobrien    return (FALSE);
38238494Sobrien  }
38338494Sobrien  if (!xdr_int(xdrs, &objp->as_stale)) {
38438494Sobrien    return (FALSE);
38538494Sobrien  }
38638494Sobrien  if (!xdr_int(xdrs, &objp->as_mok)) {
38738494Sobrien    return (FALSE);
38838494Sobrien  }
38938494Sobrien  if (!xdr_int(xdrs, &objp->as_merr)) {
39038494Sobrien    return (FALSE);
39138494Sobrien  }
39238494Sobrien  if (!xdr_int(xdrs, &objp->as_uerr)) {
39338494Sobrien    return (FALSE);
39438494Sobrien  }
39538494Sobrien  return (TRUE);
39638494Sobrien}
39738494Sobrien
39838494Sobrien
39938494Sobrien
40038494Sobrienbool_t
40138494Sobrienxdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp)
40238494Sobrien{
40338494Sobrien  if (!xdr_array(xdrs,
404174313Sobrien		 (char **) ((voidp) &objp->amq_mount_tree_list_val),
40538494Sobrien		 (u_int *) &objp->amq_mount_tree_list_len,
40638494Sobrien		 ~0,
40738494Sobrien		 sizeof(amq_mount_tree_p),
40838494Sobrien		 (XDRPROC_T_TYPE) xdr_amq_mount_tree_p)) {
40938494Sobrien    return (FALSE);
41038494Sobrien  }
41138494Sobrien  return (TRUE);
41238494Sobrien}
41338494Sobrien
41438494Sobrien
41538494Sobrien
41638494Sobrien/*
41738494Sobrien * Compute length of list
41838494Sobrien */
41938494Sobrienbool_t
42038494Sobrienxdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead)
42138494Sobrien{
42238494Sobrien  mntfs *mf;
42338494Sobrien  u_int len = 0;
42438494Sobrien
42538494Sobrien  for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) {
426174313Sobrien    if (!(mf->mf_fsflags & FS_AMQINFO))
42738494Sobrien      continue;
42838494Sobrien    len++;
42938494Sobrien  }
43038494Sobrien  xdr_u_int(xdrs, &len);
43138494Sobrien
43238494Sobrien  /*
43338494Sobrien   * Send individual data items
43438494Sobrien   */
43538494Sobrien  for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) {
43638494Sobrien    int up;
437174313Sobrien    if (!(mf->mf_fsflags & FS_AMQINFO))
43838494Sobrien      continue;
43938494Sobrien
44038494Sobrien    if (!xdr_amq_string(xdrs, &mf->mf_ops->fs_type)) {
44138494Sobrien      return (FALSE);
44238494Sobrien    }
44338494Sobrien    if (!xdr_amq_string(xdrs, &mf->mf_mount)) {
44438494Sobrien      return (FALSE);
44538494Sobrien    }
44638494Sobrien    if (!xdr_amq_string(xdrs, &mf->mf_info)) {
44738494Sobrien      return (FALSE);
44838494Sobrien    }
44938494Sobrien    if (!xdr_amq_string(xdrs, &mf->mf_server->fs_host)) {
45038494Sobrien      return (FALSE);
45138494Sobrien    }
45238494Sobrien    if (!xdr_int(xdrs, &mf->mf_error)) {
45338494Sobrien      return (FALSE);
45438494Sobrien    }
45538494Sobrien    if (!xdr_int(xdrs, &mf->mf_refc)) {
45638494Sobrien      return (FALSE);
45738494Sobrien    }
458174313Sobrien    if (FSRV_ERROR(mf->mf_server) || FSRV_ISDOWN(mf->mf_server))
45938494Sobrien      up = 0;
460174313Sobrien    else if (FSRV_ISUP(mf->mf_server))
461174313Sobrien      up = 1;
46238494Sobrien    else
463174313Sobrien      up = -1;
46438494Sobrien    if (!xdr_int(xdrs, &up)) {
46538494Sobrien      return (FALSE);
46638494Sobrien    }
46738494Sobrien  }
46838494Sobrien  return (TRUE);
46938494Sobrien}
47038494Sobrien
47138494Sobrien
47238494Sobrienbool_t
47338494Sobrienxdr_pri_free(XDRPROC_T_TYPE xdr_args, caddr_t args_ptr)
47438494Sobrien{
47538494Sobrien  XDR xdr;
47638494Sobrien
47738494Sobrien  xdr.x_op = XDR_FREE;
47838494Sobrien  return ((*xdr_args) (&xdr, (caddr_t *) args_ptr));
47938494Sobrien}
480