/* * TeleStax, Open Source Cloud Communications Copyright 2012. * TeleStax and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.mobicents.smsc.tools.smppsimulator; import java.io.FileInputStream; import java.io.IOException; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import com.cloudhopper.smpp.pdu.DataSm; import com.cloudhopper.smpp.pdu.DeliverSm; import com.cloudhopper.smpp.pdu.Pdu; import com.cloudhopper.smpp.pdu.SubmitSm; import com.cloudhopper.smpp.transcoder.DefaultPduTranscoder; import com.cloudhopper.smpp.transcoder.DefaultPduTranscoderContext; /** * * @author sergey vetyutnev * */ public class SmppPcapParser { private SmppAccepter smppAccepter; private String fileName; private int port; private DefaultPduTranscoderContext context; private DefaultPduTranscoder dpt; public SmppPcapParser(SmppAccepter smppAccepter, String fileName, int port) { this.smppAccepter = smppAccepter; this.fileName = fileName; this.port = port; this.context = new DefaultPduTranscoderContext(); this.dpt = new DefaultPduTranscoder(context); } public void parse() throws Exception { FileInputStream fis = null; try { fis = new FileInputStream(fileName); byte[] globHeader = new byte[24]; if (fis.read(globHeader) < 24) throw new Exception("Not enouph data for a global header"); int network = ((globHeader[20] & 0xFF) << 0) + ((globHeader[21] & 0xFF) << 8) + ((globHeader[22] & 0xFF) << 16) + ((globHeader[23] & 0xFF) << 24); int recCnt = 0; while (fis.available() > 0) { if (!this.smppAccepter.needContinue()) return; // Packet Header // typedef struct pcaprec_hdr_s { // guint32 ts_sec; /* timestamp seconds */ // guint32 ts_usec; /* timestamp microseconds */ // guint32 incl_len; /* number of octets of packet saved in file // */ // guint32 orig_len; /* actual length of packet */ // } pcaprec_hdr_t; byte[] packetHeader = new byte[16]; if (fis.read(packetHeader) < 16) throw new Exception("Not enouph data for a packet header"); int ts_sec = (packetHeader[0] & 0xFF) + (((int) packetHeader[1] & 0xFF) << 8) + (((int) packetHeader[2] & 0xFF) << 16) + (((int) packetHeader[3] & 0xFF) << 24); int ts_usec = (packetHeader[4] & 0xFF) + (((int) packetHeader[5] & 0xFF) << 8) + (((int) packetHeader[6] & 0xFF) << 16) + (((int) packetHeader[7] & 0xFF) << 24); int incl_len = (packetHeader[8] & 0xFF) + (((int) packetHeader[9] & 0xFF) << 8) + (((int) packetHeader[10] & 0xFF) << 16) + (((int) packetHeader[11] & 0xFF) << 24); int orig_len = (packetHeader[12] & 0xFF) + (((int) packetHeader[13] & 0xFF) << 8) + (((int) packetHeader[14] & 0xFF) << 16) + (((int) packetHeader[15] & 0xFF) << 24); byte[] data = new byte[incl_len]; if (fis.read(data) < incl_len) throw new Exception("Not enouph data for a packet data"); recCnt++; this.parsePacket(data, network); } } finally { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } int finished = 0; } private void parsePacket(byte[] data, int network) throws Exception { switch (network) { case 1: // DLT_EN10MB // check the min possible length if (data == null || data.length < 34) { return; } // Ethernet II level if (data[12] != 8 || data[13] != 0) { // this is not IP protocol - return return; } byte[] ipData = new byte[data.length - 14]; System.arraycopy(data, 14, ipData, 0, data.length - 14); this.parseIpV4Packet(ipData); break; } } private void parseIpV4Packet(byte[] data) throws Exception { // IP protocol level int version = (data[0] & 0xF0) >> 4; // 14 int ipHeaderLen = (data[0] & 0x0F) * 4; if (version != 4) { // TODO: add support for IP V6 return; } int ipProtocolId = data[9] & 0xFF; // 23 if (ipProtocolId != 6) { // 6 == TCP protocol return; } int startTcpBlock = ipHeaderLen; // TCP int sourcePort = ((data[startTcpBlock + 0] & 0xFF) << 8) + (data[startTcpBlock + 1] & 0xFF); int destPort = ((data[startTcpBlock + 2] & 0xFF) << 8) + (data[startTcpBlock + 3] & 0xFF); if (sourcePort != this.port && destPort != this.port) { // wrong port -> this is nor a SMPP packet return; } int tcpHeaderLen = ((data[startTcpBlock + 12] & 0xF0) >> 4) * 4; byte[] tcpData = new byte[data.length - ipHeaderLen - tcpHeaderLen]; System.arraycopy(data, ipHeaderLen + tcpHeaderLen, tcpData, 0, tcpData.length); if (tcpData.length >= 16) { while (true) { int len = ((tcpData[0] & 0xFF) << 24) + ((tcpData[1] & 0xFF) << 16) + ((tcpData[2] & 0xFF) << 8) + (tcpData[3] & 0xFF); if (tcpData.length < len) return; byte[] smppPacket = new byte[len]; System.arraycopy(tcpData, 0, smppPacket, 0, len); parseSmppPacket(smppPacket); if (tcpData.length - len < 16) return; byte[] newTcpData = new byte[tcpData.length - len]; System.arraycopy(tcpData, len, newTcpData, 0, newTcpData.length); tcpData = newTcpData; } } } private void parseSmppPacket(byte[] data) throws Exception { ChannelBuffer buffer = ChannelBuffers.wrappedBuffer(data); try { Pdu pdu = this.dpt.decode(buffer); if (pdu instanceof SubmitSm) { SubmitSm submitPdu = (SubmitSm) pdu; smppAccepter.onNewSmppRequest(submitPdu); } else if (pdu instanceof DataSm) { DataSm dataPdu = (DataSm) pdu; smppAccepter.onNewSmppRequest(dataPdu); } else if (pdu instanceof DeliverSm) { DeliverSm deliverPdu = (DeliverSm) pdu; smppAccepter.onNewSmppRequest(deliverPdu); } } catch (Exception e) { e.printStackTrace(); // buffer = ChannelBuffers.wrappedBuffer(data); // Pdu pdu = this.dpt.decode(buffer); // int i1 = 0; } } }