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-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 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("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 162 struct nfnl_queue_msg *nfnl_queue_msg_alloc(void) 163 { 164 return (struct nfnl_queue_msg *) nl_object_alloc(&queue_msg_obj_ops); 165 } 166 167 void nfnl_queue_msg_get(struct nfnl_queue_msg *msg) 168 { 169 nl_object_get((struct nl_object *) msg); 170 } 171 172 void 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 184 void 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 190 int nfnl_queue_msg_test_group(const struct nfnl_queue_msg *msg) 191 { 192 return !!(msg->ce_mask & QUEUE_MSG_ATTR_GROUP); 193 } 194 195 uint16_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 */ 205 void 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 211 int nfnl_queue_msg_test_family(const struct nfnl_queue_msg *msg) 212 { 213 return !!(msg->ce_mask & QUEUE_MSG_ATTR_FAMILY); 214 } 215 216 uint8_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 224 void 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 230 int nfnl_queue_msg_test_packetid(const struct nfnl_queue_msg *msg) 231 { 232 return !!(msg->ce_mask & QUEUE_MSG_ATTR_PACKETID); 233 } 234 235 uint32_t nfnl_queue_msg_get_packetid(const struct nfnl_queue_msg *msg) 236 { 237 return msg->queue_msg_packetid; 238 } 239 240 void 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 246 int nfnl_queue_msg_test_hwproto(const struct nfnl_queue_msg *msg) 247 { 248 return !!(msg->ce_mask & QUEUE_MSG_ATTR_HWPROTO); 249 } 250 251 uint16_t nfnl_queue_msg_get_hwproto(const struct nfnl_queue_msg *msg) 252 { 253 return msg->queue_msg_hwproto; 254 } 255 256 void 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 262 int nfnl_queue_msg_test_hook(const struct nfnl_queue_msg *msg) 263 { 264 return !!(msg->ce_mask & QUEUE_MSG_ATTR_HOOK); 265 } 266 267 uint8_t nfnl_queue_msg_get_hook(const struct nfnl_queue_msg *msg) 268 { 269 return msg->queue_msg_hook; 270 } 271 272 void 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 278 int nfnl_queue_msg_test_mark(const struct nfnl_queue_msg *msg) 279 { 280 return !!(msg->ce_mask & QUEUE_MSG_ATTR_MARK); 281 } 282 283 uint32_t nfnl_queue_msg_get_mark(const struct nfnl_queue_msg *msg) 284 { 285 return msg->queue_msg_mark; 286 } 287 288 void 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 296 int nfnl_queue_msg_test_timestamp(const struct nfnl_queue_msg *msg) 297 { 298 return !!(msg->ce_mask & QUEUE_MSG_ATTR_TIMESTAMP); 299 } 300 301 const 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 308 void 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 314 int nfnl_queue_msg_test_indev(const struct nfnl_queue_msg *msg) 315 { 316 return !!(msg->ce_mask & QUEUE_MSG_ATTR_INDEV); 317 } 318 319 uint32_t nfnl_queue_msg_get_indev(const struct nfnl_queue_msg *msg) 320 { 321 return msg->queue_msg_indev; 322 } 323 324 void 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 330 int nfnl_queue_msg_test_outdev(const struct nfnl_queue_msg *msg) 331 { 332 return !!(msg->ce_mask & QUEUE_MSG_ATTR_OUTDEV); 333 } 334 335 uint32_t nfnl_queue_msg_get_outdev(const struct nfnl_queue_msg *msg) 336 { 337 return msg->queue_msg_outdev; 338 } 339 340 void 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 347 int nfnl_queue_msg_test_physindev(const struct nfnl_queue_msg *msg) 348 { 349 return !!(msg->ce_mask & QUEUE_MSG_ATTR_PHYSINDEV); 350 } 351 352 uint32_t nfnl_queue_msg_get_physindev(const struct nfnl_queue_msg *msg) 353 { 354 return msg->queue_msg_physindev; 355 } 356 357 void 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 364 int nfnl_queue_msg_test_physoutdev(const struct nfnl_queue_msg *msg) 365 { 366 return !!(msg->ce_mask & QUEUE_MSG_ATTR_PHYSOUTDEV); 367 } 368 369 uint32_t nfnl_queue_msg_get_physoutdev(const struct nfnl_queue_msg *msg) 370 { 371 return msg->queue_msg_physoutdev; 372 } 373 374 void 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 385 int nfnl_queue_msg_test_hwaddr(const struct nfnl_queue_msg *msg) 386 { 387 return !!(msg->ce_mask & QUEUE_MSG_ATTR_HWADDR); 388 } 389 390 const 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 402 int 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 416 int nfnl_queue_msg_test_payload(const struct nfnl_queue_msg *msg) 417 { 418 return !!(msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD); 419 } 420 421 const 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 */ 437 void 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 444 int nfnl_queue_msg_test_verdict(const struct nfnl_queue_msg *msg) 445 { 446 return !!(msg->ce_mask & QUEUE_MSG_ATTR_VERDICT); 447 } 448 449 unsigned int nfnl_queue_msg_get_verdict(const struct nfnl_queue_msg *msg) 450 { 451 return msg->queue_msg_verdict; 452 } 453 454 static 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 471 static 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 479 struct 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