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-private/netlink.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_safe("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 	if (link_cache)
    157 		nl_cache_put(link_cache);
    158 }
    159 
    160 /**
    161  * @name Allocation/Freeing
    162  * @{
    163  */
    164 
    165 struct nfnl_queue_msg *nfnl_queue_msg_alloc(void)
    166 {
    167 	return (struct nfnl_queue_msg *) nl_object_alloc(&queue_msg_obj_ops);
    168 }
    169 
    170 void nfnl_queue_msg_get(struct nfnl_queue_msg *msg)
    171 {
    172 	nl_object_get((struct nl_object *) msg);
    173 }
    174 
    175 void nfnl_queue_msg_put(struct nfnl_queue_msg *msg)
    176 {
    177 	nl_object_put((struct nl_object *) msg);
    178 }
    179 
    180 /** @} */
    181 
    182 /**
    183  * @name Attributes
    184  * @{
    185  */
    186 
    187 void nfnl_queue_msg_set_group(struct nfnl_queue_msg *msg, uint16_t group)
    188 {
    189 	msg->queue_msg_group = group;
    190 	msg->ce_mask |= QUEUE_MSG_ATTR_GROUP;
    191 }
    192 
    193 int nfnl_queue_msg_test_group(const struct nfnl_queue_msg *msg)
    194 {
    195 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_GROUP);
    196 }
    197 
    198 uint16_t nfnl_queue_msg_get_group(const struct nfnl_queue_msg *msg)
    199 {
    200 	return msg->queue_msg_group;
    201 }
    202 
    203 /**
    204 * Set the protocol family
    205 * @arg msg         NF queue message
    206 * @arg family      AF_XXX  address family  example: AF_INET, AF_UNIX, etc
    207 */
    208 void nfnl_queue_msg_set_family(struct nfnl_queue_msg *msg, uint8_t family)
    209 {
    210 	msg->queue_msg_family = family;
    211 	msg->ce_mask |= QUEUE_MSG_ATTR_FAMILY;
    212 }
    213 
    214 int nfnl_queue_msg_test_family(const struct nfnl_queue_msg *msg)
    215 {
    216 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_FAMILY);
    217 }
    218 
    219 uint8_t nfnl_queue_msg_get_family(const struct nfnl_queue_msg *msg)
    220 {
    221 	if (msg->ce_mask & QUEUE_MSG_ATTR_FAMILY)
    222 		return msg->queue_msg_family;
    223 	else
    224 		return AF_UNSPEC;
    225 }
    226 
    227 void nfnl_queue_msg_set_packetid(struct nfnl_queue_msg *msg, uint32_t packetid)
    228 {
    229 	msg->queue_msg_packetid = packetid;
    230 	msg->ce_mask |= QUEUE_MSG_ATTR_PACKETID;
    231 }
    232 
    233 int nfnl_queue_msg_test_packetid(const struct nfnl_queue_msg *msg)
    234 {
    235 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_PACKETID);
    236 }
    237 
    238 uint32_t nfnl_queue_msg_get_packetid(const struct nfnl_queue_msg *msg)
    239 {
    240 	return msg->queue_msg_packetid;
    241 }
    242 
    243 void nfnl_queue_msg_set_hwproto(struct nfnl_queue_msg *msg, uint16_t hwproto)
    244 {
    245 	msg->queue_msg_hwproto = hwproto;
    246 	msg->ce_mask |= QUEUE_MSG_ATTR_HWPROTO;
    247 }
    248 
    249 int nfnl_queue_msg_test_hwproto(const struct nfnl_queue_msg *msg)
    250 {
    251 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_HWPROTO);
    252 }
    253 
    254 uint16_t nfnl_queue_msg_get_hwproto(const struct nfnl_queue_msg *msg)
    255 {
    256 	return msg->queue_msg_hwproto;
    257 }
    258 
    259 void nfnl_queue_msg_set_hook(struct nfnl_queue_msg *msg, uint8_t hook)
    260 {
    261 	msg->queue_msg_hook = hook;
    262 	msg->ce_mask |= QUEUE_MSG_ATTR_HOOK;
    263 }
    264 
    265 int nfnl_queue_msg_test_hook(const struct nfnl_queue_msg *msg)
    266 {
    267 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_HOOK);
    268 }
    269 
    270 uint8_t nfnl_queue_msg_get_hook(const struct nfnl_queue_msg *msg)
    271 {
    272 	return msg->queue_msg_hook;
    273 }
    274 
    275 void nfnl_queue_msg_set_mark(struct nfnl_queue_msg *msg, uint32_t mark)
    276 {
    277 	msg->queue_msg_mark = mark;
    278 	msg->ce_mask |= QUEUE_MSG_ATTR_MARK;
    279 }
    280 
    281 int nfnl_queue_msg_test_mark(const struct nfnl_queue_msg *msg)
    282 {
    283 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_MARK);
    284 }
    285 
    286 uint32_t nfnl_queue_msg_get_mark(const struct nfnl_queue_msg *msg)
    287 {
    288 	return msg->queue_msg_mark;
    289 }
    290 
    291 void nfnl_queue_msg_set_timestamp(struct nfnl_queue_msg *msg,
    292 				  struct timeval *tv)
    293 {
    294 	msg->queue_msg_timestamp.tv_sec = tv->tv_sec;
    295 	msg->queue_msg_timestamp.tv_usec = tv->tv_usec;
    296 	msg->ce_mask |= QUEUE_MSG_ATTR_TIMESTAMP;
    297 }
    298 
    299 int nfnl_queue_msg_test_timestamp(const struct nfnl_queue_msg *msg)
    300 {
    301 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_TIMESTAMP);
    302 }
    303 
    304 const struct timeval *nfnl_queue_msg_get_timestamp(const struct nfnl_queue_msg *msg)
    305 {
    306 	if (!(msg->ce_mask & QUEUE_MSG_ATTR_TIMESTAMP))
    307 		return NULL;
    308 	return &msg->queue_msg_timestamp;
    309 }
    310 
    311 void nfnl_queue_msg_set_indev(struct nfnl_queue_msg *msg, uint32_t indev)
    312 {
    313 	msg->queue_msg_indev = indev;
    314 	msg->ce_mask |= QUEUE_MSG_ATTR_INDEV;
    315 }
    316 
    317 int nfnl_queue_msg_test_indev(const struct nfnl_queue_msg *msg)
    318 {
    319 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_INDEV);
    320 }
    321 
    322 uint32_t nfnl_queue_msg_get_indev(const struct nfnl_queue_msg *msg)
    323 {
    324 	return msg->queue_msg_indev;
    325 }
    326 
    327 void nfnl_queue_msg_set_outdev(struct nfnl_queue_msg *msg, uint32_t outdev)
    328 {
    329 	msg->queue_msg_outdev = outdev;
    330 	msg->ce_mask |= QUEUE_MSG_ATTR_OUTDEV;
    331 }
    332 
    333 int nfnl_queue_msg_test_outdev(const struct nfnl_queue_msg *msg)
    334 {
    335 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_OUTDEV);
    336 }
    337 
    338 uint32_t nfnl_queue_msg_get_outdev(const struct nfnl_queue_msg *msg)
    339 {
    340 	return msg->queue_msg_outdev;
    341 }
    342 
    343 void nfnl_queue_msg_set_physindev(struct nfnl_queue_msg *msg,
    344 				  uint32_t physindev)
    345 {
    346 	msg->queue_msg_physindev = physindev;
    347 	msg->ce_mask |= QUEUE_MSG_ATTR_PHYSINDEV;
    348 }
    349 
    350 int nfnl_queue_msg_test_physindev(const struct nfnl_queue_msg *msg)
    351 {
    352 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_PHYSINDEV);
    353 }
    354 
    355 uint32_t nfnl_queue_msg_get_physindev(const struct nfnl_queue_msg *msg)
    356 {
    357 	return msg->queue_msg_physindev;
    358 }
    359 
    360 void nfnl_queue_msg_set_physoutdev(struct nfnl_queue_msg *msg,
    361 				   uint32_t physoutdev)
    362 {
    363 	msg->queue_msg_physoutdev = physoutdev;
    364 	msg->ce_mask |= QUEUE_MSG_ATTR_PHYSOUTDEV;
    365 }
    366 
    367 int nfnl_queue_msg_test_physoutdev(const struct nfnl_queue_msg *msg)
    368 {
    369 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_PHYSOUTDEV);
    370 }
    371 
    372 uint32_t nfnl_queue_msg_get_physoutdev(const struct nfnl_queue_msg *msg)
    373 {
    374 	return msg->queue_msg_physoutdev;
    375 }
    376 
    377 void nfnl_queue_msg_set_hwaddr(struct nfnl_queue_msg *msg, uint8_t *hwaddr,
    378 			       int len)
    379 {
    380 	if (len > sizeof(msg->queue_msg_hwaddr))
    381 		len = sizeof(msg->queue_msg_hwaddr);
    382 
    383 	msg->queue_msg_hwaddr_len = len;
    384 	memcpy(msg->queue_msg_hwaddr, hwaddr, len);
    385 	msg->ce_mask |= QUEUE_MSG_ATTR_HWADDR;
    386 }
    387 
    388 int nfnl_queue_msg_test_hwaddr(const struct nfnl_queue_msg *msg)
    389 {
    390 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_HWADDR);
    391 }
    392 
    393 const uint8_t *nfnl_queue_msg_get_hwaddr(const struct nfnl_queue_msg *msg,
    394 					 int *len)
    395 {
    396 	if (!(msg->ce_mask & QUEUE_MSG_ATTR_HWADDR)) {
    397 		*len = 0;
    398 		return NULL;
    399 	}
    400 
    401 	*len = msg->queue_msg_hwaddr_len;
    402 	return msg->queue_msg_hwaddr;
    403 }
    404 
    405 int nfnl_queue_msg_set_payload(struct nfnl_queue_msg *msg, uint8_t *payload,
    406 			       int len)
    407 {
    408 	free(msg->queue_msg_payload);
    409 	msg->queue_msg_payload = malloc(len);
    410 	if (!msg->queue_msg_payload)
    411 		return -NLE_NOMEM;
    412 
    413 	memcpy(msg->queue_msg_payload, payload, len);
    414 	msg->queue_msg_payload_len = len;
    415 	msg->ce_mask |= QUEUE_MSG_ATTR_PAYLOAD;
    416 	return 0;
    417 }
    418 
    419 int nfnl_queue_msg_test_payload(const struct nfnl_queue_msg *msg)
    420 {
    421 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD);
    422 }
    423 
    424 const void *nfnl_queue_msg_get_payload(const struct nfnl_queue_msg *msg, int *len)
    425 {
    426 	if (!(msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD)) {
    427 		*len = 0;
    428 		return NULL;
    429 	}
    430 
    431 	*len = msg->queue_msg_payload_len;
    432 	return msg->queue_msg_payload;
    433 }
    434 
    435 /**
    436 * Return the number of items matching a filter in the cache
    437 * @arg msg        queue msg
    438 * @arg verdict    NF_DROP, NF_ACCEPT, NF_REPEAT, etc
    439 */
    440 void nfnl_queue_msg_set_verdict(struct nfnl_queue_msg *msg,
    441 				unsigned int verdict)
    442 {
    443 	msg->queue_msg_verdict = verdict;
    444 	msg->ce_mask |= QUEUE_MSG_ATTR_VERDICT;
    445 }
    446 
    447 int nfnl_queue_msg_test_verdict(const struct nfnl_queue_msg *msg)
    448 {
    449 	return !!(msg->ce_mask & QUEUE_MSG_ATTR_VERDICT);
    450 }
    451 
    452 unsigned int nfnl_queue_msg_get_verdict(const struct nfnl_queue_msg *msg)
    453 {
    454 	return msg->queue_msg_verdict;
    455 }
    456 
    457 static const struct trans_tbl nfnl_queue_msg_attrs[] = {
    458 	__ADD(QUEUE_MSG_ATTR_GROUP,		group)
    459 	__ADD(QUEUE_MSG_ATTR_FAMILY,		family)
    460 	__ADD(QUEUE_MSG_ATTR_PACKETID,		packetid)
    461 	__ADD(QUEUE_MSG_ATTR_HWPROTO,		hwproto)
    462 	__ADD(QUEUE_MSG_ATTR_HOOK,		hook)
    463 	__ADD(QUEUE_MSG_ATTR_MARK,		mark)
    464 	__ADD(QUEUE_MSG_ATTR_TIMESTAMP,		timestamp)
    465 	__ADD(QUEUE_MSG_ATTR_INDEV,		indev)
    466 	__ADD(QUEUE_MSG_ATTR_OUTDEV,		outdev)
    467 	__ADD(QUEUE_MSG_ATTR_PHYSINDEV,		physindev)
    468 	__ADD(QUEUE_MSG_ATTR_PHYSOUTDEV,	physoutdev)
    469 	__ADD(QUEUE_MSG_ATTR_HWADDR,		hwaddr)
    470 	__ADD(QUEUE_MSG_ATTR_PAYLOAD,		payload)
    471 	__ADD(QUEUE_MSG_ATTR_VERDICT,		verdict)
    472 };
    473 
    474 static char *nfnl_queue_msg_attrs2str(int attrs, char *buf, size_t len)
    475 {
    476 	return __flags2str(attrs, buf, len, nfnl_queue_msg_attrs,
    477 			   ARRAY_SIZE(nfnl_queue_msg_attrs));
    478 }
    479 
    480 /** @} */
    481 
    482 struct nl_object_ops queue_msg_obj_ops = {
    483 	.oo_name		= "netfilter/queuemsg",
    484 	.oo_size		= sizeof(struct nfnl_queue_msg),
    485 	.oo_free_data		= nfnl_queue_msg_free_data,
    486 	.oo_clone		= nfnl_queue_msg_clone,
    487 	.oo_dump = {
    488 	    [NL_DUMP_LINE]	= nfnl_queue_msg_dump,
    489 	    [NL_DUMP_DETAILS]	= nfnl_queue_msg_dump,
    490 	    [NL_DUMP_STATS]	= nfnl_queue_msg_dump,
    491 	},
    492 	.oo_attrs2str		= nfnl_queue_msg_attrs2str,
    493 };
    494 
    495 /** @} */
    496