1 /* 2 * lib/netfilter/queue_msg_obj.c Netfilter Queue Message 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) 2007, 2008 Patrick McHardy <kaber (at) trash.net> 10 */ 11 12 #include <netlink-private/netlink.h> 13 #include <netlink/netfilter/nfnl.h> 14 #include <netlink/netfilter/netfilter.h> 15 #include <netlink/netfilter/queue_msg.h> 16 #include <linux/netfilter.h> 17 18 /** @cond SKIP */ 19 #define QUEUE_MSG_ATTR_GROUP (1UL << 0) 20 #define QUEUE_MSG_ATTR_FAMILY (1UL << 1) 21 #define QUEUE_MSG_ATTR_PACKETID (1UL << 2) 22 #define QUEUE_MSG_ATTR_HWPROTO (1UL << 3) 23 #define QUEUE_MSG_ATTR_HOOK (1UL << 4) 24 #define QUEUE_MSG_ATTR_MARK (1UL << 5) 25 #define QUEUE_MSG_ATTR_TIMESTAMP (1UL << 6) 26 #define QUEUE_MSG_ATTR_INDEV (1UL << 7) 27 #define QUEUE_MSG_ATTR_OUTDEV (1UL << 8) 28 #define QUEUE_MSG_ATTR_PHYSINDEV (1UL << 9) 29 #define QUEUE_MSG_ATTR_PHYSOUTDEV (1UL << 10) 30 #define QUEUE_MSG_ATTR_HWADDR (1UL << 11) 31 #define QUEUE_MSG_ATTR_PAYLOAD (1UL << 12) 32 #define QUEUE_MSG_ATTR_VERDICT (1UL << 13) 33 /** @endcond */ 34 35 static void nfnl_queue_msg_free_data(struct nl_object *c) 36 { 37 struct nfnl_queue_msg *msg = (struct nfnl_queue_msg *) c; 38 39 if (msg == NULL) 40 return; 41 42 free(msg->queue_msg_payload); 43 } 44 45 static int nfnl_queue_msg_clone(struct nl_object *_dst, struct nl_object *_src) 46 { 47 struct nfnl_queue_msg *dst = (struct nfnl_queue_msg *) _dst; 48 struct nfnl_queue_msg *src = (struct nfnl_queue_msg *) _src; 49 int err; 50 51 if (src->queue_msg_payload) { 52 err = nfnl_queue_msg_set_payload(dst, src->queue_msg_payload, 53 src->queue_msg_payload_len); 54 if (err < 0) 55 goto errout; 56 } 57 58 return 0; 59 errout: 60 return err; 61 } 62 63 static void nfnl_queue_msg_dump(struct nl_object *a, struct nl_dump_params *p) 64 { 65 struct nfnl_queue_msg *msg = (struct nfnl_queue_msg *) a; 66 struct nl_cache *link_cache; 67 char buf[64]; 68 69 link_cache = nl_cache_mngt_require_safe("route/link"); 70 71 nl_new_line(p); 72 73 if (msg->ce_mask & QUEUE_MSG_ATTR_GROUP) 74 nl_dump(p, "GROUP=%u ", msg->queue_msg_group); 75 76 if (msg->ce_mask & QUEUE_MSG_ATTR_INDEV) { 77 if (link_cache) 78 nl_dump(p, "IN=%s ", 79 rtnl_link_i2name(link_cache, 80 msg->queue_msg_indev, 81 buf, sizeof(buf))); 82 else 83 nl_dump(p, "IN=%d ", msg->queue_msg_indev); 84 } 85 86 if (msg->ce_mask & QUEUE_MSG_ATTR_PHYSINDEV) { 87 if (link_cache) 88 nl_dump(p, "PHYSIN=%s ", 89 rtnl_link_i2name(link_cache, 90 msg->queue_msg_physindev, 91 buf, sizeof(buf))); 92 else 93 nl_dump(p, "IN=%d ", msg->queue_msg_physindev); 94 } 95 96 if (msg->ce_mask & QUEUE_MSG_ATTR_OUTDEV) { 97 if (link_cache) 98 nl_dump(p, "OUT=%s ", 99 rtnl_link_i2name(link_cache, 100 msg->queue_msg_outdev, 101 buf, sizeof(buf))); 102 else 103 nl_dump(p, "OUT=%d ", msg->queue_msg_outdev); 104 } 105 106 if (msg->ce_mask & QUEUE_MSG_ATTR_PHYSOUTDEV) { 107 if (link_cache) 108 nl_dump(p, "PHYSOUT=%s ", 109 rtnl_link_i2name(link_cache, 110 msg->queue_msg_physoutdev, 111 buf, sizeof(buf))); 112 else 113 nl_dump(p, "PHYSOUT=%d ", msg->queue_msg_physoutdev); 114 } 115 116 if (msg->ce_mask & QUEUE_MSG_ATTR_HWADDR) { 117 int i; 118 119 nl_dump(p, "MAC"); 120 for (i = 0; i < msg->queue_msg_hwaddr_len; i++) 121 nl_dump(p, "%c%02x", i?':':'=', 122 msg->queue_msg_hwaddr[i]); 123 nl_dump(p, " "); 124 } 125 126 if (msg->ce_mask & QUEUE_MSG_ATTR_FAMILY) 127 nl_dump(p, "FAMILY=%s ", 128 nl_af2str(msg->queue_msg_family, buf, sizeof(buf))); 129 130 if (msg->ce_mask & QUEUE_MSG_ATTR_HWPROTO) 131 nl_dump(p, "HWPROTO=%s ", 132 nl_ether_proto2str(ntohs(msg->queue_msg_hwproto), 133 buf, sizeof(buf))); 134 135 if (msg->ce_mask & QUEUE_MSG_ATTR_HOOK) 136 nl_dump(p, "HOOK=%s ", 137 nfnl_inet_hook2str(msg->queue_msg_hook, 138 buf, sizeof(buf))); 139 140 if (msg->ce_mask & QUEUE_MSG_ATTR_MARK) 141 nl_dump(p, "MARK=%d ", msg->queue_msg_mark); 142 143 if (msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD) 144 nl_dump(p, "PAYLOADLEN=%d ", msg->queue_msg_payload_len); 145 146 if (msg->ce_mask & QUEUE_MSG_ATTR_PACKETID) 147 nl_dump(p, "PACKETID=%u ", msg->queue_msg_packetid); 148 149 if (msg->ce_mask & QUEUE_MSG_ATTR_VERDICT) 150 nl_dump(p, "VERDICT=%s ", 151 nfnl_verdict2str(msg->queue_msg_verdict, 152 buf, sizeof(buf))); 153 154 nl_dump(p, "\n"); 155 156 if (link_cache) 157 nl_cache_put(link_cache); 158 } 159 160 /** 161 * @name Allocation/Freeing 162 * @{ 163 */ 164 165 struct nfnl_queue_msg *nfnl_queue_msg_alloc(void) 166 { 167 return (struct nfnl_queue_msg *) nl_object_alloc(&queue_msg_obj_ops); 168 } 169 170 void nfnl_queue_msg_get(struct nfnl_queue_msg *msg) 171 { 172 nl_object_get((struct nl_object *) msg); 173 } 174 175 void nfnl_queue_msg_put(struct nfnl_queue_msg *msg) 176 { 177 nl_object_put((struct nl_object *) msg); 178 } 179 180 /** @} */ 181 182 /** 183 * @name Attributes 184 * @{ 185 */ 186 187 void nfnl_queue_msg_set_group(struct nfnl_queue_msg *msg, uint16_t group) 188 { 189 msg->queue_msg_group = group; 190 msg->ce_mask |= QUEUE_MSG_ATTR_GROUP; 191 } 192 193 int nfnl_queue_msg_test_group(const struct nfnl_queue_msg *msg) 194 { 195 return !!(msg->ce_mask & QUEUE_MSG_ATTR_GROUP); 196 } 197 198 uint16_t nfnl_queue_msg_get_group(const struct nfnl_queue_msg *msg) 199 { 200 return msg->queue_msg_group; 201 } 202 203 /** 204 * Set the protocol family 205 * @arg msg NF queue message 206 * @arg family AF_XXX address family example: AF_INET, AF_UNIX, etc 207 */ 208 void nfnl_queue_msg_set_family(struct nfnl_queue_msg *msg, uint8_t family) 209 { 210 msg->queue_msg_family = family; 211 msg->ce_mask |= QUEUE_MSG_ATTR_FAMILY; 212 } 213 214 int nfnl_queue_msg_test_family(const struct nfnl_queue_msg *msg) 215 { 216 return !!(msg->ce_mask & QUEUE_MSG_ATTR_FAMILY); 217 } 218 219 uint8_t nfnl_queue_msg_get_family(const struct nfnl_queue_msg *msg) 220 { 221 if (msg->ce_mask & QUEUE_MSG_ATTR_FAMILY) 222 return msg->queue_msg_family; 223 else 224 return AF_UNSPEC; 225 } 226 227 void nfnl_queue_msg_set_packetid(struct nfnl_queue_msg *msg, uint32_t packetid) 228 { 229 msg->queue_msg_packetid = packetid; 230 msg->ce_mask |= QUEUE_MSG_ATTR_PACKETID; 231 } 232 233 int nfnl_queue_msg_test_packetid(const struct nfnl_queue_msg *msg) 234 { 235 return !!(msg->ce_mask & QUEUE_MSG_ATTR_PACKETID); 236 } 237 238 uint32_t nfnl_queue_msg_get_packetid(const struct nfnl_queue_msg *msg) 239 { 240 return msg->queue_msg_packetid; 241 } 242 243 void nfnl_queue_msg_set_hwproto(struct nfnl_queue_msg *msg, uint16_t hwproto) 244 { 245 msg->queue_msg_hwproto = hwproto; 246 msg->ce_mask |= QUEUE_MSG_ATTR_HWPROTO; 247 } 248 249 int nfnl_queue_msg_test_hwproto(const struct nfnl_queue_msg *msg) 250 { 251 return !!(msg->ce_mask & QUEUE_MSG_ATTR_HWPROTO); 252 } 253 254 uint16_t nfnl_queue_msg_get_hwproto(const struct nfnl_queue_msg *msg) 255 { 256 return msg->queue_msg_hwproto; 257 } 258 259 void nfnl_queue_msg_set_hook(struct nfnl_queue_msg *msg, uint8_t hook) 260 { 261 msg->queue_msg_hook = hook; 262 msg->ce_mask |= QUEUE_MSG_ATTR_HOOK; 263 } 264 265 int nfnl_queue_msg_test_hook(const struct nfnl_queue_msg *msg) 266 { 267 return !!(msg->ce_mask & QUEUE_MSG_ATTR_HOOK); 268 } 269 270 uint8_t nfnl_queue_msg_get_hook(const struct nfnl_queue_msg *msg) 271 { 272 return msg->queue_msg_hook; 273 } 274 275 void nfnl_queue_msg_set_mark(struct nfnl_queue_msg *msg, uint32_t mark) 276 { 277 msg->queue_msg_mark = mark; 278 msg->ce_mask |= QUEUE_MSG_ATTR_MARK; 279 } 280 281 int nfnl_queue_msg_test_mark(const struct nfnl_queue_msg *msg) 282 { 283 return !!(msg->ce_mask & QUEUE_MSG_ATTR_MARK); 284 } 285 286 uint32_t nfnl_queue_msg_get_mark(const struct nfnl_queue_msg *msg) 287 { 288 return msg->queue_msg_mark; 289 } 290 291 void nfnl_queue_msg_set_timestamp(struct nfnl_queue_msg *msg, 292 struct timeval *tv) 293 { 294 msg->queue_msg_timestamp.tv_sec = tv->tv_sec; 295 msg->queue_msg_timestamp.tv_usec = tv->tv_usec; 296 msg->ce_mask |= QUEUE_MSG_ATTR_TIMESTAMP; 297 } 298 299 int nfnl_queue_msg_test_timestamp(const struct nfnl_queue_msg *msg) 300 { 301 return !!(msg->ce_mask & QUEUE_MSG_ATTR_TIMESTAMP); 302 } 303 304 const struct timeval *nfnl_queue_msg_get_timestamp(const struct nfnl_queue_msg *msg) 305 { 306 if (!(msg->ce_mask & QUEUE_MSG_ATTR_TIMESTAMP)) 307 return NULL; 308 return &msg->queue_msg_timestamp; 309 } 310 311 void nfnl_queue_msg_set_indev(struct nfnl_queue_msg *msg, uint32_t indev) 312 { 313 msg->queue_msg_indev = indev; 314 msg->ce_mask |= QUEUE_MSG_ATTR_INDEV; 315 } 316 317 int nfnl_queue_msg_test_indev(const struct nfnl_queue_msg *msg) 318 { 319 return !!(msg->ce_mask & QUEUE_MSG_ATTR_INDEV); 320 } 321 322 uint32_t nfnl_queue_msg_get_indev(const struct nfnl_queue_msg *msg) 323 { 324 return msg->queue_msg_indev; 325 } 326 327 void nfnl_queue_msg_set_outdev(struct nfnl_queue_msg *msg, uint32_t outdev) 328 { 329 msg->queue_msg_outdev = outdev; 330 msg->ce_mask |= QUEUE_MSG_ATTR_OUTDEV; 331 } 332 333 int nfnl_queue_msg_test_outdev(const struct nfnl_queue_msg *msg) 334 { 335 return !!(msg->ce_mask & QUEUE_MSG_ATTR_OUTDEV); 336 } 337 338 uint32_t nfnl_queue_msg_get_outdev(const struct nfnl_queue_msg *msg) 339 { 340 return msg->queue_msg_outdev; 341 } 342 343 void nfnl_queue_msg_set_physindev(struct nfnl_queue_msg *msg, 344 uint32_t physindev) 345 { 346 msg->queue_msg_physindev = physindev; 347 msg->ce_mask |= QUEUE_MSG_ATTR_PHYSINDEV; 348 } 349 350 int nfnl_queue_msg_test_physindev(const struct nfnl_queue_msg *msg) 351 { 352 return !!(msg->ce_mask & QUEUE_MSG_ATTR_PHYSINDEV); 353 } 354 355 uint32_t nfnl_queue_msg_get_physindev(const struct nfnl_queue_msg *msg) 356 { 357 return msg->queue_msg_physindev; 358 } 359 360 void nfnl_queue_msg_set_physoutdev(struct nfnl_queue_msg *msg, 361 uint32_t physoutdev) 362 { 363 msg->queue_msg_physoutdev = physoutdev; 364 msg->ce_mask |= QUEUE_MSG_ATTR_PHYSOUTDEV; 365 } 366 367 int nfnl_queue_msg_test_physoutdev(const struct nfnl_queue_msg *msg) 368 { 369 return !!(msg->ce_mask & QUEUE_MSG_ATTR_PHYSOUTDEV); 370 } 371 372 uint32_t nfnl_queue_msg_get_physoutdev(const struct nfnl_queue_msg *msg) 373 { 374 return msg->queue_msg_physoutdev; 375 } 376 377 void nfnl_queue_msg_set_hwaddr(struct nfnl_queue_msg *msg, uint8_t *hwaddr, 378 int len) 379 { 380 if (len > sizeof(msg->queue_msg_hwaddr)) 381 len = sizeof(msg->queue_msg_hwaddr); 382 383 msg->queue_msg_hwaddr_len = len; 384 memcpy(msg->queue_msg_hwaddr, hwaddr, len); 385 msg->ce_mask |= QUEUE_MSG_ATTR_HWADDR; 386 } 387 388 int nfnl_queue_msg_test_hwaddr(const struct nfnl_queue_msg *msg) 389 { 390 return !!(msg->ce_mask & QUEUE_MSG_ATTR_HWADDR); 391 } 392 393 const uint8_t *nfnl_queue_msg_get_hwaddr(const struct nfnl_queue_msg *msg, 394 int *len) 395 { 396 if (!(msg->ce_mask & QUEUE_MSG_ATTR_HWADDR)) { 397 *len = 0; 398 return NULL; 399 } 400 401 *len = msg->queue_msg_hwaddr_len; 402 return msg->queue_msg_hwaddr; 403 } 404 405 int nfnl_queue_msg_set_payload(struct nfnl_queue_msg *msg, uint8_t *payload, 406 int len) 407 { 408 free(msg->queue_msg_payload); 409 msg->queue_msg_payload = malloc(len); 410 if (!msg->queue_msg_payload) 411 return -NLE_NOMEM; 412 413 memcpy(msg->queue_msg_payload, payload, len); 414 msg->queue_msg_payload_len = len; 415 msg->ce_mask |= QUEUE_MSG_ATTR_PAYLOAD; 416 return 0; 417 } 418 419 int nfnl_queue_msg_test_payload(const struct nfnl_queue_msg *msg) 420 { 421 return !!(msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD); 422 } 423 424 const void *nfnl_queue_msg_get_payload(const struct nfnl_queue_msg *msg, int *len) 425 { 426 if (!(msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD)) { 427 *len = 0; 428 return NULL; 429 } 430 431 *len = msg->queue_msg_payload_len; 432 return msg->queue_msg_payload; 433 } 434 435 /** 436 * Return the number of items matching a filter in the cache 437 * @arg msg queue msg 438 * @arg verdict NF_DROP, NF_ACCEPT, NF_REPEAT, etc 439 */ 440 void nfnl_queue_msg_set_verdict(struct nfnl_queue_msg *msg, 441 unsigned int verdict) 442 { 443 msg->queue_msg_verdict = verdict; 444 msg->ce_mask |= QUEUE_MSG_ATTR_VERDICT; 445 } 446 447 int nfnl_queue_msg_test_verdict(const struct nfnl_queue_msg *msg) 448 { 449 return !!(msg->ce_mask & QUEUE_MSG_ATTR_VERDICT); 450 } 451 452 unsigned int nfnl_queue_msg_get_verdict(const struct nfnl_queue_msg *msg) 453 { 454 return msg->queue_msg_verdict; 455 } 456 457 static const struct trans_tbl nfnl_queue_msg_attrs[] = { 458 __ADD(QUEUE_MSG_ATTR_GROUP, group) 459 __ADD(QUEUE_MSG_ATTR_FAMILY, family) 460 __ADD(QUEUE_MSG_ATTR_PACKETID, packetid) 461 __ADD(QUEUE_MSG_ATTR_HWPROTO, hwproto) 462 __ADD(QUEUE_MSG_ATTR_HOOK, hook) 463 __ADD(QUEUE_MSG_ATTR_MARK, mark) 464 __ADD(QUEUE_MSG_ATTR_TIMESTAMP, timestamp) 465 __ADD(QUEUE_MSG_ATTR_INDEV, indev) 466 __ADD(QUEUE_MSG_ATTR_OUTDEV, outdev) 467 __ADD(QUEUE_MSG_ATTR_PHYSINDEV, physindev) 468 __ADD(QUEUE_MSG_ATTR_PHYSOUTDEV, physoutdev) 469 __ADD(QUEUE_MSG_ATTR_HWADDR, hwaddr) 470 __ADD(QUEUE_MSG_ATTR_PAYLOAD, payload) 471 __ADD(QUEUE_MSG_ATTR_VERDICT, verdict) 472 }; 473 474 static char *nfnl_queue_msg_attrs2str(int attrs, char *buf, size_t len) 475 { 476 return __flags2str(attrs, buf, len, nfnl_queue_msg_attrs, 477 ARRAY_SIZE(nfnl_queue_msg_attrs)); 478 } 479 480 /** @} */ 481 482 struct nl_object_ops queue_msg_obj_ops = { 483 .oo_name = "netfilter/queuemsg", 484 .oo_size = sizeof(struct nfnl_queue_msg), 485 .oo_free_data = nfnl_queue_msg_free_data, 486 .oo_clone = nfnl_queue_msg_clone, 487 .oo_dump = { 488 [NL_DUMP_LINE] = nfnl_queue_msg_dump, 489 [NL_DUMP_DETAILS] = nfnl_queue_msg_dump, 490 [NL_DUMP_STATS] = nfnl_queue_msg_dump, 491 }, 492 .oo_attrs2str = nfnl_queue_msg_attrs2str, 493 }; 494 495 /** @} */ 496