Como veo que tuviste dificultades para armar paquetes ... te tiro una ayudita ...
usando Raw sockets tenés que armar el paquete by hand, vamos al ejemplo de armar un paquete
TCP :
// Somewhere in the code ...
class Package
{
public Int16 SourcePort,DestinationPort,Window,CheckSum,UrgentPtr;
public Int32 SequenceNumber,AckNumber;
public Byte DataOffset,Reserved,ControlBits;
public Byte [] Options
= new Byte[1],Data
= new Byte[1]; };
private static Byte[] makeTCPackage(Package PackageInfo)
{
// El paquete per se ... en una lista
System.Collections.Generic.List<Byte> mPacketBytes
= new System.Collections.Generic.List<Byte>(); int optionBytes = 0;
// Empaquetamos el Puerto de origen y agregamos
// no limpiamos los bits que se truncan anyways
mPacketBytes.Add((Byte) (PackageInfo.SourcePort >> 8));
mPacketBytes.Add((Byte) PackageInfo.SourcePort ); // truncamos y dejamos donde estaba
// Empaquetamos el de Destino y agregamos
mPacketBytes.Add((Byte) (PackageInfo.DestinationPort >> 8));
mPacketBytes.Add((Byte) PackageInfo.DestinationPort);
// Empaquetamos el Sequence Number (en 4 pasos de un byte) y agregamos
mPacketBytes.Add((Byte) (PackageInfo.SequenceNumber >> 24));
mPacketBytes.Add((Byte) (PackageInfo.SequenceNumber >> 16));
mPacketBytes.Add((Byte) (PackageInfo.SequenceNumber >> 8));
mPacketBytes.Add((Byte) PackageInfo.SequenceNumber);
// Empaquetamos el Ack Number (en 4 pasos de un byte) y agregamos
mPacketBytes.Add((Byte) (PackageInfo.AckNumber >> 24));
mPacketBytes.Add((Byte) (PackageInfo.AckNumber >> 16));
mPacketBytes.Add((Byte) (PackageInfo.AckNumber >> 8));
mPacketBytes.Add((Byte) PackageInfo.AckNumber);
// 4 Bits de Data Offset + 2 de reserved
mPacketBytes.Add((Byte) (PackageInfo.DataOffset <<4));
// 2 de reserved + 6 de control bit
mPacketBytes.Add((Byte) ((PackageInfo.ControlBits << 2) >> 2));
// 2 bytes de Window
mPacketBytes.Add((Byte) (PackageInfo.Window >> 8));
mPacketBytes.Add((Byte) PackageInfo.Window);
// 2 de checksum
mPacketBytes.Add((Byte) (PackageInfo.CheckSum >> 8));
mPacketBytes.Add((Byte) PackageInfo.CheckSum);
// urgentPtr .. 2 bytes
mPacketBytes.Add((Byte) (PackageInfo.UrgentPtr >> 8));
mPacketBytes.Add((Byte) PackageInfo.UrgentPtr);
// Options
foreach(Byte mOptions in PackageInfo.Options)
{
mPacketBytes.Add(mOptions);
++optionBytes;
}
// Padding (4 columnas de 8 bits)
while((optionBytes++)%4 != 0)
{
mPacketBytes.Add((Byte) 0);
}
//Data
foreach(Byte mBData in PackageInfo.Data)
{
mPacketBytes.Add(mBData);
}
Byte[] mRawPacket
= new Byte[mPacketBytes
.Count]; mPacketBytes.CopyTo(mRawPacket);
return mRawPacket;
}
usás package para rellenar los datos y obtenerlos en un Byte[] para más tarde enviarlo ...
o de última usás algún port de PCap a .net, si bien podés PInvokear, mejor evitalo ...
otro detalle : forget about Managed C++
Saludos ~
P.S : en Linux se requiere privilegios root para poder mandar paquetes raw, sino : Exception -> Access denied
P.S 2 : eso no está optimizado, está escrito de manera que se vea bien