libnftnl  1.2.9
nft-ct-timeout-add.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * (C) 2012-2016 by Pablo Neira Ayuso <pablo@netfilter.org>
4  */
5 
6 #include <stdlib.h>
7 #include <time.h>
8 #include <string.h>
9 #include <netinet/in.h>
10 
11 #include <linux/netfilter.h>
12 #include <linux/netfilter/nf_tables.h>
13 
14 #include <obj.h>
15 #include <libmnl/libmnl.h>
16 #include <libnftnl/object.h>
17 
18 static struct nftnl_obj *obj_add_parse(int argc, char *argv[])
19 {
20  size_t timeout_array_size;
21  struct nftnl_obj *t;
22  uint32_t *timeout;
23  uint16_t family;
24  uint8_t l4proto;
25 
26  if (strcmp(argv[1], "ip") == 0)
27  family = NFPROTO_IPV4;
28  else if (strcmp(argv[1], "ip6") == 0)
29  family = NFPROTO_IPV6;
30  else if (strcmp(argv[1], "inet") == 0)
31  family = NFPROTO_INET;
32  else if (strcmp(argv[1], "bridge") == 0)
33  family = NFPROTO_BRIDGE;
34  else if (strcmp(argv[1], "arp") == 0)
35  family = NFPROTO_ARP;
36  else {
37  fprintf(stderr, "Unknown family: ip, ip6, inet, bridge, arp\n");
38  return NULL;
39  }
40 
41  if (strcmp(argv[4], "udp") == 0)
42  l4proto = IPPROTO_UDP;
43  else if (strcmp(argv[4], "tcp") == 0)
44  l4proto = IPPROTO_TCP;
45  else {
46  fprintf(stderr, "Unknown layer 4 protocol\n");
47  return NULL;
48  }
49 
50  t = nftnl_obj_alloc();
51  if (t == NULL) {
52  perror("OOM");
53  return NULL;
54  }
55 
56  timeout_array_size = sizeof(uint32_t) * (NFTNL_CTTIMEOUT_TCP_MAX);
57  timeout = calloc(1, timeout_array_size);
58  if (timeout == NULL) {
59  perror("OOM");
60  return NULL;
61  }
62 
63  timeout[NFTNL_CTTIMEOUT_TCP_ESTABLISHED] = 111;
64  timeout[NFTNL_CTTIMEOUT_TCP_CLOSE] = 16;
65  timeout[NFTNL_CTTIMEOUT_TCP_CLOSE_WAIT] = 14;
66  nftnl_obj_set_u32(t, NFTNL_OBJ_FAMILY, family);
67  nftnl_obj_set_u32(t, NFTNL_OBJ_TYPE, NFT_OBJECT_CT_TIMEOUT);
68  nftnl_obj_set_str(t, NFTNL_OBJ_TABLE, argv[2]);
69  nftnl_obj_set_str(t, NFTNL_OBJ_NAME, argv[3]);
70  nftnl_obj_set_u8(t, NFTNL_OBJ_CT_TIMEOUT_L4PROTO, l4proto);
71  nftnl_obj_set_u16(t, NFTNL_OBJ_CT_TIMEOUT_L3PROTO, NFPROTO_IPV4);
72  nftnl_obj_set_data(t, NFTNL_OBJ_CT_TIMEOUT_ARRAY,
73  timeout, timeout_array_size);
74  return t;
75 
76 }
77 
78 int main(int argc, char *argv[])
79 {
80  struct mnl_socket *nl;
81  char buf[MNL_SOCKET_BUFFER_SIZE];
82  struct nlmsghdr *nlh;
83  uint32_t portid, seq, obj_seq, family;
84  struct nftnl_obj *t;
85  struct mnl_nlmsg_batch *batch;
86  int ret;
87 
88  if (argc != 5) {
89  fprintf(stderr, "%s <family> <table> <name> <protocol> \n", argv[0]);
90  exit(EXIT_FAILURE);
91  }
92 
93  t = obj_add_parse(argc, argv);
94  if (t == NULL) {
95  exit(EXIT_FAILURE);
96  }
97 
98  seq = time(NULL);
99  batch = mnl_nlmsg_batch_start(buf, sizeof(buf));
100 
101  nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++);
102  mnl_nlmsg_batch_next(batch);
103 
104  obj_seq = seq;
105  family = nftnl_obj_get_u32(t, NFTNL_OBJ_FAMILY);
106  nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
107  NFT_MSG_NEWOBJ, family, NLM_F_ACK | NLM_F_CREATE, seq++);
108  nftnl_obj_nlmsg_build_payload(nlh, t);
109  nftnl_obj_free(t);
110  mnl_nlmsg_batch_next(batch);
111 
112  nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++);
113  mnl_nlmsg_batch_next(batch);
114 
115  nl = mnl_socket_open(NETLINK_NETFILTER);
116  if (nl == NULL) {
117  perror("mnl_socket_open");
118  exit(EXIT_FAILURE);
119  }
120 
121  if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
122  perror("mnl_socket_bind");
123  exit(EXIT_FAILURE);
124  }
125  portid = mnl_socket_get_portid(nl);
126 
127  if (mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch),
128  mnl_nlmsg_batch_size(batch)) < 0) {
129  perror("mnl_socket_send");
130  exit(EXIT_FAILURE);
131  }
132 
133  mnl_nlmsg_batch_stop(batch);
134 
135  ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
136  while (ret > 0) {
137  ret = mnl_cb_run(buf, ret, obj_seq, portid, NULL, NULL);
138  if (ret <= 0)
139  break;
140  ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
141  }
142  if (ret == -1) {
143  perror("error");
144  exit(EXIT_FAILURE);
145  }
146  mnl_socket_close(nl);
147 
148  return EXIT_SUCCESS;
149 }