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@trash.net> 10 */ 11 12#include <netlink-local.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 35static 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 45static 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; 59errout: 60 return err; 61} 62 63static 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("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 157/** 158 * @name Allocation/Freeing 159 * @{ 160 */ 161 162struct nfnl_queue_msg *nfnl_queue_msg_alloc(void) 163{ 164 return (struct nfnl_queue_msg *) nl_object_alloc(&queue_msg_obj_ops); 165} 166 167void nfnl_queue_msg_get(struct nfnl_queue_msg *msg) 168{ 169 nl_object_get((struct nl_object *) msg); 170} 171 172void nfnl_queue_msg_put(struct nfnl_queue_msg *msg) 173{ 174 nl_object_put((struct nl_object *) msg); 175} 176 177/** @} */ 178 179/** 180 * @name Attributes 181 * @{ 182 */ 183 184void nfnl_queue_msg_set_group(struct nfnl_queue_msg *msg, uint16_t group) 185{ 186 msg->queue_msg_group = group; 187 msg->ce_mask |= QUEUE_MSG_ATTR_GROUP; 188} 189 190int nfnl_queue_msg_test_group(const struct nfnl_queue_msg *msg) 191{ 192 return !!(msg->ce_mask & QUEUE_MSG_ATTR_GROUP); 193} 194 195uint16_t nfnl_queue_msg_get_group(const struct nfnl_queue_msg *msg) 196{ 197 return msg->queue_msg_group; 198} 199 200/** 201* Set the protocol family 202* @arg msg NF queue message 203* @arg family AF_XXX address family example: AF_INET, AF_UNIX, etc 204*/ 205void nfnl_queue_msg_set_family(struct nfnl_queue_msg *msg, uint8_t family) 206{ 207 msg->queue_msg_family = family; 208 msg->ce_mask |= QUEUE_MSG_ATTR_FAMILY; 209} 210 211int nfnl_queue_msg_test_family(const struct nfnl_queue_msg *msg) 212{ 213 return !!(msg->ce_mask & QUEUE_MSG_ATTR_FAMILY); 214} 215 216uint8_t nfnl_queue_msg_get_family(const struct nfnl_queue_msg *msg) 217{ 218 if (msg->ce_mask & QUEUE_MSG_ATTR_FAMILY) 219 return msg->queue_msg_family; 220 else 221 return AF_UNSPEC; 222} 223 224void nfnl_queue_msg_set_packetid(struct nfnl_queue_msg *msg, uint32_t packetid) 225{ 226 msg->queue_msg_packetid = packetid; 227 msg->ce_mask |= QUEUE_MSG_ATTR_PACKETID; 228} 229 230int nfnl_queue_msg_test_packetid(const struct nfnl_queue_msg *msg) 231{ 232 return !!(msg->ce_mask & QUEUE_MSG_ATTR_PACKETID); 233} 234 235uint32_t nfnl_queue_msg_get_packetid(const struct nfnl_queue_msg *msg) 236{ 237 return msg->queue_msg_packetid; 238} 239 240void nfnl_queue_msg_set_hwproto(struct nfnl_queue_msg *msg, uint16_t hwproto) 241{ 242 msg->queue_msg_hwproto = hwproto; 243 msg->ce_mask |= QUEUE_MSG_ATTR_HWPROTO; 244} 245 246int nfnl_queue_msg_test_hwproto(const struct nfnl_queue_msg *msg) 247{ 248 return !!(msg->ce_mask & QUEUE_MSG_ATTR_HWPROTO); 249} 250 251uint16_t nfnl_queue_msg_get_hwproto(const struct nfnl_queue_msg *msg) 252{ 253 return msg->queue_msg_hwproto; 254} 255 256void nfnl_queue_msg_set_hook(struct nfnl_queue_msg *msg, uint8_t hook) 257{ 258 msg->queue_msg_hook = hook; 259 msg->ce_mask |= QUEUE_MSG_ATTR_HOOK; 260} 261 262int nfnl_queue_msg_test_hook(const struct nfnl_queue_msg *msg) 263{ 264 return !!(msg->ce_mask & QUEUE_MSG_ATTR_HOOK); 265} 266 267uint8_t nfnl_queue_msg_get_hook(const struct nfnl_queue_msg *msg) 268{ 269 return msg->queue_msg_hook; 270} 271 272void nfnl_queue_msg_set_mark(struct nfnl_queue_msg *msg, uint32_t mark) 273{ 274 msg->queue_msg_mark = mark; 275 msg->ce_mask |= QUEUE_MSG_ATTR_MARK; 276} 277 278int nfnl_queue_msg_test_mark(const struct nfnl_queue_msg *msg) 279{ 280 return !!(msg->ce_mask & QUEUE_MSG_ATTR_MARK); 281} 282 283uint32_t nfnl_queue_msg_get_mark(const struct nfnl_queue_msg *msg) 284{ 285 return msg->queue_msg_mark; 286} 287 288void nfnl_queue_msg_set_timestamp(struct nfnl_queue_msg *msg, 289 struct timeval *tv) 290{ 291 msg->queue_msg_timestamp.tv_sec = tv->tv_sec; 292 msg->queue_msg_timestamp.tv_usec = tv->tv_usec; 293 msg->ce_mask |= QUEUE_MSG_ATTR_TIMESTAMP; 294} 295 296int nfnl_queue_msg_test_timestamp(const struct nfnl_queue_msg *msg) 297{ 298 return !!(msg->ce_mask & QUEUE_MSG_ATTR_TIMESTAMP); 299} 300 301const struct timeval *nfnl_queue_msg_get_timestamp(const struct nfnl_queue_msg *msg) 302{ 303 if (!(msg->ce_mask & QUEUE_MSG_ATTR_TIMESTAMP)) 304 return NULL; 305 return &msg->queue_msg_timestamp; 306} 307 308void nfnl_queue_msg_set_indev(struct nfnl_queue_msg *msg, uint32_t indev) 309{ 310 msg->queue_msg_indev = indev; 311 msg->ce_mask |= QUEUE_MSG_ATTR_INDEV; 312} 313 314int nfnl_queue_msg_test_indev(const struct nfnl_queue_msg *msg) 315{ 316 return !!(msg->ce_mask & QUEUE_MSG_ATTR_INDEV); 317} 318 319uint32_t nfnl_queue_msg_get_indev(const struct nfnl_queue_msg *msg) 320{ 321 return msg->queue_msg_indev; 322} 323 324void nfnl_queue_msg_set_outdev(struct nfnl_queue_msg *msg, uint32_t outdev) 325{ 326 msg->queue_msg_outdev = outdev; 327 msg->ce_mask |= QUEUE_MSG_ATTR_OUTDEV; 328} 329 330int nfnl_queue_msg_test_outdev(const struct nfnl_queue_msg *msg) 331{ 332 return !!(msg->ce_mask & QUEUE_MSG_ATTR_OUTDEV); 333} 334 335uint32_t nfnl_queue_msg_get_outdev(const struct nfnl_queue_msg *msg) 336{ 337 return msg->queue_msg_outdev; 338} 339 340void nfnl_queue_msg_set_physindev(struct nfnl_queue_msg *msg, 341 uint32_t physindev) 342{ 343 msg->queue_msg_physindev = physindev; 344 msg->ce_mask |= QUEUE_MSG_ATTR_PHYSINDEV; 345} 346 347int nfnl_queue_msg_test_physindev(const struct nfnl_queue_msg *msg) 348{ 349 return !!(msg->ce_mask & QUEUE_MSG_ATTR_PHYSINDEV); 350} 351 352uint32_t nfnl_queue_msg_get_physindev(const struct nfnl_queue_msg *msg) 353{ 354 return msg->queue_msg_physindev; 355} 356 357void nfnl_queue_msg_set_physoutdev(struct nfnl_queue_msg *msg, 358 uint32_t physoutdev) 359{ 360 msg->queue_msg_physoutdev = physoutdev; 361 msg->ce_mask |= QUEUE_MSG_ATTR_PHYSOUTDEV; 362} 363 364int nfnl_queue_msg_test_physoutdev(const struct nfnl_queue_msg *msg) 365{ 366 return !!(msg->ce_mask & QUEUE_MSG_ATTR_PHYSOUTDEV); 367} 368 369uint32_t nfnl_queue_msg_get_physoutdev(const struct nfnl_queue_msg *msg) 370{ 371 return msg->queue_msg_physoutdev; 372} 373 374void nfnl_queue_msg_set_hwaddr(struct nfnl_queue_msg *msg, uint8_t *hwaddr, 375 int len) 376{ 377 if (len > sizeof(msg->queue_msg_hwaddr)) 378 len = sizeof(msg->queue_msg_hwaddr); 379 380 msg->queue_msg_hwaddr_len = len; 381 memcpy(msg->queue_msg_hwaddr, hwaddr, len); 382 msg->ce_mask |= QUEUE_MSG_ATTR_HWADDR; 383} 384 385int nfnl_queue_msg_test_hwaddr(const struct nfnl_queue_msg *msg) 386{ 387 return !!(msg->ce_mask & QUEUE_MSG_ATTR_HWADDR); 388} 389 390const uint8_t *nfnl_queue_msg_get_hwaddr(const struct nfnl_queue_msg *msg, 391 int *len) 392{ 393 if (!(msg->ce_mask & QUEUE_MSG_ATTR_HWADDR)) { 394 *len = 0; 395 return NULL; 396 } 397 398 *len = msg->queue_msg_hwaddr_len; 399 return msg->queue_msg_hwaddr; 400} 401 402int nfnl_queue_msg_set_payload(struct nfnl_queue_msg *msg, uint8_t *payload, 403 int len) 404{ 405 free(msg->queue_msg_payload); 406 msg->queue_msg_payload = malloc(len); 407 if (!msg->queue_msg_payload) 408 return -NLE_NOMEM; 409 410 memcpy(msg->queue_msg_payload, payload, len); 411 msg->queue_msg_payload_len = len; 412 msg->ce_mask |= QUEUE_MSG_ATTR_PAYLOAD; 413 return 0; 414} 415 416int nfnl_queue_msg_test_payload(const struct nfnl_queue_msg *msg) 417{ 418 return !!(msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD); 419} 420 421const void *nfnl_queue_msg_get_payload(const struct nfnl_queue_msg *msg, int *len) 422{ 423 if (!(msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD)) { 424 *len = 0; 425 return NULL; 426 } 427 428 *len = msg->queue_msg_payload_len; 429 return msg->queue_msg_payload; 430} 431 432/** 433* Return the number of items matching a filter in the cache 434* @arg msg queue msg 435* @arg verdict NF_DROP, NF_ACCEPT, NF_REPEAT, etc 436*/ 437void nfnl_queue_msg_set_verdict(struct nfnl_queue_msg *msg, 438 unsigned int verdict) 439{ 440 msg->queue_msg_verdict = verdict; 441 msg->ce_mask |= QUEUE_MSG_ATTR_VERDICT; 442} 443 444int nfnl_queue_msg_test_verdict(const struct nfnl_queue_msg *msg) 445{ 446 return !!(msg->ce_mask & QUEUE_MSG_ATTR_VERDICT); 447} 448 449unsigned int nfnl_queue_msg_get_verdict(const struct nfnl_queue_msg *msg) 450{ 451 return msg->queue_msg_verdict; 452} 453 454static struct trans_tbl nfnl_queue_msg_attrs[] = { 455 __ADD(QUEUE_MSG_ATTR_GROUP, group) 456 __ADD(QUEUE_MSG_ATTR_FAMILY, family) 457 __ADD(QUEUE_MSG_ATTR_PACKETID, packetid) 458 __ADD(QUEUE_MSG_ATTR_HWPROTO, hwproto) 459 __ADD(QUEUE_MSG_ATTR_HOOK, hook) 460 __ADD(QUEUE_MSG_ATTR_MARK, mark) 461 __ADD(QUEUE_MSG_ATTR_TIMESTAMP, timestamp) 462 __ADD(QUEUE_MSG_ATTR_INDEV, indev) 463 __ADD(QUEUE_MSG_ATTR_OUTDEV, outdev) 464 __ADD(QUEUE_MSG_ATTR_PHYSINDEV, physindev) 465 __ADD(QUEUE_MSG_ATTR_PHYSOUTDEV, physoutdev) 466 __ADD(QUEUE_MSG_ATTR_HWADDR, hwaddr) 467 __ADD(QUEUE_MSG_ATTR_PAYLOAD, payload) 468 __ADD(QUEUE_MSG_ATTR_VERDICT, verdict) 469}; 470 471static char *nfnl_queue_msg_attrs2str(int attrs, char *buf, size_t len) 472{ 473 return __flags2str(attrs, buf, len, nfnl_queue_msg_attrs, 474 ARRAY_SIZE(nfnl_queue_msg_attrs)); 475} 476 477/** @} */ 478 479struct nl_object_ops queue_msg_obj_ops = { 480 .oo_name = "netfilter/queuemsg", 481 .oo_size = sizeof(struct nfnl_queue_msg), 482 .oo_free_data = nfnl_queue_msg_free_data, 483 .oo_clone = nfnl_queue_msg_clone, 484 .oo_dump = { 485 [NL_DUMP_LINE] = nfnl_queue_msg_dump, 486 [NL_DUMP_DETAILS] = nfnl_queue_msg_dump, 487 [NL_DUMP_STATS] = nfnl_queue_msg_dump, 488 }, 489 .oo_attrs2str = nfnl_queue_msg_attrs2str, 490}; 491 492/** @} */ 493