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