Mercurial > dropbear
comparison svr-main.c @ 309:474c1a700b67 ucc-axis-hack
add inetd server mode
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sun, 26 Mar 2006 08:26:39 +0000 |
parents | 973fccb59ea4 |
children |
comparison
equal
deleted
inserted
replaced
308:6e5f8ce73bf2 | 309:474c1a700b67 |
---|---|
38 static void main_inetd(); | 38 static void main_inetd(); |
39 #endif | 39 #endif |
40 #ifdef NON_INETD_MODE | 40 #ifdef NON_INETD_MODE |
41 static void main_noinetd(); | 41 static void main_noinetd(); |
42 #endif | 42 #endif |
43 #ifdef INETD_SERVER_MODE | |
44 static void main_inetd_server(); | |
45 #endif | |
43 static void commonsetup(); | 46 static void commonsetup(); |
47 | |
48 static void blank_dropbear_log(int priority, const char* format, va_list param) | |
49 { | |
50 return; | |
51 } | |
44 | 52 |
45 #if defined(DBMULTI_dropbear) || !defined(DROPBEAR_MULTI) | 53 #if defined(DBMULTI_dropbear) || !defined(DROPBEAR_MULTI) |
46 #if defined(DBMULTI_dropbear) && defined(DROPBEAR_MULTI) | 54 #if defined(DBMULTI_dropbear) && defined(DROPBEAR_MULTI) |
47 int dropbear_main(int argc, char ** argv) | 55 int dropbear_main(int argc, char ** argv) |
48 #else | 56 #else |
53 _dropbear_log = svr_dropbear_log; | 61 _dropbear_log = svr_dropbear_log; |
54 | 62 |
55 /* get commandline options */ | 63 /* get commandline options */ |
56 svr_getopts(argc, argv); | 64 svr_getopts(argc, argv); |
57 | 65 |
66 #ifdef INETD_SERVER_MODE | |
67 if (svr_opts.inetd_dropbear_path) { | |
68 main_inetd_server(); | |
69 /* notreached */ | |
70 } | |
71 #endif | |
72 | |
58 #ifdef INETD_MODE | 73 #ifdef INETD_MODE |
59 /* service program mode */ | 74 /* service program mode */ |
60 if (svr_opts.inetdmode) { | 75 if (svr_opts.inetdmode) { |
61 main_inetd(); | 76 main_inetd(); |
62 /* notreached */ | 77 /* notreached */ |
88 dropbear_exit("Unable to getpeername: %s", strerror(errno)); | 103 dropbear_exit("Unable to getpeername: %s", strerror(errno)); |
89 } | 104 } |
90 | 105 |
91 /* In case our inetd was lax in logging source addresses */ | 106 /* In case our inetd was lax in logging source addresses */ |
92 addrstring = getaddrstring(&remoteaddr, 1); | 107 addrstring = getaddrstring(&remoteaddr, 1); |
93 dropbear_log(LOG_INFO, "Child connection from %s", addrstring); | 108 dropbear_log(LOG_INFO, "Child inetd connection from %s", addrstring); |
94 | 109 |
95 /* Don't check the return value - it may just fail since inetd has | 110 /* Don't check the return value - it may just fail since inetd has |
96 * already done setsid() after forking (xinetd on Darwin appears to do | 111 * already done setsid() after forking (xinetd on Darwin appears to do |
97 * this */ | 112 * this */ |
98 setsid(); | 113 setsid(); |
321 | 336 |
322 /* don't reach here */ | 337 /* don't reach here */ |
323 } | 338 } |
324 #endif /* NON_INETD_MODE */ | 339 #endif /* NON_INETD_MODE */ |
325 | 340 |
341 #ifdef INETD_SERVER_MODE | |
342 void main_inetd_server() { | |
343 fd_set fds; | |
344 struct timeval seltimeout; | |
345 unsigned int i; | |
346 int val; | |
347 int maxsock = -1; | |
348 int listensocks[MAX_LISTEN_ADDR]; | |
349 size_t listensockcount = 0; | |
350 FILE *pidfile = NULL; | |
351 | |
352 int childsock; | |
353 | |
354 /* fork */ | |
355 if (svr_opts.forkbg) { | |
356 int closefds = 0; | |
357 #ifndef DEBUG_TRACE | |
358 if (!svr_opts.usingsyslog) { | |
359 closefds = 1; | |
360 } | |
361 #endif | |
362 if (daemon(0, closefds) < 0) { | |
363 dropbear_exit("Failed to daemonize: %s", strerror(errno)); | |
364 } | |
365 } | |
366 | |
367 commonsetup(); | |
368 | |
369 /* should be done after syslog is working */ | |
370 if (svr_opts.forkbg) { | |
371 dropbear_log(LOG_INFO, "Running in background"); | |
372 } else { | |
373 dropbear_log(LOG_INFO, "Not forking"); | |
374 } | |
375 | |
376 /* create a PID file so that we can be killed easily */ | |
377 pidfile = fopen(DROPBEAR_PIDFILE, "w"); | |
378 if (pidfile) { | |
379 fprintf(pidfile, "%d\n", getpid()); | |
380 fclose(pidfile); | |
381 } | |
382 | |
383 /* Set up the listening sockets */ | |
384 listensockcount = listensockets(listensocks, MAX_LISTEN_ADDR, &maxsock); | |
385 if (listensockcount == 0) | |
386 { | |
387 dropbear_exit("No listening ports available."); | |
388 } | |
389 | |
390 /* incoming connection select loop */ | |
391 for(;;) { | |
392 | |
393 FD_ZERO(&fds); | |
394 | |
395 seltimeout.tv_sec = 60; | |
396 seltimeout.tv_usec = 0; | |
397 | |
398 /* listening sockets */ | |
399 for (i = 0; i < listensockcount; i++) { | |
400 FD_SET(listensocks[i], &fds); | |
401 } | |
402 | |
403 val = select(maxsock+1, &fds, NULL, NULL, &seltimeout); | |
404 | |
405 if (exitflag) { | |
406 unlink(DROPBEAR_PIDFILE); | |
407 dropbear_exit("Terminated by signal"); | |
408 } | |
409 | |
410 if (val == 0) { | |
411 /* timeout reached */ | |
412 continue; | |
413 } | |
414 | |
415 if (val < 0) { | |
416 if (errno == EINTR) { | |
417 continue; | |
418 } | |
419 dropbear_exit("Listening socket error"); | |
420 } | |
421 | |
422 /* handle each socket which has something to say */ | |
423 for (i = 0; i < listensockcount; i++) { | |
424 | |
425 struct sockaddr_storage remoteaddr; | |
426 socklen_t remoteaddrlen = 0; | |
427 pid_t fork_ret = 0; | |
428 | |
429 if (!FD_ISSET(listensocks[i], &fds)) | |
430 continue; | |
431 | |
432 remoteaddrlen = sizeof(remoteaddr); | |
433 childsock = accept(listensocks[i], | |
434 (struct sockaddr*)&remoteaddr, &remoteaddrlen); | |
435 | |
436 if (childsock < 0) { | |
437 /* accept failed */ | |
438 continue; | |
439 } | |
440 | |
441 fork_ret = fork(); | |
442 if (fork_ret < 0) { | |
443 dropbear_log(LOG_WARNING, "error forking: %s", strerror(errno)); | |
444 goto out; | |
445 | |
446 } else if (fork_ret > 0) { | |
447 /* parent */ | |
448 } else { | |
449 | |
450 char * argv[3]; | |
451 | |
452 /* child */ | |
453 | |
454 if (setsid() < 0) { | |
455 dropbear_exit("setsid: %s", strerror(errno)); | |
456 } | |
457 | |
458 /* make sure we close sockets */ | |
459 for (i = 0; i < listensockcount; i++) { | |
460 m_close(listensocks[i]); | |
461 } | |
462 | |
463 close(STDIN_FILENO); | |
464 close(STDOUT_FILENO); | |
465 //close(STDERR_FILENO); | |
466 | |
467 dup2(childsock, STDIN_FILENO); | |
468 dup2(childsock, STDOUT_FILENO); | |
469 | |
470 argv[0] = "dropbear"; | |
471 argv[1] = "-i"; | |
472 argv[2] = NULL; | |
473 | |
474 execv(svr_opts.inetd_dropbear_path, argv); | |
475 dropbear_exit("failed to fork inetd dropbear"); | |
476 | |
477 } | |
478 out: | |
479 /* This section is important for the parent too */ | |
480 m_close(childsock); | |
481 } | |
482 | |
483 } /* for(;;) loop */ | |
484 | |
485 /* don't reach here */ | |
486 } | |
487 #endif /* INETD_SERVER_MODE */ | |
326 | 488 |
327 /* catch + reap zombie children */ | 489 /* catch + reap zombie children */ |
328 static void sigchld_handler(int UNUSED(unused)) { | 490 static void sigchld_handler(int UNUSED(unused)) { |
329 struct sigaction sa_chld; | 491 struct sigaction sa_chld; |
330 | 492 |
381 | 543 |
382 /* Now we can setup the hostkeys - needs to be after logging is on, | 544 /* Now we can setup the hostkeys - needs to be after logging is on, |
383 * otherwise we might end up blatting error messages to the socket */ | 545 * otherwise we might end up blatting error messages to the socket */ |
384 loadhostkeys(); | 546 loadhostkeys(); |
385 | 547 |
386 seedrandom(); | 548 seedrandom(); |
387 } | 549 } |
388 | 550 |
389 /* Set up listening sockets for all the requested ports */ | 551 /* Set up listening sockets for all the requested ports */ |
390 static size_t listensockets(int *sock, size_t sockcount, int *maxfd) { | 552 static size_t listensockets(int *sock, size_t sockcount, int *maxfd) { |
391 | 553 |