1 /* $Id$ */
2
3 /*
4 ** Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
5 ** Copyright (C) 2005-2013 Sourcefire, Inc.
6 ** AUTHOR: Steven Sturges
7 **
8 ** This program is free software; you can redistribute it and/or modify
9 ** it under the terms of the GNU General Public License Version 2 as
10 ** published by the Free Software Foundation. You may not use, modify or
11 ** distribute this program under any other version of the GNU General
12 ** Public License.
13 **
14 ** This program is distributed in the hope that it will be useful,
15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ** GNU General Public License for more details.
18 **
19 ** You should have received a copy of the GNU General Public License
20 ** along with this program; if not, write to the Free Software
21 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 */
23
24 /* session_expect.c
25 *
26 * Purpose: Handle hash table storage and lookups for ignoring
27 * entire data streams.
28 *
29 * Arguments:
30 *
31 * Effect:
32 *
33 * Comments:
34 *
35 * Any comments?
36 *
37 */
38 #include <sys/types.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <errno.h>
42 #ifndef WIN32
43 #include <sys/socket.h>
44 #include <netinet/in.h>
45 #include <arpa/inet.h>
46 #endif /* WIN32 */
47 #include <time.h>
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "snort.h"
54 #include "session_api.h"
55 #include "stream_api.h"
56 #include "session_expect.h"
57 #include "sf_types.h"
58 #include "snort_debug.h"
59 #include "decode.h"
60 #include "sfxhash.h"
61 #include "util.h"
62 #include "ipv6_port.h"
63 #include "sfPolicy.h"
64 #include "sfPolicyUserData.h"
65 #include "sfdaq.h"
66 #include "stream5_ha.h"
67
68 /* Reasonably small, and power of 2 */
69 #define EXPECT_HASH_SIZE 1024
70
71 /* Number of unique ExpectSessionData stored in each hash entry. */
72 #define NUM_SESSION_DATA_MAX 8
73 #define STREAM_EXPECT_CLEAN_LIMIT 5
74
75 /* In spp_stream5.c, stream callback ID (stream_cb_idx) is initially 1
76 * and only increments. */
77 #define INVALIDCBID 0
78
79 typedef struct _ExpectedSessionData
80 {
81 uint32_t preprocId;
82 unsigned cbId;
83 Stream_Event se;
84 void *appData;
85 void (*appDataFreeFn)(void *);
86 struct _ExpectedSessionData *next;
87 } ExpectedSessionData;
88
89 typedef struct _ExpectedSessionDataList
90 {
91 ExpectedSessionData *data;
92 struct _ExpectedSessionDataList *next;
93 } ExpectedSessionDataList;
94
95 typedef struct _ExpectHashKey
96 {
97 struct in6_addr ip1;
98 struct in6_addr ip2;
99 uint16_t port1;
100 uint16_t port2;
101 uint32_t protocol;
102 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
103 uint32_t carrierid;
104 #endif
105 } ExpectHashKey;
106
107 typedef struct _ExpectNode
108 {
109 time_t expires;
110 unsigned data_list_count;
111 int16_t appId;
112 char reversed_key;
113 char direction;
114 ExpectedSessionDataList *data_list;
115 ExpectedSessionDataList *data_list_tail;
116 struct _ExpectNode* manditory_next;
117 } ExpectNode;
118
119 typedef struct _MandatoryEarlySessionCreator
120 {
121 struct _MandatoryEarlySessionCreator* next;
122 MandatoryEarlySessionCreatorFn callback;
123 } MandatoryEarlySessionCreator;
124
125 /* The hash table of expected channels */
126 static SFXHASH *channelHash = NULL;
127
freeExpectedSessionData(ExpectedSessionData * data)128 static void freeExpectedSessionData(ExpectedSessionData *data)
129 {
130 ExpectedSessionData *tmp;
131
132 while ((tmp = data))
133 {
134 data = tmp->next;
135 if (tmp->appData && tmp->appDataFreeFn)
136 tmp->appDataFreeFn(tmp->appData);
137 free(tmp);
138 }
139 }
140
freeNodeAppData(ExpectNode * node)141 static void freeNodeAppData(ExpectNode *node)
142 {
143 ExpectedSessionDataList *data_list;
144
145 while ((data_list = node->data_list))
146 {
147 node->data_list = data_list->next;
148 freeExpectedSessionData(data_list->data);
149 free(data_list);
150 }
151 node->data_list_tail = NULL;
152 node->data_list_count = 0;
153 }
154
freeHashNode(void * k,void * p)155 static int freeHashNode(void *k, void *p)
156 {
157 freeNodeAppData((ExpectNode*)p);
158 return 0;
159 }
160
161 static sfaddr_t zeroed;
162
163 /**Either expect or expect future session.
164 *
165 * Preprocessors may add sessions to be expected altogether or to be associated with some data. For example,
166 * FTP preprocessor may add data channel that should be expected. Alternatively, FTP preprocessor may add
167 * session with appId FTP-DATA.
168 *
169 * It is assumed that only one of cliPort or srvPort should be known (!0). This violation of this assumption
170 * will cause hash collision that will cause some session to be not expected and expected. This will occur only
171 * rarely and therefore acceptable design optimization.
172 *
173 * Also, appId is assumed to be consistent between different preprocessors. Each session can be assigned only
174 * one AppId. When new appId mismatches existing appId, new appId and associated data is not stored.
175 *
176 * @param cliIP - client IP address. All preprocessors must have consistent view of client side of a session.
177 * @param cliPort - client port number
178 * @param srvIP - server IP address. All preprocessors must have consisten view of server side of a session.
179 * @param srvPort - server port number
180 * @param protocol - IPPROTO_TCP or IPPROTO_UDP.
181 * @param direction - direction of session. Assumed that direction value for session being expected or expected will
182 * remain same across different calls to this function.
183 * @param expiry - session expiry in seconds.
184 */
StreamExpectAddChannel(const Packet * ctrlPkt,sfaddr_t * cliIP,uint16_t cliPort,sfaddr_t * srvIP,uint16_t srvPort,char direction,uint8_t flags,uint8_t protocol,uint32_t timeout,int16_t appId,uint32_t preprocId,void * appData,void (* appDataFreeFn)(void *),ExpectNode ** packetExpectedNode)185 int StreamExpectAddChannel(const Packet *ctrlPkt, sfaddr_t* cliIP, uint16_t cliPort,
186 sfaddr_t* srvIP, uint16_t srvPort, char direction, uint8_t flags,
187 uint8_t protocol, uint32_t timeout, int16_t appId, uint32_t preprocId,
188 void *appData, void (*appDataFreeFn)(void*), ExpectNode** packetExpectedNode)
189 {
190 return StreamExpectAddChannelPreassignCallback(ctrlPkt, cliIP, cliPort, srvIP, srvPort,
191 direction, flags, protocol, timeout, appId, preprocId,
192 appData, appDataFreeFn, INVALIDCBID, SE_REXMIT, packetExpectedNode);
193 }
194
StreamExpectAddChannelPreassignCallback(const Packet * ctrlPkt,sfaddr_t * cliIP,uint16_t cliPort,sfaddr_t * srvIP,uint16_t srvPort,char direction,uint8_t flags,uint8_t protocol,uint32_t timeout,int16_t appId,uint32_t preprocId,void * appData,void (* appDataFreeFn)(void *),unsigned cbId,Stream_Event se,ExpectNode ** packetExpectedNode)195 int StreamExpectAddChannelPreassignCallback(const Packet *ctrlPkt, sfaddr_t* cliIP, uint16_t cliPort,
196 sfaddr_t* srvIP, uint16_t srvPort, char direction, uint8_t flags,
197 uint8_t protocol, uint32_t timeout, int16_t appId, uint32_t preprocId,
198 void *appData, void (*appDataFreeFn)(void*), unsigned cbId,
199 Stream_Event se, ExpectNode** packetExpectedNode)
200 {
201 ExpectHashKey hashKey;
202 SFXHASH_NODE *hash_node;
203 ExpectNode new_node;
204 ExpectNode *node;
205 ExpectedSessionDataList *data_list;
206 ExpectedSessionData *data;
207 char reversed_key;
208 SFIP_RET rval;
209 time_t now = ctrlPkt->pkth->ts.tv_sec;
210
211 if (cliPort != UNKNOWN_PORT)
212 srvPort = UNKNOWN_PORT;
213
214 #if defined(DEBUG_MSGS)
215 {
216 char src_ip[INET6_ADDRSTRLEN];
217 char dst_ip[INET6_ADDRSTRLEN];
218
219 sfip_ntop(cliIP, src_ip, sizeof(src_ip));
220 sfip_ntop(srvIP, dst_ip, sizeof(dst_ip));
221 DebugMessage(DEBUG_STREAM, "Creating expected %s-%u -> %s-%u %u appid %d preproc %u\n", src_ip,
222 cliPort, dst_ip, srvPort, protocol, appId, preprocId);
223 }
224 #endif
225
226 /* Add the info to a tree that marks this channel as one to expect.
227 * Only one of the port values may be UNKNOWN_PORT.
228 * As a sanity check, the IP addresses may not be 0 or 255.255.255.255.
229 */
230 if ((cliPort == UNKNOWN_PORT) && (srvPort == UNKNOWN_PORT))
231 return -1;
232
233 if (sfaddr_family(cliIP) == AF_INET)
234 {
235 if (!sfaddr_get_ip4_value(cliIP) || sfaddr_get_ip4_value(cliIP) == 0xFFFFFFFF)
236 {
237 return -1;
238 }
239 }
240 else if (sfip_fast_eq6(cliIP, IP_ARG(zeroed)))
241 {
242 return -1;
243 }
244
245 if (sfaddr_family(srvIP) == AF_INET)
246 {
247 if (!sfaddr_get_ip4_value(srvIP) || sfaddr_get_ip4_value(srvIP) == 0xFFFFFFFF)
248 {
249 return -1;
250 }
251 }
252 else if (sfip_fast_eq6(srvIP, IP_ARG(zeroed)))
253 {
254 return -1;
255 }
256
257 rval = sfip_compare(cliIP, srvIP);
258 if (rval == SFIP_LESSER || (rval == SFIP_EQUAL && cliPort < srvPort))
259 {
260 sfaddr_copy_to_raw(&hashKey.ip1, cliIP);
261 hashKey.port1 = cliPort;
262 sfaddr_copy_to_raw(&hashKey.ip2, srvIP);
263 hashKey.port2 = srvPort;
264 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
265 hashKey.carrierid = GET_OUTER_IPH_PROTOID(ctrlPkt, pkth);
266 #endif
267 reversed_key = 0;
268 }
269 else
270 {
271 sfaddr_copy_to_raw(&hashKey.ip1, srvIP);
272 hashKey.port1 = srvPort;
273 sfaddr_copy_to_raw(&hashKey.ip2, cliIP);
274 hashKey.port2 = cliPort;
275 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
276 hashKey.carrierid = GET_OUTER_IPH_PROTOID(ctrlPkt, pkth);
277 #endif
278 reversed_key = 1;
279 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "reversed\n"););
280 }
281
282 /* Actually add it to the hash table with a timestamp of now.
283 * so we can expire entries that are older than a configurable
284 * time. Those entries will be for sessions that we missed or
285 * never occured. Should not keep the entry around indefinitely.
286 */
287 hashKey.protocol = (uint32_t)protocol;
288
289 hash_node = sfxhash_find_node(channelHash, &hashKey);
290 if( hash_node )
291 {
292 if( !( node = hash_node->data ) )
293 sfxhash_free_node( channelHash, hash_node );
294 }
295 else
296 node = NULL;
297
298 if( node )
299 {
300 int expired;
301
302 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "exists\n"););
303 /*
304 * This handles the case where there is already an entry
305 * for this key (IP addresses/port). It could occur when
306 * multiple users from behind a NAT'd Firewall all go to the
307 * same site when in FTP Port mode. To get around this issue,
308 * we keep a counter of the number of pending open channels
309 * with the same known endpoints (2 IPs & a port). When that
310 * channel is actually opened, the counter is decremented, and
311 * the entry is removed when the counter hits 0.
312 * Because all of this is single threaded, there is no potential
313 * for a race condition.
314 */
315 expired = ( node->expires != 0 ) && ( now > node->expires );
316 if( expired )
317 {
318 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "expected session is expired\n"););
319 //free older data
320 freeNodeAppData( node );
321 node->appId = appId;
322 }
323
324 if( node->appId != appId )
325 {
326 if( node->appId && appId )
327 {
328 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "expected session has different appId %d != %d\n",
329 node->appId, appId););
330 return -1;
331 }
332 node->appId = appId;
333 }
334
335 if( node->data_list_count >= NUM_SESSION_DATA_MAX )
336 {
337 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "expected session has maximum data slots used\n"););
338 return -1;
339 }
340
341 if( ( data_list = node->data_list_tail ) )
342 {
343 for( data = data_list->data; data && data->preprocId != preprocId; data = data->next );
344 if( data )
345 {
346 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Found an existing occurance\n"););
347 data_list = NULL;
348 }
349 }
350
351 data = malloc( sizeof( *data ) );
352 if( !data )
353 {
354 if( !node->data_list_count )
355 sfxhash_free_node( channelHash, hash_node );
356
357 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Memory alloc error\n"););
358 return -1;
359 }
360 data->appData = appData;
361 data->cbId = cbId;
362 data->se = se;
363 data->appDataFreeFn = appDataFreeFn;
364 data->preprocId = preprocId;
365
366 if( !data_list )
367 {
368 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Adding new occurance\n"););
369 data_list = calloc( 1, sizeof( *data_list ) );
370 if( !data_list )
371 {
372 if( !node->data_list_count )
373 sfxhash_free_node( channelHash, hash_node );
374
375 free( data );
376 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Memory alloc error\n"););
377 return -1;
378 }
379
380 if( node->data_list_tail )
381 {
382 node->data_list_tail->next = data_list;
383 node->data_list_tail = data_list;
384 }
385 else
386 node->data_list = node->data_list_tail = data_list;
387
388 node->data_list_count++;
389 }
390 #ifdef DEBUG_MSGS
391 else
392 {
393 DebugMessage(DEBUG_STREAM, "Using an existing occurance\n");
394 }
395 #endif
396 data->next = data_list->data;
397 data_list->data = data;
398
399 if( flags & EXPECT_FLAG_ALWAYS )
400 node->expires = 0;
401 else
402 node->expires = now + timeout;
403 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Updating expect channel node with %u occurances\n", node->data_list_count););
404 }
405 else
406 {
407 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Adding expect channel node\n"););
408
409 new_node.appId = appId;
410 new_node.reversed_key = reversed_key;
411 new_node.direction = direction;
412 /* now + 5 minutes (configurable?)
413 *
414 * use the time that we keep sessions around
415 * since this info would effectively be invalid
416 * after that anyway because the session that
417 * caused this will be gone.
418 */
419 if( flags & EXPECT_FLAG_ALWAYS )
420 new_node.expires = 0;
421 else
422 new_node.expires = now + timeout;
423
424 data = malloc( sizeof( *data ) );
425 if( !data )
426 {
427 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Memory alloc error\n"););
428 return -1;
429 }
430 data->appData = appData;
431 data->cbId = cbId;
432 data->se = se;
433 data->appDataFreeFn = appDataFreeFn;
434 data->preprocId = preprocId;
435 data->next = NULL;
436 data_list = malloc( sizeof( *data_list ) );
437
438 if( !data_list )
439 {
440 free( data );
441 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Memory alloc error\n"););
442 return -1;
443 }
444 data_list->next = NULL;
445 data_list->data = data;
446 new_node.data_list_count = 1;
447 new_node.data_list = new_node.data_list_tail = data_list;
448
449 /* Add it to the table */
450 if( sfxhash_add( channelHash, &hashKey, &new_node ) != SFXHASH_OK )
451 {
452 /* Uh, shouldn't get here...
453 * There is already a node or couldn't alloc space
454 * for key. This means bigger problems, but fail
455 * gracefully.
456 */
457 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
458 "Failed to add channel node to expected hash table\n"););
459 free( data_list );
460 free( data );
461 return -1;
462 }
463 node = (ExpectNode*)sfxhash_mru(channelHash);
464
465 #ifdef HAVE_DAQ_DP_ADD_DC
466 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
467 "Adding expected to DAQ\n"););
468 // when adding expected channel send expected flow parameters to the DAQ
469 // for forwarding to firmware...
470 {
471 DAQ_DC_Params params;
472
473 memset(¶ms, 0, sizeof(params));
474 params.flags = 0;
475 params.timeout_ms = 1 * 1000; // 1 second
476 if( cliPort == UNKNOWN_PORT )
477 DAQ_Add_Dynamic_Protocol_Channel( ctrlPkt, cliIP, cliPort, srvIP, srvPort, protocol, ¶ms );
478 else
479 DAQ_Add_Dynamic_Protocol_Channel( ctrlPkt, srvIP, srvPort, cliIP, cliPort, protocol, ¶ms );
480 }
481 #endif
482
483 }
484
485 if (packetExpectedNode && snort_conf->mandatoryESCreators && node)
486 {
487 ExpectNode* expectedNode;
488 MandatoryEarlySessionCreator* creator;
489
490 for (expectedNode = *packetExpectedNode;
491 expectedNode && node != expectedNode;
492 expectedNode = expectedNode->manditory_next);
493
494 if (!expectedNode)
495 {
496 node->manditory_next = *packetExpectedNode;
497 *packetExpectedNode = node;
498 }
499 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Using expected node %p with packet expected %p\n", node, *packetExpectedNode););
500 for (creator = snort_conf->mandatoryESCreators; creator; creator = creator->next)
501 creator->callback(ctrlPkt->ssnptr, node);
502 }
503
504 return 0;
505 }
506
getNextExpectedNode(ExpectNode * expectedNode)507 ExpectNode* getNextExpectedNode(ExpectNode* expectedNode)
508 {
509 if (expectedNode)
510 return expectedNode->manditory_next;
511 return NULL;
512 }
513
getApplicationDataFromExpectedNode(ExpectNode * expectedNode,uint32_t preprocId)514 void* getApplicationDataFromExpectedNode(ExpectNode* expectedNode, uint32_t preprocId)
515 {
516 ExpectedSessionData *data;
517
518 if (!expectedNode->data_list_tail)
519 return NULL;
520
521 for (data = expectedNode->data_list_tail->data;
522 data && data->preprocId != preprocId;
523 data = data->next);
524 return data ? data->appData : NULL;
525 }
526
addApplicationDataToExpectedNode(ExpectNode * expectedNode,uint32_t preprocId,void * appData,void (* appDataFreeFn)(void *))527 int addApplicationDataToExpectedNode(ExpectNode* expectedNode, uint32_t preprocId,
528 void *appData, void (*appDataFreeFn)(void*))
529 {
530 ExpectedSessionData *data;
531
532 if (!expectedNode->data_list_tail)
533 return -1;
534
535 if (expectedNode->data_list_count >= NUM_SESSION_DATA_MAX)
536 {
537 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "expected session has maximum data slots used\n"););
538 return -1;
539 }
540
541 data = malloc( sizeof( *data ) );
542 if( !data )
543 {
544 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Memory alloc error\n"););
545 return -1;
546 }
547 data->appData = appData;
548 data->cbId = INVALIDCBID;
549 data->se = SE_REXMIT;
550 data->appDataFreeFn = appDataFreeFn;
551 data->preprocId = preprocId;
552 data->next = expectedNode->data_list_tail->data;
553 expectedNode->data_list_tail->data = data;
554 expectedNode->data_list_count++;
555
556 return 0;
557
558 }
559
registerMandatoryEarlySessionCreator(struct _SnortConfig * sc,MandatoryEarlySessionCreatorFn callback)560 void registerMandatoryEarlySessionCreator(struct _SnortConfig *sc,
561 MandatoryEarlySessionCreatorFn callback)
562 {
563 MandatoryEarlySessionCreator* mandatoryESCreator;
564
565 for (mandatoryESCreator = sc->mandatoryESCreators;
566 mandatoryESCreator && mandatoryESCreator->callback != callback;
567 mandatoryESCreator = mandatoryESCreator->next);
568
569 if (mandatoryESCreator)
570 {
571 WarningMessage("Mandatory early session creator callback function is already registered");
572 return;
573 }
574
575 mandatoryESCreator = (MandatoryEarlySessionCreator*)SnortAlloc(sizeof(*mandatoryESCreator));
576 mandatoryESCreator->callback = callback;
577 mandatoryESCreator->next = sc->mandatoryESCreators;
578 sc->mandatoryESCreators = mandatoryESCreator;
579 }
580
FreeMandatoryEarlySessionCreators(MandatoryEarlySessionCreator * mandatoryESCreators)581 void FreeMandatoryEarlySessionCreators(MandatoryEarlySessionCreator* mandatoryESCreators)
582 {
583 MandatoryEarlySessionCreator* mandatoryESCreator;
584
585 while ((mandatoryESCreator = mandatoryESCreators))
586 {
587 mandatoryESCreators = mandatoryESCreator->next;
588 free(mandatoryESCreator);
589 }
590 }
591
StreamExpectIsExpected(Packet * p,SFXHASH_NODE ** expected_hash_node)592 int StreamExpectIsExpected(Packet *p, SFXHASH_NODE **expected_hash_node)
593 {
594 sfaddr_t* srcIP;
595 sfaddr_t* dstIP;
596 SFXHASH_NODE *hash_node;
597 ExpectHashKey hashKey;
598 ExpectNode *node;
599 SFIP_RET rval;
600 uint16_t port1;
601 uint16_t port2;
602 char reversed_key;
603
604 /* No hash table, or its empty? Get out of dodge. */
605 if (!sfxhash_count(channelHash))
606 {
607 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "No expected sessions\n"););
608 return 0;
609 }
610
611 srcIP = GET_SRC_IP(p);
612 dstIP = GET_DST_IP(p);
613
614 #if defined(DEBUG_MSGS)
615 {
616 char src_ip[INET6_ADDRSTRLEN];
617 char dst_ip[INET6_ADDRSTRLEN];
618
619 sfip_ntop(srcIP, src_ip, sizeof(src_ip));
620 sfip_ntop(dstIP, dst_ip, sizeof(dst_ip));
621 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
622 DebugMessage(DEBUG_STREAM, "Checking isExpected %s-%u -> %s-%u %u %u\n", src_ip,
623 p->sp, dst_ip, p->dp, GET_IPH_PROTO(p), GET_OUTER_IPH_PROTOID(p, pkth));
624 #else
625 DebugMessage(DEBUG_STREAM, "Checking isExpected %s-%u -> %s-%u %u\n", src_ip,
626 p->sp, dst_ip, p->dp, GET_IPH_PROTO(p));
627 #endif
628 }
629 #endif
630
631 rval = sfip_compare(dstIP, srcIP);
632 if (rval == SFIP_LESSER || (rval == SFIP_EQUAL && p->dp < p->sp))
633 {
634 sfaddr_copy_to_raw(&hashKey.ip1, dstIP);
635 sfaddr_copy_to_raw(&hashKey.ip2, srcIP);
636 hashKey.port1 = p->dp;
637 hashKey.port2 = 0;
638 port1 = 0;
639 port2 = p->sp;
640 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
641 hashKey.carrierid = GET_OUTER_IPH_PROTOID(p, pkth);
642 #endif
643 reversed_key = 1;
644 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "reversed\n"););
645 }
646 else
647 {
648 sfaddr_copy_to_raw(&hashKey.ip1, srcIP);
649 sfaddr_copy_to_raw(&hashKey.ip2, dstIP);
650 hashKey.port1 = 0;
651 hashKey.port2 = p->dp;
652 port1 = p->sp;
653 port2 = 0;
654 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
655 hashKey.carrierid = GET_OUTER_IPH_PROTOID(p, pkth);
656 #endif
657 reversed_key = 0;
658 }
659 hashKey.protocol = (uint32_t)GET_IPH_PROTO(p);
660
661 hash_node = sfxhash_find_node(channelHash, &hashKey);
662 if (hash_node)
663 {
664 if (!(node = hash_node->data))
665 sfxhash_free_node(channelHash, hash_node);
666 }
667 else
668 node = NULL;
669 if (!node)
670 {
671 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Could not find with dp\n"););
672 hashKey.port1 = port1;
673 hashKey.port2 = port2;
674 hash_node = sfxhash_find_node(channelHash, &hashKey);
675 if (hash_node)
676 {
677 if (!(node = hash_node->data))
678 sfxhash_free_node(channelHash, hash_node);
679 }
680 }
681 if (node)
682 {
683 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Found expected\n"););
684 if (node->expires && p->pkth->ts.tv_sec > node->expires)
685 {
686 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Expected expired\n"););
687 sfxhash_free_node(channelHash, hash_node);
688 return 0;
689 }
690 if (!node->data_list)
691 {
692 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Expected session has no data???\n"););
693 sfxhash_free_node(channelHash, hash_node);
694 return 0;
695 }
696 /* Make sure the packet direction is correct */
697 switch (node->direction)
698 {
699 case SSN_DIR_BOTH:
700 break;
701 case SSN_DIR_FROM_CLIENT:
702 case SSN_DIR_FROM_SERVER:
703 if (node->reversed_key != reversed_key)
704 {
705 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Expected is the wrong direction\n"););
706 return 0;
707 }
708 break;
709 }
710 *expected_hash_node = hash_node;
711 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "using expected\n"););
712 return 1;
713 }
714 else
715 {
716 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Could not find with sp\n"););
717 }
718 return 0;
719 }
720
StreamExpectProcessNode(Packet * p,SessionControlBlock * lws,SFXHASH_NODE * expected_hash_node)721 char StreamExpectProcessNode(Packet *p, SessionControlBlock* lws, SFXHASH_NODE *expected_hash_node)
722 {
723 SFXHASH_NODE *hash_node;
724 ExpectNode *node;
725 ExpectedSessionDataList *data_list;
726 ExpectedSessionData *data;
727 time_t now;
728 int retVal = SSN_DIR_NONE;
729 unsigned i;
730
731 node = expected_hash_node->data;
732 node->data_list_count--;
733 data_list = node->data_list;
734 node->data_list = data_list->next;
735
736 while ((data = data_list->data))
737 {
738 data_list->data = data->next;
739 if (data->appData &&
740 session_api->set_application_data(lws, data->preprocId, data->appData, data->appDataFreeFn)
741 && data->appDataFreeFn)
742 {
743 data->appDataFreeFn(data->appData);
744 }
745
746 if(data->cbId != INVALIDCBID)
747 {
748 stream_api->set_event_handler(lws, data->cbId, data->se);
749 p->packet_flags |= PKT_EARLY_REASSEMBLY;
750 }
751
752 free(data);
753 }
754 free(data_list);
755
756 /* If this is 0, we're ignoring, otherwise setting id of new session */
757 if (!node->appId)
758 retVal = node->direction;
759 #ifdef TARGET_BASED
760 else if (lws->ha_state.application_protocol != node->appId)
761 {
762 lws->ha_state.application_protocol = node->appId;
763 #ifdef ENABLE_HA
764 lws->ha_flags |= HA_FLAG_MODIFIED;
765 #endif
766 session_api->set_application_protocol_id( lws, node->appId );
767 p->application_protocol_ordinal = node->appId;
768 }
769 #endif
770
771 #if defined(DEBUG_MSGS)
772 {
773 sfaddr_t* srcIP;
774 sfaddr_t* dstIP;
775 char src_ip[INET6_ADDRSTRLEN];
776 char dst_ip[INET6_ADDRSTRLEN];
777
778 srcIP = GET_SRC_IP(p);
779 dstIP = GET_DST_IP(p);
780 sfip_ntop(srcIP, src_ip, sizeof(src_ip));
781 sfip_ntop(dstIP, dst_ip, sizeof(dst_ip));
782 DebugMessage(DEBUG_STREAM,
783 "Ignoring channel %s:%d --> %s:%d, policyId %d\n",
784 src_ip, p->sp,
785 dst_ip, p->dp, getNapRuntimePolicy());
786 }
787 #endif
788
789 if (!node->data_list)
790 sfxhash_free_node(channelHash, expected_hash_node);
791
792 now = p->pkth->ts.tv_sec;
793 /* Clean the hash table of at most STREAM_EXPECT_CLEAN_LIMIT expired nodes */
794 for (i = 0; i < STREAM_EXPECT_CLEAN_LIMIT && (hash_node = sfxhash_lru_node(channelHash)); i++)
795 {
796 node = hash_node->data;
797 if (node)
798 {
799 if (node->expires && now > node->expires)
800 {
801 /* sayonara baby... */
802 sfxhash_free_node(channelHash, hash_node);
803 }
804 else
805 {
806 /* This one's not expired, fine...
807 * no need to prune further.
808 */
809 break;
810 }
811 }
812 }
813
814 return retVal;
815 }
816
StreamExpectCheck(Packet * p,SessionControlBlock * lws)817 char StreamExpectCheck(Packet *p, SessionControlBlock* lws)
818 {
819 SFXHASH_NODE *hash_node;
820
821 if (!StreamExpectIsExpected(p, &hash_node))
822 return SSN_DIR_NONE;
823
824 return StreamExpectProcessNode(p, lws, hash_node);
825 }
826
StreamExpectInit(uint32_t max)827 void StreamExpectInit (uint32_t max)
828 {
829 if (!channelHash)
830 {
831 // number of entries * overhead per entry
832 max *= (sizeof(SFXHASH_NODE) + sizeof(long) +
833 sizeof(ExpectHashKey) + sizeof(ExpectNode));
834
835 // add in fixed cost of hash table
836 max += (sizeof(SFXHASH_NODE**) * EXPECT_HASH_SIZE) + sizeof(long);
837
838 channelHash = sfxhash_new(
839 EXPECT_HASH_SIZE, sizeof(ExpectHashKey),
840 sizeof(ExpectNode), max, 1, freeHashNode, freeHashNode, 1);
841
842 if (!channelHash)
843 FatalError("Failed to create the expected channel hash table.\n");
844 }
845
846 memset(&zeroed, 0, sizeof(zeroed));
847 }
848
StreamExpectCleanup(void)849 void StreamExpectCleanup(void)
850 {
851 if (channelHash)
852 {
853 sfxhash_delete(channelHash);
854 channelHash = NULL;
855 }
856 }
857
858