summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2010-12-23 14:33:16 +0100
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2010-12-23 14:33:16 +0100
commitcce6edeef0e3829fb88185cebf13b21963afe032 (patch)
treedc32e18925a9eb358d5883ce4b51fc6962875021
parent6c4f5407eb7470a0a1522212667bb28119e52118 (diff)
Listing/saving of large sets could produce broken listing, fixed.
The wrapper around getnameinfo was not snprintf-compatible and that could cause broken listing/saving for large sets.
-rw-r--r--lib/print.c5
-rw-r--r--lib/session.c20
2 files changed, 16 insertions, 9 deletions
diff --git a/lib/print.c b/lib/print.c
index 767fd04..b6819e5 100644
--- a/lib/print.c
+++ b/lib/print.c
@@ -162,7 +162,9 @@ __getnameinfo##f(char *buf, unsigned int len, \
sizeof(saddr), \
buf, len, NULL, 0, \
flags | NI_NUMERICHOST); \
- return (err != 0 ? -1 : (int)strlen(buf)); \
+ D("getnameinfo err: %i, errno %i", err, errno); \
+ return (err == 0 ? (int)strlen(buf) : \
+ (err == EAI_OVERFLOW || err == EAI_SYSTEM) ? (int)len : -1);\
}
#define SNPRINTF_IP(mask, f) \
@@ -236,6 +238,7 @@ ipset_print_ip(char *buf, unsigned int len,
size = snprintf_ipv6(buf, len, flags, ip, cidr);
else
return -1;
+ D("size %i, len %u", size, len);
SNPRINTF_FAILURE(size, len, offset);
D("len: %u, offset %u", len, offset);
diff --git a/lib/session.c b/lib/session.c
index 4a08b94..2a57378 100644
--- a/lib/session.c
+++ b/lib/session.c
@@ -636,9 +636,10 @@ safe_snprintf(struct ipset_session *session, const char *fmt, ...)
int len, ret, loop = 0;
retry:
- len = IPSET_OUTBUFLEN - strlen(session->outbuf);
+ len = strlen(session->outbuf);
+ D("len: %u, retry %u", len, loop);
va_start(args, fmt);
- ret = vsnprintf(session->outbuf + IPSET_OUTBUFLEN - len, len,
+ ret = vsnprintf(session->outbuf + len, IPSET_OUTBUFLEN - len,
fmt, args);
va_end(args);
@@ -646,13 +647,14 @@ retry:
return ipset_err(session,
"Internal error at printing to output buffer");
- if (ret >= len) {
+ if (ret >= IPSET_OUTBUFLEN - len) {
/* Buffer was too small, push it out and retry */
+ D("print buffer and try again: %u", len);
if (loop++)
return ipset_err(session,
"Internal error at printing, loop detected!");
- session->outbuf[IPSET_OUTBUFLEN - len] = '\0';
+ session->outbuf[len] = '\0';
if (!call_outfn(session))
goto retry;
}
@@ -666,21 +668,23 @@ safe_dprintf(struct ipset_session *session, ipset_printfn fn,
int len, ret, loop = 0;
retry:
- len = IPSET_OUTBUFLEN - strlen(session->outbuf);
- ret = fn(session->outbuf + IPSET_OUTBUFLEN - len, len,
+ len = strlen(session->outbuf);
+ D("len: %u, retry %u", len, loop);
+ ret = fn(session->outbuf + len, IPSET_OUTBUFLEN - len,
session->data, opt, session->envopts);
if (ret < 0)
return ipset_err(session,
"Internal error at printing to output buffer");
- if (ret >= len) {
+ if (ret >= IPSET_OUTBUFLEN - len) {
/* Buffer was too small, push it out and retry */
+ D("print buffer and try again: %u", len);
if (loop++)
return ipset_err(session,
"Internal error at printing, loop detected!");
- session->outbuf[IPSET_OUTBUFLEN - len] = '\0';
+ session->outbuf[len] = '\0';
if (!call_outfn(session))
goto retry;
}