1 /* 2 * Copyright (c) 1990 Jan-Simon Pendry 3 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 4 * Copyright (c) 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Jan-Simon Pendry at Imperial College, London. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its 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 THE REGENTS 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 REGENTS 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 * from: @(#)nfs_start.c 8.1 (Berkeley) 6/6/93 35 * $Id: nfs_start.c,v 1.20 2015/08/20 22:46:32 deraadt Exp $ 36 */ 37 38 #include "am.h" 39 #include "amq.h" 40 #include <signal.h> 41 #include <unistd.h> 42 #include <setjmp.h> 43 44 extern jmp_buf select_intr; 45 extern int select_intr_valid; 46 47 #ifdef HAS_TFS 48 /* 49 * Use replacement for RPC/UDP transport 50 * so that we do NFS gatewaying. 51 */ 52 #define svcudp_create svcudp2_create 53 extern SVCXPRT *svcudp2_create(int); 54 #endif /* HAS_TFS */ 55 56 unsigned short nfs_port; 57 SVCXPRT *nfsxprt, *lnfsxprt; 58 SVCXPRT *amqp, *lamqp; 59 60 extern int fwd_sock; 61 int max_fds = -1; 62 63 #ifdef DEBUG 64 /* 65 * Check that we are not burning resources 66 */ 67 static void 68 checkup(void) 69 { 70 static int max_fd = 0; 71 static char *max_mem = 0; 72 73 int next_fd = dup(0); 74 extern caddr_t sbrk(int); 75 caddr_t next_mem = sbrk(0); 76 close(next_fd); 77 78 /*if (max_fd < 0) { 79 max_fd = next_fd; 80 } else*/ if (max_fd < next_fd) { 81 dlog("%d new fds allocated; total is %d", 82 next_fd - max_fd, next_fd); 83 max_fd = next_fd; 84 } 85 86 /*if (max_mem == 0) { 87 max_mem = next_mem; 88 } else*/ if (max_mem < next_mem) { 89 dlog("%#lx bytes of memory allocated; total is %#lx (%ld pages)", 90 (unsigned long)(next_mem - max_mem), 91 (unsigned long)next_mem, 92 ((unsigned long)next_mem+getpagesize()-1)/getpagesize()); 93 max_mem = next_mem; 94 } 95 } 96 #endif /* DEBUG */ 97 98 static int 99 do_select(sigset_t *mask, sigset_t *omask, int fds, fd_set *fdp, 100 struct timeval *tvp) 101 { 102 int sig; 103 int nsel; 104 105 if ((sig = setjmp(select_intr))) { 106 select_intr_valid = 0; 107 /* Got a signal */ 108 switch (sig) { 109 case SIGINT: 110 case SIGTERM: 111 amd_state = Finishing; 112 reschedule_timeout_mp(); 113 break; 114 } 115 nsel = -1; 116 errno = EINTR; 117 } else { 118 select_intr_valid = 1; 119 /* 120 * Invalidate the current clock value 121 */ 122 clock_valid = 0; 123 /* 124 * Allow interrupts. If a signal 125 * occurs, then it will cause a longjmp 126 * up above. 127 */ 128 sigprocmask(SIG_SETMASK, omask, NULL); 129 /* 130 * Wait for input 131 */ 132 nsel = select(fds, fdp, NULL, NULL, 133 tvp->tv_sec ? tvp : (struct timeval *) 0); 134 135 } 136 137 sigprocmask(SIG_BLOCK, mask, NULL); 138 139 /* 140 * Perhaps reload the cache? 141 */ 142 if (do_mapc_reload < clocktime()) { 143 mapc_reload(); 144 do_mapc_reload = clocktime() + ONE_HOUR; 145 } 146 return nsel; 147 } 148 149 /* 150 * Determine whether anything is left in 151 * the RPC input queue. 152 */ 153 static int 154 rpc_pending_now(void) 155 { 156 struct timeval tvv; 157 int nsel; 158 fd_set *fdsp; 159 int fdsn; 160 161 fdsn = howmany(max_fds+1, NFDBITS) * sizeof(fd_mask); 162 if ((fdsp = malloc(fdsn)) == NULL) 163 return(0); 164 memset(fdsp, 0, fdsn); 165 FD_SET(fwd_sock, fdsp); 166 167 tvv.tv_sec = tvv.tv_usec = 0; 168 nsel = select(max_fds+1, fdsp, NULL, NULL, &tvv); 169 if (nsel < 1) { 170 free(fdsp); 171 return(0); 172 } 173 if (FD_ISSET(fwd_sock, fdsp)) { 174 free(fdsp); 175 return(1); 176 } 177 free(fdsp); 178 return(0); 179 } 180 181 static serv_state 182 run_rpc(void) 183 { 184 sigset_t mask, omask; 185 186 sigemptyset(&mask); 187 sigaddset(&mask, SIGINT); 188 sigaddset(&mask, SIGTERM); 189 sigaddset(&mask, SIGCHLD); 190 sigaddset(&mask, SIGHUP); 191 sigprocmask(SIG_BLOCK, &mask, &omask); 192 193 next_softclock = clocktime(); 194 195 amd_state = Run; 196 197 /* 198 * Keep on trucking while we are in Run mode. This state 199 * is switched to Quit after all the file systems have 200 * been unmounted. 201 */ 202 while ((int)amd_state <= (int)Finishing) { 203 struct timeval tvv; 204 int nsel; 205 time_t now; 206 #ifdef __OpenBSD__ 207 extern int __svc_fdsetsize; 208 extern fd_set *__svc_fdset; 209 fd_set *fdsp; 210 int fdsn = __svc_fdsetsize; 211 int bytes; 212 213 if (fwd_sock > fdsn) 214 fdsn = fwd_sock; 215 bytes = howmany(fdsn, NFDBITS) * sizeof(fd_mask); 216 217 fdsp = malloc(bytes); 218 memset(fdsp, 0, bytes); 219 memcpy(fdsp, __svc_fdset, bytes); 220 FD_SET(fwd_sock, fdsp); 221 #else 222 fd_set *fdsp; 223 int fdsn = FDSETSIZE; 224 bytes = howmany(fdsn, NFDBITS) * sizeof(fd_mask); 225 fdsp = malloc(bytes); 226 memcpy(fdsp, &svc_fdset, bytes); 227 FD_SET(fwd_sock, fdsp); 228 #endif 229 230 #ifdef DEBUG 231 checkup(); 232 #endif /* DEBUG */ 233 234 /* 235 * If the full timeout code is not called, 236 * then recompute the time delta manually. 237 */ 238 now = clocktime(); 239 240 if (next_softclock <= now) { 241 if (amd_state == Finishing) 242 umount_exported(); 243 tvv.tv_sec = softclock(); 244 } else { 245 tvv.tv_sec = next_softclock - now; 246 } 247 tvv.tv_usec = 0; 248 249 if (amd_state == Finishing && last_used_map < 0) { 250 flush_mntfs(); 251 amd_state = Quit; 252 break; 253 } 254 255 #ifdef DEBUG 256 if (tvv.tv_sec) 257 dlog("Select waits for %llds", (long long)tvv.tv_sec); 258 else 259 dlog("Select waits for Godot"); 260 #endif /* DEBUG */ 261 262 nsel = do_select(&mask, &omask, fdsn + 1, fdsp, &tvv); 263 264 265 switch (nsel) { 266 case -1: 267 if (errno == EINTR) { 268 #ifdef DEBUG 269 dlog("select interrupted"); 270 #endif /* DEBUG */ 271 continue; 272 } 273 perror("select"); 274 break; 275 276 case 0: 277 #ifdef DEBUG 278 /*dlog("select returned 0");*/ 279 #endif /* DEBUG */ 280 break; 281 282 default: 283 /* Read all pending NFS responses at once to avoid 284 having responses queue up as a consequence of 285 retransmissions. */ 286 if (FD_ISSET(fwd_sock, fdsp)) { 287 FD_CLR(fwd_sock, fdsp); 288 --nsel; 289 do { 290 fwd_reply(); 291 } while (rpc_pending_now() > 0); 292 } 293 294 if (nsel) { 295 /* 296 * Anything left must be a normal 297 * RPC request. 298 */ 299 #ifdef __OpenBSD__ 300 svc_getreqset2(fdsp, fdsn); 301 #else 302 svc_getreqset(fdsp); 303 #endif 304 } 305 break; 306 } 307 free(fdsp); 308 } 309 310 sigprocmask(SIG_SETMASK, &omask, NULL); 311 312 if (amd_state == Quit) 313 amd_state = Done; 314 315 return amd_state; 316 } 317 318 static int 319 bindnfs_port(int so) 320 { 321 unsigned short port; 322 int error = bind_resv_port(so, &port); 323 if (error == 0) 324 nfs_port = port; 325 return error; 326 } 327 328 void 329 unregister_amq(void) 330 { 331 #ifdef DEBUG 332 Debug(D_AMQ) 333 #endif /* DEBUG */ 334 (void) pmap_unset(AMQ_PROGRAM, AMQ_VERSION); 335 } 336 337 int 338 mount_automounter(pid_t ppid) 339 { 340 struct sockaddr_in sin; 341 int so, so2, nmount; 342 int sinlen; 343 int on = 1; 344 345 so = socket(AF_INET, SOCK_DGRAM, 0); 346 347 if (so < 0 || bindnfs_port(so) < 0) { 348 perror("Can't create privileged nfs port"); 349 return 1; 350 } 351 352 if ((nfsxprt = svcudp_create(so)) == NULL || 353 (amqp = svcudp_create(so)) == NULL) { 354 plog(XLOG_FATAL, "cannot create rpc/udp service"); 355 return 2; 356 } 357 358 sinlen = sizeof sin; 359 if (getsockname(so, (struct sockaddr *)&sin, &sinlen) == -1) { 360 perror("Can't get information on socket"); 361 return 1; 362 } 363 364 so2 = socket(AF_INET, SOCK_DGRAM, 0); 365 if (so2 < 0) { 366 perror("Can't create 2nd socket"); 367 return 1; 368 } 369 370 setsockopt(so2, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on); 371 372 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 373 if (bind(so2, (struct sockaddr *)&sin, sizeof sin) == -1) { 374 perror("Can't bind 2nd socket"); 375 return 1; 376 } 377 378 if ((lnfsxprt = svcudp_create(so2)) == NULL || 379 (lamqp = svcudp_create(so2)) == NULL) { 380 plog(XLOG_FATAL, "cannot create rpc/udp service"); 381 return 2; 382 } 383 384 if (!svc_register(nfsxprt, NFS_PROGRAM, NFS_VERSION, nfs_program_2, 0)) { 385 plog(XLOG_FATAL, "unable to register (NFS_PROGRAM, NFS_VERSION, 0)"); 386 return 3; 387 } 388 389 /* 390 * Start RPC forwarding 391 */ 392 if (fwd_init() != 0) 393 return 3; 394 395 /* 396 * One or other of so, fwd_sock 397 * must be the highest fd on 398 * which to select. 399 */ 400 if (so > max_fds) 401 max_fds = so; 402 if (so2 > max_fds) 403 max_fds = so2; 404 if (fwd_sock > max_fds) 405 max_fds = fwd_sock; 406 407 /* 408 * Construct the root automount node 409 */ 410 make_root_node(); 411 412 /* 413 * Pick up the pieces from a previous run 414 * This is likely to (indirectly) need the rpc_fwd package 415 * so it *must* come after the call to fwd_init(). 416 */ 417 if (restart_existing_mounts) 418 restart(); 419 420 /* 421 * Mount the top-level auto-mountpoints 422 */ 423 nmount = mount_exported(); 424 425 /* 426 * Now safe to tell parent that we are up and running 427 */ 428 if (ppid) 429 kill(ppid, SIGQUIT); 430 431 if (nmount == 0) { 432 plog(XLOG_FATAL, "No work to do - quitting"); 433 amd_state = Done; 434 return 0; 435 } 436 437 #ifdef DEBUG 438 Debug(D_AMQ) { 439 #endif /* DEBUG */ 440 /* 441 * Register with amq 442 */ 443 unregister_amq(); 444 445 if (!svc_register(amqp, AMQ_PROGRAM, AMQ_VERSION, amq_program_57, IPPROTO_UDP)) { 446 plog(XLOG_FATAL, "unable to register (AMQ_PROGRAM, AMQ_VERSION, udp)"); 447 return 3; 448 } 449 #ifdef DEBUG 450 } 451 #endif /* DEBUG */ 452 453 /* 454 * Start timeout_mp rolling 455 */ 456 reschedule_timeout_mp(); 457 458 /* 459 * Start the server 460 */ 461 if (run_rpc() != Done) { 462 plog(XLOG_FATAL, "run_rpc failed"); 463 amd_state = Done; 464 } 465 466 return 0; 467 } 468