1 /* libnfqnetlink.c: generic library for access to nf_queue
3 * (C) 2005 by Harald Welte <laforge@gnumonks.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include <netinet/in.h>
27 #include <sys/socket.h>
29 #include <libnfnetlink/libnfnetlink.h>
30 #include <libnetfilter_queue/libnetfilter_queue.h>
34 struct nfnl_handle nfnlh;
35 struct nfqnl_q_handle *qh_list;
40 struct nfqnl_q_handle *next;
41 struct nfqnl_handle *h;
54 /***********************************************************************
56 ***********************************************************************/
58 static void del_qh(struct nfqnl_q_handle *qh)
60 struct nfqnl_q_handle *cur_qh, *prev_qh = NULL;
62 for (cur_qh = qh->h->qh_list; cur_qh; cur_qh = cur_qh->next) {
65 prev_qh->next = qh->next;
67 qh->h->qh_list = qh->next;
74 static void add_qh(struct nfqnl_q_handle *qh)
76 qh->next = qh->h->qh_list;
80 static struct nfqnl_q_handle *find_qh(struct nfqnl_handle *h, u_int16_t id)
82 struct nfqnl_q_handle *qh;
84 for (qh = h->qh_list; qh; qh = qh->next) {
91 /* build a NFQNL_MSG_CONFIG message */
93 __build_send_cfg_msg(struct nfqnl_handle *h, u_int8_t command,
94 u_int16_t queuenum, u_int16_t pf)
96 char buf[NFNL_HEADER_LEN
97 +NFA_LENGTH(sizeof(struct nfqnl_msg_config_cmd))];
98 struct nfqnl_msg_config_cmd cmd;
99 struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
101 nfnl_fill_hdr(&h->nfnlh, nmh, 0, AF_UNSPEC, queuenum,
102 NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
104 cmd.command = command;
106 nfnl_addattr_l(nmh, sizeof(buf), NFQA_CFG_CMD, &cmd, sizeof(cmd));
108 return nfnl_talk(&h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
111 static int __nfqnl_rcv_pkt(struct nlmsghdr *nlh, struct nfattr *nfa[],
114 struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
115 struct nfqnl_handle *h = data;
116 u_int16_t queue_num = ntohs(nfmsg->res_id);
117 struct nfqnl_q_handle *qh = find_qh(h, queue_num);
118 struct nfnl_q_data nfqa;
128 return qh->cb(qh, nfmsg, &nfqa, qh->data);
131 static struct nfnl_callback pkt_cb = {
132 .call = &__nfqnl_rcv_pkt,
133 .attr_count = NFQA_MAX,
136 /* public interface */
138 struct nfnl_handle *nfqnl_nfnlh(struct nfqnl_handle *h)
143 int nfqnl_fd(struct nfqnl_handle *h)
145 return nfnl_fd(nfqnl_nfnlh(h));
148 struct nfqnl_handle *nfqnl_open(void)
150 struct nfqnl_handle *h;
153 h = malloc(sizeof(*h));
157 memset(h, 0, sizeof(*h));
159 err = nfnl_open(&h->nfnlh, NFNL_SUBSYS_QUEUE, NFQNL_MSG_MAX, 0);
166 err = nfnl_callback_register(&h->nfnlh, NFQNL_MSG_PACKET, &pkt_cb);
174 nfnl_close(&h->nfnlh);
180 int nfqnl_close(struct nfqnl_handle *h)
182 int ret = nfnl_close(&h->nfnlh);
188 /* bind nf_queue from a specific protocol family */
189 int nfqnl_bind_pf(struct nfqnl_handle *h, u_int16_t pf)
191 return __build_send_cfg_msg(h, NFQNL_CFG_CMD_PF_BIND, 0, pf);
194 /* unbind nf_queue from a specific protocol family */
195 int nfqnl_unbind_pf(struct nfqnl_handle *h, u_int16_t pf)
197 return __build_send_cfg_msg(h, NFQNL_CFG_CMD_PF_UNBIND, 0, pf);
200 /* bind this socket to a specific queue number */
201 struct nfqnl_q_handle *nfqnl_create_queue(struct nfqnl_handle *h,
207 struct nfqnl_q_handle *qh;
212 qh = malloc(sizeof(*qh));
214 memset(qh, 0, sizeof(*qh));
220 ret = __build_send_cfg_msg(h, NFQNL_CFG_CMD_BIND, num, 0);
231 /* unbind this socket from a specific queue number */
232 int nfqnl_destroy_queue(struct nfqnl_q_handle *qh)
234 int ret = __build_send_cfg_msg(qh->h, NFQNL_CFG_CMD_UNBIND, qh->id, 0);
243 int nfqnl_handle_packet(struct nfqnl_handle *h, char *buf, int len)
245 return nfnl_handle_packet(&h->nfnlh, buf, len);
248 int nfqnl_set_mode(struct nfqnl_q_handle *qh,
249 u_int8_t mode, u_int32_t range)
251 char buf[NFNL_HEADER_LEN
252 +NFA_LENGTH(sizeof(struct nfqnl_msg_config_params))];
253 struct nfqnl_msg_config_params params;
254 struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
256 nfnl_fill_hdr(&qh->h->nfnlh, nmh, 0, AF_UNSPEC, qh->id,
257 NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
259 params.copy_range = htonl(range);
260 params.copy_mode = mode;
261 nfnl_addattr_l(nmh, sizeof(buf), NFQA_CFG_PARAMS, ¶ms,
264 return nfnl_talk(&qh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
267 static int __set_verdict(struct nfqnl_q_handle *qh, u_int32_t id,
268 u_int32_t verdict, u_int32_t mark, int set_mark,
269 u_int32_t data_len, unsigned char *data)
271 struct nfqnl_msg_verdict_hdr vh;
272 char buf[NFNL_HEADER_LEN
273 +NFA_LENGTH(sizeof(mark))
274 +NFA_LENGTH(sizeof(vh))];
275 struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
280 memset(iov, 0, sizeof(iov));
282 vh.verdict = htonl(verdict);
285 nfnl_fill_hdr(&qh->h->nfnlh, nmh, 0, AF_UNSPEC, qh->id,
286 NFQNL_MSG_VERDICT, NLM_F_REQUEST);
288 /* add verdict header */
289 nfnl_addattr_l(nmh, sizeof(buf), NFQA_VERDICT_HDR, &vh, sizeof(vh));
292 nfnl_addattr32(nmh, sizeof(buf), NFQA_MARK, mark);
294 iov[0].iov_base = nmh;
295 iov[0].iov_len = NLMSG_TAIL(nmh) - (void *)nmh;
299 struct nfattr data_attr;
301 nfnl_build_nfa_iovec(&iov[1], &data_attr, NFQA_PAYLOAD,
306 return nfnl_sendiov(&qh->h->nfnlh, iov, nvecs, 0);
309 int nfqnl_set_verdict(struct nfqnl_q_handle *qh, u_int32_t id,
310 u_int32_t verdict, u_int32_t data_len,
313 return __set_verdict(qh, id, verdict, 0, 0, data_len, buf);
316 int nfqnl_set_verdict_mark(struct nfqnl_q_handle *qh, u_int32_t id,
317 u_int32_t verdict, u_int32_t mark,
318 u_int32_t datalen, unsigned char *buf)
320 return __set_verdict(qh, id, verdict, mark, 1, datalen, buf);
323 /*************************************************************
324 * Message parsing functions
325 *************************************************************/
327 struct nfqnl_msg_packet_hdr *nfqnl_get_msg_packet_hdr(struct nfnl_q_data *nfad)
329 return nfnl_get_pointer_to_data(nfad->data, NFQA_PACKET_HDR,
330 struct nfqnl_msg_packet_hdr);
333 uint32_t nfqnl_get_nfmark(struct nfnl_q_data *nfad)
335 return ntohl(nfnl_get_data(nfad->data, NFQA_MARK, u_int32_t));
338 struct nfqnl_msg_packet_timestamp *nfqnl_get_timestamp(struct nfnl_q_data *nfad)
340 return nfnl_get_pointer_to_data(nfad->data, NFQA_TIMESTAMP,
341 struct nfqnl_msg_packet_timestamp);
344 /* all nfqnl_get_*dev() functions return 0 if not set, since linux only allows
345 * ifindex >= 1, see net/core/dev.c:2600 (in 2.6.13.1) */
346 u_int32_t nfqnl_get_indev(struct nfnl_q_data *nfad)
348 return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_INDEV, u_int32_t));
351 u_int32_t nfqnl_get_physindev(struct nfnl_q_data *nfad)
353 return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_PHYSINDEV, u_int32_t));
356 u_int32_t nfqnl_get_outdev(struct nfnl_q_data *nfad)
358 return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_OUTDEV, u_int32_t));
361 u_int32_t nfqnl_get_physoutdev(struct nfnl_q_data *nfad)
363 return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_PHYSOUTDEV, u_int32_t));
366 struct nfqnl_msg_packet_hw *nfqnl_get_packet_hw(struct nfnl_q_data *nfad)
368 return nfnl_get_pointer_to_data(nfad->data, NFQA_HWADDR,
369 struct nfqnl_msg_packet_hw);
372 int nfqnl_get_payload(struct nfnl_q_data *nfad, char **data,
373 unsigned int *datalen)
375 *data = nfnl_get_pointer_to_data(nfad->data, NFQA_PAYLOAD, char);
377 *datalen = NFA_PAYLOAD(nfad->data[NFQA_PAYLOAD-1]);