libnftnl 1.2.9
nft-rule-ct-expectation-add.c
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * (C) 2019 by Stéphane Veyret <sveyret@gmail.com>
4 */
5
6#include <stdlib.h>
7#include <time.h>
8#include <string.h>
9#include <stddef.h> /* for offsetof */
10#include <netinet/in.h>
11#include <netinet/ip.h>
12#include <netinet/tcp.h>
13#include <arpa/inet.h>
14#include <sys/types.h>
15#include <sys/socket.h>
16#include <errno.h>
17
18#include <linux/netfilter.h>
19#include <linux/netfilter/nfnetlink.h>
20#include <linux/netfilter/nf_tables.h>
21
22#include <libmnl/libmnl.h>
23#include <libnftnl/rule.h>
24#include <libnftnl/expr.h>
25
26static uint16_t parse_family(char *str, const char *option)
27{
28 if (strcmp(str, "ip") == 0)
29 return NFPROTO_IPV4;
30 else if (strcmp(str, "ip6") == 0)
31 return NFPROTO_IPV6;
32 else if (strcmp(str, "inet") == 0)
33 return NFPROTO_INET;
34 else if (strcmp(str, "arp") == 0)
35 return NFPROTO_INET;
36 fprintf(stderr, "Unknown %s: ip, ip6, inet, arp\n", option);
37 exit(EXIT_FAILURE);
38}
39
40static void add_ct_expect(struct nftnl_rule *r, const char *obj_name)
41{
42 struct nftnl_expr *e;
43
44 e = nftnl_expr_alloc("objref");
45 if (e == NULL) {
46 perror("expr objref oom");
47 exit(EXIT_FAILURE);
48 }
49 nftnl_expr_set_str(e, NFTNL_EXPR_OBJREF_IMM_NAME, obj_name);
50 nftnl_expr_set_u32(e, NFTNL_EXPR_OBJREF_IMM_TYPE, NFT_OBJECT_CT_EXPECT);
51
52 nftnl_rule_add_expr(r, e);
53}
54
55static struct nftnl_rule *setup_rule(uint8_t family, const char *table,
56 const char *chain, const char *handle,
57 const char *obj_name)
58{
59 struct nftnl_rule *r = NULL;
60 uint64_t handle_num;
61
62 r = nftnl_rule_alloc();
63 if (r == NULL) {
64 perror("OOM");
65 exit(EXIT_FAILURE);
66 }
67
68 nftnl_rule_set_str(r, NFTNL_RULE_TABLE, table);
69 nftnl_rule_set_str(r, NFTNL_RULE_CHAIN, chain);
70 nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, family);
71
72 if (handle != NULL) {
73 handle_num = atoll(handle);
74 nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, handle_num);
75 }
76
77 add_ct_expect(r, obj_name);
78
79 return r;
80}
81
82int main(int argc, char *argv[])
83{
84 char buf[MNL_SOCKET_BUFFER_SIZE];
85 struct mnl_nlmsg_batch *batch;
86 uint32_t seq = time(NULL);
87 struct mnl_socket *nl;
88 struct nftnl_rule *r;
89 struct nlmsghdr *nlh;
90 uint8_t family;
91 int ret;
92
93 if (argc < 5 || argc > 6) {
94 fprintf(stderr,
95 "Usage: %s <family> <table> <chain> [<handle>] <name>\n",
96 argv[0]);
97 exit(EXIT_FAILURE);
98 }
99 family = parse_family(argv[1], "family");
100
101 if (argc < 6)
102 r = setup_rule(family, argv[2], argv[3], NULL, argv[4]);
103 else
104 r = setup_rule(family, argv[2], argv[3], argv[4], argv[5]);
105
106 nl = mnl_socket_open(NETLINK_NETFILTER);
107 if (nl == NULL) {
108 perror("mnl_socket_open");
109 exit(EXIT_FAILURE);
110 }
111
112 if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
113 perror("mnl_socket_bind");
114 exit(EXIT_FAILURE);
115 }
116
117 batch = mnl_nlmsg_batch_start(buf, sizeof(buf));
118
119 nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++);
120 mnl_nlmsg_batch_next(batch);
121
122 nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
123 NFT_MSG_NEWRULE,
124 nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY),
125 NLM_F_APPEND | NLM_F_CREATE | NLM_F_ACK,
126 seq++);
127 nftnl_rule_nlmsg_build_payload(nlh, r);
128 nftnl_rule_free(r);
129 mnl_nlmsg_batch_next(batch);
130
131 nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++);
132 mnl_nlmsg_batch_next(batch);
133
134 ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch),
135 mnl_nlmsg_batch_size(batch));
136 if (ret == -1) {
137 perror("mnl_socket_sendto");
138 exit(EXIT_FAILURE);
139 }
140
141 mnl_nlmsg_batch_stop(batch);
142
143 ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
144 if (ret == -1) {
145 perror("mnl_socket_recvfrom");
146 exit(EXIT_FAILURE);
147 }
148
149 ret = mnl_cb_run(buf, ret, 0, mnl_socket_get_portid(nl), NULL, NULL);
150 if (ret < 0) {
151 perror("mnl_cb_run");
152 exit(EXIT_FAILURE);
153 }
154
155 mnl_socket_close(nl);
156
157 return EXIT_SUCCESS;
158}