libnetfilter_conntrack  1.0.9
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  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 
712 static int
713 nfct_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 
731 static int
732 nfct_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 
749 static int
750 nfct_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 
769 static int
770 nfct_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 
791 static 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 
810 static 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 
830 static 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 
859 static int
860 nfct_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 
905 int
906 nfct_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 
1035 int 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)