/*
* Copyright 2010 NCHOVY
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.krakenapps.pcap.decoder.tcp;
import java.util.Collection;
import org.krakenapps.pcap.Protocol;
public class TcpFlagHandler {
private final TcpProtocolMapper mapper;
public TcpFlagHandler(TcpProtocolMapper mapper) {
this.mapper = mapper;
}
public void handle(TcpSessionTable sessionTable, TcpSessionImpl session, TcpPacket packet) {
switch (packet.getFlags()) {
case TcpFlag.SYN:
if (session == null)
onSynSent(sessionTable, packet);
else
packet.setGarbage(true);
break;
case (TcpFlag.SYN + TcpFlag.ACK):
if (session != null && isVaildSynAck(sessionTable, session, packet))
onSynAckSent(sessionTable, packet);
else
packet.setGarbage(true);
break;
case TcpFlag.RST:
case (TcpFlag.RST + TcpFlag.ACK):
if (session != null)
onResetArrived(sessionTable, session, packet);
else
packet.setGarbage(true);
break;
default:
return;
}
}
private void onSynSent(TcpSessionTable sessionTable, TcpPacket packet) {
TcpSessionKey key = new TcpSessionKeyImpl(packet.getSourceAddress(), packet.getDestinationAddress(), packet.getSourcePort(), packet.getDestinationPort());
sessionTable.openSession(mapper, key, packet);
TcpSessionImpl session = sessionTable.getSession(key);
session.setClientFirstSeq(packet.getSeq());
}
private boolean isVaildSynAck(TcpSessionTable sessionTable, TcpSessionImpl session, TcpPacket packet) {
if (session == null)
return false;
else {
if ((session.getClientState() == TcpState.SYN_SENT) && (session.getServerState() == TcpState.SYN_RCVD))
return true;
else
return false;
}
}
private void onSynAckSent(TcpSessionTable manager, TcpPacket packet) {
TcpSessionKey key = packet.getSessionKey();
TcpSessionImpl session = manager.getSession(key);
session.createServer(packet);
session.setServerFirstSeq(packet.getSeq());
}
private void onResetArrived(TcpSessionTable sessionTable, TcpSessionImpl session, TcpPacket packet) {
int seq;
int received;
packet.setDirection(session);
if (packet.getDirection() == TcpDirection.ToServer) {
seq = session.retRelativeClientSeq(packet.getSeq());
received = session.getServer().getLastFrameReceived();
} else {
seq = session.retRelativeServerSeq(packet.getSeq());
received = session.getClient().getLastFrameReceived();
}
if ((received == seq) || ((received + 1) == seq)) {
Protocol protocol = session.getProtocol();
Collection<TcpProcessor> processors = mapper.getTcpProcessors(protocol);
if (processors == null)
return;
for (TcpProcessor p : processors) {
p.onReset(session.getKey());
}
sessionTable.abnormalClose(packet.getSessionKey());
}
/* invalid RST packet */
else
packet.setGarbage(true);
}
}