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