Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow receiving broadcast packets in UDP #66

Merged
merged 4 commits into from
Nov 23, 2017
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 61 additions & 3 deletions src/iface/ethernet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ impl<'b, 'c> InterfaceInner<'b, 'c> {
}
}

if !self.has_ip_addr(ipv4_repr.dst_addr) {
if !ipv4_repr.dst_addr.is_broadcast() && !self.has_ip_addr(ipv4_repr.dst_addr) {
// Ignore IP packets not directed at us.
return Ok(Packet::None)
}
Expand Down Expand Up @@ -884,7 +884,6 @@ mod test {
let mut packet_unicast = UdpPacket::new(&mut udp_bytes_unicast);
let mut packet_broadcast = UdpPacket::new(&mut udp_bytes_broadcast);

// Unknown Ipv4 Protocol with no payload
let udp_repr = UdpRepr {
src_port: 67,
dst_port: 68,
Expand Down Expand Up @@ -949,10 +948,69 @@ mod test {

// Ensure that the port unreachable error does not trigger an
// ICMP error response when the destination address is a
// broadcast address
// broadcast address and no socket is bound to the port.
assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr,
packet_broadcast.into_inner()), Ok(Packet::None));
}

#[test]
#[cfg(feature = "socket-udp")]
fn test_handle_udp_broadcast() {
use socket::{UdpPacketBuffer, UdpSocket, UdpSocketBuffer};
use wire::IpEndpoint;

static UDP_PAYLOAD: [u8; 5] = [0x48, 0x65, 0x6c, 0x6c, 0x6f];

let (iface, mut socket_set) = create_loopback();

let rx_buffer = UdpSocketBuffer::new(vec![UdpPacketBuffer::new(vec![0; 15])]);
let tx_buffer = UdpSocketBuffer::new(vec![UdpPacketBuffer::new(vec![0; 15])]);

let udp_socket = UdpSocket::new(rx_buffer, tx_buffer);

let mut udp_bytes = vec![0u8; 13];
let mut packet = UdpPacket::new(&mut udp_bytes);

let socket_handle = socket_set.add(udp_socket);

let src_ip = Ipv4Address([0x7f, 0x00, 0x00, 0x02]);

let udp_repr = UdpRepr {
src_port: 67,
dst_port: 68,
payload: &UDP_PAYLOAD
};

let ip_repr = IpRepr::Ipv4(Ipv4Repr {
src_addr: src_ip,
dst_addr: Ipv4Address::BROADCAST,
protocol: IpProtocol::Udp,
payload_len: udp_repr.buffer_len(),
ttl: 0x40
});

{
// Bind the socket to port 68
let mut socket = socket_set.get::<UdpSocket>(socket_handle);
assert_eq!(socket.bind(68), Ok(()));
assert!(!socket.can_recv());
assert!(socket.can_send());
}

udp_repr.emit(&mut packet, &ip_repr.src_addr(), &ip_repr.dst_addr(),
&ChecksumCapabilities::default());

// Packet should be handled by bound UDP socket
assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr, packet.into_inner()),
Ok(Packet::None));

{
// Make sure the payload to the UDP packet processed by process_udp is
// appended to the bound sockets rx_buffer
let mut socket = socket_set.get::<UdpSocket>(socket_handle);
assert!(socket.can_recv());
assert_eq!(socket.recv(), Ok((&UDP_PAYLOAD[..], IpEndpoint::new(src_ip.into(), 67))));
}
}

#[test]
Expand Down