libnftnl  1.0.2
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 
23 int main(int argc, char *argv[])
24 {
25  struct mnl_socket *nl;
26  char buf[MNL_SOCKET_BUFFER_SIZE];
27  struct nlmsghdr *nlh;
28  uint32_t portid, seq;
29  struct nft_chain *t = NULL;
30  int ret, family, hooknum = 0;
31 
32  if (argc != 4 && argc != 6) {
33  fprintf(stderr, "Usage: %s <family> <table> <chain> "
34  "[<hooknum> <prio>]\n",
35  argv[0]);
36  exit(EXIT_FAILURE);
37  }
38 
39  if (strcmp(argv[1], "ip") == 0)
40  family = NFPROTO_IPV4;
41  else if (strcmp(argv[1], "ip6") == 0)
42  family = NFPROTO_IPV6;
43  else if (strcmp(argv[1], "bridge") == 0)
44  family = NFPROTO_BRIDGE;
45  else if (strcmp(argv[1], "arp") == 0)
46  family = NFPROTO_ARP;
47  else {
48  fprintf(stderr, "Unknown family: ip, ip6, bridge, arp\n");
49  exit(EXIT_FAILURE);
50  }
51 
52  if (argc == 6) {
53  /* This is a base chain, set the hook number */
54  if (strcmp(argv[4], "NF_INET_LOCAL_IN") == 0)
55  hooknum = NF_INET_LOCAL_IN;
56  else if (strcmp(argv[4], "NF_INET_LOCAL_OUT") == 0)
57  hooknum = NF_INET_LOCAL_OUT;
58  else if (strcmp(argv[4], "NF_INET_PRE_ROUTING") == 0)
59  hooknum = NF_INET_PRE_ROUTING;
60  else if (strcmp(argv[4], "NF_INET_POST_ROUTING") == 0)
61  hooknum = NF_INET_POST_ROUTING;
62  else if (strcmp(argv[4], "NF_INET_FORWARD") == 0)
63  hooknum = NF_INET_FORWARD;
64  else {
65  fprintf(stderr, "Unknown hook: %s\n", argv[4]);
66  exit(EXIT_FAILURE);
67  }
68  }
69 
70  t = nft_chain_alloc();
71  if (t == NULL) {
72  perror("OOM");
73  exit(EXIT_FAILURE);
74  }
75  seq = time(NULL);
76  nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, family,
77  NLM_F_EXCL|NLM_F_ACK, seq);
78  nft_chain_attr_set(t, NFT_CHAIN_ATTR_TABLE, argv[2]);
79  nft_chain_attr_set(t, NFT_CHAIN_ATTR_NAME, argv[3]);
80  if (argc == 6) {
81  nft_chain_attr_set_u32(t, NFT_CHAIN_ATTR_HOOKNUM, hooknum);
82  nft_chain_attr_set_u32(t, NFT_CHAIN_ATTR_PRIO, atoi(argv[5]));
83  }
84  nft_chain_nlmsg_build_payload(nlh, t);
85  nft_chain_free(t);
86 
87  nl = mnl_socket_open(NETLINK_NETFILTER);
88  if (nl == NULL) {
89  perror("mnl_socket_open");
90  exit(EXIT_FAILURE);
91  }
92 
93  if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
94  perror("mnl_socket_bind");
95  exit(EXIT_FAILURE);
96  }
97  portid = mnl_socket_get_portid(nl);
98 
99  if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
100  perror("mnl_socket_send");
101  exit(EXIT_FAILURE);
102  }
103 
104  ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
105  while (ret > 0) {
106  ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
107  if (ret <= 0)
108  break;
109  ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
110  }
111  if (ret == -1) {
112  perror("error");
113  exit(EXIT_FAILURE);
114  }
115  mnl_socket_close(nl);
116 
117  return EXIT_SUCCESS;
118 }