build-aux/
libnftables.pc
libtool
+nftversion.h
# cscope files
/cscope.*
check_PROGRAMS =
dist_man_MANS =
CLEANFILES =
+DISTCLEANFILES =
###############################################################################
\
$(NULL)
+DISTCLEANFILES += nftversion.h
+
###############################################################################
AM_CPPFLAGS = \
)
AC_SUBST([unitdir])
+AC_ARG_WITH([stable-release], [AS_HELP_STRING([--with-stable-release],
+ [Stable release number])],
+ [], [with_stable_release=0])
+AC_CONFIG_COMMANDS([stable_release],
+ [STABLE_RELEASE=$stable_release],
+ [stable_release=$with_stable_release])
+AC_CONFIG_COMMANDS([nftversion.h], [
+(
+ echo "static char nftversion[[]] = {"
+ echo " ${VERSION}," | tr '.' ','
+ echo " ${STABLE_RELEASE}"
+ echo "};"
+ echo "static char nftbuildstamp[[]] = {"
+ for ((i = 56; i >= 0; i-= 8)); do
+ echo " ((uint64_t)MAKE_STAMP >> $i) & 0xff,"
+ done
+ echo "};"
+) >nftversion.h
+])
+# Current date should be fetched exactly once per build,
+# so have 'make' call date and pass the value to every 'gcc' call
+AC_SUBST([MAKE_STAMP], ["\$(shell date +%s)"])
+CFLAGS="${CFLAGS} -DMAKE_STAMP=\${MAKE_STAMP}"
+
AC_CONFIG_FILES([ \
Makefile \
libnftables.pc \
uint32_t owner;
const char *comment;
bool has_xt_stmts;
+ bool is_from_future;
};
extern struct table *table_alloc(void);
#include <nft.h>
#include <iface.h>
+#include <nftversion.h>
#include <libmnl/libmnl.h>
#include <libnftnl/common.h>
if (nlt == NULL)
memory_allocation_error();
+ udbuf = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
+ if (!udbuf)
+ memory_allocation_error();
+
nftnl_table_set_u32(nlt, NFTNL_TABLE_FAMILY, cmd->handle.family);
if (cmd->table) {
nftnl_table_set_u32(nlt, NFTNL_TABLE_FLAGS, cmd->table->flags);
if (cmd->table->comment) {
- udbuf = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
- if (!udbuf)
- memory_allocation_error();
if (!nftnl_udata_put_strz(udbuf, NFTNL_UDATA_TABLE_COMMENT, cmd->table->comment))
memory_allocation_error();
- nftnl_table_set_data(nlt, NFTNL_TABLE_USERDATA, nftnl_udata_buf_data(udbuf),
- nftnl_udata_buf_len(udbuf));
- nftnl_udata_buf_free(udbuf);
}
} else {
nftnl_table_set_u32(nlt, NFTNL_TABLE_FLAGS, 0);
}
+ if (!nftnl_udata_put(udbuf, NFTNL_UDATA_TABLE_NFTVER,
+ sizeof(nftversion), nftversion) ||
+ !nftnl_udata_put(udbuf, NFTNL_UDATA_TABLE_NFTBLD,
+ sizeof(nftbuildstamp), nftbuildstamp))
+ memory_allocation_error();
+ nftnl_table_set_data(nlt, NFTNL_TABLE_USERDATA,
+ nftnl_udata_buf_data(udbuf),
+ nftnl_udata_buf_len(udbuf));
+ nftnl_udata_buf_free(udbuf);
+
nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
NFT_MSG_NEWTABLE,
cmd->handle.family,
*/
#include <nft.h>
+#include <nftversion.h>
#include <errno.h>
#include <libmnl/libmnl.h>
if (value[len - 1] != '\0')
return -1;
break;
+ case NFTNL_UDATA_TABLE_NFTVER:
+ if (len != sizeof(nftversion))
+ return -1;
+ break;
+ case NFTNL_UDATA_TABLE_NFTBLD:
+ if (len != sizeof(nftbuildstamp))
+ return -1;
+ break;
default:
return 0;
}
return 0;
}
+static int version_cmp(const struct nftnl_udata **ud)
+{
+ const char *udbuf;
+ size_t i;
+
+ /* netlink attribute lengths checked by table_parse_udata_cb() */
+ if (ud[NFTNL_UDATA_TABLE_NFTVER]) {
+ udbuf = nftnl_udata_get(ud[NFTNL_UDATA_TABLE_NFTVER]);
+ for (i = 0; i < sizeof(nftversion); i++) {
+ if (nftversion[i] != udbuf[i])
+ return nftversion[i] - udbuf[i];
+ }
+ }
+ if (ud[NFTNL_UDATA_TABLE_NFTBLD]) {
+ udbuf = nftnl_udata_get(ud[NFTNL_UDATA_TABLE_NFTBLD]);
+ for (i = 0; i < sizeof(nftbuildstamp); i++) {
+ if (nftbuildstamp[i] != udbuf[i])
+ return nftbuildstamp[i] - udbuf[i];
+ }
+ }
+ return 0;
+}
+
struct table *netlink_delinearize_table(struct netlink_ctx *ctx,
const struct nftnl_table *nlt)
{
}
if (ud[NFTNL_UDATA_TABLE_COMMENT])
table->comment = xstrdup(nftnl_udata_get(ud[NFTNL_UDATA_TABLE_COMMENT]));
+ table->is_from_future = version_cmp(ud) < 0;
}
return table;
fprintf(octx->error_fp,
"# Warning: table %s %s is managed by iptables-nft, do not touch!\n",
family, table->handle.table.name);
+ if (table->is_from_future)
+ fprintf(octx->error_fp,
+ "# Warning: table %s %s was created by a newer version of nftables? Content may be incomplete!\n",
+ family, table->handle.table.name);
nft_print(octx, "table %s %s {", family, table->handle.table.name);
if (nft_output_handle(octx) || table->flags & TABLE_F_OWNER)