1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 2002-2012 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * *
19 ***********************************************************************/
20 #pragma prototyped
21 /*
22 * netflow method
23 *
24 * Glenn Fowler
25 * AT&T Research
26 */
27
28 #include "flowlib.h"
29
30 Dssformat_t* netflow_formats = netflow_first_format;
31
32 static Cxvariable_t fields[] =
33 {
34
35 CXV("bytes", "number", NETFLOW_bytes, "Bytes sent in duration (synthesized).")
36 CXV("count", "number", NETFLOW_count, "Number of records that follow in packet (header).")
37 CXV("direction", "number", NETFLOW_direction, "Flow direction: 0 - ingress flow, 1 - egress flow.")
38 CXV("dst_addr", "ipaddr_t", NETFLOW_dst_addr, "Destination ip address.")
39 CXV("dst_addrv4", "ipv4addr_t", NETFLOW_dst_addrv4, "Destination ipv4 address.")
40 CXV("dst_addrv6", "ipv6addr_t", NETFLOW_dst_addrv6, "Destination ipv6 address.")
41 CXV("dst_as", "as_t", NETFLOW_dst_as, "Destination BGP AS number.")
42 CXV("dst_as16", "as16_t", NETFLOW_dst_as16, "Destination BGP AS16 number.")
43 CXV("dst_as32", "as32_t", NETFLOW_dst_as32, "Destination BGP AS32 number.")
44 CXV("dst_mask", "number", NETFLOW_dst_mask, "Destination address prefix mask bits.")
45 CXV("dst_maskv4", "number", NETFLOW_dst_maskv4, "Destination ipv4 address prefix mask bits.")
46 CXV("dst_maskv6", "number", NETFLOW_dst_maskv6, "Destination ipv6 address prefix mask bits.")
47 CXV("dst_port", "number", NETFLOW_dst_port, "TCP/UDP destination port number.")
48 CXV("dst_prefix", "ipprefix_t", NETFLOW_dst_prefix, "Destination ip prefix.")
49 CXV("dst_prefixv4", "ipv4prefix_t", NETFLOW_dst_prefixv4, "Destination ipv4 prefix.")
50 CXV("dst_prefixv6", "ipv6prefix_t", NETFLOW_dst_prefixv6, "Destination ipv6 prefix.")
51 CXV("dst_tos", "number", NETFLOW_dst_tos, "Type of Service on exiting outgoing interface.")
52 CXV("dst_vlan", "number", NETFLOW_dst_vlan, "Virtual LAN identifier associated with egress interface.")
53 CXV("end", "ns_t", NETFLOW_end, "Flow end time in 64 bit nanoseconds since the epoch (synthesized).")
54 CXV("engine_id", "number", NETFLOW_engine_id, "ID number of the flow switching engine.")
55 CXV("engine_type", "number", NETFLOW_engine_type, "Type of flow switching engine 0: RP, 1: VIP/linecard.")
56 CXV("first", "elapsed_t", NETFLOW_first, "Elapsed milliseconds at flow start.")
57 CXV("flags", "number", NETFLOW_flags, "Reason flow was discarded, etc.")
58 CXV("flow_active_timeout", "number", NETFLOW_flow_active_timeout, "Timeout value (in seconds) for active flow cache entries.")
59 CXV("flow_inactive_timeout", "number", NETFLOW_flow_inactive_timeout, "Timeout value (in seconds) for inactive flow cache entries.")
60 CXV("flow_label", "number", NETFLOW_flow_label, "ipv6 RFC 2460 flow label.")
61 CXV("flow_sequence", "number", NETFLOW_flow_sequence, "Flow sequence counter (header).")
62 CXV("flows", "number", NETFLOW_flows, "Number of flows that were aggregated.")
63 CXV("forwarding_code", "number", NETFLOW_forwarding_code, "Forwarding reason code.")
64 CXV("forwarding_status", "number", NETFLOW_forwarding_status, "Forwarding status 0: unknown, 1: forwarded, 2: dropped, 3: consumed.")
65 CXV("fragment_offset", "number", NETFLOW_fragment_offset, "Fragmented packet fragment-offset.")
66 CXV("hop", "ipaddr_t", NETFLOW_hop, "Next hop ip address.")
67 CXV("hopv4", "ipv4addr_t", NETFLOW_hopv4, "Next hop ipv4 address.")
68 CXV("hopv6", "ipv6addr_t", NETFLOW_hopv6, "Next hop ipv6 address.")
69 CXV("icmp_type", "number", NETFLOW_icmp_type, "Internet Control Message Protocol packet type coded as ((type*256)+code).")
70 CXV("ident", "number", NETFLOW_ident, "Identification field.")
71 CXV("if_desc", "string", NETFLOW_if_desc, "Full interface name.")
72 CXV("if_name", "string", NETFLOW_if_name, "Shortened interface name.")
73 CXV("in_bytes", "number", NETFLOW_in_bytes, "Incoming counter for the number of bytes associated with an ip Flow.")
74 CXV("in_dst_mac", "number", NETFLOW_in_dst_mac, "Incoming destination MAC address.")
75 CXV("in_permanent_bytes", "number", NETFLOW_in_permanent_bytes, "Permanent flow byte count.")
76 CXV("in_permanent_packets", "number", NETFLOW_in_permanent_packets, "Permanent flow packet count.")
77 CXV("in_packets", "number", NETFLOW_in_packets, "Incoming counter for the number of packets associated with an ip Flow.")
78 CXV("in_src_mac", "number", NETFLOW_in_src_mac, "Incoming source MAC address.")
79 CXV("input_snmp", "number", NETFLOW_input_snmp, "Input interface index.")
80 CXV("ip_protocol_version", "number", NETFLOW_ip_protocol_version, "ip version 6: ipv6, 4 or not specified: ipv4.")
81 CXV("last", "elapsed_t", NETFLOW_last, "Elapsed milliseconds at flow end.")
82 CXV("max_packet_length", "number", NETFLOW_max_packet_length, "Maximum incoming ip packet length.")
83 CXV("max_ttl", "number", NETFLOW_max_ttl, "Maximum TTL on incoming packets.")
84 CXV("min_packet_length", "number", NETFLOW_min_packet_length, "Minimum incoming ip packet length.")
85 CXV("min_ttl", "number", NETFLOW_min_ttl, "Minimum TTL on incoming packets.")
86 CXV("mpls_label_1", "number", NETFLOW_mpls_label_1, "Stack position 1 MPLS label: 20 bits MPLS label, 3 bits experimental, 1 bit end-of-stack.")
87 CXV("mpls_label_2", "number", NETFLOW_mpls_label_2, "Stack position 2 MPLS label: 20 bits MPLS label, 3 bits experimental, 1 bit end-of-stack.")
88 CXV("mpls_label_3", "number", NETFLOW_mpls_label_3, "Stack position 3 MPLS label: 20 bits MPLS label, 3 bits experimental, 1 bit end-of-stack.")
89 CXV("mpls_label_4", "number", NETFLOW_mpls_label_4, "Stack position 4 MPLS label: 20 bits MPLS label, 3 bits experimental, 1 bit end-of-stack.")
90 CXV("mpls_label_5", "number", NETFLOW_mpls_label_5, "Stack position 5 MPLS label: 20 bits MPLS label, 3 bits experimental, 1 bit end-of-stack.")
91 CXV("mpls_label_6", "number", NETFLOW_mpls_label_6, "Stack position 6 MPLS label: 20 bits MPLS label, 3 bits experimental, 1 bit end-of-stack.")
92 CXV("mpls_label_7", "number", NETFLOW_mpls_label_7, "Stack position 7 MPLS label: 20 bits MPLS label, 3 bits experimental, 1 bit end-of-stack.")
93 CXV("mpls_label_8", "number", NETFLOW_mpls_label_8, "Stack position 8 MPLS label: 20 bits MPLS label, 3 bits experimental, 1 bit end-of-stack.")
94 CXV("mpls_label_9", "number", NETFLOW_mpls_label_9, "Stack position 9 MPLS label: 20 bits MPLS label, 3 bits experimental, 1 bit end-of-stack.")
95 CXV("mpls_label_10", "number", NETFLOW_mpls_label_10, "Stack position 10 MPLS label: 20 bits MPLS label, 3 bits experimental, 1 bit end-of-stack.")
96 CXV("mpls_top_label_class", "number", NETFLOW_mpls_top_label_class, "Forwarding Equivalent Class corresponding to the MPLS Top Label.")
97 CXV("mpls_top_label_type", "number", NETFLOW_mpls_top_label_type, "MPLS top label type: 0x00 UNKNOWN 0x01 TE-MIDPT 0x02 ATOM 0x03 VPN 0x04 BGP 0x05 LDP.")
98 CXV("mul_dst_bytes", "number", NETFLOW_mul_dst_bytes, "Multicast outgoing byte count.")
99 CXV("mul_dst_packets", "number", NETFLOW_mul_dst_packets, "Multicast outgoing packet count.")
100 CXV("mul_igmp_type", "number", NETFLOW_mul_igmp_type, "Internet Group Management Protocol packet type coded.")
101 CXV("nsec", "number", NETFLOW_nsec, "Residual nanoseconds (header).")
102 CXV("option_headers", "number", NETFLOW_option_headers, "Bit-encoded field identifying ipv6 option headers found in the flow.")
103 CXV("out_bytes", "number", NETFLOW_out_bytes, "Outgoing counter for the number of bytes associated with an ip Flow.")
104 CXV("out_dst_mac", "number", NETFLOW_out_dst_mac, "Outgoing destination MAC address.")
105 CXV("out_packets", "number", NETFLOW_out_packets, "Outgoing counter for the number of packets associated with an ip Flow.")
106 CXV("out_src_mac", "number", NETFLOW_out_src_mac, "Outgoing source MAC address.")
107 CXV("output_snmp", "number", NETFLOW_output_snmp, "Output interface index.")
108 CXV("packets", "number", NETFLOW_packets, "Number of packets in flow.")
109 CXV("prot", "number", NETFLOW_protocol, "ip protocol, e.g., 6=TCP, 17=UDP, ...")
110 CXV("router_sc", "ipaddr_t", NETFLOW_router_sc, "Router shortcut ip address (V7).")
111 CXV("router_scv4", "ipv4addr_t", NETFLOW_router_scv4, "Router shortcut ipv4 address.")
112 CXV("router_scv6", "ipv6addr_t", NETFLOW_router_scv6, "Router shortcut ipv6 address.")
113 CXV("sampler_algorithm", "number", NETFLOW_sampler_algorithm, "0x01: deterministic, 0x02: random.")
114 CXV("sampler_interval", "number", NETFLOW_sampler_interval, "Sampling interval.")
115 CXV("sampler_mode", "number", NETFLOW_sampler_mode, "Sampling mode.")
116 CXV("sampler_name", "string", NETFLOW_sampler_name, "Flow sampler name.")
117 CXV("src_addr", "ipaddr_t", NETFLOW_src_addr, "Source ip address.")
118 CXV("src_addrv4", "ipv4addr_t", NETFLOW_src_addrv4, "Source ipv4 address.")
119 CXV("src_addrv6", "ipv6addr_t", NETFLOW_src_addrv6, "Source ipv6 address.")
120 CXV("src_as", "as_t", NETFLOW_src_as, "Source BGP AS number.")
121 CXV("src_as16", "as16_t", NETFLOW_src_as16, "Source BGP AS16 number.")
122 CXV("src_as32", "as32_t", NETFLOW_src_as32, "Source BGP AS32 number.")
123 CXV("src_mask", "number", NETFLOW_src_mask, "Source address prefix mask bits.")
124 CXV("src_maskv4", "number", NETFLOW_src_maskv4, "Source ipv4 address prefix mask bits.")
125 CXV("src_maskv6", "number", NETFLOW_src_maskv6, "Source ipv6 address prefix mask bits.")
126 CXV("src_port", "number", NETFLOW_src_port, "TCP/UDP source port number.")
127 CXV("src_prefix", "ipprefix_t", NETFLOW_src_prefix, "Source ip prefix.")
128 CXV("src_prefixv4", "ipv4prefix_t", NETFLOW_src_prefixv4, "Source ipv4 prefix.")
129 CXV("src_prefixv6", "ipv6prefix_t", NETFLOW_src_prefixv6, "Source ipv6 prefix.")
130 CXV("src_tos", "number", NETFLOW_src_tos, "ip type-of-service upon entering incoming interface.")
131 CXV("src_vlan", "number", NETFLOW_src_vlan, "Virtual LAN identifier associated with ingress interface.")
132 CXV("start", "ns_t", NETFLOW_start, "Flow start time in 64 bit nanoseconds since the epoch (synthesized).")
133 CXV("tcp_flags", "number", NETFLOW_tcp_flags, "Cumulative OR of tcp flags for this flow.")
134 CXV("tcp_misseq_cnt", "number", NETFLOW_tcp_misseq_cnt, "Number of mis-sequenced tcp packets (V1).")
135 CXV("tcp_retx_cnt", "number", NETFLOW_tcp_retx_cnt, "Number of mis-seq with delay > 1sec (V1).")
136 CXV("tcp_retx_secs", "number", NETFLOW_tcp_retx_secs, "Number of seconds between mis-sequenced packets (V1).")
137 CXV("time", "time_t", NETFLOW_time, "Current time in seconds since the epoch (header).")
138 CXV("tos", "number", NETFLOW_tos, "ip type-of-service (synthesized).")
139 CXV("total_bytes_exp", "number", NETFLOW_total_bytes_exp, "The number of bytes exported by the observation domain.")
140 CXV("total_flows_exp", "number", NETFLOW_total_flows_exp, "The number of flows exported by the observation domain.")
141 CXV("total_packets_exp", "number", NETFLOW_total_packets_exp, "The number of packets exported by the observation domain.")
142 CXV("uptime", "elapsed_t", NETFLOW_uptime, "Elapsed milliseconds since the router booted (header).")
143 CXV("vendor_43", "number", NETFLOW_vendor_43, "Vendor private value.")
144 CXV("vendor_51", "number", NETFLOW_vendor_51, "Vendor private value.")
145 CXV("vendor_65", "number", NETFLOW_vendor_65, "Vendor private value.")
146 CXV("vendor_66", "number", NETFLOW_vendor_66, "Vendor private value.")
147 CXV("vendor_67", "number", NETFLOW_vendor_67, "Vendor private value.")
148 CXV("vendor_68", "number", NETFLOW_vendor_68, "Vendor private value.")
149 CXV("vendor_69", "number", NETFLOW_vendor_69, "Vendor private value.")
150 CXV("vendor_87", "number", NETFLOW_vendor_87, "Vendor private value.")
151 CXV("version", "number", NETFLOW_version, "Record version (header).")
152
153 {0}
154 };
155
156 static int
op_get(Cx_t * cx,Cxinstruction_t * pc,Cxoperand_t * r,Cxoperand_t * a,Cxoperand_t * b,void * data,Cxdisc_t * disc)157 op_get(Cx_t* cx, Cxinstruction_t* pc, Cxoperand_t* r, Cxoperand_t* a, Cxoperand_t* b, void* data, Cxdisc_t* disc)
158 {
159 Netflow_method_t* gp = (Netflow_method_t*)(((Dssrecord_t*)(data))->file)->dss->data;
160 Netflow_file_t* pp = (Netflow_file_t*)(((Dssrecord_t*)(data))->file)->data;
161 Netflow_t* rp = (Netflow_t*)DSSDATA(data);
162 Cxvariable_t* vp = pc->data.variable;
163 Netflow_field_t* fp;
164
165 if (pp->template && vp->index > 0 && vp->index <= NETFLOW_TEMPLATE)
166 {
167 fp = &pp->template->field[vp->index - 1];
168 switch (fp->type)
169 {
170 case NETFLOW_BUFFER:
171 r->value.buffer.data = pp->data + fp->offset;
172 r->value.buffer.size = fp->size;
173 break;
174 case NETFLOW_NUMBER:
175 r->value.number = swapget(0, pp->data + fp->offset, fp->size);
176 break;
177 default:
178 memset(&r->value, 0, sizeof(r->value));
179 break;
180 }
181 return 0;
182 }
183 switch (vp->index)
184 {
185 case NETFLOW_bytes:
186 r->value.number = rp->bytes ? rp->bytes : rp->in_bytes;
187 break;
188 case NETFLOW_count:
189 r->value.number = rp->count;
190 break;
191 case NETFLOW_direction:
192 r->value.number = rp->direction;
193 break;
194 case NETFLOW_dst_addr:
195 if (rp->set & NETFLOW_SET_dst_addrv6)
196 {
197 r->value.buffer.data = rp->dst_addrv6;
198 r->value.buffer.size = sizeof(rp->dst_addrv6) - 1;
199 r->type = gp->type_ipv6addr;
200 }
201 else
202 {
203 r->value.number = rp->dst_addrv4;
204 r->type = gp->type_ipv4addr;
205 }
206 break;
207 case NETFLOW_dst_addrv4:
208 r->value.number = rp->dst_addrv4;
209 break;
210 case NETFLOW_dst_addrv6:
211 r->value.buffer.data = rp->dst_addrv6;
212 r->value.buffer.size = sizeof(rp->dst_addrv6) - 1;
213 break;
214 case NETFLOW_dst_as:
215 r->value.number = rp->dst_as16 ? rp->dst_as16 : rp->dst_as32;
216 break;
217 case NETFLOW_dst_as16:
218 r->value.number = rp->dst_as16;
219 break;
220 case NETFLOW_dst_as32:
221 r->value.number = rp->dst_as32;
222 break;
223 case NETFLOW_dst_mask:
224 r->value.number = (rp->set & NETFLOW_SET_dst_addrv6) ? rp->dst_addrv6[IP6BITS] : rp->dst_maskv4;
225 break;
226 case NETFLOW_dst_maskv4:
227 r->value.number = rp->dst_maskv4;
228 break;
229 case NETFLOW_dst_maskv6:
230 r->value.number = rp->dst_addrv6[IP6BITS];
231 break;
232 case NETFLOW_dst_port:
233 r->value.number = rp->dst_port;
234 break;
235 case NETFLOW_dst_prefix:
236 if (rp->set & NETFLOW_SET_dst_addrv6)
237 {
238 r->value.buffer.data = rp->dst_addrv6;
239 r->value.buffer.size = sizeof(rp->dst_addrv6);
240 r->type = gp->type_ipv6prefix;
241 }
242 else
243 {
244 r->value.number = (Cxnumber_t)rp->dst_addrv4 * 64 + rp->dst_maskv4;
245 r->type = gp->type_ipv4prefix;
246 }
247 break;
248 case NETFLOW_dst_prefixv4:
249 r->value.number = (Cxnumber_t)rp->dst_addrv4 * 64 + rp->dst_maskv4;
250 break;
251 case NETFLOW_dst_prefixv6:
252 r->value.buffer.data = rp->dst_addrv6;
253 r->value.buffer.size = sizeof(rp->dst_addrv6);
254 break;
255 case NETFLOW_dst_tos:
256 r->value.number = rp->dst_tos ? rp->dst_tos : rp->src_tos;
257 break;
258 case NETFLOW_dst_vlan:
259 r->value.number = rp->dst_vlan;
260 break;
261 case NETFLOW_end:
262 #if _typ_int64_t
263 r->value.number = (int64_t)rp->end; /* ms cc requires signed */
264 #else
265 r->value.number = rp->end;
266 #endif
267 break;
268 case NETFLOW_engine_id:
269 r->value.number = rp->engine_id;
270 break;
271 case NETFLOW_engine_type:
272 r->value.number = rp->engine_type;
273 break;
274 case NETFLOW_first:
275 r->value.number = rp->first;
276 break;
277 case NETFLOW_flags:
278 r->value.number = rp->forwarding_code;
279 break;
280 case NETFLOW_flow_active_timeout:
281 r->value.number = rp->flow_active_timeout;
282 break;
283 case NETFLOW_flow_inactive_timeout:
284 r->value.number = rp->flow_inactive_timeout;
285 break;
286 case NETFLOW_flow_label:
287 r->value.number = rp->flow_label;
288 break;
289 case NETFLOW_sampler_random_interval:
290 r->value.number = rp->sampler_random_interval;
291 break;
292 case NETFLOW_flow_sequence:
293 r->value.number = rp->flow_sequence;
294 break;
295 case NETFLOW_flows:
296 r->value.number = rp->flows;
297 break;
298 case NETFLOW_forwarding_code:
299 r->value.number = rp->forwarding_code;
300 break;
301 case NETFLOW_forwarding_status:
302 r->value.number = rp->forwarding_status;
303 break;
304 case NETFLOW_fragment_offset:
305 r->value.number = rp->fragment_offset;
306 break;
307 case NETFLOW_hop:
308 if (rp->set & NETFLOW_SET_hopv6)
309 {
310 r->value.buffer.data = rp->hopv6;
311 r->value.buffer.size = sizeof(rp->hopv6);
312 r->type = gp->type_ipv6addr;
313 }
314 else
315 {
316 r->value.number = rp->hopv4;
317 r->type = gp->type_ipv4addr;
318 }
319 break;
320 case NETFLOW_hopv4:
321 r->value.number = rp->hopv4;
322 break;
323 case NETFLOW_hopv6:
324 r->value.buffer.data = rp->hopv6;
325 r->value.buffer.size = sizeof(rp->hopv6);
326 break;
327 case NETFLOW_ident:
328 r->value.number = rp->ident;
329 break;
330 case NETFLOW_icmp_type:
331 r->value.number = rp->icmp_type;
332 break;
333 case NETFLOW_if_desc:
334 r->value.string.size = strlen(r->value.string.data = (char*)rp->if_desc);
335 break;
336 case NETFLOW_if_name:
337 r->value.string.size = strlen(r->value.string.data = (char*)rp->if_name);
338 break;
339 case NETFLOW_in_bytes:
340 r->value.number = rp->in_bytes;
341 break;
342 case NETFLOW_in_dst_mac:
343 r->value.number = rp->in_dst_mac;
344 break;
345 case NETFLOW_in_permanent_bytes:
346 r->value.number = rp->in_permanent_bytes;
347 break;
348 case NETFLOW_in_permanent_packets:
349 r->value.number = rp->in_permanent_packets;
350 break;
351 case NETFLOW_in_packets:
352 r->value.number = rp->in_packets ? rp->in_packets : rp->packets;
353 break;
354 case NETFLOW_in_src_mac:
355 r->value.number = rp->in_src_mac;
356 break;
357 case NETFLOW_input_snmp:
358 r->value.number = rp->input_snmp ? rp->input_snmp : rp->input;
359 break;
360 case NETFLOW_ip_protocol_version:
361 r->value.number = rp->ip_protocol_version;
362 break;
363 case NETFLOW_last:
364 r->value.number = rp->last;
365 break;
366 case NETFLOW_max_packet_length:
367 r->value.number = rp->max_packet_length;
368 break;
369 case NETFLOW_max_ttl:
370 r->value.number = rp->max_ttl;
371 break;
372 case NETFLOW_min_packet_length:
373 r->value.number = rp->min_packet_length;
374 break;
375 case NETFLOW_min_ttl:
376 r->value.number = rp->min_ttl;
377 break;
378 case NETFLOW_mpls_label_1:
379 r->value.number = rp->mpls_label_1;
380 break;
381 case NETFLOW_mpls_label_2:
382 r->value.number = rp->mpls_label_2;
383 break;
384 case NETFLOW_mpls_label_3:
385 r->value.number = rp->mpls_label_3;
386 break;
387 case NETFLOW_mpls_label_4:
388 r->value.number = rp->mpls_label_4;
389 break;
390 case NETFLOW_mpls_label_5:
391 r->value.number = rp->mpls_label_5;
392 break;
393 case NETFLOW_mpls_label_6:
394 r->value.number = rp->mpls_label_6;
395 break;
396 case NETFLOW_mpls_label_7:
397 r->value.number = rp->mpls_label_7;
398 break;
399 case NETFLOW_mpls_label_8:
400 r->value.number = rp->mpls_label_8;
401 break;
402 case NETFLOW_mpls_label_9:
403 r->value.number = rp->mpls_label_9;
404 break;
405 case NETFLOW_mpls_label_10:
406 r->value.number = rp->mpls_label_10;
407 break;
408 case NETFLOW_mpls_top_label_class:
409 r->value.number = rp->mpls_top_label_class;
410 break;
411 case NETFLOW_mpls_top_label_type:
412 r->value.number = rp->mpls_top_label_type;
413 break;
414 case NETFLOW_mul_dst_bytes:
415 r->value.number = rp->mul_dst_bytes;
416 break;
417 case NETFLOW_mul_dst_packets:
418 r->value.number = rp->mul_dst_packets;
419 break;
420 case NETFLOW_mul_igmp_type:
421 r->value.number = rp->mul_igmp_type;
422 break;
423 case NETFLOW_nsec:
424 r->value.number = rp->nsec;
425 break;
426 case NETFLOW_option_headers:
427 r->value.number = rp->option_headers;
428 break;
429 case NETFLOW_out_bytes:
430 r->value.number = rp->out_bytes;
431 break;
432 case NETFLOW_out_dst_mac:
433 r->value.number = rp->out_dst_mac;
434 break;
435 case NETFLOW_out_packets:
436 r->value.number = rp->out_packets ? rp->out_packets : rp->packets;
437 break;
438 case NETFLOW_out_src_mac:
439 r->value.number = rp->out_src_mac;
440 break;
441 case NETFLOW_output_snmp:
442 r->value.number = rp->output_snmp ? rp->output_snmp : rp->output;
443 break;
444 case NETFLOW_packets:
445 r->value.number = rp->packets ? rp->packets : rp->out_packets ? rp->out_packets : rp->in_packets;
446 break;
447 case NETFLOW_protocol:
448 r->value.number = rp->protocol;
449 break;
450 case NETFLOW_router_sc:
451 if (rp->set & NETFLOW_SET_router_scv6)
452 {
453 r->value.buffer.data = rp->router_scv6;
454 r->value.buffer.size = sizeof(rp->router_scv6);
455 r->type = gp->type_ipv6addr;
456 }
457 else
458 {
459 r->value.number = rp->router_scv4;
460 r->type = gp->type_ipv4addr;
461 }
462 break;
463 case NETFLOW_router_scv4:
464 r->value.number = rp->router_scv4;
465 break;
466 case NETFLOW_router_scv6:
467 r->value.buffer.data = rp->router_scv6;
468 r->value.buffer.size = sizeof(rp->router_scv6);
469 break;
470 case NETFLOW_sampler_algorithm:
471 r->value.number = rp->sampler_algorithm;
472 break;
473 case NETFLOW_sampler_interval:
474 r->value.number = rp->sampler_interval;
475 break;
476 case NETFLOW_sampler_mode:
477 r->value.number = rp->sampler_mode;
478 break;
479 case NETFLOW_sampler_name:
480 r->value.string.size = strlen(r->value.string.data = (char*)rp->sampler_name);
481 break;
482 case NETFLOW_src_addr:
483 if (rp->set & NETFLOW_SET_src_addrv6)
484 {
485 r->value.buffer.data = rp->src_addrv6;
486 r->value.buffer.size = sizeof(rp->src_addrv6) - 1;
487 r->type = gp->type_ipv6addr;
488 }
489 else
490 {
491 r->value.number = rp->src_addrv4;
492 r->type = gp->type_ipv4addr;
493 }
494 break;
495 case NETFLOW_src_addrv4:
496 r->value.number = rp->src_addrv4;
497 break;
498 case NETFLOW_src_addrv6:
499 r->value.buffer.data = rp->src_addrv6;
500 r->value.buffer.size = sizeof(rp->src_addrv6) - 1;
501 break;
502 case NETFLOW_src_as:
503 r->value.number = rp->src_as16 ? rp->src_as16 : rp->src_as32;
504 break;
505 case NETFLOW_src_as16:
506 r->value.number = rp->src_as16;
507 break;
508 case NETFLOW_src_as32:
509 r->value.number = rp->src_as32;
510 break;
511 case NETFLOW_src_mask:
512 r->value.number = (rp->set & NETFLOW_SET_src_addrv6) ? rp->src_addrv6[IP6BITS] : rp->src_maskv4;
513 break;
514 case NETFLOW_src_maskv4:
515 r->value.number = rp->src_maskv4;
516 break;
517 case NETFLOW_src_maskv6:
518 r->value.number = rp->src_addrv6[IP6BITS];
519 break;
520 case NETFLOW_src_port:
521 r->value.number = rp->src_port;
522 break;
523 case NETFLOW_src_prefix:
524 if (rp->set & NETFLOW_SET_src_addrv6)
525 {
526 r->value.buffer.data = rp->src_addrv6;
527 r->value.buffer.size = sizeof(rp->src_addrv6);
528 r->type = gp->type_ipv6prefix;
529 }
530 else
531 {
532 r->value.number = (Cxnumber_t)rp->src_addrv4 * 64 + rp->src_maskv4;
533 r->type = gp->type_ipv4prefix;
534 }
535 break;
536 case NETFLOW_src_prefixv4:
537 r->value.number = (Cxnumber_t)rp->src_addrv4 * 64 + rp->src_maskv4;
538 break;
539 case NETFLOW_src_prefixv6:
540 r->value.buffer.data = rp->src_addrv6;
541 r->value.buffer.size = sizeof(rp->src_addrv6);
542 break;
543 case NETFLOW_src_tos:
544 r->value.number = rp->src_tos;
545 break;
546 case NETFLOW_src_vlan:
547 r->value.number = rp->src_vlan;
548 break;
549 case NETFLOW_start:
550 #if _typ_int64_t
551 r->value.number = (int64_t)rp->start; /* ms cc requires signed */
552 #else
553 r->value.number = rp->start;
554 #endif
555 break;
556 case NETFLOW_tcp_flags:
557 r->value.number = rp->tcp_flags;
558 break;
559 case NETFLOW_tcp_misseq_cnt:
560 r->value.number = rp->tcp_misseq_cnt;
561 break;
562 case NETFLOW_tcp_retx_cnt:
563 r->value.number = rp->tcp_retx_cnt;
564 break;
565 case NETFLOW_tcp_retx_secs:
566 r->value.number = rp->tcp_retx_secs;
567 break;
568 case NETFLOW_time:
569 r->value.number = rp->time;
570 break;
571 case NETFLOW_tos:
572 r->value.number = rp->src_tos;
573 break;
574 case NETFLOW_total_bytes_exp:
575 r->value.number = rp->total_bytes_exp;
576 break;
577 case NETFLOW_total_flows_exp:
578 r->value.number = rp->total_flows_exp;
579 break;
580 case NETFLOW_total_packets_exp:
581 r->value.number = rp->total_packets_exp;
582 break;
583 case NETFLOW_uptime:
584 r->value.number = rp->uptime;
585 break;
586 case NETFLOW_vendor_43:
587 r->value.number = rp->vendor_43;
588 break;
589 case NETFLOW_vendor_51:
590 r->value.number = rp->vendor_51;
591 break;
592 case NETFLOW_vendor_65:
593 r->value.number = rp->vendor_65;
594 break;
595 case NETFLOW_vendor_66:
596 r->value.number = rp->vendor_66;
597 break;
598 case NETFLOW_vendor_67:
599 r->value.number = rp->vendor_67;
600 break;
601 case NETFLOW_vendor_68:
602 r->value.number = rp->vendor_68;
603 break;
604 case NETFLOW_vendor_69:
605 r->value.number = rp->vendor_69;
606 break;
607 case NETFLOW_vendor_87:
608 r->value.number = rp->vendor_87;
609 break;
610 case NETFLOW_version:
611 r->value.number = rp->version;
612 break;
613 default:
614 if (disc->errorf)
615 (*disc->errorf)(cx, disc, ERROR_PANIC, "%s: variable index %d not implemented", vp->name, vp->index);
616 return -1;
617 }
618 return 0;
619 }
620
621 static Cxcallout_t local_callouts[] =
622 {
623 CXC(CX_GET, "void", "void", op_get, 0)
624 };
625
626 /*
627 * methf
628 */
629
630 extern Dsslib_t dss_lib_netflow;
631
632 static Dssmeth_t*
netflowmeth(const char * name,const char * options,const char * schema,Dssdisc_t * disc,Dssmeth_t * meth)633 netflowmeth(const char* name, const char* options, const char* schema, Dssdisc_t* disc, Dssmeth_t* meth)
634 {
635 Dssformat_t* fp;
636 char* s;
637 int i;
638
639 for (fp = netflow_formats; fp; fp = fp->next)
640 dtinsert(meth->formats, fp);
641 for (i = 0; i < elementsof(local_callouts); i++)
642 if (cxaddcallout(meth->cx, &local_callouts[i], disc))
643 return 0;
644 for (i = 0; fields[i].name; i++)
645 if (cxaddvariable(meth->cx, &fields[i], disc))
646 return 0;
647 if (options)
648 {
649 if (dssoptlib(meth->cx->buf, &dss_lib_netflow, NiL, disc))
650 return 0;
651 s = sfstruse(meth->cx->buf);
652 for (;;)
653 {
654 switch (optstr(options, s))
655 {
656 case '?':
657 if (disc->errorf)
658 (*disc->errorf)(NiL, disc, ERROR_USAGE|4, "%s", opt_info.arg);
659 return 0;
660 case ':':
661 if (disc->errorf)
662 (*disc->errorf)(NiL, disc, 2, "%s", opt_info.arg);
663 return 0;
664 }
665 break;
666 }
667 }
668 return meth;
669 }
670
671 #define BUFFER(n,f) { offsetof(Netflow_t,n), sizeof(flow->n), NETFLOW_BUFFER, f }
672 #define NUMBER(n,f) { offsetof(Netflow_t,n), sizeof(flow->n), NETFLOW_NUMBER, f }
673
674 static Netflow_t* flow;
675
676 /*
677 * NOTE: template.field[] order, NETFLOW_* and Netflow_t must all match
678 */
679
680 static const Netflow_template_t template =
681 {
682 0,
683 0,
684 0,
685 0,
686 0,
687 0,
688 {
689 NUMBER(in_bytes, 0),
690 NUMBER(in_packets, 0),
691 NUMBER(flows, 0),
692 NUMBER(protocol, 0),
693 NUMBER(src_tos, 0),
694 NUMBER(tcp_flags, 0),
695 NUMBER(src_port, 0),
696 NUMBER(src_addrv4, NETFLOW_SET_src_addrv4),
697 NUMBER(src_maskv4, 0),
698 NUMBER(input_snmp, 0),
699 NUMBER(dst_port, 0),
700 NUMBER(dst_addrv4, NETFLOW_SET_dst_addrv4),
701 NUMBER(dst_maskv4, 0),
702 NUMBER(output_snmp, 0),
703 NUMBER(hopv4, NETFLOW_SET_hopv4),
704 NUMBER(src_as16, 0),
705 NUMBER(dst_as16, 0),
706 NUMBER(bgp_hopv4, NETFLOW_SET_bgp_hopv4),
707 NUMBER(mul_dst_packets, 0),
708 NUMBER(mul_dst_bytes, 0),
709 NUMBER(last, 0),
710 NUMBER(first, 0),
711 NUMBER(out_bytes, 0),
712 NUMBER(out_packets, 0),
713 NUMBER(min_packet_length, 0),
714 NUMBER(max_packet_length, 0),
715 BUFFER(src_addrv6, NETFLOW_SET_src_addrv6),
716 BUFFER(dst_addrv6, NETFLOW_SET_dst_addrv6),
717 NUMBER(src_maskv6, 0),
718 NUMBER(dst_maskv6, 0),
719 NUMBER(flow_label, 0),
720 NUMBER(icmp_type, 0),
721 NUMBER(mul_igmp_type, 0),
722 NUMBER(sampler_interval, 0),
723 NUMBER(sampler_algorithm, 0),
724 NUMBER(flow_active_timeout, 0),
725 NUMBER(flow_inactive_timeout, 0),
726 NUMBER(engine_type, 0),
727 NUMBER(engine_id, 0),
728 NUMBER(total_bytes_exp, 0),
729 NUMBER(total_packets_exp, 0),
730 NUMBER(total_flows_exp, 0),
731 BUFFER(vendor_43, 0),
732 NUMBER(src_prefixv4, NETFLOW_SET_src_addrv4),
733 NUMBER(dst_prefixv4, NETFLOW_SET_dst_addrv4),
734 NUMBER(mpls_top_label_type, 0),
735 NUMBER(mpls_top_label_class, 0),
736 NUMBER(sampler_id, 0),
737 NUMBER(sampler_mode, 0),
738 NUMBER(sampler_random_interval, 0),
739 BUFFER(vendor_51, 0),
740 NUMBER(min_ttl, 0),
741 NUMBER(max_ttl, 0),
742 NUMBER(ident, 0),
743 NUMBER(dst_tos, 0),
744 NUMBER(in_src_mac, 0),
745 NUMBER(out_dst_mac, 0),
746 NUMBER(src_vlan, 0),
747 NUMBER(dst_vlan, 0),
748 NUMBER(ip_protocol_version, 0),
749 NUMBER(direction, 0),
750 BUFFER(hopv6, NETFLOW_SET_hopv6),
751 BUFFER(bgp_hopv6, NETFLOW_SET_bgp_hopv6),
752 NUMBER(option_headers, 0),
753 BUFFER(vendor_65, 0),
754 BUFFER(vendor_66, 0),
755 BUFFER(vendor_67, 0),
756 BUFFER(vendor_68, 0),
757 BUFFER(vendor_69, 0),
758 NUMBER(mpls_label_1, 0),
759 NUMBER(mpls_label_2, 0),
760 NUMBER(mpls_label_3, 0),
761 NUMBER(mpls_label_4, 0),
762 NUMBER(mpls_label_5, 0),
763 NUMBER(mpls_label_6, 0),
764 NUMBER(mpls_label_7, 0),
765 NUMBER(mpls_label_8, 0),
766 NUMBER(mpls_label_9, 0),
767 NUMBER(mpls_label_10, 0),
768 NUMBER(in_dst_mac, 0),
769 NUMBER(out_src_mac, 0),
770 BUFFER(if_name, 0),
771 BUFFER(if_desc, 0),
772 BUFFER(sampler_name, 0),
773 NUMBER(in_permanent_bytes, 0),
774 NUMBER(in_permanent_packets, 0),
775 BUFFER(vendor_87, 0),
776 NUMBER(fragment_offset, 0),
777 NUMBER(forwarding_status, 0),
778 }
779 };
780
781 /*
782 * openf
783 */
784
785 static int
netflowopen(Dss_t * dss,Dssdisc_t * disc)786 netflowopen(Dss_t* dss, Dssdisc_t* disc)
787 {
788 Netflow_method_t* flow;
789
790 if (!(flow = vmnewof(dss->vm, 0, Netflow_method_t, 1, 0)) ||
791 !(flow->type_ipv4addr = cxtype(dss->cx, "ipv4addr_t", disc)) ||
792 !(flow->type_ipv4prefix = cxtype(dss->cx, "ipv4prefix_t", disc)) ||
793 !(flow->type_ipv6addr = cxtype(dss->cx, "ipv6addr_t", disc)) ||
794 !(flow->type_ipv6prefix = cxtype(dss->cx, "ipv6prefix_t", disc)) ||
795 !(flow->tmp = sfstropen()))
796 {
797 if (flow)
798 vmfree(dss->vm, flow);
799 if (disc->errorf)
800 (*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
801 return -1;
802 }
803 flow->base = (Netflow_template_t*)&template;
804 dss->data = flow;
805 return 0;
806 }
807
808 static const char* libraries[] = { "time_t", "ip_t", 0 };
809
810 static Dssmeth_t method =
811 {
812 "netflow",
813 "Cisco router netflow dump data",
814 CXH,
815 netflowmeth,
816 netflowopen,
817 0,
818 0,
819 "%(time:%+u%K)s %(prot)d %(src_addr)s:%(src_port)d %(dst_addr)s:%(dst_port)d %(hop)s"
820 };
821
822 Dsslib_t dss_lib_netflow =
823 {
824 "netflow",
825 "netflow method"
826 "[-1ls5Pp0?\n@(#)$Id: dss netflow method (AT&T Research) 2010-02-02 $\n]"
827 USAGE_LICENSE,
828 CXH,
829 &libraries[0],
830 &method,
831 };
832