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(&params, 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, &params );
478             else
479                DAQ_Add_Dynamic_Protocol_Channel( ctrlPkt, srvIP, srvPort, cliIP, cliPort, protocol, &params );
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