libnftnl  1.2.9
nft-set-add.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * (C) 2013 by Pablo Neira Ayuso <pablo@netfilter.org>
4  *
5  * This software has been sponsored by Sophos Astaro <http://www.sophos.com>
6  */
7 
8 #include <stdlib.h>
9 #include <time.h>
10 #include <string.h>
11 #include <stddef.h> /* for offsetof */
12 #include <netinet/in.h>
13 #include <netinet/ip.h>
14 #include <netinet/tcp.h>
15 #include <arpa/inet.h>
16 #include <sys/types.h>
17 #include <sys/socket.h>
18 #include <errno.h>
19 
20 #include <linux/netfilter.h>
21 #include <linux/netfilter/nfnetlink.h>
22 #include <linux/netfilter/nf_tables.h>
23 
24 #include <libmnl/libmnl.h>
25 #include <libnftnl/set.h>
26 
27 static struct nftnl_set *setup_set(uint8_t family, const char *table,
28  const char *name)
29 {
30  struct nftnl_set *s = NULL;
31 
32  s = nftnl_set_alloc();
33  if (s == NULL) {
34  perror("OOM");
35  exit(EXIT_FAILURE);
36  }
37 
38  nftnl_set_set_str(s, NFTNL_SET_TABLE, table);
39  nftnl_set_set_str(s, NFTNL_SET_NAME, name);
40  nftnl_set_set_u32(s, NFTNL_SET_FAMILY, family);
41  nftnl_set_set_u32(s, NFTNL_SET_KEY_LEN, sizeof(uint16_t));
42  /* inet service type, see nftables/include/datatypes.h */
43  nftnl_set_set_u32(s, NFTNL_SET_KEY_TYPE, 13);
44  nftnl_set_set_u32(s, NFTNL_SET_ID, 1);
45 
46  return s;
47 }
48 
49 int main(int argc, char *argv[])
50 {
51  struct mnl_socket *nl;
52  struct nftnl_set *s;
53  struct nlmsghdr *nlh;
54  struct mnl_nlmsg_batch *batch;
55  uint8_t family;
56  char buf[MNL_SOCKET_BUFFER_SIZE];
57  uint32_t seq = time(NULL);
58  int ret;
59 
60  if (argc != 4) {
61  fprintf(stderr, "Usage: %s <family> <table> <setname>\n", argv[0]);
62  exit(EXIT_FAILURE);
63  }
64 
65  if (strcmp(argv[1], "ip") == 0)
66  family = NFPROTO_IPV4;
67  else if (strcmp(argv[1], "ip6") == 0)
68  family = NFPROTO_IPV6;
69  else if (strcmp(argv[1], "inet") == 0)
70  family = NFPROTO_INET;
71  else if (strcmp(argv[1], "bridge") == 0)
72  family = NFPROTO_BRIDGE;
73  else if (strcmp(argv[1], "arp") == 0)
74  family = NFPROTO_ARP;
75  else {
76  fprintf(stderr, "Unknown family: ip, ip6, inet, bridge, arp\n");
77  exit(EXIT_FAILURE);
78  }
79 
80  s = setup_set(family, argv[2], argv[3]);
81 
82  nl = mnl_socket_open(NETLINK_NETFILTER);
83  if (nl == NULL) {
84  perror("mnl_socket_open");
85  exit(EXIT_FAILURE);
86  }
87 
88  if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
89  perror("mnl_socket_bind");
90  exit(EXIT_FAILURE);
91  }
92 
93  batch = mnl_nlmsg_batch_start(buf, sizeof(buf));
94 
95  nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++);
96  mnl_nlmsg_batch_next(batch);
97 
98  nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
99  NFT_MSG_NEWSET, family,
100  NLM_F_CREATE | NLM_F_ACK, seq++);
101 
102  nftnl_set_nlmsg_build_payload(nlh, s);
103  nftnl_set_free(s);
104  mnl_nlmsg_batch_next(batch);
105 
106  nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++);
107  mnl_nlmsg_batch_next(batch);
108 
109  ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch),
110  mnl_nlmsg_batch_size(batch));
111  if (ret == -1) {
112  perror("mnl_socket_sendto");
113  exit(EXIT_FAILURE);
114  }
115 
116  mnl_nlmsg_batch_stop(batch);
117 
118  ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
119  if (ret == -1) {
120  perror("mnl_socket_recvfrom");
121  exit(EXIT_FAILURE);
122  }
123 
124  ret = mnl_cb_run(buf, ret, 0, mnl_socket_get_portid(nl), NULL, NULL);
125  if (ret < 0) {
126  perror("mnl_cb_run");
127  exit(EXIT_FAILURE);
128  }
129 
130  mnl_socket_close(nl);
131 
132  return EXIT_SUCCESS;
133 }