• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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