summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2009-08-21 16:06:11 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2009-08-21 16:06:11 +0200
commit9d99a7699d7021a1c219d6553e037ac7ba4a5a37 (patch)
tree54c7c4383e3c2e627ea7736e3345d558dcdf23b9
parent58411110894c0a9e6a1a1ec9dbdf2fbe2ef3da00 (diff)
downloadconntrack-tools-9d99a7699d7021a1c219d6553e037ac7ba4a5a37.tar.gz
conntrack-tools-9d99a7699d7021a1c219d6553e037ac7ba4a5a37.zip
conntrackd: allow to remove file descriptors from set
With this patch, we can remove file descriptors dinamically from our own file descriptor pool. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/fds.h9
-rw-r--r--src/fds.c46
2 files changed, 55 insertions, 0 deletions
diff --git a/include/fds.h b/include/fds.h
index 019d3f9..f3728d7 100644
--- a/include/fds.h
+++ b/include/fds.h
@@ -1,13 +1,22 @@
#ifndef _FDS_H_
#define _FDS_H_
+#include "linux_list.h"
+
struct fds {
int maxfd;
fd_set readfds;
+ struct list_head list;
+};
+
+struct fds_item {
+ struct list_head head;
+ int fd;
};
struct fds *create_fds(void);
void destroy_fds(struct fds *);
int register_fd(int fd, struct fds *fds);
+int unregister_fd(int fd, struct fds *fds);
#endif
diff --git a/src/fds.c b/src/fds.c
index fac3482..6304fcd 100644
--- a/src/fds.c
+++ b/src/fds.c
@@ -27,20 +27,66 @@ struct fds *create_fds(void)
if (fds == NULL)
return NULL;
+ INIT_LIST_HEAD(&fds->list);
+
return fds;
}
void destroy_fds(struct fds *fds)
{
+ struct fds_item *this, *tmp;
+
+ list_for_each_entry_safe(this, tmp, &fds->list, head) {
+ list_del(&this->head);
+ FD_CLR(this->fd, &fds->readfds);
+ free(this);
+ }
free(fds);
}
int register_fd(int fd, struct fds *fds)
{
+ struct fds_item *item;
+
FD_SET(fd, &fds->readfds);
if (fd > fds->maxfd)
fds->maxfd = fd;
+ item = calloc(sizeof(struct fds_item), 1);
+ if (item == NULL)
+ return -1;
+
+ item->fd = fd;
+ list_add(&item->head, &fds->list);
+
return 0;
}
+
+int unregister_fd(int fd, struct fds *fds)
+{
+ int found = 0, maxfd = -1;
+ struct fds_item *this, *tmp;
+
+ list_for_each_entry_safe(this, tmp, &fds->list, head) {
+ if (this->fd == fd) {
+ list_del(&this->head);
+ FD_CLR(this->fd, &fds->readfds);
+ free(this);
+ found = 1;
+ /* ... and recalculate maxfd, see below. */
+ }
+ }
+ /* not found, report an error. */
+ if (!found)
+ return -1;
+
+ /* calculate the new maximum fd. */
+ list_for_each_entry(this, &fds->list, head) {
+ if (maxfd < this->fd) {
+ maxfd = this->fd;
+ }
+ }
+ return 0;
+}
+