1 /*
2  *  Copyright (c) 2009-2020 Peter Haag
3  *  Copyright (c) 2004-2008, SWITCH - Teleinformatikdienste fuer Lehre und Forschung
4  *  All rights reserved.
5  *
6  *  Redistribution and use in source and binary forms, with or without
7  *  modification, are permitted provided that the following conditions are met:
8  *
9  *   * Redistributions of source code must retain the above copyright notice,
10  *	 this list of conditions and the following disclaimer.
11  *   * Redistributions in binary form must reproduce the above copyright notice,
12  *	 this list of conditions and the following disclaimer in the documentation
13  *	 and/or other materials provided with the distribution.
14  *   * Neither the name of the author nor the names of its contributors may be
15  *	 used to endorse or promote products derived from this software without
16  *	 specific prior written permission.
17  *
18  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  *  POSSIBILITY OF SUCH DAMAGE.
29  *
30  */
31 
32 #include "config.h"
33 
34 #include <stdio.h>
35 #include <unistd.h>
36 #include <stdlib.h>
37 #include <stdarg.h>
38 #include <errno.h>
39 #include <time.h>
40 #include <string.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <fcntl.h>
44 #include <sys/socket.h>
45 #include <netinet/in.h>
46 #include <arpa/inet.h>
47 
48 #ifdef HAVE_STDINT_H
49 #include <stdint.h>
50 #endif
51 
52 #include "util.h"
53 #include "nfdump.h"
54 #include "nffile.h"
55 #include "collector.h"
56 #include "nfx.h"
57 
58 extern extension_descriptor_t extension_descriptor[];
59 
60 static time_t	when;
61 uint32_t offset  = 10;
62 uint32_t msecs   = 10;
63 
64 static extension_info_t extension_info;
65 
66 #define NEED_PACKRECORD 1
67 #include "nffile_inline.c"
68 #undef NEED_PACKRECORD
69 
70 void *GenRecord(int af, void *buff_ptr, char *src_ip, char *dst_ip, int src_port, int dst_port,
71 	int proto, int tcp_flags, int tos, uint64_t packets, uint64_t bytes, int src_as, int dst_as);
72 
73 static void SetIPaddress(master_record_t *record, int af,  char *src_ip, char *dst_ip);
74 
75 static void SetNextIPaddress(master_record_t *record, int af,  char *next_ip);
76 
77 static void SetRouterIPaddress(master_record_t *record, int af,  char *next_ip);
78 
79 static void SetBGPNextIPaddress(master_record_t *record, int af,  char *next_ip);
80 
81 static void UpdateRecord(master_record_t *record);
82 
SetIPaddress(master_record_t * record,int af,char * src_ip,char * dst_ip)83 static void SetIPaddress(master_record_t *record, int af,  char *src_ip, char *dst_ip) {
84 
85 	if ( af == PF_INET6 ) {
86 		SetFlag(record->flags, FLAG_IPV6_ADDR);
87 		inet_pton(PF_INET6, src_ip, &(record->V6.srcaddr[0]));
88 		inet_pton(PF_INET6, dst_ip, &(record->V6.dstaddr[0]));
89 		record->V6.srcaddr[0] = ntohll(record->V6.srcaddr[0]);
90 		record->V6.srcaddr[1] = ntohll(record->V6.srcaddr[1]);
91 		record->V6.dstaddr[0] = ntohll(record->V6.dstaddr[0]);
92 		record->V6.dstaddr[1] = ntohll(record->V6.dstaddr[1]);
93 	} else {
94 		ClearFlag(record->flags, FLAG_IPV6_ADDR);
95 		inet_pton(PF_INET, src_ip, &record->V4.srcaddr);
96 		inet_pton(PF_INET, dst_ip, &record->V4.dstaddr);
97 		record->V4.srcaddr = ntohl(record->V4.srcaddr);
98 		record->V4.dstaddr = ntohl(record->V4.dstaddr);
99 	}
100 
101 } // End of SetIPaddress
102 
SetNextIPaddress(master_record_t * record,int af,char * next_ip)103 static void SetNextIPaddress(master_record_t *record, int af,  char *next_ip) {
104 
105 	if ( af == PF_INET6 ) {
106 		SetFlag(record->flags, FLAG_IPV6_NH);
107 		inet_pton(PF_INET6, next_ip, &(record->ip_nexthop.V6[0]));
108 		record->ip_nexthop.V6[0] = ntohll(record->ip_nexthop.V6[0]);
109 		record->ip_nexthop.V6[1] = ntohll(record->ip_nexthop.V6[1]);
110 	} else {
111 		ClearFlag(record->flags, FLAG_IPV6_NH);
112 		inet_pton(PF_INET, next_ip, &record->ip_nexthop.V4);
113 		record->ip_nexthop.V4 = ntohl(record->ip_nexthop.V4);
114 	}
115 
116 } // End of SetNextIPaddress
117 
SetRouterIPaddress(master_record_t * record,int af,char * next_ip)118 static void SetRouterIPaddress(master_record_t *record, int af,  char *next_ip) {
119 
120 	if ( af == PF_INET6 ) {
121 		SetFlag(record->flags, FLAG_IPV6_NH);
122 		inet_pton(PF_INET6, next_ip, &(record->ip_router.V6[0]));
123 		record->ip_router.V6[0] = ntohll(record->ip_router.V6[0]);
124 		record->ip_router.V6[1] = ntohll(record->ip_router.V6[1]);
125 	} else {
126 		ClearFlag(record->flags, FLAG_IPV6_NH);
127 		inet_pton(PF_INET, next_ip, &record->ip_router.V4);
128 		record->ip_router.V4 = ntohl(record->ip_router.V4);
129 	}
130 
131 } // End of SetRouterIPaddress
132 
SetBGPNextIPaddress(master_record_t * record,int af,char * next_ip)133 static void SetBGPNextIPaddress(master_record_t *record, int af,  char *next_ip) {
134 
135 	if ( af == PF_INET6 ) {
136 		SetFlag(record->flags, FLAG_IPV6_NHB);
137 		inet_pton(PF_INET6, next_ip, &(record->bgp_nexthop.V6[0]));
138 		record->bgp_nexthop.V6[0] = ntohll(record->bgp_nexthop.V6[0]);
139 		record->bgp_nexthop.V6[1] = ntohll(record->bgp_nexthop.V6[1]);
140 	} else {
141 		ClearFlag(record->flags, FLAG_IPV6_NHB);
142 		inet_pton(PF_INET, next_ip, &record->bgp_nexthop.V4);
143 		record->bgp_nexthop.V4 = ntohl(record->bgp_nexthop.V4);
144 	}
145 
146 } // End of SetBGPNextIPaddress
147 
148 
UpdateRecord(master_record_t * record)149 static void UpdateRecord(master_record_t *record) {
150 
151 	record->first		= when;
152 	record->last		 = when + offset;
153 	record->msec_first   = msecs;
154 	record->msec_last	= msecs + 10;
155 
156 	when   += 10;
157 	offset += 10;
158 
159 	msecs += 100;
160 	if ( msecs > 1000 )
161 		msecs = msecs - 1000;
162 
163 	record->fwd_status++;
164 
165 } // End of UpdateRecord
166 
main(int argc,char ** argv)167 int main( int argc, char **argv ) {
168 int i, c;
169 master_record_t		record;
170 nffile_t			*nffile;
171 
172 	when = ISO2UNIX(strdup("200407111030"));
173 	while ((c = getopt(argc, argv, "h")) != EOF) {
174 		switch(c) {
175 			case 'h':
176 				break;
177 			default:
178 				fprintf(stderr, "ERROR: Unsupported option: '%c'\n", c);
179 				exit(255);
180 		}
181 	}
182 
183 	extension_info.map = (extension_map_t *)malloc(sizeof(extension_map_t) + 32 * sizeof(uint16_t));
184 	if ( !extension_info.map ) {
185 		fprintf(stderr, "malloc() error in %s line %d: %s\n", __FILE__, __LINE__, strerror (errno));
186 		exit(255);
187 	}
188 	extension_info.map->type = ExtensionMapType;
189 	extension_info.map->map_id = 0;
190 	i = 0;
191 	extension_info.map->ex_id[i++] = EX_IO_SNMP_2;
192 	extension_info.map->ex_id[i++] = EX_AS_2;
193 	extension_info.map->ex_id[i++] = EX_MULIPLE;
194 	extension_info.map->ex_id[i++] = EX_NEXT_HOP_v4;
195 	extension_info.map->ex_id[i++] = EX_NEXT_HOP_BGP_v4;
196 	extension_info.map->ex_id[i++] = EX_VLAN;
197 	extension_info.map->ex_id[i++] = EX_OUT_PKG_4;
198 	extension_info.map->ex_id[i++] = EX_OUT_BYTES_4;
199 	extension_info.map->ex_id[i++] = EX_AGGR_FLOWS_4;
200  	extension_info.map->ex_id[i++] = EX_MAC_1;
201  	extension_info.map->ex_id[i++] = EX_MAC_2;
202  	extension_info.map->ex_id[i++] = EX_MPLS;
203  	extension_info.map->ex_id[i++] = EX_ROUTER_IP_v4;
204  	extension_info.map->ex_id[i++] = EX_ROUTER_ID;
205  	extension_info.map->ex_id[i++] = EX_BGPADJ;
206 	extension_info.map->ex_id[i] = 0;
207 	extension_info.map->size = sizeof(extension_map_t) + i * sizeof(uint16_t);
208 
209 	// align 32bits
210 	if (( extension_info.map->size & 0x3 ) != 0 ) {
211 		extension_info.map->size += 4 - ( extension_info.map->size & 0x3 );
212 	}
213 
214 	extension_info.map->extension_size = 0;
215 	i=0;
216 	while (extension_info.map->ex_id[i]) {
217 		int id = extension_info.map->ex_id[i];
218 		extension_info.map->extension_size += extension_descriptor[id].size;
219 		i++;
220 	}
221 	memset((void *)&record, 0, sizeof(record));
222 
223 	nffile = OpenNewFile("-", NULL, NOT_COMPRESSED, 0, NULL);
224 	if ( !nffile ) {
225 		exit(255);
226 	}
227 
228 	AppendToBuffer(nffile, (void *)extension_info.map, extension_info.map->size);
229 
230 	record.map_ref = extension_info.map;
231 	record.type	= CommonRecordType;
232 
233 	record.flags   		= 0;
234 	record.exporter_sysid = 1;
235 	record.tcp_flags   	= 1;
236 	record.tos 		   	= 2;
237 	record.fwd_status	= 0;
238 	record.srcport 	 	= 1024;
239 	record.dstport 	 	= 25;
240 	record.prot 	 	= IPPROTO_TCP;
241 	record.input 	 	= 12;
242 	record.output 	 	= 14;
243 	record.srcas 	 	= 775;
244 	record.dstas 	 	= 8404;
245 	SetIPaddress(&record,  PF_INET, "172.16.1.66", "192.168.170.100");
246 	SetNextIPaddress(&record,  PF_INET, "172.72.1.2");
247 	SetBGPNextIPaddress(&record,  PF_INET, "172.73.2.3");
248 	SetRouterIPaddress(&record,  PF_INET, "127.0.0.1");
249 	record.engine_type	= 5;
250 	record.engine_id	= 6;
251 	record.dPkts 	 	= 202;
252 	record.dOctets 	 	= 303;
253 	record.dst_tos		= 128;
254 	record.dir			= 1;
255 	record.src_mask		= 16;
256 	record.dst_mask		= 24;
257 	record.src_vlan		= 82;
258 	record.dst_vlan		= 93;
259 	record.out_pkts		= 212;
260 	record.out_bytes	= 3234;
261 	record.aggr_flows	= 3;
262 	record.in_src_mac	= 0x0234567890aaLL;
263 	record.out_dst_mac	= 0xffeeddccbbaaLL;
264 	record.out_src_mac	= 0xaa3456789002LL;
265 	record.in_dst_mac	= 0xaaeeddccbbffLL;
266 	record.mpls_label[0] = 1010 << 4;
267 	record.mpls_label[1] = 2020 << 4;
268 	record.mpls_label[2] = 3030 << 4;
269 	record.mpls_label[3] = 4040 << 4;
270 	record.mpls_label[4] = 5050 << 4;
271 	record.mpls_label[5] = 6060 << 4;
272 	record.mpls_label[6] = 7070 << 4;
273 	record.mpls_label[7] = 8080 << 4;
274 	record.mpls_label[8] = 9090 << 4;
275 	record.mpls_label[9] = (100100 << 4) + 1;
276 	record.client_nw_delay_usec = 2;
277 	record.server_nw_delay_usec = 22;
278 	record.appl_latency_usec = 222;
279 	record.bgpNextAdjacentAS = 45804;
280 	record.bgpPrevAdjacentAS = 32775;
281 
282 	fprintf(stderr, "IPv4 32bit packets 32bit bytes\n");
283 	UpdateRecord(&record);
284 	PackRecord(&record, nffile);
285 
286 	SetIPaddress(&record,  PF_INET, "172.16.2.66", "192.168.170.101");
287 	fprintf(stderr, "IPv4 32bit packets 32bit bytes\n");
288 	UpdateRecord(&record);
289 	PackRecord(&record, nffile);
290 
291 	record.dPkts 	 	= 101;
292 	record.dOctets 	 	= 102;
293 	fprintf(stderr, "IPv4 32bit packets 32bit bytes\n");
294 	UpdateRecord(&record);
295 	PackRecord(&record, nffile);
296 
297 	SetIPaddress(&record,  PF_INET, "172.16.3.66", "192.168.170.102");
298 	fprintf(stderr, "IPv4 32bit packets 32bit bytes\n");
299 	UpdateRecord(&record);
300 	PackRecord(&record, nffile);
301 
302 	SetIPaddress(&record,  PF_INET, "172.16.4.66", "192.168.170.103");
303 	record.srcport 	 = 2024;
304 	record.prot 	 = IPPROTO_UDP;
305 	record.tcp_flags = 1;
306 	record.tos 		 = 1;
307 	record.dPkts 	 = 1001;
308 	record.dOctets 	 = 1002;
309 	fprintf(stderr, "IPv4 32bit packets 32bit bytes\n");
310 	UpdateRecord(&record);
311 	PackRecord(&record, nffile);
312 
313 	SetIPaddress(&record,  PF_INET, "172.16.5.66", "192.168.170.104");
314 	record.srcport 	 	= 3024;
315 	record.prot 	 	= 51;
316 	record.tcp_flags 	= 2;
317 	record.tos 		 	= 2;
318 	record.dPkts 	 	= 10001;
319 	record.dOctets 	 	= 10002;
320 	fprintf(stderr, "IPv4 32bit packets 32bit bytes\n");
321 	UpdateRecord(&record);
322 	PackRecord(&record, nffile);
323 
324 	SetIPaddress(&record,  PF_INET, "172.16.6.66", "192.168.170.105");
325 	record.srcport 	 	= 4024;
326 	record.prot 	 	= IPPROTO_TCP;
327 	record.tcp_flags 	= 4;
328 	record.tos 		 	= 3;
329 	record.dPkts 	 	= 100001;
330 	record.dOctets 	 	= 100002;
331 	fprintf(stderr, "IPv4 32bit packets 32bit bytes\n");
332 	UpdateRecord(&record);
333 	PackRecord(&record, nffile);
334 
335 	SetIPaddress(&record,  PF_INET, "172.16.7.66", "192.168.170.106");
336 	record.srcport 	 	= 5024;
337 	record.tcp_flags 	= 8;
338 	record.tos 		 	= 4;
339 	record.dPkts 	 	= 1000001;
340 	record.dOctets 	 	= 1000002;
341 	fprintf(stderr, "IPv4 32bit packets 32bit bytes\n");
342 	UpdateRecord(&record);
343 	PackRecord(&record, nffile);
344 
345 	SetIPaddress(&record,  PF_INET, "172.16.8.66", "192.168.170.107");
346 	record.tcp_flags 	= 1;
347 	record.tos 		 	= 4;
348 	record.dPkts 	 	= 10000001;
349 	record.dOctets 	 	= 1001;
350 	fprintf(stderr, "IPv4 32bit packets 32bit bytes\n");
351 	UpdateRecord(&record);
352 	PackRecord(&record, nffile);
353 
354 	SetIPaddress(&record,  PF_INET, "172.16.9.66", "192.168.170.108");
355 	record.srcport 	 	= 6024;
356 	record.tcp_flags 	= 16;
357 	record.tos 		 	= 5;
358 	record.dPkts 	 	= 500;
359 	record.dOctets 	 	= 10000001;
360 	fprintf(stderr, "IPv4 32bit packets 32bit bytes\n");
361 	UpdateRecord(&record);
362 	PackRecord(&record, nffile);
363 
364 	SetIPaddress(&record,  PF_INET, "172.16.10.66", "192.168.170.109");
365 	fprintf(stderr, "IPv4 32bit packets 32bit bytes\n");
366 	UpdateRecord(&record);
367 	PackRecord(&record, nffile);
368 
369 	SetIPaddress(&record,  PF_INET, "172.16.11.66", "192.168.170.110");
370 	record.srcport 		= 7024;
371 	record.tcp_flags 	= 32;
372 	record.tos 		 	= 255;
373 	record.dPkts 	 	= 5000;
374 	record.dOctets 	 	= 100000001;
375 	fprintf(stderr, "IPv4 32bit packets 32bit bytes\n");
376 	UpdateRecord(&record);
377 	PackRecord(&record, nffile);
378 
379 	SetIPaddress(&record,  PF_INET, "172.16.12.66", "192.168.170.111");
380 	record.srcport 	 	= 8024;
381 	record.tcp_flags 	= 63;
382 	record.tos 		 	= 0;
383 	record.dOctets 	 	= 1000000001;
384 	fprintf(stderr, "IPv4 32bit packets 32bit bytes\n");
385 	UpdateRecord(&record);
386 	PackRecord(&record, nffile);
387 
388 	SetIPaddress(&record,  PF_INET, "172.16.13.66", "192.168.170.112");
389 	record.srcport 	 	= 0;
390 	record.dstport 	 	= 8;
391 	record.prot 	 	= IPPROTO_ICMP;
392 	record.tcp_flags 	= 0;
393 	record.tos 		 	= 0;
394 	record.dPkts 	 	= 50002;
395 	record.dOctets 	 	= 50000;
396 	fprintf(stderr, "IPv4 32bit packets 32bit bytes\n");
397 	UpdateRecord(&record);
398 	PackRecord(&record, nffile);
399 
400 	SetIPaddress(&record,  PF_INET, "172.160.160.166", "172.160.160.180");
401 	record.srcport 	 = 10024;
402 	record.dstport 	 = 25000;
403 	record.prot 	 = IPPROTO_TCP;
404 	record.dPkts 	 = 500001;
405 	record.dOctets 	 = 500000;
406 	fprintf(stderr, "IPv4 32bit packets 32bit bytes\n");
407 	UpdateRecord(&record);
408 	PackRecord(&record, nffile);
409 
410 	SetIPaddress(&record,  PF_INET6, "fe80::2110:abcd:1234:0", "fe80::2110:abcd:1235:4321");
411 //	SetNextIPaddress(&record,  PF_INET6, "2003:234:aabb::211:24ff:fe80:d01e");
412 //	SetBGPNextIPaddress(&record,  PF_INET6, "2004:234:aabb::211:24ff:fe80:d01e");
413 	record.srcport 	 = 1024;
414 	record.dstport 	 = 25;
415 	record.tcp_flags = 27;
416 	record.dPkts 	 = 10;
417 	record.dOctets 	 = 15100;
418 	fprintf(stderr, "IPv6 32bit packets 32bit bytes\n");
419 	UpdateRecord(&record);
420 	PackRecord(&record, nffile);
421 
422 	SetIPaddress(&record,  PF_INET6, "2001:234:aabb:cc:211:24ff:fe80:d01e", "2001:620:1f:8:203:baff:fe52:38e5");
423 	record.src_mask		= 88;
424 	record.dst_mask		= 48;
425 	record.srcport 	 = 10240;
426 	record.dstport 	 = 52345;
427 	record.dPkts 	 = 10100;
428 	record.dOctets 	 = 15000000;
429 	fprintf(stderr, "IPv6 32bit packets 32bit bytes\n");
430 	UpdateRecord(&record);
431 	PackRecord(&record, nffile);
432 
433 	record.dPkts 	 = 10100000;
434 	record.dOctets 	 = 0x100000000LL;
435 	fprintf(stderr, "IPv6 32bit packets 64bit bytes\n");
436 	UpdateRecord(&record);
437 	PackRecord(&record, nffile);
438 
439 	record.dPkts 	 = 0x100000000LL;
440 	record.dOctets 	 = 15000000;
441 	fprintf(stderr, "IPv6 64bit packets 32bit bytes\n");
442 	UpdateRecord(&record);
443 	PackRecord(&record, nffile);
444 
445 	record.dOctets 	 = 0x200000000LL;
446 	fprintf(stderr, "IPv6 64bit packets 64bit bytes\n");
447 	UpdateRecord(&record);
448 	PackRecord(&record, nffile);
449 
450 	SetIPaddress(&record,  PF_INET, "172.16.14.18", "192.168.170.113");
451 //	SetNextIPaddress(&record,  PF_INET, "172.72.1.2");
452 //	SetBGPNextIPaddress(&record,  PF_INET, "172.73.2.3");
453 	record.src_mask		= 16;
454 	record.dst_mask		= 24;
455 	record.srcport 	 = 10240;
456 	record.dstport 	 = 52345;
457 	record.dPkts 	 = 10100000;
458 	record.dOctets 	 = 0x100000000LL;
459 	fprintf(stderr, "IPv4 32bit packets 64bit bytes\n");
460 	UpdateRecord(&record);
461 	PackRecord(&record, nffile);
462 
463 	SetIPaddress(&record,  PF_INET, "172.16.15.18", "192.168.170.114");
464 	record.dPkts 	 = 0x100000000LL;
465 	record.dOctets 	 = 15000000;
466 	fprintf(stderr, "IPv4 64bit packets 32bit bytes\n");
467 	UpdateRecord(&record);
468 	PackRecord(&record, nffile);
469 
470 	SetIPaddress(&record,  PF_INET, "172.16.16.18", "192.168.170.115");
471 	record.dOctets 	 = 0x200000000LL;
472 	fprintf(stderr, "IPv4 64bit packets 64bit bytes\n");
473 	UpdateRecord(&record);
474 	PackRecord(&record, nffile);
475 
476 	extension_info.map->ex_id[0] = EX_IO_SNMP_4;
477 
478 	extension_info.map->extension_size = 0;
479 	i=0;
480 	while (extension_info.map->ex_id[i]) {
481 		int id = extension_info.map->ex_id[i];
482 		extension_info.map->extension_size += extension_descriptor[id].size;
483 		i++;
484 	}
485 
486 	memcpy(nffile->buff_ptr, (void *)extension_info.map, extension_info.map->size);
487 	nffile->buff_ptr += extension_info.map->size;
488 	nffile->block_header->NumRecords++;
489 	nffile->block_header->size 		+= extension_info.map->size;
490 
491 	UpdateRecord(&record);
492 	fprintf(stderr, "4 bytes interfaces, 2 bytes AS numbers %d %d\n", record.fwd_status, nffile->block_header->NumRecords);
493 	PackRecord(&record, nffile);
494 
495 	extension_info.map->ex_id[0] = EX_IO_SNMP_2;
496 	extension_info.map->ex_id[1] = EX_AS_4;
497 
498 	extension_info.map->extension_size = 0;
499 	i=0;
500 	while (extension_info.map->ex_id[i]) {
501 		int id = extension_info.map->ex_id[i];
502 		extension_info.map->extension_size += extension_descriptor[id].size;
503 		i++;
504 	}
505 
506 	memcpy(nffile->buff_ptr, (void *)extension_info.map, extension_info.map->size);
507 	nffile->buff_ptr += extension_info.map->size;
508 	nffile->block_header->NumRecords++;
509 	nffile->block_header->size 		+= extension_info.map->size;
510 
511 	UpdateRecord(&record);
512 	fprintf(stderr, "2 bytes interfaces, 4 bytes AS numbers %d %d\n", record.fwd_status, nffile->block_header->NumRecords);
513 	PackRecord(&record, nffile);
514 
515 	extension_info.map->ex_id[0] = EX_IO_SNMP_4;
516 
517 	extension_info.map->extension_size = 0;
518 	i=0;
519 	while (extension_info.map->ex_id[i]) {
520 		int id = extension_info.map->ex_id[i];
521 		extension_info.map->extension_size += extension_descriptor[id].size;
522 		i++;
523 	}
524 
525 	memcpy(nffile->buff_ptr, (void *)extension_info.map, extension_info.map->size);
526 	nffile->buff_ptr += extension_info.map->size;
527 	nffile->block_header->NumRecords++;
528 	nffile->block_header->size 		+= extension_info.map->size;
529 
530 	UpdateRecord(&record);
531 	fprintf(stderr, "4 bytes interfaces, 4 bytes AS numbers %d %d\n", record.fwd_status, nffile->block_header->NumRecords);
532 	PackRecord(&record, nffile);
533 
534 	if ( nffile->block_header->NumRecords ) {
535 		if ( WriteBlock(nffile) <= 0 ) {
536 			fprintf(stderr, "Failed to write output buffer to disk: '%s'" , strerror(errno));
537 		}
538 	}
539 
540 	return 0;
541 }
542 
543