/// ************************************************************************
/// Copyright (C) 2001, Patrick Charles and Jonas Lehmann *
/// Distributed under the Mozilla Public License *
/// http://www.mozilla.org/NPL/MPL-1.1.txt *
/// *************************************************************************
///
using System;
using AnsiEscapeSequences_Fields = SharpPcap.Packets.Util.AnsiEscapeSequences_Fields;
using ArrayHelper = SharpPcap.Packets.Util.ArrayHelper;
using Timeval = SharpPcap.Packets.Util.Timeval;
namespace SharpPcap.Packets
{
/// A UDP packet.
///
/// Extends an IP packet, adding a UDP header and UDP data payload.
///
///
[Serializable]
public class UDPPacket : IPPacket, UDPFields
{
/// Fetch the port number on the source host.
virtual public int SourcePort
{
get
{
return ArrayHelper.extractInteger(Bytes, _ipOffset + UDPFields_Fields.UDP_SP_POS, UDPFields_Fields.UDP_PORT_LEN);
}
set
{
ArrayHelper.insertLong(Bytes, value, _ipOffset + UDPFields_Fields.UDP_SP_POS, UDPFields_Fields.UDP_PORT_LEN);
}
}
/// Fetch the port number on the target host.
virtual public int DestinationPort
{
get
{
return ArrayHelper.extractInteger(Bytes, _ipOffset + UDPFields_Fields.UDP_DP_POS, UDPFields_Fields.UDP_PORT_LEN);
}
set
{
ArrayHelper.insertLong(Bytes, value, _ipOffset + UDPFields_Fields.UDP_DP_POS, UDPFields_Fields.UDP_PORT_LEN);
}
}
/// Fetch the total length of the UDP packet, including header and
/// data payload, in bytes.
///
virtual public int UDPLength
{
get
{
// should produce the same value as header.length + data.length
return Length;
}
set
{
ArrayHelper.insertLong(Bytes, value, _ipOffset + UDPFields_Fields.UDP_LEN_POS, UDPFields_Fields.UDP_LEN_LEN);
}
}
/// Fetch the header checksum.
virtual public int UDPChecksum
{
get
{
return GetTransportLayerChecksum(_ipOffset + UDPFields_Fields.UDP_CSUM_POS);
}
set
{
SetTransportLayerChecksum(value, UDPFields_Fields.UDP_CSUM_POS);
}
}
/// Check if the TCP packet is valid, checksum-wise.
public override bool ValidChecksum
{
get
{
return ValidUDPChecksum;
}
}
virtual public bool ValidUDPChecksum
{
get
{
return base.IsValidTransportLayerChecksum(true);
}
}
/// Fetch the UDP header a byte array.
virtual public byte[] UDPHeader
{
get
{
if (_udpHeaderBytes == null)
{
_udpHeaderBytes = PacketEncoding.extractHeader(_ipOffset, UDPFields_Fields.UDP_HEADER_LEN, Bytes);
}
return _udpHeaderBytes;
}
}
/// Fetch the UDP header as a byte array.
override public byte[] Header
{
get
{
return UDPHeader;
}
}
/// Fetch the UDP header length in bytes.
virtual public int UDPHeaderLength
{
get
{
return UDPFields_Fields.UDP_HEADER_LEN;
}
}
/// Fetches the packet header length.
override public int HeaderLength
{
get
{
return UDPHeaderLength;
}
}
/// Fetches the length of the payload data.
virtual public int PayloadDataLength
{
get
{
return (IPPayloadLength - UDPHeaderLength);
}
}
/// Fetch the UDP data as a byte array.
virtual public byte[] UDPData
{
get
{
if (_udpDataBytes == null)
{
_udpDataBytes = new byte[PayloadDataLength];
Array.Copy(Bytes, _ipOffset + UDPHeaderLength, _udpDataBytes, 0, PayloadDataLength);
}
return _udpDataBytes;
}
set
{
SetData(value);
}
}
///
/// Sets the data section of this udp packet
///
/// the data bytes
public void SetData(byte[] data)
{
if (IPVersion != IPVersions.IPv4)
throw new System.NotImplementedException("IPVersion of " + IPVersion + " is unrecognized");
byte[] headers = ArrayHelper.copy(Bytes, 0, UDPFields_Fields.UDP_HEADER_LEN + IPHeaderLength + EthernetHeaderLength);
byte[] newBytes = ArrayHelper.join(headers, data);
this.Bytes = newBytes;
UDPLength = Bytes.Length - IPHeaderLength - EthernetHeaderLength;
//update ip total length length
IPTotalLength = IPHeaderLength + UDPFields_Fields.UDP_HEADER_LEN + data.Length;
//update also offset and pcap header
OnOffsetChanged();
}
/// Fetch ascii escape sequence of the color associated with this packet type.
override public System.String Color
{
get
{
return AnsiEscapeSequences_Fields.LIGHT_GREEN;
}
}
/// Create a new UDP packet.
public UDPPacket(int lLen, byte[] bytes)
: base(lLen, bytes)
{
}
/// Create a new UDP packet.
public UDPPacket(int lLen, byte[] bytes, Timeval tv)
: this(lLen, bytes)
{
this._timeval = tv;
}
/// Fetch the total length of the UDP packet, including header and
/// data payload, in bytes.
///
public int Length
{
get
{
// should produce the same value as header.length + data.length
return ArrayHelper.extractInteger(Bytes, _ipOffset + UDPFields_Fields.UDP_LEN_POS, UDPFields_Fields.UDP_LEN_LEN);
}
}
/// Fetch the header checksum.
public int Checksum
{
get
{
return UDPChecksum;
}
set
{
UDPChecksum=value;
}
}
/// Computes the UDP checksum, optionally updating the UDP checksum header.
///
///
/// Specifies whether or not to update the UDP checksum header
/// after computing the checksum. A value of true indicates the
/// header should be updated, a value of false indicates it should
/// not be updated.
///
/// The computed UDP checksum.
///
public int ComputeUDPChecksum(bool update)
{
if (IPVersion != IPVersions.IPv4)
throw new System.NotImplementedException("IPVersion of " + IPVersion + " is unrecognized");
// copy the udp section with data
byte[] udp = IPData;
// reset the checksum field (checksum is calculated when this field is
// zeroed)
ArrayHelper.insertLong(udp, 0, UDPFields_Fields.UDP_CSUM_POS, UDPFields_Fields.UDP_CSUM_LEN);
//pseudo ip header should be attached to the udp+data
udp = AttachPseudoIPHeader(udp);
// compute the one's complement sum of the udp header
int cs = ChecksumUtils.OnesComplementSum(udp);
if (update)
{
UDPChecksum = cs;
}
return cs;
}
public int ComputeUDPChecksum()
{
return ComputeUDPChecksum(true);
}
private byte[] _udpHeaderBytes = null;
private byte[] _udpDataBytes = null;
/// Fetch the UDP data as a byte array.
public override byte[] Data
{
get
{
return UDPData;
}
}
/// Convert this UDP packet to a readable string.
public override System.String ToString()
{
return ToColoredString(false);
}
/// Generate string with contents describing this UDP packet.
/// whether or not the string should contain ansi
/// color escape sequences.
///
public override System.String ToColoredString(bool colored)
{
System.Text.StringBuilder buffer = new System.Text.StringBuilder();
buffer.Append('[');
if (colored)
buffer.Append(Color);
buffer.Append("UDPPacket");
if (colored)
buffer.Append(AnsiEscapeSequences_Fields.RESET);
buffer.Append(": ");
buffer.Append(SourceAddress);
buffer.Append('.');
buffer.Append(IPPort.getName(SourcePort));
buffer.Append(" -> ");
buffer.Append(DestinationAddress);
buffer.Append('.');
buffer.Append(IPPort.getName(DestinationPort));
buffer.Append(" l=" + UDPFields_Fields.UDP_HEADER_LEN + "," + (Length - UDPFields_Fields.UDP_HEADER_LEN));
buffer.Append(']');
return buffer.ToString();
}
}
}