directory restructuring
[platform/upstream/libnetfilter_queue.git] / src / libnfnetlink_queue.c
1 /* libnfqnetlink.c: generic library for access to nf_queue
2  *
3  * (C) 2005 by Harald Welte <laforge@gnumonks.org>
4  *
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
8  *
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.
13  *
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
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <ctype.h>
24 #include <time.h>
25 #include <errno.h>
26 #include <netinet/in.h>
27 #include <sys/socket.h>
28 #include <linux/netlink.h>
29 #include <linux/netfilter/nfnetlink.h>
30 #include <linux/netfilter/nfnetlink_queue.h>
31 #include "libnfnetlink_queue.h"
32
33 /***********************************************************************
34  * low level stuff 
35  ***********************************************************************/
36
37 int nfqnl_open(struct nfqnl_handle *h)
38 {
39         int err;
40
41         memset(h, 0, sizeof(*h));
42
43         err = nfnl_open(&h->nfnlh, NFNL_SUBSYS_QUEUE, 0);
44         if (err < 0)
45                 return err;
46
47         return 0;
48 }
49
50 int nfqnl_close(struct nfqnl_handle *h)
51 {
52         return nfnl_close(&h->nfnlh);
53 }
54
55 /* build a NFQNL_MSG_CONFIG message */
56 static int
57 __build_send_cfg_msg(struct nfqnl_handle *h, u_int8_t command,
58                      u_int16_t queuenum, u_int16_t pf)
59 {
60         char buf[NLMSG_LENGTH(sizeof(struct nlmsghdr))
61                 +NLMSG_LENGTH(sizeof(struct nfgenmsg))
62                 +NFA_LENGTH(sizeof(struct nfqnl_msg_config_cmd))];
63         struct nfqnl_msg_config_cmd cmd;
64         struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
65
66         nfnl_fill_hdr(&h->nfnlh, nmh, 0, AF_UNSPEC, queuenum,
67                       NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
68
69         cmd.command = command;
70         cmd.pf = htons(pf);
71         nfnl_addattr_l(nmh, sizeof(buf), NFQA_CFG_CMD, &cmd, sizeof(cmd));
72
73         return nfnl_send(&h->nfnlh, nmh);
74 }
75
76 /* bind nf_queue from a specific protocol family */
77 int nfqnl_bind_pf(struct nfqnl_handle *h, u_int16_t pf)
78 {
79         return __build_send_cfg_msg(h, NFQNL_CFG_CMD_PF_BIND, 0, pf);
80 }
81
82 /* unbind nf_queue from a specific protocol family */
83 int nfqnl_unbind_pf(struct nfqnl_handle *h, u_int16_t pf)
84 {
85         return __build_send_cfg_msg(h, NFQNL_CFG_CMD_PF_UNBIND, 0, pf);
86 }
87
88 /* bind this socket to a specific queue number */
89 int nfqnl_create_queue(struct nfqnl_handle *h,
90                        struct nfqnl_q_handle *qh, u_int16_t num)
91 {
92         qh->h = h;
93         qh->id = num;
94
95         return __build_send_cfg_msg(h, NFQNL_CFG_CMD_BIND, num, 0);
96 }
97
98 /* unbind this socket from a specific queue number */
99 int nfqnl_destroy_queue(struct nfqnl_q_handle *qh)
100 {
101         int ret = __build_send_cfg_msg(qh->h, NFQNL_CFG_CMD_UNBIND, qh->id, 0);
102         if (ret == 0)
103                 qh->h = NULL;
104
105         return ret;
106 }
107
108 int nfqnl_set_mode(struct nfqnl_q_handle *qh,
109                    u_int8_t mode, u_int32_t range)
110 {
111         char buf[NLMSG_LENGTH(sizeof(struct nlmsghdr))
112                 +NLMSG_LENGTH(sizeof(struct nfgenmsg))
113                 +NFA_LENGTH(sizeof(struct nfqnl_msg_config_params))];
114         struct nfqnl_msg_config_params params;
115         struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
116
117         nfnl_fill_hdr(&qh->h->nfnlh, nmh, 0, AF_UNSPEC, qh->id,
118                       NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
119
120         params.copy_range = htonl(range);
121         params.copy_mode = mode;
122         nfnl_addattr_l(nmh, sizeof(buf), NFQA_CFG_PARAMS, &params,
123                        sizeof(params));
124
125         return nfnl_send(&qh->h->nfnlh, nmh);
126 }
127
128 static int __set_verdict(struct nfqnl_q_handle *qh, u_int32_t id,
129                          u_int32_t verdict, u_int32_t mark, int set_mark,
130                          u_int32_t data_len, unsigned char *data)
131 {
132         struct nfqnl_msg_verdict_hdr vh;
133         char buf[NLMSG_LENGTH(sizeof(struct nlmsghdr))
134                 +NLMSG_LENGTH(sizeof(struct nfgenmsg))
135                 +NFA_LENGTH(sizeof(mark))
136                 +NFA_LENGTH(sizeof(vh))];
137         struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
138
139         struct iovec iov[3];
140         int nvecs;
141
142         vh.verdict = htonl(verdict);
143         vh.id = htonl(id);
144
145         nfnl_fill_hdr(&qh->h->nfnlh, nmh, 0, AF_UNSPEC, qh->id,
146                       NFQNL_MSG_VERDICT, NLM_F_REQUEST);
147                         
148         /* add verdict header */
149         nfnl_addattr_l(nmh, sizeof(buf), NFQA_VERDICT_HDR, &vh, sizeof(vh));
150
151         if (set_mark)
152                 nfnl_addattr32(nmh, sizeof(buf), NFQA_MARK, mark);
153
154         iov[0].iov_base = nmh;
155         iov[0].iov_len = NLMSG_TAIL(nmh) - (void *)nmh;
156         nvecs = 1;
157
158         if (data_len) {
159                 struct nfattr data_attr;
160
161                 nfnl_build_nfa_iovec(&iov[1], &data_attr, NFQA_PAYLOAD,
162                                      data_len, data);
163                 nvecs += 2;
164         }
165
166         return nfnl_sendiov(&qh->h->nfnlh, iov, nvecs, 0);
167 }
168
169 int nfqnl_set_verdict(struct nfqnl_q_handle *qh, u_int32_t id,
170                       u_int32_t verdict, u_int32_t data_len, 
171                       unsigned char *buf)
172 {
173         return __set_verdict(qh, id, verdict, 0, 0, data_len, buf);
174 }       
175
176 int nfqnl_set_verdict_mark(struct nfqnl_q_handle *qh, u_int32_t id,
177                            u_int32_t verdict, u_int32_t mark,
178                            u_int32_t datalen, unsigned char *buf)
179 {
180         return __set_verdict(qh, id, verdict, mark, 1, datalen, buf);
181 }