Commit Graph

204 Commits

Author SHA1 Message Date
Dan Robertson bed3d8bd4b Add Address Resolution for IPv6
Add Address Resolution via NDISC for IPv6.

Closes: #196
Approved by: whitequark
2018-05-07 23:49:56 +08:00
Dan Robertson 010e55beed Fix ICMPv6 checksum function
The ICMPv6 checksum calculation requires the pseudo header.

Closes: #196
Approved by: whitequark
2018-05-07 23:49:56 +08:00
whitequark 485b46a5e6 fn PacketMetadata::empty() → const PacketMetadata::EMPTY.
Fixes #181.
2018-03-24 03:23:37 +00:00
Dan Robertson 826ba29b72 Add has_solicited_node to EthernetInterface
- Add a function to EthernetInterface useful for determining if a
   received packet with the source address being a solicited node
   address is the solicited node address for an IPv6 address assigned
   to the interface.
 - Add SOLICITED_NODES_PREFIX to Ipv6Cidr
 - Fix some nits

Closes: #175
Approved by: whitequark
2018-03-04 03:23:12 +08:00
Astro e3e9d9d4c5 Allow broadcast/multicast traffic to UDP sockets
Closes: #173
Approved by: whitequark
2018-03-03 06:16:40 +08:00
Astro cd00d63c51 Add multicast capability to lookup_hardware_addr()
Closes: #172
Approved by: whitequark
2018-03-02 08:33:37 +08:00
whitequark 3d12690009 Use storage::PacketBuffer for implementing socket::IcmpSocket.
This substantially increases its space efficiency.
2018-02-22 12:23:35 +00:00
whitequark c474d0c32e Factor out storage::PacketBuffer from socket::UdpSocket. 2018-02-22 11:34:58 +00:00
Philipp Oppermann ed2dcaaff9 Use separate metadata and payload buffers for UDP sockets.
Co-authored-by: Dan Robertson <danlrobertson89@gmail.com>
2018-02-22 06:33:11 +00:00
Dan Robertson 9747733dd7 Use time types in socket
Use the time types (Instant and Duration) in the socket modules instead
of a simple u64.

Closes: #141
Approved by: whitequark
2018-02-16 10:44:03 +08:00
Dan Robertson e0b48caca3 Update phy mod to use new time types
Update everything but the socket types to use the new time types instead
of a basic u64

Closes: #141
Approved by: whitequark
2018-02-16 10:44:03 +08:00
Dan Robertson 1f9e14de71 Update iface and phy_wait to use new time types
Update the EthernetInterface poll functions to use Instant and Duration
instead of a simple u64 value.

Closes: #141
Approved by: whitequark
2018-02-16 10:44:02 +08:00
Dan Robertson e09e20df95 Add basic ICMPv6 reply
Add basic ICMPv6 handling

 - ICMPv6
   - Handle ICMPv6 echo requests
   - Send ICMPv6 error messages
     - When know listening UDP socket is found in process_udp
     - When the next header is not known
   - Update icmpv6 test to be more useful
 - ICMPv4
   - Handle one more case where we are sending too much data
2018-02-05 16:24:25 +00:00
whitequark 0ddd4c9001 Route broadcast packets directly.
Closes #120.
2018-01-15 11:56:14 +00:00
Dan Robertson 4a78b02fcf Add process_ipv6 to EthernetInterface
- Add `process_ipv6` to `EthernetInterface`
 - Add basic test for `process_ipv6`
 - Add `deny(unused)` if either proto-ipv4 or proto-ipv6 is enabled
 - Add `cfg`s where needed to avoid compile time errors due to the above
2018-01-15 11:54:26 +00:00
Dan Robertson b653a6e421 Fix documentation warnings.
- There are several warnings that are thrown when running `cargo doc`. Fix
  these warnings.
- Convert all module documentation to use /*! for consistency.
2018-01-05 19:38:23 +00:00
Dan Robertson 22b048c225 Ensure ICMPv4 error replies comply with size requirements
- Add MIN_MTU constants to the IP version modules.
 - Ensure that ICMPv4 error replies comply with the size requirements
   specified in RFC 1812 § 4.3.2.3.
2018-01-05 19:21:45 +00:00
whitequark 7c0bae7d36 Simplify. NFC. 2017-12-27 00:09:50 +00:00
Dan Robertson 439e0a2cc1 Add the proto-ipv4 feature. 2017-12-24 13:28:59 +00:00
whitequark 85487bf3bc EthernetInterface::set_ipv4_gateway should panic on non-unicast addrs. 2017-12-22 13:07:11 +00:00
whitequark f1a7fbe973 Split `poll_at`/`poll_delay` out of `poll`.
The previous model was flawed. Consider the following case:
  * The main loop looks as follows (pseudocode):
      loop {
        let _ = (tcp:1234).read_all()
        wait(iface.poll())
      }
  * The remote end is continuously transmitting data and at some
    point fills the window of (tcp:1234), stopping the transmission
    afterwards.
  * The local end processes the packets and, as a part of egress
    routine, emits an ACK. That also updates the window, and
    the socket's poll_at() routine returns None, since there is
    nothing to transmit or retransmit.
  * The local end now waits indefinitely even though it can start
    processing the data in the socket buffers right now.
2017-12-22 12:59:52 +00:00
whitequark 8b6050f711 Clean up our feature story and more aggressively test features. 2017-12-22 08:54:58 +00:00
whitequark bf53b73e09 Fix accidental conversion of a slice to owned.
This broke #![no_std] builds.
2017-12-18 15:03:38 +00:00
whitequark 946376897e Make EthernetInterfaceBuilder::ip_addrs optional.
It's perfectly reasonable to have an interface with no addresses
assigned to it.
2017-12-18 13:53:27 +00:00
Dan Robertson c5c2264cdc Use hop limit instead of ttl
Use hop limit instead of ttl for method and member names.
2017-12-18 13:47:34 +00:00
Dan Robertson ee60efefd3 Add Ipv6Repr and Ipv6Packet to wire
- Add the Ipv6Repr and Ipv6Packet structures to the wire module
 - Add basic tests for the new structures
 - Update IpRepr to include the Ipv6 variant
2017-12-18 13:47:34 +00:00
Dan Robertson 4a98190f9b Replace EthernetInterface::new with EthernetInterfaceBuilder. 2017-12-18 13:29:29 +00:00
whitequark 05677dbd76 Fix 14185a16. 2017-12-18 11:42:55 +00:00
whitequark 19f52bd46c Do not fill neighbor cache with IPs not on the same network as us.
This is pointless (`route` doesn't even check the cache in that case)
and wastes cache space.
2017-12-18 11:06:26 +00:00
whitequark 8dd9bdeaad Trace neighbor discovery status on a per-socket basis.
This avoids delaying the first packets for new neighbors by
(at least) the ARP cache silence time, or potentially even
indefinitely.
2017-12-18 11:06:24 +00:00
Dan Robertson 888b098dca Process the Icmpv4Repr in IcmpSocket::process
- Use the Icmpv4Repr in IcmpSocket::process instead of the raw payload.
 - Update the IcmpSocket tests.
2017-12-09 00:10:09 +00:00
whitequark 26b8052ee9 Make packet dumps emitted for broken packets more useful.
Before this commit, only the outermost frame (the Ethernet one)
would be shown, which is really no help at all.
2017-12-08 07:11:08 +00:00
Jeremy Soller 8604eaa8f9 Allow receiving broadcast packets via UDP sockets. 2017-11-23 07:01:35 +00:00
Dan Robertson 308afc5a25 Remove debug println in test_evict
The println's surrounding the final cache fill in test_evict that causes
PADDR_B to be evicted are not needed.
2017-11-22 08:03:39 +00:00
whitequark ff530020dd Style. NFC. 2017-11-22 07:44:03 +00:00
whitequark 98a3ec8c3a Limit the rate at which sockets will request neighbor discovery.
The rate of emission of neighbor discovery packets is already
limited at the level of the entire neighbor cache, but poll()
would uselessly spin until the answer arrives (if ever).
2017-11-22 07:20:31 +00:00
whitequark 715aa4b217 Add a missing feature check. 2017-11-21 12:02:25 +00:00
whitequark 52a6e27206 Implement eviction in neighbor cache for fixed storage size. 2017-11-21 11:53:26 +00:00
whitequark 29a338228d Fix a broken macro invocation. 2017-11-21 11:06:53 +00:00
whitequark eaa50d0003 Rewrite the ARP cache to allow for flood protection and expiration. 2017-11-21 10:53:55 +00:00
Egor Karavaev 1e809daf7a Make `Error::Unaddressable` ignored for ICMP sockets as well. 2017-11-13 14:16:03 +00:00
Egor Karavaev eb7d0e346e ICMP sockets don't end ICMP packets processing. 2017-11-13 14:16:03 +00:00
whitequark 19373c58c8 Style. NFCI. 2017-11-09 02:07:24 +00:00
Dan Robertson adb5014780 Add ICMP sockets
- Add support for ICMP sockets
 - Add tests for ICMP sockets
 - Rename proto-<type> features to socket-<type>
 - Update documentation
2017-11-09 00:08:24 +00:00
Philipp Oppermann c3e07dad9a Store plain DeviceT instead of Managed<_> in EthernetInterface 2017-11-08 09:34:35 +00:00
whitequark d9fa7f6bc6 Rename proto-* features back to socket-*.
A proto-* feature does not make sense for ICMP, where the protocol
is always enabled, but sockets, not.
2017-11-06 09:51:03 +00:00
whitequark 7039ec8b04 Rename a few tests. NFC. 2017-11-04 02:42:51 +00:00
Philipp Oppermann 6a8e21cec0 Redesign the phy::Device trait to avoid Drop impls. 2017-11-03 23:15:07 +00:00
Dan Robertson b64257812b Do not send ICMPv4 responses to broadcasts
- Do not send ICMPv4 responses for packets with a broadcast destination
   address.
   - Do not send DstUnreachable with ProtoUnreachable on receipt of a
     packet with an unknown protocol with a non-unicast destination
     address.
   - Do not send DstUnreachable with PortUnreachable on receipt of a
     UDP packet when no sockets are listening on the destination port
     and the destination address is a non-unicast address.
 - Send the correct amount of the original datagram when sending Destination
   Unreachable error responses.
   - Do not assume that a ip datagram has a payload when sending a proto
     unreachable ICMPv4 error response.
 - Add tests to iface tests.
   - Ensure ICMP error responses are correctly formed when the
     datagram has no payload.
   - Ensure ICMP error responses are correctly handled for UDP packets
     when no socket is listening on the destination port.
   - Ensure the correct amount of the original payload is returned in
     Destination Unreachable responses.
2017-11-01 06:34:10 +00:00
Dan Robertson 1cafcfc19f Tests: Add basic interface tests
- Add tests for the following
   - ICMP error responses are not sent in response to broadcast requests
   - ARP requests are responded to and inserted into the cache
   - ARP requests for someone else are not responded to, but the sender
     is still inserted in the cache
2017-10-28 19:33:01 +00:00
whitequark a9a00baa49 Rename Cargo features: socket-* → proto-*. 2017-10-25 00:20:40 +00:00
whitequark a7e6a1b5ae Simplify. NFC. 2017-10-24 23:12:55 +00:00
Dan Robertson eef65d2676 Implement set_ttl for Tcp and Udp sockets
- Add the ttl member to the IpRepr
 - Add the ttl member along with setters and getters to the tcp and udp
   socket types
 - Add unit tests for the new set_ttl parameter
 - Update usage of IpRepr to include the ttl value
2017-10-24 23:02:18 +00:00
whitequark 4f689be81b Dump malformed ingress packets at DEBUG log level. 2017-10-24 20:37:52 +00:00
Egor Karavaev 19b1b764ed Implement a SocketRef smart pointer to detect state changes. 2017-10-05 03:44:20 +00:00
whitequark eb33cdcf68 Fix a typo. 2017-10-04 01:54:39 +00:00
whitequark b2cfb94b48 Explain the return value of poll(). 2017-10-03 20:41:45 +00:00
whitequark bf9584555c Drop the pretense that anyone cares about non-IP over Ethernet.
To be precise, I'm talking about IPX, AppleTalk and DECnet here,
not things like PPPoE, ATAoE, FCoE, or PTP, which make sense
to implement on top of EthernetInterface but do not work on
the same level on top of it as IP.
2017-10-03 15:17:29 +00:00
Egor Karavaev 5be76b8dc1 Add support for IPv4 default gateway. 2017-10-03 15:17:29 +00:00
whitequark 72481c2661 Formatting. NFC. 2017-10-03 14:27:01 +00:00
Steffen Butzer 61cb64406d support hardware based checksum settings in during packet send/recv
- makes sure the checksum is zeroed when not emitted by software
  (This is required by some implementations such as STM32 to work properly)
2017-10-02 21:40:08 +00:00
Steffen Butzer f9093d15aa phy: introduce hardware based checksum settings, rename DeviceLimits
this contains a rename of occurrences of
DeviceLimits -> DeviceCapabilities.
2017-10-02 21:40:08 +00:00
whitequark dd0f4b706a Enforce some lints. 2017-09-25 00:46:53 +00:00
whitequark 4826d37c45 Allow disabling any of: raw, TCP or UDP sockets. 2017-09-25 00:20:22 +00:00
Egor Karavaev 0e88617b82 Uncomment associated constants. 2017-09-24 23:25:18 +00:00
whitequark a1b2605af7 Revert "Keep dispatching packets from a socket as long as there are any."
This reverts commit 51b2f18d1165bf7257de8894df101299cc93b094.

There's no throughput difference so far as I could measure, but
this greatly increases worst-case latency. At some later point
we could perhaps pass a deadline to the poll function, but for now
reverting this is simple enough.
2017-09-22 18:09:18 +00:00
whitequark 05a480575c Keep dispatching packets from a socket as long as there are any.
Typically, the poll function is used as a part of a larger RTOS.
If we only dispatch one packet per socket per poll() call,
then we have to wait for a complete scheduler roundtrip,
which is potentially a lot of time, and as a result we are
not filling the peer's window efficiently.
2017-09-22 17:55:49 +00:00
Egor Karavaev 8404fe908c Factor out TcpSocket::accepts. 2017-09-08 00:57:42 +00:00
Egor Karavaev 02b699e18c Factor out UdpSocket::accepts. 2017-09-08 00:57:19 +00:00
Egor Karavaev b4d6a53e34 Factor out RawSocket::accepts. 2017-09-08 00:56:42 +00:00
whitequark 8876d71802 According to RFC 1122, unsupported IP options MUST be ignored. 2017-09-01 19:31:09 +00:00
whitequark 7db21529e5 An unaddressable egress packet should not be a reportable error. 2017-09-01 10:30:56 +00:00
whitequark b585fbd368 Exhaustion of transmit buffers should not be a reportable error. 2017-08-31 16:27:50 +00:00
whitequark c2bc20e9bf Move the TCP receive window clamping hack downwards in stack.
Otherwise, our response ACKs did not get the clamping treatment,
and severe packet loss resulted.

Also, explain why it's needed and how it works.
2017-08-30 14:00:14 +00:00
whitequark 5a066fbc6c Return from EthernetInterface::poll() on errors, don't swallow them.
We still print them into our debug log though, because it has more
context; the caller may opt to ignore any poll errors and only
use the smoltcp debug log as a, well, debugging aid, or it could
print user-visible warnings to alert the user to unusual network
conditions.
2017-08-30 10:20:11 +00:00
whitequark 996389d653 Compute soft deadline in poll() and use nonblocking sockets.
Before this commit, anything that touched RawSocket or TapInterface
worked partly by accident and partly because of a horrible crutch
that resulted in massive latencies as well as inevitable packet loss
every time an ARP request had to be issued. Also, there was no way
to use poll() other than by continuously calling it in a busy loop.

After this commit, poll() indicates when the earliest timer expires,
and so the caller can sleep until that moment (or until packets
arrive).

Note that there is a subtle problem remaining: every time poll()
is called, every socket with a pending outbound packet whose
IP address doesn't correspond to a MAC address will send a new
ARP request, resulting in potentially a whole lot of such requests.
ARP rate limiting is a separate topic though.
2017-08-29 19:47:11 +00:00
whitequark cdf236412f Clarify a function name. 2017-08-28 12:45:33 +00:00
whitequark 695c61fd05 Break up the EthernetInterface::dispatch macro atrocity into functions.
There wasn't any real reason for it to be a macro, it was ugly
and unreadable, and it resulted in combinatorial bloat when compiled.
2017-08-28 05:49:56 +00:00
whitequark 34db543cac Factor out packet parsing from Socket::process.
Not only is it incredibly wasteful, but this information is
in any case already necessary within the EthernetInterface::process_*
methods.
2017-08-28 05:48:16 +00:00
whitequark 379bc60924 Get rid of unused arguments in Socket::{process,dispatch}.
I've left those "for consistency" but it just implies data
dependencies where there are none, and bloats signatures.
2017-08-28 04:14:25 +00:00
whitequark 760174048d Get rid of IpPayload and indirection in Socket::dispatch.
This was just completely pointless, and only served to obfuscate
the data path and make testing harder.
2017-08-28 03:56:34 +00:00
whitequark bab5c0b7aa Unify EthernetInterface::{send_response,emit} transmit paths. 2017-08-28 02:11:04 +00:00
whitequark 1d01189278 Use FnOnce, not FnMut, in Socket::dispatch() functions.
There was never any reason to use FnMut and this significantly
simplifies the job of the borrow checker.
2017-08-28 00:59:33 +00:00
whitequark 5b2de544c8 Radically simplify and optimize TCP packet dispatch.
This commit completely reworks packet dispatch in TCP sockets,
and brings significant improvements to processing as well.

In particular:
  * Challenge ACKs now do not reset retransmit timer; instead,
    TcpSocket::process directly returns a TcpRepr without altering
    any internal state at all.
  * Retransmit and close (aka TIME-WAIT) timers are unified
    and restructured into a enum that actually matches semantics
    of the timers.
  * If a packet cannot be emitted, no internal state is changed.
  * The dispatch of RST packets in case of connection abort
    is brought in line with dispatch of all other packets.
  * Packet dispatch now follows a series of steps with clean
    separation of concerns, like packet processing:
      1. If we should retransmit, update state to assume that
         all in-flight packets are lost.
      2. Prepare the packet that would be sent next, considering
         the in-flight packets, if any.
      3. Check if the packet contains anything new, or it's the same
         as the one already in flight. If it is, bail.
      4. Finalize and try to actually transmit the packet.
         If we can't do that, bail.
      5. Update the internal state to reflect that the packet
         we've just sent is in flight.
2017-08-25 03:53:31 +00:00
whitequark 9d0084171f Rework responses to TCP packets and factor in RST replies to TcpSocket. 2017-08-22 22:32:05 +00:00
whitequark 7c9a072dd2 Fix a typo that broke ARP replies. 2017-08-22 07:44:43 +00:00
whitequark 925e13b61a Simplify ARP handling code in EthernetInterface. 2017-08-21 07:28:38 +00:00
whitequark be1038f382 Assert that the transmit frame returned by driver has right length.
We checked for frames too short before, but frames too long are
troublesome too, since e.g. TCP and UDP do not carry an explicit
payload length in their headers.
2017-08-06 15:09:55 +00:00
whitequark 8d8a4ea583 Get rid of Result<_, ()>.
The use of this type has several drawbacks:
  * It does not allow distinguishing between different error
    conditions. In fact, we wrongly conflated some of them
    before this commit.
  * It does not allow propagation via ? and requires manual use
    of map_err, which is especially tiresome for downstream code.
  * It prevents us from expanding the set of error conditions
    even if right now we have only one.
  * It prevents us from blanket using Result<T> everywhere
    (a nitpick at most).

Instead, use Result<T, Error> everywhere, and differentiate error
conditions where applicable.
2017-07-27 13:55:47 +00:00
whitequark d35fd9940e Fix ICMP error returned by EthernetInterface for unknown IP protocols. 2017-07-24 07:07:43 +00:00
whitequark 936bd44f8f Clean up socket error handling in EthernetInterface. 2017-07-24 07:01:35 +00:00
whitequark c8d714cd87 Reorganize EthernetInterface impl. NFC. 2017-07-24 06:56:06 +00:00
whitequark b97cacd521 Inject the current timestamp into Device::{transmit,receive}.
Various parts of smoltcp require an arrow of time; a monotonically
increasing timestamp. Most obviously this is TCP sockets, but
the tracer and the pcap writer devices also benefit from having
timestamps. There are a few ways this could be implemented:
  1. using a static Cell, global for the entire smoltcp crate;
  2. using a static method on Device;
  3. using an instance method on Device;
  4. passing the current timestamp into *Interface::poll.

The first two options are undesirable because they create a notion
of global clock, and interfere e.g. with mocking.
The third option is undesirable because not all devices are
inherently tied to a particular clock, e.g. a loopback device isn't.

Therefore, the timestamp is injected into both sockets and devices
through the *Interface::poll method.
2017-07-23 09:48:14 +00:00
whitequark 6ad8fea31f Fix a typo in 5c3fc493. 2017-06-27 21:51:56 +00:00
whitequark 04bd8a0051 Discard packets with non-unicast source addresses at IP level.
This is required by RFC 1122 and helps avoid "broadcast storms".
2017-06-26 17:01:23 +00:00
Egor Karavaev 4f2804e104 Don't reply to a TCP RST packet with another TCP RST packet. 2017-06-26 05:48:30 +00:00
Egor Karavaev 1e8cd1a65f Refactor EthernetInterface::poll.
Also, after this commit, we stop iterating over TCP/UDP sockets after
finding one that accepts the packet.
2017-06-26 05:48:27 +00:00
whitequark b86d22701d Expose PSH flag in TcpRepr. 2017-06-25 08:20:25 +00:00
whitequark 74823b0dff try! → ? 2017-06-24 16:34:32 +00:00
whitequark 8b27330c8b Do not attempt to validate length of packets being emitted.
This is a form of an uninitialized read bug; although safe it caused
panics. In short, transmit buffers received from the network stack
should be considered uninitialized (in practice they will often
contain previously transmitted packets or parts thereof). Wrapping
them with the only method we had (e.g. Ipv4Packet) treated the buffer
as if it contained a valid incoming packet, which can easily fail
with Error::Truncated.

This commit splits every `fn new(buffer: T) -> Result<Self, Error>`
method on a `Packet` into three smaller ones:
  * `fn check_len(&self) -> Result<(), Error>`, purely a validator;
  * `fn new(T) -> Self`, purely a wrapper;
  * `fn new_checked(T) -> Result<Self, Error>`, a validating wrapper.

This makes it easy to process ingress packets (using `new_checked`),
egress packets (using `new`), and, if needed, maintain the invariants
at any point during packet construction (using `check_len`).

Fixes #17.
2017-06-24 11:42:32 +00:00