libnftnl 1.2.6
nft-chain-add.c
1/*
2 * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This software has been sponsored by Sophos Astaro <http://www.sophos.com>
10 */
11
12#include <stdlib.h>
13#include <time.h>
14#include <string.h>
15#include <netinet/in.h>
16
17#include <linux/netfilter.h>
18#include <linux/netfilter/nf_tables.h>
19
20#include <libmnl/libmnl.h>
21#include <libnftnl/chain.h>
22
23static struct nftnl_chain *chain_add_parse(int argc, char *argv[])
24{
25 struct nftnl_chain *t;
26 int hooknum = 0;
27
28 if (argc == 6) {
29 /* This is a base chain, set the hook number */
30 if (strcmp(argv[4], "NF_INET_LOCAL_IN") == 0)
31 hooknum = NF_INET_LOCAL_IN;
32 else if (strcmp(argv[4], "NF_INET_LOCAL_OUT") == 0)
33 hooknum = NF_INET_LOCAL_OUT;
34 else if (strcmp(argv[4], "NF_INET_PRE_ROUTING") == 0)
35 hooknum = NF_INET_PRE_ROUTING;
36 else if (strcmp(argv[4], "NF_INET_POST_ROUTING") == 0)
37 hooknum = NF_INET_POST_ROUTING;
38 else if (strcmp(argv[4], "NF_INET_FORWARD") == 0)
39 hooknum = NF_INET_FORWARD;
40 else {
41 fprintf(stderr, "Unknown hook: %s\n", argv[4]);
42 return NULL;
43 }
44 }
45
46 t = nftnl_chain_alloc();
47 if (t == NULL) {
48 perror("OOM");
49 return NULL;
50 }
51 nftnl_chain_set_str(t, NFTNL_CHAIN_TABLE, argv[2]);
52 nftnl_chain_set_str(t, NFTNL_CHAIN_NAME, argv[3]);
53 if (argc == 6) {
54 nftnl_chain_set_u32(t, NFTNL_CHAIN_HOOKNUM, hooknum);
55 nftnl_chain_set_u32(t, NFTNL_CHAIN_PRIO, atoi(argv[5]));
56 }
57
58 return t;
59}
60
61int main(int argc, char *argv[])
62{
63 struct mnl_socket *nl;
64 char buf[MNL_SOCKET_BUFFER_SIZE];
65 struct nlmsghdr *nlh;
66 uint32_t portid, seq, chain_seq;
67 int ret, family;
68 struct nftnl_chain *t;
69 struct mnl_nlmsg_batch *batch;
70
71 if (argc != 4 && argc != 6) {
72 fprintf(stderr, "Usage: %s <family> <table> <chain> "
73 "[<hooknum> <prio>]\n",
74 argv[0]);
75 exit(EXIT_FAILURE);
76 }
77
78 if (strcmp(argv[1], "ip") == 0)
79 family = NFPROTO_IPV4;
80 else if (strcmp(argv[1], "ip6") == 0)
81 family = NFPROTO_IPV6;
82 else if (strcmp(argv[1], "inet") == 0)
83 family = NFPROTO_INET;
84 else if (strcmp(argv[1], "bridge") == 0)
85 family = NFPROTO_BRIDGE;
86 else if (strcmp(argv[1], "arp") == 0)
87 family = NFPROTO_ARP;
88 else {
89 fprintf(stderr, "Unknown family: ip, ip6, inet, bridge, arp\n");
90 exit(EXIT_FAILURE);
91 }
92
93 t = chain_add_parse(argc, argv);
94 if (t == NULL)
95 exit(EXIT_FAILURE);
96
97 seq = time(NULL);
98 batch = mnl_nlmsg_batch_start(buf, sizeof(buf));
99
100 nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++);
101 mnl_nlmsg_batch_next(batch);
102
103 chain_seq = seq;
104 nlh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
105 NFT_MSG_NEWCHAIN, family,
106 NLM_F_CREATE | NLM_F_ACK, seq++);
107 nftnl_chain_nlmsg_build_payload(nlh, t);
108 nftnl_chain_free(t);
109 mnl_nlmsg_batch_next(batch);
110
111 nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++);
112 mnl_nlmsg_batch_next(batch);
113
114 nl = mnl_socket_open(NETLINK_NETFILTER);
115 if (nl == NULL) {
116 perror("mnl_socket_open");
117 exit(EXIT_FAILURE);
118 }
119
120 if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
121 perror("mnl_socket_bind");
122 exit(EXIT_FAILURE);
123 }
124 portid = mnl_socket_get_portid(nl);
125
126 if (mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch),
127 mnl_nlmsg_batch_size(batch)) < 0) {
128 perror("mnl_socket_send");
129 exit(EXIT_FAILURE);
130 }
131
132 mnl_nlmsg_batch_stop(batch);
133
134 ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
135 while (ret > 0) {
136 ret = mnl_cb_run(buf, ret, chain_seq, portid, NULL, NULL);
137 if (ret <= 0)
138 break;
139 ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
140 }
141 if (ret == -1) {
142 perror("error");
143 exit(EXIT_FAILURE);
144 }
145 mnl_socket_close(nl);
146
147 return EXIT_SUCCESS;
148}