libnetfilter_queue  1.0.3
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 
116 {
117  struct nfnl_handle *nfnlh;
118  struct nfnl_subsys_handle *nfnlssh;
119  struct nfq_q_handle *qh_list;
120 };
121 
123 {
124  struct nfq_q_handle *next;
125  struct nfq_handle *h;
126  uint16_t id;
127 
128  nfq_callback *cb;
129  void *data;
130 };
131 
132 struct nfq_data {
133  struct nfattr **data;
134 };
135 
136 int nfq_errno;
137 EXPORT_SYMBOL(nfq_errno);
138 
139 /***********************************************************************
140  * low level stuff
141  ***********************************************************************/
142 
143 static void del_qh(struct nfq_q_handle *qh)
144 {
145  struct nfq_q_handle *cur_qh, *prev_qh = NULL;
146 
147  for (cur_qh = qh->h->qh_list; cur_qh; cur_qh = cur_qh->next) {
148  if (cur_qh == qh) {
149  if (prev_qh)
150  prev_qh->next = qh->next;
151  else
152  qh->h->qh_list = qh->next;
153  return;
154  }
155  prev_qh = cur_qh;
156  }
157 }
158 
159 static void add_qh(struct nfq_q_handle *qh)
160 {
161  qh->next = qh->h->qh_list;
162  qh->h->qh_list = qh;
163 }
164 
165 static struct nfq_q_handle *find_qh(struct nfq_handle *h, uint16_t id)
166 {
167  struct nfq_q_handle *qh;
168 
169  for (qh = h->qh_list; qh; qh = qh->next) {
170  if (qh->id == id)
171  return qh;
172  }
173  return NULL;
174 }
175 
176 /* build a NFQNL_MSG_CONFIG message */
177  static int
178 __build_send_cfg_msg(struct nfq_handle *h, uint8_t command,
179  uint16_t queuenum, uint16_t pf)
180 {
181  union {
182  char buf[NFNL_HEADER_LEN
183  +NFA_LENGTH(sizeof(struct nfqnl_msg_config_cmd))];
184  struct nlmsghdr nmh;
185  } u;
186  struct nfqnl_msg_config_cmd cmd;
187 
188  nfnl_fill_hdr(h->nfnlssh, &u.nmh, 0, AF_UNSPEC, queuenum,
189  NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
190 
191  cmd._pad = 0;
192  cmd.command = command;
193  cmd.pf = htons(pf);
194  nfnl_addattr_l(&u.nmh, sizeof(u), NFQA_CFG_CMD, &cmd, sizeof(cmd));
195 
196  return nfnl_query(h->nfnlh, &u.nmh);
197 }
198 
199 static int __nfq_rcv_pkt(struct nlmsghdr *nlh, struct nfattr *nfa[],
200  void *data)
201 {
202  struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
203  struct nfq_handle *h = data;
204  uint16_t queue_num = ntohs(nfmsg->res_id);
205  struct nfq_q_handle *qh = find_qh(h, queue_num);
206  struct nfq_data nfqa;
207 
208  if (!qh)
209  return -ENODEV;
210 
211  if (!qh->cb)
212  return -ENODEV;
213 
214  nfqa.data = nfa;
215 
216  return qh->cb(qh, nfmsg, &nfqa, qh->data);
217 }
218 
219 /* public interface */
220 
221 struct nfnl_handle *nfq_nfnlh(struct nfq_handle *h)
222 {
223  return h->nfnlh;
224 }
225 EXPORT_SYMBOL(nfq_nfnlh);
226 
297 int nfq_fd(struct nfq_handle *h)
298 {
299  return nfnl_fd(nfq_nfnlh(h));
300 }
301 EXPORT_SYMBOL(nfq_fd);
352 struct nfq_handle *nfq_open(void)
353 {
354  struct nfnl_handle *nfnlh = nfnl_open();
355  struct nfq_handle *qh;
356 
357  if (!nfnlh)
358  return NULL;
359 
360  /* unset netlink sequence tracking by default */
361  nfnl_unset_sequence_tracking(nfnlh);
362 
363  qh = nfq_open_nfnl(nfnlh);
364  if (!qh)
365  nfnl_close(nfnlh);
366 
367  return qh;
368 }
369 EXPORT_SYMBOL(nfq_open);
370 
385 struct nfq_handle *nfq_open_nfnl(struct nfnl_handle *nfnlh)
386 {
387  struct nfnl_callback pkt_cb = {
388  .call = __nfq_rcv_pkt,
389  .attr_count = NFQA_MAX,
390  };
391  struct nfq_handle *h;
392  int err;
393 
394  h = malloc(sizeof(*h));
395  if (!h)
396  return NULL;
397 
398  memset(h, 0, sizeof(*h));
399  h->nfnlh = nfnlh;
400 
401  h->nfnlssh = nfnl_subsys_open(h->nfnlh, NFNL_SUBSYS_QUEUE,
402  NFQNL_MSG_MAX, 0);
403  if (!h->nfnlssh) {
404  /* FIXME: nfq_errno */
405  goto out_free;
406  }
407 
408  pkt_cb.data = h;
409  err = nfnl_callback_register(h->nfnlssh, NFQNL_MSG_PACKET, &pkt_cb);
410  if (err < 0) {
411  nfq_errno = err;
412  goto out_close;
413  }
414 
415  return h;
416 out_close:
417  nfnl_subsys_close(h->nfnlssh);
418 out_free:
419  free(h);
420  return NULL;
421 }
422 EXPORT_SYMBOL(nfq_open_nfnl);
423 
441 int nfq_close(struct nfq_handle *h)
442 {
443  int ret;
444 
445  ret = nfnl_close(h->nfnlh);
446  if (ret == 0)
447  free(h);
448  return ret;
449 }
450 EXPORT_SYMBOL(nfq_close);
451 
463 int nfq_bind_pf(struct nfq_handle *h, uint16_t pf)
464 {
465  return __build_send_cfg_msg(h, NFQNL_CFG_CMD_PF_BIND, 0, pf);
466 }
467 EXPORT_SYMBOL(nfq_bind_pf);
468 
479 int nfq_unbind_pf(struct nfq_handle *h, uint16_t pf)
480 {
481  return __build_send_cfg_msg(h, NFQNL_CFG_CMD_PF_UNBIND, 0, pf);
482 }
483 EXPORT_SYMBOL(nfq_unbind_pf);
484 
485 
528  uint16_t num,
529  nfq_callback *cb,
530  void *data)
531 {
532  int ret;
533  struct nfq_q_handle *qh;
534 
535  if (find_qh(h, num))
536  return NULL;
537 
538  qh = malloc(sizeof(*qh));
539  if (!qh)
540  return NULL;
541 
542  memset(qh, 0, sizeof(*qh));
543  qh->h = h;
544  qh->id = num;
545  qh->cb = cb;
546  qh->data = data;
547 
548  ret = __build_send_cfg_msg(h, NFQNL_CFG_CMD_BIND, num, 0);
549  if (ret < 0) {
550  nfq_errno = ret;
551  free(qh);
552  return NULL;
553  }
554 
555  add_qh(qh);
556  return qh;
557 }
558 EXPORT_SYMBOL(nfq_create_queue);
559 
577 {
578  int ret = __build_send_cfg_msg(qh->h, NFQNL_CFG_CMD_UNBIND, qh->id, 0);
579  if (ret == 0) {
580  del_qh(qh);
581  free(qh);
582  }
583 
584  return ret;
585 }
586 EXPORT_SYMBOL(nfq_destroy_queue);
587 
600 int nfq_handle_packet(struct nfq_handle *h, char *buf, int len)
601 {
602  return nfnl_handle_packet(h->nfnlh, buf, len);
603 }
604 EXPORT_SYMBOL(nfq_handle_packet);
605 
621 int nfq_set_mode(struct nfq_q_handle *qh,
622  uint8_t mode, uint32_t range)
623 {
624  union {
625  char buf[NFNL_HEADER_LEN
626  +NFA_LENGTH(sizeof(struct nfqnl_msg_config_params))];
627  struct nlmsghdr nmh;
628  } u;
629  struct nfqnl_msg_config_params params;
630 
631  nfnl_fill_hdr(qh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, qh->id,
632  NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
633 
634  params.copy_range = htonl(range);
635  params.copy_mode = mode;
636  nfnl_addattr_l(&u.nmh, sizeof(u), NFQA_CFG_PARAMS, &params,
637  sizeof(params));
638 
639  return nfnl_query(qh->h->nfnlh, &u.nmh);
640 }
641 EXPORT_SYMBOL(nfq_set_mode);
642 
712  uint32_t mask, uint32_t flags)
713 {
714  union {
715  char buf[NFNL_HEADER_LEN
716  +NFA_LENGTH(sizeof(mask)
717  +NFA_LENGTH(sizeof(flags)))];
718  struct nlmsghdr nmh;
719  } u;
720 
721  mask = htonl(mask);
722  flags = htonl(flags);
723 
724  nfnl_fill_hdr(qh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, qh->id,
725  NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
726 
727  nfnl_addattr32(&u.nmh, sizeof(u), NFQA_CFG_FLAGS, flags);
728  nfnl_addattr32(&u.nmh, sizeof(u), NFQA_CFG_MASK, mask);
729 
730  return nfnl_query(qh->h->nfnlh, &u.nmh);
731 }
732 EXPORT_SYMBOL(nfq_set_queue_flags);
733 
746  uint32_t queuelen)
747 {
748  union {
749  char buf[NFNL_HEADER_LEN
750  +NFA_LENGTH(sizeof(struct nfqnl_msg_config_params))];
751  struct nlmsghdr nmh;
752  } u;
753  uint32_t queue_maxlen = htonl(queuelen);
754 
755  nfnl_fill_hdr(qh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, qh->id,
756  NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
757 
758  nfnl_addattr_l(&u.nmh, sizeof(u), NFQA_CFG_QUEUE_MAXLEN, &queue_maxlen,
759  sizeof(queue_maxlen));
760 
761  return nfnl_query(qh->h->nfnlh, &u.nmh);
762 }
763 EXPORT_SYMBOL(nfq_set_queue_maxlen);
764 
769 static int __set_verdict(struct nfq_q_handle *qh, uint32_t id,
770  uint32_t verdict, uint32_t mark, int set_mark,
771  uint32_t data_len, const unsigned char *data,
772  enum nfqnl_msg_types type)
773 {
774  struct nfqnl_msg_verdict_hdr vh;
775  union {
776  char buf[NFNL_HEADER_LEN
777  +NFA_LENGTH(sizeof(mark))
778  +NFA_LENGTH(sizeof(vh))];
779  struct nlmsghdr nmh;
780  } u;
781 
782  struct iovec iov[3];
783  int nvecs;
784 
785  /* This must be declared here (and not inside the data
786  * handling block) because the iovec points to this. */
787  struct nfattr data_attr;
788 
789  memset(iov, 0, sizeof(iov));
790 
791  vh.verdict = htonl(verdict);
792  vh.id = htonl(id);
793 
794  nfnl_fill_hdr(qh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, qh->id,
795  type, NLM_F_REQUEST);
796 
797  /* add verdict header */
798  nfnl_addattr_l(&u.nmh, sizeof(u), NFQA_VERDICT_HDR, &vh, sizeof(vh));
799 
800  if (set_mark)
801  nfnl_addattr32(&u.nmh, sizeof(u), NFQA_MARK, mark);
802 
803  iov[0].iov_base = &u.nmh;
804  iov[0].iov_len = NLMSG_TAIL(&u.nmh) - (void *)&u.nmh;
805  nvecs = 1;
806 
807  if (data_len) {
808  /* The typecast here is to cast away data's const-ness: */
809  nfnl_build_nfa_iovec(&iov[1], &data_attr, NFQA_PAYLOAD,
810  data_len, (unsigned char *) data);
811  nvecs += 2;
812  /* Add the length of the appended data to the message
813  * header. The size of the attribute is given in the
814  * nfa_len field and is set in the nfnl_build_nfa_iovec()
815  * function. */
816  u.nmh.nlmsg_len += data_attr.nfa_len;
817  }
818 
819  return nfnl_sendiov(qh->h->nfnlh, iov, nvecs, 0);
820 }
821 
850 int nfq_set_verdict(struct nfq_q_handle *qh, uint32_t id,
851  uint32_t verdict, uint32_t data_len,
852  const unsigned char *buf)
853 {
854  return __set_verdict(qh, id, verdict, 0, 0, data_len, buf,
855  NFQNL_MSG_VERDICT);
856 }
857 EXPORT_SYMBOL(nfq_set_verdict);
858 
868 int nfq_set_verdict2(struct nfq_q_handle *qh, uint32_t id,
869  uint32_t verdict, uint32_t mark,
870  uint32_t data_len, const unsigned char *buf)
871 {
872  return __set_verdict(qh, id, verdict, htonl(mark), 1, data_len,
873  buf, NFQNL_MSG_VERDICT);
874 }
875 EXPORT_SYMBOL(nfq_set_verdict2);
876 
889 int nfq_set_verdict_batch(struct nfq_q_handle *qh, uint32_t id,
890  uint32_t verdict)
891 {
892  return __set_verdict(qh, id, verdict, 0, 0, 0, NULL,
893  NFQNL_MSG_VERDICT_BATCH);
894 }
895 EXPORT_SYMBOL(nfq_set_verdict_batch);
896 
904 int nfq_set_verdict_batch2(struct nfq_q_handle *qh, uint32_t id,
905  uint32_t verdict, uint32_t mark)
906 {
907  return __set_verdict(qh, id, verdict, htonl(mark), 1, 0,
908  NULL, NFQNL_MSG_VERDICT_BATCH);
909 }
910 EXPORT_SYMBOL(nfq_set_verdict_batch2);
911 
926 int nfq_set_verdict_mark(struct nfq_q_handle *qh, uint32_t id,
927  uint32_t verdict, uint32_t mark,
928  uint32_t data_len, const unsigned char *buf)
929 {
930  return __set_verdict(qh, id, verdict, mark, 1, data_len, buf,
931  NFQNL_MSG_VERDICT);
932 }
933 EXPORT_SYMBOL(nfq_set_verdict_mark);
934 
941 /*************************************************************
942  * Message parsing functions
943  *************************************************************/
944 
968 struct nfqnl_msg_packet_hdr *nfq_get_msg_packet_hdr(struct nfq_data *nfad)
969 {
970  return nfnl_get_pointer_to_data(nfad->data, NFQA_PACKET_HDR,
971  struct nfqnl_msg_packet_hdr);
972 }
973 EXPORT_SYMBOL(nfq_get_msg_packet_hdr);
974 
981 uint32_t nfq_get_nfmark(struct nfq_data *nfad)
982 {
983  return ntohl(nfnl_get_data(nfad->data, NFQA_MARK, uint32_t));
984 }
985 EXPORT_SYMBOL(nfq_get_nfmark);
986 
996 int nfq_get_timestamp(struct nfq_data *nfad, struct timeval *tv)
997 {
998  struct nfqnl_msg_packet_timestamp *qpt;
999  qpt = nfnl_get_pointer_to_data(nfad->data, NFQA_TIMESTAMP,
1000  struct nfqnl_msg_packet_timestamp);
1001  if (!qpt)
1002  return -1;
1003 
1004  tv->tv_sec = __be64_to_cpu(qpt->sec);
1005  tv->tv_usec = __be64_to_cpu(qpt->usec);
1006 
1007  return 0;
1008 }
1009 EXPORT_SYMBOL(nfq_get_timestamp);
1010 
1022 uint32_t nfq_get_indev(struct nfq_data *nfad)
1023 {
1024  return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_INDEV, uint32_t));
1025 }
1026 EXPORT_SYMBOL(nfq_get_indev);
1027 
1036 uint32_t nfq_get_physindev(struct nfq_data *nfad)
1037 {
1038  return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_PHYSINDEV, uint32_t));
1039 }
1040 EXPORT_SYMBOL(nfq_get_physindev);
1041 
1050 uint32_t nfq_get_outdev(struct nfq_data *nfad)
1051 {
1052  return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_OUTDEV, uint32_t));
1053 }
1054 EXPORT_SYMBOL(nfq_get_outdev);
1055 
1066 uint32_t nfq_get_physoutdev(struct nfq_data *nfad)
1067 {
1068  return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_PHYSOUTDEV, uint32_t));
1069 }
1070 EXPORT_SYMBOL(nfq_get_physoutdev);
1071 
1110 int nfq_get_indev_name(struct nlif_handle *nlif_handle,
1111  struct nfq_data *nfad, char *name)
1112 {
1113  uint32_t ifindex = nfq_get_indev(nfad);
1114  return nlif_index2name(nlif_handle, ifindex, name);
1115 }
1116 EXPORT_SYMBOL(nfq_get_indev_name);
1117 
1130 int nfq_get_physindev_name(struct nlif_handle *nlif_handle,
1131  struct nfq_data *nfad, char *name)
1132 {
1133  uint32_t ifindex = nfq_get_physindev(nfad);
1134  return nlif_index2name(nlif_handle, ifindex, name);
1135 }
1136 EXPORT_SYMBOL(nfq_get_physindev_name);
1137 
1150 int nfq_get_outdev_name(struct nlif_handle *nlif_handle,
1151  struct nfq_data *nfad, char *name)
1152 {
1153  uint32_t ifindex = nfq_get_outdev(nfad);
1154  return nlif_index2name(nlif_handle, ifindex, name);
1155 }
1156 EXPORT_SYMBOL(nfq_get_outdev_name);
1157 
1171 int nfq_get_physoutdev_name(struct nlif_handle *nlif_handle,
1172  struct nfq_data *nfad, char *name)
1173 {
1174  uint32_t ifindex = nfq_get_physoutdev(nfad);
1175  return nlif_index2name(nlif_handle, ifindex, name);
1176 }
1177 EXPORT_SYMBOL(nfq_get_physoutdev_name);
1178 
1201 struct nfqnl_msg_packet_hw *nfq_get_packet_hw(struct nfq_data *nfad)
1202 {
1203  return nfnl_get_pointer_to_data(nfad->data, NFQA_HWADDR,
1204  struct nfqnl_msg_packet_hw);
1205 }
1206 EXPORT_SYMBOL(nfq_get_packet_hw);
1207 
1218 int nfq_get_uid(struct nfq_data *nfad, uint32_t *uid)
1219 {
1220  if (!nfnl_attr_present(nfad->data, NFQA_UID))
1221  return 0;
1222 
1223  *uid = ntohl(nfnl_get_data(nfad->data, NFQA_UID, uint32_t));
1224  return 1;
1225 }
1226 EXPORT_SYMBOL(nfq_get_uid);
1227 
1238 int nfq_get_gid(struct nfq_data *nfad, uint32_t *gid)
1239 {
1240  if (!nfnl_attr_present(nfad->data, NFQA_GID))
1241  return 0;
1242 
1243  *gid = ntohl(nfnl_get_data(nfad->data, NFQA_GID, uint32_t));
1244  return 1;
1245 }
1246 EXPORT_SYMBOL(nfq_get_gid);
1247 
1259 int nfq_get_secctx(struct nfq_data *nfad, unsigned char **secdata)
1260 {
1261  if (!nfnl_attr_present(nfad->data, NFQA_SECCTX))
1262  return -1;
1263 
1264  *secdata = (unsigned char *)nfnl_get_pointer_to_data(nfad->data,
1265  NFQA_SECCTX, char);
1266 
1267  if (*secdata)
1268  return NFA_PAYLOAD(nfad->data[NFQA_SECCTX-1]);
1269 
1270  return 0;
1271 }
1272 EXPORT_SYMBOL(nfq_get_secctx);
1273 
1285 int nfq_get_payload(struct nfq_data *nfad, unsigned char **data)
1286 {
1287  *data = (unsigned char *)
1288  nfnl_get_pointer_to_data(nfad->data, NFQA_PAYLOAD, char);
1289  if (*data)
1290  return NFA_PAYLOAD(nfad->data[NFQA_PAYLOAD-1]);
1291 
1292  return -1;
1293 }
1294 EXPORT_SYMBOL(nfq_get_payload);
1295 
1300 #define SNPRINTF_FAILURE(ret, rem, offset, len) \
1301 do { \
1302  if (ret < 0) \
1303  return ret; \
1304  len += ret; \
1305  if (ret > rem) \
1306  ret = rem; \
1307  offset += ret; \
1308  rem -= ret; \
1309 } while (0)
1310 
1339 int nfq_snprintf_xml(char *buf, size_t rem, struct nfq_data *tb, int flags)
1340 {
1341  struct nfqnl_msg_packet_hdr *ph;
1342  struct nfqnl_msg_packet_hw *hwph;
1343  uint32_t mark, ifi;
1344  uint32_t uid, gid;
1345  int size, offset = 0, len = 0, ret;
1346  unsigned char *data;
1347 
1348  size = snprintf(buf + offset, rem, "<pkt>");
1349  SNPRINTF_FAILURE(size, rem, offset, len);
1350 
1351  if (flags & NFQ_XML_TIME) {
1352  time_t t;
1353  struct tm tm;
1354 
1355  t = time(NULL);
1356  if (localtime_r(&t, &tm) == NULL)
1357  return -1;
1358 
1359  size = snprintf(buf + offset, rem, "<when>");
1360  SNPRINTF_FAILURE(size, rem, offset, len);
1361 
1362  size = snprintf(buf + offset, rem,
1363  "<hour>%d</hour>", tm.tm_hour);
1364  SNPRINTF_FAILURE(size, rem, offset, len);
1365 
1366  size = snprintf(buf + offset,
1367  rem, "<min>%02d</min>", tm.tm_min);
1368  SNPRINTF_FAILURE(size, rem, offset, len);
1369 
1370  size = snprintf(buf + offset,
1371  rem, "<sec>%02d</sec>", tm.tm_sec);
1372  SNPRINTF_FAILURE(size, rem, offset, len);
1373 
1374  size = snprintf(buf + offset, rem, "<wday>%d</wday>",
1375  tm.tm_wday + 1);
1376  SNPRINTF_FAILURE(size, rem, offset, len);
1377 
1378  size = snprintf(buf + offset, rem, "<day>%d</day>", tm.tm_mday);
1379  SNPRINTF_FAILURE(size, rem, offset, len);
1380 
1381  size = snprintf(buf + offset, rem, "<month>%d</month>",
1382  tm.tm_mon + 1);
1383  SNPRINTF_FAILURE(size, rem, offset, len);
1384 
1385  size = snprintf(buf + offset, rem, "<year>%d</year>",
1386  1900 + tm.tm_year);
1387  SNPRINTF_FAILURE(size, rem, offset, len);
1388 
1389  size = snprintf(buf + offset, rem, "</when>");
1390  SNPRINTF_FAILURE(size, rem, offset, len);
1391  }
1392 
1393  ph = nfq_get_msg_packet_hdr(tb);
1394  if (ph) {
1395  size = snprintf(buf + offset, rem,
1396  "<hook>%u</hook><id>%u</id>",
1397  ph->hook, ntohl(ph->packet_id));
1398  SNPRINTF_FAILURE(size, rem, offset, len);
1399 
1400  hwph = nfq_get_packet_hw(tb);
1401  if (hwph && (flags & NFQ_XML_HW)) {
1402  int i, hlen = ntohs(hwph->hw_addrlen);
1403 
1404  size = snprintf(buf + offset, rem, "<hw><proto>%04x"
1405  "</proto>",
1406  ntohs(ph->hw_protocol));
1407  SNPRINTF_FAILURE(size, rem, offset, len);
1408 
1409  size = snprintf(buf + offset, rem, "<src>");
1410  SNPRINTF_FAILURE(size, rem, offset, len);
1411 
1412  for (i=0; i<hlen; i++) {
1413  size = snprintf(buf + offset, rem, "%02x",
1414  hwph->hw_addr[i]);
1415  SNPRINTF_FAILURE(size, rem, offset, len);
1416  }
1417 
1418  size = snprintf(buf + offset, rem, "</src></hw>");
1419  SNPRINTF_FAILURE(size, rem, offset, len);
1420  } else if (flags & NFQ_XML_HW) {
1421  size = snprintf(buf + offset, rem, "<hw><proto>%04x"
1422  "</proto></hw>",
1423  ntohs(ph->hw_protocol));
1424  SNPRINTF_FAILURE(size, rem, offset, len);
1425  }
1426  }
1427 
1428  mark = nfq_get_nfmark(tb);
1429  if (mark && (flags & NFQ_XML_MARK)) {
1430  size = snprintf(buf + offset, rem, "<mark>%u</mark>", mark);
1431  SNPRINTF_FAILURE(size, rem, offset, len);
1432  }
1433 
1434  ifi = nfq_get_indev(tb);
1435  if (ifi && (flags & NFQ_XML_DEV)) {
1436  size = snprintf(buf + offset, rem, "<indev>%u</indev>", ifi);
1437  SNPRINTF_FAILURE(size, rem, offset, len);
1438  }
1439 
1440  ifi = nfq_get_outdev(tb);
1441  if (ifi && (flags & NFQ_XML_DEV)) {
1442  size = snprintf(buf + offset, rem, "<outdev>%u</outdev>", ifi);
1443  SNPRINTF_FAILURE(size, rem, offset, len);
1444  }
1445 
1446  ifi = nfq_get_physindev(tb);
1447  if (ifi && (flags & NFQ_XML_PHYSDEV)) {
1448  size = snprintf(buf + offset, rem,
1449  "<physindev>%u</physindev>", ifi);
1450  SNPRINTF_FAILURE(size, rem, offset, len);
1451  }
1452 
1453  ifi = nfq_get_physoutdev(tb);
1454  if (ifi && (flags & NFQ_XML_PHYSDEV)) {
1455  size = snprintf(buf + offset, rem,
1456  "<physoutdev>%u</physoutdev>", ifi);
1457  SNPRINTF_FAILURE(size, rem, offset, len);
1458  }
1459 
1460  if (nfq_get_uid(tb, &uid) && (flags & NFQ_XML_UID)) {
1461  size = snprintf(buf + offset, rem, "<uid>%u</uid>", uid);
1462  SNPRINTF_FAILURE(size, rem, offset, len);
1463  }
1464 
1465  if (nfq_get_gid(tb, &gid) && (flags & NFQ_XML_GID)) {
1466  size = snprintf(buf + offset, rem, "<gid>%u</gid>", gid);
1467  SNPRINTF_FAILURE(size, rem, offset, len);
1468  }
1469 
1470  ret = nfq_get_payload(tb, &data);
1471  if (ret >= 0 && (flags & NFQ_XML_PAYLOAD)) {
1472  int i;
1473 
1474  size = snprintf(buf + offset, rem, "<payload>");
1475  SNPRINTF_FAILURE(size, rem, offset, len);
1476 
1477  for (i=0; i<ret; i++) {
1478  size = snprintf(buf + offset, rem, "%02x",
1479  data[i] & 0xff);
1480  SNPRINTF_FAILURE(size, rem, offset, len);
1481  }
1482 
1483  size = snprintf(buf + offset, rem, "</payload>");
1484  SNPRINTF_FAILURE(size, rem, offset, len);
1485  }
1486 
1487  size = snprintf(buf + offset, rem, "</pkt>");
1488  SNPRINTF_FAILURE(size, rem, offset, len);
1489 
1490  return len;
1491 }
1492 EXPORT_SYMBOL(nfq_snprintf_xml);
1493 
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)
int nfq_set_verdict(struct nfq_q_handle *qh, uint32_t id, uint32_t verdict, uint32_t data_len, const unsigned char *buf)