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