source: trunk/athena/bin/quota/nfs.c @ 13698

Revision 13698, 5.0 KB checked in by rbasch, 25 years ago (diff)
In get_nfs_quota(), add break's to the case blocks handling the status of the getquota RPC, and add a default case. In callaurpc(), use pmap_rmtcall() both as a ping of the remote host, and to obtain the server's UDP port number. This gives us control of the timeout in the initial contact of the host, and lets us skip the portmapper exchange done by clntudp_create().
Line 
1/* Copyright 1999 by the Massachusetts Institute of Technology.
2 *
3 * Permission to use, copy, modify, and distribute this
4 * software and its documentation for any purpose and without
5 * fee is hereby granted, provided that the above copyright
6 * notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting
8 * documentation, and that the name of M.I.T. not be used in
9 * advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission.
11 * M.I.T. makes no representations about the suitability of
12 * this software for any purpose.  It is provided "as is"
13 * without express or implied warranty.
14 */
15
16/* This contains the NFS quota-checking routines. */
17
18static const char rcsid[] = "$Id: nfs.c,v 1.4 1999-10-07 17:06:22 rbasch Exp $";
19
20#include <sys/types.h>
21#include <sys/param.h>
22#include <sys/socket.h>
23#include <sys/time.h>
24
25#include <netinet/in.h>
26
27#include <rpc/rpc.h>
28#ifdef HAVE_RPC_CLNT_SOC_H
29#include <rpc/clnt_soc.h>
30#endif
31#include <rpc/pmap_prot.h>
32#include <rpc/pmap_clnt.h>
33#include <rpcsvc/rquota.h>
34
35#include <netdb.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <unistd.h>
40
41#include "quota.h"
42
43#ifndef GQR_RQUOTA_USES_GQR_RQUOTA
44#define gqr_rquota getquota_rslt_u.gqr_rquota
45#endif
46
47#ifndef GQR_RQUOTA_USES_GQR_STATUS
48#define gqr_status status
49#endif
50
51static int callaurpc(char *host, int prognum, int versnum, int procnum,
52                     xdrproc_t inproc, struct getquota_args *in,
53                     xdrproc_t outproc, struct getquota_rslt *out);
54
55int get_nfs_quota(struct quota_fs *fs, uid_t uid, int verbose)
56{
57  struct getquota_args gq_args;
58  struct getquota_rslt gq_result;
59  struct rquota quota;
60  int status;
61  char *host, *path;
62  double bscale;
63
64  /* If user is root, punt. (I don't know why. This is just what the
65   * old code did. Probably assuming root will be mapped to "nobody"?)
66   */
67  if (getuid() == 0)
68    return -1;
69
70  host = strdup(fs->device);
71  path = strchr(host, ':');
72  if (!path)
73    return -1;
74  *path++ = '\0';
75
76  gq_args.gqa_pathp = path;
77  gq_args.gqa_uid = uid;
78
79  if (callaurpc(host, RQUOTAPROG, RQUOTAVERS,
80                (verbose ? RQUOTAPROC_GETQUOTA : RQUOTAPROC_GETACTIVEQUOTA),
81                xdr_getquota_args, &gq_args,
82                xdr_getquota_rslt, &gq_result) != 0)
83    {
84      free(host);
85      return -1;
86    }
87
88  quota = gq_result.gqr_rquota;
89  switch (gq_result.gqr_status)
90    {
91    case Q_OK:
92      bscale = quota.rq_bsize / 512.0;
93      fs->have_quota = fs->have_blocks = fs->have_files = 1;
94      fs->dqb.dqb_curblocks = quota.rq_curblocks * bscale;
95      fs->dqb.dqb_bsoftlimit = quota.rq_bsoftlimit * bscale;
96      fs->dqb.dqb_bhardlimit = quota.rq_bhardlimit * bscale;
97      fs->dqb.dqb_btimelimit = quota.rq_btimeleft;
98      fs->dqb.dqb_curfiles = quota.rq_curfiles;
99      fs->dqb.dqb_fsoftlimit = quota.rq_fsoftlimit;
100      fs->dqb.dqb_fhardlimit = quota.rq_fhardlimit;
101      fs->dqb.dqb_ftimelimit = quota.rq_ftimeleft;
102
103      if (fs->dqb.dqb_btimelimit)
104        fs->warn_blocks = 1;
105      if (fs->dqb.dqb_ftimelimit)
106        fs->warn_files = 1;
107
108      status = 0;
109      break;
110
111    case Q_NOQUOTA:
112      fs->have_quota = 0;
113      status = -1;
114      break;
115
116    case Q_EPERM:
117      if (verbose)
118        fprintf(stderr, "quota: %s: Permission denied\n", host);
119      status = -1;
120      break;
121
122    default:
123      if (verbose)
124        fprintf(stderr, "quota: %s: Unrecognized status %d\n", host, status);
125      status = -1;
126      break;
127
128    }
129
130  free(host);
131  return status;
132}
133
134static int callaurpc(char *host, int prognum, int versnum, int procnum,
135                     xdrproc_t inproc, struct getquota_args *in,
136                     xdrproc_t outproc, struct getquota_rslt *out)
137{
138  struct sockaddr_in server_addr;
139  struct hostent *hp;
140  struct timeval timeout;
141  CLIENT *client;
142  int socket, status;
143  u_short port;
144  u_long pmap_port;
145  struct pmap map;
146
147  socket = RPC_ANYSOCK;
148  if ((hp = gethostbyname(host)) == NULL)
149    return RPC_UNKNOWNHOST;
150  timeout.tv_usec = 0;
151  timeout.tv_sec = 6;
152  memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
153  server_addr.sin_family = AF_INET;
154
155  /* Ask the remote portmapper for the program's UDP port number.
156   * This also provides a handy ping of the remote host, as we can
157   * thus specify a non-default (shorter) timeout for the portmapper
158   * exchange.
159   */
160  map.pm_prog = prognum;
161  map.pm_vers = versnum;
162  map.pm_prot = IPPROTO_UDP;
163  map.pm_port = 0;
164  status = pmap_rmtcall(&server_addr, PMAPPROG, PMAPVERS, PMAPPROC_GETPORT,
165                        xdr_pmap, (caddr_t) &map,
166                        xdr_u_short, (caddr_t) &port,
167                        timeout, &pmap_port);
168  if (status != RPC_SUCCESS)
169    return status;
170
171  /* now really create a udp client handle */
172  server_addr.sin_port = htons(port);
173  if ((client = clntudp_create(&server_addr, prognum,
174                               versnum, timeout, &socket)) == NULL)
175    return rpc_createerr.cf_stat;
176  auth_destroy(client->cl_auth);
177  client->cl_auth = authunix_create_default();
178
179  timeout.tv_usec = 0;
180  timeout.tv_sec = 25;
181  status = clnt_call(client, procnum, inproc, (caddr_t) in, outproc,
182                     (caddr_t) out, timeout);
183
184  auth_destroy(client->cl_auth);
185  clnt_destroy(client);
186  return status;
187}
Note: See TracBrowser for help on using the repository browser.