Home | History | Annotate | Download | only in netfilter
      1 /*
      2  * lib/netfilter/queue_msg.c	Netfilter Queue Messages
      3  *
      4  *	This library is free software; you can redistribute it and/or
      5  *	modify it under the terms of the GNU Lesser General Public
      6  *	License as published by the Free Software Foundation version 2.1
      7  *	of the License.
      8  *
      9  * Copyright (c) 2007, 2008 Patrick McHardy <kaber (at) trash.net>
     10  * Copyright (c) 2010       Karl Hiramoto <karl (at) hiramoto.org>
     11  */
     12 
     13 /**
     14  * @ingroup nfnl
     15  * @defgroup queue Queue
     16  * @brief
     17  * @{
     18  */
     19 
     20 #include <sys/types.h>
     21 #include <linux/netfilter/nfnetlink_queue.h>
     22 
     23 #include <netlink-private/netlink.h>
     24 #include <netlink/attr.h>
     25 #include <netlink/netfilter/nfnl.h>
     26 #include <netlink/netfilter/queue_msg.h>
     27 #include <byteswap.h>
     28 
     29 static struct nl_cache_ops nfnl_queue_msg_ops;
     30 
     31 #if __BYTE_ORDER == __BIG_ENDIAN
     32 static uint64_t ntohll(uint64_t x)
     33 {
     34 	return x;
     35 }
     36 #elif __BYTE_ORDER == __LITTLE_ENDIAN
     37 static uint64_t ntohll(uint64_t x)
     38 {
     39 	return bswap_64(x);
     40 }
     41 #endif
     42 
     43 static struct nla_policy queue_policy[NFQA_MAX+1] = {
     44 	[NFQA_PACKET_HDR]		= {
     45 		.minlen	= sizeof(struct nfqnl_msg_packet_hdr),
     46 	},
     47 	[NFQA_VERDICT_HDR]		= {
     48 		.minlen	= sizeof(struct nfqnl_msg_verdict_hdr),
     49 	},
     50 	[NFQA_MARK]			= { .type = NLA_U32 },
     51 	[NFQA_TIMESTAMP]		= {
     52 		.minlen = sizeof(struct nfqnl_msg_packet_timestamp),
     53 	},
     54 	[NFQA_IFINDEX_INDEV]		= { .type = NLA_U32 },
     55 	[NFQA_IFINDEX_OUTDEV]		= { .type = NLA_U32 },
     56 	[NFQA_IFINDEX_PHYSINDEV]	= { .type = NLA_U32 },
     57 	[NFQA_IFINDEX_PHYSOUTDEV]	= { .type = NLA_U32 },
     58 	[NFQA_HWADDR]			= {
     59 		.minlen	= sizeof(struct nfqnl_msg_packet_hw),
     60 	},
     61 };
     62 
     63 int nfnlmsg_queue_msg_parse(struct nlmsghdr *nlh,
     64 			    struct nfnl_queue_msg **result)
     65 {
     66 	struct nfnl_queue_msg *msg;
     67 	struct nlattr *tb[NFQA_MAX+1];
     68 	struct nlattr *attr;
     69 	int err;
     70 
     71 	msg = nfnl_queue_msg_alloc();
     72 	if (!msg)
     73 		return -NLE_NOMEM;
     74 
     75 	msg->ce_msgtype = nlh->nlmsg_type;
     76 
     77 	err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, NFQA_MAX,
     78 			  queue_policy);
     79 	if (err < 0)
     80 		goto errout;
     81 
     82 	nfnl_queue_msg_set_group(msg, nfnlmsg_res_id(nlh));
     83 	nfnl_queue_msg_set_family(msg, nfnlmsg_family(nlh));
     84 
     85 	attr = tb[NFQA_PACKET_HDR];
     86 	if (attr) {
     87 		struct nfqnl_msg_packet_hdr *hdr = nla_data(attr);
     88 
     89 		nfnl_queue_msg_set_packetid(msg, ntohl(hdr->packet_id));
     90 		if (hdr->hw_protocol)
     91 			nfnl_queue_msg_set_hwproto(msg, hdr->hw_protocol);
     92 		nfnl_queue_msg_set_hook(msg, hdr->hook);
     93 	}
     94 
     95 	attr = tb[NFQA_MARK];
     96 	if (attr)
     97 		nfnl_queue_msg_set_mark(msg, ntohl(nla_get_u32(attr)));
     98 
     99 	attr = tb[NFQA_TIMESTAMP];
    100 	if (attr) {
    101 		struct nfqnl_msg_packet_timestamp *timestamp = nla_data(attr);
    102 		struct timeval tv;
    103 
    104 		tv.tv_sec = ntohll(timestamp->sec);
    105 		tv.tv_usec = ntohll(timestamp->usec);
    106 		nfnl_queue_msg_set_timestamp(msg, &tv);
    107 	}
    108 
    109 	attr = tb[NFQA_IFINDEX_INDEV];
    110 	if (attr)
    111 		nfnl_queue_msg_set_indev(msg, ntohl(nla_get_u32(attr)));
    112 
    113 	attr = tb[NFQA_IFINDEX_OUTDEV];
    114 	if (attr)
    115 		nfnl_queue_msg_set_outdev(msg, ntohl(nla_get_u32(attr)));
    116 
    117 	attr = tb[NFQA_IFINDEX_PHYSINDEV];
    118 	if (attr)
    119 		nfnl_queue_msg_set_physindev(msg, ntohl(nla_get_u32(attr)));
    120 
    121 	attr = tb[NFQA_IFINDEX_PHYSOUTDEV];
    122 	if (attr)
    123 		nfnl_queue_msg_set_physoutdev(msg, ntohl(nla_get_u32(attr)));
    124 
    125 	attr = tb[NFQA_HWADDR];
    126 	if (attr) {
    127 		struct nfqnl_msg_packet_hw *hw = nla_data(attr);
    128 
    129 		nfnl_queue_msg_set_hwaddr(msg, hw->hw_addr,
    130 					  ntohs(hw->hw_addrlen));
    131 	}
    132 
    133 	attr = tb[NFQA_PAYLOAD];
    134 	if (attr) {
    135 		err = nfnl_queue_msg_set_payload(msg, nla_data(attr),
    136 						 nla_len(attr));
    137 		if (err < 0)
    138 			goto errout;
    139 	}
    140 
    141 	*result = msg;
    142 	return 0;
    143 
    144 errout:
    145 	nfnl_queue_msg_put(msg);
    146 	return err;
    147 }
    148 
    149 static int queue_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
    150 			    struct nlmsghdr *nlh, struct nl_parser_param *pp)
    151 {
    152 	struct nfnl_queue_msg *msg;
    153 	int err;
    154 
    155 	if ((err = nfnlmsg_queue_msg_parse(nlh, &msg)) < 0)
    156 		return err;
    157 
    158 	err = pp->pp_cb((struct nl_object *) msg, pp);
    159 	nfnl_queue_msg_put(msg);
    160 	return err;
    161 }
    162 
    163 /** @} */
    164 
    165 static struct nl_msg *
    166 __nfnl_queue_msg_build_verdict(const struct nfnl_queue_msg *msg,
    167 							   uint8_t type)
    168 {
    169 	struct nl_msg *nlmsg;
    170 	struct nfqnl_msg_verdict_hdr verdict;
    171 
    172 	nlmsg = nfnlmsg_alloc_simple(NFNL_SUBSYS_QUEUE, type, 0,
    173 				     nfnl_queue_msg_get_family(msg),
    174 				     nfnl_queue_msg_get_group(msg));
    175 	if (nlmsg == NULL)
    176 		return NULL;
    177 
    178 	verdict.id = htonl(nfnl_queue_msg_get_packetid(msg));
    179 	verdict.verdict = htonl(nfnl_queue_msg_get_verdict(msg));
    180 	if (nla_put(nlmsg, NFQA_VERDICT_HDR, sizeof(verdict), &verdict) < 0)
    181 		goto nla_put_failure;
    182 
    183 	if (nfnl_queue_msg_test_mark(msg) &&
    184 	    nla_put_u32(nlmsg, NFQA_MARK,
    185 			ntohl(nfnl_queue_msg_get_mark(msg))) < 0)
    186 		goto nla_put_failure;
    187 
    188 	return nlmsg;
    189 
    190 nla_put_failure:
    191 	nlmsg_free(nlmsg);
    192 	return NULL;
    193 }
    194 
    195 struct nl_msg *
    196 nfnl_queue_msg_build_verdict(const struct nfnl_queue_msg *msg)
    197 {
    198 	return __nfnl_queue_msg_build_verdict(msg, NFQNL_MSG_VERDICT);
    199 }
    200 
    201 struct nl_msg *
    202 nfnl_queue_msg_build_verdict_batch(const struct nfnl_queue_msg *msg)
    203 {
    204 	return __nfnl_queue_msg_build_verdict(msg, NFQNL_MSG_VERDICT_BATCH);
    205 }
    206 
    207 /**
    208 * Send a message verdict/mark
    209 * @arg nlh            netlink messsage header
    210 * @arg msg            queue msg
    211 * @return 0 on OK or error code
    212 */
    213 int nfnl_queue_msg_send_verdict(struct nl_sock *nlh,
    214 				const struct nfnl_queue_msg *msg)
    215 {
    216 	struct nl_msg *nlmsg;
    217 	int err;
    218 
    219 	nlmsg = nfnl_queue_msg_build_verdict(msg);
    220 	if (nlmsg == NULL)
    221 		return -NLE_NOMEM;
    222 
    223 	err = nl_send_auto_complete(nlh, nlmsg);
    224 	nlmsg_free(nlmsg);
    225 	if (err < 0)
    226 		return err;
    227 	return wait_for_ack(nlh);
    228 }
    229 
    230 /**
    231 * Send a message batched verdict/mark
    232 * @arg nlh            netlink messsage header
    233 * @arg msg            queue msg
    234 * @return 0 on OK or error code
    235 */
    236 int nfnl_queue_msg_send_verdict_batch(struct nl_sock *nlh,
    237 									  const struct nfnl_queue_msg *msg)
    238 {
    239 	struct nl_msg *nlmsg;
    240 	int err;
    241 
    242 	nlmsg = nfnl_queue_msg_build_verdict_batch(msg);
    243 	if (nlmsg == NULL)
    244 		return -NLE_NOMEM;
    245 
    246 	err = nl_send_auto_complete(nlh, nlmsg);
    247 	nlmsg_free(nlmsg);
    248 	if (err < 0)
    249 		return err;
    250 	return wait_for_ack(nlh);
    251 }
    252 
    253 /**
    254 * Send a message verdict including the payload
    255 * @arg nlh            netlink messsage header
    256 * @arg msg            queue msg
    257 * @arg payload_data   packet payload data
    258 * @arg payload_len    payload length
    259 * @return 0 on OK or error code
    260 */
    261 int nfnl_queue_msg_send_verdict_payload(struct nl_sock *nlh,
    262 				const struct nfnl_queue_msg *msg,
    263 				const void *payload_data, unsigned payload_len)
    264 {
    265 	struct nl_msg *nlmsg;
    266 	int err;
    267 	struct iovec iov[3];
    268 	struct nlattr nla;
    269 
    270 	nlmsg = nfnl_queue_msg_build_verdict(msg);
    271 	if (nlmsg == NULL)
    272 		return -NLE_NOMEM;
    273 
    274 	memset(iov, 0, sizeof(iov));
    275 
    276 	iov[0].iov_base = (void *) nlmsg_hdr(nlmsg);
    277 	iov[0].iov_len = nlmsg_hdr(nlmsg)->nlmsg_len;
    278 
    279 	nla.nla_type = NFQA_PAYLOAD;
    280 	nla.nla_len = payload_len + sizeof(nla);
    281 	nlmsg_hdr(nlmsg)->nlmsg_len += nla.nla_len;
    282 
    283 	iov[1].iov_base = (void *) &nla;
    284 	iov[1].iov_len = sizeof(nla);
    285 
    286 	iov[2].iov_base = (void *) payload_data;
    287 	iov[2].iov_len = NLA_ALIGN(payload_len);
    288 
    289 	nl_complete_msg(nlh, nlmsg);
    290 	err = nl_send_iovec(nlh, nlmsg, iov, 3);
    291 
    292 	nlmsg_free(nlmsg);
    293 	if (err < 0)
    294 		return err;
    295 	return wait_for_ack(nlh);
    296 }
    297 
    298 #define NFNLMSG_QUEUE_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_QUEUE, (type))
    299 static struct nl_cache_ops nfnl_queue_msg_ops = {
    300 	.co_name		= "netfilter/queue_msg",
    301 	.co_hdrsize		= NFNL_HDRLEN,
    302 	.co_msgtypes		= {
    303 		{ NFNLMSG_QUEUE_TYPE(NFQNL_MSG_PACKET), NL_ACT_NEW, "new" },
    304 		END_OF_MSGTYPES_LIST,
    305 	},
    306 	.co_protocol		= NETLINK_NETFILTER,
    307 	.co_msg_parser		= queue_msg_parser,
    308 	.co_obj_ops		= &queue_msg_obj_ops,
    309 };
    310 
    311 static void __init nfnl_msg_queue_init(void)
    312 {
    313 	nl_cache_mngt_register(&nfnl_queue_msg_ops);
    314 }
    315 
    316 static void __exit nfnl_queue_msg_exit(void)
    317 {
    318 	nl_cache_mngt_unregister(&nfnl_queue_msg_ops);
    319 }
    320 
    321 /** @} */
    322