libnetfilter_log  1.0.1
nf-log.c
1 /* This example is placed in the public domain. */
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <arpa/inet.h>
5 
6 #include <libnetfilter_log/linux_nfnetlink_log.h>
7 
8 #include <libmnl/libmnl.h>
9 #include <libnetfilter_log/libnetfilter_log.h>
10 
11 #ifdef BUILD_NFCT
12 #include <linux/netfilter/nf_conntrack_common.h>
13 #include <linux/netfilter/nf_conntrack_tuple_common.h>
14 #include <libnetfilter_conntrack/libnetfilter_conntrack.h>
15 #endif
16 
17 #ifdef BUILD_NFCT
18 static int print_ctinfo(const struct nlattr *const attr)
19 {
20  uint32_t ctinfo;
21 
22  if (attr == NULL)
23  return MNL_CB_OK;
24 
25  ctinfo = ntohl(mnl_attr_get_u32(attr));
26  printf(" ip_conntrack_info:");
27 
28  switch (CTINFO2DIR(ctinfo)) {
29  case IP_CT_DIR_ORIGINAL:
30  printf(" ORIGINAL /");
31  break;
32  case IP_CT_DIR_REPLY:
33  printf(" REPLY /");
34  break;
35  default:
36  printf(" unknown dir: %d\n", CTINFO2DIR(ctinfo));
37  return MNL_CB_ERROR;
38  }
39 
40  switch (ctinfo) {
41  case IP_CT_ESTABLISHED:
42  case IP_CT_ESTABLISHED_REPLY:
43  printf(" ESTABLISHED\n");
44  break;
45  case IP_CT_RELATED:
46  case IP_CT_RELATED_REPLY:
47  printf(" RELATED\n");
48  break;
49  case IP_CT_NEW:
50  case IP_CT_NEW_REPLY:
51  printf(" NEW\n");
52  break;
53  default:
54  printf(" unknown ctinfo: %d\n", ctinfo);
55  return MNL_CB_ERROR;
56  }
57 
58  return MNL_CB_OK;
59 }
60 
61 static int print_nfct(uint8_t family,
62  const struct nlattr *const info_attr,
63  const struct nlattr *const ct_attr)
64 {
65  char buf[4096];
66  struct nf_conntrack *ct = NULL;
67 
68  if (info_attr != NULL)
69  print_ctinfo(info_attr);
70 
71  if (ct_attr == NULL)
72  return MNL_CB_OK;
73 
74  ct = nfct_new();
75  if (ct == NULL) {
76  perror("nfct_new");
77  return MNL_CB_ERROR;
78  }
79 
80  if (nfct_payload_parse(mnl_attr_get_payload(ct_attr),
81  mnl_attr_get_payload_len(ct_attr),
82  family, ct) < 0) {
83  perror("nfct_payload_parse");
84  nfct_destroy(ct);
85  return MNL_CB_ERROR;
86  }
87 
88  nfct_snprintf(buf, sizeof(buf), ct, 0, NFCT_O_DEFAULT, 0);
89  printf(" %s\n", buf);
90  nfct_destroy(ct);
91 
92  return MNL_CB_OK;
93 }
94 #else
95 static int print_nfct(uint8_t family,
96  const struct nlattr *const info_attr,
97  const struct nlattr *const ct_attr)
98 {
99  return MNL_CB_OK;
100 }
101 #endif
102 
103 static int log_cb(const struct nlmsghdr *nlh, void *data)
104 {
105  struct nlattr *attrs[NFULA_MAX + 1] = { NULL };
106  struct nfulnl_msg_packet_hdr *ph = NULL;
107  struct nfgenmsg *nfg;
108  const char *prefix = NULL;
109  uint32_t mark = 0;
110  char buf[4096];
111  int ret;
112 
113  ret = nflog_nlmsg_parse(nlh, attrs);
114  if (ret != MNL_CB_OK)
115  return ret;
116 
117  nfg = mnl_nlmsg_get_payload(nlh);
118 
119  if (attrs[NFULA_PACKET_HDR])
120  ph = mnl_attr_get_payload(attrs[NFULA_PACKET_HDR]);
121  if (attrs[NFULA_PREFIX])
122  prefix = mnl_attr_get_str(attrs[NFULA_PREFIX]);
123  if (attrs[NFULA_MARK])
124  mark = ntohl(mnl_attr_get_u32(attrs[NFULA_MARK]));
125 
126  printf("log received (prefix=\"%s\" hw=0x%04x hook=%u mark=%u)\n",
127  prefix ? prefix : "", ntohs(ph->hw_protocol), ph->hook,
128  mark);
129 
130  ret = nflog_nlmsg_snprintf(buf, sizeof(buf), nlh, attrs,
131  NFLOG_OUTPUT_XML, NFLOG_XML_ALL);
132  if (ret < 0)
133  return MNL_CB_ERROR;
134  printf("%s (ret=%d)\n", buf, ret);
135 
136  print_nfct(nfg->nfgen_family, attrs[NFULA_CT_INFO], attrs[NFULA_CT]);
137 
138  return MNL_CB_OK;
139 }
140 
141 int main(int argc, char *argv[])
142 {
143  struct mnl_socket *nl;
144  char buf[MNL_SOCKET_BUFFER_SIZE];
145  struct nlmsghdr *nlh;
146  int ret;
147  unsigned int portid, qnum;
148 
149  if (argc != 2) {
150  printf("Usage: %s [queue_num]\n", argv[0]);
151  exit(EXIT_FAILURE);
152  }
153  qnum = atoi(argv[1]);
154 
155  nl = mnl_socket_open(NETLINK_NETFILTER);
156  if (nl == NULL) {
157  perror("mnl_socket_open");
158  exit(EXIT_FAILURE);
159  }
160 
161  if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
162  perror("mnl_socket_bind");
163  exit(EXIT_FAILURE);
164  }
165  portid = mnl_socket_get_portid(nl);
166 
167  /* kernels 3.8 and later is required to omit PF_(UN)BIND */
168 
169  nlh = nflog_nlmsg_put_header(buf, NFULNL_MSG_CONFIG, AF_INET, 0);
170  if (nflog_attr_put_cfg_cmd(nlh, NFULNL_CFG_CMD_PF_UNBIND) < 0) {
171  perror("nflog_attr_put_cfg_cmd");
172  exit(EXIT_FAILURE);
173  }
174 
175  if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
176  perror("mnl_socket_sendto");
177  exit(EXIT_FAILURE);
178  }
179 
180  nlh = nflog_nlmsg_put_header(buf, NFULNL_MSG_CONFIG, AF_INET, 0);
181  if (nflog_attr_put_cfg_cmd(nlh, NFULNL_CFG_CMD_PF_BIND) < 0) {
182  perror("nflog_attr_put_cfg_cmd");
183  exit(EXIT_FAILURE);
184  }
185 
186  if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
187  perror("mnl_socket_sendto");
188  exit(EXIT_FAILURE);
189  }
190 
191  nlh = nflog_nlmsg_put_header(buf, NFULNL_MSG_CONFIG, AF_INET, qnum);
192  if (nflog_attr_put_cfg_cmd(nlh, NFULNL_CFG_CMD_BIND) < 0) {
193  perror("nflog_attr_put_cfg_cmd");
194  exit(EXIT_FAILURE);
195  }
196 
197  if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
198  perror("mnl_socket_sendto");
199  exit(EXIT_FAILURE);
200  }
201 
202  nlh = nflog_nlmsg_put_header(buf, NFULNL_MSG_CONFIG, AF_UNSPEC, qnum);
203  if (nflog_attr_put_cfg_mode(nlh, NFULNL_COPY_PACKET, 0xffff) < 0) {
204  perror("nflog_attr_put_cfg_mode");
205  exit(EXIT_FAILURE);
206  }
207 
208 #ifdef BUILD_NFCT
209  mnl_attr_put_u16(nlh, NFULA_CFG_FLAGS, htons(NFULNL_CFG_F_CONNTRACK));
210 #endif
211 
212  if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
213  perror("mnl_socket_sendto");
214  exit(EXIT_FAILURE);
215  }
216 
217  ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
218  if (ret == -1) {
219  perror("mnl_socket_recvfrom");
220  exit(EXIT_FAILURE);
221  }
222  while (ret > 0) {
223  ret = mnl_cb_run(buf, ret, 0, portid, log_cb, NULL);
224  if (ret < 0){
225  perror("mnl_cb_run");
226  exit(EXIT_FAILURE);
227  }
228 
229  ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
230  if (ret == -1) {
231  perror("mnl_socket_recvfrom");
232  exit(EXIT_FAILURE);
233  }
234  }
235 
236  mnl_socket_close(nl);
237 
238  return 0;
239 }
int nflog_nlmsg_snprintf(char *buf, size_t bufsiz, const struct nlmsghdr *nlh, struct nlattr **attr, enum nflog_output_type type, uint32_t flags)
Definition: nlmsg.c:191
int nflog_attr_put_cfg_cmd(struct nlmsghdr *nlh, uint8_t cmd)
Definition: nlmsg.c:78
int nflog_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr **attr)
Definition: nlmsg.c:157
struct nlmsghdr * nflog_nlmsg_put_header(char *buf, uint8_t type, uint8_t family, uint16_t qnum)
Definition: nlmsg.c:32
int nflog_attr_put_cfg_mode(struct nlmsghdr *nlh, uint8_t mode, uint32_t range)
Definition: nlmsg.c:57