commit
5947c5947e
|
@ -26,23 +26,23 @@ jobs:
|
|||
- std proto-ipv4
|
||||
|
||||
# Test features chosen to be as orthogonal as possible.
|
||||
- std ethernet phy-raw_socket proto-ipv6 socket-udp
|
||||
- std ethernet phy-tap_interface proto-ipv6 socket-udp
|
||||
- std ethernet proto-ipv4 proto-igmp socket-raw
|
||||
- std ethernet proto-ipv4 socket-udp socket-tcp
|
||||
- std ethernet proto-ipv4 proto-dhcpv4 socket-udp
|
||||
- std ethernet proto-ipv6 socket-udp
|
||||
- std ethernet proto-ipv6 socket-tcp
|
||||
- std ethernet proto-ipv4 socket-icmp socket-tcp
|
||||
- std ethernet proto-ipv6 socket-icmp socket-tcp
|
||||
- std medium-ethernet phy-raw_socket proto-ipv6 socket-udp
|
||||
- std medium-ethernet phy-tuntap_interface proto-ipv6 socket-udp
|
||||
- std medium-ethernet proto-ipv4 proto-igmp socket-raw
|
||||
- std medium-ethernet proto-ipv4 socket-udp socket-tcp
|
||||
- std medium-ethernet proto-ipv4 proto-dhcpv4 socket-udp
|
||||
- std medium-ethernet proto-ipv6 socket-udp
|
||||
- std medium-ethernet proto-ipv6 socket-tcp
|
||||
- std medium-ethernet proto-ipv4 socket-icmp socket-tcp
|
||||
- std medium-ethernet proto-ipv6 socket-icmp socket-tcp
|
||||
|
||||
# Test features chosen to be as aggressive as possible.
|
||||
- std ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp async
|
||||
- std medium-ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp async
|
||||
|
||||
include:
|
||||
# Test alloc feature which requires nightly.
|
||||
- rust: nightly
|
||||
features: alloc ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp
|
||||
features: alloc medium-ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp
|
||||
- rust: nightly
|
||||
features: alloc proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp
|
||||
steps:
|
||||
|
@ -69,7 +69,7 @@ jobs:
|
|||
|
||||
features:
|
||||
# These feature sets cannot run tests, so we only check they build.
|
||||
- ethernet proto-ipv6 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp async
|
||||
- medium-ip medium-ethernet proto-ipv6 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp async
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
|
29
Cargo.toml
29
Cargo.toml
|
@ -32,12 +32,13 @@ url = "1.0"
|
|||
std = ["managed/std"]
|
||||
alloc = ["managed/alloc"]
|
||||
verbose = []
|
||||
ethernet = ["socket"]
|
||||
"phy-raw_socket" = ["std", "libc", "ethernet"]
|
||||
"phy-tap_interface" = ["std", "libc", "ethernet"]
|
||||
"medium-ethernet" = ["socket"]
|
||||
"medium-ip" = ["socket"]
|
||||
"phy-raw_socket" = ["std", "libc", "medium-ethernet"]
|
||||
"phy-tuntap_interface" = ["std", "libc", "medium-ethernet"]
|
||||
"proto-ipv4" = []
|
||||
"proto-igmp" = ["proto-ipv4"]
|
||||
"proto-dhcpv4" = ["proto-ipv4", "socket-raw", "ethernet"]
|
||||
"proto-dhcpv4" = ["proto-ipv4", "socket-raw", "medium-ethernet"]
|
||||
"proto-ipv6" = []
|
||||
"socket" = []
|
||||
"socket-raw" = ["socket"]
|
||||
|
@ -47,8 +48,8 @@ ethernet = ["socket"]
|
|||
"async" = []
|
||||
default = [
|
||||
"std", "log", # needed for `cargo test --no-default-features --features default` :/
|
||||
"ethernet",
|
||||
"phy-raw_socket", "phy-tap_interface",
|
||||
"medium-ethernet", "medium-ip",
|
||||
"phy-raw_socket", "phy-tuntap_interface",
|
||||
"proto-ipv4", "proto-igmp", "proto-dhcpv4", "proto-ipv6",
|
||||
"socket-raw", "socket-icmp", "socket-udp", "socket-tcp",
|
||||
"async"
|
||||
|
@ -68,35 +69,35 @@ required-features = ["std", "phy-raw_socket", "proto-ipv4"]
|
|||
|
||||
[[example]]
|
||||
name = "httpclient"
|
||||
required-features = ["std", "phy-tap_interface", "proto-ipv4", "proto-ipv6", "socket-tcp"]
|
||||
required-features = ["std", "medium-ethernet", "medium-ip", "phy-tuntap_interface", "proto-ipv4", "proto-ipv6", "socket-tcp"]
|
||||
|
||||
[[example]]
|
||||
name = "ping"
|
||||
required-features = ["std", "phy-tap_interface", "proto-ipv4", "proto-ipv6", "socket-icmp"]
|
||||
required-features = ["std", "medium-ethernet", "medium-ip", "phy-tuntap_interface", "proto-ipv4", "proto-ipv6", "socket-icmp"]
|
||||
|
||||
[[example]]
|
||||
name = "server"
|
||||
required-features = ["std", "phy-tap_interface", "proto-ipv4", "socket-tcp", "socket-udp"]
|
||||
required-features = ["std", "medium-ethernet", "medium-ip", "phy-tuntap_interface", "proto-ipv4", "socket-tcp", "socket-udp"]
|
||||
|
||||
[[example]]
|
||||
name = "client"
|
||||
required-features = ["std", "phy-tap_interface", "proto-ipv4", "socket-tcp", "socket-udp"]
|
||||
required-features = ["std", "medium-ethernet", "medium-ip", "phy-tuntap_interface", "proto-ipv4", "socket-tcp", "socket-udp"]
|
||||
|
||||
[[example]]
|
||||
name = "loopback"
|
||||
required-features = ["log", "proto-ipv4", "socket-tcp"]
|
||||
required-features = ["log", "medium-ethernet", "proto-ipv4", "socket-tcp"]
|
||||
|
||||
[[example]]
|
||||
name = "multicast"
|
||||
required-features = ["std", "phy-tap_interface", "proto-ipv4", "proto-igmp", "socket-udp"]
|
||||
required-features = ["std", "medium-ethernet", "medium-ip", "phy-tuntap_interface", "proto-ipv4", "proto-igmp", "socket-udp"]
|
||||
|
||||
[[example]]
|
||||
name = "benchmark"
|
||||
required-features = ["std", "phy-tap_interface", "proto-ipv4", "socket-raw", "socket-udp"]
|
||||
required-features = ["std", "medium-ethernet", "medium-ip", "phy-tuntap_interface", "proto-ipv4", "socket-raw", "socket-udp"]
|
||||
|
||||
[[example]]
|
||||
name = "dhcp_client"
|
||||
required-features = ["std", "phy-tap_interface", "proto-ipv4", "proto-dhcpv4", "socket-raw"]
|
||||
required-features = ["std", "medium-ethernet", "medium-ip", "phy-tuntap_interface", "proto-ipv4", "proto-dhcpv4", "socket-raw"]
|
||||
|
||||
[profile.release]
|
||||
debug = 2
|
||||
|
|
24
README.md
24
README.md
|
@ -170,9 +170,9 @@ or `BufWriter` is used, which are of course not available on heap-less systems.
|
|||
|
||||
This feature is disabled by default.
|
||||
|
||||
### Features `phy-raw_socket` and `phy-tap_interface`
|
||||
### Features `phy-raw_socket` and `phy-tuntap_interface`
|
||||
|
||||
Enable `smoltcp::phy::RawSocket` and `smoltcp::phy::TapInterface`, respectively.
|
||||
Enable `smoltcp::phy::RawSocket` and `smoltcp::phy::TunTapInterface`, respectively.
|
||||
|
||||
These features are enabled by default.
|
||||
|
||||
|
@ -270,19 +270,19 @@ The host is assigned the hardware address `02-00-00-00-00-02`, IPv4 address `192
|
|||
Read its [source code](/examples/httpclient.rs), then run it as:
|
||||
|
||||
```sh
|
||||
cargo run --example httpclient -- tap0 ADDRESS URL
|
||||
cargo run --example httpclient -- --tap tap0 ADDRESS URL
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
```sh
|
||||
cargo run --example httpclient -- tap0 93.184.216.34 http://example.org/
|
||||
cargo run --example httpclient -- --tap 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/
|
||||
cargo run --example httpclient -- --tap 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.
|
||||
|
@ -297,7 +297,7 @@ The host is assigned the hardware address `02-00-00-00-00-02` and IPv4 address `
|
|||
Read its [source code](/examples/ping.rs), then run it as:
|
||||
|
||||
```sh
|
||||
cargo run --example ping -- tap0 ADDRESS
|
||||
cargo run --example ping -- --tap tap0 ADDRESS
|
||||
```
|
||||
|
||||
It sends a series of 4 ICMP ECHO\_REQUEST packets to the given address at one second intervals and
|
||||
|
@ -319,7 +319,7 @@ The host is assigned the hardware address `02-00-00-00-00-01` and IPv4 address `
|
|||
Read its [source code](/examples/server.rs), then run it as:
|
||||
|
||||
```sh
|
||||
cargo run --example server -- tap0
|
||||
cargo run --example server -- --tap tap0
|
||||
```
|
||||
|
||||
It responds to:
|
||||
|
@ -349,7 +349,7 @@ The host is assigned the hardware address `02-00-00-00-00-02` and IPv4 address `
|
|||
Read its [source code](/examples/client.rs), then run it as:
|
||||
|
||||
```sh
|
||||
cargo run --example client -- tap0 ADDRESS PORT
|
||||
cargo run --example client -- --tap tap0 ADDRESS PORT
|
||||
```
|
||||
|
||||
It connects to the given address (not a hostname) and port (e.g. `socat stdio tcp4-listen:1234`),
|
||||
|
@ -362,7 +362,7 @@ _examples/benchmark.rs_ implements a simple throughput benchmark.
|
|||
Read its [source code](/examples/benchmark.rs), then run it as:
|
||||
|
||||
```sh
|
||||
cargo run --release --example benchmark -- tap0 [reader|writer]
|
||||
cargo run --release --example benchmark -- --tap tap0 [reader|writer]
|
||||
```
|
||||
|
||||
It establishes a connection to itself from a different thread and reads or writes a large amount
|
||||
|
@ -372,9 +372,9 @@ A typical result (achieved on a Intel Core i7-7500U CPU and a Linux 4.9.65 x86_6
|
|||
on a Dell XPS 13 9360 laptop) is as follows:
|
||||
|
||||
```
|
||||
$ cargo run -q --release --example benchmark tap0 reader
|
||||
$ cargo run -q --release --example benchmark -- --tap tap0 reader
|
||||
throughput: 2.556 Gbps
|
||||
$ cargo run -q --release --example benchmark tap0 writer
|
||||
$ cargo run -q --release --example benchmark -- --tap tap0 writer
|
||||
throughput: 5.301 Gbps
|
||||
```
|
||||
|
||||
|
@ -391,7 +391,7 @@ Although it does not require `std`, this example still requires the `alloc` feat
|
|||
Read its [source code](/examples/loopback.rs), then run it without `std`:
|
||||
|
||||
```sh
|
||||
cargo run --example loopback --no-default-features --features="log proto-ipv4 socket-tcp alloc"
|
||||
cargo run --example loopback --no-default-features --features="log proto-ipv4 socket-tcp alloc"
|
||||
```
|
||||
|
||||
... or with `std` (in this case the features don't have to be explicitly listed):
|
||||
|
|
|
@ -11,9 +11,9 @@ use std::net::TcpStream;
|
|||
use std::os::unix::io::AsRawFd;
|
||||
use log::debug;
|
||||
|
||||
use smoltcp::phy::wait as phy_wait;
|
||||
use smoltcp::phy::{Device, Medium, wait as phy_wait};
|
||||
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
|
||||
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder};
|
||||
use smoltcp::iface::{NeighborCache, InterfaceBuilder};
|
||||
use smoltcp::socket::SocketSet;
|
||||
use smoltcp::socket::{TcpSocket, TcpSocketBuffer};
|
||||
use smoltcp::time::{Duration, Instant};
|
||||
|
@ -62,12 +62,12 @@ fn main() {
|
|||
utils::setup_logging("info");
|
||||
|
||||
let (mut opts, mut free) = utils::create_options();
|
||||
utils::add_tap_options(&mut opts, &mut free);
|
||||
utils::add_tuntap_options(&mut opts, &mut free);
|
||||
utils::add_middleware_options(&mut opts, &mut free);
|
||||
free.push("MODE");
|
||||
|
||||
let mut matches = utils::parse_options(&opts, free);
|
||||
let device = utils::parse_tap_options(&mut matches);
|
||||
let device = utils::parse_tuntap_options(&mut matches);
|
||||
let fd = device.as_raw_fd();
|
||||
let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false);
|
||||
let mode = match matches.free[0].as_ref() {
|
||||
|
@ -90,11 +90,15 @@ fn main() {
|
|||
|
||||
let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
|
||||
let ip_addrs = [IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24)];
|
||||
let mut iface = EthernetInterfaceBuilder::new(device)
|
||||
let medium = device.capabilities().medium;
|
||||
let mut builder = InterfaceBuilder::new(device)
|
||||
.ip_addrs(ip_addrs);
|
||||
if medium == Medium::Ethernet {
|
||||
builder = builder
|
||||
.ethernet_addr(ethernet_addr)
|
||||
.neighbor_cache(neighbor_cache)
|
||||
.ip_addrs(ip_addrs)
|
||||
.finalize();
|
||||
.neighbor_cache(neighbor_cache);
|
||||
}
|
||||
let mut iface = builder.finalize();
|
||||
|
||||
let mut sockets = SocketSet::new(vec![]);
|
||||
let tcp1_handle = sockets.add(tcp1_socket);
|
||||
|
|
|
@ -5,9 +5,9 @@ use std::collections::BTreeMap;
|
|||
use std::os::unix::io::AsRawFd;
|
||||
use log::debug;
|
||||
|
||||
use smoltcp::phy::wait as phy_wait;
|
||||
use smoltcp::phy::{Device, Medium, wait as phy_wait};
|
||||
use smoltcp::wire::{EthernetAddress, Ipv4Address, IpAddress, IpCidr};
|
||||
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder, Routes};
|
||||
use smoltcp::iface::{NeighborCache, InterfaceBuilder, Routes};
|
||||
use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
|
||||
use smoltcp::time::Instant;
|
||||
|
||||
|
@ -15,13 +15,14 @@ fn main() {
|
|||
utils::setup_logging("");
|
||||
|
||||
let (mut opts, mut free) = utils::create_options();
|
||||
utils::add_tap_options(&mut opts, &mut free);
|
||||
utils::add_tuntap_options(&mut opts, &mut free);
|
||||
utils::add_middleware_options(&mut opts, &mut free);
|
||||
free.push("ADDRESS");
|
||||
free.push("PORT");
|
||||
|
||||
let mut matches = utils::parse_options(&opts, free);
|
||||
let device = utils::parse_tap_options(&mut matches);
|
||||
let device = utils::parse_tuntap_options(&mut matches);
|
||||
|
||||
let fd = device.as_raw_fd();
|
||||
let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false);
|
||||
let address = IpAddress::from_str(&matches.free[0]).expect("invalid address format");
|
||||
|
@ -39,12 +40,17 @@ fn main() {
|
|||
let mut routes_storage = [None; 1];
|
||||
let mut routes = Routes::new(&mut routes_storage[..]);
|
||||
routes.add_default_ipv4_route(default_v4_gw).unwrap();
|
||||
let mut iface = EthernetInterfaceBuilder::new(device)
|
||||
.ethernet_addr(ethernet_addr)
|
||||
.neighbor_cache(neighbor_cache)
|
||||
|
||||
let medium = device.capabilities().medium;
|
||||
let mut builder = InterfaceBuilder::new(device)
|
||||
.ip_addrs(ip_addrs)
|
||||
.routes(routes)
|
||||
.finalize();
|
||||
.routes(routes);
|
||||
if medium == Medium::Ethernet {
|
||||
builder = builder
|
||||
.ethernet_addr(ethernet_addr)
|
||||
.neighbor_cache(neighbor_cache);
|
||||
}
|
||||
let mut iface = builder.finalize();
|
||||
|
||||
let mut sockets = SocketSet::new(vec![]);
|
||||
let tcp_handle = sockets.add(tcp_socket);
|
||||
|
|
|
@ -3,9 +3,9 @@ mod utils;
|
|||
|
||||
use std::collections::BTreeMap;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use smoltcp::phy::wait as phy_wait;
|
||||
use smoltcp::phy::{Device, Medium, wait as phy_wait};
|
||||
use smoltcp::wire::{EthernetAddress, Ipv4Address, IpCidr, Ipv4Cidr};
|
||||
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder, Routes};
|
||||
use smoltcp::iface::{NeighborCache, InterfaceBuilder, Routes};
|
||||
use smoltcp::socket::{SocketSet, RawSocketBuffer, RawPacketMetadata};
|
||||
use smoltcp::time::Instant;
|
||||
use smoltcp::dhcp::Dhcpv4Client;
|
||||
|
@ -15,11 +15,11 @@ fn main() {
|
|||
utils::setup_logging("");
|
||||
|
||||
let (mut opts, mut free) = utils::create_options();
|
||||
utils::add_tap_options(&mut opts, &mut free);
|
||||
utils::add_tuntap_options(&mut opts, &mut free);
|
||||
utils::add_middleware_options(&mut opts, &mut free);
|
||||
|
||||
let mut matches = utils::parse_options(&opts, free);
|
||||
let device = utils::parse_tap_options(&mut matches);
|
||||
let device = utils::parse_tuntap_options(&mut matches);
|
||||
let fd = device.as_raw_fd();
|
||||
let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false);
|
||||
|
||||
|
@ -28,12 +28,17 @@ fn main() {
|
|||
let ip_addrs = [IpCidr::new(Ipv4Address::UNSPECIFIED.into(), 0)];
|
||||
let mut routes_storage = [None; 1];
|
||||
let routes = Routes::new(&mut routes_storage[..]);
|
||||
let mut iface = EthernetInterfaceBuilder::new(device)
|
||||
.ethernet_addr(ethernet_addr)
|
||||
.neighbor_cache(neighbor_cache)
|
||||
|
||||
let medium = device.capabilities().medium;
|
||||
let mut builder = InterfaceBuilder::new(device)
|
||||
.ip_addrs(ip_addrs)
|
||||
.routes(routes)
|
||||
.finalize();
|
||||
.routes(routes);
|
||||
if medium == Medium::Ethernet {
|
||||
builder = builder
|
||||
.ethernet_addr(ethernet_addr)
|
||||
.neighbor_cache(neighbor_cache);
|
||||
}
|
||||
let mut iface = builder.finalize();
|
||||
|
||||
let mut sockets = SocketSet::new(vec![]);
|
||||
let dhcp_rx_buffer = RawSocketBuffer::new(
|
||||
|
|
|
@ -6,9 +6,9 @@ use std::os::unix::io::AsRawFd;
|
|||
use url::Url;
|
||||
use log::debug;
|
||||
|
||||
use smoltcp::phy::wait as phy_wait;
|
||||
use smoltcp::phy::{Device, Medium, wait as phy_wait};
|
||||
use smoltcp::wire::{EthernetAddress, Ipv4Address, Ipv6Address, IpAddress, IpCidr};
|
||||
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder, Routes};
|
||||
use smoltcp::iface::{NeighborCache, InterfaceBuilder, Routes};
|
||||
use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
|
||||
use smoltcp::time::Instant;
|
||||
|
||||
|
@ -16,13 +16,13 @@ fn main() {
|
|||
utils::setup_logging("");
|
||||
|
||||
let (mut opts, mut free) = utils::create_options();
|
||||
utils::add_tap_options(&mut opts, &mut free);
|
||||
utils::add_tuntap_options(&mut opts, &mut free);
|
||||
utils::add_middleware_options(&mut opts, &mut free);
|
||||
free.push("ADDRESS");
|
||||
free.push("URL");
|
||||
|
||||
let mut matches = utils::parse_options(&opts, free);
|
||||
let device = utils::parse_tap_options(&mut matches);
|
||||
let device = utils::parse_tuntap_options(&mut matches);
|
||||
let fd = device.as_raw_fd();
|
||||
let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false);
|
||||
let address = IpAddress::from_str(&matches.free[0]).expect("invalid address format");
|
||||
|
@ -45,12 +45,17 @@ fn main() {
|
|||
let mut routes = Routes::new(&mut routes_storage[..]);
|
||||
routes.add_default_ipv4_route(default_v4_gw).unwrap();
|
||||
routes.add_default_ipv6_route(default_v6_gw).unwrap();
|
||||
let mut iface = EthernetInterfaceBuilder::new(device)
|
||||
.ethernet_addr(ethernet_addr)
|
||||
.neighbor_cache(neighbor_cache)
|
||||
|
||||
let medium = device.capabilities().medium;
|
||||
let mut builder = InterfaceBuilder::new(device)
|
||||
.ip_addrs(ip_addrs)
|
||||
.routes(routes)
|
||||
.finalize();
|
||||
.routes(routes);
|
||||
if medium == Medium::Ethernet {
|
||||
builder = builder
|
||||
.ethernet_addr(ethernet_addr)
|
||||
.neighbor_cache(neighbor_cache);
|
||||
}
|
||||
let mut iface = builder.finalize();
|
||||
|
||||
let mut sockets = SocketSet::new(vec![]);
|
||||
let tcp_handle = sockets.add(tcp_socket);
|
||||
|
|
|
@ -9,9 +9,9 @@ mod utils;
|
|||
use core::str;
|
||||
use log::{info, debug, error};
|
||||
|
||||
use smoltcp::phy::Loopback;
|
||||
use smoltcp::phy::{Loopback, Medium};
|
||||
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
|
||||
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder};
|
||||
use smoltcp::iface::{NeighborCache, InterfaceBuilder};
|
||||
use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
|
||||
use smoltcp::time::{Duration, Instant};
|
||||
|
||||
|
@ -65,7 +65,7 @@ mod mock {
|
|||
|
||||
fn main() {
|
||||
let clock = mock::Clock::new();
|
||||
let device = Loopback::new();
|
||||
let device = Loopback::new(Medium::Ethernet);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
let device = {
|
||||
|
@ -83,7 +83,7 @@ fn main() {
|
|||
let mut neighbor_cache = NeighborCache::new(&mut neighbor_cache_entries[..]);
|
||||
|
||||
let mut ip_addrs = [IpCidr::new(IpAddress::v4(127, 0, 0, 1), 8)];
|
||||
let mut iface = EthernetInterfaceBuilder::new(device)
|
||||
let mut iface = InterfaceBuilder::new(device)
|
||||
.ethernet_addr(EthernetAddress::default())
|
||||
.neighbor_cache(neighbor_cache)
|
||||
.ip_addrs(ip_addrs)
|
||||
|
|
|
@ -7,7 +7,7 @@ use log::debug;
|
|||
use smoltcp::phy::wait as phy_wait;
|
||||
use smoltcp::wire::{EthernetAddress, IpVersion, IpProtocol, IpAddress, IpCidr, Ipv4Address,
|
||||
Ipv4Packet, IgmpPacket, IgmpRepr};
|
||||
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder};
|
||||
use smoltcp::iface::{NeighborCache, InterfaceBuilder};
|
||||
use smoltcp::socket::{SocketSet,
|
||||
RawSocket, RawSocketBuffer, RawPacketMetadata,
|
||||
UdpSocket, UdpSocketBuffer, UdpPacketMetadata};
|
||||
|
@ -20,11 +20,11 @@ fn main() {
|
|||
utils::setup_logging("warn");
|
||||
|
||||
let (mut opts, mut free) = utils::create_options();
|
||||
utils::add_tap_options(&mut opts, &mut free);
|
||||
utils::add_tuntap_options(&mut opts, &mut free);
|
||||
utils::add_middleware_options(&mut opts, &mut free);
|
||||
|
||||
let mut matches = utils::parse_options(&opts, free);
|
||||
let device = utils::parse_tap_options(&mut matches);
|
||||
let device = utils::parse_tuntap_options(&mut matches);
|
||||
let fd = device.as_raw_fd();
|
||||
let device = utils::parse_middleware_options(&mut matches,
|
||||
device,
|
||||
|
@ -37,7 +37,7 @@ fn main() {
|
|||
let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x02]);
|
||||
let ip_addr = IpCidr::new(IpAddress::from(local_addr), 24);
|
||||
let mut ipv4_multicast_storage = [None; 1];
|
||||
let mut iface = EthernetInterfaceBuilder::new(device)
|
||||
let mut iface = InterfaceBuilder::new(device)
|
||||
.ethernet_addr(ethernet_addr)
|
||||
.neighbor_cache(neighbor_cache)
|
||||
.ip_addrs([ip_addr])
|
||||
|
|
|
@ -8,13 +8,13 @@ use std::collections::HashMap;
|
|||
use log::debug;
|
||||
use byteorder::{ByteOrder, NetworkEndian};
|
||||
|
||||
use smoltcp::time::{Duration, Instant};
|
||||
use smoltcp::{phy::Medium, time::{Duration, Instant}};
|
||||
use smoltcp::phy::Device;
|
||||
use smoltcp::phy::wait as phy_wait;
|
||||
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr,
|
||||
Ipv6Address, Icmpv6Repr, Icmpv6Packet,
|
||||
Ipv4Address, Icmpv4Repr, Icmpv4Packet};
|
||||
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder, Routes};
|
||||
use smoltcp::iface::{NeighborCache, InterfaceBuilder, Routes};
|
||||
use smoltcp::socket::{SocketSet, IcmpSocket, IcmpSocketBuffer, IcmpPacketMetadata, IcmpEndpoint};
|
||||
|
||||
macro_rules! send_icmp_ping {
|
||||
|
@ -55,7 +55,7 @@ fn main() {
|
|||
utils::setup_logging("warn");
|
||||
|
||||
let (mut opts, mut free) = utils::create_options();
|
||||
utils::add_tap_options(&mut opts, &mut free);
|
||||
utils::add_tuntap_options(&mut opts, &mut free);
|
||||
utils::add_middleware_options(&mut opts, &mut free);
|
||||
opts.optopt("c", "count", "Amount of echo request packets to send (default: 4)", "COUNT");
|
||||
opts.optopt("i", "interval",
|
||||
|
@ -66,7 +66,7 @@ fn main() {
|
|||
free.push("ADDRESS");
|
||||
|
||||
let mut matches = utils::parse_options(&opts, free);
|
||||
let device = utils::parse_tap_options(&mut matches);
|
||||
let device = utils::parse_tuntap_options(&mut matches);
|
||||
let fd = device.as_raw_fd();
|
||||
let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false);
|
||||
let device_caps = device.capabilities();
|
||||
|
@ -98,12 +98,17 @@ fn main() {
|
|||
let mut routes = Routes::new(&mut routes_storage[..]);
|
||||
routes.add_default_ipv4_route(default_v4_gw).unwrap();
|
||||
routes.add_default_ipv6_route(default_v6_gw).unwrap();
|
||||
let mut iface = EthernetInterfaceBuilder::new(device)
|
||||
.ethernet_addr(ethernet_addr)
|
||||
|
||||
let medium = device.capabilities().medium;
|
||||
let mut builder = InterfaceBuilder::new(device)
|
||||
.ip_addrs(ip_addrs)
|
||||
.routes(routes)
|
||||
.neighbor_cache(neighbor_cache)
|
||||
.finalize();
|
||||
.routes(routes);
|
||||
if medium == Medium::Ethernet {
|
||||
builder = builder
|
||||
.ethernet_addr(ethernet_addr)
|
||||
.neighbor_cache(neighbor_cache);
|
||||
}
|
||||
let mut iface = builder.finalize();
|
||||
|
||||
let mut sockets = SocketSet::new(vec![]);
|
||||
let icmp_handle = sockets.add(icmp_socket);
|
||||
|
|
|
@ -6,9 +6,9 @@ use std::fmt::Write;
|
|||
use std::os::unix::io::AsRawFd;
|
||||
use log::debug;
|
||||
|
||||
use smoltcp::phy::wait as phy_wait;
|
||||
use smoltcp::phy::{Device, Medium, wait as phy_wait};
|
||||
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
|
||||
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder};
|
||||
use smoltcp::iface::{NeighborCache, InterfaceBuilder};
|
||||
use smoltcp::socket::SocketSet;
|
||||
use smoltcp::socket::{UdpSocket, UdpSocketBuffer, UdpPacketMetadata};
|
||||
use smoltcp::socket::{TcpSocket, TcpSocketBuffer};
|
||||
|
@ -18,11 +18,11 @@ fn main() {
|
|||
utils::setup_logging("");
|
||||
|
||||
let (mut opts, mut free) = utils::create_options();
|
||||
utils::add_tap_options(&mut opts, &mut free);
|
||||
utils::add_tuntap_options(&mut opts, &mut free);
|
||||
utils::add_middleware_options(&mut opts, &mut free);
|
||||
|
||||
let mut matches = utils::parse_options(&opts, free);
|
||||
let device = utils::parse_tap_options(&mut matches);
|
||||
let device = utils::parse_tuntap_options(&mut matches);
|
||||
let fd = device.as_raw_fd();
|
||||
let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false);
|
||||
|
||||
|
@ -54,11 +54,16 @@ fn main() {
|
|||
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 mut iface = EthernetInterfaceBuilder::new(device)
|
||||
|
||||
let medium = device.capabilities().medium;
|
||||
let mut builder = InterfaceBuilder::new(device)
|
||||
.ip_addrs(ip_addrs);
|
||||
if medium == Medium::Ethernet {
|
||||
builder = builder
|
||||
.ethernet_addr(ethernet_addr)
|
||||
.neighbor_cache(neighbor_cache)
|
||||
.ip_addrs(ip_addrs)
|
||||
.finalize();
|
||||
.neighbor_cache(neighbor_cache);
|
||||
}
|
||||
let mut iface = builder.finalize();
|
||||
|
||||
let mut sockets = SocketSet::new(vec![]);
|
||||
let udp_handle = sockets.add(udp_socket);
|
||||
|
|
|
@ -14,10 +14,10 @@ use log::{Level, LevelFilter, trace};
|
|||
use env_logger::Builder;
|
||||
use getopts::{Options, Matches};
|
||||
|
||||
use smoltcp::phy::{Device, EthernetTracer, FaultInjector};
|
||||
#[cfg(feature = "phy-tap_interface")]
|
||||
use smoltcp::phy::TapInterface;
|
||||
use smoltcp::phy::{PcapWriter, PcapSink, PcapMode, PcapLinkType};
|
||||
use smoltcp::phy::{Device, Tracer, FaultInjector, Medium};
|
||||
#[cfg(feature = "phy-tuntap_interface")]
|
||||
use smoltcp::phy::TunTapInterface;
|
||||
use smoltcp::phy::{PcapWriter, PcapSink, PcapMode};
|
||||
use smoltcp::phy::RawSocket;
|
||||
use smoltcp::time::{Duration, Instant};
|
||||
|
||||
|
@ -77,14 +77,20 @@ pub fn parse_options(options: &Options, free: Vec<&str>) -> Matches {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn add_tap_options(_opts: &mut Options, free: &mut Vec<&str>) {
|
||||
free.push("INTERFACE");
|
||||
pub fn add_tuntap_options(opts: &mut Options, _free: &mut Vec<&str>) {
|
||||
opts.optopt("", "tun", "TUN interface to use", "tun0");
|
||||
opts.optopt("", "tap", "TAP interface to use", "tap0");
|
||||
}
|
||||
|
||||
#[cfg(feature = "phy-tap_interface")]
|
||||
pub fn parse_tap_options(matches: &mut Matches) -> TapInterface {
|
||||
let interface = matches.free.remove(0);
|
||||
TapInterface::new(&interface).unwrap()
|
||||
#[cfg(feature = "phy-tuntap_interface")]
|
||||
pub fn parse_tuntap_options(matches: &mut Matches) -> TunTapInterface {
|
||||
let tun = matches.opt_str("tun");
|
||||
let tap = matches.opt_str("tap");
|
||||
match(tun,tap) {
|
||||
(Some(tun), None) => TunTapInterface::new(&tun, Medium::Ip).unwrap(),
|
||||
(None, Some(tap)) => TunTapInterface::new(&tap, Medium::Ethernet).unwrap(),
|
||||
_ => panic!("You must specify exactly one of --tun or --tap"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_raw_socket_options(matches: &mut Matches) -> RawSocket {
|
||||
|
@ -105,7 +111,7 @@ pub fn add_middleware_options(opts: &mut Options, _free: &mut Vec<&str>) {
|
|||
}
|
||||
|
||||
pub fn parse_middleware_options<D>(matches: &mut Matches, device: D, loopback: bool)
|
||||
-> FaultInjector<EthernetTracer<PcapWriter<D, Rc<dyn PcapSink>>>>
|
||||
-> FaultInjector<Tracer<PcapWriter<D, Rc<dyn PcapSink>>>>
|
||||
where D: for<'a> Device<'a>
|
||||
{
|
||||
let drop_chance = matches.opt_str("drop-chance").map(|s| u8::from_str(&s).unwrap())
|
||||
|
@ -130,13 +136,17 @@ pub fn parse_middleware_options<D>(matches: &mut Matches, device: D, loopback: b
|
|||
|
||||
let seed = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().subsec_nanos();
|
||||
|
||||
let device = PcapWriter::new(device, Rc::new(RefCell::new(pcap_writer)) as Rc<dyn PcapSink>,
|
||||
if loopback { PcapMode::TxOnly } else { PcapMode::Both },
|
||||
PcapLinkType::Ethernet);
|
||||
let device = EthernetTracer::new(device, |_timestamp, _printer| {
|
||||
let device = PcapWriter::new(
|
||||
device,
|
||||
Rc::new(RefCell::new(pcap_writer)) as Rc<dyn PcapSink>,
|
||||
if loopback { PcapMode::TxOnly } else { PcapMode::Both },
|
||||
);
|
||||
|
||||
let device = Tracer::new(device, |_timestamp, _printer| {
|
||||
#[cfg(feature = "log")]
|
||||
trace!("{}", _printer);
|
||||
});
|
||||
|
||||
let mut device = FaultInjector::new(device, seed);
|
||||
device.set_drop_chance(drop_chance);
|
||||
device.set_corrupt_chance(corrupt_chance);
|
||||
|
|
|
@ -6,10 +6,10 @@ use std as core;
|
|||
extern crate getopts;
|
||||
|
||||
use core::cmp;
|
||||
use smoltcp::phy::Loopback;
|
||||
use smoltcp::phy::{Loopback, Medium};
|
||||
use smoltcp::wire::{EthernetAddress, EthernetFrame, EthernetProtocol};
|
||||
use smoltcp::wire::{IpAddress, IpCidr, Ipv4Packet, Ipv6Packet, TcpPacket};
|
||||
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder};
|
||||
use smoltcp::iface::{NeighborCache, InterfaceBuilder};
|
||||
use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
|
||||
use smoltcp::time::{Duration, Instant};
|
||||
|
||||
|
@ -118,7 +118,7 @@ fuzz_target!(|data: &[u8]| {
|
|||
utils::add_middleware_options(&mut opts, &mut free);
|
||||
|
||||
let mut matches = utils::parse_options(&opts, free);
|
||||
let device = utils::parse_middleware_options(&mut matches, Loopback::new(),
|
||||
let device = utils::parse_middleware_options(&mut matches, Loopback::new(Medium::Ethernet),
|
||||
/*loopback=*/true);
|
||||
|
||||
smoltcp::phy::FuzzInjector::new(device,
|
||||
|
@ -130,7 +130,7 @@ fuzz_target!(|data: &[u8]| {
|
|||
let neighbor_cache = NeighborCache::new(&mut neighbor_cache_entries[..]);
|
||||
|
||||
let ip_addrs = [IpCidr::new(IpAddress::v4(127, 0, 0, 1), 8)];
|
||||
let mut iface = EthernetInterfaceBuilder::new(device)
|
||||
let mut iface = InterfaceBuilder::new(device)
|
||||
.ethernet_addr(EthernetAddress::default())
|
||||
.neighbor_cache(neighbor_cache)
|
||||
.ip_addrs(ip_addrs)
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::wire::{IpVersion, IpProtocol, IpEndpoint, IpAddress,
|
|||
use crate::wire::dhcpv4::field as dhcpv4_field;
|
||||
use crate::socket::{SocketSet, SocketHandle, RawSocket, RawSocketBuffer};
|
||||
use crate::phy::{Device, ChecksumCapabilities};
|
||||
use crate::iface::EthernetInterface as Interface;
|
||||
use crate::iface::Interface;
|
||||
use crate::time::{Instant, Duration};
|
||||
use super::{UDP_SERVER_PORT, UDP_CLIENT_PORT};
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,19 +4,19 @@ The `iface` module deals with the *network interfaces*. It filters incoming fram
|
|||
provides lookup and caching of hardware addresses, and handles management packets.
|
||||
*/
|
||||
|
||||
#[cfg(feature = "ethernet")]
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
mod neighbor;
|
||||
mod route;
|
||||
#[cfg(feature = "ethernet")]
|
||||
mod ethernet;
|
||||
#[cfg(any(feature = "medium-ethernet", feature = "medium-ip"))]
|
||||
mod interface;
|
||||
|
||||
#[cfg(feature = "ethernet")]
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
pub use self::neighbor::Neighbor as Neighbor;
|
||||
#[cfg(feature = "ethernet")]
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
pub(crate) use self::neighbor::Answer as NeighborAnswer;
|
||||
#[cfg(feature = "ethernet")]
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
pub use self::neighbor::Cache as NeighborCache;
|
||||
pub use self::route::{Route, Routes};
|
||||
#[cfg(feature = "ethernet")]
|
||||
pub use self::ethernet::{Interface as EthernetInterface,
|
||||
InterfaceBuilder as EthernetInterfaceBuilder};
|
||||
|
||||
#[cfg(any(feature = "medium-ethernet", feature = "medium-ip"))]
|
||||
pub use self::interface::{Interface, InterfaceBuilder};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#![cfg_attr(not(any(test, feature = "std")), no_std)]
|
||||
#![deny(unsafe_code)]
|
||||
#![cfg_attr(all(any(feature = "proto-ipv4", feature = "proto-ipv6"), feature = "ethernet"), deny(unused))]
|
||||
#![cfg_attr(all(any(feature = "proto-ipv4", feature = "proto-ipv6"), feature = "medium-ethernet"), deny(unused))]
|
||||
|
||||
//! The _smoltcp_ library is built in a layered structure, with the layers corresponding
|
||||
//! to the levels of API abstraction. Only the highest layers would be used by a typical
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use core::str::FromStr;
|
||||
use core::result;
|
||||
|
||||
#[cfg(feature = "ethernet")]
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
use crate::wire::EthernetAddress;
|
||||
use crate::wire::{IpAddress, IpCidr, IpEndpoint};
|
||||
#[cfg(feature = "proto-ipv4")]
|
||||
|
@ -118,7 +118,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ethernet")]
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
fn accept_mac_joined_with(&mut self, separator: u8) -> Result<EthernetAddress> {
|
||||
let mut octets = [0u8; 6];
|
||||
for (n, octet) in octets.iter_mut().enumerate() {
|
||||
|
@ -130,7 +130,7 @@ impl<'a> Parser<'a> {
|
|||
Ok(EthernetAddress(octets))
|
||||
}
|
||||
|
||||
#[cfg(feature = "ethernet")]
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
fn accept_mac(&mut self) -> Result<EthernetAddress> {
|
||||
if let Some(mac) = self.try_do(|p| p.accept_mac_joined_with(b'-')) {
|
||||
return Ok(mac)
|
||||
|
@ -352,7 +352,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ethernet")]
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
impl FromStr for EthernetAddress {
|
||||
type Err = ();
|
||||
|
||||
|
@ -473,7 +473,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(feature = "proto-ipv4", feature = "ethernet"))]
|
||||
#[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))]
|
||||
fn test_mac() {
|
||||
assert_eq!(EthernetAddress::from_str(""), Err(()));
|
||||
assert_eq!(EthernetAddress::from_str("02:00:00:00:00:00"),
|
||||
|
|
|
@ -10,13 +10,14 @@ use alloc::collections::VecDeque;
|
|||
use alloc::VecDeque;
|
||||
|
||||
use crate::Result;
|
||||
use crate::phy::{self, Device, DeviceCapabilities};
|
||||
use crate::phy::{self, Device, DeviceCapabilities, Medium};
|
||||
use crate::time::Instant;
|
||||
|
||||
/// A loopback device.
|
||||
#[derive(Debug)]
|
||||
pub struct Loopback {
|
||||
queue: VecDeque<Vec<u8>>,
|
||||
medium: Medium,
|
||||
}
|
||||
|
||||
#[allow(clippy::new_without_default)]
|
||||
|
@ -25,9 +26,10 @@ impl Loopback {
|
|||
///
|
||||
/// Every packet transmitted through this device will be received through it
|
||||
/// in FIFO order.
|
||||
pub fn new() -> Loopback {
|
||||
pub fn new(medium: Medium) -> Loopback {
|
||||
Loopback {
|
||||
queue: VecDeque::new(),
|
||||
medium,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +41,7 @@ impl<'a> Device<'a> for Loopback {
|
|||
fn capabilities(&self) -> DeviceCapabilities {
|
||||
DeviceCapabilities {
|
||||
max_transmission_unit: 65535,
|
||||
medium: self.medium,
|
||||
..DeviceCapabilities::default()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,10 @@ and implementations of it:
|
|||
* _middleware_ [Tracer](struct.Tracer.html) and
|
||||
[FaultInjector](struct.FaultInjector.html), to facilitate debugging;
|
||||
* _adapters_ [RawSocket](struct.RawSocket.html) and
|
||||
[TapInterface](struct.TapInterface.html), to transmit and receive frames
|
||||
[TunTapInterface](struct.TunTapInterface.html), to transmit and receive frames
|
||||
on the host OS.
|
||||
|
||||
*/
|
||||
#![cfg_attr(feature = "medium-ethernet", doc = r##"
|
||||
# Examples
|
||||
|
||||
An implementation of the [Device](trait.Device.html) trait for a simple hardware
|
||||
|
@ -18,7 +19,7 @@ Ethernet controller could look as follows:
|
|||
|
||||
```rust
|
||||
use smoltcp::Result;
|
||||
use smoltcp::phy::{self, DeviceCapabilities, Device};
|
||||
use smoltcp::phy::{self, DeviceCapabilities, Device, Medium};
|
||||
use smoltcp::time::Instant;
|
||||
|
||||
struct StmPhy {
|
||||
|
@ -52,6 +53,7 @@ impl<'a> phy::Device<'a> for StmPhy {
|
|||
let mut caps = DeviceCapabilities::default();
|
||||
caps.max_transmission_unit = 1536;
|
||||
caps.max_burst_size = Some(1);
|
||||
caps.medium = Medium::Ethernet;
|
||||
caps
|
||||
}
|
||||
}
|
||||
|
@ -82,12 +84,12 @@ impl<'a> phy::TxToken for StmPhyTxToken<'a> {
|
|||
}
|
||||
}
|
||||
```
|
||||
*/
|
||||
"##)]
|
||||
|
||||
use crate::Result;
|
||||
use crate::time::Instant;
|
||||
|
||||
#[cfg(all(any(feature = "phy-raw_socket", feature = "phy-tap_interface"), unix))]
|
||||
#[cfg(all(any(feature = "phy-raw_socket", feature = "phy-tuntap_interface"), unix))]
|
||||
mod sys;
|
||||
|
||||
mod tracer;
|
||||
|
@ -98,10 +100,10 @@ mod pcap_writer;
|
|||
mod loopback;
|
||||
#[cfg(all(feature = "phy-raw_socket", unix))]
|
||||
mod raw_socket;
|
||||
#[cfg(all(feature = "phy-tap_interface", any(target_os = "linux", target_os = "android")))]
|
||||
mod tap_interface;
|
||||
#[cfg(all(feature = "phy-tuntap_interface", any(target_os = "linux", target_os = "android")))]
|
||||
mod tuntap_interface;
|
||||
|
||||
#[cfg(all(any(feature = "phy-raw_socket", feature = "phy-tap_interface"), unix))]
|
||||
#[cfg(all(any(feature = "phy-raw_socket", feature = "phy-tuntap_interface"), unix))]
|
||||
pub use self::sys::wait;
|
||||
|
||||
pub use self::tracer::Tracer;
|
||||
|
@ -112,12 +114,8 @@ pub use self::pcap_writer::{PcapLinkType, PcapMode, PcapSink, PcapWriter};
|
|||
pub use self::loopback::Loopback;
|
||||
#[cfg(all(feature = "phy-raw_socket", unix))]
|
||||
pub use self::raw_socket::RawSocket;
|
||||
#[cfg(all(feature = "phy-tap_interface", any(target_os = "linux", target_os = "android")))]
|
||||
pub use self::tap_interface::TapInterface;
|
||||
|
||||
#[cfg(feature = "ethernet")]
|
||||
/// A tracer device for Ethernet frames.
|
||||
pub type EthernetTracer<T> = Tracer<T, super::wire::EthernetFrame<&'static [u8]>>;
|
||||
#[cfg(all(feature = "phy-tuntap_interface", any(target_os = "linux", target_os = "android")))]
|
||||
pub use self::tuntap_interface::TunTapInterface;
|
||||
|
||||
/// A description of checksum behavior for a particular protocol.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
@ -192,6 +190,13 @@ impl ChecksumCapabilities {
|
|||
#[derive(Debug, Clone, Default)]
|
||||
#[non_exhaustive]
|
||||
pub struct DeviceCapabilities {
|
||||
/// Medium of the device.
|
||||
///
|
||||
/// This indicates what kind of packet the sent/received bytes are, and determines
|
||||
/// some behaviors of Interface. For example, ARP/NDISC address resolution is only done
|
||||
/// for Ethernet mediums.
|
||||
pub medium: Medium,
|
||||
|
||||
/// Maximum transmission unit.
|
||||
///
|
||||
/// The network device is unable to send or receive frames larger than the value returned
|
||||
|
@ -222,6 +227,36 @@ pub struct DeviceCapabilities {
|
|||
pub checksum: ChecksumCapabilities,
|
||||
}
|
||||
|
||||
/// Type of medium of a device.
|
||||
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
||||
pub enum Medium {
|
||||
/// Ethernet medium. Devices of this type send and receive Ethernet frames,
|
||||
/// and interfaces using it must do neighbor discovery via ARP or NDISC.
|
||||
///
|
||||
/// Examples of devices of this type are Ethernet, WiFi (802.11), Linux `tap`, and VPNs in tap (layer 2) mode.
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
Ethernet,
|
||||
|
||||
/// IP medium. Devices of this type send and receive IP frames, without an
|
||||
/// Ethernet header. MAC addresses are not used, and no neighbor discovery (ARP, NDISC) is done.
|
||||
///
|
||||
/// Examples of devices of this type are the Linux `tun`, PPP interfaces, VPNs in tun (layer 3) mode.
|
||||
#[cfg(feature = "medium-ip")]
|
||||
Ip,
|
||||
}
|
||||
|
||||
|
||||
impl Default for Medium {
|
||||
fn default() -> Medium {
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
return Medium::Ethernet;
|
||||
#[cfg(all(feature = "medium-ip", not(feature = "medium-ethernet")))]
|
||||
return Medium::Ip;
|
||||
#[cfg(all(not(feature = "medium-ip"), not(feature = "medium-ethernet")))]
|
||||
panic!("No medium enabled");
|
||||
}
|
||||
}
|
||||
|
||||
/// An interface for sending and receiving raw network frames.
|
||||
///
|
||||
/// The interface is based on _tokens_, which are types that allow to receive/transmit a
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::cell::RefCell;
|
|||
#[cfg(feature = "std")]
|
||||
use std::io::Write;
|
||||
use byteorder::{ByteOrder, NativeEndian};
|
||||
use phy::Medium;
|
||||
|
||||
use crate::Result;
|
||||
use crate::phy::{self, DeviceCapabilities, Device};
|
||||
|
@ -14,7 +15,7 @@ enum_with_unknown! {
|
|||
/// Ethernet frames
|
||||
Ethernet = 1,
|
||||
/// IPv4 or IPv6 packets (depending on the version field)
|
||||
Ip = 101
|
||||
Ip = 101,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,7 +129,14 @@ pub struct PcapWriter<D, S>
|
|||
|
||||
impl<D: for<'a> Device<'a>, S: PcapSink + Clone> PcapWriter<D, S> {
|
||||
/// Creates a packet capture writer.
|
||||
pub fn new(lower: D, sink: S, mode: PcapMode, link_type: PcapLinkType) -> PcapWriter<D, S> {
|
||||
pub fn new(lower: D, sink: S, mode: PcapMode) -> PcapWriter<D, S> {
|
||||
let medium = lower.capabilities().medium;
|
||||
let link_type = match medium {
|
||||
#[cfg(feature = "medium-ip")]
|
||||
Medium::Ip => PcapLinkType::Ip,
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
Medium::Ethernet => PcapLinkType::Ethernet,
|
||||
};
|
||||
sink.global_header(link_type);
|
||||
PcapWriter { lower, sink, mode }
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::io;
|
|||
use std::os::unix::io::{RawFd, AsRawFd};
|
||||
|
||||
use crate::Result;
|
||||
use crate::phy::{self, sys, DeviceCapabilities, Device};
|
||||
use crate::phy::{self, sys, DeviceCapabilities, Device, Medium};
|
||||
use crate::time::Instant;
|
||||
|
||||
/// A socket that captures or transmits the complete frame.
|
||||
|
@ -44,6 +44,7 @@ impl<'a> Device<'a> for RawSocket {
|
|||
fn capabilities(&self) -> DeviceCapabilities {
|
||||
DeviceCapabilities {
|
||||
max_transmission_unit: self.mtu,
|
||||
medium: Medium::Ethernet,
|
||||
..DeviceCapabilities::default()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
#[cfg(any(feature = "phy-raw_socket",
|
||||
feature = "phy-tap_interface"))]
|
||||
#![allow(unused)]
|
||||
|
||||
pub const SIOCGIFMTU: libc::c_ulong = 0x8921;
|
||||
#[cfg(any(feature = "phy-raw_socket"))]
|
||||
pub const SIOCGIFINDEX: libc::c_ulong = 0x8933;
|
||||
#[cfg(any(feature = "phy-raw_socket"))]
|
||||
pub const ETH_P_ALL: libc::c_short = 0x0003;
|
||||
|
||||
#[cfg(feature = "phy-tap_interface")]
|
||||
pub const TUNSETIFF: libc::c_ulong = 0x400454CA;
|
||||
#[cfg(feature = "phy-tap_interface")]
|
||||
pub const IFF_TUN: libc::c_int = 0x0001;
|
||||
pub const IFF_TAP: libc::c_int = 0x0002;
|
||||
#[cfg(feature = "phy-tap_interface")]
|
||||
pub const IFF_NO_PI: libc::c_int = 0x1000;
|
||||
|
|
|
@ -12,15 +12,15 @@ mod imp;
|
|||
pub mod raw_socket;
|
||||
#[cfg(all(feature = "phy-raw_socket", not(any(target_os = "linux", target_os = "android")), unix))]
|
||||
pub mod bpf;
|
||||
#[cfg(all(feature = "phy-tap_interface", any(target_os = "linux", target_os = "android")))]
|
||||
pub mod tap_interface;
|
||||
#[cfg(all(feature = "phy-tuntap_interface", any(target_os = "linux", target_os = "android")))]
|
||||
pub mod tuntap_interface;
|
||||
|
||||
#[cfg(all(feature = "phy-raw_socket", any(target_os = "linux", target_os = "android")))]
|
||||
pub use self::raw_socket::RawSocketDesc;
|
||||
#[cfg(all(feature = "phy-raw_socket", not(any(target_os = "linux", target_os = "android")), unix))]
|
||||
pub use self::bpf::BpfDevice as RawSocketDesc;
|
||||
#[cfg(all(feature = "phy-tap_interface", any(target_os = "linux", target_os = "android")))]
|
||||
pub use self::tap_interface::TapInterfaceDesc;
|
||||
#[cfg(all(feature = "phy-tuntap_interface", any(target_os = "linux", target_os = "android")))]
|
||||
pub use self::tuntap_interface::TunTapInterfaceDesc;
|
||||
|
||||
/// Wait until given file descriptor becomes readable, but no longer than given timeout.
|
||||
pub fn wait(fd: RawFd, duration: Option<Duration>) -> io::Result<()> {
|
||||
|
@ -60,7 +60,7 @@ pub fn wait(fd: RawFd, duration: Option<Duration>) -> io::Result<()> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(all(any(feature = "phy-tap_interface", feature = "phy-raw_socket"), unix))]
|
||||
#[cfg(all(any(feature = "phy-tuntap_interface", feature = "phy-raw_socket"), unix))]
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
struct ifreq {
|
||||
|
@ -68,7 +68,7 @@ struct ifreq {
|
|||
ifr_data: libc::c_int /* ifr_ifindex or ifr_mtu */
|
||||
}
|
||||
|
||||
#[cfg(all(any(feature = "phy-tap_interface", feature = "phy-raw_socket"), unix))]
|
||||
#[cfg(all(any(feature = "phy-tuntap_interface", feature = "phy-raw_socket"), unix))]
|
||||
fn ifreq_for(name: &str) -> ifreq {
|
||||
let mut ifreq = ifreq {
|
||||
ifr_name: [0; libc::IF_NAMESIZE],
|
||||
|
@ -81,7 +81,7 @@ fn ifreq_for(name: &str) -> ifreq {
|
|||
}
|
||||
|
||||
#[cfg(all(any(target_os = "linux", target_os = "android"),
|
||||
any(feature = "phy-tap_interface", feature = "phy-raw_socket")))]
|
||||
any(feature = "phy-tuntap_interface", feature = "phy-raw_socket")))]
|
||||
fn ifreq_ioctl(lower: libc::c_int, ifreq: &mut ifreq,
|
||||
cmd: libc::c_ulong) -> io::Result<libc::c_int> {
|
||||
unsafe {
|
||||
|
|
|
@ -1,22 +1,23 @@
|
|||
use std::io;
|
||||
use std::os::unix::io::{RawFd, AsRawFd};
|
||||
use super::*;
|
||||
use crate::wire::EthernetFrame;
|
||||
use crate::{phy::Medium, wire::EthernetFrame};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TapInterfaceDesc {
|
||||
pub struct TunTapInterfaceDesc {
|
||||
lower: libc::c_int,
|
||||
ifreq: ifreq
|
||||
ifreq: ifreq,
|
||||
medium: Medium,
|
||||
}
|
||||
|
||||
impl AsRawFd for TapInterfaceDesc {
|
||||
impl AsRawFd for TunTapInterfaceDesc {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.lower
|
||||
}
|
||||
}
|
||||
|
||||
impl TapInterfaceDesc {
|
||||
pub fn new(name: &str) -> io::Result<TapInterfaceDesc> {
|
||||
impl TunTapInterfaceDesc {
|
||||
pub fn new(name: &str, medium: Medium) -> io::Result<TunTapInterfaceDesc> {
|
||||
let lower = unsafe {
|
||||
let lower = libc::open("/dev/net/tun\0".as_ptr() as *const libc::c_char,
|
||||
libc::O_RDWR | libc::O_NONBLOCK);
|
||||
|
@ -24,14 +25,21 @@ impl TapInterfaceDesc {
|
|||
lower
|
||||
};
|
||||
|
||||
Ok(TapInterfaceDesc {
|
||||
lower: lower,
|
||||
ifreq: ifreq_for(name)
|
||||
Ok(TunTapInterfaceDesc {
|
||||
lower,
|
||||
ifreq: ifreq_for(name),
|
||||
medium,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn attach_interface(&mut self) -> io::Result<()> {
|
||||
self.ifreq.ifr_data = imp::IFF_TAP | imp::IFF_NO_PI;
|
||||
let mode = match self.medium {
|
||||
#[cfg(feature = "medium-ip")]
|
||||
Medium::Ip => imp::IFF_TUN,
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
Medium::Ethernet => imp::IFF_TAP,
|
||||
};
|
||||
self.ifreq.ifr_data = mode | imp::IFF_NO_PI;
|
||||
ifreq_ioctl(self.lower, &mut self.ifreq, imp::TUNSETIFF).map(|_| ())
|
||||
}
|
||||
|
||||
|
@ -46,9 +54,19 @@ impl TapInterfaceDesc {
|
|||
|
||||
unsafe { libc::close(lower); }
|
||||
|
||||
// Propagate error after close, to ensure we always close.
|
||||
let ip_mtu = ip_mtu?;
|
||||
|
||||
// SIOCGIFMTU returns the IP MTU (typically 1500 bytes.)
|
||||
// smoltcp counts the entire Ethernet packet in the MTU, so add the Ethernet header size to it.
|
||||
Ok(ip_mtu? + EthernetFrame::<&[u8]>::header_len())
|
||||
let mtu = match self.medium {
|
||||
#[cfg(feature = "medium-ip")]
|
||||
Medium::Ip => ip_mtu,
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
Medium::Ethernet => ip_mtu + EthernetFrame::<&[u8]>::header_len(),
|
||||
};
|
||||
|
||||
Ok(mtu)
|
||||
}
|
||||
|
||||
pub fn recv(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
|
||||
|
@ -70,7 +88,7 @@ impl TapInterfaceDesc {
|
|||
}
|
||||
}
|
||||
|
||||
impl Drop for TapInterfaceDesc {
|
||||
impl Drop for TunTapInterfaceDesc {
|
||||
fn drop(&mut self) {
|
||||
unsafe { libc::close(self.lower); }
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
use crate::Result;
|
||||
use crate::wire::pretty_print::{PrettyPrint, PrettyPrinter};
|
||||
use crate::phy::{self, DeviceCapabilities, Device};
|
||||
use core::fmt;
|
||||
|
||||
use crate::{Result, wire::pretty_print::{PrettyIndent, PrettyPrint}};
|
||||
use crate::phy::{self, DeviceCapabilities, Device, Medium};
|
||||
use crate::time::Instant;
|
||||
|
||||
/// A tracer device.
|
||||
|
@ -8,14 +9,14 @@ use crate::time::Instant;
|
|||
/// A tracer is a device that pretty prints all packets traversing it
|
||||
/// using the provided writer function, and then passes them to another
|
||||
/// device.
|
||||
pub struct Tracer<D: for<'a> Device<'a>, P: PrettyPrint> {
|
||||
pub struct Tracer<D: for<'a> Device<'a>> {
|
||||
inner: D,
|
||||
writer: fn(Instant, PrettyPrinter<P>),
|
||||
writer: fn(Instant, Packet),
|
||||
}
|
||||
|
||||
impl<D: for<'a> Device<'a>, P: PrettyPrint> Tracer<D, P> {
|
||||
impl<D: for<'a> Device<'a>> Tracer<D> {
|
||||
/// Create a tracer device.
|
||||
pub fn new(inner: D, writer: fn(timestamp: Instant, printer: PrettyPrinter<P>)) -> Tracer<D, P> {
|
||||
pub fn new(inner: D, writer: fn(timestamp: Instant, packet: Packet)) -> Tracer<D> {
|
||||
Tracer { inner, writer }
|
||||
}
|
||||
|
||||
|
@ -40,65 +41,100 @@ impl<D: for<'a> Device<'a>, P: PrettyPrint> Tracer<D, P> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, D, P> Device<'a> for Tracer<D, P>
|
||||
impl<'a, D> Device<'a> for Tracer<D>
|
||||
where D: for<'b> Device<'b>,
|
||||
P: PrettyPrint + 'a,
|
||||
{
|
||||
type RxToken = RxToken<<D as Device<'a>>::RxToken, P>;
|
||||
type TxToken = TxToken<<D as Device<'a>>::TxToken, P>;
|
||||
type RxToken = RxToken<<D as Device<'a>>::RxToken>;
|
||||
type TxToken = TxToken<<D as Device<'a>>::TxToken>;
|
||||
|
||||
fn capabilities(&self) -> DeviceCapabilities { self.inner.capabilities() }
|
||||
|
||||
fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
|
||||
let &mut Self { ref mut inner, writer, .. } = self;
|
||||
let medium = inner.capabilities().medium;
|
||||
inner.receive().map(|(rx_token, tx_token)| {
|
||||
let rx = RxToken { token: rx_token, writer };
|
||||
let tx = TxToken { token: tx_token, writer };
|
||||
let rx = RxToken { token: rx_token, writer, medium };
|
||||
let tx = TxToken { token: tx_token, writer, medium };
|
||||
(rx, tx)
|
||||
})
|
||||
}
|
||||
|
||||
fn transmit(&'a mut self) -> Option<Self::TxToken> {
|
||||
let &mut Self { ref mut inner, writer } = self;
|
||||
let medium = inner.capabilities().medium;
|
||||
inner.transmit().map(|tx_token| {
|
||||
TxToken { token: tx_token, writer }
|
||||
TxToken { token: tx_token, medium, writer }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct RxToken<Rx: phy::RxToken, P: PrettyPrint> {
|
||||
pub struct RxToken<Rx: phy::RxToken> {
|
||||
token: Rx,
|
||||
writer: fn(Instant, PrettyPrinter<P>)
|
||||
writer: fn(Instant, Packet),
|
||||
medium: Medium,
|
||||
}
|
||||
|
||||
impl<Rx: phy::RxToken, P: PrettyPrint> phy::RxToken for RxToken<Rx, P> {
|
||||
impl<Rx: phy::RxToken> phy::RxToken for RxToken<Rx> {
|
||||
fn consume<R, F>(self, timestamp: Instant, f: F) -> Result<R>
|
||||
where F: FnOnce(&mut [u8]) -> Result<R>
|
||||
{
|
||||
let Self { token, writer } = self;
|
||||
let Self { token, writer, medium } = self;
|
||||
token.consume(timestamp, |buffer| {
|
||||
writer(timestamp, PrettyPrinter::<P>::new("<- ", &buffer));
|
||||
writer(timestamp, Packet{
|
||||
buffer,
|
||||
medium,
|
||||
prefix: "<- ",
|
||||
});
|
||||
f(buffer)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct TxToken<Tx: phy::TxToken, P: PrettyPrint> {
|
||||
pub struct TxToken<Tx: phy::TxToken> {
|
||||
token: Tx,
|
||||
writer: fn(Instant, PrettyPrinter<P>)
|
||||
writer: fn(Instant, Packet),
|
||||
medium: Medium,
|
||||
}
|
||||
|
||||
impl<Tx: phy::TxToken, P: PrettyPrint> phy::TxToken for TxToken<Tx, P> {
|
||||
impl<Tx: phy::TxToken> phy::TxToken for TxToken<Tx> {
|
||||
fn consume<R, F>(self, timestamp: Instant, len: usize, f: F) -> Result<R>
|
||||
where F: FnOnce(&mut [u8]) -> Result<R>
|
||||
{
|
||||
let Self { token, writer } = self;
|
||||
let Self { token, writer, medium } = self;
|
||||
token.consume(timestamp, len, |buffer| {
|
||||
let result = f(buffer);
|
||||
writer(timestamp, PrettyPrinter::<P>::new("-> ", &buffer));
|
||||
writer(timestamp, Packet{
|
||||
buffer,
|
||||
medium,
|
||||
prefix: "-> ",
|
||||
});
|
||||
result
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Packet<'a> {
|
||||
buffer: &'a [u8],
|
||||
medium: Medium,
|
||||
prefix: &'static str,
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for Packet<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut indent = PrettyIndent::new(self.prefix);
|
||||
match self.medium {
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
Medium::Ethernet => crate::wire::EthernetFrame::<&'static [u8]>::pretty_print(&self.buffer, f, &mut indent),
|
||||
#[cfg(feature = "medium-ip")]
|
||||
Medium::Ip => match crate::wire::IpVersion::of_packet(&self.buffer) {
|
||||
#[cfg(feature = "proto-ipv4")]
|
||||
Ok(crate::wire::IpVersion::Ipv4) => crate::wire::Ipv4Packet::<&'static [u8]>::pretty_print(&self.buffer, f, &mut indent),
|
||||
#[cfg(feature = "proto-ipv6")]
|
||||
Ok(crate::wire::IpVersion::Ipv6) => crate::wire::Ipv6Packet::<&'static [u8]>::pretty_print(&self.buffer, f, &mut indent),
|
||||
_ => f.write_str("unrecognized IP version")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,46 +5,49 @@ use std::io;
|
|||
use std::os::unix::io::{RawFd, AsRawFd};
|
||||
|
||||
use crate::Result;
|
||||
use crate::phy::{self, sys, DeviceCapabilities, Device};
|
||||
use crate::phy::{self, sys, DeviceCapabilities, Device, Medium};
|
||||
use crate::time::Instant;
|
||||
|
||||
/// A virtual Ethernet interface.
|
||||
/// A virtual TUN (IP) or TAP (Ethernet) interface.
|
||||
#[derive(Debug)]
|
||||
pub struct TapInterface {
|
||||
lower: Rc<RefCell<sys::TapInterfaceDesc>>,
|
||||
mtu: usize
|
||||
pub struct TunTapInterface {
|
||||
lower: Rc<RefCell<sys::TunTapInterfaceDesc>>,
|
||||
mtu: usize,
|
||||
medium: Medium,
|
||||
}
|
||||
|
||||
impl AsRawFd for TapInterface {
|
||||
impl AsRawFd for TunTapInterface {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.lower.borrow().as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl TapInterface {
|
||||
/// Attaches to a TAP interface called `name`, or creates it if it does not exist.
|
||||
impl TunTapInterface {
|
||||
/// Attaches to a TUN/TAP interface called `name`, or creates it if it does not exist.
|
||||
///
|
||||
/// If `name` is a persistent interface configured with UID of the current user,
|
||||
/// no special privileges are needed. Otherwise, this requires superuser privileges
|
||||
/// or a corresponding capability set on the executable.
|
||||
pub fn new(name: &str) -> io::Result<TapInterface> {
|
||||
let mut lower = sys::TapInterfaceDesc::new(name)?;
|
||||
pub fn new(name: &str, medium: Medium) -> io::Result<TunTapInterface> {
|
||||
let mut lower = sys::TunTapInterfaceDesc::new(name, medium)?;
|
||||
lower.attach_interface()?;
|
||||
let mtu = lower.interface_mtu()?;
|
||||
Ok(TapInterface {
|
||||
Ok(TunTapInterface {
|
||||
lower: Rc::new(RefCell::new(lower)),
|
||||
mtu: mtu
|
||||
mtu,
|
||||
medium,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Device<'a> for TapInterface {
|
||||
impl<'a> Device<'a> for TunTapInterface {
|
||||
type RxToken = RxToken;
|
||||
type TxToken = TxToken;
|
||||
|
||||
fn capabilities(&self) -> DeviceCapabilities {
|
||||
DeviceCapabilities {
|
||||
max_transmission_unit: self.mtu,
|
||||
medium: self.medium,
|
||||
..DeviceCapabilities::default()
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +91,7 @@ impl phy::RxToken for RxToken {
|
|||
|
||||
#[doc(hidden)]
|
||||
pub struct TxToken {
|
||||
lower: Rc<RefCell<sys::TapInterfaceDesc>>,
|
||||
lower: Rc<RefCell<sys::TunTapInterfaceDesc>>,
|
||||
}
|
||||
|
||||
impl phy::TxToken for TxToken {
|
|
@ -3,7 +3,7 @@ use core::cmp;
|
|||
use core::task::Waker;
|
||||
|
||||
use crate::{Error, Result};
|
||||
use crate::phy::{ChecksumCapabilities, DeviceCapabilities};
|
||||
use crate::phy::ChecksumCapabilities;
|
||||
use crate::socket::{Socket, SocketMeta, SocketHandle, PollAt};
|
||||
use crate::storage::{PacketBuffer, PacketMetadata};
|
||||
#[cfg(feature = "async")]
|
||||
|
@ -400,7 +400,7 @@ impl<'a> IcmpSocket<'a> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn dispatch<F>(&mut self, _caps: &DeviceCapabilities, emit: F) -> Result<()>
|
||||
pub(crate) fn dispatch<F>(&mut self, emit: F) -> Result<()>
|
||||
where F: FnOnce((IpRepr, IcmpRepr)) -> Result<()>
|
||||
{
|
||||
let handle = self.meta.handle;
|
||||
|
@ -528,9 +528,9 @@ mod test_ipv4 {
|
|||
#[test]
|
||||
fn test_send_dispatch() {
|
||||
let mut socket = socket(buffer(0), buffer(1));
|
||||
let caps = DeviceCapabilities::default();
|
||||
let checksum = ChecksumCapabilities::default();
|
||||
|
||||
assert_eq!(socket.dispatch(&caps, |_| unreachable!()),
|
||||
assert_eq!(socket.dispatch(|_| unreachable!()),
|
||||
Err(Error::Exhausted));
|
||||
|
||||
// This buffer is too long
|
||||
|
@ -539,13 +539,13 @@ mod test_ipv4 {
|
|||
|
||||
let mut bytes = [0xff; 24];
|
||||
let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
|
||||
ECHOV4_REPR.emit(&mut packet, &caps.checksum);
|
||||
ECHOV4_REPR.emit(&mut packet, &checksum);
|
||||
|
||||
assert_eq!(socket.send_slice(&packet.into_inner()[..], REMOTE_IPV4.into()), Ok(()));
|
||||
assert_eq!(socket.send_slice(b"123456", REMOTE_IPV4.into()), Err(Error::Exhausted));
|
||||
assert!(!socket.can_send());
|
||||
|
||||
assert_eq!(socket.dispatch(&caps, |(ip_repr, icmp_repr)| {
|
||||
assert_eq!(socket.dispatch(|(ip_repr, icmp_repr)| {
|
||||
assert_eq!(ip_repr, LOCAL_IPV4_REPR);
|
||||
assert_eq!(icmp_repr, ECHOV4_REPR.into());
|
||||
Err(Error::Unaddressable)
|
||||
|
@ -553,7 +553,7 @@ mod test_ipv4 {
|
|||
// buffer is not taken off of the tx queue due to the error
|
||||
assert!(!socket.can_send());
|
||||
|
||||
assert_eq!(socket.dispatch(&caps, |(ip_repr, icmp_repr)| {
|
||||
assert_eq!(socket.dispatch(|(ip_repr, icmp_repr)| {
|
||||
assert_eq!(ip_repr, LOCAL_IPV4_REPR);
|
||||
assert_eq!(icmp_repr, ECHOV4_REPR.into());
|
||||
Ok(())
|
||||
|
@ -565,16 +565,16 @@ mod test_ipv4 {
|
|||
#[test]
|
||||
fn test_set_hop_limit_v4() {
|
||||
let mut s = socket(buffer(0), buffer(1));
|
||||
let caps = DeviceCapabilities::default();
|
||||
let checksum = ChecksumCapabilities::default();
|
||||
|
||||
let mut bytes = [0xff; 24];
|
||||
let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
|
||||
ECHOV4_REPR.emit(&mut packet, &caps.checksum);
|
||||
ECHOV4_REPR.emit(&mut packet, &checksum);
|
||||
|
||||
s.set_hop_limit(Some(0x2a));
|
||||
|
||||
assert_eq!(s.send_slice(&packet.into_inner()[..], REMOTE_IPV4.into()), Ok(()));
|
||||
assert_eq!(s.dispatch(&caps, |(ip_repr, _)| {
|
||||
assert_eq!(s.dispatch(|(ip_repr, _)| {
|
||||
assert_eq!(ip_repr, IpRepr::Ipv4(Ipv4Repr {
|
||||
src_addr: Ipv4Address::UNSPECIFIED,
|
||||
dst_addr: REMOTE_IPV4,
|
||||
|
@ -594,20 +594,20 @@ mod test_ipv4 {
|
|||
assert!(!socket.can_recv());
|
||||
assert_eq!(socket.recv(), Err(Error::Exhausted));
|
||||
|
||||
let caps = DeviceCapabilities::default();
|
||||
let checksum = ChecksumCapabilities::default();
|
||||
|
||||
let mut bytes = [0xff; 24];
|
||||
let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
|
||||
ECHOV4_REPR.emit(&mut packet, &caps.checksum);
|
||||
ECHOV4_REPR.emit(&mut packet, &checksum);
|
||||
let data = &packet.into_inner()[..];
|
||||
|
||||
assert!(socket.accepts(&REMOTE_IPV4_REPR, &ECHOV4_REPR.into(), &caps.checksum));
|
||||
assert_eq!(socket.process(&REMOTE_IPV4_REPR, &ECHOV4_REPR.into(), &caps.checksum),
|
||||
assert!(socket.accepts(&REMOTE_IPV4_REPR, &ECHOV4_REPR.into(), &checksum));
|
||||
assert_eq!(socket.process(&REMOTE_IPV4_REPR, &ECHOV4_REPR.into(), &checksum),
|
||||
Ok(()));
|
||||
assert!(socket.can_recv());
|
||||
|
||||
assert!(socket.accepts(&REMOTE_IPV4_REPR, &ECHOV4_REPR.into(), &caps.checksum));
|
||||
assert_eq!(socket.process(&REMOTE_IPV4_REPR, &ECHOV4_REPR.into(), &caps.checksum),
|
||||
assert!(socket.accepts(&REMOTE_IPV4_REPR, &ECHOV4_REPR.into(), &checksum));
|
||||
assert_eq!(socket.process(&REMOTE_IPV4_REPR, &ECHOV4_REPR.into(), &checksum),
|
||||
Err(Error::Exhausted));
|
||||
|
||||
assert_eq!(socket.recv(), Ok((&data[..], REMOTE_IPV4.into())));
|
||||
|
@ -619,7 +619,7 @@ mod test_ipv4 {
|
|||
let mut socket = socket(buffer(1), buffer(1));
|
||||
assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
|
||||
|
||||
let caps = DeviceCapabilities::default();
|
||||
let checksum = ChecksumCapabilities::default();
|
||||
let mut bytes = [0xff; 20];
|
||||
let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
|
||||
let icmp_repr = Icmpv4Repr::EchoRequest {
|
||||
|
@ -627,11 +627,11 @@ mod test_ipv4 {
|
|||
seq_no: 0x5678,
|
||||
data: &[0xff; 16]
|
||||
};
|
||||
icmp_repr.emit(&mut packet, &caps.checksum);
|
||||
icmp_repr.emit(&mut packet, &checksum);
|
||||
|
||||
// Ensure that a packet with an identifier that isn't the bound
|
||||
// ID is not accepted
|
||||
assert!(!socket.accepts(&REMOTE_IPV4_REPR, &icmp_repr.into(), &caps.checksum));
|
||||
assert!(!socket.accepts(&REMOTE_IPV4_REPR, &icmp_repr.into(), &checksum));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -639,11 +639,11 @@ mod test_ipv4 {
|
|||
let mut socket = socket(buffer(1), buffer(1));
|
||||
assert_eq!(socket.bind(Endpoint::Udp(LOCAL_END_V4)), Ok(()));
|
||||
|
||||
let caps = DeviceCapabilities::default();
|
||||
let checksum = ChecksumCapabilities::default();
|
||||
|
||||
let mut bytes = [0xff; 18];
|
||||
let mut packet = UdpPacket::new_unchecked(&mut bytes);
|
||||
UDP_REPR.emit(&mut packet, &REMOTE_IPV4.into(), &LOCAL_IPV4.into(), &caps.checksum);
|
||||
UDP_REPR.emit(&mut packet, &REMOTE_IPV4.into(), &LOCAL_IPV4.into(), &checksum);
|
||||
|
||||
let data = &packet.into_inner()[..];
|
||||
|
||||
|
@ -670,14 +670,14 @@ mod test_ipv4 {
|
|||
|
||||
// Ensure we can accept ICMP error response to the bound
|
||||
// UDP port
|
||||
assert!(socket.accepts(&ip_repr, &icmp_repr.into(), &caps.checksum));
|
||||
assert_eq!(socket.process(&ip_repr, &icmp_repr.into(), &caps.checksum),
|
||||
assert!(socket.accepts(&ip_repr, &icmp_repr.into(), &checksum));
|
||||
assert_eq!(socket.process(&ip_repr, &icmp_repr.into(), &checksum),
|
||||
Ok(()));
|
||||
assert!(socket.can_recv());
|
||||
|
||||
let mut bytes = [0x00; 46];
|
||||
let mut packet = Icmpv4Packet::new_unchecked(&mut bytes[..]);
|
||||
icmp_repr.emit(&mut packet, &caps.checksum);
|
||||
icmp_repr.emit(&mut packet, &checksum);
|
||||
assert_eq!(socket.recv(), Ok((&packet.into_inner()[..], REMOTE_IPV4.into())));
|
||||
assert!(!socket.can_recv());
|
||||
}
|
||||
|
@ -727,9 +727,9 @@ mod test_ipv6 {
|
|||
#[test]
|
||||
fn test_send_dispatch() {
|
||||
let mut socket = socket(buffer(0), buffer(1));
|
||||
let caps = DeviceCapabilities::default();
|
||||
let checksum = ChecksumCapabilities::default();
|
||||
|
||||
assert_eq!(socket.dispatch(&caps, |_| unreachable!()),
|
||||
assert_eq!(socket.dispatch(|_| unreachable!()),
|
||||
Err(Error::Exhausted));
|
||||
|
||||
// This buffer is too long
|
||||
|
@ -738,13 +738,13 @@ mod test_ipv6 {
|
|||
|
||||
let mut bytes = vec![0xff; 24];
|
||||
let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
|
||||
ECHOV6_REPR.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &caps.checksum);
|
||||
ECHOV6_REPR.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &checksum);
|
||||
|
||||
assert_eq!(socket.send_slice(&packet.into_inner()[..], REMOTE_IPV6.into()), Ok(()));
|
||||
assert_eq!(socket.send_slice(b"123456", REMOTE_IPV6.into()), Err(Error::Exhausted));
|
||||
assert!(!socket.can_send());
|
||||
|
||||
assert_eq!(socket.dispatch(&caps, |(ip_repr, icmp_repr)| {
|
||||
assert_eq!(socket.dispatch(|(ip_repr, icmp_repr)| {
|
||||
assert_eq!(ip_repr, LOCAL_IPV6_REPR);
|
||||
assert_eq!(icmp_repr, ECHOV6_REPR.into());
|
||||
Err(Error::Unaddressable)
|
||||
|
@ -752,7 +752,7 @@ mod test_ipv6 {
|
|||
// buffer is not taken off of the tx queue due to the error
|
||||
assert!(!socket.can_send());
|
||||
|
||||
assert_eq!(socket.dispatch(&caps, |(ip_repr, icmp_repr)| {
|
||||
assert_eq!(socket.dispatch(|(ip_repr, icmp_repr)| {
|
||||
assert_eq!(ip_repr, LOCAL_IPV6_REPR);
|
||||
assert_eq!(icmp_repr, ECHOV6_REPR.into());
|
||||
Ok(())
|
||||
|
@ -764,16 +764,16 @@ mod test_ipv6 {
|
|||
#[test]
|
||||
fn test_set_hop_limit() {
|
||||
let mut s = socket(buffer(0), buffer(1));
|
||||
let caps = DeviceCapabilities::default();
|
||||
let checksum = ChecksumCapabilities::default();
|
||||
|
||||
let mut bytes = vec![0xff; 24];
|
||||
let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
|
||||
ECHOV6_REPR.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &caps.checksum);
|
||||
ECHOV6_REPR.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &checksum);
|
||||
|
||||
s.set_hop_limit(Some(0x2a));
|
||||
|
||||
assert_eq!(s.send_slice(&packet.into_inner()[..], REMOTE_IPV6.into()), Ok(()));
|
||||
assert_eq!(s.dispatch(&caps, |(ip_repr, _)| {
|
||||
assert_eq!(s.dispatch(|(ip_repr, _)| {
|
||||
assert_eq!(ip_repr, IpRepr::Ipv6(Ipv6Repr {
|
||||
src_addr: Ipv6Address::UNSPECIFIED,
|
||||
dst_addr: REMOTE_IPV6,
|
||||
|
@ -793,20 +793,20 @@ mod test_ipv6 {
|
|||
assert!(!socket.can_recv());
|
||||
assert_eq!(socket.recv(), Err(Error::Exhausted));
|
||||
|
||||
let caps = DeviceCapabilities::default();
|
||||
let checksum = ChecksumCapabilities::default();
|
||||
|
||||
let mut bytes = [0xff; 24];
|
||||
let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
|
||||
ECHOV6_REPR.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &caps.checksum);
|
||||
ECHOV6_REPR.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &checksum);
|
||||
let data = &packet.into_inner()[..];
|
||||
|
||||
assert!(socket.accepts(&REMOTE_IPV6_REPR, &ECHOV6_REPR.into(), &caps.checksum));
|
||||
assert_eq!(socket.process(&REMOTE_IPV6_REPR, &ECHOV6_REPR.into(), &caps.checksum),
|
||||
assert!(socket.accepts(&REMOTE_IPV6_REPR, &ECHOV6_REPR.into(), &checksum));
|
||||
assert_eq!(socket.process(&REMOTE_IPV6_REPR, &ECHOV6_REPR.into(), &checksum),
|
||||
Ok(()));
|
||||
assert!(socket.can_recv());
|
||||
|
||||
assert!(socket.accepts(&REMOTE_IPV6_REPR, &ECHOV6_REPR.into(), &caps.checksum));
|
||||
assert_eq!(socket.process(&REMOTE_IPV6_REPR, &ECHOV6_REPR.into(), &caps.checksum),
|
||||
assert!(socket.accepts(&REMOTE_IPV6_REPR, &ECHOV6_REPR.into(), &checksum));
|
||||
assert_eq!(socket.process(&REMOTE_IPV6_REPR, &ECHOV6_REPR.into(), &checksum),
|
||||
Err(Error::Exhausted));
|
||||
|
||||
assert_eq!(socket.recv(), Ok((&data[..], REMOTE_IPV6.into())));
|
||||
|
@ -818,7 +818,7 @@ mod test_ipv6 {
|
|||
let mut socket = socket(buffer(1), buffer(1));
|
||||
assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
|
||||
|
||||
let caps = DeviceCapabilities::default();
|
||||
let checksum = ChecksumCapabilities::default();
|
||||
let mut bytes = [0xff; 20];
|
||||
let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
|
||||
let icmp_repr = Icmpv6Repr::EchoRequest {
|
||||
|
@ -826,11 +826,11 @@ mod test_ipv6 {
|
|||
seq_no: 0x5678,
|
||||
data: &[0xff; 16]
|
||||
};
|
||||
icmp_repr.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &caps.checksum);
|
||||
icmp_repr.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &checksum);
|
||||
|
||||
// Ensure that a packet with an identifier that isn't the bound
|
||||
// ID is not accepted
|
||||
assert!(!socket.accepts(&REMOTE_IPV6_REPR, &icmp_repr.into(), &caps.checksum));
|
||||
assert!(!socket.accepts(&REMOTE_IPV6_REPR, &icmp_repr.into(), &checksum));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -838,11 +838,11 @@ mod test_ipv6 {
|
|||
let mut socket = socket(buffer(1), buffer(1));
|
||||
assert_eq!(socket.bind(Endpoint::Udp(LOCAL_END_V6)), Ok(()));
|
||||
|
||||
let caps = DeviceCapabilities::default();
|
||||
let checksum = ChecksumCapabilities::default();
|
||||
|
||||
let mut bytes = [0xff; 18];
|
||||
let mut packet = UdpPacket::new_unchecked(&mut bytes);
|
||||
UDP_REPR.emit(&mut packet, &REMOTE_IPV6.into(), &LOCAL_IPV6.into(), &caps.checksum);
|
||||
UDP_REPR.emit(&mut packet, &REMOTE_IPV6.into(), &LOCAL_IPV6.into(), &checksum);
|
||||
|
||||
let data = &packet.into_inner()[..];
|
||||
|
||||
|
@ -869,14 +869,14 @@ mod test_ipv6 {
|
|||
|
||||
// Ensure we can accept ICMP error response to the bound
|
||||
// UDP port
|
||||
assert!(socket.accepts(&ip_repr, &icmp_repr.into(), &caps.checksum));
|
||||
assert_eq!(socket.process(&ip_repr, &icmp_repr.into(), &caps.checksum),
|
||||
assert!(socket.accepts(&ip_repr, &icmp_repr.into(), &checksum));
|
||||
assert_eq!(socket.process(&ip_repr, &icmp_repr.into(), &checksum),
|
||||
Ok(()));
|
||||
assert!(socket.can_recv());
|
||||
|
||||
let mut bytes = [0x00; 66];
|
||||
let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]);
|
||||
icmp_repr.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &caps.checksum);
|
||||
icmp_repr.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &checksum);
|
||||
assert_eq!(socket.recv(), Ok((&packet.into_inner()[..], REMOTE_IPV6.into())));
|
||||
assert!(!socket.can_recv());
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ use core::{cmp, fmt, mem};
|
|||
use core::task::Waker;
|
||||
|
||||
use crate::{Error, Result};
|
||||
use crate::phy::DeviceCapabilities;
|
||||
use crate::time::{Duration, Instant};
|
||||
use crate::socket::{Socket, SocketMeta, SocketHandle, PollAt};
|
||||
use crate::storage::{Assembler, RingBuffer};
|
||||
|
@ -1662,7 +1661,7 @@ impl<'a> TcpSocket<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn dispatch<F>(&mut self, timestamp: Instant, caps: &DeviceCapabilities,
|
||||
pub(crate) fn dispatch<F>(&mut self, timestamp: Instant, ip_mtu: usize,
|
||||
emit: F) -> Result<()>
|
||||
where F: FnOnce((IpRepr, TcpRepr)) -> Result<()> {
|
||||
if !self.remote_endpoint.is_specified() { return Err(Error::Exhausted) }
|
||||
|
@ -1789,7 +1788,7 @@ impl<'a> TcpSocket<'a> {
|
|||
let offset = self.remote_last_seq - self.local_seq_no;
|
||||
let win_limit = self.local_seq_no + self.remote_win_len - self.remote_last_seq;
|
||||
let size = cmp::min(cmp::min(win_limit, self.remote_mss),
|
||||
caps.max_transmission_unit - ip_repr.buffer_len() - repr.mss_header_len());
|
||||
ip_mtu - ip_repr.buffer_len() - repr.mss_header_len());
|
||||
repr.payload = self.tx_buffer.get_allocated(offset, size);
|
||||
// If we've sent everything we had in the buffer, follow it with the PSH or FIN
|
||||
// flags, depending on whether the transmit half of the connection is open.
|
||||
|
@ -1848,7 +1847,7 @@ impl<'a> TcpSocket<'a> {
|
|||
|
||||
if repr.control == TcpControl::Syn {
|
||||
// Fill the MSS option. See RFC 6691 for an explanation of this calculation.
|
||||
let mut max_segment_size = caps.max_transmission_unit;
|
||||
let mut max_segment_size = ip_mtu;
|
||||
max_segment_size -= ip_repr.buffer_len();
|
||||
max_segment_size -= repr.mss_header_len();
|
||||
repr.max_seg_size = Some(max_segment_size as u16);
|
||||
|
@ -2044,11 +2043,8 @@ mod test {
|
|||
|
||||
fn recv<F>(socket: &mut TcpSocket, timestamp: Instant, mut f: F)
|
||||
where F: FnMut(Result<TcpRepr>) {
|
||||
let caps = DeviceCapabilities {
|
||||
max_transmission_unit: 1520,
|
||||
..Default::default()
|
||||
};
|
||||
let result = socket.dispatch(timestamp, &caps, |(ip_repr, tcp_repr)| {
|
||||
let mtu = 1520;
|
||||
let result = socket.dispatch(timestamp, mtu, |(ip_repr, tcp_repr)| {
|
||||
let ip_repr = ip_repr.lower(&[IpCidr::new(LOCAL_END.addr, 24)]).unwrap();
|
||||
|
||||
assert_eq!(ip_repr.protocol(), IpProtocol::Tcp);
|
||||
|
@ -4897,13 +4893,10 @@ mod test {
|
|||
#[test]
|
||||
fn test_set_hop_limit() {
|
||||
let mut s = socket_syn_received();
|
||||
let caps = DeviceCapabilities {
|
||||
max_transmission_unit: 1520,
|
||||
..Default::default()
|
||||
};
|
||||
let mtu = 1520;
|
||||
|
||||
s.set_hop_limit(Some(0x2a));
|
||||
assert_eq!(s.dispatch(Instant::from_millis(0), &caps, |(ip_repr, _)| {
|
||||
assert_eq!(s.dispatch(Instant::from_millis(0), mtu, |(ip_repr, _)| {
|
||||
assert_eq!(ip_repr.hop_limit(), 0x2a);
|
||||
Ok(())
|
||||
}), Ok(()));
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::phy::ChecksumCapabilities;
|
|||
use crate::wire::ip::checksum;
|
||||
use crate::wire::{IpAddress, IpProtocol, Ipv6Packet, Ipv6Repr};
|
||||
use crate::wire::MldRepr;
|
||||
#[cfg(feature = "ethernet")]
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
use crate::wire::NdiscRepr;
|
||||
|
||||
enum_with_unknown! {
|
||||
|
@ -536,7 +536,7 @@ pub enum Repr<'a> {
|
|||
seq_no: u16,
|
||||
data: &'a [u8]
|
||||
},
|
||||
#[cfg(feature = "ethernet")]
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
Ndisc(NdiscRepr<'a>),
|
||||
Mld(MldRepr<'a>),
|
||||
}
|
||||
|
@ -617,7 +617,7 @@ impl<'a> Repr<'a> {
|
|||
data: packet.payload()
|
||||
})
|
||||
},
|
||||
#[cfg(feature = "ethernet")]
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
(msg_type, 0) if msg_type.is_ndisc() => {
|
||||
NdiscRepr::parse(packet).map(Repr::Ndisc)
|
||||
},
|
||||
|
@ -639,7 +639,7 @@ impl<'a> Repr<'a> {
|
|||
&Repr::EchoReply { data, .. } => {
|
||||
field::ECHO_SEQNO.end + data.len()
|
||||
},
|
||||
#[cfg(feature = "ethernet")]
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
&Repr::Ndisc(ndisc) => {
|
||||
ndisc.buffer_len()
|
||||
},
|
||||
|
@ -710,7 +710,7 @@ impl<'a> Repr<'a> {
|
|||
packet.payload_mut()[..data_len].copy_from_slice(&data[..data_len])
|
||||
},
|
||||
|
||||
#[cfg(feature = "ethernet")]
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
Repr::Ndisc(ndisc) => {
|
||||
ndisc.emit(packet)
|
||||
},
|
||||
|
|
|
@ -77,9 +77,9 @@ mod field {
|
|||
|
||||
pub mod pretty_print;
|
||||
|
||||
#[cfg(feature = "ethernet")]
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
mod ethernet;
|
||||
#[cfg(all(feature = "proto-ipv4", feature = "ethernet"))]
|
||||
#[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))]
|
||||
mod arp;
|
||||
pub(crate) mod ip;
|
||||
#[cfg(feature = "proto-ipv4")]
|
||||
|
@ -102,9 +102,9 @@ mod icmpv6;
|
|||
mod icmp;
|
||||
#[cfg(feature = "proto-igmp")]
|
||||
mod igmp;
|
||||
#[cfg(all(feature = "proto-ipv6", feature = "ethernet"))]
|
||||
#[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))]
|
||||
mod ndisc;
|
||||
#[cfg(all(feature = "proto-ipv6", feature = "ethernet"))]
|
||||
#[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))]
|
||||
mod ndiscoption;
|
||||
#[cfg(feature = "proto-ipv6")]
|
||||
mod mld;
|
||||
|
@ -115,14 +115,14 @@ pub(crate) mod dhcpv4;
|
|||
|
||||
pub use self::pretty_print::PrettyPrinter;
|
||||
|
||||
#[cfg(feature = "ethernet")]
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
pub use self::ethernet::{EtherType as EthernetProtocol,
|
||||
Address as EthernetAddress,
|
||||
Frame as EthernetFrame,
|
||||
HEADER_LEN as ETHERNET_HEADER_LEN,
|
||||
Repr as EthernetRepr};
|
||||
|
||||
#[cfg(all(feature = "proto-ipv4", feature = "ethernet"))]
|
||||
#[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))]
|
||||
pub use self::arp::{Hardware as ArpHardware,
|
||||
Operation as ArpOperation,
|
||||
Packet as ArpPacket,
|
||||
|
@ -193,12 +193,12 @@ pub use self::icmpv6::{Message as Icmpv6Message,
|
|||
pub use self::icmp::Repr as IcmpRepr;
|
||||
|
||||
|
||||
#[cfg(all(feature = "proto-ipv6", feature = "ethernet"))]
|
||||
#[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))]
|
||||
pub use self::ndisc::{Repr as NdiscRepr,
|
||||
RouterFlags as NdiscRouterFlags,
|
||||
NeighborFlags as NdiscNeighborFlags};
|
||||
|
||||
#[cfg(all(feature = "proto-ipv6", feature = "ethernet"))]
|
||||
#[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))]
|
||||
pub use self::ndiscoption::{NdiscOption,
|
||||
Repr as NdiscOptionRepr,
|
||||
Type as NdiscOptionType,
|
||||
|
|
Loading…
Reference in New Issue