libnetfilter_conntrack  1.0.8
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  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 
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  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 
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  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 
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  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 
328 static int
329 nfct_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 
375 static int
376 nfct_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 
399 static int
400 nfct_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 
428 static int
429 nfct_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 
452 static int
453 nfct_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 
477 static int
478 nfct_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 
498 static int
499 nfct_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 
518 static 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 
542 static int
543 nfct_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 
592 static int
593 nfct_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 
613 static int
614 nfct_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 
663 static int
664 nfct_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 
682 static int
683 nfct_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  strncpy(ct->helper_name, mnl_attr_get_str(tb[CTA_HELP_NAME]),
694  NFCT_HELPER_NAME_MAX);
695  ct->helper_name[NFCT_HELPER_NAME_MAX-1] = '\0';
696  set_bit(ATTR_HELPER_NAME, ct->head.set);
697 
698  if (!tb[CTA_HELP_INFO])
699  return 0;
700 
701  ct->helper_info_len = mnl_attr_get_payload_len(tb[CTA_HELP_INFO]);
702  ct->helper_info = calloc(1, ct->helper_info_len);
703  if (ct->helper_info == NULL)
704  return -1;
705 
706  memcpy(ct->helper_info, mnl_attr_get_payload(tb[CTA_HELP_INFO]),
707  ct->helper_info_len);
708  set_bit(ATTR_HELPER_INFO, ct->head.set);
709 
710  return 0;
711 }
712 
713 static int
714 nfct_parse_secctx_attr_cb(const struct nlattr *attr, void *data)
715 {
716  const struct nlattr **tb = data;
717  int type = mnl_attr_get_type(attr);
718 
719  if (mnl_attr_type_valid(attr, CTA_SECCTX_MAX) < 0)
720  return MNL_CB_OK;
721 
722  switch(type) {
723  case CTA_SECCTX_NAME:
724  if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
725  abi_breakage();
726  break;
727  }
728  tb[type] = attr;
729  return MNL_CB_OK;
730 }
731 
732 static int
733 nfct_parse_secctx(const struct nlattr *attr, struct nf_conntrack *ct)
734 {
735  struct nlattr *tb[CTA_SECCTX_MAX+1] = {};
736 
737  if (mnl_attr_parse_nested(attr, nfct_parse_secctx_attr_cb, tb) < 0)
738  return -1;
739 
740  if (!tb[CTA_SECCTX_NAME])
741  return 0;
742 
743  ct->secctx = strdup(NFA_DATA(tb[CTA_SECCTX_NAME]));
744  if (ct->secctx)
745  set_bit(ATTR_SECCTX, ct->head.set);
746 
747  return 0;
748 }
749 
750 static int
751 nfct_parse_timestamp_attr_cb(const struct nlattr *attr, void *data)
752 {
753  const struct nlattr **tb = data;
754  int type = mnl_attr_get_type(attr);
755 
756  if (mnl_attr_type_valid(attr, CTA_TIMESTAMP_MAX) < 0)
757  return MNL_CB_OK;
758 
759  switch(type) {
760  case CTA_TIMESTAMP_START:
761  case CTA_TIMESTAMP_STOP:
762  if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
763  abi_breakage();
764  break;
765  }
766  tb[type] = attr;
767  return MNL_CB_OK;
768 }
769 
770 static int
771 nfct_parse_timestamp(const struct nlattr *attr, struct nf_conntrack *ct)
772 {
773  struct nlattr *tb[CTA_TIMESTAMP_MAX+1] = {};
774 
775  if (mnl_attr_parse_nested(attr, nfct_parse_timestamp_attr_cb, tb) < 0)
776  return -1;
777 
778  if (tb[CTA_TIMESTAMP_START]) {
779  ct->timestamp.start =
780  be64toh(mnl_attr_get_u64(tb[CTA_TIMESTAMP_START]));
781  set_bit(ATTR_TIMESTAMP_START, ct->head.set);
782  }
783  if (tb[CTA_TIMESTAMP_STOP]) {
784  ct->timestamp.stop =
785  be64toh(mnl_attr_get_u64(tb[CTA_TIMESTAMP_STOP]));
786  set_bit(ATTR_TIMESTAMP_STOP, ct->head.set);
787  }
788 
789  return 0;
790 }
791 
792 static int nfct_parse_labels(const struct nlattr *attr, struct nf_conntrack *ct)
793 {
794  uint16_t len = mnl_attr_get_payload_len(attr);
795  struct nfct_bitmask *mask;
796  uint32_t *bits;
797 
798  if (len == 0)
799  return 0;
800 
801  mask = nfct_bitmask_new((len * CHAR_BIT) - 1);
802  if (!mask)
803  return -1;
804  bits = mnl_attr_get_payload(attr);
805 
806  memcpy(mask->bits, bits, len);
807  nfct_set_attr(ct, ATTR_CONNLABELS, mask);
808  return 0;
809 }
810 
811 static int nfct_parse_synproxy_attr_cb(const struct nlattr *attr, void *data)
812 {
813  int type = mnl_attr_get_type(attr);
814  const struct nlattr **tb = data;
815 
816  if (mnl_attr_type_valid(attr, CTA_SYNPROXY_MAX) < 0)
817  return MNL_CB_OK;
818 
819  switch(type) {
820  case CTA_SYNPROXY_ISN:
821  case CTA_SYNPROXY_ITS:
822  case CTA_SYNPROXY_TSOFF:
823  if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
824  abi_breakage();
825  break;
826  }
827  tb[type] = attr;
828  return MNL_CB_OK;
829 }
830 
831 static int nfct_parse_synproxy(const struct nlattr *attr,
832  struct nf_conntrack *ct)
833 {
834  struct nlattr *tb[CTA_SYNPROXY + 1] = {};
835 
836  if (mnl_attr_parse_nested(attr, nfct_parse_synproxy_attr_cb, tb) < 0)
837  return -1;
838 
839  if (tb[CTA_SYNPROXY_ISN]) {
840  ct->synproxy.isn =
841  ntohl(mnl_attr_get_u32(tb[CTA_SYNPROXY_ISN]));
842  set_bit(ATTR_SYNPROXY_ISN, ct->head.set);
843  }
844 
845  if (tb[CTA_SYNPROXY_ITS]) {
846  ct->synproxy.its =
847  ntohl(mnl_attr_get_u32(tb[CTA_SYNPROXY_ITS]));
848  set_bit(ATTR_SYNPROXY_ITS, ct->head.set);
849  }
850 
851  if (tb[CTA_SYNPROXY_TSOFF]) {
852  ct->synproxy.tsoff =
853  ntohl(mnl_attr_get_u32(tb[CTA_SYNPROXY_TSOFF]));
854  set_bit(ATTR_SYNPROXY_TSOFF, ct->head.set);
855  }
856 
857  return 0;
858 }
859 
860 static int
861 nfct_parse_conntrack_attr_cb(const struct nlattr *attr, void *data)
862 {
863  const struct nlattr **tb = data;
864  int type = mnl_attr_get_type(attr);
865 
866  if (mnl_attr_type_valid(attr, CTA_MAX) < 0)
867  return MNL_CB_OK;
868 
869  switch(type) {
870  case CTA_TUPLE_ORIG:
871  case CTA_TUPLE_REPLY:
872  case CTA_TUPLE_MASTER:
873  case CTA_NAT_SEQ_ADJ_ORIG:
874  case CTA_NAT_SEQ_ADJ_REPLY:
875  case CTA_PROTOINFO:
876  case CTA_COUNTERS_ORIG:
877  case CTA_COUNTERS_REPLY:
878  case CTA_HELP:
879  case CTA_SECCTX:
880  case CTA_TIMESTAMP:
881  if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
882  abi_breakage();
883  break;
884  case CTA_STATUS:
885  case CTA_TIMEOUT:
886  case CTA_MARK:
887  case CTA_SECMARK:
888  case CTA_USE:
889  case CTA_ID:
890  if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
891  abi_breakage();
892  break;
893  case CTA_ZONE:
894  if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
895  abi_breakage();
896  break;
897  case CTA_NAT_SRC:
898  case CTA_NAT_DST:
899  /* deprecated */
900  break;
901  }
902  tb[type] = attr;
903  return MNL_CB_OK;
904 }
905 
906 int
907 nfct_payload_parse(const void *payload, size_t payload_len,
908  uint16_t l3num, struct nf_conntrack *ct)
909 {
910  struct nlattr *tb[CTA_MAX+1] = {};
911 
912  if (mnl_attr_parse_payload(payload, payload_len,
913  nfct_parse_conntrack_attr_cb, tb) < 0)
914  return -1;
915 
916  if (tb[CTA_TUPLE_ORIG]) {
917  ct->head.orig.l3protonum = l3num;
918  set_bit(ATTR_ORIG_L3PROTO, ct->head.set);
919 
920  if (nfct_parse_tuple(tb[CTA_TUPLE_ORIG], &ct->head.orig,
921  __DIR_ORIG, ct->head.set) < 0)
922  return -1;
923  }
924 
925  if (tb[CTA_TUPLE_REPLY]) {
926  ct->repl.l3protonum = l3num;
927  set_bit(ATTR_REPL_L3PROTO, ct->head.set);
928 
929  if (nfct_parse_tuple(tb[CTA_TUPLE_REPLY], &ct->repl,
930  __DIR_REPL, ct->head.set) < 0)
931  return -1;
932  }
933 
934  if (tb[CTA_TUPLE_MASTER]) {
935  ct->master.l3protonum = l3num;
936  set_bit(ATTR_MASTER_L3PROTO, ct->head.set);
937 
938  if (nfct_parse_tuple(tb[CTA_TUPLE_MASTER], &ct->master,
939  __DIR_MASTER, ct->head.set) < 0)
940  return -1;
941  }
942 
943  if (tb[CTA_NAT_SEQ_ADJ_ORIG]) {
944  if (nfct_parse_nat_seq(tb[CTA_NAT_SEQ_ADJ_ORIG],
945  ct, __DIR_ORIG) < 0)
946  return -1;
947  }
948 
949  if (tb[CTA_NAT_SEQ_ADJ_REPLY]) {
950  if (nfct_parse_nat_seq(tb[CTA_NAT_SEQ_ADJ_REPLY],
951  ct, __DIR_REPL) < 0)
952  return -1;
953  }
954 
955  if (tb[CTA_STATUS]) {
956  ct->status = ntohl(mnl_attr_get_u32(tb[CTA_STATUS]));
957  set_bit(ATTR_STATUS, ct->head.set);
958  }
959 
960  if (tb[CTA_PROTOINFO]) {
961  if (nfct_parse_protoinfo(tb[CTA_PROTOINFO], ct) < 0)
962  return -1;
963  }
964 
965  if (tb[CTA_TIMEOUT]) {
966  ct->timeout = ntohl(mnl_attr_get_u32(tb[CTA_TIMEOUT]));
967  set_bit(ATTR_TIMEOUT, ct->head.set);
968  }
969 
970  if (tb[CTA_MARK]) {
971  ct->mark = ntohl(mnl_attr_get_u32(tb[CTA_MARK]));
972  set_bit(ATTR_MARK, ct->head.set);
973  }
974 
975  if (tb[CTA_SECMARK]) {
976  ct->secmark = ntohl(mnl_attr_get_u32(tb[CTA_SECMARK]));
977  set_bit(ATTR_SECMARK, ct->head.set);
978  }
979 
980  if (tb[CTA_COUNTERS_ORIG]) {
981  if (nfct_parse_counters(tb[CTA_COUNTERS_ORIG],
982  ct, __DIR_ORIG) < 0)
983  return -1;
984  }
985 
986  if (tb[CTA_COUNTERS_REPLY]) {
987  if (nfct_parse_counters(tb[CTA_COUNTERS_REPLY],
988  ct, __DIR_REPL) < 0)
989  return -1;
990  }
991 
992  if (tb[CTA_USE]) {
993  ct->use = ntohl(mnl_attr_get_u32(tb[CTA_USE]));
994  set_bit(ATTR_USE, ct->head.set);
995  }
996 
997  if (tb[CTA_ID]) {
998  ct->id = ntohl(mnl_attr_get_u32(tb[CTA_ID]));
999  set_bit(ATTR_ID, ct->head.set);
1000  }
1001 
1002  if (tb[CTA_HELP]) {
1003  if (nfct_parse_helper(tb[CTA_HELP], ct) < 0)
1004  return -1;
1005  }
1006 
1007  if (tb[CTA_ZONE]) {
1008  ct->zone = ntohs(mnl_attr_get_u16(tb[CTA_ZONE]));
1009  set_bit(ATTR_ZONE, ct->head.set);
1010  }
1011 
1012  if (tb[CTA_SECCTX]) {
1013  if (nfct_parse_secctx(tb[CTA_SECCTX], ct) < 0)
1014  return -1;
1015  }
1016 
1017  if (tb[CTA_TIMESTAMP]) {
1018  if (nfct_parse_timestamp(tb[CTA_TIMESTAMP], ct) < 0)
1019  return -1;
1020  }
1021 
1022  if (tb[CTA_LABELS]) {
1023  if (nfct_parse_labels(tb[CTA_LABELS], ct) < 0)
1024  return -1;
1025  }
1026  /* CTA_LABELS_MASK: never sent by kernel */
1027 
1028  if (tb[CTA_SYNPROXY]) {
1029  if (nfct_parse_synproxy(tb[CTA_SYNPROXY], ct) < 0)
1030  return -1;
1031  }
1032 
1033  return 0;
1034 }
1035 
1036 int nfct_nlmsg_parse(const struct nlmsghdr *nlh, struct nf_conntrack *ct)
1037 {
1038  struct nfgenmsg *nfhdr = mnl_nlmsg_get_payload(nlh);
1039 
1040  return nfct_payload_parse((uint8_t *)nfhdr + sizeof(struct nfgenmsg),
1041  mnl_nlmsg_get_payload_len(nlh) - sizeof(struct nfgenmsg),
1042  nfhdr->nfgen_family, ct);
1043 }
void nfct_set_attr(struct nf_conntrack *ct, const enum nf_conntrack_attr type, const void *value)