static int tunnel(struct gt_service *svc, int fd, struct sockaddr *cliaddr) { AUTOCLEAN(char *tmbuf, autofreestr) = NULL; AUTOCLEAN(struct addrinfo *addr, autofreeaddrinfo) = NULL; AUTOCLEAN(int sd, autofreesocket) = -1; AUTOCLEAN(int efd, autofreesocket) = -1; AUTOCLEAN(gss_name_t name, autofreegssname) = GSS_C_NO_NAME; AUTOCLEAN(gss_name_t srcname, autofreegssname) = GSS_C_NO_NAME; AUTOCLEAN(gss_cred_id_t cred, autofreegsscred) = GSS_C_NO_CREDENTIAL; AUTOCLEAN(gss_ctx_id_t ctx, autofreegssctx) = GSS_C_NO_CONTEXT; AUTOCLEAN(gss_buffer_desc output, autofreegssbuf) = GSS_C_EMPTY_BUFFER; gss_buffer_desc input = GSS_C_EMPTY_BUFFER; gss_buffer_desc namebuf; OM_uint32 maj, min; OM_uint32 ignore; struct epoll_event events[MAX_EVENTS]; size_t tmlen; int pfd; /* plain text fd */ int cfd; /* cipher text fd */ int ret; /* We allocate a 1 MiB buffer for messages, that's also the maximum msg * size */ tmbuf = malloc(MAX_MSG_SIZE); if (!tmbuf) return ENOMEM; if (svc->exec) { fprintf(stderr, "[%s] EXEC option not supported yet, sorry!\n", svc->name); return ENOTSUP; } ret = string_to_addrinfo(svc->connect, &addr); if (ret) return ret; errno = 0; sd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if (sd == -1) return errno; ret = connect(sd, addr->ai_addr, addr->ai_addrlen); if (ret != 0) { ret = errno; fprintf(stderr, "[%s] Failed to connect to server '%s': %s\n", svc->name, svc->connect, strerror(ret)); return ret; } if (svc->target_name) { namebuf.length = strlen(svc->target_name); namebuf.value = svc->target_name; maj = gss_import_name(&min, &namebuf, GSS_C_NT_HOSTBASED_SERVICE, &name); if (maj != GSS_S_COMPLETE) { fprintf(stderr, "[%s] Failed to import name: '%s' (%d/%d)\n", svc->name, svc->target_name, (int)maj, (int)min); return EINVAL; } } if (svc->client) { pfd = fd; cfd = sd; do { maj = gss_init_sec_context(&min, cred, &ctx, name, GSS_C_NO_OID, GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG, 0, GSS_C_NO_CHANNEL_BINDINGS, &input, NULL, &output, NULL, NULL); if (maj != GSS_S_COMPLETE && maj != GSS_S_CONTINUE_NEEDED) { gt_gss_error(svc->name, GSS_C_NO_OID, maj, min); return EBADE; } if (output.length > MAX_MSG_SIZE) return ENOSPC; if (output.length > 0) { memcpy(tmbuf, output.value, output.length); tmlen = output.length; (void)gss_release_buffer(&ignore, &output); ret = send_msg(cfd, tmbuf, tmlen, true); if (ret) return ret; } if (maj == GSS_S_CONTINUE_NEEDED) { tmlen = MAX_MSG_SIZE; ret = recv_msg(cfd, tmbuf, &tmlen, true); if (ret) return ret; input.value = tmbuf; input.length = tmlen; } } while (maj == GSS_S_CONTINUE_NEEDED); } else { pfd = sd; cfd = fd; if (name != GSS_C_NO_NAME) { maj = gss_acquire_cred(&min, name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_ACCEPT, &cred, NULL, NULL); if (maj != GSS_S_COMPLETE) { fprintf(stderr, "[%s] Failed to acquire creds for '%s' (%d/%d)\n", svc->name, svc->target_name?svc->target_name:"", (int)maj, (int)min); return EIO; } } do { tmlen = MAX_MSG_SIZE; ret = recv_msg(cfd, tmbuf, &tmlen, true); if (ret) return ret; input.value = tmbuf; input.length = tmlen; maj = gss_accept_sec_context(&min, &ctx, cred, &input, GSS_C_NO_CHANNEL_BINDINGS, &srcname, NULL, &output, NULL, NULL, NULL); if (maj != GSS_S_COMPLETE && maj != GSS_S_CONTINUE_NEEDED) { gt_gss_error(svc->name, GSS_C_NO_OID, maj, min); return EBADE; } if (output.length > MAX_MSG_SIZE) return ENOSPC; if (output.length > 0) { memcpy(tmbuf, output.value, output.length); tmlen = output.length; (void)gss_release_buffer(&ignore, &output); ret = send_msg(cfd, tmbuf, tmlen, true); if (ret) return ret; } } while (maj == GSS_S_CONTINUE_NEEDED); } /* negotiation completed, now handle traffic */ ret = init_epoll(cfd, pfd, &efd); if (ret) return ret; while (efd != -1) { struct epoll_event *ev; int n; n = epoll_wait(efd, events, MAX_EVENTS, -1); if (n == -1) { ret = errno; if (ret == EINTR) continue; return ret; } for (int i = 0; i < n; i++) { ev = &events[i]; if (ev->events & (EPOLLERR|EPOLLHUP)) { /* one of the peers gave up */ return ENOLINK; } /* RECEIVE */ tmlen = MAX_MSG_SIZE; ret = recv_msg(ev->data.fd, tmbuf, &tmlen, (ev->data.fd == cfd)); if (ret) return ret; if (ev->data.fd == cfd) { /* sender encrypts */ input.value = tmbuf; input.length = tmlen; maj = gss_unwrap(&min, ctx, &input, &output, NULL, NULL); if (maj != GSS_S_COMPLETE) { gt_gss_error(svc->name, GSS_C_NO_OID, maj, min); return EIO; } if (output.length > MAX_MSG_SIZE) return ENOSPC; memcpy(tmbuf, output.value, output.length); tmlen = output.length; (void)gss_release_buffer(&ignore, &output); } /* RESEND */ if (ev->data.fd == pfd) { /* receiver encrypts */ input.value = tmbuf; input.length = tmlen; maj = gss_wrap(&min, ctx, 1, 0, &input, NULL, &output); if (maj != GSS_S_COMPLETE) { gt_gss_error(svc->name, GSS_C_NO_OID, maj, min); return EIO; } if (output.length > MAX_MSG_SIZE) return ENOSPC; memcpy(tmbuf, output.value, output.length); tmlen = output.length; (void)gss_release_buffer(&ignore, &output); } /* send to the other fd, add header only if we encrypted */ ret = send_msg((ev->data.fd == pfd)?cfd:pfd, tmbuf, tmlen, (ev->data.fd == pfd)); if (ret) return ret; } } return 0; }
int main(int argc, const char* argv[]) { struct sockaddr_in sAddr; struct epoll_event ev; struct epoll_event evlist[MAX_EVENTS]; int ready, i; int listensock = 0; int result=0, val = 0; //init epoll if( init_epoll() ){ exit(-1); } printf("epoll instance created success! \n"); //create socket if ( -1 == (listensock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))) { perror("create socket error!"); exit(1); } val = 1; result = setsockopt(listensock, SOL_SOCKET, SO_REUSEADDR, &val,sizeof(val)); if( result < 0 ){ perror("set socket option error!"); exit(1); } sAddr.sin_family = AF_INET; sAddr.sin_port = htons(g_server_port); sAddr.sin_addr.s_addr = INADDR_ANY; //now bind the address and port result = bind(listensock, (struct sockaddr*)&sAddr, sizeof(sAddr)); if ( result < 0 ) { perror("bind error!"); exit(1); } //print server ready info printf("Server get ready at port : %d \n", g_server_port); result = listen(listensock, 5); if( result < 0 ) { perror("listen error!"); exit(1); } setnonblocking(listensock); //set nonblocking ev.events = EPOLLIN|EPOLLET; //edge-trigged ev.data.fd = listensock; if( epoll_ctl(epfd, EPOLL_CTL_ADD, listensock, &ev) == -1 ){ perror("epoll_ctl add error!"); exit(-1); } //now we will epoll_wait the event // while(1) { //Fetch up to MAX_EVENTS items from the ready list //printf("About to epoll_wait() \n"); ready = epoll_wait(epfd, evlist, MAX_EVENTS, -1); if( ready == -1 ){ if( errno == EINTR ){ printf("Get an intr signal!\n"); continue; } else { perror("epoll_wait error!"); exit(-1); } } for(i=0;i<ready;i++){ /* printf("fd=%d, events: %s%s%s%s \n",evlist[i].data.fd, (evlist[i].events & EPOLLIN)? "EPOLLIN ":"", (evlist[i].events & EPOLLOUT)? "EPOLLOUT ":"", (evlist[i].events & EPOLLHUP)? "EPOLLHUP ":"", (evlist[i].events & EPOLLERR)? "EPOLLERR ":""); */ //deal with events if( evlist[i].events & EPOLLIN ){ if( evlist[i].data.fd == listensock ){ handle_accept(evlist[i].data.fd); } else { handle_read(evlist[i].data.fd); } } else if( evlist[i].events & EPOLLOUT){ handle_write(evlist[i].data.fd); } else if( evlist[i].events &(EPOLLHUP|EPOLLERR)){ printf("Client on descriptor #%d disconnetcted. \n", evlist[i].data.fd); if( close( evlist[i].data.fd ) == -1 ){ perror("close fd error!"); exit(-1); } } }//end of for ready }//end of while return 0; }
void server_init (engine_t *E, server_functions_t *F, conn_type_t *listen_connection_type, void *listen_connection_extra) { if (F != NULL) { if (F->sighup) { sf.sighup = F->sighup; } if (F->sigusr1) { sf.sigusr1 = F->sigusr1; } if (F->save_index) { sf.save_index = F->save_index; } if (F->cron) { sf.cron = F->cron; } } init_epoll (); init_netbuffers (); if (udp_enabled) { init_msg_buffers (0); } if (daemonize) { setsid (); reopen_logs (); } if (!E->sfd) { E->sfd = server_socket (port, E->settings_addr, backlog, 0); } if (E->sfd < 0) { kprintf ("cannot open server socket at port %d: %m\n", port); exit (1); } if (change_user (username) < 0) { kprintf ("fatal: cannot change user to %s\n", username ? username : "******"); exit (1); } if (binlogname && !binlog_disabled) { assert (append_to_binlog (Binlog) == log_readto_pos); } init_listening_connection (E->sfd, listen_connection_type, listen_connection_extra); if (udp_enabled) { add_udp_socket (port, 0); } if (binlog_disabled && binlog_fd >= 0) { epoll_pre_event = read_new_events; } struct sigaction sa; memset (&sa, 0, sizeof (sa)); sa.sa_handler = sigint_handler; sigemptyset (&sa.sa_mask); sigaddset (&sa.sa_mask, SIGTERM); sigaction (SIGINT, &sa, NULL); sa.sa_handler = sigterm_handler; sigemptyset (&sa.sa_mask); sigaddset (&sa.sa_mask, SIGINT); sigaction (SIGTERM, &sa, NULL); sa.sa_handler = SIG_IGN; sigaction (SIGPIPE, &sa, NULL); sigaction (SIGPOLL, &sa, NULL); if (daemonize) { sa.sa_handler = sighup_handler; sigemptyset (&sa.sa_mask); sigaction (SIGHUP, &sa, NULL); } }
int lib_main_loop(struct core_control *ctl_params) { int sockfd[2]; pid_t new_proc_pid; struct com_msg_open_session *recv_open_msg = NULL; struct com_msg_ta_created new_ta_info; int ret, event_count, i; sigset_t sig_empty_set, sig_block_set; struct epoll_event cur_events[MAX_CURR_EVENTS]; struct ta_loop_arg ta_loop_args = {0}; int shm_fds[4]; int shm_fd_count; memset(&new_ta_info, 0, sizeof(struct com_msg_ta_created)); child_stack = calloc(1, CHILD_STACK_SIZE); if (!child_stack) { OT_LOG(LOG_ERR, "Sigempty set failed"); exit(EXIT_FAILURE); } if (sigemptyset(&sig_empty_set)) { OT_LOG(LOG_ERR, "Sigempty set failed"); exit(EXIT_FAILURE); } if (sigfillset(&sig_block_set)) { OT_LOG(LOG_ERR, "Sigempty set failed"); exit(EXIT_FAILURE); } if (init_epoll()) { OT_LOG(LOG_ERR, "Epoll init failure"); exit(EXIT_FAILURE); } /* listen to inbound connections from the manager */ if (epoll_reg_fd(ctl_params->comm_sock_fd, EPOLLIN)) { OT_LOG(LOG_ERR, "Failed reg manager socket"); exit(EXIT_FAILURE); } if (epoll_reg_fd(ctl_params->self_pipe_fd, EPOLLIN)) { OT_LOG(LOG_ERR, "Failed reg self pipe socket"); exit(EXIT_FAILURE); } #ifdef GRACEFUL_TERMINATION /* Cleanup function if process need to be cleaned gracefully */ ctl_params->fn_cleanup_launher = cleanup_launcher; #endif OT_LOG(LOG_ERR, "Entering the launcher mainloop"); for (;;) { if (pthread_sigmask(SIG_SETMASK, &sig_empty_set, NULL)) { OT_LOG(LOG_ERR, "Problem with signal mask setting"); continue; } event_count = wrap_epoll_wait(cur_events, MAX_CURR_EVENTS); if (event_count == -1) { if (errno == EINTR) { check_signal_status(ctl_params); continue; } /* Log error and hope the error clears itself */ OT_LOG(LOG_ERR, "Failed return from epoll_wait"); continue; } if (pthread_sigmask(SIG_SETMASK, &sig_block_set, NULL)) { OT_LOG(LOG_ERR, "Problem with signal mask setting"); continue; } /* Note: All signals are blocked */ for (i = 0; i < event_count; i++) { if (cur_events[i].data.fd == ctl_params->self_pipe_fd) { if (cur_events[i].events & EPOLLERR) { OT_LOG(LOG_ERR, "Something wrong with self pipe"); exit(EXIT_FAILURE); } check_signal_status(ctl_params); continue; } /* Launcher is monitoring only two socket and second one is manager fd */ if (cur_events[i].events & EPOLLERR || cur_events[i].events & EPOLLHUP) { OT_LOG(LOG_ERR, "Manager socket error"); exit(EXIT_FAILURE); } ret = com_recv_msg(ctl_params->comm_sock_fd, (void **)&recv_open_msg, NULL, shm_fds, &shm_fd_count); if (ret == -1) { free(recv_open_msg); /* TODO: Figur out why -1, but for now lets * hope the error clears itself*/ continue; } else if (ret > 0) { /* ignore message */ free(recv_open_msg); continue; } recv_open_msg->msg_hdr.shareable_fd_count = 0; if (shm_fd_count > 0 && shm_fd_count <= 4) { recv_open_msg->msg_hdr.shareable_fd_count = shm_fd_count; memcpy(recv_open_msg->msg_hdr.shareable_fd, shm_fds, sizeof(int)*shm_fd_count); } /* Extrac info from message */ if (recv_open_msg->msg_hdr.msg_name != COM_MSG_NAME_OPEN_SESSION || recv_open_msg->msg_hdr.msg_type != COM_TYPE_QUERY) { OT_LOG(LOG_ERR, "Invalid message"); goto close_fd; } /* Received correct mesage from manager. Prepare response message. * PID is filled later */ new_ta_info.msg_hdr.msg_name = COM_MSG_NAME_CREATED_TA; new_ta_info.msg_hdr.msg_type = COM_TYPE_RESPONSE; new_ta_info.msg_hdr.sess_id = recv_open_msg->msg_hdr.sess_id; /* create a socket pair so the manager and TA can communicate */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) == -1) { OT_LOG(LOG_ERR, "failed to create a socket pair"); send_err_msg_to_manager(ctl_params->comm_sock_fd, &new_ta_info); goto close_fd; } /* * Clone now to create the TA subprocess */ /* Fill ta loop arguments */ ta_loop_args.com_sock = sockfd[1]; ta_loop_args.ctl_params = ctl_params; ta_loop_args.recv_open_msg = recv_open_msg; new_proc_pid = clone(ta_process_loop, child_stack + CHILD_STACK_SIZE, SIGCHLD | CLONE_PARENT, &ta_loop_args); if (new_proc_pid == -1) { send_err_msg_to_manager(ctl_params->comm_sock_fd, &new_ta_info); goto close_pair; } new_ta_info.pid = new_proc_pid; ret = com_send_msg(ctl_params->comm_sock_fd, &new_ta_info, sizeof(struct com_msg_ta_created), NULL, 0); if (ret == sizeof(struct com_msg_ta_created)) { if (send_fd(ctl_params->comm_sock_fd, &sockfd[0], 1, NULL, 0) == -1) { OT_LOG(LOG_ERR, "Failed to send TA sock"); kill(new_proc_pid, SIGKILL); /* TODO: Check what is causing error, but for now * lets hope the error clears itself*/ } } else { OT_LOG(LOG_ERR, "Failed to send response msg"); kill(new_proc_pid, SIGKILL); /* TODO: Check what is causing error, but for now lets * hope the error clears itself*/ } close_pair: /* parent process will stay as the launcher */ close(sockfd[0]); close(sockfd[1]); close_fd: /* close possibly forwarded file descriptors */ while (recv_open_msg->msg_hdr.shareable_fd_count > 0) { recv_open_msg->msg_hdr.shareable_fd_count--; close(recv_open_msg->msg_hdr.shareable_fd [recv_open_msg->msg_hdr.shareable_fd_count]); } free(recv_open_msg); } } }
int run_watchdog (int pids[], int num_pids, char* port, char* email_address, char* mail_server) { signal (SIGPIPE, SIG_IGN); pid_t pid = fork(); if (pid < 0) { PERR ("fork"); exit (EXIT_FAILURE); } if (pid == 0) { umask(0); openlog ("SPROCKETS_WATCHDOG", LOG_CONS, LOG_DAEMON); pid_t sid = setsid(); if (sid < 0) { PMSG ("Sprockets watchdog failed to setsid. Exiting now.\n"); exit (EXIT_FAILURE); } if ((chdir("/")) < 0) { PMSG ("Sprockets watchdog failed to chdir. Exiting now.\n"); exit (EXIT_FAILURE); } int sigs[] = { SIGINT, SIGQUIT, SIGHUP, SIGCHLD }; int sfd = setup_sighandlers (sigs, 3); if (sfd == 0) { PMSG ("Sprockets watchdog failed to set sighandlers. Exiting now.\n"); exit (EXIT_FAILURE); } int epfd = init_epoll (sfd); if (epfd == 0) { PMSG ("Sprockets watchdog failed to initialize epoll. Exiting now.\n"); exit (EXIT_FAILURE); } int server_fd = NULL; if (port != NULL) { server_fd = sprocket_tcp_server (port, NULL); if (server_fd == 0) { PMSG ("Couldn't start watchdog server\n"); exit (EXIT_FAILURE); } if (add_fd_to_epoll (epfd, server_fd) == 0) { PERR ("Couldn't add watchdog server to epoll\n"); exit (EXIT_FAILURE); } } close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); syslog (LOG_NOTICE, "Sprockets watchdog successfully started\n"); int paused_for_signal = 0; char* stats = NULL; auto_string* stat_buffer = NULL; pthread_mutex_t stats_mutex; pthread_mutex_init(&stats_mutex, NULL); auto_array* thread_array = auto_array_create (10); if (thread_array == NULL) { syslog (LOG_CRIT, "Unable to create thread array - out of memory"); exit (EXIT_FAILURE); } while (1) { struct epoll_event events[MAX_EPOLL_EVENTS]; int num_fd = epoll_wait(epfd, events, MAX_EPOLL_EVENTS, 500); if (num_fd == -1) { if (errno == EINTR) { syslog (LOG_NOTICE, "epoll_wait interrupted. Continuing\n"); continue; } syslog (LOG_CRIT, "epoll_wait error: %s\n", strerror (errno)); exit (EXIT_FAILURE); } if (num_fd != 0) { // no fds timeout occurred for (int i = 0; i < num_fd; ++i) { if (events[i].data.fd == sfd) { // caught signal struct signalfd_siginfo fdsi; int s = read (sfd, &fdsi, sizeof fdsi); if (s != sizeof fdsi) { syslog (LOG_CRIT, "Read signal error: %s\n", strerror (errno)); continue; } switch (fdsi.ssi_signo) { case SIGINT: syslog (LOG_NOTICE, "Caught SIGINT - pausing\n"); paused_for_signal = 1; break; case SIGQUIT: syslog (LOG_NOTICE, "Caught SIGQUIT - exiting\n"); for (int ii = 0; ii < num_pids; ++ii) { if (pids[ii] != 0) { kill (pids[ii], SIGTERM); } } for (int ii = 0; ii < thread_array->count; ++ii) { watchdog_thread* wt = auto_array_get (thread_array, ii); char ex[2] = "EX"; write (wt->pipe_write, ex, 2); auto_array_delete (thread_array, free); } exit (EXIT_SUCCESS); case SIGHUP: syslog (LOG_NOTICE, "Caught SIGHUP\n"); paused_for_signal = 0; break; case SIGCHLD: syslog (LOG_NOTICE, "Caught SIGCHLD\n"); break; default: syslog (LOG_NOTICE, "Caught unknown signal\n"); break; } } else if (events[i].data.fd == server_fd) { struct sockaddr_in addr; socklen_t addr_sz = 0; int client_fd = accept (server_fd, (struct sockaddr*) &addr, &addr_sz); watchdog_thread_args* thread_args = malloc (sizeof thread_args); if (thread_args == NULL) { syslog (LOG_CRIT, "Malloc returned NULL: %s", strerror (errno)); exit (EXIT_FAILURE); } watchdog_thread* dog_thread = malloc (sizeof dog_thread); if (dog_thread == NULL) { syslog (LOG_CRIT, "Malloc returned NULL: %s", strerror (errno)); exit (EXIT_FAILURE); } int pipefd[2]; if (pipe (pipefd) < 0) { syslog (LOG_CRIT, "watchdog pipe error: %s", strerror (errno)); continue; } dog_thread->pipe_write = pipefd[1]; thread_args->pipe_read = pipefd[0]; thread_args->client_fd = client_fd; thread_args->stats = &stats; thread_args->stats_mutex = &stats_mutex; pthread_attr_t attr; int trv = 0; if ((trv = pthread_attr_init (&attr)) != 0) { syslog (LOG_CRIT, "pthread_attr_init: %s\n", strerror (trv)); continue; } if ((trv = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) != 0) { syslog (LOG_CRIT, "pthread_attr_setdetachstate: %s\n", strerror (trv)); continue; } if ((trv = pthread_create(&dog_thread->th_id, &attr, client_thread, thread_args)) != 0) { syslog (LOG_CRIT, "pthread_create: %s\n", strerror (trv)); continue; } auto_array_add (thread_array, dog_thread); pthread_attr_destroy(&attr); } } } if (paused_for_signal) { syslog (LOG_NOTICE, "Paused for signal\n"); } else { auto_array* stat_files = auto_array_create (num_pids); for (int i = 0; i < num_pids; ++i) { if (pids[i] == 0) { continue; } char pid[32]; sprintf (pid, "%d", pids[i]); FILE* p = get_stat_filep (pid); if (p == NULL) { syslog (LOG_CRIT, "Process with pid %s has halted", pid); if (email_address != NULL && mail_server != NULL) { char msg[2048]; snprintf (msg, 2048, email_alert_msg_format, email_address, email_address, pid); send_email (mail_server, email_address, email_address, msg); pids[i] = 0; } continue; } auto_array_add (stat_files, p); } pthread_mutex_lock(&stats_mutex); if (stat_buffer != NULL) { auto_string_delete (stat_buffer); } stat_buffer = auto_string_create (1024); if (stat_buffer == NULL) { syslog (LOG_CRIT, "Unable to create stat buffer - out of memory"); exit (EXIT_FAILURE); } for (int i = 0; i < stat_files->count; ++i) { FILE* f = auto_array_get (stat_files, i); char* tmp = get_proc_string (f); if (tmp != NULL) { auto_string_append (stat_buffer, tmp); free (tmp); } } stats = stat_buffer->buf; pthread_mutex_unlock (&stats_mutex); for (int i = 0; i < thread_array->count; ++i) { watchdog_thread* wt = auto_array_get (thread_array, i); char ok[2] = "OK"; if (write (wt->pipe_write, ok, 2) <= 0) { syslog (LOG_CRIT, "watchdog write client thread: %s", strerror (errno)); auto_array_remove (thread_array, i); close (wt->pipe_write); free (wt); } } auto_array_delete (stat_files, close_file); } } } return pid; }
int main(int argc, char *argv[]) { int c; int _argc = 0; unsigned long packet_cnt = 0; char *_argv[3]; pid_t pid; static User_Linker *usrinfo = NULL; while ((c = getopt(argc, argv, "dDv:")) != -1) { switch (c) { case 'd': become_daemon = 0; break; case 'D': execed = 1; break; default: return -1; } } if (become_daemon) { if (!execed) { if ((pid = vfork()) < 0) { fprintf(stderr, "vfork failed\n"); exit(1); } else if (pid != 0) { exit(0); //parent progress exit } _argv[_argc++] = argv[0]; _argv[_argc++] = "-D"; _argv[_argc++] = NULL; execv(_argv[0], _argv); /* Not reached */ fprintf(stderr, "Couldn't exec\n"); _exit(1); } else { setsid(); chdir("/"); umask(0); close(0); close(1); close(2); } FILE *f = fopen("/var/run/lldpd.pid", "w"); if (!f) { ERROR("can't open /var/run/lldpd.pid"); return -1; } } INFO("lldp start"); /*Create epoll*/ TST(init_epoll()==0,-1); /*Initialize client control socket*/ //TST(ctlserver_socket_init()==0,-1); TST(packet_socket_init(SVR_PORT_SD, &packet_handler_1, &usrinfo)==0, -1); TST(packet_socket_init(SVR_PORT_FT, &packet_handler_2, &usrinfo)==0, -1); epoll_main_loop(usrinfo, &packet_cnt); //ctlserver_socket_cleanup(); packet_socket_cleanup(&packet_handler_1); packet_socket_cleanup(&packet_handler_2); free_user_link_linker(usrinfo); return 0; }
int ta_process_loop(int man_sockfd, struct com_msg_open_session *open_msg) { int ret; pthread_t ta_logic_thread; pthread_attr_t attr; struct epoll_event cur_events[MAX_CURR_EVENTS]; int event_count, i; char proc_name[MAX_PR_NAME]; /* For now */ sigset_t sig_empty_set; /* Set new ta process name */ strncpy(proc_name, open_msg->ta_so_name, MAX_PR_NAME); prctl(PR_SET_NAME, (unsigned long)proc_name); strncpy(argv0, proc_name, argv0_len); /* Load TA to this process */ ret = load_ta(open_msg->ta_so_name, &interface); if (ret != TEE_SUCCESS || interface == NULL) { OT_LOG(LOG_ERR, "Failed to load the TA"); exit(EXIT_FAILURE); } /* Note: All signal are blocked. Prepare allow set when we can accept signals */ if (sigemptyset(&sig_empty_set)) { OT_LOG(LOG_ERR, "Sigempty set failed: %s", strerror(errno)) exit(EXIT_FAILURE); } /* create an eventfd, that will allow the writer to increment the count by 1 * for each new event, and the reader to decrement by 1 each time, this will allow the * reader to be notified for each new event, as opposed to being notified just once that * there are "event(s)" pending*/ event_fd = eventfd(0, EFD_SEMAPHORE); if (event_fd == -1) { OT_LOG(LOG_ERR, "Failed to initialize eventfd"); exit(EXIT_FAILURE); } /* Initializations of TODO and DONE queues*/ INIT_LIST(&tasks_todo.list); INIT_LIST(&tasks_done.list); /* Init epoll and register FD/data */ if (init_epoll()) exit(EXIT_FAILURE); /* listen to inbound connections from the manager */ if (epoll_reg_fd(man_sockfd, EPOLLIN)) exit(EXIT_FAILURE); /* listen for communications from the TA thread process */ if (epoll_reg_fd(event_fd, EPOLLIN)) exit(EXIT_FAILURE); /* Signal handling */ if (epoll_reg_fd(self_pipe_fd, EPOLLIN)) exit(EXIT_FAILURE); /* Init worker thread */ ret = pthread_attr_init(&attr); if (ret) { OT_LOG(LOG_ERR, "Failed to create attr for thread: %s", strerror(errno)) exit(EXIT_FAILURE); } /* TODO: Should we reserver space for thread stack? */ ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (ret) { OT_LOG(LOG_ERR, "Failed set DETACHED: %s", strerror(errno)) exit(EXIT_FAILURE); } /* Known error: CA can not determ if TA is launched or not, because framework is calling * create entry point and open session function. Those functions return values is mapped * into one return value. */ if (interface->create() != TEE_SUCCESS) { OT_LOG(LOG_ERR, "TA create entry point failed"); exit(EXIT_SUCCESS); } /* Launch worker thread and pass open session message as a parameter */ ret = pthread_create(&ta_logic_thread, &attr, ta_internal_thread, open_msg); if (ret) { OT_LOG(LOG_ERR, "Failed launch thread: %s", strerror(errno)) interface->destroy(); exit(EXIT_FAILURE); } pthread_attr_destroy(&attr); /* Not needed any more */ /* Allow signal delivery */ if (pthread_sigmask(SIG_SETMASK, &sig_empty_set, NULL)) { OT_LOG(LOG_ERR, "failed to allow signals: %s", strerror(errno)) exit(EXIT_FAILURE); } /* Enter into the main part of this io_thread */ for (;;) { event_count = wrap_epoll_wait(cur_events, MAX_CURR_EVENTS); if (event_count == -1) { if (errno == EINTR) { continue; } /* Log error and hope the error clears itself */ OT_LOG(LOG_ERR, "Failed return from epoll_wait"); continue; } for (i = 0; i < event_count; i++) { if (cur_events[i].data.fd == man_sockfd) { receive_from_manager(&cur_events[i], man_sockfd); } else if (cur_events[i].data.fd == event_fd) { reply_to_manager(&cur_events[i], man_sockfd); } else if (cur_events[i].data.fd == self_pipe_fd) { } else { OT_LOG(LOG_ERR, "unknown event source"); } } } /* Should never reach here */ exit(EXIT_FAILURE); }
/*! * \brief initializes the static vars/arrays * \param h - pointer to the io_wait_h that will be initialized * \param max_fd - maximum allowed fd number * \param poll_method - poll method (0 for automatic best fit) */ int init_io_wait(io_wait_h* h, char *name, int max_fd, enum poll_types poll_method, int max_prio) { char * poll_err; memset(h, 0, sizeof(*h)); h->name = name; h->max_prio = max_prio; h->max_fd_no=max_fd; #ifdef HAVE_EPOLL h->epfd=-1; #endif #ifdef HAVE_KQUEUE h->kq_fd=-1; #endif #ifdef HAVE_DEVPOLL h->dpoll_fd=-1; #endif poll_err=check_poll_method(poll_method); /* set an appropiate poll method */ if (poll_err || (poll_method==0)){ poll_method=choose_poll_method(); if (poll_err){ LM_ERR("%s, using %s instead\n", poll_err, poll_method_str[poll_method]); }else{ LM_INFO("using %s as the io watch method" " (auto detected)\n", poll_method_str[poll_method]); } } h->poll_method=poll_method; /* common stuff, everybody has fd_hash */ h->fd_hash=local_malloc(sizeof(*(h->fd_hash))*h->max_fd_no); if (h->fd_hash==0){ LM_CRIT("could not alloc fd hashtable (%ld bytes)\n", (long)sizeof(*(h->fd_hash))*h->max_fd_no ); goto error; } memset((void*)h->fd_hash, 0, sizeof(*(h->fd_hash))*h->max_fd_no); /* init the fd array as needed for priority ordering */ h->fd_array=local_malloc(sizeof(*(h->fd_array))*h->max_fd_no); if (h->fd_array==0){ LM_CRIT("could not alloc fd array (%ld bytes)\n", (long)sizeof(*(h->fd_hash))*h->max_fd_no); goto error; } memset((void*)h->fd_array, 0, sizeof(*(h->fd_array))*h->max_fd_no); /* array with indexes in fd_array where the priority changes */ h->prio_idx=local_malloc(sizeof(*(h->prio_idx))*h->max_prio); if (h->prio_idx==0){ LM_CRIT("could not alloc fd array (%ld bytes)\n", (long)sizeof(*(h->prio_idx))*h->max_prio); goto error; } memset((void*)h->prio_idx, 0, sizeof(*(h->prio_idx))*h->max_prio); switch(poll_method){ case POLL_POLL: break; #ifdef HAVE_SELECT case POLL_SELECT: if ((poll_method==POLL_SELECT) && (init_select(h)<0)){ LM_CRIT("select init failed\n"); goto error; } break; #endif #ifdef HAVE_DEVPOLL case POLL_DEVPOLL: if ((poll_method==POLL_DEVPOLL) && (init_devpoll(h)<0)){ LM_CRIT("/dev/poll init failed\n"); goto error; } h->dp_changes=local_malloc(sizeof(*(h->dp_changes))*h->max_fd_no); if (h->dp_changes==0){ LM_CRIT("could not alloc db changes array (%ld bytes)\n", (long)sizeof(*(h->dp_changes))*h->max_fd_no); goto error; } memset((void*)h->dp_changes, 0, sizeof(*(h->dp_changes))*h->max_fd_no); break; #endif #ifdef HAVE_SIGIO_RT case POLL_SIGIO_RT: if ((poll_method==POLL_SIGIO_RT) && (init_sigio(h, 0)<0)){ LM_CRIT("sigio init failed\n"); goto error; } break; #endif #ifdef HAVE_EPOLL case POLL_EPOLL_LT: case POLL_EPOLL_ET: h->ep_array=local_malloc(sizeof(*(h->ep_array))*h->max_fd_no); if (h->ep_array==0){ LM_CRIT("could not alloc epoll array\n"); goto error; } memset((void*)h->ep_array, 0, sizeof(*(h->ep_array))*h->max_fd_no); if (init_epoll(h)<0){ LM_CRIT("epoll init failed\n"); goto error; } break; #endif #ifdef HAVE_KQUEUE case POLL_KQUEUE: h->kq_array=local_malloc(sizeof(*(h->kq_array))*h->max_fd_no); if (h->kq_array==0){ LM_CRIT("could not alloc kqueue event array\n"); goto error; } h->kq_changes_size=KQ_CHANGES_ARRAY_SIZE; h->kq_changes=local_malloc(sizeof(*(h->kq_changes))* h->kq_changes_size); if (h->kq_changes==0){ LM_CRIT("could not alloc kqueue changes array\n"); goto error; } h->kq_nchanges=0; memset((void*)h->kq_array, 0, sizeof(*(h->kq_array))*h->max_fd_no); memset((void*)h->kq_changes, 0, sizeof(*(h->kq_changes))* h->kq_changes_size); if (init_kqueue(h)<0){ LM_CRIT("kqueue init failed\n"); goto error; } break; #endif default: LM_CRIT("unknown/unsupported poll method %s (%d)\n", poll_method_str[poll_method], poll_method); goto error; } return 0; error: return -1; }
static void mstpd_run(void * param) { int i; struct stpDriver stpDrv = { .stp_set_state = do_set_stp_state, .stp_create_msti = do_create_stp_msti, .stp_delete_msti = do_delete_stp_msti, .stp_flush_all_fids = do_flush_all_fids_of_port, .alert_push = alert_push, .get_ifflags = do_get_flags, .if_shutdown = do_if_shutdown, .get_speed_duplex = do_get_speed_duplex, .get_hwaddr = do_get_hwaddr, .get_bridge_portno = do_get_bridge_portno, #ifdef KERNEL_BRIDGE_TURN_ON .br_set_state = br_set_state, .br_set_ageing_time = br_set_ageing_time, .br_flush_port = br_flush_port, #endif .if_index_to_name = do_if_index_to_name, .if_name_to_index = do_if_name_to_index, }; init_stp_driver(&stpDrv); usleep(500000); /* wait for ubus stable*/ if(init_epoll() != 0){ goto run_mstp_faild; } if(packet_sock_init() != 0){ goto run_mstp_faild; } /* 初始网络套接字,用于获取网络接口信息*/ if(netsock_init() != 0){ goto run_mstp_faild; } #ifdef KERNEL_BRIDGE_TURN_ON /* 初始化桥操作入口,用于监视桥状态和相关操作 */ if(init_bridge_ops() != 0){ goto run_mstp_faild; } #endif for(i=1; i< MAX_MSTID; i++) msti_new_flag[i] = 1; #ifndef KERNEL_BRIDGE_TURN_ON //内核开启Bridge 支持 char ifname[10]; for(i=1; i<6; i++){ sprintf(ifname, "lan%d", i); ifname[4] = 0; set_if_to_promisc(ifname); } #endif join_bridge_to_mstp(); epoll_main_loop(); goto over_mstpd; run_mstp_faild: ERROR(GLOBAL_OUT_GROUP, "initination run MSTP faild.\n"); over_mstpd: pthread_exit(0); }
/*! * \brief initializes the static vars/arrays * \param h - pointer to the io_wait_h that will be initialized * \param max_fd - maximum allowed fd number * \param poll_method - poll method (0 for automatic best fit) */ int init_io_wait(io_wait_h* h, char *name, int max_fd, enum poll_types poll_method, int async) { char * poll_err; memset(h, 0, sizeof(*h)); h->name = name; h->max_fd_no=max_fd; #ifdef HAVE_EPOLL h->epfd=-1; #endif #ifdef HAVE_KQUEUE h->kq_fd=-1; #endif #ifdef HAVE_DEVPOLL h->dpoll_fd=-1; #endif poll_err=check_poll_method(poll_method); /* set an appropiate poll method */ if (poll_err || (poll_method==0)){ poll_method=choose_poll_method(); if (poll_err){ LM_ERR("%s, using %s instead\n", poll_err, poll_method_str[poll_method]); }else{ LM_INFO("using %s as the io watch method" " (auto detected)\n", poll_method_str[poll_method]); } } h->poll_method=poll_method; if (h->poll_method != POLL_POLL && h->poll_method != POLL_EPOLL_LT && h->poll_method != POLL_EPOLL_ET) { if (async) LM_WARN("Tried to enable async polling but current poll method is %d." " Currently we only support POLL and EPOLL \n",h->poll_method); async=0; } /* common stuff, everybody has fd_hash */ h->fd_hash=local_malloc(sizeof(*(h->fd_hash))*h->max_fd_no); if (h->fd_hash==0){ LM_CRIT("could not alloc fd hashtable (%ld bytes)\n", (long)sizeof(*(h->fd_hash))*h->max_fd_no ); goto error; } memset((void*)h->fd_hash, 0, sizeof(*(h->fd_hash))*h->max_fd_no); switch(poll_method){ case POLL_POLL: #ifdef HAVE_SELECT case POLL_SELECT: #endif #ifdef HAVE_SIGIO_RT case POLL_SIGIO_RT: #endif #ifdef HAVE_DEVPOLL case POLL_DEVPOLL: #endif h->fd_array=local_malloc(sizeof(*(h->fd_array))*h->max_fd_no); if (h->fd_array==0){ LM_CRIT("could not alloc fd array (%ld bytes)\n", (long)sizeof(*(h->fd_hash))*h->max_fd_no); goto error; } memset((void*)h->fd_array, 0, sizeof(*(h->fd_array))*h->max_fd_no); #ifdef HAVE_SIGIO_RT if ((poll_method==POLL_SIGIO_RT) && (init_sigio(h, 0)<0)){ LM_CRIT("sigio init failed\n"); goto error; } #endif #ifdef HAVE_DEVPOLL if ((poll_method==POLL_DEVPOLL) && (init_devpoll(h)<0)){ LM_CRIT("/dev/poll init failed\n"); goto error; } #endif #ifdef HAVE_SELECT if ((poll_method==POLL_SELECT) && (init_select(h)<0)){ LM_CRIT("select init failed\n"); goto error; } #endif break; #ifdef HAVE_EPOLL case POLL_EPOLL_LT: case POLL_EPOLL_ET: h->ep_array=local_malloc(sizeof(*(h->ep_array))*h->max_fd_no); if (h->ep_array==0){ LM_CRIT("could not alloc epoll array\n"); goto error; } memset((void*)h->ep_array, 0, sizeof(*(h->ep_array))*h->max_fd_no); if (init_epoll(h)<0){ LM_CRIT("epoll init failed\n"); goto error; } break; #endif #ifdef HAVE_KQUEUE case POLL_KQUEUE: h->kq_array=local_malloc(sizeof(*(h->kq_array))*h->max_fd_no); if (h->kq_array==0){ LM_CRIT("could not alloc kqueue event array\n"); goto error; } h->kq_changes_size=KQ_CHANGES_ARRAY_SIZE; h->kq_changes=local_malloc(sizeof(*(h->kq_changes))* h->kq_changes_size); if (h->kq_changes==0){ LM_CRIT("could not alloc kqueue changes array\n"); goto error; } h->kq_nchanges=0; memset((void*)h->kq_array, 0, sizeof(*(h->kq_array))*h->max_fd_no); memset((void*)h->kq_changes, 0, sizeof(*(h->kq_changes))* h->kq_changes_size); if (init_kqueue(h)<0){ LM_CRIT("kqueue init failed\n"); goto error; } break; #endif default: LM_CRIT("unknown/unsupported poll method %s (%d)\n", poll_method_str[poll_method], poll_method); goto error; } return 0; error: return -1; }
/* initializes the static vars/arrays * params: h - pointer to the io_wait_h that will be initialized * max_fd - maximum allowed fd number * poll_m - poll method (0 for automatic best fit) */ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method) { char * poll_err; if (_os_ver==0) _os_ver=get_sys_version(0,0,0); memset(h, 0, sizeof(*h)); h->max_fd_no=max_fd; #ifdef HAVE_EPOLL h->epfd=-1; #endif #ifdef HAVE_KQUEUE h->kq_fd=-1; #endif #ifdef HAVE_DEVPOLL h->dpoll_fd=-1; #endif poll_err=check_poll_method(poll_method); /* set an appropiate poll method */ if (poll_err || (poll_method==0)){ poll_method=choose_poll_method(); if (poll_err){ LOG(L_ERR, "ERROR: init_io_wait: %s, using %s instead\n", poll_err, poll_method_str[poll_method]); }else{ LOG(L_INFO, "init_io_wait: using %s as the io watch method" " (auto detected)\n", poll_method_str[poll_method]); } } h->poll_method=poll_method; /* common stuff, everybody has fd_hash */ h->fd_hash=local_malloc(sizeof(*(h->fd_hash))*h->max_fd_no); if (h->fd_hash==0){ LOG(L_CRIT, "ERROR: init_io_wait: could not alloc" " fd hashtable (%ld bytes)\n", (long)sizeof(*(h->fd_hash))*h->max_fd_no ); goto error; } memset((void*)h->fd_hash, 0, sizeof(*(h->fd_hash))*h->max_fd_no); switch(poll_method){ case POLL_POLL: #ifdef HAVE_SELECT case POLL_SELECT: #endif #ifdef HAVE_SIGIO_RT case POLL_SIGIO_RT: #endif #ifdef HAVE_DEVPOLL case POLL_DEVPOLL: #endif h->fd_array=local_malloc(sizeof(*(h->fd_array))*h->max_fd_no); if (h->fd_array==0){ LOG(L_CRIT, "ERROR: init_io_wait: could not" " alloc fd array (%ld bytes)\n", (long)sizeof(*(h->fd_hash))*h->max_fd_no); goto error; } memset((void*)h->fd_array, 0, sizeof(*(h->fd_array))*h->max_fd_no); #ifdef HAVE_SIGIO_RT if ((poll_method==POLL_SIGIO_RT) && (init_sigio(h, 0)<0)){ LOG(L_CRIT, "ERROR: init_io_wait: sigio init failed\n"); goto error; } #endif #ifdef HAVE_DEVPOLL if ((poll_method==POLL_DEVPOLL) && (init_devpoll(h)<0)){ LOG(L_CRIT, "ERROR: init_io_wait: /dev/poll init failed\n"); goto error; } #endif #ifdef HAVE_SELECT if ((poll_method==POLL_SELECT) && (init_select(h)<0)){ LOG(L_CRIT, "ERROR: init_io_wait: select init failed\n"); goto error; } #endif break; #ifdef HAVE_EPOLL case POLL_EPOLL_LT: case POLL_EPOLL_ET: h->ep_array=local_malloc(sizeof(*(h->ep_array))*h->max_fd_no); if (h->ep_array==0){ LOG(L_CRIT, "ERROR: init_io_wait: could not alloc" " epoll array\n"); goto error; } memset((void*)h->ep_array, 0, sizeof(*(h->ep_array))*h->max_fd_no); if (init_epoll(h)<0){ LOG(L_CRIT, "ERROR: init_io_wait: epoll init failed\n"); goto error; } break; #endif #ifdef HAVE_KQUEUE case POLL_KQUEUE: h->kq_array=local_malloc(sizeof(*(h->kq_array))*h->max_fd_no); if (h->kq_array==0){ LOG(L_CRIT, "ERROR: init_io_wait: could not alloc" " kqueue event array\n"); goto error; } h->kq_changes_size=KQ_CHANGES_ARRAY_SIZE; h->kq_changes=local_malloc(sizeof(*(h->kq_changes))* h->kq_changes_size); if (h->kq_changes==0){ LOG(L_CRIT, "ERROR: init_io_wait: could not alloc" " kqueue changes array\n"); goto error; } h->kq_nchanges=0; memset((void*)h->kq_array, 0, sizeof(*(h->kq_array))*h->max_fd_no); memset((void*)h->kq_changes, 0, sizeof(*(h->kq_changes))* h->kq_changes_size); if (init_kqueue(h)<0){ LOG(L_CRIT, "ERROR: init_io_wait: kqueue init failed\n"); goto error; } break; #endif default: LOG(L_CRIT, "BUG: init_io_wait: unknown/unsupported poll" " method %s (%d)\n", poll_method_str[poll_method], poll_method); goto error; } return 0; error: return -1; }
void start_server (void) { char buf[64]; int i, prev_time = 0; init_epoll (); init_netbuffers (); if (!sfd) { sfd = server_socket (port, settings_addr, backlog, 0); } if (sfd < 0) { kprintf ("cannot open server socket at port %d: %m\n", port); exit (3); } vkprintf (1, "created listening socket at %s:%d, fd=%d\n", conv_addr (settings_addr.s_addr, buf), port, sfd); if (daemonize) { setsid (); } if (change_user (username) < 0) { kprintf ("fatal: cannot change user to %s\n", username ? username : "******"); exit (1); } if (binlogname && !binlog_disabled) { assert (append_to_binlog (Binlog) == log_readto_pos); } init_listening_connection (sfd, &ct_rpc_server, ©exec_result_rpc_server); sigset_t signal_set; sigemptyset (&signal_set); sigaddset (&signal_set, SIGINT); sigaddset (&signal_set, SIGTERM); sigaddset (&signal_set, SIGUSR1); if (daemonize) { sigaddset (&signal_set, SIGHUP); } struct sigaction act; act.sa_handler = copyexec_results_sig_handler; act.sa_mask = signal_set; act.sa_flags = 0; for (i = 1; i <= SIGRTMAX; i++) { if (sigismember (&signal_set, i)) { if (sigaction (i, &act, NULL) < 0) { kprintf ("sigaction (%d) failed. %m\n", i); exit (1); } } } for (i = 0; ; i++) { if (!(i & 255)) { vkprintf (1, "epoll_work(): %d out of %d connections, network buffers: %d used, %d out of %d allocated\n", active_connections, maxconn, NB_used, NB_alloc, NB_max); } epoll_work (71); if (interrupted_by_term_signal ()) { break; } if (pending_signals & (1LL << SIGHUP)) { pending_signals_clear_bit (&signal_set, SIGHUP); kprintf ("got SIGHUP.\n"); sync_binlog (2); } if (pending_signals & (1LL << SIGUSR1)) { pending_signals_clear_bit (&signal_set, SIGUSR1); kprintf ("got SIGUSR1, rotate logs.\n"); reopen_logs (); sync_binlog (2); } if (now != prev_time) { prev_time = now; cron (); } if (quit_steps && !--quit_steps) break; } epoll_close (sfd); close (sfd); flush_binlog_last (); sync_binlog (2); }