205 results for "":
Improving error handling - panics vs. proper errors
Before we move on to parsing more of our raw packets, I want to take some time to improve our error handling strategy.
Currently, the ersatz
codebase contains a mix of Result<T, E>
, and some
methods that panic, like unwrap()
and expect()
.
We also have a custom Error
enum that lets us return rawsock errors, IO errors,
or Win32 errors:
pub enum Error {
Rawsock(rawsock::Error),
IO(std::io::Error),
Win32(u32),
}
The perils of ooc arguments
The ooc language is known to be friendly to C libraries, and we have a slew of them covered on GitHub, but one common hurdle is how to correctly declare extern functions.
Argument types
For an ooc function prototype, there are many types of arguments. You can go with regular variable declarations, like so:
something: func (a: Int, b: Int, c: String)
But in this case, a
and b
have the same type, so you can also use multi-declarations
to shorten it a bit:
Consuming Ethernet frames with the nom crate
Now that we’ve found the best way to find the “default network interface”… what can we do with that interface?
Well, listen for network traffic of course!
use rawsock::open_best_library;
use std::time::Instant;
fn main() -> Result<(), Error> {
let lib = open_best_library()?;
let iface_name = format!(r#"\Device\NPF_{}"#, netinfo::default_nic_guid()?);
let iface = lib.open_interface(&iface_name)?;
println!("Listening for packets...");
// doing some low-cost logging over here
let start = Instant::now();
iface.loop_infinite_dyn(&mut |packet| {
println!(
"{:?} | received {} bytes",
start.elapsed(),
packet.len()
);
})?;
Ok(())
}
So you want to live-reload Rust
Good morning! It is still 2020, and the world is literally on fire, so I guess we could all use a distraction.
This article continues the tradition of me getting shamelessly nerd-sniped - once by Pascal about small strings, then again by a twitch viewer about Rust enum sizes.
This time, Ana was handing out free nerdsnipes, so I got in line, and mine was:
Pin and suffering
I’d like to think that my understanding of “async Rust” has increased over the past year or so. I’m 100% onboard with the basic principle: I would like to handle thousands of concurrent tasks using a handful of threads. That sounds great!
And to become proficient with async Rust, I’ve accepted a lot of things. There are blue functions and red functions, and red (async) functions are contagious.
Developing over SSH
With the previous part’s VM still running, let’s try connecting to our machine over SSH.
Network addresses, loopback and IP nets
Normally, to connect to a machine, you’d find its IP address. On Linux, a decade
ago, you would’ve used ifconfig
. Nowadays you can use ip addr
:
The loopback interface (lo
) is local, so it’s not useful to reach the box from
the outside: you can see it can be accessed over IPv4 at address 127.0.0.1 but
not just! What we’re reading here is 127.0.0.1/8, which corresponds to the range
127.0.0.1 - 127.255.255.255
The curse of strong typing
It happened when I least expected it.
Someone, somewhere (above me, presumably) made a decision. “From now on”, they declared, “all our new stuff must be written in Rust”.
I’m not sure where they got that idea from. Maybe they’ve been reading propaganda. Maybe they fell prey to some confident asshole, and convinced themselves that Rust was the answer to their problems.
Parsing and serializing ICMP packets with cookie-factory.
In the last part, we’ve finally parsed some IPv4 packets. We even found a way to filter only IPv4 packets that contain ICMP packets.
There’s one thing we haven’t done though, and that’s verify their checksum. Folks could be sending us invalid IPv4 packets and we’d be parsing them like a fool!
This series is getting quite long, so let’s jump right into it.
Day 11 (Advent of Code 2022)
It’s a new day, it’s a new advent of code puzzle.
In that one, we have to apparently cosplay as an IBM mainframe and just.. crunch them numbers. This doesn’t look fun, and I can’t think of a clever twist to make it fun, so let’s try to make it short and sweet.
Parsing
Our input looks like this:
Monkey 0:
Starting items: 79, 98
Operation: new = old * 19
Test: divisible by 23
If true: throw to monkey 2
If false: throw to monkey 3
Monkey 1:
Starting items: 54, 65, 75, 74
Operation: new = old + 6
Test: divisible by 19
If true: throw to monkey 2
If false: throw to monkey 0
(etc)
Day 16 (Advent of Code 2022)
Let’s tackle the day 16 puzzle!
Parsing
The input looks like this:
Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
Valve BB has flow rate=13; tunnels lead to valves CC, AA
Valve CC has flow rate=2; tunnels lead to valves DD, BB
Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
Valve EE has flow rate=3; tunnels lead to valves FF, DD
Valve FF has flow rate=0; tunnels lead to valves EE, GG
Valve GG has flow rate=0; tunnels lead to valves FF, HH
Valve HH has flow rate=22; tunnel leads to valve GG
Valve II has flow rate=0; tunnels lead to valves AA, JJ
Valve JJ has flow rate=21; tunnel leads to valve II