1/* 2 * 3 * parts of this are lifted from the bsd quota program and are 4 * therefore under the following copyright: 5 * 6 * Copyright (c) 1980, 1990, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * Robert Elz at The University of Melbourne. 11 * 12 * Ported for AIX (jfs) by Joerg Schumacher (J.Schumacher@tu-bs.de) at the 13 * Technische Universitaet Braunschweig, FRG 14 */ 15 16#ifdef HAVE_CONFIG_H 17#include "config.h" 18#endif /* HAVE_CONFIG_H */ 19 20#if !defined(NO_QUOTA_SUPPORT) && !defined(HAVE_LIBQUOTA) 21#include <stdio.h> 22#include <string.h> 23#include <sys/types.h> 24#include <sys/socket.h> 25#include <sys/param.h> /* for DEV_BSIZE */ 26#include <sys/time.h> /* <rpc/rpc.h> on ultrix doesn't include this */ 27#ifdef HAVE_NETDB_H 28#include <netdb.h> 29#endif /* HAVE_NETDB_H */ 30#include <netinet/in.h> 31#ifndef PORTMAP 32#define PORTMAP 1 33#endif 34#include <rpc/rpc.h> 35#include <rpc/pmap_prot.h> 36#include <rpcsvc/rquota.h> 37 38 39#include <atalk/afp.h> 40#include <atalk/logger.h> 41 42#include "unix.h" 43 44/* lifted (with modifications) from the bsd quota program */ 45static int 46callaurpc(struct vol *vol, 47 u_long prognum, u_long versnum, u_long procnum, 48 xdrproc_t inproc, char *in, 49 xdrproc_t outproc, char *out) 50{ 51 enum clnt_stat clnt_stat; 52 struct timeval tottimeout; 53 54 if (!vol->v_nfsclient) { 55 struct hostent *hp; 56 struct sockaddr_in server_addr; 57 struct timeval timeout; 58 int socket = RPC_ANYSOCK; 59 60 if ((hp = gethostbyname(vol->v_gvs)) == NULL) 61 return ((int) RPC_UNKNOWNHOST); 62 timeout.tv_usec = 0; 63 timeout.tv_sec = 6; 64 memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length); 65 server_addr.sin_family = AF_INET; 66 server_addr.sin_port = 0; 67 68 if ((vol->v_nfsclient = (void *) 69 clntudp_create(&server_addr, prognum, versnum, 70 timeout, &socket)) == NULL) 71 return ((int) rpc_createerr.cf_stat); 72 73 ((CLIENT *) vol->v_nfsclient)->cl_auth = authunix_create_default(); 74 } 75 76 tottimeout.tv_sec = 10; 77 tottimeout.tv_usec = 0; 78 clnt_stat = clnt_call((CLIENT *) vol->v_nfsclient, procnum, 79 inproc, in, outproc, out, tottimeout); 80 return ((int) clnt_stat); 81} 82 83 84/* sunos 4 machines structure things a little differently. */ 85#ifdef USE_OLD_RQUOTA 86#define GQR_STATUS gqr_status 87#define GQR_RQUOTA gqr_rquota 88#else /* USE_OLD_RQUOTA */ 89#define GQR_STATUS status 90#define GQR_RQUOTA getquota_rslt_u.gqr_rquota 91#endif /* USE_OLD_RQUOTA */ 92 93int getnfsquota(struct vol *vol, const int uid, const uint32_t bsize, 94 struct dqblk *dqp) 95{ 96 97 struct getquota_args gq_args; 98 struct getquota_rslt gq_rslt; 99 struct timeval tv; 100 char *hostpath; 101 102 /* figure out the host and path */ 103 if ((hostpath = strchr(vol->v_gvs, ':')) == NULL) { 104 LOG(log_error, logtype_afpd, "can't find hostname for %s", vol->v_gvs); 105 return AFPERR_PARAM; 106 } 107 108 if (*(hostpath + 1) != '/') 109 return AFPERR_PARAM; 110 111 /* separate host from hostpath */ 112 *hostpath = '\0'; 113 114 gq_args.gqa_pathp = hostpath + 1; 115 gq_args.gqa_uid = uid; 116 117 if(callaurpc(vol, RQUOTAPROG, RQUOTAVERS, RQUOTAPROC_GETQUOTA, 118 (xdrproc_t) xdr_getquota_args, (char *) &gq_args, 119 (xdrproc_t) xdr_getquota_rslt, (char *) &gq_rslt) != 0) { 120 LOG(log_info, logtype_afpd, "nfsquota: can't retrieve nfs quota information. \ 121 make sure that rpc.rquotad is running on %s.", vol->v_gvs); 122 *hostpath = ':'; 123 return AFPERR_PARAM; 124 } 125 126 switch (gq_rslt.GQR_STATUS) { 127 case Q_NOQUOTA: 128 break; 129 130 case Q_EPERM: 131 LOG(log_error, logtype_afpd, "nfsquota: quota permission error, host: %s", 132 vol->v_gvs); 133 break; 134 135 case Q_OK: /* we only copy the bits that we need. */ 136 gettimeofday(&tv, NULL); 137 138#if defined(__svr4__) || defined(TRU64) 139 /* why doesn't using bsize work? */ 140#define NFS_BSIZE gq_rslt.GQR_RQUOTA.rq_bsize / DEV_BSIZE 141#else /* __svr4__ || TRU64 */ 142 /* NOTE: linux' rquotad program doesn't currently report the 143 * correct rq_bsize. */ 144 /* NOTE: This is integer division and can introduce rounding errors */ 145#define NFS_BSIZE gq_rslt.GQR_RQUOTA.rq_bsize / bsize 146#endif /* __svr4__ || TRU64 */ 147 148 dqp->dqb_bhardlimit = 149 gq_rslt.GQR_RQUOTA.rq_bhardlimit*NFS_BSIZE; 150 dqp->dqb_bsoftlimit = 151 gq_rslt.GQR_RQUOTA.rq_bsoftlimit*NFS_BSIZE; 152 dqp->dqb_curblocks = 153 gq_rslt.GQR_RQUOTA.rq_curblocks*NFS_BSIZE; 154 155#ifdef ultrix 156 dqp->dqb_bwarn = gq_rslt.GQR_RQUOTA.rq_btimeleft; 157#else /* ultrix */ 158 dqp->dqb_btimelimit = 159 tv.tv_sec + gq_rslt.GQR_RQUOTA.rq_btimeleft; 160#endif /* ultrix */ 161 162 *hostpath = ':'; 163 return AFP_OK; 164 break; 165 166 default: 167 LOG(log_info, logtype_afpd, "bad rpc result, host: %s", vol->v_gvs); 168 break; 169 } 170 171 *hostpath = ':'; 172 return AFPERR_PARAM; 173} 174#endif /* ! NO_QUOTA_SUPPORT && !HAVE_LIBQUOTA */ 175