1/*
2 * (C) 2005-2011 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
10#include "internal/internal.h"
11
12/*
13 * XML output sample:
14 *
15 * <flow type="new">
16 *	<layer3 protonum="2" protoname="IPv4">
17 *		<expected>
18 *			<src>192.168.0.2</src>
19 *			<dst>192.168.1.2</dst>
20 *		</expected>
21 *		<mask>
22 *			<src>255.255.255.255</src>
23 *			<dst>255.255.255.255</dst>
24 *		</mask>
25 *		<master>
26 *			<src>192.168.0.2</src>
27 *			<dst>192.168.1.2</dst>
28 *		</master>
29 *	</layer3>
30 *	<layer4 protonum="6" protoname="tcp">
31 *		<expected>
32 *			<sport>0</sport>
33 *			<dport>41739</dport>
34 *		</expected>
35 *		<mask>
36 *			<sport>0</sport>
37 *			<dport>65535</dport>
38 *		</mask>
39 *		<master>
40 *			<sport>36390</sport>
41 *			<dport>21</dport>
42 *		</master>
43 *	</layer4>
44 *	<meta>
45 *		<helper-name>ftp</helper-name>
46 *		<timeout>300</timeout>
47 *		<zone>0</zone>
48 *	</meta>
49 * </flow>
50 */
51
52static int
53snprintf_expect_meta_xml(char *buf, size_t len,
54			 const struct nf_expect *exp, unsigned int flags)
55{
56	int ret;
57	unsigned int size = 0, offset = 0;
58
59	ret = snprintf(buf, len, "<meta>");
60	BUFFER_SIZE(ret, size, len, offset);
61
62	if (test_bit(ATTR_EXP_HELPER_NAME, exp->set)) {
63		ret = snprintf(buf+offset, len,
64				"<helper-name>%s</helper-name>",
65				exp->helper_name);
66		BUFFER_SIZE(ret, size, len, offset);
67	}
68	if (test_bit(ATTR_EXP_TIMEOUT, exp->set)) {
69		ret = snprintf(buf+offset, len, "<timeout>%u</timeout>",
70				exp->timeout);
71		BUFFER_SIZE(ret, size, len, offset);
72	}
73	if (test_bit(ATTR_EXP_CLASS, exp->set)) {
74		ret = snprintf(buf+offset, len, "<class>%u</class>",
75				exp->class);
76		BUFFER_SIZE(ret, size, len, offset);
77	}
78	if (test_bit(ATTR_EXP_ZONE, exp->set)) {
79		ret = snprintf(buf+offset, len, "<zone>%u</zone>", exp->zone);
80		BUFFER_SIZE(ret, size, len, offset);
81	}
82        if (flags & NFCT_OF_TIME) {
83                time_t t;
84                struct tm tm;
85
86                t = time(NULL);
87                if (localtime_r(&t, &tm) == NULL)
88                        goto err_out;
89
90                ret = snprintf(buf+offset, len, "<when>");
91                BUFFER_SIZE(ret, size, len, offset);
92
93                ret = __snprintf_localtime_xml(buf+offset, len, &tm);
94                BUFFER_SIZE(ret, size, len, offset);
95
96                ret = snprintf(buf+offset, len, "</when>");
97                BUFFER_SIZE(ret, size, len, offset);
98        }
99err_out:
100	if (exp->flags & NF_CT_EXPECT_PERMANENT) {
101		ret = snprintf(buf+offset, len, "<permanent/>");
102		BUFFER_SIZE(ret, size, len, offset);
103	}
104	if (exp->flags & NF_CT_EXPECT_INACTIVE) {
105		ret = snprintf(buf+offset, len, "<inactive/>");
106		BUFFER_SIZE(ret, size, len, offset);
107	}
108	if (exp->flags & NF_CT_EXPECT_USERSPACE) {
109		ret = snprintf(buf+offset, len, "<userspace/>");
110		BUFFER_SIZE(ret, size, len, offset);
111	}
112
113	ret = snprintf(buf+offset, len, "</meta>");
114	BUFFER_SIZE(ret, size, len, offset);
115
116	return size;
117}
118
119static int
120snprintf_expect_layer3_xml(char *buf, size_t len, const struct nf_expect *exp)
121{
122	int ret;
123	unsigned int size = 0, offset = 0;
124
125        ret = snprintf(buf+offset, len,
126                       "<layer3 protonum=\"%d\" protoname=\"%s\">",
127			exp->expected.orig.l3protonum,
128			__l3proto2str(exp->expected.orig.l3protonum));
129        BUFFER_SIZE(ret, size, len, offset);
130
131        ret = snprintf(buf+offset, len, "<expected>");
132        BUFFER_SIZE(ret, size, len, offset);
133
134        ret = __snprintf_addr_xml(buf+offset, len, &exp->expected.orig,
135				__ADDR_SRC);
136        BUFFER_SIZE(ret, size, len, offset);
137
138        ret = __snprintf_addr_xml(buf+offset, len, &exp->expected.orig,
139				__ADDR_DST);
140        BUFFER_SIZE(ret, size, len, offset);
141
142        ret = snprintf(buf+offset, len, "</expected>");
143        BUFFER_SIZE(ret, size, len, offset);
144
145        ret = snprintf(buf+offset, len, "<mask>");
146        BUFFER_SIZE(ret, size, len, offset);
147
148        ret = __snprintf_addr_xml(buf+offset, len, &exp->mask.orig,
149				__ADDR_SRC);
150        BUFFER_SIZE(ret, size, len, offset);
151
152        ret = __snprintf_addr_xml(buf+offset, len, &exp->mask.orig,
153				__ADDR_DST);
154        BUFFER_SIZE(ret, size, len, offset);
155
156        ret = snprintf(buf+offset, len, "</mask>");
157        BUFFER_SIZE(ret, size, len, offset);
158
159        ret = snprintf(buf+offset, len, "<master>");
160        BUFFER_SIZE(ret, size, len, offset);
161
162        ret = __snprintf_addr_xml(buf+offset, len, &exp->master.orig,
163				__ADDR_SRC);
164        BUFFER_SIZE(ret, size, len, offset);
165
166        ret = __snprintf_addr_xml(buf+offset, len, &exp->master.orig,
167				__ADDR_DST);
168        BUFFER_SIZE(ret, size, len, offset);
169
170        ret = snprintf(buf+offset, len, "</master>");
171        BUFFER_SIZE(ret, size, len, offset);
172
173        ret = snprintf(buf+offset, len, "</layer3>");
174        BUFFER_SIZE(ret, size, len, offset);
175
176	return size;
177}
178
179static int
180snprintf_expect_layer4_xml(char *buf, size_t len, const struct nf_expect *exp)
181{
182	int ret;
183	unsigned int size = 0, offset = 0;
184
185        ret = snprintf(buf+offset, len,
186                       "<layer4 protonum=\"%d\" protoname=\"%s\">",
187			exp->expected.orig.protonum,
188			__proto2str(exp->expected.orig.protonum));
189        BUFFER_SIZE(ret, size, len, offset);
190
191        ret = snprintf(buf+offset, len, "<expected>");
192        BUFFER_SIZE(ret, size, len, offset);
193
194	ret = __snprintf_proto_xml(buf+offset, len, &exp->expected.orig,
195				__ADDR_SRC);
196        BUFFER_SIZE(ret, size, len, offset);
197
198	ret = __snprintf_proto_xml(buf+offset, len, &exp->expected.orig,
199				__ADDR_DST);
200        BUFFER_SIZE(ret, size, len, offset);
201
202        ret = snprintf(buf+offset, len, "</expected>");
203        BUFFER_SIZE(ret, size, len, offset);
204
205        ret = snprintf(buf+offset, len, "<mask>");
206        BUFFER_SIZE(ret, size, len, offset);
207
208	ret = __snprintf_proto_xml(buf+offset, len, &exp->mask.orig,
209				__ADDR_SRC);
210        BUFFER_SIZE(ret, size, len, offset);
211
212	ret = __snprintf_proto_xml(buf+offset, len, &exp->mask.orig,
213				__ADDR_DST);
214        BUFFER_SIZE(ret, size, len, offset);
215
216        ret = snprintf(buf+offset, len, "</mask>");
217        BUFFER_SIZE(ret, size, len, offset);
218
219        ret = snprintf(buf+offset, len, "<master>");
220        BUFFER_SIZE(ret, size, len, offset);
221
222	ret = __snprintf_proto_xml(buf+offset, len, &exp->master.orig,
223				__ADDR_SRC);
224        BUFFER_SIZE(ret, size, len, offset);
225
226	ret = __snprintf_proto_xml(buf+offset, len, &exp->master.orig,
227				__ADDR_DST);
228        BUFFER_SIZE(ret, size, len, offset);
229
230        ret = snprintf(buf+offset, len, "</master>");
231        BUFFER_SIZE(ret, size, len, offset);
232
233	ret = snprintf(buf+offset, len, "</layer4>");
234        BUFFER_SIZE(ret, size, len, offset)
235
236	return size;
237}
238
239int __snprintf_expect_xml(char *buf, unsigned int len,
240			  const struct nf_expect *exp,
241			  unsigned int msg_type, unsigned int flags)
242{
243	int ret = 0, size = 0, offset = 0;
244
245	switch(msg_type) {
246		case NFCT_T_NEW:
247			ret = snprintf(buf, len, "<flow type=\"new\">");
248			break;
249		case NFCT_T_UPDATE:
250			ret = snprintf(buf, len, "<flow type=\"update\">");
251			break;
252		case NFCT_T_DESTROY:
253			ret = snprintf(buf, len, "<flow type=\"destroy\">");
254			break;
255		default:
256			ret = snprintf(buf, len, "<flow>");
257			break;
258	}
259	BUFFER_SIZE(ret, size, len, offset);
260
261	ret = snprintf_expect_layer3_xml(buf+offset, len, exp);
262	BUFFER_SIZE(ret, size, len, offset);
263
264	ret = snprintf_expect_layer4_xml(buf+offset, len, exp);
265	BUFFER_SIZE(ret, size, len, offset);
266
267	ret = snprintf_expect_meta_xml(buf+offset, len, exp, flags);
268	BUFFER_SIZE(ret, size, len, offset);
269
270	ret = snprintf(buf+offset, len, "</flow>");
271	BUFFER_SIZE(ret, size, len, offset);
272
273	return size;
274}
275