00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <byteswap.h>
00023 #include <sys/types.h>
00024 #include <linux/netfilter/nfnetlink_conntrack.h>
00025
00026 #include <netlink-local.h>
00027 #include <netlink/attr.h>
00028 #include <netlink/netfilter/nfnl.h>
00029 #include <netlink/netfilter/ct.h>
00030
00031 static struct nl_cache_ops nfnl_ct_ops;
00032
00033 #if __BYTE_ORDER == __BIG_ENDIAN
00034 static uint64_t ntohll(uint64_t x)
00035 {
00036 return x;
00037 }
00038 #elif __BYTE_ORDER == __LITTLE_ENDIAN
00039 static uint64_t ntohll(uint64_t x)
00040 {
00041 return __bswap_64(x);
00042 }
00043 #endif
00044
00045 static struct nla_policy ct_policy[CTA_MAX+1] = {
00046 [CTA_TUPLE_ORIG] = { .type = NLA_NESTED },
00047 [CTA_TUPLE_REPLY] = { .type = NLA_NESTED },
00048 [CTA_STATUS] = { .type = NLA_U32 },
00049 [CTA_PROTOINFO] = { .type = NLA_NESTED },
00050
00051
00052 [CTA_TIMEOUT] = { .type = NLA_U32 },
00053 [CTA_MARK] = { .type = NLA_U32 },
00054 [CTA_COUNTERS_ORIG] = { .type = NLA_NESTED },
00055 [CTA_COUNTERS_REPLY] = { .type = NLA_NESTED },
00056 [CTA_USE] = { .type = NLA_U32 },
00057 [CTA_ID] = { .type = NLA_U32 },
00058
00059 };
00060
00061 static struct nla_policy ct_tuple_policy[CTA_TUPLE_MAX+1] = {
00062 [CTA_TUPLE_IP] = { .type = NLA_NESTED },
00063 [CTA_TUPLE_PROTO] = { .type = NLA_NESTED },
00064 };
00065
00066 static struct nla_policy ct_ip_policy[CTA_IP_MAX+1] = {
00067 [CTA_IP_V4_SRC] = { .type = NLA_U32 },
00068 [CTA_IP_V4_DST] = { .type = NLA_U32 },
00069 [CTA_IP_V6_SRC] = { .minlen = 16 },
00070 [CTA_IP_V6_DST] = { .minlen = 16 },
00071 };
00072
00073 static struct nla_policy ct_proto_policy[CTA_PROTO_MAX+1] = {
00074 [CTA_PROTO_NUM] = { .type = NLA_U8 },
00075 [CTA_PROTO_SRC_PORT] = { .type = NLA_U16 },
00076 [CTA_PROTO_DST_PORT] = { .type = NLA_U16 },
00077 [CTA_PROTO_ICMP_ID] = { .type = NLA_U16 },
00078 [CTA_PROTO_ICMP_TYPE] = { .type = NLA_U8 },
00079 [CTA_PROTO_ICMP_CODE] = { .type = NLA_U8 },
00080 [CTA_PROTO_ICMPV6_ID] = { .type = NLA_U16 },
00081 [CTA_PROTO_ICMPV6_TYPE] = { .type = NLA_U8 },
00082 [CTA_PROTO_ICMPV6_CODE] = { .type = NLA_U8 },
00083 };
00084
00085 static struct nla_policy ct_protoinfo_policy[CTA_PROTOINFO_MAX+1] = {
00086 [CTA_PROTOINFO_TCP] = { .type = NLA_NESTED },
00087 };
00088
00089 static struct nla_policy ct_protoinfo_tcp_policy[CTA_PROTOINFO_TCP_MAX+1] = {
00090 [CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 },
00091 [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 },
00092 [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 },
00093 [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .minlen = 2 },
00094 [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .minlen = 2 },
00095
00096 };
00097
00098 static struct nla_policy ct_counters_policy[CTA_COUNTERS_MAX+1] = {
00099 [CTA_COUNTERS_PACKETS] = { .type = NLA_U64 },
00100 [CTA_COUNTERS_BYTES] = { .type = NLA_U64 },
00101 [CTA_COUNTERS32_PACKETS]= { .type = NLA_U32 },
00102 [CTA_COUNTERS32_BYTES] = { .type = NLA_U32 },
00103 };
00104
00105 static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr)
00106 {
00107 struct nlattr *tb[CTA_IP_MAX+1];
00108 struct nl_addr *addr;
00109 int err;
00110
00111 err = nla_parse_nested(tb, CTA_IP_MAX, attr, ct_ip_policy);
00112 if (err < 0)
00113 goto errout;
00114
00115 if (tb[CTA_IP_V4_SRC]) {
00116 addr = nl_addr_alloc_attr(tb[CTA_IP_V4_SRC], AF_INET);
00117 if (addr == NULL)
00118 goto errout_enomem;
00119 err = nfnl_ct_set_src(ct, repl, addr);
00120 nl_addr_put(addr);
00121 if (err < 0)
00122 goto errout;
00123 }
00124 if (tb[CTA_IP_V4_DST]) {
00125 addr = nl_addr_alloc_attr(tb[CTA_IP_V4_DST], AF_INET);
00126 if (addr == NULL)
00127 goto errout_enomem;
00128 err = nfnl_ct_set_dst(ct, repl, addr);
00129 nl_addr_put(addr);
00130 if (err < 0)
00131 goto errout;
00132 }
00133 if (tb[CTA_IP_V6_SRC]) {
00134 addr = nl_addr_alloc_attr(tb[CTA_IP_V6_SRC], AF_INET6);
00135 if (addr == NULL)
00136 goto errout_enomem;
00137 err = nfnl_ct_set_src(ct, repl, addr);
00138 nl_addr_put(addr);
00139 if (err < 0)
00140 goto errout;
00141 }
00142 if (tb[CTA_IP_V6_DST]) {
00143 addr = nl_addr_alloc_attr(tb[CTA_IP_V6_DST], AF_INET6);
00144 if (addr == NULL)
00145 goto errout_enomem;
00146 err = nfnl_ct_set_dst(ct, repl, addr);
00147 nl_addr_put(addr);
00148 if (err < 0)
00149 goto errout;
00150 }
00151
00152 return 0;
00153
00154 errout_enomem:
00155 err = -NLE_NOMEM;
00156 errout:
00157 return err;
00158 }
00159
00160 static int ct_parse_proto(struct nfnl_ct *ct, int repl, struct nlattr *attr)
00161 {
00162 struct nlattr *tb[CTA_PROTO_MAX+1];
00163 int err;
00164
00165 err = nla_parse_nested(tb, CTA_PROTO_MAX, attr, ct_proto_policy);
00166 if (err < 0)
00167 return err;
00168
00169 if (!repl && tb[CTA_PROTO_NUM])
00170 nfnl_ct_set_proto(ct, nla_get_u8(tb[CTA_PROTO_NUM]));
00171 if (tb[CTA_PROTO_SRC_PORT])
00172 nfnl_ct_set_src_port(ct, repl,
00173 ntohs(nla_get_u16(tb[CTA_PROTO_SRC_PORT])));
00174 if (tb[CTA_PROTO_DST_PORT])
00175 nfnl_ct_set_dst_port(ct, repl,
00176 ntohs(nla_get_u16(tb[CTA_PROTO_DST_PORT])));
00177 if (tb[CTA_PROTO_ICMP_ID])
00178 nfnl_ct_set_icmp_id(ct, repl,
00179 ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID])));
00180 if (tb[CTA_PROTO_ICMP_TYPE])
00181 nfnl_ct_set_icmp_type(ct, repl,
00182 nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]));
00183 if (tb[CTA_PROTO_ICMP_CODE])
00184 nfnl_ct_set_icmp_code(ct, repl,
00185 nla_get_u8(tb[CTA_PROTO_ICMP_CODE]));
00186
00187 return 0;
00188 }
00189
00190 static int ct_parse_tuple(struct nfnl_ct *ct, int repl, struct nlattr *attr)
00191 {
00192 struct nlattr *tb[CTA_TUPLE_MAX+1];
00193 int err;
00194
00195 err = nla_parse_nested(tb, CTA_TUPLE_MAX, attr, ct_tuple_policy);
00196 if (err < 0)
00197 return err;
00198
00199 if (tb[CTA_TUPLE_IP]) {
00200 err = ct_parse_ip(ct, repl, tb[CTA_TUPLE_IP]);
00201 if (err < 0)
00202 return err;
00203 }
00204
00205 if (tb[CTA_TUPLE_PROTO]) {
00206 err = ct_parse_proto(ct, repl, tb[CTA_TUPLE_PROTO]);
00207 if (err < 0)
00208 return err;
00209 }
00210
00211 return 0;
00212 }
00213
00214 static int ct_parse_protoinfo_tcp(struct nfnl_ct *ct, struct nlattr *attr)
00215 {
00216 struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1];
00217 int err;
00218
00219 err = nla_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr,
00220 ct_protoinfo_tcp_policy);
00221 if (err < 0)
00222 return err;
00223
00224 if (tb[CTA_PROTOINFO_TCP_STATE])
00225 nfnl_ct_set_tcp_state(ct,
00226 nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]));
00227
00228 return 0;
00229 }
00230
00231 static int ct_parse_protoinfo(struct nfnl_ct *ct, struct nlattr *attr)
00232 {
00233 struct nlattr *tb[CTA_PROTOINFO_MAX+1];
00234 int err;
00235
00236 err = nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr,
00237 ct_protoinfo_policy);
00238 if (err < 0)
00239 return err;
00240
00241 if (tb[CTA_PROTOINFO_TCP]) {
00242 err = ct_parse_protoinfo_tcp(ct, tb[CTA_PROTOINFO_TCP]);
00243 if (err < 0)
00244 return err;
00245 }
00246
00247 return 0;
00248 }
00249
00250 static int ct_parse_counters(struct nfnl_ct *ct, int repl, struct nlattr *attr)
00251 {
00252 struct nlattr *tb[CTA_COUNTERS_MAX+1];
00253 int err;
00254
00255 err = nla_parse_nested(tb, CTA_COUNTERS_MAX, attr, ct_counters_policy);
00256 if (err < 0)
00257 return err;
00258
00259 if (tb[CTA_COUNTERS_PACKETS])
00260 nfnl_ct_set_packets(ct, repl,
00261 ntohll(nla_get_u64(tb[CTA_COUNTERS_PACKETS])));
00262 if (tb[CTA_COUNTERS32_PACKETS])
00263 nfnl_ct_set_packets(ct, repl,
00264 ntohl(nla_get_u32(tb[CTA_COUNTERS32_PACKETS])));
00265 if (tb[CTA_COUNTERS_BYTES])
00266 nfnl_ct_set_bytes(ct, repl,
00267 ntohll(nla_get_u64(tb[CTA_COUNTERS_BYTES])));
00268 if (tb[CTA_COUNTERS32_BYTES])
00269 nfnl_ct_set_bytes(ct, repl,
00270 ntohl(nla_get_u32(tb[CTA_COUNTERS32_BYTES])));
00271
00272 return 0;
00273 }
00274
00275 int nfnlmsg_ct_group(struct nlmsghdr *nlh)
00276 {
00277 switch (nfnlmsg_subtype(nlh)) {
00278 case IPCTNL_MSG_CT_NEW:
00279 if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL))
00280 return NFNLGRP_CONNTRACK_NEW;
00281 else
00282 return NFNLGRP_CONNTRACK_UPDATE;
00283 case IPCTNL_MSG_CT_DELETE:
00284 return NFNLGRP_CONNTRACK_DESTROY;
00285 default:
00286 return NFNLGRP_NONE;
00287 }
00288 }
00289
00290 int nfnlmsg_ct_parse(struct nlmsghdr *nlh, struct nfnl_ct **result)
00291 {
00292 struct nfnl_ct *ct;
00293 struct nlattr *tb[CTA_MAX+1];
00294 int err;
00295
00296 ct = nfnl_ct_alloc();
00297 if (!ct)
00298 return -NLE_NOMEM;
00299
00300 ct->ce_msgtype = nlh->nlmsg_type;
00301
00302 err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_MAX,
00303 ct_policy);
00304 if (err < 0)
00305 goto errout;
00306
00307 nfnl_ct_set_family(ct, nfnlmsg_family(nlh));
00308
00309 if (tb[CTA_TUPLE_ORIG]) {
00310 err = ct_parse_tuple(ct, 0, tb[CTA_TUPLE_ORIG]);
00311 if (err < 0)
00312 goto errout;
00313 }
00314 if (tb[CTA_TUPLE_REPLY]) {
00315 err = ct_parse_tuple(ct, 1, tb[CTA_TUPLE_REPLY]);
00316 if (err < 0)
00317 goto errout;
00318 }
00319
00320 if (tb[CTA_PROTOINFO]) {
00321 err = ct_parse_protoinfo(ct, tb[CTA_PROTOINFO]);
00322 if (err < 0)
00323 goto errout;
00324 }
00325
00326 if (tb[CTA_STATUS])
00327 nfnl_ct_set_status(ct, ntohl(nla_get_u32(tb[CTA_STATUS])));
00328 if (tb[CTA_TIMEOUT])
00329 nfnl_ct_set_timeout(ct, ntohl(nla_get_u32(tb[CTA_TIMEOUT])));
00330 if (tb[CTA_MARK])
00331 nfnl_ct_set_mark(ct, ntohl(nla_get_u32(tb[CTA_MARK])));
00332 if (tb[CTA_USE])
00333 nfnl_ct_set_use(ct, ntohl(nla_get_u32(tb[CTA_USE])));
00334 if (tb[CTA_ID])
00335 nfnl_ct_set_id(ct, ntohl(nla_get_u32(tb[CTA_ID])));
00336
00337 if (tb[CTA_COUNTERS_ORIG]) {
00338 err = ct_parse_counters(ct, 0, tb[CTA_COUNTERS_ORIG]);
00339 if (err < 0)
00340 goto errout;
00341 }
00342
00343 if (tb[CTA_COUNTERS_REPLY]) {
00344 err = ct_parse_counters(ct, 1, tb[CTA_COUNTERS_REPLY]);
00345 if (err < 0)
00346 goto errout;
00347 }
00348
00349 *result = ct;
00350 return 0;
00351
00352 errout:
00353 nfnl_ct_put(ct);
00354 return err;
00355 }
00356
00357 static int ct_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
00358 struct nlmsghdr *nlh, struct nl_parser_param *pp)
00359 {
00360 struct nfnl_ct *ct;
00361 int err;
00362
00363 if ((err = nfnlmsg_ct_parse(nlh, &ct)) < 0)
00364 goto errout;
00365
00366 err = pp->pp_cb((struct nl_object *) ct, pp);
00367 errout:
00368 nfnl_ct_put(ct);
00369 return err;
00370 }
00371
00372 int nfnl_ct_dump_request(struct nl_sock *sk)
00373 {
00374 return nfnl_send_simple(sk, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET,
00375 NLM_F_DUMP, AF_UNSPEC, 0);
00376 }
00377
00378 static int ct_request_update(struct nl_cache *cache, struct nl_sock *sk)
00379 {
00380 return nfnl_ct_dump_request(sk);
00381 }
00382
00383 static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct,
00384 int repl)
00385 {
00386 struct nlattr *tuple, *ip, *proto;
00387 struct nl_addr *addr;
00388 int family;
00389
00390 family = nfnl_ct_get_family(ct);
00391
00392 tuple = nla_nest_start(msg, repl ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG);
00393 if (!tuple)
00394 goto nla_put_failure;
00395
00396 ip = nla_nest_start(msg, CTA_TUPLE_IP);
00397 if (!ip)
00398 goto nla_put_failure;
00399
00400 addr = nfnl_ct_get_src(ct, repl);
00401 if (addr)
00402 NLA_PUT_ADDR(msg,
00403 family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC,
00404 addr);
00405
00406 addr = nfnl_ct_get_dst(ct, repl);
00407 if (addr)
00408 NLA_PUT_ADDR(msg,
00409 family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST,
00410 addr);
00411
00412 nla_nest_end(msg, ip);
00413
00414 proto = nla_nest_start(msg, CTA_TUPLE_PROTO);
00415 if (!proto)
00416 goto nla_put_failure;
00417
00418 if (nfnl_ct_test_proto(ct))
00419 NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_ct_get_proto(ct));
00420
00421 if (nfnl_ct_test_src_port(ct, repl))
00422 NLA_PUT_U16(msg, CTA_PROTO_SRC_PORT,
00423 htons(nfnl_ct_get_src_port(ct, repl)));
00424
00425 if (nfnl_ct_test_dst_port(ct, repl))
00426 NLA_PUT_U16(msg, CTA_PROTO_DST_PORT,
00427 htons(nfnl_ct_get_dst_port(ct, repl)));
00428
00429 if (nfnl_ct_test_icmp_id(ct, repl))
00430 NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID,
00431 htons(nfnl_ct_get_icmp_id(ct, repl)));
00432
00433 if (nfnl_ct_test_icmp_type(ct, repl))
00434 NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE,
00435 nfnl_ct_get_icmp_type(ct, repl));
00436
00437 if (nfnl_ct_test_icmp_code(ct, repl))
00438 NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE,
00439 nfnl_ct_get_icmp_code(ct, repl));
00440
00441 nla_nest_end(msg, proto);
00442
00443 nla_nest_end(msg, tuple);
00444 return 0;
00445
00446 nla_put_failure:
00447 return -NLE_MSGSIZE;
00448 }
00449
00450 static int nfnl_ct_build_message(const struct nfnl_ct *ct, int cmd, int flags,
00451 struct nl_msg **result)
00452 {
00453 struct nl_msg *msg;
00454 int err;
00455
00456 msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK, cmd, flags,
00457 nfnl_ct_get_family(ct), 0);
00458 if (msg == NULL)
00459 return -NLE_NOMEM;
00460
00461 if ((err = nfnl_ct_build_tuple(msg, ct, 0)) < 0)
00462 goto err_out;
00463
00464 *result = msg;
00465 return 0;
00466
00467 err_out:
00468 nlmsg_free(msg);
00469 return err;
00470 }
00471
00472 int nfnl_ct_build_add_request(const struct nfnl_ct *ct, int flags,
00473 struct nl_msg **result)
00474 {
00475 return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_NEW, flags, result);
00476 }
00477
00478 int nfnl_ct_add(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
00479 {
00480 struct nl_msg *msg;
00481 int err;
00482
00483 if ((err = nfnl_ct_build_add_request(ct, flags, &msg)) < 0)
00484 return err;
00485
00486 err = nl_send_auto_complete(sk, msg);
00487 nlmsg_free(msg);
00488 if (err < 0)
00489 return err;
00490
00491 return wait_for_ack(sk);
00492 }
00493
00494 int nfnl_ct_build_delete_request(const struct nfnl_ct *ct, int flags,
00495 struct nl_msg **result)
00496 {
00497 return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_DELETE, flags, result);
00498 }
00499
00500 int nfnl_ct_del(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
00501 {
00502 struct nl_msg *msg;
00503 int err;
00504
00505 if ((err = nfnl_ct_build_delete_request(ct, flags, &msg)) < 0)
00506 return err;
00507
00508 err = nl_send_auto_complete(sk, msg);
00509 nlmsg_free(msg);
00510 if (err < 0)
00511 return err;
00512
00513 return wait_for_ack(sk);
00514 }
00515
00516 int nfnl_ct_build_query_request(const struct nfnl_ct *ct, int flags,
00517 struct nl_msg **result)
00518 {
00519 return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_GET, flags, result);
00520 }
00521
00522 int nfnl_ct_query(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
00523 {
00524 struct nl_msg *msg;
00525 int err;
00526
00527 if ((err = nfnl_ct_build_query_request(ct, flags, &msg)) < 0)
00528 return err;
00529
00530 err = nl_send_auto_complete(sk, msg);
00531 nlmsg_free(msg);
00532 if (err < 0)
00533 return err;
00534
00535 return wait_for_ack(sk);
00536 }
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553 int nfnl_ct_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
00554 {
00555 return nl_cache_alloc_and_fill(&nfnl_ct_ops, sk, result);
00556 }
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 static struct nl_af_group ct_groups[] = {
00568 { AF_UNSPEC, NFNLGRP_CONNTRACK_NEW },
00569 { AF_UNSPEC, NFNLGRP_CONNTRACK_UPDATE },
00570 { AF_UNSPEC, NFNLGRP_CONNTRACK_DESTROY },
00571 { END_OF_GROUP_LIST },
00572 };
00573
00574 #define NFNLMSG_CT_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK, (type))
00575 static struct nl_cache_ops nfnl_ct_ops = {
00576 .co_name = "netfilter/ct",
00577 .co_hdrsize = NFNL_HDRLEN,
00578 .co_msgtypes = {
00579 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_NEW), NL_ACT_NEW, "new" },
00580 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_GET), NL_ACT_GET, "get" },
00581 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_DELETE), NL_ACT_DEL, "del" },
00582 END_OF_MSGTYPES_LIST,
00583 },
00584 .co_protocol = NETLINK_NETFILTER,
00585 .co_groups = ct_groups,
00586 .co_request_update = ct_request_update,
00587 .co_msg_parser = ct_msg_parser,
00588 .co_obj_ops = &ct_obj_ops,
00589 };
00590
00591 static void __init ct_init(void)
00592 {
00593 nl_cache_mngt_register(&nfnl_ct_ops);
00594 }
00595
00596 static void __exit ct_exit(void)
00597 {
00598 nl_cache_mngt_unregister(&nfnl_ct_ops);
00599 }
00600
00601