1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//! User Datagram Protocol related packet processing
use prelude::*;
/// The UDP parser
pub struct UdpParser;
impl Parsable<PathIp> for UdpParser {
/// Parse an `UdpPacket` from an `&[u8]`
fn parse<'a>(&mut self,
input: &'a [u8],
result: Option<&ParserResultVec>,
path: Option<&mut PathIp>)
-> IResult<&'a [u8], ParserResult> {
do_parse!(input,
// Check the IP protocol from the parent parser (IPv4 or IPv6)
expr_opt!(match result {
Some(vector) => match vector.last() {
// Check the parent node for the correct IP protocol
Some(ref any) => match (any.downcast_ref::<Ipv4Packet>(),
any.downcast_ref::<Ipv6Packet>()) {
// IPv4
(Some(ipv4), _) => if ipv4.protocol == IpProtocol::Udp {
Some(())
} else {
None
},
// IPv6
(_, Some(ipv6)) => if ipv6.next_header == IpProtocol::Udp {
Some(())
} else {
None
},
_ => None,
},
// Previous result found, but not correct parent
_ => None,
},
// Parse also if no result is given, for testability
None => Some(()),
}) >>
// Parse the header
src: be_u16 >>
dst: be_u16 >>
len: be_u16 >>
checksum: be_u16 >>
// Try to track the connection
path_error: expr_opt!(match track_connection(path, result, src, dst) {
Err(e) => Some(Some(e.code)),
Ok(()) => Some(None),
}) >>
(Box::new(UdpPacket {
header: UdpHeader {
source_port: src,
dest_port: dst,
length: len,
checksum: checksum,
},
path_error: path_error,
}))
)
}
}
impl fmt::Display for UdpParser {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "UDP")
}
}
#[derive(Debug, Eq, PartialEq)]
/// Representation of an User Datagram Protocol packet
pub struct UdpPacket {
/// The header of the UDP packet
pub header: UdpHeader,
/// Set to some error code if the connection tracking failed
pub path_error: Option<PathErrorType>,
}
#[derive(Debug, Eq, PartialEq)]
/// Representation of an User Datagram Protocol packet header
pub struct UdpHeader {
/// This field identifies the sender's port when meaningful and should be assumed to be the
/// port to reply to if needed. If not used, then it should be zero. If the source host is the
/// client, the port number is likely to be an ephemeral port number. If the source host is the
/// server, the port number is likely to be a well-known port number.
pub source_port: u16,
/// This field identifies the receiver's port and is required. Similar to source port number,
/// if the client is the destination host then the port number will likely be an ephemeral port
/// number and if the destination host is the server then the port number will likely be a
/// well-known port number.
pub dest_port: u16,
/// A field that specifies the length in bytes of the UDP header and UDP data. The minimum
/// length is 8 bytes because that is the length of the header. The field size sets a
/// theoretical limit of 65,535 bytes (8 byte header + 65,527 bytes of data) for a UDP
/// datagram. The practical limit for the data length which is imposed by the underlying IPv4
/// protocol is 65,507 bytes (65,535 − 8 byte UDP header − 20 byte IP header).
/// In IPv6 jumbograms it is possible to have UDP packets of size greater than 65,535 bytes.
/// RFC 2675 specifies that the length field is set to zero if the length of the UDP header
/// plus UDP data is greater than 65,535.
pub length: u16,
/// The checksum field may be used for error-checking of the header and data. This field is
/// optional in IPv4, and mandatory in IPv6. The field carries all-zeros if unused.
pub checksum: u16,
}