parse_mnl.c revision 8a44513648da0c5f5551f96b329cf56b66f5b303
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
17static int
18nfct_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
45static int
46nfct_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
118static int
119nfct_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
148static int
149nfct_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
243static 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
267int
268nfct_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
301static int
302nfct_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
329static int
330nfct_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
376static int
377nfct_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
400static int
401nfct_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
429static int
430nfct_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
453static int
454nfct_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
478static int
479nfct_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
499static int
500nfct_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
519static 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
543static int
544nfct_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
593static int
594nfct_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
614static int
615nfct_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
664static int
665nfct_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
683static int
684nfct_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
714static int
715nfct_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
733static int
734nfct_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
751static int
752nfct_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
771static int
772nfct_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
793static 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
812static int
813nfct_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
858int
859nfct_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
983int 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