Branch data Line data Source code
1 : : /* Copyright (c) 2002-2009 InMon Corp. Licensed under the terms of either the
2 : : * Sun Industry Standards Source License 1.1, that is available at:
3 : : * http://host-sflow.sourceforge.net/sissl.html
4 : : * or the InMon sFlow License, that is available at:
5 : : * http://www.inmon.com/technology/sflowlicense.txt
6 : : */
7 : :
8 : : #ifndef __CHECKER__ /* Don't run sparse on anything in this file. */
9 : :
10 : : #include <assert.h>
11 : : #include "sflow_api.h"
12 : :
13 : : static void resetSampleCollector(SFLReceiver *receiver);
14 : : static void sendSample(SFLReceiver *receiver);
15 : : static void sflError(SFLReceiver *receiver, char *errm);
16 : : inline static void putNet32(SFLReceiver *receiver, u_int32_t val);
17 : : inline static void putAddress(SFLReceiver *receiver, SFLAddress *addr);
18 : : #ifdef SFLOW_DO_SOCKET
19 : : static void initSocket(SFLReceiver *receiver);
20 : : #endif
21 : :
22 : : /*_________________--------------------------__________________
23 : : _________________ sfl_receiver_init __________________
24 : : -----------------__________________________------------------
25 : : */
26 : :
27 : 6 : void sfl_receiver_init(SFLReceiver *receiver, SFLAgent *agent)
28 : : {
29 : : /* first clear everything */
30 : 6 : memset(receiver, 0, sizeof(*receiver));
31 : :
32 : : /* now copy in the parameters */
33 : 6 : receiver->agent = agent;
34 : :
35 : : /* set defaults */
36 : 6 : receiver->sFlowRcvrMaximumDatagramSize = SFL_DEFAULT_DATAGRAM_SIZE;
37 : 6 : receiver->sFlowRcvrPort = SFL_DEFAULT_COLLECTOR_PORT;
38 : :
39 : : #ifdef SFLOW_DO_SOCKET
40 : : /* initialize the socket address */
41 : : initSocket(receiver);
42 : : #endif
43 : :
44 : : /* preset some of the header fields */
45 : 6 : receiver->sampleCollector.datap = receiver->sampleCollector.data;
46 : 6 : putNet32(receiver, SFLDATAGRAM_VERSION5);
47 : 6 : putAddress(receiver, &agent->myIP);
48 : 6 : putNet32(receiver, agent->subId);
49 : :
50 : : /* prepare to receive the first sample */
51 : 6 : resetSampleCollector(receiver);
52 : 6 : }
53 : :
54 : : /*_________________---------------------------__________________
55 : : _________________ reset __________________
56 : : -----------------___________________________------------------
57 : :
58 : : called on timeout, or when owner string is cleared
59 : : */
60 : :
61 : 0 : static void reset(SFLReceiver *receiver) {
62 : : // ask agent to tell samplers and pollers to stop sending samples
63 : 0 : sfl_agent_resetReceiver(receiver->agent, receiver);
64 : : // reinitialize
65 : 0 : sfl_receiver_init(receiver, receiver->agent);
66 : 0 : }
67 : :
68 : : #ifdef SFLOW_DO_SOCKET
69 : : /*_________________---------------------------__________________
70 : : _________________ initSocket __________________
71 : : -----------------___________________________------------------
72 : : */
73 : :
74 : : static void initSocket(SFLReceiver *receiver) {
75 : : if(receiver->sFlowRcvrAddress.type == SFLADDRESSTYPE_IP_V6) {
76 : : struct sockaddr_in6 *sa6 = &receiver->receiver6;
77 : : sa6->sin6_port = htons((u_int16_t)receiver->sFlowRcvrPort);
78 : : sa6->sin6_family = AF_INET6;
79 : : sa6->sin6_addr = receiver->sFlowRcvrAddress.address.ip_v6;
80 : : }
81 : : else {
82 : : struct sockaddr_in *sa4 = &receiver->receiver4;
83 : : sa4->sin_port = htons((u_int16_t)receiver->sFlowRcvrPort);
84 : : sa4->sin_family = AF_INET;
85 : : sa4->sin_addr = receiver->sFlowRcvrAddress.address.ip_v4;
86 : : }
87 : : }
88 : : #endif
89 : :
90 : : /*_________________----------------------------------------_____________
91 : : _________________ MIB Vars _____________
92 : : -----------------________________________________________-------------
93 : : */
94 : :
95 : 0 : char * sfl_receiver_get_sFlowRcvrOwner(SFLReceiver *receiver) {
96 : 0 : return receiver->sFlowRcvrOwner;
97 : : }
98 : 6 : void sfl_receiver_set_sFlowRcvrOwner(SFLReceiver *receiver, char *sFlowRcvrOwner) {
99 : 6 : receiver->sFlowRcvrOwner = sFlowRcvrOwner;
100 [ + - ][ - + ]: 6 : if(sFlowRcvrOwner == NULL || sFlowRcvrOwner[0] == '\0') {
101 : : // reset condition! owner string was cleared
102 : 0 : reset(receiver);
103 : : }
104 : 6 : }
105 : 0 : time_t sfl_receiver_get_sFlowRcvrTimeout(SFLReceiver *receiver) {
106 : 0 : return receiver->sFlowRcvrTimeout;
107 : : }
108 : 6 : void sfl_receiver_set_sFlowRcvrTimeout(SFLReceiver *receiver, time_t sFlowRcvrTimeout) {
109 : 6 : receiver->sFlowRcvrTimeout =sFlowRcvrTimeout;
110 : 6 : }
111 : 0 : u_int32_t sfl_receiver_get_sFlowRcvrMaximumDatagramSize(SFLReceiver *receiver) {
112 : 0 : return receiver->sFlowRcvrMaximumDatagramSize;
113 : : }
114 : 0 : void sfl_receiver_set_sFlowRcvrMaximumDatagramSize(SFLReceiver *receiver, u_int32_t sFlowRcvrMaximumDatagramSize) {
115 : 0 : u_int32_t mdz = sFlowRcvrMaximumDatagramSize;
116 [ # # ]: 0 : if(mdz < SFL_MIN_DATAGRAM_SIZE) mdz = SFL_MIN_DATAGRAM_SIZE;
117 : 0 : receiver->sFlowRcvrMaximumDatagramSize = mdz;
118 : 0 : }
119 : 0 : SFLAddress *sfl_receiver_get_sFlowRcvrAddress(SFLReceiver *receiver) {
120 : 0 : return &receiver->sFlowRcvrAddress;
121 : : }
122 : 0 : void sfl_receiver_set_sFlowRcvrAddress(SFLReceiver *receiver, SFLAddress *sFlowRcvrAddress) {
123 [ # # ]: 0 : if(sFlowRcvrAddress) receiver->sFlowRcvrAddress = *sFlowRcvrAddress; // structure copy
124 : : #ifdef SFLOW_DO_SOCKET
125 : : initSocket(receiver);
126 : : #endif
127 : 0 : }
128 : 0 : u_int32_t sfl_receiver_get_sFlowRcvrPort(SFLReceiver *receiver) {
129 : 0 : return receiver->sFlowRcvrPort;
130 : : }
131 : 0 : void sfl_receiver_set_sFlowRcvrPort(SFLReceiver *receiver, u_int32_t sFlowRcvrPort) {
132 : 0 : receiver->sFlowRcvrPort = sFlowRcvrPort;
133 : : // update the socket structure
134 : : #ifdef SFLOW_DO_SOCKET
135 : : initSocket(receiver);
136 : : #endif
137 : 0 : }
138 : :
139 : : /*_________________---------------------------__________________
140 : : _________________ sfl_receiver_tick __________________
141 : : -----------------___________________________------------------
142 : : */
143 : :
144 : 15 : void sfl_receiver_tick(SFLReceiver *receiver, time_t now)
145 : : {
146 : : // if there are any samples to send, flush them now
147 [ + + ]: 15 : if(receiver->sampleCollector.numSamples > 0) sendSample(receiver);
148 : : // check the timeout
149 [ + - ][ - + ]: 15 : if(receiver->sFlowRcvrTimeout && (u_int32_t)receiver->sFlowRcvrTimeout != 0xFFFFFFFF) {
150 : : // count down one tick and reset if we reach 0
151 [ # # ]: 0 : if(--receiver->sFlowRcvrTimeout == 0) reset(receiver);
152 : : }
153 : 15 : }
154 : :
155 : : /*_________________-----------------------------__________________
156 : : _________________ receiver write utilities __________________
157 : : -----------------_____________________________------------------
158 : : */
159 : :
160 : 14 : inline static void put32(SFLReceiver *receiver, u_int32_t val)
161 : : {
162 : 14 : *receiver->sampleCollector.datap++ = val;
163 : 14 : }
164 : :
165 : 915 : inline static void putNet32(SFLReceiver *receiver, u_int32_t val)
166 : : {
167 : 915 : *receiver->sampleCollector.datap++ = htonl(val);
168 : 915 : }
169 : :
170 : 4 : inline static void putNet32_run(SFLReceiver *receiver, void *obj, size_t quads)
171 : : {
172 : 4 : u_int32_t *from = (u_int32_t *)obj;
173 [ + + ]: 7 : while(quads--) putNet32(receiver, *from++);
174 : 4 : }
175 : :
176 : 68 : inline static void putNet64(SFLReceiver *receiver, u_int64_t val64)
177 : : {
178 : 68 : u_int32_t *firstQuadPtr = receiver->sampleCollector.datap;
179 : : // first copy the bytes in
180 : 68 : memcpy((u_char *)firstQuadPtr, &val64, 8);
181 [ + - ]: 68 : if(htonl(1) != 1) {
182 : : // swap the bytes, and reverse the quads too
183 : 68 : u_int32_t tmp = *receiver->sampleCollector.datap++;
184 : 68 : *firstQuadPtr = htonl(*receiver->sampleCollector.datap);
185 : 68 : *receiver->sampleCollector.datap++ = htonl(tmp);
186 : : }
187 : 0 : else receiver->sampleCollector.datap += 2;
188 : 68 : }
189 : :
190 : 0 : inline static void put128(SFLReceiver *receiver, u_char *val)
191 : : {
192 : 0 : memcpy(receiver->sampleCollector.datap, val, 16);
193 : 0 : receiver->sampleCollector.datap += 4;
194 : 0 : }
195 : :
196 : 14 : inline static void putString(SFLReceiver *receiver, SFLString *s)
197 : : {
198 : 14 : putNet32(receiver, s->len);
199 : 14 : memcpy(receiver->sampleCollector.datap, s->str, s->len);
200 : 14 : receiver->sampleCollector.datap += (s->len + 3) / 4; /* pad to 4-byte boundary */
201 [ + - ]: 14 : if ((s->len % 4) != 0){
202 : 14 : u_int8_t padding = 4 - (s->len % 4);
203 : 14 : memset(((u_int8_t*)receiver->sampleCollector.datap)-padding, 0, padding);
204 : : }
205 : 14 : }
206 : :
207 : 14 : inline static u_int32_t stringEncodingLength(SFLString *s) {
208 : : // answer in bytes, so remember to mulitply by 4 after rounding up to nearest 4-byte boundary
209 : 14 : return 4 + (((s->len + 3) / 4) * 4);
210 : : }
211 : :
212 : 8 : inline static void putAddress(SFLReceiver *receiver, SFLAddress *addr)
213 : : {
214 : : // encode unspecified addresses as IPV4:0.0.0.0 - or should we flag this as an error?
215 [ + + ]: 8 : if(addr->type == 0) {
216 : 2 : putNet32(receiver, SFLADDRESSTYPE_IP_V4);
217 : 2 : put32(receiver, 0);
218 : : }
219 : : else {
220 : 6 : putNet32(receiver, addr->type);
221 [ + - ]: 6 : if(addr->type == SFLADDRESSTYPE_IP_V4) put32(receiver, addr->address.ip_v4.addr);
222 : 0 : else put128(receiver, addr->address.ip_v6.addr);
223 : : }
224 : 8 : }
225 : :
226 : 2 : inline static u_int32_t addressEncodingLength(SFLAddress *addr) {
227 [ - + ]: 2 : return (addr->type == SFLADDRESSTYPE_IP_V6) ? 20 : 8; // type + address (unspecified == IPV4)
228 : : }
229 : :
230 : 4 : inline static void putMACAddress(SFLReceiver *receiver,
231 : : const struct eth_addr mac)
232 : : {
233 : 4 : memcpy(receiver->sampleCollector.datap, &mac, 6);
234 : 4 : receiver->sampleCollector.datap += 2;
235 : 4 : }
236 : :
237 : 14 : inline static void putSwitch(SFLReceiver *receiver, SFLExtended_switch *sw)
238 : : {
239 : 14 : putNet32(receiver, sw->src_vlan);
240 : 14 : putNet32(receiver, sw->src_priority);
241 : 14 : putNet32(receiver, sw->dst_vlan);
242 : 14 : putNet32(receiver, sw->dst_priority);
243 : 14 : }
244 : :
245 : 0 : inline static void putRouter(SFLReceiver *receiver, SFLExtended_router *router)
246 : : {
247 : 0 : putAddress(receiver, &router->nexthop);
248 : 0 : putNet32(receiver, router->src_mask);
249 : 0 : putNet32(receiver, router->dst_mask);
250 : 0 : }
251 : :
252 : 0 : inline static u_int32_t routerEncodingLength(SFLExtended_router *router) {
253 : 0 : return addressEncodingLength(&router->nexthop) + 8;
254 : : }
255 : :
256 : 0 : inline static void putGateway(SFLReceiver *receiver, SFLExtended_gateway *gw)
257 : : {
258 : 0 : putAddress(receiver, &gw->nexthop);
259 : 0 : putNet32(receiver, gw->as);
260 : 0 : putNet32(receiver, gw->src_as);
261 : 0 : putNet32(receiver, gw->src_peer_as);
262 : 0 : putNet32(receiver, gw->dst_as_path_segments);
263 : : {
264 : 0 : u_int32_t seg = 0;
265 [ # # ]: 0 : for(; seg < gw->dst_as_path_segments; seg++) {
266 : 0 : putNet32(receiver, gw->dst_as_path[seg].type);
267 : 0 : putNet32(receiver, gw->dst_as_path[seg].length);
268 : 0 : putNet32_run(receiver, gw->dst_as_path[seg].as.seq, gw->dst_as_path[seg].length);
269 : : }
270 : : }
271 : 0 : putNet32(receiver, gw->communities_length);
272 : 0 : putNet32_run(receiver, gw->communities, gw->communities_length);
273 : 0 : putNet32(receiver, gw->localpref);
274 : 0 : }
275 : :
276 : 0 : inline static u_int32_t gatewayEncodingLength(SFLExtended_gateway *gw) {
277 : 0 : u_int32_t elemSiz = addressEncodingLength(&gw->nexthop);
278 : 0 : u_int32_t seg = 0;
279 : 0 : elemSiz += 16; // as, src_as, src_peer_as, dst_as_path_segments
280 [ # # ]: 0 : for(; seg < gw->dst_as_path_segments; seg++) {
281 : 0 : elemSiz += 8; // type, length
282 : 0 : elemSiz += 4 * gw->dst_as_path[seg].length; // set/seq bytes
283 : : }
284 : 0 : elemSiz += 4; // communities_length
285 : 0 : elemSiz += 4 * gw->communities_length; // communities
286 : 0 : elemSiz += 4; // localpref
287 : 0 : return elemSiz;
288 : : }
289 : :
290 : 0 : inline static void putUser(SFLReceiver *receiver, SFLExtended_user *user)
291 : : {
292 : 0 : putNet32(receiver, user->src_charset);
293 : 0 : putString(receiver, &user->src_user);
294 : 0 : putNet32(receiver, user->dst_charset);
295 : 0 : putString(receiver, &user->dst_user);
296 : 0 : }
297 : :
298 : 0 : inline static u_int32_t userEncodingLength(SFLExtended_user *user) {
299 : 0 : return 4
300 : 0 : + stringEncodingLength(&user->src_user)
301 : : + 4
302 : 0 : + stringEncodingLength(&user->dst_user);
303 : : }
304 : :
305 : 0 : inline static void putUrl(SFLReceiver *receiver, SFLExtended_url *url)
306 : : {
307 : 0 : putNet32(receiver, url->direction);
308 : 0 : putString(receiver, &url->url);
309 : 0 : putString(receiver, &url->host);
310 : 0 : }
311 : :
312 : 0 : inline static u_int32_t urlEncodingLength(SFLExtended_url *url) {
313 : 0 : return 4
314 : 0 : + stringEncodingLength(&url->url)
315 : 0 : + stringEncodingLength(&url->host);
316 : : }
317 : :
318 : 4 : inline static void putLabelStack(SFLReceiver *receiver, SFLLabelStack *labelStack)
319 : : {
320 : 4 : putNet32(receiver, labelStack->depth);
321 : 4 : putNet32_run(receiver, labelStack->stack, labelStack->depth);
322 : 4 : }
323 : :
324 : 4 : inline static u_int32_t labelStackEncodingLength(SFLLabelStack *labelStack) {
325 : 4 : return 4 + (4 * labelStack->depth);
326 : : }
327 : :
328 : 2 : inline static void putMpls(SFLReceiver *receiver, SFLExtended_mpls *mpls)
329 : : {
330 : 2 : putAddress(receiver, &mpls->nextHop);
331 : 2 : putLabelStack(receiver, &mpls->in_stack);
332 : 2 : putLabelStack(receiver, &mpls->out_stack);
333 : 2 : }
334 : :
335 : 2 : inline static u_int32_t mplsEncodingLength(SFLExtended_mpls *mpls) {
336 : 4 : return addressEncodingLength(&mpls->nextHop)
337 : 2 : + labelStackEncodingLength(&mpls->in_stack)
338 : 2 : + labelStackEncodingLength(&mpls->out_stack);
339 : : }
340 : :
341 : 0 : inline static void putNat(SFLReceiver *receiver, SFLExtended_nat *nat)
342 : : {
343 : 0 : putAddress(receiver, &nat->src);
344 : 0 : putAddress(receiver, &nat->dst);
345 : 0 : }
346 : :
347 : 0 : inline static u_int32_t natEncodingLength(SFLExtended_nat *nat) {
348 : 0 : return addressEncodingLength(&nat->src)
349 : 0 : + addressEncodingLength(&nat->dst);
350 : : }
351 : :
352 : 0 : inline static void putMplsTunnel(SFLReceiver *receiver, SFLExtended_mpls_tunnel *tunnel)
353 : : {
354 : 0 : putString(receiver, &tunnel->tunnel_lsp_name);
355 : 0 : putNet32(receiver, tunnel->tunnel_id);
356 : 0 : putNet32(receiver, tunnel->tunnel_cos);
357 : 0 : }
358 : :
359 : 0 : inline static u_int32_t mplsTunnelEncodingLength(SFLExtended_mpls_tunnel *tunnel) {
360 : 0 : return stringEncodingLength(&tunnel->tunnel_lsp_name) + 8;
361 : : }
362 : :
363 : 0 : inline static void putMplsVc(SFLReceiver *receiver, SFLExtended_mpls_vc *vc)
364 : : {
365 : 0 : putString(receiver, &vc->vc_instance_name);
366 : 0 : putNet32(receiver, vc->vll_vc_id);
367 : 0 : putNet32(receiver, vc->vc_label_cos);
368 : 0 : }
369 : :
370 : 0 : inline static u_int32_t mplsVcEncodingLength(SFLExtended_mpls_vc *vc) {
371 : 0 : return stringEncodingLength( &vc->vc_instance_name) + 8;
372 : : }
373 : :
374 : 0 : inline static void putMplsFtn(SFLReceiver *receiver, SFLExtended_mpls_FTN *ftn)
375 : : {
376 : 0 : putString(receiver, &ftn->mplsFTNDescr);
377 : 0 : putNet32(receiver, ftn->mplsFTNMask);
378 : 0 : }
379 : :
380 : 0 : inline static u_int32_t mplsFtnEncodingLength(SFLExtended_mpls_FTN *ftn) {
381 : 0 : return stringEncodingLength( &ftn->mplsFTNDescr) + 4;
382 : : }
383 : :
384 : 0 : inline static void putMplsLdpFec(SFLReceiver *receiver, SFLExtended_mpls_LDP_FEC *ldpfec)
385 : : {
386 : 0 : putNet32(receiver, ldpfec->mplsFecAddrPrefixLength);
387 : 0 : }
388 : :
389 : 0 : inline static u_int32_t mplsLdpFecEncodingLength(SFLExtended_mpls_LDP_FEC *ldpfec) {
390 : 0 : return 4;
391 : : }
392 : :
393 : 0 : inline static void putVlanTunnel(SFLReceiver *receiver, SFLExtended_vlan_tunnel *vlanTunnel)
394 : : {
395 : 0 : putLabelStack(receiver, &vlanTunnel->stack);
396 : 0 : }
397 : :
398 : 0 : inline static u_int32_t vlanTunnelEncodingLength(SFLExtended_vlan_tunnel *vlanTunnel) {
399 : 0 : return labelStackEncodingLength(&vlanTunnel->stack);
400 : : }
401 : :
402 : :
403 : 14 : inline static void putGenericCounters(SFLReceiver *receiver, SFLIf_counters *counters)
404 : : {
405 : 14 : putNet32(receiver, counters->ifIndex);
406 : 14 : putNet32(receiver, counters->ifType);
407 : 14 : putNet64(receiver, counters->ifSpeed);
408 : 14 : putNet32(receiver, counters->ifDirection);
409 : 14 : putNet32(receiver, counters->ifStatus);
410 : 14 : putNet64(receiver, counters->ifInOctets);
411 : 14 : putNet32(receiver, counters->ifInUcastPkts);
412 : 14 : putNet32(receiver, counters->ifInMulticastPkts);
413 : 14 : putNet32(receiver, counters->ifInBroadcastPkts);
414 : 14 : putNet32(receiver, counters->ifInDiscards);
415 : 14 : putNet32(receiver, counters->ifInErrors);
416 : 14 : putNet32(receiver, counters->ifInUnknownProtos);
417 : 14 : putNet64(receiver, counters->ifOutOctets);
418 : 14 : putNet32(receiver, counters->ifOutUcastPkts);
419 : 14 : putNet32(receiver, counters->ifOutMulticastPkts);
420 : 14 : putNet32(receiver, counters->ifOutBroadcastPkts);
421 : 14 : putNet32(receiver, counters->ifOutDiscards);
422 : 14 : putNet32(receiver, counters->ifOutErrors);
423 : 14 : putNet32(receiver, counters->ifPromiscuousMode);
424 : 14 : }
425 : :
426 : :
427 : : /*_________________-----------------------------__________________
428 : : _________________ computeFlowSampleSize __________________
429 : : -----------------_____________________________------------------
430 : : */
431 : :
432 : 14 : static int computeFlowSampleSize(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs)
433 : : {
434 : 14 : SFLFlow_sample_element *elem = fs->elements;
435 : : #ifdef SFL_USE_32BIT_INDEX
436 : : u_int siz = 52; /* tag, length, sequence_number, ds_class, ds_index, sampling_rate,
437 : : sample_pool, drops, inputFormat, input, outputFormat, output, number of elements */
438 : : #else
439 : 14 : u_int siz = 40; /* tag, length, sequence_number, source_id, sampling_rate,
440 : : sample_pool, drops, input, output, number of elements */
441 : : #endif
442 : :
443 : 14 : fs->num_elements = 0; /* we're going to count them again even if this was set by the client */
444 [ + + ]: 48 : for(; elem != NULL; elem = elem->nxt) {
445 : 34 : u_int elemSiz = 0;
446 : 34 : fs->num_elements++;
447 : 34 : siz += 8; /* tag, length */
448 [ + - - - : 34 : switch(elem->tag) {
+ - - - -
+ - - - -
- - + +
- ]
449 : : case SFLFLOW_HEADER:
450 : 14 : elemSiz = 16; /* header_protocol, frame_length, stripped, header_length */
451 : 14 : elemSiz += ((elem->flowType.header.header_length + 3) / 4) * 4; /* header, rounded up to nearest 4 bytes */
452 : 14 : break;
453 : 0 : case SFLFLOW_ETHERNET: elemSiz = sizeof(SFLSampled_ethernet); break;
454 : 0 : case SFLFLOW_IPV4: elemSiz = sizeof(SFLSampled_ipv4); break;
455 : 0 : case SFLFLOW_IPV6: elemSiz = sizeof(SFLSampled_ipv6); break;
456 : 14 : case SFLFLOW_EX_SWITCH: elemSiz = sizeof(SFLExtended_switch); break;
457 : 0 : case SFLFLOW_EX_ROUTER: elemSiz = routerEncodingLength(&elem->flowType.router); break;
458 : 0 : case SFLFLOW_EX_GATEWAY: elemSiz = gatewayEncodingLength(&elem->flowType.gateway); break;
459 : 0 : case SFLFLOW_EX_USER: elemSiz = userEncodingLength(&elem->flowType.user); break;
460 : 0 : case SFLFLOW_EX_URL: elemSiz = urlEncodingLength(&elem->flowType.url); break;
461 : 2 : case SFLFLOW_EX_MPLS: elemSiz = mplsEncodingLength(&elem->flowType.mpls); break;
462 : 0 : case SFLFLOW_EX_NAT: elemSiz = natEncodingLength(&elem->flowType.nat); break;
463 : 0 : case SFLFLOW_EX_MPLS_TUNNEL: elemSiz = mplsTunnelEncodingLength(&elem->flowType.mpls_tunnel); break;
464 : 0 : case SFLFLOW_EX_MPLS_VC: elemSiz = mplsVcEncodingLength(&elem->flowType.mpls_vc); break;
465 : 0 : case SFLFLOW_EX_MPLS_FTN: elemSiz = mplsFtnEncodingLength(&elem->flowType.mpls_ftn); break;
466 : 0 : case SFLFLOW_EX_MPLS_LDP_FEC: elemSiz = mplsLdpFecEncodingLength(&elem->flowType.mpls_ldp_fec); break;
467 : 0 : case SFLFLOW_EX_VLAN_TUNNEL: elemSiz = vlanTunnelEncodingLength(&elem->flowType.vlan_tunnel); break;
468 : : case SFLFLOW_EX_IPV4_TUNNEL_EGRESS:
469 : : case SFLFLOW_EX_IPV4_TUNNEL_INGRESS:
470 : 2 : elemSiz = sizeof(SFLSampled_ipv4);
471 : 2 : break;
472 : : case SFLFLOW_EX_VNI_EGRESS:
473 : : case SFLFLOW_EX_VNI_INGRESS:
474 : 2 : elemSiz = sizeof(SFLExtended_vni);
475 : 2 : break;
476 : : default:
477 : 0 : sflError(receiver, "unexpected packet_data_tag");
478 : 0 : return -1;
479 : : break;
480 : : }
481 : : // cache the element size, and accumulate it into the overall FlowSample size
482 : 34 : elem->length = elemSiz;
483 : 34 : siz += elemSiz;
484 : : }
485 : :
486 : 14 : return siz;
487 : : }
488 : :
489 : : /*_________________-------------------------------__________________
490 : : _________________ sfl_receiver_writeFlowSample __________________
491 : : -----------------_______________________________------------------
492 : : */
493 : :
494 : 14 : int sfl_receiver_writeFlowSample(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs)
495 : : {
496 : : int packedSize;
497 [ - + ]: 14 : if(fs == NULL) return -1;
498 [ - + ]: 14 : if((packedSize = computeFlowSampleSize(receiver, fs)) == -1) return -1;
499 : :
500 : : // check in case this one sample alone is too big for the datagram
501 : : // in fact - if it is even half as big then we should ditch it. Very
502 : : // important to avoid overruning the packet buffer.
503 [ - + ]: 14 : if(packedSize > (int)(receiver->sFlowRcvrMaximumDatagramSize / 2)) {
504 : 0 : sflError(receiver, "flow sample too big for datagram");
505 : 0 : return -1;
506 : : }
507 : :
508 : : // if the sample pkt is full enough so that this sample might put
509 : : // it over the limit, then we should send it now before going on.
510 [ - + ]: 14 : if((receiver->sampleCollector.pktlen + packedSize) >= receiver->sFlowRcvrMaximumDatagramSize)
511 : 0 : sendSample(receiver);
512 : :
513 : 14 : receiver->sampleCollector.numSamples++;
514 : :
515 : : #ifdef SFL_USE_32BIT_INDEX
516 : : putNet32(receiver, SFLFLOW_SAMPLE_EXPANDED);
517 : : #else
518 : 14 : putNet32(receiver, SFLFLOW_SAMPLE);
519 : : #endif
520 : :
521 : 14 : putNet32(receiver, packedSize - 8); // don't include tag and len
522 : 14 : putNet32(receiver, fs->sequence_number);
523 : :
524 : : #ifdef SFL_USE_32BIT_INDEX
525 : : putNet32(receiver, fs->ds_class);
526 : : putNet32(receiver, fs->ds_index);
527 : : #else
528 : 14 : putNet32(receiver, fs->source_id);
529 : : #endif
530 : :
531 : 14 : putNet32(receiver, fs->sampling_rate);
532 : 14 : putNet32(receiver, fs->sample_pool);
533 : 14 : putNet32(receiver, fs->drops);
534 : :
535 : : #ifdef SFL_USE_32BIT_INDEX
536 : : putNet32(receiver, fs->inputFormat);
537 : : putNet32(receiver, fs->input);
538 : : putNet32(receiver, fs->outputFormat);
539 : : putNet32(receiver, fs->output);
540 : : #else
541 : 14 : putNet32(receiver, fs->input);
542 : 14 : putNet32(receiver, fs->output);
543 : : #endif
544 : :
545 : 14 : putNet32(receiver, fs->num_elements);
546 : :
547 : : {
548 : 14 : SFLFlow_sample_element *elem = fs->elements;
549 [ + + ]: 48 : for(; elem != NULL; elem = elem->nxt) {
550 : :
551 : 34 : putNet32(receiver, elem->tag);
552 : 34 : putNet32(receiver, elem->length); // length cached in computeFlowSampleSize()
553 : :
554 [ + - + - : 34 : switch(elem->tag) {
+ - - - -
+ - - - -
- - + - ]
555 : : case SFLFLOW_HEADER:
556 : 14 : putNet32(receiver, elem->flowType.header.header_protocol);
557 : 14 : putNet32(receiver, elem->flowType.header.frame_length);
558 : 14 : putNet32(receiver, elem->flowType.header.stripped);
559 : 14 : putNet32(receiver, elem->flowType.header.header_length);
560 : : /* the header */
561 : 14 : memcpy(receiver->sampleCollector.datap, elem->flowType.header.header_bytes, elem->flowType.header.header_length);
562 : : /* round up to multiple of 4 to preserve alignment */
563 : 14 : receiver->sampleCollector.datap += ((elem->flowType.header.header_length + 3) / 4);
564 : 14 : break;
565 : : case SFLFLOW_ETHERNET:
566 : 0 : putNet32(receiver, elem->flowType.ethernet.eth_len);
567 : 0 : putMACAddress(receiver, elem->flowType.ethernet.src_mac);
568 : 0 : putMACAddress(receiver, elem->flowType.ethernet.dst_mac);
569 : 0 : putNet32(receiver, elem->flowType.ethernet.eth_type);
570 : 0 : break;
571 : : case SFLFLOW_IPV4:
572 : : case SFLFLOW_EX_IPV4_TUNNEL_EGRESS:
573 : : case SFLFLOW_EX_IPV4_TUNNEL_INGRESS:
574 : 2 : putNet32(receiver, elem->flowType.ipv4.length);
575 : 2 : putNet32(receiver, elem->flowType.ipv4.protocol);
576 : 2 : put32(receiver, elem->flowType.ipv4.src_ip.addr);
577 : 2 : put32(receiver, elem->flowType.ipv4.dst_ip.addr);
578 : 2 : putNet32(receiver, elem->flowType.ipv4.src_port);
579 : 2 : putNet32(receiver, elem->flowType.ipv4.dst_port);
580 : 2 : putNet32(receiver, elem->flowType.ipv4.tcp_flags);
581 : 2 : putNet32(receiver, elem->flowType.ipv4.tos);
582 : 2 : break;
583 : : case SFLFLOW_IPV6:
584 : 0 : putNet32(receiver, elem->flowType.ipv6.length);
585 : 0 : putNet32(receiver, elem->flowType.ipv6.protocol);
586 : 0 : put128(receiver, elem->flowType.ipv6.src_ip.addr);
587 : 0 : put128(receiver, elem->flowType.ipv6.dst_ip.addr);
588 : 0 : putNet32(receiver, elem->flowType.ipv6.src_port);
589 : 0 : putNet32(receiver, elem->flowType.ipv6.dst_port);
590 : 0 : putNet32(receiver, elem->flowType.ipv6.tcp_flags);
591 : 0 : putNet32(receiver, elem->flowType.ipv6.priority);
592 : 0 : break;
593 : 14 : case SFLFLOW_EX_SWITCH: putSwitch(receiver, &elem->flowType.sw); break;
594 : 0 : case SFLFLOW_EX_ROUTER: putRouter(receiver, &elem->flowType.router); break;
595 : 0 : case SFLFLOW_EX_GATEWAY: putGateway(receiver, &elem->flowType.gateway); break;
596 : 0 : case SFLFLOW_EX_USER: putUser(receiver, &elem->flowType.user); break;
597 : 0 : case SFLFLOW_EX_URL: putUrl(receiver, &elem->flowType.url); break;
598 : 2 : case SFLFLOW_EX_MPLS: putMpls(receiver, &elem->flowType.mpls); break;
599 : 0 : case SFLFLOW_EX_NAT: putNat(receiver, &elem->flowType.nat); break;
600 : 0 : case SFLFLOW_EX_MPLS_TUNNEL: putMplsTunnel(receiver, &elem->flowType.mpls_tunnel); break;
601 : 0 : case SFLFLOW_EX_MPLS_VC: putMplsVc(receiver, &elem->flowType.mpls_vc); break;
602 : 0 : case SFLFLOW_EX_MPLS_FTN: putMplsFtn(receiver, &elem->flowType.mpls_ftn); break;
603 : 0 : case SFLFLOW_EX_MPLS_LDP_FEC: putMplsLdpFec(receiver, &elem->flowType.mpls_ldp_fec); break;
604 : 0 : case SFLFLOW_EX_VLAN_TUNNEL: putVlanTunnel(receiver, &elem->flowType.vlan_tunnel); break;
605 : : case SFLFLOW_EX_VNI_EGRESS:
606 : : case SFLFLOW_EX_VNI_INGRESS:
607 : 2 : putNet32(receiver, elem->flowType.tunnel_vni.vni);
608 : 2 : break;
609 : :
610 : : default:
611 : 0 : sflError(receiver, "unexpected packet_data_tag");
612 : 0 : return -1;
613 : : break;
614 : : }
615 : : }
616 : : }
617 : :
618 : : // sanity check
619 [ - + ]: 14 : assert(((u_char *)receiver->sampleCollector.datap
620 : : - (u_char *)receiver->sampleCollector.data
621 : : - receiver->sampleCollector.pktlen) == (u_int32_t)packedSize);
622 : :
623 : : // update the pktlen
624 : 14 : receiver->sampleCollector.pktlen = (u_char *)receiver->sampleCollector.datap - (u_char *)receiver->sampleCollector.data;
625 : 14 : return packedSize;
626 : : }
627 : :
628 : : /*_________________-----------------------------__________________
629 : : _________________ computeCountersSampleSize __________________
630 : : -----------------_____________________________------------------
631 : : */
632 : :
633 : 20 : static int computeCountersSampleSize(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_TYPE *cs)
634 : : {
635 : 20 : SFLCounters_sample_element *elem = cs->elements;
636 : : #ifdef SFL_USE_32BIT_INDEX
637 : : u_int siz = 24; /* tag, length, sequence_number, ds_class, ds_index, number of elements */
638 : : #else
639 : 20 : u_int siz = 20; /* tag, length, sequence_number, source_id, number of elements */
640 : : #endif
641 : :
642 : 20 : cs->num_elements = 0; /* we're going to count them again even if this was set by the client */
643 [ + + ]: 76 : for(; elem != NULL; elem = elem->nxt) {
644 : 56 : u_int elemSiz = 0;
645 : 56 : cs->num_elements++;
646 : 56 : siz += 8; /* tag, length */
647 [ + - - - : 56 : switch(elem->tag) {
- + + + +
+ - ]
648 : 14 : case SFLCOUNTERS_GENERIC: elemSiz = SFL_CTR_GENERIC_XDR_SIZE; break;
649 : 0 : case SFLCOUNTERS_ETHERNET: elemSiz = SFL_CTR_ETHERNET_XDR_SIZE; break;
650 : 0 : case SFLCOUNTERS_TOKENRING: elemSiz = sizeof(elem->counterBlock.tokenring); break;
651 : 0 : case SFLCOUNTERS_VG: elemSiz = sizeof(elem->counterBlock.vg); break;
652 : 0 : case SFLCOUNTERS_VLAN: elemSiz = sizeof(elem->counterBlock.vlan); break;
653 : 2 : case SFLCOUNTERS_LACP: elemSiz = SFL_CTR_LACP_XDR_SIZE; break;
654 : 14 : case SFLCOUNTERS_OPENFLOWPORT: elemSiz = SFL_CTR_OPENFLOWPORT_XDR_SIZE; break;
655 : 14 : case SFLCOUNTERS_PORTNAME: elemSiz = stringEncodingLength(&elem->counterBlock.portName.portName); break;
656 : 6 : case SFLCOUNTERS_APP_RESOURCES: elemSiz = SFL_CTR_APP_RESOURCES_XDR_SIZE; break;
657 : 6 : case SFLCOUNTERS_OVSDP: elemSiz = SFL_CTR_OVSDP_XDR_SIZE; break;
658 : : default:
659 : 0 : sflError(receiver, "unexpected counters_tag");
660 : 0 : return -1;
661 : : break;
662 : : }
663 : : // cache the element size, and accumulate it into the overall FlowSample size
664 : 56 : elem->length = elemSiz;
665 : 56 : siz += elemSiz;
666 : : }
667 : 20 : return siz;
668 : : }
669 : :
670 : : /*_________________----------------------------------__________________
671 : : _________________ sfl_receiver_writeCountersSample __________________
672 : : -----------------__________________________________------------------
673 : : */
674 : :
675 : 20 : int sfl_receiver_writeCountersSample(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_TYPE *cs)
676 : : {
677 : : int packedSize;
678 [ - + ]: 20 : if(cs == NULL) return -1;
679 : : // if the sample pkt is full enough so that this sample might put
680 : : // it over the limit, then we should send it now.
681 [ - + ]: 20 : if((packedSize = computeCountersSampleSize(receiver, cs)) == -1) return -1;
682 : :
683 : : // check in case this one sample alone is too big for the datagram
684 : : // in fact - if it is even half as big then we should ditch it. Very
685 : : // important to avoid overruning the packet buffer.
686 [ - + ]: 20 : if(packedSize > (int)(receiver->sFlowRcvrMaximumDatagramSize / 2)) {
687 : 0 : sflError(receiver, "counters sample too big for datagram");
688 : 0 : return -1;
689 : : }
690 : :
691 [ - + ]: 20 : if((receiver->sampleCollector.pktlen + packedSize) >= receiver->sFlowRcvrMaximumDatagramSize)
692 : 0 : sendSample(receiver);
693 : :
694 : 20 : receiver->sampleCollector.numSamples++;
695 : :
696 : : #ifdef SFL_USE_32BIT_INDEX
697 : : putNet32(receiver, SFLCOUNTERS_SAMPLE_EXPANDED);
698 : : #else
699 : 20 : putNet32(receiver, SFLCOUNTERS_SAMPLE);
700 : : #endif
701 : :
702 : 20 : putNet32(receiver, packedSize - 8); // tag and length not included
703 : 20 : putNet32(receiver, cs->sequence_number);
704 : :
705 : : #ifdef SFL_USE_32BIT_INDEX
706 : : putNet32(receiver, cs->ds_class);
707 : : putNet32(receiver, cs->ds_index);
708 : : #else
709 : 20 : putNet32(receiver, cs->source_id);
710 : : #endif
711 : :
712 : 20 : putNet32(receiver, cs->num_elements);
713 : :
714 : : {
715 : 20 : SFLCounters_sample_element *elem = cs->elements;
716 [ + + ]: 76 : for(; elem != NULL; elem = elem->nxt) {
717 : :
718 : 56 : putNet32(receiver, elem->tag);
719 : 56 : putNet32(receiver, elem->length); // length cached in computeCountersSampleSize()
720 : :
721 [ + - - - : 56 : switch(elem->tag) {
- + + + +
+ - ]
722 : : case SFLCOUNTERS_GENERIC:
723 : 14 : putGenericCounters(receiver, &(elem->counterBlock.generic));
724 : 14 : break;
725 : : case SFLCOUNTERS_ETHERNET:
726 : : // all these counters are 32-bit
727 : 0 : putNet32_run(receiver, &elem->counterBlock.ethernet, sizeof(elem->counterBlock.ethernet) / 4);
728 : 0 : break;
729 : : case SFLCOUNTERS_TOKENRING:
730 : : // all these counters are 32-bit
731 : 0 : putNet32_run(receiver, &elem->counterBlock.tokenring, sizeof(elem->counterBlock.tokenring) / 4);
732 : 0 : break;
733 : : case SFLCOUNTERS_VG:
734 : : // mixed sizes
735 : 0 : putNet32(receiver, elem->counterBlock.vg.dot12InHighPriorityFrames);
736 : 0 : putNet64(receiver, elem->counterBlock.vg.dot12InHighPriorityOctets);
737 : 0 : putNet32(receiver, elem->counterBlock.vg.dot12InNormPriorityFrames);
738 : 0 : putNet64(receiver, elem->counterBlock.vg.dot12InNormPriorityOctets);
739 : 0 : putNet32(receiver, elem->counterBlock.vg.dot12InIPMErrors);
740 : 0 : putNet32(receiver, elem->counterBlock.vg.dot12InOversizeFrameErrors);
741 : 0 : putNet32(receiver, elem->counterBlock.vg.dot12InDataErrors);
742 : 0 : putNet32(receiver, elem->counterBlock.vg.dot12InNullAddressedFrames);
743 : 0 : putNet32(receiver, elem->counterBlock.vg.dot12OutHighPriorityFrames);
744 : 0 : putNet64(receiver, elem->counterBlock.vg.dot12OutHighPriorityOctets);
745 : 0 : putNet32(receiver, elem->counterBlock.vg.dot12TransitionIntoTrainings);
746 : 0 : putNet64(receiver, elem->counterBlock.vg.dot12HCInHighPriorityOctets);
747 : 0 : putNet64(receiver, elem->counterBlock.vg.dot12HCInNormPriorityOctets);
748 : 0 : putNet64(receiver, elem->counterBlock.vg.dot12HCOutHighPriorityOctets);
749 : 0 : break;
750 : : case SFLCOUNTERS_VLAN:
751 : : // mixed sizes
752 : 0 : putNet32(receiver, elem->counterBlock.vlan.vlan_id);
753 : 0 : putNet64(receiver, elem->counterBlock.vlan.octets);
754 : 0 : putNet32(receiver, elem->counterBlock.vlan.ucastPkts);
755 : 0 : putNet32(receiver, elem->counterBlock.vlan.multicastPkts);
756 : 0 : putNet32(receiver, elem->counterBlock.vlan.broadcastPkts);
757 : 0 : putNet32(receiver, elem->counterBlock.vlan.discards);
758 : 0 : break;
759 : : case SFLCOUNTERS_LACP:
760 : 2 : putMACAddress(receiver, elem->counterBlock.lacp.actorSystemID);
761 : 2 : putMACAddress(receiver, elem->counterBlock.lacp.partnerSystemID);
762 : 2 : putNet32(receiver, elem->counterBlock.lacp.attachedAggID);
763 : 2 : put32(receiver, elem->counterBlock.lacp.portState.all);
764 : 2 : putNet32(receiver, elem->counterBlock.lacp.LACPDUsRx);
765 : 2 : putNet32(receiver, elem->counterBlock.lacp.markerPDUsRx);
766 : 2 : putNet32(receiver, elem->counterBlock.lacp.markerResponsePDUsRx);
767 : 2 : putNet32(receiver, elem->counterBlock.lacp.unknownRx);
768 : 2 : putNet32(receiver, elem->counterBlock.lacp.illegalRx);
769 : 2 : putNet32(receiver, elem->counterBlock.lacp.LACPDUsTx);
770 : 2 : putNet32(receiver, elem->counterBlock.lacp.markerPDUsTx);
771 : 2 : putNet32(receiver, elem->counterBlock.lacp.markerResponsePDUsTx);
772 : 2 : break;
773 : : case SFLCOUNTERS_OPENFLOWPORT:
774 : 14 : putNet64(receiver, elem->counterBlock.ofPort.datapath_id);
775 : 14 : putNet32(receiver, elem->counterBlock.ofPort.port_no);
776 : 14 : break;
777 : : case SFLCOUNTERS_PORTNAME:
778 : 14 : putString(receiver, &elem->counterBlock.portName.portName);
779 : 14 : break;
780 : : case SFLCOUNTERS_APP_RESOURCES:
781 : 6 : putNet32(receiver, elem->counterBlock.appResources.user_time);
782 : 6 : putNet32(receiver, elem->counterBlock.appResources.system_time);
783 : 6 : putNet64(receiver, elem->counterBlock.appResources.mem_used);
784 : 6 : putNet64(receiver, elem->counterBlock.appResources.mem_max);
785 : 6 : putNet32(receiver, elem->counterBlock.appResources.fd_open);
786 : 6 : putNet32(receiver, elem->counterBlock.appResources.fd_max);
787 : 6 : putNet32(receiver, elem->counterBlock.appResources.conn_open);
788 : 6 : putNet32(receiver, elem->counterBlock.appResources.conn_max);
789 : 6 : break;
790 : : case SFLCOUNTERS_OVSDP:
791 : 6 : putNet32(receiver, elem->counterBlock.ovsdp.n_hit);
792 : 6 : putNet32(receiver, elem->counterBlock.ovsdp.n_missed);
793 : 6 : putNet32(receiver, elem->counterBlock.ovsdp.n_lost);
794 : 6 : putNet32(receiver, elem->counterBlock.ovsdp.n_mask_hit);
795 : 6 : putNet32(receiver, elem->counterBlock.ovsdp.n_flows);
796 : 6 : putNet32(receiver, elem->counterBlock.ovsdp.n_masks);
797 : 6 : break;
798 : : default:
799 : 0 : sflError(receiver, "unexpected counters_tag");
800 : 0 : return -1;
801 : : break;
802 : : }
803 : : }
804 : : }
805 : : // sanity check
806 [ - + ]: 20 : assert(((u_char *)receiver->sampleCollector.datap
807 : : - (u_char *)receiver->sampleCollector.data
808 : : - receiver->sampleCollector.pktlen) == (u_int32_t)packedSize);
809 : :
810 : : // update the pktlen
811 : 20 : receiver->sampleCollector.pktlen = (u_char *)receiver->sampleCollector.datap - (u_char *)receiver->sampleCollector.data;
812 : 20 : return packedSize;
813 : : }
814 : :
815 : : /*_________________---------------------------------__________________
816 : : _________________ sfl_receiver_samplePacketsSent __________________
817 : : -----------------_________________________________------------------
818 : : */
819 : :
820 : 0 : u_int32_t sfl_receiver_samplePacketsSent(SFLReceiver *receiver)
821 : : {
822 : 0 : return receiver->sampleCollector.packetSeqNo;
823 : : }
824 : :
825 : : /*_________________---------------------------__________________
826 : : _________________ sendSample __________________
827 : : -----------------___________________________------------------
828 : : */
829 : :
830 : 9 : static void sendSample(SFLReceiver *receiver)
831 : : {
832 : : /* construct and send out the sample, then reset for the next one... */
833 : : /* first fill in the header with the latest values */
834 : : /* version, agent_address and sub_agent_id were pre-set. */
835 [ - + ]: 9 : u_int32_t hdrIdx = (receiver->agent->myIP.type == SFLADDRESSTYPE_IP_V6) ? 7 : 4;
836 : 9 : receiver->sampleCollector.data[hdrIdx++] = htonl(++receiver->sampleCollector.packetSeqNo); /* seq no */
837 : 9 : receiver->sampleCollector.data[hdrIdx++] = htonl((receiver->agent->now - receiver->agent->bootTime) * 1000); /* uptime */
838 : 9 : receiver->sampleCollector.data[hdrIdx++] = htonl(receiver->sampleCollector.numSamples); /* num samples */
839 : : /* send */
840 [ + - ]: 9 : if(receiver->agent->sendFn) (*receiver->agent->sendFn)(receiver->agent->magic,
841 : : receiver->agent,
842 : : receiver,
843 : 9 : (u_char *)receiver->sampleCollector.data,
844 : : receiver->sampleCollector.pktlen);
845 : : else {
846 : : #ifdef SFLOW_DO_SOCKET
847 : : /* send it myself */
848 : : if (receiver->sFlowRcvrAddress.type == SFLADDRESSTYPE_IP_V6) {
849 : : u_int32_t soclen = sizeof(struct sockaddr_in6);
850 : : int result = sendto(receiver->agent->receiverSocket6,
851 : : receiver->sampleCollector.data,
852 : : receiver->sampleCollector.pktlen,
853 : : 0,
854 : : (struct sockaddr *)&receiver->receiver6,
855 : : soclen);
856 : : if(result == -1 && errno != EINTR) sfl_agent_sysError(receiver->agent, "receiver", "IPv6 socket sendto error");
857 : : if(result == 0) sfl_agent_error(receiver->agent, "receiver", "IPv6 socket sendto returned 0");
858 : : }
859 : : else {
860 : : u_int32_t soclen = sizeof(struct sockaddr_in);
861 : : int result = sendto(receiver->agent->receiverSocket4,
862 : : receiver->sampleCollector.data,
863 : : receiver->sampleCollector.pktlen,
864 : : 0,
865 : : (struct sockaddr *)&receiver->receiver4,
866 : : soclen);
867 : : if(result == -1 && errno != EINTR) sfl_agent_sysError(receiver->agent, "receiver", "socket sendto error");
868 : : if(result == 0) sfl_agent_error(receiver->agent, "receiver", "socket sendto returned 0");
869 : : }
870 : : #endif
871 : : }
872 : :
873 : : /* reset for the next time */
874 : 9 : resetSampleCollector(receiver);
875 : 9 : }
876 : :
877 : : /*_________________---------------------------__________________
878 : : _________________ resetSampleCollector __________________
879 : : -----------------___________________________------------------
880 : : */
881 : :
882 : 15 : static void resetSampleCollector(SFLReceiver *receiver)
883 : : {
884 : 15 : receiver->sampleCollector.pktlen = 0;
885 : 15 : receiver->sampleCollector.numSamples = 0;
886 : : /* point the datap to just after the header */
887 : 30 : receiver->sampleCollector.datap = (receiver->agent->myIP.type == SFLADDRESSTYPE_IP_V6) ?
888 [ - + ]: 15 : (receiver->sampleCollector.data + 10) : (receiver->sampleCollector.data + 7);
889 : :
890 : 15 : receiver->sampleCollector.pktlen = (u_char *)receiver->sampleCollector.datap - (u_char *)receiver->sampleCollector.data;
891 : 15 : }
892 : :
893 : : /*_________________---------------------------__________________
894 : : _________________ sflError __________________
895 : : -----------------___________________________------------------
896 : : */
897 : :
898 : 0 : static void sflError(SFLReceiver *receiver, char *msg)
899 : : {
900 : 0 : sfl_agent_error(receiver->agent, "receiver", msg);
901 : 0 : resetSampleCollector(receiver);
902 : 0 : }
903 : :
904 : : #endif /* !__CHECKER__ */
|