|  | @@ -876,13 +876,12 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
 | 
	
		
			
				|  |  |          let ip_payload = ipv6_packet.payload();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          #[cfg(feature = "socket-raw")]
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            if self.raw_socket_filter(sockets, &ipv6_repr.into(), ip_payload) {
 | 
	
		
			
				|  |  | -                return Ok(Packet::None);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +        let handled_by_raw_socket = self.raw_socket_filter(sockets, &ipv6_repr.into(), ip_payload);
 | 
	
		
			
				|  |  | +        #[cfg(not(feature = "socket-raw"))]
 | 
	
		
			
				|  |  | +        let handled_by_raw_socket = false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        self.process_nxt_hdr(sockets, timestamp, ipv6_repr, ipv6_repr.next_header, ip_payload)
 | 
	
		
			
				|  |  | +        self.process_nxt_hdr(sockets, timestamp, ipv6_repr, ipv6_repr.next_header,
 | 
	
		
			
				|  |  | +                             handled_by_raw_socket, ip_payload)
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /// Given the next header value forward the payload onto the correct process
 | 
	
	
		
			
				|  | @@ -890,7 +889,7 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
 | 
	
		
			
				|  |  |      #[cfg(feature = "proto-ipv6")]
 | 
	
		
			
				|  |  |      fn process_nxt_hdr<'frame>
 | 
	
		
			
				|  |  |                     (&mut self, sockets: &mut SocketSet, timestamp: Instant, ipv6_repr: Ipv6Repr,
 | 
	
		
			
				|  |  | -                    nxt_hdr: IpProtocol, ip_payload: &'frame [u8])
 | 
	
		
			
				|  |  | +                    nxt_hdr: IpProtocol, handled_by_raw_socket: bool, ip_payload: &'frame [u8])
 | 
	
		
			
				|  |  |                     -> Result<Packet<'frame>>
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |          match nxt_hdr {
 | 
	
	
		
			
				|  | @@ -899,14 +898,18 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              #[cfg(feature = "socket-udp")]
 | 
	
		
			
				|  |  |              IpProtocol::Udp =>
 | 
	
		
			
				|  |  | -                self.process_udp(sockets, ipv6_repr.into(), ip_payload),
 | 
	
		
			
				|  |  | +                self.process_udp(sockets, ipv6_repr.into(), handled_by_raw_socket, ip_payload),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              #[cfg(feature = "socket-tcp")]
 | 
	
		
			
				|  |  |              IpProtocol::Tcp =>
 | 
	
		
			
				|  |  |                  self.process_tcp(sockets, timestamp, ipv6_repr.into(), ip_payload),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              IpProtocol::HopByHop =>
 | 
	
		
			
				|  |  | -                self.process_hopbyhop(sockets, timestamp, ipv6_repr, ip_payload),
 | 
	
		
			
				|  |  | +                self.process_hopbyhop(sockets, timestamp, ipv6_repr, handled_by_raw_socket, ip_payload),
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            #[cfg(feature = "socket-raw")]
 | 
	
		
			
				|  |  | +            _ if handled_by_raw_socket =>
 | 
	
		
			
				|  |  | +                Ok(Packet::None),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              _ => {
 | 
	
		
			
				|  |  |                  // Send back as much of the original payload as we can.
 | 
	
	
		
			
				|  | @@ -970,10 +973,6 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          match ipv4_repr.protocol {
 | 
	
		
			
				|  |  | -            #[cfg(feature = "socket-raw")]
 | 
	
		
			
				|  |  | -            _ if handled_by_raw_socket =>
 | 
	
		
			
				|  |  | -                Ok(Packet::None),
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |              IpProtocol::Icmp =>
 | 
	
		
			
				|  |  |                  self.process_icmpv4(sockets, ip_repr, ip_payload),
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -983,12 +982,16 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              #[cfg(feature = "socket-udp")]
 | 
	
		
			
				|  |  |              IpProtocol::Udp =>
 | 
	
		
			
				|  |  | -                self.process_udp(sockets, ip_repr, ip_payload),
 | 
	
		
			
				|  |  | +                self.process_udp(sockets, ip_repr, handled_by_raw_socket, ip_payload),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              #[cfg(feature = "socket-tcp")]
 | 
	
		
			
				|  |  |              IpProtocol::Tcp =>
 | 
	
		
			
				|  |  |                  self.process_tcp(sockets, timestamp, ip_repr, ip_payload),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +            #[cfg(feature = "socket-raw")]
 | 
	
		
			
				|  |  | +            _ if handled_by_raw_socket =>
 | 
	
		
			
				|  |  | +                Ok(Packet::None),
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |              _ => {
 | 
	
		
			
				|  |  |                  // Send back as much of the original payload as we can.
 | 
	
		
			
				|  |  |                  let payload_len = icmp_reply_payload_len(ip_payload.len(), IPV4_MIN_MTU,
 | 
	
	
		
			
				|  | @@ -1170,7 +1173,8 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      #[cfg(feature = "proto-ipv6")]
 | 
	
		
			
				|  |  |      fn process_hopbyhop<'frame>(&mut self, sockets: &mut SocketSet, timestamp: Instant,
 | 
	
		
			
				|  |  | -                                ipv6_repr: Ipv6Repr, ip_payload: &'frame [u8]) -> Result<Packet<'frame>>
 | 
	
		
			
				|  |  | +                                ipv6_repr: Ipv6Repr, handled_by_raw_socket: bool,
 | 
	
		
			
				|  |  | +                                ip_payload: &'frame [u8]) -> Result<Packet<'frame>>
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |          let hbh_pkt = Ipv6HopByHopHeader::new_checked(ip_payload)?;
 | 
	
		
			
				|  |  |          let hbh_repr = Ipv6HopByHopRepr::parse(&hbh_pkt)?;
 | 
	
	
		
			
				|  | @@ -1195,7 +1199,7 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          self.process_nxt_hdr(sockets, timestamp, ipv6_repr, hbh_repr.next_header,
 | 
	
		
			
				|  |  | -                             &ip_payload[hbh_repr.buffer_len()..])
 | 
	
		
			
				|  |  | +                             handled_by_raw_socket, &ip_payload[hbh_repr.buffer_len()..])
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      #[cfg(feature = "proto-ipv4")]
 | 
	
	
		
			
				|  | @@ -1314,7 +1318,7 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      #[cfg(feature = "socket-udp")]
 | 
	
		
			
				|  |  |      fn process_udp<'frame>(&self, sockets: &mut SocketSet,
 | 
	
		
			
				|  |  | -                           ip_repr: IpRepr, ip_payload: &'frame [u8]) ->
 | 
	
		
			
				|  |  | +                           ip_repr: IpRepr, handled_by_raw_socket: bool, ip_payload: &'frame [u8]) ->
 | 
	
		
			
				|  |  |                            Result<Packet<'frame>>
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |          let (src_addr, dst_addr) = (ip_repr.src_addr(), ip_repr.dst_addr());
 | 
	
	
		
			
				|  | @@ -1336,6 +1340,12 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
 | 
	
		
			
				|  |  |          // The packet wasn't handled by a socket, send an ICMP port unreachable packet.
 | 
	
		
			
				|  |  |          match ip_repr {
 | 
	
		
			
				|  |  |              #[cfg(feature = "proto-ipv4")]
 | 
	
		
			
				|  |  | +            IpRepr::Ipv4(_) if handled_by_raw_socket =>
 | 
	
		
			
				|  |  | +                Ok(Packet::None),
 | 
	
		
			
				|  |  | +            #[cfg(feature = "proto-ipv6")]
 | 
	
		
			
				|  |  | +            IpRepr::Ipv6(_) if handled_by_raw_socket =>
 | 
	
		
			
				|  |  | +                Ok(Packet::None),
 | 
	
		
			
				|  |  | +            #[cfg(feature = "proto-ipv4")]
 | 
	
		
			
				|  |  |              IpRepr::Ipv4(ipv4_repr) => {
 | 
	
		
			
				|  |  |                  let payload_len = icmp_reply_payload_len(ip_payload.len(), IPV4_MIN_MTU,
 | 
	
		
			
				|  |  |                                                           ipv4_repr.buffer_len());
 | 
	
	
		
			
				|  | @@ -1957,7 +1967,7 @@ mod test {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          // Ensure that the unknown protocol triggers an error response.
 | 
	
		
			
				|  |  |          // And we correctly handle no payload.
 | 
	
		
			
				|  |  | -        assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr, data),
 | 
	
		
			
				|  |  | +        assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr, false, data),
 | 
	
		
			
				|  |  |                     Ok(expected_repr));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          let ip_repr = IpRepr::Ipv4(Ipv4Repr {
 | 
	
	
		
			
				|  | @@ -1977,7 +1987,7 @@ mod test {
 | 
	
		
			
				|  |  |          // ICMP error response when the destination address is a
 | 
	
		
			
				|  |  |          // 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));
 | 
	
		
			
				|  |  | +                   false, packet_broadcast.into_inner()), Ok(Packet::None));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      #[test]
 | 
	
	
		
			
				|  | @@ -2040,7 +2050,7 @@ mod test {
 | 
	
		
			
				|  |  |                        &ChecksumCapabilities::default());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          // Packet should be handled by bound UDP socket
 | 
	
		
			
				|  |  | -        assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr, packet.into_inner()),
 | 
	
		
			
				|  |  | +        assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr, false, packet.into_inner()),
 | 
	
		
			
				|  |  |                     Ok(Packet::None));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          {
 | 
	
	
		
			
				|  | @@ -2198,10 +2208,10 @@ mod test {
 | 
	
		
			
				|  |  |          assert_eq!(expected_ip_repr.buffer_len() + expected_icmp_repr.buffer_len(), MIN_MTU);
 | 
	
		
			
				|  |  |          // The expected packet and the generated packet are equal
 | 
	
		
			
				|  |  |          #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
 | 
	
		
			
				|  |  | -        assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr.into(), payload),
 | 
	
		
			
				|  |  | +        assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr.into(), false, payload),
 | 
	
		
			
				|  |  |                     Ok(Packet::Icmpv4((expected_ip_repr, expected_icmp_repr))));
 | 
	
		
			
				|  |  |          #[cfg(feature = "proto-ipv6")]
 | 
	
		
			
				|  |  | -        assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr.into(), payload),
 | 
	
		
			
				|  |  | +        assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr.into(), false, payload),
 | 
	
		
			
				|  |  |                     Ok(Packet::Icmpv6((expected_ip_repr, expected_icmp_repr))));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -2645,4 +2655,82 @@ mod test {
 | 
	
		
			
				|  |  |          assert_eq!(iface.inner.process_ipv4(&mut socket_set, Instant::from_millis(0), &frame),
 | 
	
		
			
				|  |  |                     Ok(Packet::None));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #[test]
 | 
	
		
			
				|  |  | +    #[cfg(all(feature = "proto-ipv4", feature = "socket-raw", feature = "socket-udp"))]
 | 
	
		
			
				|  |  | +    fn test_raw_socket_with_udp_socket() {
 | 
	
		
			
				|  |  | +        use socket::{UdpSocket, UdpSocketBuffer, UdpPacketMetadata,
 | 
	
		
			
				|  |  | +                     RawSocket, RawSocketBuffer, RawPacketMetadata};
 | 
	
		
			
				|  |  | +        use wire::{IpVersion, IpEndpoint, Ipv4Packet, UdpPacket, UdpRepr};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        static UDP_PAYLOAD: [u8; 5] = [0x48, 0x65, 0x6c, 0x6c, 0x6f];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let (mut iface, mut socket_set) = create_loopback();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let udp_rx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; 15]);
 | 
	
		
			
				|  |  | +        let udp_tx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; 15]);
 | 
	
		
			
				|  |  | +        let udp_socket = UdpSocket::new(udp_rx_buffer, udp_tx_buffer);
 | 
	
		
			
				|  |  | +        let udp_socket_handle = socket_set.add(udp_socket);
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            // Bind the socket to port 68
 | 
	
		
			
				|  |  | +            let mut socket = socket_set.get::<UdpSocket>(udp_socket_handle);
 | 
	
		
			
				|  |  | +            assert_eq!(socket.bind(68), Ok(()));
 | 
	
		
			
				|  |  | +            assert!(!socket.can_recv());
 | 
	
		
			
				|  |  | +            assert!(socket.can_send());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let packets = 1;
 | 
	
		
			
				|  |  | +        let raw_rx_buffer = RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * 1]);
 | 
	
		
			
				|  |  | +        let raw_tx_buffer = RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * packets]);
 | 
	
		
			
				|  |  | +        let raw_socket = RawSocket::new(IpVersion::Ipv4, IpProtocol::Udp, raw_rx_buffer, raw_tx_buffer);
 | 
	
		
			
				|  |  | +        socket_set.add(raw_socket);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let src_addr = Ipv4Address([127, 0, 0, 2]);
 | 
	
		
			
				|  |  | +        let dst_addr = Ipv4Address([127, 0, 0, 1]);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let udp_repr = UdpRepr {
 | 
	
		
			
				|  |  | +            src_port: 67,
 | 
	
		
			
				|  |  | +            dst_port: 68,
 | 
	
		
			
				|  |  | +            payload: &UDP_PAYLOAD
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        let mut bytes = vec![0xff; udp_repr.buffer_len()];
 | 
	
		
			
				|  |  | +        let mut packet = UdpPacket::new_unchecked(&mut bytes[..]);
 | 
	
		
			
				|  |  | +        udp_repr.emit(&mut packet, &src_addr.into(), &dst_addr.into(), &ChecksumCapabilities::default());
 | 
	
		
			
				|  |  | +        let ipv4_repr = Ipv4Repr {
 | 
	
		
			
				|  |  | +            src_addr: src_addr,
 | 
	
		
			
				|  |  | +            dst_addr: dst_addr,
 | 
	
		
			
				|  |  | +            protocol: IpProtocol::Udp,
 | 
	
		
			
				|  |  | +            hop_limit: 64,
 | 
	
		
			
				|  |  | +            payload_len: udp_repr.buffer_len()
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // Emit to ethernet frame
 | 
	
		
			
				|  |  | +        let mut eth_bytes = vec![0u8;
 | 
	
		
			
				|  |  | +            EthernetFrame::<&[u8]>::header_len() +
 | 
	
		
			
				|  |  | +            ipv4_repr.buffer_len() + udp_repr.buffer_len()
 | 
	
		
			
				|  |  | +        ];
 | 
	
		
			
				|  |  | +        let frame = {
 | 
	
		
			
				|  |  | +            let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes);
 | 
	
		
			
				|  |  | +            ipv4_repr.emit(
 | 
	
		
			
				|  |  | +                &mut Ipv4Packet::new_unchecked(frame.payload_mut()),
 | 
	
		
			
				|  |  | +                &ChecksumCapabilities::default());
 | 
	
		
			
				|  |  | +            udp_repr.emit(
 | 
	
		
			
				|  |  | +                &mut UdpPacket::new_unchecked(
 | 
	
		
			
				|  |  | +                    &mut frame.payload_mut()[ipv4_repr.buffer_len()..]),
 | 
	
		
			
				|  |  | +                &src_addr.into(),
 | 
	
		
			
				|  |  | +                &dst_addr.into(),
 | 
	
		
			
				|  |  | +                &ChecksumCapabilities::default());
 | 
	
		
			
				|  |  | +            EthernetFrame::new_unchecked(&*frame.into_inner())
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assert_eq!(iface.inner.process_ipv4(&mut socket_set, Instant::from_millis(0), &frame),
 | 
	
		
			
				|  |  | +                   Ok(Packet::None));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            // Make sure the UDP socket can still receive in presence of a Raw socket that handles UDP
 | 
	
		
			
				|  |  | +            let mut socket = socket_set.get::<UdpSocket>(udp_socket_handle);
 | 
	
		
			
				|  |  | +            assert!(socket.can_recv());
 | 
	
		
			
				|  |  | +            assert_eq!(socket.recv(), Ok((&UDP_PAYLOAD[..], IpEndpoint::new(src_addr.into(), 67))));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  }
 |