sprayd.c revision 50476
113240Sgraichen/*
213240Sgraichen * Copyright (c) 1994 Christos Zoulas
313240Sgraichen * All rights reserved.
413240Sgraichen *
513240Sgraichen * Redistribution and use in source and binary forms, with or without
613240Sgraichen * modification, are permitted provided that the following conditions
713240Sgraichen * are met:
813240Sgraichen * 1. Redistributions of source code must retain the above copyright
913240Sgraichen *    notice, this list of conditions and the following disclaimer.
1013240Sgraichen * 2. Redistributions in binary form must reproduce the above copyright
1113240Sgraichen *    notice, this list of conditions and the following disclaimer in the
1213240Sgraichen *    documentation and/or other materials provided with the distribution.
1313240Sgraichen * 3. All advertising materials mentioning features or use of this software
1413240Sgraichen *    must display the following acknowledgement:
1513240Sgraichen *	This product includes software developed by Christos Zoulas.
1613240Sgraichen * 4. The name of the author may not be used to endorse or promote products
1713240Sgraichen *    derived from this software without specific prior written permission.
1813240Sgraichen *
1913240Sgraichen * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2013240Sgraichen * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2113240Sgraichen * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2213240Sgraichen * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2313240Sgraichen * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2413240Sgraichen * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2513240Sgraichen * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2613240Sgraichen * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2713240Sgraichen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2813240Sgraichen * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2913240Sgraichen */
3013240Sgraichen
3113240Sgraichen#ifndef lint
3231489Scharnierstatic const char rcsid[] =
3350476Speter  "$FreeBSD: head/libexec/rpc.sprayd/sprayd.c 50476 1999-08-28 00:22:10Z peter $";
3413240Sgraichen#endif /* not lint */
3513240Sgraichen
3631489Scharnier#include <rpc/rpc.h>
3731489Scharnier#include <rpc/pmap_clnt.h>
3831489Scharnier#include <rpcsvc/spray.h>
3931489Scharnier#include <signal.h>
4013240Sgraichen#include <stdio.h>
4113240Sgraichen#include <stdlib.h>
4213240Sgraichen#include <sys/time.h>
4313240Sgraichen#include <sys/socket.h>
4413240Sgraichen#include <syslog.h>
4531489Scharnier#include <unistd.h>
4613240Sgraichen
4713240Sgraichenstatic void spray_service __P((struct svc_req *, SVCXPRT *));
4813240Sgraichen
4913240Sgraichenstatic int from_inetd = 1;
5013240Sgraichen
5113240Sgraichen#define	timersub(tvp, uvp, vvp)						\
5213240Sgraichen	do {								\
5313240Sgraichen		(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec;		\
5413240Sgraichen		(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec;	\
5513240Sgraichen		if ((vvp)->tv_usec < 0) {				\
5613240Sgraichen			(vvp)->tv_sec--;				\
5713240Sgraichen			(vvp)->tv_usec += 1000000;			\
5813240Sgraichen		}							\
5913240Sgraichen	} while (0)
6013240Sgraichen
6113240Sgraichen#define TIMEOUT 120
6213240Sgraichen
6313240Sgraichenvoid
6413240Sgraichencleanup()
6513240Sgraichen{
6613240Sgraichen	(void) pmap_unset(SPRAYPROG, SPRAYVERS);
6713240Sgraichen	exit(0);
6813240Sgraichen}
6913240Sgraichen
7013240Sgraichenvoid
7113240Sgraichendie()
7213240Sgraichen{
7313240Sgraichen	exit(0);
7413240Sgraichen}
7513240Sgraichen
7613240Sgraichenint
7713240Sgraichenmain(argc, argv)
7813240Sgraichen	int argc;
7913240Sgraichen	char *argv[];
8013240Sgraichen{
8113240Sgraichen	SVCXPRT *transp;
8213240Sgraichen	int sock = 0;
8313240Sgraichen	int proto = 0;
8413240Sgraichen	struct sockaddr_in from;
8513240Sgraichen	int fromlen;
8613240Sgraichen
8713240Sgraichen	/*
8813240Sgraichen	 * See if inetd started us
8913240Sgraichen	 */
9013240Sgraichen	fromlen = sizeof(from);
9113240Sgraichen	if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0) {
9213240Sgraichen		from_inetd = 0;
9313240Sgraichen		sock = RPC_ANYSOCK;
9413240Sgraichen		proto = IPPROTO_UDP;
9513240Sgraichen	}
9613240Sgraichen
9713240Sgraichen	if (!from_inetd) {
9813240Sgraichen		daemon(0, 0);
9913240Sgraichen
10013240Sgraichen		(void) pmap_unset(SPRAYPROG, SPRAYVERS);
10113240Sgraichen
10213240Sgraichen		(void) signal(SIGINT, cleanup);
10313240Sgraichen		(void) signal(SIGTERM, cleanup);
10413240Sgraichen		(void) signal(SIGHUP, cleanup);
10513240Sgraichen	} else {
10613240Sgraichen		(void) signal(SIGALRM, die);
10713240Sgraichen		alarm(TIMEOUT);
10813240Sgraichen	}
10913240Sgraichen
11013240Sgraichen	openlog("rpc.sprayd", LOG_CONS|LOG_PID, LOG_DAEMON);
11113240Sgraichen
11213240Sgraichen	transp = svcudp_create(sock);
11313240Sgraichen	if (transp == NULL) {
11431489Scharnier		syslog(LOG_ERR, "cannot create udp service");
11513240Sgraichen		return 1;
11613240Sgraichen	}
11713240Sgraichen	if (!svc_register(transp, SPRAYPROG, SPRAYVERS, spray_service, proto)) {
11813240Sgraichen		syslog(LOG_ERR,
11931489Scharnier		    "unable to register (SPRAYPROG, SPRAYVERS, %s)",
12013240Sgraichen		    proto ? "udp" : "(inetd)");
12113240Sgraichen		return 1;
12213240Sgraichen	}
12313240Sgraichen
12413240Sgraichen	svc_run();
12513240Sgraichen	syslog(LOG_ERR, "svc_run returned");
12613240Sgraichen	return 1;
12713240Sgraichen}
12813240Sgraichen
12913240Sgraichen
13013240Sgraichenstatic void
13113240Sgraichenspray_service(rqstp, transp)
13213240Sgraichen	struct svc_req *rqstp;
13313240Sgraichen	SVCXPRT *transp;
13413240Sgraichen{
13513240Sgraichen	static spraycumul scum;
13613240Sgraichen	static struct timeval clear, get;
13713240Sgraichen
13813240Sgraichen	switch (rqstp->rq_proc) {
13913240Sgraichen	case SPRAYPROC_CLEAR:
14013240Sgraichen		scum.counter = 0;
14113240Sgraichen		(void) gettimeofday(&clear, 0);
14213240Sgraichen		/*FALLTHROUGH*/
14313240Sgraichen
14413240Sgraichen	case NULLPROC:
14513240Sgraichen		(void)svc_sendreply(transp, xdr_void, (char *)NULL);
14613240Sgraichen		return;
14713240Sgraichen
14813240Sgraichen	case SPRAYPROC_SPRAY:
14913240Sgraichen		scum.counter++;
15013240Sgraichen		return;
15113240Sgraichen
15213240Sgraichen	case SPRAYPROC_GET:
15313240Sgraichen		(void) gettimeofday(&get, 0);
15413240Sgraichen		timersub(&get, &clear, &get);
15513240Sgraichen		scum.clock.sec = get.tv_sec;
15613240Sgraichen		scum.clock.usec = get.tv_usec;
15713240Sgraichen		break;
15813240Sgraichen
15913240Sgraichen	default:
16013240Sgraichen		svcerr_noproc(transp);
16113240Sgraichen		return;
16213240Sgraichen	}
16313240Sgraichen
16413240Sgraichen	if (!svc_sendreply(transp, xdr_spraycumul, (caddr_t)&scum)) {
16513240Sgraichen		svcerr_systemerr(transp);
16613240Sgraichen		syslog(LOG_ERR, "bad svc_sendreply");
16713240Sgraichen	}
16813240Sgraichen}
169