libnl
3.2.3
|
00001 /* 00002 * lib/netfilter/ct_obj.c Conntrack 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) 2003-2008 Thomas Graf <tgraf@suug.ch> 00010 * Copyright (c) 2007 Philip Craig <philipc@snapgear.com> 00011 * Copyright (c) 2007 Secure Computing Corporation 00012 */ 00013 00014 #include <sys/types.h> 00015 #include <linux/netfilter/nfnetlink_conntrack.h> 00016 #include <linux/netfilter/nf_conntrack_common.h> 00017 #include <linux/netfilter/nf_conntrack_tcp.h> 00018 00019 #include <netlink-local.h> 00020 #include <netlink/netfilter/nfnl.h> 00021 #include <netlink/netfilter/ct.h> 00022 00023 /** @cond SKIP */ 00024 #define CT_ATTR_FAMILY (1UL << 0) 00025 #define CT_ATTR_PROTO (1UL << 1) 00026 00027 #define CT_ATTR_TCP_STATE (1UL << 2) 00028 00029 #define CT_ATTR_STATUS (1UL << 3) 00030 #define CT_ATTR_TIMEOUT (1UL << 4) 00031 #define CT_ATTR_MARK (1UL << 5) 00032 #define CT_ATTR_USE (1UL << 6) 00033 #define CT_ATTR_ID (1UL << 7) 00034 00035 #define CT_ATTR_ORIG_SRC (1UL << 8) 00036 #define CT_ATTR_ORIG_DST (1UL << 9) 00037 #define CT_ATTR_ORIG_SRC_PORT (1UL << 10) 00038 #define CT_ATTR_ORIG_DST_PORT (1UL << 11) 00039 #define CT_ATTR_ORIG_ICMP_ID (1UL << 12) 00040 #define CT_ATTR_ORIG_ICMP_TYPE (1UL << 13) 00041 #define CT_ATTR_ORIG_ICMP_CODE (1UL << 14) 00042 #define CT_ATTR_ORIG_PACKETS (1UL << 15) 00043 #define CT_ATTR_ORIG_BYTES (1UL << 16) 00044 00045 #define CT_ATTR_REPL_SRC (1UL << 17) 00046 #define CT_ATTR_REPL_DST (1UL << 18) 00047 #define CT_ATTR_REPL_SRC_PORT (1UL << 19) 00048 #define CT_ATTR_REPL_DST_PORT (1UL << 20) 00049 #define CT_ATTR_REPL_ICMP_ID (1UL << 21) 00050 #define CT_ATTR_REPL_ICMP_TYPE (1UL << 22) 00051 #define CT_ATTR_REPL_ICMP_CODE (1UL << 23) 00052 #define CT_ATTR_REPL_PACKETS (1UL << 24) 00053 #define CT_ATTR_REPL_BYTES (1UL << 25) 00054 /** @endcond */ 00055 00056 static void ct_free_data(struct nl_object *c) 00057 { 00058 struct nfnl_ct *ct = (struct nfnl_ct *) c; 00059 00060 if (ct == NULL) 00061 return; 00062 00063 nl_addr_put(ct->ct_orig.src); 00064 nl_addr_put(ct->ct_orig.dst); 00065 nl_addr_put(ct->ct_repl.src); 00066 nl_addr_put(ct->ct_repl.dst); 00067 } 00068 00069 static int ct_clone(struct nl_object *_dst, struct nl_object *_src) 00070 { 00071 struct nfnl_ct *dst = (struct nfnl_ct *) _dst; 00072 struct nfnl_ct *src = (struct nfnl_ct *) _src; 00073 struct nl_addr *addr; 00074 00075 if (src->ct_orig.src) { 00076 addr = nl_addr_clone(src->ct_orig.src); 00077 if (!addr) 00078 return -NLE_NOMEM; 00079 dst->ct_orig.src = addr; 00080 } 00081 00082 if (src->ct_orig.dst) { 00083 addr = nl_addr_clone(src->ct_orig.dst); 00084 if (!addr) 00085 return -NLE_NOMEM; 00086 dst->ct_orig.dst = addr; 00087 } 00088 00089 if (src->ct_repl.src) { 00090 addr = nl_addr_clone(src->ct_repl.src); 00091 if (!addr) 00092 return -NLE_NOMEM; 00093 dst->ct_repl.src = addr; 00094 } 00095 00096 if (src->ct_repl.dst) { 00097 addr = nl_addr_clone(src->ct_repl.dst); 00098 if (!addr) 00099 return -NLE_NOMEM; 00100 dst->ct_repl.dst = addr; 00101 } 00102 00103 return 0; 00104 } 00105 00106 static void dump_addr(struct nl_dump_params *p, struct nl_addr *addr, int port) 00107 { 00108 char buf[64]; 00109 00110 if (addr) 00111 nl_dump(p, "%s", nl_addr2str(addr, buf, sizeof(buf))); 00112 00113 if (port) 00114 nl_dump(p, ":%u ", port); 00115 else if (addr) 00116 nl_dump(p, " "); 00117 } 00118 00119 static void dump_icmp(struct nl_dump_params *p, struct nfnl_ct *ct, int reply) 00120 { 00121 if (nfnl_ct_test_icmp_type(ct, reply)) 00122 nl_dump(p, "icmp type %d ", nfnl_ct_get_icmp_type(ct, reply)); 00123 00124 if (nfnl_ct_test_icmp_type(ct, reply)) 00125 nl_dump(p, "code %d ", nfnl_ct_get_icmp_code(ct, reply)); 00126 00127 if (nfnl_ct_test_icmp_type(ct, reply)) 00128 nl_dump(p, "id %d ", nfnl_ct_get_icmp_id(ct, reply)); 00129 } 00130 00131 static void ct_dump_tuples(struct nfnl_ct *ct, struct nl_dump_params *p) 00132 { 00133 struct nl_addr *orig_src, *orig_dst, *reply_src, *reply_dst; 00134 int orig_sport = 0, orig_dport = 0, reply_sport = 0, reply_dport = 0; 00135 int sync = 0; 00136 00137 orig_src = nfnl_ct_get_src(ct, 0); 00138 orig_dst = nfnl_ct_get_dst(ct, 0); 00139 reply_src = nfnl_ct_get_src(ct, 1); 00140 reply_dst = nfnl_ct_get_dst(ct, 1); 00141 00142 if (nfnl_ct_test_src_port(ct, 0)) 00143 orig_sport = nfnl_ct_get_src_port(ct, 0); 00144 00145 if (nfnl_ct_test_dst_port(ct, 0)) 00146 orig_dport = nfnl_ct_get_dst_port(ct, 0); 00147 00148 if (nfnl_ct_test_src_port(ct, 1)) 00149 reply_sport = nfnl_ct_get_src_port(ct, 1); 00150 00151 if (nfnl_ct_test_dst_port(ct, 1)) 00152 reply_dport = nfnl_ct_get_dst_port(ct, 1); 00153 00154 if (orig_src && orig_dst && reply_src && reply_dst && 00155 orig_sport == reply_dport && orig_dport == reply_sport && 00156 !nl_addr_cmp(orig_src, reply_dst) && 00157 !nl_addr_cmp(orig_dst, reply_src)) 00158 sync = 1; 00159 00160 dump_addr(p, orig_src, orig_sport); 00161 nl_dump(p, sync ? "<-> " : "-> "); 00162 dump_addr(p, orig_dst, orig_dport); 00163 dump_icmp(p, ct, 0); 00164 00165 if (!sync) { 00166 dump_addr(p, reply_src, reply_sport); 00167 nl_dump(p, "<- "); 00168 dump_addr(p, reply_dst, reply_dport); 00169 dump_icmp(p, ct, 1); 00170 } 00171 } 00172 00173 /* Compatible with /proc/net/nf_conntrack */ 00174 static void ct_dump_line(struct nl_object *a, struct nl_dump_params *p) 00175 { 00176 struct nfnl_ct *ct = (struct nfnl_ct *) a; 00177 char buf[64]; 00178 00179 nl_new_line(p); 00180 00181 if (nfnl_ct_test_proto(ct)) 00182 nl_dump(p, "%s ", 00183 nl_ip_proto2str(nfnl_ct_get_proto(ct), buf, sizeof(buf))); 00184 00185 if (nfnl_ct_test_tcp_state(ct)) 00186 nl_dump(p, "%s ", 00187 nfnl_ct_tcp_state2str(nfnl_ct_get_tcp_state(ct), 00188 buf, sizeof(buf))); 00189 00190 ct_dump_tuples(ct, p); 00191 00192 if (nfnl_ct_test_mark(ct) && nfnl_ct_get_mark(ct)) 00193 nl_dump(p, "mark %u ", nfnl_ct_get_mark(ct)); 00194 00195 nl_dump(p, "\n"); 00196 } 00197 00198 static void ct_dump_details(struct nl_object *a, struct nl_dump_params *p) 00199 { 00200 struct nfnl_ct *ct = (struct nfnl_ct *) a; 00201 char buf[64]; 00202 int fp = 0; 00203 00204 ct_dump_line(a, p); 00205 00206 nl_dump(p, " id 0x%x ", ct->ct_id); 00207 nl_dump_line(p, "family %s ", 00208 nl_af2str(ct->ct_family, buf, sizeof(buf))); 00209 00210 if (nfnl_ct_test_use(ct)) 00211 nl_dump(p, "refcnt %u ", nfnl_ct_get_use(ct)); 00212 00213 if (nfnl_ct_test_timeout(ct)) { 00214 uint64_t timeout_ms = nfnl_ct_get_timeout(ct) * 1000UL; 00215 nl_dump(p, "timeout %s ", 00216 nl_msec2str(timeout_ms, buf, sizeof(buf))); 00217 } 00218 00219 if (ct->ct_status) 00220 nl_dump(p, "<"); 00221 00222 #define PRINT_FLAG(str) \ 00223 { nl_dump(p, "%s%s", fp++ ? "," : "", (str)); } 00224 00225 if (ct->ct_status & IPS_EXPECTED) 00226 PRINT_FLAG("EXPECTED"); 00227 if (!(ct->ct_status & IPS_SEEN_REPLY)) 00228 PRINT_FLAG("NOREPLY"); 00229 if (ct->ct_status & IPS_ASSURED) 00230 PRINT_FLAG("ASSURED"); 00231 if (!(ct->ct_status & IPS_CONFIRMED)) 00232 PRINT_FLAG("NOTSENT"); 00233 if (ct->ct_status & IPS_SRC_NAT) 00234 PRINT_FLAG("SNAT"); 00235 if (ct->ct_status & IPS_DST_NAT) 00236 PRINT_FLAG("DNAT"); 00237 if (ct->ct_status & IPS_SEQ_ADJUST) 00238 PRINT_FLAG("SEQADJUST"); 00239 if (!(ct->ct_status & IPS_SRC_NAT_DONE)) 00240 PRINT_FLAG("SNAT_INIT"); 00241 if (!(ct->ct_status & IPS_DST_NAT_DONE)) 00242 PRINT_FLAG("DNAT_INIT"); 00243 if (ct->ct_status & IPS_DYING) 00244 PRINT_FLAG("DYING"); 00245 if (ct->ct_status & IPS_FIXED_TIMEOUT) 00246 PRINT_FLAG("FIXED_TIMEOUT"); 00247 #undef PRINT_FLAG 00248 00249 if (ct->ct_status) 00250 nl_dump(p, ">"); 00251 nl_dump(p, "\n"); 00252 } 00253 00254 static void ct_dump_stats(struct nl_object *a, struct nl_dump_params *p) 00255 { 00256 struct nfnl_ct *ct = (struct nfnl_ct *) a; 00257 double res; 00258 char *unit; 00259 00260 ct_dump_details(a, p); 00261 00262 nl_dump_line(p, " # packets volume\n"); 00263 00264 res = nl_cancel_down_bytes(nfnl_ct_get_bytes(ct, 1), &unit); 00265 nl_dump_line(p, " rx %10llu %7.2f %s\n", 00266 nfnl_ct_get_packets(ct, 1), res, unit); 00267 00268 res = nl_cancel_down_bytes(nfnl_ct_get_bytes(ct, 0), &unit); 00269 nl_dump_line(p, " tx %10llu %7.2f %s\n", 00270 nfnl_ct_get_packets(ct, 0), res, unit); 00271 } 00272 00273 static int ct_compare(struct nl_object *_a, struct nl_object *_b, 00274 uint32_t attrs, int flags) 00275 { 00276 struct nfnl_ct *a = (struct nfnl_ct *) _a; 00277 struct nfnl_ct *b = (struct nfnl_ct *) _b; 00278 int diff = 0; 00279 00280 #define CT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, CT_ATTR_##ATTR, a, b, EXPR) 00281 #define CT_DIFF_VAL(ATTR, FIELD) CT_DIFF(ATTR, a->FIELD != b->FIELD) 00282 #define CT_DIFF_ADDR(ATTR, FIELD) \ 00283 ((flags & LOOSE_COMPARISON) \ 00284 ? CT_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \ 00285 : CT_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD))) 00286 00287 diff |= CT_DIFF_VAL(FAMILY, ct_family); 00288 diff |= CT_DIFF_VAL(PROTO, ct_proto); 00289 diff |= CT_DIFF_VAL(TCP_STATE, ct_protoinfo.tcp.state); 00290 diff |= CT_DIFF_VAL(TIMEOUT, ct_timeout); 00291 diff |= CT_DIFF_VAL(MARK, ct_mark); 00292 diff |= CT_DIFF_VAL(USE, ct_use); 00293 diff |= CT_DIFF_VAL(ID, ct_id); 00294 diff |= CT_DIFF_ADDR(ORIG_SRC, ct_orig.src); 00295 diff |= CT_DIFF_ADDR(ORIG_DST, ct_orig.dst); 00296 diff |= CT_DIFF_VAL(ORIG_SRC_PORT, ct_orig.proto.port.src); 00297 diff |= CT_DIFF_VAL(ORIG_DST_PORT, ct_orig.proto.port.dst); 00298 diff |= CT_DIFF_VAL(ORIG_ICMP_ID, ct_orig.proto.icmp.id); 00299 diff |= CT_DIFF_VAL(ORIG_ICMP_TYPE, ct_orig.proto.icmp.type); 00300 diff |= CT_DIFF_VAL(ORIG_ICMP_CODE, ct_orig.proto.icmp.code); 00301 diff |= CT_DIFF_VAL(ORIG_PACKETS, ct_orig.packets); 00302 diff |= CT_DIFF_VAL(ORIG_BYTES, ct_orig.bytes); 00303 diff |= CT_DIFF_ADDR(REPL_SRC, ct_repl.src); 00304 diff |= CT_DIFF_ADDR(REPL_DST, ct_repl.dst); 00305 diff |= CT_DIFF_VAL(REPL_SRC_PORT, ct_repl.proto.port.src); 00306 diff |= CT_DIFF_VAL(REPL_DST_PORT, ct_repl.proto.port.dst); 00307 diff |= CT_DIFF_VAL(REPL_ICMP_ID, ct_repl.proto.icmp.id); 00308 diff |= CT_DIFF_VAL(REPL_ICMP_TYPE, ct_repl.proto.icmp.type); 00309 diff |= CT_DIFF_VAL(REPL_ICMP_CODE, ct_repl.proto.icmp.code); 00310 diff |= CT_DIFF_VAL(REPL_PACKETS, ct_repl.packets); 00311 diff |= CT_DIFF_VAL(REPL_BYTES, ct_repl.bytes); 00312 00313 if (flags & LOOSE_COMPARISON) 00314 diff |= CT_DIFF(STATUS, (a->ct_status ^ b->ct_status) & 00315 b->ct_status_mask); 00316 else 00317 diff |= CT_DIFF(STATUS, a->ct_status != b->ct_status); 00318 00319 #undef CT_DIFF 00320 #undef CT_DIFF_VAL 00321 #undef CT_DIFF_ADDR 00322 00323 return diff; 00324 } 00325 00326 static const struct trans_tbl ct_attrs[] = { 00327 __ADD(CT_ATTR_FAMILY, family) 00328 __ADD(CT_ATTR_PROTO, proto) 00329 __ADD(CT_ATTR_TCP_STATE, tcpstate) 00330 __ADD(CT_ATTR_STATUS, status) 00331 __ADD(CT_ATTR_TIMEOUT, timeout) 00332 __ADD(CT_ATTR_MARK, mark) 00333 __ADD(CT_ATTR_USE, use) 00334 __ADD(CT_ATTR_ID, id) 00335 __ADD(CT_ATTR_ORIG_SRC, origsrc) 00336 __ADD(CT_ATTR_ORIG_DST, origdst) 00337 __ADD(CT_ATTR_ORIG_SRC_PORT, origsrcport) 00338 __ADD(CT_ATTR_ORIG_DST_PORT, origdstport) 00339 __ADD(CT_ATTR_ORIG_ICMP_ID, origicmpid) 00340 __ADD(CT_ATTR_ORIG_ICMP_TYPE, origicmptype) 00341 __ADD(CT_ATTR_ORIG_ICMP_CODE, origicmpcode) 00342 __ADD(CT_ATTR_ORIG_PACKETS, origpackets) 00343 __ADD(CT_ATTR_ORIG_BYTES, origbytes) 00344 __ADD(CT_ATTR_REPL_SRC, replysrc) 00345 __ADD(CT_ATTR_REPL_DST, replydst) 00346 __ADD(CT_ATTR_REPL_SRC_PORT, replysrcport) 00347 __ADD(CT_ATTR_REPL_DST_PORT, replydstport) 00348 __ADD(CT_ATTR_REPL_ICMP_ID, replyicmpid) 00349 __ADD(CT_ATTR_REPL_ICMP_TYPE, replyicmptype) 00350 __ADD(CT_ATTR_REPL_ICMP_CODE, replyicmpcode) 00351 __ADD(CT_ATTR_REPL_PACKETS, replypackets) 00352 __ADD(CT_ATTR_REPL_BYTES, replybytes) 00353 }; 00354 00355 static char *ct_attrs2str(int attrs, char *buf, size_t len) 00356 { 00357 return __flags2str(attrs, buf, len, ct_attrs, ARRAY_SIZE(ct_attrs)); 00358 } 00359 00360 /** 00361 * @name Allocation/Freeing 00362 * @{ 00363 */ 00364 00365 struct nfnl_ct *nfnl_ct_alloc(void) 00366 { 00367 return (struct nfnl_ct *) nl_object_alloc(&ct_obj_ops); 00368 } 00369 00370 void nfnl_ct_get(struct nfnl_ct *ct) 00371 { 00372 nl_object_get((struct nl_object *) ct); 00373 } 00374 00375 void nfnl_ct_put(struct nfnl_ct *ct) 00376 { 00377 nl_object_put((struct nl_object *) ct); 00378 } 00379 00380 /** @} */ 00381 00382 /** 00383 * @name Attributes 00384 * @{ 00385 */ 00386 00387 void nfnl_ct_set_family(struct nfnl_ct *ct, uint8_t family) 00388 { 00389 ct->ct_family = family; 00390 ct->ce_mask |= CT_ATTR_FAMILY; 00391 } 00392 00393 uint8_t nfnl_ct_get_family(const struct nfnl_ct *ct) 00394 { 00395 if (ct->ce_mask & CT_ATTR_FAMILY) 00396 return ct->ct_family; 00397 else 00398 return AF_UNSPEC; 00399 } 00400 00401 void nfnl_ct_set_proto(struct nfnl_ct *ct, uint8_t proto) 00402 { 00403 ct->ct_proto = proto; 00404 ct->ce_mask |= CT_ATTR_PROTO; 00405 } 00406 00407 int nfnl_ct_test_proto(const struct nfnl_ct *ct) 00408 { 00409 return !!(ct->ce_mask & CT_ATTR_PROTO); 00410 } 00411 00412 uint8_t nfnl_ct_get_proto(const struct nfnl_ct *ct) 00413 { 00414 return ct->ct_proto; 00415 } 00416 00417 void nfnl_ct_set_tcp_state(struct nfnl_ct *ct, uint8_t state) 00418 { 00419 ct->ct_protoinfo.tcp.state = state; 00420 ct->ce_mask |= CT_ATTR_TCP_STATE; 00421 } 00422 00423 int nfnl_ct_test_tcp_state(const struct nfnl_ct *ct) 00424 { 00425 return !!(ct->ce_mask & CT_ATTR_TCP_STATE); 00426 } 00427 00428 uint8_t nfnl_ct_get_tcp_state(const struct nfnl_ct *ct) 00429 { 00430 return ct->ct_protoinfo.tcp.state; 00431 } 00432 00433 static const struct trans_tbl tcp_states[] = { 00434 __ADD(TCP_CONNTRACK_NONE,NONE) 00435 __ADD(TCP_CONNTRACK_SYN_SENT,SYN_SENT) 00436 __ADD(TCP_CONNTRACK_SYN_RECV,SYN_RECV) 00437 __ADD(TCP_CONNTRACK_ESTABLISHED,ESTABLISHED) 00438 __ADD(TCP_CONNTRACK_FIN_WAIT,FIN_WAIT) 00439 __ADD(TCP_CONNTRACK_CLOSE_WAIT,CLOSE_WAIT) 00440 __ADD(TCP_CONNTRACK_LAST_ACK,LAST_ACK) 00441 __ADD(TCP_CONNTRACK_TIME_WAIT,TIME_WAIT) 00442 __ADD(TCP_CONNTRACK_CLOSE,CLOSE) 00443 __ADD(TCP_CONNTRACK_LISTEN,LISTEN) 00444 }; 00445 00446 char *nfnl_ct_tcp_state2str(uint8_t state, char *buf, size_t len) 00447 { 00448 return __type2str(state, buf, len, tcp_states, ARRAY_SIZE(tcp_states)); 00449 } 00450 00451 int nfnl_ct_str2tcp_state(const char *name) 00452 { 00453 return __str2type(name, tcp_states, ARRAY_SIZE(tcp_states)); 00454 } 00455 00456 void nfnl_ct_set_status(struct nfnl_ct *ct, uint32_t status) 00457 { 00458 ct->ct_status_mask |= status; 00459 ct->ct_status |= status; 00460 ct->ce_mask |= CT_ATTR_STATUS; 00461 } 00462 00463 void nfnl_ct_unset_status(struct nfnl_ct *ct, uint32_t status) 00464 { 00465 ct->ct_status_mask |= status; 00466 ct->ct_status &= ~status; 00467 ct->ce_mask |= CT_ATTR_STATUS; 00468 } 00469 00470 uint32_t nfnl_ct_get_status(const struct nfnl_ct *ct) 00471 { 00472 return ct->ct_status; 00473 } 00474 00475 static const struct trans_tbl status_flags[] = { 00476 __ADD(IPS_EXPECTED, expected) 00477 __ADD(IPS_SEEN_REPLY, seen_reply) 00478 __ADD(IPS_ASSURED, assured) 00479 __ADD(IPS_CONFIRMED, confirmed) 00480 __ADD(IPS_SRC_NAT, snat) 00481 __ADD(IPS_DST_NAT, dnat) 00482 __ADD(IPS_SEQ_ADJUST, seqadjust) 00483 __ADD(IPS_SRC_NAT_DONE, snat_done) 00484 __ADD(IPS_DST_NAT_DONE, dnat_done) 00485 __ADD(IPS_DYING, dying) 00486 __ADD(IPS_FIXED_TIMEOUT, fixed_timeout) 00487 }; 00488 00489 char * nfnl_ct_status2str(int flags, char *buf, size_t len) 00490 { 00491 return __flags2str(flags, buf, len, status_flags, 00492 ARRAY_SIZE(status_flags)); 00493 } 00494 00495 int nfnl_ct_str2status(const char *name) 00496 { 00497 return __str2flags(name, status_flags, ARRAY_SIZE(status_flags)); 00498 } 00499 00500 void nfnl_ct_set_timeout(struct nfnl_ct *ct, uint32_t timeout) 00501 { 00502 ct->ct_timeout = timeout; 00503 ct->ce_mask |= CT_ATTR_TIMEOUT; 00504 } 00505 00506 int nfnl_ct_test_timeout(const struct nfnl_ct *ct) 00507 { 00508 return !!(ct->ce_mask & CT_ATTR_TIMEOUT); 00509 } 00510 00511 uint32_t nfnl_ct_get_timeout(const struct nfnl_ct *ct) 00512 { 00513 return ct->ct_timeout; 00514 } 00515 00516 void nfnl_ct_set_mark(struct nfnl_ct *ct, uint32_t mark) 00517 { 00518 ct->ct_mark = mark; 00519 ct->ce_mask |= CT_ATTR_MARK; 00520 } 00521 00522 int nfnl_ct_test_mark(const struct nfnl_ct *ct) 00523 { 00524 return !!(ct->ce_mask & CT_ATTR_MARK); 00525 } 00526 00527 uint32_t nfnl_ct_get_mark(const struct nfnl_ct *ct) 00528 { 00529 return ct->ct_mark; 00530 } 00531 00532 void nfnl_ct_set_use(struct nfnl_ct *ct, uint32_t use) 00533 { 00534 ct->ct_use = use; 00535 ct->ce_mask |= CT_ATTR_USE; 00536 } 00537 00538 int nfnl_ct_test_use(const struct nfnl_ct *ct) 00539 { 00540 return !!(ct->ce_mask & CT_ATTR_USE); 00541 } 00542 00543 uint32_t nfnl_ct_get_use(const struct nfnl_ct *ct) 00544 { 00545 return ct->ct_use; 00546 } 00547 00548 void nfnl_ct_set_id(struct nfnl_ct *ct, uint32_t id) 00549 { 00550 ct->ct_id = id; 00551 ct->ce_mask |= CT_ATTR_ID; 00552 } 00553 00554 int nfnl_ct_test_id(const struct nfnl_ct *ct) 00555 { 00556 return !!(ct->ce_mask & CT_ATTR_ID); 00557 } 00558 00559 uint32_t nfnl_ct_get_id(const struct nfnl_ct *ct) 00560 { 00561 return ct->ct_id; 00562 } 00563 00564 static int ct_set_addr(struct nfnl_ct *ct, struct nl_addr *addr, 00565 int attr, struct nl_addr ** ct_addr) 00566 { 00567 if (ct->ce_mask & CT_ATTR_FAMILY) { 00568 if (addr->a_family != ct->ct_family) 00569 return -NLE_AF_MISMATCH; 00570 } else 00571 nfnl_ct_set_family(ct, addr->a_family); 00572 00573 if (*ct_addr) 00574 nl_addr_put(*ct_addr); 00575 00576 nl_addr_get(addr); 00577 *ct_addr = addr; 00578 ct->ce_mask |= attr; 00579 00580 return 0; 00581 } 00582 00583 int nfnl_ct_set_src(struct nfnl_ct *ct, int repl, struct nl_addr *addr) 00584 { 00585 struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; 00586 int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC; 00587 return ct_set_addr(ct, addr, attr, &dir->src); 00588 } 00589 00590 int nfnl_ct_set_dst(struct nfnl_ct *ct, int repl, struct nl_addr *addr) 00591 { 00592 struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; 00593 int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST; 00594 return ct_set_addr(ct, addr, attr, &dir->dst); 00595 } 00596 00597 struct nl_addr *nfnl_ct_get_src(const struct nfnl_ct *ct, int repl) 00598 { 00599 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; 00600 int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC; 00601 if (!(ct->ce_mask & attr)) 00602 return NULL; 00603 return dir->src; 00604 } 00605 00606 struct nl_addr *nfnl_ct_get_dst(const struct nfnl_ct *ct, int repl) 00607 { 00608 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; 00609 int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST; 00610 if (!(ct->ce_mask & attr)) 00611 return NULL; 00612 return dir->dst; 00613 } 00614 00615 void nfnl_ct_set_src_port(struct nfnl_ct *ct, int repl, uint16_t port) 00616 { 00617 struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; 00618 int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT; 00619 00620 dir->proto.port.src = port; 00621 ct->ce_mask |= attr; 00622 } 00623 00624 int nfnl_ct_test_src_port(const struct nfnl_ct *ct, int repl) 00625 { 00626 int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT; 00627 return !!(ct->ce_mask & attr); 00628 } 00629 00630 uint16_t nfnl_ct_get_src_port(const struct nfnl_ct *ct, int repl) 00631 { 00632 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; 00633 00634 return dir->proto.port.src; 00635 } 00636 00637 void nfnl_ct_set_dst_port(struct nfnl_ct *ct, int repl, uint16_t port) 00638 { 00639 struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; 00640 int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT; 00641 00642 dir->proto.port.dst = port; 00643 ct->ce_mask |= attr; 00644 } 00645 00646 int nfnl_ct_test_dst_port(const struct nfnl_ct *ct, int repl) 00647 { 00648 int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT; 00649 return !!(ct->ce_mask & attr); 00650 } 00651 00652 uint16_t nfnl_ct_get_dst_port(const struct nfnl_ct *ct, int repl) 00653 { 00654 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; 00655 00656 return dir->proto.port.dst; 00657 } 00658 00659 void nfnl_ct_set_icmp_id(struct nfnl_ct *ct, int repl, uint16_t id) 00660 { 00661 struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; 00662 int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID; 00663 00664 dir->proto.icmp.id = id; 00665 ct->ce_mask |= attr; 00666 } 00667 00668 int nfnl_ct_test_icmp_id(const struct nfnl_ct *ct, int repl) 00669 { 00670 int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID; 00671 return !!(ct->ce_mask & attr); 00672 } 00673 00674 uint16_t nfnl_ct_get_icmp_id(const struct nfnl_ct *ct, int repl) 00675 { 00676 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; 00677 00678 return dir->proto.icmp.id; 00679 } 00680 00681 void nfnl_ct_set_icmp_type(struct nfnl_ct *ct, int repl, uint8_t type) 00682 { 00683 struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; 00684 int attr = repl ? CT_ATTR_REPL_ICMP_TYPE : CT_ATTR_ORIG_ICMP_TYPE; 00685 00686 dir->proto.icmp.type = type; 00687 ct->ce_mask |= attr; 00688 } 00689 00690 int nfnl_ct_test_icmp_type(const struct nfnl_ct *ct, int repl) 00691 { 00692 int attr = repl ? CT_ATTR_REPL_ICMP_TYPE : CT_ATTR_ORIG_ICMP_TYPE; 00693 return !!(ct->ce_mask & attr); 00694 } 00695 00696 uint8_t nfnl_ct_get_icmp_type(const struct nfnl_ct *ct, int repl) 00697 { 00698 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; 00699 00700 return dir->proto.icmp.type; 00701 } 00702 00703 void nfnl_ct_set_icmp_code(struct nfnl_ct *ct, int repl, uint8_t code) 00704 { 00705 struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; 00706 int attr = repl ? CT_ATTR_REPL_ICMP_CODE : CT_ATTR_ORIG_ICMP_CODE; 00707 00708 dir->proto.icmp.code = code; 00709 ct->ce_mask |= attr; 00710 } 00711 00712 int nfnl_ct_test_icmp_code(const struct nfnl_ct *ct, int repl) 00713 { 00714 int attr = repl ? CT_ATTR_REPL_ICMP_CODE : CT_ATTR_ORIG_ICMP_CODE; 00715 return !!(ct->ce_mask & attr); 00716 } 00717 00718 uint8_t nfnl_ct_get_icmp_code(const struct nfnl_ct *ct, int repl) 00719 { 00720 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; 00721 00722 return dir->proto.icmp.code; 00723 } 00724 00725 void nfnl_ct_set_packets(struct nfnl_ct *ct, int repl, uint64_t packets) 00726 { 00727 struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; 00728 int attr = repl ? CT_ATTR_REPL_PACKETS : CT_ATTR_ORIG_PACKETS; 00729 00730 dir->packets = packets; 00731 ct->ce_mask |= attr; 00732 } 00733 00734 int nfnl_ct_test_packets(const struct nfnl_ct *ct, int repl) 00735 { 00736 int attr = repl ? CT_ATTR_REPL_PACKETS : CT_ATTR_ORIG_PACKETS; 00737 return !!(ct->ce_mask & attr); 00738 } 00739 00740 uint64_t nfnl_ct_get_packets(const struct nfnl_ct *ct, int repl) 00741 { 00742 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; 00743 00744 return dir->packets; 00745 } 00746 00747 void nfnl_ct_set_bytes(struct nfnl_ct *ct, int repl, uint64_t bytes) 00748 { 00749 struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; 00750 int attr = repl ? CT_ATTR_REPL_BYTES : CT_ATTR_ORIG_BYTES; 00751 00752 dir->bytes = bytes; 00753 ct->ce_mask |= attr; 00754 } 00755 00756 int nfnl_ct_test_bytes(const struct nfnl_ct *ct, int repl) 00757 { 00758 int attr = repl ? CT_ATTR_REPL_BYTES : CT_ATTR_ORIG_BYTES; 00759 return !!(ct->ce_mask & attr); 00760 } 00761 00762 uint64_t nfnl_ct_get_bytes(const struct nfnl_ct *ct, int repl) 00763 { 00764 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; 00765 00766 return dir->bytes; 00767 } 00768 00769 /** @} */ 00770 00771 struct nl_object_ops ct_obj_ops = { 00772 .oo_name = "netfilter/ct", 00773 .oo_size = sizeof(struct nfnl_ct), 00774 .oo_free_data = ct_free_data, 00775 .oo_clone = ct_clone, 00776 .oo_dump = { 00777 [NL_DUMP_LINE] = ct_dump_line, 00778 [NL_DUMP_DETAILS] = ct_dump_details, 00779 [NL_DUMP_STATS] = ct_dump_stats, 00780 }, 00781 .oo_compare = ct_compare, 00782 .oo_attrs2str = ct_attrs2str, 00783 }; 00784 00785 /** @} */