1 /* $NetBSD: sprayd.c,v 1.15 2009/10/21 01:07:46 snj Exp $ */
2
3 /*-
4 * SPDX-License-Identifier: BSD-2-Clause
5 *
6 * Copyright (c) 1994 Christos Zoulas
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <rpc/rpc.h>
31 #include <rpcsvc/spray.h>
32 #include <signal.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <sys/time.h>
36 #include <sys/socket.h>
37 #include <syslog.h>
38 #include <unistd.h>
39
40 static void spray_service(struct svc_req *, SVCXPRT *);
41
42 static int from_inetd = 1;
43
44 #define timersub(tvp, uvp, vvp) \
45 do { \
46 (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
47 (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
48 if ((vvp)->tv_usec < 0) { \
49 (vvp)->tv_sec--; \
50 (vvp)->tv_usec += 1000000; \
51 } \
52 } while (0)
53
54 #define TIMEOUT 120
55
56 static void
cleanup(int sig __unused)57 cleanup(int sig __unused)
58 {
59 (void)rpcb_unset(SPRAYPROG, SPRAYVERS, NULL);
60 exit(0);
61 }
62
63 static void
die(int sig __unused)64 die(int sig __unused)
65 {
66 exit(0);
67 }
68
69 int
main(int argc __unused,char * argv[]__unused)70 main(int argc __unused, char *argv[] __unused)
71 {
72 SVCXPRT *transp;
73 int ok;
74 struct sockaddr_storage from;
75 socklen_t fromlen;
76
77 /*
78 * See if inetd started us
79 */
80 fromlen = sizeof(from);
81 if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0) {
82 from_inetd = 0;
83 }
84
85 if (!from_inetd) {
86 daemon(0, 0);
87
88 (void)rpcb_unset(SPRAYPROG, SPRAYVERS, NULL);
89
90 (void)signal(SIGINT, cleanup);
91 (void)signal(SIGTERM, cleanup);
92 (void)signal(SIGHUP, cleanup);
93 } else {
94 (void)signal(SIGALRM, die);
95 alarm(TIMEOUT);
96 }
97
98 openlog("rpc.sprayd", LOG_PID, LOG_DAEMON);
99
100 if (from_inetd) {
101 transp = svc_tli_create(0, NULL, NULL, 0, 0);
102 if (transp == NULL) {
103 syslog(LOG_ERR, "cannot create udp service.");
104 exit(1);
105 }
106 ok = svc_reg(transp, SPRAYPROG, SPRAYVERS,
107 spray_service, NULL);
108 } else
109 ok = svc_create(spray_service,
110 SPRAYPROG, SPRAYVERS, "udp");
111 if (!ok) {
112 syslog(LOG_ERR,
113 "unable to register (SPRAYPROG, SPRAYVERS, %s)",
114 (!from_inetd)?"udp":"(inetd)");
115 exit(1);
116 }
117
118 svc_run();
119 syslog(LOG_ERR, "svc_run returned");
120 return 1;
121 }
122
123
124 static void
spray_service(struct svc_req * rqstp,SVCXPRT * transp)125 spray_service(struct svc_req *rqstp, SVCXPRT *transp)
126 {
127 static spraycumul scum;
128 static struct timeval clear, get;
129
130 switch (rqstp->rq_proc) {
131 case SPRAYPROC_CLEAR:
132 scum.counter = 0;
133 (void)gettimeofday(&clear, 0);
134 /*FALLTHROUGH*/
135
136 case NULLPROC:
137 (void)svc_sendreply(transp, (xdrproc_t)xdr_void, NULL);
138 return;
139
140 case SPRAYPROC_SPRAY:
141 scum.counter++;
142 return;
143
144 case SPRAYPROC_GET:
145 (void)gettimeofday(&get, 0);
146 timersub(&get, &clear, &get);
147 scum.clock.sec = get.tv_sec;
148 scum.clock.usec = get.tv_usec;
149 break;
150
151 default:
152 svcerr_noproc(transp);
153 return;
154 }
155
156 if (!svc_sendreply(transp, (xdrproc_t)xdr_spraycumul, &scum)) {
157 svcerr_systemerr(transp);
158 syslog(LOG_WARNING, "bad svc_sendreply");
159 }
160 }
161