libnetfilter_queue  1.0.5
nfqnl_test.c
1 
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <netinet/in.h>
6 #include <linux/types.h>
7 #include <linux/netfilter.h> /* for NF_ACCEPT */
8 #include <errno.h>
9 
10 #include <libnetfilter_queue/libnetfilter_queue.h>
11 
12 /* returns packet id */
13 static uint32_t print_pkt (struct nfq_data *tb)
14 {
15  int id = 0;
16  struct nfqnl_msg_packet_hdr *ph;
17  struct nfqnl_msg_packet_hw *hwph;
18  uint32_t mark, ifi, uid, gid;
19  int ret;
20  unsigned char *data, *secdata;
21 
22  ph = nfq_get_msg_packet_hdr(tb);
23  if (ph) {
24  id = ntohl(ph->packet_id);
25  printf("hw_protocol=0x%04x hook=%u id=%u ",
26  ntohs(ph->hw_protocol), ph->hook, id);
27  }
28 
29  hwph = nfq_get_packet_hw(tb);
30  if (hwph) {
31  int i, hlen = ntohs(hwph->hw_addrlen);
32 
33  printf("hw_src_addr=");
34  for (i = 0; i < hlen-1; i++)
35  printf("%02x:", hwph->hw_addr[i]);
36  printf("%02x ", hwph->hw_addr[hlen-1]);
37  }
38 
39  mark = nfq_get_nfmark(tb);
40  if (mark)
41  printf("mark=%u ", mark);
42 
43  ifi = nfq_get_indev(tb);
44  if (ifi)
45  printf("indev=%u ", ifi);
46 
47  ifi = nfq_get_outdev(tb);
48  if (ifi)
49  printf("outdev=%u ", ifi);
50  ifi = nfq_get_physindev(tb);
51  if (ifi)
52  printf("physindev=%u ", ifi);
53 
54  ifi = nfq_get_physoutdev(tb);
55  if (ifi)
56  printf("physoutdev=%u ", ifi);
57 
58  if (nfq_get_uid(tb, &uid))
59  printf("uid=%u ", uid);
60 
61  if (nfq_get_gid(tb, &gid))
62  printf("gid=%u ", gid);
63 
64  ret = nfq_get_secctx(tb, &secdata);
65  if (ret > 0)
66  printf("secctx=\"%.*s\" ", ret, secdata);
67 
68  ret = nfq_get_payload(tb, &data);
69  if (ret >= 0)
70  printf("payload_len=%d ", ret);
71 
72  fputc('\n', stdout);
73 
74  return id;
75 }
76 
77 
78 static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
79  struct nfq_data *nfa, void *data)
80 {
81  uint32_t id = print_pkt(nfa);
82  printf("entering callback\n");
83  return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
84 }
85 
86 int main(int argc, char **argv)
87 {
88  struct nfq_handle *h;
89  struct nfq_q_handle *qh;
90  int fd;
91  int rv;
92  uint32_t queue = 0;
93  char buf[4096] __attribute__ ((aligned));
94 
95  if (argc == 2) {
96  queue = atoi(argv[1]);
97  if (queue > 65535) {
98  fprintf(stderr, "Usage: %s [<0-65535>]\n", argv[0]);
99  exit(EXIT_FAILURE);
100  }
101  }
102 
103  printf("opening library handle\n");
104  h = nfq_open();
105  if (!h) {
106  fprintf(stderr, "error during nfq_open()\n");
107  exit(1);
108  }
109 
110  printf("unbinding existing nf_queue handler for AF_INET (if any)\n");
111  if (nfq_unbind_pf(h, AF_INET) < 0) {
112  fprintf(stderr, "error during nfq_unbind_pf()\n");
113  exit(1);
114  }
115 
116  printf("binding nfnetlink_queue as nf_queue handler for AF_INET\n");
117  if (nfq_bind_pf(h, AF_INET) < 0) {
118  fprintf(stderr, "error during nfq_bind_pf()\n");
119  exit(1);
120  }
121 
122  printf("binding this socket to queue '%d'\n", queue);
123  qh = nfq_create_queue(h, queue, &cb, NULL);
124  if (!qh) {
125  fprintf(stderr, "error during nfq_create_queue()\n");
126  exit(1);
127  }
128 
129  printf("setting copy_packet mode\n");
130  if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) {
131  fprintf(stderr, "can't set packet_copy mode\n");
132  exit(1);
133  }
134 
135  printf("setting flags to request UID and GID\n");
136  if (nfq_set_queue_flags(qh, NFQA_CFG_F_UID_GID, NFQA_CFG_F_UID_GID)) {
137  fprintf(stderr, "This kernel version does not allow to "
138  "retrieve process UID/GID.\n");
139  }
140 
141  printf("setting flags to request security context\n");
142  if (nfq_set_queue_flags(qh, NFQA_CFG_F_SECCTX, NFQA_CFG_F_SECCTX)) {
143  fprintf(stderr, "This kernel version does not allow to "
144  "retrieve security context.\n");
145  }
146 
147  printf("Waiting for packets...\n");
148 
149  fd = nfq_fd(h);
150 
151  for (;;) {
152  if ((rv = recv(fd, buf, sizeof(buf), 0)) >= 0) {
153  printf("pkt received\n");
154  nfq_handle_packet(h, buf, rv);
155  continue;
156  }
157  /* if your application is too slow to digest the packets that
158  * are sent from kernel-space, the socket buffer that we use
159  * to enqueue packets may fill up returning ENOBUFS. Depending
160  * on your application, this error may be ignored. Please, see
161  * the doxygen documentation of this library on how to improve
162  * this situation.
163  */
164  if (rv < 0 && errno == ENOBUFS) {
165  printf("losing packets!\n");
166  continue;
167  }
168  perror("recv failed");
169  break;
170  }
171 
172  printf("unbinding from queue 0\n");
173  nfq_destroy_queue(qh);
174 
175 #ifdef INSANE
176  /* normally, applications SHOULD NOT issue this command, since
177  * it detaches other programs/sockets from AF_INET, too ! */
178  printf("unbinding from AF_INET\n");
179  nfq_unbind_pf(h, AF_INET);
180 #endif
181 
182  printf("closing library handle\n");
183  nfq_close(h);
184 
185  exit(0);
186 }
struct nfqnl_msg_packet_hw * nfq_get_packet_hw(struct nfq_data *nfad)
int nfq_bind_pf(struct nfq_handle *h, uint16_t pf)
uint32_t nfq_get_indev(struct nfq_data *nfad)
int nfq_fd(struct nfq_handle *h)
struct nfq_q_handle * nfq_create_queue(struct nfq_handle *h, uint16_t num, nfq_callback *cb, void *data)
struct nfqnl_msg_packet_hdr * nfq_get_msg_packet_hdr(struct nfq_data *nfad)
int nfq_get_payload(struct nfq_data *nfad, unsigned char **data)
uint32_t nfq_get_physoutdev(struct nfq_data *nfad)
struct nfq_handle * nfq_open(void)
int nfq_set_mode(struct nfq_q_handle *qh, uint8_t mode, uint32_t range)
uint32_t nfq_get_physindev(struct nfq_data *nfad)
int nfq_get_gid(struct nfq_data *nfad, uint32_t *gid)
int nfq_destroy_queue(struct nfq_q_handle *qh)
uint32_t nfq_get_nfmark(struct nfq_data *nfad)
int nfq_unbind_pf(struct nfq_handle *h, uint16_t pf)
int nfq_handle_packet(struct nfq_handle *h, char *buf, int len)
int nfq_get_secctx(struct nfq_data *nfad, unsigned char **secdata)
int nfq_close(struct nfq_handle *h)
int nfq_get_uid(struct nfq_data *nfad, uint32_t *uid)
int nfq_set_queue_flags(struct nfq_q_handle *qh, uint32_t mask, uint32_t flags)
uint32_t nfq_get_outdev(struct nfq_data *nfad)
int nfq_set_verdict(struct nfq_q_handle *qh, uint32_t id, uint32_t verdict, uint32_t data_len, const unsigned char *buf)