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