use rocket::{ http::Status, request::{FromRequest, Outcome, Request}, }; use std::net::IpAddr; use crate::types::MacAddr; pub struct ClientEUI64 { pub mac_address: MacAddr, } #[derive(Debug)] pub enum EUI64Error { NotIPV6, NotEUI64, InvalidMACAddr, } #[rocket::async_trait] impl<'r> FromRequest<'r> for ClientEUI64 { type Error = EUI64Error; async fn from_request(request: &'r Request<'_>) -> Outcome { let client_ip = match request.client_ip() { Some(IpAddr::V6(ip)) => ip, _ => return Outcome::Failure((Status::Forbidden, EUI64Error::NotIPV6)), }; if client_ip.segments()[0] == 0xfe80 { let octets = client_ip.octets(); let mut mac = [&octets[8..11], &octets[13..]].concat(); mac[0] ^= 0x2; let mac: [u8; 6] = match mac.try_into() { Ok(t) => t, Err(_) => { return Outcome::Failure(( Status::InternalServerError, EUI64Error::InvalidMACAddr, )) } }; return Outcome::Success(ClientEUI64 { mac_address: MacAddr(mac), }); } else { return Outcome::Failure((Status::Forbidden, EUI64Error::NotEUI64)); } } }