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