Home | History | Annotate | Download | only in netfilter
      1 /*
      2  * lib/netfilter/log_msg_obj.c	Netfilter Log 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) 2003-2008 Thomas Graf <tgraf (at) suug.ch>
     10  * Copyright (c) 2007 Philip Craig <philipc (at) snapgear.com>
     11  * Copyright (c) 2007 Secure Computing Corporation
     12  */
     13 
     14 #include <netlink-private/netlink.h>
     15 #include <netlink/netfilter/nfnl.h>
     16 #include <netlink/netfilter/netfilter.h>
     17 #include <netlink/netfilter/log_msg.h>
     18 
     19 /** @cond SKIP */
     20 #define LOG_MSG_ATTR_FAMILY		(1UL << 0)
     21 #define LOG_MSG_ATTR_HWPROTO		(1UL << 1)
     22 #define LOG_MSG_ATTR_HOOK		(1UL << 2)
     23 #define LOG_MSG_ATTR_MARK		(1UL << 3)
     24 #define LOG_MSG_ATTR_TIMESTAMP		(1UL << 4)
     25 #define LOG_MSG_ATTR_INDEV		(1UL << 5)
     26 #define LOG_MSG_ATTR_OUTDEV		(1UL << 6)
     27 #define LOG_MSG_ATTR_PHYSINDEV		(1UL << 7)
     28 #define LOG_MSG_ATTR_PHYSOUTDEV		(1UL << 8)
     29 #define LOG_MSG_ATTR_HWADDR		(1UL << 9)
     30 #define LOG_MSG_ATTR_PAYLOAD		(1UL << 10)
     31 #define LOG_MSG_ATTR_PREFIX		(1UL << 11)
     32 #define LOG_MSG_ATTR_UID		(1UL << 12)
     33 #define LOG_MSG_ATTR_GID		(1UL << 13)
     34 #define LOG_MSG_ATTR_SEQ		(1UL << 14)
     35 #define LOG_MSG_ATTR_SEQ_GLOBAL		(1UL << 15)
     36 /** @endcond */
     37 
     38 static void log_msg_free_data(struct nl_object *c)
     39 {
     40 	struct nfnl_log_msg *msg = (struct nfnl_log_msg *) c;
     41 
     42 	if (msg == NULL)
     43 		return;
     44 
     45 	free(msg->log_msg_payload);
     46 	free(msg->log_msg_prefix);
     47 }
     48 
     49 static int log_msg_clone(struct nl_object *_dst, struct nl_object *_src)
     50 {
     51 	struct nfnl_log_msg *dst = (struct nfnl_log_msg *) _dst;
     52 	struct nfnl_log_msg *src = (struct nfnl_log_msg *) _src;
     53 	int err;
     54 
     55 	if (src->log_msg_payload) {
     56 		err = nfnl_log_msg_set_payload(dst, src->log_msg_payload,
     57 					       src->log_msg_payload_len);
     58 		if (err < 0)
     59 			goto errout;
     60 	}
     61 
     62 	if (src->log_msg_prefix) {
     63 		err = nfnl_log_msg_set_prefix(dst, src->log_msg_prefix);
     64 		if (err < 0)
     65 			goto errout;
     66 	}
     67 
     68 	return 0;
     69 errout:
     70 	return err;
     71 }
     72 
     73 static void log_msg_dump(struct nl_object *a, struct nl_dump_params *p)
     74 {
     75 	struct nfnl_log_msg *msg = (struct nfnl_log_msg *) a;
     76 	struct nl_cache *link_cache;
     77 	char buf[64];
     78 
     79 	link_cache = nl_cache_mngt_require_safe("route/link");
     80 
     81 	nl_new_line(p);
     82 
     83 	if (msg->ce_mask & LOG_MSG_ATTR_PREFIX)
     84 		nl_dump(p, "%s", msg->log_msg_prefix);
     85 
     86 	if (msg->ce_mask & LOG_MSG_ATTR_INDEV) {
     87 		if (link_cache)
     88 			nl_dump(p, "IN=%s ",
     89 				rtnl_link_i2name(link_cache,
     90 						 msg->log_msg_indev,
     91 						 buf, sizeof(buf)));
     92 		else
     93 			nl_dump(p, "IN=%d ", msg->log_msg_indev);
     94 	}
     95 
     96 	if (msg->ce_mask & LOG_MSG_ATTR_PHYSINDEV) {
     97 		if (link_cache)
     98 			nl_dump(p, "PHYSIN=%s ",
     99 				rtnl_link_i2name(link_cache,
    100 						 msg->log_msg_physindev,
    101 						 buf, sizeof(buf)));
    102 		else
    103 			nl_dump(p, "IN=%d ", msg->log_msg_physindev);
    104 	}
    105 
    106 	if (msg->ce_mask & LOG_MSG_ATTR_OUTDEV) {
    107 		if (link_cache)
    108 			nl_dump(p, "OUT=%s ",
    109 				rtnl_link_i2name(link_cache,
    110 						 msg->log_msg_outdev,
    111 						 buf, sizeof(buf)));
    112 		else
    113 			nl_dump(p, "OUT=%d ", msg->log_msg_outdev);
    114 	}
    115 
    116 	if (msg->ce_mask & LOG_MSG_ATTR_PHYSOUTDEV) {
    117 		if (link_cache)
    118 			nl_dump(p, "PHYSOUT=%s ",
    119 				rtnl_link_i2name(link_cache,
    120 						 msg->log_msg_physoutdev,
    121 						 buf, sizeof(buf)));
    122 		else
    123 			nl_dump(p, "PHYSOUT=%d ", msg->log_msg_physoutdev);
    124 	}
    125 
    126 	if (msg->ce_mask & LOG_MSG_ATTR_HWADDR) {
    127 		int i;
    128 
    129 		nl_dump(p, "MAC");
    130 		for (i = 0; i < msg->log_msg_hwaddr_len; i++)
    131 			nl_dump(p, "%c%02x", i?':':'=', msg->log_msg_hwaddr[i]);
    132 		nl_dump(p, " ");
    133 	}
    134 
    135 	/* FIXME: parse the payload to get iptables LOG compatible format */
    136 
    137 	if (msg->ce_mask & LOG_MSG_ATTR_FAMILY)
    138 		nl_dump(p, "FAMILY=%s ",
    139 			nl_af2str(msg->log_msg_family, buf, sizeof(buf)));
    140 
    141 	if (msg->ce_mask & LOG_MSG_ATTR_HWPROTO)
    142 		nl_dump(p, "HWPROTO=%s ",
    143 			nl_ether_proto2str(ntohs(msg->log_msg_hwproto),
    144 					   buf, sizeof(buf)));
    145 
    146 	if (msg->ce_mask & LOG_MSG_ATTR_HOOK)
    147 		nl_dump(p, "HOOK=%s ",
    148 			nfnl_inet_hook2str(msg->log_msg_hook,
    149 					   buf, sizeof(buf)));
    150 
    151 	if (msg->ce_mask & LOG_MSG_ATTR_MARK)
    152 		nl_dump(p, "MARK=%u ", msg->log_msg_mark);
    153 
    154 	if (msg->ce_mask & LOG_MSG_ATTR_PAYLOAD)
    155 		nl_dump(p, "PAYLOADLEN=%d ", msg->log_msg_payload_len);
    156 
    157 	if (msg->ce_mask & LOG_MSG_ATTR_UID)
    158 		nl_dump(p, "UID=%u ", msg->log_msg_uid);
    159 
    160 	if (msg->ce_mask & LOG_MSG_ATTR_GID)
    161 		nl_dump(p, "GID=%u ", msg->log_msg_gid);
    162 
    163 	if (msg->ce_mask & LOG_MSG_ATTR_SEQ)
    164 		nl_dump(p, "SEQ=%d ", msg->log_msg_seq);
    165 
    166 	if (msg->ce_mask & LOG_MSG_ATTR_SEQ_GLOBAL)
    167 		nl_dump(p, "SEQGLOBAL=%d ", msg->log_msg_seq_global);
    168 
    169 	nl_dump(p, "\n");
    170 
    171 	if (link_cache)
    172 		nl_cache_put(link_cache);
    173 }
    174 
    175 /**
    176  * @name Allocation/Freeing
    177  * @{
    178  */
    179 
    180 struct nfnl_log_msg *nfnl_log_msg_alloc(void)
    181 {
    182 	return (struct nfnl_log_msg *) nl_object_alloc(&log_msg_obj_ops);
    183 }
    184 
    185 void nfnl_log_msg_get(struct nfnl_log_msg *msg)
    186 {
    187 	nl_object_get((struct nl_object *) msg);
    188 }
    189 
    190 void nfnl_log_msg_put(struct nfnl_log_msg *msg)
    191 {
    192 	nl_object_put((struct nl_object *) msg);
    193 }
    194 
    195 /** @} */
    196 
    197 /**
    198  * @name Attributes
    199  * @{
    200  */
    201 
    202 void nfnl_log_msg_set_family(struct nfnl_log_msg *msg, uint8_t family)
    203 {
    204 	msg->log_msg_family = family;
    205 	msg->ce_mask |= LOG_MSG_ATTR_FAMILY;
    206 }
    207 
    208 uint8_t nfnl_log_msg_get_family(const struct nfnl_log_msg *msg)
    209 {
    210 	if (msg->ce_mask & LOG_MSG_ATTR_FAMILY)
    211 		return msg->log_msg_family;
    212 	else
    213 		return AF_UNSPEC;
    214 }
    215 
    216 void nfnl_log_msg_set_hwproto(struct nfnl_log_msg *msg, uint16_t hwproto)
    217 {
    218 	msg->log_msg_hwproto = hwproto;
    219 	msg->ce_mask |= LOG_MSG_ATTR_HWPROTO;
    220 }
    221 
    222 int nfnl_log_msg_test_hwproto(const struct nfnl_log_msg *msg)
    223 {
    224 	return !!(msg->ce_mask & LOG_MSG_ATTR_HWPROTO);
    225 }
    226 
    227 uint16_t nfnl_log_msg_get_hwproto(const struct nfnl_log_msg *msg)
    228 {
    229 	return msg->log_msg_hwproto;
    230 }
    231 
    232 void nfnl_log_msg_set_hook(struct nfnl_log_msg *msg, uint8_t hook)
    233 {
    234 	msg->log_msg_hook = hook;
    235 	msg->ce_mask |= LOG_MSG_ATTR_HOOK;
    236 }
    237 
    238 int nfnl_log_msg_test_hook(const struct nfnl_log_msg *msg)
    239 {
    240 	return !!(msg->ce_mask & LOG_MSG_ATTR_HOOK);
    241 }
    242 
    243 uint8_t nfnl_log_msg_get_hook(const struct nfnl_log_msg *msg)
    244 {
    245 	return msg->log_msg_hook;
    246 }
    247 
    248 void nfnl_log_msg_set_mark(struct nfnl_log_msg *msg, uint32_t mark)
    249 {
    250 	msg->log_msg_mark = mark;
    251 	msg->ce_mask |= LOG_MSG_ATTR_MARK;
    252 }
    253 
    254 int nfnl_log_msg_test_mark(const struct nfnl_log_msg *msg)
    255 {
    256 	return !!(msg->ce_mask & LOG_MSG_ATTR_MARK);
    257 }
    258 
    259 uint32_t nfnl_log_msg_get_mark(const struct nfnl_log_msg *msg)
    260 {
    261 	return msg->log_msg_mark;
    262 }
    263 
    264 void nfnl_log_msg_set_timestamp(struct nfnl_log_msg *msg, struct timeval *tv)
    265 {
    266 	msg->log_msg_timestamp.tv_sec = tv->tv_sec;
    267 	msg->log_msg_timestamp.tv_usec = tv->tv_usec;
    268 	msg->ce_mask |= LOG_MSG_ATTR_TIMESTAMP;
    269 }
    270 
    271 const struct timeval *nfnl_log_msg_get_timestamp(const struct nfnl_log_msg *msg)
    272 {
    273 	if (!(msg->ce_mask & LOG_MSG_ATTR_TIMESTAMP))
    274 		return NULL;
    275 	return &msg->log_msg_timestamp;
    276 }
    277 
    278 void nfnl_log_msg_set_indev(struct nfnl_log_msg *msg, uint32_t indev)
    279 {
    280 	msg->log_msg_indev = indev;
    281 	msg->ce_mask |= LOG_MSG_ATTR_INDEV;
    282 }
    283 
    284 uint32_t nfnl_log_msg_get_indev(const struct nfnl_log_msg *msg)
    285 {
    286 	return msg->log_msg_indev;
    287 }
    288 
    289 void nfnl_log_msg_set_outdev(struct nfnl_log_msg *msg, uint32_t outdev)
    290 {
    291 	msg->log_msg_outdev = outdev;
    292 	msg->ce_mask |= LOG_MSG_ATTR_OUTDEV;
    293 }
    294 
    295 uint32_t nfnl_log_msg_get_outdev(const struct nfnl_log_msg *msg)
    296 {
    297 	return msg->log_msg_outdev;
    298 }
    299 
    300 void nfnl_log_msg_set_physindev(struct nfnl_log_msg *msg, uint32_t physindev)
    301 {
    302 	msg->log_msg_physindev = physindev;
    303 	msg->ce_mask |= LOG_MSG_ATTR_PHYSINDEV;
    304 }
    305 
    306 uint32_t nfnl_log_msg_get_physindev(const struct nfnl_log_msg *msg)
    307 {
    308 	return msg->log_msg_physindev;
    309 }
    310 
    311 void nfnl_log_msg_set_physoutdev(struct nfnl_log_msg *msg, uint32_t physoutdev)
    312 {
    313 	msg->log_msg_physoutdev = physoutdev;
    314 	msg->ce_mask |= LOG_MSG_ATTR_PHYSOUTDEV;
    315 }
    316 
    317 uint32_t nfnl_log_msg_get_physoutdev(const struct nfnl_log_msg *msg)
    318 {
    319 	return msg->log_msg_physoutdev;
    320 }
    321 
    322 void nfnl_log_msg_set_hwaddr(struct nfnl_log_msg *msg, uint8_t *hwaddr, int len)
    323 {
    324 	if (len > sizeof(msg->log_msg_hwaddr))
    325 		len = sizeof(msg->log_msg_hwaddr);
    326 	msg->log_msg_hwaddr_len = len;
    327 	memcpy(msg->log_msg_hwaddr, hwaddr, len);
    328 	msg->ce_mask |= LOG_MSG_ATTR_HWADDR;
    329 }
    330 
    331 const uint8_t *nfnl_log_msg_get_hwaddr(const struct nfnl_log_msg *msg, int *len)
    332 {
    333 	if (!(msg->ce_mask & LOG_MSG_ATTR_HWADDR)) {
    334 		*len = 0;
    335 		return NULL;
    336 	}
    337 
    338 	*len = msg->log_msg_hwaddr_len;
    339 	return msg->log_msg_hwaddr;
    340 }
    341 
    342 int nfnl_log_msg_set_payload(struct nfnl_log_msg *msg, uint8_t *payload, int len)
    343 {
    344 	free(msg->log_msg_payload);
    345 	msg->log_msg_payload = malloc(len);
    346 	if (!msg->log_msg_payload)
    347 		return -NLE_NOMEM;
    348 
    349 	memcpy(msg->log_msg_payload, payload, len);
    350 	msg->log_msg_payload_len = len;
    351 	msg->ce_mask |= LOG_MSG_ATTR_PAYLOAD;
    352 	return 0;
    353 }
    354 
    355 const void *nfnl_log_msg_get_payload(const struct nfnl_log_msg *msg, int *len)
    356 {
    357 	if (!(msg->ce_mask & LOG_MSG_ATTR_PAYLOAD)) {
    358 		*len = 0;
    359 		return NULL;
    360 	}
    361 
    362 	*len = msg->log_msg_payload_len;
    363 	return msg->log_msg_payload;
    364 }
    365 
    366 int nfnl_log_msg_set_prefix(struct nfnl_log_msg *msg, void *prefix)
    367 {
    368 	free(msg->log_msg_prefix);
    369 	msg->log_msg_prefix = strdup(prefix);
    370 	if (!msg->log_msg_prefix)
    371 		return -NLE_NOMEM;
    372 
    373 	msg->ce_mask |= LOG_MSG_ATTR_PREFIX;
    374 	return 0;
    375 }
    376 
    377 const char *nfnl_log_msg_get_prefix(const struct nfnl_log_msg *msg)
    378 {
    379 	return msg->log_msg_prefix;
    380 }
    381 
    382 void nfnl_log_msg_set_uid(struct nfnl_log_msg *msg, uint32_t uid)
    383 {
    384 	msg->log_msg_uid = uid;
    385 	msg->ce_mask |= LOG_MSG_ATTR_UID;
    386 }
    387 
    388 int nfnl_log_msg_test_uid(const struct nfnl_log_msg *msg)
    389 {
    390 	return !!(msg->ce_mask & LOG_MSG_ATTR_UID);
    391 }
    392 
    393 uint32_t nfnl_log_msg_get_uid(const struct nfnl_log_msg *msg)
    394 {
    395 	return msg->log_msg_uid;
    396 }
    397 
    398 void nfnl_log_msg_set_gid(struct nfnl_log_msg *msg, uint32_t gid)
    399 {
    400 	msg->log_msg_gid = gid;
    401 	msg->ce_mask |= LOG_MSG_ATTR_GID;
    402 }
    403 
    404 int nfnl_log_msg_test_gid(const struct nfnl_log_msg *msg)
    405 {
    406 	return !!(msg->ce_mask & LOG_MSG_ATTR_GID);
    407 }
    408 
    409 uint32_t nfnl_log_msg_get_gid(const struct nfnl_log_msg *msg)
    410 {
    411 	return msg->log_msg_gid;
    412 }
    413 
    414 
    415 void nfnl_log_msg_set_seq(struct nfnl_log_msg *msg, uint32_t seq)
    416 {
    417 	msg->log_msg_seq = seq;
    418 	msg->ce_mask |= LOG_MSG_ATTR_SEQ;
    419 }
    420 
    421 int nfnl_log_msg_test_seq(const struct nfnl_log_msg *msg)
    422 {
    423 	return !!(msg->ce_mask & LOG_MSG_ATTR_SEQ);
    424 }
    425 
    426 uint32_t nfnl_log_msg_get_seq(const struct nfnl_log_msg *msg)
    427 {
    428 	return msg->log_msg_seq;
    429 }
    430 
    431 void nfnl_log_msg_set_seq_global(struct nfnl_log_msg *msg, uint32_t seq_global)
    432 {
    433 	msg->log_msg_seq_global = seq_global;
    434 	msg->ce_mask |= LOG_MSG_ATTR_SEQ_GLOBAL;
    435 }
    436 
    437 int nfnl_log_msg_test_seq_global(const struct nfnl_log_msg *msg)
    438 {
    439 	return !!(msg->ce_mask & LOG_MSG_ATTR_SEQ_GLOBAL);
    440 }
    441 
    442 uint32_t nfnl_log_msg_get_seq_global(const struct nfnl_log_msg *msg)
    443 {
    444 	return msg->log_msg_seq_global;
    445 }
    446 
    447 /** @} */
    448 
    449 struct nl_object_ops log_msg_obj_ops = {
    450 	.oo_name		= "netfilter/log_msg",
    451 	.oo_size		= sizeof(struct nfnl_log_msg),
    452 	.oo_free_data		= log_msg_free_data,
    453 	.oo_clone		= log_msg_clone,
    454 	.oo_dump = {
    455 	    [NL_DUMP_LINE]	= log_msg_dump,
    456 	    [NL_DUMP_DETAILS]	= log_msg_dump,
    457 	    [NL_DUMP_STATS]	= log_msg_dump,
    458 	},
    459 };
    460 
    461 /** @} */
    462