From d559314e3e3debe1ff8c2c1372701df6154a53ef Mon Sep 17 00:00:00 2001 From: Steven Barth Date: Mon, 15 Dec 2014 10:13:39 +0100 Subject: [PATCH 2/3] build: make nftables usable with mini-gmp libgmp usually compiles to >400KB which can put a burden on embedded device firmware especially if libgmp isn't used for other purposes. mini-gmp in contrast adds only ~30KB to the nft-binary itself. However mini-gmp does not support gmp_sscanf and gmp_printf. This patch: * Adds a configure flag --without-libgmp to select mini-gmp * Replaces the single gmp_sscanf occurence with mpz_set_str * Replaces calls to gmp_printf outside of pr_debug with a minimalistic mpz_printf usable to format one mpz_t * Replaces gmp_vasprintf in erec_vcreate with vasprintf and rewrites the single user of the gmp format-flags * Changes the parser token VERSION to IPHDRVERSION to avoid clashes with the VERSION-define in config.h Signed-off-by: Steven Barth --- configure.ac | 17 ++++++++++++++--- include/expression.h | 2 +- include/gmputil.h | 10 ++++++++++ include/utils.h | 3 +-- src/Makefile.am | 4 ++++ src/ct.c | 2 +- src/datatype.c | 8 +++----- src/erec.c | 6 +++++- src/evaluate.c | 8 ++++++-- src/gmputil.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/parser_bison.y | 6 +++--- src/scanner.l | 2 +- 12 files changed, 102 insertions(+), 20 deletions(-) diff --git a/configure.ac b/configure.ac index b55b2b1..1e3729d 100644 --- a/configure.ac +++ b/configure.ac @@ -73,8 +73,18 @@ AM_CONDITIONAL([BUILD_PDF], [test "$DBLATEX" == "found"]) PKG_CHECK_MODULES([LIBMNL], [libmnl >= 1.0.3]) PKG_CHECK_MODULES([LIBNFTNL], [libnftnl >= 1.0.2]) -AC_CHECK_LIB([gmp], [__gmpz_init], , - AC_MSG_ERROR([No suitable version of libgmp found])) +AC_ARG_WITH([libgmp], [AS_HELP_STRING([--without-libgmp], + [Disable libgmp support (use builtin mini-gmp)])], [], + [with_libgmp=yes]) +AS_IF([test "x$with_libgmp" != xno], [ +AC_CHECK_LIB([gmp],[__gmpz_init], , AC_MSG_ERROR([No suitable version of libgmp found])) +]) +AM_CONDITIONAL([BUILD_MINIGMP], [test "x$with_libgmp" == xno]) + + +AS_IF([test "x$with_libgmp" != xyes -a "x$CONFIG_DEBUG" = xy], [ +AC_MSG_ERROR([--without-libgmp MUST be used with --disable-debug]) +]) AC_ARG_WITH([cli], [AS_HELP_STRING([--without-cli], [disable interactive CLI (libreadline support)])], @@ -130,4 +140,5 @@ AC_OUTPUT echo " nft configuration: cli support: ${with_cli} - enable debugging: ${with_debug}" + enable debugging: ${with_debug} + use shared libgmp: ${with_libgmp}" diff --git a/include/expression.h b/include/expression.h index 4b96879..7477c3e 100644 --- a/include/expression.h +++ b/include/expression.h @@ -2,7 +2,7 @@ #define NFTABLES_EXPRESSION_H #include -#include +#include #include #include diff --git a/include/gmputil.h b/include/gmputil.h index 63eb0ba..b9ced6d 100644 --- a/include/gmputil.h +++ b/include/gmputil.h @@ -1,9 +1,17 @@ #ifndef NFTABLES_GMPUTIL_H #define NFTABLES_GMPUTIL_H +#include + +#ifdef HAVE_LIBGMP #include +#else +#include +#endif + #include + enum mpz_word_order { MPZ_MSWF = 1, MPZ_LSWF = -1, @@ -48,4 +56,6 @@ extern void mpz_import_data(mpz_t rop, const void *data, unsigned int len); extern void mpz_switch_byteorder(mpz_t rop, unsigned int len); +extern int mpz_printf(const char *format, const mpz_t value); + #endif /* NFTABLES_GMPUTIL_H */ diff --git a/include/utils.h b/include/utils.h index 15b2e39..3c436ba 100644 --- a/include/utils.h +++ b/include/utils.h @@ -9,14 +9,13 @@ #include #include #include -#include #define BITS_PER_BYTE 8 #ifdef DEBUG #define pr_debug(fmt, arg...) gmp_printf(fmt, ##arg) #else -#define pr_debug(fmt, arg...) ({ if (false) gmp_printf(fmt, ##arg); 0; }) +#define pr_debug(fmt, arg...) ({ if (false) {}; 0; }) #endif #define __fmtstring(x, y) __attribute__((format(printf, x, y))) diff --git a/src/Makefile.am b/src/Makefile.am index 378424d..099052a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,4 +51,8 @@ if BUILD_CLI nft_SOURCES += cli.c endif +if BUILD_MINIGMP +nft_SOURCES += mini-gmp.c +endif + nft_LDADD = ${LIBMNL_LIBS} ${LIBNFTNL_LIBS} diff --git a/src/ct.c b/src/ct.c index 2eb85ea..759e65d 100644 --- a/src/ct.c +++ b/src/ct.c @@ -110,7 +110,7 @@ static void ct_label_type_print(const struct expr *expr) return; } /* can happen when connlabel.conf is altered after rules were added */ - gmp_printf("0x%Zx", expr->value); + mpz_printf("0x%Zx", expr->value); } static struct error_record *ct_label_type_parse(const struct expr *sym, diff --git a/src/datatype.c b/src/datatype.c index 4519d87..40ce898 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -186,7 +186,7 @@ void symbol_table_print(const struct symbol_table *tbl, static void invalid_type_print(const struct expr *expr) { - gmp_printf("0x%Zx [invalid type]", expr->value); + mpz_printf("0x%Zx [invalid type]", expr->value); } const struct datatype invalid_type = { @@ -268,18 +268,16 @@ static void integer_type_print(const struct expr *expr) if (expr->dtype->basefmt != NULL) fmt = expr->dtype->basefmt; - gmp_printf(fmt, expr->value); + mpz_printf(fmt, expr->value); } static struct error_record *integer_type_parse(const struct expr *sym, struct expr **res) { mpz_t v; - int len; mpz_init(v); - if (gmp_sscanf(sym->identifier, "%Zu%n", v, &len) != 1 || - (int)strlen(sym->identifier) != len) { + if (mpz_set_str(v, sym->identifier, 0)) { mpz_clear(v); return error(&sym->location, "Could not parse %s", sym->dtype->desc); diff --git a/src/erec.c b/src/erec.c index 82543e6..810e9bf 100644 --- a/src/erec.c +++ b/src/erec.c @@ -44,6 +44,7 @@ static void erec_destroy(struct error_record *erec) xfree(erec); } +__attribute__((format(printf, 3, 0))) struct error_record *erec_vcreate(enum error_record_types type, const struct location *loc, const char *fmt, va_list ap) @@ -55,10 +56,13 @@ struct error_record *erec_vcreate(enum error_record_types type, erec->num_locations = 0; erec_add_location(erec, loc); - gmp_vasprintf(&erec->msg, fmt, ap); + if (vasprintf(&erec->msg, fmt, ap) < 0) + erec->msg = NULL; + return erec; } +__attribute__((format(printf, 3, 4))) struct error_record *erec_create(enum error_record_types type, const struct location *loc, const char *fmt, ...) diff --git a/src/evaluate.c b/src/evaluate.c index 0732660..3cb5cca 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -232,9 +232,13 @@ static int expr_evaluate_value(struct eval_ctx *ctx, struct expr **expr) case TYPE_INTEGER: mpz_init_bitmask(mask, ctx->ectx.len); if (mpz_cmp((*expr)->value, mask) > 0) { + char *valstr = mpz_get_str(NULL, 10, (*expr)->value); + char *rangestr = mpz_get_str(NULL, 10, mask); expr_error(ctx->msgs, *expr, - "Value %Zu exceeds valid range 0-%Zu", - (*expr)->value, mask); + "Value %s exceeds valid range 0-%s", + valstr, rangestr); + free(valstr); + free(rangestr); mpz_clear(mask); return -1; } diff --git a/src/gmputil.c b/src/gmputil.c index cb46445..acbf369 100644 --- a/src/gmputil.c +++ b/src/gmputil.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include @@ -148,6 +147,59 @@ void mpz_switch_byteorder(mpz_t rop, unsigned int len) mpz_import_data(rop, data, BYTEORDER_HOST_ENDIAN, len); } +int mpz_printf(const char *f, const mpz_t value) +{ + /* minimalistic gmp_printf replacement to format a single mpz_t + * using only mini-gmp functions */ + int n = 0; + while (*f) { + if (*f != '%') { + if (fputc(*f, stdout) != *f) + return -1; + + ++n; + } else { + unsigned long prec = 0; + int base; + size_t len; + char *str; + bool ok; + + if (*++f == '.') + prec = strtoul(++f, (char**)&f, 10); + + if (*f++ != 'Z') + return -1; + + if (*f == 'u') + base = 10; + else if (*f == 'x') + base = 16; + else + return -1; + + len = mpz_sizeinbase(value, base); + while (prec-- > len) { + if (fputc('0', stdout) != '0') + return -1; + + ++n; + } + + str = mpz_get_str(NULL, base, value); + ok = str && fwrite(str, 1, len, stdout) == len; + free(str); + + if (!ok) + return -1; + + n += len; + } + ++f; + } + return n; +} + static void *gmp_xrealloc(void *ptr, size_t old_size, size_t new_size) { return xrealloc(ptr, new_size); diff --git a/src/parser_bison.y b/src/parser_bison.y index 99dbd08..eb5cf90 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -237,7 +237,7 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token OPERATION "operation" %token IP "ip" -%token VERSION "version" +%token IPHDRVERSION "version" %token HDRLENGTH "hdrlength" %token TOS "tos" %token LENGTH "length" @@ -1947,7 +1947,7 @@ ip_hdr_expr : IP ip_hdr_field } ; -ip_hdr_field : VERSION { $$ = IPHDR_VERSION; } +ip_hdr_field : IPHDRVERSION { $$ = IPHDR_VERSION; } | HDRLENGTH { $$ = IPHDR_HDRLENGTH; } | TOS { $$ = IPHDR_TOS; } | LENGTH { $$ = IPHDR_LENGTH; } @@ -1994,7 +1994,7 @@ ip6_hdr_expr : IP6 ip6_hdr_field } ; -ip6_hdr_field : VERSION { $$ = IP6HDR_VERSION; } +ip6_hdr_field : IPHDRVERSION { $$ = IP6HDR_VERSION; } | PRIORITY { $$ = IP6HDR_PRIORITY; } | FLOWLABEL { $$ = IP6HDR_FLOWLABEL; } | LENGTH { $$ = IP6HDR_LENGTH; } diff --git a/src/scanner.l b/src/scanner.l index ed87da6..92b6a10 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -349,7 +349,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "operation" { return OPERATION; } "ip" { return IP; } -"version" { return VERSION; } +"version" { return IPHDRVERSION; } "hdrlength" { return HDRLENGTH; } "tos" { return TOS; } "length" { return LENGTH; } -- 2.1.3