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 
126 struct nfq_handle
127 {
128  struct nfnl_handle *nfnlh;
129  struct nfnl_subsys_handle *nfnlssh;
130  struct nfq_q_handle *qh_list;
131 };
132 
133 struct 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 
143 struct nfq_data {
144  struct nfattr **data;
145 };
146 
147 EXPORT_SYMBOL int nfq_errno;
148 
149 /***********************************************************************
150  * low level stuff
151  ***********************************************************************/
152 
153 static 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 
169 static void add_qh(struct nfq_q_handle *qh)
170 {
171  qh->next = qh->h->qh_list;
172  qh->h->qh_list = qh;
173 }
174 
175 static 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 
209 static 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 
231 EXPORT_SYMBOL
232 struct nfnl_handle *nfq_nfnlh(struct nfq_handle *h)
233 {
234  return h->nfnlh;
235 }
236 
307 EXPORT_SYMBOL
308 int nfq_fd(struct nfq_handle *h)
309 {
310  return nfnl_fd(nfq_nfnlh(h));
311 }
362 EXPORT_SYMBOL
363 struct 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 
395 EXPORT_SYMBOL
396 struct 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;
427 out_close:
428  nfnl_subsys_close(h->nfnlssh);
429 out_free:
430  free(h);
431  return NULL;
432 }
433 
451 EXPORT_SYMBOL
452 int 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 
473 EXPORT_SYMBOL
474 int 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 
489 EXPORT_SYMBOL
490 int 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 
537 EXPORT_SYMBOL
538 struct 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 
584 EXPORT_SYMBOL
585 int 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 
608 EXPORT_SYMBOL
609 int nfq_handle_packet(struct nfq_handle *h, char *buf, int len)
610 {
611  return nfnl_handle_packet(h->nfnlh, buf, len);
612 }
613 
629 EXPORT_SYMBOL
630 int 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 
718 EXPORT_SYMBOL
719 int 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 
751 EXPORT_SYMBOL
752 int 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 
774 static 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 
855 EXPORT_SYMBOL
856 int 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 
873 EXPORT_SYMBOL
874 int 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 
894 EXPORT_SYMBOL
895 int 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 
909 EXPORT_SYMBOL
910 int 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 
931 EXPORT_SYMBOL
932 int 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 
973 EXPORT_SYMBOL
974 struct 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 
986 EXPORT_SYMBOL
987 uint32_t nfq_get_nfmark(struct nfq_data *nfad)
988 {
989  return ntohl(nfnl_get_data(nfad->data, NFQA_MARK, uint32_t));
990 }
991 
1001 EXPORT_SYMBOL
1002 int 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 
1027 EXPORT_SYMBOL
1028 uint32_t nfq_get_indev(struct nfq_data *nfad)
1029 {
1030  return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_INDEV, uint32_t));
1031 }
1032 
1041 EXPORT_SYMBOL
1042 uint32_t nfq_get_physindev(struct nfq_data *nfad)
1043 {
1044  return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_PHYSINDEV, uint32_t));
1045 }
1046 
1055 EXPORT_SYMBOL
1056 uint32_t nfq_get_outdev(struct nfq_data *nfad)
1057 {
1058  return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_OUTDEV, uint32_t));
1059 }
1060 
1071 EXPORT_SYMBOL
1072 uint32_t nfq_get_physoutdev(struct nfq_data *nfad)
1073 {
1074  return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_PHYSOUTDEV, uint32_t));
1075 }
1076 
1115 EXPORT_SYMBOL
1116 int 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 
1135 EXPORT_SYMBOL
1136 int 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 
1155 EXPORT_SYMBOL
1156 int 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 
1176 EXPORT_SYMBOL
1177 int 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 
1206 EXPORT_SYMBOL
1207 struct 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 
1235 EXPORT_SYMBOL
1236 uint32_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 
1255 EXPORT_SYMBOL
1256 int 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 
1276 EXPORT_SYMBOL
1277 int 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 
1297 EXPORT_SYMBOL
1298 int 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 
1323 EXPORT_SYMBOL
1324 int 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) \
1339 do { \
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 
1377 EXPORT_SYMBOL
1378 int 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 
struct nfqnl_msg_packet_hw * nfq_get_packet_hw(struct nfq_data *nfad)
int nfq_bind_pf(struct nfq_handle *h, uint16_t pf)
int nfq_set_verdict_batch(struct nfq_q_handle *qh, uint32_t id, uint32_t verdict)
int nfq_get_outdev_name(struct nlif_handle *nlif_handle, struct nfq_data *nfad, char *name)
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)
int nfq_set_queue_maxlen(struct nfq_q_handle *qh, uint32_t queuelen)
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)
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)
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)
struct nfq_handle * nfq_open(void)
int nfq_set_mode(struct nfq_q_handle *qh, uint8_t mode, uint32_t range)
int nfq_get_timestamp(struct nfq_data *nfad, struct timeval *tv)
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_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)
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_indev_name(struct nlif_handle *nlif_handle, struct nfq_data *nfad, char *name)
int nfq_get_uid(struct nfq_data *nfad, uint32_t *uid)
int nfq_get_physindev_name(struct nlif_handle *nlif_handle, struct nfq_data *nfad, char *name)
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_verdict2(struct nfq_q_handle *qh, uint32_t id, uint32_t verdict, uint32_t mark, uint32_t data_len, const unsigned char *buf)
uint32_t nfq_get_skbinfo(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)