libnftnl 1.2.3
nft-flowtable-add.c
1#include <stdlib.h>
2#include <time.h>
3#include <string.h>
4#include <netinet/in.h>
5
6#include <linux/netfilter.h>
7#include <linux/netfilter/nf_tables.h>
8
9#include <libmnl/libmnl.h>
10#include <libnftnl/flowtable.h>
11
12static struct nftnl_flowtable *flowtable_add_parse(int argc, char *argv[])
13{
14 const char *dev_array[] = { "eth0", "tap0", NULL };
15 struct nftnl_flowtable *t;
16 int hooknum = 0;
17
18 if (strcmp(argv[4], "ingress") == 0)
19 hooknum = NF_NETDEV_INGRESS;
20 else {
21 fprintf(stderr, "Unknown hook: %s\n", argv[4]);
22 return NULL;
23 }
24
25 t = nftnl_flowtable_alloc();
26 if (t == NULL) {
27 perror("OOM");
28 return NULL;
29 }
30 nftnl_flowtable_set_str(t, NFTNL_FLOWTABLE_TABLE, argv[2]);
31 nftnl_flowtable_set_str(t, NFTNL_FLOWTABLE_NAME, argv[3]);
32 if (argc == 6) {
33 nftnl_flowtable_set_u32(t, NFTNL_FLOWTABLE_HOOKNUM, hooknum);
34 nftnl_flowtable_set_u32(t, NFTNL_FLOWTABLE_PRIO, atoi(argv[5]));
35 }
36 nftnl_flowtable_set_data(t, NFTNL_FLOWTABLE_DEVICES, dev_array, 0);
37
38 return t;
39}
40
41int main(int argc, char *argv[])
42{
43 struct mnl_socket *nl;
44 char buf[MNL_SOCKET_BUFFER_SIZE];
45 struct nlmsghdr *nlh;
46 uint32_t portid, seq, flowtable_seq;
47 int ret, family;
48 struct nftnl_flowtable *t;
49 struct mnl_nlmsg_batch *batch;
50 int batching;
51
52 if (argc != 6) {
53 fprintf(stderr, "Usage: %s <family> <table> <name> <hook> <prio>\n",
54 argv[0]);
55 exit(EXIT_FAILURE);
56 }
57
58 if (strcmp(argv[1], "ip") == 0)
59 family = NFPROTO_IPV4;
60 else if (strcmp(argv[1], "ip6") == 0)
61 family = NFPROTO_IPV6;
62 else if (strcmp(argv[1], "inet") == 0)
63 family = NFPROTO_INET;
64 else if (strcmp(argv[1], "bridge") == 0)
65 family = NFPROTO_BRIDGE;
66 else if (strcmp(argv[1], "arp") == 0)
67 family = NFPROTO_ARP;
68 else {
69 fprintf(stderr, "Unknown family: ip, ip6, inet, bridge, arp\n");
70 exit(EXIT_FAILURE);
71 }
72
73 t = flowtable_add_parse(argc, argv);
74 if (t == NULL)
75 exit(EXIT_FAILURE);
76
77 batching = nftnl_batch_is_supported();
78 if (batching < 0) {
79 perror("cannot talk to nfnetlink");
80 exit(EXIT_FAILURE);
81 }
82
83 seq = time(NULL);
84 batch = mnl_nlmsg_batch_start(buf, sizeof(buf));
85
86 if (batching) {
87 nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++);
88 mnl_nlmsg_batch_next(batch);
89 }
90
91 flowtable_seq = seq;
92 nlh = nftnl_flowtable_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
93 NFT_MSG_NEWFLOWTABLE, family,
94 NLM_F_CREATE|NLM_F_ACK, seq++);
95 nftnl_flowtable_nlmsg_build_payload(nlh, t);
96 nftnl_flowtable_free(t);
97 mnl_nlmsg_batch_next(batch);
98
99 if (batching) {
100 nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++);
101 mnl_nlmsg_batch_next(batch);
102 }
103
104 nl = mnl_socket_open(NETLINK_NETFILTER);
105 if (nl == NULL) {
106 perror("mnl_socket_open");
107 exit(EXIT_FAILURE);
108 }
109
110 if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
111 perror("mnl_socket_bind");
112 exit(EXIT_FAILURE);
113 }
114 portid = mnl_socket_get_portid(nl);
115
116 if (mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch),
117 mnl_nlmsg_batch_size(batch)) < 0) {
118 perror("mnl_socket_send");
119 exit(EXIT_FAILURE);
120 }
121
122 mnl_nlmsg_batch_stop(batch);
123
124 ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
125 while (ret > 0) {
126 ret = mnl_cb_run(buf, ret, flowtable_seq, portid, NULL, NULL);
127 if (ret <= 0)
128 break;
129 ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
130 }
131 if (ret == -1) {
132 perror("error");
133 exit(EXIT_FAILURE);
134 }
135 mnl_socket_close(nl);
136
137 return EXIT_SUCCESS;
138}