50 lines
1.3 KiB
Rust
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));
|
||
|
}
|
||
|
}
|
||
|
}
|