diff options
Diffstat (limited to '_queue')
-rw-r--r-- | _queue/include/libnfnetlink_queue/libipq.h | 4 | ||||
-rw-r--r-- | _queue/include/libnfnetlink_queue/libnfnetlink_queue.h | 53 | ||||
-rw-r--r-- | _queue/src/libipq_compat.c | 27 | ||||
-rw-r--r-- | _queue/src/libnfnetlink_queue.c | 181 |
4 files changed, 197 insertions, 68 deletions
diff --git a/_queue/include/libnfnetlink_queue/libipq.h b/_queue/include/libnfnetlink_queue/libipq.h index 483a514..06c10c1 100644 --- a/_queue/include/libnfnetlink_queue/libipq.h +++ b/_queue/include/libnfnetlink_queue/libipq.h @@ -52,8 +52,8 @@ typedef unsigned long ipq_id_t; struct ipq_handle { - struct nfqnl_handle nfqnlh; - struct nfqnl_q_handle qh; + struct nfqnl_handle *nfqnlh; + struct nfqnl_q_handle *qh; u_int8_t family; u_int8_t blocking; }; diff --git a/_queue/include/libnfnetlink_queue/libnfnetlink_queue.h b/_queue/include/libnfnetlink_queue/libnfnetlink_queue.h index b3aad73..b4d6f81 100644 --- a/_queue/include/libnfnetlink_queue/libnfnetlink_queue.h +++ b/_queue/include/libnfnetlink_queue/libnfnetlink_queue.h @@ -13,39 +13,32 @@ #include <linux/netfilter/nfnetlink_queue.h> #include <libnfnetlink/libnfnetlink.h> +struct nfqnl_handle; +struct nfqnl_q_handle; -#define NFQN -struct nfqnl_handle -{ - struct nfnl_handle nfnlh; -}; - -struct nfqnl_q_handle -{ - struct nfqnl_handle *h; - u_int16_t id; -}; - -struct ctnl_msg_handler { - int type; - int (*handler)(struct sockaddr_nl *, struct nlmsghdr *, void *arg); -}; - -struct ctnl_handle { - struct nfnl_handle nfnlh; - struct ctnl_msg_handler *handler[NFQNL_MSG_MAX]; -}; - -extern int nfqnl_open(struct nfqnl_handle *h); +extern int nfqnl_errno; + +extern struct nfnl_handle *nfqnl_nfnlh(struct nfqnl_handle *h); +extern int nfqnl_fd(struct nfqnl_handle *h); + +typedef nfqnl_callback(struct nfqnl_q_handle *gh, struct nfgenmsg *nfmsg, + struct nfattr *nfa[], void *data); + + +extern struct nfqnl_handle *nfqnl_open(void); extern int nfqnl_close(struct nfqnl_handle *h); extern int nfqnl_bind_pf(struct nfqnl_handle *h, u_int16_t pf); extern int nfqnl_unbind_pf(struct nfqnl_handle *h, u_int16_t pf); -extern int nfqnl_create_queue(struct nfqnl_handle *h, - struct nfqnl_q_handle *qh, u_int16_t num); +extern struct nfqnl_q_handle *nfqnl_create_queue(struct nfqnl_handle *h, + u_int16_t num, + nfqnl_callback *cb, + void *data); extern int nfqnl_destroy_queue(struct nfqnl_q_handle *qh); +extern int nfqnl_handle_packet(struct nfqnl_handle *h, char *buf, int len); + extern int nfqnl_set_mode(struct nfqnl_q_handle *qh, u_int8_t mode, unsigned int len); @@ -54,8 +47,10 @@ extern int nfqnl_set_verdict(struct nfqnl_q_handle *qh, u_int32_t verdict, u_int32_t data_len, unsigned char *buf); - -extern int nfqnl_set_verdict_mark(struct nfqnl_q_handle *qh, u_int32_t id, - u_int32_t verdict, u_int32_t mark, - u_int32_t datalen, unsigned char *buf); +extern int nfqnl_set_verdict_mark(struct nfqnl_q_handle *qh, + u_int32_t id, + u_int32_t verdict, + u_int32_t mark, + u_int32_t datalen, + unsigned char *buf); #endif /* __LIBNFQNETLINK_H */ diff --git a/_queue/src/libipq_compat.c b/_queue/src/libipq_compat.c index 9e99674..d263aed 100644 --- a/_queue/src/libipq_compat.c +++ b/_queue/src/libipq_compat.c @@ -27,8 +27,8 @@ #include <sys/time.h> #include <sys/types.h> -#include "libnfnetlink_queue.h" -#include "libipq.h" +#include <libnfnetlink_queue/libnfnetlink_queue.h> +#include <libnfnetlink_queue/libipq.h> /**************************************************************************** * @@ -216,16 +216,16 @@ struct ipq_handle *ipq_create_handle(u_int32_t flags, u_int32_t protocol) memset(h, 0, sizeof(struct ipq_handle)); - status = nfqnl_open(&h->nfqnlh); - if (status < 0) { + h->nfqnlh = nfqnl_open(); + if (!h->nfqnlh) { ipq_errno = IPQ_ERR_SOCKET; goto err_free; } if (protocol == PF_INET) - status = nfqnl_bind_pf(&h->nfqnlh, PF_INET); + status = nfqnl_bind_pf(h->nfqnlh, PF_INET); else if (protocol == PF_INET6) - status = nfqnl_bind_pf(&h->nfqnlh, PF_INET6); + status = nfqnl_bind_pf(h->nfqnlh, PF_INET6); else { ipq_errno = IPQ_ERR_PROTOCOL; goto err_close; @@ -236,8 +236,8 @@ struct ipq_handle *ipq_create_handle(u_int32_t flags, u_int32_t protocol) goto err_close; } - status = nfqnl_create_queue(&h->nfqnlh, &h->qh, 0); - if (status < 0) { + h->qh = nfqnl_create_queue(h->nfqnlh, 0, NULL, NULL); + if (!h->qh) { ipq_errno = IPQ_ERR_BIND; goto err_close; } @@ -245,7 +245,7 @@ struct ipq_handle *ipq_create_handle(u_int32_t flags, u_int32_t protocol) return h; err_close: - nfqnl_close(&h->nfqnlh); + nfqnl_close(h->nfqnlh); err_free: free(h); return NULL; @@ -258,7 +258,7 @@ err_free: int ipq_destroy_handle(struct ipq_handle *h) { if (h) { - nfqnl_close(&h->nfqnlh); + nfqnl_close(h->nfqnlh); free(h); } return 0; @@ -267,7 +267,7 @@ int ipq_destroy_handle(struct ipq_handle *h) int ipq_set_mode(const struct ipq_handle *h, u_int8_t mode, size_t range) { - return nfqnl_set_mode(&h->qh, mode, range); + return nfqnl_set_mode(h->qh, mode, range); } /* @@ -288,7 +288,7 @@ ssize_t ipq_read(const struct ipq_handle *h, * in order to build a data structure that is compatible to * the old ipq interface... */ - nfa = nfnl_parse_hdr(&h->nfqnlh.nfnlh, nlh, &msg); + nfa = nfnl_parse_hdr(nfqnl_nfnlh(h->nfqnlh), nlh, &msg); if (!msg || !nfa) return 0; @@ -298,6 +298,7 @@ ssize_t ipq_read(const struct ipq_handle *h, nfnl_parse_attr(tb, NFQA_MAX, nfa, 0xffff); + return 0; } int ipq_message_type(const unsigned char *buf) @@ -323,7 +324,7 @@ int ipq_set_verdict(const struct ipq_handle *h, size_t data_len, unsigned char *buf) { - return nfqnl_set_verdict(&h->qh, id, verdict, data_len, buf); + return nfqnl_set_verdict(h->qh, id, verdict, data_len, buf); } /* Not implemented yet */ diff --git a/_queue/src/libnfnetlink_queue.c b/_queue/src/libnfnetlink_queue.c index d65c2eb..62f914d 100644 --- a/_queue/src/libnfnetlink_queue.c +++ b/_queue/src/libnfnetlink_queue.c @@ -32,26 +32,60 @@ #include <libnfnetlink/libnfnetlink.h> #include <libnfnetlink_queue/libnfnetlink_queue.h> +struct nfqnl_handle +{ + struct nfnl_handle nfnlh; + struct nfqnl_q_handle *qh_list; +}; + +struct nfqnl_q_handle +{ + struct nfqnl_q_handle *next; + struct nfqnl_handle *h; + u_int16_t id; + + nfqnl_callback *cb; + void *data; +}; + + +int nfqnl_errno; + /*********************************************************************** * low level stuff ***********************************************************************/ -int nfqnl_open(struct nfqnl_handle *h) +static void del_qh(struct nfqnl_q_handle *qh) { - int err; - - memset(h, 0, sizeof(*h)); - - err = nfnl_open(&h->nfnlh, NFNL_SUBSYS_QUEUE, 0); - if (err < 0) - return err; + struct nfqnl_q_handle *cur_qh, *prev_qh = NULL; + + for (cur_qh = qh->h->qh_list; cur_qh; cur_qh = cur_qh->next) { + if (cur_qh == qh) { + if (prev_qh) + prev_qh->next = qh->next; + else + qh->h->qh_list = qh->next; + return; + } + prev_qh = cur_qh; + } +} - return 0; +static void add_qh(struct nfqnl_q_handle *qh) +{ + qh->next = qh->h->qh_list; + qh->h->qh_list = qh; } -int nfqnl_close(struct nfqnl_handle *h) +static struct nfqnl_q_handle *find_qh(struct nfqnl_handle *h, u_int16_t id) { - return nfnl_close(&h->nfnlh); + struct nfqnl_q_handle *qh; + + for (qh = h->qh_list; qh; qh = qh->next) { + if (qh->id == id) + return qh; + } + return NULL; } /* build a NFQNL_MSG_CONFIG message */ @@ -59,8 +93,7 @@ static int __build_send_cfg_msg(struct nfqnl_handle *h, u_int8_t command, u_int16_t queuenum, u_int16_t pf) { - char buf[NLMSG_LENGTH(sizeof(struct nlmsghdr)) - +NLMSG_LENGTH(sizeof(struct nfgenmsg)) + char buf[NFNL_HEADER_LEN +NFA_LENGTH(sizeof(struct nfqnl_msg_config_cmd))]; struct nfqnl_msg_config_cmd cmd; struct nlmsghdr *nmh = (struct nlmsghdr *) buf; @@ -72,7 +105,81 @@ __build_send_cfg_msg(struct nfqnl_handle *h, u_int8_t command, cmd.pf = htons(pf); nfnl_addattr_l(nmh, sizeof(buf), NFQA_CFG_CMD, &cmd, sizeof(cmd)); - return nfnl_send(&h->nfnlh, nmh); + return nfnl_talk(&h->nfnlh, nmh, 0, 0, NULL, NULL, NULL); +} + +static int __nfqnl_rcv_pkt(struct nlmsghdr *nlh, struct nfattr *nfa[], + void *data) +{ + struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); + struct nfqnl_handle *h = data; + u_int16_t queue_num = ntohs(nfmsg->res_id); + struct nfqnl_q_handle *qh = find_qh(h, queue_num); + + if (!qh) + return -ENODEV; + + if (!qh->cb) + return -ENODEV; + + return qh->cb(qh, nfmsg, nfa, qh->data); +} + +static struct nfnl_callback pkt_cb = { + .call = &__nfqnl_rcv_pkt, + .attr_count = NFQA_MAX, +}; + +/* public interface */ + +struct nfnl_handle *nfqnl_nfnlh(struct nfqnl_handle *h) +{ + return &h->nfnlh; +} + +int nfqnl_fd(struct nfqnl_handle *h) +{ + return nfnl_fd(nfqnl_nfnlh(h)); +} + +struct nfqnl_handle *nfqnl_open(void) +{ + struct nfqnl_handle *h; + int err; + + h = malloc(sizeof(*h)); + if (!h) + return NULL; + + memset(h, 0, sizeof(*h)); + + err = nfnl_open(&h->nfnlh, NFNL_SUBSYS_QUEUE, NFQNL_MSG_MAX, 0); + if (err < 0) { + nfqnl_errno = err; + goto out_free; + } + + pkt_cb.data = h; + err = nfnl_callback_register(&h->nfnlh, NFQNL_MSG_PACKET, &pkt_cb); + if (err < 0) { + nfqnl_errno = err; + goto out_close; + } + + return h; +out_close: + nfnl_close(&h->nfnlh); +out_free: + free(h); + return NULL; +} + +int nfqnl_close(struct nfqnl_handle *h) +{ + int ret = nfnl_close(&h->nfnlh); + if (ret == 0) + free(h); + return ret; } /* bind nf_queue from a specific protocol family */ @@ -88,30 +195,57 @@ int nfqnl_unbind_pf(struct nfqnl_handle *h, u_int16_t pf) } /* bind this socket to a specific queue number */ -int nfqnl_create_queue(struct nfqnl_handle *h, - struct nfqnl_q_handle *qh, u_int16_t num) +struct nfqnl_q_handle *nfqnl_create_queue(struct nfqnl_handle *h, + u_int16_t num, + nfqnl_callback *cb, + void *data) { + int ret; + struct nfqnl_q_handle *qh; + + if (find_qh(h, num)) + return NULL; + + qh = malloc(sizeof(*qh)); + + memset(qh, 0, sizeof(*qh)); qh->h = h; qh->id = num; + qh->cb = cb; + qh->data = data; + + ret = __build_send_cfg_msg(h, NFQNL_CFG_CMD_BIND, num, 0); + if (ret < 0) { + nfqnl_errno = ret; + free(qh); + return NULL; + } - return __build_send_cfg_msg(h, NFQNL_CFG_CMD_BIND, num, 0); + add_qh(qh); + return qh; } /* unbind this socket from a specific queue number */ int nfqnl_destroy_queue(struct nfqnl_q_handle *qh) { int ret = __build_send_cfg_msg(qh->h, NFQNL_CFG_CMD_UNBIND, qh->id, 0); - if (ret == 0) - qh->h = NULL; + if (ret == 0) { + del_qh(qh); + free(qh); + } return ret; } +int nfqnl_handle_packet(struct nfqnl_handle *h, char *buf, int len) +{ + return nfnl_handle_packet(&h->nfnlh, buf, len); +} + int nfqnl_set_mode(struct nfqnl_q_handle *qh, u_int8_t mode, u_int32_t range) { - char buf[NLMSG_LENGTH(sizeof(struct nlmsghdr)) - +NLMSG_LENGTH(sizeof(struct nfgenmsg)) + char buf[NFNL_HEADER_LEN +NFA_LENGTH(sizeof(struct nfqnl_msg_config_params))]; struct nfqnl_msg_config_params params; struct nlmsghdr *nmh = (struct nlmsghdr *) buf; @@ -124,7 +258,7 @@ int nfqnl_set_mode(struct nfqnl_q_handle *qh, nfnl_addattr_l(nmh, sizeof(buf), NFQA_CFG_PARAMS, ¶ms, sizeof(params)); - return nfnl_send(&qh->h->nfnlh, nmh); + return nfnl_talk(&qh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL); } static int __set_verdict(struct nfqnl_q_handle *qh, u_int32_t id, @@ -132,8 +266,7 @@ static int __set_verdict(struct nfqnl_q_handle *qh, u_int32_t id, u_int32_t data_len, unsigned char *data) { struct nfqnl_msg_verdict_hdr vh; - char buf[NLMSG_LENGTH(sizeof(struct nlmsghdr)) - +NLMSG_LENGTH(sizeof(struct nfgenmsg)) + char buf[NFNL_HEADER_LEN +NFA_LENGTH(sizeof(mark)) +NFA_LENGTH(sizeof(vh))]; struct nlmsghdr *nmh = (struct nlmsghdr *) buf; |