Skip to content

Commit

Permalink
Initial release
Browse files Browse the repository at this point in the history
  • Loading branch information
j123b567 committed Mar 16, 2017
0 parents commit f1a7d9b
Show file tree
Hide file tree
Showing 10 changed files with 342 additions and 0 deletions.
40 changes: 40 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#Autosave files
*~

#build
[Oo]bj/
[Bb]in/
packages/
TestResults/

# globs
Makefile.in
*.DS_Store
*.sln.cache
*.suo
*.cache
*.pidb
*.userprefs
*.usertasks
config.log
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.user
*.tar.gz
tarballs/
test-results/
Thumbs.db

#Mac bundle stuff
*.dmg
*.app

#resharper
*_Resharper.*
*.Resharper

#dotCover
*.dotCover
24 changes: 24 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Copyright (c) 2017 Jan Breuer,

All Rights Reserved

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Serial port capture to PCAP
===========

This tool can capture serial port traffic and store all data in PCAP format. It is later possible to open it by Wireshark and analyze it.

This tool was created to capture Modbus-RTU on RS-485 but can be used to any other similar traffic.

Tutorial on using this capture is on YouTube https://www.youtube.com/watch?v=YtudbhexPv8

Tool is only for command line,
usage: `serialpcap <portName> [<baudRate> [<frameGapMs]]`

- `portName` is name of the port, e.g. COM1, /dev/ttyUSB0, ...
- `baudrate` is speed of the serial port (default 9600)
- `frameGapMs` is gap between frames in ms (default 10)
17 changes: 17 additions & 0 deletions SerialPCAP.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SerialPCAP", "SerialPCAP\SerialPCAP.csproj", "{AEC1B396-2795-427A-BF9A-63580F155879}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AEC1B396-2795-427A-BF9A-63580F155879}.Debug|x86.ActiveCfg = Debug|x86
{AEC1B396-2795-427A-BF9A-63580F155879}.Debug|x86.Build.0 = Debug|x86
{AEC1B396-2795-427A-BF9A-63580F155879}.Release|x86.ActiveCfg = Release|x86
{AEC1B396-2795-427A-BF9A-63580F155879}.Release|x86.Build.0 = Release|x86
EndGlobalSection
EndGlobal
59 changes: 59 additions & 0 deletions SerialPCAP/CaptureSerial.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System;
using System.IO;
using System.IO.Ports;
namespace SerialPCAP
{
public class CaptureSerial
{
SerialPort m_serialPort;
Packet m_packet = null;

public CaptureSerial(string portName, int baudRate, int readTimeout)
{
m_serialPort = new SerialPort();
m_serialPort.PortName = portName;
m_serialPort.BaudRate = baudRate;
m_serialPort.Parity = Parity.None;
m_serialPort.StopBits = StopBits.One;
m_serialPort.DataBits = 8;
m_serialPort.Handshake = Handshake.None;
m_serialPort.ReadTimeout = readTimeout;
m_serialPort.Open();
}

public void Close()
{
m_serialPort.Close();
}

public bool WritePacket(BinaryWriter writer)
{
try
{
while (true)
{
var b = (byte)m_serialPort.ReadByte();
if (m_packet == null)
{
m_packet = new Packet();
}
m_packet.Data.Add(b);
if (m_packet.Data.Count >= 300)
{
throw new TimeoutException();
}
}
}
catch (TimeoutException)
{
if (m_packet != null)
{
m_packet.Write(writer);
m_packet = null;
}
}
return true;
}
}
}

40 changes: 40 additions & 0 deletions SerialPCAP/Packet.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.IO;
using System.Collections.Generic;

namespace SerialPCAP
{
public class Packet
{
public DateTime Timestamp;
public List<byte> Data;

public Packet()
{
Timestamp = DateTime.Now;
Data = new List<byte>();
}

public void Write(BinaryWriter writer)
{
double unixTimestamp = ConvertToUnixTimestamp(Timestamp);
var ts_sec = (uint)Math.Floor(unixTimestamp);
var ts_usec = (uint)((unixTimestamp - ts_sec)*1000000);
writer.Write(ts_sec);
writer.Write(ts_usec);

byte[] data = Data.ToArray();
writer.Write(data.Length);
writer.Write(data.Length);
writer.Write(data);
}

public static double ConvertToUnixTimestamp(DateTime date)
{
DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
TimeSpan diff = date.ToUniversalTime() - origin;
return diff.TotalSeconds;
}
}
}

19 changes: 19 additions & 0 deletions SerialPCAP/PcapHeader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using System.IO;
namespace SerialPCAP
{
public static class PcapHeader
{
public static void Write(BinaryWriter writer)
{
writer.Write((uint)0xa1b2c3d4); /* magic number */
writer.Write((ushort)2); /* major version number */
writer.Write((ushort)4); /* minor version number */
writer.Write((int)0); /* GMT to local correction */
writer.Write((uint)0); /* accuracy of timestamps */
writer.Write((uint)1024); /* max length of captured packets, in octets */
writer.Write((uint)147); /* data link type */
}
}
}

59 changes: 59 additions & 0 deletions SerialPCAP/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System;
using System.IO;
using System.IO.Ports;

namespace SerialPCAP
{
class MainClass
{
public static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("usage: serialpcap <portName> [<baudRate> [<frameGapMs]]");
Console.WriteLine();
Console.WriteLine("Available portName:");
// Get a list of serial port names.
string[] ports = SerialPort.GetPortNames();
// Display each port name to the console.
foreach (string port in ports)
{
Console.WriteLine(" " + port);
}
Console.WriteLine();
Console.WriteLine("baudRate: serial port speed (default 9600)");
Console.WriteLine();
Console.WriteLine("frameGapMs: inter frame gap in miliseconds (defailt 10)");
}
else {
string portName = args[0];
int baudRate = 9600;
if (args.Length >= 2) baudRate = Int32.Parse(args[1]);
int frameGapMs = 10;
if (args.Length >= 3) frameGapMs = Int32.Parse(args[2]);

string outputFile = "serial-" + DateTime.UtcNow.ToString("yyyyMMdd-HHmmss") + ".pcap";
var capture = new CaptureSerial(portName, baudRate, frameGapMs);

Console.WriteLine("Serial port: " + portName);
Console.WriteLine("Baud rate: " + baudRate + " Bd");
Console.WriteLine("Frame gap: " + frameGapMs + " ms");
Console.WriteLine("Output file: " + outputFile);
Console.WriteLine();
Console.WriteLine("Starting capture (press Ctrl+c to stop)");

using (BinaryWriter writer = new BinaryWriter(File.Open(outputFile, FileMode.Create)))
{
PcapHeader.Write(writer);

while (capture.WritePacket(writer))
{
writer.Flush();
}
}

capture.Close();
}
}
}
}
27 changes: 27 additions & 0 deletions SerialPCAP/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Reflection;
using System.Runtime.CompilerServices;

// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.

[assembly: AssemblyTitle("SerialPCAP")]
[assembly: AssemblyDescription("Serial capture to PCAP")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Jan Breuer")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("Jan Breuer")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.

[assembly: AssemblyVersion("1.0.*")]

// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]

42 changes: 42 additions & 0 deletions SerialPCAP/SerialPCAP.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{AEC1B396-2795-427A-BF9A-63580F155879}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>SerialPCAP</RootNamespace>
<AssemblyName>SerialPCAP</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ExternalConsole>true</ExternalConsole>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ExternalConsole>true</ExternalConsole>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Packet.cs" />
<Compile Include="PcapHeader.cs" />
<Compile Include="CaptureSerial.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

0 comments on commit f1a7d9b

Please sign in to comment.