瀏覽代碼

Add support for IPv6 gateways.

Closes: #207
Approved by: dlrobertson
Valentin Lorentz 7 年之前
父節點
當前提交
4bf917ced3
共有 6 個文件被更改,包括 158 次插入41 次删除
  1. 1 1
      Cargo.toml
  2. 13 1
      README.md
  3. 6 2
      examples/httpclient.rs
  4. 74 27
      examples/ping.rs
  5. 58 4
      src/iface/ethernet.rs
  6. 6 6
      src/socket/icmp.rs

+ 1 - 1
Cargo.toml

@@ -57,7 +57,7 @@ required-features = ["std", "phy-raw_socket", "proto-ipv4"]
 
 
 [[example]]
 [[example]]
 name = "httpclient"
 name = "httpclient"
-required-features = ["std", "phy-tap_interface", "proto-ipv4", "socket-tcp"]
+required-features = ["std", "phy-tap_interface", "proto-ipv4", "proto-ipv6", "socket-tcp"]
 
 
 [[example]]
 [[example]]
 name = "ping"
 name = "ping"

+ 13 - 1
README.md

@@ -190,6 +190,10 @@ a specific user:
 sudo ip tuntap add name tap0 mode tap user $USER
 sudo ip tuntap add name tap0 mode tap user $USER
 sudo ip link set tap0 up
 sudo ip link set tap0 up
 sudo ip addr add 192.168.69.100/24 dev tap0
 sudo ip addr add 192.168.69.100/24 dev tap0
+sudo ip -6 addr add fe80::100/64 dev tap0
+sudo ip -6 addr add fdaa::100/64 dev tap0
+sudo ip -6 route add fe80::/64 dev tap0
+sudo ip -6 route add fdaa::/64 dev tap0
 ```
 ```
 
 
 It's possible to let _smoltcp_ access Internet by enabling routing for the tap interface:
 It's possible to let _smoltcp_ access Internet by enabling routing for the tap interface:
@@ -197,6 +201,8 @@ It's possible to let _smoltcp_ access Internet by enabling routing for the tap i
 ```sh
 ```sh
 sudo iptables -t nat -A POSTROUTING -s 192.168.69.0/24 -j MASQUERADE
 sudo iptables -t nat -A POSTROUTING -s 192.168.69.0/24 -j MASQUERADE
 sudo sysctl net.ipv4.ip_forward=1
 sudo sysctl net.ipv4.ip_forward=1
+sudo ip6tables -t nat -A POSTROUTING -s fdaa::/64 -j MASQUERADE
+sudo sysctl -w net.ipv6.conf.all.forwarding=1
 ```
 ```
 
 
 ### Fault injection
 ### Fault injection
@@ -245,7 +251,7 @@ sudo ./target/debug/examples/tcpdump eth0
 
 
 _examples/httpclient.rs_ emulates a network host that can initiate HTTP requests.
 _examples/httpclient.rs_ emulates a network host that can initiate HTTP requests.
 
 
-The host is assigned the hardware address `02-00-00-00-00-02` and IPv4 address `192.168.69.1`.
+The host is assigned the hardware address `02-00-00-00-00-02`, IPv4 address `192.168.69.1`, and IPv6 address `fdaa::1`.
 
 
 Read its [source code](/examples/httpclient.rs), then run it as:
 Read its [source code](/examples/httpclient.rs), then run it as:
 
 
@@ -259,6 +265,12 @@ For example:
 cargo run --example httpclient -- tap0 93.184.216.34 http://example.org/
 cargo run --example httpclient -- tap0 93.184.216.34 http://example.org/
 ```
 ```
 
 
+or:
+
+```sh
+cargo run --example httpclient -- tap0 2606:2800:220:1:248:1893:25c8:1946 http://example.org/
+```
+
 It connects to the given address (not a hostname) and URL, and prints any returned response data.
 It connects to the given address (not a hostname) and URL, and prints any returned response data.
 The TCP socket buffers are limited to 1024 bytes to make packet traces more interesting.
 The TCP socket buffers are limited to 1024 bytes to make packet traces more interesting.
 
 

+ 6 - 2
examples/httpclient.rs

@@ -13,7 +13,7 @@ use std::collections::BTreeMap;
 use std::os::unix::io::AsRawFd;
 use std::os::unix::io::AsRawFd;
 use url::Url;
 use url::Url;
 use smoltcp::phy::wait as phy_wait;
 use smoltcp::phy::wait as phy_wait;
-use smoltcp::wire::{EthernetAddress, Ipv4Address, IpAddress, IpCidr};
+use smoltcp::wire::{EthernetAddress, Ipv4Address, Ipv6Address, IpAddress, IpCidr};
 use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder};
 use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder};
 use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
 use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
 use smoltcp::time::Instant;
 use smoltcp::time::Instant;
@@ -42,13 +42,17 @@ fn main() {
     let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
     let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
 
 
     let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x02]);
     let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x02]);
-    let ip_addrs = [IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24)];
+    let ip_addrs = [IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24),
+                    IpCidr::new(IpAddress::v6(0xfdaa, 0, 0, 0, 0, 0, 0, 1), 64),
+                    IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64)];
     let default_v4_gw = Ipv4Address::new(192, 168, 69, 100);
     let default_v4_gw = Ipv4Address::new(192, 168, 69, 100);
+    let default_v6_gw = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0x100);
     let mut iface = EthernetInterfaceBuilder::new(device)
     let mut iface = EthernetInterfaceBuilder::new(device)
             .ethernet_addr(ethernet_addr)
             .ethernet_addr(ethernet_addr)
             .neighbor_cache(neighbor_cache)
             .neighbor_cache(neighbor_cache)
             .ip_addrs(ip_addrs)
             .ip_addrs(ip_addrs)
             .ipv4_gateway(default_v4_gw)
             .ipv4_gateway(default_v4_gw)
+            .ipv6_gateway(default_v6_gw)
             .finalize();
             .finalize();
 
 
     let mut sockets = SocketSet::new(vec![]);
     let mut sockets = SocketSet::new(vec![]);

+ 74 - 27
examples/ping.rs

@@ -15,12 +15,47 @@ use smoltcp::time::{Duration, Instant};
 use smoltcp::phy::Device;
 use smoltcp::phy::Device;
 use smoltcp::phy::wait as phy_wait;
 use smoltcp::phy::wait as phy_wait;
 use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr,
 use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr,
+                    Ipv6Address, Icmpv6Repr, Icmpv6Packet,
                     Ipv4Address, Icmpv4Repr, Icmpv4Packet};
                     Ipv4Address, Icmpv4Repr, Icmpv4Packet};
 use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder};
 use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder};
 use smoltcp::socket::{SocketSet, IcmpSocket, IcmpSocketBuffer, IcmpPacketMetadata, IcmpEndpoint};
 use smoltcp::socket::{SocketSet, IcmpSocket, IcmpSocketBuffer, IcmpPacketMetadata, IcmpEndpoint};
 use std::collections::HashMap;
 use std::collections::HashMap;
 use byteorder::{ByteOrder, NetworkEndian};
 use byteorder::{ByteOrder, NetworkEndian};
 
 
+macro_rules! send_icmp_ping {
+    ( $repr_type:ident, $packet_type:ident, $ident:expr, $seq_no:expr,
+      $echo_payload:expr, $socket:expr, $remote_addr:expr ) => {{
+        let icmp_repr = $repr_type::EchoRequest {
+            ident: $ident,
+            seq_no: $seq_no,
+            data: &$echo_payload,
+        };
+
+        let icmp_payload = $socket
+            .send(icmp_repr.buffer_len(), $remote_addr)
+            .unwrap();
+
+        let mut icmp_packet = $packet_type::new(icmp_payload);
+        (icmp_repr, icmp_packet)
+    }}
+}
+
+macro_rules! get_icmp_pong {
+    ( $repr_type:ident, $repr:expr, $payload:expr, $waiting_queue:expr, $remote_addr:expr,
+      $timestamp:expr, $received:expr ) => {{
+        if let $repr_type::EchoReply { seq_no, data, .. } = $repr {
+            if let Some(_) = $waiting_queue.get(&seq_no) {
+                let packet_timestamp_ms = NetworkEndian::read_i64(data);
+                println!("{} bytes from {}: icmp_seq={}, time={}ms",
+                         data.len(), $remote_addr, seq_no,
+                         $timestamp.total_millis() - packet_timestamp_ms);
+                $waiting_queue.remove(&seq_no);
+                $received += 1;
+            }
+        }
+    }}
+}
+
 fn main() {
 fn main() {
     utils::setup_logging("warn");
     utils::setup_logging("warn");
 
 
@@ -40,7 +75,7 @@ fn main() {
     let fd = device.as_raw_fd();
     let fd = device.as_raw_fd();
     let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false);
     let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false);
     let device_caps = device.capabilities();
     let device_caps = device.capabilities();
-    let address  = Ipv4Address::from_str(&matches.free[0]).expect("invalid address format");
+    let address  = IpAddress::from_str(&matches.free[0]).expect("invalid address format");
     let count    = matches.opt_str("count").map(|s| usize::from_str(&s).unwrap()).unwrap_or(4);
     let count    = matches.opt_str("count").map(|s| usize::from_str(&s).unwrap()).unwrap_or(4);
     let interval = matches.opt_str("interval")
     let interval = matches.opt_str("interval")
         .map(|s| Duration::from_secs(u64::from_str(&s).unwrap()))
         .map(|s| Duration::from_secs(u64::from_str(&s).unwrap()))
@@ -52,19 +87,23 @@ fn main() {
     let neighbor_cache = NeighborCache::new(BTreeMap::new());
     let neighbor_cache = NeighborCache::new(BTreeMap::new());
 
 
     let remote_addr = address;
     let remote_addr = address;
-    let local_addr  = Ipv4Address::new(192, 168, 69, 1);
 
 
     let icmp_rx_buffer = IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY], vec![0; 256]);
     let icmp_rx_buffer = IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY], vec![0; 256]);
     let icmp_tx_buffer = IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY], vec![0; 256]);
     let icmp_tx_buffer = IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY], vec![0; 256]);
     let icmp_socket = IcmpSocket::new(icmp_rx_buffer, icmp_tx_buffer);
     let icmp_socket = IcmpSocket::new(icmp_rx_buffer, icmp_tx_buffer);
 
 
     let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x02]);
     let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x02]);
-    let ip_addr = IpCidr::new(IpAddress::from(local_addr), 24);
+    let src_ipv6 = IpAddress::v6(0xfdaa, 0, 0, 0, 0, 0, 0, 1);
+    let ip_addrs = [IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24),
+                    IpCidr::new(src_ipv6, 64),
+                    IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64)];
     let default_v4_gw = Ipv4Address::new(192, 168, 69, 100);
     let default_v4_gw = Ipv4Address::new(192, 168, 69, 100);
+    let default_v6_gw = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0x100);
     let mut iface = EthernetInterfaceBuilder::new(device)
     let mut iface = EthernetInterfaceBuilder::new(device)
             .ethernet_addr(ethernet_addr)
             .ethernet_addr(ethernet_addr)
-            .ip_addrs([ip_addr])
+            .ip_addrs(ip_addrs)
             .ipv4_gateway(default_v4_gw)
             .ipv4_gateway(default_v4_gw)
+            .ipv6_gateway(default_v6_gw)
             .neighbor_cache(neighbor_cache)
             .neighbor_cache(neighbor_cache)
             .finalize();
             .finalize();
 
 
@@ -77,7 +116,6 @@ fn main() {
     let mut echo_payload = [0xffu8; 40];
     let mut echo_payload = [0xffu8; 40];
     let mut waiting_queue = HashMap::new();
     let mut waiting_queue = HashMap::new();
     let ident = 0x22b;
     let ident = 0x22b;
-    let endpoint = IpAddress::Ipv4(remote_addr);
 
 
     loop {
     loop {
         iface.poll(&mut sockets, Instant::now()).unwrap();
         iface.poll(&mut sockets, Instant::now()).unwrap();
@@ -93,18 +131,23 @@ fn main() {
             if socket.can_send() && seq_no < count as u16 &&
             if socket.can_send() && seq_no < count as u16 &&
                     send_at <= timestamp {
                     send_at <= timestamp {
                 NetworkEndian::write_i64(&mut echo_payload, timestamp.total_millis());
                 NetworkEndian::write_i64(&mut echo_payload, timestamp.total_millis());
-                let icmp_repr = Icmpv4Repr::EchoRequest {
-                    ident: ident,
-                    seq_no,
-                    data: &echo_payload,
-                };
-
-                let icmp_payload = socket
-                    .send(icmp_repr.buffer_len(), endpoint)
-                    .unwrap();
 
 
-                let mut icmp_packet = Icmpv4Packet::new(icmp_payload);
+                match remote_addr {
-                icmp_repr.emit(&mut icmp_packet, &device_caps.checksum);
+                    IpAddress::Ipv4(_) => {
+                        let (icmp_repr, mut icmp_packet) = send_icmp_ping!(
+                                Icmpv4Repr, Icmpv4Packet, ident, seq_no,
+                                echo_payload, socket, remote_addr);
+                        icmp_repr.emit(&mut icmp_packet, &device_caps.checksum);
+                    },
+                    IpAddress::Ipv6(_) => {
+                        let (icmp_repr, mut icmp_packet) = send_icmp_ping!(
+                                Icmpv6Repr, Icmpv6Packet, ident, seq_no,
+                                echo_payload, socket, remote_addr);
+                        icmp_repr.emit(&src_ipv6, &remote_addr,
+                                       &mut icmp_packet, &device_caps.checksum);
+                    },
+                    _ => unimplemented!()
+                }
 
 
                 waiting_queue.insert(seq_no, timestamp);
                 waiting_queue.insert(seq_no, timestamp);
                 seq_no += 1;
                 seq_no += 1;
@@ -113,18 +156,22 @@ fn main() {
 
 
             if socket.can_recv() {
             if socket.can_recv() {
                 let (payload, _) = socket.recv().unwrap();
                 let (payload, _) = socket.recv().unwrap();
-                let icmp_packet = Icmpv4Packet::new(&payload);
+
-                let icmp_repr = Icmpv4Repr::parse(&icmp_packet, &device_caps.checksum).unwrap();
+                match remote_addr {
-
+                    IpAddress::Ipv4(_) => {
-                if let Icmpv4Repr::EchoReply { seq_no, data, .. } = icmp_repr {
+                        let icmp_packet = Icmpv4Packet::new(&payload);
-                    if let Some(_) = waiting_queue.get(&seq_no) {
+                        let icmp_repr = Icmpv4Repr::parse(&icmp_packet, &device_caps.checksum).unwrap();
-                        let packet_timestamp_ms = NetworkEndian::read_i64(data);
+                        get_icmp_pong!(Icmpv4Repr, icmp_repr, payload,
-                        println!("{} bytes from {}: icmp_seq={}, time={}ms",
+                                waiting_queue, remote_addr, timestamp, received);
-                                 data.len(), remote_addr, seq_no,
-                                 timestamp.total_millis() - packet_timestamp_ms);
-                        waiting_queue.remove(&seq_no);
-                        received += 1;
                     }
                     }
+                    IpAddress::Ipv6(_) => {
+                        let icmp_packet = Icmpv6Packet::new(&payload);
+                        let icmp_repr = Icmpv6Repr::parse(&remote_addr, &src_ipv6,
+                                &icmp_packet, &device_caps.checksum).unwrap();
+                        get_icmp_pong!(Icmpv6Repr, icmp_repr, payload,
+                                waiting_queue, remote_addr, timestamp, received);
+                    },
+                    _ => unimplemented!()
                 }
                 }
             }
             }
 
 

+ 58 - 4
src/iface/ethernet.rs

@@ -65,6 +65,8 @@ struct InterfaceInner<'b, 'c> {
     ip_addrs:               ManagedSlice<'c, IpCidr>,
     ip_addrs:               ManagedSlice<'c, IpCidr>,
     #[cfg(feature = "proto-ipv4")]
     #[cfg(feature = "proto-ipv4")]
     ipv4_gateway:           Option<Ipv4Address>,
     ipv4_gateway:           Option<Ipv4Address>,
+    #[cfg(feature = "proto-ipv6")]
+    ipv6_gateway:           Option<Ipv6Address>,
     device_capabilities:    DeviceCapabilities,
     device_capabilities:    DeviceCapabilities,
 }
 }
 
 
@@ -77,6 +79,8 @@ pub struct InterfaceBuilder <'b, 'c, DeviceT: for<'d> Device<'d>> {
     ip_addrs:            ManagedSlice<'c, IpCidr>,
     ip_addrs:            ManagedSlice<'c, IpCidr>,
     #[cfg(feature = "proto-ipv4")]
     #[cfg(feature = "proto-ipv4")]
     ipv4_gateway:        Option<Ipv4Address>,
     ipv4_gateway:        Option<Ipv4Address>,
+    #[cfg(feature = "proto-ipv6")]
+    ipv6_gateway:        Option<Ipv6Address>,
 }
 }
 
 
 impl<'b, 'c, DeviceT> InterfaceBuilder<'b, 'c, DeviceT>
 impl<'b, 'c, DeviceT> InterfaceBuilder<'b, 'c, DeviceT>
@@ -113,7 +117,9 @@ impl<'b, 'c, DeviceT> InterfaceBuilder<'b, 'c, DeviceT>
             neighbor_cache:      None,
             neighbor_cache:      None,
             ip_addrs:            ManagedSlice::Borrowed(&mut []),
             ip_addrs:            ManagedSlice::Borrowed(&mut []),
             #[cfg(feature = "proto-ipv4")]
             #[cfg(feature = "proto-ipv4")]
-            ipv4_gateway:        None
+            ipv4_gateway:        None,
+            #[cfg(feature = "proto-ipv6")]
+            ipv6_gateway:        None,
         }
         }
     }
     }
 
 
@@ -158,11 +164,28 @@ impl<'b, 'c, DeviceT> InterfaceBuilder<'b, 'c, DeviceT>
         where T: Into<Ipv4Address>
         where T: Into<Ipv4Address>
     {
     {
         let addr = gateway.into();
         let addr = gateway.into();
-        InterfaceInner::check_gateway_addr(&addr);
+        InterfaceInner::check_ipv4_gateway_addr(&addr);
         self.ipv4_gateway = Some(addr);
         self.ipv4_gateway = Some(addr);
         self
         self
     }
     }
 
 
+    /// Set the IPv6 gateway the interface will use. See also
+    /// [ipv6_gateway].
+    ///
+    /// # Panics
+    /// This function panics if the given address is not unicast.
+    ///
+    /// [ipv6_gateway]: struct.EthernetInterface.html#method.ipv6_gateway
+    #[cfg(feature = "proto-ipv6")]
+    pub fn ipv6_gateway<T>(mut self, gateway: T) -> InterfaceBuilder<'b, 'c, DeviceT>
+        where T: Into<Ipv6Address>
+    {
+        let addr = gateway.into();
+        InterfaceInner::check_ipv6_gateway_addr(&addr);
+        self.ipv6_gateway = Some(addr);
+        self
+    }
+
     /// Set the Neighbor Cache the interface will use.
     /// Set the Neighbor Cache the interface will use.
     pub fn neighbor_cache(mut self, neighbor_cache: NeighborCache<'b>) ->
     pub fn neighbor_cache(mut self, neighbor_cache: NeighborCache<'b>) ->
                          InterfaceBuilder<'b, 'c, DeviceT> {
                          InterfaceBuilder<'b, 'c, DeviceT> {
@@ -192,6 +215,8 @@ impl<'b, 'c, DeviceT> InterfaceBuilder<'b, 'c, DeviceT>
                         ip_addrs: self.ip_addrs,
                         ip_addrs: self.ip_addrs,
                         #[cfg(feature = "proto-ipv4")]
                         #[cfg(feature = "proto-ipv4")]
                         ipv4_gateway: self.ipv4_gateway,
                         ipv4_gateway: self.ipv4_gateway,
+                        #[cfg(feature = "proto-ipv6")]
+                        ipv6_gateway: self.ipv6_gateway,
                     }
                     }
                 }
                 }
             },
             },
@@ -299,7 +324,24 @@ impl<'b, 'c, DeviceT> Interface<'b, 'c, DeviceT>
     pub fn set_ipv4_gateway<GatewayAddrT>(&mut self, gateway: GatewayAddrT)
     pub fn set_ipv4_gateway<GatewayAddrT>(&mut self, gateway: GatewayAddrT)
             where GatewayAddrT: Into<Option<Ipv4Address>> {
             where GatewayAddrT: Into<Option<Ipv4Address>> {
         self.inner.ipv4_gateway = gateway.into();
         self.inner.ipv4_gateway = gateway.into();
-        self.inner.ipv4_gateway.map(|addr| InterfaceInner::check_gateway_addr(&addr));
+        self.inner.ipv4_gateway.map(|addr| InterfaceInner::check_ipv4_gateway_addr(&addr));
+    }
+
+    /// Get the IPv6 gateway of the interface.
+    #[cfg(feature = "proto-ipv6")]
+    pub fn ipv6_gateway(&self) -> Option<Ipv6Address> {
+        self.inner.ipv6_gateway
+    }
+
+    /// Set the IPv6 gateway of the interface.
+    ///
+    /// # Panics
+    /// This function panics if the given address is not unicast.
+    #[cfg(feature = "proto-ipv6")]
+    pub fn set_ipv6_gateway<GatewayAddrT>(&mut self, gateway: GatewayAddrT)
+            where GatewayAddrT: Into<Option<Ipv6Address>> {
+        self.inner.ipv6_gateway = gateway.into();
+        self.inner.ipv6_gateway.map(|addr| InterfaceInner::check_ipv6_gateway_addr(&addr));
     }
     }
 
 
     /// Transmit packets queued in the given sockets, and receive packets queued
     /// Transmit packets queued in the given sockets, and receive packets queued
@@ -490,7 +532,14 @@ impl<'b, 'c> InterfaceInner<'b, 'c> {
     }
     }
 
 
     #[cfg(feature = "proto-ipv4")]
     #[cfg(feature = "proto-ipv4")]
-    fn check_gateway_addr(addr: &Ipv4Address) {
+    fn check_ipv4_gateway_addr(addr: &Ipv4Address) {
+        if !addr.is_unicast() {
+            panic!("gateway IP address {} is not unicast", addr);
+        }
+    }
+
+    #[cfg(feature = "proto-ipv6")]
+    fn check_ipv6_gateway_addr(addr: &Ipv6Address) {
         if !addr.is_unicast() {
         if !addr.is_unicast() {
             panic!("gateway IP address {} is not unicast", addr);
             panic!("gateway IP address {} is not unicast", addr);
         }
         }
@@ -1146,6 +1195,11 @@ impl<'b, 'c> InterfaceInner<'b, 'c> {
                 Some(gateway) => Ok(gateway.into()),
                 Some(gateway) => Ok(gateway.into()),
                 None => Err(Error::Unaddressable),
                 None => Err(Error::Unaddressable),
             }
             }
+            #[cfg(feature = "proto-ipv6")]
+            &IpAddress::Ipv6(_) => match self.ipv6_gateway {
+                Some(gateway) => Ok(gateway.into()),
+                None => Err(Error::Unaddressable),
+            }
             _ => Err(Error::Unaddressable)
             _ => Err(Error::Unaddressable)
         }
         }
     }
     }

+ 6 - 6
src/socket/icmp.rs

@@ -341,7 +341,7 @@ impl<'a, 'b> IcmpSocket<'a, 'b> {
                     let ip_repr = IpRepr::Ipv6(Ipv6Repr {
                     let ip_repr = IpRepr::Ipv6(Ipv6Repr {
                         src_addr:    src_addr,
                         src_addr:    src_addr,
                         dst_addr:    ipv6_addr,
                         dst_addr:    ipv6_addr,
-                        next_header: IpProtocol::Icmp,
+                        next_header: IpProtocol::Icmpv6,
                         payload_len: repr.buffer_len(),
                         payload_len: repr.buffer_len(),
                         hop_limit:   hop_limit,
                         hop_limit:   hop_limit,
                     });
                     });
@@ -609,7 +609,7 @@ mod test_ipv6 {
     static LOCAL_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
     static LOCAL_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
         src_addr: Ipv6Address::UNSPECIFIED,
         src_addr: Ipv6Address::UNSPECIFIED,
         dst_addr: REMOTE_IPV6,
         dst_addr: REMOTE_IPV6,
-        next_header: IpProtocol::Icmp,
+        next_header: IpProtocol::Icmpv6,
         payload_len: 24,
         payload_len: 24,
         hop_limit: 0x40
         hop_limit: 0x40
     });
     });
@@ -617,7 +617,7 @@ mod test_ipv6 {
     static REMOTE_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
     static REMOTE_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
         src_addr: REMOTE_IPV6,
         src_addr: REMOTE_IPV6,
         dst_addr: LOCAL_IPV6,
         dst_addr: LOCAL_IPV6,
-        next_header: IpProtocol::Icmp,
+        next_header: IpProtocol::Icmpv6,
         payload_len: 24,
         payload_len: 24,
         hop_limit: 0x40
         hop_limit: 0x40
     });
     });
@@ -683,7 +683,7 @@ mod test_ipv6 {
             assert_eq!(ip_repr, IpRepr::Ipv6(Ipv6Repr {
             assert_eq!(ip_repr, IpRepr::Ipv6(Ipv6Repr {
                 src_addr: Ipv6Address::UNSPECIFIED,
                 src_addr: Ipv6Address::UNSPECIFIED,
                 dst_addr: REMOTE_IPV6,
                 dst_addr: REMOTE_IPV6,
-                next_header: IpProtocol::Icmp,
+                next_header: IpProtocol::Icmpv6,
                 payload_len: ECHOV6_REPR.buffer_len(),
                 payload_len: ECHOV6_REPR.buffer_len(),
                 hop_limit: 0x2a,
                 hop_limit: 0x2a,
             }));
             }));
@@ -757,7 +757,7 @@ mod test_ipv6 {
             header: Ipv6Repr {
             header: Ipv6Repr {
                 src_addr: LOCAL_IPV6,
                 src_addr: LOCAL_IPV6,
                 dst_addr: REMOTE_IPV6,
                 dst_addr: REMOTE_IPV6,
-                next_header: IpProtocol::Icmp,
+                next_header: IpProtocol::Icmpv6,
                 payload_len: 12,
                 payload_len: 12,
                 hop_limit: 0x40
                 hop_limit: 0x40
             },
             },
@@ -766,7 +766,7 @@ mod test_ipv6 {
         let ip_repr = IpRepr::Unspecified {
         let ip_repr = IpRepr::Unspecified {
             src_addr: REMOTE_IPV6.into(),
             src_addr: REMOTE_IPV6.into(),
             dst_addr: LOCAL_IPV6.into(),
             dst_addr: LOCAL_IPV6.into(),
-            protocol: IpProtocol::Icmp,
+            protocol: IpProtocol::Icmpv6,
             payload_len: icmp_repr.buffer_len(),
             payload_len: icmp_repr.buffer_len(),
             hop_limit: 0x40
             hop_limit: 0x40
         };
         };