libnetfilter_conntrack 1.1.0
conntrack/parse_mnl.c
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 abi_breakage();
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 abi_breakage();
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 abi_breakage();
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 abi_breakage();
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 abi_breakage();
256 break;
257 case CTA_TUPLE_ZONE:
258 if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
259 abi_breakage();
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 abi_breakage();
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 abi_breakage();
322 break;
323 }
324 tb[type] = attr;
325 return MNL_CB_OK;
326}
327
328static int
329nfct_parse_protoinfo_tcp(const struct nlattr *attr, struct nf_conntrack *ct)
330{
331 struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1] = {};
332
333 if (mnl_attr_parse_nested(attr, nfct_parse_pinfo_tcp_attr_cb, tb) < 0)
334 return -1;
335
336 if (tb[CTA_PROTOINFO_TCP_STATE]) {
337 ct->protoinfo.tcp.state =
338 mnl_attr_get_u8(tb[CTA_PROTOINFO_TCP_STATE]);
339 set_bit(ATTR_TCP_STATE, ct->head.set);
340 }
341
342 if (tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL]) {
343 memcpy(&ct->protoinfo.tcp.wscale[__DIR_ORIG],
344 mnl_attr_get_payload(tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL]),
345 sizeof(uint8_t));
346 set_bit(ATTR_TCP_WSCALE_ORIG, ct->head.set);
347 }
348
349 if (tb[CTA_PROTOINFO_TCP_WSCALE_REPLY]) {
350 memcpy(&ct->protoinfo.tcp.wscale[__DIR_REPL],
351 mnl_attr_get_payload(tb[CTA_PROTOINFO_TCP_WSCALE_REPLY]),
352 sizeof(uint8_t));
353 set_bit(ATTR_TCP_WSCALE_REPL, ct->head.set);
354 }
355
356 if (tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL]) {
357 memcpy(&ct->protoinfo.tcp.flags[0],
358 mnl_attr_get_payload(tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL]),
359 sizeof(struct nf_ct_tcp_flags));
360 set_bit(ATTR_TCP_FLAGS_ORIG, ct->head.set);
361 set_bit(ATTR_TCP_MASK_ORIG, ct->head.set);
362 }
363
364 if (tb[CTA_PROTOINFO_TCP_FLAGS_REPLY]) {
365 memcpy(&ct->protoinfo.tcp.flags[1],
366 mnl_attr_get_payload(tb[CTA_PROTOINFO_TCP_FLAGS_REPLY]),
367 sizeof(struct nf_ct_tcp_flags));
368 set_bit(ATTR_TCP_FLAGS_REPL, ct->head.set);
369 set_bit(ATTR_TCP_MASK_REPL, ct->head.set);
370 }
371
372 return 0;
373}
374
375static int
376nfct_parse_pinfo_sctp_attr_cb(const struct nlattr *attr, void *data)
377{
378 const struct nlattr **tb = data;
379 int type = mnl_attr_get_type(attr);
380
381 if (mnl_attr_type_valid(attr, CTA_PROTOINFO_SCTP_MAX) < 0)
382 return MNL_CB_OK;
383
384 switch(type) {
385 case CTA_PROTOINFO_SCTP_STATE:
386 if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0)
387 abi_breakage();
388 break;
389 case CTA_PROTOINFO_SCTP_VTAG_ORIGINAL:
390 case CTA_PROTOINFO_SCTP_VTAG_REPLY:
391 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
392 abi_breakage();
393 break;
394 }
395 tb[type] = attr;
396 return MNL_CB_OK;
397}
398
399static int
400nfct_parse_protoinfo_sctp(const struct nlattr *attr, struct nf_conntrack *ct)
401{
402 struct nlattr *tb[CTA_PROTOINFO_SCTP_MAX+1] = {};
403
404 if (mnl_attr_parse_nested(attr, nfct_parse_pinfo_sctp_attr_cb, tb) < 0)
405 return -1;
406
407 if (tb[CTA_PROTOINFO_SCTP_STATE]) {
408 ct->protoinfo.sctp.state =
409 mnl_attr_get_u8(tb[CTA_PROTOINFO_SCTP_STATE]);
410 set_bit(ATTR_SCTP_STATE, ct->head.set);
411 }
412
413 if (tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]) {
414 ct->protoinfo.sctp.vtag[__DIR_ORIG] =
415 ntohl(mnl_attr_get_u32(tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]));
416 set_bit(ATTR_SCTP_VTAG_ORIG, ct->head.set);
417 }
418
419 if (tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]) {
420 ct->protoinfo.sctp.vtag[__DIR_REPL] =
421 ntohl(mnl_attr_get_u32(tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]));
422 set_bit(ATTR_SCTP_VTAG_REPL, ct->head.set);
423 }
424
425 return 0;
426}
427
428static int
429nfct_parse_pinfo_dccp_attr_cb(const struct nlattr *attr, void *data)
430{
431 const struct nlattr **tb = data;
432 int type = mnl_attr_get_type(attr);
433
434 if (mnl_attr_type_valid(attr, CTA_PROTOINFO_DCCP_MAX) < 0)
435 return MNL_CB_OK;
436
437 switch(type) {
438 case CTA_PROTOINFO_DCCP_STATE:
439 case CTA_PROTOINFO_DCCP_ROLE:
440 if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0)
441 abi_breakage();
442 break;
443 case CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ:
444 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
445 abi_breakage();
446 break;
447 }
448 tb[type] = attr;
449 return MNL_CB_OK;
450}
451
452static int
453nfct_parse_protoinfo_dccp(const struct nlattr *attr, struct nf_conntrack *ct)
454{
455 struct nlattr *tb[CTA_PROTOINFO_DCCP_MAX+1] = {};
456
457 if (mnl_attr_parse_nested(attr, nfct_parse_pinfo_dccp_attr_cb, tb) < 0)
458 return -1;
459
460 if (tb[CTA_PROTOINFO_DCCP_STATE]) {
461 ct->protoinfo.dccp.state = mnl_attr_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]);
462 set_bit(ATTR_DCCP_STATE, ct->head.set);
463 }
464 if (tb[CTA_PROTOINFO_DCCP_ROLE]) {
465 ct->protoinfo.dccp.role = mnl_attr_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]);
466 set_bit(ATTR_DCCP_ROLE, ct->head.set);
467 }
468 if (tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ]) {
469 ct->protoinfo.dccp.handshake_seq = be64toh(
470 mnl_attr_get_u64(tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ]));
471 set_bit(ATTR_DCCP_HANDSHAKE_SEQ, ct->head.set);
472 }
473
474 return 0;
475}
476
477static int
478nfct_parse_protoinfo_attr_cb(const struct nlattr *attr, void *data)
479{
480 const struct nlattr **tb = data;
481 int type = mnl_attr_get_type(attr);
482
483 if (mnl_attr_type_valid(attr, CTA_PROTOINFO_TCP_MAX) < 0)
484 return MNL_CB_OK;
485
486 switch(type) {
487 case CTA_PROTOINFO_TCP:
488 case CTA_PROTOINFO_SCTP:
489 case CTA_PROTOINFO_DCCP:
490 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
491 abi_breakage();
492 break;
493 }
494 tb[type] = attr;
495 return MNL_CB_OK;
496}
497
498static int
499nfct_parse_protoinfo(const struct nlattr *attr, struct nf_conntrack *ct)
500{
501 struct nlattr *tb[CTA_PROTOINFO_MAX+1] = {};
502
503 if (mnl_attr_parse_nested(attr, nfct_parse_protoinfo_attr_cb, tb) < 0)
504 return -1;
505
506 if (tb[CTA_PROTOINFO_TCP])
507 nfct_parse_protoinfo_tcp(tb[CTA_PROTOINFO_TCP], ct);
508
509 if (tb[CTA_PROTOINFO_SCTP])
510 nfct_parse_protoinfo_sctp(tb[CTA_PROTOINFO_SCTP], ct);
511
512 if (tb[CTA_PROTOINFO_DCCP])
513 nfct_parse_protoinfo_dccp(tb[CTA_PROTOINFO_DCCP], ct);
514
515 return 0;
516}
517
518static int nfct_parse_counters_attr_cb(const struct nlattr *attr, void *data)
519{
520 const struct nlattr **tb = data;
521 int type = mnl_attr_get_type(attr);
522
523 if (mnl_attr_type_valid(attr, CTA_COUNTERS_MAX) < 0)
524 return MNL_CB_OK;
525
526 switch(type) {
527 case CTA_COUNTERS_PACKETS:
528 case CTA_COUNTERS_BYTES:
529 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
530 abi_breakage();
531 break;
532 case CTA_COUNTERS32_PACKETS:
533 case CTA_COUNTERS32_BYTES:
534 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
535 abi_breakage();
536 break;
537 }
538 tb[type] = attr;
539 return MNL_CB_OK;
540}
541
542static int
543nfct_parse_counters(const struct nlattr *attr, struct nf_conntrack *ct,
544 int dir)
545{
546 struct nlattr *tb[CTA_COUNTERS_MAX+1] = {};
547
548 if (mnl_attr_parse_nested(attr, nfct_parse_counters_attr_cb, tb) < 0)
549 return -1;
550
551 if (tb[CTA_COUNTERS_PACKETS] || tb[CTA_COUNTERS32_PACKETS]) {
552 if (tb[CTA_COUNTERS32_PACKETS]) {
553 ct->counters[dir].packets =
554 ntohl(mnl_attr_get_u32(tb[CTA_COUNTERS32_PACKETS]));
555 }
556 if (tb[CTA_COUNTERS_PACKETS]) {
557 ct->counters[dir].packets =
558 be64toh(mnl_attr_get_u64(tb[CTA_COUNTERS_PACKETS]));
559 }
560 switch(dir) {
561 case __DIR_ORIG:
562 set_bit(ATTR_ORIG_COUNTER_PACKETS, ct->head.set);
563 break;
564 case __DIR_REPL:
565 set_bit(ATTR_REPL_COUNTER_PACKETS, ct->head.set);
566 break;
567 }
568 }
569 if (tb[CTA_COUNTERS_BYTES] || tb[CTA_COUNTERS32_BYTES]) {
570 if (tb[CTA_COUNTERS32_BYTES]) {
571 ct->counters[dir].bytes =
572 ntohl(mnl_attr_get_u32(tb[CTA_COUNTERS32_BYTES]));
573 }
574 if (tb[CTA_COUNTERS_BYTES]) {
575 ct->counters[dir].bytes =
576 be64toh(mnl_attr_get_u64(tb[CTA_COUNTERS_BYTES]));
577 }
578
579 switch(dir) {
580 case __DIR_ORIG:
581 set_bit(ATTR_ORIG_COUNTER_BYTES, ct->head.set);
582 break;
583 case __DIR_REPL:
584 set_bit(ATTR_REPL_COUNTER_BYTES, ct->head.set);
585 break;
586 }
587 }
588
589 return 0;
590}
591
592static int
593nfct_parse_nat_seq_attr_cb(const struct nlattr *attr, void *data)
594{
595 const struct nlattr **tb = data;
596 int type = mnl_attr_get_type(attr);
597
598 if (mnl_attr_type_valid(attr, CTA_NAT_SEQ_MAX) < 0)
599 return MNL_CB_OK;
600
601 switch(type) {
602 case CTA_NAT_SEQ_CORRECTION_POS:
603 case CTA_NAT_SEQ_OFFSET_BEFORE:
604 case CTA_NAT_SEQ_OFFSET_AFTER:
605 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
606 abi_breakage();
607 break;
608 }
609 tb[type] = attr;
610 return MNL_CB_OK;
611}
612
613static int
614nfct_parse_nat_seq(const struct nlattr *attr, struct nf_conntrack *ct, int dir)
615{
616 struct nlattr *tb[CTA_NAT_SEQ_MAX+1] = {};
617
618 if (mnl_attr_parse_nested(attr, nfct_parse_nat_seq_attr_cb, tb) < 0)
619 return -1;
620
621 if (tb[CTA_NAT_SEQ_CORRECTION_POS]) {
622 ct->natseq[dir].correction_pos =
623 ntohl(mnl_attr_get_u32(tb[CTA_NAT_SEQ_CORRECTION_POS]));
624 switch(dir) {
625 case __DIR_ORIG:
626 set_bit(ATTR_ORIG_NAT_SEQ_CORRECTION_POS, ct->head.set);
627 break;
628 case __DIR_REPL:
629 set_bit(ATTR_REPL_NAT_SEQ_CORRECTION_POS, ct->head.set);
630 break;
631 }
632 }
633
634 if (tb[CTA_NAT_SEQ_OFFSET_BEFORE]) {
635 ct->natseq[dir].offset_before =
636 ntohl(mnl_attr_get_u32(tb[CTA_NAT_SEQ_OFFSET_BEFORE]));
637 switch(dir) {
638 case __DIR_ORIG:
639 set_bit(ATTR_ORIG_NAT_SEQ_OFFSET_BEFORE, ct->head.set);
640 break;
641 case __DIR_REPL:
642 set_bit(ATTR_REPL_NAT_SEQ_OFFSET_BEFORE, ct->head.set);
643 break;
644 }
645 }
646
647 if (tb[CTA_NAT_SEQ_OFFSET_AFTER]) {
648 ct->natseq[dir].offset_after =
649 ntohl(mnl_attr_get_u32(tb[CTA_NAT_SEQ_OFFSET_AFTER]));
650 switch(dir) {
651 case __DIR_ORIG:
652 set_bit(ATTR_ORIG_NAT_SEQ_OFFSET_AFTER, ct->head.set);
653 break;
654 case __DIR_REPL:
655 set_bit(ATTR_REPL_NAT_SEQ_OFFSET_AFTER, ct->head.set);
656 break;
657 }
658 }
659
660 return 0;
661}
662
663static int
664nfct_parse_helper_attr_cb(const struct nlattr *attr, void *data)
665{
666 const struct nlattr **tb = data;
667 int type = mnl_attr_get_type(attr);
668
669 if (mnl_attr_type_valid(attr, CTA_HELP_MAX) < 0)
670 return MNL_CB_OK;
671
672 switch(type) {
673 case CTA_HELP_NAME:
674 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
675 abi_breakage();
676 break;
677 }
678 tb[type] = attr;
679 return MNL_CB_OK;
680}
681
682static int
683nfct_parse_helper(const struct nlattr *attr, struct nf_conntrack *ct)
684{
685 struct nlattr *tb[CTA_HELP_MAX+1] = {};
686
687 if (mnl_attr_parse_nested(attr, nfct_parse_helper_attr_cb, tb) < 0)
688 return -1;
689
690 if (!tb[CTA_HELP_NAME])
691 return 0;
692
693 snprintf(ct->helper_name, NFCT_HELPER_NAME_MAX, "%s",
694 mnl_attr_get_str(tb[CTA_HELP_NAME]));
695 set_bit(ATTR_HELPER_NAME, ct->head.set);
696
697 if (!tb[CTA_HELP_INFO])
698 return 0;
699
700 ct->helper_info_len = mnl_attr_get_payload_len(tb[CTA_HELP_INFO]);
701 ct->helper_info = calloc(1, ct->helper_info_len);
702 if (ct->helper_info == NULL)
703 return -1;
704
705 memcpy(ct->helper_info, mnl_attr_get_payload(tb[CTA_HELP_INFO]),
706 ct->helper_info_len);
707 set_bit(ATTR_HELPER_INFO, ct->head.set);
708
709 return 0;
710}
711
712static int
713nfct_parse_secctx_attr_cb(const struct nlattr *attr, void *data)
714{
715 const struct nlattr **tb = data;
716 int type = mnl_attr_get_type(attr);
717
718 if (mnl_attr_type_valid(attr, CTA_SECCTX_MAX) < 0)
719 return MNL_CB_OK;
720
721 switch(type) {
722 case CTA_SECCTX_NAME:
723 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
724 abi_breakage();
725 break;
726 }
727 tb[type] = attr;
728 return MNL_CB_OK;
729}
730
731static int
732nfct_parse_secctx(const struct nlattr *attr, struct nf_conntrack *ct)
733{
734 struct nlattr *tb[CTA_SECCTX_MAX+1] = {};
735
736 if (mnl_attr_parse_nested(attr, nfct_parse_secctx_attr_cb, tb) < 0)
737 return -1;
738
739 if (!tb[CTA_SECCTX_NAME])
740 return 0;
741
742 ct->secctx = strdup(NFA_DATA(tb[CTA_SECCTX_NAME]));
743 if (ct->secctx)
744 set_bit(ATTR_SECCTX, ct->head.set);
745
746 return 0;
747}
748
749static int
750nfct_parse_timestamp_attr_cb(const struct nlattr *attr, void *data)
751{
752 const struct nlattr **tb = data;
753 int type = mnl_attr_get_type(attr);
754
755 if (mnl_attr_type_valid(attr, CTA_TIMESTAMP_MAX) < 0)
756 return MNL_CB_OK;
757
758 switch(type) {
759 case CTA_TIMESTAMP_START:
760 case CTA_TIMESTAMP_STOP:
761 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
762 abi_breakage();
763 break;
764 }
765 tb[type] = attr;
766 return MNL_CB_OK;
767}
768
769static int
770nfct_parse_timestamp(const struct nlattr *attr, struct nf_conntrack *ct)
771{
772 struct nlattr *tb[CTA_TIMESTAMP_MAX+1] = {};
773
774 if (mnl_attr_parse_nested(attr, nfct_parse_timestamp_attr_cb, tb) < 0)
775 return -1;
776
777 if (tb[CTA_TIMESTAMP_START]) {
778 ct->timestamp.start =
779 be64toh(mnl_attr_get_u64(tb[CTA_TIMESTAMP_START]));
780 set_bit(ATTR_TIMESTAMP_START, ct->head.set);
781 }
782 if (tb[CTA_TIMESTAMP_STOP]) {
783 ct->timestamp.stop =
784 be64toh(mnl_attr_get_u64(tb[CTA_TIMESTAMP_STOP]));
785 set_bit(ATTR_TIMESTAMP_STOP, ct->head.set);
786 }
787
788 return 0;
789}
790
791static int nfct_parse_labels(const struct nlattr *attr, struct nf_conntrack *ct)
792{
793 uint16_t len = mnl_attr_get_payload_len(attr);
794 struct nfct_bitmask *mask;
795 uint32_t *bits;
796
797 if (len == 0)
798 return 0;
799
800 mask = nfct_bitmask_new((len * CHAR_BIT) - 1);
801 if (!mask)
802 return -1;
803 bits = mnl_attr_get_payload(attr);
804
805 memcpy(mask->bits, bits, len);
806 nfct_set_attr(ct, ATTR_CONNLABELS, mask);
807 return 0;
808}
809
810static int nfct_parse_synproxy_attr_cb(const struct nlattr *attr, void *data)
811{
812 int type = mnl_attr_get_type(attr);
813 const struct nlattr **tb = data;
814
815 if (mnl_attr_type_valid(attr, CTA_SYNPROXY_MAX) < 0)
816 return MNL_CB_OK;
817
818 switch(type) {
819 case CTA_SYNPROXY_ISN:
820 case CTA_SYNPROXY_ITS:
821 case CTA_SYNPROXY_TSOFF:
822 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
823 abi_breakage();
824 break;
825 }
826 tb[type] = attr;
827 return MNL_CB_OK;
828}
829
830static int nfct_parse_synproxy(const struct nlattr *attr,
831 struct nf_conntrack *ct)
832{
833 struct nlattr *tb[CTA_SYNPROXY + 1] = {};
834
835 if (mnl_attr_parse_nested(attr, nfct_parse_synproxy_attr_cb, tb) < 0)
836 return -1;
837
838 if (tb[CTA_SYNPROXY_ISN]) {
839 ct->synproxy.isn =
840 ntohl(mnl_attr_get_u32(tb[CTA_SYNPROXY_ISN]));
841 set_bit(ATTR_SYNPROXY_ISN, ct->head.set);
842 }
843
844 if (tb[CTA_SYNPROXY_ITS]) {
845 ct->synproxy.its =
846 ntohl(mnl_attr_get_u32(tb[CTA_SYNPROXY_ITS]));
847 set_bit(ATTR_SYNPROXY_ITS, ct->head.set);
848 }
849
850 if (tb[CTA_SYNPROXY_TSOFF]) {
851 ct->synproxy.tsoff =
852 ntohl(mnl_attr_get_u32(tb[CTA_SYNPROXY_TSOFF]));
853 set_bit(ATTR_SYNPROXY_TSOFF, ct->head.set);
854 }
855
856 return 0;
857}
858
859static int
860nfct_parse_conntrack_attr_cb(const struct nlattr *attr, void *data)
861{
862 const struct nlattr **tb = data;
863 int type = mnl_attr_get_type(attr);
864
865 if (mnl_attr_type_valid(attr, CTA_MAX) < 0)
866 return MNL_CB_OK;
867
868 switch(type) {
869 case CTA_TUPLE_ORIG:
870 case CTA_TUPLE_REPLY:
871 case CTA_TUPLE_MASTER:
872 case CTA_NAT_SEQ_ADJ_ORIG:
873 case CTA_NAT_SEQ_ADJ_REPLY:
874 case CTA_PROTOINFO:
875 case CTA_COUNTERS_ORIG:
876 case CTA_COUNTERS_REPLY:
877 case CTA_HELP:
878 case CTA_SECCTX:
879 case CTA_TIMESTAMP:
880 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
881 abi_breakage();
882 break;
883 case CTA_STATUS:
884 case CTA_TIMEOUT:
885 case CTA_MARK:
886 case CTA_SECMARK:
887 case CTA_USE:
888 case CTA_ID:
889 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
890 abi_breakage();
891 break;
892 case CTA_ZONE:
893 if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
894 abi_breakage();
895 break;
896 case CTA_NAT_SRC:
897 case CTA_NAT_DST:
898 /* deprecated */
899 break;
900 }
901 tb[type] = attr;
902 return MNL_CB_OK;
903}
904
905int
906nfct_payload_parse(const void *payload, size_t payload_len,
907 uint16_t l3num, struct nf_conntrack *ct)
908{
909 struct nlattr *tb[CTA_MAX+1] = {};
910
911 if (mnl_attr_parse_payload(payload, payload_len,
912 nfct_parse_conntrack_attr_cb, tb) < 0)
913 return -1;
914
915 if (tb[CTA_TUPLE_ORIG]) {
916 ct->head.orig.l3protonum = l3num;
917 set_bit(ATTR_ORIG_L3PROTO, ct->head.set);
918
919 if (nfct_parse_tuple(tb[CTA_TUPLE_ORIG], &ct->head.orig,
920 __DIR_ORIG, ct->head.set) < 0)
921 return -1;
922 }
923
924 if (tb[CTA_TUPLE_REPLY]) {
925 ct->repl.l3protonum = l3num;
926 set_bit(ATTR_REPL_L3PROTO, ct->head.set);
927
928 if (nfct_parse_tuple(tb[CTA_TUPLE_REPLY], &ct->repl,
929 __DIR_REPL, ct->head.set) < 0)
930 return -1;
931 }
932
933 if (tb[CTA_TUPLE_MASTER]) {
934 ct->master.l3protonum = l3num;
935 set_bit(ATTR_MASTER_L3PROTO, ct->head.set);
936
937 if (nfct_parse_tuple(tb[CTA_TUPLE_MASTER], &ct->master,
938 __DIR_MASTER, ct->head.set) < 0)
939 return -1;
940 }
941
942 if (tb[CTA_NAT_SEQ_ADJ_ORIG]) {
943 if (nfct_parse_nat_seq(tb[CTA_NAT_SEQ_ADJ_ORIG],
944 ct, __DIR_ORIG) < 0)
945 return -1;
946 }
947
948 if (tb[CTA_NAT_SEQ_ADJ_REPLY]) {
949 if (nfct_parse_nat_seq(tb[CTA_NAT_SEQ_ADJ_REPLY],
950 ct, __DIR_REPL) < 0)
951 return -1;
952 }
953
954 if (tb[CTA_STATUS]) {
955 ct->status = ntohl(mnl_attr_get_u32(tb[CTA_STATUS]));
956 set_bit(ATTR_STATUS, ct->head.set);
957 }
958
959 if (tb[CTA_PROTOINFO]) {
960 if (nfct_parse_protoinfo(tb[CTA_PROTOINFO], ct) < 0)
961 return -1;
962 }
963
964 if (tb[CTA_TIMEOUT]) {
965 ct->timeout = ntohl(mnl_attr_get_u32(tb[CTA_TIMEOUT]));
966 set_bit(ATTR_TIMEOUT, ct->head.set);
967 }
968
969 if (tb[CTA_MARK]) {
970 ct->mark = ntohl(mnl_attr_get_u32(tb[CTA_MARK]));
971 set_bit(ATTR_MARK, ct->head.set);
972 }
973
974 if (tb[CTA_SECMARK]) {
975 ct->secmark = ntohl(mnl_attr_get_u32(tb[CTA_SECMARK]));
976 set_bit(ATTR_SECMARK, ct->head.set);
977 }
978
979 if (tb[CTA_COUNTERS_ORIG]) {
980 if (nfct_parse_counters(tb[CTA_COUNTERS_ORIG],
981 ct, __DIR_ORIG) < 0)
982 return -1;
983 }
984
985 if (tb[CTA_COUNTERS_REPLY]) {
986 if (nfct_parse_counters(tb[CTA_COUNTERS_REPLY],
987 ct, __DIR_REPL) < 0)
988 return -1;
989 }
990
991 if (tb[CTA_USE]) {
992 ct->use = ntohl(mnl_attr_get_u32(tb[CTA_USE]));
993 set_bit(ATTR_USE, ct->head.set);
994 }
995
996 if (tb[CTA_ID]) {
997 ct->id = ntohl(mnl_attr_get_u32(tb[CTA_ID]));
998 set_bit(ATTR_ID, ct->head.set);
999 }
1000
1001 if (tb[CTA_HELP]) {
1002 if (nfct_parse_helper(tb[CTA_HELP], ct) < 0)
1003 return -1;
1004 }
1005
1006 if (tb[CTA_ZONE]) {
1007 ct->zone = ntohs(mnl_attr_get_u16(tb[CTA_ZONE]));
1008 set_bit(ATTR_ZONE, ct->head.set);
1009 }
1010
1011 if (tb[CTA_SECCTX]) {
1012 if (nfct_parse_secctx(tb[CTA_SECCTX], ct) < 0)
1013 return -1;
1014 }
1015
1016 if (tb[CTA_TIMESTAMP]) {
1017 if (nfct_parse_timestamp(tb[CTA_TIMESTAMP], ct) < 0)
1018 return -1;
1019 }
1020
1021 if (tb[CTA_LABELS]) {
1022 if (nfct_parse_labels(tb[CTA_LABELS], ct) < 0)
1023 return -1;
1024 }
1025 /* CTA_LABELS_MASK: never sent by kernel */
1026
1027 if (tb[CTA_SYNPROXY]) {
1028 if (nfct_parse_synproxy(tb[CTA_SYNPROXY], ct) < 0)
1029 return -1;
1030 }
1031
1032 return 0;
1033}
1034
1035int nfct_nlmsg_parse(const struct nlmsghdr *nlh, struct nf_conntrack *ct)
1036{
1037 struct nfgenmsg *nfhdr = mnl_nlmsg_get_payload(nlh);
1038
1039 return nfct_payload_parse((uint8_t *)nfhdr + sizeof(struct nfgenmsg),
1040 mnl_nlmsg_get_payload_len(nlh) - sizeof(struct nfgenmsg),
1041 nfhdr->nfgen_family, ct);
1042}
void nfct_set_attr(struct nf_conntrack *ct, const enum nf_conntrack_attr type, const void *value)