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 : : #include "sflow_api.h"
9 : : #include "util.h"
10 : :
11 : : static void * sflAlloc(SFLAgent *agent, size_t bytes);
12 : : static void sflFree(SFLAgent *agent, void *obj);
13 : : static void sfl_agent_jumpTableAdd(SFLAgent *agent, SFLSampler *sampler);
14 : : static void sfl_agent_jumpTableRemove(SFLAgent *agent, SFLSampler *sampler);
15 : :
16 : : /*________________--------------------------__________________
17 : : ________________ sfl_agent_init __________________
18 : : ----------------__________________________------------------
19 : : */
20 : :
21 : 6 : void sfl_agent_init(SFLAgent *agent,
22 : : SFLAddress *myIP, /* IP address of this agent in net byte order */
23 : : u_int32_t subId, /* agent_sub_id */
24 : : time_t bootTime, /* agent boot time */
25 : : time_t now, /* time now */
26 : : void *magic, /* ptr to pass back in logging and alloc fns */
27 : : allocFn_t allocFn,
28 : : freeFn_t freeFn,
29 : : errorFn_t errorFn,
30 : : sendFn_t sendFn)
31 : : {
32 : : /* first clear everything */
33 : 6 : memset(agent, 0, sizeof(*agent));
34 : : /* now copy in the parameters */
35 : 6 : agent->myIP = *myIP; /* structure copy */
36 : 6 : agent->subId = subId;
37 : 6 : agent->bootTime = bootTime;
38 : 6 : agent->now = now;
39 : 6 : agent->magic = magic;
40 : 6 : agent->allocFn = allocFn;
41 : 6 : agent->freeFn = freeFn;
42 : 6 : agent->errorFn = errorFn;
43 : 6 : agent->sendFn = sendFn;
44 : :
45 : : #ifdef SFLOW_DO_SOCKET
46 : : if(sendFn == NULL) {
47 : : /* open the socket - really need one for v4 and another for v6? */
48 : : if((agent->receiverSocket4 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
49 : : sfl_agent_sysError(agent, "agent", "IPv4 socket open failed");
50 : : if((agent->receiverSocket6 = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) == -1)
51 : : sfl_agent_sysError(agent, "agent", "IPv6 socket open failed");
52 : : }
53 : : #endif
54 : 6 : }
55 : :
56 : : /*_________________---------------------------__________________
57 : : _________________ sfl_agent_release __________________
58 : : -----------------___________________________------------------
59 : : */
60 : :
61 : 6 : void sfl_agent_release(SFLAgent *agent)
62 : : {
63 : : /* release and free the samplers, pollers and receivers */
64 : 6 : SFLSampler *sm = agent->samplers;
65 : 6 : SFLPoller *pl = agent->pollers;
66 : 6 : SFLReceiver *rcv = agent->receivers;
67 : :
68 [ + + ]: 12 : for(; sm != NULL; ) {
69 : 6 : SFLSampler *nextSm = sm->nxt;
70 : 6 : sflFree(agent, sm);
71 : 6 : sm = nextSm;
72 : : }
73 : 6 : agent->samplers = NULL;
74 : :
75 [ + + ]: 12 : for(; pl != NULL; ) {
76 : 6 : SFLPoller *nextPl = pl->nxt;
77 : 6 : sflFree(agent, pl);
78 : 6 : pl = nextPl;
79 : : }
80 : 6 : agent->pollers = NULL;
81 : :
82 [ + + ]: 12 : for(; rcv != NULL; ) {
83 : 6 : SFLReceiver *nextRcv = rcv->nxt;
84 : 6 : sflFree(agent, rcv);
85 : 6 : rcv = nextRcv;
86 : : }
87 : 6 : agent->receivers = NULL;
88 : :
89 : : #ifdef SFLOW_DO_SOCKET
90 : : /* close the sockets */
91 : : if(agent->receiverSocket4 > 0) close(agent->receiverSocket4);
92 : : if(agent->receiverSocket6 > 0) close(agent->receiverSocket6);
93 : : #endif
94 : 6 : }
95 : :
96 : :
97 : : /*_________________---------------------------__________________
98 : : _________________ sfl_agent_set_* __________________
99 : : -----------------___________________________------------------
100 : : */
101 : :
102 : 0 : void sfl_agent_set_agentAddress(SFLAgent *agent, SFLAddress *addr)
103 : : {
104 [ # # ][ # # ]: 0 : if(addr && memcmp(addr, &agent->myIP, sizeof(agent->myIP)) != 0) {
105 : : /* change of address */
106 : 0 : agent->myIP = *addr; /* structure copy */
107 : : /* reset sequence numbers here? */
108 : : }
109 : 0 : }
110 : :
111 : 0 : void sfl_agent_set_agentSubId(SFLAgent *agent, u_int32_t subId)
112 : : {
113 [ # # ]: 0 : if(subId != agent->subId) {
114 : : /* change of subId */
115 : 0 : agent->subId = subId;
116 : : /* reset sequence numbers here? */
117 : : }
118 : 0 : }
119 : :
120 : : /*_________________---------------------------__________________
121 : : _________________ sfl_agent_tick __________________
122 : : -----------------___________________________------------------
123 : : */
124 : :
125 : 15 : void sfl_agent_tick(SFLAgent *agent, time_t now)
126 : : {
127 : 15 : SFLReceiver *rcv = agent->receivers;
128 : 15 : SFLSampler *sm = agent->samplers;
129 : 15 : SFLPoller *pl = agent->pollers;
130 : 15 : agent->now = now;
131 : : /* samplers use ticks to decide when they are sampling too fast */
132 [ + + ]: 30 : for(; sm != NULL; sm = sm->nxt) sfl_sampler_tick(sm, now);
133 : : /* pollers use ticks to decide when to ask for counters */
134 [ + + ]: 47 : for(; pl != NULL; pl = pl->nxt) sfl_poller_tick(pl, now);
135 : : /* receivers use ticks to flush send data. By doing this
136 : : * step last we ensure that fresh counters polled during
137 : : * sfl_poller_tick() above will be flushed promptly.
138 : : */
139 [ + + ]: 30 : for(; rcv != NULL; rcv = rcv->nxt) sfl_receiver_tick(rcv, now);
140 : 15 : }
141 : :
142 : : /*_________________---------------------------__________________
143 : : _________________ sfl_agent_addReceiver __________________
144 : : -----------------___________________________------------------
145 : : */
146 : :
147 : 6 : SFLReceiver *sfl_agent_addReceiver(SFLAgent *agent)
148 : : {
149 : 6 : SFLReceiver *rcv = (SFLReceiver *)sflAlloc(agent, sizeof(SFLReceiver));
150 : 6 : sfl_receiver_init(rcv, agent);
151 : : /* add to end of list - to preserve the receiver index numbers for existing receivers */
152 : : {
153 : 6 : SFLReceiver *r, *prev = NULL;
154 [ - + ]: 6 : for(r = agent->receivers; r != NULL; prev = r, r = r->nxt);
155 [ - + ]: 6 : if(prev) prev->nxt = rcv;
156 : 6 : else agent->receivers = rcv;
157 : 6 : rcv->nxt = NULL;
158 : : }
159 : 6 : return rcv;
160 : : }
161 : :
162 : : /*_________________---------------------------__________________
163 : : _________________ sfl_dsi_compare __________________
164 : : -----------------___________________________------------------
165 : :
166 : : Note that if there is a mixture of ds_classes for this agent, then
167 : : the simple numeric comparison may not be correct - the sort order (for
168 : : the purposes of the SNMP MIB) should really be determined by the OID
169 : : that these numeric ds_class numbers are a shorthand for. For example,
170 : : ds_class == 0 means ifIndex, which is the oid "1.3.6.1.2.1.2.2.1"
171 : : */
172 : :
173 : 40 : static inline int sfl_dsi_compare(SFLDataSource_instance *pdsi1, SFLDataSource_instance *pdsi2) {
174 : : /* could have used just memcmp(), but not sure if that would
175 : : give the right answer on little-endian platforms. Safer to be explicit... */
176 : 40 : int cmp = pdsi2->ds_class - pdsi1->ds_class;
177 [ + + ]: 40 : if(cmp == 0) cmp = pdsi2->ds_index - pdsi1->ds_index;
178 [ + + ]: 40 : if(cmp == 0) cmp = pdsi2->ds_instance - pdsi1->ds_instance;
179 : 40 : return cmp;
180 : : }
181 : :
182 : : /*_________________---------------------------__________________
183 : : _________________ sfl_agent_addSampler __________________
184 : : -----------------___________________________------------------
185 : : */
186 : :
187 : 6 : SFLSampler *sfl_agent_addSampler(SFLAgent *agent, SFLDataSource_instance *pdsi)
188 : : {
189 : : /* Keep the list sorted. */
190 : 6 : SFLSampler *prev = NULL, *sm = agent->samplers;
191 [ - + ]: 6 : for(; sm != NULL; prev = sm, sm = sm->nxt) {
192 : 0 : int64_t cmp = sfl_dsi_compare(pdsi, &sm->dsi);
193 [ # # ]: 0 : if(cmp == 0) return sm; /* found - return existing one */
194 [ # # ]: 0 : if(cmp < 0) break; /* insert here */
195 : : }
196 : : /* either we found the insert point, or reached the end of the list...*/
197 : :
198 : : {
199 : 6 : SFLSampler *newsm = (SFLSampler *)sflAlloc(agent, sizeof(SFLSampler));
200 : 6 : sfl_sampler_init(newsm, agent, pdsi);
201 [ - + ]: 6 : if(prev) prev->nxt = newsm;
202 : 6 : else agent->samplers = newsm;
203 : 6 : newsm->nxt = sm;
204 : :
205 : : /* see if we should go in the ifIndex jumpTable */
206 [ - + ]: 6 : if(SFL_DS_CLASS(newsm->dsi) == 0) {
207 : 0 : SFLSampler *test = sfl_agent_getSamplerByIfIndex(agent, SFL_DS_INDEX(newsm->dsi));
208 [ # # ][ # # ]: 0 : if(test && (SFL_DS_INSTANCE(newsm->dsi) < SFL_DS_INSTANCE(test->dsi))) {
209 : : /* replace with this new one because it has a lower ds_instance number */
210 : 0 : sfl_agent_jumpTableRemove(agent, test);
211 : 0 : test = NULL;
212 : : }
213 [ # # ]: 0 : if(test == NULL) sfl_agent_jumpTableAdd(agent, newsm);
214 : : }
215 : 6 : return newsm;
216 : : }
217 : : }
218 : :
219 : : /*_________________---------------------------__________________
220 : : _________________ sfl_agent_addPoller __________________
221 : : -----------------___________________________------------------
222 : : */
223 : :
224 : 14 : SFLPoller *sfl_agent_addPoller(SFLAgent *agent,
225 : : SFLDataSource_instance *pdsi,
226 : : void *magic, /* ptr to pass back in getCountersFn() */
227 : : getCountersFn_t getCountersFn)
228 : : {
229 : : /* keep the list sorted */
230 : 14 : SFLPoller *prev = NULL, *pl = agent->pollers;
231 [ + + ]: 28 : for(; pl != NULL; prev = pl, pl = pl->nxt) {
232 : 14 : int64_t cmp = sfl_dsi_compare(pdsi, &pl->dsi);
233 [ - + ]: 14 : if(cmp == 0) return pl; /* found - return existing one */
234 [ - + ]: 14 : if(cmp < 0) break; /* insert here */
235 : : }
236 : : /* either we found the insert point, or reached the end of the list... */
237 : : {
238 : 14 : SFLPoller *newpl = (SFLPoller *)sflAlloc(agent, sizeof(SFLPoller));
239 : 14 : sfl_poller_init(newpl, agent, pdsi, magic, getCountersFn);
240 [ + + ]: 14 : if(prev) prev->nxt = newpl;
241 : 6 : else agent->pollers = newpl;
242 : 14 : newpl->nxt = pl;
243 : 14 : return newpl;
244 : : }
245 : : }
246 : :
247 : : /*_________________---------------------------__________________
248 : : _________________ sfl_agent_removeSampler __________________
249 : : -----------------___________________________------------------
250 : : */
251 : :
252 : 8 : int sfl_agent_removeSampler(SFLAgent *agent, SFLDataSource_instance *pdsi)
253 : : {
254 : : /* find it, unlink it and free it */
255 : 8 : SFLSampler *prev = NULL, *sm = agent->samplers;
256 [ + + ]: 16 : for(; sm != NULL; prev = sm, sm = sm->nxt) {
257 [ - + ]: 8 : if(sfl_dsi_compare(pdsi, &sm->dsi) == 0) {
258 [ # # ]: 0 : if(prev == NULL) agent->samplers = sm->nxt;
259 : 0 : else prev->nxt = sm->nxt;
260 : 0 : sfl_agent_jumpTableRemove(agent, sm);
261 : 0 : sflFree(agent, sm);
262 : 0 : return 1;
263 : : }
264 : : }
265 : : /* not found */
266 : 8 : return 0;
267 : : }
268 : :
269 : : /*_________________---------------------------__________________
270 : : _________________ sfl_agent_removePoller __________________
271 : : -----------------___________________________------------------
272 : : */
273 : :
274 : 8 : int sfl_agent_removePoller(SFLAgent *agent, SFLDataSource_instance *pdsi)
275 : : {
276 : : /* find it, unlink it and free it */
277 : 8 : SFLPoller *prev = NULL, *pl = agent->pollers;
278 [ + - ]: 18 : for(; pl != NULL; prev = pl, pl = pl->nxt) {
279 [ + + ]: 18 : if(sfl_dsi_compare(pdsi, &pl->dsi) == 0) {
280 [ - + ]: 8 : if(prev == NULL) agent->pollers = pl->nxt;
281 : 8 : else prev->nxt = pl->nxt;
282 : 8 : sflFree(agent, pl);
283 : 8 : return 1;
284 : : }
285 : : }
286 : : /* not found */
287 : 0 : return 0;
288 : : }
289 : :
290 : : /*_________________--------------------------------__________________
291 : : _________________ sfl_agent_jumpTableAdd __________________
292 : : -----------------________________________________------------------
293 : : */
294 : :
295 : 0 : static void sfl_agent_jumpTableAdd(SFLAgent *agent, SFLSampler *sampler)
296 : : {
297 : 0 : u_int32_t hashIndex = SFL_DS_INDEX(sampler->dsi) % SFL_HASHTABLE_SIZ;
298 : 0 : sampler->hash_nxt = agent->jumpTable[hashIndex];
299 : 0 : agent->jumpTable[hashIndex] = sampler;
300 : 0 : }
301 : :
302 : : /*_________________--------------------------------__________________
303 : : _________________ sfl_agent_jumpTableRemove __________________
304 : : -----------------________________________________------------------
305 : : */
306 : :
307 : 0 : static void sfl_agent_jumpTableRemove(SFLAgent *agent, SFLSampler *sampler)
308 : : {
309 : 0 : u_int32_t hashIndex = SFL_DS_INDEX(sampler->dsi) % SFL_HASHTABLE_SIZ;
310 : 0 : SFLSampler *search = agent->jumpTable[hashIndex], *prev = NULL;
311 [ # # ][ # # ]: 0 : for( ; search != NULL; prev = search, search = search->hash_nxt) if(search == sampler) break;
312 [ # # ]: 0 : if(search) {
313 : : // found - unlink
314 [ # # ]: 0 : if(prev) prev->hash_nxt = search->hash_nxt;
315 : 0 : else agent->jumpTable[hashIndex] = search->hash_nxt;
316 : 0 : search->hash_nxt = NULL;
317 : : }
318 : 0 : }
319 : :
320 : : /*_________________--------------------------------__________________
321 : : _________________ sfl_agent_getSamplerByIfIndex __________________
322 : : -----------------________________________________------------------
323 : : fast lookup (pointers cached in hash table). If there are multiple
324 : : sampler instances for a given ifIndex, then this fn will return
325 : : the one with the lowest instance number. Since the samplers
326 : : list is sorted, this means the other instances will be accesible
327 : : by following the sampler->nxt pointer (until the ds_class
328 : : or ds_index changes). This is helpful if you need to offer
329 : : the same flowSample to multiple samplers.
330 : : */
331 : :
332 : 0 : SFLSampler *sfl_agent_getSamplerByIfIndex(SFLAgent *agent, u_int32_t ifIndex)
333 : : {
334 : 0 : SFLSampler *search = agent->jumpTable[ifIndex % SFL_HASHTABLE_SIZ];
335 [ # # ][ # # ]: 0 : for( ; search != NULL; search = search->hash_nxt) if(SFL_DS_INDEX(search->dsi) == ifIndex) break;
336 : 0 : return search;
337 : : }
338 : :
339 : : /*_________________---------------------------__________________
340 : : _________________ sfl_agent_getSampler __________________
341 : : -----------------___________________________------------------
342 : : */
343 : :
344 : 0 : SFLSampler *sfl_agent_getSampler(SFLAgent *agent, SFLDataSource_instance *pdsi)
345 : : {
346 : : /* find it and return it */
347 : 0 : SFLSampler *sm = agent->samplers;
348 [ # # ]: 0 : for(; sm != NULL; sm = sm->nxt)
349 [ # # ]: 0 : if(sfl_dsi_compare(pdsi, &sm->dsi) == 0) return sm;
350 : : /* not found */
351 : 0 : return NULL;
352 : : }
353 : :
354 : : /*_________________---------------------------__________________
355 : : _________________ sfl_agent_getPoller __________________
356 : : -----------------___________________________------------------
357 : : */
358 : :
359 : 0 : SFLPoller *sfl_agent_getPoller(SFLAgent *agent, SFLDataSource_instance *pdsi)
360 : : {
361 : : /* find it and return it */
362 : 0 : SFLPoller *pl = agent->pollers;
363 [ # # ]: 0 : for(; pl != NULL; pl = pl->nxt)
364 [ # # ]: 0 : if(sfl_dsi_compare(pdsi, &pl->dsi) == 0) return pl;
365 : : /* not found */
366 : 0 : return NULL;
367 : : }
368 : :
369 : : /*_________________-----------------------------------__________________
370 : : _________________ sfl_agent_getPollerByBridgePort __________________
371 : : -----------------___________________________________------------------
372 : : */
373 : :
374 : 0 : SFLPoller *sfl_agent_getPollerByBridgePort(SFLAgent *agent, uint32_t port_no)
375 : : {
376 : : /* find it and return it */
377 : 0 : SFLPoller *pl = agent->pollers;
378 [ # # ]: 0 : for(; pl != NULL; pl = pl->nxt)
379 [ # # ]: 0 : if(pl->bridgePort == port_no) return pl;
380 : : /* not found */
381 : 0 : return NULL;
382 : : }
383 : :
384 : : /*_________________---------------------------__________________
385 : : _________________ sfl_agent_getReceiver __________________
386 : : -----------------___________________________------------------
387 : : */
388 : :
389 : 20 : SFLReceiver *sfl_agent_getReceiver(SFLAgent *agent, u_int32_t receiverIndex)
390 : : {
391 : 20 : u_int32_t rcvIdx = 0;
392 : 20 : SFLReceiver *rcv = agent->receivers;
393 [ + - ]: 20 : for(; rcv != NULL; rcv = rcv->nxt)
394 [ + - ]: 20 : if(receiverIndex == ++rcvIdx) return rcv;
395 : :
396 : : /* not found - ran off the end of the table */
397 : 0 : return NULL;
398 : : }
399 : :
400 : : /*_________________---------------------------__________________
401 : : _________________ sfl_agent_getNextSampler __________________
402 : : -----------------___________________________------------------
403 : : */
404 : :
405 : 0 : SFLSampler *sfl_agent_getNextSampler(SFLAgent *agent, SFLDataSource_instance *pdsi)
406 : : {
407 : : /* return the one lexograpically just after it - assume they are sorted
408 : : correctly according to the lexographical ordering of the object ids */
409 : 0 : SFLSampler *sm = sfl_agent_getSampler(agent, pdsi);
410 [ # # ]: 0 : return sm ? sm->nxt : NULL;
411 : : }
412 : :
413 : : /*_________________---------------------------__________________
414 : : _________________ sfl_agent_getNextPoller __________________
415 : : -----------------___________________________------------------
416 : : */
417 : :
418 : 0 : SFLPoller *sfl_agent_getNextPoller(SFLAgent *agent, SFLDataSource_instance *pdsi)
419 : : {
420 : : /* return the one lexograpically just after it - assume they are sorted
421 : : correctly according to the lexographical ordering of the object ids */
422 : 0 : SFLPoller *pl = sfl_agent_getPoller(agent, pdsi);
423 [ # # ]: 0 : return pl ? pl->nxt : NULL;
424 : : }
425 : :
426 : : /*_________________---------------------------__________________
427 : : _________________ sfl_agent_getNextReceiver __________________
428 : : -----------------___________________________------------------
429 : : */
430 : :
431 : 0 : SFLReceiver *sfl_agent_getNextReceiver(SFLAgent *agent, u_int32_t receiverIndex)
432 : : {
433 : 0 : return sfl_agent_getReceiver(agent, receiverIndex + 1);
434 : : }
435 : :
436 : :
437 : : /*_________________---------------------------__________________
438 : : _________________ sfl_agent_resetReceiver __________________
439 : : -----------------___________________________------------------
440 : : */
441 : :
442 : 0 : void sfl_agent_resetReceiver(SFLAgent *agent, SFLReceiver *receiver)
443 : : {
444 : : /* tell samplers and pollers to stop sending to this receiver */
445 : : /* first get his receiverIndex */
446 : 0 : u_int32_t rcvIdx = 0;
447 : 0 : SFLReceiver *rcv = agent->receivers;
448 [ # # ]: 0 : for(; rcv != NULL; rcv = rcv->nxt) {
449 : 0 : rcvIdx++; /* thanks to Diego Valverde for pointing out this bugfix */
450 [ # # ]: 0 : if(rcv == receiver) {
451 : : /* now tell anyone that is using it to stop */
452 : 0 : SFLSampler *sm = agent->samplers;
453 : 0 : SFLPoller *pl = agent->pollers;
454 : :
455 [ # # ]: 0 : for(; sm != NULL; sm = sm->nxt)
456 [ # # ]: 0 : if(sfl_sampler_get_sFlowFsReceiver(sm) == rcvIdx) sfl_sampler_set_sFlowFsReceiver(sm, 0);
457 : :
458 [ # # ]: 0 : for(; pl != NULL; pl = pl->nxt)
459 [ # # ]: 0 : if(sfl_poller_get_sFlowCpReceiver(pl) == rcvIdx) sfl_poller_set_sFlowCpReceiver(pl, 0);
460 : :
461 : 0 : break;
462 : : }
463 : : }
464 : 0 : }
465 : :
466 : : /*_________________---------------------------__________________
467 : : _________________ sfl_agent_error __________________
468 : : -----------------___________________________------------------
469 : : */
470 : : #define MAX_ERRMSG_LEN 1000
471 : :
472 : 0 : void sfl_agent_error(SFLAgent *agent, char *modName, char *msg)
473 : : {
474 : : char errm[MAX_ERRMSG_LEN];
475 : 0 : snprintf(errm, sizeof errm, "sfl_agent_error: %s: %s\n", modName, msg);
476 [ # # ]: 0 : if(agent->errorFn) (*agent->errorFn)(agent->magic, agent, errm);
477 : : else {
478 : 0 : fprintf(stderr, "%s\n", errm);
479 : 0 : fflush(stderr);
480 : : }
481 : 0 : }
482 : :
483 : : /*_________________---------------------------__________________
484 : : _________________ sfl_agent_sysError __________________
485 : : -----------------___________________________------------------
486 : : */
487 : :
488 : 0 : void sfl_agent_sysError(SFLAgent *agent, char *modName, char *msg)
489 : : {
490 : : char errm[MAX_ERRMSG_LEN];
491 : 0 : snprintf(errm, sizeof errm, "sfl_agent_sysError: %s: %s (errno = %d - %s)\n", modName, msg, errno, ovs_strerror(errno));
492 [ # # ]: 0 : if(agent->errorFn) (*agent->errorFn)(agent->magic, agent, errm);
493 : : else {
494 : 0 : fprintf(stderr, "%s\n", errm);
495 : 0 : fflush(stderr);
496 : : }
497 : 0 : }
498 : :
499 : :
500 : : /*_________________---------------------------__________________
501 : : _________________ alloc and free __________________
502 : : -----------------___________________________------------------
503 : : */
504 : :
505 : 26 : static void * sflAlloc(SFLAgent *agent, size_t bytes)
506 : : {
507 [ + - ]: 26 : if(agent->allocFn) return (*agent->allocFn)(agent->magic, agent, bytes);
508 : 0 : else return SFL_ALLOC(bytes);
509 : : }
510 : :
511 : 26 : static void sflFree(SFLAgent *agent, void *obj)
512 : : {
513 [ + - ]: 26 : if(agent->freeFn) (*agent->freeFn)(agent->magic, agent, obj);
514 : 0 : else SFL_FREE(obj);
515 : 26 : }
|