Home | History | Annotate | Line # | Download | only in rpc.rquotad
rquotad.c revision 1.27
      1  1.27   bouyer /*	$NetBSD: rquotad.c,v 1.27 2011/03/24 17:05:43 bouyer Exp $	*/
      2   1.7  thorpej 
      3   1.1  deraadt /*
      4  1.19   bouyer  * by Manuel Bouyer (bouyer (at) ensta.fr). Public domain.
      5   1.1  deraadt  */
      6   1.1  deraadt 
      7   1.9      mrg #include <sys/cdefs.h>
      8   1.9      mrg #ifndef lint
      9  1.27   bouyer __RCSID("$NetBSD: rquotad.c,v 1.27 2011/03/24 17:05:43 bouyer Exp $");
     10   1.9      mrg #endif
     11   1.9      mrg 
     12   1.1  deraadt #include <sys/param.h>
     13   1.1  deraadt #include <sys/types.h>
     14   1.1  deraadt #include <sys/mount.h>
     15   1.1  deraadt #include <sys/file.h>
     16   1.1  deraadt #include <sys/stat.h>
     17   1.9      mrg #include <sys/socket.h>
     18   1.5      jtc #include <signal.h>
     19   1.1  deraadt 
     20   1.1  deraadt #include <stdio.h>
     21   1.1  deraadt #include <fstab.h>
     22   1.1  deraadt #include <ctype.h>
     23   1.1  deraadt #include <stdlib.h>
     24   1.1  deraadt #include <string.h>
     25   1.1  deraadt #include <pwd.h>
     26   1.1  deraadt #include <grp.h>
     27   1.1  deraadt #include <errno.h>
     28   1.9      mrg #include <unistd.h>
     29   1.1  deraadt 
     30   1.1  deraadt #include <syslog.h>
     31   1.1  deraadt 
     32  1.27   bouyer #include <quota/quotaprop.h>
     33  1.27   bouyer #include <quota/quota.h>
     34   1.1  deraadt #include <rpc/rpc.h>
     35   1.1  deraadt #include <rpcsvc/rquota.h>
     36   1.2      cgd #include <arpa/inet.h>
     37   1.1  deraadt 
     38  1.15     fvdl void rquota_service(struct svc_req *request, SVCXPRT *transp);
     39  1.20   bouyer void ext_rquota_service(struct svc_req *request, SVCXPRT *transp);
     40  1.20   bouyer void sendquota(struct svc_req *request, int vers, SVCXPRT *transp);
     41  1.15     fvdl void cleanup(int);
     42  1.15     fvdl int main(int, char *[]);
     43   1.1  deraadt 
     44   1.4  mycroft int from_inetd = 1;
     45   1.4  mycroft 
     46  1.27   bouyer static uint32_t
     47  1.27   bouyer qlim2rqlim(uint64_t lim)
     48  1.27   bouyer {
     49  1.27   bouyer 	if (lim == UQUAD_MAX)
     50  1.27   bouyer 		return 0;
     51  1.27   bouyer 	else
     52  1.27   bouyer 		return (lim + 1);
     53  1.27   bouyer }
     54  1.27   bouyer 
     55   1.4  mycroft void
     56  1.15     fvdl cleanup(int dummy)
     57   1.4  mycroft {
     58  1.11      mrg 
     59  1.15     fvdl 	(void)rpcb_unset(RQUOTAPROG, RQUOTAVERS, NULL);
     60  1.20   bouyer 	(void)rpcb_unset(RQUOTAPROG, EXT_RQUOTAVERS, NULL);
     61   1.4  mycroft 	exit(0);
     62   1.4  mycroft }
     63   1.4  mycroft 
     64   1.1  deraadt int
     65  1.15     fvdl main(int argc, char *argv[])
     66   1.1  deraadt {
     67   1.4  mycroft 	SVCXPRT *transp;
     68  1.15     fvdl 	struct sockaddr_storage from;
     69  1.23      mrg 	socklen_t fromlen;
     70   1.1  deraadt 
     71   1.3  mycroft 	fromlen = sizeof(from);
     72  1.15     fvdl 	if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0)
     73   1.1  deraadt 		from_inetd = 0;
     74   1.3  mycroft 
     75   1.1  deraadt 	if (!from_inetd) {
     76   1.1  deraadt 		daemon(0, 0);
     77   1.3  mycroft 
     78  1.16     fvdl 		(void) rpcb_unset(RQUOTAPROG, RQUOTAVERS, NULL);
     79  1.20   bouyer 		(void) rpcb_unset(RQUOTAPROG, EXT_RQUOTAVERS, NULL);
     80   1.4  mycroft 		(void) signal(SIGINT, cleanup);
     81   1.4  mycroft 		(void) signal(SIGTERM, cleanup);
     82   1.4  mycroft 		(void) signal(SIGHUP, cleanup);
     83   1.1  deraadt 	}
     84   1.3  mycroft 
     85  1.13      mrg 	openlog("rpc.rquotad", LOG_PID, LOG_DAEMON);
     86   1.1  deraadt 
     87   1.1  deraadt 	/* create and register the service */
     88  1.15     fvdl 	if (from_inetd) {
     89  1.15     fvdl 		transp = svc_dg_create(0, 0, 0);
     90  1.15     fvdl 		if (transp == NULL) {
     91  1.15     fvdl 			syslog(LOG_ERR, "couldn't create udp service.");
     92  1.15     fvdl 			exit(1);
     93  1.15     fvdl 		}
     94  1.15     fvdl 		if (!svc_reg(transp, RQUOTAPROG, RQUOTAVERS, rquota_service,
     95  1.15     fvdl 		    NULL)) {
     96  1.15     fvdl 			syslog(LOG_ERR,
     97  1.15     fvdl 			    "unable to register (RQUOTAPROG, RQUOTAVERS).");
     98  1.15     fvdl 			exit(1);
     99  1.15     fvdl 		}
    100  1.20   bouyer 		if (!svc_reg(transp, RQUOTAPROG, EXT_RQUOTAVERS,
    101  1.20   bouyer 		    ext_rquota_service, NULL)) {
    102  1.20   bouyer 			syslog(LOG_ERR,
    103  1.20   bouyer 			    "unable to register (RQUOTAPROG, EXT_RQUOTAVERS).");
    104  1.20   bouyer 			exit(1);
    105  1.20   bouyer 		}
    106  1.15     fvdl 	} else {
    107  1.15     fvdl 		if (!svc_create(rquota_service, RQUOTAPROG, RQUOTAVERS, "udp")){
    108  1.15     fvdl 			syslog(LOG_ERR,
    109  1.15     fvdl 			    "unable to create (RQUOTAPROG, RQUOTAVERS).");
    110  1.15     fvdl 			exit(1);
    111  1.15     fvdl 		}
    112  1.20   bouyer 		if (!svc_create(ext_rquota_service, RQUOTAPROG,
    113  1.20   bouyer 		    EXT_RQUOTAVERS, "udp")){
    114  1.20   bouyer 			syslog(LOG_ERR,
    115  1.20   bouyer 			    "unable to create (RQUOTAPROG, EXT_RQUOTAVERS).");
    116  1.20   bouyer 			exit(1);
    117  1.20   bouyer 		}
    118   1.1  deraadt 	}
    119   1.4  mycroft 
    120   1.1  deraadt 	svc_run();
    121   1.4  mycroft 	syslog(LOG_ERR, "svc_run returned");
    122   1.4  mycroft 	exit(1);
    123   1.1  deraadt }
    124   1.1  deraadt 
    125   1.1  deraadt void
    126  1.15     fvdl rquota_service(struct svc_req *request, SVCXPRT *transp)
    127   1.1  deraadt {
    128   1.1  deraadt 	switch (request->rq_proc) {
    129   1.1  deraadt 	case NULLPROC:
    130   1.4  mycroft 		(void)svc_sendreply(transp, xdr_void, (char *)NULL);
    131   1.1  deraadt 		break;
    132   1.4  mycroft 
    133   1.1  deraadt 	case RQUOTAPROC_GETQUOTA:
    134   1.1  deraadt 	case RQUOTAPROC_GETACTIVEQUOTA:
    135  1.20   bouyer 		sendquota(request, RQUOTAVERS, transp);
    136  1.20   bouyer 		break;
    137  1.20   bouyer 
    138  1.20   bouyer 	default:
    139  1.20   bouyer 		svcerr_noproc(transp);
    140  1.20   bouyer 		break;
    141  1.20   bouyer 	}
    142  1.20   bouyer 	if (from_inetd)
    143  1.20   bouyer 		exit(0);
    144  1.20   bouyer }
    145  1.20   bouyer 
    146  1.20   bouyer void
    147  1.20   bouyer ext_rquota_service(struct svc_req *request, SVCXPRT *transp)
    148  1.20   bouyer {
    149  1.20   bouyer 	switch (request->rq_proc) {
    150  1.20   bouyer 	case NULLPROC:
    151  1.20   bouyer 		(void)svc_sendreply(transp, xdr_void, (char *)NULL);
    152  1.20   bouyer 		break;
    153  1.20   bouyer 
    154  1.20   bouyer 	case RQUOTAPROC_GETQUOTA:
    155  1.20   bouyer 	case RQUOTAPROC_GETACTIVEQUOTA:
    156  1.20   bouyer 		sendquota(request, EXT_RQUOTAVERS, transp);
    157   1.1  deraadt 		break;
    158   1.4  mycroft 
    159   1.1  deraadt 	default:
    160   1.4  mycroft 		svcerr_noproc(transp);
    161   1.1  deraadt 		break;
    162   1.1  deraadt 	}
    163   1.4  mycroft 	if (from_inetd)
    164   1.4  mycroft 		exit(0);
    165   1.1  deraadt }
    166   1.1  deraadt 
    167   1.1  deraadt /* read quota for the specified id, and send it */
    168   1.1  deraadt void
    169  1.20   bouyer sendquota(struct svc_req *request, int vers, SVCXPRT *transp)
    170   1.1  deraadt {
    171   1.1  deraadt 	struct getquota_args getq_args;
    172  1.20   bouyer 	struct ext_getquota_args ext_getq_args;
    173   1.1  deraadt 	struct getquota_rslt getq_rslt;
    174  1.27   bouyer 	struct ufs_quota_entry qe[QUOTA_NLIMITS];
    175  1.27   bouyer 	const char *class;
    176   1.1  deraadt 	struct timeval timev;
    177   1.1  deraadt 
    178  1.12    perry 	memset((char *)&getq_args, 0, sizeof(getq_args));
    179  1.21   bouyer 	memset((char *)&ext_getq_args, 0, sizeof(ext_getq_args));
    180  1.20   bouyer 	switch (vers) {
    181  1.20   bouyer 	case RQUOTAVERS:
    182  1.20   bouyer 		if (!svc_getargs(transp, xdr_getquota_args,
    183  1.20   bouyer 		    (caddr_t)&getq_args)) {
    184  1.20   bouyer 			svcerr_decode(transp);
    185  1.20   bouyer 			return;
    186  1.20   bouyer 		}
    187  1.20   bouyer 		ext_getq_args.gqa_pathp = getq_args.gqa_pathp;
    188  1.20   bouyer 		ext_getq_args.gqa_id = getq_args.gqa_uid;
    189  1.20   bouyer 		ext_getq_args.gqa_type = RQUOTA_USRQUOTA;
    190  1.20   bouyer 		break;
    191  1.20   bouyer 	case EXT_RQUOTAVERS:
    192  1.20   bouyer 		if (!svc_getargs(transp, xdr_ext_getquota_args,
    193  1.20   bouyer 		    (caddr_t)&ext_getq_args)) {
    194  1.20   bouyer 			svcerr_decode(transp);
    195  1.20   bouyer 			return;
    196  1.20   bouyer 		}
    197  1.20   bouyer 		break;
    198   1.1  deraadt 	}
    199  1.25   bouyer 	switch (ext_getq_args.gqa_type) {
    200  1.25   bouyer 	case RQUOTA_USRQUOTA:
    201  1.27   bouyer 		class = QUOTADICT_CLASS_USER;
    202  1.25   bouyer 		break;
    203  1.25   bouyer 	case RQUOTA_GRPQUOTA:
    204  1.27   bouyer 		class = QUOTADICT_CLASS_GROUP;
    205  1.25   bouyer 		break;
    206  1.25   bouyer 	default:
    207  1.25   bouyer 		getq_rslt.status = Q_NOQUOTA;
    208  1.25   bouyer 		goto out;
    209  1.25   bouyer 	}
    210   1.1  deraadt 	if (request->rq_cred.oa_flavor != AUTH_UNIX) {
    211   1.1  deraadt 		/* bad auth */
    212   1.1  deraadt 		getq_rslt.status = Q_EPERM;
    213  1.27   bouyer 	} else if (!getufsquota(ext_getq_args.gqa_pathp, qe,
    214  1.27   bouyer 	    ext_getq_args.gqa_id, class)) {
    215   1.4  mycroft 		/* failed, return noquota */
    216   1.4  mycroft 		getq_rslt.status = Q_NOQUOTA;
    217   1.1  deraadt 	} else {
    218   1.1  deraadt 		gettimeofday(&timev, NULL);
    219   1.1  deraadt 		getq_rslt.status = Q_OK;
    220   1.1  deraadt 		getq_rslt.getquota_rslt_u.gqr_rquota.rq_active = TRUE;
    221   1.1  deraadt 		getq_rslt.getquota_rslt_u.gqr_rquota.rq_bsize = DEV_BSIZE;
    222   1.1  deraadt 		getq_rslt.getquota_rslt_u.gqr_rquota.rq_bhardlimit =
    223  1.27   bouyer 		    qlim2rqlim(qe[QUOTA_LIMIT_BLOCK].ufsqe_hardlimit);
    224   1.1  deraadt 		getq_rslt.getquota_rslt_u.gqr_rquota.rq_bsoftlimit =
    225  1.27   bouyer 		    qlim2rqlim(qe[QUOTA_LIMIT_BLOCK].ufsqe_softlimit);
    226   1.1  deraadt 		getq_rslt.getquota_rslt_u.gqr_rquota.rq_curblocks =
    227  1.27   bouyer 		    qe[QUOTA_LIMIT_BLOCK].ufsqe_cur;
    228   1.1  deraadt 		getq_rslt.getquota_rslt_u.gqr_rquota.rq_fhardlimit =
    229  1.27   bouyer 		    qlim2rqlim(qe[QUOTA_LIMIT_FILE].ufsqe_hardlimit);
    230   1.1  deraadt 		getq_rslt.getquota_rslt_u.gqr_rquota.rq_fsoftlimit =
    231  1.27   bouyer 		    qlim2rqlim(qe[QUOTA_LIMIT_FILE].ufsqe_softlimit);
    232   1.1  deraadt 		getq_rslt.getquota_rslt_u.gqr_rquota.rq_curfiles =
    233  1.27   bouyer 		    qe[QUOTA_LIMIT_FILE].ufsqe_cur;
    234   1.1  deraadt 		getq_rslt.getquota_rslt_u.gqr_rquota.rq_btimeleft =
    235  1.27   bouyer 		    qe[QUOTA_LIMIT_BLOCK].ufsqe_time - timev.tv_sec;
    236   1.1  deraadt 		getq_rslt.getquota_rslt_u.gqr_rquota.rq_ftimeleft =
    237  1.27   bouyer 		    qe[QUOTA_LIMIT_FILE].ufsqe_time - timev.tv_sec;
    238   1.1  deraadt 	}
    239  1.25   bouyer out:
    240  1.10    lukem 	if (!svc_sendreply(transp, xdr_getquota_rslt, (char *)&getq_rslt))
    241   1.4  mycroft 		svcerr_systemerr(transp);
    242   1.4  mycroft 	if (!svc_freeargs(transp, xdr_getquota_args, (caddr_t)&getq_args)) {
    243   1.4  mycroft 		syslog(LOG_ERR, "unable to free arguments");
    244   1.4  mycroft 		exit(1);
    245   1.4  mycroft 	}
    246   1.1  deraadt }
    247