|
|
|
@ -706,33 +706,47 @@ call_outfn(struct ipset_session *session)
|
|
|
|
|
/* Handle printing failures */
|
|
|
|
|
static jmp_buf printf_failure;
|
|
|
|
|
|
|
|
|
|
static int __attribute__((format(printf, 2, 3)))
|
|
|
|
|
safe_snprintf(struct ipset_session *session, const char *fmt, ...)
|
|
|
|
|
static int
|
|
|
|
|
handle_snprintf_error(struct ipset_session *session,
|
|
|
|
|
int len, int ret, int loop)
|
|
|
|
|
{
|
|
|
|
|
va_list args;
|
|
|
|
|
int len, ret, loop = 0;
|
|
|
|
|
|
|
|
|
|
retry:
|
|
|
|
|
len = strlen(session->outbuf);
|
|
|
|
|
D("len: %u, retry %u", len, loop);
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
|
ret = vsnprintf(session->outbuf + len, IPSET_OUTBUFLEN - len,
|
|
|
|
|
fmt, args);
|
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
|
|
if (ret < 0 || ret >= IPSET_OUTBUFLEN - len) {
|
|
|
|
|
/* Buffer was too small, push it out and retry */
|
|
|
|
|
D("print buffer and try again: %u", len);
|
|
|
|
|
if (loop++) {
|
|
|
|
|
D("print buffer and try again: len: %u, ret: %d", len, ret);
|
|
|
|
|
if (loop) {
|
|
|
|
|
ipset_err(session,
|
|
|
|
|
"Internal error at printing, loop detected!");
|
|
|
|
|
longjmp(printf_failure, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
session->outbuf[len] = '\0';
|
|
|
|
|
if (!call_outfn(session))
|
|
|
|
|
goto retry;
|
|
|
|
|
if (call_outfn(session)) {
|
|
|
|
|
ipset_err(session,
|
|
|
|
|
"Internal error, could not print output buffer!");
|
|
|
|
|
longjmp(printf_failure, 1);
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int __attribute__((format(printf, 2, 3)))
|
|
|
|
|
safe_snprintf(struct ipset_session *session, const char *fmt, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list args;
|
|
|
|
|
int len, ret, loop = 0;
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
len = strlen(session->outbuf);
|
|
|
|
|
D("len: %u, retry %u", len, loop);
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
|
ret = vsnprintf(session->outbuf + len,
|
|
|
|
|
IPSET_OUTBUFLEN - len,
|
|
|
|
|
fmt, args);
|
|
|
|
|
va_end(args);
|
|
|
|
|
loop = handle_snprintf_error(session, len, ret, loop);
|
|
|
|
|
} while (loop);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -742,25 +756,14 @@ safe_dprintf(struct ipset_session *session, ipset_printfn fn,
|
|
|
|
|
{
|
|
|
|
|
int len, ret, loop = 0;
|
|
|
|
|
|
|
|
|
|
retry:
|
|
|
|
|
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 || ret >= IPSET_OUTBUFLEN - len) {
|
|
|
|
|
/* Buffer was too small, push it out and retry */
|
|
|
|
|
D("print buffer and try again: %u", len);
|
|
|
|
|
if (loop++) {
|
|
|
|
|
ipset_err(session,
|
|
|
|
|
"Internal error at printing, loop detected!");
|
|
|
|
|
longjmp(printf_failure, 1);
|
|
|
|
|
}
|
|
|
|
|
do {
|
|
|
|
|
len = strlen(session->outbuf);
|
|
|
|
|
D("len: %u, retry %u", len, loop);
|
|
|
|
|
ret = fn(session->outbuf + len, IPSET_OUTBUFLEN - len,
|
|
|
|
|
session->data, opt, session->envopts);
|
|
|
|
|
loop = handle_snprintf_error(session, len, ret, loop);
|
|
|
|
|
} while (loop);
|
|
|
|
|
|
|
|
|
|
session->outbuf[len] = '\0';
|
|
|
|
|
if (!call_outfn(session))
|
|
|
|
|
goto retry;
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|