1 /*
2 ** @internal
3 **
4 ** yafhooks.c
5 ** YAF Active Flow Table Plugin Interface
6 **
7 ** ------------------------------------------------------------------------
8 ** Copyright (C) 2007-2015 Carnegie Mellon University. All Rights Reserved.
9 ** ------------------------------------------------------------------------
10 ** Authors: Brian Trammell
11 ** ------------------------------------------------------------------------
12 ** @OPENSOURCE_HEADER_START@
13 ** Use of the YAF system and related source code is subject to the terms
14 ** of the following licenses:
15 **
16 ** GNU Public License (GPL) Rights pursuant to Version 2, June 1991
17 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013
18 **
19 ** NO WARRANTY
20 **
21 ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER
22 ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY
23 ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN
24 ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
25 ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT
26 ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE,
27 ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE
28 ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT,
29 ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY
30 ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF
31 ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES.
32 ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF
33 ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON
34 ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE
35 ** DELIVERABLES UNDER THIS LICENSE.
36 **
37 ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie
38 ** Mellon University, its trustees, officers, employees, and agents from
39 ** all claims or demands made against them (and any related losses,
40 ** expenses, or attorney's fees) arising out of, or relating to Licensee's
41 ** and/or its sub licensees' negligent use or willful misuse of or
42 ** negligent conduct or willful misconduct regarding the Software,
43 ** facilities, or other rights or assistance granted by Carnegie Mellon
44 ** University under this License, including, but not limited to, any
45 ** claims of product liability, personal injury, death, damage to
46 ** property, or violation of any laws or regulations.
47 **
48 ** Carnegie Mellon University Software Engineering Institute authored
49 ** documents are sponsored by the U.S. Department of Defense under
50 ** Contract FA8721-05-C-0003. Carnegie Mellon University retains
51 ** copyrights in all material produced under this contract. The U.S.
52 ** Government retains a non-exclusive, royalty-free license to publish or
53 ** reproduce these documents, or allow others to do so, for U.S.
54 ** Government purposes only pursuant to the copyright license under the
55 ** contract clause at 252.227.7013.
56 **
57 ** @OPENSOURCE_HEADER_END@
58 ** ------------------------------------------------------------------------
59 */
60
61 #define _YAF_SOURCE_
62 #include <yaf/yafhooks.h>
63 #include <ltdl.h>
64 #if YAF_ENABLE_HOOKS
65 /* define a quick variable argument number macro to simply sending an error back to the yaf "core" */
66 #define gerr(e, ...) {if (NULL == e) { *e = g_error_new(__VA_ARGS__); } else { g_set_error(e, __VA_ARGS__); }}
67
68 #define YAF_SEARCH_LIB "/usr/local/lib/yaf"
69
70 /** this flag contains the number of plugins that have been hooked in */
71 unsigned int yaf_hooked = 0;
72
73 static const char *pluginFunctionNames[] = {
74 "ypGetMetaData",
75 "ypHookPacket",
76 "ypFlowPacket",
77 "ypFlowClose",
78 "ypFlowAlloc",
79 "ypFlowFree",
80 "ypFlowWrite",
81 "ypGetInfoModel",
82 "ypGetTemplate",
83 "ypSetPluginOpt",
84 "ypSetPluginConf",
85 #if YAF_ENABLE_APPLABEL
86 "ypScanPayload",
87 #endif
88 "ypValidateFlowTab",
89 "ypGetTemplateCount",
90 "ypFreeLists"
91 };
92
93 typedef const struct yfHookMetaData* (*yfHookGetMetaData_fn)(void);
94 typedef gboolean (*yfHookPacket_fn)(yfFlowKey_t *key, const uint8_t *pkt,
95 size_t caplen, uint16_t iplen,
96 yfTCPInfo_t *tcpinfo, yfL2Info_t *l2info);
97 typedef void (*yfHookFlowPacket_fn)(void * yfHookConext, yfFlow_t *flow,
98 yfFlowVal_t *val, const uint8_t *pkt,
99 size_t caplen, uint16_t iplen,
100 yfTCPInfo_t *tcpinfo, yfL2Info_t *l2info);
101 typedef gboolean (*yfHookFlowClose_fn)(void * yfHookConext, yfFlow_t *flow);
102 typedef void (*yfHookFlowAlloc_fn)(void ** yfHookConext, yfFlow_t *flow, void *yfctx);
103 typedef void (*yfHookFlowFree_fn)(void * yfHookConext, yfFlow_t *flow);
104 typedef gboolean (*yfWriteFlowHook_fn)(void * yfHookConext,
105 fbSubTemplateMultiList_t *rec,
106 fbSubTemplateMultiListEntry_t *stml,
107 yfFlow_t *flow, GError **err);
108 typedef fbInfoElement_t * (*yfHookGetInfoModel_fn)(void);
109 typedef gboolean (*yfHookGetTemplate_fn)(fbSession_t *session);
110 typedef void (*yfHookSetPluginOpt_fn)(const char * pluginOpt, void *yfctx);
111 typedef void (*yfHookSetPluginConf_fn)(const char * pluginConf, void **yfctx);
112 #if YAF_ENABLE_APPLABEL
113 typedef void (*yfHookScanPayload_fn)(void *yfHookConext, yfFlow_t *flow,
114 const uint8_t *pkt, size_t caplen,
115 pcre *expression, uint16_t offset,
116 uint16_t elementID, uint16_t applabel);
117 #endif
118 typedef gboolean (*yfHookValidateFlowTab_fn)(void *yfctx,
119 uint32_t max_payload,
120 gboolean uniflow,
121 gboolean silkmode,
122 gboolean applabelmode,
123 gboolean entropymode,
124 gboolean fingerprintmode,
125 gboolean fpExportMode,
126 gboolean udp_max_payload,
127 uint16_t udp_uniflow_port,
128 GError **err);
129 typedef uint8_t (*yfHookGetTemplateCount_fn)(void *yfHookConext, yfFlow_t *flow);
130 typedef void (*yfHookFreeLists_fn)(void * yfHookConext, yfFlow_t *flow);
131
132 typedef struct yfHooksFuncs_st {
133 yfHookGetMetaData_fn getMetaData;
134 yfHookPacket_fn hookPacket;
135 yfHookFlowPacket_fn flowPacket;
136 yfHookFlowClose_fn flowClose;
137 yfHookFlowAlloc_fn flowAlloc;
138 yfHookFlowFree_fn flowFree;
139 yfWriteFlowHook_fn flowWrite;
140 yfHookGetInfoModel_fn modelGet;
141 yfHookGetTemplate_fn templateGet;
142 yfHookSetPluginOpt_fn setPluginOpt;
143 yfHookSetPluginConf_fn setPluginConf;
144 #if YAF_ENABLE_APPLABEL
145 yfHookScanPayload_fn scanPayload;
146 #endif
147 yfHookValidateFlowTab_fn validateFlowTab;
148 yfHookGetTemplateCount_fn getTemplateCount;
149 yfHookFreeLists_fn freeLists;
150 } yfHooksFuncs_t;
151
152 typedef struct yfHookPlugin_st {
153 lt_dlhandle pluginHandle;
154 union {
155 lt_ptr genPtr[sizeof (pluginFunctionNames) /
156 sizeof (char *)];
157 yfHooksFuncs_t funcPtrs;
158 } ufptr;
159 struct yfHookPlugin_st *next;
160 } yfHookPlugin_t;
161
162
163 /** pointer to a _simple_ linked list of plugins registered
164 for this program run
165 */
166 static yfHookPlugin_t *headPlugin = NULL;
167
168 /** keeps a running sum of the total amount of data exported
169 by the plugins, so that there isn't an overrun in the fixed
170 size output buffer
171 */
172 static uint32_t totalPluginExportData = 0;
173
174 /** need to remember the export data size of each hooked plugin, and
175 advance the data array pointer an appropriate amount for each
176 write call
177 */
178 static uint32_t pluginExportSize[YAF_MAX_HOOKS];
179
180 /**
181 * yfHookPacket
182 *
183 *
184 *
185 */
186 gboolean
yfHookPacket(yfFlowKey_t * key,const uint8_t * pkt,size_t caplen,uint16_t iplen,yfTCPInfo_t * tcpinfo,yfL2Info_t * l2info)187 yfHookPacket (
188 yfFlowKey_t * key,
189 const uint8_t * pkt,
190 size_t caplen,
191 uint16_t iplen,
192 yfTCPInfo_t * tcpinfo,
193 yfL2Info_t * l2info)
194 {
195 yfHookPlugin_t *pluginIndex;
196 unsigned int loop;
197
198 pluginIndex = headPlugin;
199
200 for (loop = 0; loop < yaf_hooked; loop++) {
201 if (NULL == pluginIndex) {
202 break;
203 }
204 if (FALSE == (pluginIndex->ufptr.funcPtrs.hookPacket) (key, pkt,
205 caplen, iplen, tcpinfo,
206 l2info))
207 {
208 return FALSE;
209 }
210 pluginIndex = pluginIndex->next;
211 }
212
213 return TRUE;
214 }
215
216 /**
217 * yfHookFlowPacket
218 *
219 *
220 *
221 */
222 void
yfHookFlowPacket(yfFlow_t * flow,yfFlowVal_t * val,const uint8_t * pkt,size_t caplen,uint16_t iplen,yfTCPInfo_t * tcpinfo,yfL2Info_t * l2info)223 yfHookFlowPacket (
224 yfFlow_t * flow,
225 yfFlowVal_t *val,
226 const uint8_t *pkt,
227 size_t caplen,
228 uint16_t iplen,
229 yfTCPInfo_t * tcpinfo,
230 yfL2Info_t * l2info)
231 {
232 yfHookPlugin_t *pluginIndex;
233 unsigned int loop = 0;
234
235 pluginIndex = headPlugin;
236
237 for (loop=0; loop < yaf_hooked; loop++) {
238 if (NULL == pluginIndex) {
239 break;
240 }
241 (pluginIndex->ufptr.funcPtrs.flowPacket)((flow->hfctx)[loop],
242 flow, val, pkt, caplen, iplen,
243 tcpinfo, l2info);
244 pluginIndex = pluginIndex->next;
245 }
246 return;
247 }
248
249 /**
250 * yfHookValidateFlowTab
251 *
252 * Check to make sure plugin can operate with flowtable options
253 *
254 */
255 void
yfHookValidateFlowTab(void ** yfctx,uint32_t max_payload,gboolean uniflow,gboolean silkmode,gboolean applabelmode,gboolean entropymode,gboolean fingerprintmode,gboolean fpExportMode,gboolean udp_max_payload,uint16_t udp_uniflow_port)256 yfHookValidateFlowTab(
257 void **yfctx,
258 uint32_t max_payload,
259 gboolean uniflow,
260 gboolean silkmode,
261 gboolean applabelmode,
262 gboolean entropymode,
263 gboolean fingerprintmode,
264 gboolean fpExportMode,
265 gboolean udp_max_payload,
266 uint16_t udp_uniflow_port)
267 {
268
269 yfHookPlugin_t *pluginIndex;
270 yfHookPlugin_t *currentIndex;
271 yfHookPlugin_t *lastIndex;
272 int loop = 0;
273 GError *err = NULL;
274 int hooked = yaf_hooked;
275
276 pluginIndex = headPlugin;
277 lastIndex = headPlugin;
278
279 for (loop = 0; loop < hooked; loop++) {
280 if (NULL == pluginIndex) {
281 break;
282 }
283 if (FALSE == pluginIndex->ufptr.funcPtrs.validateFlowTab(yfctx[loop],
284 max_payload,
285 uniflow,
286 silkmode,
287 applabelmode,
288 entropymode,
289 fingerprintmode,
290 fpExportMode,
291 udp_max_payload,
292 udp_uniflow_port,
293 &err))
294 {
295 g_warning("Plugin: %s", err->message);
296 currentIndex = pluginIndex;
297 pluginIndex = pluginIndex->next;
298 if (currentIndex == headPlugin) {
299 headPlugin = pluginIndex;
300 } else {
301 lastIndex->next = pluginIndex->next;
302 }
303 free(currentIndex);
304 yaf_hooked--;
305 g_clear_error(&err);
306 } else {
307 pluginIndex = pluginIndex->next;
308 }
309
310 }
311 return;
312 }
313
314
315 /**
316 *
317 *
318 *
319 *
320 */
321 gboolean
yfHookFlowClose(yfFlow_t * flow)322 yfHookFlowClose (
323 yfFlow_t * flow)
324 {
325 yfHookPlugin_t *pluginIndex;
326 unsigned int loop = 0;
327
328 pluginIndex = headPlugin;
329
330 for (loop=0; loop < yaf_hooked; loop++) {
331 if (NULL == pluginIndex) {
332 break;
333 }
334 if (FALSE == pluginIndex->ufptr.funcPtrs.flowClose((flow->hfctx)[loop],
335 flow))
336 {
337 return FALSE;
338 }
339 pluginIndex = pluginIndex->next;
340 }
341
342 return TRUE;
343 }
344
345 /**
346 * yfHookFlowAlloc
347 *
348 * this is called to give the plugins a chance to allocate flow state information
349 * for each flow captured by yaf
350 *
351 * @param flow the pointer to the flow context state structure, but more importantly
352 * in this case, it contains the array of pointers (hfctx) which hold the
353 * plugin context state
354 *
355 */
356 void
yfHookFlowAlloc(yfFlow_t * flow,void ** yfctx)357 yfHookFlowAlloc (
358 yfFlow_t * flow,
359 void **yfctx)
360 {
361 yfHookPlugin_t *pluginIndex;
362 unsigned int loop = 0;
363
364 pluginIndex = headPlugin;
365
366 for (loop=0; loop < yaf_hooked; loop++) {
367 if (NULL == pluginIndex) {
368 break;
369 }
370 (pluginIndex->ufptr.funcPtrs.flowAlloc) (&((flow->hfctx)[loop]),
371 flow, yfctx[loop]);
372 pluginIndex = pluginIndex->next;
373 }
374 return;
375 }
376
377 /**
378 * yfHookFlowFree
379 *
380 * this frees all memory associated with the flow state in all of the attached
381 * plugins
382 *
383 * @param flow a pointer to the flow context structure
384 *
385 */
386 void
yfHookFlowFree(yfFlow_t * flow)387 yfHookFlowFree (
388 yfFlow_t * flow)
389 {
390 yfHookPlugin_t *pluginIndex;
391 unsigned int loop = 0;
392
393 pluginIndex = headPlugin;
394
395 for (loop=0; loop < yaf_hooked; loop++) {
396 if (NULL == pluginIndex) {
397 break;
398 }
399 (pluginIndex->ufptr.funcPtrs.flowFree) ((flow->hfctx)[loop], flow);
400 pluginIndex = pluginIndex->next;
401 }
402
403 return;
404 }
405
406 /**
407 * yfHookGetInfoModel
408 *
409 * returns the IPFIX info model aggregated for all plugins
410 *
411 * @bug it permanently caches an aggregate of all the info model
412 * information from each plugin; some might call this a leak
413 *
414 * @return pointer to an array of fbInfoElement_t that contains
415 * the sum of the IPFIX IE's from all active plugins
416 *
417 */
418 fbInfoElement_t *
yfHookGetInfoModel()419 yfHookGetInfoModel (
420 )
421 {
422 static unsigned int cached = 0;
423 yfHookPlugin_t *pluginIndex;
424 static fbInfoElement_t *cachedIM = NULL;
425 fbInfoElement_t *tempIM = NULL;
426 unsigned int totalIMSize = 0;
427 unsigned int partialIMSize = 0;
428 unsigned int imIndex;
429 unsigned int loop;
430
431 if (0 == yaf_hooked) {
432 return NULL;
433 }
434
435 if (yaf_hooked == cached && 0 != cached) {
436 return cachedIM;
437 } else if (0 != cached ) {
438 g_free(cachedIM);
439 cachedIM = NULL;
440 }
441
442
443 /* iterate through the plugins and on the first pass simply count the
444 number of info model enteries each one has
445 */
446 pluginIndex = headPlugin;
447 for (loop=0; loop < yaf_hooked; loop++) {
448 if (NULL == pluginIndex) {
449 g_error("internal error iterating plugins, cannot continue");
450 break;
451 }
452 tempIM = (pluginIndex->ufptr.funcPtrs.modelGet) ();
453 if (NULL != tempIM) {
454 partialIMSize = 0;
455 for (partialIMSize = 0; (tempIM+partialIMSize)->ref.name != NULL ; partialIMSize++) {
456 }
457 totalIMSize += partialIMSize;
458 }
459 pluginIndex = pluginIndex->next;
460 }
461
462 /* allocate an array of info element enteries to hold the sum total of all
463 IE's from all the plugins. Add 1 to add a NULL entry at the end
464 */
465 cachedIM = g_new(fbInfoElement_t, totalIMSize+1);
466
467 /* now iterate through each plugin and copy each info model entry from
468 the returned array into the local cache copy that was just allocated
469 */
470 pluginIndex = headPlugin;
471 imIndex = 0;
472 for (loop=0; loop < yaf_hooked; loop++) {
473 if (NULL == pluginIndex) {
474 g_error("internal error iterating plugins, cannot continue");
475 break;
476 }
477 tempIM = (pluginIndex->ufptr.funcPtrs.modelGet) ();
478 if (NULL != tempIM) {
479 for (partialIMSize = 0; (tempIM+partialIMSize)->ref.name != NULL; partialIMSize++) {
480 memcpy(cachedIM+imIndex, tempIM+partialIMSize,
481 sizeof(fbInfoElement_t));
482 imIndex++;
483 }
484 }
485 pluginIndex = pluginIndex->next;
486 }
487
488
489 /* copy the NULL element field into the end of the combined $ array, this
490 works because at the end of the previous for loop, partialIMSize should
491 always be pointing to a NULL field, based on the for loop test */
492 memcpy(cachedIM+totalIMSize, tempIM+partialIMSize,
493 sizeof(fbInfoElement_t));
494
495
496 cached = yaf_hooked;
497 return cachedIM;
498 }
499
500 /**
501 * yfHookGetTemplate
502 *
503 * gets the IPFIX info model template for the export data from _all_ the
504 * plugins and turns it into a single template to return. It caches the
505 * results so that future queries are a lot faster. It can invalidate the
506 * cached result if the number of plugins registered changes.
507 *
508 * @return pointer to an array of fbInfoElementSpec_t structures that describe
509 * the info model template
510 *
511 */
512 gboolean
yfHookGetTemplate(fbSession_t * session)513 yfHookGetTemplate (
514 fbSession_t *session)
515 {
516 yfHookPlugin_t *pluginIndex = NULL;
517 int loop;
518 int hooked = yaf_hooked;
519
520 /* first check if we've cached any results yet, if not, do the work
521 then check to see if this result was cached before (good chance it was,
522 but make sure it is up to date)
523 if it's not up to date, through it away and recompute the result
524 */
525
526 if (0 == yaf_hooked) {
527 return TRUE;
528 }
529
530 pluginIndex = headPlugin;
531
532 for (loop = 0; loop < hooked; loop++) {
533 if (NULL == pluginIndex) {
534 g_error("internal error iterating plugins, cannot continue");
535 return FALSE;
536 }
537 if (!(pluginIndex->ufptr.funcPtrs.templateGet) (session)){
538 g_debug("Error Getting Template for Hooks: "
539 "Plugin can not be used");
540 yaf_hooked--;
541 }
542 pluginIndex = pluginIndex->next;
543 }
544
545 return TRUE;
546 }
547
548 /**
549 *
550 *
551 *
552 *
553 */
554 gboolean
yfWriteFlowHook(fbSubTemplateMultiList_t * rec,fbSubTemplateMultiListEntry_t * stml,yfFlow_t * flow,GError ** err)555 yfWriteFlowHook (
556 fbSubTemplateMultiList_t *rec,
557 fbSubTemplateMultiListEntry_t *stml,
558 yfFlow_t * flow,
559 GError ** err)
560 {
561 yfHookPlugin_t *pluginIndex;
562 unsigned int loop;
563
564 pluginIndex = headPlugin;
565
566 for (loop = 0; loop < yaf_hooked; loop++) {
567 if (NULL == pluginIndex) {
568 break;
569 }
570
571 if (FALSE == pluginIndex->ufptr.funcPtrs.flowWrite((flow->hfctx)[loop],
572 rec, stml, flow, err))
573 {
574 return FALSE;
575 }
576 pluginIndex = pluginIndex->next;
577 }
578
579 return TRUE;
580 }
581
582
583
584 /**
585 *yfHookAddNewHook
586 *
587 * adds another hook (plugin) into yaf
588 *
589 * @param hookName the file name of the plugin to load
590 * @param hookOpts a string of command line options for the plugin to process
591 * @param hookConf the filename of the configuration file to load
592 * @param hfctx context for yaf plugins
593 * @param err the error value that gets set if this call didn't work
594 *
595 * @return TRUE if plugin loaded fine, other FALSE
596 *
597 */
598 gboolean
yfHookAddNewHook(const char * hookName,const char * hookOpts,const char * hookConf,void ** yfctx,GError ** err)599 yfHookAddNewHook (
600 const char *hookName,
601 const char *hookOpts,
602 const char *hookConf,
603 void **yfctx,
604 GError ** err)
605 {
606 int rc;
607 lt_dlhandle libHandle;
608 lt_ptr genericLtPtr;
609 unsigned int loop;
610 yfHookPlugin_t *newPlugin = NULL;
611 yfHookPlugin_t *pluginIndex;
612 const struct yfHookMetaData *md;
613
614 /* check to make sure we aren't exceeding the number of allowed hooks */
615 if (YAF_MAX_HOOKS == yaf_hooked) {
616 gerr(err, YAF_ERROR_DOMAIN, YAF_ERROR_IMPL,
617 "Maximum number of plugins exceeded, limit is %d",
618 YAF_MAX_HOOKS);
619 return FALSE;
620 }
621
622 /* initialize the dynamic loader library before we ty to use it, it is
623 harmless to call this one than once */
624 if ((rc = lt_dlinit ())) {
625 gerr(err, YAF_ERROR_DOMAIN, YAF_ERROR_IMPL,
626 "Couldn't initialize LTDL library loader: %s",
627 lt_dlerror ());
628 return FALSE;
629 }
630
631
632 /* load the plugin by name, the library will try platform appropriate
633 extensions */
634 libHandle = lt_dlopenext(hookName);
635 if (NULL == libHandle) {
636 gerr(err, YAF_ERROR_DOMAIN, YAF_ERROR_ARGUMENT,
637 "failed to load plugin \"%s\" with reason: %s", hookName,
638 lt_dlerror ());
639 return FALSE;
640 }
641
642
643 /* build a new handle for the plugin and initialize it */
644 newPlugin = (yfHookPlugin_t *) malloc (sizeof (yfHookPlugin_t));
645 if (NULL == newPlugin) {
646 lt_dlclose(libHandle);
647 gerr(err, YAF_ERROR_DOMAIN, YAF_ERROR_IMPL,
648 "couldn't allocate memory to load plugin\n");
649 return FALSE;
650 }
651 newPlugin->pluginHandle = libHandle;
652 newPlugin->next = NULL;
653
654 /* load in all the function pointers from the library, search by name */
655 for (loop = 0; loop < sizeof (pluginFunctionNames)/sizeof (char *); loop++)
656 {
657 genericLtPtr = lt_dlsym (libHandle, pluginFunctionNames[loop]);
658 if (NULL == genericLtPtr) {
659 break;
660 }
661 newPlugin->ufptr.genPtr[loop] = genericLtPtr;
662 }
663
664 /* make sure all the functions were loaded correctly */
665 if (loop < sizeof (pluginFunctionNames) / sizeof (char *)) {
666 gerr(err, YAF_ERROR_DOMAIN, YAF_ERROR_ARGUMENT,
667 "missing function \"%s\" in %s plugin",
668 pluginFunctionNames[loop], hookName);
669 return FALSE;
670 }
671
672 /* insert this plugin into an empty plugin list */
673 if (NULL == headPlugin) {
674 headPlugin = newPlugin;
675 } else {
676 /*if there is alredy a plugin installed, add this plugin to the list */
677 pluginIndex = headPlugin;
678 while (pluginIndex->next) {
679 pluginIndex = pluginIndex->next;
680 }
681
682 pluginIndex->next = newPlugin;
683 }
684
685
686 /** get the metadata information from the plugin, and make sure that
687 yaf can still operate with it installed */
688 md = newPlugin->ufptr.funcPtrs.getMetaData();
689 if (YAF_HOOK_INTERFACE_VERSION < md->version)
690 {
691 gerr(err, YAF_ERROR_DOMAIN, YAF_ERROR_IMPL,
692 "incompatible plugin version, max supported is %d, plugin is %d",
693 YAF_HOOK_INTERFACE_VERSION, md->version);
694 return FALSE;
695 } else if (YAF_HOOK_INTERFACE_VERSION != md->version) {
696 g_warning("Incompatible plugin version.");
697 g_warning("YAF uses version %d, Plugin is version: %d",
698 YAF_HOOK_INTERFACE_VERSION, md->version);
699 g_warning("Make sure you set LTDL_LIBRARY_PATH to correct location.");
700 g_warning("yaf continuing...some functionality may not be available.");
701 }
702
703 if (YAF_HOOKS_MAX_EXPORT < totalPluginExportData + md->exportDataSize) {
704 gerr(err, YAF_ERROR_DOMAIN, YAF_ERROR_IMPL,
705 "maximum plugin export data limit exceeded");
706 return FALSE;
707 }
708 #ifndef YAF_ENABLE_APPLABEL
709 if (md->requireAppLabel == 1) {
710 gerr(err, YAF_ERROR_DOMAIN, YAF_ERROR_IMPL,
711 "this plugin requires --enable-applabel");
712 return FALSE;
713 }
714 #endif
715
716 /* record the export size for this plugin, and update the running total */
717 pluginExportSize[yaf_hooked] = md->exportDataSize;
718 totalPluginExportData += md->exportDataSize;
719
720 /* pass hookConf to plugin */
721 newPlugin->ufptr.funcPtrs.setPluginConf(hookConf, &(yfctx[yaf_hooked]));
722
723 /* pass hookOpts to plugin */
724 newPlugin->ufptr.funcPtrs.setPluginOpt(hookOpts, yfctx[yaf_hooked]);
725
726 /** mark that another plugin has been hooked */
727 yaf_hooked++;
728
729 return TRUE;
730 }
731
732 #if YAF_ENABLE_APPLABEL
733 /**
734 * yfHookScanPayload
735 *
736 *
737 */
738 void
yfHookScanPayload(yfFlow_t * flow,const uint8_t * pkt,size_t caplen,pcre * expression,uint16_t offset,uint16_t elementID,uint16_t applabel)739 yfHookScanPayload (
740 yfFlow_t *flow,
741 const uint8_t *pkt,
742 size_t caplen,
743 pcre *expression,
744 uint16_t offset,
745 uint16_t elementID,
746 uint16_t applabel)
747
748 {
749 yfHookPlugin_t *pluginIndex;
750 unsigned int loop = 0;
751
752 pluginIndex = headPlugin;
753
754 for (loop = 0; loop < yaf_hooked; loop++) {
755 if (NULL == pluginIndex) {
756 break;
757 }
758 (pluginIndex->ufptr.funcPtrs.scanPayload)((flow->hfctx)[loop], flow,
759 pkt, caplen, expression,
760 offset, elementID, applabel);
761
762 pluginIndex = pluginIndex->next;
763 }
764 return;
765 }
766
767 #endif
768
769 /**
770 *yfHookGetTemplateCount
771 *
772 *
773 */
774 uint8_t
yfHookGetTemplateCount(yfFlow_t * flow)775 yfHookGetTemplateCount(
776 yfFlow_t *flow)
777 {
778
779 uint8_t count = 0;
780 unsigned int loop;
781 yfHookPlugin_t *pluginIndex;
782
783 pluginIndex = headPlugin;
784
785 for (loop = 0; loop < yaf_hooked; loop++) {
786 if (NULL == pluginIndex) {
787 break;
788 }
789 count += ((pluginIndex->ufptr.funcPtrs.getTemplateCount)((flow->hfctx)[loop], flow));
790 pluginIndex = pluginIndex->next;
791 }
792 return count;
793 }
794
795 /**
796 * yfHookFreeLists
797 *
798 *
799 */
800 void
yfHookFreeLists(yfFlow_t * flow)801 yfHookFreeLists(
802 yfFlow_t *flow)
803 {
804 unsigned int loop;
805 yfHookPlugin_t *pluginIndex;
806
807 pluginIndex = headPlugin;
808
809 for (loop = 0; loop < yaf_hooked; loop++) {
810 if (NULL == pluginIndex) {
811 break;
812 }
813 (pluginIndex->ufptr.funcPtrs.freeLists)((flow->hfctx)[loop], flow);
814 pluginIndex = pluginIndex->next;
815 }
816 }
817
818 #endif
819