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