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$"; 3413240Sgraichen#endif /* not lint */ 3513240Sgraichen 3631489Scharnier#include <rpc/rpc.h> 3731489Scharnier#include <rpcsvc/spray.h> 3831489Scharnier#include <signal.h> 3913240Sgraichen#include <stdio.h> 4013240Sgraichen#include <stdlib.h> 4113240Sgraichen#include <sys/time.h> 4213240Sgraichen#include <sys/socket.h> 4313240Sgraichen#include <syslog.h> 4431489Scharnier#include <unistd.h> 4513240Sgraichen 4690336Simpstatic void spray_service(struct svc_req *, SVCXPRT *); 4713240Sgraichen 4813240Sgraichenstatic int from_inetd = 1; 4913240Sgraichen 5013240Sgraichen#define timersub(tvp, uvp, vvp) \ 5113240Sgraichen do { \ 5213240Sgraichen (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ 5313240Sgraichen (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ 5413240Sgraichen if ((vvp)->tv_usec < 0) { \ 5513240Sgraichen (vvp)->tv_sec--; \ 5613240Sgraichen (vvp)->tv_usec += 1000000; \ 5713240Sgraichen } \ 5813240Sgraichen } while (0) 5913240Sgraichen 6013240Sgraichen#define TIMEOUT 120 6113240Sgraichen 6213240Sgraichenvoid 6390336Simpcleanup(int sig __unused) 6413240Sgraichen{ 65100120Salfred (void) rpcb_unset(SPRAYPROG, SPRAYVERS, NULL); 6613240Sgraichen exit(0); 6713240Sgraichen} 6813240Sgraichen 6913240Sgraichenvoid 7090336Simpdie(int sig __unused) 7113240Sgraichen{ 7213240Sgraichen exit(0); 7313240Sgraichen} 7413240Sgraichen 7513240Sgraichenint 7690336Simpmain(int argc, char *argv[]) 7713240Sgraichen{ 7813240Sgraichen SVCXPRT *transp; 79100120Salfred int ok; 80100120Salfred struct sockaddr_storage from; 81141918Sstefanf socklen_t fromlen; 8213240Sgraichen 8313240Sgraichen /* 8413240Sgraichen * See if inetd started us 8513240Sgraichen */ 8613240Sgraichen fromlen = sizeof(from); 8713240Sgraichen if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0) { 8813240Sgraichen from_inetd = 0; 8913240Sgraichen } 9013240Sgraichen 9113240Sgraichen if (!from_inetd) { 9213240Sgraichen daemon(0, 0); 9313240Sgraichen 94100120Salfred (void) rpcb_unset(SPRAYPROG, SPRAYVERS, NULL); 9513240Sgraichen 9613240Sgraichen (void) signal(SIGINT, cleanup); 9713240Sgraichen (void) signal(SIGTERM, cleanup); 9813240Sgraichen (void) signal(SIGHUP, cleanup); 9913240Sgraichen } else { 10013240Sgraichen (void) signal(SIGALRM, die); 10113240Sgraichen alarm(TIMEOUT); 10213240Sgraichen } 10313240Sgraichen 10413240Sgraichen openlog("rpc.sprayd", LOG_CONS|LOG_PID, LOG_DAEMON); 10513240Sgraichen 106100120Salfred if (from_inetd) { 107100120Salfred transp = svc_tli_create(0, NULL, NULL, 0, 0); 108100120Salfred if (transp == NULL) { 109100120Salfred syslog(LOG_ERR, "cannot create udp service."); 110100120Salfred exit(1); 111100120Salfred } 112100120Salfred ok = svc_reg(transp, SPRAYPROG, SPRAYVERS, 113100120Salfred spray_service, NULL); 114100120Salfred } else 115100120Salfred ok = svc_create(spray_service, 116100120Salfred SPRAYPROG, SPRAYVERS, "udp"); 117100120Salfred if (!ok) { 11813240Sgraichen syslog(LOG_ERR, 11931489Scharnier "unable to register (SPRAYPROG, SPRAYVERS, %s)", 120100120Salfred (!from_inetd)?"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 13190336Simpspray_service(struct svc_req *rqstp, SVCXPRT *transp) 13213240Sgraichen{ 13313240Sgraichen static spraycumul scum; 13413240Sgraichen static struct timeval clear, get; 13513240Sgraichen 13613240Sgraichen switch (rqstp->rq_proc) { 13713240Sgraichen case SPRAYPROC_CLEAR: 13813240Sgraichen scum.counter = 0; 13913240Sgraichen (void) gettimeofday(&clear, 0); 14013240Sgraichen /*FALLTHROUGH*/ 14113240Sgraichen 14213240Sgraichen case NULLPROC: 14395658Sdes (void)svc_sendreply(transp, (xdrproc_t)xdr_void, NULL); 14413240Sgraichen return; 14513240Sgraichen 14613240Sgraichen case SPRAYPROC_SPRAY: 14713240Sgraichen scum.counter++; 14813240Sgraichen return; 14913240Sgraichen 15013240Sgraichen case SPRAYPROC_GET: 15113240Sgraichen (void) gettimeofday(&get, 0); 15213240Sgraichen timersub(&get, &clear, &get); 15313240Sgraichen scum.clock.sec = get.tv_sec; 15413240Sgraichen scum.clock.usec = get.tv_usec; 15513240Sgraichen break; 15613240Sgraichen 15713240Sgraichen default: 15813240Sgraichen svcerr_noproc(transp); 15913240Sgraichen return; 16013240Sgraichen } 16113240Sgraichen 16295658Sdes if (!svc_sendreply(transp, (xdrproc_t)xdr_spraycumul, &scum)) { 16313240Sgraichen svcerr_systemerr(transp); 16413240Sgraichen syslog(LOG_ERR, "bad svc_sendreply"); 16513240Sgraichen } 16613240Sgraichen} 167