Home | History | Annotate | Download | only in netfilter
      1 /*
      2  * lib/netfilter/queue_msg_obj.c	Netfilter Queue Message Object
      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  */
     11 
     12 #include <netlink-local.h>
     13 #include <netlink/netfilter/nfnl.h>
     14 #include <netlink/netfilter/netfilter.h>
     15 #include <netlink/netfilter/queue_msg.h>
     16 #include <linux/netfilter.h>
     17 
     18 /** @cond SKIP */
     19 #define QUEUE_MSG_ATTR_GROUP		(1UL << 0)
     20 #define QUEUE_MSG_ATTR_FAMILY		(1UL << 1)
     21 #define QUEUE_MSG_ATTR_PACKETID		(1UL << 2)
     22 #define QUEUE_MSG_ATTR_HWPROTO		(1UL << 3)
     23 #define QUEUE_MSG_ATTR_HOOK		(1UL << 4)
     24 #define QUEUE_MSG_ATTR_MARK		(1UL << 5)
     25 #define QUEUE_MSG_ATTR_TIMESTAMP	(1UL << 6)
     26 #define QUEUE_MSG_ATTR_INDEV		(1UL << 7)
     27 #define QUEUE_MSG_ATTR_OUTDEV		(1UL << 8)
     28 #define QUEUE_MSG_ATTR_PHYSINDEV	(1UL << 9)
     29 #define QUEUE_MSG_ATTR_PHYSOUTDEV	(1UL << 10)
     30 #define QUEUE_MSG_ATTR_HWADDR		(1UL << 11)
     31 #define QUEUE_MSG_ATTR_PAYLOAD		(1UL << 12)
     32 #define QUEUE_MSG_ATTR_VERDICT		(1UL << 13)
     33 /** @endcond */
     34 
     35 static void nfnl_queue_msg_free_data(struct nl_object *c)
     36 {
     37 	struct nfnl_queue_msg *msg = (struct nfnl_queue_msg *) c;
     38 
     39 	if (msg == NULL)
     40 		return;
     41 
     42 	free(msg->queue_msg_payload);
     43 }
     44 
     45 static int nfnl_queue_msg_clone(struct nl_object *_dst, struct nl_object *_src)
     46 {
     47 	struct nfnl_queue_msg *dst = (struct nfnl_queue_msg *) _dst;
     48 	struct nfnl_queue_msg *src = (struct nfnl_queue_msg *) _src;
     49 	int err;
     50 
     51 	if (src->queue_msg_payload) {
     52 		err = nfnl_queue_msg_set_payload(dst, src->queue_msg_payload,
     53 						 src->queue_msg_payload_len);
     54 		if (err < 0)
     55 			goto errout;
     56 	}
     57 
     58 	return 0;
     59 errout:
     60 	return err;
     61 }
     62 
     63 static void nfnl_queue_msg_dump(struct nl_object *a, struct nl_dump_params *p)
     64 {
     65 	struct nfnl_queue_msg *msg = (struct nfnl_queue_msg *) a;
     66 	struct nl_cache *link_cache;
     67 	char buf[64];
     68 
     69 	link_cache = nl_cache_mngt_require("route/link");
     70 
     71 	nl_new_line(p);
     72 
     73 	if (msg->ce_mask & QUEUE_MSG_ATTR_GROUP)
     74 		nl_dump(p, "GROUP=%u ", msg->queue_msg_group);
     75 
     76 	if (msg->ce_mask & QUEUE_MSG_ATTR_INDEV) {
     77 		if (link_cache)
     78 			nl_dump(p, "IN=%s ",
     79 				rtnl_link_i2name(link_cache,
     80 						 msg->queue_msg_indev,
     81 						 buf, sizeof(buf)));
     82 		else
     83 			nl_dump(p, "IN=%d ", msg->queue_msg_indev);
     84 	}
     85 
     86 	if (msg->ce_mask & QUEUE_MSG_ATTR_PHYSINDEV) {
     87 		if (link_cache)
     88 			nl_dump(p, "PHYSIN=%s ",
     89 				rtnl_link_i2name(link_cache,
     90 						 msg->queue_msg_physindev,
     91 						 buf, sizeof(buf)));
     92 		else
     93 			nl_dump(p, "IN=%d ", msg->queue_msg_physindev);
     94 	}
     95 
     96 	if (msg->ce_mask & QUEUE_MSG_ATTR_OUTDEV) {
     97 		if (link_cache)
     98 			nl_dump(p, "OUT=%s ",
     99 				rtnl_link_i2name(link_cache,
    100 						 msg->queue_msg_outdev,
    101 						 buf, sizeof(buf)));
    102 		else
    103 			nl_dump(p, "OUT=%d ", msg->queue_msg_outdev);
    104 	}
    105 
    106 	if (msg->ce_mask & QUEUE_MSG_ATTR_PHYSOUTDEV) {
    107 		if (link_cache)
    108 			nl_dump(p, "PHYSOUT=%s ",
    109 				rtnl_link_i2name(link_cache,
    110 						 msg->queue_msg_physoutdev,
    111 						 buf, sizeof(buf)));
    112 		else
    113 			nl_dump(p, "PHYSOUT=%d ", msg->queue_msg_physoutdev);
    114 	}
    115 
    116 	if (msg->ce_mask & QUEUE_MSG_ATTR_HWADDR) {
    117 		int i;
    118 
    119 		nl_dump(p, "MAC");
    120 		for (i = 0; i < msg->queue_msg_hwaddr_len; i++)
    121 			nl_dump(p, "%c%02x", i?':':'=',
    122 				msg->queue_msg_hwaddr[i]);
    123 		nl_dump(p, " ");
    124 	}
    125 
    126 	if (msg->ce_mask & QUEUE_MSG_ATTR_FAMILY)
    127 		nl_dump(p, "FAMILY=%s ",
    128 			nl_af2str(msg->queue_msg_family, buf, sizeof(buf)));
    129 
    130 	if (msg->ce_mask & QUEUE_MSG_ATTR_HWPROTO)
    131 		nl_dump(p, "HWPROTO=%s ",
    132 			nl_ether_proto2str(ntohs(msg->queue_msg_hwproto),
    133 					   buf, sizeof(buf)));
    134 
    135 	if (msg->ce_mask & QUEUE_MSG_ATTR_HOOK)
    136 		nl_dump(p, "HOOK=%s ",
    137 			nfnl_inet_hook2str(msg->queue_msg_hook,
    138 					   buf, sizeof(buf)));
    139 
    140 	if (msg->ce_mask & QUEUE_MSG_ATTR_MARK)
    141 		nl_dump(p, "MARK=%d ", msg->queue_msg_mark);
    142 
    143 	if (msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD)
    144 		nl_dump(p, "PAYLOADLEN=%d ", msg->queue_msg_payload_len);
    145 
    146 	if (msg->ce_mask & QUEUE_MSG_ATTR_PACKETID)
    147 		nl_dump(p, "PACKETID=%u ", msg->queue_msg_packetid);
    148 
    149 	if (msg->ce_mask & QUEUE_MSG_ATTR_VERDICT)
    150 		nl_dump(p, "VERDICT=%s ",
    151 			nfnl_verdict2str(msg->queue_msg_verdict,
    152 					 buf, sizeof(buf)));
    153 
    154 	nl_dump(p, "\n");
    155 }
    156 
    157 /**
    158  * @name Allocation/Freeing
    159  * @{
    160  */
    161 
    162 struct nfnl_queue_msg *nfnl_queue_msg_alloc(void)
    163 {
    164 	return (struct nfnl_queue_msg *) nl_object_alloc(&queue_msg_obj_ops);
    165 }
    166 
    167 void nfnl_queue_msg_get(struct nfnl_queue_msg *msg)
    168 {
    169 	nl_object_get((struct nl_object *) msg);
    170 }
    171 
    172 void nfnl_queue_msg_put(struct nfnl_queue_msg *msg)
    173 {
    174 	nl_object_put((struct nl_object *) msg);
    175 }
    176 
    177 /** @} */
    178 
    179 /**
    180  * @name Attributes
    181  * @{
    182  */
    183 
    184 void nfnl_queue_msg_set_group(struct nfnl_queue_msg *msg, uint16_t group)
    185 {
    186 	msg->queue_msg_group = group;
    187 	msg->ce_mask |= QUEUE_MSG_ATTR_GROUP;
    188 }
    189 
    190 int nfnl_queue_msg_test_group(const struct nfnl_queue_msg *msg)
    191 {
    192 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_GROUP);
    193 }
    194 
    195 uint16_t nfnl_queue_msg_get_group(const struct nfnl_queue_msg *msg)
    196 {
    197 	return msg->queue_msg_group;
    198 }
    199 
    200 /**
    201 * Set the protocol family
    202 * @arg msg         NF queue message
    203 * @arg family      AF_XXX  address family  example: AF_INET, AF_UNIX, etc
    204 */
    205 void nfnl_queue_msg_set_family(struct nfnl_queue_msg *msg, uint8_t family)
    206 {
    207 	msg->queue_msg_family = family;
    208 	msg->ce_mask |= QUEUE_MSG_ATTR_FAMILY;
    209 }
    210 
    211 int nfnl_queue_msg_test_family(const struct nfnl_queue_msg *msg)
    212 {
    213 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_FAMILY);
    214 }
    215 
    216 uint8_t nfnl_queue_msg_get_family(const struct nfnl_queue_msg *msg)
    217 {
    218 	if (msg->ce_mask & QUEUE_MSG_ATTR_FAMILY)
    219 		return msg->queue_msg_family;
    220 	else
    221 		return AF_UNSPEC;
    222 }
    223 
    224 void nfnl_queue_msg_set_packetid(struct nfnl_queue_msg *msg, uint32_t packetid)
    225 {
    226 	msg->queue_msg_packetid = packetid;
    227 	msg->ce_mask |= QUEUE_MSG_ATTR_PACKETID;
    228 }
    229 
    230 int nfnl_queue_msg_test_packetid(const struct nfnl_queue_msg *msg)
    231 {
    232 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_PACKETID);
    233 }
    234 
    235 uint32_t nfnl_queue_msg_get_packetid(const struct nfnl_queue_msg *msg)
    236 {
    237 	return msg->queue_msg_packetid;
    238 }
    239 
    240 void nfnl_queue_msg_set_hwproto(struct nfnl_queue_msg *msg, uint16_t hwproto)
    241 {
    242 	msg->queue_msg_hwproto = hwproto;
    243 	msg->ce_mask |= QUEUE_MSG_ATTR_HWPROTO;
    244 }
    245 
    246 int nfnl_queue_msg_test_hwproto(const struct nfnl_queue_msg *msg)
    247 {
    248 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_HWPROTO);
    249 }
    250 
    251 uint16_t nfnl_queue_msg_get_hwproto(const struct nfnl_queue_msg *msg)
    252 {
    253 	return msg->queue_msg_hwproto;
    254 }
    255 
    256 void nfnl_queue_msg_set_hook(struct nfnl_queue_msg *msg, uint8_t hook)
    257 {
    258 	msg->queue_msg_hook = hook;
    259 	msg->ce_mask |= QUEUE_MSG_ATTR_HOOK;
    260 }
    261 
    262 int nfnl_queue_msg_test_hook(const struct nfnl_queue_msg *msg)
    263 {
    264 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_HOOK);
    265 }
    266 
    267 uint8_t nfnl_queue_msg_get_hook(const struct nfnl_queue_msg *msg)
    268 {
    269 	return msg->queue_msg_hook;
    270 }
    271 
    272 void nfnl_queue_msg_set_mark(struct nfnl_queue_msg *msg, uint32_t mark)
    273 {
    274 	msg->queue_msg_mark = mark;
    275 	msg->ce_mask |= QUEUE_MSG_ATTR_MARK;
    276 }
    277 
    278 int nfnl_queue_msg_test_mark(const struct nfnl_queue_msg *msg)
    279 {
    280 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_MARK);
    281 }
    282 
    283 uint32_t nfnl_queue_msg_get_mark(const struct nfnl_queue_msg *msg)
    284 {
    285 	return msg->queue_msg_mark;
    286 }
    287 
    288 void nfnl_queue_msg_set_timestamp(struct nfnl_queue_msg *msg,
    289 				  struct timeval *tv)
    290 {
    291 	msg->queue_msg_timestamp.tv_sec = tv->tv_sec;
    292 	msg->queue_msg_timestamp.tv_usec = tv->tv_usec;
    293 	msg->ce_mask |= QUEUE_MSG_ATTR_TIMESTAMP;
    294 }
    295 
    296 int nfnl_queue_msg_test_timestamp(const struct nfnl_queue_msg *msg)
    297 {
    298 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_TIMESTAMP);
    299 }
    300 
    301 const struct timeval *nfnl_queue_msg_get_timestamp(const struct nfnl_queue_msg *msg)
    302 {
    303 	if (!(msg->ce_mask & QUEUE_MSG_ATTR_TIMESTAMP))
    304 		return NULL;
    305 	return &msg->queue_msg_timestamp;
    306 }
    307 
    308 void nfnl_queue_msg_set_indev(struct nfnl_queue_msg *msg, uint32_t indev)
    309 {
    310 	msg->queue_msg_indev = indev;
    311 	msg->ce_mask |= QUEUE_MSG_ATTR_INDEV;
    312 }
    313 
    314 int nfnl_queue_msg_test_indev(const struct nfnl_queue_msg *msg)
    315 {
    316 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_INDEV);
    317 }
    318 
    319 uint32_t nfnl_queue_msg_get_indev(const struct nfnl_queue_msg *msg)
    320 {
    321 	return msg->queue_msg_indev;
    322 }
    323 
    324 void nfnl_queue_msg_set_outdev(struct nfnl_queue_msg *msg, uint32_t outdev)
    325 {
    326 	msg->queue_msg_outdev = outdev;
    327 	msg->ce_mask |= QUEUE_MSG_ATTR_OUTDEV;
    328 }
    329 
    330 int nfnl_queue_msg_test_outdev(const struct nfnl_queue_msg *msg)
    331 {
    332 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_OUTDEV);
    333 }
    334 
    335 uint32_t nfnl_queue_msg_get_outdev(const struct nfnl_queue_msg *msg)
    336 {
    337 	return msg->queue_msg_outdev;
    338 }
    339 
    340 void nfnl_queue_msg_set_physindev(struct nfnl_queue_msg *msg,
    341 				  uint32_t physindev)
    342 {
    343 	msg->queue_msg_physindev = physindev;
    344 	msg->ce_mask |= QUEUE_MSG_ATTR_PHYSINDEV;
    345 }
    346 
    347 int nfnl_queue_msg_test_physindev(const struct nfnl_queue_msg *msg)
    348 {
    349 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_PHYSINDEV);
    350 }
    351 
    352 uint32_t nfnl_queue_msg_get_physindev(const struct nfnl_queue_msg *msg)
    353 {
    354 	return msg->queue_msg_physindev;
    355 }
    356 
    357 void nfnl_queue_msg_set_physoutdev(struct nfnl_queue_msg *msg,
    358 				   uint32_t physoutdev)
    359 {
    360 	msg->queue_msg_physoutdev = physoutdev;
    361 	msg->ce_mask |= QUEUE_MSG_ATTR_PHYSOUTDEV;
    362 }
    363 
    364 int nfnl_queue_msg_test_physoutdev(const struct nfnl_queue_msg *msg)
    365 {
    366 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_PHYSOUTDEV);
    367 }
    368 
    369 uint32_t nfnl_queue_msg_get_physoutdev(const struct nfnl_queue_msg *msg)
    370 {
    371 	return msg->queue_msg_physoutdev;
    372 }
    373 
    374 void nfnl_queue_msg_set_hwaddr(struct nfnl_queue_msg *msg, uint8_t *hwaddr,
    375 			       int len)
    376 {
    377 	if (len > sizeof(msg->queue_msg_hwaddr))
    378 		len = sizeof(msg->queue_msg_hwaddr);
    379 
    380 	msg->queue_msg_hwaddr_len = len;
    381 	memcpy(msg->queue_msg_hwaddr, hwaddr, len);
    382 	msg->ce_mask |= QUEUE_MSG_ATTR_HWADDR;
    383 }
    384 
    385 int nfnl_queue_msg_test_hwaddr(const struct nfnl_queue_msg *msg)
    386 {
    387 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_HWADDR);
    388 }
    389 
    390 const uint8_t *nfnl_queue_msg_get_hwaddr(const struct nfnl_queue_msg *msg,
    391 					 int *len)
    392 {
    393 	if (!(msg->ce_mask & QUEUE_MSG_ATTR_HWADDR)) {
    394 		*len = 0;
    395 		return NULL;
    396 	}
    397 
    398 	*len = msg->queue_msg_hwaddr_len;
    399 	return msg->queue_msg_hwaddr;
    400 }
    401 
    402 int nfnl_queue_msg_set_payload(struct nfnl_queue_msg *msg, uint8_t *payload,
    403 			       int len)
    404 {
    405 	free(msg->queue_msg_payload);
    406 	msg->queue_msg_payload = malloc(len);
    407 	if (!msg->queue_msg_payload)
    408 		return -NLE_NOMEM;
    409 
    410 	memcpy(msg->queue_msg_payload, payload, len);
    411 	msg->queue_msg_payload_len = len;
    412 	msg->ce_mask |= QUEUE_MSG_ATTR_PAYLOAD;
    413 	return 0;
    414 }
    415 
    416 int nfnl_queue_msg_test_payload(const struct nfnl_queue_msg *msg)
    417 {
    418 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD);
    419 }
    420 
    421 const void *nfnl_queue_msg_get_payload(const struct nfnl_queue_msg *msg, int *len)
    422 {
    423 	if (!(msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD)) {
    424 		*len = 0;
    425 		return NULL;
    426 	}
    427 
    428 	*len = msg->queue_msg_payload_len;
    429 	return msg->queue_msg_payload;
    430 }
    431 
    432 /**
    433 * Return the number of items matching a filter in the cache
    434 * @arg msg        queue msg
    435 * @arg verdict    NF_DROP, NF_ACCEPT, NF_REPEAT, etc
    436 */
    437 void nfnl_queue_msg_set_verdict(struct nfnl_queue_msg *msg,
    438 				unsigned int verdict)
    439 {
    440 	msg->queue_msg_verdict = verdict;
    441 	msg->ce_mask |= QUEUE_MSG_ATTR_VERDICT;
    442 }
    443 
    444 int nfnl_queue_msg_test_verdict(const struct nfnl_queue_msg *msg)
    445 {
    446 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_VERDICT);
    447 }
    448 
    449 unsigned int nfnl_queue_msg_get_verdict(const struct nfnl_queue_msg *msg)
    450 {
    451 	return msg->queue_msg_verdict;
    452 }
    453 
    454 static struct trans_tbl nfnl_queue_msg_attrs[] = {
    455 	__ADD(QUEUE_MSG_ATTR_GROUP,		group)
    456 	__ADD(QUEUE_MSG_ATTR_FAMILY,		family)
    457 	__ADD(QUEUE_MSG_ATTR_PACKETID,		packetid)
    458 	__ADD(QUEUE_MSG_ATTR_HWPROTO,		hwproto)
    459 	__ADD(QUEUE_MSG_ATTR_HOOK,		hook)
    460 	__ADD(QUEUE_MSG_ATTR_MARK,		mark)
    461 	__ADD(QUEUE_MSG_ATTR_TIMESTAMP,		timestamp)
    462 	__ADD(QUEUE_MSG_ATTR_INDEV,		indev)
    463 	__ADD(QUEUE_MSG_ATTR_OUTDEV,		outdev)
    464 	__ADD(QUEUE_MSG_ATTR_PHYSINDEV,		physindev)
    465 	__ADD(QUEUE_MSG_ATTR_PHYSOUTDEV,	physoutdev)
    466 	__ADD(QUEUE_MSG_ATTR_HWADDR,		hwaddr)
    467 	__ADD(QUEUE_MSG_ATTR_PAYLOAD,		payload)
    468 	__ADD(QUEUE_MSG_ATTR_VERDICT,		verdict)
    469 };
    470 
    471 static char *nfnl_queue_msg_attrs2str(int attrs, char *buf, size_t len)
    472 {
    473 	return __flags2str(attrs, buf, len, nfnl_queue_msg_attrs,
    474 			   ARRAY_SIZE(nfnl_queue_msg_attrs));
    475 }
    476 
    477 /** @} */
    478 
    479 struct nl_object_ops queue_msg_obj_ops = {
    480 	.oo_name		= "netfilter/queuemsg",
    481 	.oo_size		= sizeof(struct nfnl_queue_msg),
    482 	.oo_free_data		= nfnl_queue_msg_free_data,
    483 	.oo_clone		= nfnl_queue_msg_clone,
    484 	.oo_dump = {
    485 	    [NL_DUMP_LINE]	= nfnl_queue_msg_dump,
    486 	    [NL_DUMP_DETAILS]	= nfnl_queue_msg_dump,
    487 	    [NL_DUMP_STATS]	= nfnl_queue_msg_dump,
    488 	},
    489 	.oo_attrs2str		= nfnl_queue_msg_attrs2str,
    490 };
    491 
    492 /** @} */
    493