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