00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <byteswap.h>
00022 #include <sys/types.h>
00023 #include <linux/netfilter/nfnetlink_conntrack.h>
00024
00025 #include <netlink-local.h>
00026 #include <netlink/attr.h>
00027 #include <netlink/netfilter/nfnl.h>
00028 #include <netlink/netfilter/ct.h>
00029
00030 static struct nl_cache_ops nfnl_ct_ops;
00031
00032 #if __BYTE_ORDER == __BIG_ENDIAN
00033 static uint64_t ntohll(uint64_t x)
00034 {
00035 return x;
00036 }
00037 #elif __BYTE_ORDER == __LITTLE_ENDIAN
00038 static uint64_t ntohll(uint64_t x)
00039 {
00040 return __bswap_64(x);
00041 }
00042 #endif
00043
00044 static struct nla_policy ct_policy[CTA_MAX+1] = {
00045 [CTA_TUPLE_ORIG] = { .type = NLA_NESTED },
00046 [CTA_TUPLE_REPLY] = { .type = NLA_NESTED },
00047 [CTA_STATUS] = { .type = NLA_U32 },
00048 [CTA_PROTOINFO] = { .type = NLA_NESTED },
00049
00050
00051 [CTA_TIMEOUT] = { .type = NLA_U32 },
00052 [CTA_MARK] = { .type = NLA_U32 },
00053 [CTA_COUNTERS_ORIG] = { .type = NLA_NESTED },
00054 [CTA_COUNTERS_REPLY] = { .type = NLA_NESTED },
00055 [CTA_USE] = { .type = NLA_U32 },
00056 [CTA_ID] = { .type = NLA_U32 },
00057
00058 };
00059
00060 static struct nla_policy ct_tuple_policy[CTA_TUPLE_MAX+1] = {
00061 [CTA_TUPLE_IP] = { .type = NLA_NESTED },
00062 [CTA_TUPLE_PROTO] = { .type = NLA_NESTED },
00063 };
00064
00065 static struct nla_policy ct_ip_policy[CTA_IP_MAX+1] = {
00066 [CTA_IP_V4_SRC] = { .type = NLA_U32 },
00067 [CTA_IP_V4_DST] = { .type = NLA_U32 },
00068 [CTA_IP_V6_SRC] = { .minlen = 16 },
00069 [CTA_IP_V6_DST] = { .minlen = 16 },
00070 };
00071
00072 static struct nla_policy ct_proto_policy[CTA_PROTO_MAX+1] = {
00073 [CTA_PROTO_NUM] = { .type = NLA_U8 },
00074 [CTA_PROTO_SRC_PORT] = { .type = NLA_U16 },
00075 [CTA_PROTO_DST_PORT] = { .type = NLA_U16 },
00076 [CTA_PROTO_ICMP_ID] = { .type = NLA_U16 },
00077 [CTA_PROTO_ICMP_TYPE] = { .type = NLA_U8 },
00078 [CTA_PROTO_ICMP_CODE] = { .type = NLA_U8 },
00079 [CTA_PROTO_ICMPV6_ID] = { .type = NLA_U16 },
00080 [CTA_PROTO_ICMPV6_TYPE] = { .type = NLA_U8 },
00081 [CTA_PROTO_ICMPV6_CODE] = { .type = NLA_U8 },
00082 };
00083
00084 static struct nla_policy ct_protoinfo_policy[CTA_PROTOINFO_MAX+1] = {
00085 [CTA_PROTOINFO_TCP] = { .type = NLA_NESTED },
00086 };
00087
00088 static struct nla_policy ct_protoinfo_tcp_policy[CTA_PROTOINFO_TCP_MAX+1] = {
00089 [CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 },
00090 [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 },
00091 [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 },
00092 [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .minlen = 2 },
00093 [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .minlen = 2 },
00094
00095 };
00096
00097 static struct nla_policy ct_counters_policy[CTA_COUNTERS_MAX+1] = {
00098 [CTA_COUNTERS_PACKETS] = { .type = NLA_U64 },
00099 [CTA_COUNTERS_BYTES] = { .type = NLA_U64 },
00100 [CTA_COUNTERS32_PACKETS]= { .type = NLA_U32 },
00101 [CTA_COUNTERS32_BYTES] = { .type = NLA_U32 },
00102 };
00103
00104 static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr)
00105 {
00106 struct nlattr *tb[CTA_IP_MAX+1];
00107 struct nl_addr *addr;
00108 int err;
00109
00110 err = nla_parse_nested(tb, CTA_IP_MAX, attr, ct_ip_policy);
00111 if (err < 0)
00112 goto errout;
00113
00114 if (tb[CTA_IP_V4_SRC]) {
00115 addr = nla_get_addr(tb[CTA_IP_V4_SRC], AF_INET);
00116 if (addr == NULL)
00117 goto errout_errno;
00118 err = nfnl_ct_set_src(ct, repl, addr);
00119 nl_addr_put(addr);
00120 if (err < 0)
00121 goto errout;
00122 }
00123 if (tb[CTA_IP_V4_DST]) {
00124 addr = nla_get_addr(tb[CTA_IP_V4_DST], AF_INET);
00125 if (addr == NULL)
00126 goto errout_errno;
00127 err = nfnl_ct_set_dst(ct, repl, addr);
00128 nl_addr_put(addr);
00129 if (err < 0)
00130 goto errout;
00131 }
00132 if (tb[CTA_IP_V6_SRC]) {
00133 addr = nla_get_addr(tb[CTA_IP_V6_SRC], AF_INET6);
00134 if (addr == NULL)
00135 goto errout_errno;
00136 err = nfnl_ct_set_src(ct, repl, addr);
00137 nl_addr_put(addr);
00138 if (err < 0)
00139 goto errout;
00140 }
00141 if (tb[CTA_IP_V6_DST]) {
00142 addr = nla_get_addr(tb[CTA_IP_V6_DST], AF_INET6);
00143 if (addr == NULL)
00144 goto errout_errno;
00145 err = nfnl_ct_set_dst(ct, repl, addr);
00146 nl_addr_put(addr);
00147 if (err < 0)
00148 goto errout;
00149 }
00150
00151 return 0;
00152
00153 errout_errno:
00154 return nl_get_errno();
00155 errout:
00156 return err;
00157 }
00158
00159 static int ct_parse_proto(struct nfnl_ct *ct, int repl, struct nlattr *attr)
00160 {
00161 struct nlattr *tb[CTA_PROTO_MAX+1];
00162 int err;
00163
00164 err = nla_parse_nested(tb, CTA_PROTO_MAX, attr, ct_proto_policy);
00165 if (err < 0)
00166 return err;
00167
00168 if (!repl && tb[CTA_PROTO_NUM])
00169 nfnl_ct_set_proto(ct, nla_get_u8(tb[CTA_PROTO_NUM]));
00170 if (tb[CTA_PROTO_SRC_PORT])
00171 nfnl_ct_set_src_port(ct, repl,
00172 nla_get_u16(tb[CTA_PROTO_SRC_PORT]));
00173 if (tb[CTA_PROTO_DST_PORT])
00174 nfnl_ct_set_dst_port(ct, repl,
00175 nla_get_u16(tb[CTA_PROTO_DST_PORT]));
00176 if (tb[CTA_PROTO_ICMP_ID])
00177 nfnl_ct_set_icmp_id(ct, repl,
00178 nla_get_u16(tb[CTA_PROTO_ICMP_ID]));
00179 if (tb[CTA_PROTO_ICMP_TYPE])
00180 nfnl_ct_set_icmp_type(ct, repl,
00181 nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]));
00182 if (tb[CTA_PROTO_ICMP_CODE])
00183 nfnl_ct_set_icmp_code(ct, repl,
00184 nla_get_u8(tb[CTA_PROTO_ICMP_CODE]));
00185
00186 return 0;
00187 }
00188
00189 static int ct_parse_tuple(struct nfnl_ct *ct, int repl, struct nlattr *attr)
00190 {
00191 struct nlattr *tb[CTA_TUPLE_MAX+1];
00192 int err;
00193
00194 err = nla_parse_nested(tb, CTA_TUPLE_MAX, attr, ct_tuple_policy);
00195 if (err < 0)
00196 return err;
00197
00198 if (tb[CTA_TUPLE_IP]) {
00199 err = ct_parse_ip(ct, repl, tb[CTA_TUPLE_IP]);
00200 if (err < 0)
00201 return err;
00202 }
00203
00204 if (tb[CTA_TUPLE_PROTO]) {
00205 err = ct_parse_proto(ct, repl, tb[CTA_TUPLE_PROTO]);
00206 if (err < 0)
00207 return err;
00208 }
00209
00210 return 0;
00211 }
00212
00213 static int ct_parse_protoinfo_tcp(struct nfnl_ct *ct, struct nlattr *attr)
00214 {
00215 struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1];
00216 int err;
00217
00218 err = nla_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr,
00219 ct_protoinfo_tcp_policy);
00220 if (err < 0)
00221 return err;
00222
00223 if (tb[CTA_PROTOINFO_TCP_STATE])
00224 nfnl_ct_set_tcp_state(ct,
00225 nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]));
00226
00227 return 0;
00228 }
00229
00230 static int ct_parse_protoinfo(struct nfnl_ct *ct, struct nlattr *attr)
00231 {
00232 struct nlattr *tb[CTA_PROTOINFO_MAX+1];
00233 int err;
00234
00235 err = nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr,
00236 ct_protoinfo_policy);
00237 if (err < 0)
00238 return err;
00239
00240 if (tb[CTA_PROTOINFO_TCP]) {
00241 err = ct_parse_protoinfo_tcp(ct, tb[CTA_PROTOINFO_TCP]);
00242 if (err < 0)
00243 return err;
00244 }
00245
00246 return 0;
00247 }
00248
00249 static int ct_parse_counters(struct nfnl_ct *ct, int repl, struct nlattr *attr)
00250 {
00251 struct nlattr *tb[CTA_COUNTERS_MAX+1];
00252 int err;
00253
00254 err = nla_parse_nested(tb, CTA_COUNTERS_MAX, attr, ct_counters_policy);
00255 if (err < 0)
00256 return err;
00257
00258 if (tb[CTA_COUNTERS_PACKETS])
00259 nfnl_ct_set_packets(ct, repl,
00260 ntohll(nla_get_u64(tb[CTA_COUNTERS_PACKETS])));
00261 if (tb[CTA_COUNTERS32_PACKETS])
00262 nfnl_ct_set_packets(ct, repl,
00263 ntohl(nla_get_u32(tb[CTA_COUNTERS32_PACKETS])));
00264 if (tb[CTA_COUNTERS_BYTES])
00265 nfnl_ct_set_bytes(ct, repl,
00266 ntohll(nla_get_u64(tb[CTA_COUNTERS_BYTES])));
00267 if (tb[CTA_COUNTERS32_BYTES])
00268 nfnl_ct_set_bytes(ct, repl,
00269 ntohl(nla_get_u32(tb[CTA_COUNTERS32_BYTES])));
00270
00271 return 0;
00272 }
00273
00274 int nfnlmsg_ct_group(struct nlmsghdr *nlh)
00275 {
00276 switch (nfnlmsg_subtype(nlh)) {
00277 case IPCTNL_MSG_CT_NEW:
00278 if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL))
00279 return NFNLGRP_CONNTRACK_NEW;
00280 else
00281 return NFNLGRP_CONNTRACK_UPDATE;
00282 case IPCTNL_MSG_CT_DELETE:
00283 return NFNLGRP_CONNTRACK_DESTROY;
00284 default:
00285 return NFNLGRP_NONE;
00286 }
00287 }
00288
00289 struct nfnl_ct *nfnlmsg_ct_parse(struct nlmsghdr *nlh)
00290 {
00291 struct nfnl_ct *ct;
00292 struct nlattr *tb[CTA_MAX+1];
00293 int err;
00294
00295 ct = nfnl_ct_alloc();
00296 if (!ct)
00297 return NULL;
00298
00299 ct->ce_msgtype = nlh->nlmsg_type;
00300
00301 err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_MAX,
00302 ct_policy);
00303 if (err < 0)
00304 goto errout;
00305
00306 nfnl_ct_set_family(ct, nfnlmsg_family(nlh));
00307
00308 if (tb[CTA_TUPLE_ORIG]) {
00309 err = ct_parse_tuple(ct, 0, tb[CTA_TUPLE_ORIG]);
00310 if (err < 0)
00311 goto errout;
00312 }
00313 if (tb[CTA_TUPLE_REPLY]) {
00314 err = ct_parse_tuple(ct, 1, tb[CTA_TUPLE_REPLY]);
00315 if (err < 0)
00316 goto errout;
00317 }
00318
00319 if (tb[CTA_PROTOINFO]) {
00320 err = ct_parse_protoinfo(ct, tb[CTA_PROTOINFO]);
00321 if (err < 0)
00322 goto errout;
00323 }
00324
00325 if (tb[CTA_STATUS])
00326 nfnl_ct_set_status(ct, ntohl(nla_get_u32(tb[CTA_STATUS])));
00327 if (tb[CTA_TIMEOUT])
00328 nfnl_ct_set_timeout(ct, ntohl(nla_get_u32(tb[CTA_TIMEOUT])));
00329 if (tb[CTA_MARK])
00330 nfnl_ct_set_mark(ct, ntohl(nla_get_u32(tb[CTA_MARK])));
00331 if (tb[CTA_USE])
00332 nfnl_ct_set_use(ct, ntohl(nla_get_u32(tb[CTA_USE])));
00333 if (tb[CTA_ID])
00334 nfnl_ct_set_id(ct, ntohl(nla_get_u32(tb[CTA_ID])));
00335
00336 if (tb[CTA_COUNTERS_ORIG]) {
00337 err = ct_parse_counters(ct, 0, tb[CTA_COUNTERS_ORIG]);
00338 if (err < 0)
00339 goto errout;
00340 }
00341
00342 if (tb[CTA_COUNTERS_REPLY]) {
00343 err = ct_parse_counters(ct, 1, tb[CTA_COUNTERS_REPLY]);
00344 if (err < 0)
00345 goto errout;
00346 }
00347
00348 return ct;
00349
00350 errout:
00351 nfnl_ct_put(ct);
00352 return NULL;
00353 }
00354
00355 static int ct_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
00356 struct nlmsghdr *nlh, struct nl_parser_param *pp)
00357 {
00358 struct nfnl_ct *ct;
00359 int err;
00360
00361 ct = nfnlmsg_ct_parse(nlh);
00362 if (ct == NULL)
00363 goto errout_errno;
00364
00365 err = pp->pp_cb((struct nl_object *) ct, pp);
00366 if (err < 0)
00367 goto errout;
00368
00369 err = P_ACCEPT;
00370
00371 errout:
00372 nfnl_ct_put(ct);
00373 return err;
00374
00375 errout_errno:
00376 err = nl_get_errno();
00377 goto errout;
00378 }
00379
00380 int nfnl_ct_dump_request(struct nl_handle *h)
00381 {
00382 return nfnl_send_simple(h, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET,
00383 NLM_F_DUMP, AF_UNSPEC, 0);
00384 }
00385
00386 static int ct_request_update(struct nl_cache *c, struct nl_handle *h)
00387 {
00388 return nfnl_ct_dump_request(h);
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 struct nl_cache *nfnl_ct_alloc_cache(struct nl_handle *handle)
00408 {
00409 struct nl_cache *cache;
00410
00411 cache = nl_cache_alloc(&nfnl_ct_ops);
00412 if (!cache)
00413 return NULL;
00414
00415 if (handle && nl_cache_refill(handle, cache) < 0) {
00416 free(cache);
00417 return NULL;
00418 }
00419
00420 return cache;
00421 }
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 static struct nl_af_group ct_groups[] = {
00433 { AF_UNSPEC, NFNLGRP_CONNTRACK_NEW },
00434 { AF_UNSPEC, NFNLGRP_CONNTRACK_UPDATE },
00435 { AF_UNSPEC, NFNLGRP_CONNTRACK_DESTROY },
00436 { END_OF_GROUP_LIST },
00437 };
00438
00439 #define NFNLMSG_CT_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK, (type))
00440 static struct nl_cache_ops nfnl_ct_ops = {
00441 .co_name = "netfilter/ct",
00442 .co_hdrsize = NFNL_HDRLEN,
00443 .co_msgtypes = {
00444 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_NEW), NL_ACT_NEW, "new" },
00445 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_GET), NL_ACT_GET, "get" },
00446 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_DELETE), NL_ACT_DEL, "del" },
00447 END_OF_MSGTYPES_LIST,
00448 },
00449 .co_protocol = NETLINK_NETFILTER,
00450 .co_groups = ct_groups,
00451 .co_request_update = ct_request_update,
00452 .co_msg_parser = ct_msg_parser,
00453 .co_obj_ops = &ct_obj_ops,
00454 };
00455
00456 static void __init ct_init(void)
00457 {
00458 nl_cache_mngt_register(&nfnl_ct_ops);
00459 }
00460
00461 static void __exit ct_exit(void)
00462 {
00463 nl_cache_mngt_unregister(&nfnl_ct_ops);
00464 }
00465
00466