ip.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. use core::fmt;
  2. use {Error, Result};
  3. use super::{Ipv4Address, Ipv4Packet, Ipv4Repr};
  4. /// Internet protocol version.
  5. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
  6. pub enum Version {
  7. Unspecified,
  8. Ipv4,
  9. #[doc(hidden)]
  10. __Nonexhaustive,
  11. }
  12. impl Version {
  13. /// Return the version of an IP packet stored in the provided buffer.
  14. ///
  15. /// This function never returns `Ok(IpVersion::Unspecified)`; instead,
  16. /// unknown versions result in `Err(Error::Unrecognized)`.
  17. pub fn of_packet(data: &[u8]) -> Result<Version> {
  18. match data[0] >> 4 {
  19. 4 => Ok(Version::Ipv4),
  20. _ => Err(Error::Unrecognized)
  21. }
  22. }
  23. }
  24. impl fmt::Display for Version {
  25. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  26. match self {
  27. &Version::Unspecified => write!(f, "IPv?"),
  28. &Version::Ipv4 => write!(f, "IPv4"),
  29. &Version::__Nonexhaustive => unreachable!()
  30. }
  31. }
  32. }
  33. enum_with_unknown! {
  34. /// IP datagram encapsulated protocol.
  35. pub enum Protocol(u8) {
  36. Icmp = 0x01,
  37. Tcp = 0x06,
  38. Udp = 0x11
  39. }
  40. }
  41. impl fmt::Display for Protocol {
  42. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  43. match self {
  44. &Protocol::Icmp => write!(f, "ICMP"),
  45. &Protocol::Tcp => write!(f, "TCP"),
  46. &Protocol::Udp => write!(f, "UDP"),
  47. &Protocol::Unknown(id) => write!(f, "0x{:02x}", id)
  48. }
  49. }
  50. }
  51. /// An internetworking address.
  52. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
  53. pub enum Address {
  54. /// An unspecified address.
  55. /// May be used as a placeholder for storage where the address is not assigned yet.
  56. Unspecified,
  57. /// An IPv4 address.
  58. Ipv4(Ipv4Address)
  59. }
  60. impl Address {
  61. /// Create an address wrapping an IPv4 address with the given octets.
  62. pub fn v4(a0: u8, a1: u8, a2: u8, a3: u8) -> Address {
  63. Address::Ipv4(Ipv4Address::new(a0, a1, a2, a3))
  64. }
  65. /// Query whether the address is a valid unicast address.
  66. pub fn is_unicast(&self) -> bool {
  67. match self {
  68. &Address::Unspecified => false,
  69. &Address::Ipv4(addr) => addr.is_unicast()
  70. }
  71. }
  72. /// Query whether the address is the broadcast address.
  73. pub fn is_broadcast(&self) -> bool {
  74. match self {
  75. &Address::Unspecified => false,
  76. &Address::Ipv4(addr) => addr.is_broadcast()
  77. }
  78. }
  79. /// Query whether the address falls into the "unspecified" range.
  80. pub fn is_unspecified(&self) -> bool {
  81. match self {
  82. &Address::Unspecified => true,
  83. &Address::Ipv4(addr) => addr.is_unspecified()
  84. }
  85. }
  86. /// Return an unspecified address that has the same IP version as `self`.
  87. pub fn to_unspecified(&self) -> Address {
  88. match self {
  89. &Address::Unspecified => Address::Unspecified,
  90. &Address::Ipv4(_) => Address::Ipv4(Ipv4Address::UNSPECIFIED),
  91. }
  92. }
  93. }
  94. impl Default for Address {
  95. fn default() -> Address {
  96. Address::Unspecified
  97. }
  98. }
  99. impl From<Ipv4Address> for Address {
  100. fn from(addr: Ipv4Address) -> Self {
  101. Address::Ipv4(addr)
  102. }
  103. }
  104. impl fmt::Display for Address {
  105. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  106. match self {
  107. &Address::Unspecified => write!(f, "*"),
  108. &Address::Ipv4(addr) => write!(f, "{}", addr)
  109. }
  110. }
  111. }
  112. /// An internet endpoint address.
  113. ///
  114. /// An endpoint can be constructed from a port, in which case the address is unspecified.
  115. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
  116. pub struct Endpoint {
  117. pub addr: Address,
  118. pub port: u16
  119. }
  120. impl Endpoint {
  121. pub const UNSPECIFIED: Endpoint = Endpoint { addr: Address::Unspecified, port: 0 };
  122. /// Create an endpoint address from given address and port.
  123. pub fn new(addr: Address, port: u16) -> Endpoint {
  124. Endpoint { addr: addr, port: port }
  125. }
  126. /// Query whether the endpoint has a specified address and port.
  127. pub fn is_specified(&self) -> bool {
  128. !self.addr.is_unspecified() && self.port != 0
  129. }
  130. }
  131. impl fmt::Display for Endpoint {
  132. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  133. write!(f, "{}:{}", self.addr, self.port)
  134. }
  135. }
  136. impl From<u16> for Endpoint {
  137. fn from(port: u16) -> Endpoint {
  138. Endpoint { addr: Address::Unspecified, port: port }
  139. }
  140. }
  141. impl<T: Into<Address>> From<(T, u16)> for Endpoint {
  142. fn from((addr, port): (T, u16)) -> Endpoint {
  143. Endpoint { addr: addr.into(), port: port }
  144. }
  145. }
  146. /// An IP packet representation.
  147. ///
  148. /// This enum abstracts the various versions of IP packets. It either contains a concrete
  149. /// high-level representation for some IP protocol version, or an unspecified representation,
  150. /// which permits the `IpAddress::Unspecified` addresses.
  151. #[derive(Debug, Clone, PartialEq, Eq)]
  152. pub enum IpRepr {
  153. Unspecified {
  154. src_addr: Address,
  155. dst_addr: Address,
  156. protocol: Protocol,
  157. payload_len: usize
  158. },
  159. Ipv4(Ipv4Repr),
  160. #[doc(hidden)]
  161. __Nonexhaustive
  162. }
  163. impl From<Ipv4Repr> for IpRepr {
  164. fn from(repr: Ipv4Repr) -> IpRepr {
  165. IpRepr::Ipv4(repr)
  166. }
  167. }
  168. impl IpRepr {
  169. /// Return the protocol version.
  170. pub fn version(&self) -> Version {
  171. match self {
  172. &IpRepr::Unspecified { .. } => Version::Unspecified,
  173. &IpRepr::Ipv4(_) => Version::Ipv4,
  174. &IpRepr::__Nonexhaustive => unreachable!()
  175. }
  176. }
  177. /// Return the source address.
  178. pub fn src_addr(&self) -> Address {
  179. match self {
  180. &IpRepr::Unspecified { src_addr, .. } => src_addr,
  181. &IpRepr::Ipv4(repr) => Address::Ipv4(repr.src_addr),
  182. &IpRepr::__Nonexhaustive => unreachable!()
  183. }
  184. }
  185. /// Return the destination address.
  186. pub fn dst_addr(&self) -> Address {
  187. match self {
  188. &IpRepr::Unspecified { dst_addr, .. } => dst_addr,
  189. &IpRepr::Ipv4(repr) => Address::Ipv4(repr.dst_addr),
  190. &IpRepr::__Nonexhaustive => unreachable!()
  191. }
  192. }
  193. /// Return the protocol.
  194. pub fn protocol(&self) -> Protocol {
  195. match self {
  196. &IpRepr::Unspecified { protocol, .. } => protocol,
  197. &IpRepr::Ipv4(repr) => repr.protocol,
  198. &IpRepr::__Nonexhaustive => unreachable!()
  199. }
  200. }
  201. /// Return the payload length.
  202. pub fn payload_len(&self) -> usize {
  203. match self {
  204. &IpRepr::Unspecified { payload_len, .. } => payload_len,
  205. &IpRepr::Ipv4(repr) => repr.payload_len,
  206. &IpRepr::__Nonexhaustive => unreachable!()
  207. }
  208. }
  209. /// Set the payload length.
  210. pub fn set_payload_len(&mut self, length: usize) {
  211. match self {
  212. &mut IpRepr::Unspecified { ref mut payload_len, .. } =>
  213. *payload_len = length,
  214. &mut IpRepr::Ipv4(Ipv4Repr { ref mut payload_len, .. }) =>
  215. *payload_len = length,
  216. &mut IpRepr::__Nonexhaustive => unreachable!()
  217. }
  218. }
  219. /// Convert an unspecified representation into a concrete one, or return
  220. /// `Err(Error::Unaddressable)` if not possible.
  221. ///
  222. /// # Panics
  223. /// This function panics if source and destination addresses belong to different families,
  224. /// or the destination address is unspecified, since this indicates a logic error.
  225. pub fn lower(&self, fallback_src_addrs: &[Address]) -> Result<IpRepr> {
  226. match self {
  227. &IpRepr::Unspecified {
  228. src_addr: Address::Ipv4(src_addr),
  229. dst_addr: Address::Ipv4(dst_addr),
  230. protocol, payload_len
  231. } => {
  232. Ok(IpRepr::Ipv4(Ipv4Repr {
  233. src_addr: src_addr,
  234. dst_addr: dst_addr,
  235. protocol: protocol,
  236. payload_len: payload_len
  237. }))
  238. }
  239. &IpRepr::Unspecified {
  240. src_addr: Address::Unspecified,
  241. dst_addr: Address::Ipv4(dst_addr),
  242. protocol, payload_len
  243. } => {
  244. let mut src_addr = None;
  245. for addr in fallback_src_addrs {
  246. match addr {
  247. &Address::Ipv4(addr) => {
  248. src_addr = Some(addr);
  249. break
  250. }
  251. _ => ()
  252. }
  253. }
  254. Ok(IpRepr::Ipv4(Ipv4Repr {
  255. src_addr: src_addr.ok_or(Error::Unaddressable)?,
  256. dst_addr: dst_addr,
  257. protocol: protocol,
  258. payload_len: payload_len
  259. }))
  260. }
  261. &IpRepr::Unspecified { dst_addr: Address::Unspecified, .. } =>
  262. panic!("unspecified destination IP address"),
  263. // &IpRepr::Unspecified { .. } =>
  264. // panic!("source and destination IP address families do not match"),
  265. &IpRepr::Ipv4(mut repr) => {
  266. if repr.src_addr.is_unspecified() {
  267. for addr in fallback_src_addrs {
  268. match addr {
  269. &Address::Ipv4(addr) => {
  270. repr.src_addr = addr;
  271. return Ok(IpRepr::Ipv4(repr));
  272. }
  273. _ => ()
  274. }
  275. }
  276. Err(Error::Unaddressable)
  277. } else {
  278. Ok(IpRepr::Ipv4(repr))
  279. }
  280. },
  281. &IpRepr::__Nonexhaustive => unreachable!()
  282. }
  283. }
  284. /// Return the length of a header that will be emitted from this high-level representation.
  285. ///
  286. /// # Panics
  287. /// This function panics if invoked on an unspecified representation.
  288. pub fn buffer_len(&self) -> usize {
  289. match self {
  290. &IpRepr::Unspecified { .. } =>
  291. panic!("unspecified IP representation"),
  292. &IpRepr::Ipv4(repr) =>
  293. repr.buffer_len(),
  294. &IpRepr::__Nonexhaustive =>
  295. unreachable!()
  296. }
  297. }
  298. /// Emit this high-level representation into a buffer.
  299. ///
  300. /// # Panics
  301. /// This function panics if invoked on an unspecified representation.
  302. pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, buffer: T) {
  303. match self {
  304. &IpRepr::Unspecified { .. } =>
  305. panic!("unspecified IP representation"),
  306. &IpRepr::Ipv4(repr) =>
  307. repr.emit(&mut Ipv4Packet::new(buffer)),
  308. &IpRepr::__Nonexhaustive =>
  309. unreachable!()
  310. }
  311. }
  312. /// Return the total length of a packet that will be emitted from this
  313. /// high-level representation.
  314. ///
  315. /// This is the same as `repr.buffer_len() + repr.payload_len()`.
  316. ///
  317. /// # Panics
  318. /// This function panics if invoked on an unspecified representation.
  319. pub fn total_len(&self) -> usize {
  320. self.buffer_len() + self.payload_len()
  321. }
  322. }
  323. pub mod checksum {
  324. use byteorder::{ByteOrder, NetworkEndian};
  325. use super::*;
  326. fn propagate_carries(word: u32) -> u16 {
  327. let sum = (word >> 16) + (word & 0xffff);
  328. ((sum >> 16) as u16) + (sum as u16)
  329. }
  330. /// Compute an RFC 1071 compliant checksum (without the final complement).
  331. pub fn data(data: &[u8]) -> u16 {
  332. let mut accum: u32 = 0;
  333. let mut i = 0;
  334. while i < data.len() {
  335. let word;
  336. if i + 2 <= data.len() {
  337. word = NetworkEndian::read_u16(&data[i..i + 2]) as u32
  338. } else {
  339. word = (data[i] as u32) << 8
  340. }
  341. accum += word;
  342. i += 2;
  343. }
  344. propagate_carries(accum)
  345. }
  346. /// Combine several RFC 1071 compliant checksums.
  347. pub fn combine(checksums: &[u16]) -> u16 {
  348. let mut accum: u32 = 0;
  349. for &word in checksums {
  350. accum += word as u32;
  351. }
  352. propagate_carries(accum)
  353. }
  354. /// Compute an IP pseudo header checksum.
  355. pub fn pseudo_header(src_addr: &Address, dst_addr: &Address,
  356. protocol: Protocol, length: u32) -> u16 {
  357. match (src_addr, dst_addr) {
  358. (&Address::Ipv4(src_addr), &Address::Ipv4(dst_addr)) => {
  359. let mut proto_len = [0u8; 4];
  360. proto_len[1] = protocol.into();
  361. NetworkEndian::write_u16(&mut proto_len[2..4], length as u16);
  362. combine(&[
  363. data(src_addr.as_bytes()),
  364. data(dst_addr.as_bytes()),
  365. data(&proto_len[..])
  366. ])
  367. },
  368. _ => panic!("Unexpected pseudo header addresses: {}, {}",
  369. src_addr, dst_addr)
  370. }
  371. }
  372. }
  373. #[cfg(test)]
  374. mod test {
  375. use super::*;
  376. use wire::{Ipv4Address, IpProtocol, IpAddress, Ipv4Repr};
  377. #[test]
  378. fn ip_repr_lower() {
  379. let ip_addr_a = Ipv4Address::new(1, 2, 3, 4);
  380. let ip_addr_b = Ipv4Address::new(5, 6, 7, 8);
  381. let proto = IpProtocol::Icmp;
  382. let payload_len = 10;
  383. assert_eq!(
  384. IpRepr::Unspecified{
  385. src_addr: IpAddress::Ipv4(ip_addr_a),
  386. dst_addr: IpAddress::Ipv4(ip_addr_b),
  387. protocol: proto,
  388. payload_len
  389. }.lower(&[]),
  390. Ok(IpRepr::Ipv4(Ipv4Repr{
  391. src_addr: ip_addr_a,
  392. dst_addr: ip_addr_b,
  393. protocol: proto,
  394. payload_len
  395. }))
  396. );
  397. assert_eq!(
  398. IpRepr::Unspecified{
  399. src_addr: IpAddress::Unspecified,
  400. dst_addr: IpAddress::Ipv4(ip_addr_b),
  401. protocol: proto,
  402. payload_len
  403. }.lower(&[]),
  404. Err(Error::Unaddressable)
  405. );
  406. assert_eq!(
  407. IpRepr::Unspecified{
  408. src_addr: IpAddress::Unspecified,
  409. dst_addr: IpAddress::Ipv4(ip_addr_b),
  410. protocol: proto,
  411. payload_len
  412. }.lower(&[IpAddress::Ipv4(ip_addr_a)]),
  413. Ok(IpRepr::Ipv4(Ipv4Repr{
  414. src_addr: ip_addr_a,
  415. dst_addr: ip_addr_b,
  416. protocol: proto,
  417. payload_len
  418. }))
  419. );
  420. assert_eq!(
  421. IpRepr::Ipv4(Ipv4Repr{
  422. src_addr: ip_addr_a,
  423. dst_addr: ip_addr_b,
  424. protocol: proto,
  425. payload_len
  426. }).lower(&[]),
  427. Ok(IpRepr::Ipv4(Ipv4Repr{
  428. src_addr: ip_addr_a,
  429. dst_addr: ip_addr_b,
  430. protocol: proto,
  431. payload_len
  432. }))
  433. );
  434. assert_eq!(
  435. IpRepr::Ipv4(Ipv4Repr{
  436. src_addr: Ipv4Address::UNSPECIFIED,
  437. dst_addr: ip_addr_b,
  438. protocol: proto,
  439. payload_len
  440. }).lower(&[]),
  441. Err(Error::Unaddressable)
  442. );
  443. assert_eq!(
  444. IpRepr::Ipv4(Ipv4Repr{
  445. src_addr: Ipv4Address::UNSPECIFIED,
  446. dst_addr: ip_addr_b,
  447. protocol: proto,
  448. payload_len
  449. }).lower(&[IpAddress::Ipv4(ip_addr_a)]),
  450. Ok(IpRepr::Ipv4(Ipv4Repr{
  451. src_addr: ip_addr_a,
  452. dst_addr: ip_addr_b,
  453. protocol: proto,
  454. payload_len
  455. }))
  456. );
  457. }
  458. #[test]
  459. fn endpoint_unspecified() {
  460. assert!(!Endpoint::UNSPECIFIED.is_specified());
  461. }
  462. }