summaryrefslogtreecommitdiffstats
path: root/src/nlmsg.c
blob: 6c4a1394d3aee4c6f9a582718f7ffe0215aa307d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*
 * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */
#include <arpa/inet.h>
#include <time.h>
#include <endian.h>
#include <stdlib.h>
#include <string.h>

#include <libmnl/libmnl.h>

#ifndef __aligned_be64
#define __aligned_be64 __be64 __attribute__((aligned(8)))
#define __aligned_le64 __le64 __attribute__((aligned(8)))
#endif

#include <linux/netfilter/nfnetlink_queue.h>

#include <libnetfilter_queue/libnetfilter_queue.h>

#include "internal.h"

/**
 * \defgroup nfq_verd Verdict helpers
 * @{
 */

void nfq_nlmsg_verdict_put(struct nlmsghdr *nlh, int id, int verdict)
{
	struct nfqnl_msg_verdict_hdr vh = {
		.verdict	= htonl(verdict),
		.id		= htonl(id),
	};
	mnl_attr_put(nlh, NFQA_VERDICT_HDR, sizeof(vh), &vh);
}
EXPORT_SYMBOL(nfq_nlmsg_verdict_put);

void nfq_nlmsg_verdict_put_mark(struct nlmsghdr *nlh, uint32_t mark)
{
	mnl_attr_put_u32(nlh, NFQA_MARK, htonl(mark));
}
EXPORT_SYMBOL(nfq_nlmsg_verdict_put_mark);

void
nfq_nlmsg_verdict_put_pkt(struct nlmsghdr *nlh, const void *pkt, uint32_t plen)
{
	mnl_attr_put(nlh, NFQA_PAYLOAD, plen, pkt);
}
EXPORT_SYMBOL(nfq_nlmsg_verdict_put_pkt);

/**
 * @}
 */

/**
 * \defgroup nfq_cfg Config helpers
 * @{
 */

/**
 * nfq_nlmsg_cfg_build_request- build netlink config message
 * \param buf Buffer where netlink message is going to be written.
 * \param cfg Structure that contains the config parameters.
 * \param command nfqueue nfnetlink command.
 *
 * This function returns a pointer to the netlink message. If something goes
 * wrong it returns NULL.
 *
 * Possible commands are:
 *
 * - NFQNL_CFG_CMD_NONE: Do nothing. It can be useful to know if the queue
 *   subsystem is working.
 * - NFQNL_CFG_CMD_BIND: Binds the program to a specific queue.
 * - NFQNL_CFG_CMD_UNBIND: Unbinds the program to a specifiq queue.
 * - NFQNL_CFG_CMD_PF_BIND: Binds to process packets belonging to the given
 *   protocol family (ie. PF_INET, PF_INET6, etc).
 * - NFQNL_CFG_CMD_PF_UNBIND: Unbinds from processing packets belonging to the
 *   given protocol family.
 */
void nfq_nlmsg_cfg_put_cmd(struct nlmsghdr *nlh, uint16_t pf, uint8_t cmd)
{
	struct nfqnl_msg_config_cmd command = {
		.command = cmd,
		.pf = htons(pf),
	};
	mnl_attr_put(nlh, NFQA_CFG_CMD, sizeof(command), &command);
}
EXPORT_SYMBOL(nfq_nlmsg_cfg_put_cmd);

void nfq_nlmsg_cfg_put_params(struct nlmsghdr *nlh, uint8_t mode, int range)
{
	struct nfqnl_msg_config_params params = {
		.copy_range = htonl(range),
		.copy_mode = mode,
	};
	mnl_attr_put(nlh, NFQA_CFG_PARAMS, sizeof(params), &params);
}
EXPORT_SYMBOL(nfq_nlmsg_cfg_put_params);

void nfq_nlmsg_cfg_put_qmaxlen(struct nlmsghdr *nlh, uint32_t queue_maxlen)
{
	mnl_attr_put_u32(nlh, NFQA_CFG_QUEUE_MAXLEN, htonl(queue_maxlen));
}
EXPORT_SYMBOL(nfq_nlmsg_cfg_put_qmaxlen);

/**
 * @}
 */

/**
 * \defgroup nlmsg Netlink message helper functions
 * @{
 */

static int nfq_pkt_parse_attr_cb(const struct nlattr *attr, void *data)
{
	const struct nlattr **tb = data;
	int type = mnl_attr_get_type(attr);

	/* skip unsupported attribute in user-space */
	if (mnl_attr_type_valid(attr, NFQA_MAX) < 0)
		return MNL_CB_OK;

	switch(type) {
	case NFQA_MARK:
	case NFQA_IFINDEX_INDEV:
	case NFQA_IFINDEX_OUTDEV:
	case NFQA_IFINDEX_PHYSINDEV:
	case NFQA_IFINDEX_PHYSOUTDEV:
		if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
			return MNL_CB_ERROR;
		break;
	case NFQA_TIMESTAMP:
		if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC,
		    sizeof(struct nfqnl_msg_packet_timestamp)) < 0) {
			return MNL_CB_ERROR;
		}
		break;
	case NFQA_HWADDR:
		if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC,
		    sizeof(struct nfqnl_msg_packet_hw)) < 0) {
			return MNL_CB_ERROR;
		}
		break;
	case NFQA_PAYLOAD:
		break;
	}
	tb[type] = attr;
	return MNL_CB_OK;
}

/**
 * nfq_pkt_parse - set packet attributes from netlink message
 * \param nlh netlink message that you want to read.
 * \param pkt pointer to the packet to set.
 *
 * This function returns MNL_CB_ERROR if any error occurs, or MNL_CB_OK on
 * success.
 */
int nfq_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr **attr)
{
	return mnl_attr_parse(nlh, sizeof(struct nfgenmsg),
			      nfq_pkt_parse_attr_cb, attr);
}
EXPORT_SYMBOL(nfq_nlmsg_parse);

/**
 * @}
 */