int main_serv(t_ftpserv *ftpserv) { int newsockfd; struct sockaddr_in cli_addr; int pid; t_client *newclient; int clilen; ftpserv->sockfd = make_listen_socket(ftpserv); clilen = sizeof (cli_addr); while (42) { newsockfd = accept(ftpserv->sockfd, (struct sockaddr *) &cli_addr, &clilen); if ((pid = fork()) == -1) exit_perror("fork"); if (pid == 0) { newclient = make_newclient(newsockfd); serv_cl(ftpserv, newclient); exit(0); } } return 0; }
int poll_connection(int pollfd, int events, myconn_t* conn) { if (!conn) { fprintf(stderr, "%s bad connection\n", __FUNCTION__); return -1; } struct epoll_event epv = { .events = events, .data.ptr = conn, }; int op; if (conn->status) { op = EPOLL_CTL_MOD; } else { conn->status = 1; op = EPOLL_CTL_ADD; } if (epoll_ctl(pollfd, op, conn->fd, &epv) < 0) { fprintf(stderr, "epoll add failed[fd=%d], events=%0X: %s\n", conn->fd, events, strerror(errno)); del_connection(conn); return -1; } /* printf("Event Add OK[fd=%d], op=%d, evnets=%0X\n", ev->fd, op, events); */ return 0; } int unpoll_connection(int pollfd, myconn_t* conn) { if (epoll_ctl(pollfd, EPOLL_CTL_DEL, conn->fd, NULL) < 0) { fprintf(stderr, "epoll del failed[fd=%d]: %s\n", conn->fd, strerror(errno)); return -1; } return 0; } /* callbacks */ void on_event_hup_dft(myconn_t* arg); /* default */ void on_event_error_dft(myconn_t* arg); /* default */ extern event_handler_t accept_socket_handler; extern event_handler_t echo_socket_handler; /* listen socket */ int make_listen_socket(short port); myconn_t* make_listen_connection(short port) { int fd; if ((fd = make_listen_socket(port)) < 0) { return NULL; } myconn_t* c = new_connection(fd, &accept_socket_handler, NULL); c->last_active = -1; /* no update active */ return c; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; void *kadm_handle; kadm5_server_context *server_context; kadm5_config_params conf; int signal_fd, listen_fd; int log_fd; slave *slaves = NULL; u_int32_t current_version = 0, old_version = 0; krb5_keytab keytab; int optind; char **files; optind = krb5_program_setup(&context, argc, argv, args, num_args, NULL); if(help_flag) krb5_std_usage(0, args, num_args); if(version_flag) { print_version(NULL); exit(0); } if (config_file == NULL) config_file = HDB_DB_DIR "/kdc.conf"; ret = krb5_prepend_config_files_default(config_file, &files); if (ret) krb5_err(context, 1, ret, "getting configuration files"); ret = krb5_set_config_files(context, files); krb5_free_config_files(files); if (ret) krb5_err(context, 1, ret, "reading configuration files"); time_before_gone = parse_time (slave_time_gone, "s"); if (time_before_gone < 0) krb5_errx (context, 1, "couldn't parse time: %s", slave_time_gone); time_before_missing = parse_time (slave_time_missing, "s"); if (time_before_missing < 0) krb5_errx (context, 1, "couldn't parse time: %s", slave_time_missing); if (detach_from_console) daemon(0, 0); pidfile (NULL); krb5_openlog (context, "ipropd-master", &log_facility); krb5_set_warn_dest(context, log_facility); ret = krb5_kt_register(context, &hdb_kt_ops); if(ret) krb5_err(context, 1, ret, "krb5_kt_register"); ret = krb5_kt_resolve(context, keytab_str, &keytab); if(ret) krb5_err(context, 1, ret, "krb5_kt_resolve: %s", keytab_str); memset(&conf, 0, sizeof(conf)); if(realm) { conf.mask |= KADM5_CONFIG_REALM; conf.realm = realm; } ret = kadm5_init_with_skey_ctx (context, KADM5_ADMIN_SERVICE, NULL, KADM5_ADMIN_SERVICE, &conf, 0, 0, &kadm_handle); if (ret) krb5_err (context, 1, ret, "kadm5_init_with_password_ctx"); server_context = (kadm5_server_context *)kadm_handle; log_fd = open (server_context->log_context.log_file, O_RDONLY, 0); if (log_fd < 0) krb5_err (context, 1, errno, "open %s", server_context->log_context.log_file); signal_fd = make_signal_socket (context); listen_fd = make_listen_socket (context, port_str); signal (SIGPIPE, SIG_IGN); for (;;) { slave *p; fd_set readset; int max_fd = 0; struct timeval to = {30, 0}; u_int32_t vers; if (signal_fd >= FD_SETSIZE || listen_fd >= FD_SETSIZE) krb5_errx (context, 1, "fd too large"); FD_ZERO(&readset); FD_SET(signal_fd, &readset); max_fd = max(max_fd, signal_fd); FD_SET(listen_fd, &readset); max_fd = max(max_fd, listen_fd); for (p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; FD_SET(p->fd, &readset); max_fd = max(max_fd, p->fd); } ret = select (max_fd + 1, &readset, NULL, NULL, &to); if (ret < 0) { if (errno == EINTR) continue; else krb5_err (context, 1, errno, "select"); } if (ret == 0) { old_version = current_version; kadm5_log_get_version_fd (log_fd, ¤t_version); if (current_version > old_version) { for (p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; send_diffs (context, p, log_fd, database, current_version); } } } if (ret && FD_ISSET(signal_fd, &readset)) { struct sockaddr_un peer_addr; socklen_t peer_len = sizeof(peer_addr); if(recvfrom(signal_fd, (void *)&vers, sizeof(vers), 0, (struct sockaddr *)&peer_addr, &peer_len) < 0) { krb5_warn (context, errno, "recvfrom"); continue; } --ret; assert(ret >= 0); old_version = current_version; kadm5_log_get_version_fd (log_fd, ¤t_version); for (p = slaves; p != NULL; p = p->next) send_diffs (context, p, log_fd, database, current_version); } for(p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; if (ret && FD_ISSET(p->fd, &readset)) { --ret; assert(ret >= 0); if(process_msg (context, p, log_fd, database, current_version)) slave_dead(p); } else if (slave_gone_p (p)) slave_dead (p); else if (slave_missing_p (p)) send_are_you_there (context, p); } if (ret && FD_ISSET(listen_fd, &readset)) { add_slave (context, keytab, &slaves, listen_fd); --ret; assert(ret >= 0); } write_stats(context, slaves, current_version); } return 0; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; void *kadm_handle; kadm5_server_context *server_context; kadm5_config_params conf; krb5_socket_t signal_fd, listen_fd; int log_fd; slave *slaves = NULL; uint32_t current_version = 0, old_version = 0; uint32_t current_tstamp = 0; krb5_keytab keytab; char **files; int aret; int optidx = 0; int restarter_fd = -1; struct stat st; setprogname(argv[0]); if (getarg(args, num_args, argc, argv, &optidx)) krb5_std_usage(1, args, num_args); if (help_flag) krb5_std_usage(0, args, num_args); if (version_flag) { print_version(NULL); exit(0); } if (detach_from_console && daemon_child == -1) roken_detach_prep(argc, argv, "--daemon-child"); rk_pidfile(NULL); ret = krb5_init_context(&context); if (ret) errx(1, "krb5_init_context failed: %d", ret); setup_signal(); if (config_file == NULL) { aret = asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(context)); if (aret == -1 || config_file == NULL) errx(1, "out of memory"); } ret = krb5_prepend_config_files_default(config_file, &files); if (ret) krb5_err(context, 1, ret, "getting configuration files"); ret = krb5_set_config_files(context, files); krb5_free_config_files(files); if (ret) krb5_err(context, 1, ret, "reading configuration files"); time_before_gone = parse_time (slave_time_gone, "s"); if (time_before_gone < 0) krb5_errx (context, 1, "couldn't parse time: %s", slave_time_gone); time_before_missing = parse_time (slave_time_missing, "s"); if (time_before_missing < 0) krb5_errx (context, 1, "couldn't parse time: %s", slave_time_missing); krb5_openlog(context, "ipropd-master", &log_facility); krb5_set_warn_dest(context, log_facility); ret = krb5_kt_register(context, &hdb_get_kt_ops); if(ret) krb5_err(context, 1, ret, "krb5_kt_register"); ret = krb5_kt_resolve(context, keytab_str, &keytab); if(ret) krb5_err(context, 1, ret, "krb5_kt_resolve: %s", keytab_str); memset(&conf, 0, sizeof(conf)); if(realm) { conf.mask |= KADM5_CONFIG_REALM; conf.realm = realm; } ret = kadm5_init_with_skey_ctx (context, KADM5_ADMIN_SERVICE, NULL, KADM5_ADMIN_SERVICE, &conf, 0, 0, &kadm_handle); if (ret) krb5_err (context, 1, ret, "kadm5_init_with_password_ctx"); server_context = (kadm5_server_context *)kadm_handle; log_fd = open (server_context->log_context.log_file, O_RDONLY, 0); if (log_fd < 0) krb5_err (context, 1, errno, "open %s", server_context->log_context.log_file); if (fstat(log_fd, &st) == -1) krb5_err(context, 1, errno, "stat %s", server_context->log_context.log_file); if (flock(log_fd, LOCK_SH) == -1) krb5_err(context, 1, errno, "shared flock %s", server_context->log_context.log_file); kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_LAST, ¤t_version, ¤t_tstamp); flock(log_fd, LOCK_UN); signal_fd = make_signal_socket (context); listen_fd = make_listen_socket (context, port_str); krb5_warnx(context, "ipropd-master started at version: %lu", (unsigned long)current_version); roken_detach_finish(NULL, daemon_child); restarter_fd = restarter(context, NULL); while (exit_flag == 0){ slave *p; fd_set readset; int max_fd = 0; struct timeval to = {30, 0}; uint32_t vers; struct stat st2;; #ifndef NO_LIMIT_FD_SETSIZE if (signal_fd >= FD_SETSIZE || listen_fd >= FD_SETSIZE || restarter_fd >= FD_SETSIZE) krb5_errx (context, IPROPD_RESTART, "fd too large"); #endif FD_ZERO(&readset); FD_SET(signal_fd, &readset); max_fd = max(max_fd, signal_fd); FD_SET(listen_fd, &readset); max_fd = max(max_fd, listen_fd); if (restarter_fd > -1) { FD_SET(restarter_fd, &readset); max_fd = max(max_fd, restarter_fd); } for (p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; FD_SET(p->fd, &readset); max_fd = max(max_fd, p->fd); } ret = select (max_fd + 1, &readset, NULL, NULL, &to); if (ret < 0) { if (errno == EINTR) continue; else krb5_err (context, IPROPD_RESTART, errno, "select"); } if (stat(server_context->log_context.log_file, &st2) == -1) { krb5_warn(context, errno, "could not stat log file by path"); st2 = st; } if (st2.st_dev != st.st_dev || st2.st_ino != st.st_ino) { (void) close(log_fd); log_fd = open(server_context->log_context.log_file, O_RDONLY, 0); if (log_fd < 0) krb5_err(context, 1, IPROPD_RESTART_SLOW, "open %s", server_context->log_context.log_file); if (fstat(log_fd, &st) == -1) krb5_err(context, IPROPD_RESTART_SLOW, errno, "stat %s", server_context->log_context.log_file); if (flock(log_fd, LOCK_SH) == -1) krb5_err(context, IPROPD_RESTART, errno, "shared flock %s", server_context->log_context.log_file); kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_LAST, ¤t_version, ¤t_tstamp); flock(log_fd, LOCK_UN); } if (ret == 0) { /* Recover from failed transactions */ if (kadm5_log_init_nb(server_context) == 0) kadm5_log_end(server_context); if (flock(log_fd, LOCK_SH) == -1) krb5_err(context, IPROPD_RESTART, errno, "could not lock log file"); kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_LAST, ¤t_version, ¤t_tstamp); flock(log_fd, LOCK_UN); if (current_version > old_version) { krb5_warnx(context, "Missed a signal, updating slaves %lu to %lu", (unsigned long)old_version, (unsigned long)current_version); for (p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; send_diffs (server_context, p, log_fd, database, current_version, current_tstamp); } old_version = current_version; } } if (ret && FD_ISSET(restarter_fd, &readset)) { exit_flag = SIGTERM; break; } if (ret && FD_ISSET(signal_fd, &readset)) { #ifndef NO_UNIX_SOCKETS struct sockaddr_un peer_addr; #else struct sockaddr_storage peer_addr; #endif socklen_t peer_len = sizeof(peer_addr); if(recvfrom(signal_fd, (void *)&vers, sizeof(vers), 0, (struct sockaddr *)&peer_addr, &peer_len) < 0) { krb5_warn (context, errno, "recvfrom"); continue; } --ret; assert(ret >= 0); old_version = current_version; if (flock(log_fd, LOCK_SH) == -1) krb5_err(context, IPROPD_RESTART, errno, "shared flock %s", server_context->log_context.log_file); kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_LAST, ¤t_version, ¤t_tstamp); flock(log_fd, LOCK_UN); if (current_version != old_version) { /* * If current_version < old_version then the log got * truncated and we'll end up doing full propagations. * * Truncating the log when the current version is * numerically small can lead to race conditions. * Ideally we should identify log versions as * {init_or_trunc_time, vno}, then we could not have any * such race conditions, but this would either require * breaking backwards compatibility for the protocol or * adding new messages to it. */ krb5_warnx(context, "Got a signal, updating slaves %lu to %lu", (unsigned long)old_version, (unsigned long)current_version); for (p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; send_diffs (server_context, p, log_fd, database, current_version, current_tstamp); } } else { krb5_warnx(context, "Got a signal, but no update in log version %lu", (unsigned long)current_version); } } for(p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; if (ret && FD_ISSET(p->fd, &readset)) { --ret; assert(ret >= 0); if(process_msg (server_context, p, log_fd, database, current_version, current_tstamp)) slave_dead(context, p); } else if (slave_gone_p (p)) slave_dead(context, p); else if (slave_missing_p (p)) send_are_you_there (context, p); } if (ret && FD_ISSET(listen_fd, &readset)) { add_slave (context, keytab, &slaves, listen_fd); --ret; assert(ret >= 0); } write_stats(context, slaves, current_version); } if(exit_flag == SIGINT || exit_flag == SIGTERM) krb5_warnx(context, "%s terminated", getprogname()); #ifdef SIGXCPU else if(exit_flag == SIGXCPU) krb5_warnx(context, "%s CPU time limit exceeded", getprogname()); #endif else krb5_warnx(context, "%s unexpected exit reason: %ld", getprogname(), (long)exit_flag); write_master_down(context); return 0; }
int get_listen_socket(const char *addr, int port, int *s, int *ipv6) { char portstr[8]; struct addrinfo hints; struct addrinfo *result; struct addrinfo *iter; struct addrinfo *ipv4_addr; struct addrinfo *ipv6_addr; int ret; int fd; int ipv6_flag; assert(s != NULL); assert(ipv6 != NULL); ipv4_addr = NULL; ipv6_addr = NULL; fd = -1; ipv6_flag = 0; /* Check port. */ if (port <= 0 || port > 65535) return -1; assert(snprintf(portstr, sizeof(portstr), "%d", port) > 0); /* Prepare hints for getaddrinfo(). */ memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; hints.ai_flags |= AI_PASSIVE; /* Get the addresses with getaddrinfo(). */ result = NULL; ret = getaddrinfo(addr, portstr, &hints, &result); if (ret != 0) return -1; /* Iterate over the results and bookmark interesting addresses. */ for (iter = result; iter != NULL; iter = iter->ai_next) { if (iter->ai_family == AF_INET6) ipv6_addr = iter; else if (iter->ai_family == AF_INET) ipv4_addr = iter; } /* Give preference to the IPv6 socket if possible. */ if (ipv6_addr != NULL) { fd = make_listen_socket(ipv6_addr); if (fd != -1) ipv6_flag = 1; } if (fd == -1 && ipv4_addr != NULL) fd = make_listen_socket(ipv4_addr); /* Free the results before returning. */ freeaddrinfo(result); if (fd == -1) return -1; *s = fd; *ipv6 = ipv6_flag; return 0; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; void *kadm_handle; kadm5_server_context *server_context; kadm5_config_params conf; krb5_socket_t signal_fd, listen_fd; int log_fd; slave *slaves = NULL; uint32_t current_version = 0, old_version = 0; krb5_keytab keytab; int optidx; char **files; optidx = krb5_program_setup(&context, argc, argv, args, num_args, NULL); if(help_flag) krb5_std_usage(0, args, num_args); if(version_flag) { print_version(NULL); exit(0); } setup_signal(); if (config_file == NULL) { asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(context)); if (config_file == NULL) errx(1, "out of memory"); } ret = krb5_prepend_config_files_default(config_file, &files); if (ret) krb5_err(context, 1, ret, "getting configuration files"); ret = krb5_set_config_files(context, files); krb5_free_config_files(files); if (ret) krb5_err(context, 1, ret, "reading configuration files"); time_before_gone = parse_time (slave_time_gone, "s"); if (time_before_gone < 0) krb5_errx (context, 1, "couldn't parse time: %s", slave_time_gone); time_before_missing = parse_time (slave_time_missing, "s"); if (time_before_missing < 0) krb5_errx (context, 1, "couldn't parse time: %s", slave_time_missing); #ifdef SUPPORT_DETACH if (detach_from_console) daemon(0, 0); #endif pidfile (NULL); krb5_openlog (context, "ipropd-master", &log_facility); krb5_set_warn_dest(context, log_facility); ret = krb5_kt_register(context, &hdb_kt_ops); if(ret) krb5_err(context, 1, ret, "krb5_kt_register"); ret = krb5_kt_resolve(context, keytab_str, &keytab); if(ret) krb5_err(context, 1, ret, "krb5_kt_resolve: %s", keytab_str); memset(&conf, 0, sizeof(conf)); if(realm) { conf.mask |= KADM5_CONFIG_REALM; conf.realm = realm; } ret = kadm5_init_with_skey_ctx (context, KADM5_ADMIN_SERVICE, NULL, KADM5_ADMIN_SERVICE, &conf, 0, 0, &kadm_handle); if (ret) krb5_err (context, 1, ret, "kadm5_init_with_password_ctx"); server_context = (kadm5_server_context *)kadm_handle; log_fd = open (server_context->log_context.log_file, O_RDONLY, 0); if (log_fd < 0) krb5_err (context, 1, errno, "open %s", server_context->log_context.log_file); signal_fd = make_signal_socket (context); listen_fd = make_listen_socket (context, port_str); kadm5_log_get_version_fd (log_fd, ¤t_version); krb5_warnx(context, "ipropd-master started at version: %lu", (unsigned long)current_version); while(exit_flag == 0){ slave *p; fd_set readset; int max_fd = 0; struct timeval to = {30, 0}; uint32_t vers; #ifndef NO_LIMIT_FD_SETSIZE if (signal_fd >= FD_SETSIZE || listen_fd >= FD_SETSIZE) krb5_errx (context, 1, "fd too large"); #endif FD_ZERO(&readset); FD_SET(signal_fd, &readset); max_fd = max(max_fd, signal_fd); FD_SET(listen_fd, &readset); max_fd = max(max_fd, listen_fd); for (p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; FD_SET(p->fd, &readset); max_fd = max(max_fd, p->fd); } ret = select (max_fd + 1, &readset, NULL, NULL, &to); if (ret < 0) { if (errno == EINTR) continue; else krb5_err (context, 1, errno, "select"); } if (ret == 0) { old_version = current_version; kadm5_log_get_version_fd (log_fd, ¤t_version); if (current_version > old_version) { krb5_warnx(context, "Missed a signal, updating slaves %lu to %lu", (unsigned long)old_version, (unsigned long)current_version); for (p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; send_diffs (context, p, log_fd, database, current_version); } } } if (ret && FD_ISSET(signal_fd, &readset)) { #ifndef NO_UNIX_SOCKETS struct sockaddr_un peer_addr; #else struct sockaddr_storage peer_addr; #endif socklen_t peer_len = sizeof(peer_addr); if(recvfrom(signal_fd, (void *)&vers, sizeof(vers), 0, (struct sockaddr *)&peer_addr, &peer_len) < 0) { krb5_warn (context, errno, "recvfrom"); continue; } --ret; assert(ret >= 0); old_version = current_version; kadm5_log_get_version_fd (log_fd, ¤t_version); if (current_version > old_version) { krb5_warnx(context, "Got a signal, updating slaves %lu to %lu", (unsigned long)old_version, (unsigned long)current_version); for (p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; send_diffs (context, p, log_fd, database, current_version); } } else { krb5_warnx(context, "Got a signal, but no update in log version %lu", (unsigned long)current_version); } } for(p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; if (ret && FD_ISSET(p->fd, &readset)) { --ret; assert(ret >= 0); if(process_msg (context, p, log_fd, database, current_version)) slave_dead(context, p); } else if (slave_gone_p (p)) slave_dead(context, p); else if (slave_missing_p (p)) send_are_you_there (context, p); } if (ret && FD_ISSET(listen_fd, &readset)) { add_slave (context, keytab, &slaves, listen_fd); --ret; assert(ret >= 0); } write_stats(context, slaves, current_version); } if(exit_flag == SIGINT || exit_flag == SIGTERM) krb5_warnx(context, "%s terminated", getprogname()); #ifdef SIGXCPU else if(exit_flag == SIGXCPU) krb5_warnx(context, "%s CPU time limit exceeded", getprogname()); #endif else krb5_warnx(context, "%s unexpected exit reason: %ld", getprogname(), (long)exit_flag); write_master_down(context); return 0; }