1 /* $OpenBSD: lockd.c,v 1.12 2009/11/15 09:07:56 chl Exp $ */ 2 3 /* 4 * Copyright (c) 1995 5 * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed for the FreeBSD project 18 * 4. Neither the name of the author nor the names of any co-contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 */ 35 36 #include <sys/param.h> 37 #include <sys/socket.h> 38 #include <netinet/in.h> 39 #include <rpc/rpc.h> 40 #include <rpc/pmap_clnt.h> 41 #include <rpcsvc/sm_inter.h> 42 #include "nlm_prot.h" 43 #include <arpa/inet.h> 44 #include <stdio.h> 45 #include <syslog.h> 46 #include <stdlib.h> 47 #include <err.h> 48 #include <errno.h> 49 #include <signal.h> 50 #include <string.h> 51 #include <unistd.h> 52 #include <netdb.h> 53 54 #include "lockd.h" 55 56 int debug_level = 0; /* 0 = no debugging syslog() calls */ 57 int _rpcsvcdirty = 0; 58 int grace_expired; 59 60 void nlm_prog_0(struct svc_req *, SVCXPRT *); 61 void nlm_prog_1(struct svc_req *, SVCXPRT *); 62 void nlm_prog_3(struct svc_req *, SVCXPRT *); 63 void nlm_prog_4(struct svc_req *, SVCXPRT *); 64 65 static void sigalarm_handler(int); 66 static void usage(void); 67 68 int 69 main(int argc, char *argv[]) 70 { 71 SVCXPRT *transp; 72 int ch; 73 struct sigaction sigchild, sigalarm; 74 int grace_period = 30; 75 76 while ((ch = getopt(argc, argv, "d:g:")) != (-1)) { 77 switch (ch) { 78 case 'd': 79 debug_level = atoi(optarg); 80 if (!debug_level) { 81 usage(); 82 /* NOTREACHED */ 83 } 84 break; 85 case 'g': 86 grace_period = atoi(optarg); 87 if (!grace_period) { 88 usage(); 89 /* NOTREACHED */ 90 } 91 break; 92 default: 93 case '?': 94 usage(); 95 /* NOTREACHED */ 96 } 97 } 98 99 (void) pmap_unset(NLM_PROG, NLM_SM); 100 (void) pmap_unset(NLM_PROG, NLM_VERS); 101 (void) pmap_unset(NLM_PROG, NLM_VERSX); 102 (void) pmap_unset(NLM_PROG, NLM_VERS4); 103 104 transp = svcudp_create(RPC_ANYSOCK); 105 if (transp == NULL) { 106 fprintf(stderr, "cannot create udp service.\n"); 107 exit(1); 108 } 109 if (!svc_register(transp, NLM_PROG, NLM_SM, 110 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_0, IPPROTO_UDP)) { 111 fprintf(stderr, "unable to register (NLM_PROG, NLM_SM, udp).\n"); 112 exit(1); 113 } 114 if (!svc_register(transp, NLM_PROG, NLM_VERS, 115 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_1, IPPROTO_UDP)) { 116 fprintf(stderr, "unable to register (NLM_PROG, NLM_VERS, udp).\n"); 117 exit(1); 118 } 119 if (!svc_register(transp, NLM_PROG, NLM_VERSX, 120 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_3, IPPROTO_UDP)) { 121 fprintf(stderr, "unable to register (NLM_PROG, NLM_VERSX, udp).\n"); 122 exit(1); 123 } 124 if (!svc_register(transp, NLM_PROG, NLM_VERS4, 125 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_4, IPPROTO_UDP)) { 126 fprintf(stderr, "unable to register (NLM_PROG, NLM_VERS4, udp).\n"); 127 exit(1); 128 } 129 transp = svctcp_create(RPC_ANYSOCK, 0, 0); 130 if (transp == NULL) { 131 fprintf(stderr, "cannot create tcp service.\n"); 132 exit(1); 133 } 134 if (!svc_register(transp, NLM_PROG, NLM_VERS, 135 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_1, IPPROTO_TCP)) { 136 fprintf(stderr, "unable to register (NLM_PROG, NLM_VERS, tcp).\n"); 137 exit(1); 138 } 139 if (!svc_register(transp, NLM_PROG, NLM_VERSX, 140 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_3, IPPROTO_TCP)) { 141 fprintf(stderr, "unable to register (NLM_PROG, NLM_VERSX, tcp).\n"); 142 exit(1); 143 } 144 if (!svc_register(transp, NLM_PROG, NLM_VERS4, 145 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_4, IPPROTO_TCP)) { 146 fprintf(stderr, "unable to register (NLM_PROG, NLM_VERS4, tcp).\n"); 147 exit(1); 148 } 149 150 /* 151 * Note that it is NOT sensible to run this program from inetd - the 152 * protocol assumes that it will run immediately at boot time. 153 */ 154 if (daemon(0, 0) == -1) { 155 err(1, "cannot fork"); 156 /* NOTREACHED */ 157 } 158 159 openlog("rpc.lockd", 0, LOG_DAEMON); 160 if (debug_level) 161 syslog(LOG_INFO, "Starting, debug level %d", debug_level); 162 else 163 syslog(LOG_INFO, "Starting"); 164 165 sigchild.sa_handler = sigchild_handler; 166 sigemptyset(&sigchild.sa_mask); 167 sigchild.sa_flags = SA_RESTART; 168 if (sigaction(SIGCHLD, &sigchild, NULL) != 0) { 169 syslog(LOG_WARNING, "sigaction(SIGCHLD) failed (%m)"); 170 exit(1); 171 } 172 sigalarm.sa_handler = sigalarm_handler; 173 sigemptyset(&sigalarm.sa_mask); 174 sigalarm.sa_flags = SA_RESETHAND; /* should only happen once */ 175 sigalarm.sa_flags |= SA_RESTART; 176 if (sigaction(SIGALRM, &sigalarm, NULL) != 0) { 177 syslog(LOG_WARNING, "sigaction(SIGALRM) failed (%m)"); 178 exit(1); 179 } 180 grace_expired = 0; 181 if (alarm(10) == (unsigned int)-1) { 182 syslog(LOG_WARNING, "alarm failed (%m)"); 183 exit(1); 184 } 185 186 svc_run(); /* Should never return */ 187 return 1; 188 } 189 190 static void 191 /*ARGSUSED*/ 192 sigalarm_handler(int s) 193 { 194 grace_expired = 1; 195 } 196 197 static void 198 usage() 199 { 200 errx(1, "usage: rpc.lockd [-d [debug_level]] [-g grace_period]"); 201 } 202