sentinel_driver/types/
network.rs1use bytes::{BufMut, BytesMut};
2use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
3
4use crate::error::{Error, Result};
5use crate::types::{FromSql, Oid, ToSql};
6
7const AF_INET: u8 = 2;
8const AF_INET6: u8 = 3;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12pub struct PgInet {
13 pub addr: IpAddr,
14 pub netmask: u8,
15}
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
19pub struct PgCidr {
20 pub addr: IpAddr,
21 pub netmask: u8,
22}
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
26pub struct PgMacAddr(pub [u8; 6]);
27
28fn encode_inet(addr: &IpAddr, netmask: u8, is_cidr: bool, buf: &mut BytesMut) {
31 match addr {
32 IpAddr::V4(v4) => {
33 buf.put_u8(AF_INET);
34 buf.put_u8(netmask);
35 buf.put_u8(u8::from(is_cidr));
36 buf.put_u8(4);
37 buf.put_slice(&v4.octets());
38 }
39 IpAddr::V6(v6) => {
40 buf.put_u8(AF_INET6);
41 buf.put_u8(netmask);
42 buf.put_u8(u8::from(is_cidr));
43 buf.put_u8(16);
44 buf.put_slice(&v6.octets());
45 }
46 }
47}
48
49fn decode_inet(buf: &[u8]) -> Result<(IpAddr, u8, bool)> {
50 if buf.len() < 4 {
51 return Err(Error::Decode(format!(
52 "inet: expected at least 4 bytes, got {}",
53 buf.len()
54 )));
55 }
56
57 let family = buf[0];
58 let netmask = buf[1];
59 let is_cidr = buf[2] != 0;
60 let addr_len = buf[3] as usize;
61
62 if buf.len() < 4 + addr_len {
63 return Err(Error::Decode(format!(
64 "inet: address truncated, expected {} bytes, got {}",
65 4 + addr_len,
66 buf.len()
67 )));
68 }
69
70 let addr = match family {
71 AF_INET => {
72 if addr_len != 4 {
73 return Err(Error::Decode(format!(
74 "inet: IPv4 address should be 4 bytes, got {addr_len}"
75 )));
76 }
77 IpAddr::V4(Ipv4Addr::new(buf[4], buf[5], buf[6], buf[7]))
78 }
79 AF_INET6 => {
80 if addr_len != 16 {
81 return Err(Error::Decode(format!(
82 "inet: IPv6 address should be 16 bytes, got {addr_len}"
83 )));
84 }
85 let octets: [u8; 16] = buf[4..20]
86 .try_into()
87 .map_err(|_| Error::Decode("inet: IPv6 slice error".into()))?;
88 IpAddr::V6(Ipv6Addr::from(octets))
89 }
90 _ => {
91 return Err(Error::Decode(format!(
92 "inet: unknown address family {family}"
93 )));
94 }
95 };
96
97 Ok((addr, netmask, is_cidr))
98}
99
100impl ToSql for PgInet {
103 fn oid(&self) -> Oid {
104 Oid::INET
105 }
106
107 fn to_sql(&self, buf: &mut BytesMut) -> Result<()> {
108 encode_inet(&self.addr, self.netmask, false, buf);
109 Ok(())
110 }
111}
112
113impl FromSql for PgInet {
114 fn oid() -> Oid {
115 Oid::INET
116 }
117
118 fn from_sql(buf: &[u8]) -> Result<Self> {
119 let (addr, netmask, _is_cidr) = decode_inet(buf)?;
120 Ok(PgInet { addr, netmask })
121 }
122}
123
124impl ToSql for PgCidr {
127 fn oid(&self) -> Oid {
128 Oid::CIDR
129 }
130
131 fn to_sql(&self, buf: &mut BytesMut) -> Result<()> {
132 encode_inet(&self.addr, self.netmask, true, buf);
133 Ok(())
134 }
135}
136
137impl FromSql for PgCidr {
138 fn oid() -> Oid {
139 Oid::CIDR
140 }
141
142 fn from_sql(buf: &[u8]) -> Result<Self> {
143 let (addr, netmask, _is_cidr) = decode_inet(buf)?;
144 Ok(PgCidr { addr, netmask })
145 }
146}
147
148impl ToSql for PgMacAddr {
151 fn oid(&self) -> Oid {
152 Oid::MACADDR
153 }
154
155 fn to_sql(&self, buf: &mut BytesMut) -> Result<()> {
156 buf.put_slice(&self.0);
157 Ok(())
158 }
159}
160
161impl FromSql for PgMacAddr {
162 fn oid() -> Oid {
163 Oid::MACADDR
164 }
165
166 fn from_sql(buf: &[u8]) -> Result<Self> {
167 let arr: [u8; 6] = buf
168 .try_into()
169 .map_err(|_| Error::Decode(format!("macaddr: expected 6 bytes, got {}", buf.len())))?;
170 Ok(PgMacAddr(arr))
171 }
172}
173
174#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
178pub struct PgMacAddr8(pub [u8; 8]);
179
180impl ToSql for PgMacAddr8 {
181 fn oid(&self) -> Oid {
182 Oid::MACADDR8
183 }
184
185 fn to_sql(&self, buf: &mut BytesMut) -> Result<()> {
186 buf.put_slice(&self.0);
187 Ok(())
188 }
189}
190
191impl FromSql for PgMacAddr8 {
192 fn oid() -> Oid {
193 Oid::MACADDR8
194 }
195
196 fn from_sql(buf: &[u8]) -> Result<Self> {
197 let arr: [u8; 8] = buf
198 .try_into()
199 .map_err(|_| Error::Decode(format!("macaddr8: expected 8 bytes, got {}", buf.len())))?;
200 Ok(PgMacAddr8(arr))
201 }
202}
203
204impl ToSql for IpAddr {
207 fn oid(&self) -> Oid {
208 Oid::INET
209 }
210
211 fn to_sql(&self, buf: &mut BytesMut) -> Result<()> {
212 let netmask = match self {
213 IpAddr::V4(_) => 32,
214 IpAddr::V6(_) => 128,
215 };
216 encode_inet(self, netmask, false, buf);
217 Ok(())
218 }
219}
220
221impl FromSql for IpAddr {
222 fn oid() -> Oid {
223 Oid::INET
224 }
225
226 fn from_sql(buf: &[u8]) -> Result<Self> {
227 let (addr, _netmask, _is_cidr) = decode_inet(buf)?;
228 Ok(addr)
229 }
230}