浏览代码

Allow receiving broadcast packets via UDP sockets.

Jeremy Soller 7 年之前
父节点
当前提交
d8b25cdce8
共有 1 个文件被更改,包括 61 次插入3 次删除
  1. 61 3
      src/iface/ethernet.rs

+ 61 - 3
src/iface/ethernet.rs

@@ -418,7 +418,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)
         }
@@ -912,7 +912,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,
@@ -977,10 +976,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]