1 /*
2  *  Copyright (c) 2017, Peter Haag
3  *  Copyright (c) 2016, Peter Haag
4  *  Copyright (c) 2014, Peter Haag
5  *  Copyright (c) 2009, Peter Haag
6  *  Copyright (c) 2004-2008, SWITCH - Teleinformatikdienste fuer Lehre und Forschung
7  *  All rights reserved.
8  *
9  *  Redistribution and use in source and binary forms, with or without
10  *  modification, are permitted provided that the following conditions are met:
11  *
12  *   * Redistributions of source code must retain the above copyright notice,
13  *     this list of conditions and the following disclaimer.
14  *   * Redistributions in binary form must reproduce the above copyright notice,
15  *     this list of conditions and the following disclaimer in the documentation
16  *     and/or other materials provided with the distribution.
17  *   * Neither the name of the author nor the names of its contributors may be
18  *     used to endorse or promote products derived from this software without
19  *     specific prior written permission.
20  *
21  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  *  POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34 
35 static inline int CheckBufferSpace(nffile_t *nffile, size_t required);
36 
37 static inline void AppendToBuffer(nffile_t *nffile, void *record, size_t required);
38 
39 static inline void CopyV6IP(uint32_t *dst, uint32_t *src);
40 
41 static inline void ExpandRecord_v2(common_record_t *input_record, extension_info_t *extension_info, exporter_info_record_t *exporter_info, master_record_t *output_record );
42 
43 #ifdef NEED_PACKRECORD
44 static void PackRecord(master_record_t *master_record, nffile_t *nffile);
45 #endif
46 
CheckBufferSpace(nffile_t * nffile,size_t required)47 static inline int CheckBufferSpace(nffile_t *nffile, size_t required) {
48 
49 	dbg_printf("Buffer Size %u\n", nffile->block_header->size);
50 	// flush current buffer to disc
51 	if ( (nffile->block_header->size + required )  > WRITE_BUFFSIZE ) {
52 
53 		// this should never happen, but catch it anyway
54 		if ( required > WRITE_BUFFSIZE ) {
55 			LogError("Required buffer size %zu too big for output buffer!" , required);
56 			return 0;
57 		}
58 
59 		if ( WriteBlock(nffile) <= 0 ) {
60 			LogError("Failed to write output buffer to disk: '%s'" , strerror(errno));
61 			return 0;
62 		}
63 	}
64 
65 	return 1;
66 } // End of CheckBufferSpace
67 
68 // Use 4 uint32_t copy cycles, as SPARC CPUs brak
CopyV6IP(uint32_t * dst,uint32_t * src)69 static inline void CopyV6IP(uint32_t *dst, uint32_t *src) {
70 	dst[0] = src[0];
71 	dst[1] = src[1];
72 	dst[2] = src[2];
73 	dst[3] = src[3];
74 } // End of CopyV6IP
75 
76 /*
77  * Expand file record into master record for further processing
78  * LP64 CPUs need special 32bit operations as it is not guarateed, that 64bit
79  * values are aligned
80  */
ExpandRecord_v2(common_record_t * input_record,extension_info_t * extension_info,exporter_info_record_t * exporter_info,master_record_t * output_record)81 static inline void ExpandRecord_v2(common_record_t *input_record, extension_info_t *extension_info, exporter_info_record_t *exporter_info, master_record_t *output_record ) {
82 extension_map_t *extension_map = extension_info->map;
83 uint32_t	i, *u;
84 void		*p = (void *)input_record;
85 // printf("Byte: %u\n", _b);
86 
87 #ifdef NSEL
88 		// nasty bug work around - compat issues 1.6.10 - 1.6.12 onwards
89 		union {
90 			uint16_t port[2];
91 			uint32_t vrf;
92 		} compat_nel_bug;
93 		compat_nel_bug.vrf = 0;
94 		int compat_nel = 0;
95 #endif
96 
97 	// set map ref
98 	output_record->map_ref = extension_map;
99 
100 	// Copy common data block
101 	memcpy((void *)output_record, (void *)input_record, COMMON_RECORD_DATA_SIZE);
102 	p = (void *)input_record->data;
103 
104 	if ( exporter_info ) {
105 		uint32_t sysid = exporter_info->sysid;
106 		output_record->exporter_sysid = sysid;
107 		input_record->exporter_sysid  = sysid;
108 		output_record->exp_ref 		  = exporter_info;
109 	} else {
110 		output_record->exp_ref 		  = NULL;
111 	}
112 	output_record->label = NULL;
113 
114 	// map icmp type/code in it's own vars
115 	output_record->icmp = output_record->dstport;
116 
117 	// Required extension 1 - IP addresses
118 	if ( (input_record->flags & FLAG_IPV6_ADDR) != 0 )	{ // IPv6
119 		// IPv6
120 		// keep compiler happy
121 		// memcpy((void *)output_record->V6.srcaddr, p, 4 * sizeof(uint64_t));
122 		memcpy((void *)output_record->ip_union._ip_64.addr, p, 4 * sizeof(uint64_t));
123 		p = (void *)((pointer_addr_t)p + 4 * sizeof(uint64_t));
124 	} else {
125 		// IPv4
126 		u = (uint32_t *)p;
127 		output_record->V6.srcaddr[0] = 0;
128 		output_record->V6.srcaddr[1] = 0;
129 		output_record->V4.srcaddr 	 = u[0];
130 
131 		output_record->V6.dstaddr[0] = 0;
132 		output_record->V6.dstaddr[1] = 0;
133 		output_record->V4.dstaddr 	 = u[1];
134 		p = (void *)((pointer_addr_t)p + 2 * sizeof(uint32_t));
135 	}
136 
137 	// Required extension 2 - packet counter
138 	if ( (input_record->flags & FLAG_PKG_64 ) != 0 ) {
139 		// 64bit packet counter
140 		value64_t	l, *v = (value64_t *)p;
141 		l.val.val32[0] = v->val.val32[0];
142 		l.val.val32[1] = v->val.val32[1];
143 		output_record->dPkts = l.val.val64;
144 		p = (void *)((pointer_addr_t)p + sizeof(uint64_t));
145 	} else {
146 		// 32bit packet counter
147 		output_record->dPkts = *((uint32_t *)p);
148 		p = (void *)((pointer_addr_t)p + sizeof(uint32_t));
149 	}
150 
151 	// Required extension 3 - byte counter
152 	if ( (input_record->flags & FLAG_BYTES_64 ) != 0 ) {
153 		// 64bit byte counter
154 		value64_t	l, *v = (value64_t *)p;
155 		l.val.val32[0] = v->val.val32[0];
156 		l.val.val32[1] = v->val.val32[1];
157 		output_record->dOctets = l.val.val64;
158 		p = (void *)((pointer_addr_t)p + sizeof(uint64_t));
159 	} else {
160 		// 32bit bytes counter
161 		output_record->dOctets = *((uint32_t *)p);
162 		p = (void *)((pointer_addr_t)p + sizeof(uint32_t));
163 	}
164 
165 	// preset one single flow
166 	output_record->aggr_flows = 1;
167 
168 	// Process optional extensions
169 	i=0;
170 	while ( extension_map->ex_id[i] ) {
171 		switch (extension_map->ex_id[i++]) {
172 			// 0 - 3 should never be in an extension table so - ignore it
173 			case 0:
174 			case 1:
175 			case 2:
176 			case 3:
177 				break;
178 			case EX_IO_SNMP_2: {
179 				tpl_ext_4_t *tpl = (tpl_ext_4_t *)p;
180 				output_record->input  = tpl->input;
181 				output_record->output = tpl->output;
182 				p = (void *)tpl->data;
183 				} break;
184 			case EX_IO_SNMP_4: {
185 				tpl_ext_5_t *tpl = (tpl_ext_5_t *)p;
186 				output_record->input  = tpl->input;
187 				output_record->output = tpl->output;
188 				p = (void *)tpl->data;
189 				} break;
190 			case EX_AS_2: {
191 				tpl_ext_6_t *tpl = (tpl_ext_6_t *)p;
192 				output_record->srcas = tpl->src_as;
193 				output_record->dstas = tpl->dst_as;
194 				p = (void *)tpl->data;
195 				} break;
196 			case EX_AS_4: {
197 				tpl_ext_7_t *tpl = (tpl_ext_7_t *)p;
198 				output_record->srcas = tpl->src_as;
199 				output_record->dstas = tpl->dst_as;
200 				p = (void *)tpl->data;
201 				} break;
202 			case EX_MULIPLE: {
203 				tpl_ext_8_t *tpl = (tpl_ext_8_t *)p;
204 				// use a 32 bit int to copy all 4 fields
205 				output_record->any = tpl->any;
206 				p = (void *)tpl->data;
207 				} break;
208 			case EX_NEXT_HOP_v4: {
209 				tpl_ext_9_t *tpl = (tpl_ext_9_t *)p;
210 				output_record->ip_nexthop.V6[0] = 0;
211 				output_record->ip_nexthop.V6[1] = 0;
212 				output_record->ip_nexthop.V4	= tpl->nexthop;
213 				p = (void *)tpl->data;
214 				ClearFlag(output_record->flags, FLAG_IPV6_NH);
215 				} break;
216 			case EX_NEXT_HOP_v6: {
217 				tpl_ext_10_t *tpl = (tpl_ext_10_t *)p;
218 				CopyV6IP((uint32_t *)output_record->ip_nexthop.V6, (uint32_t *)tpl->nexthop);
219 				p = (void *)tpl->data;
220 				SetFlag(output_record->flags, FLAG_IPV6_NH);
221 				} break;
222 			case EX_NEXT_HOP_BGP_v4: {
223 				tpl_ext_11_t *tpl = (tpl_ext_11_t *)p;
224 				output_record->bgp_nexthop.V6[0] = 0;
225 				output_record->bgp_nexthop.V6[1] = 0;
226 				output_record->bgp_nexthop.V4	= tpl->bgp_nexthop;
227 				ClearFlag(output_record->flags, FLAG_IPV6_NHB);
228 				p = (void *)tpl->data;
229 				} break;
230 			case EX_NEXT_HOP_BGP_v6: {
231 				tpl_ext_12_t *tpl = (tpl_ext_12_t *)p;
232 				CopyV6IP((uint32_t *)output_record->bgp_nexthop.V6, (uint32_t *)tpl->bgp_nexthop);
233 				p = (void *)tpl->data;
234 				SetFlag(output_record->flags, FLAG_IPV6_NHB);
235 				} break;
236 			case EX_VLAN: {
237 				tpl_ext_13_t *tpl = (tpl_ext_13_t *)p;
238 				output_record->src_vlan = tpl->src_vlan;
239 				output_record->dst_vlan = tpl->dst_vlan;
240 				p = (void *)tpl->data;
241 				} break;
242 			case EX_OUT_PKG_4: {
243 				tpl_ext_14_t *tpl = (tpl_ext_14_t *)p;
244 				output_record->out_pkts = tpl->out_pkts;
245 				p = (void *)tpl->data;
246 				} break;
247 			case EX_OUT_PKG_8: {
248 				tpl_ext_15_t v, *tpl = (tpl_ext_15_t *)p;
249 				v.v[0] = tpl->v[0];
250 				v.v[1] = tpl->v[1];
251 				output_record->out_pkts = v.out_pkts;
252 				p = (void *)tpl->data;
253 				} break;
254 			case EX_OUT_BYTES_4: {
255 				tpl_ext_16_t *tpl = (tpl_ext_16_t *)p;
256 				output_record->out_bytes = tpl->out_bytes;
257 				p = (void *)tpl->data;
258 				} break;
259 			case EX_OUT_BYTES_8: {
260 				tpl_ext_17_t v,*tpl = (tpl_ext_17_t *)p;
261 				v.v[0] = tpl->v[0];
262 				v.v[1] = tpl->v[1];
263 				output_record->out_bytes = v.out_bytes;
264 				p = (void *)tpl->data;
265 				} break;
266 			case EX_AGGR_FLOWS_4: {
267 				tpl_ext_18_t *tpl = (tpl_ext_18_t *)p;
268 				output_record->aggr_flows = tpl->aggr_flows;
269 				p = (void *)tpl->data;
270 				} break;
271 			case EX_AGGR_FLOWS_8: {
272 				tpl_ext_19_t v, *tpl = (tpl_ext_19_t *)p;
273 				v.v[0] = tpl->v[0];
274 				v.v[1] = tpl->v[1];
275 				output_record->aggr_flows = v.aggr_flows;
276 				p = (void *)tpl->data;
277 				} break;
278 			case EX_MAC_1: {
279 				tpl_ext_20_t v, *tpl = (tpl_ext_20_t *)p;
280 				v.v1[0] = tpl->v1[0];
281 				v.v1[1] = tpl->v1[1];
282 				output_record->in_src_mac = v.in_src_mac;
283 
284 				v.v2[0] = tpl->v2[0];
285 				v.v2[1] = tpl->v2[1];
286 				output_record->out_dst_mac = v.out_dst_mac;
287 				p = (void *)tpl->data;
288 				} break;
289 			case EX_MAC_2: {
290 				tpl_ext_21_t v, *tpl = (tpl_ext_21_t *)p;
291 				v.v1[0] = tpl->v1[0];
292 				v.v1[1] = tpl->v1[1];
293 				output_record->in_dst_mac = v.in_dst_mac;
294 				v.v2[0] = tpl->v2[0];
295 				v.v2[1] = tpl->v2[1];
296 				output_record->out_src_mac = v.out_src_mac;
297 				p = (void *)tpl->data;
298 				} break;
299 			case EX_MPLS: {
300 				tpl_ext_22_t *tpl = (tpl_ext_22_t *)p;
301 				int j;
302 				for (j=0; j<10; j++ ) {
303 					output_record->mpls_label[j] = tpl->mpls_label[j];
304 				}
305 				p = (void *)tpl->data;
306 			} break;
307 			case EX_ROUTER_IP_v4: {
308 				tpl_ext_23_t *tpl = (tpl_ext_23_t *)p;
309 				output_record->ip_router.V6[0] = 0;
310 				output_record->ip_router.V6[1] = 0;
311 				output_record->ip_router.V4	= tpl->router_ip;
312 				p = (void *)tpl->data;
313 				ClearFlag(output_record->flags, FLAG_IPV6_EXP);
314 				} break;
315 			case EX_ROUTER_IP_v6: {
316 				tpl_ext_24_t *tpl = (tpl_ext_24_t *)p;
317 				CopyV6IP((uint32_t *)output_record->ip_router.V6, (uint32_t *)tpl->router_ip);
318 				p = (void *)tpl->data;
319 				SetFlag(output_record->flags, FLAG_IPV6_EXP);
320 				} break;
321 			case EX_ROUTER_ID: {
322 				tpl_ext_25_t *tpl = (tpl_ext_25_t *)p;
323 				output_record->engine_type = tpl->engine_type;
324 				output_record->engine_id   = tpl->engine_id;
325 				p = (void *)tpl->data;
326 				} break;
327 			case EX_BGPADJ: {
328 				tpl_ext_26_t *tpl = (tpl_ext_26_t *)p;
329 				output_record->bgpNextAdjacentAS = tpl->bgpNextAdjacentAS;
330 				output_record->bgpPrevAdjacentAS = tpl->bgpPrevAdjacentAS;
331 				p = (void *)tpl->data;
332 			} break;
333 			case EX_LATENCY: {
334 				tpl_ext_latency_t *tpl = (tpl_ext_latency_t *)p;
335 				output_record->client_nw_delay_usec = tpl->client_nw_delay_usec;
336 				output_record->server_nw_delay_usec = tpl->server_nw_delay_usec;
337 				output_record->appl_latency_usec = tpl->appl_latency_usec;
338 				p = (void *)tpl->data;
339 			} break;
340 			case EX_RECEIVED: {
341 				tpl_ext_27_t *tpl = (tpl_ext_27_t *)p;
342 				value64_t v;
343 				v.val.val32[0] = tpl->v[0];
344 				v.val.val32[1] = tpl->v[1];
345 				output_record->received = v.val.val64;
346 				p = (void *)tpl->data;
347 			} break;
348 #ifdef NSEL
349 			case EX_NSEL_COMMON: {
350 				tpl_ext_37_t *tpl = (tpl_ext_37_t *)p;
351 				value64_t v;
352 				v.val.val32[0] = tpl->v[0];
353 				v.val.val32[1] = tpl->v[1];
354 				output_record->event_time = v.val.val64;
355 				output_record->conn_id 	  = tpl->conn_id;
356 				output_record->event   	  = tpl->fw_event;
357 				output_record->event_flag = FW_EVENT;
358 				output_record->fw_xevent  = tpl->fw_xevent;
359 				output_record->icmp = tpl->nsel_icmp;
360 				output_record->sec_group_tag = tpl->sec_group_tag;
361 				p = (void *)tpl->data;
362 			} break;
363 			case EX_NSEL_XLATE_PORTS: {
364 				tpl_ext_38_t *tpl = (tpl_ext_38_t *)p;
365 				output_record->xlate_src_port = tpl->xlate_src_port;
366 				output_record->xlate_dst_port = tpl->xlate_dst_port;
367 				p = (void *)tpl->data;
368 			} break;
369 			case EX_NSEL_XLATE_IP_v4: {
370 				tpl_ext_39_t *tpl = (tpl_ext_39_t *)p;
371 				output_record->xlate_src_ip.V6[0] = 0;
372 				output_record->xlate_src_ip.V6[1] = 0;
373 				output_record->xlate_src_ip.V4	= tpl->xlate_src_ip;
374 				output_record->xlate_dst_ip.V6[0] = 0;
375 				output_record->xlate_dst_ip.V6[1] = 0;
376 				output_record->xlate_dst_ip.V4	= tpl->xlate_dst_ip;
377 				p = (void *)tpl->data;
378 				output_record->xlate_flags = 0;
379 				} break;
380 			case EX_NSEL_XLATE_IP_v6: {
381 				tpl_ext_40_t *tpl = (tpl_ext_40_t *)p;
382 				output_record->xlate_src_ip.V6[0] = tpl->xlate_src_ip[0];
383 				output_record->xlate_src_ip.V6[1] = tpl->xlate_src_ip[1];
384 				output_record->xlate_dst_ip.V6[0] = tpl->xlate_dst_ip[0];
385 				output_record->xlate_dst_ip.V6[1] = tpl->xlate_dst_ip[1];
386 				p = (void *)tpl->data;
387 				output_record->xlate_flags = 1;
388 				} break;
389 			case EX_NSEL_ACL: {
390 				tpl_ext_41_t *tpl = (tpl_ext_41_t *)p;
391 				int j;
392 				for (j=0; j<3; j++) {
393 					output_record->ingress_acl_id[j] = tpl->ingress_acl_id[j];
394 					output_record->egress_acl_id[j] = tpl->egress_acl_id[j];
395 				}
396 				p = (void *)tpl->data;
397 			} break;
398 			case EX_NSEL_USER: {
399 				tpl_ext_42_t *tpl = (tpl_ext_42_t *)p;
400 				strncpy((void *)output_record->username, (void *)tpl->username, sizeof(output_record->username));
401 				output_record->username[sizeof(output_record->username)-1] = '\0';	// safety 0
402 				p = (void *)tpl->data;
403 			} break;
404 			case EX_NSEL_USER_MAX: {
405 				tpl_ext_43_t *tpl = (tpl_ext_43_t *)p;
406 				strncpy((void *)output_record->username, (void *)tpl->username, sizeof(output_record->username));
407 				output_record->username[sizeof(output_record->username)-1] = '\0';	// safety 0
408 				p = (void *)tpl->data;
409 			} break;
410 			case EX_NEL_COMMON: {
411 				tpl_ext_46_t *tpl = (tpl_ext_46_t *)p;
412 				output_record->event 	  = tpl->nat_event;
413 				output_record->event_flag = FW_EVENT;
414 				// XXX	- 3 bytes unused
415 				output_record->egress_vrfid  = tpl->egress_vrfid;
416 				output_record->ingress_vrfid = tpl->ingress_vrfid;
417 				p = (void *)tpl->data;
418 
419 				// remember this value, if we read old 1.6.10 files
420 				compat_nel_bug.vrf = tpl->egress_vrfid;
421 				if ( compat_nel ) {
422 					output_record->xlate_src_port = compat_nel_bug.port[0];
423 					output_record->xlate_dst_port = compat_nel_bug.port[1];
424 					output_record->egress_vrfid   = 0;
425 				}
426 			} break;
427 			// compat record v1.6.10
428 			case EX_NEL_GLOBAL_IP_v4: {
429 				tpl_ext_47_t *tpl = (tpl_ext_47_t *)p;
430 				output_record->xlate_src_ip.V6[0] = 0;
431 				output_record->xlate_src_ip.V6[1] = 0;
432 				output_record->xlate_src_ip.V4	= tpl->nat_inside;
433 				output_record->xlate_dst_ip.V6[0] = 0;
434 				output_record->xlate_dst_ip.V6[1] = 0;
435 				output_record->xlate_dst_ip.V4	= tpl->nat_outside;
436 				p = (void *)tpl->data;
437 
438 				output_record->xlate_src_port = compat_nel_bug.port[0];
439 				output_record->xlate_dst_port = compat_nel_bug.port[1];
440 				output_record->egress_vrfid   = 0;
441 				compat_nel = 1;
442 			} break;
443 			case EX_PORT_BLOCK_ALLOC: {
444 				tpl_ext_48_t *tpl = (tpl_ext_48_t *)p;
445 				output_record->block_start = tpl->block_start;
446 				output_record->block_end = tpl->block_end;
447 				output_record->block_step = tpl->block_step;
448 				output_record->block_size = tpl->block_size;
449 				if ( output_record->block_end == 0 && output_record->block_size != 0 )
450 					output_record->block_end = output_record->block_start + output_record->block_size - 1;
451 				p = (void *)tpl->data;
452 			} break;
453 
454 #endif
455 		}
456 	}
457 
458 } // End of ExpandRecord_v2
459 
460 #ifdef NEED_PACKRECORD
PackRecord(master_record_t * master_record,nffile_t * nffile)461 static void PackRecord(master_record_t *master_record, nffile_t *nffile) {
462 extension_map_t *extension_map = master_record->map_ref;
463 common_record_t *common_record;
464 uint32_t required =  COMMON_RECORD_DATA_SIZE + extension_map->extension_size;
465 size_t	 size;
466 void	 *p;
467 int		i;
468 
469 	// check size of packets and bytes
470 	if ( master_record->dPkts >  0xffffffffLL ) {
471 		master_record->flags |= FLAG_PKG_64;
472 		required += 8;
473 	} else {
474 		master_record->flags &= ~FLAG_PKG_64;
475 		required += 4;
476 	}
477 
478 	if ( master_record->dOctets >  0xffffffffLL ) {
479 		master_record->flags |= FLAG_BYTES_64;
480 		required += 8;
481 	} else {
482 		master_record->flags &= ~FLAG_BYTES_64;
483 		required += 4;
484 	}
485 	if ( (master_record->flags & FLAG_IPV6_ADDR) != 0 )	// IPv6
486 		required += 32;
487 	else
488 		required += 8;
489 
490 	master_record->size = required;
491 
492 	// flush current buffer to disc if not enough space
493 	if ( !CheckBufferSpace(nffile, required) ) {
494 		return;
495 	}
496 
497 	// enough buffer space available at this point
498 	common_record = (common_record_t *)nffile->buff_ptr;
499 
500 	// write common record
501 	size = COMMON_RECORD_DATA_SIZE;
502 	memcpy((void *)common_record, (void *)master_record, size);
503 	common_record->reserved = 0;
504 	p = (void *)((pointer_addr_t)common_record + size);
505 
506 	// Required extension 1 - IP addresses
507 	if ( (master_record->flags & FLAG_IPV6_ADDR) != 0 )	{ // IPv6
508 		// IPv6
509 		// keep compiler happy
510 		// memcpy(p, (void *)master_record->V6.srcaddr, 4 * sizeof(uint64_t));
511 		memcpy(p, (void *)master_record->ip_union._ip_64.addr, 4 * sizeof(uint64_t));
512 		p = (void *)((pointer_addr_t)p + 4 * sizeof(uint64_t));
513 	} else {
514 		// IPv4
515 		uint32_t *u = (uint32_t *)p;
516 		u[0] = master_record->V4.srcaddr;
517 		u[1] = master_record->V4.dstaddr;
518 		p = (void *)((pointer_addr_t)p + 2 * sizeof(uint32_t));
519 	}
520 
521 	// Required extension 2 - packet counter
522 	if ( (master_record->flags & FLAG_PKG_64 ) != 0 ) {
523 		// 64bit packet counter
524 		value64_t	l, *v = (value64_t *)p;
525 		l.val.val64 = master_record->dPkts;
526 		v->val.val32[0] = l.val.val32[0];
527 		v->val.val32[1] = l.val.val32[1];
528 		p = (void *)((pointer_addr_t)p + sizeof(uint64_t));
529 	} else {
530 		// 32bit packet counter
531 		*((uint32_t *)p) = master_record->dPkts;
532 		p = (void *)((pointer_addr_t)p + sizeof(uint32_t));
533 	}
534 
535 	// Required extension 3 - byte counter
536 	if ( (master_record->flags & FLAG_BYTES_64 ) != 0 ) {
537 		// 64bit byte counter
538 		value64_t	l, *v = (value64_t *)p;
539 		l.val.val64 = master_record->dOctets;
540 		v->val.val32[0] = l.val.val32[0];
541 		v->val.val32[1] = l.val.val32[1];
542 		p = (void *)((pointer_addr_t)p + sizeof(uint64_t));
543 	} else {
544 		// 32bit bytes counter
545 		*((uint32_t *)p) = master_record->dOctets;
546 		p = (void *)((pointer_addr_t)p + sizeof(uint32_t));
547 	}
548 
549 	// Process optional extensions
550 	i=0;
551 	while ( extension_map->ex_id[i] ) {
552 		switch (extension_map->ex_id[i++]) {
553 			// 0 - 3 should never be in an extension table so - ignore it
554 			case 0:
555 			case 1:
556 			case 2:
557 			case 3:
558 				break;
559 			case EX_IO_SNMP_2: { // input/output SNMP 2 byte
560 				tpl_ext_4_t *tpl = (tpl_ext_4_t *)p;
561 				tpl->input  = master_record->input;
562 				tpl->output = master_record->output;
563 				p = (void *)tpl->data;
564 				} break;
565 			case EX_IO_SNMP_4: { // input/output SNMP 4 byte
566 				tpl_ext_5_t *tpl = (tpl_ext_5_t *)p;
567 				tpl->input  = master_record->input;
568 				tpl->output = master_record->output;
569 				p = (void *)tpl->data;
570 				} break;
571 			case EX_AS_2: { // srcas/dstas 2 byte
572 				tpl_ext_6_t *tpl = (tpl_ext_6_t *)p;
573 				tpl->src_as = master_record->srcas;
574 				tpl->dst_as = master_record->dstas;
575 				p = (void *)tpl->data;
576 				} break;
577 			case EX_AS_4: { // srcas/dstas 4 byte
578 				tpl_ext_7_t *tpl = (tpl_ext_7_t *)p;
579 				tpl->src_as = master_record->srcas;
580 				tpl->dst_as = master_record->dstas;
581 				p = (void *)tpl->data;
582 				} break;
583 			case EX_MULIPLE: {
584 				tpl_ext_8_t *tpl = (tpl_ext_8_t *)p;
585 				// use a 32 bit int to copy all 4 fields
586 				tpl->any = master_record->any;
587 				p = (void *)tpl->data;
588 				} break;
589 			case EX_NEXT_HOP_v4: {
590 				tpl_ext_9_t *tpl = (tpl_ext_9_t *)p;
591 				tpl->nexthop = master_record->ip_nexthop.V4;
592 				p = (void *)tpl->data;
593 				} break;
594 			case EX_NEXT_HOP_v6: {
595 				tpl_ext_10_t *tpl = (tpl_ext_10_t *)p;
596 				tpl->nexthop[0] = master_record->ip_nexthop.V6[0];
597 				tpl->nexthop[1] = master_record->ip_nexthop.V6[1];
598 				p = (void *)tpl->data;
599 				} break;
600 			case EX_NEXT_HOP_BGP_v4: {
601 				tpl_ext_11_t *tpl = (tpl_ext_11_t *)p;
602 				tpl->bgp_nexthop = master_record->bgp_nexthop.V4;
603 				p = (void *)tpl->data;
604 				} break;
605 			case EX_NEXT_HOP_BGP_v6: {
606 				tpl_ext_12_t *tpl = (tpl_ext_12_t *)p;
607 				tpl->bgp_nexthop[0] = master_record->bgp_nexthop.V6[0];
608 				tpl->bgp_nexthop[1] = master_record->bgp_nexthop.V6[1];
609 				p = (void *)tpl->data;
610 				} break;
611 			case EX_VLAN: {
612 				tpl_ext_13_t *tpl = (tpl_ext_13_t *)p;
613 				tpl->src_vlan = master_record->src_vlan;
614 				tpl->dst_vlan = master_record->dst_vlan;
615 				p = (void *)tpl->data;
616 				} break;
617 			case EX_OUT_PKG_4: {
618 				tpl_ext_14_t *tpl = (tpl_ext_14_t *)p;
619 				tpl->out_pkts = master_record->out_pkts;
620 				p = (void *)tpl->data;
621 				} break;
622 			case EX_OUT_PKG_8: {
623 				tpl_ext_15_t v, *tpl = (tpl_ext_15_t *)p;
624 				v.out_pkts = master_record->out_pkts;
625 				tpl->v[0] = v.v[0];
626 				tpl->v[1] = v.v[1];
627 				p = (void *)tpl->data;
628 				} break;
629 			case EX_OUT_BYTES_4: {
630 				tpl_ext_16_t *tpl = (tpl_ext_16_t *)p;
631 				tpl->out_bytes = master_record->out_bytes;
632 				p = (void *)tpl->data;
633 				} break;
634 			case EX_OUT_BYTES_8: {
635 				tpl_ext_17_t v, *tpl = (tpl_ext_17_t *)p;
636 				v.out_bytes = master_record->out_bytes;
637 				tpl->v[0] = v.v[0];
638 				tpl->v[1] = v.v[1];
639 				p = (void *)tpl->data;
640 				} break;
641 			case EX_AGGR_FLOWS_4: {
642 				tpl_ext_18_t *tpl = (tpl_ext_18_t *)p;
643 				tpl->aggr_flows = master_record->aggr_flows;
644 				p = (void *)tpl->data;
645 				} break;
646 			case EX_AGGR_FLOWS_8: {
647 				tpl_ext_19_t v, *tpl = (tpl_ext_19_t *)p;
648 				v.aggr_flows = master_record->aggr_flows;
649 				tpl->v[0] = v.v[0];
650 				tpl->v[1] = v.v[1];
651 				p = (void *)tpl->data;
652 				} break;
653 			case EX_MAC_1: {
654 				tpl_ext_20_t v, *tpl = (tpl_ext_20_t *)p;
655 				v.in_src_mac = master_record->in_src_mac;
656 				tpl->v1[0] = v.v1[0];
657 				tpl->v1[1] = v.v1[1];
658 				v.out_dst_mac = master_record->out_dst_mac;
659 				tpl->v2[0] = v.v2[0];
660 				tpl->v2[1] = v.v2[1];
661 				p = (void *)tpl->data;
662 				} break;
663 			case EX_MAC_2: {
664 				tpl_ext_21_t v, *tpl = (tpl_ext_21_t *)p;
665 				v.in_dst_mac = master_record->in_dst_mac;
666 				tpl->v1[0] = v.v1[0];
667 				tpl->v1[1] = v.v1[1];
668 				v.out_src_mac = master_record->out_src_mac;
669 				tpl->v2[0] = v.v2[0];
670 				tpl->v2[1] = v.v2[1];
671 				p = (void *)tpl->data;
672 				} break;
673 			case EX_MPLS: {
674 				tpl_ext_22_t *tpl = (tpl_ext_22_t *)p;
675 				int j;
676 				for (j=0; j<10; j++ ) {
677 					tpl->mpls_label[j] = master_record->mpls_label[j];
678 				}
679 				p = (void *)tpl->data;
680 				} break;
681 			case EX_ROUTER_IP_v4: {
682 				tpl_ext_23_t *tpl = (tpl_ext_23_t *)p;
683 				tpl->router_ip = master_record->ip_router.V4;
684 				p = (void *)tpl->data;
685 				} break;
686 			case EX_ROUTER_IP_v6: {
687 				tpl_ext_24_t *tpl = (tpl_ext_24_t *)p;
688 				tpl->router_ip[0] = master_record->ip_router.V6[0];
689 				tpl->router_ip[1] = master_record->ip_router.V6[1];
690 				p = (void *)tpl->data;
691 				} break;
692 			case EX_ROUTER_ID: {
693 				tpl_ext_25_t *tpl = (tpl_ext_25_t *)p;
694 				tpl->engine_type = master_record->engine_type;
695 				tpl->engine_id   = master_record->engine_id;
696 				p = (void *)tpl->data;
697 				} break;
698 			case EX_BGPADJ: {
699 				tpl_ext_26_t *tpl = (tpl_ext_26_t *)p;
700 				tpl->bgpNextAdjacentAS = master_record->bgpNextAdjacentAS;
701 				tpl->bgpPrevAdjacentAS = master_record->bgpPrevAdjacentAS;
702 				p = (void *)tpl->data;
703 				} break;
704 			case EX_RECEIVED: {
705 				tpl_ext_27_t *tpl = (tpl_ext_27_t *)p;
706 				tpl->received = master_record->received;
707 				p = (void *)tpl->data;
708 				} break;
709 			case EX_LATENCY: {
710 				tpl_ext_latency_t *tpl = (tpl_ext_latency_t *)p;
711 				tpl->client_nw_delay_usec = master_record->client_nw_delay_usec;
712 				tpl->server_nw_delay_usec = master_record->server_nw_delay_usec;
713 				tpl->appl_latency_usec	  = master_record->appl_latency_usec;
714 				p = (void *)tpl->data;
715 			} break;
716 #ifdef NSEL
717 			case EX_NSEL_COMMON: {
718 				tpl_ext_37_t *tpl = (tpl_ext_37_t *)p;
719 				tpl->event_time = master_record->event_time;
720 				tpl->conn_id    = master_record->conn_id;
721 				tpl->fw_event   = master_record->event;
722 				tpl->nsel_icmp  = master_record->icmp;
723 				tpl->fill  = 0;
724 				tpl->sec_group_tag = master_record->sec_group_tag;
725 				tpl->fw_xevent = master_record->fw_xevent;
726 				p = (void *)tpl->data;
727 				} break;
728 			case EX_NSEL_XLATE_PORTS: {
729 				tpl_ext_38_t *tpl = (tpl_ext_38_t *)p;
730 				tpl->xlate_src_port	 = master_record->xlate_src_port;
731 				tpl->xlate_dst_port	 = master_record->xlate_dst_port;
732 				p = (void *)tpl->data;
733 				} break;
734 			case EX_NSEL_XLATE_IP_v4: {
735 				tpl_ext_39_t *tpl = (tpl_ext_39_t *)p;
736 				tpl->xlate_src_ip = master_record->xlate_src_ip.V4;
737 				tpl->xlate_dst_ip = master_record->xlate_dst_ip.V4;
738 				p = (void *)tpl->data;
739 				} break;
740 			case EX_NSEL_XLATE_IP_v6: {
741 				tpl_ext_40_t *tpl = (tpl_ext_40_t *)p;
742 				tpl->xlate_src_ip[0] = master_record->xlate_src_ip.V6[0];
743 				tpl->xlate_src_ip[1] = master_record->xlate_src_ip.V6[1];
744 				p = (void *)tpl->data;
745 				tpl->xlate_dst_ip[0] = master_record->xlate_dst_ip.V6[0];
746 				tpl->xlate_dst_ip[1] = master_record->xlate_dst_ip.V6[1];
747 				p = (void *)tpl->data;
748 				} break;
749 			case EX_NSEL_ACL: {
750 				tpl_ext_41_t *tpl = (tpl_ext_41_t *)p;
751 				int j;
752 				for (j=0; j<3; j++) {
753 					tpl->ingress_acl_id[j] = master_record->ingress_acl_id[j];
754 					tpl->egress_acl_id[j]  = master_record->egress_acl_id[j];
755 				}
756 				p = (void *)tpl->data;
757 			} break;
758 			case EX_NSEL_USER: {
759 				tpl_ext_42_t *tpl = (tpl_ext_42_t *)p;
760 				strncpy((void *)tpl->username, (void *)master_record->username, sizeof(tpl->username));
761 				tpl->username[sizeof(tpl->username)-1] = '\0';	// safety 0
762 				p = (void *)tpl->data;
763 			} break;
764 			case EX_NSEL_USER_MAX: {
765 				tpl_ext_43_t *tpl = (tpl_ext_43_t *)p;
766 				strncpy((void *)tpl->username, (void *)master_record->username, sizeof(tpl->username));
767 				tpl->username[sizeof(tpl->username)-1] = '\0';	// safety 0
768 				p = (void *)tpl->data;
769 			} break;
770 			case EX_NEL_COMMON: {
771 				tpl_ext_46_t *tpl = (tpl_ext_46_t *)p;
772 				tpl->nat_event  = master_record->event;
773 				tpl->fill  = 0;
774 				tpl->flags = 0;
775 				tpl->egress_vrfid  = master_record->egress_vrfid;
776 				tpl->ingress_vrfid = master_record->ingress_vrfid;
777 				p = (void *)tpl->data;
778 			} break;
779 			case EX_PORT_BLOCK_ALLOC: {
780 				tpl_ext_48_t *tpl = (tpl_ext_48_t *)p;
781 				tpl->block_start = master_record->block_start;
782 				tpl->block_end   = master_record->block_end;
783 				tpl->block_step  = master_record->block_step;
784 				tpl->block_size  = master_record->block_size;
785 				p = (void *)tpl->data;
786 			} break;
787 #endif
788 		}
789 	}
790 
791 	nffile->block_header->size += required;
792 	nffile->block_header->NumRecords++;
793 #ifdef DEVEL
794 	if ( ((pointer_addr_t)p - (pointer_addr_t)nffile->buff_ptr) != required ) {
795 		fprintf(stderr, "Packrecord: size missmatch: required: %i, written: %li!\n",
796 			required, (long)((ptrdiff_t)p - (ptrdiff_t)nffile->buff_ptr));
797 		exit(255);
798 	}
799 #endif
800 	nffile->buff_ptr = p;
801 
802 } // End of PackRecord
803 #endif
804 
AppendToBuffer(nffile_t * nffile,void * record,size_t required)805 static inline void AppendToBuffer(nffile_t *nffile, void *record, size_t required) {
806 
807 	// flush current buffer to disc
808 	if ( !CheckBufferSpace(nffile, required)) {
809 		return;
810 	}
811 
812 	// enough buffer space available at this point
813 	memcpy(nffile->buff_ptr, record, required);
814 
815 	// update stat
816 	nffile->block_header->NumRecords++;
817 	nffile->block_header->size += required;
818 
819 	// advance write pointer
820 	nffile->buff_ptr = (void *)((pointer_addr_t)nffile->buff_ptr + required);
821 
822 } // End of AppendToBuffer
823