int main(int argc, char * argv[]) { /* State variables. */ int * socks_s; int sock_t; struct wire_requestqueue * Q_t; struct dispatch_state * dstate; /* Command-line parameters. */ intmax_t opt_n = 0; char * opt_p = NULL; char * opt_t = NULL; ADDRLIST opt_s; char * opt_s_1 = NULL; /* Working variables. */ size_t opt_s_size; struct sock_addr ** sas; size_t i; const char * ch; WARNP_INIT; /* We have no addresses to listen on yet. */ if ((opt_s = addrlist_init(0)) == NULL) { warnp("addrlist_init"); exit(1); } /* Parse the command line. */ while ((ch = GETOPT(argc, argv)) != NULL) { GETOPT_SWITCH(ch) { GETOPT_OPTARG("-n"): if (opt_n != 0) usage(); if (PARSENUM(&opt_n, optarg, 0, 65535)) { warn0("Invalid option: -n %s", optarg); usage(); } break; GETOPT_OPTARG("-p"): if (opt_p != NULL) usage(); if ((opt_p = strdup(optarg)) == NULL) OPT_EPARSE(ch, optarg); break; GETOPT_OPTARG("-s"): /* Keep a copy of the path for pidfile generation. */ if ((opt_s_1 == NULL) && ((opt_s_1 = strdup(optarg)) == NULL)) OPT_EPARSE(ch, optarg); /* Attempt to resolve to a list of addresses. */ if ((sas = sock_resolve(optarg)) == NULL) { warnp("Cannot resolve address: %s", optarg); exit(1); } if (sas[0] == NULL) { warn0("No addresses found for %s", optarg); exit(1); } /* Push pointers to addresses onto the list. */ for (i = 0; sas[i] != NULL; i++) { if (addrlist_append(opt_s, &sas[i], 1)) OPT_EPARSE(ch, optarg); } /* Free the array (but keep the addresses). */ free(sas); break; GETOPT_OPTARG("-t"): if (opt_t != NULL) usage(); if ((opt_t = strdup(optarg)) == NULL) OPT_EPARSE(ch, optarg); break; GETOPT_OPT("--version"): fprintf(stderr, "kivaloo-mux @VERSION@\n"); exit(0); GETOPT_MISSING_ARG: warn0("Missing argument to %s\n", ch); usage(); GETOPT_DEFAULT: warn0("illegal option -- %s\n", ch); usage(); } } argc -= optind; argv += optind; /* We should have processed all the arguments. */ if (argc != 0) usage(); /* Sanity-check options. */ if ((opt_s_size = addrlist_getsize(opt_s)) == 0) usage(); if (opt_t == NULL) usage(); /* Resolve target address. */ if ((sas = sock_resolve(opt_t)) == NULL) { warnp("Error resolving socket address: %s", opt_t); exit(1); } if (sas[0] == NULL) { warn0("No addresses found for %s", opt_t); exit(1); } /* Connect to the target. */ if ((sock_t = sock_connect(sas)) == -1) exit(1); /* Free the target address(es). */ sock_addr_freelist(sas); /* Create a queue of requests to the target. */ if ((Q_t = wire_requestqueue_init(sock_t)) == NULL) { warnp("Cannot create request queue"); exit(1); } /* Allocate array of source sockets. */ if ((socks_s = malloc(opt_s_size * sizeof(int))) == NULL) { warnp("malloc"); exit(1); } /* Create listening sockets. */ for (i = 0; i < opt_s_size; i++) { if ((socks_s[i] = sock_listener(*addrlist_get(opt_s, i))) == -1) exit(1); } /* Initialize the dispatcher. */ if ((dstate = dispatch_init(socks_s, opt_s_size, Q_t, opt_n ? (size_t)opt_n : SIZE_MAX)) == NULL) { warnp("Failed to initialize dispatcher"); exit(1); } /* Daemonize and write pid. */ if (opt_p == NULL) { if (asprintf(&opt_p, "%s.pid", opt_s_1) == -1) { warnp("asprintf"); exit(1); } } if (daemonize(opt_p)) { warnp("Failed to daemonize"); exit(1); } /* Loop until the dispatcher is finished. */ do { if (events_run()) { warnp("Error running event loop"); exit(1); } } while (dispatch_alive(dstate)); /* Clean up the dispatcher. */ dispatch_done(dstate); /* Shut down the request queue. */ wire_requestqueue_destroy(Q_t); wire_requestqueue_free(Q_t); /* Close sockets. */ for (i = 0; i < opt_s_size; i++) close(socks_s[i]); free(socks_s); close(sock_t); /* Free source socket addresses. */ for (i = 0; i < addrlist_getsize(opt_s); i++) sock_addr_free(*addrlist_get(opt_s, i)); addrlist_free(opt_s); /* Shut down the event subsystem. */ events_shutdown(); /* Free option strings. */ free(opt_p); free(opt_s_1); free(opt_t); /* Success! */ return (0); }
/* * Free all malloc'ed memory for the specified service */ void sc_free( struct service_config *scp ) { #ifdef HAVE_MDNS COND_FREE( SC_MDNS_NAME(scp) ); xinetd_mdns_svc_free(scp); #endif #ifdef LIBWRAP COND_FREE( SC_LIBWRAP(scp) ); #endif COND_FREE( SC_NAME(scp) ) ; COND_FREE( SC_ID(scp) ) ; COND_FREE( SC_PROTONAME(scp) ) ; COND_FREE( SC_SERVER(scp) ) ; COND_FREE( (char *)SC_REDIR_ADDR(scp) ) ; COND_FREE( (char *)SC_BIND_ADDR(scp) ) ; COND_FREE( (char *)SC_ORIG_BIND_ADDR(scp) ) ; COND_FREE( (char *)SC_BANNER(scp) ) ; COND_FREE( (char *)SC_BANNER_SUCCESS(scp) ) ; COND_FREE( (char *)SC_BANNER_FAIL(scp) ) ; if ( SC_SERVER_ARGV(scp) ) { char **pp ; /* * argv[ 0 ] is a special case because it may not have been allocated yet */ if ( SC_SERVER_ARGV(scp)[ 0 ] != NULL) free( SC_SERVER_ARGV(scp)[ 0 ] ) ; for ( pp = &SC_SERVER_ARGV(scp)[ 1 ] ; *pp != NULL ; pp++ ) free( *pp ) ; free( (char *) SC_SERVER_ARGV(scp) ) ; } COND_FREE( LOG_GET_FILELOG( SC_LOG( scp ) )->fl_filename ) ; if ( SC_ACCESS_TIMES(scp) != NULL ) { ti_free( SC_ACCESS_TIMES(scp) ) ; pset_destroy( SC_ACCESS_TIMES(scp) ) ; } if ( SC_ONLY_FROM(scp) != NULL ) { addrlist_free( SC_ONLY_FROM(scp) ) ; pset_destroy( SC_ONLY_FROM(scp) ) ; } if ( SC_NO_ACCESS(scp) != NULL ) { addrlist_free( SC_NO_ACCESS(scp) ) ; pset_destroy( SC_NO_ACCESS(scp) ) ; } if ( SC_ENV_VAR_DEFS(scp) != NULL ) release_string_pset( SC_ENV_VAR_DEFS(scp) ) ; if ( SC_PASS_ENV_VARS(scp) != NULL ) release_string_pset( SC_PASS_ENV_VARS(scp) ) ; if ( SC_ENV( scp )->env_type == CUSTOM_ENV && SC_ENV( scp )->env_handle != ENV_NULL ) env_destroy( SC_ENV( scp )->env_handle ) ; if (SC_DISABLED(scp) ) release_string_pset( SC_DISABLED(scp) ) ; if (SC_ENABLED(scp) ) release_string_pset( SC_ENABLED(scp) ) ; CLEAR( *scp ) ; FREE_SCONF( scp ) ; }