diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-09 13:08:37 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-09 13:08:37 +0000 |
commit | 971e619d8602fa52b1bfcb3ea65b7ab96be85318 (patch) | |
tree | 26feb2498c72b796e07b86349d17f544046de279 /src/gmputil.c | |
parent | Initial commit. (diff) | |
download | nftables-upstream.tar.xz nftables-upstream.zip |
Adding upstream version 1.0.9.upstream/1.0.9upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/gmputil.c')
-rw-r--r-- | src/gmputil.c | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/src/gmputil.c b/src/gmputil.c new file mode 100644 index 0000000..cb26b55 --- /dev/null +++ b/src/gmputil.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2008 Patrick McHardy <kaber@trash.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Development of this code funded by Astaro AG (http://www.astaro.com/) + */ + +#include <nft.h> + +#include <stddef.h> +#include <stdarg.h> +#include <stdio.h> +#include <unistd.h> + +#include <nftables.h> +#include <datatype.h> +#include <utils.h> + +void mpz_bitmask(mpz_t rop, unsigned int width) +{ + mpz_set_ui(rop, 0); + mpz_setbit(rop, width); + mpz_sub_ui(rop, rop, 1); +} + +void mpz_init_bitmask(mpz_t rop, unsigned int width) +{ + mpz_init2(rop, width); + mpz_bitmask(rop, width); +} + +void mpz_prefixmask(mpz_t rop, unsigned int width, unsigned int prefix_len) +{ + mpz_bitmask(rop, prefix_len); + mpz_lshift_ui(rop, width - prefix_len); +} + +void mpz_lshift_ui(mpz_t rop, unsigned int n) +{ + mpz_mul_2exp(rop, rop, n); +} + +void mpz_rshift_ui(mpz_t rop, unsigned int n) +{ + mpz_tdiv_q_2exp(rop, rop, n); +} + +#define mpz_get_type(type, endian, op) \ +({ \ + type ret = 0; \ + size_t cnt; \ + mpz_export(&ret, &cnt, MPZ_LSWF, sizeof(ret), endian, 0, op); \ + assert(cnt <= 1); \ + ret; \ + }) + +uint64_t mpz_get_uint64(const mpz_t op) +{ + return mpz_get_type(uint64_t, MPZ_HOST_ENDIAN, op); +} + +uint32_t mpz_get_uint32(const mpz_t op) +{ + return mpz_get_type(uint32_t, MPZ_HOST_ENDIAN, op); +} + +uint16_t mpz_get_uint16(const mpz_t op) +{ + return mpz_get_type(uint16_t, MPZ_HOST_ENDIAN, op); +} + +uint8_t mpz_get_uint8(const mpz_t op) +{ + return mpz_get_type(uint8_t, MPZ_HOST_ENDIAN, op); +} + +uint32_t mpz_get_be32(const mpz_t op) +{ + return mpz_get_type(uint32_t, MPZ_BIG_ENDIAN, op); +} + +uint16_t mpz_get_be16(const mpz_t op) +{ + return mpz_get_type(uint16_t, MPZ_BIG_ENDIAN, op); +} + +void *__mpz_export_data(void *data, const mpz_t op, enum byteorder byteorder, + unsigned int len) +{ + enum mpz_word_order order; + enum mpz_byte_order endian; + + switch (byteorder) { + case BYTEORDER_BIG_ENDIAN: + default: + order = MPZ_MSWF; + endian = MPZ_BIG_ENDIAN; + break; + case BYTEORDER_HOST_ENDIAN: + order = MPZ_HWO; + endian = MPZ_HOST_ENDIAN; + break; + } + + memset(data, 0, len); + mpz_export(data, NULL, order, len, endian, 0, op); + return data; +} + +void __mpz_import_data(mpz_t rop, const void *data, enum byteorder byteorder, + unsigned int len) +{ + enum mpz_word_order order; + enum mpz_byte_order endian; + + switch (byteorder) { + case BYTEORDER_BIG_ENDIAN: + default: + order = MPZ_MSWF; + endian = MPZ_BIG_ENDIAN; + break; + case BYTEORDER_HOST_ENDIAN: + order = MPZ_HWO; + endian = MPZ_HOST_ENDIAN; + break; + } + + mpz_import(rop, len, order, 1, endian, 0, data); +} + +void __mpz_switch_byteorder(mpz_t rop, unsigned int len) +{ + char data[len]; + + __mpz_export_data(data, rop, BYTEORDER_BIG_ENDIAN, len); + __mpz_import_data(rop, data, BYTEORDER_HOST_ENDIAN, len); +} + +#ifndef HAVE_LIBGMP +/* mini-gmp doesn't have a gmp_printf so we use our own minimal + * variant here which is able to format a single mpz_t. + */ +int mpz_vfprintf(FILE *fp, const char *f, va_list args) +{ + const mpz_t *value = va_arg(args, const mpz_t *); + int n = 0; + + while (*f) { + if (*f != '%') { + if (fputc(*f, fp) != *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', fp) != '0') + return -1; + + ++n; + } + + str = mpz_get_str(NULL, base, *value); + ok = str && fwrite(str, 1, len, fp) == len; + free(str); + + if (!ok) + return -1; + + n += len; + } + ++f; + } + return n; +} +#endif |