ct.c revision eed2afaab7aa72fae393a395a8879b91a922ff5e
1/* 2 * lib/netfilter/ct.c Conntrack 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) 2003-2008 Thomas Graf <tgraf@suug.ch> 10 * Copyright (c) 2007 Philip Craig <philipc@snapgear.com> 11 * Copyright (c) 2007 Secure Computing Corporation 12 * Copyright (c= 2008 Patrick McHardy <kaber@trash.net> 13 */ 14 15/** 16 * @ingroup nfnl 17 * @defgroup ct Conntrack 18 * @brief 19 * @{ 20 */ 21 22#include <byteswap.h> 23#include <sys/types.h> 24#include <linux/netfilter/nfnetlink_conntrack.h> 25 26#include <netlink-local.h> 27#include <netlink/attr.h> 28#include <netlink/netfilter/nfnl.h> 29#include <netlink/netfilter/ct.h> 30 31static struct nl_cache_ops nfnl_ct_ops; 32 33#if __BYTE_ORDER == __BIG_ENDIAN 34static uint64_t ntohll(uint64_t x) 35{ 36 return x; 37} 38#elif __BYTE_ORDER == __LITTLE_ENDIAN 39static uint64_t ntohll(uint64_t x) 40{ 41 return __bswap_64(x); 42} 43#endif 44 45static struct nla_policy ct_policy[CTA_MAX+1] = { 46 [CTA_TUPLE_ORIG] = { .type = NLA_NESTED }, 47 [CTA_TUPLE_REPLY] = { .type = NLA_NESTED }, 48 [CTA_STATUS] = { .type = NLA_U32 }, 49 [CTA_PROTOINFO] = { .type = NLA_NESTED }, 50 //[CTA_HELP] 51 //[CTA_NAT_SRC] 52 [CTA_TIMEOUT] = { .type = NLA_U32 }, 53 [CTA_MARK] = { .type = NLA_U32 }, 54 [CTA_COUNTERS_ORIG] = { .type = NLA_NESTED }, 55 [CTA_COUNTERS_REPLY] = { .type = NLA_NESTED }, 56 [CTA_USE] = { .type = NLA_U32 }, 57 [CTA_ID] = { .type = NLA_U32 }, 58 //[CTA_NAT_DST] 59}; 60 61static struct nla_policy ct_tuple_policy[CTA_TUPLE_MAX+1] = { 62 [CTA_TUPLE_IP] = { .type = NLA_NESTED }, 63 [CTA_TUPLE_PROTO] = { .type = NLA_NESTED }, 64}; 65 66static struct nla_policy ct_ip_policy[CTA_IP_MAX+1] = { 67 [CTA_IP_V4_SRC] = { .type = NLA_U32 }, 68 [CTA_IP_V4_DST] = { .type = NLA_U32 }, 69 [CTA_IP_V6_SRC] = { .minlen = 16 }, 70 [CTA_IP_V6_DST] = { .minlen = 16 }, 71}; 72 73static struct nla_policy ct_proto_policy[CTA_PROTO_MAX+1] = { 74 [CTA_PROTO_NUM] = { .type = NLA_U8 }, 75 [CTA_PROTO_SRC_PORT] = { .type = NLA_U16 }, 76 [CTA_PROTO_DST_PORT] = { .type = NLA_U16 }, 77 [CTA_PROTO_ICMP_ID] = { .type = NLA_U16 }, 78 [CTA_PROTO_ICMP_TYPE] = { .type = NLA_U8 }, 79 [CTA_PROTO_ICMP_CODE] = { .type = NLA_U8 }, 80 [CTA_PROTO_ICMPV6_ID] = { .type = NLA_U16 }, 81 [CTA_PROTO_ICMPV6_TYPE] = { .type = NLA_U8 }, 82 [CTA_PROTO_ICMPV6_CODE] = { .type = NLA_U8 }, 83}; 84 85static struct nla_policy ct_protoinfo_policy[CTA_PROTOINFO_MAX+1] = { 86 [CTA_PROTOINFO_TCP] = { .type = NLA_NESTED }, 87}; 88 89static struct nla_policy ct_protoinfo_tcp_policy[CTA_PROTOINFO_TCP_MAX+1] = { 90 [CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 }, 91 [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 }, 92 [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 }, 93 [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .minlen = 2 }, 94 [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .minlen = 2 }, 95 96}; 97 98static struct nla_policy ct_counters_policy[CTA_COUNTERS_MAX+1] = { 99 [CTA_COUNTERS_PACKETS] = { .type = NLA_U64 }, 100 [CTA_COUNTERS_BYTES] = { .type = NLA_U64 }, 101 [CTA_COUNTERS32_PACKETS]= { .type = NLA_U32 }, 102 [CTA_COUNTERS32_BYTES] = { .type = NLA_U32 }, 103}; 104 105static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr) 106{ 107 struct nlattr *tb[CTA_IP_MAX+1]; 108 struct nl_addr *addr; 109 int err; 110 111 err = nla_parse_nested(tb, CTA_IP_MAX, attr, ct_ip_policy); 112 if (err < 0) 113 goto errout; 114 115 if (tb[CTA_IP_V4_SRC]) { 116 addr = nl_addr_alloc_attr(tb[CTA_IP_V4_SRC], AF_INET); 117 if (addr == NULL) 118 goto errout_enomem; 119 err = nfnl_ct_set_src(ct, repl, addr); 120 nl_addr_put(addr); 121 if (err < 0) 122 goto errout; 123 } 124 if (tb[CTA_IP_V4_DST]) { 125 addr = nl_addr_alloc_attr(tb[CTA_IP_V4_DST], AF_INET); 126 if (addr == NULL) 127 goto errout_enomem; 128 err = nfnl_ct_set_dst(ct, repl, addr); 129 nl_addr_put(addr); 130 if (err < 0) 131 goto errout; 132 } 133 if (tb[CTA_IP_V6_SRC]) { 134 addr = nl_addr_alloc_attr(tb[CTA_IP_V6_SRC], AF_INET6); 135 if (addr == NULL) 136 goto errout_enomem; 137 err = nfnl_ct_set_src(ct, repl, addr); 138 nl_addr_put(addr); 139 if (err < 0) 140 goto errout; 141 } 142 if (tb[CTA_IP_V6_DST]) { 143 addr = nl_addr_alloc_attr(tb[CTA_IP_V6_DST], AF_INET6); 144 if (addr == NULL) 145 goto errout_enomem; 146 err = nfnl_ct_set_dst(ct, repl, addr); 147 nl_addr_put(addr); 148 if (err < 0) 149 goto errout; 150 } 151 152 return 0; 153 154errout_enomem: 155 err = -NLE_NOMEM; 156errout: 157 return err; 158} 159 160static int ct_parse_proto(struct nfnl_ct *ct, int repl, struct nlattr *attr) 161{ 162 struct nlattr *tb[CTA_PROTO_MAX+1]; 163 int err; 164 165 err = nla_parse_nested(tb, CTA_PROTO_MAX, attr, ct_proto_policy); 166 if (err < 0) 167 return err; 168 169 if (!repl && tb[CTA_PROTO_NUM]) 170 nfnl_ct_set_proto(ct, nla_get_u8(tb[CTA_PROTO_NUM])); 171 if (tb[CTA_PROTO_SRC_PORT]) 172 nfnl_ct_set_src_port(ct, repl, 173 nla_get_u16(tb[CTA_PROTO_SRC_PORT])); 174 if (tb[CTA_PROTO_DST_PORT]) 175 nfnl_ct_set_dst_port(ct, repl, 176 nla_get_u16(tb[CTA_PROTO_DST_PORT])); 177 if (tb[CTA_PROTO_ICMP_ID]) 178 nfnl_ct_set_icmp_id(ct, repl, 179 nla_get_u16(tb[CTA_PROTO_ICMP_ID])); 180 if (tb[CTA_PROTO_ICMP_TYPE]) 181 nfnl_ct_set_icmp_type(ct, repl, 182 nla_get_u8(tb[CTA_PROTO_ICMP_TYPE])); 183 if (tb[CTA_PROTO_ICMP_CODE]) 184 nfnl_ct_set_icmp_code(ct, repl, 185 nla_get_u8(tb[CTA_PROTO_ICMP_CODE])); 186 187 return 0; 188} 189 190static int ct_parse_tuple(struct nfnl_ct *ct, int repl, struct nlattr *attr) 191{ 192 struct nlattr *tb[CTA_TUPLE_MAX+1]; 193 int err; 194 195 err = nla_parse_nested(tb, CTA_TUPLE_MAX, attr, ct_tuple_policy); 196 if (err < 0) 197 return err; 198 199 if (tb[CTA_TUPLE_IP]) { 200 err = ct_parse_ip(ct, repl, tb[CTA_TUPLE_IP]); 201 if (err < 0) 202 return err; 203 } 204 205 if (tb[CTA_TUPLE_PROTO]) { 206 err = ct_parse_proto(ct, repl, tb[CTA_TUPLE_PROTO]); 207 if (err < 0) 208 return err; 209 } 210 211 return 0; 212} 213 214static int ct_parse_protoinfo_tcp(struct nfnl_ct *ct, struct nlattr *attr) 215{ 216 struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1]; 217 int err; 218 219 err = nla_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr, 220 ct_protoinfo_tcp_policy); 221 if (err < 0) 222 return err; 223 224 if (tb[CTA_PROTOINFO_TCP_STATE]) 225 nfnl_ct_set_tcp_state(ct, 226 nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE])); 227 228 return 0; 229} 230 231static int ct_parse_protoinfo(struct nfnl_ct *ct, struct nlattr *attr) 232{ 233 struct nlattr *tb[CTA_PROTOINFO_MAX+1]; 234 int err; 235 236 err = nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, 237 ct_protoinfo_policy); 238 if (err < 0) 239 return err; 240 241 if (tb[CTA_PROTOINFO_TCP]) { 242 err = ct_parse_protoinfo_tcp(ct, tb[CTA_PROTOINFO_TCP]); 243 if (err < 0) 244 return err; 245 } 246 247 return 0; 248} 249 250static int ct_parse_counters(struct nfnl_ct *ct, int repl, struct nlattr *attr) 251{ 252 struct nlattr *tb[CTA_COUNTERS_MAX+1]; 253 int err; 254 255 err = nla_parse_nested(tb, CTA_COUNTERS_MAX, attr, ct_counters_policy); 256 if (err < 0) 257 return err; 258 259 if (tb[CTA_COUNTERS_PACKETS]) 260 nfnl_ct_set_packets(ct, repl, 261 ntohll(nla_get_u64(tb[CTA_COUNTERS_PACKETS]))); 262 if (tb[CTA_COUNTERS32_PACKETS]) 263 nfnl_ct_set_packets(ct, repl, 264 ntohl(nla_get_u32(tb[CTA_COUNTERS32_PACKETS]))); 265 if (tb[CTA_COUNTERS_BYTES]) 266 nfnl_ct_set_bytes(ct, repl, 267 ntohll(nla_get_u64(tb[CTA_COUNTERS_BYTES]))); 268 if (tb[CTA_COUNTERS32_BYTES]) 269 nfnl_ct_set_bytes(ct, repl, 270 ntohl(nla_get_u32(tb[CTA_COUNTERS32_BYTES]))); 271 272 return 0; 273} 274 275int nfnlmsg_ct_group(struct nlmsghdr *nlh) 276{ 277 switch (nfnlmsg_subtype(nlh)) { 278 case IPCTNL_MSG_CT_NEW: 279 if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL)) 280 return NFNLGRP_CONNTRACK_NEW; 281 else 282 return NFNLGRP_CONNTRACK_UPDATE; 283 case IPCTNL_MSG_CT_DELETE: 284 return NFNLGRP_CONNTRACK_DESTROY; 285 default: 286 return NFNLGRP_NONE; 287 } 288} 289 290int nfnlmsg_ct_parse(struct nlmsghdr *nlh, struct nfnl_ct **result) 291{ 292 struct nfnl_ct *ct; 293 struct nlattr *tb[CTA_MAX+1]; 294 int err; 295 296 ct = nfnl_ct_alloc(); 297 if (!ct) 298 return -NLE_NOMEM; 299 300 ct->ce_msgtype = nlh->nlmsg_type; 301 302 err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_MAX, 303 ct_policy); 304 if (err < 0) 305 goto errout; 306 307 nfnl_ct_set_family(ct, nfnlmsg_family(nlh)); 308 309 if (tb[CTA_TUPLE_ORIG]) { 310 err = ct_parse_tuple(ct, 0, tb[CTA_TUPLE_ORIG]); 311 if (err < 0) 312 goto errout; 313 } 314 if (tb[CTA_TUPLE_REPLY]) { 315 err = ct_parse_tuple(ct, 1, tb[CTA_TUPLE_REPLY]); 316 if (err < 0) 317 goto errout; 318 } 319 320 if (tb[CTA_PROTOINFO]) { 321 err = ct_parse_protoinfo(ct, tb[CTA_PROTOINFO]); 322 if (err < 0) 323 goto errout; 324 } 325 326 if (tb[CTA_STATUS]) 327 nfnl_ct_set_status(ct, ntohl(nla_get_u32(tb[CTA_STATUS]))); 328 if (tb[CTA_TIMEOUT]) 329 nfnl_ct_set_timeout(ct, ntohl(nla_get_u32(tb[CTA_TIMEOUT]))); 330 if (tb[CTA_MARK]) 331 nfnl_ct_set_mark(ct, ntohl(nla_get_u32(tb[CTA_MARK]))); 332 if (tb[CTA_USE]) 333 nfnl_ct_set_use(ct, ntohl(nla_get_u32(tb[CTA_USE]))); 334 if (tb[CTA_ID]) 335 nfnl_ct_set_id(ct, ntohl(nla_get_u32(tb[CTA_ID]))); 336 337 if (tb[CTA_COUNTERS_ORIG]) { 338 err = ct_parse_counters(ct, 0, tb[CTA_COUNTERS_ORIG]); 339 if (err < 0) 340 goto errout; 341 } 342 343 if (tb[CTA_COUNTERS_REPLY]) { 344 err = ct_parse_counters(ct, 1, tb[CTA_COUNTERS_REPLY]); 345 if (err < 0) 346 goto errout; 347 } 348 349 *result = ct; 350 return 0; 351 352errout: 353 nfnl_ct_put(ct); 354 return err; 355} 356 357static int ct_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, 358 struct nlmsghdr *nlh, struct nl_parser_param *pp) 359{ 360 struct nfnl_ct *ct; 361 int err; 362 363 if ((err = nfnlmsg_ct_parse(nlh, &ct)) < 0) 364 goto errout; 365 366 err = pp->pp_cb((struct nl_object *) ct, pp); 367 if (err < 0) 368 goto errout; 369 370 err = P_ACCEPT; 371 372errout: 373 nfnl_ct_put(ct); 374 return err; 375} 376 377int nfnl_ct_dump_request(struct nl_handle *h) 378{ 379 return nfnl_send_simple(h, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET, 380 NLM_F_DUMP, AF_UNSPEC, 0); 381} 382 383static int ct_request_update(struct nl_cache *c, struct nl_handle *h) 384{ 385 return nfnl_ct_dump_request(h); 386} 387 388static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct, 389 int repl) 390{ 391 struct nlattr *tuple, *ip, *proto; 392 struct nl_addr *addr; 393 int family; 394 395 family = nfnl_ct_get_family(ct); 396 397 tuple = nla_nest_start(msg, repl ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG); 398 if (!tuple) 399 goto nla_put_failure; 400 401 ip = nla_nest_start(msg, CTA_TUPLE_IP); 402 if (!ip) 403 goto nla_put_failure; 404 405 addr = nfnl_ct_get_src(ct, repl); 406 if (addr) 407 NLA_PUT_ADDR(msg, 408 family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC, 409 addr); 410 411 addr = nfnl_ct_get_dst(ct, repl); 412 if (addr) 413 NLA_PUT_ADDR(msg, 414 family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST, 415 addr); 416 417 nla_nest_end(msg, ip); 418 419 proto = nla_nest_start(msg, CTA_TUPLE_PROTO); 420 if (!proto) 421 goto nla_put_failure; 422 423 if (nfnl_ct_test_proto(ct)) 424 NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_ct_get_proto(ct)); 425 426 if (nfnl_ct_test_src_port(ct, repl)) 427 NLA_PUT_U16(msg, CTA_PROTO_SRC_PORT, 428 nfnl_ct_get_src_port(ct, repl)); 429 430 if (nfnl_ct_test_dst_port(ct, repl)) 431 NLA_PUT_U16(msg, CTA_PROTO_DST_PORT, 432 nfnl_ct_get_dst_port(ct, repl)); 433 434 if (nfnl_ct_test_icmp_id(ct, repl)) 435 NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID, 436 nfnl_ct_get_icmp_id(ct, repl)); 437 438 if (nfnl_ct_test_icmp_type(ct, repl)) 439 NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE, 440 nfnl_ct_get_icmp_type(ct, repl)); 441 442 if (nfnl_ct_test_icmp_code(ct, repl)) 443 NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE, 444 nfnl_ct_get_icmp_code(ct, repl)); 445 446 nla_nest_end(msg, proto); 447 448 nla_nest_end(msg, tuple); 449 return 0; 450 451nla_put_failure: 452 return -NLE_MSGSIZE; 453} 454 455static int nfnl_ct_build_message(const struct nfnl_ct *ct, int cmd, int flags, 456 struct nl_msg **result) 457{ 458 struct nl_msg *msg; 459 int err; 460 461 msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK, cmd, flags, 462 nfnl_ct_get_family(ct), 0); 463 if (msg == NULL) 464 return -NLE_NOMEM; 465 466 if ((err = nfnl_ct_build_tuple(msg, ct, 0)) < 0) 467 goto err_out; 468 469 *result = msg; 470 return 0; 471 472err_out: 473 nlmsg_free(msg); 474 return err; 475} 476 477int nfnl_ct_build_add_request(const struct nfnl_ct *ct, int flags, 478 struct nl_msg **result) 479{ 480 return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_NEW, flags, result); 481} 482 483int nfnl_ct_add(struct nl_handle *h, const struct nfnl_ct *ct, int flags) 484{ 485 struct nl_msg *msg; 486 int err; 487 488 if ((err = nfnl_ct_build_add_request(ct, flags, &msg)) < 0) 489 return err; 490 491 err = nl_send_auto_complete(h, msg); 492 nlmsg_free(msg); 493 if (err < 0) 494 return err; 495 496 return nl_wait_for_ack(h); 497} 498 499int nfnl_ct_build_delete_request(const struct nfnl_ct *ct, int flags, 500 struct nl_msg **result) 501{ 502 return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_DELETE, flags, result); 503} 504 505int nfnl_ct_del(struct nl_handle *h, const struct nfnl_ct *ct, int flags) 506{ 507 struct nl_msg *msg; 508 int err; 509 510 if ((err = nfnl_ct_build_delete_request(ct, flags, &msg)) < 0) 511 return err; 512 513 err = nl_send_auto_complete(h, msg); 514 nlmsg_free(msg); 515 if (err < 0) 516 return err; 517 518 return nl_wait_for_ack(h); 519} 520 521int nfnl_ct_build_query_request(const struct nfnl_ct *ct, int flags, 522 struct nl_msg **result) 523{ 524 return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_GET, flags, result); 525} 526 527int nfnl_ct_query(struct nl_handle *h, const struct nfnl_ct *ct, int flags) 528{ 529 struct nl_msg *msg; 530 int err; 531 532 if ((err = nfnl_ct_build_query_request(ct, flags, &msg)) < 0) 533 return err; 534 535 err = nl_send_auto_complete(h, msg); 536 nlmsg_free(msg); 537 if (err < 0) 538 return err; 539 540 return nl_wait_for_ack(h); 541} 542 543/** 544 * @name Cache Management 545 * @{ 546 */ 547 548/** 549 * Build a conntrack cache holding all conntrack currently in the kernel 550 * @arg handle netlink handle 551 * @arg result Pointer to store resulting cache. 552 * 553 * Allocates a new cache, initializes it properly and updates it to 554 * contain all conntracks currently in the kernel. 555 * 556 * @return 0 on success or a negative error code. 557 */ 558int nfnl_ct_alloc_cache(struct nl_handle *sock, struct nl_cache **result) 559{ 560 return nl_cache_alloc_and_fill(&nfnl_ct_ops, sock, result); 561} 562 563/** @} */ 564 565/** 566 * @name Conntrack Addition 567 * @{ 568 */ 569 570/** @} */ 571 572static struct nl_af_group ct_groups[] = { 573 { AF_UNSPEC, NFNLGRP_CONNTRACK_NEW }, 574 { AF_UNSPEC, NFNLGRP_CONNTRACK_UPDATE }, 575 { AF_UNSPEC, NFNLGRP_CONNTRACK_DESTROY }, 576 { END_OF_GROUP_LIST }, 577}; 578 579#define NFNLMSG_CT_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK, (type)) 580static struct nl_cache_ops nfnl_ct_ops = { 581 .co_name = "netfilter/ct", 582 .co_hdrsize = NFNL_HDRLEN, 583 .co_msgtypes = { 584 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_NEW), NL_ACT_NEW, "new" }, 585 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_GET), NL_ACT_GET, "get" }, 586 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_DELETE), NL_ACT_DEL, "del" }, 587 END_OF_MSGTYPES_LIST, 588 }, 589 .co_protocol = NETLINK_NETFILTER, 590 .co_groups = ct_groups, 591 .co_request_update = ct_request_update, 592 .co_msg_parser = ct_msg_parser, 593 .co_obj_ops = &ct_obj_ops, 594}; 595 596static void __init ct_init(void) 597{ 598 nl_cache_mngt_register(&nfnl_ct_ops); 599} 600 601static void __exit ct_exit(void) 602{ 603 nl_cache_mngt_unregister(&nfnl_ct_ops); 604} 605 606/** @} */ 607