Class PacketBuilder
- Namespace
- VpnHood.Net.Packets
- Assembly
- VpnHood.Net.Packets.dll
Provides methods that parse IP packets and build new ones: UDP, TCP, ICMP and the replies a router or a host sends.
public static class PacketBuilder
- Inheritance
-
PacketBuilder
- Inherited Members
Examples
using var ipPacket = PacketBuilder.BuildUdp(
new IPEndPoint(IPAddress.Parse("10.0.0.2"), 5353),
new IPEndPoint(IPAddress.Parse("10.0.0.1"), 53),
"hello"u8);
ipPacket.UpdateAllChecksums(); // BuildUdp computes no checksum itself
var bytes = ipPacket.Buffer; // the packet's own bytes, ready for a TUN device
Remarks
A built packet owns the memory it is built in: an array rented from Shared, or memory
from the MemoryPool<T> given. Dispose it to return the memory. Its time to live is 64. A method with an
updateChecksum parameter computes the checksums when it is true; the others compute
none, so call UpdateAllChecksums(IpPacket) before sending.
Methods
Attach(PacketMemory)
Parses the IP packet at the start of some memory, without copying it: the packet reads and writes the memory.
public static IpPacket Attach(PacketMemory memory)
Parameters
memoryPacketMemoryThe memory, which holds the packet from its first byte and may be longer: a Memory<T> or an array the caller keeps, or memory given to the packet (see PacketMemory), which stays the caller's when parsing fails.
Returns
- IpPacket
An IpV4Packet or IpV6Packet; dispose it to return the memory it was given.
Exceptions
- NotSupportedException
The version is neither 4 nor 6.
- ArgumentException
The bytes are no valid IP packet.
- IndexOutOfRangeException
The memory is empty.
BuildDns(IPAddress, IPAddress, int, int, string, ushort?)
Builds an IP packet that carries a DNS query for a name's IPv4 addresses (type A, class IN, recursion desired) over UDP.
public static IpPacket BuildDns(IPAddress sourceAddress, IPAddress destinationAddress, int sourcePort, int destinationPort, string host, ushort? queryId = null)
Parameters
sourceAddressIPAddressThe source address.
destinationAddressIPAddressThe DNS server's address, of the same IP version.
sourcePortintThe source port.
destinationPortintThe DNS server's port, usually 53.
hoststringThe name to look up.
queryIdushort?The query's ID, or null for a random one.
Returns
- IpPacket
The packet; dispose it to return its memory.
Remarks
No checksum is computed: call UpdateAllChecksums(IpPacket) before sending.
Exceptions
- ArgumentException
The addresses are of different IP versions.
- NotSupportedException
The addresses are neither IPv4 nor IPv6.
BuildDns(IPEndPoint, IPEndPoint, string, ushort?)
Builds an IP packet that carries a DNS query for a name's IPv4 addresses (type A, class IN, recursion desired) over UDP.
public static IpPacket BuildDns(IPEndPoint sourceEndPoint, IPEndPoint destinationEndPoint, string host, ushort? queryId = null)
Parameters
sourceEndPointIPEndPointThe source address and port.
destinationEndPointIPEndPointThe DNS server's address and port, of the same IP version.
hoststringThe name to look up.
queryIdushort?The query's ID, or null for a random one.
Returns
- IpPacket
The packet; dispose it to return its memory.
Remarks
No checksum is computed: call UpdateAllChecksums(IpPacket) before sending.
Exceptions
- ArgumentException
The addresses are of different IP versions.
- NotSupportedException
The addresses are neither IPv4 nor IPv6.
BuildIcmpEchoReply(IPAddress, IPAddress, ReadOnlySpan<byte>, ushort, ushort, bool)
Builds an ICMPv4 or ICMPv6 echo reply, the answer to a ping, by the addresses' IP version.
public static IpPacket BuildIcmpEchoReply(IPAddress sourceAddress, IPAddress destinationAddress, ReadOnlySpan<byte> payload, ushort identifier = 0, ushort sequenceNumber = 0, bool updateChecksum = true)
Parameters
sourceAddressIPAddressThe source address.
destinationAddressIPAddressThe destination address, of the same IP version.
payloadReadOnlySpan<byte>The echo's data, which is copied in: the request's data, for a reply to it.
identifierushortThe echo's identifier: the request's, for a reply to it.
sequenceNumberushortThe echo's sequence number: the request's, for a reply to it.
updateChecksumbool
Returns
- IpPacket
The packet; dispose it to return its memory.
Exceptions
- ArgumentException
The addresses are of different IP versions.
- NotSupportedException
The addresses are neither IPv4 nor IPv6.
BuildIcmpEchoRequest(IPAddress, IPAddress, ReadOnlySpan<byte>, ushort, ushort, bool)
Builds an ICMPv4 or ICMPv6 echo request, a ping, by the addresses' IP version.
public static IpPacket BuildIcmpEchoRequest(IPAddress sourceAddress, IPAddress destinationAddress, ReadOnlySpan<byte> payload, ushort identifier = 0, ushort sequenceNumber = 0, bool updateChecksum = true)
Parameters
sourceAddressIPAddressThe source address.
destinationAddressIPAddressThe destination address, of the same IP version.
payloadReadOnlySpan<byte>The echo's data, which is copied in.
identifierushortThe echo's identifier.
sequenceNumberushortThe echo's sequence number.
updateChecksumbool
Returns
- IpPacket
The packet; dispose it to return its memory.
Exceptions
- ArgumentException
The addresses are of different IP versions.
- NotSupportedException
The addresses are neither IPv4 nor IPv6.
BuildIcmpPacketTooBigReply(IpPacket, int, bool)
Builds the ICMP error that tells a packet's sender it is too big for the next link: ICMPv6 "packet too big", or ICMPv4 "fragmentation needed".
public static IpPacket BuildIcmpPacketTooBigReply(IpPacket ipPacket, int mtu, bool updateChecksum = true)
Parameters
ipPacketIpPacketThe packet that is too big. The error goes from its destination to its source and carries its start.
mtuintThe next link's MTU in bytes, which the error carries; ICMPv4 carries its low 16 bits.
updateChecksumbool
Returns
- IpPacket
The error packet; dispose it to return its memory.
Exceptions
- ObjectDisposedException
ipPacketis disposed.
BuildIcmpUnreachablePortReply(IpPacket, bool)
Builds the ICMP error that tells a packet's sender its destination port is unreachable.
public static IpPacket BuildIcmpUnreachablePortReply(IpPacket ipPacket, bool updateChecksum = true)
Parameters
ipPacketIpPacketThe packet that cannot be delivered. The error goes from its destination to its source and carries its start.
updateChecksumbool
Returns
- IpPacket
The error packet; dispose it to return its memory.
Exceptions
- ObjectDisposedException
ipPacketis disposed.
BuildIcmpUnreachableReply(IpPacket, bool)
Builds the ICMP error that tells a packet's sender its destination is unreachable: ICMPv4 "host unreachable", or ICMPv6 "address unreachable".
public static IpPacket BuildIcmpUnreachableReply(IpPacket ipPacket, bool updateChecksum = true)
Parameters
ipPacketIpPacketThe packet that cannot be delivered. The error goes from its destination to its source and carries its start.
updateChecksumbool
Returns
- IpPacket
The error packet; dispose it to return its memory.
Exceptions
- ObjectDisposedException
ipPacketis disposed.
BuildIcmpV4(IPAddress, IPAddress, ReadOnlySpan<byte>)
Builds an IPv4 packet that carries an ICMPv4 message, with its type, code and message-specific field zero.
public static IpPacket BuildIcmpV4(IPAddress sourceAddress, IPAddress destinationAddress, ReadOnlySpan<byte> payload)
Parameters
sourceAddressIPAddressThe source address, IPv4.
destinationAddressIPAddressThe destination address, IPv4.
payloadReadOnlySpan<byte>The message's payload, which is copied in.
Returns
- IpPacket
The packet; dispose it to return its memory.
Remarks
Type zero is an echo reply: set Type through ExtractIcmpV4(IpPacket). No checksum is computed: call UpdateAllChecksums(IpPacket) before sending.
Exceptions
- ArgumentException
The addresses are of different IP versions, or the packet would be too large.
BuildIcmpV4EchoReply(IPAddress, IPAddress, ReadOnlySpan<byte>, ushort, ushort, bool)
Builds an ICMPv4 echo reply, the answer to a ping.
public static IpPacket BuildIcmpV4EchoReply(IPAddress sourceAddress, IPAddress destinationAddress, ReadOnlySpan<byte> payload, ushort identifier = 0, ushort sequenceNumber = 0, bool updateChecksum = true)
Parameters
sourceAddressIPAddressThe source address, IPv4.
destinationAddressIPAddressThe destination address, IPv4.
payloadReadOnlySpan<byte>The echo's data, which is copied in: the request's data, for a reply to it.
identifierushortThe echo's identifier: the request's, for a reply to it.
sequenceNumberushortThe echo's sequence number: the request's, for a reply to it.
updateChecksumbool
Returns
- IpPacket
The packet; dispose it to return its memory.
Exceptions
- ArgumentException
An address is not IPv4.
BuildIcmpV4EchoRequest(IPAddress, IPAddress, ReadOnlySpan<byte>, ushort, ushort, bool)
Builds an ICMPv4 echo request, a ping.
public static IpPacket BuildIcmpV4EchoRequest(IPAddress sourceAddress, IPAddress destinationAddress, ReadOnlySpan<byte> payload, ushort identifier = 0, ushort sequenceNumber = 0, bool updateChecksum = true)
Parameters
sourceAddressIPAddressThe source address, IPv4.
destinationAddressIPAddressThe destination address, IPv4.
payloadReadOnlySpan<byte>The echo's data, which is copied in.
identifierushortThe echo's identifier.
sequenceNumberushortThe echo's sequence number.
updateChecksumbool
Returns
- IpPacket
The packet; dispose it to return its memory.
Exceptions
- ArgumentException
An address is not IPv4.
BuildIcmpV4Error(IpPacket, IcmpV4Type, IcmpV4Code, uint, bool)
Builds an ICMPv4 error about a packet, from its destination back to its source.
public static IpPacket BuildIcmpV4Error(IpPacket ipPacket, IcmpV4Type icmpV4Type, IcmpV4Code code, uint messageSpecific, bool updateChecksum)
Parameters
ipPacketIpPacketThe IPv4 packet the error is about.
icmpV4TypeIcmpV4TypeThe error's type.
codeIcmpV4CodeThe error's code.
messageSpecificuintThe 4 bytes after the checksum, such as the next-hop MTU in the low 16 bits.
updateChecksumbool
Returns
- IpPacket
The error packet; dispose it to return its memory.
Remarks
The error carries the packet's IP header and up to the first 8 bytes of its payload, as RFC 792 asks.
Exceptions
- ArgumentNullException
ipPacketis null.- ObjectDisposedException
ipPacketis disposed.
BuildIcmpV6(IPAddress, IPAddress, ReadOnlySpan<byte>)
Builds an IPv6 packet that carries an ICMPv6 message, with its type, code and message-specific field zero.
public static IpPacket BuildIcmpV6(IPAddress sourceAddress, IPAddress destinationAddress, ReadOnlySpan<byte> payload)
Parameters
sourceAddressIPAddressThe source address, IPv6.
destinationAddressIPAddressThe destination address, IPv6.
payloadReadOnlySpan<byte>The message's payload, which is copied in.
Returns
- IpPacket
The packet; dispose it to return its memory.
Remarks
Set Type through ExtractIcmpV6(IpPacket). No checksum is computed: call UpdateAllChecksums(IpPacket) before sending.
Exceptions
- ArgumentException
The addresses are of different IP versions.
BuildIcmpV6EchoReply(IPAddress, IPAddress, ReadOnlySpan<byte>, ushort, ushort, bool)
Builds an ICMPv6 echo reply, the answer to a ping.
public static IpPacket BuildIcmpV6EchoReply(IPAddress sourceAddress, IPAddress destinationAddress, ReadOnlySpan<byte> payload, ushort identifier = 0, ushort sequenceNumber = 0, bool updateChecksum = true)
Parameters
sourceAddressIPAddressThe source address, IPv6.
destinationAddressIPAddressThe destination address, IPv6.
payloadReadOnlySpan<byte>The echo's data, which is copied in: the request's data, for a reply to it.
identifierushortThe echo's identifier: the request's, for a reply to it.
sequenceNumberushortThe echo's sequence number: the request's, for a reply to it.
updateChecksumbool
Returns
- IpPacket
The packet; dispose it to return its memory.
Exceptions
- ArgumentException
An address is not IPv6.
BuildIcmpV6EchoRequest(IPAddress, IPAddress, ReadOnlySpan<byte>, ushort, ushort, bool)
Builds an ICMPv6 echo request, a ping.
public static IpPacket BuildIcmpV6EchoRequest(IPAddress sourceAddress, IPAddress destinationAddress, ReadOnlySpan<byte> payload, ushort identifier = 0, ushort sequenceNumber = 0, bool updateChecksum = true)
Parameters
sourceAddressIPAddressThe source address, IPv6.
destinationAddressIPAddressThe destination address, IPv6.
payloadReadOnlySpan<byte>The echo's data, which is copied in.
identifierushortThe echo's identifier.
sequenceNumberushortThe echo's sequence number.
updateChecksumbool
Returns
- IpPacket
The packet; dispose it to return its memory.
Exceptions
- ArgumentException
An address is not IPv6.
BuildIcmpV6Error(IpPacket, IcmpV6Type, IcmpV6Code, uint, bool)
Builds an ICMPv6 error about a packet, from its destination back to its source.
public static IpPacket BuildIcmpV6Error(IpPacket ipPacket, IcmpV6Type icmpV6Type, IcmpV6Code code, uint messageSpecific, bool updateChecksum = true)
Parameters
ipPacketIpPacketThe IPv6 packet the error is about.
icmpV6TypeIcmpV6TypeThe error's type.
codeIcmpV6CodeThe error's code.
messageSpecificuintThe 4 bytes after the checksum, such as the MTU of a "packet too big" error.
updateChecksumbool
Returns
- IpPacket
The error packet; dispose it to return its memory.
Remarks
The error carries the packet's first 1232 bytes, or the whole packet when it is shorter, so that the error is no longer than 1280 bytes, IPv6's minimum MTU, as RFC 4443 asks.
Exceptions
- ArgumentNullException
ipPacketis null.- ObjectDisposedException
ipPacketis disposed.
BuildIp(IPAddress, IPAddress, IpProtocol, int, MemoryPool<byte>?)
Builds an IP packet with an empty payload of a given length, for the caller to fill.
public static IpPacket BuildIp(IPAddress sourceAddress, IPAddress destinationAddress, IpProtocol protocol, int payloadLength, MemoryPool<byte>? memoryPool = null)
Parameters
sourceAddressIPAddressThe source address.
destinationAddressIPAddressThe destination address, of the same IP version.
protocolIpProtocolThe protocol of the payload.
payloadLengthintThe payload's length in bytes; at most 65515 for IPv4 and 65535 for IPv6.
memoryPoolMemoryPool<byte>The pool to rent the packet's memory from, or null for an array of Shared.
Returns
- IpPacket
The packet, with its payload zero; dispose it to return its memory.
Exceptions
- ArgumentException
The addresses are of different IP versions, or the payload is longer than their IP version allows.
- NotSupportedException
The addresses are neither IPv4 nor IPv6.
BuildIp(ReadOnlySpan<byte>, ReadOnlySpan<byte>, IpProtocol, int, MemoryPool<byte>?)
Builds an IP packet with an empty payload of a given length, for the caller to fill, from raw address bytes.
public static IpPacket BuildIp(ReadOnlySpan<byte> sourceAddress, ReadOnlySpan<byte> destinationAddress, IpProtocol protocol, int payloadLength, MemoryPool<byte>? memoryPool = null)
Parameters
sourceAddressReadOnlySpan<byte>The source address: 4 bytes for IPv4, 16 for IPv6.
destinationAddressReadOnlySpan<byte>The destination address, of the same length.
protocolIpProtocolThe protocol of the payload.
payloadLengthintThe payload's length in bytes; at most 65515 for IPv4 and 65535 for IPv6.
memoryPoolMemoryPool<byte>The pool to rent the packet's memory from, or null for an array of Shared.
Returns
- IpPacket
The packet, with its payload zero; dispose it to return its memory.
Exceptions
- ArgumentException
The addresses differ in length, or the payload is longer than their IP version allows.
- NotSupportedException
The addresses are neither 4 nor 16 bytes long.
BuildIp(IpAddressValue, IpAddressValue, IpProtocol, int, MemoryPool<byte>?)
Builds an IP packet with an empty payload of a given length, for the caller to fill, from address values.
public static IpPacket BuildIp(IpAddressValue sourceAddress, IpAddressValue destinationAddress, IpProtocol protocol, int payloadLength, MemoryPool<byte>? memoryPool = null)
Parameters
sourceAddressIpAddressValueThe source address.
destinationAddressIpAddressValueThe destination address, of the same IP version.
protocolIpProtocolThe protocol of the payload.
payloadLengthintThe payload's length in bytes; at most 65515 for IPv4 and 65535 for IPv6.
memoryPoolMemoryPool<byte>The pool to rent the packet's memory from, or null for an array of Shared.
Returns
- IpPacket
The packet, with its payload zero; dispose it to return its memory.
Exceptions
- ArgumentException
The addresses are of different IP versions, or the payload is longer than their IP version allows.
- NotSupportedException
The addresses hold no address.
BuildTcp(IPAddress, IPAddress, int, int, ReadOnlySpan<byte>, ReadOnlySpan<byte>)
Builds an IP packet that carries a TCP segment, with its flags, numbers and window zero.
public static IpPacket BuildTcp(IPAddress sourceAddress, IPAddress destinationAddress, int sourcePort, int destinationPort, ReadOnlySpan<byte> options, ReadOnlySpan<byte> payload)
Parameters
sourceAddressIPAddressThe source address.
destinationAddressIPAddressThe destination address, of the same IP version.
sourcePortintThe source port, from 0 to 65535.
destinationPortintThe destination port, from 0 to 65535.
optionsReadOnlySpan<byte>The TCP options, a multiple of 4 bytes up to 40, which are copied in.
payloadReadOnlySpan<byte>The segment's payload, which is copied in.
Returns
- IpPacket
The packet; dispose it to return its memory.
Remarks
No checksum is computed: call UpdateAllChecksums(IpPacket) before sending.
Exceptions
- ArgumentException
The addresses are of different IP versions, or the packet would be too large.
- ArgumentOutOfRangeException
optionsis longer than 40 bytes or not a multiple of 4.- NotSupportedException
The addresses are neither IPv4 nor IPv6.
BuildTcp(IPEndPoint, IPEndPoint, ReadOnlySpan<byte>, ReadOnlySpan<byte>)
Builds an IP packet that carries a TCP segment, with its flags, numbers and window zero.
public static IpPacket BuildTcp(IPEndPoint sourceEndPoint, IPEndPoint destinationEndPoint, ReadOnlySpan<byte> options, ReadOnlySpan<byte> payload)
Parameters
sourceEndPointIPEndPointThe source address and port.
destinationEndPointIPEndPointThe destination address and port, of the same IP version.
optionsReadOnlySpan<byte>The TCP options, a multiple of 4 bytes up to 40, which are copied in.
payloadReadOnlySpan<byte>The segment's payload, which is copied in.
Returns
- IpPacket
The packet; dispose it to return its memory.
Remarks
No checksum is computed: call UpdateAllChecksums(IpPacket) before sending.
Exceptions
- ArgumentException
The addresses are of different IP versions, or the packet would be too large.
- ArgumentOutOfRangeException
optionsis longer than 40 bytes or not a multiple of 4.- NotSupportedException
The addresses are neither IPv4 nor IPv6.
BuildTcp(IpEndPointValue, IpEndPointValue, ReadOnlySpan<byte>, ReadOnlySpan<byte>)
Builds an IP packet that carries a TCP segment, with its flags, numbers and window zero.
public static IpPacket BuildTcp(IpEndPointValue sourceEndPoint, IpEndPointValue destinationEndPoint, ReadOnlySpan<byte> options, ReadOnlySpan<byte> payload)
Parameters
sourceEndPointIpEndPointValueThe source address and port.
destinationEndPointIpEndPointValueThe destination address and port, of the same IP version.
optionsReadOnlySpan<byte>The TCP options, a multiple of 4 bytes up to 40, which are copied in.
payloadReadOnlySpan<byte>The segment's payload, which is copied in.
Returns
- IpPacket
The packet; dispose it to return its memory.
Remarks
No checksum is computed: call UpdateAllChecksums(IpPacket) before sending.
Exceptions
- ArgumentException
The addresses are of different IP versions, or the packet would be too large.
- ArgumentOutOfRangeException
optionsis longer than 40 bytes or not a multiple of 4.- NotSupportedException
The addresses are neither IPv4 nor IPv6.
BuildTcpResetReply(IpPacket, bool)
Builds the TCP reset (RST) that refuses a TCP packet, from its destination back to its source.
public static IpPacket BuildTcpResetReply(IpPacket ipPacket, bool updateChecksum = true)
Parameters
Returns
- IpPacket
The reset packet; dispose it to return its memory.
Remarks
A reset for a SYN without ACK acknowledges it: sequence number 0, acknowledgment number the SYN's sequence number plus 1. For any other packet, the reset's sequence number is the packet's acknowledgment number, with no ACK.
Exceptions
- ArgumentNullException
ipPacketis null.- ArgumentException
ipPacketdoes not carry TCP, or its TCP segment is invalid.- InvalidDataException
ipPacketis a fragment.
BuildUdp(IPAddress, IPAddress, int, int, ReadOnlySpan<byte>)
Builds an IP packet that carries a UDP datagram.
public static IpPacket BuildUdp(IPAddress sourceAddress, IPAddress destinationAddress, int sourcePort, int destinationPort, ReadOnlySpan<byte> payload)
Parameters
sourceAddressIPAddressThe source address.
destinationAddressIPAddressThe destination address, of the same IP version.
sourcePortintThe source port, from 0 to 65535.
destinationPortintThe destination port, from 0 to 65535.
payloadReadOnlySpan<byte>The datagram's payload, which is copied in.
Returns
- IpPacket
The packet; dispose it to return its memory.
Remarks
No checksum is computed: call UpdateAllChecksums(IpPacket) before sending.
Exceptions
- ArgumentException
The addresses are of different IP versions, or the packet would be too large.
- NotSupportedException
The addresses are neither IPv4 nor IPv6.
BuildUdp(IPEndPoint, IPEndPoint, ReadOnlySpan<byte>)
Builds an IP packet that carries a UDP datagram.
public static IpPacket BuildUdp(IPEndPoint sourceEndPoint, IPEndPoint destinationEndPoint, ReadOnlySpan<byte> payload)
Parameters
sourceEndPointIPEndPointThe source address and port.
destinationEndPointIPEndPointThe destination address and port, of the same IP version.
payloadReadOnlySpan<byte>The datagram's payload, which is copied in.
Returns
- IpPacket
The packet; dispose it to return its memory.
Remarks
No checksum is computed: call UpdateAllChecksums(IpPacket) before sending.
Exceptions
- ArgumentException
The addresses are of different IP versions, or the packet would be too large.
- NotSupportedException
The addresses are neither IPv4 nor IPv6.
Parse(ReadOnlySpan<byte>, MemoryPool<byte>?)
Parses the IP packet at the start of some bytes into a copy that the returned packet owns.
public static IpPacket Parse(ReadOnlySpan<byte> buffer, MemoryPool<byte>? memoryPool = null)
Parameters
bufferReadOnlySpan<byte>The bytes, which hold the packet from the first byte and may be longer.
memoryPoolMemoryPool<byte>The pool to rent the copy's memory from, or null for an array of Shared.
Returns
- IpPacket
An IpV4Packet or IpV6Packet; dispose it to return its memory.
Examples
// Parse copies the received bytes into pooled memory; PacketBuilder.Attach would read them in place
using var ipPacket = PacketBuilder.Parse(received);
Console.WriteLine($"{ipPacket.SourceAddress} -> {ipPacket.DestinationAddress}, {ipPacket.Protocol}");
if (ipPacket.Protocol == IpProtocol.Udp && !ipPacket.IsFragment) {
var udp = ipPacket.ExtractUdp(); // a view over the packet's bytes, not a copy
Console.WriteLine($"UDP {udp.SourcePort} -> {udp.DestinationPort}, {udp.Payload.Length} bytes, " +
$"checksum valid: {udp.IsChecksumValid(ipPacket)}");
}
Exceptions
- ArgumentException
The bytes are no valid IP packet.
- ArgumentOutOfRangeException
bufferis shorter than the packet's length field says.- NotSupportedException
The version is neither 4 nor 6.
- IndexOutOfRangeException
bufferis empty.