parsers.rs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. #![cfg_attr(
  2. not(all(feature = "proto-ipv6", feature = "proto-ipv4")),
  3. allow(dead_code)
  4. )]
  5. use core::result;
  6. use core::str::FromStr;
  7. #[cfg(feature = "medium-ethernet")]
  8. use crate::wire::EthernetAddress;
  9. use crate::wire::{IpAddress, IpCidr, IpEndpoint};
  10. #[cfg(feature = "proto-ipv4")]
  11. use crate::wire::{Ipv4Address, Ipv4Cidr};
  12. #[cfg(feature = "proto-ipv6")]
  13. use crate::wire::{Ipv6Address, Ipv6Cidr};
  14. type Result<T> = result::Result<T, ()>;
  15. struct Parser<'a> {
  16. data: &'a [u8],
  17. pos: usize,
  18. }
  19. impl<'a> Parser<'a> {
  20. fn new(data: &'a str) -> Parser<'a> {
  21. Parser {
  22. data: data.as_bytes(),
  23. pos: 0,
  24. }
  25. }
  26. fn lookahead_char(&self, ch: u8) -> bool {
  27. if self.pos < self.data.len() {
  28. self.data[self.pos] == ch
  29. } else {
  30. false
  31. }
  32. }
  33. fn advance(&mut self) -> Result<u8> {
  34. match self.data.get(self.pos) {
  35. Some(&chr) => {
  36. self.pos += 1;
  37. Ok(chr)
  38. }
  39. None => Err(()),
  40. }
  41. }
  42. fn try_do<F, T>(&mut self, f: F) -> Option<T>
  43. where
  44. F: FnOnce(&mut Parser<'a>) -> Result<T>,
  45. {
  46. let pos = self.pos;
  47. match f(self) {
  48. Ok(res) => Some(res),
  49. Err(()) => {
  50. self.pos = pos;
  51. None
  52. }
  53. }
  54. }
  55. fn accept_eof(&mut self) -> Result<()> {
  56. if self.data.len() == self.pos {
  57. Ok(())
  58. } else {
  59. Err(())
  60. }
  61. }
  62. fn until_eof<F, T>(&mut self, f: F) -> Result<T>
  63. where
  64. F: FnOnce(&mut Parser<'a>) -> Result<T>,
  65. {
  66. let res = f(self)?;
  67. self.accept_eof()?;
  68. Ok(res)
  69. }
  70. fn accept_char(&mut self, chr: u8) -> Result<()> {
  71. if self.advance()? == chr {
  72. Ok(())
  73. } else {
  74. Err(())
  75. }
  76. }
  77. fn accept_str(&mut self, string: &[u8]) -> Result<()> {
  78. for byte in string.iter() {
  79. self.accept_char(*byte)?;
  80. }
  81. Ok(())
  82. }
  83. fn accept_digit(&mut self, hex: bool) -> Result<u8> {
  84. let digit = self.advance()?;
  85. if (b'0'..=b'9').contains(&digit) {
  86. Ok(digit - b'0')
  87. } else if hex && (b'a'..=b'f').contains(&digit) {
  88. Ok(digit - b'a' + 10)
  89. } else if hex && (b'A'..=b'F').contains(&digit) {
  90. Ok(digit - b'A' + 10)
  91. } else {
  92. Err(())
  93. }
  94. }
  95. fn accept_number(&mut self, max_digits: usize, max_value: u32, hex: bool) -> Result<u32> {
  96. let mut value = self.accept_digit(hex)? as u32;
  97. for _ in 1..max_digits {
  98. match self.try_do(|p| p.accept_digit(hex)) {
  99. Some(digit) => {
  100. value *= if hex { 16 } else { 10 };
  101. value += digit as u32;
  102. }
  103. None => break,
  104. }
  105. }
  106. if value < max_value {
  107. Ok(value)
  108. } else {
  109. Err(())
  110. }
  111. }
  112. #[cfg(feature = "medium-ethernet")]
  113. fn accept_mac_joined_with(&mut self, separator: u8) -> Result<EthernetAddress> {
  114. let mut octets = [0u8; 6];
  115. for (n, octet) in octets.iter_mut().enumerate() {
  116. *octet = self.accept_number(2, 0x100, true)? as u8;
  117. if n != 5 {
  118. self.accept_char(separator)?;
  119. }
  120. }
  121. Ok(EthernetAddress(octets))
  122. }
  123. #[cfg(feature = "medium-ethernet")]
  124. fn accept_mac(&mut self) -> Result<EthernetAddress> {
  125. if let Some(mac) = self.try_do(|p| p.accept_mac_joined_with(b'-')) {
  126. return Ok(mac);
  127. }
  128. if let Some(mac) = self.try_do(|p| p.accept_mac_joined_with(b':')) {
  129. return Ok(mac);
  130. }
  131. Err(())
  132. }
  133. #[cfg(feature = "proto-ipv6")]
  134. fn accept_ipv4_mapped_ipv6_part(&mut self, parts: &mut [u16], idx: &mut usize) -> Result<()> {
  135. let octets = self.accept_ipv4_octets()?;
  136. parts[*idx] = ((octets[0] as u16) << 8) | (octets[1] as u16);
  137. *idx += 1;
  138. parts[*idx] = ((octets[2] as u16) << 8) | (octets[3] as u16);
  139. *idx += 1;
  140. Ok(())
  141. }
  142. #[cfg(feature = "proto-ipv6")]
  143. fn accept_ipv6_part(
  144. &mut self,
  145. (head, tail): (&mut [u16; 8], &mut [u16; 6]),
  146. (head_idx, tail_idx): (&mut usize, &mut usize),
  147. mut use_tail: bool,
  148. is_cidr: bool,
  149. ) -> Result<()> {
  150. let double_colon = match self.try_do(|p| p.accept_str(b"::")) {
  151. Some(_) if !use_tail && *head_idx < 7 => {
  152. // Found a double colon. Start filling out the
  153. // tail and set the double colon flag in case
  154. // this is the last character we can parse.
  155. use_tail = true;
  156. true
  157. }
  158. Some(_) => {
  159. // This is a bad address. Only one double colon is
  160. // allowed and an address is only 128 bits.
  161. return Err(());
  162. }
  163. None => {
  164. if *head_idx != 0 || use_tail && *tail_idx != 0 {
  165. // If this is not the first number or the position following
  166. // a double colon, we expect there to be a single colon.
  167. self.accept_char(b':')?;
  168. }
  169. false
  170. }
  171. };
  172. match self.try_do(|p| p.accept_number(4, 0x10000, true)) {
  173. Some(part) if !use_tail && *head_idx < 8 => {
  174. // Valid u16 to be added to the address
  175. head[*head_idx] = part as u16;
  176. *head_idx += 1;
  177. if *head_idx == 6 && head[0..*head_idx] == [0, 0, 0, 0, 0, 0xffff] {
  178. self.try_do(|p| {
  179. p.accept_char(b':')?;
  180. p.accept_ipv4_mapped_ipv6_part(head, head_idx)
  181. });
  182. }
  183. Ok(())
  184. }
  185. Some(part) if *tail_idx < 6 => {
  186. // Valid u16 to be added to the address
  187. tail[*tail_idx] = part as u16;
  188. *tail_idx += 1;
  189. if *tail_idx == 1 && tail[0] == 0xffff && head[0..8] == [0, 0, 0, 0, 0, 0, 0, 0] {
  190. self.try_do(|p| {
  191. p.accept_char(b':')?;
  192. p.accept_ipv4_mapped_ipv6_part(tail, tail_idx)
  193. });
  194. }
  195. Ok(())
  196. }
  197. Some(_) => {
  198. // Tail or head section is too long
  199. Err(())
  200. }
  201. None if double_colon && (is_cidr || self.pos == self.data.len()) => {
  202. // The address ends with "::". E.g. 1234:: or ::
  203. Ok(())
  204. }
  205. None => {
  206. // Invalid address
  207. Err(())
  208. }
  209. }?;
  210. if *head_idx + *tail_idx > 8 {
  211. // The head and tail indexes add up to a bad address length.
  212. Err(())
  213. } else if !self.lookahead_char(b':') {
  214. if *head_idx < 8 && !use_tail {
  215. // There was no double colon found, and the head is too short
  216. return Err(());
  217. }
  218. Ok(())
  219. } else {
  220. // Continue recursing
  221. self.accept_ipv6_part((head, tail), (head_idx, tail_idx), use_tail, is_cidr)
  222. }
  223. }
  224. #[cfg(feature = "proto-ipv6")]
  225. fn accept_ipv6(&mut self, is_cidr: bool) -> Result<Ipv6Address> {
  226. // IPv6 addresses may contain a "::" to indicate a series of
  227. // 16 bit sections that evaluate to 0. E.g.
  228. //
  229. // fe80:0000:0000:0000:0000:0000:0000:0001
  230. //
  231. // May be written as
  232. //
  233. // fe80::1
  234. //
  235. // As a result, we need to find the first section of colon
  236. // delimited u16's before a possible "::", then the
  237. // possible second section after the "::", and finally
  238. // combine the second optional section to the end of the
  239. // final address.
  240. //
  241. // See https://tools.ietf.org/html/rfc4291#section-2.2
  242. // for details.
  243. let (mut addr, mut tail) = ([0u16; 8], [0u16; 6]);
  244. let (mut head_idx, mut tail_idx) = (0, 0);
  245. self.accept_ipv6_part(
  246. (&mut addr, &mut tail),
  247. (&mut head_idx, &mut tail_idx),
  248. false,
  249. is_cidr,
  250. )?;
  251. // We need to copy the tail portion (the portion following the "::") to the
  252. // end of the address.
  253. addr[8 - tail_idx..].copy_from_slice(&tail[..tail_idx]);
  254. Ok(Ipv6Address::from_parts(&addr))
  255. }
  256. fn accept_ipv4_octets(&mut self) -> Result<[u8; 4]> {
  257. let mut octets = [0u8; 4];
  258. for (n, octet) in octets.iter_mut().enumerate() {
  259. *octet = self.accept_number(3, 0x100, false)? as u8;
  260. if n != 3 {
  261. self.accept_char(b'.')?;
  262. }
  263. }
  264. Ok(octets)
  265. }
  266. #[cfg(feature = "proto-ipv4")]
  267. fn accept_ipv4(&mut self) -> Result<Ipv4Address> {
  268. let octets = self.accept_ipv4_octets()?;
  269. Ok(Ipv4Address(octets))
  270. }
  271. fn accept_ip(&mut self) -> Result<IpAddress> {
  272. #[cfg(feature = "proto-ipv4")]
  273. #[allow(clippy::single_match)]
  274. match self.try_do(|p| p.accept_ipv4()) {
  275. Some(ipv4) => return Ok(IpAddress::Ipv4(ipv4)),
  276. None => (),
  277. }
  278. #[cfg(feature = "proto-ipv6")]
  279. #[allow(clippy::single_match)]
  280. match self.try_do(|p| p.accept_ipv6(false)) {
  281. Some(ipv6) => return Ok(IpAddress::Ipv6(ipv6)),
  282. None => (),
  283. }
  284. Err(())
  285. }
  286. #[cfg(feature = "proto-ipv4")]
  287. fn accept_ipv4_endpoint(&mut self) -> Result<IpEndpoint> {
  288. let ip = self.accept_ipv4()?;
  289. let port = if self.accept_eof().is_ok() {
  290. 0
  291. } else {
  292. self.accept_char(b':')?;
  293. self.accept_number(5, 65535, false)?
  294. };
  295. Ok(IpEndpoint {
  296. addr: IpAddress::Ipv4(ip),
  297. port: port as u16,
  298. })
  299. }
  300. #[cfg(feature = "proto-ipv6")]
  301. fn accept_ipv6_endpoint(&mut self) -> Result<IpEndpoint> {
  302. if self.lookahead_char(b'[') {
  303. self.accept_char(b'[')?;
  304. let ip = self.accept_ipv6(false)?;
  305. self.accept_char(b']')?;
  306. self.accept_char(b':')?;
  307. let port = self.accept_number(5, 65535, false)?;
  308. Ok(IpEndpoint {
  309. addr: IpAddress::Ipv6(ip),
  310. port: port as u16,
  311. })
  312. } else {
  313. let ip = self.accept_ipv6(false)?;
  314. Ok(IpEndpoint {
  315. addr: IpAddress::Ipv6(ip),
  316. port: 0,
  317. })
  318. }
  319. }
  320. fn accept_ip_endpoint(&mut self) -> Result<IpEndpoint> {
  321. #[cfg(feature = "proto-ipv4")]
  322. #[allow(clippy::single_match)]
  323. match self.try_do(|p| p.accept_ipv4_endpoint()) {
  324. Some(ipv4) => return Ok(ipv4),
  325. None => (),
  326. }
  327. #[cfg(feature = "proto-ipv6")]
  328. #[allow(clippy::single_match)]
  329. match self.try_do(|p| p.accept_ipv6_endpoint()) {
  330. Some(ipv6) => return Ok(ipv6),
  331. None => (),
  332. }
  333. Err(())
  334. }
  335. }
  336. #[cfg(feature = "medium-ethernet")]
  337. impl FromStr for EthernetAddress {
  338. type Err = ();
  339. /// Parse a string representation of an Ethernet address.
  340. fn from_str(s: &str) -> Result<EthernetAddress> {
  341. Parser::new(s).until_eof(|p| p.accept_mac())
  342. }
  343. }
  344. #[cfg(feature = "proto-ipv4")]
  345. impl FromStr for Ipv4Address {
  346. type Err = ();
  347. /// Parse a string representation of an IPv4 address.
  348. fn from_str(s: &str) -> Result<Ipv4Address> {
  349. Parser::new(s).until_eof(|p| p.accept_ipv4())
  350. }
  351. }
  352. #[cfg(feature = "proto-ipv6")]
  353. impl FromStr for Ipv6Address {
  354. type Err = ();
  355. /// Parse a string representation of an IPv6 address.
  356. fn from_str(s: &str) -> Result<Ipv6Address> {
  357. Parser::new(s).until_eof(|p| p.accept_ipv6(false))
  358. }
  359. }
  360. impl FromStr for IpAddress {
  361. type Err = ();
  362. /// Parse a string representation of an IP address.
  363. fn from_str(s: &str) -> Result<IpAddress> {
  364. Parser::new(s).until_eof(|p| p.accept_ip())
  365. }
  366. }
  367. #[cfg(feature = "proto-ipv4")]
  368. impl FromStr for Ipv4Cidr {
  369. type Err = ();
  370. /// Parse a string representation of an IPv4 CIDR.
  371. fn from_str(s: &str) -> Result<Ipv4Cidr> {
  372. Parser::new(s).until_eof(|p| {
  373. let ip = p.accept_ipv4()?;
  374. p.accept_char(b'/')?;
  375. let prefix_len = p.accept_number(2, 33, false)? as u8;
  376. Ok(Ipv4Cidr::new(ip, prefix_len))
  377. })
  378. }
  379. }
  380. #[cfg(feature = "proto-ipv6")]
  381. impl FromStr for Ipv6Cidr {
  382. type Err = ();
  383. /// Parse a string representation of an IPv6 CIDR.
  384. fn from_str(s: &str) -> Result<Ipv6Cidr> {
  385. // https://tools.ietf.org/html/rfc4291#section-2.3
  386. Parser::new(s).until_eof(|p| {
  387. let ip = p.accept_ipv6(true)?;
  388. p.accept_char(b'/')?;
  389. let prefix_len = p.accept_number(3, 129, false)? as u8;
  390. Ok(Ipv6Cidr::new(ip, prefix_len))
  391. })
  392. }
  393. }
  394. impl FromStr for IpCidr {
  395. type Err = ();
  396. /// Parse a string representation of an IP CIDR.
  397. fn from_str(s: &str) -> Result<IpCidr> {
  398. #[cfg(feature = "proto-ipv4")]
  399. #[allow(clippy::single_match)]
  400. match Ipv4Cidr::from_str(s) {
  401. Ok(cidr) => return Ok(IpCidr::Ipv4(cidr)),
  402. Err(_) => (),
  403. }
  404. #[cfg(feature = "proto-ipv6")]
  405. #[allow(clippy::single_match)]
  406. match Ipv6Cidr::from_str(s) {
  407. Ok(cidr) => return Ok(IpCidr::Ipv6(cidr)),
  408. Err(_) => (),
  409. }
  410. Err(())
  411. }
  412. }
  413. impl FromStr for IpEndpoint {
  414. type Err = ();
  415. fn from_str(s: &str) -> Result<IpEndpoint> {
  416. Parser::new(s).until_eof(|p| p.accept_ip_endpoint())
  417. }
  418. }
  419. #[cfg(test)]
  420. mod test {
  421. use super::*;
  422. macro_rules! check_cidr_test_array {
  423. ($tests:expr, $from_str:path, $variant:path) => {
  424. for &(s, cidr) in &$tests {
  425. assert_eq!($from_str(s), cidr);
  426. assert_eq!(IpCidr::from_str(s), cidr.map($variant));
  427. if let Ok(cidr) = cidr {
  428. assert_eq!($from_str(&format!("{}", cidr)), Ok(cidr));
  429. assert_eq!(IpCidr::from_str(&format!("{}", cidr)), Ok($variant(cidr)));
  430. }
  431. }
  432. };
  433. }
  434. #[test]
  435. #[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))]
  436. fn test_mac() {
  437. assert_eq!(EthernetAddress::from_str(""), Err(()));
  438. assert_eq!(
  439. EthernetAddress::from_str("02:00:00:00:00:00"),
  440. Ok(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x00]))
  441. );
  442. assert_eq!(
  443. EthernetAddress::from_str("01:23:45:67:89:ab"),
  444. Ok(EthernetAddress([0x01, 0x23, 0x45, 0x67, 0x89, 0xab]))
  445. );
  446. assert_eq!(
  447. EthernetAddress::from_str("cd:ef:10:00:00:00"),
  448. Ok(EthernetAddress([0xcd, 0xef, 0x10, 0x00, 0x00, 0x00]))
  449. );
  450. assert_eq!(
  451. EthernetAddress::from_str("00:00:00:ab:cd:ef"),
  452. Ok(EthernetAddress([0x00, 0x00, 0x00, 0xab, 0xcd, 0xef]))
  453. );
  454. assert_eq!(
  455. EthernetAddress::from_str("00-00-00-ab-cd-ef"),
  456. Ok(EthernetAddress([0x00, 0x00, 0x00, 0xab, 0xcd, 0xef]))
  457. );
  458. assert_eq!(
  459. EthernetAddress::from_str("AB-CD-EF-00-00-00"),
  460. Ok(EthernetAddress([0xab, 0xcd, 0xef, 0x00, 0x00, 0x00]))
  461. );
  462. assert_eq!(EthernetAddress::from_str("100:00:00:00:00:00"), Err(()));
  463. assert_eq!(EthernetAddress::from_str("002:00:00:00:00:00"), Err(()));
  464. assert_eq!(EthernetAddress::from_str("02:00:00:00:00:000"), Err(()));
  465. assert_eq!(EthernetAddress::from_str("02:00:00:00:00:0x"), Err(()));
  466. }
  467. #[test]
  468. #[cfg(feature = "proto-ipv4")]
  469. fn test_ipv4() {
  470. assert_eq!(Ipv4Address::from_str(""), Err(()));
  471. assert_eq!(
  472. Ipv4Address::from_str("1.2.3.4"),
  473. Ok(Ipv4Address([1, 2, 3, 4]))
  474. );
  475. assert_eq!(
  476. Ipv4Address::from_str("001.2.3.4"),
  477. Ok(Ipv4Address([1, 2, 3, 4]))
  478. );
  479. assert_eq!(Ipv4Address::from_str("0001.2.3.4"), Err(()));
  480. assert_eq!(Ipv4Address::from_str("999.2.3.4"), Err(()));
  481. assert_eq!(Ipv4Address::from_str("1.2.3.4.5"), Err(()));
  482. assert_eq!(Ipv4Address::from_str("1.2.3"), Err(()));
  483. assert_eq!(Ipv4Address::from_str("1.2.3."), Err(()));
  484. assert_eq!(Ipv4Address::from_str("1.2.3.4."), Err(()));
  485. }
  486. #[test]
  487. #[cfg(feature = "proto-ipv6")]
  488. fn test_ipv6() {
  489. // Obviously not valid
  490. assert_eq!(Ipv6Address::from_str(""), Err(()));
  491. assert_eq!(
  492. Ipv6Address::from_str("fe80:0:0:0:0:0:0:1"),
  493. Ok(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1))
  494. );
  495. assert_eq!(Ipv6Address::from_str("::1"), Ok(Ipv6Address::LOOPBACK));
  496. assert_eq!(Ipv6Address::from_str("::"), Ok(Ipv6Address::UNSPECIFIED));
  497. assert_eq!(
  498. Ipv6Address::from_str("fe80::1"),
  499. Ok(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1))
  500. );
  501. assert_eq!(
  502. Ipv6Address::from_str("1234:5678::"),
  503. Ok(Ipv6Address::new(0x1234, 0x5678, 0, 0, 0, 0, 0, 0))
  504. );
  505. assert_eq!(
  506. Ipv6Address::from_str("1234:5678::8765:4321"),
  507. Ok(Ipv6Address::new(0x1234, 0x5678, 0, 0, 0, 0, 0x8765, 0x4321))
  508. );
  509. // Two double colons in address
  510. assert_eq!(Ipv6Address::from_str("1234:5678::1::1"), Err(()));
  511. assert_eq!(
  512. Ipv6Address::from_str("4444:333:22:1::4"),
  513. Ok(Ipv6Address::new(0x4444, 0x0333, 0x0022, 0x0001, 0, 0, 0, 4))
  514. );
  515. assert_eq!(
  516. Ipv6Address::from_str("1:1:1:1:1:1::"),
  517. Ok(Ipv6Address::new(1, 1, 1, 1, 1, 1, 0, 0))
  518. );
  519. assert_eq!(
  520. Ipv6Address::from_str("::1:1:1:1:1:1"),
  521. Ok(Ipv6Address::new(0, 0, 1, 1, 1, 1, 1, 1))
  522. );
  523. assert_eq!(Ipv6Address::from_str("::1:1:1:1:1:1:1"), Err(()));
  524. // Double colon appears too late indicating an address that is too long
  525. assert_eq!(Ipv6Address::from_str("1:1:1:1:1:1:1::"), Err(()));
  526. // Section after double colon is too long for a valid address
  527. assert_eq!(Ipv6Address::from_str("::1:1:1:1:1:1:1"), Err(()));
  528. // Obviously too long
  529. assert_eq!(Ipv6Address::from_str("1:1:1:1:1:1:1:1:1"), Err(()));
  530. // Address is too short
  531. assert_eq!(Ipv6Address::from_str("1:1:1:1:1:1:1"), Err(()));
  532. // Long number
  533. assert_eq!(Ipv6Address::from_str("::000001"), Err(()));
  534. // IPv4-Mapped address
  535. assert_eq!(
  536. Ipv6Address::from_str("::ffff:192.168.1.1"),
  537. Ok(Ipv6Address([
  538. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1
  539. ]))
  540. );
  541. assert_eq!(
  542. Ipv6Address::from_str("0:0:0:0:0:ffff:192.168.1.1"),
  543. Ok(Ipv6Address([
  544. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1
  545. ]))
  546. );
  547. assert_eq!(
  548. Ipv6Address::from_str("0::ffff:192.168.1.1"),
  549. Ok(Ipv6Address([
  550. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1
  551. ]))
  552. );
  553. // Only ffff is allowed in position 6 when IPv4 mapped
  554. assert_eq!(Ipv6Address::from_str("0:0:0:0:0:eeee:192.168.1.1"), Err(()));
  555. // Positions 1-5 must be 0 when IPv4 mapped
  556. assert_eq!(Ipv6Address::from_str("0:0:0:0:1:ffff:192.168.1.1"), Err(()));
  557. assert_eq!(Ipv6Address::from_str("1::ffff:192.168.1.1"), Err(()));
  558. // Out of range ipv4 octet
  559. assert_eq!(Ipv6Address::from_str("0:0:0:0:0:ffff:256.168.1.1"), Err(()));
  560. // Invalid hex in ipv4 octet
  561. assert_eq!(Ipv6Address::from_str("0:0:0:0:0:ffff:c0.168.1.1"), Err(()));
  562. }
  563. #[test]
  564. #[cfg(feature = "proto-ipv4")]
  565. fn test_ip_ipv4() {
  566. assert_eq!(IpAddress::from_str(""), Err(()));
  567. assert_eq!(
  568. IpAddress::from_str("1.2.3.4"),
  569. Ok(IpAddress::Ipv4(Ipv4Address([1, 2, 3, 4])))
  570. );
  571. assert_eq!(IpAddress::from_str("x"), Err(()));
  572. }
  573. #[test]
  574. #[cfg(feature = "proto-ipv6")]
  575. fn test_ip_ipv6() {
  576. assert_eq!(IpAddress::from_str(""), Err(()));
  577. assert_eq!(
  578. IpAddress::from_str("fe80::1"),
  579. Ok(IpAddress::Ipv6(Ipv6Address::new(
  580. 0xfe80, 0, 0, 0, 0, 0, 0, 1
  581. )))
  582. );
  583. assert_eq!(IpAddress::from_str("x"), Err(()));
  584. }
  585. #[test]
  586. #[cfg(feature = "proto-ipv4")]
  587. fn test_cidr_ipv4() {
  588. let tests = [
  589. (
  590. "127.0.0.1/8",
  591. Ok(Ipv4Cidr::new(Ipv4Address([127, 0, 0, 1]), 8u8)),
  592. ),
  593. (
  594. "192.168.1.1/24",
  595. Ok(Ipv4Cidr::new(Ipv4Address([192, 168, 1, 1]), 24u8)),
  596. ),
  597. (
  598. "8.8.8.8/32",
  599. Ok(Ipv4Cidr::new(Ipv4Address([8, 8, 8, 8]), 32u8)),
  600. ),
  601. (
  602. "8.8.8.8/0",
  603. Ok(Ipv4Cidr::new(Ipv4Address([8, 8, 8, 8]), 0u8)),
  604. ),
  605. ("", Err(())),
  606. ("1", Err(())),
  607. ("127.0.0.1", Err(())),
  608. ("127.0.0.1/", Err(())),
  609. ("127.0.0.1/33", Err(())),
  610. ("127.0.0.1/111", Err(())),
  611. ("/32", Err(())),
  612. ];
  613. check_cidr_test_array!(tests, Ipv4Cidr::from_str, IpCidr::Ipv4);
  614. }
  615. #[test]
  616. #[cfg(feature = "proto-ipv6")]
  617. fn test_cidr_ipv6() {
  618. let tests = [
  619. (
  620. "fe80::1/64",
  621. Ok(Ipv6Cidr::new(
  622. Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
  623. 64u8,
  624. )),
  625. ),
  626. (
  627. "fe80::/64",
  628. Ok(Ipv6Cidr::new(
  629. Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0),
  630. 64u8,
  631. )),
  632. ),
  633. ("::1/128", Ok(Ipv6Cidr::new(Ipv6Address::LOOPBACK, 128u8))),
  634. ("::/128", Ok(Ipv6Cidr::new(Ipv6Address::UNSPECIFIED, 128u8))),
  635. (
  636. "fe80:0:0:0:0:0:0:1/64",
  637. Ok(Ipv6Cidr::new(
  638. Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
  639. 64u8,
  640. )),
  641. ),
  642. ("fe80:0:0:0:0:0:0:1|64", Err(())),
  643. ("fe80::|64", Err(())),
  644. ("fe80::1::/64", Err(())),
  645. ];
  646. check_cidr_test_array!(tests, Ipv6Cidr::from_str, IpCidr::Ipv6);
  647. }
  648. #[test]
  649. #[cfg(feature = "proto-ipv4")]
  650. fn test_endpoint_ipv4() {
  651. assert_eq!(IpEndpoint::from_str(""), Err(()));
  652. assert_eq!(IpEndpoint::from_str("x"), Err(()));
  653. assert_eq!(
  654. IpEndpoint::from_str("127.0.0.1"),
  655. Ok(IpEndpoint {
  656. addr: IpAddress::v4(127, 0, 0, 1),
  657. port: 0
  658. })
  659. );
  660. assert_eq!(
  661. IpEndpoint::from_str("127.0.0.1:12345"),
  662. Ok(IpEndpoint {
  663. addr: IpAddress::v4(127, 0, 0, 1),
  664. port: 12345
  665. })
  666. );
  667. }
  668. #[test]
  669. #[cfg(feature = "proto-ipv6")]
  670. fn test_endpoint_ipv6() {
  671. assert_eq!(IpEndpoint::from_str(""), Err(()));
  672. assert_eq!(IpEndpoint::from_str("x"), Err(()));
  673. assert_eq!(
  674. IpEndpoint::from_str("fe80::1"),
  675. Ok(IpEndpoint {
  676. addr: IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1),
  677. port: 0
  678. })
  679. );
  680. assert_eq!(
  681. IpEndpoint::from_str("[fe80::1]:12345"),
  682. Ok(IpEndpoint {
  683. addr: IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1),
  684. port: 12345
  685. })
  686. );
  687. }
  688. }