summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoern Engel <joern@logfs.org>2012-01-17 10:31:55 -0800
committerJoern Engel <joern@logfs.org>2012-01-17 10:31:55 -0800
commit1c8f5e7187ec44133236198cbae7b0dae218aed2 (patch)
treee66e4c1cf95817324bfac7583b3d4cf31a63dfcb
parentd3e3761bda56a89807f7fd1b24541aab9d332dbe (diff)
downloadcancd-1c8f5e7187ec44133236198cbae7b0dae218aed2.tar.gz
Copy data from ip-file to name-file
Also remove the "optimization" strcmp, as it was buggy. Signed-off-by: Joern Engel <joern@logfs.org>
-rw-r--r--cancd.c53
1 files changed, 49 insertions, 4 deletions
diff --git a/cancd.c b/cancd.c
index 467ecab..15fff83 100644
--- a/cancd.c
+++ b/cancd.c
@@ -364,7 +364,7 @@ static struct source_ip *get_source_ip(struct sockaddr_in *addr)
if (!sip) {
sip = calloc(1, sizeof(*sip));
sip->had_newline = 1;
- sip->filename = get_path(&addr->sin_addr);
+ sip->tmpfilename = get_path(&addr->sin_addr);
err = btree_insert32(&btree, key, sip);
assert(!err);
sem_post(&dns_sem);
@@ -372,13 +372,60 @@ static struct source_ip *get_source_ip(struct sockaddr_in *addr)
return sip;
}
+/*
+ * Basically just returns the filename, but with a twist. The until the DNS
+ * resolver gives us a decent filename, we use a temporary one based on the
+ * IP address. Once we have a decent filename, we copy everything from the
+ * temporary file to the final one. So hopefully there is just a short
+ * window with IP filenames around and never should we lose data.
+ */
+static const char *copy_tmpfile(struct source_ip *sip)
+{
+ int fd, tmpfd;
+ const char *name, *tmpname;
+
+ name = sip->filename;
+ tmpname = sip->tmpfilename;
+ if (name && tmpname) {
+ char buf[4096];
+ ssize_t count;
+
+ fd = open(name, O_WRONLY | O_APPEND | O_CREAT, 0600);
+ if (fd < 0) {
+ syslog(LOG_ERR, "Unable to open \"%s\": %s", name,
+ strerror(errno));
+ goto out;
+ }
+ tmpfd = open(tmpname, O_RDONLY);
+ if (tmpfd < 0) {
+ syslog(LOG_ERR, "Unable to open \"%s\": %s", name,
+ strerror(errno));
+ close(fd);
+ goto out;
+ }
+ while ((count = read(tmpfd, buf, sizeof(buf))) > 0)
+ do_write(fd, buf, count);
+ close(tmpfd);
+ close(fd);
+ unlink(tmpname);
+ sip->tmpfilename = NULL;
+ free((void *)tmpname);
+ }
+out:
+ if (sip->tmpfilename)
+ return sip->tmpfilename;
+ if (sip->filename)
+ return sip->filename;
+ return NULL;
+}
+
static void do_output(char *buf, int len, struct sockaddr_in *addr, socklen_t socklen)
{
int fd;
const char *name;
struct source_ip *sip = get_source_ip(addr);
- name = sip->filename;
+ name = copy_tmpfile(sip);
if (!name)
return;
@@ -636,8 +683,6 @@ static void dns_visitor(void *_sip, long unused, u32 ip, size_t unused2)
he = gethostbyaddr(&ip, 4, AF_INET);
if (!he)
return;
- if (strcmp(he->h_name, sip->filename) == 0)
- return;
new = strdup(he->h_name);
if (!new)
return;