parse_mnl.c revision 8a44513648da0c5f5551f96b329cf56b66f5b303
1/* 2 * (C) 2005-2012 by Pablo Neira Ayuso <pablo@netfilter.org> 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This code has been sponsored by Vyatta Inc. <http://www.vyatta.com> 10 */ 11 12#include "internal/internal.h" 13#include <libmnl/libmnl.h> 14#include <limits.h> 15#include <endian.h> 16 17static int 18nfct_parse_ip_attr_cb(const struct nlattr *attr, void *data) 19{ 20 const struct nlattr **tb = data; 21 int type = mnl_attr_get_type(attr); 22 23 /* skip unsupported attribute in user-space */ 24 if (mnl_attr_type_valid(attr, CTA_IP_MAX) < 0) 25 return MNL_CB_OK; 26 27 switch(type) { 28 case CTA_IP_V4_SRC: 29 case CTA_IP_V4_DST: 30 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) 31 return MNL_CB_ERROR; 32 break; 33 case CTA_IP_V6_SRC: 34 case CTA_IP_V6_DST: 35 if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, 36 sizeof(struct in6_addr)) < 0) { 37 return MNL_CB_ERROR; 38 } 39 break; 40 } 41 tb[type] = attr; 42 return MNL_CB_OK; 43} 44 45static int 46nfct_parse_ip(const struct nlattr *attr, struct __nfct_tuple *tuple, 47 const int dir, uint32_t *set) 48{ 49 struct nlattr *tb[CTA_IP_MAX+1] = {}; 50 51 if (mnl_attr_parse_nested(attr, nfct_parse_ip_attr_cb, tb) < 0) 52 return -1; 53 54 if (tb[CTA_IP_V4_SRC]) { 55 tuple->src.v4 = mnl_attr_get_u32(tb[CTA_IP_V4_SRC]); 56 switch(dir) { 57 case __DIR_ORIG: 58 set_bit(ATTR_ORIG_IPV4_SRC, set); 59 break; 60 case __DIR_REPL: 61 set_bit(ATTR_REPL_IPV4_SRC, set); 62 break; 63 case __DIR_MASTER: 64 set_bit(ATTR_MASTER_IPV4_SRC, set); 65 break; 66 } 67 } 68 69 if (tb[CTA_IP_V4_DST]) { 70 tuple->dst.v4 = mnl_attr_get_u32(tb[CTA_IP_V4_DST]); 71 switch(dir) { 72 case __DIR_ORIG: 73 set_bit(ATTR_ORIG_IPV4_DST, set); 74 break; 75 case __DIR_REPL: 76 set_bit(ATTR_REPL_IPV4_DST, set); 77 break; 78 case __DIR_MASTER: 79 set_bit(ATTR_MASTER_IPV4_DST, set); 80 break; 81 } 82 } 83 84 if (tb[CTA_IP_V6_SRC]) { 85 memcpy(&tuple->src.v6, mnl_attr_get_payload(tb[CTA_IP_V6_SRC]), 86 sizeof(struct in6_addr)); 87 switch(dir) { 88 case __DIR_ORIG: 89 set_bit(ATTR_ORIG_IPV6_SRC, set); 90 break; 91 case __DIR_REPL: 92 set_bit(ATTR_REPL_IPV6_SRC, set); 93 break; 94 case __DIR_MASTER: 95 set_bit(ATTR_MASTER_IPV6_SRC, set); 96 break; 97 } 98 } 99 100 if (tb[CTA_IP_V6_DST]) { 101 memcpy(&tuple->dst.v6, mnl_attr_get_payload(tb[CTA_IP_V6_DST]), 102 sizeof(struct in6_addr)); 103 switch(dir) { 104 case __DIR_ORIG: 105 set_bit(ATTR_ORIG_IPV6_DST, set); 106 break; 107 case __DIR_REPL: 108 set_bit(ATTR_REPL_IPV6_DST, set); 109 break; 110 case __DIR_MASTER: 111 set_bit(ATTR_MASTER_IPV6_DST, set); 112 break; 113 } 114 } 115 return 0; 116} 117 118static int 119nfct_parse_proto_attr_cb(const struct nlattr *attr, void *data) 120{ 121 const struct nlattr **tb = data; 122 int type = mnl_attr_get_type(attr); 123 124 if (mnl_attr_type_valid(attr, CTA_PROTO_MAX) < 0) 125 return MNL_CB_OK; 126 127 switch(type) { 128 case CTA_PROTO_SRC_PORT: 129 case CTA_PROTO_DST_PORT: 130 case CTA_PROTO_ICMP_ID: 131 case CTA_PROTO_ICMPV6_ID: 132 if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) 133 return MNL_CB_ERROR; 134 break; 135 case CTA_PROTO_NUM: 136 case CTA_PROTO_ICMP_TYPE: 137 case CTA_PROTO_ICMP_CODE: 138 case CTA_PROTO_ICMPV6_TYPE: 139 case CTA_PROTO_ICMPV6_CODE: 140 if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0) 141 return MNL_CB_ERROR; 142 break; 143 } 144 tb[type] = attr; 145 return MNL_CB_OK; 146} 147 148static int 149nfct_parse_proto(const struct nlattr *attr, struct __nfct_tuple *tuple, 150 const int dir, uint32_t *set) 151{ 152 struct nlattr *tb[CTA_PROTO_MAX+1] = {}; 153 154 if (mnl_attr_parse_nested(attr, nfct_parse_proto_attr_cb, tb) < 0) 155 return -1; 156 157 if (tb[CTA_PROTO_NUM]) { 158 tuple->protonum = mnl_attr_get_u8(tb[CTA_PROTO_NUM]); 159 switch(dir) { 160 case __DIR_ORIG: 161 set_bit(ATTR_ORIG_L4PROTO, set); 162 break; 163 case __DIR_REPL: 164 set_bit(ATTR_REPL_L4PROTO, set); 165 break; 166 case __DIR_MASTER: 167 set_bit(ATTR_MASTER_L4PROTO, set); 168 break; 169 } 170 } 171 172 if (tb[CTA_PROTO_SRC_PORT]) { 173 tuple->l4src.tcp.port = 174 mnl_attr_get_u16(tb[CTA_PROTO_SRC_PORT]); 175 switch(dir) { 176 case __DIR_ORIG: 177 set_bit(ATTR_ORIG_PORT_SRC, set); 178 break; 179 case __DIR_REPL: 180 set_bit(ATTR_REPL_PORT_SRC, set); 181 break; 182 case __DIR_MASTER: 183 set_bit(ATTR_MASTER_PORT_SRC, set); 184 break; 185 } 186 } 187 188 if (tb[CTA_PROTO_DST_PORT]) { 189 tuple->l4dst.tcp.port = 190 mnl_attr_get_u16(tb[CTA_PROTO_DST_PORT]); 191 switch(dir) { 192 case __DIR_ORIG: 193 set_bit(ATTR_ORIG_PORT_DST, set); 194 break; 195 case __DIR_REPL: 196 set_bit(ATTR_REPL_PORT_DST, set); 197 break; 198 case __DIR_MASTER: 199 set_bit(ATTR_MASTER_PORT_DST, set); 200 break; 201 } 202 } 203 204 if (tb[CTA_PROTO_ICMP_TYPE]) { 205 tuple->l4dst.icmp.type = 206 mnl_attr_get_u8(tb[CTA_PROTO_ICMP_TYPE]); 207 set_bit(ATTR_ICMP_TYPE, set); 208 } 209 210 if (tb[CTA_PROTO_ICMP_CODE]) { 211 tuple->l4dst.icmp.code = 212 mnl_attr_get_u8(tb[CTA_PROTO_ICMP_CODE]); 213 set_bit(ATTR_ICMP_CODE, set); 214 } 215 216 if (tb[CTA_PROTO_ICMP_ID]) { 217 tuple->l4src.icmp.id = 218 mnl_attr_get_u16(tb[CTA_PROTO_ICMP_ID]); 219 set_bit(ATTR_ICMP_ID, set); 220 } 221 222 if (tb[CTA_PROTO_ICMPV6_TYPE]) { 223 tuple->l4dst.icmp.type = 224 mnl_attr_get_u8(tb[CTA_PROTO_ICMPV6_TYPE]); 225 set_bit(ATTR_ICMP_TYPE, set); 226 } 227 228 if (tb[CTA_PROTO_ICMPV6_CODE]) { 229 tuple->l4dst.icmp.code = 230 mnl_attr_get_u8(tb[CTA_PROTO_ICMPV6_CODE]); 231 set_bit(ATTR_ICMP_CODE, set); 232 } 233 234 if (tb[CTA_PROTO_ICMPV6_ID]) { 235 tuple->l4src.icmp.id = 236 mnl_attr_get_u16(tb[CTA_PROTO_ICMPV6_ID]); 237 set_bit(ATTR_ICMP_ID, set); 238 } 239 240 return 0; 241} 242 243static int nfct_parse_tuple_attr_cb(const struct nlattr *attr, void *data) 244{ 245 const struct nlattr **tb = data; 246 int type = mnl_attr_get_type(attr); 247 248 if (mnl_attr_type_valid(attr, CTA_TUPLE_MAX) < 0) 249 return MNL_CB_OK; 250 251 switch(type) { 252 case CTA_TUPLE_IP: 253 case CTA_TUPLE_PROTO: 254 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) 255 return MNL_CB_ERROR; 256 break; 257 case CTA_TUPLE_ZONE: 258 if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) 259 return MNL_CB_ERROR; 260 break; 261 } 262 263 tb[type] = attr; 264 return MNL_CB_OK; 265} 266 267int 268nfct_parse_tuple(const struct nlattr *attr, struct __nfct_tuple *tuple, 269 int dir, uint32_t *set) 270{ 271 struct nlattr *tb[CTA_TUPLE_MAX+1] = {}; 272 273 if (mnl_attr_parse_nested(attr, nfct_parse_tuple_attr_cb, tb) < 0) 274 return -1; 275 276 if (tb[CTA_TUPLE_IP]) { 277 if (nfct_parse_ip(tb[CTA_TUPLE_IP], tuple, dir, set) < 0) 278 return -1; 279 } 280 281 if (tb[CTA_TUPLE_PROTO]) { 282 if (nfct_parse_proto(tb[CTA_TUPLE_PROTO], tuple, dir, set) < 0) 283 return -1; 284 } 285 286 if (tb[CTA_TUPLE_ZONE]) { 287 tuple->zone = ntohs(mnl_attr_get_u16(tb[CTA_TUPLE_ZONE])); 288 switch(dir) { 289 case __DIR_ORIG: 290 set_bit(ATTR_ORIG_ZONE, set); 291 break; 292 case __DIR_REPL: 293 set_bit(ATTR_REPL_ZONE, set); 294 break; 295 } 296 } 297 298 return 0; 299} 300 301static int 302nfct_parse_pinfo_tcp_attr_cb(const struct nlattr *attr, void *data) 303{ 304 const struct nlattr **tb = data; 305 int type = mnl_attr_get_type(attr); 306 307 if (mnl_attr_type_valid(attr, CTA_PROTOINFO_TCP_MAX) < 0) 308 return MNL_CB_OK; 309 310 switch(type) { 311 case CTA_PROTOINFO_TCP_STATE: 312 case CTA_PROTOINFO_TCP_WSCALE_ORIGINAL: 313 case CTA_PROTOINFO_TCP_WSCALE_REPLY: 314 if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0) 315 return MNL_CB_ERROR; 316 break; 317 case CTA_PROTOINFO_TCP_FLAGS_ORIGINAL: 318 case CTA_PROTOINFO_TCP_FLAGS_REPLY: 319 if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, 320 sizeof(struct nf_ct_tcp_flags)) < 0) { 321 return MNL_CB_ERROR; 322 } 323 break; 324 } 325 tb[type] = attr; 326 return MNL_CB_OK; 327} 328 329static int 330nfct_parse_protoinfo_tcp(const struct nlattr *attr, struct nf_conntrack *ct) 331{ 332 struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1] = {}; 333 334 if (mnl_attr_parse_nested(attr, nfct_parse_pinfo_tcp_attr_cb, tb) < 0) 335 return -1; 336 337 if (tb[CTA_PROTOINFO_TCP_STATE]) { 338 ct->protoinfo.tcp.state = 339 mnl_attr_get_u8(tb[CTA_PROTOINFO_TCP_STATE]); 340 set_bit(ATTR_TCP_STATE, ct->head.set); 341 } 342 343 if (tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL]) { 344 memcpy(&ct->protoinfo.tcp.wscale[__DIR_ORIG], 345 mnl_attr_get_payload(tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL]), 346 sizeof(uint8_t)); 347 set_bit(ATTR_TCP_WSCALE_ORIG, ct->head.set); 348 } 349 350 if (tb[CTA_PROTOINFO_TCP_WSCALE_REPLY]) { 351 memcpy(&ct->protoinfo.tcp.wscale[__DIR_REPL], 352 mnl_attr_get_payload(tb[CTA_PROTOINFO_TCP_WSCALE_REPLY]), 353 sizeof(uint8_t)); 354 set_bit(ATTR_TCP_WSCALE_REPL, ct->head.set); 355 } 356 357 if (tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL]) { 358 memcpy(&ct->protoinfo.tcp.flags[0], 359 mnl_attr_get_payload(tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL]), 360 sizeof(struct nf_ct_tcp_flags)); 361 set_bit(ATTR_TCP_FLAGS_ORIG, ct->head.set); 362 set_bit(ATTR_TCP_MASK_ORIG, ct->head.set); 363 } 364 365 if (tb[CTA_PROTOINFO_TCP_FLAGS_REPLY]) { 366 memcpy(&ct->protoinfo.tcp.flags[1], 367 mnl_attr_get_payload(tb[CTA_PROTOINFO_TCP_FLAGS_REPLY]), 368 sizeof(struct nf_ct_tcp_flags)); 369 set_bit(ATTR_TCP_FLAGS_REPL, ct->head.set); 370 set_bit(ATTR_TCP_MASK_REPL, ct->head.set); 371 } 372 373 return 0; 374} 375 376static int 377nfct_parse_pinfo_sctp_attr_cb(const struct nlattr *attr, void *data) 378{ 379 const struct nlattr **tb = data; 380 int type = mnl_attr_get_type(attr); 381 382 if (mnl_attr_type_valid(attr, CTA_PROTOINFO_SCTP_MAX) < 0) 383 return MNL_CB_OK; 384 385 switch(type) { 386 case CTA_PROTOINFO_SCTP_STATE: 387 if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0) 388 return MNL_CB_ERROR; 389 break; 390 case CTA_PROTOINFO_SCTP_VTAG_ORIGINAL: 391 case CTA_PROTOINFO_SCTP_VTAG_REPLY: 392 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) 393 return MNL_CB_ERROR; 394 break; 395 } 396 tb[type] = attr; 397 return MNL_CB_OK; 398} 399 400static int 401nfct_parse_protoinfo_sctp(const struct nlattr *attr, struct nf_conntrack *ct) 402{ 403 struct nlattr *tb[CTA_PROTOINFO_SCTP_MAX+1] = {}; 404 405 if (mnl_attr_parse_nested(attr, nfct_parse_pinfo_sctp_attr_cb, tb) < 0) 406 return -1; 407 408 if (tb[CTA_PROTOINFO_SCTP_STATE]) { 409 ct->protoinfo.sctp.state = 410 mnl_attr_get_u8(tb[CTA_PROTOINFO_SCTP_STATE]); 411 set_bit(ATTR_SCTP_STATE, ct->head.set); 412 } 413 414 if (tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]) { 415 ct->protoinfo.sctp.vtag[__DIR_ORIG] = 416 ntohl(mnl_attr_get_u32(tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL])); 417 set_bit(ATTR_SCTP_VTAG_ORIG, ct->head.set); 418 } 419 420 if (tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]) { 421 ct->protoinfo.sctp.vtag[__DIR_REPL] = 422 ntohl(mnl_attr_get_u32(tb[CTA_PROTOINFO_SCTP_VTAG_REPLY])); 423 set_bit(ATTR_SCTP_VTAG_REPL, ct->head.set); 424 } 425 426 return 0; 427} 428 429static int 430nfct_parse_pinfo_dccp_attr_cb(const struct nlattr *attr, void *data) 431{ 432 const struct nlattr **tb = data; 433 int type = mnl_attr_get_type(attr); 434 435 if (mnl_attr_type_valid(attr, CTA_PROTOINFO_DCCP_MAX) < 0) 436 return MNL_CB_OK; 437 438 switch(type) { 439 case CTA_PROTOINFO_DCCP_STATE: 440 case CTA_PROTOINFO_DCCP_ROLE: 441 if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0) 442 return MNL_CB_ERROR; 443 break; 444 case CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ: 445 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) 446 return MNL_CB_ERROR; 447 break; 448 } 449 tb[type] = attr; 450 return MNL_CB_OK; 451} 452 453static int 454nfct_parse_protoinfo_dccp(const struct nlattr *attr, struct nf_conntrack *ct) 455{ 456 struct nlattr *tb[CTA_PROTOINFO_DCCP_MAX+1] = {}; 457 458 if (mnl_attr_parse_nested(attr, nfct_parse_pinfo_dccp_attr_cb, tb) < 0) 459 return -1; 460 461 if (tb[CTA_PROTOINFO_DCCP_STATE]) { 462 ct->protoinfo.dccp.state = mnl_attr_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]); 463 set_bit(ATTR_DCCP_STATE, ct->head.set); 464 } 465 if (tb[CTA_PROTOINFO_DCCP_ROLE]) { 466 ct->protoinfo.dccp.role = mnl_attr_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]); 467 set_bit(ATTR_DCCP_ROLE, ct->head.set); 468 } 469 if (tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ]) { 470 ct->protoinfo.dccp.handshake_seq = be64toh( 471 mnl_attr_get_u64(tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ])); 472 set_bit(ATTR_DCCP_HANDSHAKE_SEQ, ct->head.set); 473 } 474 475 return 0; 476} 477 478static int 479nfct_parse_protoinfo_attr_cb(const struct nlattr *attr, void *data) 480{ 481 const struct nlattr **tb = data; 482 int type = mnl_attr_get_type(attr); 483 484 if (mnl_attr_type_valid(attr, CTA_PROTOINFO_TCP_MAX) < 0) 485 return MNL_CB_OK; 486 487 switch(type) { 488 case CTA_PROTOINFO_TCP: 489 case CTA_PROTOINFO_SCTP: 490 case CTA_PROTOINFO_DCCP: 491 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) 492 return MNL_CB_ERROR; 493 break; 494 } 495 tb[type] = attr; 496 return MNL_CB_OK; 497} 498 499static int 500nfct_parse_protoinfo(const struct nlattr *attr, struct nf_conntrack *ct) 501{ 502 struct nlattr *tb[CTA_PROTOINFO_MAX+1] = {}; 503 504 if (mnl_attr_parse_nested(attr, nfct_parse_protoinfo_attr_cb, tb) < 0) 505 return -1; 506 507 if (tb[CTA_PROTOINFO_TCP]) 508 nfct_parse_protoinfo_tcp(tb[CTA_PROTOINFO_TCP], ct); 509 510 if (tb[CTA_PROTOINFO_SCTP]) 511 nfct_parse_protoinfo_sctp(tb[CTA_PROTOINFO_SCTP], ct); 512 513 if (tb[CTA_PROTOINFO_DCCP]) 514 nfct_parse_protoinfo_dccp(tb[CTA_PROTOINFO_DCCP], ct); 515 516 return 0; 517} 518 519static int nfct_parse_counters_attr_cb(const struct nlattr *attr, void *data) 520{ 521 const struct nlattr **tb = data; 522 int type = mnl_attr_get_type(attr); 523 524 if (mnl_attr_type_valid(attr, CTA_COUNTERS_MAX) < 0) 525 return MNL_CB_OK; 526 527 switch(type) { 528 case CTA_COUNTERS_PACKETS: 529 case CTA_COUNTERS_BYTES: 530 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) 531 return MNL_CB_ERROR; 532 break; 533 case CTA_COUNTERS32_PACKETS: 534 case CTA_COUNTERS32_BYTES: 535 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) 536 return MNL_CB_ERROR; 537 break; 538 } 539 tb[type] = attr; 540 return MNL_CB_OK; 541} 542 543static int 544nfct_parse_counters(const struct nlattr *attr, struct nf_conntrack *ct, 545 int dir) 546{ 547 struct nlattr *tb[CTA_COUNTERS_MAX+1] = {}; 548 549 if (mnl_attr_parse_nested(attr, nfct_parse_counters_attr_cb, tb) < 0) 550 return -1; 551 552 if (tb[CTA_COUNTERS_PACKETS] || tb[CTA_COUNTERS32_PACKETS]) { 553 if (tb[CTA_COUNTERS32_PACKETS]) { 554 ct->counters[dir].packets = 555 ntohl(mnl_attr_get_u32(tb[CTA_COUNTERS32_PACKETS])); 556 } 557 if (tb[CTA_COUNTERS_PACKETS]) { 558 ct->counters[dir].packets = 559 be64toh(mnl_attr_get_u64(tb[CTA_COUNTERS_PACKETS])); 560 } 561 switch(dir) { 562 case __DIR_ORIG: 563 set_bit(ATTR_ORIG_COUNTER_PACKETS, ct->head.set); 564 break; 565 case __DIR_REPL: 566 set_bit(ATTR_REPL_COUNTER_PACKETS, ct->head.set); 567 break; 568 } 569 } 570 if (tb[CTA_COUNTERS_BYTES] || tb[CTA_COUNTERS32_BYTES]) { 571 if (tb[CTA_COUNTERS32_BYTES]) { 572 ct->counters[dir].bytes = 573 ntohl(mnl_attr_get_u32(tb[CTA_COUNTERS32_BYTES])); 574 } 575 if (tb[CTA_COUNTERS_BYTES]) { 576 ct->counters[dir].bytes = 577 be64toh(mnl_attr_get_u64(tb[CTA_COUNTERS_BYTES])); 578 } 579 580 switch(dir) { 581 case __DIR_ORIG: 582 set_bit(ATTR_ORIG_COUNTER_BYTES, ct->head.set); 583 break; 584 case __DIR_REPL: 585 set_bit(ATTR_REPL_COUNTER_BYTES, ct->head.set); 586 break; 587 } 588 } 589 590 return 0; 591} 592 593static int 594nfct_parse_nat_seq_attr_cb(const struct nlattr *attr, void *data) 595{ 596 const struct nlattr **tb = data; 597 int type = mnl_attr_get_type(attr); 598 599 if (mnl_attr_type_valid(attr, CTA_NAT_SEQ_MAX) < 0) 600 return MNL_CB_OK; 601 602 switch(type) { 603 case CTA_NAT_SEQ_CORRECTION_POS: 604 case CTA_NAT_SEQ_OFFSET_BEFORE: 605 case CTA_NAT_SEQ_OFFSET_AFTER: 606 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) 607 return MNL_CB_ERROR; 608 break; 609 } 610 tb[type] = attr; 611 return MNL_CB_OK; 612} 613 614static int 615nfct_parse_nat_seq(const struct nlattr *attr, struct nf_conntrack *ct, int dir) 616{ 617 struct nlattr *tb[CTA_NAT_SEQ_MAX+1] = {}; 618 619 if (mnl_attr_parse_nested(attr, nfct_parse_nat_seq_attr_cb, tb) < 0) 620 return -1; 621 622 if (tb[CTA_NAT_SEQ_CORRECTION_POS]) { 623 ct->natseq[dir].correction_pos = 624 ntohl(mnl_attr_get_u32(tb[CTA_NAT_SEQ_CORRECTION_POS])); 625 switch(dir) { 626 case __DIR_ORIG: 627 set_bit(ATTR_ORIG_NAT_SEQ_CORRECTION_POS, ct->head.set); 628 break; 629 case __DIR_REPL: 630 set_bit(ATTR_REPL_NAT_SEQ_CORRECTION_POS, ct->head.set); 631 break; 632 } 633 } 634 635 if (tb[CTA_NAT_SEQ_OFFSET_BEFORE]) { 636 ct->natseq[dir].offset_before = 637 ntohl(mnl_attr_get_u32(tb[CTA_NAT_SEQ_OFFSET_BEFORE])); 638 switch(dir) { 639 case __DIR_ORIG: 640 set_bit(ATTR_ORIG_NAT_SEQ_OFFSET_BEFORE, ct->head.set); 641 break; 642 case __DIR_REPL: 643 set_bit(ATTR_REPL_NAT_SEQ_OFFSET_BEFORE, ct->head.set); 644 break; 645 } 646 } 647 648 if (tb[CTA_NAT_SEQ_OFFSET_AFTER]) { 649 ct->natseq[dir].offset_after = 650 ntohl(mnl_attr_get_u32(tb[CTA_NAT_SEQ_OFFSET_AFTER])); 651 switch(dir) { 652 case __DIR_ORIG: 653 set_bit(ATTR_ORIG_NAT_SEQ_OFFSET_AFTER, ct->head.set); 654 break; 655 case __DIR_REPL: 656 set_bit(ATTR_REPL_NAT_SEQ_OFFSET_AFTER, ct->head.set); 657 break; 658 } 659 } 660 661 return 0; 662} 663 664static int 665nfct_parse_helper_attr_cb(const struct nlattr *attr, void *data) 666{ 667 const struct nlattr **tb = data; 668 int type = mnl_attr_get_type(attr); 669 670 if (mnl_attr_type_valid(attr, CTA_HELP_MAX) < 0) 671 return MNL_CB_OK; 672 673 switch(type) { 674 case CTA_HELP_NAME: 675 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) 676 return MNL_CB_ERROR; 677 break; 678 } 679 tb[type] = attr; 680 return MNL_CB_OK; 681} 682 683static int 684nfct_parse_helper(const struct nlattr *attr, struct nf_conntrack *ct) 685{ 686 struct nlattr *tb[CTA_HELP_MAX+1] = {}; 687 688 if (mnl_attr_parse_nested(attr, nfct_parse_helper_attr_cb, tb) < 0) 689 return -1; 690 691 if (!tb[CTA_HELP_NAME]) 692 return 0; 693 694 strncpy(ct->helper_name, mnl_attr_get_str(tb[CTA_HELP_NAME]), 695 NFCT_HELPER_NAME_MAX); 696 ct->helper_name[NFCT_HELPER_NAME_MAX-1] = '\0'; 697 set_bit(ATTR_HELPER_NAME, ct->head.set); 698 699 if (!tb[CTA_HELP_INFO]) 700 return 0; 701 702 ct->helper_info_len = mnl_attr_get_payload_len(tb[CTA_HELP_INFO]); 703 ct->helper_info = calloc(1, ct->helper_info_len); 704 if (ct->helper_info == NULL) 705 return -1; 706 707 memcpy(ct->helper_info, mnl_attr_get_payload(tb[CTA_HELP_INFO]), 708 ct->helper_info_len); 709 set_bit(ATTR_HELPER_INFO, ct->head.set); 710 711 return 0; 712} 713 714static int 715nfct_parse_secctx_attr_cb(const struct nlattr *attr, void *data) 716{ 717 const struct nlattr **tb = data; 718 int type = mnl_attr_get_type(attr); 719 720 if (mnl_attr_type_valid(attr, CTA_SECCTX_MAX) < 0) 721 return MNL_CB_OK; 722 723 switch(type) { 724 case CTA_SECCTX_NAME: 725 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) 726 return MNL_CB_ERROR; 727 break; 728 } 729 tb[type] = attr; 730 return MNL_CB_OK; 731} 732 733static int 734nfct_parse_secctx(const struct nlattr *attr, struct nf_conntrack *ct) 735{ 736 struct nlattr *tb[CTA_SECCTX_MAX+1] = {}; 737 738 if (mnl_attr_parse_nested(attr, nfct_parse_secctx_attr_cb, tb) < 0) 739 return -1; 740 741 if (!tb[CTA_SECCTX_NAME]) 742 return 0; 743 744 ct->secctx = strdup(NFA_DATA(tb[CTA_SECCTX_NAME])); 745 if (ct->secctx) 746 set_bit(ATTR_SECCTX, ct->head.set); 747 748 return 0; 749} 750 751static int 752nfct_parse_timestamp_attr_cb(const struct nlattr *attr, void *data) 753{ 754 const struct nlattr **tb = data; 755 int type = mnl_attr_get_type(attr); 756 757 if (mnl_attr_type_valid(attr, CTA_TIMESTAMP_MAX) < 0) 758 return MNL_CB_OK; 759 760 switch(type) { 761 case CTA_TIMESTAMP_START: 762 case CTA_TIMESTAMP_STOP: 763 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) 764 return MNL_CB_ERROR; 765 break; 766 } 767 tb[type] = attr; 768 return MNL_CB_OK; 769} 770 771static int 772nfct_parse_timestamp(const struct nlattr *attr, struct nf_conntrack *ct) 773{ 774 struct nlattr *tb[CTA_TIMESTAMP_MAX+1] = {}; 775 776 if (mnl_attr_parse_nested(attr, nfct_parse_timestamp_attr_cb, tb) < 0) 777 return -1; 778 779 if (tb[CTA_TIMESTAMP_START]) { 780 ct->timestamp.start = 781 be64toh(mnl_attr_get_u64(tb[CTA_TIMESTAMP_START])); 782 set_bit(ATTR_TIMESTAMP_START, ct->head.set); 783 } 784 if (tb[CTA_TIMESTAMP_STOP]) { 785 ct->timestamp.stop = 786 be64toh(mnl_attr_get_u64(tb[CTA_TIMESTAMP_STOP])); 787 set_bit(ATTR_TIMESTAMP_STOP, ct->head.set); 788 } 789 790 return 0; 791} 792 793static int nfct_parse_labels(const struct nlattr *attr, struct nf_conntrack *ct) 794{ 795 uint16_t len = mnl_attr_get_payload_len(attr); 796 struct nfct_bitmask *mask; 797 uint32_t *bits; 798 799 if (len == 0) 800 return 0; 801 802 mask = nfct_bitmask_new((len * CHAR_BIT) - 1); 803 if (!mask) 804 return -1; 805 bits = mnl_attr_get_payload(attr); 806 807 memcpy(mask->bits, bits, len); 808 nfct_set_attr(ct, ATTR_CONNLABELS, mask); 809 return 0; 810} 811 812static int 813nfct_parse_conntrack_attr_cb(const struct nlattr *attr, void *data) 814{ 815 const struct nlattr **tb = data; 816 int type = mnl_attr_get_type(attr); 817 818 if (mnl_attr_type_valid(attr, CTA_MAX) < 0) 819 return MNL_CB_OK; 820 821 switch(type) { 822 case CTA_TUPLE_ORIG: 823 case CTA_TUPLE_REPLY: 824 case CTA_TUPLE_MASTER: 825 case CTA_NAT_SEQ_ADJ_ORIG: 826 case CTA_NAT_SEQ_ADJ_REPLY: 827 case CTA_PROTOINFO: 828 case CTA_COUNTERS_ORIG: 829 case CTA_COUNTERS_REPLY: 830 case CTA_HELP: 831 case CTA_SECCTX: 832 case CTA_TIMESTAMP: 833 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) 834 return MNL_CB_ERROR; 835 break; 836 case CTA_STATUS: 837 case CTA_TIMEOUT: 838 case CTA_MARK: 839 case CTA_SECMARK: 840 case CTA_USE: 841 case CTA_ID: 842 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) 843 return MNL_CB_ERROR; 844 break; 845 case CTA_ZONE: 846 if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) 847 return MNL_CB_ERROR; 848 break; 849 case CTA_NAT_SRC: 850 case CTA_NAT_DST: 851 /* deprecated */ 852 break; 853 } 854 tb[type] = attr; 855 return MNL_CB_OK; 856} 857 858int 859nfct_payload_parse(const void *payload, size_t payload_len, 860 uint16_t l3num, struct nf_conntrack *ct) 861{ 862 struct nlattr *tb[CTA_MAX+1] = {}; 863 864 if (mnl_attr_parse_payload(payload, payload_len, 865 nfct_parse_conntrack_attr_cb, tb) < 0) 866 return -1; 867 868 if (tb[CTA_TUPLE_ORIG]) { 869 ct->head.orig.l3protonum = l3num; 870 set_bit(ATTR_ORIG_L3PROTO, ct->head.set); 871 872 if (nfct_parse_tuple(tb[CTA_TUPLE_ORIG], &ct->head.orig, 873 __DIR_ORIG, ct->head.set) < 0) 874 return -1; 875 } 876 877 if (tb[CTA_TUPLE_REPLY]) { 878 ct->repl.l3protonum = l3num; 879 set_bit(ATTR_REPL_L3PROTO, ct->head.set); 880 881 if (nfct_parse_tuple(tb[CTA_TUPLE_REPLY], &ct->repl, 882 __DIR_REPL, ct->head.set) < 0) 883 return -1; 884 } 885 886 if (tb[CTA_TUPLE_MASTER]) { 887 ct->master.l3protonum = l3num; 888 set_bit(ATTR_MASTER_L3PROTO, ct->head.set); 889 890 if (nfct_parse_tuple(tb[CTA_TUPLE_MASTER], &ct->master, 891 __DIR_MASTER, ct->head.set) < 0) 892 return -1; 893 } 894 895 if (tb[CTA_NAT_SEQ_ADJ_ORIG]) { 896 if (nfct_parse_nat_seq(tb[CTA_NAT_SEQ_ADJ_ORIG], 897 ct, __DIR_ORIG) < 0) 898 return -1; 899 } 900 901 if (tb[CTA_NAT_SEQ_ADJ_REPLY]) { 902 if (nfct_parse_nat_seq(tb[CTA_NAT_SEQ_ADJ_REPLY], 903 ct, __DIR_REPL) < 0) 904 return -1; 905 } 906 907 if (tb[CTA_STATUS]) { 908 ct->status = ntohl(mnl_attr_get_u32(tb[CTA_STATUS])); 909 set_bit(ATTR_STATUS, ct->head.set); 910 } 911 912 if (tb[CTA_PROTOINFO]) { 913 if (nfct_parse_protoinfo(tb[CTA_PROTOINFO], ct) < 0) 914 return -1; 915 } 916 917 if (tb[CTA_TIMEOUT]) { 918 ct->timeout = ntohl(mnl_attr_get_u32(tb[CTA_TIMEOUT])); 919 set_bit(ATTR_TIMEOUT, ct->head.set); 920 } 921 922 if (tb[CTA_MARK]) { 923 ct->mark = ntohl(mnl_attr_get_u32(tb[CTA_MARK])); 924 set_bit(ATTR_MARK, ct->head.set); 925 } 926 927 if (tb[CTA_SECMARK]) { 928 ct->secmark = ntohl(mnl_attr_get_u32(tb[CTA_SECMARK])); 929 set_bit(ATTR_SECMARK, ct->head.set); 930 } 931 932 if (tb[CTA_COUNTERS_ORIG]) { 933 if (nfct_parse_counters(tb[CTA_COUNTERS_ORIG], 934 ct, __DIR_ORIG) < 0) 935 return -1; 936 } 937 938 if (tb[CTA_COUNTERS_REPLY]) { 939 if (nfct_parse_counters(tb[CTA_COUNTERS_REPLY], 940 ct, __DIR_REPL) < 0) 941 return -1; 942 } 943 944 if (tb[CTA_USE]) { 945 ct->use = ntohl(mnl_attr_get_u32(tb[CTA_USE])); 946 set_bit(ATTR_USE, ct->head.set); 947 } 948 949 if (tb[CTA_ID]) { 950 ct->id = ntohl(mnl_attr_get_u32(tb[CTA_ID])); 951 set_bit(ATTR_ID, ct->head.set); 952 } 953 954 if (tb[CTA_HELP]) { 955 if (nfct_parse_helper(tb[CTA_HELP], ct) < 0) 956 return -1; 957 } 958 959 if (tb[CTA_ZONE]) { 960 ct->zone = ntohs(mnl_attr_get_u16(tb[CTA_ZONE])); 961 set_bit(ATTR_ZONE, ct->head.set); 962 } 963 964 if (tb[CTA_SECCTX]) { 965 if (nfct_parse_secctx(tb[CTA_SECCTX], ct) < 0) 966 return -1; 967 } 968 969 if (tb[CTA_TIMESTAMP]) { 970 if (nfct_parse_timestamp(tb[CTA_TIMESTAMP], ct) < 0) 971 return -1; 972 } 973 974 if (tb[CTA_LABELS]) { 975 if (nfct_parse_labels(tb[CTA_LABELS], ct) < 0) 976 return -1; 977 } 978 /* CTA_LABELS_MASK: never sent by kernel */ 979 980 return 0; 981} 982 983int nfct_nlmsg_parse(const struct nlmsghdr *nlh, struct nf_conntrack *ct) 984{ 985 struct nfgenmsg *nfhdr = mnl_nlmsg_get_payload(nlh); 986 987 return nfct_payload_parse((uint8_t *)nfhdr + sizeof(struct nfgenmsg), 988 mnl_nlmsg_get_payload_len(nlh) - sizeof(struct nfgenmsg), 989 nfhdr->nfgen_family, ct); 990} 991