]> git.decadent.org.uk Git - nfs-utils.git/blob - utils/rquotad/rquota_svc.c
update manpages for showmount and mountd
[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
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #ifdef HAVE_TCP_WRAPPER
27 #include "tcpwrapper.h"
28 #endif
29
30 #include <unistd.h>
31 #include <errno.h>
32 #include <rpc/rpc.h>
33 #include "rquota.h"
34 #include <stdlib.h>
35 #include <rpc/pmap_clnt.h>
36 #include <string.h>
37 #include <memory.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <syslog.h>
41 #include <signal.h>
42 #include <getopt.h>
43 #include <rpcmisc.h>
44 #include <nfslib.h>
45
46 #ifdef __STDC__
47 #define SIG_PF void(*)(int)
48 #endif
49
50 static struct option longopts[] =
51 {
52         { "help", 0, 0, 'h' },
53         { "version", 0, 0, 'v' },
54         { "port", 1, 0, 'p' },
55         { NULL, 0, 0, 0 }
56 };
57
58 /*
59  * Global authentication credentials.
60  */
61 struct authunix_parms *unix_cred;
62
63 static void rquotaprog_1(struct svc_req *rqstp, register SVCXPRT *transp)
64 {
65    union {
66       getquota_args rquotaproc_getquota_1_arg;
67       getquota_args rquotaproc_getactivequota_1_arg;
68    } argument;
69    char *result;
70    xdrproc_t xdr_argument, xdr_result;
71    char *(*local)(char *, struct svc_req *);
72
73 #ifdef HAVE_TCP_WRAPPER
74    /* remote host authorization check */
75    if (!check_default("rquotad", svc_getcaller(transp),
76                       rqstp->rq_proc, RQUOTAPROG)) {
77          svcerr_auth (transp, AUTH_FAILED);
78          return;
79    }
80 #endif
81
82    /*
83     * Don't bother authentication for NULLPROC.
84     */
85    if (rqstp->rq_proc == NULLPROC) {
86       (void) svc_sendreply(transp, (xdrproc_t) xdr_void, (char *)NULL);
87       return;
88    }
89
90    /*
91     * First get authentication.
92     */
93    switch (rqstp->rq_cred.oa_flavor) {
94       case AUTH_UNIX:
95          unix_cred = (struct authunix_parms *)rqstp->rq_clntcred;
96          break;
97       case AUTH_NULL:
98       default:
99          svcerr_weakauth(transp);
100          return;
101    }
102
103    switch (rqstp->rq_proc) {
104       case RQUOTAPROC_GETQUOTA:
105          xdr_argument = (xdrproc_t) xdr_getquota_args;
106          xdr_result = (xdrproc_t) xdr_getquota_rslt;
107          local = (char *(*)(char *, struct svc_req *)) rquotaproc_getquota_1_svc;
108          break;
109
110       case RQUOTAPROC_GETACTIVEQUOTA:
111          xdr_argument = (xdrproc_t) xdr_getquota_args;
112          xdr_result = (xdrproc_t) xdr_getquota_rslt;
113          local = (char *(*)(char *, struct svc_req *)) rquotaproc_getactivequota_1_svc;
114          break;
115
116       default:
117          svcerr_noproc(transp);
118          return;
119    }
120
121    (void) memset((char *)&argument, 0, sizeof (argument));
122    if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) {
123       svcerr_decode(transp);
124       return;
125    }
126    result = (*local)((char *)&argument, rqstp);
127    if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
128       svcerr_systemerr(transp);
129    }
130
131    if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) {
132       syslog(LOG_ERR, "unable to free arguments");
133       exit(1);
134    }
135    return;
136 }
137
138 static void rquotaprog_2(struct svc_req *rqstp, register SVCXPRT *transp)
139 {
140    union {
141       ext_getquota_args rquotaproc_getquota_2_arg;
142       ext_getquota_args rquotaproc_getactivequota_2_arg;
143    } argument;
144    char *result;
145    xdrproc_t xdr_argument, xdr_result;
146    char *(*local)(char *, struct svc_req *);
147
148 #ifdef HAVE_TCP_WRAPPER
149    /* remote host authorization check */
150    if (!check_default("rquotad", svc_getcaller(transp),
151                       rqstp->rq_proc, RQUOTAPROG)) {
152          svcerr_auth (transp, AUTH_FAILED);
153          return;
154    }
155 #endif
156
157    /*
158     * Don't bother authentication for NULLPROC.
159     */
160    if (rqstp->rq_proc == NULLPROC) {
161       (void) svc_sendreply(transp, (xdrproc_t) xdr_void, (char *)NULL);
162       return;
163    }
164
165    /*
166     * First get authentication.
167     */
168    switch (rqstp->rq_cred.oa_flavor) {
169       case AUTH_UNIX:
170          unix_cred = (struct authunix_parms *)rqstp->rq_clntcred;
171          break;
172       case AUTH_NULL:
173       default:
174          svcerr_weakauth(transp);
175          return;
176    }
177
178    switch (rqstp->rq_proc) {
179       case RQUOTAPROC_GETQUOTA:
180          xdr_argument = (xdrproc_t) xdr_ext_getquota_args;
181          xdr_result = (xdrproc_t) xdr_getquota_rslt;
182          local = (char *(*)(char *, struct svc_req *)) rquotaproc_getquota_2_svc;
183          break;
184
185       case RQUOTAPROC_GETACTIVEQUOTA:
186          xdr_argument = (xdrproc_t) xdr_ext_getquota_args;
187          xdr_result = (xdrproc_t) xdr_getquota_rslt;
188          local = (char *(*)(char *, struct svc_req *)) rquotaproc_getactivequota_2_svc;
189          break;
190
191       default:
192          svcerr_noproc(transp);
193          return;
194    }
195
196    (void) memset((char *)&argument, 0, sizeof (argument));
197    if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) {
198       svcerr_decode(transp);
199       return;
200    }
201    result = (*local)((char *)&argument, rqstp);
202    if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
203       svcerr_systemerr(transp);
204    }
205
206    if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) {
207       syslog(LOG_ERR, "unable to free arguments");
208       exit(1);
209    }
210    return;
211 }
212
213 static void
214 usage(const char *prog, int n)
215 {
216   fprintf(stderr, "Usage: %s [-p|--port port] [-h|-?|--help] [-v|--version]\n", prog);
217   exit(n);
218 }
219
220 static void
221 killer (int sig)
222 {
223    (void) pmap_unset(RQUOTAPROG, RQUOTAVERS);
224    (void) pmap_unset(RQUOTAPROG, EXT_RQUOTAVERS);
225    syslog(LOG_ERR, "caught signal %d, un-registering and exiting.", sig);
226 }
227
228 int main(int argc, char **argv)
229 {
230    register SVCXPRT *transp;
231    int c;
232    int port = 0;
233    struct sigaction sa;
234
235    (void) pmap_unset(RQUOTAPROG, RQUOTAVERS);
236    (void) pmap_unset(RQUOTAPROG, EXT_RQUOTAVERS);
237
238    openlog("rquota", LOG_PID, LOG_DAEMON);
239
240    while ((c = getopt_long(argc, argv, "hp:v", longopts, NULL)) != EOF) {
241      switch (c) {
242      case '?':
243      case 'h':
244        usage(argv[0], 0);
245        break;
246      case 'p':
247        port = atoi(optarg);
248        if (port < 1 || port > 65535) {
249          fprintf(stderr, "%s: bad port number: %s\n",
250                  argv[0], optarg);
251          usage(argv[0], 1);
252        }
253        break;
254      case 'v':
255        printf("rquotad %s\n", VERSION);
256        exit(0);
257      default:
258        usage(argv[0], 1);
259      }
260    }
261
262    if (chdir(NFS_STATEDIR)) {
263      fprintf(stderr, "%s: chdir(%s) failed: %s\n",
264              argv [0], NFS_STATEDIR, strerror(errno));
265
266      exit(1);
267    }
268
269    /* WARNING: the following works on Linux and SysV, but not BSD! */
270    sa.sa_handler = SIG_IGN;
271    sa.sa_flags = 0;
272    sigemptyset(&sa.sa_mask);
273    sigaction(SIGCHLD, &sa, NULL);
274
275    sa.sa_handler = killer;
276    sigaction(SIGHUP, &sa, NULL);
277    sigaction(SIGINT, &sa, NULL);
278    sigaction(SIGTERM, &sa, NULL);
279
280    if (port)
281      transp = svcudp_create(makesock(port, IPPROTO_UDP));
282    else
283      transp = svcudp_create(svcudp_socket (RQUOTAPROG, 1));
284    if (transp == NULL) {
285       syslog(LOG_ERR, "cannot create udp service.");
286       exit(1);
287    }
288    if (!svc_register(transp, RQUOTAPROG, RQUOTAVERS, rquotaprog_1, IPPROTO_UDP)) {
289       syslog(LOG_ERR, "unable to register (RQUOTAPROG, RQUOTAVERS, udp).");
290       exit(1);
291    }
292    if (!svc_register(transp, RQUOTAPROG, EXT_RQUOTAVERS, rquotaprog_2, IPPROTO_UDP)) {
293       syslog(LOG_ERR, "unable to register (RQUOTAPROG, EXT_RQUOTAVERS, udp).");
294       exit(1);
295    }
296
297    daemon(1,1);
298    svc_run();
299
300    syslog(LOG_ERR, "svc_run returned");
301    exit(1);
302    /* NOTREACHED */
303 }