]> git.decadent.org.uk Git - nfs-utils.git/blob - utils/rquotad/rquota_svc.c
2001-03-10 Tavis Barr <tavis@boole.isetr.columbia.edu>
[nfs-utils.git] / utils / rquotad / rquota_svc.c
1 /*
2  * QUOTA    An implementation of the diskquota system for the LINUX
3  *          operating system. QUOTA is implemented using the BSD systemcall
4  *          interface as the means of communication with the user level.
5  *          Should work for all filesystems because of integration into the
6  *          VFS layer of the operating system.
7  *          This is based on the Melbourne quota system wich uses both user and
8  *          group quota files.
9  *
10  *          This part accepts the rquota rpc-requests.
11  *
12  * Version: $Id: rquota_svc.c,v 2.6 1996/11/17 16:59:46 mvw Exp mvw $
13  *
14  * Author:  Marco van Wieringen <mvw@planets.elm.net>
15  *
16  *          This program is free software; you can redistribute it and/or
17  *          modify it under the terms of the GNU General Public License
18  *          as published by the Free Software Foundation; either version
19  *          2 of the License, or (at your option) any later version.
20  */
21 #include "config.h"
22
23 #ifdef HAVE_TCP_WRAPPER
24 #include "tcpwrapper.h"
25 #endif
26
27 #include <unistd.h>
28 #include <rpc/rpc.h>
29 #include "rquota.h"
30 #include <stdlib.h>
31 #include <rpc/pmap_clnt.h>
32 #include <string.h>
33 #include <memory.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <syslog.h>
37 #include <signal.h>
38 #include <getopt.h>
39 #include <rpcmisc.h>
40
41 #ifdef __STDC__
42 #define SIG_PF void(*)(int)
43 #endif
44
45 extern getquota_rslt *rquotaproc_getquota_1(getquota_args *argp,
46                                             struct svc_req *rqstp);
47 extern getquota_rslt *rquotaproc_getactivequota_1(getquota_args *argp,
48                                                   struct svc_req *rqstp);
49 extern getquota_rslt *rquotaproc_getquota_2(ext_getquota_args *argp,
50                                             struct svc_req *rqstp);
51 extern getquota_rslt *rquotaproc_getactivequota_2(ext_getquota_args *argp,
52                                                   struct svc_req *rqstp);
53
54 static struct option longopts[] =
55 {
56         { "help", 0, 0, 'h' },
57         { "version", 0, 0, 'v' },
58         { "port", 1, 0, 'p' },
59         { NULL, 0, 0, 0 }
60 };
61
62 /*
63  * Global authentication credentials.
64  */
65 struct authunix_parms *unix_cred;
66
67 static void rquotaprog_1(struct svc_req *rqstp, register SVCXPRT *transp)
68 {
69    union {
70       getquota_args rquotaproc_getquota_1_arg;
71       getquota_args rquotaproc_getactivequota_1_arg;
72    } argument;
73    char *result;
74    xdrproc_t xdr_argument, xdr_result;
75    char *(*local)(char *, struct svc_req *);
76
77 #ifdef HAVE_TCP_WRAPPER
78    /* remote host authorization check */
79    if (!check_default("rquotad", svc_getcaller(transp),
80                       rqstp->rq_proc, RQUOTAPROG)) {
81          svcerr_auth (transp, AUTH_FAILED);
82          return;
83    }
84 #endif
85
86    /*
87     * Don't bother authentication for NULLPROC.
88     */
89    if (rqstp->rq_proc == NULLPROC) {
90       (void) svc_sendreply(transp, (xdrproc_t) xdr_void, (char *)NULL);
91       return;
92    }
93
94    /*
95     * First get authentication.
96     */
97    switch (rqstp->rq_cred.oa_flavor) {
98       case AUTH_UNIX:
99          unix_cred = (struct authunix_parms *)rqstp->rq_clntcred;
100          break;
101       case AUTH_NULL:
102       default:
103          svcerr_weakauth(transp);
104          return;
105    }
106
107    switch (rqstp->rq_proc) {
108       case RQUOTAPROC_GETQUOTA:
109          xdr_argument = (xdrproc_t) xdr_getquota_args;
110          xdr_result = (xdrproc_t) xdr_getquota_rslt;
111          local = (char *(*)(char *, struct svc_req *)) rquotaproc_getquota_1;
112          break;
113
114       case RQUOTAPROC_GETACTIVEQUOTA:
115          xdr_argument = (xdrproc_t) xdr_getquota_args;
116          xdr_result = (xdrproc_t) xdr_getquota_rslt;
117          local = (char *(*)(char *, struct svc_req *)) rquotaproc_getactivequota_1;
118          break;
119
120       default:
121          svcerr_noproc(transp);
122          return;
123    }
124
125    (void) memset((char *)&argument, 0, sizeof (argument));
126    if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) {
127       svcerr_decode(transp);
128       return;
129    }
130    result = (*local)((char *)&argument, rqstp);
131    if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
132       svcerr_systemerr(transp);
133    }
134
135    if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) {
136       syslog(LOG_ERR, "unable to free arguments");
137       exit(1);
138    }
139    return;
140 }
141
142 static void rquotaprog_2(struct svc_req *rqstp, register SVCXPRT *transp)
143 {
144    union {
145       ext_getquota_args rquotaproc_getquota_2_arg;
146       ext_getquota_args rquotaproc_getactivequota_2_arg;
147    } argument;
148    char *result;
149    xdrproc_t xdr_argument, xdr_result;
150    char *(*local)(char *, struct svc_req *);
151
152 #ifdef HAVE_TCP_WRAPPER
153    /* remote host authorization check */
154    if (!check_default("rquotad", svc_getcaller(transp),
155                       rqstp->rq_proc, RQUOTAPROG)) {
156          svcerr_auth (transp, AUTH_FAILED);
157          return;
158    }
159 #endif
160
161    /*
162     * Don't bother authentication for NULLPROC.
163     */
164    if (rqstp->rq_proc == NULLPROC) {
165       (void) svc_sendreply(transp, (xdrproc_t) xdr_void, (char *)NULL);
166       return;
167    }
168
169    /*
170     * First get authentication.
171     */
172    switch (rqstp->rq_cred.oa_flavor) {
173       case AUTH_UNIX:
174          unix_cred = (struct authunix_parms *)rqstp->rq_clntcred;
175          break;
176       case AUTH_NULL:
177       default:
178          svcerr_weakauth(transp);
179          return;
180    }
181
182    switch (rqstp->rq_proc) {
183       case RQUOTAPROC_GETQUOTA:
184          xdr_argument = (xdrproc_t) xdr_ext_getquota_args;
185          xdr_result = (xdrproc_t) xdr_getquota_rslt;
186          local = (char *(*)(char *, struct svc_req *)) rquotaproc_getquota_2;
187          break;
188
189       case RQUOTAPROC_GETACTIVEQUOTA:
190          xdr_argument = (xdrproc_t) xdr_ext_getquota_args;
191          xdr_result = (xdrproc_t) xdr_getquota_rslt;
192          local = (char *(*)(char *, struct svc_req *)) rquotaproc_getactivequota_2;
193          break;
194
195       default:
196          svcerr_noproc(transp);
197          return;
198    }
199
200    (void) memset((char *)&argument, 0, sizeof (argument));
201    if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) {
202       svcerr_decode(transp);
203       return;
204    }
205    result = (*local)((char *)&argument, rqstp);
206    if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
207       svcerr_systemerr(transp);
208    }
209
210    if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) {
211       syslog(LOG_ERR, "unable to free arguments");
212       exit(1);
213    }
214    return;
215 }
216
217 static void
218 usage(const char *prog, int n)
219 {
220   fprintf(stderr, "Usage: %s [-p|--port port] [-h|-?|--help] [-v|--version]\n", prog);
221   exit(n);
222 }
223
224 int main(int argc, char **argv)
225 {
226    register SVCXPRT *transp;
227    char c;
228    int port = 0;
229
230    (void) pmap_unset(RQUOTAPROG, RQUOTAVERS);
231    (void) pmap_unset(RQUOTAPROG, EXT_RQUOTAVERS);
232
233    openlog("rquota", LOG_PID, LOG_DAEMON);
234
235    while ((c = getopt_long(argc, argv, "hp:v", longopts, NULL)) != EOF) {
236      switch (c) {
237      case '?':
238      case 'h':
239        usage(argv[0], 0);
240        break;
241      case 'p':
242        port = atoi(optarg);
243        if (port < 1 || port > 65535) {
244          fprintf(stderr, "%s: bad port number: %s\n",
245                  argv[0], optarg);
246          usage(argv[0], 1);
247        }
248        break;
249      case 'v':
250        printf("rquotad %s\n", VERSION);
251        exit(0);
252      default:
253        usage(argv[0], 1);
254      }
255    }
256
257    /* WARNING: the following works on Linux and SysV, but not BSD! */
258    signal(SIGCHLD, SIG_IGN);
259
260    if (port)
261      transp = svcudp_create(makesock(port, IPPROTO_UDP));
262    else
263      transp = svcudp_create(RPC_ANYSOCK);
264    if (transp == NULL) {
265       syslog(LOG_ERR, "cannot create udp service.");
266       exit(1);
267    }
268    if (!svc_register(transp, RQUOTAPROG, RQUOTAVERS, rquotaprog_1, IPPROTO_UDP)) {
269       syslog(LOG_ERR, "unable to register (RQUOTAPROG, RQUOTAVERS, udp).");
270       exit(1);
271    }
272    if (!svc_register(transp, RQUOTAPROG, EXT_RQUOTAVERS, rquotaprog_2, IPPROTO_UDP)) {
273       syslog(LOG_ERR, "unable to register (RQUOTAPROG, EXT_RQUOTAVERS, udp).");
274       exit(1);
275    }
276
277    daemon(1,1);
278    svc_run();
279
280    syslog(LOG_ERR, "svc_run returned");
281    exit(1);
282    /* NOTREACHED */
283 }