diff --git a/libknet/Makefile.am b/libknet/Makefile.am index 4843d749..33b894a2 100644 --- a/libknet/Makefile.am +++ b/libknet/Makefile.am @@ -1,20 +1,21 @@ MAINTAINERCLEANFILES = Makefile.in LIBS = -lpthread \ -version-info $(libversion) libversion = 0:0:0 sources = \ + common.c \ handle.c \ host.c \ listener.c include_HEADERS = libknet.h noinst_HEADERS = libknet-private.h noinst_LIBRARIES = libknet.a #lib_LTLIBRARIES = libknet.la libknet_a_SOURCES = $(sources) #libknet_la_SOURCES = $(sources) diff --git a/utils.c b/libknet/common.c similarity index 71% copy from utils.c copy to libknet/common.c index c7022ce9..994dbb03 100644 --- a/utils.c +++ b/libknet/common.c @@ -1,25 +1,22 @@ #include "config.h" #include #include -#include "utils.h" +#include "libknet-private.h" -int utils_debug = 0; -int utils_syslog = 0; - -int knet_fdset_cloexec(int fd) +int _fdset_cloexec(int fd) { int fdflags; fdflags = fcntl(fd, F_GETFD, 0); if (fdflags < 0) return -1; fdflags |= FD_CLOEXEC; if (fcntl(fd, F_SETFD, fdflags) < 0) return -1; return 0; } diff --git a/libknet/handle.c b/libknet/handle.c index a9f152a4..f56565c7 100644 --- a/libknet/handle.c +++ b/libknet/handle.c @@ -1,360 +1,359 @@ #include "config.h" #include #include #include #include #include #include -#include "utils.h" #include "libknet-private.h" #define KNET_MAX_EVENTS 8 #define KNET_PING_TIMERES 200000 #define KNET_DATABUFSIZE 131072 /* 128k */ #define KNET_PINGBUFSIZE sizeof(struct knet_frame) static void *_handle_control_thread(void *data); static void *_handle_heartbt_thread(void *data); knet_handle_t knet_handle_new(int fd, uint16_t node_id) { knet_handle_t knet_h; struct epoll_event ev; if ((knet_h = malloc(sizeof(struct knet_handle))) == NULL) return NULL; memset(knet_h, 0, sizeof(struct knet_handle)); if ((knet_h->databuf = malloc(KNET_DATABUFSIZE))== NULL) goto exit_fail1; memset(knet_h->databuf, 0, KNET_DATABUFSIZE); if ((knet_h->pingbuf = malloc(KNET_PINGBUFSIZE))== NULL) goto exit_fail2; memset(knet_h->pingbuf, 0, KNET_PINGBUFSIZE); if (pthread_rwlock_init(&knet_h->list_rwlock, NULL) != 0) goto exit_fail3; knet_h->sockfd = fd; knet_h->epollfd = epoll_create(KNET_MAX_EVENTS); knet_h->node_id = node_id; if (knet_h->epollfd < 0) goto exit_fail4; - if (knet_fdset_cloexec(knet_h->epollfd) != 0) + if (_fdset_cloexec(knet_h->epollfd) != 0) goto exit_fail5; memset(&ev, 0, sizeof(struct epoll_event)); ev.events = EPOLLIN; ev.data.fd = knet_h->sockfd; if (epoll_ctl(knet_h->epollfd, EPOLL_CTL_ADD, knet_h->sockfd, &ev) != 0) goto exit_fail5; if (pthread_create(&knet_h->control_thread, 0, _handle_control_thread, (void *) knet_h) != 0) goto exit_fail5; if (pthread_create(&knet_h->heartbt_thread, 0, _handle_heartbt_thread, (void *) knet_h) != 0) goto exit_fail6; return knet_h; exit_fail6: pthread_cancel(knet_h->control_thread); exit_fail5: close(knet_h->epollfd); exit_fail4: pthread_rwlock_destroy(&knet_h->list_rwlock); exit_fail3: free(knet_h->databuf); exit_fail2: free(knet_h->pingbuf); exit_fail1: free(knet_h); return NULL; } int knet_handle_free(knet_handle_t knet_h) { void *retval; if ((knet_h->host_head != NULL) || (knet_h->listener_head != NULL)) goto exit_busy; pthread_cancel(knet_h->heartbt_thread); pthread_join(knet_h->heartbt_thread, &retval); if (retval != PTHREAD_CANCELED) goto exit_busy; pthread_cancel(knet_h->control_thread); pthread_join(knet_h->control_thread, &retval); if (retval != PTHREAD_CANCELED) goto exit_busy; close(knet_h->epollfd); pthread_rwlock_destroy(&knet_h->list_rwlock); free(knet_h->databuf); free(knet_h->pingbuf); free(knet_h); return 0; exit_busy: errno = EBUSY; return -EBUSY; } void knet_handle_setfwd(knet_handle_t knet_h, int enabled) { knet_h->enabled = (enabled == 1) ? 1 : 0; } void knet_link_timeout(struct knet_link *lnk, time_t interval, time_t timeout, int precision) { lnk->ping_interval = interval * 1000; /* microseconds */ lnk->pong_timeout = timeout * 1000; /* microseconds */ lnk->latency_fix = precision; lnk->latency_exp = precision - \ ((lnk->ping_interval * precision) / 8000000); } static void _handle_data_send(knet_handle_t knet_h) { int j; ssize_t len, snt; struct knet_host *i; len = read(knet_h->sockfd, knet_h->databuf->kf_data, KNET_DATABUFSIZE - KNET_FRAME_SIZE); if (len == 0) { /* TODO: disconnection, should never happen! */ return; } len += KNET_FRAME_SIZE; if (knet_h->enabled != 1) /* data forward is disabled */ return; /* TODO: packet inspection */ knet_h->databuf->kf_type = KNET_FRAME_DATA; if (pthread_rwlock_rdlock(&knet_h->list_rwlock) != 0) return; for (i = knet_h->host_head; i != NULL; i = i->next) { for (j = 0; j < KNET_MAX_LINK; j++) { if (i->link[j].enabled != 1) /* link is disabled */ continue; snt = sendto(i->link[j].sock, knet_h->databuf, len, MSG_DONTWAIT, (struct sockaddr *) &i->link[j].address, sizeof(struct sockaddr_storage)); if ((i->active == 0) && (snt == len)) break; } } pthread_rwlock_unlock(&knet_h->list_rwlock); } static void _handle_recv_frame(knet_handle_t knet_h, int sockfd) { ssize_t len; struct sockaddr_storage address; socklen_t addrlen; struct knet_host *src_host; struct knet_link *src_link; unsigned long long latency_last; if (pthread_rwlock_rdlock(&knet_h->list_rwlock) != 0) return; addrlen = sizeof(struct sockaddr_storage); len = recvfrom(sockfd, knet_h->databuf, KNET_DATABUFSIZE, MSG_DONTWAIT, (struct sockaddr *) &address, &addrlen); if (len < (KNET_FRAME_SIZE + 1)) goto exit_unlock; if (ntohl(knet_h->databuf->kf_magic) != KNET_FRAME_MAGIC) goto exit_unlock; if (knet_h->databuf->kf_version != KNET_FRAME_VERSION) goto exit_unlock; src_host = NULL; src_link = NULL; if ((knet_h->databuf->kf_type & KNET_FRAME_PMSK) != 0) { knet_h->databuf->kf_node = ntohs(knet_h->databuf->kf_node); src_host = knet_h->host_index[knet_h->databuf->kf_node]; if (src_host == NULL) /* host not found */ goto exit_unlock; src_link = src_host->link + (knet_h->databuf->kf_link % KNET_MAX_LINK); } switch (knet_h->databuf->kf_type) { case KNET_FRAME_DATA: if (knet_h->enabled != 1) /* data forward is disabled */ break; write(knet_h->sockfd, knet_h->databuf->kf_data, len - KNET_FRAME_SIZE); break; case KNET_FRAME_PING: knet_h->databuf->kf_type = KNET_FRAME_PONG; knet_h->databuf->kf_node = htons(knet_h->node_id); sendto(src_link->sock, knet_h->databuf, len, MSG_DONTWAIT, (struct sockaddr *) &src_link->address, sizeof(struct sockaddr_storage)); break; case KNET_FRAME_PONG: clock_gettime(CLOCK_MONOTONIC, &src_link->pong_last); timespec_diff(knet_h->databuf->kf_time, src_link->pong_last, &latency_last); src_link->latency = ((src_link->latency * src_link->latency_exp) + ((latency_last / 1000llu) * (src_link->latency_fix - src_link->latency_exp))) / src_link->latency_fix; if (src_link->latency < src_link->pong_timeout) src_link->enabled = 1; break; default: goto exit_unlock; } exit_unlock: pthread_rwlock_unlock(&knet_h->list_rwlock); } static void _handle_check_each(knet_handle_t knet_h, struct knet_link *dst_link) { int len; struct timespec clock_now, pong_last; unsigned long long diff_ping; /* caching last pong to avoid race conditions */ pong_last = dst_link->pong_last; if (clock_gettime(CLOCK_MONOTONIC, &clock_now) != 0) return; timespec_diff(dst_link->ping_last, clock_now, &diff_ping); if (diff_ping >= (dst_link->ping_interval * 1000llu)) { knet_h->pingbuf->kf_time = clock_now; knet_h->pingbuf->kf_link = dst_link->link_id; len = sendto(dst_link->sock, knet_h->pingbuf, KNET_PINGBUFSIZE, MSG_DONTWAIT, (struct sockaddr *) &dst_link->address, sizeof(struct sockaddr_storage)); if (len == KNET_PINGBUFSIZE) dst_link->ping_last = clock_now; } if (dst_link->enabled == 1) { timespec_diff(pong_last, clock_now, &diff_ping); if (diff_ping >= (dst_link->pong_timeout * 1000llu)) dst_link->enabled = 0; /* TODO: might need write lock */ } } static void *_handle_heartbt_thread(void *data) { int j; knet_handle_t knet_h; struct knet_host *i; knet_h = (knet_handle_t) data; /* preparing ping buffer */ knet_h->pingbuf->kf_magic = htonl(KNET_FRAME_MAGIC); knet_h->pingbuf->kf_version = KNET_FRAME_VERSION; knet_h->pingbuf->kf_type = KNET_FRAME_PING; knet_h->pingbuf->kf_node = htons(knet_h->node_id); while (1) { usleep(KNET_PING_TIMERES); if (pthread_rwlock_rdlock(&knet_h->list_rwlock) != 0) continue; for (i = knet_h->host_head; i != NULL; i = i->next) { for (j = 0; j < KNET_MAX_LINK; j++) { if (i->link[j].ready != 1) continue; _handle_check_each(knet_h, &i->link[j]); } } pthread_rwlock_unlock(&knet_h->list_rwlock); } return NULL; } static void *_handle_control_thread(void *data) { int i, nev; knet_handle_t knet_h; struct epoll_event events[KNET_MAX_EVENTS]; knet_h = (knet_handle_t) data; /* preparing data buffer */ knet_h->databuf->kf_magic = htonl(KNET_FRAME_MAGIC); knet_h->databuf->kf_version = KNET_FRAME_VERSION; while (1) { nev = epoll_wait(knet_h->epollfd, events, KNET_MAX_EVENTS, -1); for (i = 0; i < nev; i++) { if (events[i].data.fd == knet_h->sockfd) { _handle_data_send(knet_h); } else { _handle_recv_frame(knet_h, events[i].data.fd); } } } return NULL; } diff --git a/libknet/libknet-private.h b/libknet/libknet-private.h index 44e6bb9e..750986aa 100644 --- a/libknet/libknet-private.h +++ b/libknet/libknet-private.h @@ -1,34 +1,36 @@ #ifndef __KNETHANDLE_H__ #define __KNETHANDLE_H__ /* NOTE: you shouldn't need to include this header normally, it is provided for * testing purpose only. */ #include "libknet.h" #define timespec_diff(start, end, diff) \ do { \ if (end.tv_sec > start.tv_sec) \ *(diff) = ((end.tv_sec - start.tv_sec) * 1000000000llu) \ + end.tv_nsec - start.tv_nsec; \ else \ *(diff) = end.tv_nsec - start.tv_nsec; \ } while (0); struct knet_handle { int sockfd; int epollfd; uint16_t node_id; unsigned int enabled:1; struct knet_host *host_head; struct knet_host *host_index[KNET_MAX_HOST]; struct knet_listener *listener_head; struct knet_frame *databuf; struct knet_frame *pingbuf; pthread_t control_thread; pthread_t heartbt_thread; pthread_rwlock_t list_rwlock; }; +int _fdset_cloexec(int fd); + #endif diff --git a/libknet/listener.c b/libknet/listener.c index 5cae6a25..fbef9117 100644 --- a/libknet/listener.c +++ b/libknet/listener.c @@ -1,122 +1,122 @@ #include "config.h" #include #include #include #include +#include -#include "utils.h" #include "libknet-private.h" int knet_listener_acquire(knet_handle_t knet_h, struct knet_listener **head, int writelock) { int ret; if (writelock != 0) ret = pthread_rwlock_wrlock(&knet_h->list_rwlock); else ret = pthread_rwlock_rdlock(&knet_h->list_rwlock); if (head) *head = (ret == 0) ? knet_h->listener_head : NULL; return ret; } int knet_listener_release(knet_handle_t knet_h) { return pthread_rwlock_unlock(&knet_h->list_rwlock); } int knet_listener_add(knet_handle_t knet_h, struct knet_listener *listener) { int value; struct epoll_event ev; listener->sock = socket(listener->address.ss_family, SOCK_DGRAM, 0); if (listener->sock < 0) return listener->sock; value = KNET_RING_RCVBUFF; setsockopt(listener->sock, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)); - if (knet_fdset_cloexec(listener->sock) != 0) + if (_fdset_cloexec(listener->sock) != 0) goto exit_fail1; if (bind(listener->sock, (struct sockaddr *) &listener->address, sizeof(struct sockaddr_storage)) != 0) goto exit_fail1; memset(&ev, 0, sizeof(struct epoll_event)); ev.events = EPOLLIN; ev.data.fd = listener->sock; if (epoll_ctl(knet_h->epollfd, EPOLL_CTL_ADD, listener->sock, &ev) != 0) goto exit_fail1; if (pthread_rwlock_wrlock(&knet_h->list_rwlock) != 0) goto exit_fail2; /* pushing new host to the front */ listener->next = knet_h->listener_head; knet_h->listener_head = listener; pthread_rwlock_unlock(&knet_h->list_rwlock); return 0; exit_fail2: epoll_ctl(knet_h->epollfd, EPOLL_CTL_DEL, listener->sock, &ev); exit_fail1: close(listener->sock); return -1; } int knet_listener_remove(knet_handle_t knet_h, struct knet_listener *listener) { int i, ret; struct epoll_event ev; /* kernel < 2.6.9 bug (see epoll_ctl man) */ struct knet_host *host; struct knet_listener *l; if (pthread_rwlock_wrlock(&knet_h->list_rwlock) != 0) return -EINVAL; ret = 0; /* checking if listener is in use */ for (host = knet_h->host_head; host != NULL; host = host->next) { for (i = 0; i < KNET_MAX_LINK; i++) { if (host->link[i].ready != 1) continue; if (host->link[i].sock == listener->sock) { ret = -EBUSY; goto exit_fail1; } } } /* TODO: use a doubly-linked list? */ if (listener == knet_h->listener_head) { knet_h->listener_head = knet_h->listener_head->next; } else { for (l = knet_h->listener_head; l != NULL; l = l->next) { if (listener == l->next) { l->next = l->next->next; break; } } } epoll_ctl(knet_h->epollfd, EPOLL_CTL_DEL, listener->sock, &ev); close(listener->sock); exit_fail1: pthread_rwlock_unlock(&knet_h->list_rwlock); if (ret < 0) errno = -ret; return ret; } diff --git a/libvty/vty.c b/libvty/vty.c index 40993542..07576b32 100644 --- a/libvty/vty.c +++ b/libvty/vty.c @@ -1,333 +1,339 @@ #include "config.h" #include #include #include #include #include #include #include #include #include #include "cfg.h" #include "utils.h" #include "netutils.h" #include "vty.h" #include "vty_auth.h" #include "vty_cli.h" #include "vty_cli_cmds.h" #include "vty_utils.h" static int vty_max_connections = KNET_VTY_DEFAULT_MAX_CONN; static int vty_current_connections = 0; static int daemon_quit = 0; pthread_mutex_t knet_vty_mutex = PTHREAD_MUTEX_INITIALIZER; int knet_vty_config = -1; struct knet_vty knet_vtys[KNET_VTY_TOTAL_MAX_CONN]; static int knet_vty_init_listener(const char *ip_addr, const char *port) { - int sockfd = -1, sockopt = 1; + int sockfd = -1, sockopt = 1, sockflags = -1; int socktype = SOCK_STREAM; int err = 0; struct sockaddr_storage ss; memset(&ss, 0, sizeof(struct sockaddr_storage)); if (strtoaddr(ip_addr, port, (struct sockaddr *)&ss, sizeof(struct sockaddr_storage)) != 0) return -1; pthread_mutex_lock(&knet_vty_mutex); /* handle sigpipe if we decide to use KEEPALIVE */ sockfd = socket(ss.ss_family, socktype, 0); if (sockfd < 0) { err = sockfd; goto out_clean; } err = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&sockopt, sizeof(sockopt)); if (err) goto out_clean; - if (knet_fdset_cloexec(sockfd) < 0) { + sockflags = fcntl(sockfd, F_GETFD, 0); + if (sockflags < 0) { + err = -1; + goto out_clean; + } + sockflags |= FD_CLOEXEC; + if (fcntl(sockfd, F_SETFD, sockflags) < 0) err = -1; goto out_clean; } err = bind(sockfd, (struct sockaddr *)&ss, sizeof(struct sockaddr_storage)); if (err) goto out_clean; err = listen(sockfd, 0); if (err) goto out_clean; pthread_mutex_unlock(&knet_vty_mutex); return sockfd; out_clean: if (sockfd >= 0) close(sockfd); pthread_mutex_unlock(&knet_vty_mutex); return err; } static void knet_vty_close_listener(int listener_fd) { pthread_mutex_lock(&knet_vty_mutex); if (listener_fd <= 0) goto out_clean; close(listener_fd); listener_fd = 0; out_clean: pthread_mutex_unlock(&knet_vty_mutex); return; } static void sigterm_handler(int sig) { daemon_quit = 1; } static void sigpipe_handler(int sig) { return; } static void knet_vty_close(struct knet_vty *vty) { if (knet_vty_config == vty->conn_num) knet_vty_config = -1; knet_vty_free_history(vty); vty->active = 0; close(vty->vty_sock); vty_current_connections--; } static void *vty_accept_thread(void *arg) { struct knet_vty *vty = (struct knet_vty *)&knet_vtys[*(int *)arg]; char *src_ip[2]; int err; knet_vty_print_banner(vty); if (vty->got_epipe) goto out_clean; src_ip[0] = NULL; err = addrtostr((struct sockaddr *)&vty->src_sa, vty->src_sa_len, src_ip); if (!err) { strncpy(vty->ip, src_ip[0], sizeof(vty->ip)); } else { strcpy(vty->ip, "unknown"); } if (src_ip[0]) addrtostr_free(src_ip); if ((knet_vty_auth_user(vty, NULL) < 0) && (!vty->got_epipe)) { log_info("User failed to authenticate (ip: %s)", vty->ip); goto out_clean; } if (vty->got_epipe) goto out_clean; log_info("User %s connected from %s", vty->username, vty->ip); knet_vty_write(vty, "Welcome %s (%s) on vty(%d)\n\n", vty->username, vty->ip, vty->conn_num); if (vty->got_epipe) goto out_clean; if (knet_vty_set_iacs(vty) < 0) { knet_vty_write(vty, "Unable to set telnet session preferences"); goto out_clean; } if (vty->got_epipe) goto out_clean; knet_vty_cli_bind(vty); out_clean: pthread_mutex_lock(&knet_vty_mutex); knet_vty_close(vty); pthread_mutex_unlock(&knet_vty_mutex); return NULL; } /* * mainloop is not thread safe as there should only be one */ int knet_vty_main_loop(void) { int vty_listener_fd; int vty_accept_fd; struct sockaddr_storage incoming_sa; socklen_t salen; fd_set rfds; int se_result = 0; struct timeval tv; int err = 0; int conn_index, found; signal(SIGTERM, sigterm_handler); signal(SIGINT, sigterm_handler); signal(SIGPIPE, sigpipe_handler); memset(&knet_vtys, 0, sizeof(knet_vtys)); if (knet_read_conf() < 0) { log_error("Unable to read config file %s", knet_cfg_head.conffile); return -1; } vty_listener_fd = knet_vty_init_listener(knet_cfg_head.vty_ip, knet_cfg_head.vty_port); if (vty_listener_fd < 0) { log_error("Unable to setup vty listener"); return -1; } while (se_result >= 0 && !daemon_quit) { FD_ZERO (&rfds); FD_SET (vty_listener_fd, &rfds); tv.tv_sec = 1; tv.tv_usec = 0; se_result = select((vty_listener_fd + 1), &rfds, 0, 0, &tv); if ((se_result == -1) && (daemon_quit)) { log_info("Got a SIGTERM, requesting CLI threads to exit"); for(conn_index = 0; conn_index < KNET_VTY_TOTAL_MAX_CONN; conn_index++) { if (knet_vtys[conn_index].active) { knet_vty_write(&knet_vtys[conn_index], "%s%sServer is going down..%s%s", telnet_newline, telnet_newline, telnet_newline, telnet_newline); knet_vty_close(&knet_vtys[conn_index]); knet_vtys[conn_index].got_epipe = 1; } } sleep(2); log_info("Have a nice day! Goodbye"); goto out; } if (se_result == -1) { err = se_result; log_error("Unable to select on vty listener socket!"); goto out; } if (se_result == 0) { pthread_mutex_lock(&knet_vty_mutex); for(conn_index = 0; conn_index < KNET_VTY_TOTAL_MAX_CONN; conn_index++) { if ((knet_vtys[conn_index].active) && (!knet_vtys[conn_index].disable_idle)) { knet_vtys[conn_index].idle++; if (knet_vtys[conn_index].idle > KNET_VTY_CLI_TIMEOUT) { knet_vty_close(&knet_vtys[conn_index]); knet_vtys[conn_index].got_epipe = 1; } } } pthread_mutex_unlock(&knet_vty_mutex); continue; } if (!FD_ISSET(vty_listener_fd, &rfds)) continue; memset(&incoming_sa, 0, sizeof(struct sockaddr_storage)); salen = sizeof(struct sockaddr_storage); vty_accept_fd = accept(vty_listener_fd, (struct sockaddr *)&incoming_sa, &salen); if (vty_accept_fd < 0) { log_error("Unable to accept connection to vty"); continue; } // check for ip address access list here against incoming_sa pthread_mutex_lock(&knet_vty_mutex); found = 0; for(conn_index = 0; conn_index <= vty_max_connections; conn_index++) { if (knet_vtys[conn_index].active == 0) { found = 1; break; } } if ((vty_current_connections == vty_max_connections) || (!found)) { errno = ECONNREFUSED; log_error("Too many connections to VTY or no available slots"); close(vty_accept_fd); pthread_mutex_unlock(&knet_vty_mutex); continue; } vty_current_connections++; memset(&knet_vtys[conn_index], 0, sizeof(struct knet_vty)); knet_vtys[conn_index].vty_sock = vty_accept_fd; knet_vtys[conn_index].conn_num = conn_index; memcpy(&knet_vtys[conn_index].src_sa, &incoming_sa, salen); knet_vtys[conn_index].src_sa_len = salen; knet_vtys[conn_index].active = 1; err = pthread_create(&knet_vtys[conn_index].vty_thread, NULL, vty_accept_thread, (void *)&conn_index); if (err < 0) { log_error("Unable to spawn vty thread"); memset(&knet_vtys[conn_index], 0, sizeof(struct knet_vty)); vty_current_connections--; } pthread_mutex_unlock(&knet_vty_mutex); } out: knet_vty_close_listener(vty_listener_fd); // reverse running config to close/release resources; return err; } /* int knet_vty_set_max_connections(const int max_connections) { int err = 0; pthread_mutex_lock(&knet_vty_mutex); if ((max_connections > KNET_VTY_TOTAL_MAX_CONN) || (max_connections < 1)) { errno = EINVAL; err = -1; } else { vty_max_connections = max_connections; } pthread_mutex_unlock(&knet_vty_mutex); return err; } */ diff --git a/utils.c b/utils.c index c7022ce9..1db4aac9 100644 --- a/utils.c +++ b/utils.c @@ -1,25 +1,9 @@ #include "config.h" #include #include #include "utils.h" int utils_debug = 0; int utils_syslog = 0; - -int knet_fdset_cloexec(int fd) -{ - int fdflags; - - fdflags = fcntl(fd, F_GETFD, 0); - if (fdflags < 0) - return -1; - - fdflags |= FD_CLOEXEC; - - if (fcntl(fd, F_SETFD, fdflags) < 0) - return -1; - - return 0; -} diff --git a/utils.h b/utils.h index 5b38426e..3c4596d5 100644 --- a/utils.h +++ b/utils.h @@ -1,34 +1,32 @@ #ifndef __UTILS_H__ #define __UTILS_H__ #include #include #include #include extern int utils_debug; extern int utils_syslog; #define log_debug(fmt, args...) \ do { \ if (utils_debug) { \ printf("DEBUG(%s:%i|%s): " fmt "\n", __FILE__, __LINE__, __FUNCTION__, ##args); \ if (utils_syslog) syslog(LOG_DEBUG, "DEBUG(%s:%i|%s): " fmt, __FILE__, __LINE__, __FUNCTION__, ##args); \ } \ } while (0); #define log_info(fmt, args...) \ do { \ fprintf(stderr, "Notice: " fmt "\n", ##args); \ if (utils_syslog) syslog(LOG_INFO, fmt, ##args); \ } while (0); #define log_error(fmt, args...) \ do { \ fprintf(stderr, "Error: " fmt " (%s)\n", ##args, strerror(errno)); \ if (utils_syslog) syslog(LOG_ERR, fmt, ##args); \ } while (0); -int knet_fdset_cloexec(int fd); - #endif