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-local.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("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 
    172 /**
    173  * @name Allocation/Freeing
    174  * @{
    175  */
    176 
    177 struct nfnl_log_msg *nfnl_log_msg_alloc(void)
    178 {
    179 	return (struct nfnl_log_msg *) nl_object_alloc(&log_msg_obj_ops);
    180 }
    181 
    182 void nfnl_log_msg_get(struct nfnl_log_msg *msg)
    183 {
    184 	nl_object_get((struct nl_object *) msg);
    185 }
    186 
    187 void nfnl_log_msg_put(struct nfnl_log_msg *msg)
    188 {
    189 	nl_object_put((struct nl_object *) msg);
    190 }
    191 
    192 /** @} */
    193 
    194 /**
    195  * @name Attributes
    196  * @{
    197  */
    198 
    199 void nfnl_log_msg_set_family(struct nfnl_log_msg *msg, uint8_t family)
    200 {
    201 	msg->log_msg_family = family;
    202 	msg->ce_mask |= LOG_MSG_ATTR_FAMILY;
    203 }
    204 
    205 uint8_t nfnl_log_msg_get_family(const struct nfnl_log_msg *msg)
    206 {
    207 	if (msg->ce_mask & LOG_MSG_ATTR_FAMILY)
    208 		return msg->log_msg_family;
    209 	else
    210 		return AF_UNSPEC;
    211 }
    212 
    213 void nfnl_log_msg_set_hwproto(struct nfnl_log_msg *msg, uint16_t hwproto)
    214 {
    215 	msg->log_msg_hwproto = hwproto;
    216 	msg->ce_mask |= LOG_MSG_ATTR_HWPROTO;
    217 }
    218 
    219 int nfnl_log_msg_test_hwproto(const struct nfnl_log_msg *msg)
    220 {
    221 	return !!(msg->ce_mask & LOG_MSG_ATTR_HWPROTO);
    222 }
    223 
    224 uint16_t nfnl_log_msg_get_hwproto(const struct nfnl_log_msg *msg)
    225 {
    226 	return msg->log_msg_hwproto;
    227 }
    228 
    229 void nfnl_log_msg_set_hook(struct nfnl_log_msg *msg, uint8_t hook)
    230 {
    231 	msg->log_msg_hook = hook;
    232 	msg->ce_mask |= LOG_MSG_ATTR_HOOK;
    233 }
    234 
    235 int nfnl_log_msg_test_hook(const struct nfnl_log_msg *msg)
    236 {
    237 	return !!(msg->ce_mask & LOG_MSG_ATTR_HOOK);
    238 }
    239 
    240 uint8_t nfnl_log_msg_get_hook(const struct nfnl_log_msg *msg)
    241 {
    242 	return msg->log_msg_hook;
    243 }
    244 
    245 void nfnl_log_msg_set_mark(struct nfnl_log_msg *msg, uint32_t mark)
    246 {
    247 	msg->log_msg_mark = mark;
    248 	msg->ce_mask |= LOG_MSG_ATTR_MARK;
    249 }
    250 
    251 int nfnl_log_msg_test_mark(const struct nfnl_log_msg *msg)
    252 {
    253 	return !!(msg->ce_mask & LOG_MSG_ATTR_MARK);
    254 }
    255 
    256 uint32_t nfnl_log_msg_get_mark(const struct nfnl_log_msg *msg)
    257 {
    258 	return msg->log_msg_mark;
    259 }
    260 
    261 void nfnl_log_msg_set_timestamp(struct nfnl_log_msg *msg, struct timeval *tv)
    262 {
    263 	msg->log_msg_timestamp.tv_sec = tv->tv_sec;
    264 	msg->log_msg_timestamp.tv_usec = tv->tv_usec;
    265 	msg->ce_mask |= LOG_MSG_ATTR_TIMESTAMP;
    266 }
    267 
    268 const struct timeval *nfnl_log_msg_get_timestamp(const struct nfnl_log_msg *msg)
    269 {
    270 	if (!(msg->ce_mask & LOG_MSG_ATTR_TIMESTAMP))
    271 		return NULL;
    272 	return &msg->log_msg_timestamp;
    273 }
    274 
    275 void nfnl_log_msg_set_indev(struct nfnl_log_msg *msg, uint32_t indev)
    276 {
    277 	msg->log_msg_indev = indev;
    278 	msg->ce_mask |= LOG_MSG_ATTR_INDEV;
    279 }
    280 
    281 uint32_t nfnl_log_msg_get_indev(const struct nfnl_log_msg *msg)
    282 {
    283 	return msg->log_msg_indev;
    284 }
    285 
    286 void nfnl_log_msg_set_outdev(struct nfnl_log_msg *msg, uint32_t outdev)
    287 {
    288 	msg->log_msg_outdev = outdev;
    289 	msg->ce_mask |= LOG_MSG_ATTR_OUTDEV;
    290 }
    291 
    292 uint32_t nfnl_log_msg_get_outdev(const struct nfnl_log_msg *msg)
    293 {
    294 	return msg->log_msg_outdev;
    295 }
    296 
    297 void nfnl_log_msg_set_physindev(struct nfnl_log_msg *msg, uint32_t physindev)
    298 {
    299 	msg->log_msg_physindev = physindev;
    300 	msg->ce_mask |= LOG_MSG_ATTR_PHYSINDEV;
    301 }
    302 
    303 uint32_t nfnl_log_msg_get_physindev(const struct nfnl_log_msg *msg)
    304 {
    305 	return msg->log_msg_physindev;
    306 }
    307 
    308 void nfnl_log_msg_set_physoutdev(struct nfnl_log_msg *msg, uint32_t physoutdev)
    309 {
    310 	msg->log_msg_physoutdev = physoutdev;
    311 	msg->ce_mask |= LOG_MSG_ATTR_PHYSOUTDEV;
    312 }
    313 
    314 uint32_t nfnl_log_msg_get_physoutdev(const struct nfnl_log_msg *msg)
    315 {
    316 	return msg->log_msg_physoutdev;
    317 }
    318 
    319 void nfnl_log_msg_set_hwaddr(struct nfnl_log_msg *msg, uint8_t *hwaddr, int len)
    320 {
    321 	if (len > sizeof(msg->log_msg_hwaddr))
    322 		len = sizeof(msg->log_msg_hwaddr);
    323 	msg->log_msg_hwaddr_len = len;
    324 	memcpy(msg->log_msg_hwaddr, hwaddr, len);
    325 	msg->ce_mask |= LOG_MSG_ATTR_HWADDR;
    326 }
    327 
    328 const uint8_t *nfnl_log_msg_get_hwaddr(const struct nfnl_log_msg *msg, int *len)
    329 {
    330 	if (!(msg->ce_mask & LOG_MSG_ATTR_HWADDR)) {
    331 		*len = 0;
    332 		return NULL;
    333 	}
    334 
    335 	*len = msg->log_msg_hwaddr_len;
    336 	return msg->log_msg_hwaddr;
    337 }
    338 
    339 int nfnl_log_msg_set_payload(struct nfnl_log_msg *msg, uint8_t *payload, int len)
    340 {
    341 	free(msg->log_msg_payload);
    342 	msg->log_msg_payload = malloc(len);
    343 	if (!msg->log_msg_payload)
    344 		return -NLE_NOMEM;
    345 
    346 	memcpy(msg->log_msg_payload, payload, len);
    347 	msg->log_msg_payload_len = len;
    348 	msg->ce_mask |= LOG_MSG_ATTR_PAYLOAD;
    349 	return 0;
    350 }
    351 
    352 const void *nfnl_log_msg_get_payload(const struct nfnl_log_msg *msg, int *len)
    353 {
    354 	if (!(msg->ce_mask & LOG_MSG_ATTR_PAYLOAD)) {
    355 		*len = 0;
    356 		return NULL;
    357 	}
    358 
    359 	*len = msg->log_msg_payload_len;
    360 	return msg->log_msg_payload;
    361 }
    362 
    363 int nfnl_log_msg_set_prefix(struct nfnl_log_msg *msg, void *prefix)
    364 {
    365 	free(msg->log_msg_prefix);
    366 	msg->log_msg_prefix = strdup(prefix);
    367 	if (!msg->log_msg_prefix)
    368 		return -NLE_NOMEM;
    369 
    370 	msg->ce_mask |= LOG_MSG_ATTR_PREFIX;
    371 	return 0;
    372 }
    373 
    374 const char *nfnl_log_msg_get_prefix(const struct nfnl_log_msg *msg)
    375 {
    376 	return msg->log_msg_prefix;
    377 }
    378 
    379 void nfnl_log_msg_set_uid(struct nfnl_log_msg *msg, uint32_t uid)
    380 {
    381 	msg->log_msg_uid = uid;
    382 	msg->ce_mask |= LOG_MSG_ATTR_UID;
    383 }
    384 
    385 int nfnl_log_msg_test_uid(const struct nfnl_log_msg *msg)
    386 {
    387 	return !!(msg->ce_mask & LOG_MSG_ATTR_UID);
    388 }
    389 
    390 uint32_t nfnl_log_msg_get_uid(const struct nfnl_log_msg *msg)
    391 {
    392 	return msg->log_msg_uid;
    393 }
    394 
    395 void nfnl_log_msg_set_gid(struct nfnl_log_msg *msg, uint32_t gid)
    396 {
    397 	msg->log_msg_gid = gid;
    398 	msg->ce_mask |= LOG_MSG_ATTR_GID;
    399 }
    400 
    401 int nfnl_log_msg_test_gid(const struct nfnl_log_msg *msg)
    402 {
    403 	return !!(msg->ce_mask & LOG_MSG_ATTR_GID);
    404 }
    405 
    406 uint32_t nfnl_log_msg_get_gid(const struct nfnl_log_msg *msg)
    407 {
    408 	return msg->log_msg_gid;
    409 }
    410 
    411 
    412 void nfnl_log_msg_set_seq(struct nfnl_log_msg *msg, uint32_t seq)
    413 {
    414 	msg->log_msg_seq = seq;
    415 	msg->ce_mask |= LOG_MSG_ATTR_SEQ;
    416 }
    417 
    418 int nfnl_log_msg_test_seq(const struct nfnl_log_msg *msg)
    419 {
    420 	return !!(msg->ce_mask & LOG_MSG_ATTR_SEQ);
    421 }
    422 
    423 uint32_t nfnl_log_msg_get_seq(const struct nfnl_log_msg *msg)
    424 {
    425 	return msg->log_msg_seq;
    426 }
    427 
    428 void nfnl_log_msg_set_seq_global(struct nfnl_log_msg *msg, uint32_t seq_global)
    429 {
    430 	msg->log_msg_seq_global = seq_global;
    431 	msg->ce_mask |= LOG_MSG_ATTR_SEQ_GLOBAL;
    432 }
    433 
    434 int nfnl_log_msg_test_seq_global(const struct nfnl_log_msg *msg)
    435 {
    436 	return !!(msg->ce_mask & LOG_MSG_ATTR_SEQ_GLOBAL);
    437 }
    438 
    439 uint32_t nfnl_log_msg_get_seq_global(const struct nfnl_log_msg *msg)
    440 {
    441 	return msg->log_msg_seq_global;
    442 }
    443 
    444 /** @} */
    445 
    446 struct nl_object_ops log_msg_obj_ops = {
    447 	.oo_name		= "netfilter/log_msg",
    448 	.oo_size		= sizeof(struct nfnl_log_msg),
    449 	.oo_free_data		= log_msg_free_data,
    450 	.oo_clone		= log_msg_clone,
    451 	.oo_dump = {
    452 	    [NL_DUMP_LINE]	= log_msg_dump,
    453 	    [NL_DUMP_DETAILS]	= log_msg_dump,
    454 	    [NL_DUMP_STATS]	= log_msg_dump,
    455 	},
    456 };
    457 
    458 /** @} */
    459