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
27static 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
49int 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}