libnetfilter_queue 1.0.5
libnetfilter_queue.c
1/* libnetfilter_queue.c: generic library for access to nf_queue
2 *
3 * (C) 2005 by Harald Welte <laforge@gnumonks.org>
4 * (C) 2005, 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation (or any later at your option)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * 2006-01-23 Andreas Florath <andreas@florath.net>
20 * Fix __set_verdict() that it can now handle payload.
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <unistd.h>
26#include <string.h>
27#include <ctype.h>
28#include <time.h>
29#include <errno.h>
30#include <netinet/in.h>
31#include <sys/socket.h>
32
33#include <libnfnetlink/libnfnetlink.h>
34#include <libnetfilter_queue/libnetfilter_queue.h>
35#include "internal.h"
36
126struct nfq_handle
127{
128 struct nfnl_handle *nfnlh;
129 struct nfnl_subsys_handle *nfnlssh;
130 struct nfq_q_handle *qh_list;
131};
132
133struct nfq_q_handle
134{
135 struct nfq_q_handle *next;
136 struct nfq_handle *h;
137 uint16_t id;
138
139 nfq_callback *cb;
140 void *data;
141};
142
143struct nfq_data {
144 struct nfattr **data;
145};
146
147EXPORT_SYMBOL int nfq_errno;
148
149/***********************************************************************
150 * low level stuff
151 ***********************************************************************/
152
153static void del_qh(struct nfq_q_handle *qh)
154{
155 struct nfq_q_handle *cur_qh, *prev_qh = NULL;
156
157 for (cur_qh = qh->h->qh_list; cur_qh; cur_qh = cur_qh->next) {
158 if (cur_qh == qh) {
159 if (prev_qh)
160 prev_qh->next = qh->next;
161 else
162 qh->h->qh_list = qh->next;
163 return;
164 }
165 prev_qh = cur_qh;
166 }
167}
168
169static void add_qh(struct nfq_q_handle *qh)
170{
171 qh->next = qh->h->qh_list;
172 qh->h->qh_list = qh;
173}
174
175static struct nfq_q_handle *find_qh(struct nfq_handle *h, uint16_t id)
176{
177 struct nfq_q_handle *qh;
178
179 for (qh = h->qh_list; qh; qh = qh->next) {
180 if (qh->id == id)
181 return qh;
182 }
183 return NULL;
184}
185
186/* build a NFQNL_MSG_CONFIG message */
187 static int
188__build_send_cfg_msg(struct nfq_handle *h, uint8_t command,
189 uint16_t queuenum, uint16_t pf)
190{
191 union {
192 char buf[NFNL_HEADER_LEN
193 +NFA_LENGTH(sizeof(struct nfqnl_msg_config_cmd))];
194 struct nlmsghdr nmh;
195 } u;
196 struct nfqnl_msg_config_cmd cmd;
197
198 nfnl_fill_hdr(h->nfnlssh, &u.nmh, 0, AF_UNSPEC, queuenum,
199 NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
200
201 cmd._pad = 0;
202 cmd.command = command;
203 cmd.pf = htons(pf);
204 nfnl_addattr_l(&u.nmh, sizeof(u), NFQA_CFG_CMD, &cmd, sizeof(cmd));
205
206 return nfnl_query(h->nfnlh, &u.nmh);
207}
208
209static int __nfq_rcv_pkt(struct nlmsghdr *nlh, struct nfattr *nfa[],
210 void *data)
211{
212 struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
213 struct nfq_handle *h = data;
214 uint16_t queue_num = ntohs(nfmsg->res_id);
215 struct nfq_q_handle *qh = find_qh(h, queue_num);
216 struct nfq_data nfqa;
217
218 if (!qh)
219 return -ENODEV;
220
221 if (!qh->cb)
222 return -ENODEV;
223
224 nfqa.data = nfa;
225
226 return qh->cb(qh, nfmsg, &nfqa, qh->data);
227}
228
229/* public interface */
230
231EXPORT_SYMBOL
232struct nfnl_handle *nfq_nfnlh(struct nfq_handle *h)
233{
234 return h->nfnlh;
235}
236
307EXPORT_SYMBOL
308int nfq_fd(struct nfq_handle *h)
309{
310 return nfnl_fd(nfq_nfnlh(h));
311}
362EXPORT_SYMBOL
363struct nfq_handle *nfq_open(void)
364{
365 struct nfnl_handle *nfnlh = nfnl_open();
366 struct nfq_handle *qh;
367
368 if (!nfnlh)
369 return NULL;
370
371 /* unset netlink sequence tracking by default */
372 nfnl_unset_sequence_tracking(nfnlh);
373
374 qh = nfq_open_nfnl(nfnlh);
375 if (!qh)
376 nfnl_close(nfnlh);
377
378 return qh;
379}
380
395EXPORT_SYMBOL
396struct nfq_handle *nfq_open_nfnl(struct nfnl_handle *nfnlh)
397{
398 struct nfnl_callback pkt_cb = {
399 .call = __nfq_rcv_pkt,
400 .attr_count = NFQA_MAX,
401 };
402 struct nfq_handle *h;
403 int err;
404
405 h = malloc(sizeof(*h));
406 if (!h)
407 return NULL;
408
409 memset(h, 0, sizeof(*h));
410 h->nfnlh = nfnlh;
411
412 h->nfnlssh = nfnl_subsys_open(h->nfnlh, NFNL_SUBSYS_QUEUE,
413 NFQNL_MSG_MAX, 0);
414 if (!h->nfnlssh) {
415 /* FIXME: nfq_errno */
416 goto out_free;
417 }
418
419 pkt_cb.data = h;
420 err = nfnl_callback_register(h->nfnlssh, NFQNL_MSG_PACKET, &pkt_cb);
421 if (err < 0) {
422 nfq_errno = err;
423 goto out_close;
424 }
425
426 return h;
427out_close:
428 nfnl_subsys_close(h->nfnlssh);
429out_free:
430 free(h);
431 return NULL;
432}
433
451EXPORT_SYMBOL
452int nfq_close(struct nfq_handle *h)
453{
454 int ret;
455
456 ret = nfnl_close(h->nfnlh);
457 if (ret == 0)
458 free(h);
459 return ret;
460}
461
473EXPORT_SYMBOL
474int nfq_bind_pf(struct nfq_handle *h, uint16_t pf)
475{
476 return __build_send_cfg_msg(h, NFQNL_CFG_CMD_PF_BIND, 0, pf);
477}
478
489EXPORT_SYMBOL
490int nfq_unbind_pf(struct nfq_handle *h, uint16_t pf)
491{
492 return __build_send_cfg_msg(h, NFQNL_CFG_CMD_PF_UNBIND, 0, pf);
493}
494
495
537EXPORT_SYMBOL
538struct nfq_q_handle *nfq_create_queue(struct nfq_handle *h, uint16_t num,
539 nfq_callback *cb, void *data)
540{
541 int ret;
542 struct nfq_q_handle *qh;
543
544 if (find_qh(h, num))
545 return NULL;
546
547 qh = malloc(sizeof(*qh));
548 if (!qh)
549 return NULL;
550
551 memset(qh, 0, sizeof(*qh));
552 qh->h = h;
553 qh->id = num;
554 qh->cb = cb;
555 qh->data = data;
556
557 ret = __build_send_cfg_msg(h, NFQNL_CFG_CMD_BIND, num, 0);
558 if (ret < 0) {
559 nfq_errno = ret;
560 free(qh);
561 return NULL;
562 }
563
564 add_qh(qh);
565 return qh;
566}
567
584EXPORT_SYMBOL
585int nfq_destroy_queue(struct nfq_q_handle *qh)
586{
587 int ret = __build_send_cfg_msg(qh->h, NFQNL_CFG_CMD_UNBIND, qh->id, 0);
588 if (ret == 0) {
589 del_qh(qh);
590 free(qh);
591 }
592
593 return ret;
594}
595
608EXPORT_SYMBOL
609int nfq_handle_packet(struct nfq_handle *h, char *buf, int len)
610{
611 return nfnl_handle_packet(h->nfnlh, buf, len);
612}
613
629EXPORT_SYMBOL
630int nfq_set_mode(struct nfq_q_handle *qh, uint8_t mode, uint32_t range)
631{
632 union {
633 char buf[NFNL_HEADER_LEN
634 +NFA_LENGTH(sizeof(struct nfqnl_msg_config_params))];
635 struct nlmsghdr nmh;
636 } u;
637 struct nfqnl_msg_config_params params;
638
639 nfnl_fill_hdr(qh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, qh->id,
640 NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
641
642 params.copy_range = htonl(range);
643 params.copy_mode = mode;
644 nfnl_addattr_l(&u.nmh, sizeof(u), NFQA_CFG_PARAMS, &params,
645 sizeof(params));
646
647 return nfnl_query(qh->h->nfnlh, &u.nmh);
648}
649
718EXPORT_SYMBOL
719int nfq_set_queue_flags(struct nfq_q_handle *qh, uint32_t mask, uint32_t flags)
720{
721 union {
722 char buf[NFNL_HEADER_LEN
723 +NFA_LENGTH(sizeof(mask)
724 +NFA_LENGTH(sizeof(flags)))];
725 struct nlmsghdr nmh;
726 } u;
727
728 mask = htonl(mask);
729 flags = htonl(flags);
730
731 nfnl_fill_hdr(qh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, qh->id,
732 NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
733
734 nfnl_addattr32(&u.nmh, sizeof(u), NFQA_CFG_FLAGS, flags);
735 nfnl_addattr32(&u.nmh, sizeof(u), NFQA_CFG_MASK, mask);
736
737 return nfnl_query(qh->h->nfnlh, &u.nmh);
738}
739
751EXPORT_SYMBOL
752int nfq_set_queue_maxlen(struct nfq_q_handle *qh, uint32_t queuelen)
753{
754 union {
755 char buf[NFNL_HEADER_LEN
756 +NFA_LENGTH(sizeof(struct nfqnl_msg_config_params))];
757 struct nlmsghdr nmh;
758 } u;
759 uint32_t queue_maxlen = htonl(queuelen);
760
761 nfnl_fill_hdr(qh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, qh->id,
762 NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
763
764 nfnl_addattr_l(&u.nmh, sizeof(u), NFQA_CFG_QUEUE_MAXLEN, &queue_maxlen,
765 sizeof(queue_maxlen));
766
767 return nfnl_query(qh->h->nfnlh, &u.nmh);
768}
769
774static int __set_verdict(struct nfq_q_handle *qh, uint32_t id,
775 uint32_t verdict, uint32_t mark, int set_mark,
776 uint32_t data_len, const unsigned char *data,
777 enum nfqnl_msg_types type)
778{
779 struct nfqnl_msg_verdict_hdr vh;
780 union {
781 char buf[NFNL_HEADER_LEN
782 +NFA_LENGTH(sizeof(mark))
783 +NFA_LENGTH(sizeof(vh))];
784 struct nlmsghdr nmh;
785 } u;
786
787 struct iovec iov[3];
788 int nvecs;
789
790 /* This must be declared here (and not inside the data
791 * handling block) because the iovec points to this. */
792 struct nfattr data_attr;
793
794 memset(iov, 0, sizeof(iov));
795
796 vh.verdict = htonl(verdict);
797 vh.id = htonl(id);
798
799 nfnl_fill_hdr(qh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, qh->id,
800 type, NLM_F_REQUEST);
801
802 /* add verdict header */
803 nfnl_addattr_l(&u.nmh, sizeof(u), NFQA_VERDICT_HDR, &vh, sizeof(vh));
804
805 if (set_mark)
806 nfnl_addattr32(&u.nmh, sizeof(u), NFQA_MARK, mark);
807
808 iov[0].iov_base = &u.nmh;
809 iov[0].iov_len = NLMSG_TAIL(&u.nmh) - (void *)&u.nmh;
810 nvecs = 1;
811
812 if (data_len) {
813 /* The typecast here is to cast away data's const-ness: */
814 nfnl_build_nfa_iovec(&iov[1], &data_attr, NFQA_PAYLOAD,
815 data_len, (unsigned char *) data);
816 nvecs += 2;
817 /* Add the length of the appended data to the message
818 * header. The size of the attribute is given in the
819 * nfa_len field and is set in the nfnl_build_nfa_iovec()
820 * function. */
821 u.nmh.nlmsg_len += data_attr.nfa_len;
822 }
823
824 return nfnl_sendiov(qh->h->nfnlh, iov, nvecs, 0);
825}
826
855EXPORT_SYMBOL
856int nfq_set_verdict(struct nfq_q_handle *qh, uint32_t id,
857 uint32_t verdict, uint32_t data_len,
858 const unsigned char *buf)
859{
860 return __set_verdict(qh, id, verdict, 0, 0, data_len, buf,
861 NFQNL_MSG_VERDICT);
862}
863
873EXPORT_SYMBOL
874int nfq_set_verdict2(struct nfq_q_handle *qh, uint32_t id,
875 uint32_t verdict, uint32_t mark,
876 uint32_t data_len, const unsigned char *buf)
877{
878 return __set_verdict(qh, id, verdict, htonl(mark), 1, data_len,
879 buf, NFQNL_MSG_VERDICT);
880}
881
894EXPORT_SYMBOL
895int nfq_set_verdict_batch(struct nfq_q_handle *qh, uint32_t id,
896 uint32_t verdict)
897{
898 return __set_verdict(qh, id, verdict, 0, 0, 0, NULL,
899 NFQNL_MSG_VERDICT_BATCH);
900}
901
909EXPORT_SYMBOL
910int nfq_set_verdict_batch2(struct nfq_q_handle *qh, uint32_t id,
911 uint32_t verdict, uint32_t mark)
912{
913 return __set_verdict(qh, id, verdict, htonl(mark), 1, 0,
914 NULL, NFQNL_MSG_VERDICT_BATCH);
915}
916
931EXPORT_SYMBOL
932int nfq_set_verdict_mark(struct nfq_q_handle *qh, uint32_t id,
933 uint32_t verdict, uint32_t mark,
934 uint32_t data_len, const unsigned char *buf)
935{
936 return __set_verdict(qh, id, verdict, mark, 1, data_len, buf,
937 NFQNL_MSG_VERDICT);
938}
939
946/*************************************************************
947 * Message parsing functions
948 *************************************************************/
949
973EXPORT_SYMBOL
974struct nfqnl_msg_packet_hdr *nfq_get_msg_packet_hdr(struct nfq_data *nfad)
975{
976 return nfnl_get_pointer_to_data(nfad->data, NFQA_PACKET_HDR,
977 struct nfqnl_msg_packet_hdr);
978}
979
986EXPORT_SYMBOL
987uint32_t nfq_get_nfmark(struct nfq_data *nfad)
988{
989 return ntohl(nfnl_get_data(nfad->data, NFQA_MARK, uint32_t));
990}
991
1001EXPORT_SYMBOL
1002int nfq_get_timestamp(struct nfq_data *nfad, struct timeval *tv)
1003{
1004 struct nfqnl_msg_packet_timestamp *qpt;
1005 qpt = nfnl_get_pointer_to_data(nfad->data, NFQA_TIMESTAMP,
1006 struct nfqnl_msg_packet_timestamp);
1007 if (!qpt)
1008 return -1;
1009
1010 tv->tv_sec = __be64_to_cpu(qpt->sec);
1011 tv->tv_usec = __be64_to_cpu(qpt->usec);
1012
1013 return 0;
1014}
1015
1027EXPORT_SYMBOL
1028uint32_t nfq_get_indev(struct nfq_data *nfad)
1029{
1030 return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_INDEV, uint32_t));
1031}
1032
1041EXPORT_SYMBOL
1042uint32_t nfq_get_physindev(struct nfq_data *nfad)
1043{
1044 return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_PHYSINDEV, uint32_t));
1045}
1046
1055EXPORT_SYMBOL
1056uint32_t nfq_get_outdev(struct nfq_data *nfad)
1057{
1058 return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_OUTDEV, uint32_t));
1059}
1060
1071EXPORT_SYMBOL
1072uint32_t nfq_get_physoutdev(struct nfq_data *nfad)
1073{
1074 return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_PHYSOUTDEV, uint32_t));
1075}
1076
1115EXPORT_SYMBOL
1116int nfq_get_indev_name(struct nlif_handle *nlif_handle,
1117 struct nfq_data *nfad, char *name)
1118{
1119 uint32_t ifindex = nfq_get_indev(nfad);
1120 return nlif_index2name(nlif_handle, ifindex, name);
1121}
1122
1135EXPORT_SYMBOL
1136int nfq_get_physindev_name(struct nlif_handle *nlif_handle,
1137 struct nfq_data *nfad, char *name)
1138{
1139 uint32_t ifindex = nfq_get_physindev(nfad);
1140 return nlif_index2name(nlif_handle, ifindex, name);
1141}
1142
1155EXPORT_SYMBOL
1156int nfq_get_outdev_name(struct nlif_handle *nlif_handle,
1157 struct nfq_data *nfad, char *name)
1158{
1159 uint32_t ifindex = nfq_get_outdev(nfad);
1160 return nlif_index2name(nlif_handle, ifindex, name);
1161}
1162
1176EXPORT_SYMBOL
1177int nfq_get_physoutdev_name(struct nlif_handle *nlif_handle,
1178 struct nfq_data *nfad, char *name)
1179{
1180 uint32_t ifindex = nfq_get_physoutdev(nfad);
1181 return nlif_index2name(nlif_handle, ifindex, name);
1182}
1183
1206EXPORT_SYMBOL
1207struct nfqnl_msg_packet_hw *nfq_get_packet_hw(struct nfq_data *nfad)
1208{
1209 return nfnl_get_pointer_to_data(nfad->data, NFQA_HWADDR,
1210 struct nfqnl_msg_packet_hw);
1211}
1212
1235EXPORT_SYMBOL
1236uint32_t nfq_get_skbinfo(struct nfq_data *nfad)
1237{
1238 if (!nfnl_attr_present(nfad->data, NFQA_SKB_INFO))
1239 return 0;
1240
1241 return ntohl(nfnl_get_data(nfad->data, NFQA_SKB_INFO, uint32_t));
1242}
1243
1255EXPORT_SYMBOL
1256int nfq_get_uid(struct nfq_data *nfad, uint32_t *uid)
1257{
1258 if (!nfnl_attr_present(nfad->data, NFQA_UID))
1259 return 0;
1260
1261 *uid = ntohl(nfnl_get_data(nfad->data, NFQA_UID, uint32_t));
1262 return 1;
1263}
1264
1276EXPORT_SYMBOL
1277int nfq_get_gid(struct nfq_data *nfad, uint32_t *gid)
1278{
1279 if (!nfnl_attr_present(nfad->data, NFQA_GID))
1280 return 0;
1281
1282 *gid = ntohl(nfnl_get_data(nfad->data, NFQA_GID, uint32_t));
1283 return 1;
1284}
1285
1297EXPORT_SYMBOL
1298int nfq_get_secctx(struct nfq_data *nfad, unsigned char **secdata)
1299{
1300 if (!nfnl_attr_present(nfad->data, NFQA_SECCTX))
1301 return -1;
1302
1303 *secdata = (unsigned char *)nfnl_get_pointer_to_data(nfad->data,
1304 NFQA_SECCTX, char);
1305
1306 if (*secdata)
1307 return NFA_PAYLOAD(nfad->data[NFQA_SECCTX-1]);
1308
1309 return 0;
1310}
1311
1323EXPORT_SYMBOL
1324int nfq_get_payload(struct nfq_data *nfad, unsigned char **data)
1325{
1326 *data = (unsigned char *)
1327 nfnl_get_pointer_to_data(nfad->data, NFQA_PAYLOAD, char);
1328 if (*data)
1329 return NFA_PAYLOAD(nfad->data[NFQA_PAYLOAD-1]);
1330
1331 return -1;
1332}
1333
1338#define SNPRINTF_FAILURE(ret, rem, offset, len) \
1339do { \
1340 if (ret < 0) \
1341 return ret; \
1342 len += ret; \
1343 if (ret > rem) \
1344 ret = rem; \
1345 offset += ret; \
1346 rem -= ret; \
1347} while (0)
1348
1377EXPORT_SYMBOL
1378int nfq_snprintf_xml(char *buf, size_t rem, struct nfq_data *tb, int flags)
1379{
1380 struct nfqnl_msg_packet_hdr *ph;
1381 struct nfqnl_msg_packet_hw *hwph;
1382 uint32_t mark, ifi;
1383 uint32_t uid, gid;
1384 int size, offset = 0, len = 0, ret;
1385 unsigned char *data;
1386
1387 size = snprintf(buf + offset, rem, "<pkt>");
1388 SNPRINTF_FAILURE(size, rem, offset, len);
1389
1390 if (flags & NFQ_XML_TIME) {
1391 time_t t;
1392 struct tm tm;
1393
1394 t = time(NULL);
1395 if (localtime_r(&t, &tm) == NULL)
1396 return -1;
1397
1398 size = snprintf(buf + offset, rem, "<when>");
1399 SNPRINTF_FAILURE(size, rem, offset, len);
1400
1401 size = snprintf(buf + offset, rem,
1402 "<hour>%d</hour>", tm.tm_hour);
1403 SNPRINTF_FAILURE(size, rem, offset, len);
1404
1405 size = snprintf(buf + offset,
1406 rem, "<min>%02d</min>", tm.tm_min);
1407 SNPRINTF_FAILURE(size, rem, offset, len);
1408
1409 size = snprintf(buf + offset,
1410 rem, "<sec>%02d</sec>", tm.tm_sec);
1411 SNPRINTF_FAILURE(size, rem, offset, len);
1412
1413 size = snprintf(buf + offset, rem, "<wday>%d</wday>",
1414 tm.tm_wday + 1);
1415 SNPRINTF_FAILURE(size, rem, offset, len);
1416
1417 size = snprintf(buf + offset, rem, "<day>%d</day>", tm.tm_mday);
1418 SNPRINTF_FAILURE(size, rem, offset, len);
1419
1420 size = snprintf(buf + offset, rem, "<month>%d</month>",
1421 tm.tm_mon + 1);
1422 SNPRINTF_FAILURE(size, rem, offset, len);
1423
1424 size = snprintf(buf + offset, rem, "<year>%d</year>",
1425 1900 + tm.tm_year);
1426 SNPRINTF_FAILURE(size, rem, offset, len);
1427
1428 size = snprintf(buf + offset, rem, "</when>");
1429 SNPRINTF_FAILURE(size, rem, offset, len);
1430 }
1431
1432 ph = nfq_get_msg_packet_hdr(tb);
1433 if (ph) {
1434 size = snprintf(buf + offset, rem,
1435 "<hook>%u</hook><id>%u</id>",
1436 ph->hook, ntohl(ph->packet_id));
1437 SNPRINTF_FAILURE(size, rem, offset, len);
1438
1439 hwph = nfq_get_packet_hw(tb);
1440 if (hwph && (flags & NFQ_XML_HW)) {
1441 int i, hlen = ntohs(hwph->hw_addrlen);
1442
1443 size = snprintf(buf + offset, rem, "<hw><proto>%04x"
1444 "</proto>",
1445 ntohs(ph->hw_protocol));
1446 SNPRINTF_FAILURE(size, rem, offset, len);
1447
1448 size = snprintf(buf + offset, rem, "<src>");
1449 SNPRINTF_FAILURE(size, rem, offset, len);
1450
1451 for (i=0; i<hlen; i++) {
1452 size = snprintf(buf + offset, rem, "%02x",
1453 hwph->hw_addr[i]);
1454 SNPRINTF_FAILURE(size, rem, offset, len);
1455 }
1456
1457 size = snprintf(buf + offset, rem, "</src></hw>");
1458 SNPRINTF_FAILURE(size, rem, offset, len);
1459 } else if (flags & NFQ_XML_HW) {
1460 size = snprintf(buf + offset, rem, "<hw><proto>%04x"
1461 "</proto></hw>",
1462 ntohs(ph->hw_protocol));
1463 SNPRINTF_FAILURE(size, rem, offset, len);
1464 }
1465 }
1466
1467 mark = nfq_get_nfmark(tb);
1468 if (mark && (flags & NFQ_XML_MARK)) {
1469 size = snprintf(buf + offset, rem, "<mark>%u</mark>", mark);
1470 SNPRINTF_FAILURE(size, rem, offset, len);
1471 }
1472
1473 ifi = nfq_get_indev(tb);
1474 if (ifi && (flags & NFQ_XML_DEV)) {
1475 size = snprintf(buf + offset, rem, "<indev>%u</indev>", ifi);
1476 SNPRINTF_FAILURE(size, rem, offset, len);
1477 }
1478
1479 ifi = nfq_get_outdev(tb);
1480 if (ifi && (flags & NFQ_XML_DEV)) {
1481 size = snprintf(buf + offset, rem, "<outdev>%u</outdev>", ifi);
1482 SNPRINTF_FAILURE(size, rem, offset, len);
1483 }
1484
1485 ifi = nfq_get_physindev(tb);
1486 if (ifi && (flags & NFQ_XML_PHYSDEV)) {
1487 size = snprintf(buf + offset, rem,
1488 "<physindev>%u</physindev>", ifi);
1489 SNPRINTF_FAILURE(size, rem, offset, len);
1490 }
1491
1492 ifi = nfq_get_physoutdev(tb);
1493 if (ifi && (flags & NFQ_XML_PHYSDEV)) {
1494 size = snprintf(buf + offset, rem,
1495 "<physoutdev>%u</physoutdev>", ifi);
1496 SNPRINTF_FAILURE(size, rem, offset, len);
1497 }
1498
1499 if (nfq_get_uid(tb, &uid) && (flags & NFQ_XML_UID)) {
1500 size = snprintf(buf + offset, rem, "<uid>%u</uid>", uid);
1501 SNPRINTF_FAILURE(size, rem, offset, len);
1502 }
1503
1504 if (nfq_get_gid(tb, &gid) && (flags & NFQ_XML_GID)) {
1505 size = snprintf(buf + offset, rem, "<gid>%u</gid>", gid);
1506 SNPRINTF_FAILURE(size, rem, offset, len);
1507 }
1508
1509 ret = nfq_get_payload(tb, &data);
1510 if (ret >= 0 && (flags & NFQ_XML_PAYLOAD)) {
1511 int i;
1512
1513 size = snprintf(buf + offset, rem, "<payload>");
1514 SNPRINTF_FAILURE(size, rem, offset, len);
1515
1516 for (i=0; i<ret; i++) {
1517 size = snprintf(buf + offset, rem, "%02x",
1518 data[i] & 0xff);
1519 SNPRINTF_FAILURE(size, rem, offset, len);
1520 }
1521
1522 size = snprintf(buf + offset, rem, "</payload>");
1523 SNPRINTF_FAILURE(size, rem, offset, len);
1524 }
1525
1526 size = snprintf(buf + offset, rem, "</pkt>");
1527 SNPRINTF_FAILURE(size, rem, offset, len);
1528
1529 return len;
1530}
1531
int nfq_unbind_pf(struct nfq_handle *h, uint16_t pf)
struct nfq_handle * nfq_open(void)
int nfq_bind_pf(struct nfq_handle *h, uint16_t pf)
int nfq_close(struct nfq_handle *h)
int nfq_get_secctx(struct nfq_data *nfad, unsigned char **secdata)
int nfq_get_outdev_name(struct nlif_handle *nlif_handle, struct nfq_data *nfad, char *name)
int nfq_get_timestamp(struct nfq_data *nfad, struct timeval *tv)
struct nfqnl_msg_packet_hw * nfq_get_packet_hw(struct nfq_data *nfad)
int nfq_get_physindev_name(struct nlif_handle *nlif_handle, struct nfq_data *nfad, char *name)
int nfq_get_physoutdev_name(struct nlif_handle *nlif_handle, struct nfq_data *nfad, char *name)
uint32_t nfq_get_physoutdev(struct nfq_data *nfad)
uint32_t nfq_get_physindev(struct nfq_data *nfad)
int nfq_get_gid(struct nfq_data *nfad, uint32_t *gid)
uint32_t nfq_get_nfmark(struct nfq_data *nfad)
struct nfqnl_msg_packet_hdr * nfq_get_msg_packet_hdr(struct nfq_data *nfad)
uint32_t nfq_get_skbinfo(struct nfq_data *nfad)
int nfq_get_indev_name(struct nlif_handle *nlif_handle, struct nfq_data *nfad, char *name)
int nfq_get_uid(struct nfq_data *nfad, uint32_t *uid)
uint32_t nfq_get_outdev(struct nfq_data *nfad)
uint32_t nfq_get_indev(struct nfq_data *nfad)
int nfq_get_payload(struct nfq_data *nfad, unsigned char **data)
int nfq_snprintf_xml(char *buf, size_t rem, struct nfq_data *tb, int flags)
int nfq_set_verdict_batch2(struct nfq_q_handle *qh, uint32_t id, uint32_t verdict, uint32_t mark)
int nfq_fd(struct nfq_handle *h)
int nfq_destroy_queue(struct nfq_q_handle *qh)
struct nfq_q_handle * nfq_create_queue(struct nfq_handle *h, uint16_t num, nfq_callback *cb, void *data)
int nfq_set_verdict(struct nfq_q_handle *qh, uint32_t id, uint32_t verdict, uint32_t data_len, const unsigned char *buf)
int nfq_handle_packet(struct nfq_handle *h, char *buf, int len)
int nfq_set_mode(struct nfq_q_handle *qh, uint8_t mode, uint32_t range)
int nfq_set_verdict2(struct nfq_q_handle *qh, uint32_t id, uint32_t verdict, uint32_t mark, uint32_t data_len, const unsigned char *buf)
int nfq_set_queue_flags(struct nfq_q_handle *qh, uint32_t mask, uint32_t flags)
int nfq_set_verdict_batch(struct nfq_q_handle *qh, uint32_t id, uint32_t verdict)
int nfq_set_queue_maxlen(struct nfq_q_handle *qh, uint32_t queuelen)
int nfq_set_verdict_mark(struct nfq_q_handle *qh, uint32_t id, uint32_t verdict, uint32_t mark, uint32_t data_len, const unsigned char *buf)