libnl
3.2.3
|
00001 /* 00002 * lib/netfilter/queue_msg_obj.c Netfilter Queue Message Object 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation version 2.1 00007 * of the License. 00008 * 00009 * Copyright (c) 2007, 2008 Patrick McHardy <kaber@trash.net> 00010 */ 00011 00012 #include <netlink-local.h> 00013 #include <netlink/netfilter/nfnl.h> 00014 #include <netlink/netfilter/netfilter.h> 00015 #include <netlink/netfilter/queue_msg.h> 00016 #include <linux/netfilter.h> 00017 00018 /** @cond SKIP */ 00019 #define QUEUE_MSG_ATTR_GROUP (1UL << 0) 00020 #define QUEUE_MSG_ATTR_FAMILY (1UL << 1) 00021 #define QUEUE_MSG_ATTR_PACKETID (1UL << 2) 00022 #define QUEUE_MSG_ATTR_HWPROTO (1UL << 3) 00023 #define QUEUE_MSG_ATTR_HOOK (1UL << 4) 00024 #define QUEUE_MSG_ATTR_MARK (1UL << 5) 00025 #define QUEUE_MSG_ATTR_TIMESTAMP (1UL << 6) 00026 #define QUEUE_MSG_ATTR_INDEV (1UL << 7) 00027 #define QUEUE_MSG_ATTR_OUTDEV (1UL << 8) 00028 #define QUEUE_MSG_ATTR_PHYSINDEV (1UL << 9) 00029 #define QUEUE_MSG_ATTR_PHYSOUTDEV (1UL << 10) 00030 #define QUEUE_MSG_ATTR_HWADDR (1UL << 11) 00031 #define QUEUE_MSG_ATTR_PAYLOAD (1UL << 12) 00032 #define QUEUE_MSG_ATTR_VERDICT (1UL << 13) 00033 /** @endcond */ 00034 00035 static void nfnl_queue_msg_free_data(struct nl_object *c) 00036 { 00037 struct nfnl_queue_msg *msg = (struct nfnl_queue_msg *) c; 00038 00039 if (msg == NULL) 00040 return; 00041 00042 free(msg->queue_msg_payload); 00043 } 00044 00045 static int nfnl_queue_msg_clone(struct nl_object *_dst, struct nl_object *_src) 00046 { 00047 struct nfnl_queue_msg *dst = (struct nfnl_queue_msg *) _dst; 00048 struct nfnl_queue_msg *src = (struct nfnl_queue_msg *) _src; 00049 int err; 00050 00051 if (src->queue_msg_payload) { 00052 err = nfnl_queue_msg_set_payload(dst, src->queue_msg_payload, 00053 src->queue_msg_payload_len); 00054 if (err < 0) 00055 goto errout; 00056 } 00057 00058 return 0; 00059 errout: 00060 return err; 00061 } 00062 00063 static void nfnl_queue_msg_dump(struct nl_object *a, struct nl_dump_params *p) 00064 { 00065 struct nfnl_queue_msg *msg = (struct nfnl_queue_msg *) a; 00066 struct nl_cache *link_cache; 00067 char buf[64]; 00068 00069 link_cache = nl_cache_mngt_require("route/link"); 00070 00071 nl_new_line(p); 00072 00073 if (msg->ce_mask & QUEUE_MSG_ATTR_GROUP) 00074 nl_dump(p, "GROUP=%u ", msg->queue_msg_group); 00075 00076 if (msg->ce_mask & QUEUE_MSG_ATTR_INDEV) { 00077 if (link_cache) 00078 nl_dump(p, "IN=%s ", 00079 rtnl_link_i2name(link_cache, 00080 msg->queue_msg_indev, 00081 buf, sizeof(buf))); 00082 else 00083 nl_dump(p, "IN=%d ", msg->queue_msg_indev); 00084 } 00085 00086 if (msg->ce_mask & QUEUE_MSG_ATTR_PHYSINDEV) { 00087 if (link_cache) 00088 nl_dump(p, "PHYSIN=%s ", 00089 rtnl_link_i2name(link_cache, 00090 msg->queue_msg_physindev, 00091 buf, sizeof(buf))); 00092 else 00093 nl_dump(p, "IN=%d ", msg->queue_msg_physindev); 00094 } 00095 00096 if (msg->ce_mask & QUEUE_MSG_ATTR_OUTDEV) { 00097 if (link_cache) 00098 nl_dump(p, "OUT=%s ", 00099 rtnl_link_i2name(link_cache, 00100 msg->queue_msg_outdev, 00101 buf, sizeof(buf))); 00102 else 00103 nl_dump(p, "OUT=%d ", msg->queue_msg_outdev); 00104 } 00105 00106 if (msg->ce_mask & QUEUE_MSG_ATTR_PHYSOUTDEV) { 00107 if (link_cache) 00108 nl_dump(p, "PHYSOUT=%s ", 00109 rtnl_link_i2name(link_cache, 00110 msg->queue_msg_physoutdev, 00111 buf, sizeof(buf))); 00112 else 00113 nl_dump(p, "PHYSOUT=%d ", msg->queue_msg_physoutdev); 00114 } 00115 00116 if (msg->ce_mask & QUEUE_MSG_ATTR_HWADDR) { 00117 int i; 00118 00119 nl_dump(p, "MAC"); 00120 for (i = 0; i < msg->queue_msg_hwaddr_len; i++) 00121 nl_dump(p, "%c%02x", i?':':'=', 00122 msg->queue_msg_hwaddr[i]); 00123 nl_dump(p, " "); 00124 } 00125 00126 if (msg->ce_mask & QUEUE_MSG_ATTR_FAMILY) 00127 nl_dump(p, "FAMILY=%s ", 00128 nl_af2str(msg->queue_msg_family, buf, sizeof(buf))); 00129 00130 if (msg->ce_mask & QUEUE_MSG_ATTR_HWPROTO) 00131 nl_dump(p, "HWPROTO=%s ", 00132 nl_ether_proto2str(ntohs(msg->queue_msg_hwproto), 00133 buf, sizeof(buf))); 00134 00135 if (msg->ce_mask & QUEUE_MSG_ATTR_HOOK) 00136 nl_dump(p, "HOOK=%s ", 00137 nfnl_inet_hook2str(msg->queue_msg_hook, 00138 buf, sizeof(buf))); 00139 00140 if (msg->ce_mask & QUEUE_MSG_ATTR_MARK) 00141 nl_dump(p, "MARK=%d ", msg->queue_msg_mark); 00142 00143 if (msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD) 00144 nl_dump(p, "PAYLOADLEN=%d ", msg->queue_msg_payload_len); 00145 00146 if (msg->ce_mask & QUEUE_MSG_ATTR_PACKETID) 00147 nl_dump(p, "PACKETID=%u ", msg->queue_msg_packetid); 00148 00149 if (msg->ce_mask & QUEUE_MSG_ATTR_VERDICT) 00150 nl_dump(p, "VERDICT=%s ", 00151 nfnl_verdict2str(msg->queue_msg_verdict, 00152 buf, sizeof(buf))); 00153 00154 nl_dump(p, "\n"); 00155 } 00156 00157 /** 00158 * @name Allocation/Freeing 00159 * @{ 00160 */ 00161 00162 struct nfnl_queue_msg *nfnl_queue_msg_alloc(void) 00163 { 00164 return (struct nfnl_queue_msg *) nl_object_alloc(&queue_msg_obj_ops); 00165 } 00166 00167 void nfnl_queue_msg_get(struct nfnl_queue_msg *msg) 00168 { 00169 nl_object_get((struct nl_object *) msg); 00170 } 00171 00172 void nfnl_queue_msg_put(struct nfnl_queue_msg *msg) 00173 { 00174 nl_object_put((struct nl_object *) msg); 00175 } 00176 00177 /** @} */ 00178 00179 /** 00180 * @name Attributes 00181 * @{ 00182 */ 00183 00184 void nfnl_queue_msg_set_group(struct nfnl_queue_msg *msg, uint16_t group) 00185 { 00186 msg->queue_msg_group = group; 00187 msg->ce_mask |= QUEUE_MSG_ATTR_GROUP; 00188 } 00189 00190 int nfnl_queue_msg_test_group(const struct nfnl_queue_msg *msg) 00191 { 00192 return !!(msg->ce_mask & QUEUE_MSG_ATTR_GROUP); 00193 } 00194 00195 uint16_t nfnl_queue_msg_get_group(const struct nfnl_queue_msg *msg) 00196 { 00197 return msg->queue_msg_group; 00198 } 00199 00200 /** 00201 * Set the protocol family 00202 * @arg msg NF queue message 00203 * @arg family AF_XXX address family example: AF_INET, AF_UNIX, etc 00204 */ 00205 void nfnl_queue_msg_set_family(struct nfnl_queue_msg *msg, uint8_t family) 00206 { 00207 msg->queue_msg_family = family; 00208 msg->ce_mask |= QUEUE_MSG_ATTR_FAMILY; 00209 } 00210 00211 int nfnl_queue_msg_test_family(const struct nfnl_queue_msg *msg) 00212 { 00213 return !!(msg->ce_mask & QUEUE_MSG_ATTR_FAMILY); 00214 } 00215 00216 uint8_t nfnl_queue_msg_get_family(const struct nfnl_queue_msg *msg) 00217 { 00218 if (msg->ce_mask & QUEUE_MSG_ATTR_FAMILY) 00219 return msg->queue_msg_family; 00220 else 00221 return AF_UNSPEC; 00222 } 00223 00224 void nfnl_queue_msg_set_packetid(struct nfnl_queue_msg *msg, uint32_t packetid) 00225 { 00226 msg->queue_msg_packetid = packetid; 00227 msg->ce_mask |= QUEUE_MSG_ATTR_PACKETID; 00228 } 00229 00230 int nfnl_queue_msg_test_packetid(const struct nfnl_queue_msg *msg) 00231 { 00232 return !!(msg->ce_mask & QUEUE_MSG_ATTR_PACKETID); 00233 } 00234 00235 uint32_t nfnl_queue_msg_get_packetid(const struct nfnl_queue_msg *msg) 00236 { 00237 return msg->queue_msg_packetid; 00238 } 00239 00240 void nfnl_queue_msg_set_hwproto(struct nfnl_queue_msg *msg, uint16_t hwproto) 00241 { 00242 msg->queue_msg_hwproto = hwproto; 00243 msg->ce_mask |= QUEUE_MSG_ATTR_HWPROTO; 00244 } 00245 00246 int nfnl_queue_msg_test_hwproto(const struct nfnl_queue_msg *msg) 00247 { 00248 return !!(msg->ce_mask & QUEUE_MSG_ATTR_HWPROTO); 00249 } 00250 00251 uint16_t nfnl_queue_msg_get_hwproto(const struct nfnl_queue_msg *msg) 00252 { 00253 return msg->queue_msg_hwproto; 00254 } 00255 00256 void nfnl_queue_msg_set_hook(struct nfnl_queue_msg *msg, uint8_t hook) 00257 { 00258 msg->queue_msg_hook = hook; 00259 msg->ce_mask |= QUEUE_MSG_ATTR_HOOK; 00260 } 00261 00262 int nfnl_queue_msg_test_hook(const struct nfnl_queue_msg *msg) 00263 { 00264 return !!(msg->ce_mask & QUEUE_MSG_ATTR_HOOK); 00265 } 00266 00267 uint8_t nfnl_queue_msg_get_hook(const struct nfnl_queue_msg *msg) 00268 { 00269 return msg->queue_msg_hook; 00270 } 00271 00272 void nfnl_queue_msg_set_mark(struct nfnl_queue_msg *msg, uint32_t mark) 00273 { 00274 msg->queue_msg_mark = mark; 00275 msg->ce_mask |= QUEUE_MSG_ATTR_MARK; 00276 } 00277 00278 int nfnl_queue_msg_test_mark(const struct nfnl_queue_msg *msg) 00279 { 00280 return !!(msg->ce_mask & QUEUE_MSG_ATTR_MARK); 00281 } 00282 00283 uint32_t nfnl_queue_msg_get_mark(const struct nfnl_queue_msg *msg) 00284 { 00285 return msg->queue_msg_mark; 00286 } 00287 00288 void nfnl_queue_msg_set_timestamp(struct nfnl_queue_msg *msg, 00289 struct timeval *tv) 00290 { 00291 msg->queue_msg_timestamp.tv_sec = tv->tv_sec; 00292 msg->queue_msg_timestamp.tv_usec = tv->tv_usec; 00293 msg->ce_mask |= QUEUE_MSG_ATTR_TIMESTAMP; 00294 } 00295 00296 int nfnl_queue_msg_test_timestamp(const struct nfnl_queue_msg *msg) 00297 { 00298 return !!(msg->ce_mask & QUEUE_MSG_ATTR_TIMESTAMP); 00299 } 00300 00301 const struct timeval *nfnl_queue_msg_get_timestamp(const struct nfnl_queue_msg *msg) 00302 { 00303 if (!(msg->ce_mask & QUEUE_MSG_ATTR_TIMESTAMP)) 00304 return NULL; 00305 return &msg->queue_msg_timestamp; 00306 } 00307 00308 void nfnl_queue_msg_set_indev(struct nfnl_queue_msg *msg, uint32_t indev) 00309 { 00310 msg->queue_msg_indev = indev; 00311 msg->ce_mask |= QUEUE_MSG_ATTR_INDEV; 00312 } 00313 00314 int nfnl_queue_msg_test_indev(const struct nfnl_queue_msg *msg) 00315 { 00316 return !!(msg->ce_mask & QUEUE_MSG_ATTR_INDEV); 00317 } 00318 00319 uint32_t nfnl_queue_msg_get_indev(const struct nfnl_queue_msg *msg) 00320 { 00321 return msg->queue_msg_indev; 00322 } 00323 00324 void nfnl_queue_msg_set_outdev(struct nfnl_queue_msg *msg, uint32_t outdev) 00325 { 00326 msg->queue_msg_outdev = outdev; 00327 msg->ce_mask |= QUEUE_MSG_ATTR_OUTDEV; 00328 } 00329 00330 int nfnl_queue_msg_test_outdev(const struct nfnl_queue_msg *msg) 00331 { 00332 return !!(msg->ce_mask & QUEUE_MSG_ATTR_OUTDEV); 00333 } 00334 00335 uint32_t nfnl_queue_msg_get_outdev(const struct nfnl_queue_msg *msg) 00336 { 00337 return msg->queue_msg_outdev; 00338 } 00339 00340 void nfnl_queue_msg_set_physindev(struct nfnl_queue_msg *msg, 00341 uint32_t physindev) 00342 { 00343 msg->queue_msg_physindev = physindev; 00344 msg->ce_mask |= QUEUE_MSG_ATTR_PHYSINDEV; 00345 } 00346 00347 int nfnl_queue_msg_test_physindev(const struct nfnl_queue_msg *msg) 00348 { 00349 return !!(msg->ce_mask & QUEUE_MSG_ATTR_PHYSINDEV); 00350 } 00351 00352 uint32_t nfnl_queue_msg_get_physindev(const struct nfnl_queue_msg *msg) 00353 { 00354 return msg->queue_msg_physindev; 00355 } 00356 00357 void nfnl_queue_msg_set_physoutdev(struct nfnl_queue_msg *msg, 00358 uint32_t physoutdev) 00359 { 00360 msg->queue_msg_physoutdev = physoutdev; 00361 msg->ce_mask |= QUEUE_MSG_ATTR_PHYSOUTDEV; 00362 } 00363 00364 int nfnl_queue_msg_test_physoutdev(const struct nfnl_queue_msg *msg) 00365 { 00366 return !!(msg->ce_mask & QUEUE_MSG_ATTR_PHYSOUTDEV); 00367 } 00368 00369 uint32_t nfnl_queue_msg_get_physoutdev(const struct nfnl_queue_msg *msg) 00370 { 00371 return msg->queue_msg_physoutdev; 00372 } 00373 00374 void nfnl_queue_msg_set_hwaddr(struct nfnl_queue_msg *msg, uint8_t *hwaddr, 00375 int len) 00376 { 00377 if (len > sizeof(msg->queue_msg_hwaddr)) 00378 len = sizeof(msg->queue_msg_hwaddr); 00379 00380 msg->queue_msg_hwaddr_len = len; 00381 memcpy(msg->queue_msg_hwaddr, hwaddr, len); 00382 msg->ce_mask |= QUEUE_MSG_ATTR_HWADDR; 00383 } 00384 00385 int nfnl_queue_msg_test_hwaddr(const struct nfnl_queue_msg *msg) 00386 { 00387 return !!(msg->ce_mask & QUEUE_MSG_ATTR_HWADDR); 00388 } 00389 00390 const uint8_t *nfnl_queue_msg_get_hwaddr(const struct nfnl_queue_msg *msg, 00391 int *len) 00392 { 00393 if (!(msg->ce_mask & QUEUE_MSG_ATTR_HWADDR)) { 00394 *len = 0; 00395 return NULL; 00396 } 00397 00398 *len = msg->queue_msg_hwaddr_len; 00399 return msg->queue_msg_hwaddr; 00400 } 00401 00402 int nfnl_queue_msg_set_payload(struct nfnl_queue_msg *msg, uint8_t *payload, 00403 int len) 00404 { 00405 free(msg->queue_msg_payload); 00406 msg->queue_msg_payload = malloc(len); 00407 if (!msg->queue_msg_payload) 00408 return -NLE_NOMEM; 00409 00410 memcpy(msg->queue_msg_payload, payload, len); 00411 msg->queue_msg_payload_len = len; 00412 msg->ce_mask |= QUEUE_MSG_ATTR_PAYLOAD; 00413 return 0; 00414 } 00415 00416 int nfnl_queue_msg_test_payload(const struct nfnl_queue_msg *msg) 00417 { 00418 return !!(msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD); 00419 } 00420 00421 const void *nfnl_queue_msg_get_payload(const struct nfnl_queue_msg *msg, int *len) 00422 { 00423 if (!(msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD)) { 00424 *len = 0; 00425 return NULL; 00426 } 00427 00428 *len = msg->queue_msg_payload_len; 00429 return msg->queue_msg_payload; 00430 } 00431 00432 /** 00433 * Return the number of items matching a filter in the cache 00434 * @arg msg queue msg 00435 * @arg verdict NF_DROP, NF_ACCEPT, NF_REPEAT, etc 00436 */ 00437 void nfnl_queue_msg_set_verdict(struct nfnl_queue_msg *msg, 00438 unsigned int verdict) 00439 { 00440 msg->queue_msg_verdict = verdict; 00441 msg->ce_mask |= QUEUE_MSG_ATTR_VERDICT; 00442 } 00443 00444 int nfnl_queue_msg_test_verdict(const struct nfnl_queue_msg *msg) 00445 { 00446 return !!(msg->ce_mask & QUEUE_MSG_ATTR_VERDICT); 00447 } 00448 00449 unsigned int nfnl_queue_msg_get_verdict(const struct nfnl_queue_msg *msg) 00450 { 00451 return msg->queue_msg_verdict; 00452 } 00453 00454 static const struct trans_tbl nfnl_queue_msg_attrs[] = { 00455 __ADD(QUEUE_MSG_ATTR_GROUP, group) 00456 __ADD(QUEUE_MSG_ATTR_FAMILY, family) 00457 __ADD(QUEUE_MSG_ATTR_PACKETID, packetid) 00458 __ADD(QUEUE_MSG_ATTR_HWPROTO, hwproto) 00459 __ADD(QUEUE_MSG_ATTR_HOOK, hook) 00460 __ADD(QUEUE_MSG_ATTR_MARK, mark) 00461 __ADD(QUEUE_MSG_ATTR_TIMESTAMP, timestamp) 00462 __ADD(QUEUE_MSG_ATTR_INDEV, indev) 00463 __ADD(QUEUE_MSG_ATTR_OUTDEV, outdev) 00464 __ADD(QUEUE_MSG_ATTR_PHYSINDEV, physindev) 00465 __ADD(QUEUE_MSG_ATTR_PHYSOUTDEV, physoutdev) 00466 __ADD(QUEUE_MSG_ATTR_HWADDR, hwaddr) 00467 __ADD(QUEUE_MSG_ATTR_PAYLOAD, payload) 00468 __ADD(QUEUE_MSG_ATTR_VERDICT, verdict) 00469 }; 00470 00471 static char *nfnl_queue_msg_attrs2str(int attrs, char *buf, size_t len) 00472 { 00473 return __flags2str(attrs, buf, len, nfnl_queue_msg_attrs, 00474 ARRAY_SIZE(nfnl_queue_msg_attrs)); 00475 } 00476 00477 /** @} */ 00478 00479 struct nl_object_ops queue_msg_obj_ops = { 00480 .oo_name = "netfilter/queuemsg", 00481 .oo_size = sizeof(struct nfnl_queue_msg), 00482 .oo_free_data = nfnl_queue_msg_free_data, 00483 .oo_clone = nfnl_queue_msg_clone, 00484 .oo_dump = { 00485 [NL_DUMP_LINE] = nfnl_queue_msg_dump, 00486 [NL_DUMP_DETAILS] = nfnl_queue_msg_dump, 00487 [NL_DUMP_STATS] = nfnl_queue_msg_dump, 00488 }, 00489 .oo_attrs2str = nfnl_queue_msg_attrs2str, 00490 }; 00491 00492 /** @} */