1 /* $OpenBSD: lockd.c,v 1.14 2015/04/18 18:28:38 deraadt 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/socket.h> 37 #include <netinet/in.h> 38 #include <rpc/rpc.h> 39 #include <rpc/pmap_clnt.h> 40 #include <rpcsvc/sm_inter.h> 41 #include "nlm_prot.h" 42 #include <arpa/inet.h> 43 #include <stdio.h> 44 #include <syslog.h> 45 #include <stdlib.h> 46 #include <err.h> 47 #include <errno.h> 48 #include <signal.h> 49 #include <limits.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 const char *errstr; 73 int ch; 74 struct sigaction sigchild, sigalarm; 75 int grace_period = 30; 76 77 while ((ch = getopt(argc, argv, "d:g:")) != (-1)) { 78 switch (ch) { 79 case 'd': 80 debug_level = strtonum(optarg, 1, INT_MAX, &errstr); 81 if (errstr) { 82 usage(); 83 /* NOTREACHED */ 84 } 85 break; 86 case 'g': 87 grace_period = strtonum(optarg, 1, INT_MAX, &errstr); 88 if (errstr) { 89 usage(); 90 /* NOTREACHED */ 91 } 92 break; 93 default: 94 case '?': 95 usage(); 96 /* NOTREACHED */ 97 } 98 } 99 100 (void) pmap_unset(NLM_PROG, NLM_SM); 101 (void) pmap_unset(NLM_PROG, NLM_VERS); 102 (void) pmap_unset(NLM_PROG, NLM_VERSX); 103 (void) pmap_unset(NLM_PROG, NLM_VERS4); 104 105 transp = svcudp_create(RPC_ANYSOCK); 106 if (transp == NULL) { 107 fprintf(stderr, "cannot create udp service.\n"); 108 exit(1); 109 } 110 if (!svc_register(transp, NLM_PROG, NLM_SM, 111 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_0, IPPROTO_UDP)) { 112 fprintf(stderr, "unable to register (NLM_PROG, NLM_SM, udp).\n"); 113 exit(1); 114 } 115 if (!svc_register(transp, NLM_PROG, NLM_VERS, 116 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_1, IPPROTO_UDP)) { 117 fprintf(stderr, "unable to register (NLM_PROG, NLM_VERS, udp).\n"); 118 exit(1); 119 } 120 if (!svc_register(transp, NLM_PROG, NLM_VERSX, 121 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_3, IPPROTO_UDP)) { 122 fprintf(stderr, "unable to register (NLM_PROG, NLM_VERSX, udp).\n"); 123 exit(1); 124 } 125 if (!svc_register(transp, NLM_PROG, NLM_VERS4, 126 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_4, IPPROTO_UDP)) { 127 fprintf(stderr, "unable to register (NLM_PROG, NLM_VERS4, udp).\n"); 128 exit(1); 129 } 130 transp = svctcp_create(RPC_ANYSOCK, 0, 0); 131 if (transp == NULL) { 132 fprintf(stderr, "cannot create tcp service.\n"); 133 exit(1); 134 } 135 if (!svc_register(transp, NLM_PROG, NLM_VERS, 136 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_1, IPPROTO_TCP)) { 137 fprintf(stderr, "unable to register (NLM_PROG, NLM_VERS, tcp).\n"); 138 exit(1); 139 } 140 if (!svc_register(transp, NLM_PROG, NLM_VERSX, 141 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_3, IPPROTO_TCP)) { 142 fprintf(stderr, "unable to register (NLM_PROG, NLM_VERSX, tcp).\n"); 143 exit(1); 144 } 145 if (!svc_register(transp, NLM_PROG, NLM_VERS4, 146 (void (*) (struct svc_req *, SVCXPRT *)) nlm_prog_4, IPPROTO_TCP)) { 147 fprintf(stderr, "unable to register (NLM_PROG, NLM_VERS4, tcp).\n"); 148 exit(1); 149 } 150 151 /* 152 * Note that it is NOT sensible to run this program from inetd - the 153 * protocol assumes that it will run immediately at boot time. 154 */ 155 if (daemon(0, 0) == -1) { 156 err(1, "cannot fork"); 157 /* NOTREACHED */ 158 } 159 160 openlog("rpc.lockd", 0, LOG_DAEMON); 161 if (debug_level) 162 syslog(LOG_INFO, "Starting, debug level %d", debug_level); 163 else 164 syslog(LOG_INFO, "Starting"); 165 166 sigchild.sa_handler = sigchild_handler; 167 sigemptyset(&sigchild.sa_mask); 168 sigchild.sa_flags = SA_RESTART; 169 if (sigaction(SIGCHLD, &sigchild, NULL) != 0) { 170 syslog(LOG_WARNING, "sigaction(SIGCHLD) failed (%m)"); 171 exit(1); 172 } 173 sigalarm.sa_handler = sigalarm_handler; 174 sigemptyset(&sigalarm.sa_mask); 175 sigalarm.sa_flags = SA_RESETHAND; /* should only happen once */ 176 sigalarm.sa_flags |= SA_RESTART; 177 if (sigaction(SIGALRM, &sigalarm, NULL) != 0) { 178 syslog(LOG_WARNING, "sigaction(SIGALRM) failed (%m)"); 179 exit(1); 180 } 181 grace_expired = 0; 182 if (alarm(10) == (unsigned int)-1) { 183 syslog(LOG_WARNING, "alarm failed (%m)"); 184 exit(1); 185 } 186 187 svc_run(); /* Should never return */ 188 return 1; 189 } 190 191 static void 192 /*ARGSUSED*/ 193 sigalarm_handler(int s) 194 { 195 grace_expired = 1; 196 } 197 198 static void 199 usage() 200 { 201 errx(1, "usage: rpc.lockd [-d [debug_level]] [-g grace_period]"); 202 } 203