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