libnetfilter_conntrack  1.0.6
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 
17 static int
18 nfct_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 
45 static int
46 nfct_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 
118 static int
119 nfct_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 
148 static int
149 nfct_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 
243 static 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 
267 int
268 nfct_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 
301 static int
302 nfct_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 
329 static int
330 nfct_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 
376 static int
377 nfct_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 
400 static int
401 nfct_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 
429 static int
430 nfct_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 
453 static int
454 nfct_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 
478 static int
479 nfct_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 
499 static int
500 nfct_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 
519 static 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 
543 static int
544 nfct_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 
593 static int
594 nfct_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 
614 static int
615 nfct_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 
664 static int
665 nfct_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 
683 static int
684 nfct_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 
714 static int
715 nfct_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 
733 static int
734 nfct_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 
751 static int
752 nfct_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 
771 static int
772 nfct_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 
793 static 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 
812 static int
813 nfct_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 
858 int
859 nfct_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 
983 int 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 }
void nfct_set_attr(struct nf_conntrack *ct, const enum nf_conntrack_attr type, const void *value)