libnl 1.1
lib/netfilter/ct_obj.c
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-2006 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                         goto errout;
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                         goto errout;
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                         goto errout;
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                         goto errout;
00100                 dst->ct_repl.dst = addr;
00101         }
00102 
00103         return 0;
00104 errout:
00105         return nl_get_errno();
00106 }
00107 
00108 static void ct_dump_dir(struct nfnl_ct *ct, int repl,
00109                         struct nl_dump_params *p)
00110 {
00111         struct nl_addr *addr;
00112         char addrbuf[64];
00113 
00114         addr = nfnl_ct_get_src(ct, repl);
00115         if (addr)
00116                 dp_dump(p, "src=%s ",
00117                         nl_addr2str(addr, addrbuf, sizeof(addrbuf)));
00118 
00119         addr = nfnl_ct_get_dst(ct, repl);
00120         if (addr)
00121                 dp_dump(p, "dst=%s ",
00122                         nl_addr2str(addr, addrbuf, sizeof(addrbuf)));
00123 
00124         if (nfnl_ct_test_src_port(ct, repl))
00125                 dp_dump(p, "sport=%u ", ntohs(nfnl_ct_get_src_port(ct, repl)));
00126         if (nfnl_ct_test_dst_port(ct, repl))
00127                 dp_dump(p, "dport=%u ", ntohs(nfnl_ct_get_dst_port(ct, repl)));
00128 
00129         if (nfnl_ct_test_icmp_type(ct, repl))
00130                 dp_dump(p, "type=%d ", nfnl_ct_get_icmp_type(ct, repl));
00131         if (nfnl_ct_test_icmp_type(ct, repl))
00132                 dp_dump(p, "code=%d ", nfnl_ct_get_icmp_code(ct, repl));
00133         if (nfnl_ct_test_icmp_type(ct, repl))
00134                 dp_dump(p, "id=%d ", ntohs(nfnl_ct_get_icmp_id(ct, repl)));
00135 
00136         if (nfnl_ct_test_packets(ct, repl))
00137                 dp_dump(p, "packets=%llu ", nfnl_ct_get_packets(ct, repl));
00138         if (nfnl_ct_test_bytes(ct, repl))
00139                 dp_dump(p, "bytes=%llu ", nfnl_ct_get_bytes(ct, repl));
00140 }
00141 
00142 /* Compatible with /proc/net/nf_conntrack */
00143 static int ct_dump(struct nl_object *a, struct nl_dump_params *p)
00144 {
00145         struct nfnl_ct *ct = (struct nfnl_ct *) a;
00146         char buf[64];
00147         uint32_t status;
00148         uint8_t family;
00149         uint8_t proto;
00150 
00151         family = nfnl_ct_get_family(ct);
00152         dp_dump(p, "%-8s %u ", nl_af2str(family, buf, sizeof(buf)), family);
00153 
00154         if (nfnl_ct_test_proto(ct)) {
00155                 proto = nfnl_ct_get_proto(ct);
00156                 dp_dump(p, "%-8s %u ",
00157                         nl_ip_proto2str(proto, buf, sizeof(buf)), proto);
00158         }
00159 
00160         if (nfnl_ct_test_timeout(ct))
00161                 dp_dump(p, "%ld ", nfnl_ct_get_timeout(ct));
00162 
00163         if (nfnl_ct_test_tcp_state(ct))
00164                 dp_dump(p, "%s ",
00165                         nfnl_ct_tcp_state2str(nfnl_ct_get_tcp_state(ct),
00166                                               buf, sizeof(buf)));
00167 
00168         ct_dump_dir(ct, 0, p);
00169 
00170         status = nfnl_ct_get_status(ct);
00171         if (!(status & IPS_SEEN_REPLY))
00172                 dp_dump(p, "[UNREPLIED] ");
00173 
00174         ct_dump_dir(ct, 1, p);
00175 
00176         if (status & IPS_ASSURED)
00177                 dp_dump(p, "[ASSURED] ");
00178 
00179         if (nfnl_ct_test_mark(ct))
00180                 dp_dump(p, "mark=%u ", nfnl_ct_get_mark(ct));
00181 
00182         if (nfnl_ct_test_use(ct))
00183                 dp_dump(p, "use=%u ", nfnl_ct_get_use(ct));
00184 
00185         dp_dump(p, "\n");
00186 
00187         return 1;
00188 }
00189 
00190 static int ct_compare(struct nl_object *_a, struct nl_object *_b,
00191                         uint32_t attrs, int flags)
00192 {
00193         struct nfnl_ct *a = (struct nfnl_ct *) _a;
00194         struct nfnl_ct *b = (struct nfnl_ct *) _b;
00195         int diff = 0;
00196 
00197 #define CT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, CT_ATTR_##ATTR, a, b, EXPR)
00198 #define CT_DIFF_VAL(ATTR, FIELD) CT_DIFF(ATTR, a->FIELD != b->FIELD)
00199 #define CT_DIFF_ADDR(ATTR, FIELD) \
00200         ((flags & LOOSE_FLAG_COMPARISON) \
00201                 ? CT_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \
00202                 : CT_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD)))
00203 
00204         diff |= CT_DIFF_VAL(FAMILY,             ct_family);
00205         diff |= CT_DIFF_VAL(PROTO,              ct_proto);
00206         diff |= CT_DIFF_VAL(TCP_STATE,          ct_protoinfo.tcp.state);
00207         diff |= CT_DIFF_VAL(TIMEOUT,            ct_timeout);
00208         diff |= CT_DIFF_VAL(MARK,               ct_mark);
00209         diff |= CT_DIFF_VAL(USE,                ct_use);
00210         diff |= CT_DIFF_VAL(ID,                 ct_id);
00211         diff |= CT_DIFF_ADDR(ORIG_SRC,          ct_orig.src);
00212         diff |= CT_DIFF_ADDR(ORIG_DST,          ct_orig.dst);
00213         diff |= CT_DIFF_VAL(ORIG_SRC_PORT,      ct_orig.proto.port.src);
00214         diff |= CT_DIFF_VAL(ORIG_DST_PORT,      ct_orig.proto.port.dst);
00215         diff |= CT_DIFF_VAL(ORIG_ICMP_ID,       ct_orig.proto.icmp.id);
00216         diff |= CT_DIFF_VAL(ORIG_ICMP_TYPE,     ct_orig.proto.icmp.type);
00217         diff |= CT_DIFF_VAL(ORIG_ICMP_CODE,     ct_orig.proto.icmp.code);
00218         diff |= CT_DIFF_VAL(ORIG_PACKETS,       ct_orig.packets);
00219         diff |= CT_DIFF_VAL(ORIG_BYTES,         ct_orig.bytes);
00220         diff |= CT_DIFF_ADDR(REPL_SRC,          ct_repl.src);
00221         diff |= CT_DIFF_ADDR(REPL_DST,          ct_repl.dst);
00222         diff |= CT_DIFF_VAL(REPL_SRC_PORT,      ct_repl.proto.port.src);
00223         diff |= CT_DIFF_VAL(REPL_DST_PORT,      ct_repl.proto.port.dst);
00224         diff |= CT_DIFF_VAL(REPL_ICMP_ID,       ct_repl.proto.icmp.id);
00225         diff |= CT_DIFF_VAL(REPL_ICMP_TYPE,     ct_repl.proto.icmp.type);
00226         diff |= CT_DIFF_VAL(REPL_ICMP_CODE,     ct_repl.proto.icmp.code);
00227         diff |= CT_DIFF_VAL(REPL_PACKETS,       ct_repl.packets);
00228         diff |= CT_DIFF_VAL(REPL_BYTES,         ct_repl.bytes);
00229 
00230         if (flags & LOOSE_FLAG_COMPARISON)
00231                 diff |= CT_DIFF(STATUS, (a->ct_status ^ b->ct_status) &
00232                                         b->ct_status_mask);
00233         else
00234                 diff |= CT_DIFF(STATUS, a->ct_status != b->ct_status);
00235 
00236 #undef CT_DIFF
00237 #undef CT_DIFF_VAL
00238 #undef CT_DIFF_ADDR
00239 
00240         return diff;
00241 }
00242 
00243 static struct trans_tbl ct_attrs[] = {
00244         __ADD(CT_ATTR_FAMILY,           family)
00245         __ADD(CT_ATTR_PROTO,            proto)
00246         __ADD(CT_ATTR_TCP_STATE,        tcpstate)
00247         __ADD(CT_ATTR_STATUS,           status)
00248         __ADD(CT_ATTR_TIMEOUT,          timeout)
00249         __ADD(CT_ATTR_MARK,             mark)
00250         __ADD(CT_ATTR_USE,              use)
00251         __ADD(CT_ATTR_ID,               id)
00252         __ADD(CT_ATTR_ORIG_SRC,         origsrc)
00253         __ADD(CT_ATTR_ORIG_DST,         origdst)
00254         __ADD(CT_ATTR_ORIG_SRC_PORT,    origsrcport)
00255         __ADD(CT_ATTR_ORIG_DST_PORT,    origdstport)
00256         __ADD(CT_ATTR_ORIG_ICMP_ID,     origicmpid)
00257         __ADD(CT_ATTR_ORIG_ICMP_TYPE,   origicmptype)
00258         __ADD(CT_ATTR_ORIG_ICMP_CODE,   origicmpcode)
00259         __ADD(CT_ATTR_ORIG_PACKETS,     origpackets)
00260         __ADD(CT_ATTR_ORIG_BYTES,       origbytes)
00261         __ADD(CT_ATTR_REPL_SRC,         replysrc)
00262         __ADD(CT_ATTR_REPL_DST,         replydst)
00263         __ADD(CT_ATTR_REPL_SRC_PORT,    replysrcport)
00264         __ADD(CT_ATTR_REPL_DST_PORT,    replydstport)
00265         __ADD(CT_ATTR_REPL_ICMP_ID,     replyicmpid)
00266         __ADD(CT_ATTR_REPL_ICMP_TYPE,   replyicmptype)
00267         __ADD(CT_ATTR_REPL_ICMP_CODE,   replyicmpcode)
00268         __ADD(CT_ATTR_REPL_PACKETS,     replypackets)
00269         __ADD(CT_ATTR_REPL_BYTES,       replybytes)
00270 };
00271 
00272 static char *ct_attrs2str(int attrs, char *buf, size_t len)
00273 {
00274         return __flags2str(attrs, buf, len, ct_attrs, ARRAY_SIZE(ct_attrs));
00275 }
00276 
00277 /**
00278  * @name Allocation/Freeing
00279  * @{
00280  */
00281 
00282 struct nfnl_ct *nfnl_ct_alloc(void)
00283 {
00284         return (struct nfnl_ct *) nl_object_alloc(&ct_obj_ops);
00285 }
00286 
00287 void nfnl_ct_get(struct nfnl_ct *ct)
00288 {
00289         nl_object_get((struct nl_object *) ct);
00290 }
00291 
00292 void nfnl_ct_put(struct nfnl_ct *ct)
00293 {
00294         nl_object_put((struct nl_object *) ct);
00295 }
00296 
00297 /** @} */
00298 
00299 /**
00300  * @name Attributes
00301  * @{
00302  */
00303 
00304 void nfnl_ct_set_family(struct nfnl_ct *ct, uint8_t family)
00305 {
00306         ct->ct_family = family;
00307         ct->ce_mask |= CT_ATTR_FAMILY;
00308 }
00309 
00310 uint8_t nfnl_ct_get_family(const struct nfnl_ct *ct)
00311 {
00312         if (ct->ce_mask & CT_ATTR_FAMILY)
00313                 return ct->ct_family;
00314         else
00315                 return AF_UNSPEC;
00316 }
00317 
00318 void nfnl_ct_set_proto(struct nfnl_ct *ct, uint8_t proto)
00319 {
00320         ct->ct_proto = proto;
00321         ct->ce_mask |= CT_ATTR_PROTO;
00322 }
00323 
00324 int nfnl_ct_test_proto(const struct nfnl_ct *ct)
00325 {
00326         return !!(ct->ce_mask & CT_ATTR_PROTO);
00327 }
00328 
00329 uint8_t nfnl_ct_get_proto(const struct nfnl_ct *ct)
00330 {
00331         return ct->ct_proto;
00332 }
00333 
00334 void nfnl_ct_set_tcp_state(struct nfnl_ct *ct, uint8_t state)
00335 {
00336         ct->ct_protoinfo.tcp.state = state;
00337         ct->ce_mask |= CT_ATTR_TCP_STATE;
00338 }
00339 
00340 int nfnl_ct_test_tcp_state(const struct nfnl_ct *ct)
00341 {
00342         return !!(ct->ce_mask & CT_ATTR_TCP_STATE);
00343 }
00344 
00345 uint8_t nfnl_ct_get_tcp_state(const struct nfnl_ct *ct)
00346 {
00347         return ct->ct_protoinfo.tcp.state;
00348 }
00349 
00350 static struct trans_tbl tcp_states[] = {
00351         __ADD(TCP_CONNTRACK_NONE,NONE)
00352         __ADD(TCP_CONNTRACK_SYN_SENT,SYN_SENT)
00353         __ADD(TCP_CONNTRACK_SYN_RECV,SYN_RECV)
00354         __ADD(TCP_CONNTRACK_ESTABLISHED,ESTABLISHED)
00355         __ADD(TCP_CONNTRACK_FIN_WAIT,FIN_WAIT)
00356         __ADD(TCP_CONNTRACK_CLOSE_WAIT,CLOSE_WAIT)
00357         __ADD(TCP_CONNTRACK_LAST_ACK,LAST_ACK)
00358         __ADD(TCP_CONNTRACK_TIME_WAIT,TIME_WAIT)
00359         __ADD(TCP_CONNTRACK_CLOSE,CLOSE)
00360         __ADD(TCP_CONNTRACK_LISTEN,LISTEN)
00361 };
00362 
00363 char *nfnl_ct_tcp_state2str(uint8_t state, char *buf, size_t len)
00364 {
00365         return __type2str(state, buf, len, tcp_states, ARRAY_SIZE(tcp_states));
00366 }
00367 
00368 int nfnl_ct_str2tcp_state(const char *name)
00369 {
00370         return __str2type(name, tcp_states, ARRAY_SIZE(tcp_states));
00371 }
00372 
00373 void nfnl_ct_set_status(struct nfnl_ct *ct, uint32_t status)
00374 {
00375         ct->ct_status_mask |= status;
00376         ct->ct_status |= status;
00377         ct->ce_mask |= CT_ATTR_STATUS;
00378 }
00379 
00380 void nfnl_ct_unset_status(struct nfnl_ct *ct, uint32_t status)
00381 {
00382         ct->ct_status_mask |= status;
00383         ct->ct_status &= ~status;
00384         ct->ce_mask |= CT_ATTR_STATUS;
00385 }
00386 
00387 uint32_t nfnl_ct_get_status(const struct nfnl_ct *ct)
00388 {
00389         return ct->ct_status;
00390 }
00391 
00392 void nfnl_ct_set_timeout(struct nfnl_ct *ct, uint32_t timeout)
00393 {
00394         ct->ct_timeout = timeout;
00395         ct->ce_mask |= CT_ATTR_TIMEOUT;
00396 }
00397 
00398 int nfnl_ct_test_timeout(const struct nfnl_ct *ct)
00399 {
00400         return !!(ct->ce_mask & CT_ATTR_TIMEOUT);
00401 }
00402 
00403 uint32_t nfnl_ct_get_timeout(const struct nfnl_ct *ct)
00404 {
00405         return ct->ct_timeout;
00406 }
00407 
00408 void nfnl_ct_set_mark(struct nfnl_ct *ct, uint32_t mark)
00409 {
00410         ct->ct_mark = mark;
00411         ct->ce_mask |= CT_ATTR_MARK;
00412 }
00413 
00414 int nfnl_ct_test_mark(const struct nfnl_ct *ct)
00415 {
00416         return !!(ct->ce_mask & CT_ATTR_MARK);
00417 }
00418 
00419 uint32_t nfnl_ct_get_mark(const struct nfnl_ct *ct)
00420 {
00421         return ct->ct_mark;
00422 }
00423 
00424 void nfnl_ct_set_use(struct nfnl_ct *ct, uint32_t use)
00425 {
00426         ct->ct_use = use;
00427         ct->ce_mask |= CT_ATTR_USE;
00428 }
00429 
00430 int nfnl_ct_test_use(const struct nfnl_ct *ct)
00431 {
00432         return !!(ct->ce_mask & CT_ATTR_USE);
00433 }
00434 
00435 uint32_t nfnl_ct_get_use(const struct nfnl_ct *ct)
00436 {
00437         return ct->ct_use;
00438 }
00439 
00440 void nfnl_ct_set_id(struct nfnl_ct *ct, uint32_t id)
00441 {
00442         ct->ct_id = id;
00443         ct->ce_mask |= CT_ATTR_ID;
00444 }
00445 
00446 int nfnl_ct_test_id(const struct nfnl_ct *ct)
00447 {
00448         return !!(ct->ce_mask & CT_ATTR_ID);
00449 }
00450 
00451 uint32_t nfnl_ct_get_id(const struct nfnl_ct *ct)
00452 {
00453         return ct->ct_id;
00454 }
00455 
00456 static int ct_set_addr(struct nfnl_ct *ct, struct nl_addr *addr,
00457                 int attr, struct nl_addr ** ct_addr)
00458 {
00459         if (ct->ce_mask & CT_ATTR_FAMILY) {
00460                 if (addr->a_family != ct->ct_family)
00461                         return nl_error(EINVAL, "Address family mismatch");
00462         } else
00463                 nfnl_ct_set_family(ct, addr->a_family);
00464 
00465         if (*ct_addr)
00466                 nl_addr_put(*ct_addr);
00467 
00468         nl_addr_get(addr);
00469         *ct_addr = addr;
00470         ct->ce_mask |= attr;
00471 
00472         return 0;
00473 }
00474 
00475 int nfnl_ct_set_src(struct nfnl_ct *ct, int repl, struct nl_addr *addr)
00476 {
00477         struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
00478         int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC;
00479         return ct_set_addr(ct, addr, attr, &dir->src);
00480 }
00481 
00482 int nfnl_ct_set_dst(struct nfnl_ct *ct, int repl, struct nl_addr *addr)
00483 {
00484         struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
00485         int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST;
00486         return ct_set_addr(ct, addr, attr, &dir->dst);
00487 }
00488 
00489 struct nl_addr *nfnl_ct_get_src(const struct nfnl_ct *ct, int repl)
00490 {
00491         const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
00492         int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC;
00493         if (!(ct->ce_mask & attr))
00494                 return NULL;
00495         return dir->src;
00496 }
00497 
00498 struct nl_addr *nfnl_ct_get_dst(const struct nfnl_ct *ct, int repl)
00499 {
00500         const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
00501         int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST;
00502         if (!(ct->ce_mask & attr))
00503                 return NULL;
00504         return dir->dst;
00505 }
00506 
00507 void nfnl_ct_set_src_port(struct nfnl_ct *ct, int repl, uint16_t port)
00508 {
00509         struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
00510         int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT;
00511 
00512         dir->proto.port.src = port;
00513         ct->ce_mask |= attr;
00514 }
00515 
00516 int nfnl_ct_test_src_port(const struct nfnl_ct *ct, int repl)
00517 {
00518         int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT;
00519         return !!(ct->ce_mask & attr);
00520 }
00521 
00522 uint16_t nfnl_ct_get_src_port(const struct nfnl_ct *ct, int repl)
00523 {
00524         const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
00525 
00526         return dir->proto.port.src;
00527 }
00528 
00529 void nfnl_ct_set_dst_port(struct nfnl_ct *ct, int repl, uint16_t port)
00530 {
00531         struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
00532         int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT;
00533 
00534         dir->proto.port.dst = port;
00535         ct->ce_mask |= attr;
00536 }
00537 
00538 int nfnl_ct_test_dst_port(const struct nfnl_ct *ct, int repl)
00539 {
00540         int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT;
00541         return !!(ct->ce_mask & attr);
00542 }
00543 
00544 uint16_t nfnl_ct_get_dst_port(const struct nfnl_ct *ct, int repl)
00545 {
00546         const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
00547 
00548         return dir->proto.port.dst;
00549 }
00550 
00551 void nfnl_ct_set_icmp_id(struct nfnl_ct *ct, int repl, uint16_t id)
00552 {
00553         struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
00554         int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID;
00555 
00556         dir->proto.icmp.id = id;
00557         ct->ce_mask |= attr;
00558 }
00559 
00560 int nfnl_ct_test_icmp_id(const struct nfnl_ct *ct, int repl)
00561 {
00562         int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID;
00563         return !!(ct->ce_mask & attr);
00564 }
00565 
00566 uint16_t nfnl_ct_get_icmp_id(const struct nfnl_ct *ct, int repl)
00567 {
00568         const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
00569 
00570         return dir->proto.icmp.id;
00571 }
00572 
00573 void nfnl_ct_set_icmp_type(struct nfnl_ct *ct, int repl, uint8_t type)
00574 {
00575         struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
00576         int attr = repl ? CT_ATTR_REPL_ICMP_TYPE : CT_ATTR_ORIG_ICMP_TYPE;
00577 
00578         dir->proto.icmp.type = type;
00579         ct->ce_mask |= attr;
00580 }
00581 
00582 int nfnl_ct_test_icmp_type(const struct nfnl_ct *ct, int repl)
00583 {
00584         int attr = repl ? CT_ATTR_REPL_ICMP_TYPE : CT_ATTR_ORIG_ICMP_TYPE;
00585         return !!(ct->ce_mask & attr);
00586 }
00587 
00588 uint8_t nfnl_ct_get_icmp_type(const struct nfnl_ct *ct, int repl)
00589 {
00590         const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
00591 
00592         return dir->proto.icmp.type;
00593 }
00594 
00595 void nfnl_ct_set_icmp_code(struct nfnl_ct *ct, int repl, uint8_t code)
00596 {
00597         struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
00598         int attr = repl ? CT_ATTR_REPL_ICMP_CODE : CT_ATTR_ORIG_ICMP_CODE;
00599 
00600         dir->proto.icmp.code = code;
00601         ct->ce_mask |= attr;
00602 }
00603 
00604 int nfnl_ct_test_icmp_code(const struct nfnl_ct *ct, int repl)
00605 {
00606         int attr = repl ? CT_ATTR_REPL_ICMP_CODE : CT_ATTR_ORIG_ICMP_CODE;
00607         return !!(ct->ce_mask & attr);
00608 }
00609 
00610 uint8_t nfnl_ct_get_icmp_code(const struct nfnl_ct *ct, int repl)
00611 {
00612         const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
00613 
00614         return dir->proto.icmp.code;
00615 }
00616 
00617 void nfnl_ct_set_packets(struct nfnl_ct *ct, int repl, uint64_t packets)
00618 {
00619         struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
00620         int attr = repl ? CT_ATTR_REPL_PACKETS : CT_ATTR_ORIG_PACKETS;
00621 
00622         dir->packets = packets;
00623         ct->ce_mask |= attr;
00624 }
00625 
00626 int nfnl_ct_test_packets(const struct nfnl_ct *ct, int repl)
00627 {
00628         int attr = repl ? CT_ATTR_REPL_PACKETS : CT_ATTR_ORIG_PACKETS;
00629         return !!(ct->ce_mask & attr);
00630 }
00631 
00632 uint64_t nfnl_ct_get_packets(const struct nfnl_ct *ct, int repl)
00633 {
00634         const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
00635 
00636         return dir->packets;
00637 }
00638 
00639 void nfnl_ct_set_bytes(struct nfnl_ct *ct, int repl, uint64_t bytes)
00640 {
00641         struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
00642         int attr = repl ? CT_ATTR_REPL_BYTES : CT_ATTR_ORIG_BYTES;
00643 
00644         dir->bytes = bytes;
00645         ct->ce_mask |= attr;
00646 }
00647 
00648 int nfnl_ct_test_bytes(const struct nfnl_ct *ct, int repl)
00649 {
00650         int attr = repl ? CT_ATTR_REPL_BYTES : CT_ATTR_ORIG_BYTES;
00651         return !!(ct->ce_mask & attr);
00652 }
00653 
00654 uint64_t nfnl_ct_get_bytes(const struct nfnl_ct *ct, int repl)
00655 {
00656         const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
00657 
00658         return dir->bytes;
00659 }
00660 
00661 /** @} */
00662 
00663 struct nl_object_ops ct_obj_ops = {
00664         .oo_name                = "netfilter/ct",
00665         .oo_size                = sizeof(struct nfnl_ct),
00666         .oo_free_data           = ct_free_data,
00667         .oo_clone               = ct_clone,
00668         .oo_dump[NL_DUMP_BRIEF] = ct_dump,
00669         .oo_dump[NL_DUMP_FULL]  = ct_dump,
00670         .oo_dump[NL_DUMP_STATS] = ct_dump,
00671         .oo_compare             = ct_compare,
00672         .oo_attrs2str           = ct_attrs2str,
00673 };
00674 
00675 /** @} */