9 #include <libmnl/libmnl.h>
10 #include <linux/netfilter.h>
11 #include <linux/netfilter/nfnetlink.h>
12 #include <linux/netfilter/nfnetlink_queue.h>
14 static int parse_attr_cb(
const struct nlattr *attr,
void *data)
16 const struct nlattr **tb = data;
17 int type = mnl_attr_get_type(attr);
20 if (mnl_attr_type_valid(attr, NFQA_MAX) < 0)
25 case NFQA_IFINDEX_INDEV:
26 case NFQA_IFINDEX_OUTDEV:
27 case NFQA_IFINDEX_PHYSINDEV:
28 case NFQA_IFINDEX_PHYSOUTDEV:
29 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
30 perror(
"mnl_attr_validate");
35 if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC,
36 sizeof(
struct nfqnl_msg_packet_timestamp)) < 0) {
37 perror(
"mnl_attr_validate2");
42 if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC,
43 sizeof(
struct nfqnl_msg_packet_hw)) < 0) {
44 perror(
"mnl_attr_validate2");
55 static int queue_cb(
const struct nlmsghdr *nlh,
void *data)
57 struct nlattr *tb[NFQA_MAX+1] = {};
58 struct nfqnl_msg_packet_hdr *ph = NULL;
61 mnl_attr_parse(nlh,
sizeof(
struct nfgenmsg), parse_attr_cb, tb);
62 if (tb[NFQA_PACKET_HDR]) {
63 ph = mnl_attr_get_payload(tb[NFQA_PACKET_HDR]);
64 id = ntohl(ph->packet_id);
66 printf(
"packet received (id=%u hw=0x%04x hook=%u)\n",
67 id, ntohs(ph->hw_protocol), ph->hook);
70 return MNL_CB_OK + id;
73 static struct nlmsghdr *
74 nfq_build_cfg_pf_request(
char *buf, uint8_t command)
76 struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
77 nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG;
78 nlh->nlmsg_flags = NLM_F_REQUEST;
80 struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh,
sizeof(*nfg));
81 nfg->nfgen_family = AF_UNSPEC;
82 nfg->version = NFNETLINK_V0;
84 struct nfqnl_msg_config_cmd cmd = {
88 mnl_attr_put(nlh, NFQA_CFG_CMD,
sizeof(cmd), &cmd);
93 static struct nlmsghdr *
94 nfq_build_cfg_request(
char *buf, uint8_t command,
int queue_num)
96 struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
97 nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG;
98 nlh->nlmsg_flags = NLM_F_REQUEST;
100 struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh,
sizeof(*nfg));
101 nfg->nfgen_family = AF_UNSPEC;
102 nfg->version = NFNETLINK_V0;
103 nfg->res_id = htons(queue_num);
105 struct nfqnl_msg_config_cmd cmd = {
107 .pf = htons(AF_INET),
109 mnl_attr_put(nlh, NFQA_CFG_CMD,
sizeof(cmd), &cmd);
114 static struct nlmsghdr *
115 nfq_build_cfg_params(
char *buf, uint8_t mode,
int range,
int queue_num)
117 struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
118 nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG;
119 nlh->nlmsg_flags = NLM_F_REQUEST;
121 struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh,
sizeof(*nfg));
122 nfg->nfgen_family = AF_UNSPEC;
123 nfg->version = NFNETLINK_V0;
124 nfg->res_id = htons(queue_num);
126 struct nfqnl_msg_config_params params = {
127 .copy_range = htonl(range),
130 mnl_attr_put(nlh, NFQA_CFG_PARAMS,
sizeof(params), ¶ms);
135 static struct nlmsghdr *
136 nfq_build_verdict(
char *buf,
int id,
int queue_num,
int verd)
138 struct nlmsghdr *nlh;
139 struct nfgenmsg *nfg;
141 nlh = mnl_nlmsg_put_header(buf);
142 nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_VERDICT;
143 nlh->nlmsg_flags = NLM_F_REQUEST;
144 nfg = mnl_nlmsg_put_extra_header(nlh,
sizeof(*nfg));
145 nfg->nfgen_family = AF_UNSPEC;
146 nfg->version = NFNETLINK_V0;
147 nfg->res_id = htons(queue_num);
149 struct nfqnl_msg_verdict_hdr vh = {
150 .verdict = htonl(verd),
153 mnl_attr_put(nlh, NFQA_VERDICT_HDR,
sizeof(vh), &vh);
158 int main(
int argc,
char *argv[])
161 char buf[MNL_SOCKET_BUFFER_SIZE];
162 struct nlmsghdr *nlh;
164 unsigned int portid, queue_num;
167 printf(
"Usage: %s [queue_num]\n", argv[0]);
170 queue_num = atoi(argv[1]);
172 nl = mnl_socket_open(NETLINK_NETFILTER);
174 perror(
"mnl_socket_open");
178 if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
179 perror(
"mnl_socket_bind");
182 portid = mnl_socket_get_portid(nl);
184 nlh = nfq_build_cfg_pf_request(buf, NFQNL_CFG_CMD_PF_UNBIND);
186 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
187 perror(
"mnl_socket_sendto");
191 nlh = nfq_build_cfg_pf_request(buf, NFQNL_CFG_CMD_PF_BIND);
193 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
194 perror(
"mnl_socket_sendto");
198 nlh = nfq_build_cfg_request(buf, NFQNL_CFG_CMD_BIND, queue_num);
200 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
201 perror(
"mnl_socket_sendto");
205 nlh = nfq_build_cfg_params(buf, NFQNL_COPY_PACKET, 0xFFFF, queue_num);
207 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
208 perror(
"mnl_socket_sendto");
212 ret = mnl_socket_recvfrom(nl, buf,
sizeof(buf));
214 perror(
"mnl_socket_recvfrom");
220 ret = mnl_cb_run(buf, ret, 0, portid, queue_cb, NULL);
222 perror(
"mnl_cb_run");
226 id = ret - MNL_CB_OK;
227 nlh = nfq_build_verdict(buf,
id, queue_num, NF_ACCEPT);
228 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
229 perror(
"mnl_socket_sendto");
233 ret = mnl_socket_recvfrom(nl, buf,
sizeof(buf));
235 perror(
"mnl_socket_recvfrom");
240 mnl_socket_close(nl);