Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add support for IP mediums, v2 #346

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 18 additions & 12 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,35 +12,41 @@ matrix:
env: FEATURES='default' MODE='test'
### Test select feature permutations, chosen to be as orthogonal as possible
- rust: nightly
env: FEATURES='std ethernet phy-raw_socket proto-ipv6 socket-udp' MODE='test'
env: FEATURES='std medium-ethernet phy-raw_socket proto-ipv6 socket-udp' MODE='test'
- rust: nightly
env: FEATURES='std ethernet phy-tap_interface proto-ipv6 socket-udp' MODE='test'
env: FEATURES='std medium-ethernet phy-tap_interface proto-ipv6 socket-udp' MODE='test'
- rust: nightly
env: FEATURES='std ethernet proto-ipv4 proto-igmp socket-raw' MODE='test'
env: FEATURES='std medium-ethernet proto-ipv4 proto-igmp socket-raw' MODE='test'
- rust: nightly
env: FEATURES='std ethernet proto-ipv4 socket-udp socket-tcp' MODE='test'
env: FEATURES='std medium-ethernet proto-ipv4 socket-udp socket-tcp' MODE='test'
- rust: nightly
env: FEATURES='std ethernet proto-ipv4 proto-dhcpv4 socket-udp' MODE='test'
env: FEATURES='std medium-ethernet proto-ipv4 proto-dhcpv4 socket-udp' MODE='test'
- rust: nightly
env: FEATURES='std ethernet proto-ipv6 socket-udp' MODE='test'
env: FEATURES='std medium-ethernet proto-ipv6 socket-udp' MODE='test'
- rust: nightly
env: FEATURES='std ethernet proto-ipv6 socket-tcp' MODE='test'
env: FEATURES='std medium-ethernet proto-ipv6 socket-tcp' MODE='test'
- rust: nightly
env: FEATURES='std ethernet proto-ipv4 socket-icmp socket-tcp' MODE='test'
env: FEATURES='std medium-ethernet proto-ipv4 socket-icmp socket-tcp' MODE='test'
- rust: nightly
env: FEATURES='std ethernet proto-ipv6 socket-icmp socket-tcp' MODE='test'
env: FEATURES='std medium-ethernet proto-ipv6 socket-icmp socket-tcp' MODE='test'
### Test select feature permutations, chosen to be as aggressive as possible
- rust: nightly
env: FEATURES='ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp std'
env: FEATURES='medium-ethernet medium-ip proto-ipv4 proto-ipv6 proto-dhcpv4 proto-igmp socket-raw socket-udp socket-tcp socket-icmp std'
MODE='test'
- rust: nightly
env: FEATURES='ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp alloc'
env: FEATURES='medium-ip proto-ipv4 proto-ipv6 proto-igmp socket-raw socket-udp socket-tcp socket-icmp std'
MODE='test'
- rust: nightly
env: FEATURES='medium-ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp std'
MODE='test'
- rust: nightly
env: FEATURES='medium-ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp alloc'
MODE='test'
- rust: nightly
env: FEATURES='proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp alloc'
MODE='test'
- rust: nightly
env: FEATURES='ethernet proto-ipv4 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp'
env: FEATURES='medium-ethernet proto-ipv4 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp'
MODE='build'
- rust: nightly
env: MODE='fuzz run' ARGS='packet_parser -- -max_len=1536 -max_total_time=30'
Expand Down
12 changes: 9 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ url = "1.0"
std = ["managed/std"]
alloc = ["managed/alloc"]
verbose = []
ethernet = []
"medium-ethernet" = []
"medium-ip" = []
"phy-raw_socket" = ["std", "libc"]
"phy-tap_interface" = ["std", "libc"]
"phy-tun_interface" = ["std", "libc"]
"proto-ipv4" = []
"proto-igmp" = ["proto-ipv4"]
"proto-dhcpv4" = ["proto-ipv4", "socket-raw"]
Expand All @@ -44,8 +46,8 @@ ethernet = []
"socket-icmp" = []
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-tap_interface", "phy-tun_interface",
"proto-ipv4", "proto-igmp", "proto-ipv6",
"socket-raw", "socket-icmp", "socket-udp", "socket-tcp"
]
Expand Down Expand Up @@ -94,5 +96,9 @@ required-features = ["std", "phy-tap_interface", "proto-ipv4", "socket-raw", "so
name = "dhcp_client"
required-features = ["std", "phy-tap_interface", "proto-ipv4", "proto-dhcpv4", "socket-raw"]

[[example]]
name = "tunhttpclient"
required-features = ["std", "phy-tun_interface", "proto-ipv4", "proto-ipv6", "socket-tcp"]

[profile.release]
debug = 2
4 changes: 2 additions & 2 deletions examples/benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use std::net::TcpStream;
use std::os::unix::io::AsRawFd;
use smoltcp::phy::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};
Expand Down Expand Up @@ -94,7 +94,7 @@ 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 mut iface = InterfaceBuilder::new(device)
.ethernet_addr(ethernet_addr)
.neighbor_cache(neighbor_cache)
.ip_addrs(ip_addrs)
Expand Down
4 changes: 2 additions & 2 deletions examples/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use std::collections::BTreeMap;
use std::os::unix::io::AsRawFd;
use smoltcp::phy::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;

Expand Down Expand Up @@ -43,7 +43,7 @@ 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)
let mut iface = InterfaceBuilder::new(device)
.ethernet_addr(ethernet_addr)
.neighbor_cache(neighbor_cache)
.ip_addrs(ip_addrs)
Expand Down
4 changes: 2 additions & 2 deletions examples/dhcp_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::collections::BTreeMap;
use std::os::unix::io::AsRawFd;
use smoltcp::phy::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;
Expand All @@ -33,7 +33,7 @@ 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)
let mut iface = InterfaceBuilder::new(device)
.ethernet_addr(ethernet_addr)
.neighbor_cache(neighbor_cache)
.ip_addrs(ip_addrs)
Expand Down
4 changes: 2 additions & 2 deletions examples/httpclient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::os::unix::io::AsRawFd;
use url::Url;
use smoltcp::phy::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;

Expand Down Expand Up @@ -51,7 +51,7 @@ 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)
let mut iface = InterfaceBuilder::new(device)
.ethernet_addr(ethernet_addr)
.neighbor_cache(neighbor_cache)
.ip_addrs(ip_addrs)
Expand Down
8 changes: 4 additions & 4 deletions examples/loopback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ extern crate getopts;
mod utils;

use core::str;
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};

Expand Down Expand Up @@ -72,7 +72,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 = {
Expand All @@ -92,7 +92,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)
Expand Down
4 changes: 2 additions & 2 deletions examples/multicast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::os::unix::io::AsRawFd;
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};
Expand Down Expand Up @@ -42,7 +42,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])
Expand Down
4 changes: 2 additions & 2 deletions examples/ping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ 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};
use std::collections::HashMap;
use byteorder::{ByteOrder, NetworkEndian};
Expand Down Expand Up @@ -103,7 +103,7 @@ 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)
let mut iface = InterfaceBuilder::new(device)
.ethernet_addr(ethernet_addr)
.ip_addrs(ip_addrs)
.routes(routes)
Expand Down
4 changes: 2 additions & 2 deletions examples/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::fmt::Write;
use std::os::unix::io::AsRawFd;
use smoltcp::phy::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};
Expand Down Expand Up @@ -58,7 +58,7 @@ 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 mut iface = InterfaceBuilder::new(device)
.ethernet_addr(ethernet_addr)
.neighbor_cache(neighbor_cache)
.ip_addrs(ip_addrs)
Expand Down
124 changes: 124 additions & 0 deletions examples/tunhttpclient.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate getopts;
extern crate rand;
extern crate url;
extern crate smoltcp;

mod utils;

use smoltcp::phy::wait as phy_wait;
use std::str::{self, FromStr};
use std::collections::BTreeMap;
use std::os::unix::io::AsRawFd;
use url::Url;
use smoltcp::wire::{Ipv4Address, Ipv6Address, IpAddress, IpCidr};
use smoltcp::iface::{NeighborCache, InterfaceBuilder, Routes};
use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
use smoltcp::time::Instant;
use smoltcp::phy::TunInterface;

fn main() {
/*
Usage:
Create tun1:
sudo ip tuntap add dev tun1 mode tun user `id -un`
sudo ip link set dev tun1 up
sudo ip addr add dev tun1 local 192.168.69.0 remote 192.168.69.1
sudo iptables -t filter -I FORWARD -i tun1 -o eth0 -j ACCEPT
sudo iptables -t filter -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
sudo iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
sudo sysctl net.ipv4.ip_forward=1
./tunhttpclient 172.217.28.238 http://google.com
You should get HTML from google (IP might change throughout history, ping to see)
*/
utils::setup_logging("");

let (mut opts, mut free) = utils::create_options();
utils::add_middleware_options(&mut opts, &mut free);
free.push("ADDRESS");
free.push("URL");

let mut matches = utils::parse_options(&opts, free);
let device = TunInterface::new("tun1").unwrap();
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");
let url = Url::parse(&matches.free[1]).expect("invalid url format");

let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; 1024]);
let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; 1024]);
let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);

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_v6_gw = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0x100);
let mut routes_storage = [None; 2];
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 = InterfaceBuilder::new(device)
.ip_addrs(ip_addrs)
.routes(routes)
.finalize();

let mut sockets = SocketSet::new(vec![]);
let tcp_handle = sockets.add(tcp_socket);

enum State { Connect, Request, Response };
let mut state = State::Connect;

loop {
let timestamp = Instant::now();
match iface.poll(&mut sockets, timestamp) {
Ok(_) => {},
Err(e) => {
debug!("poll error: {}",e);
}
}

{
let mut socket = sockets.get::<TcpSocket>(tcp_handle);

state = match state {
State::Connect if !socket.is_active() => {
debug!("connecting");
let local_port = 49152 + rand::random::<u16>() % 16384;
socket.connect((address, url.port().unwrap_or(80)), local_port).unwrap();
State::Request
}
State::Request if socket.may_send() => {
debug!("sending request");
let http_get = "GET ".to_owned() + url.path() + " HTTP/1.1\r\n";
socket.send_slice(http_get.as_ref()).expect("cannot send");
let http_host = "Host: ".to_owned() + url.host_str().unwrap() + "\r\n";
socket.send_slice(http_host.as_ref()).expect("cannot send");
socket.send_slice(b"Connection: close\r\n").expect("cannot send");
socket.send_slice(b"\r\n").expect("cannot send");
State::Response
}
State::Response if socket.can_recv() => {
socket.recv(|data| {
println!("{}", str::from_utf8(data).unwrap_or("(invalid utf8)"));
(data.len(), ())
}).unwrap();
State::Response
}
State::Response if !socket.may_recv() => {
debug!("received complete response");
break
}
_ => state
}
}

phy_wait(fd, iface.poll_delay(&sockets, timestamp)).expect("wait error");
}
}
8 changes: 4 additions & 4 deletions fuzz/fuzz_targets/tcp_headers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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,
Expand All @@ -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)
Expand Down
Loading