/* Copyright 1999 by the Massachusetts Institute of Technology. * * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in * advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" * without express or implied warranty. */ #ifdef ENABLE_NFS /* This contains the NFS quota-checking routines. */ static const char rcsid[] = "$Id: nfs.c,v 1.4 1999-10-07 17:06:22 rbasch Exp $"; #include #include #include #include #include #include #ifdef HAVE_RPC_CLNT_SOC_H #include #endif #include #include #include #include #include #include #include #include #include "quota.h" #ifndef GQR_RQUOTA_USES_GQR_RQUOTA #define gqr_rquota getquota_rslt_u.gqr_rquota #endif #ifndef GQR_RQUOTA_USES_GQR_STATUS #define gqr_status status #endif static int callaurpc(char *host, int prognum, int versnum, int procnum, xdrproc_t inproc, struct getquota_args *in, xdrproc_t outproc, struct getquota_rslt *out); int get_nfs_quota(struct quota_fs *fs, uid_t uid, int verbose) { struct getquota_args gq_args; struct getquota_rslt gq_result; struct rquota quota; int status; char *host, *path; double bscale; /* If user is root, punt. (I don't know why. This is just what the * old code did. Probably assuming root will be mapped to "nobody"?) */ if (getuid() == 0) return -1; host = strdup(fs->device); path = strchr(host, ':'); if (!path) return -1; *path++ = '\0'; gq_args.gqa_pathp = path; gq_args.gqa_uid = uid; if (callaurpc(host, RQUOTAPROG, RQUOTAVERS, (verbose ? RQUOTAPROC_GETQUOTA : RQUOTAPROC_GETACTIVEQUOTA), xdr_getquota_args, &gq_args, xdr_getquota_rslt, &gq_result) != 0) { free(host); return -1; } quota = gq_result.gqr_rquota; switch (gq_result.gqr_status) { case Q_OK: bscale = quota.rq_bsize / 512.0; fs->have_quota = fs->have_blocks = fs->have_files = 1; fs->dqb.dqb_curblocks = quota.rq_curblocks * bscale; fs->dqb.dqb_bsoftlimit = quota.rq_bsoftlimit * bscale; fs->dqb.dqb_bhardlimit = quota.rq_bhardlimit * bscale; fs->dqb.dqb_btimelimit = quota.rq_btimeleft; fs->dqb.dqb_curfiles = quota.rq_curfiles; fs->dqb.dqb_fsoftlimit = quota.rq_fsoftlimit; fs->dqb.dqb_fhardlimit = quota.rq_fhardlimit; fs->dqb.dqb_ftimelimit = quota.rq_ftimeleft; if (fs->dqb.dqb_btimelimit) fs->warn_blocks = 1; if (fs->dqb.dqb_ftimelimit) fs->warn_files = 1; status = 0; break; case Q_NOQUOTA: fs->have_quota = 0; status = -1; break; case Q_EPERM: if (verbose) fprintf(stderr, "quota: %s: Permission denied\n", host); status = -1; break; default: if (verbose) fprintf(stderr, "quota: %s: Unrecognized status %d\n", host, status); status = -1; break; } free(host); return status; } static int callaurpc(char *host, int prognum, int versnum, int procnum, xdrproc_t inproc, struct getquota_args *in, xdrproc_t outproc, struct getquota_rslt *out) { struct sockaddr_in server_addr; struct hostent *hp; struct timeval timeout; CLIENT *client; int socket, status; u_short port; u_long pmap_port; struct pmap map; socket = RPC_ANYSOCK; if ((hp = gethostbyname(host)) == NULL) return RPC_UNKNOWNHOST; timeout.tv_usec = 0; timeout.tv_sec = 6; memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length); server_addr.sin_family = AF_INET; /* Ask the remote portmapper for the program's UDP port number. * This also provides a handy ping of the remote host, as we can * thus specify a non-default (shorter) timeout for the portmapper * exchange. */ map.pm_prog = prognum; map.pm_vers = versnum; map.pm_prot = IPPROTO_UDP; map.pm_port = 0; status = pmap_rmtcall(&server_addr, PMAPPROG, PMAPVERS, PMAPPROC_GETPORT, xdr_pmap, (caddr_t) &map, xdr_u_short, (caddr_t) &port, timeout, &pmap_port); if (status != RPC_SUCCESS) return status; /* now really create a udp client handle */ server_addr.sin_port = htons(port); if ((client = clntudp_create(&server_addr, prognum, versnum, timeout, &socket)) == NULL) return rpc_createerr.cf_stat; auth_destroy(client->cl_auth); client->cl_auth = authunix_create_default(); timeout.tv_usec = 0; timeout.tv_sec = 25; status = clnt_call(client, procnum, inproc, (caddr_t) in, outproc, (caddr_t) out, timeout); auth_destroy(client->cl_auth); clnt_destroy(client); return status; } #endif /* ENABLE_NFS */