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