1 /* $OpenBSD: lockd.c,v 1.11 2008/06/15 04:48:03 sturm 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 <errno.h> 48 #include <string.h> 49 #include <netdb.h> 50 51 #include "lockd.h" 52 53 int debug_level = 0; /* 0 = no debugging syslog() calls */ 54 int _rpcsvcdirty = 0; 55 int grace_expired; 56 57 void nlm_prog_0(struct svc_req *, SVCXPRT *); 58 void nlm_prog_1(struct svc_req *, SVCXPRT *); 59 void nlm_prog_3(struct svc_req *, SVCXPRT *); 60 void nlm_prog_4(struct svc_req *, SVCXPRT *); 61 62 static void sigalarm_handler(int); 63 static void usage(void); 64 65 int 66 main(int argc, char *argv[]) 67 { 68 SVCXPRT *transp; 69 int ch; 70 struct sigaction sigchild, sigalarm; 71 int grace_period = 30; 72 73 while ((ch = getopt(argc, argv, "d:g:")) != (-1)) { 74 switch (ch) { 75 case 'd': 76 debug_level = atoi(optarg); 77 if (!debug_level) { 78 usage(); 79 /* NOTREACHED */ 80 } 81 break; 82 case 'g': 83 grace_period = atoi(optarg); 84 if (!grace_period) { 85 usage(); 86 /* NOTREACHED */ 87 } 88 break; 89 default: 90 case '?': 91 usage(); 92 /* NOTREACHED */ 93 } 94 } 95 96 (void) pmap_unset(NLM_PROG, NLM_SM); 97 (void) pmap_unset(NLM_PROG, NLM_VERS); 98 (void) pmap_unset(NLM_PROG, NLM_VERSX); 99 (void) pmap_unset(NLM_PROG, NLM_VERS4); 100 101 transp = svcudp_create(RPC_ANYSOCK); 102 if (transp == NULL) { 103 fprintf(stderr, "cannot create udp service.\n"); 104 exit(1); 105 } 106 if (!svc_register(transp, NLM_PROG, NLM_SM, 107 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_0, IPPROTO_UDP)) { 108 fprintf(stderr, "unable to register (NLM_PROG, NLM_SM, udp).\n"); 109 exit(1); 110 } 111 if (!svc_register(transp, NLM_PROG, NLM_VERS, 112 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_1, IPPROTO_UDP)) { 113 fprintf(stderr, "unable to register (NLM_PROG, NLM_VERS, udp).\n"); 114 exit(1); 115 } 116 if (!svc_register(transp, NLM_PROG, NLM_VERSX, 117 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_3, IPPROTO_UDP)) { 118 fprintf(stderr, "unable to register (NLM_PROG, NLM_VERSX, udp).\n"); 119 exit(1); 120 } 121 if (!svc_register(transp, NLM_PROG, NLM_VERS4, 122 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_4, IPPROTO_UDP)) { 123 fprintf(stderr, "unable to register (NLM_PROG, NLM_VERS4, udp).\n"); 124 exit(1); 125 } 126 transp = svctcp_create(RPC_ANYSOCK, 0, 0); 127 if (transp == NULL) { 128 fprintf(stderr, "cannot create tcp service.\n"); 129 exit(1); 130 } 131 if (!svc_register(transp, NLM_PROG, NLM_VERS, 132 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_1, IPPROTO_TCP)) { 133 fprintf(stderr, "unable to register (NLM_PROG, NLM_VERS, tcp).\n"); 134 exit(1); 135 } 136 if (!svc_register(transp, NLM_PROG, NLM_VERSX, 137 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_3, IPPROTO_TCP)) { 138 fprintf(stderr, "unable to register (NLM_PROG, NLM_VERSX, tcp).\n"); 139 exit(1); 140 } 141 if (!svc_register(transp, NLM_PROG, NLM_VERS4, 142 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_4, IPPROTO_TCP)) { 143 fprintf(stderr, "unable to register (NLM_PROG, NLM_VERS4, tcp).\n"); 144 exit(1); 145 } 146 147 /* 148 * Note that it is NOT sensible to run this program from inetd - the 149 * protocol assumes that it will run immediately at boot time. 150 */ 151 if (daemon(0, 0) == -1) { 152 err(1, "cannot fork"); 153 /* NOTREACHED */ 154 } 155 156 openlog("rpc.lockd", 0, LOG_DAEMON); 157 if (debug_level) 158 syslog(LOG_INFO, "Starting, debug level %d", debug_level); 159 else 160 syslog(LOG_INFO, "Starting"); 161 162 sigchild.sa_handler = sigchild_handler; 163 sigemptyset(&sigchild.sa_mask); 164 sigchild.sa_flags = SA_RESTART; 165 if (sigaction(SIGCHLD, &sigchild, NULL) != 0) { 166 syslog(LOG_WARNING, "sigaction(SIGCHLD) failed (%m)"); 167 exit(1); 168 } 169 sigalarm.sa_handler = sigalarm_handler; 170 sigemptyset(&sigalarm.sa_mask); 171 sigalarm.sa_flags = SA_RESETHAND; /* should only happen once */ 172 sigalarm.sa_flags |= SA_RESTART; 173 if (sigaction(SIGALRM, &sigalarm, NULL) != 0) { 174 syslog(LOG_WARNING, "sigaction(SIGALRM) failed (%m)"); 175 exit(1); 176 } 177 grace_expired = 0; 178 if (alarm(10) == (unsigned int)-1) { 179 syslog(LOG_WARNING, "alarm failed (%m)"); 180 exit(1); 181 } 182 183 svc_run(); /* Should never return */ 184 return 1; 185 } 186 187 static void 188 /*ARGSUSED*/ 189 sigalarm_handler(int s) 190 { 191 grace_expired = 1; 192 } 193 194 static void 195 usage() 196 { 197 errx(1, "usage: rpc.lockd [-d [debug_level]] [-g grace_period]"); 198 } 199