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
nfct_parse_ip_attr_cb(const struct nlattr * attr,void * data)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
nfct_parse_ip(const struct nlattr * attr,struct __nfct_tuple * tuple,const int dir,uint32_t * set)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
nfct_parse_proto_attr_cb(const struct nlattr * attr,void * data)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
nfct_parse_proto(const struct nlattr * attr,struct __nfct_tuple * tuple,const int dir,uint32_t * set)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
nfct_parse_tuple_attr_cb(const struct nlattr * attr,void * data)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
nfct_parse_tuple(const struct nlattr * attr,struct __nfct_tuple * tuple,int dir,uint32_t * set)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
nfct_parse_pinfo_tcp_attr_cb(const struct nlattr * attr,void * data)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
nfct_parse_protoinfo_tcp(const struct nlattr * attr,struct nf_conntrack * ct)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
nfct_parse_pinfo_sctp_attr_cb(const struct nlattr * attr,void * data)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
nfct_parse_protoinfo_sctp(const struct nlattr * attr,struct nf_conntrack * ct)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
nfct_parse_pinfo_dccp_attr_cb(const struct nlattr * attr,void * data)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
nfct_parse_protoinfo_dccp(const struct nlattr * attr,struct nf_conntrack * ct)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
nfct_parse_protoinfo_attr_cb(const struct nlattr * attr,void * data)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
nfct_parse_protoinfo(const struct nlattr * attr,struct nf_conntrack * ct)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
nfct_parse_counters_attr_cb(const struct nlattr * attr,void * data)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
nfct_parse_counters(const struct nlattr * attr,struct nf_conntrack * ct,int dir)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
nfct_parse_nat_seq_attr_cb(const struct nlattr * attr,void * data)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
nfct_parse_nat_seq(const struct nlattr * attr,struct nf_conntrack * ct,int dir)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
nfct_parse_helper_attr_cb(const struct nlattr * attr,void * data)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
nfct_parse_helper(const struct nlattr * attr,struct nf_conntrack * ct)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
nfct_parse_secctx_attr_cb(const struct nlattr * attr,void * data)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
nfct_parse_secctx(const struct nlattr * attr,struct nf_conntrack * ct)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
nfct_parse_timestamp_attr_cb(const struct nlattr * attr,void * data)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
nfct_parse_timestamp(const struct nlattr * attr,struct nf_conntrack * ct)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
nfct_parse_labels(const struct nlattr * attr,struct nf_conntrack * ct)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
nfct_parse_conntrack_attr_cb(const struct nlattr * attr,void * data)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
nfct_payload_parse(const void * payload,size_t payload_len,uint16_t l3num,struct nf_conntrack * ct)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
nfct_nlmsg_parse(const struct nlmsghdr * nlh,struct nf_conntrack * ct)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 }
991