I think we should place osf_init in nfnl_osf.h so this way we don't need to 
include osf.h in rule.c. If you agree I will send another patchset iteration. 
Thanks.

El 10 de agosto de 2018 15:02:00 CEST, Fernando Fernandez Mancera 
<ffmanc...@riseup.net> escribió:
>Import iptables/utils/nfnl_osf.c into nftables tree with some changes
>in order
>to load OS fingerprints automatically from pf.os file.
>
>Signed-off-by: Fernando Fernandez Mancera <ffmanc...@riseup.net>
>---
> include/linux/netfilter/nfnetlink_osf.h | 119 +++++++
> include/nfnl_osf.h                      |   6 +
> include/osf.h                           |   2 +
> src/Makefile.am                         |   1 +
> src/nfnl_osf.c                          | 449 ++++++++++++++++++++++++
> src/osf.c                               |   2 +
> src/rule.c                              |   5 +
> 7 files changed, 584 insertions(+)
> create mode 100644 include/linux/netfilter/nfnetlink_osf.h
> create mode 100644 include/nfnl_osf.h
> create mode 100644 src/nfnl_osf.c
>
>diff --git a/include/linux/netfilter/nfnetlink_osf.h
>b/include/linux/netfilter/nfnetlink_osf.h
>new file mode 100644
>index 0000000..15a39d2
>--- /dev/null
>+++ b/include/linux/netfilter/nfnetlink_osf.h
>@@ -0,0 +1,119 @@
>+#ifndef _NF_OSF_H
>+#define _NF_OSF_H
>+
>+#include <linux/types.h>
>+
>+#define MAXGENRELEN   32
>+
>+#define NF_OSF_GENRE  (1 << 0)
>+#define NF_OSF_TTL    (1 << 1)
>+#define NF_OSF_LOG    (1 << 2)
>+#define NF_OSF_INVERT (1 << 3)
>+
>+#define NF_OSF_LOGLEVEL_ALL           0       /* log all matched fingerprints 
>*/
>+#define NF_OSF_LOGLEVEL_FIRST         1       /* log only the first matced
>fingerprint */
>+#define NF_OSF_LOGLEVEL_ALL_KNOWN     2       /* do not log unknown packets */
>+
>+#define NF_OSF_TTL_TRUE                       0       /* True ip and 
>fingerprint TTL comparison
>*/
>+
>+/* Check if ip TTL is less than fingerprint one */
>+#define NF_OSF_TTL_LESS                       1
>+
>+/* Do not compare ip and fingerprint TTL at all */
>+#define NF_OSF_TTL_NOCHECK            2
>+
>+#define NF_OSF_FLAGMASK               (NF_OSF_GENRE | NF_OSF_TTL | \
>+                               NF_OSF_LOG | NF_OSF_INVERT)
>+/* Wildcard MSS (kind of).
>+ * It is used to implement a state machine for the different wildcard
>values
>+ * of the MSS and window sizes.
>+ */
>+struct nf_osf_wc {
>+      __u32   wc;
>+      __u32   val;
>+};
>+
>+/* This struct represents IANA options
>+ * http://www.iana.org/assignments/tcp-parameters
>+ */
>+struct nf_osf_opt {
>+      __u16                   kind, length;
>+      struct nf_osf_wc        wc;
>+};
>+
>+struct nf_osf_info {
>+      char    genre[MAXGENRELEN];
>+      __u32   len;
>+      __u32   flags;
>+      __u32   loglevel;
>+      __u32   ttl;
>+};
>+
>+struct nf_osf_user_finger {
>+      struct nf_osf_wc        wss;
>+
>+      __u8    ttl, df;
>+      __u16   ss, mss;
>+      __u16   opt_num;
>+
>+      char    genre[MAXGENRELEN];
>+      char    version[MAXGENRELEN];
>+      char    subtype[MAXGENRELEN];
>+
>+      /* MAX_IPOPTLEN is maximum if all options are NOPs or EOLs */
>+      struct nf_osf_opt       opt[MAX_IPOPTLEN];
>+};
>+
>+struct nf_osf_nlmsg {
>+      struct nf_osf_user_finger       f;
>+      struct iphdr                    ip;
>+      struct tcphdr                   tcp;
>+};
>+
>+/* Defines for IANA option kinds */
>+enum iana_options {
>+      OSFOPT_EOL = 0,         /* End of options */
>+      OSFOPT_NOP,             /* NOP */
>+      OSFOPT_MSS,             /* Maximum segment size */
>+      OSFOPT_WSO,             /* Window scale option */
>+      OSFOPT_SACKP,           /* SACK permitted */
>+      OSFOPT_SACK,            /* SACK */
>+      OSFOPT_ECHO,
>+      OSFOPT_ECHOREPLY,
>+      OSFOPT_TS,              /* Timestamp option */
>+      OSFOPT_POCP,            /* Partial Order Connection Permitted */
>+      OSFOPT_POSP,            /* Partial Order Service Profile */
>+
>+      /* Others are not used in the current OSF */
>+      OSFOPT_EMPTY = 255,
>+};
>+
>+/*
>+ * Initial window size option state machine: multiple of mss, mtu or
>+ * plain numeric value. Can also be made as plain numeric value which
>+ * is not a multiple of specified value.
>+ */
>+enum nf_osf_window_size_options {
>+      OSF_WSS_PLAIN   = 0,
>+      OSF_WSS_MSS,
>+      OSF_WSS_MTU,
>+      OSF_WSS_MODULO,
>+      OSF_WSS_MAX,
>+};
>+
>+enum nf_osf_attr_type {
>+      OSF_ATTR_UNSPEC,
>+      OSF_ATTR_FINGER,
>+      OSF_ATTR_MAX,
>+};
>+
>+/*
>+ * Add/remove fingerprint from the kernel.
>+ */
>+enum nf_osf_msg_types {
>+      OSF_MSG_ADD,
>+      OSF_MSG_REMOVE,
>+      OSF_MSG_MAX,
>+};
>+
>+#endif /* _NF_OSF_H */
>diff --git a/include/nfnl_osf.h b/include/nfnl_osf.h
>new file mode 100644
>index 0000000..d9287e9
>--- /dev/null
>+++ b/include/nfnl_osf.h
>@@ -0,0 +1,6 @@
>+#ifndef _NFNL_OSF_H
>+#define _NFNL_OSF_H
>+
>+int nfnl_osf_load_fingerprints(struct netlink_ctx *ctx, int del);
>+
>+#endif        /* _NFNL_OSF_H */
>diff --git a/include/osf.h b/include/osf.h
>index 715b04e..0a35b07 100644
>--- a/include/osf.h
>+++ b/include/osf.h
>@@ -1,6 +1,8 @@
> #ifndef NFTABLES_OSF_H
> #define NFTABLES_OSF_H
> 
>+bool osf_init;
>+
> struct expr *osf_expr_alloc(const struct location *loc);
> 
> #endif /* NFTABLES_OSF_H */
>diff --git a/src/Makefile.am b/src/Makefile.am
>index ed3640e..e569029 100644
>--- a/src/Makefile.am
>+++ b/src/Makefile.am
>@@ -57,6 +57,7 @@ libnftables_la_SOURCES =                     \
>               services.c                      \
>               mergesort.c                     \
>               osf.c                           \
>+              nfnl_osf.c                      \
>               tcpopt.c                        \
>               socket.c                        \
>               libnftables.c
>diff --git a/src/nfnl_osf.c b/src/nfnl_osf.c
>new file mode 100644
>index 0000000..07bf682
>--- /dev/null
>+++ b/src/nfnl_osf.c
>@@ -0,0 +1,449 @@
>+/*
>+ * Copyright (c) 2005 Evgeniy Polyakov <john...@2ka.mxt.ru>
>+ *
>+ *
>+ * This program is free software; you can redistribute it and/or
>modify
>+ * it under the terms of the GNU General Public License as published
>by
>+ * the Free Software Foundation; either version 2 of the License, or
>+ * (at your option) any later version.
>+ *
>+ * This program is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>+ * GNU General Public License for more details.
>+ *
>+ * You should have received a copy of the GNU General Public License
>+ * along with this program; if not, write to the Free Software
>+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
>02110-1301, USA.
>+ */
>+
>+#include <sys/time.h>
>+
>+#include <ctype.h>
>+#include <errno.h>
>+#include <stdlib.h>
>+#include <string.h>
>+#include <time.h>
>+
>+#include <netinet/ip.h>
>+#include <netinet/tcp.h>
>+
>+#include <linux/unistd.h>
>+
>+#include <libmnl/libmnl.h>
>+
>+#include <linux/netfilter/nfnetlink.h>
>+#include <linux/netfilter/nfnetlink_osf.h>
>+#include <mnl.h>
>+#include <nfnl_osf.h>
>+
>+#define OPTDEL                        ','
>+#define OSFPDEL               ':'
>+#define MAXOPTSTRLEN          128
>+
>+static struct nf_osf_opt IANA_opts[] = {
>+      { .kind = 0, .length = 1,},
>+      { .kind=1, .length=1,},
>+      { .kind=2, .length=4,},
>+      { .kind=3, .length=3,},
>+      { .kind=4, .length=2,},
>+      { .kind=5, .length=1,},         /* SACK length is not defined */
>+      { .kind=6, .length=6,},
>+      { .kind=7, .length=6,},
>+      { .kind=8, .length=10,},
>+      { .kind=9, .length=2,},
>+      { .kind=10, .length=3,},
>+      { .kind=11, .length=1,},                /* CC: Suppose 1 */
>+      { .kind=12, .length=1,},                /* the same */
>+      { .kind=13, .length=1,},                /* and here too */
>+      { .kind=14, .length=3,},
>+      { .kind=15, .length=1,},                /* TCP Alternate Checksum Data. 
>Length is
>not defined */
>+      { .kind=16, .length=1,},
>+      { .kind=17, .length=1,},
>+      { .kind=18, .length=3,},
>+      { .kind=19, .length=18,},
>+      { .kind=20, .length=1,},
>+      { .kind=21, .length=1,},
>+      { .kind=22, .length=1,},
>+      { .kind=23, .length=1,},
>+      { .kind=24, .length=1,},
>+      { .kind=25, .length=1,},
>+      { .kind=26, .length=1,},
>+};
>+
>+static void uloga(const char *f, struct netlink_ctx *ctx, ...)
>+{
>+      if (!(ctx->debug_mask & NFT_DEBUG_NETLINK))
>+              return;
>+
>+      nft_print(ctx->octx, "%s", f);
>+}
>+
>+static void ulog(const char *f, struct netlink_ctx *ctx, ...)
>+{
>+      char str[64];
>+      struct tm tm;
>+      struct timeval tv;
>+
>+      gettimeofday(&tv, NULL);
>+      localtime_r((time_t *)&tv.tv_sec, &tm);
>+      strftime(str, sizeof(str), "%F %R:%S", &tm);
>+
>+      if (!(ctx->debug_mask & NFT_DEBUG_NETLINK))
>+              return;
>+
>+      nft_print(ctx->octx, "%s.%lu %ld %s", str, tv.tv_usec,
>+                syscall(__NR_gettid), f);
>+}
>+
>+#define ulog_err(f, ctx, a...) uloga(f ": %s [%d].\n", ctx, ##a,
>strerror(errno), errno)
>+
>+static char *nf_osf_strchr(char *ptr, char c)
>+{
>+      char *tmp;
>+
>+      tmp = strchr(ptr, c);
>+      if (tmp)
>+              *tmp = '\0';
>+
>+      while (tmp && tmp + 1 && isspace(*(tmp + 1)))
>+              tmp++;
>+
>+      return tmp;
>+}
>+
>+static void nf_osf_parse_opt(struct nf_osf_opt *opt, __u16 *optnum,
>char *obuf, int olen)
>+{
>+      int i, op;
>+      char *ptr, wc;
>+      unsigned long val;
>+
>+      ptr = &obuf[0];
>+      i = 0;
>+      while (ptr != NULL && i < olen && *ptr != 0) {
>+              val = 0;
>+              op = 0;
>+              wc = OSF_WSS_PLAIN;
>+              switch (obuf[i]) {
>+              case 'N':
>+                      op = OSFOPT_NOP;
>+                      ptr = nf_osf_strchr(&obuf[i], OPTDEL);
>+                      if (ptr) {
>+                              *ptr = '\0';
>+                              ptr++;
>+                              i += (int)(ptr - &obuf[i]);
>+                      } else
>+                              i++;
>+                      break;
>+              case 'S':
>+                      op = OSFOPT_SACKP;
>+                      ptr = nf_osf_strchr(&obuf[i], OPTDEL);
>+                      if (ptr) {
>+                              *ptr = '\0';
>+                              ptr++;
>+                              i += (int)(ptr - &obuf[i]);
>+                      } else
>+                              i++;
>+                      break;
>+              case 'T':
>+                      op = OSFOPT_TS;
>+                      ptr = nf_osf_strchr(&obuf[i], OPTDEL);
>+                      if (ptr) {
>+                              *ptr = '\0';
>+                              ptr++;
>+                              i += (int)(ptr - &obuf[i]);
>+                      } else
>+                              i++;
>+                      break;
>+              case 'W':
>+                      op = OSFOPT_WSO;
>+                      ptr = nf_osf_strchr(&obuf[i], OPTDEL);
>+                      if (ptr) {
>+                              switch (obuf[i + 1]) {
>+                              case '%':
>+                                      wc = OSF_WSS_MODULO;
>+                                      break;
>+                              case 'S':
>+                                      wc = OSF_WSS_MSS;
>+                                      break;
>+                              case 'T':
>+                                      wc = OSF_WSS_MTU;
>+                                      break;
>+                              default:
>+                                      wc = OSF_WSS_PLAIN;
>+                                      break;
>+                              }
>+
>+                              *ptr = '\0';
>+                              ptr++;
>+                              if (wc)
>+                                      val = strtoul(&obuf[i + 2], NULL, 10);
>+                              else
>+                                      val = strtoul(&obuf[i + 1], NULL, 10);
>+                              i += (int)(ptr - &obuf[i]);
>+
>+                      } else
>+                              i++;
>+                      break;
>+              case 'M':
>+                      op = OSFOPT_MSS;
>+                      ptr = nf_osf_strchr(&obuf[i], OPTDEL);
>+                      if (ptr) {
>+                              if (obuf[i + 1] == '%')
>+                                      wc = OSF_WSS_MODULO;
>+                              *ptr = '\0';
>+                              ptr++;
>+                              if (wc)
>+                                      val = strtoul(&obuf[i + 2], NULL, 10);
>+                              else
>+                                      val = strtoul(&obuf[i + 1], NULL, 10);
>+                              i += (int)(ptr - &obuf[i]);
>+                      } else
>+                              i++;
>+                      break;
>+              case 'E':
>+                      op = OSFOPT_EOL;
>+                      ptr = nf_osf_strchr(&obuf[i], OPTDEL);
>+                      if (ptr) {
>+                              *ptr = '\0';
>+                              ptr++;
>+                              i += (int)(ptr - &obuf[i]);
>+                      } else
>+                              i++;
>+                      break;
>+              default:
>+                      op = OSFOPT_EMPTY;
>+                      ptr = nf_osf_strchr(&obuf[i], OPTDEL);
>+                      if (ptr) {
>+                              ptr++;
>+                              i += (int)(ptr - &obuf[i]);
>+                      } else
>+                              i++;
>+                      break;
>+              }
>+
>+              if (op != OSFOPT_EMPTY) {
>+                      opt[*optnum].kind = IANA_opts[op].kind;
>+                      opt[*optnum].length = IANA_opts[op].length;
>+                      opt[*optnum].wc.wc = wc;
>+                      opt[*optnum].wc.val = val;
>+                      (*optnum)++;
>+              }
>+      }
>+}
>+
>+static int osf_load_line(char *buffer, int len, int del, struct
>mnl_socket *nl,
>+                       struct netlink_ctx *ctx)
>+{
>+      int i, cnt = 0;
>+      char obuf[MAXOPTSTRLEN];
>+      struct nf_osf_user_finger f;
>+      char *pbeg, *pend;
>+      struct nlmsghdr *nlh;
>+      struct nfgenmsg *nfg;
>+      char buf[MNL_SOCKET_BUFFER_SIZE];
>+
>+      memset(&f, 0, sizeof(struct nf_osf_user_finger));
>+
>+      ulog("Loading '%s'.\n", ctx, buffer);
>+
>+      for (i = 0; i < len && buffer[i] != '\0'; ++i) {
>+              if (buffer[i] == ':')
>+                      cnt++;
>+      }
>+
>+      if (cnt != 8) {
>+              ulog("Wrong input line '%s': cnt: %d, must be 8, i: %d, must be
>%d.\n", ctx, buffer, cnt, i, len);
>+              return -EINVAL;
>+      }
>+
>+      memset(obuf, 0, sizeof(obuf));
>+
>+      pbeg = buffer;
>+      pend = nf_osf_strchr(pbeg, OSFPDEL);
>+      if (pend) {
>+              *pend = '\0';
>+              if (pbeg[0] == 'S') {
>+                      f.wss.wc = OSF_WSS_MSS;
>+                      if (pbeg[1] == '%')
>+                              f.wss.val = strtoul(&pbeg[2], NULL, 10);
>+                      else if (pbeg[1] == '*')
>+                              f.wss.val = 0;
>+                      else
>+                              f.wss.val = strtoul(&pbeg[1], NULL, 10);
>+              } else if (pbeg[0] == 'T') {
>+                      f.wss.wc = OSF_WSS_MTU;
>+                      if (pbeg[1] == '%')
>+                              f.wss.val = strtoul(&pbeg[2], NULL, 10);
>+                      else if (pbeg[1] == '*')
>+                              f.wss.val = 0;
>+                      else
>+                              f.wss.val = strtoul(&pbeg[1], NULL, 10);
>+              } else if (pbeg[0] == '%') {
>+                      f.wss.wc = OSF_WSS_MODULO;
>+                      f.wss.val = strtoul(&pbeg[1], NULL, 10);
>+              } else if (isdigit(pbeg[0])) {
>+                      f.wss.wc = OSF_WSS_PLAIN;
>+                      f.wss.val = strtoul(&pbeg[0], NULL, 10);
>+              }
>+
>+              pbeg = pend + 1;
>+      }
>+      pend = nf_osf_strchr(pbeg, OSFPDEL);
>+      if (pend) {
>+              *pend = '\0';
>+              f.ttl = strtoul(pbeg, NULL, 10);
>+              pbeg = pend + 1;
>+      }
>+      pend = nf_osf_strchr(pbeg, OSFPDEL);
>+      if (pend) {
>+              *pend = '\0';
>+              f.df = strtoul(pbeg, NULL, 10);
>+              pbeg = pend + 1;
>+      }
>+      pend = nf_osf_strchr(pbeg, OSFPDEL);
>+      if (pend) {
>+              *pend = '\0';
>+              f.ss = strtoul(pbeg, NULL, 10);
>+              pbeg = pend + 1;
>+      }
>+
>+      pend = nf_osf_strchr(pbeg, OSFPDEL);
>+      if (pend) {
>+              *pend = '\0';
>+              cnt = snprintf(obuf, sizeof(obuf), "%s,", pbeg);
>+              pbeg = pend + 1;
>+      }
>+
>+      pend = nf_osf_strchr(pbeg, OSFPDEL);
>+      if (pend) {
>+              *pend = '\0';
>+              if (pbeg[0] == '@' || pbeg[0] == '*')
>+                      cnt = snprintf(f.genre, sizeof(f.genre), "%s", pbeg + 
>1);
>+              else
>+                      cnt = snprintf(f.genre, sizeof(f.genre), "%s", pbeg);
>+              pbeg = pend + 1;
>+      }
>+
>+      pend = nf_osf_strchr(pbeg, OSFPDEL);
>+      if (pend) {
>+              *pend = '\0';
>+              cnt = snprintf(f.version, sizeof(f.version), "%s", pbeg);
>+              pbeg = pend + 1;
>+      }
>+
>+      pend = nf_osf_strchr(pbeg, OSFPDEL);
>+      if (pend) {
>+              *pend = '\0';
>+              cnt =
>+                  snprintf(f.subtype, sizeof(f.subtype), "%s", pbeg);
>+              pbeg = pend + 1;
>+      }
>+
>+      nf_osf_parse_opt(f.opt, &f.opt_num, obuf, sizeof(obuf));
>+
>+      memset(buf, 0, sizeof(buf));
>+
>+      if (del) {
>+              nlh = nftnl_nlmsg_build_hdr(buf, (NFNL_SUBSYS_OSF << 8) |
>+                                          OSF_MSG_REMOVE, AF_UNSPEC,
>+                                          NLM_F_REQUEST | NLM_F_ACK,
>+                                          ctx->seqnum);
>+
>+              nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
>+              nfg->nfgen_family = AF_UNSPEC;
>+              nfg->version = NFNETLINK_V0;
>+              nfg->res_id = 0;
>+      } else {
>+              nlh = nftnl_nlmsg_build_hdr(buf, (NFNL_SUBSYS_OSF << 8) |
>+                                          OSF_MSG_ADD, AF_UNSPEC,
>+                                          NLM_F_REQUEST | NLM_F_CREATE |
>+                                          NLM_F_ACK, ctx->seqnum);
>+
>+              nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
>+              nfg->nfgen_family = AF_UNSPEC;
>+              nfg->version = NFNETLINK_V0;
>+              nfg->res_id = 0;
>+
>+              mnl_attr_put(nlh, OSF_ATTR_FINGER, sizeof(struct
>nf_osf_user_finger), &f);
>+      }
>+
>+      return nft_mnl_talk(ctx, nlh, nlh->nlmsg_len, 0, NULL);
>+}
>+
>+static int osf_load_entries(const char *path, int del, struct
>mnl_socket *nl,
>+                          struct netlink_ctx *ctx)
>+{
>+      FILE *inf;
>+      int err = 0;
>+      char buf[1024];
>+
>+      inf = fopen(path, "r");
>+      if (!inf) {
>+              ulog_err("Failed to open file '%s'", ctx, path);
>+              return -1;
>+      }
>+
>+      while(fgets(buf, sizeof(buf), inf)) {
>+              int len;
>+
>+              if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r')
>+                      continue;
>+
>+              len = strlen(buf) - 1;
>+
>+              if (len <= 0)
>+                      continue;
>+
>+              buf[len] = '\0';
>+
>+              err = osf_load_line(buf, len, del, nl, ctx);
>+              if (err)
>+                      break;
>+
>+              memset(buf, 0, sizeof(buf));
>+      }
>+
>+      fclose(inf);
>+      return err;
>+}
>+
>+int nfnl_osf_load_fingerprints(struct netlink_ctx *ctx, int del)
>+{
>+      int err;
>+      struct mnl_socket *nl;
>+      const char *fingerprints = "files/osf/pf.os";
>+
>+      if (!fingerprints) {
>+              err = -ENOENT;
>+              goto err_out_exit;
>+      }
>+
>+      nl = mnl_socket_open(NETLINK_NETFILTER);
>+      if (nl == NULL) {
>+              err = -EINVAL;
>+              ulog_err("Failed to open mnl socket", ctx);
>+              goto err_out_exit;
>+      }
>+
>+      if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
>+              err = -EINVAL;
>+              ulog_err("Failed to bind mnl socket", ctx);
>+              goto err_out_exit;
>+      }
>+
>+#ifndef NFNL_SUBSYS_OSF
>+#define NFNL_SUBSYS_OSF       5
>+#endif
>+
>+      err = osf_load_entries(fingerprints, del, nl, ctx);
>+      if (err < 0)
>+              goto err_out_close;
>+
>+      return 0;
>+
>+err_out_close:
>+      mnl_socket_close(nl);
>+err_out_exit:
>+      return err;
>+}
>diff --git a/src/osf.c b/src/osf.c
>index 131d54e..210bfbe 100644
>--- a/src/osf.c
>+++ b/src/osf.c
>@@ -3,6 +3,7 @@
> #include <utils.h>
> #include <string.h>
> #include <osf.h>
>+#include <nfnl_osf.h>
> 
>static void osf_expr_print(const struct expr *expr, struct output_ctx
>*octx)
> {
>@@ -26,6 +27,7 @@ struct expr *osf_expr_alloc(const struct location
>*loc)
>       const struct datatype *type = &string_type;
>       struct expr *expr;
> 
>+      osf_init = true;
>       expr = expr_alloc(loc, &osf_expr_ops, type,
>                         BYTEORDER_HOST_ENDIAN, len);
> 
>diff --git a/src/rule.c b/src/rule.c
>index 7a7ac73..dc1ce8b 100644
>--- a/src/rule.c
>+++ b/src/rule.c
>@@ -22,6 +22,8 @@
> #include <netdb.h>
> #include <netlink.h>
> #include <json.h>
>+#include <nfnl_osf.h>
>+#include <osf.h>
> 
> #include <libnftnl/common.h>
> #include <libnftnl/ruleset.h>
>@@ -2135,6 +2137,9 @@ int do_command(struct netlink_ctx *ctx, struct
>cmd *cmd)
>       default:
>               BUG("invalid command object type %u\n", cmd->obj);
>       }
>+
>+      if (osf_init)
>+              nfnl_osf_load_fingerprints(ctx, 0);
> }
> 
> static int payload_match_stmt_cmp(const void *p1, const void *p2)

Reply via email to