zettabgp/
util.rs

1// Copyright 2021 Vladimir Melnikov.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! This module contains some internal utilities
10
11use crate::error::BgpError;
12
13/// Gets ipv4 address from the buffer.
14pub fn decode_addrv4_from(buf: &[u8]) -> Result<std::net::Ipv4Addr, BgpError> {
15    if buf.len() < 4 {
16        return Err(BgpError::static_str("Invalid addrv4 length"));
17    }
18    Ok(std::net::Ipv4Addr::new(buf[0], buf[1], buf[2], buf[3]))
19}
20/// Stores ipv4 address into the buffer.
21pub fn encode_addrv4_to(addr: &std::net::Ipv4Addr, buf: &mut [u8]) -> Result<usize, BgpError> {
22    if buf.len() < 4 {
23        return Err(BgpError::static_str("Invalid addrv4 length"));
24    }
25    buf[0..4].clone_from_slice(&addr.octets());
26    Ok(4)
27}
28/// Gets ipv6 address from the buffer.
29pub fn decode_addrv6_from(buf: &[u8]) -> Result<std::net::Ipv6Addr, BgpError> {
30    if buf.len() < 16 {
31        return Err(BgpError::static_str("Invalid addrv6 length"));
32    }
33    Ok(std::net::Ipv6Addr::new(
34        getn_u16(&buf[0..2]),
35        getn_u16(&buf[2..4]),
36        getn_u16(&buf[4..6]),
37        getn_u16(&buf[6..8]),
38        getn_u16(&buf[8..10]),
39        getn_u16(&buf[10..12]),
40        getn_u16(&buf[12..14]),
41        getn_u16(&buf[14..16]),
42    ))
43}
44/// Stores ipv6 address into the buffer.
45pub fn encode_addrv6_to(addr: &std::net::Ipv6Addr, buf: &mut [u8]) -> Result<usize, BgpError> {
46    if buf.len() < 16 {
47        return Err(BgpError::static_str("Invalid addrv6 length"));
48    }
49    buf[0..16].clone_from_slice(&addr.octets());
50    Ok(16)
51}
52/// Gets ipv4/ipv6 address from the buffer. Address type determined by buffer length.
53pub fn decode_addr_from(buf: &[u8]) -> Result<std::net::IpAddr, BgpError> {
54    match buf.len() {
55        16 => Ok(std::net::IpAddr::V6(decode_addrv6_from(buf)?)),
56        4 => Ok(std::net::IpAddr::V4(decode_addrv4_from(buf)?)),
57        _ => Err(BgpError::static_str("Invalid addr length")),
58    }
59}
60/// Stores ipv4/ipv6 address into the buffer.
61pub fn encode_addr_to(addr: &std::net::IpAddr, buf: &mut [u8]) -> Result<usize, BgpError> {
62    match addr {
63        std::net::IpAddr::V4(a) => encode_addrv4_to(a, buf),
64        std::net::IpAddr::V6(a) => encode_addrv6_to(a, buf),
65    }
66}
67pub fn ntoh16(a: u16) -> u16 {
68    (a >> 8) | ((a & 0xff) << 8)
69}
70pub fn setn_u16(s: u16, a: &mut [u8]) {
71    a[0] = (s >> 8) as u8;
72    a[1] = (s & 0xff) as u8;
73}
74pub fn getn_u16(a: &[u8]) -> u16 {
75    (a[0] as u16) << 8 | (a[1] as u16)
76}
77pub fn getn_u32(a: &[u8]) -> u32 {
78    (a[0] as u32) << 24 | (a[1] as u32) << 16 | (a[2] as u32) << 8 | (a[3] as u32)
79}
80pub fn setn_u32(s: u32, a: &mut [u8]) {
81    a[0] = (s >> 24) as u8;
82    a[1] = ((s >> 16) & 0xff) as u8;
83    a[2] = ((s >> 8) & 0xff) as u8;
84    a[3] = (s & 0xff) as u8;
85}
86pub fn getn_u64(a: &[u8]) -> u64 {
87    ((getn_u32(a) as u64) << 32) | (getn_u32(&a[4..8]) as u64)
88}
89pub fn getn_u128(a: &[u8]) -> u128 {
90    ((getn_u64(a) as u128) << 64) | (getn_u64(&a[8..16]) as u128)
91}
92pub(crate) fn is_addpath_nlri(b: &[u8]) -> bool {
93    if b.len() < 5 {
94        false
95    } else {
96        b[0] == 0 && b[1] == 0
97    }
98}
99/// Returns BgpError::InsufficientBufferSize if slicing is out of bounds
100pub fn slice<T>(buf: &[T], start: usize, end: usize) -> Result<&[T], BgpError> {
101    if start <= end && end <= buf.len() {
102        Ok(&buf[start..end])
103    } else {
104        Err(BgpError::InsufficientBufferSize)
105    }
106}
107/// Returns BgpError::InsufficientBufferSize if slicing is out of bounds
108pub fn slice_mut<T>(buf: &mut [T], start: usize, end: usize) -> Result<&mut [T], BgpError> {
109    if start <= end && end <= buf.len() {
110        Ok(&mut buf[start..end])
111    } else {
112        Err(BgpError::InsufficientBufferSize)
113    }
114}