00001 //--------------------------------------------------------------------------
00002 // Copyright (C) 2014-2017 Cisco and/or its affiliates. All rights reserved.
00003 // Copyright (C) 2005-2013 Sourcefire, Inc.
00004 //
00005 // This program is free software; you can redistribute it and/or modify it
00006 // under the terms of the GNU General Public License Version 2 as published
00007 // by the Free Software Foundation. You may not use, modify or distribute
00008 // this program under any other version of the GNU General Public License.
00009 //
00010 // This program is distributed in the hope that it will be useful, but
00011 // WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00013 // General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License along
00016 // with this program; if not, write to the Free Software Foundation, Inc.,
00017 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018 //--------------------------------------------------------------------------
00019
00020 #ifdef HAVE_CONFIG_H
00021 #include "config.h"
00022 #endif
00023
00024 #include "udp_session.h"
00025
00026 #include "flow/session.h"
00027 #include "perf_monitor/flow_ip_tracker.h"
00028 #include "profiler/profiler_defs.h"
00029 #include "protocols/packet.h"
00030
00031 #include "udp_ha.h"
00032 #include "udp_module.h"
00033 #include "stream_udp.h"
00034
00035 // NOTE: sender is assumed to be client
00036 // responder is assumed to be server
00037
00038 const PegInfo udp_pegs[] =
00039 {
00040 SESSION_PEGS("udp"),
00041 { CountType::SUM, "ignored", "udp packets ignored" },
00042 { CountType::END, nullptr, nullptr }
00043 };
00044
00045 THREAD_LOCAL UdpStats udpStats;
00046 THREAD_LOCAL ProfileStats udp_perf_stats;
00047
00048 //-------------------------------------------------------------------------
00049
00050 static void UdpSessionCleanup(Flow* lwssn)
00051 {
00052 if ( lwssn->ssn_state.session_flags & SSNFLAG_SEEN_SENDER )
00053 udpStats.released++;
00054 }
00055
00056 static int ProcessUdp(
00057 Flow* lwssn, Packet* p, StreamUdpConfig*, SFXHASH_NODE*)
00058 {
00059 assert(lwssn->pkt_type == PktType::UDP);
00060
00061 if ( Stream::blocked_flow(lwssn, p) )
00062 return 0;
00063
00064 if ( Stream::ignored_flow(lwssn, p) )
00065 {
00066 udpStats.ignored++;
00067 return 0;
00068 }
00069
00070 /* if both seen, mark established */
00071 if (p->is_from_server())
00072 {
00073 DebugMessage(DEBUG_STREAM_STATE,
00074 "Stream: Updating on packet from responder\n");
00075 lwssn->ssn_state.session_flags |= SSNFLAG_SEEN_RESPONDER;
00076 lwssn->set_ttl(p, false);
00077 }
00078 else
00079 {
00080 DebugMessage(DEBUG_STREAM_STATE,
00081 "Stream: Updating on packet from client\n");
00082 lwssn->ssn_state.session_flags |= SSNFLAG_SEEN_SENDER;
00083 lwssn->set_ttl(p, true);
00084 }
00085
00086 if (!(lwssn->ssn_state.session_flags & SSNFLAG_ESTABLISHED))
00087 {
00088 if ((lwssn->ssn_state.session_flags & SSNFLAG_SEEN_SENDER) &&
00089 (lwssn->ssn_state.session_flags & SSNFLAG_SEEN_RESPONDER))
00090 {
00091 lwssn->ssn_state.session_flags |= SSNFLAG_ESTABLISHED;
00092 }
00093 }
00094
00095 if ( lwssn->clouseau )
00096 lwssn->clouseau->eval(p);
00097
00098 return 0;
00099 }
00100
00101 //-------------------------------------------------------------------------
00102 // UdpSession methods
00103 //-------------------------------------------------------------------------
00104
00105 UdpSession::UdpSession(Flow* flow) : Session(flow)
00106 {
00107 }
00108
00109 bool UdpSession::setup(Packet* p)
00110 {
00111 ssn_time.tv_sec = p->pkth->ts.tv_sec;
00112 ssn_time.tv_usec = p->pkth->ts.tv_usec;
00113 flow->ssn_state.session_flags |= SSNFLAG_SEEN_SENDER;
00114
00115 flow->pkt_type = p->type();
00116 flow->ip_proto = (uint8_t)p->get_ip_proto_next();
00117 flow->ssn_state.direction = FROM_CLIENT;
00118
00119 StreamUdpConfig* pc = get_udp_cfg(flow->ssn_server);
00120 flow->set_expire(p, pc->session_timeout);
00121
00122 SESSION_STATS_ADD(udpStats);
00123
00124 if (perfmon_config && (perfmon_config->perf_flags & PERF_FLOWIP))
00125 {
00126 perf_flow_ip->update_state(&flow->client_ip,
00127 &flow->server_ip, SFS_STATE_UDP_CREATED);
00128 }
00129
00130 if ( Stream::expected_flow(flow, p) )
00131 {
00132 udpStats.sessions--; // incremented in SESSIONS_STATS_ADD
00133 return false;
00134 }
00135
00136 return true;
00137 }
00138
00139 void UdpSession::clear()
00140 {
00141 UdpSessionCleanup(flow);
00142 UdpHAManager::process_deletion(flow);
00143 flow->clear();
00144 }
00145
00146 void UdpSession::update_direction(
00147 char dir, const SfIp* ip, uint16_t port)
00148 {
00149 SfIp tmpIp;
00150 uint16_t tmpPort;
00151
00152 if (flow->client_ip.equals(*ip) && (flow->client_port == port))
00153 {
00154 if ((dir == SSN_DIR_FROM_CLIENT) && (flow->ssn_state.direction == FROM_CLIENT))
00155 {
00156 /* Direction already set as CLIENT */
00157 return;
00158 }
00159 }
00160 else if (flow->server_ip.equals(*ip) && (flow->server_port == port))
00161 {
00162 if ((dir == SSN_DIR_FROM_SERVER) && (flow->ssn_state.direction == FROM_SERVER))
00163 {
00164 /* Direction already set as SERVER */
00165 return;
00166 }
00167 }
00168
00169 /* Swap them -- leave flow->ssn_state.direction the same */
00170 tmpIp = flow->client_ip;
00171 tmpPort = flow->client_port;
00172 flow->client_ip = flow->server_ip;
00173 flow->client_port = flow->server_port;
00174 flow->server_ip = tmpIp;
00175 flow->server_port = tmpPort;
00176 }
00177
00178 int UdpSession::process(Packet* p)
00179 {
00180 Profile profile(udp_perf_stats);
00181
00182 StreamUdpConfig* pc = get_udp_cfg(flow->ssn_server);
00183 // Check if the session is expired.
00184 // Should be done before we do something with the packet...
00185 if ( Stream::expired_flow(flow, p) )
00186 {
00187 udpStats.timeouts++;
00188 UdpSessionCleanup(flow);
00189 flow->restart();
00190 flow->ssn_state.session_flags |= SSNFLAG_SEEN_SENDER;
00191 udpStats.created++;
00192 UdpHAManager::process_deletion(flow);
00193 }
00194
00195 ProcessUdp(flow, p, pc, nullptr);
00196 flow->markup_packet_flags(p);
00197 flow->set_expire(p, pc->session_timeout);
00198
00199 return 0;
00200 }
00201
END OF CODE