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@suug.ch> 10 * Copyright (c) 2007 Philip Craig <philipc@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 38static 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 49static 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; 69errout: 70 return err; 71} 72 73static 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 177struct nfnl_log_msg *nfnl_log_msg_alloc(void) 178{ 179 return (struct nfnl_log_msg *) nl_object_alloc(&log_msg_obj_ops); 180} 181 182void nfnl_log_msg_get(struct nfnl_log_msg *msg) 183{ 184 nl_object_get((struct nl_object *) msg); 185} 186 187void 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 199void 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 205uint8_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 213void 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 219int nfnl_log_msg_test_hwproto(const struct nfnl_log_msg *msg) 220{ 221 return !!(msg->ce_mask & LOG_MSG_ATTR_HWPROTO); 222} 223 224uint16_t nfnl_log_msg_get_hwproto(const struct nfnl_log_msg *msg) 225{ 226 return msg->log_msg_hwproto; 227} 228 229void 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 235int nfnl_log_msg_test_hook(const struct nfnl_log_msg *msg) 236{ 237 return !!(msg->ce_mask & LOG_MSG_ATTR_HOOK); 238} 239 240uint8_t nfnl_log_msg_get_hook(const struct nfnl_log_msg *msg) 241{ 242 return msg->log_msg_hook; 243} 244 245void 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 251int nfnl_log_msg_test_mark(const struct nfnl_log_msg *msg) 252{ 253 return !!(msg->ce_mask & LOG_MSG_ATTR_MARK); 254} 255 256uint32_t nfnl_log_msg_get_mark(const struct nfnl_log_msg *msg) 257{ 258 return msg->log_msg_mark; 259} 260 261void 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 268const 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 275void 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 281uint32_t nfnl_log_msg_get_indev(const struct nfnl_log_msg *msg) 282{ 283 return msg->log_msg_indev; 284} 285 286void 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 292uint32_t nfnl_log_msg_get_outdev(const struct nfnl_log_msg *msg) 293{ 294 return msg->log_msg_outdev; 295} 296 297void 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 303uint32_t nfnl_log_msg_get_physindev(const struct nfnl_log_msg *msg) 304{ 305 return msg->log_msg_physindev; 306} 307 308void 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 314uint32_t nfnl_log_msg_get_physoutdev(const struct nfnl_log_msg *msg) 315{ 316 return msg->log_msg_physoutdev; 317} 318 319void 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 328const 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 339int 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 352const 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 363int 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 374const char *nfnl_log_msg_get_prefix(const struct nfnl_log_msg *msg) 375{ 376 return msg->log_msg_prefix; 377} 378 379void 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 385int nfnl_log_msg_test_uid(const struct nfnl_log_msg *msg) 386{ 387 return !!(msg->ce_mask & LOG_MSG_ATTR_UID); 388} 389 390uint32_t nfnl_log_msg_get_uid(const struct nfnl_log_msg *msg) 391{ 392 return msg->log_msg_uid; 393} 394 395void 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 401int nfnl_log_msg_test_gid(const struct nfnl_log_msg *msg) 402{ 403 return !!(msg->ce_mask & LOG_MSG_ATTR_GID); 404} 405 406uint32_t nfnl_log_msg_get_gid(const struct nfnl_log_msg *msg) 407{ 408 return msg->log_msg_gid; 409} 410 411 412void 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 418int nfnl_log_msg_test_seq(const struct nfnl_log_msg *msg) 419{ 420 return !!(msg->ce_mask & LOG_MSG_ATTR_SEQ); 421} 422 423uint32_t nfnl_log_msg_get_seq(const struct nfnl_log_msg *msg) 424{ 425 return msg->log_msg_seq; 426} 427 428void 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 434int 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 439uint32_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 446struct 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