project-carbon/ProjectCarbon/PacketCapture.cs

151 lines
4.0 KiB
C#

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Timers;
using System.Collections;
using System.Collections.Generic;
namespace ProjectCarbon
{
class PacketCapturedEventArgs : EventArgs
{
private DateTime timestamp;
private byte[] buffer;
public PacketCapturedEventArgs(byte[] buffer)
{
this.timestamp = DateTime.Now;
this.buffer = buffer;
}
public DateTime TimeStamp
{
get { return timestamp; }
}
public byte[] Buffer
{
get { return buffer; }
}
}
class PacketCaptureInterface: IDisposable
{
public delegate void PacketCapturedEventHandler(object sender, PacketCapturedEventArgs e);
public event PacketCapturedEventHandler OnPacketCaptured;
private Socket socket;
private IPAddress ipAddress;
private byte[] packetBuffer;
private NetworkInterface[] networkInterfaces;
private IPAddress[] addressList = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
private AsyncCallback receiveCallback;
private bool isCapturing = false;
public PacketCaptureInterface (IPAddress ip)
{
this.ipAddress = ip;
this.networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
this.packetBuffer = new byte[2000]; // default max mtu is 1500, allow for 500 bytes of extra
this.receiveCallback = new AsyncCallback(OnReceiveCallback);
}
public NetworkInterface[] NetworkInterfaces
{
get { return networkInterfaces; }
}
public IPAddress[] AddressList
{
get { return addressList; }
}
public void StartCapture()
{
if (isCapturing)
return;
try
{
socket = new Socket(ipAddress.AddressFamily,
SocketType.Raw, ProtocolType.IP);
socket.Bind(new IPEndPoint(ipAddress, 0));
socket.IOControl(IOControlCode.ReceiveAll,
BitConverter.GetBytes(1), null);
isCapturing = true;
BeginReceive();
}
catch
{
socket.Close();
}
}
public void StopCapture()
{
if (isCapturing)
{
if (socket != null)
socket.Close();
isCapturing = false;
}
}
private void BeginReceive()
{
try
{
socket.BeginReceive(packetBuffer,
0,
packetBuffer.Length,
SocketFlags.None,
receiveCallback,
null);
}
catch (ObjectDisposedException)
{
Console.WriteLine("BeginReceive: Socket has been closed.");
}
}
private void OnReceiveCallback(IAsyncResult ar)
{
try
{
int bytesReceived = socket.EndReceive(ar);
byte[] receivedBuffer = new byte[bytesReceived];
Array.Copy(packetBuffer, 0, receivedBuffer, 0, bytesReceived);
Console.WriteLine(bytesReceived);
if(OnPacketCaptured != null)
OnPacketCaptured(this, new PacketCapturedEventArgs(receivedBuffer));
BeginReceive();
}
catch (ObjectDisposedException)
{
Console.WriteLine("OnReceiveCallback: Socket has been closed.");
}
}
#region IDisposable Members
public void Dispose()
{
if (socket != null)
socket.Close();
}
#endregion
}
}