minccino/src/llv6.rs
2022-09-23 22:39:17 -07:00

50 lines
1.3 KiB
Rust

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<ClientEUI64, EUI64Error> {
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));
}
}
}