rpl.rs 97 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686
  1. //! Implementation of the RPL packet formats. See [RFC 6550 § 6].
  2. //!
  3. //! [RFC 6550 § 6]: https://datatracker.ietf.org/doc/html/rfc6550#section-6
  4. use byteorder::{ByteOrder, NetworkEndian};
  5. use super::{Error, Result};
  6. use crate::wire::icmpv6::Packet;
  7. use crate::wire::ipv6::Address;
  8. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
  9. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  10. #[repr(u8)]
  11. pub enum InstanceId {
  12. Global(u8),
  13. Local(u8),
  14. }
  15. impl From<u8> for InstanceId {
  16. fn from(val: u8) -> Self {
  17. const MASK: u8 = 0b0111_1111;
  18. if ((val >> 7) & 0xb1) == 0b0 {
  19. Self::Global(val & MASK)
  20. } else {
  21. Self::Local(val & MASK)
  22. }
  23. }
  24. }
  25. impl From<InstanceId> for u8 {
  26. fn from(val: InstanceId) -> Self {
  27. match val {
  28. InstanceId::Global(val) => 0b0000_0000 | val,
  29. InstanceId::Local(val) => 0b1000_0000 | val,
  30. }
  31. }
  32. }
  33. impl InstanceId {
  34. /// Return the real part of the ID.
  35. pub fn id(&self) -> u8 {
  36. match self {
  37. Self::Global(val) => *val,
  38. Self::Local(val) => *val,
  39. }
  40. }
  41. /// Returns `true` when the DODAG ID is the destination address of the IPv6 packet.
  42. #[inline]
  43. pub fn dodag_is_destination(&self) -> bool {
  44. match self {
  45. Self::Global(_) => false,
  46. Self::Local(val) => ((val >> 6) & 0b1) == 0b1,
  47. }
  48. }
  49. /// Returns `true` when the DODAG ID is the source address of the IPv6 packet.
  50. ///
  51. /// *NOTE*: this only makes sence when using a local RPL Instance ID and the packet is not a
  52. /// RPL control message.
  53. #[inline]
  54. pub fn dodag_is_source(&self) -> bool {
  55. !self.dodag_is_destination()
  56. }
  57. }
  58. mod field {
  59. use crate::wire::field::*;
  60. pub const RPL_INSTANCE_ID: usize = 4;
  61. // DODAG information solicitation fields (DIS)
  62. pub const DIS_FLAGS: usize = 4;
  63. pub const DIS_RESERVED: usize = 5;
  64. // DODAG information object fields (DIO)
  65. pub const DIO_VERSION_NUMBER: usize = 5;
  66. pub const DIO_RANK: Field = 6..8;
  67. pub const DIO_GROUNDED: usize = 8;
  68. pub const DIO_MOP: usize = 8;
  69. pub const DIO_PRF: usize = 8;
  70. pub const DIO_DTSN: usize = 9;
  71. //pub const DIO_FLAGS: usize = 10;
  72. //pub const DIO_RESERVED: usize = 11;
  73. pub const DIO_DODAG_ID: Field = 12..12 + 16;
  74. // Destination advertisment object (DAO)
  75. pub const DAO_K: usize = 5;
  76. pub const DAO_D: usize = 5;
  77. //pub const DAO_FLAGS: usize = 5;
  78. //pub const DAO_RESERVED: usize = 6;
  79. pub const DAO_SEQUENCE: usize = 7;
  80. pub const DAO_DODAG_ID: Field = 8..8 + 16;
  81. // Destination advertisment object ack (DAO-ACK)
  82. pub const DAO_ACK_D: usize = 5;
  83. //pub const DAO_ACK_RESERVED: usize = 5;
  84. pub const DAO_ACK_SEQUENCE: usize = 6;
  85. pub const DAO_ACK_STATUS: usize = 7;
  86. pub const DAO_ACK_DODAG_ID: Field = 8..8 + 16;
  87. }
  88. enum_with_unknown! {
  89. /// RPL Control Message subtypes.
  90. pub enum RplControlMessage(u8) {
  91. DodagInformationSolicitation = 0x00,
  92. DodagInformationObject = 0x01,
  93. DestinationAdvertisementObject = 0x02,
  94. DestinationAdvertisementObjectAck = 0x03,
  95. SecureDodagInformationSolicitation = 0x80,
  96. SecureDodagInformationObject = 0x81,
  97. SecureDesintationAdvertismentObject = 0x82,
  98. SecureDestinationAdvertisementObjectAck = 0x83,
  99. ConsistencyCheck = 0x8a,
  100. }
  101. }
  102. impl core::fmt::Display for RplControlMessage {
  103. fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
  104. match self {
  105. RplControlMessage::DodagInformationSolicitation => {
  106. write!(f, "DODAG information solicitation (DIS)")
  107. }
  108. RplControlMessage::DodagInformationObject => {
  109. write!(f, "DODAG information object (DIO)")
  110. }
  111. RplControlMessage::DestinationAdvertisementObject => {
  112. write!(f, "destination advertisment object (DAO)")
  113. }
  114. RplControlMessage::DestinationAdvertisementObjectAck => write!(
  115. f,
  116. "destination advertisment object acknowledgement (DAO-ACK)"
  117. ),
  118. RplControlMessage::SecureDodagInformationSolicitation => {
  119. write!(f, "secure DODAG information solicitation (DIS)")
  120. }
  121. RplControlMessage::SecureDodagInformationObject => {
  122. write!(f, "secure DODAG information object (DIO)")
  123. }
  124. RplControlMessage::SecureDesintationAdvertismentObject => {
  125. write!(f, "secure destination advertisment object (DAO)")
  126. }
  127. RplControlMessage::SecureDestinationAdvertisementObjectAck => write!(
  128. f,
  129. "secure destination advertisment object acknowledgement (DAO-ACK)"
  130. ),
  131. RplControlMessage::ConsistencyCheck => write!(f, "consistency check (CC)"),
  132. RplControlMessage::Unknown(id) => write!(f, "{}", id),
  133. }
  134. }
  135. }
  136. impl<T: AsRef<[u8]>> Packet<T> {
  137. /// Return the RPL instance ID.
  138. #[inline]
  139. pub fn rpl_instance_id(&self) -> InstanceId {
  140. get!(self.buffer, into: InstanceId, field: field::RPL_INSTANCE_ID)
  141. }
  142. }
  143. impl<'p, T: AsRef<[u8]> + ?Sized> Packet<&'p T> {
  144. /// Return a pointer to the options.
  145. pub fn options(&self) -> Result<&'p [u8]> {
  146. let len = self.buffer.as_ref().len();
  147. match RplControlMessage::from(self.msg_code()) {
  148. RplControlMessage::DodagInformationSolicitation if len < field::DIS_RESERVED + 1 => {
  149. return Err(Error)
  150. }
  151. RplControlMessage::DodagInformationObject if len < field::DIO_DODAG_ID.end => {
  152. return Err(Error)
  153. }
  154. RplControlMessage::DestinationAdvertisementObject
  155. if self.dao_dodag_id_present() && len < field::DAO_DODAG_ID.end =>
  156. {
  157. return Err(Error)
  158. }
  159. RplControlMessage::DestinationAdvertisementObject if len < field::DAO_SEQUENCE + 1 => {
  160. return Err(Error)
  161. }
  162. RplControlMessage::DestinationAdvertisementObjectAck
  163. if self.dao_dodag_id_present() && len < field::DAO_ACK_DODAG_ID.end =>
  164. {
  165. return Err(Error)
  166. }
  167. RplControlMessage::DestinationAdvertisementObjectAck
  168. if len < field::DAO_ACK_STATUS + 1 =>
  169. {
  170. return Err(Error)
  171. }
  172. RplControlMessage::SecureDodagInformationSolicitation
  173. | RplControlMessage::SecureDodagInformationObject
  174. | RplControlMessage::SecureDesintationAdvertismentObject
  175. | RplControlMessage::SecureDestinationAdvertisementObjectAck
  176. | RplControlMessage::ConsistencyCheck => return Err(Error),
  177. RplControlMessage::Unknown(_) => return Err(Error),
  178. _ => {}
  179. }
  180. let buffer = &self.buffer.as_ref();
  181. Ok(match RplControlMessage::from(self.msg_code()) {
  182. RplControlMessage::DodagInformationSolicitation => &buffer[field::DIS_RESERVED + 1..],
  183. RplControlMessage::DodagInformationObject => &buffer[field::DIO_DODAG_ID.end..],
  184. RplControlMessage::DestinationAdvertisementObject if self.dao_dodag_id_present() => {
  185. &buffer[field::DAO_DODAG_ID.end..]
  186. }
  187. RplControlMessage::DestinationAdvertisementObject => &buffer[field::DAO_SEQUENCE + 1..],
  188. RplControlMessage::DestinationAdvertisementObjectAck if self.dao_dodag_id_present() => {
  189. &buffer[field::DAO_ACK_DODAG_ID.end..]
  190. }
  191. RplControlMessage::DestinationAdvertisementObjectAck => {
  192. &buffer[field::DAO_ACK_STATUS + 1..]
  193. }
  194. RplControlMessage::SecureDodagInformationSolicitation
  195. | RplControlMessage::SecureDodagInformationObject
  196. | RplControlMessage::SecureDesintationAdvertismentObject
  197. | RplControlMessage::SecureDestinationAdvertisementObjectAck
  198. | RplControlMessage::ConsistencyCheck => unreachable!(),
  199. RplControlMessage::Unknown(_) => unreachable!(),
  200. })
  201. }
  202. }
  203. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  204. /// Set the RPL Instance ID field.
  205. #[inline]
  206. pub fn set_rpl_instance_id(&mut self, value: u8) {
  207. set!(self.buffer, value, field: field::RPL_INSTANCE_ID)
  208. }
  209. }
  210. impl<'p, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> Packet<&'p mut T> {
  211. /// Return a pointer to the options.
  212. pub fn options_mut(&mut self) -> &mut [u8] {
  213. match RplControlMessage::from(self.msg_code()) {
  214. RplControlMessage::DodagInformationSolicitation => {
  215. &mut self.buffer.as_mut()[field::DIS_RESERVED + 1..]
  216. }
  217. RplControlMessage::DodagInformationObject => {
  218. &mut self.buffer.as_mut()[field::DIO_DODAG_ID.end..]
  219. }
  220. RplControlMessage::DestinationAdvertisementObject => {
  221. if self.dao_dodag_id_present() {
  222. &mut self.buffer.as_mut()[field::DAO_DODAG_ID.end..]
  223. } else {
  224. &mut self.buffer.as_mut()[field::DAO_SEQUENCE + 1..]
  225. }
  226. }
  227. RplControlMessage::DestinationAdvertisementObjectAck => {
  228. if self.dao_dodag_id_present() {
  229. &mut self.buffer.as_mut()[field::DAO_ACK_DODAG_ID.end..]
  230. } else {
  231. &mut self.buffer.as_mut()[field::DAO_ACK_STATUS + 1..]
  232. }
  233. }
  234. RplControlMessage::SecureDodagInformationSolicitation
  235. | RplControlMessage::SecureDodagInformationObject
  236. | RplControlMessage::SecureDesintationAdvertismentObject
  237. | RplControlMessage::SecureDestinationAdvertisementObjectAck
  238. | RplControlMessage::ConsistencyCheck => todo!("Secure messages not supported"),
  239. RplControlMessage::Unknown(_) => todo!(),
  240. }
  241. }
  242. }
  243. /// Getters for the DODAG information solicitation (DIS) message.
  244. ///
  245. /// ```txt
  246. /// 0 1 2
  247. /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
  248. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  249. /// | Flags | Reserved | Option(s)...
  250. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  251. /// ```
  252. impl<T: AsRef<[u8]>> Packet<T> {
  253. /// Return the DIS flags field.
  254. #[inline]
  255. pub fn dis_flags(&self) -> u8 {
  256. get!(self.buffer, field: field::DIS_FLAGS)
  257. }
  258. /// Return the DIS reserved field.
  259. #[inline]
  260. pub fn dis_reserved(&self) -> u8 {
  261. get!(self.buffer, field: field::DIS_RESERVED)
  262. }
  263. }
  264. /// Setters for the DODAG information solicitation (DIS) message.
  265. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  266. /// Clear the DIS flags field.
  267. pub fn clear_dis_flags(&mut self) {
  268. self.buffer.as_mut()[field::DIS_FLAGS] = 0;
  269. }
  270. /// Clear the DIS rserved field.
  271. pub fn clear_dis_reserved(&mut self) {
  272. self.buffer.as_mut()[field::DIS_RESERVED] = 0;
  273. }
  274. }
  275. enum_with_unknown! {
  276. pub enum ModeOfOperation(u8) {
  277. NoDownwardRoutesMaintained = 0x00,
  278. NonStoringMode = 0x01,
  279. StoringModeWithoutMulticast = 0x02,
  280. StoringModeWithMulticast = 0x03,
  281. }
  282. }
  283. impl Default for ModeOfOperation {
  284. fn default() -> Self {
  285. Self::StoringModeWithoutMulticast
  286. }
  287. }
  288. /// Getters for the DODAG information object (DIO) message.
  289. ///
  290. /// ```txt
  291. /// 0 1 2 3
  292. /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  293. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  294. /// | RPLInstanceID |Version Number | Rank |
  295. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  296. /// |G|0| MOP | Prf | DTSN | Flags | Reserved |
  297. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  298. /// | |
  299. /// + +
  300. /// | |
  301. /// + DODAGID +
  302. /// | |
  303. /// + +
  304. /// | |
  305. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  306. /// | Option(s)...
  307. /// +-+-+-+-+-+-+-+-+
  308. /// ```
  309. impl<T: AsRef<[u8]>> Packet<T> {
  310. /// Return the Version Number field.
  311. #[inline]
  312. pub fn dio_version_number(&self) -> u8 {
  313. get!(self.buffer, field: field::DIO_VERSION_NUMBER)
  314. }
  315. /// Return the Rank field.
  316. #[inline]
  317. pub fn dio_rank(&self) -> u16 {
  318. get!(self.buffer, u16, field: field::DIO_RANK)
  319. }
  320. /// Return the value of the Grounded flag.
  321. #[inline]
  322. pub fn dio_grounded(&self) -> bool {
  323. get!(self.buffer, bool, field: field::DIO_GROUNDED, shift: 7, mask: 0b01)
  324. }
  325. /// Return the mode of operation field.
  326. #[inline]
  327. pub fn dio_mode_of_operation(&self) -> ModeOfOperation {
  328. get!(self.buffer, into: ModeOfOperation, field: field::DIO_MOP, shift: 3, mask: 0b111)
  329. }
  330. /// Return the DODAG preference field.
  331. #[inline]
  332. pub fn dio_dodag_preference(&self) -> u8 {
  333. get!(self.buffer, field: field::DIO_PRF, mask: 0b111)
  334. }
  335. /// Return the destination advertisment trigger sequence number.
  336. #[inline]
  337. pub fn dio_dest_adv_trigger_seq_number(&self) -> u8 {
  338. get!(self.buffer, field: field::DIO_DTSN)
  339. }
  340. /// Return the DODAG id, which is an IPv6 address.
  341. #[inline]
  342. pub fn dio_dodag_id(&self) -> Address {
  343. get!(
  344. self.buffer,
  345. into: Address,
  346. fun: from_bytes,
  347. field: field::DIO_DODAG_ID
  348. )
  349. }
  350. }
  351. /// Setters for the DODAG information object (DIO) message.
  352. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  353. /// Set the Version Number field.
  354. #[inline]
  355. pub fn set_dio_version_number(&mut self, value: u8) {
  356. set!(self.buffer, value, field: field::DIO_VERSION_NUMBER)
  357. }
  358. /// Set the Rank field.
  359. #[inline]
  360. pub fn set_dio_rank(&mut self, value: u16) {
  361. set!(self.buffer, value, u16, field: field::DIO_RANK)
  362. }
  363. /// Set the value of the Grounded flag.
  364. #[inline]
  365. pub fn set_dio_grounded(&mut self, value: bool) {
  366. set!(self.buffer, value, bool, field: field::DIO_GROUNDED, shift: 7, mask: 0b01)
  367. }
  368. /// Set the mode of operation field.
  369. #[inline]
  370. pub fn set_dio_mode_of_operation(&mut self, mode: ModeOfOperation) {
  371. let raw = (self.buffer.as_ref()[field::DIO_MOP] & !(0b111 << 3)) | (u8::from(mode) << 3);
  372. self.buffer.as_mut()[field::DIO_MOP] = raw;
  373. }
  374. /// Set the DODAG preference field.
  375. #[inline]
  376. pub fn set_dio_dodag_preference(&mut self, value: u8) {
  377. set!(self.buffer, value, field: field::DIO_PRF, mask: 0b111)
  378. }
  379. /// Set the destination advertisment trigger sequence number.
  380. #[inline]
  381. pub fn set_dio_dest_adv_trigger_seq_number(&mut self, value: u8) {
  382. set!(self.buffer, value, field: field::DIO_DTSN)
  383. }
  384. /// Set the DODAG id, which is an IPv6 address.
  385. #[inline]
  386. pub fn set_dio_dodag_id(&mut self, address: Address) {
  387. set!(self.buffer, address: address, field: field::DIO_DODAG_ID)
  388. }
  389. }
  390. /// Getters for the Destination Advertisment Object (DAO) message.
  391. ///
  392. /// ```txt
  393. /// 0 1 2 3
  394. /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  395. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  396. /// | RPLInstanceID |K|D| Flags | Reserved | DAOSequence |
  397. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  398. /// | |
  399. /// + +
  400. /// | |
  401. /// + DODAGID* +
  402. /// | |
  403. /// + +
  404. /// | |
  405. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  406. /// | Option(s)...
  407. /// +-+-+-+-+-+-+-+-+
  408. /// ```
  409. impl<T: AsRef<[u8]>> Packet<T> {
  410. /// Returns the Expect DAO-ACK flag.
  411. #[inline]
  412. pub fn dao_ack_request(&self) -> bool {
  413. get!(self.buffer, bool, field: field::DAO_K, shift: 7, mask: 0b1)
  414. }
  415. /// Returns the flag indicating that the DODAG ID is present or not.
  416. #[inline]
  417. pub fn dao_dodag_id_present(&self) -> bool {
  418. get!(self.buffer, bool, field: field::DAO_D, shift: 6, mask: 0b1)
  419. }
  420. /// Returns the DODAG sequence flag.
  421. #[inline]
  422. pub fn dao_dodag_sequence(&self) -> u8 {
  423. get!(self.buffer, field: field::DAO_SEQUENCE)
  424. }
  425. /// Returns the DODAG ID, an IPv6 address, when it is present.
  426. #[inline]
  427. pub fn dao_dodag_id(&self) -> Option<Address> {
  428. if self.dao_dodag_id_present() {
  429. Some(Address::from_bytes(
  430. &self.buffer.as_ref()[field::DAO_DODAG_ID],
  431. ))
  432. } else {
  433. None
  434. }
  435. }
  436. }
  437. /// Setters for the Destination Advertisment Object (DAO) message.
  438. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  439. /// Set the Expect DAO-ACK flag.
  440. #[inline]
  441. pub fn set_dao_ack_request(&mut self, value: bool) {
  442. set!(self.buffer, value, bool, field: field::DAO_K, shift: 7, mask: 0b1,)
  443. }
  444. /// Set the flag indicating that the DODAG ID is present or not.
  445. #[inline]
  446. pub fn set_dao_dodag_id_present(&mut self, value: bool) {
  447. set!(self.buffer, value, bool, field: field::DAO_D, shift: 6, mask: 0b1)
  448. }
  449. /// Set the DODAG sequence flag.
  450. #[inline]
  451. pub fn set_dao_dodag_sequence(&mut self, value: u8) {
  452. set!(self.buffer, value, field: field::DAO_SEQUENCE)
  453. }
  454. /// Set the DODAG ID.
  455. #[inline]
  456. pub fn set_dao_dodag_id(&mut self, address: Option<Address>) {
  457. match address {
  458. Some(address) => {
  459. self.buffer.as_mut()[field::DAO_DODAG_ID].copy_from_slice(address.as_bytes());
  460. self.set_dao_dodag_id_present(true);
  461. }
  462. None => {
  463. self.set_dao_dodag_id_present(false);
  464. }
  465. }
  466. }
  467. }
  468. /// Getters for the Destination Advertisment Object acknowledgement (DAO-ACK) message.
  469. ///
  470. /// ```txt
  471. /// 0 1 2 3
  472. /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  473. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  474. /// | RPLInstanceID |D| Reserved | DAOSequence | Status |
  475. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  476. /// | |
  477. /// + +
  478. /// | |
  479. /// + DODAGID* +
  480. /// | |
  481. /// + +
  482. /// | |
  483. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  484. /// | Option(s)...
  485. /// +-+-+-+-+-+-+-+-+
  486. /// ```
  487. impl<T: AsRef<[u8]>> Packet<T> {
  488. /// Returns the flag indicating that the DODAG ID is present or not.
  489. #[inline]
  490. pub fn dao_ack_dodag_id_present(&self) -> bool {
  491. get!(self.buffer, bool, field: field::DAO_ACK_D, shift: 6, mask: 0b1)
  492. }
  493. /// Return the DODAG sequence number.
  494. #[inline]
  495. pub fn dao_ack_sequence(&self) -> u8 {
  496. get!(self.buffer, field: field::DAO_ACK_SEQUENCE)
  497. }
  498. /// Return the DOA status field.
  499. #[inline]
  500. pub fn dao_ack_status(&self) -> u8 {
  501. get!(self.buffer, field: field::DAO_ACK_STATUS)
  502. }
  503. /// Returns the DODAG ID, an IPv6 address, when it is present.
  504. #[inline]
  505. pub fn dao_ack_dodag_id(&self) -> Option<Address> {
  506. if self.dao_ack_dodag_id_present() {
  507. Some(Address::from_bytes(
  508. &self.buffer.as_ref()[field::DAO_ACK_DODAG_ID],
  509. ))
  510. } else {
  511. None
  512. }
  513. }
  514. }
  515. /// Setters for the Destination Advertisment Object acknowledgement (DAO-ACK) message.
  516. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  517. /// Set the flag indicating that the DODAG ID is present or not.
  518. #[inline]
  519. pub fn set_dao_ack_dodag_id_present(&mut self, value: bool) {
  520. set!(self.buffer, value, bool, field: field::DAO_ACK_D, shift: 6, mask: 0b1)
  521. }
  522. /// Set the DODAG sequence number.
  523. #[inline]
  524. pub fn set_dao_ack_sequence(&mut self, value: u8) {
  525. set!(self.buffer, value, field: field::DAO_ACK_SEQUENCE)
  526. }
  527. /// Set the DOA status field.
  528. #[inline]
  529. pub fn set_dao_ack_status(&mut self, value: u8) {
  530. set!(self.buffer, value, field: field::DAO_ACK_STATUS)
  531. }
  532. /// Set the DODAG ID.
  533. #[inline]
  534. pub fn set_dao_ack_dodag_id(&mut self, address: Option<Address>) {
  535. match address {
  536. Some(address) => {
  537. self.buffer.as_mut()[field::DAO_ACK_DODAG_ID].copy_from_slice(address.as_bytes());
  538. self.set_dao_ack_dodag_id_present(true);
  539. }
  540. None => {
  541. self.set_dao_ack_dodag_id_present(false);
  542. }
  543. }
  544. }
  545. }
  546. #[derive(Debug, PartialEq, Eq, Clone, Copy)]
  547. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  548. pub enum Repr<'p> {
  549. DodagInformationSolicitation {
  550. options: &'p [u8],
  551. },
  552. DodagInformationObject {
  553. rpl_instance_id: InstanceId,
  554. version_number: u8,
  555. rank: u16,
  556. grounded: bool,
  557. mode_of_operation: ModeOfOperation,
  558. dodag_preference: u8,
  559. dtsn: u8,
  560. dodag_id: Address,
  561. options: &'p [u8],
  562. },
  563. DestinationAdvertisementObject {
  564. rpl_instance_id: InstanceId,
  565. expect_ack: bool,
  566. sequence: u8,
  567. dodag_id: Option<Address>,
  568. options: &'p [u8],
  569. },
  570. DestinationAdvertisementObjectAck {
  571. rpl_instance_id: InstanceId,
  572. sequence: u8,
  573. status: u8,
  574. dodag_id: Option<Address>,
  575. },
  576. }
  577. impl core::fmt::Display for Repr<'_> {
  578. fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
  579. match self {
  580. Repr::DodagInformationSolicitation { .. } => {
  581. write!(f, "DIS")?;
  582. }
  583. Repr::DodagInformationObject {
  584. rpl_instance_id,
  585. version_number,
  586. rank,
  587. grounded,
  588. mode_of_operation,
  589. dodag_preference,
  590. dtsn,
  591. dodag_id,
  592. ..
  593. } => {
  594. write!(
  595. f,
  596. "DIO \
  597. IID={rpl_instance_id:?} \
  598. V={version_number} \
  599. R={rank} \
  600. G={grounded} \
  601. MOP={mode_of_operation:?} \
  602. Pref={dodag_preference} \
  603. DTSN={dtsn} \
  604. DODAGID={dodag_id}"
  605. )?;
  606. }
  607. Repr::DestinationAdvertisementObject {
  608. rpl_instance_id,
  609. expect_ack,
  610. sequence,
  611. dodag_id,
  612. ..
  613. } => {
  614. write!(
  615. f,
  616. "DAO \
  617. IID={rpl_instance_id:?} \
  618. Ack={expect_ack} \
  619. Seq={sequence} \
  620. DODAGID={dodag_id:?}",
  621. )?;
  622. }
  623. Repr::DestinationAdvertisementObjectAck {
  624. rpl_instance_id,
  625. sequence,
  626. status,
  627. dodag_id,
  628. ..
  629. } => {
  630. write!(
  631. f,
  632. "DAO-ACK \
  633. IID={rpl_instance_id:?} \
  634. Seq={sequence} \
  635. Status={status} \
  636. DODAGID={dodag_id:?}",
  637. )?;
  638. }
  639. };
  640. Ok(())
  641. }
  642. }
  643. impl<'p> Repr<'p> {
  644. pub fn set_options(&mut self, options: &'p [u8]) {
  645. let opts = match self {
  646. Repr::DodagInformationSolicitation { options } => options,
  647. Repr::DodagInformationObject { options, .. } => options,
  648. Repr::DestinationAdvertisementObject { options, .. } => options,
  649. Repr::DestinationAdvertisementObjectAck { .. } => unreachable!(),
  650. };
  651. *opts = options;
  652. }
  653. pub fn parse<T: AsRef<[u8]> + ?Sized>(packet: &Packet<&'p T>) -> Result<Self> {
  654. let options = packet.options()?;
  655. match RplControlMessage::from(packet.msg_code()) {
  656. RplControlMessage::DodagInformationSolicitation => {
  657. Ok(Repr::DodagInformationSolicitation { options })
  658. }
  659. RplControlMessage::DodagInformationObject => Ok(Repr::DodagInformationObject {
  660. rpl_instance_id: packet.rpl_instance_id(),
  661. version_number: packet.dio_version_number(),
  662. rank: packet.dio_rank(),
  663. grounded: packet.dio_grounded(),
  664. mode_of_operation: packet.dio_mode_of_operation(),
  665. dodag_preference: packet.dio_dodag_preference(),
  666. dtsn: packet.dio_dest_adv_trigger_seq_number(),
  667. dodag_id: packet.dio_dodag_id(),
  668. options,
  669. }),
  670. RplControlMessage::DestinationAdvertisementObject => {
  671. Ok(Repr::DestinationAdvertisementObject {
  672. rpl_instance_id: packet.rpl_instance_id(),
  673. expect_ack: packet.dao_ack_request(),
  674. sequence: packet.dao_dodag_sequence(),
  675. dodag_id: packet.dao_dodag_id(),
  676. options,
  677. })
  678. }
  679. RplControlMessage::DestinationAdvertisementObjectAck => {
  680. Ok(Repr::DestinationAdvertisementObjectAck {
  681. rpl_instance_id: packet.rpl_instance_id(),
  682. sequence: packet.dao_ack_sequence(),
  683. status: packet.dao_ack_status(),
  684. dodag_id: packet.dao_ack_dodag_id(),
  685. })
  686. }
  687. RplControlMessage::SecureDodagInformationSolicitation
  688. | RplControlMessage::SecureDodagInformationObject
  689. | RplControlMessage::SecureDesintationAdvertismentObject
  690. | RplControlMessage::SecureDestinationAdvertisementObjectAck
  691. | RplControlMessage::ConsistencyCheck => Err(Error),
  692. RplControlMessage::Unknown(_) => Err(Error),
  693. }
  694. }
  695. pub fn buffer_len(&self) -> usize {
  696. let mut len = 4 + match self {
  697. Repr::DodagInformationSolicitation { .. } => 2,
  698. Repr::DodagInformationObject { .. } => 24,
  699. Repr::DestinationAdvertisementObject { dodag_id, .. } => {
  700. if dodag_id.is_some() {
  701. 20
  702. } else {
  703. 4
  704. }
  705. }
  706. Repr::DestinationAdvertisementObjectAck { dodag_id, .. } => {
  707. if dodag_id.is_some() {
  708. 20
  709. } else {
  710. 4
  711. }
  712. }
  713. };
  714. let opts = match self {
  715. Repr::DodagInformationSolicitation { options } => &options[..],
  716. Repr::DodagInformationObject { options, .. } => &options[..],
  717. Repr::DestinationAdvertisementObject { options, .. } => &options[..],
  718. Repr::DestinationAdvertisementObjectAck { .. } => &[],
  719. };
  720. len += opts.len();
  721. len
  722. }
  723. pub fn emit<T: AsRef<[u8]> + AsMut<[u8]> + ?Sized>(&self, packet: &mut Packet<&mut T>) {
  724. packet.set_msg_type(crate::wire::icmpv6::Message::RplControl);
  725. match self {
  726. Repr::DodagInformationSolicitation { .. } => {
  727. packet.set_msg_code(RplControlMessage::DodagInformationSolicitation.into());
  728. packet.clear_dis_flags();
  729. packet.clear_dis_reserved();
  730. }
  731. Repr::DodagInformationObject {
  732. rpl_instance_id,
  733. version_number,
  734. rank,
  735. grounded,
  736. mode_of_operation,
  737. dodag_preference,
  738. dtsn,
  739. dodag_id,
  740. ..
  741. } => {
  742. packet.set_msg_code(RplControlMessage::DodagInformationObject.into());
  743. packet.set_rpl_instance_id((*rpl_instance_id).into());
  744. packet.set_dio_version_number(*version_number);
  745. packet.set_dio_rank(*rank);
  746. packet.set_dio_grounded(*grounded);
  747. packet.set_dio_mode_of_operation(*mode_of_operation);
  748. packet.set_dio_dodag_preference(*dodag_preference);
  749. packet.set_dio_dest_adv_trigger_seq_number(*dtsn);
  750. packet.set_dio_dodag_id(*dodag_id);
  751. }
  752. Repr::DestinationAdvertisementObject {
  753. rpl_instance_id,
  754. expect_ack,
  755. sequence,
  756. dodag_id,
  757. ..
  758. } => {
  759. packet.set_msg_code(RplControlMessage::DestinationAdvertisementObject.into());
  760. packet.set_rpl_instance_id((*rpl_instance_id).into());
  761. packet.set_dao_ack_request(*expect_ack);
  762. packet.set_dao_dodag_sequence(*sequence);
  763. packet.set_dao_dodag_id(*dodag_id);
  764. }
  765. Repr::DestinationAdvertisementObjectAck {
  766. rpl_instance_id,
  767. sequence,
  768. status,
  769. dodag_id,
  770. ..
  771. } => {
  772. packet.set_msg_code(RplControlMessage::DestinationAdvertisementObjectAck.into());
  773. packet.set_rpl_instance_id((*rpl_instance_id).into());
  774. packet.set_dao_ack_sequence(*sequence);
  775. packet.set_dao_ack_status(*status);
  776. packet.set_dao_ack_dodag_id(*dodag_id);
  777. }
  778. }
  779. let options = match self {
  780. Repr::DodagInformationSolicitation { options } => &options[..],
  781. Repr::DodagInformationObject { options, .. } => &options[..],
  782. Repr::DestinationAdvertisementObject { options, .. } => &options[..],
  783. Repr::DestinationAdvertisementObjectAck { .. } => &[],
  784. };
  785. packet.options_mut().copy_from_slice(options);
  786. }
  787. }
  788. pub mod options {
  789. use byteorder::{ByteOrder, NetworkEndian};
  790. use super::{Error, InstanceId, Result};
  791. use crate::wire::ipv6::Address;
  792. /// A read/write wrapper around a RPL Control Message Option.
  793. #[derive(Debug, Clone)]
  794. pub struct Packet<T: AsRef<[u8]>> {
  795. buffer: T,
  796. }
  797. enum_with_unknown! {
  798. pub enum OptionType(u8) {
  799. Pad1 = 0x00,
  800. PadN = 0x01,
  801. DagMetricContainer = 0x02,
  802. RouteInformation = 0x03,
  803. DodagConfiguration = 0x04,
  804. RplTarget = 0x05,
  805. TransitInformation = 0x06,
  806. SolicitedInformation = 0x07,
  807. PrefixInformation = 0x08,
  808. RplTargetDescriptor = 0x09,
  809. }
  810. }
  811. impl From<&Repr<'_>> for OptionType {
  812. fn from(repr: &Repr) -> Self {
  813. match repr {
  814. Repr::Pad1 => Self::Pad1,
  815. Repr::PadN(_) => Self::PadN,
  816. Repr::DagMetricContainer => Self::DagMetricContainer,
  817. Repr::RouteInformation { .. } => Self::RouteInformation,
  818. Repr::DodagConfiguration { .. } => Self::DodagConfiguration,
  819. Repr::RplTarget { .. } => Self::RplTarget,
  820. Repr::TransitInformation { .. } => Self::TransitInformation,
  821. Repr::SolicitedInformation { .. } => Self::SolicitedInformation,
  822. Repr::PrefixInformation { .. } => Self::PrefixInformation,
  823. Repr::RplTargetDescriptor { .. } => Self::RplTargetDescriptor,
  824. }
  825. }
  826. }
  827. mod field {
  828. use crate::wire::field::*;
  829. // Generic fields.
  830. pub const TYPE: usize = 0;
  831. pub const LENGTH: usize = 1;
  832. pub const PADN: Rest = 2..;
  833. // Route Information fields.
  834. pub const ROUTE_INFO_PREFIX_LENGTH: usize = 2;
  835. pub const ROUTE_INFO_RESERVED: usize = 3;
  836. pub const ROUTE_INFO_PREFERENCE: usize = 3;
  837. pub const ROUTE_INFO_LIFETIME: Field = 4..9;
  838. // DODAG Configuration fields.
  839. pub const DODAG_CONF_FLAGS: usize = 2;
  840. pub const DODAG_CONF_AUTHENTICATION_ENABLED: usize = 2;
  841. pub const DODAG_CONF_PATH_CONTROL_SIZE: usize = 2;
  842. pub const DODAG_CONF_DIO_INTERVAL_DOUBLINGS: usize = 3;
  843. pub const DODAG_CONF_DIO_INTERVAL_MINIMUM: usize = 4;
  844. pub const DODAG_CONF_DIO_REDUNDANCY_CONSTANT: usize = 5;
  845. pub const DODAG_CONF_DIO_MAX_RANK_INCREASE: Field = 6..8;
  846. pub const DODAG_CONF_MIN_HOP_RANK_INCREASE: Field = 8..10;
  847. pub const DODAG_CONF_OBJECTIVE_CODE_POINT: Field = 10..12;
  848. pub const DODAG_CONF_DEFAULT_LIFETIME: usize = 13;
  849. pub const DODAG_CONF_LIFETIME_UNIT: Field = 14..16;
  850. // RPL Target fields.
  851. pub const RPL_TARGET_FLAGS: usize = 2;
  852. pub const RPL_TARGET_PREFIX_LENGTH: usize = 3;
  853. // Transit Information fields.
  854. pub const TRANSIT_INFO_FLAGS: usize = 2;
  855. pub const TRANSIT_INFO_EXTERNAL: usize = 2;
  856. pub const TRANSIT_INFO_PATH_CONTROL: usize = 3;
  857. pub const TRANSIT_INFO_PATH_SEQUENCE: usize = 4;
  858. pub const TRANSIT_INFO_PATH_LIFETIME: usize = 5;
  859. pub const TRANSIT_INFO_PARENT_ADDRESS: Field = 6..6 + 16;
  860. // Solicited Information fields.
  861. pub const SOLICITED_INFO_RPL_INSTANCE_ID: usize = 2;
  862. pub const SOLICITED_INFO_FLAGS: usize = 3;
  863. pub const SOLICITED_INFO_VERSION_PREDICATE: usize = 3;
  864. pub const SOLICITED_INFO_INSTANCE_ID_PREDICATE: usize = 3;
  865. pub const SOLICITED_INFO_DODAG_ID_PREDICATE: usize = 3;
  866. pub const SOLICITED_INFO_DODAG_ID: Field = 4..20;
  867. pub const SOLICITED_INFO_VERSION_NUMBER: usize = 20;
  868. // Prefix Information fields.
  869. pub const PREFIX_INFO_PREFIX_LENGTH: usize = 2;
  870. pub const PREFIX_INFO_RESERVED1: usize = 3;
  871. pub const PREFIX_INFO_ON_LINK: usize = 3;
  872. pub const PREFIX_INFO_AUTONOMOUS_CONF: usize = 3;
  873. pub const PREFIX_INFO_ROUTER_ADDRESS_FLAG: usize = 3;
  874. pub const PREFIX_INFO_VALID_LIFETIME: Field = 4..8;
  875. pub const PREFIX_INFO_PREFERRED_LIFETIME: Field = 8..12;
  876. pub const PREFIX_INFO_RESERVED2: Field = 12..16;
  877. pub const PREFIX_INFO_PREFIX: Field = 16..16 + 16;
  878. // RPL Target Descriptor fields.
  879. pub const TARGET_DESCRIPTOR: Field = 2..6;
  880. }
  881. /// Getters for the RPL Control Message Options.
  882. impl<T: AsRef<[u8]>> Packet<T> {
  883. /// Imbue a raw octet buffer with RPL Control Message Option structure.
  884. #[inline]
  885. pub fn new_unchecked(buffer: T) -> Self {
  886. Packet { buffer }
  887. }
  888. #[inline]
  889. pub fn new_checked(buffer: T) -> Result<Self> {
  890. if buffer.as_ref().is_empty() {
  891. return Err(Error);
  892. }
  893. Ok(Packet { buffer })
  894. }
  895. /// Return the type field.
  896. #[inline]
  897. pub fn option_type(&self) -> OptionType {
  898. OptionType::from(self.buffer.as_ref()[field::TYPE])
  899. }
  900. /// Return the length field.
  901. #[inline]
  902. pub fn option_length(&self) -> u8 {
  903. get!(self.buffer, field: field::LENGTH)
  904. }
  905. }
  906. impl<'p, T: AsRef<[u8]> + ?Sized> Packet<&'p T> {
  907. /// Return a pointer to the next option.
  908. #[inline]
  909. pub fn next_option(&self) -> Option<&'p [u8]> {
  910. if !self.buffer.as_ref().is_empty() {
  911. match self.option_type() {
  912. OptionType::Pad1 => Some(&self.buffer.as_ref()[1..]),
  913. OptionType::Unknown(_) => unreachable!(),
  914. _ => {
  915. let len = self.option_length();
  916. Some(&self.buffer.as_ref()[2 + len as usize..])
  917. }
  918. }
  919. } else {
  920. None
  921. }
  922. }
  923. }
  924. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  925. /// Set the Option Type field.
  926. #[inline]
  927. pub fn set_option_type(&mut self, option_type: OptionType) {
  928. self.buffer.as_mut()[field::TYPE] = option_type.into();
  929. }
  930. /// Set the Option Length field.
  931. #[inline]
  932. pub fn set_option_length(&mut self, length: u8) {
  933. self.buffer.as_mut()[field::LENGTH] = length;
  934. }
  935. }
  936. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  937. #[inline]
  938. pub fn clear_padn(&mut self, size: u8) {
  939. for b in &mut self.buffer.as_mut()[field::PADN][..size as usize] {
  940. *b = 0;
  941. }
  942. }
  943. }
  944. /// Getters for the DAG Metric Container Option Message.
  945. /// Getters for the Route Information Option Message.
  946. ///
  947. /// ```txt
  948. /// 0 1 2 3
  949. /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  950. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  951. /// | Type = 0x03 | Option Length | Prefix Length |Resvd|Prf|Resvd|
  952. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  953. /// | Route Lifetime |
  954. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  955. /// | |
  956. /// . Prefix (Variable Length) .
  957. /// . .
  958. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  959. /// ```
  960. impl<T: AsRef<[u8]>> Packet<T> {
  961. /// Return the Prefix Length field.
  962. #[inline]
  963. pub fn prefix_length(&self) -> u8 {
  964. get!(self.buffer, field: field::ROUTE_INFO_PREFIX_LENGTH)
  965. }
  966. /// Return the Route Preference field.
  967. #[inline]
  968. pub fn route_preference(&self) -> u8 {
  969. (self.buffer.as_ref()[field::ROUTE_INFO_PREFERENCE] & 0b0001_1000) >> 3
  970. }
  971. /// Return the Route Lifetime field.
  972. #[inline]
  973. pub fn route_lifetime(&self) -> u32 {
  974. get!(self.buffer, u32, field: field::ROUTE_INFO_LIFETIME)
  975. }
  976. }
  977. impl<'p, T: AsRef<[u8]> + ?Sized> Packet<&'p T> {
  978. /// Return the Prefix field.
  979. #[inline]
  980. pub fn prefix(&self) -> &'p [u8] {
  981. let option_len = self.option_length();
  982. &self.buffer.as_ref()[field::ROUTE_INFO_LIFETIME.end..]
  983. [..option_len as usize - field::ROUTE_INFO_LIFETIME.end]
  984. }
  985. }
  986. /// Setters for the Route Information Option Message.
  987. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  988. /// Set the Prefix Length field.
  989. #[inline]
  990. pub fn set_route_info_prefix_length(&mut self, value: u8) {
  991. set!(self.buffer, value, field: field::ROUTE_INFO_PREFIX_LENGTH)
  992. }
  993. /// Set the Route Preference field.
  994. #[inline]
  995. pub fn set_route_info_route_preference(&mut self, _value: u8) {
  996. todo!();
  997. }
  998. /// Set the Route Lifetime field.
  999. #[inline]
  1000. pub fn set_route_info_route_lifetime(&mut self, value: u32) {
  1001. set!(self.buffer, value, u32, field: field::ROUTE_INFO_LIFETIME)
  1002. }
  1003. /// Set the prefix field.
  1004. #[inline]
  1005. pub fn set_route_info_prefix(&mut self, _prefix: &[u8]) {
  1006. todo!();
  1007. }
  1008. /// Clear the reserved field.
  1009. #[inline]
  1010. pub fn clear_route_info_reserved(&mut self) {
  1011. self.buffer.as_mut()[field::ROUTE_INFO_RESERVED] = 0;
  1012. }
  1013. }
  1014. /// Getters for the DODAG Configuration Option Message.
  1015. ///
  1016. /// ```txt
  1017. /// 0 1 2 3
  1018. /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  1019. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1020. /// | Type = 0x04 |Opt Length = 14| Flags |A| PCS | DIOIntDoubl. |
  1021. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1022. /// | DIOIntMin. | DIORedun. | MaxRankIncrease |
  1023. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1024. /// | MinHopRankIncrease | OCP |
  1025. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1026. /// | Reserved | Def. Lifetime | Lifetime Unit |
  1027. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1028. /// ```
  1029. impl<T: AsRef<[u8]>> Packet<T> {
  1030. /// Return the Authentication Enabled field.
  1031. #[inline]
  1032. pub fn authentication_enabled(&self) -> bool {
  1033. get!(
  1034. self.buffer,
  1035. bool,
  1036. field: field::DODAG_CONF_AUTHENTICATION_ENABLED,
  1037. shift: 3,
  1038. mask: 0b1
  1039. )
  1040. }
  1041. /// Return the Path Control Size field.
  1042. #[inline]
  1043. pub fn path_control_size(&self) -> u8 {
  1044. get!(self.buffer, field: field::DODAG_CONF_PATH_CONTROL_SIZE, mask: 0b111)
  1045. }
  1046. /// Return the DIO Interval Doublings field.
  1047. #[inline]
  1048. pub fn dio_interval_doublings(&self) -> u8 {
  1049. get!(self.buffer, field: field::DODAG_CONF_DIO_INTERVAL_DOUBLINGS)
  1050. }
  1051. /// Return the DIO Interval Minimum field.
  1052. #[inline]
  1053. pub fn dio_interval_minimum(&self) -> u8 {
  1054. get!(self.buffer, field: field::DODAG_CONF_DIO_INTERVAL_MINIMUM)
  1055. }
  1056. /// Return the DIO Redundancy Constant field.
  1057. #[inline]
  1058. pub fn dio_redundancy_constant(&self) -> u8 {
  1059. get!(
  1060. self.buffer,
  1061. field: field::DODAG_CONF_DIO_REDUNDANCY_CONSTANT
  1062. )
  1063. }
  1064. /// Return the Max Rank Increase field.
  1065. #[inline]
  1066. pub fn max_rank_increase(&self) -> u16 {
  1067. get!(
  1068. self.buffer,
  1069. u16,
  1070. field: field::DODAG_CONF_DIO_MAX_RANK_INCREASE
  1071. )
  1072. }
  1073. /// Return the Minimum Hop Rank Increase field.
  1074. #[inline]
  1075. pub fn minimum_hop_rank_increase(&self) -> u16 {
  1076. get!(
  1077. self.buffer,
  1078. u16,
  1079. field: field::DODAG_CONF_MIN_HOP_RANK_INCREASE
  1080. )
  1081. }
  1082. /// Return the Objective Code Point field.
  1083. #[inline]
  1084. pub fn objective_code_point(&self) -> u16 {
  1085. get!(
  1086. self.buffer,
  1087. u16,
  1088. field: field::DODAG_CONF_OBJECTIVE_CODE_POINT
  1089. )
  1090. }
  1091. /// Return the Default Lifetime field.
  1092. #[inline]
  1093. pub fn default_lifetime(&self) -> u8 {
  1094. get!(self.buffer, field: field::DODAG_CONF_DEFAULT_LIFETIME)
  1095. }
  1096. /// Return the Lifetime Unit field.
  1097. #[inline]
  1098. pub fn lifetime_unit(&self) -> u16 {
  1099. get!(self.buffer, u16, field: field::DODAG_CONF_LIFETIME_UNIT)
  1100. }
  1101. }
  1102. /// Getters for the DODAG Configuration Option Message.
  1103. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  1104. /// Clear the Flags field.
  1105. #[inline]
  1106. pub fn clear_dodag_conf_flags(&mut self) {
  1107. self.buffer.as_mut()[field::DODAG_CONF_FLAGS] = 0;
  1108. }
  1109. /// Set the Authentication Enabled field.
  1110. #[inline]
  1111. pub fn set_dodag_conf_authentication_enabled(&mut self, value: bool) {
  1112. set!(
  1113. self.buffer,
  1114. value,
  1115. bool,
  1116. field: field::DODAG_CONF_AUTHENTICATION_ENABLED,
  1117. shift: 3,
  1118. mask: 0b1
  1119. )
  1120. }
  1121. /// Set the Path Control Size field.
  1122. #[inline]
  1123. pub fn set_dodag_conf_path_control_size(&mut self, value: u8) {
  1124. set!(
  1125. self.buffer,
  1126. value,
  1127. field: field::DODAG_CONF_PATH_CONTROL_SIZE,
  1128. mask: 0b111
  1129. )
  1130. }
  1131. /// Set the DIO Interval Doublings field.
  1132. #[inline]
  1133. pub fn set_dodag_conf_dio_interval_doublings(&mut self, value: u8) {
  1134. set!(
  1135. self.buffer,
  1136. value,
  1137. field: field::DODAG_CONF_DIO_INTERVAL_DOUBLINGS
  1138. )
  1139. }
  1140. /// Set the DIO Interval Minimum field.
  1141. #[inline]
  1142. pub fn set_dodag_conf_dio_interval_minimum(&mut self, value: u8) {
  1143. set!(
  1144. self.buffer,
  1145. value,
  1146. field: field::DODAG_CONF_DIO_INTERVAL_MINIMUM
  1147. )
  1148. }
  1149. /// Set the DIO Redundancy Constant field.
  1150. #[inline]
  1151. pub fn set_dodag_conf_dio_redundancy_constant(&mut self, value: u8) {
  1152. set!(
  1153. self.buffer,
  1154. value,
  1155. field: field::DODAG_CONF_DIO_REDUNDANCY_CONSTANT
  1156. )
  1157. }
  1158. /// Set the Max Rank Increase field.
  1159. #[inline]
  1160. pub fn set_dodag_conf_max_rank_increase(&mut self, value: u16) {
  1161. set!(
  1162. self.buffer,
  1163. value,
  1164. u16,
  1165. field: field::DODAG_CONF_DIO_MAX_RANK_INCREASE
  1166. )
  1167. }
  1168. /// Set the Minimum Hop Rank Increase field.
  1169. #[inline]
  1170. pub fn set_dodag_conf_minimum_hop_rank_increase(&mut self, value: u16) {
  1171. set!(
  1172. self.buffer,
  1173. value,
  1174. u16,
  1175. field: field::DODAG_CONF_MIN_HOP_RANK_INCREASE
  1176. )
  1177. }
  1178. /// Set the Objective Code Point field.
  1179. #[inline]
  1180. pub fn set_dodag_conf_objective_code_point(&mut self, value: u16) {
  1181. set!(
  1182. self.buffer,
  1183. value,
  1184. u16,
  1185. field: field::DODAG_CONF_OBJECTIVE_CODE_POINT
  1186. )
  1187. }
  1188. /// Set the Default Lifetime field.
  1189. #[inline]
  1190. pub fn set_dodag_conf_default_lifetime(&mut self, value: u8) {
  1191. set!(
  1192. self.buffer,
  1193. value,
  1194. field: field::DODAG_CONF_DEFAULT_LIFETIME
  1195. )
  1196. }
  1197. /// Set the Lifetime Unit field.
  1198. #[inline]
  1199. pub fn set_dodag_conf_lifetime_unit(&mut self, value: u16) {
  1200. set!(
  1201. self.buffer,
  1202. value,
  1203. u16,
  1204. field: field::DODAG_CONF_LIFETIME_UNIT
  1205. )
  1206. }
  1207. }
  1208. /// Getters for the RPL Target Option Message.
  1209. ///
  1210. /// ```txt
  1211. /// 0 1 2 3
  1212. /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  1213. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1214. /// | Type = 0x05 | Option Length | Flags | Prefix Length |
  1215. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1216. /// | |
  1217. /// + +
  1218. /// | Target Prefix (Variable Length) |
  1219. /// . .
  1220. /// . .
  1221. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1222. /// ```
  1223. impl<T: AsRef<[u8]>> Packet<T> {
  1224. /// Return the Target Prefix Length field.
  1225. pub fn target_prefix_length(&self) -> u8 {
  1226. get!(self.buffer, field: field::RPL_TARGET_PREFIX_LENGTH)
  1227. }
  1228. }
  1229. impl<'p, T: AsRef<[u8]> + ?Sized> Packet<&'p T> {
  1230. /// Return the Target Prefix field.
  1231. #[inline]
  1232. pub fn target_prefix(&self) -> &'p [u8] {
  1233. let option_len = self.option_length();
  1234. &self.buffer.as_ref()[field::RPL_TARGET_PREFIX_LENGTH + 1..]
  1235. [..option_len as usize - field::RPL_TARGET_PREFIX_LENGTH + 1]
  1236. }
  1237. }
  1238. /// Setters for the RPL Target Option Message.
  1239. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  1240. /// Clear the Flags field.
  1241. #[inline]
  1242. pub fn clear_rpl_target_flags(&mut self) {
  1243. self.buffer.as_mut()[field::RPL_TARGET_FLAGS] = 0;
  1244. }
  1245. /// Set the Target Prefix Length field.
  1246. #[inline]
  1247. pub fn set_rpl_target_prefix_length(&mut self, value: u8) {
  1248. set!(self.buffer, value, field: field::RPL_TARGET_PREFIX_LENGTH)
  1249. }
  1250. /// Set the Target Prefix field.
  1251. #[inline]
  1252. pub fn set_rpl_target_prefix(&mut self, prefix: &[u8]) {
  1253. self.buffer.as_mut()[field::RPL_TARGET_PREFIX_LENGTH + 1..][..prefix.len()]
  1254. .copy_from_slice(prefix);
  1255. }
  1256. }
  1257. /// Getters for the Transit Information Option Message.
  1258. ///
  1259. /// ```txt
  1260. /// 0 1 2 3
  1261. /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  1262. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1263. /// | Type = 0x06 | Option Length |E| Flags | Path Control |
  1264. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1265. /// | Path Sequence | Path Lifetime | |
  1266. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
  1267. /// | |
  1268. /// + +
  1269. /// | |
  1270. /// + Parent Address* +
  1271. /// | |
  1272. /// + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1273. /// | |
  1274. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1275. /// ```
  1276. impl<T: AsRef<[u8]>> Packet<T> {
  1277. /// Return the External flag.
  1278. #[inline]
  1279. pub fn is_external(&self) -> bool {
  1280. get!(
  1281. self.buffer,
  1282. bool,
  1283. field: field::TRANSIT_INFO_EXTERNAL,
  1284. shift: 7,
  1285. mask: 0b1,
  1286. )
  1287. }
  1288. /// Return the Path Control field.
  1289. #[inline]
  1290. pub fn path_control(&self) -> u8 {
  1291. get!(self.buffer, field: field::TRANSIT_INFO_PATH_CONTROL)
  1292. }
  1293. /// Return the Path Sequence field.
  1294. #[inline]
  1295. pub fn path_sequence(&self) -> u8 {
  1296. get!(self.buffer, field: field::TRANSIT_INFO_PATH_SEQUENCE)
  1297. }
  1298. /// Return the Path Lifetime field.
  1299. #[inline]
  1300. pub fn path_lifetime(&self) -> u8 {
  1301. get!(self.buffer, field: field::TRANSIT_INFO_PATH_LIFETIME)
  1302. }
  1303. /// Return the Parent Address field.
  1304. #[inline]
  1305. pub fn parent_address(&self) -> Option<Address> {
  1306. if self.option_length() > 5 {
  1307. Some(Address::from_bytes(
  1308. &self.buffer.as_ref()[field::TRANSIT_INFO_PARENT_ADDRESS],
  1309. ))
  1310. } else {
  1311. None
  1312. }
  1313. }
  1314. }
  1315. /// Setters for the Transit Information Option Message.
  1316. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  1317. /// Clear the Flags field.
  1318. #[inline]
  1319. pub fn clear_transit_info_flags(&mut self) {
  1320. self.buffer.as_mut()[field::TRANSIT_INFO_FLAGS] = 0;
  1321. }
  1322. /// Set the External flag.
  1323. #[inline]
  1324. pub fn set_transit_info_is_external(&mut self, value: bool) {
  1325. set!(
  1326. self.buffer,
  1327. value,
  1328. bool,
  1329. field: field::TRANSIT_INFO_EXTERNAL,
  1330. shift: 7,
  1331. mask: 0b1
  1332. )
  1333. }
  1334. /// Set the Path Control field.
  1335. #[inline]
  1336. pub fn set_transit_info_path_control(&mut self, value: u8) {
  1337. set!(self.buffer, value, field: field::TRANSIT_INFO_PATH_CONTROL)
  1338. }
  1339. /// Set the Path Sequence field.
  1340. #[inline]
  1341. pub fn set_transit_info_path_sequence(&mut self, value: u8) {
  1342. set!(self.buffer, value, field: field::TRANSIT_INFO_PATH_SEQUENCE)
  1343. }
  1344. /// Set the Path Lifetime field.
  1345. #[inline]
  1346. pub fn set_transit_info_path_lifetime(&mut self, value: u8) {
  1347. set!(self.buffer, value, field: field::TRANSIT_INFO_PATH_LIFETIME)
  1348. }
  1349. /// Set the Parent Address field.
  1350. #[inline]
  1351. pub fn set_transit_info_parent_address(&mut self, address: Address) {
  1352. self.buffer.as_mut()[field::TRANSIT_INFO_PARENT_ADDRESS]
  1353. .copy_from_slice(address.as_bytes());
  1354. }
  1355. }
  1356. /// Getters for the Solicited Information Option Message.
  1357. ///
  1358. /// ```txt
  1359. /// 0 1 2 3
  1360. /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  1361. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1362. /// | Type = 0x07 |Opt Length = 19| RPLInstanceID |V|I|D| Flags |
  1363. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1364. /// | |
  1365. /// + +
  1366. /// | |
  1367. /// + DODAGID +
  1368. /// | |
  1369. /// + +
  1370. /// | |
  1371. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1372. /// |Version Number |
  1373. /// +-+-+-+-+-+-+-+-+
  1374. /// ```
  1375. impl<T: AsRef<[u8]>> Packet<T> {
  1376. /// Return the RPL Instance ID field.
  1377. #[inline]
  1378. pub fn rpl_instance_id(&self) -> u8 {
  1379. get!(self.buffer, field: field::SOLICITED_INFO_RPL_INSTANCE_ID)
  1380. }
  1381. /// Return the Version Predicate flag.
  1382. #[inline]
  1383. pub fn version_predicate(&self) -> bool {
  1384. get!(
  1385. self.buffer,
  1386. bool,
  1387. field: field::SOLICITED_INFO_VERSION_PREDICATE,
  1388. shift: 7,
  1389. mask: 0b1,
  1390. )
  1391. }
  1392. /// Return the Instance ID Predicate flag.
  1393. #[inline]
  1394. pub fn instance_id_predicate(&self) -> bool {
  1395. get!(
  1396. self.buffer,
  1397. bool,
  1398. field: field::SOLICITED_INFO_INSTANCE_ID_PREDICATE,
  1399. shift: 6,
  1400. mask: 0b1,
  1401. )
  1402. }
  1403. /// Return the DODAG Predicate ID flag.
  1404. #[inline]
  1405. pub fn dodag_id_predicate(&self) -> bool {
  1406. get!(
  1407. self.buffer,
  1408. bool,
  1409. field: field::SOLICITED_INFO_DODAG_ID_PREDICATE,
  1410. shift: 5,
  1411. mask: 0b1,
  1412. )
  1413. }
  1414. /// Return the DODAG ID field.
  1415. #[inline]
  1416. pub fn dodag_id(&self) -> Address {
  1417. get!(
  1418. self.buffer,
  1419. into: Address,
  1420. fun: from_bytes,
  1421. field: field::SOLICITED_INFO_DODAG_ID
  1422. )
  1423. }
  1424. /// Return the Version Number field.
  1425. #[inline]
  1426. pub fn version_number(&self) -> u8 {
  1427. get!(self.buffer, field: field::SOLICITED_INFO_VERSION_NUMBER)
  1428. }
  1429. }
  1430. /// Setters for the Solicited Information Option Message.
  1431. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  1432. /// Clear the Flags field.
  1433. #[inline]
  1434. pub fn clear_solicited_info_flags(&mut self) {
  1435. self.buffer.as_mut()[field::SOLICITED_INFO_FLAGS] = 0;
  1436. }
  1437. /// Set the RPL Instance ID field.
  1438. #[inline]
  1439. pub fn set_solicited_info_rpl_instance_id(&mut self, value: u8) {
  1440. set!(
  1441. self.buffer,
  1442. value,
  1443. field: field::SOLICITED_INFO_RPL_INSTANCE_ID
  1444. )
  1445. }
  1446. /// Set the Version Predicate flag.
  1447. #[inline]
  1448. pub fn set_solicited_info_version_predicate(&mut self, value: bool) {
  1449. set!(
  1450. self.buffer,
  1451. value,
  1452. bool,
  1453. field: field::SOLICITED_INFO_VERSION_PREDICATE,
  1454. shift: 7,
  1455. mask: 0b1
  1456. )
  1457. }
  1458. /// Set the Instance ID Predicate flag.
  1459. #[inline]
  1460. pub fn set_solicited_info_instance_id_predicate(&mut self, value: bool) {
  1461. set!(
  1462. self.buffer,
  1463. value,
  1464. bool,
  1465. field: field::SOLICITED_INFO_INSTANCE_ID_PREDICATE,
  1466. shift: 6,
  1467. mask: 0b1
  1468. )
  1469. }
  1470. /// Set the DODAG Predicate ID flag.
  1471. #[inline]
  1472. pub fn set_solicited_info_dodag_id_predicate(&mut self, value: bool) {
  1473. set!(
  1474. self.buffer,
  1475. value,
  1476. bool,
  1477. field: field::SOLICITED_INFO_DODAG_ID_PREDICATE,
  1478. shift: 5,
  1479. mask: 0b1
  1480. )
  1481. }
  1482. /// Set the DODAG ID field.
  1483. #[inline]
  1484. pub fn set_solicited_info_dodag_id(&mut self, address: Address) {
  1485. set!(
  1486. self.buffer,
  1487. address: address,
  1488. field: field::SOLICITED_INFO_DODAG_ID
  1489. )
  1490. }
  1491. /// Set the Version Number field.
  1492. #[inline]
  1493. pub fn set_solicited_info_version_number(&mut self, value: u8) {
  1494. set!(
  1495. self.buffer,
  1496. value,
  1497. field: field::SOLICITED_INFO_VERSION_NUMBER
  1498. )
  1499. }
  1500. }
  1501. /// Getters for the Prefix Information Option Message.
  1502. ///
  1503. /// ```txt
  1504. /// 0 1 2 3
  1505. /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  1506. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1507. /// | Type = 0x08 |Opt Length = 30| Prefix Length |L|A|R|Reserved1|
  1508. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1509. /// | Valid Lifetime |
  1510. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1511. /// | Preferred Lifetime |
  1512. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1513. /// | Reserved2 |
  1514. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1515. /// | |
  1516. /// + +
  1517. /// | |
  1518. /// + Prefix +
  1519. /// | |
  1520. /// + +
  1521. /// | |
  1522. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1523. /// ```
  1524. impl<T: AsRef<[u8]>> Packet<T> {
  1525. /// Return the Prefix Length field.
  1526. #[inline]
  1527. pub fn prefix_info_prefix_length(&self) -> u8 {
  1528. get!(self.buffer, field: field::PREFIX_INFO_PREFIX_LENGTH)
  1529. }
  1530. /// Return the On-Link flag.
  1531. #[inline]
  1532. pub fn on_link(&self) -> bool {
  1533. get!(
  1534. self.buffer,
  1535. bool,
  1536. field: field::PREFIX_INFO_ON_LINK,
  1537. shift: 7,
  1538. mask: 0b1,
  1539. )
  1540. }
  1541. /// Return the Autonomous Address-Configuration flag.
  1542. #[inline]
  1543. pub fn autonomous_address_configuration(&self) -> bool {
  1544. get!(
  1545. self.buffer,
  1546. bool,
  1547. field: field::PREFIX_INFO_AUTONOMOUS_CONF,
  1548. shift: 6,
  1549. mask: 0b1,
  1550. )
  1551. }
  1552. /// Return the Router Address flag.
  1553. #[inline]
  1554. pub fn router_address(&self) -> bool {
  1555. get!(
  1556. self.buffer,
  1557. bool,
  1558. field: field::PREFIX_INFO_ROUTER_ADDRESS_FLAG,
  1559. shift: 5,
  1560. mask: 0b1,
  1561. )
  1562. }
  1563. /// Return the Valid Lifetime field.
  1564. #[inline]
  1565. pub fn valid_lifetime(&self) -> u32 {
  1566. get!(self.buffer, u32, field: field::PREFIX_INFO_VALID_LIFETIME)
  1567. }
  1568. /// Return the Preferred Lifetime field.
  1569. #[inline]
  1570. pub fn preferred_lifetime(&self) -> u32 {
  1571. get!(
  1572. self.buffer,
  1573. u32,
  1574. field: field::PREFIX_INFO_PREFERRED_LIFETIME
  1575. )
  1576. }
  1577. }
  1578. impl<'p, T: AsRef<[u8]> + ?Sized> Packet<&'p T> {
  1579. /// Return the Prefix field.
  1580. #[inline]
  1581. pub fn destination_prefix(&self) -> &'p [u8] {
  1582. &self.buffer.as_ref()[field::PREFIX_INFO_PREFIX]
  1583. }
  1584. }
  1585. /// Setters for the Prefix Information Option Message.
  1586. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  1587. /// Clear the reserved fields.
  1588. #[inline]
  1589. pub fn clear_prefix_info_reserved(&mut self) {
  1590. self.buffer.as_mut()[field::PREFIX_INFO_RESERVED1] = 0;
  1591. self.buffer.as_mut()[field::PREFIX_INFO_RESERVED2].copy_from_slice(&[0; 4]);
  1592. }
  1593. /// Set the Prefix Length field.
  1594. #[inline]
  1595. pub fn set_prefix_info_prefix_length(&mut self, value: u8) {
  1596. set!(self.buffer, value, field: field::PREFIX_INFO_PREFIX_LENGTH)
  1597. }
  1598. /// Set the On-Link flag.
  1599. #[inline]
  1600. pub fn set_prefix_info_on_link(&mut self, value: bool) {
  1601. set!(self.buffer, value, bool, field: field::PREFIX_INFO_ON_LINK, shift: 7, mask: 0b1)
  1602. }
  1603. /// Set the Autonomous Address-Configuration flag.
  1604. #[inline]
  1605. pub fn set_prefix_info_autonomous_address_configuration(&mut self, value: bool) {
  1606. set!(
  1607. self.buffer,
  1608. value,
  1609. bool,
  1610. field: field::PREFIX_INFO_AUTONOMOUS_CONF,
  1611. shift: 6,
  1612. mask: 0b1
  1613. )
  1614. }
  1615. /// Set the Router Address flag.
  1616. #[inline]
  1617. pub fn set_prefix_info_router_address(&mut self, value: bool) {
  1618. set!(
  1619. self.buffer,
  1620. value,
  1621. bool,
  1622. field: field::PREFIX_INFO_ROUTER_ADDRESS_FLAG,
  1623. shift: 5,
  1624. mask: 0b1
  1625. )
  1626. }
  1627. /// Set the Valid Lifetime field.
  1628. #[inline]
  1629. pub fn set_prefix_info_valid_lifetime(&mut self, value: u32) {
  1630. set!(
  1631. self.buffer,
  1632. value,
  1633. u32,
  1634. field: field::PREFIX_INFO_VALID_LIFETIME
  1635. )
  1636. }
  1637. /// Set the Preferred Lifetime field.
  1638. #[inline]
  1639. pub fn set_prefix_info_preferred_lifetime(&mut self, value: u32) {
  1640. set!(
  1641. self.buffer,
  1642. value,
  1643. u32,
  1644. field: field::PREFIX_INFO_PREFERRED_LIFETIME
  1645. )
  1646. }
  1647. /// Set the Prefix field.
  1648. #[inline]
  1649. pub fn set_prefix_info_destination_prefix(&mut self, prefix: &[u8]) {
  1650. self.buffer.as_mut()[field::PREFIX_INFO_PREFIX].copy_from_slice(prefix);
  1651. }
  1652. }
  1653. /// Getters for the RPL Target Descriptor Option Message.
  1654. ///
  1655. /// ```txt
  1656. /// 0 1 2 3
  1657. /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  1658. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1659. /// | Type = 0x09 |Opt Length = 4 | Descriptor
  1660. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1661. /// Descriptor (cont.) |
  1662. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1663. /// ```
  1664. impl<T: AsRef<[u8]>> Packet<T> {
  1665. /// Return the Descriptor field.
  1666. #[inline]
  1667. pub fn descriptor(&self) -> u32 {
  1668. get!(self.buffer, u32, field: field::TARGET_DESCRIPTOR)
  1669. }
  1670. }
  1671. /// Setters for the RPL Target Descriptor Option Message.
  1672. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  1673. /// Set the Descriptor field.
  1674. #[inline]
  1675. pub fn set_rpl_target_descriptor_descriptor(&mut self, value: u32) {
  1676. set!(self.buffer, value, u32, field: field::TARGET_DESCRIPTOR)
  1677. }
  1678. }
  1679. #[derive(Debug, PartialEq, Eq, Clone, Copy)]
  1680. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  1681. pub enum Repr<'p> {
  1682. Pad1,
  1683. PadN(u8),
  1684. DagMetricContainer,
  1685. RouteInformation {
  1686. prefix_length: u8,
  1687. preference: u8,
  1688. lifetime: u32,
  1689. prefix: &'p [u8],
  1690. },
  1691. DodagConfiguration {
  1692. authentication_enabled: bool,
  1693. path_control_size: u8,
  1694. dio_interval_doublings: u8,
  1695. dio_interval_min: u8,
  1696. dio_redundancy_constant: u8,
  1697. max_rank_increase: u16,
  1698. minimum_hop_rank_increase: u16,
  1699. objective_code_point: u16,
  1700. default_lifetime: u8,
  1701. lifetime_unit: u16,
  1702. },
  1703. RplTarget {
  1704. prefix_length: u8,
  1705. prefix: crate::wire::Ipv6Address, // FIXME: this is not the correct type, because the
  1706. // field can be an IPv6 address, a prefix or a
  1707. // multicast group.
  1708. },
  1709. TransitInformation {
  1710. external: bool,
  1711. path_control: u8,
  1712. path_sequence: u8,
  1713. path_lifetime: u8,
  1714. parent_address: Option<Address>,
  1715. },
  1716. SolicitedInformation {
  1717. rpl_instance_id: InstanceId,
  1718. version_predicate: bool,
  1719. instance_id_predicate: bool,
  1720. dodag_id_predicate: bool,
  1721. dodag_id: Address,
  1722. version_number: u8,
  1723. },
  1724. PrefixInformation {
  1725. prefix_length: u8,
  1726. on_link: bool,
  1727. autonomous_address_configuration: bool,
  1728. router_address: bool,
  1729. valid_lifetime: u32,
  1730. preferred_lifetime: u32,
  1731. destination_prefix: &'p [u8],
  1732. },
  1733. RplTargetDescriptor {
  1734. descriptor: u32,
  1735. },
  1736. }
  1737. impl core::fmt::Display for Repr<'_> {
  1738. fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
  1739. match self {
  1740. Repr::Pad1 => write!(f, "Pad1"),
  1741. Repr::PadN(n) => write!(f, "PadN({n})"),
  1742. Repr::DagMetricContainer => todo!(),
  1743. Repr::RouteInformation {
  1744. prefix_length,
  1745. preference,
  1746. lifetime,
  1747. prefix,
  1748. } => {
  1749. write!(
  1750. f,
  1751. "ROUTE INFO \
  1752. PrefixLength={prefix_length} \
  1753. Preference={preference} \
  1754. Lifetime={lifetime} \
  1755. Prefix={prefix:0x?}"
  1756. )
  1757. }
  1758. Repr::DodagConfiguration {
  1759. dio_interval_doublings,
  1760. dio_interval_min,
  1761. dio_redundancy_constant,
  1762. max_rank_increase,
  1763. minimum_hop_rank_increase,
  1764. objective_code_point,
  1765. default_lifetime,
  1766. lifetime_unit,
  1767. ..
  1768. } => {
  1769. write!(
  1770. f,
  1771. "DODAG CONF \
  1772. IntD={dio_interval_doublings} \
  1773. IntMin={dio_interval_min} \
  1774. RedCst={dio_redundancy_constant} \
  1775. MaxRankIncr={max_rank_increase} \
  1776. MinHopRankIncr={minimum_hop_rank_increase} \
  1777. OCP={objective_code_point} \
  1778. DefaultLifetime={default_lifetime} \
  1779. LifeUnit={lifetime_unit}"
  1780. )
  1781. }
  1782. Repr::RplTarget {
  1783. prefix_length,
  1784. prefix,
  1785. } => {
  1786. write!(
  1787. f,
  1788. "RPL Target \
  1789. PrefixLength={prefix_length} \
  1790. Prefix={prefix:0x?}"
  1791. )
  1792. }
  1793. Repr::TransitInformation {
  1794. external,
  1795. path_control,
  1796. path_sequence,
  1797. path_lifetime,
  1798. parent_address,
  1799. } => {
  1800. write!(
  1801. f,
  1802. "Transit Info \
  1803. External={external} \
  1804. PathCtrl={path_control} \
  1805. PathSqnc={path_sequence} \
  1806. PathLifetime={path_lifetime} \
  1807. Parent={parent_address:0x?}"
  1808. )
  1809. }
  1810. Repr::SolicitedInformation {
  1811. rpl_instance_id,
  1812. version_predicate,
  1813. instance_id_predicate,
  1814. dodag_id_predicate,
  1815. dodag_id,
  1816. version_number,
  1817. } => {
  1818. write!(
  1819. f,
  1820. "Solicited Info \
  1821. I={instance_id_predicate} \
  1822. IID={rpl_instance_id:0x?} \
  1823. D={dodag_id_predicate} \
  1824. DODAGID={dodag_id} \
  1825. V={version_predicate} \
  1826. Version={version_number}"
  1827. )
  1828. }
  1829. Repr::PrefixInformation {
  1830. prefix_length,
  1831. on_link,
  1832. autonomous_address_configuration,
  1833. router_address,
  1834. valid_lifetime,
  1835. preferred_lifetime,
  1836. destination_prefix,
  1837. } => {
  1838. write!(
  1839. f,
  1840. "Prefix Info \
  1841. PrefixLength={prefix_length} \
  1842. L={on_link} A={autonomous_address_configuration} R={router_address} \
  1843. Valid={valid_lifetime} \
  1844. Prefered={preferred_lifetime} \
  1845. Prefix={destination_prefix:0x?}"
  1846. )
  1847. }
  1848. Repr::RplTargetDescriptor { .. } => write!(f, "Target Descriptor"),
  1849. }
  1850. }
  1851. }
  1852. impl<'p> Repr<'p> {
  1853. pub fn parse<T: AsRef<[u8]> + ?Sized>(packet: &Packet<&'p T>) -> Result<Self> {
  1854. match packet.option_type() {
  1855. OptionType::Pad1 => Ok(Repr::Pad1),
  1856. OptionType::PadN => Ok(Repr::PadN(packet.option_length())),
  1857. OptionType::DagMetricContainer => todo!(),
  1858. OptionType::RouteInformation => Ok(Repr::RouteInformation {
  1859. prefix_length: packet.prefix_length(),
  1860. preference: packet.route_preference(),
  1861. lifetime: packet.route_lifetime(),
  1862. prefix: packet.prefix(),
  1863. }),
  1864. OptionType::DodagConfiguration => Ok(Repr::DodagConfiguration {
  1865. authentication_enabled: packet.authentication_enabled(),
  1866. path_control_size: packet.path_control_size(),
  1867. dio_interval_doublings: packet.dio_interval_doublings(),
  1868. dio_interval_min: packet.dio_interval_minimum(),
  1869. dio_redundancy_constant: packet.dio_redundancy_constant(),
  1870. max_rank_increase: packet.max_rank_increase(),
  1871. minimum_hop_rank_increase: packet.minimum_hop_rank_increase(),
  1872. objective_code_point: packet.objective_code_point(),
  1873. default_lifetime: packet.default_lifetime(),
  1874. lifetime_unit: packet.lifetime_unit(),
  1875. }),
  1876. OptionType::RplTarget => Ok(Repr::RplTarget {
  1877. prefix_length: packet.target_prefix_length(),
  1878. prefix: crate::wire::Ipv6Address::from_bytes(packet.target_prefix()),
  1879. }),
  1880. OptionType::TransitInformation => Ok(Repr::TransitInformation {
  1881. external: packet.is_external(),
  1882. path_control: packet.path_control(),
  1883. path_sequence: packet.path_sequence(),
  1884. path_lifetime: packet.path_lifetime(),
  1885. parent_address: packet.parent_address(),
  1886. }),
  1887. OptionType::SolicitedInformation => Ok(Repr::SolicitedInformation {
  1888. rpl_instance_id: InstanceId::from(packet.rpl_instance_id()),
  1889. version_predicate: packet.version_predicate(),
  1890. instance_id_predicate: packet.instance_id_predicate(),
  1891. dodag_id_predicate: packet.dodag_id_predicate(),
  1892. dodag_id: packet.dodag_id(),
  1893. version_number: packet.version_number(),
  1894. }),
  1895. OptionType::PrefixInformation => Ok(Repr::PrefixInformation {
  1896. prefix_length: packet.prefix_info_prefix_length(),
  1897. on_link: packet.on_link(),
  1898. autonomous_address_configuration: packet.autonomous_address_configuration(),
  1899. router_address: packet.router_address(),
  1900. valid_lifetime: packet.valid_lifetime(),
  1901. preferred_lifetime: packet.preferred_lifetime(),
  1902. destination_prefix: packet.destination_prefix(),
  1903. }),
  1904. OptionType::RplTargetDescriptor => Ok(Repr::RplTargetDescriptor {
  1905. descriptor: packet.descriptor(),
  1906. }),
  1907. OptionType::Unknown(_) => Err(Error),
  1908. }
  1909. }
  1910. pub fn buffer_len(&self) -> usize {
  1911. match self {
  1912. Repr::Pad1 => 1,
  1913. Repr::PadN(size) => 2 + *size as usize,
  1914. Repr::DagMetricContainer => todo!(),
  1915. Repr::RouteInformation { prefix, .. } => 2 + 6 + prefix.len(),
  1916. Repr::DodagConfiguration { .. } => 2 + 14,
  1917. Repr::RplTarget { prefix, .. } => 2 + 2 + prefix.0.len(),
  1918. Repr::TransitInformation { parent_address, .. } => {
  1919. 2 + 4 + if parent_address.is_some() { 16 } else { 0 }
  1920. }
  1921. Repr::SolicitedInformation { .. } => 2 + 2 + 16 + 1,
  1922. Repr::PrefixInformation { .. } => 32,
  1923. Repr::RplTargetDescriptor { .. } => 2 + 4,
  1924. }
  1925. }
  1926. pub fn emit<T: AsRef<[u8]> + AsMut<[u8]> + ?Sized>(&self, packet: &mut Packet<&'p mut T>) {
  1927. let mut option_length = self.buffer_len() as u8;
  1928. packet.set_option_type(self.into());
  1929. if !matches!(self, Repr::Pad1) {
  1930. option_length -= 2;
  1931. packet.set_option_length(option_length);
  1932. }
  1933. match self {
  1934. Repr::Pad1 => {}
  1935. Repr::PadN(size) => {
  1936. packet.clear_padn(*size);
  1937. }
  1938. Repr::DagMetricContainer => {
  1939. unimplemented!();
  1940. }
  1941. Repr::RouteInformation {
  1942. prefix_length,
  1943. preference,
  1944. lifetime,
  1945. prefix,
  1946. } => {
  1947. packet.clear_route_info_reserved();
  1948. packet.set_route_info_prefix_length(*prefix_length);
  1949. packet.set_route_info_route_preference(*preference);
  1950. packet.set_route_info_route_lifetime(*lifetime);
  1951. packet.set_route_info_prefix(prefix);
  1952. }
  1953. Repr::DodagConfiguration {
  1954. authentication_enabled,
  1955. path_control_size,
  1956. dio_interval_doublings,
  1957. dio_interval_min,
  1958. dio_redundancy_constant,
  1959. max_rank_increase,
  1960. minimum_hop_rank_increase,
  1961. objective_code_point,
  1962. default_lifetime,
  1963. lifetime_unit,
  1964. } => {
  1965. packet.clear_dodag_conf_flags();
  1966. packet.set_dodag_conf_authentication_enabled(*authentication_enabled);
  1967. packet.set_dodag_conf_path_control_size(*path_control_size);
  1968. packet.set_dodag_conf_dio_interval_doublings(*dio_interval_doublings);
  1969. packet.set_dodag_conf_dio_interval_minimum(*dio_interval_min);
  1970. packet.set_dodag_conf_dio_redundancy_constant(*dio_redundancy_constant);
  1971. packet.set_dodag_conf_max_rank_increase(*max_rank_increase);
  1972. packet.set_dodag_conf_minimum_hop_rank_increase(*minimum_hop_rank_increase);
  1973. packet.set_dodag_conf_objective_code_point(*objective_code_point);
  1974. packet.set_dodag_conf_default_lifetime(*default_lifetime);
  1975. packet.set_dodag_conf_lifetime_unit(*lifetime_unit);
  1976. }
  1977. Repr::RplTarget {
  1978. prefix_length,
  1979. prefix,
  1980. } => {
  1981. packet.clear_rpl_target_flags();
  1982. packet.set_rpl_target_prefix_length(*prefix_length);
  1983. packet.set_rpl_target_prefix(prefix.as_bytes());
  1984. }
  1985. Repr::TransitInformation {
  1986. external,
  1987. path_control,
  1988. path_sequence,
  1989. path_lifetime,
  1990. parent_address,
  1991. } => {
  1992. packet.clear_transit_info_flags();
  1993. packet.set_transit_info_is_external(*external);
  1994. packet.set_transit_info_path_control(*path_control);
  1995. packet.set_transit_info_path_sequence(*path_sequence);
  1996. packet.set_transit_info_path_lifetime(*path_lifetime);
  1997. if let Some(address) = parent_address {
  1998. packet.set_transit_info_parent_address(*address);
  1999. }
  2000. }
  2001. Repr::SolicitedInformation {
  2002. rpl_instance_id,
  2003. version_predicate,
  2004. instance_id_predicate,
  2005. dodag_id_predicate,
  2006. dodag_id,
  2007. version_number,
  2008. } => {
  2009. packet.clear_solicited_info_flags();
  2010. packet.set_solicited_info_rpl_instance_id((*rpl_instance_id).into());
  2011. packet.set_solicited_info_version_predicate(*version_predicate);
  2012. packet.set_solicited_info_instance_id_predicate(*instance_id_predicate);
  2013. packet.set_solicited_info_dodag_id_predicate(*dodag_id_predicate);
  2014. packet.set_solicited_info_version_number(*version_number);
  2015. packet.set_solicited_info_dodag_id(*dodag_id);
  2016. }
  2017. Repr::PrefixInformation {
  2018. prefix_length,
  2019. on_link,
  2020. autonomous_address_configuration,
  2021. router_address,
  2022. valid_lifetime,
  2023. preferred_lifetime,
  2024. destination_prefix,
  2025. } => {
  2026. packet.clear_prefix_info_reserved();
  2027. packet.set_prefix_info_prefix_length(*prefix_length);
  2028. packet.set_prefix_info_on_link(*on_link);
  2029. packet.set_prefix_info_autonomous_address_configuration(
  2030. *autonomous_address_configuration,
  2031. );
  2032. packet.set_prefix_info_router_address(*router_address);
  2033. packet.set_prefix_info_valid_lifetime(*valid_lifetime);
  2034. packet.set_prefix_info_preferred_lifetime(*preferred_lifetime);
  2035. packet.set_prefix_info_destination_prefix(destination_prefix);
  2036. }
  2037. Repr::RplTargetDescriptor { descriptor } => {
  2038. packet.set_rpl_target_descriptor_descriptor(*descriptor);
  2039. }
  2040. }
  2041. }
  2042. }
  2043. }
  2044. pub mod data {
  2045. use super::{InstanceId, Result};
  2046. use byteorder::{ByteOrder, NetworkEndian};
  2047. mod field {
  2048. use crate::wire::field::*;
  2049. pub const FLAGS: usize = 0;
  2050. pub const INSTANCE_ID: usize = 1;
  2051. pub const SENDER_RANK: Field = 2..4;
  2052. }
  2053. /// A read/write wrapper around a RPL Packet Information send with
  2054. /// an IPv6 Hop-by-Hop option, defined in RFC6553.
  2055. /// ```txt
  2056. /// 0 1 2 3
  2057. /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  2058. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  2059. /// | Option Type | Opt Data Len |
  2060. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  2061. /// |O|R|F|0|0|0|0|0| RPLInstanceID | SenderRank |
  2062. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  2063. /// | (sub-TLVs) |
  2064. /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  2065. /// ```
  2066. #[derive(Debug, PartialEq, Eq, Clone, Copy)]
  2067. pub struct Packet<T: AsRef<[u8]>> {
  2068. buffer: T,
  2069. }
  2070. impl<T: AsRef<[u8]>> Packet<T> {
  2071. #[inline]
  2072. pub fn new_unchecked(buffer: T) -> Self {
  2073. Self { buffer }
  2074. }
  2075. #[inline]
  2076. pub fn new_checked(buffer: T) -> Result<Self> {
  2077. let packet = Self::new_unchecked(buffer);
  2078. packet.check_len()?;
  2079. Ok(packet)
  2080. }
  2081. #[inline]
  2082. pub fn check_len(&self) -> Result<()> {
  2083. if self.buffer.as_ref().len() == 4 {
  2084. Ok(())
  2085. } else {
  2086. Err(crate::wire::Error)
  2087. }
  2088. }
  2089. #[inline]
  2090. pub fn is_down(&self) -> bool {
  2091. get!(self.buffer, bool, field: field::FLAGS, shift: 7, mask: 0b1)
  2092. }
  2093. #[inline]
  2094. pub fn has_rank_error(&self) -> bool {
  2095. get!(self.buffer, bool, field: field::FLAGS, shift: 6, mask: 0b1)
  2096. }
  2097. #[inline]
  2098. pub fn has_forwarding_error(&self) -> bool {
  2099. get!(self.buffer, bool, field: field::FLAGS, shift: 5, mask: 0b1)
  2100. }
  2101. #[inline]
  2102. pub fn rpl_instance_id(&self) -> InstanceId {
  2103. get!(self.buffer, into: InstanceId, field: field::INSTANCE_ID)
  2104. }
  2105. #[inline]
  2106. pub fn sender_rank(&self) -> u16 {
  2107. get!(self.buffer, u16, field: field::SENDER_RANK)
  2108. }
  2109. }
  2110. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  2111. #[inline]
  2112. pub fn set_is_down(&mut self, value: bool) {
  2113. set!(self.buffer, value, bool, field: field::FLAGS, shift: 7, mask: 0b1)
  2114. }
  2115. #[inline]
  2116. pub fn set_has_rank_error(&mut self, value: bool) {
  2117. set!(self.buffer, value, bool, field: field::FLAGS, shift: 6, mask: 0b1)
  2118. }
  2119. #[inline]
  2120. pub fn set_has_forwarding_error(&mut self, value: bool) {
  2121. set!(self.buffer, value, bool, field: field::FLAGS, shift: 5, mask: 0b1)
  2122. }
  2123. #[inline]
  2124. pub fn set_rpl_instance_id(&mut self, value: u8) {
  2125. set!(self.buffer, value, field: field::INSTANCE_ID)
  2126. }
  2127. #[inline]
  2128. pub fn set_sender_rank(&mut self, value: u16) {
  2129. set!(self.buffer, value, u16, field: field::SENDER_RANK)
  2130. }
  2131. }
  2132. /// A high-level representation of an IPv6 Extension Header Option.
  2133. #[derive(Debug, PartialEq, Eq, Clone, Copy)]
  2134. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  2135. pub struct HopByHopOption {
  2136. pub down: bool,
  2137. pub rank_error: bool,
  2138. pub forwarding_error: bool,
  2139. pub instance_id: InstanceId,
  2140. pub sender_rank: u16,
  2141. }
  2142. impl HopByHopOption {
  2143. /// Parse an IPv6 Extension Header Option and return a high-level representation.
  2144. pub fn parse<T>(opt: &Packet<&T>) -> Self
  2145. where
  2146. T: AsRef<[u8]> + ?Sized,
  2147. {
  2148. Self {
  2149. down: opt.is_down(),
  2150. rank_error: opt.has_rank_error(),
  2151. forwarding_error: opt.has_forwarding_error(),
  2152. instance_id: opt.rpl_instance_id(),
  2153. sender_rank: opt.sender_rank(),
  2154. }
  2155. }
  2156. /// Return the length of a header that will be emitted from this high-level representation.
  2157. pub const fn buffer_len(&self) -> usize {
  2158. 4
  2159. }
  2160. /// Emit a high-level representation into an IPv6 Extension Header Option.
  2161. pub fn emit<T: AsRef<[u8]> + AsMut<[u8]> + ?Sized>(&self, opt: &mut Packet<&mut T>) {
  2162. opt.set_is_down(self.down);
  2163. opt.set_has_rank_error(self.rank_error);
  2164. opt.set_has_forwarding_error(self.forwarding_error);
  2165. opt.set_rpl_instance_id(self.instance_id.into());
  2166. opt.set_sender_rank(self.sender_rank);
  2167. }
  2168. }
  2169. impl core::fmt::Display for HopByHopOption {
  2170. fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
  2171. write!(
  2172. f,
  2173. "down={} rank_error={} forw_error={} IID={:?} sender_rank={}",
  2174. self.down,
  2175. self.rank_error,
  2176. self.forwarding_error,
  2177. self.instance_id,
  2178. self.sender_rank
  2179. )
  2180. }
  2181. }
  2182. }
  2183. #[cfg(test)]
  2184. mod tests {
  2185. use super::options::{Packet as OptionPacket, Repr as OptionRepr};
  2186. use super::Repr as RplRepr;
  2187. use super::*;
  2188. use crate::phy::ChecksumCapabilities;
  2189. use crate::wire::{icmpv6::*, *};
  2190. #[test]
  2191. fn dis_packet() {
  2192. let data = [0x7a, 0x3b, 0x3a, 0x1a, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00];
  2193. let ll_src_address =
  2194. Ieee802154Address::Extended([0x9e, 0xd3, 0xa2, 0x9c, 0x57, 0x1a, 0x4f, 0xe4]);
  2195. let ll_dst_address = Ieee802154Address::Short([0xff, 0xff]);
  2196. let packet = SixlowpanIphcPacket::new_checked(&data).unwrap();
  2197. let repr =
  2198. SixlowpanIphcRepr::parse(&packet, Some(ll_src_address), Some(ll_dst_address), &[])
  2199. .unwrap();
  2200. let icmp_repr = match repr.next_header {
  2201. SixlowpanNextHeader::Uncompressed(IpProtocol::Icmpv6) => {
  2202. let icmp_packet = Icmpv6Packet::new_checked(packet.payload()).unwrap();
  2203. match Icmpv6Repr::parse(
  2204. &IpAddress::Ipv6(repr.src_addr),
  2205. &IpAddress::Ipv6(repr.dst_addr),
  2206. &icmp_packet,
  2207. &ChecksumCapabilities::ignored(),
  2208. ) {
  2209. Ok(icmp @ Icmpv6Repr::Rpl(RplRepr::DodagInformationSolicitation { .. })) => {
  2210. icmp
  2211. }
  2212. _ => unreachable!(),
  2213. }
  2214. }
  2215. _ => unreachable!(),
  2216. };
  2217. // We also try to emit the packet:
  2218. let mut buffer = vec![0u8; repr.buffer_len() + icmp_repr.buffer_len()];
  2219. repr.emit(&mut SixlowpanIphcPacket::new_unchecked(
  2220. &mut buffer[..repr.buffer_len()],
  2221. ));
  2222. icmp_repr.emit(
  2223. &repr.src_addr.into(),
  2224. &repr.dst_addr.into(),
  2225. &mut Icmpv6Packet::new_unchecked(
  2226. &mut buffer[repr.buffer_len()..][..icmp_repr.buffer_len()],
  2227. ),
  2228. &ChecksumCapabilities::ignored(),
  2229. );
  2230. assert_eq!(&data[..], &buffer[..]);
  2231. }
  2232. /// Parsing of DIO packets.
  2233. #[test]
  2234. fn dio_packet() {
  2235. let data = [
  2236. 0x9b, 0x01, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x80, 0x08, 0xf0, 0x00, 0x00, 0xfd, 0x00,
  2237. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
  2238. 0x04, 0x0e, 0x00, 0x08, 0x0c, 0x00, 0x04, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x1e,
  2239. 0x00, 0x3c, 0x08, 0x1e, 0x40, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  2240. 0x00, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2241. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2242. ];
  2243. let addr = Address::from_bytes(&[
  2244. 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01,
  2245. 0x00, 0x01,
  2246. ]);
  2247. let dest_prefix = [
  2248. 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2249. 0x00, 0x00,
  2250. ];
  2251. let packet = Packet::new_checked(&data[..]).unwrap();
  2252. assert_eq!(packet.msg_type(), Message::RplControl);
  2253. assert_eq!(
  2254. RplControlMessage::from(packet.msg_code()),
  2255. RplControlMessage::DodagInformationObject
  2256. );
  2257. let mut dio_repr = RplRepr::parse(&packet).unwrap();
  2258. match dio_repr {
  2259. RplRepr::DodagInformationObject {
  2260. rpl_instance_id,
  2261. version_number,
  2262. rank,
  2263. grounded,
  2264. mode_of_operation,
  2265. dodag_preference,
  2266. dtsn,
  2267. dodag_id,
  2268. ..
  2269. } => {
  2270. assert_eq!(rpl_instance_id, InstanceId::from(0));
  2271. assert_eq!(version_number, 240);
  2272. assert_eq!(rank, 128);
  2273. assert!(!grounded);
  2274. assert_eq!(mode_of_operation, ModeOfOperation::NonStoringMode);
  2275. assert_eq!(dodag_preference, 0);
  2276. assert_eq!(dtsn, 240);
  2277. assert_eq!(dodag_id, addr);
  2278. }
  2279. _ => unreachable!(),
  2280. }
  2281. let option = OptionPacket::new_unchecked(packet.options().unwrap());
  2282. let dodag_conf_option = OptionRepr::parse(&option).unwrap();
  2283. match dodag_conf_option {
  2284. OptionRepr::DodagConfiguration {
  2285. authentication_enabled,
  2286. path_control_size,
  2287. dio_interval_doublings,
  2288. dio_interval_min,
  2289. dio_redundancy_constant,
  2290. max_rank_increase,
  2291. minimum_hop_rank_increase,
  2292. objective_code_point,
  2293. default_lifetime,
  2294. lifetime_unit,
  2295. } => {
  2296. assert!(!authentication_enabled);
  2297. assert_eq!(path_control_size, 0);
  2298. assert_eq!(dio_interval_doublings, 8);
  2299. assert_eq!(dio_interval_min, 12);
  2300. assert_eq!(dio_redundancy_constant, 0);
  2301. assert_eq!(max_rank_increase, 1024);
  2302. assert_eq!(minimum_hop_rank_increase, 128);
  2303. assert_eq!(objective_code_point, 1);
  2304. assert_eq!(default_lifetime, 30);
  2305. assert_eq!(lifetime_unit, 60);
  2306. }
  2307. _ => unreachable!(),
  2308. }
  2309. let option = OptionPacket::new_unchecked(option.next_option().unwrap());
  2310. let prefix_info_option = OptionRepr::parse(&option).unwrap();
  2311. match prefix_info_option {
  2312. OptionRepr::PrefixInformation {
  2313. prefix_length,
  2314. on_link,
  2315. autonomous_address_configuration,
  2316. valid_lifetime,
  2317. preferred_lifetime,
  2318. destination_prefix,
  2319. ..
  2320. } => {
  2321. assert_eq!(prefix_length, 64);
  2322. assert!(!on_link);
  2323. assert!(autonomous_address_configuration);
  2324. assert_eq!(valid_lifetime, u32::MAX);
  2325. assert_eq!(preferred_lifetime, u32::MAX);
  2326. assert_eq!(destination_prefix, &dest_prefix[..]);
  2327. }
  2328. _ => unreachable!(),
  2329. }
  2330. let mut options_buffer =
  2331. vec![0u8; dodag_conf_option.buffer_len() + prefix_info_option.buffer_len()];
  2332. dodag_conf_option.emit(&mut OptionPacket::new_unchecked(
  2333. &mut options_buffer[..dodag_conf_option.buffer_len()],
  2334. ));
  2335. prefix_info_option.emit(&mut OptionPacket::new_unchecked(
  2336. &mut options_buffer[dodag_conf_option.buffer_len()..]
  2337. [..prefix_info_option.buffer_len()],
  2338. ));
  2339. dio_repr.set_options(&options_buffer[..]);
  2340. let mut buffer = vec![0u8; dio_repr.buffer_len()];
  2341. dio_repr.emit(&mut Packet::new_unchecked(&mut buffer[..]));
  2342. assert_eq!(&data[..], &buffer[..]);
  2343. }
  2344. /// Parsing of DAO packets.
  2345. #[test]
  2346. fn dao_packet() {
  2347. let data = [
  2348. 0x9b, 0x02, 0x00, 0x00, 0x00, 0x80, 0x00, 0xf1, 0x05, 0x12, 0x00, 0x80, 0xfd, 0x00,
  2349. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02,
  2350. 0x06, 0x14, 0x00, 0x00, 0x00, 0x1e, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2351. 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
  2352. ];
  2353. let target_prefix = [
  2354. 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02,
  2355. 0x00, 0x02,
  2356. ];
  2357. let parent_addr = Address::from_bytes(&[
  2358. 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01,
  2359. 0x00, 0x01,
  2360. ]);
  2361. let packet = Packet::new_checked(&data[..]).unwrap();
  2362. let mut dao_repr = RplRepr::parse(&packet).unwrap();
  2363. match dao_repr {
  2364. RplRepr::DestinationAdvertisementObject {
  2365. rpl_instance_id,
  2366. expect_ack,
  2367. sequence,
  2368. dodag_id,
  2369. ..
  2370. } => {
  2371. assert_eq!(rpl_instance_id, InstanceId::from(0));
  2372. assert!(expect_ack);
  2373. assert_eq!(sequence, 241);
  2374. assert_eq!(dodag_id, None);
  2375. }
  2376. _ => unreachable!(),
  2377. }
  2378. let option = OptionPacket::new_unchecked(packet.options().unwrap());
  2379. let rpl_target_option = OptionRepr::parse(&option).unwrap();
  2380. match rpl_target_option {
  2381. OptionRepr::RplTarget {
  2382. prefix_length,
  2383. prefix,
  2384. } => {
  2385. assert_eq!(prefix_length, 128);
  2386. assert_eq!(prefix.as_bytes(), &target_prefix[..]);
  2387. }
  2388. _ => unreachable!(),
  2389. }
  2390. let option = OptionPacket::new_unchecked(option.next_option().unwrap());
  2391. let transit_info_option = OptionRepr::parse(&option).unwrap();
  2392. match transit_info_option {
  2393. OptionRepr::TransitInformation {
  2394. external,
  2395. path_control,
  2396. path_sequence,
  2397. path_lifetime,
  2398. parent_address,
  2399. } => {
  2400. assert!(!external);
  2401. assert_eq!(path_control, 0);
  2402. assert_eq!(path_sequence, 0);
  2403. assert_eq!(path_lifetime, 30);
  2404. assert_eq!(parent_address, Some(parent_addr));
  2405. }
  2406. _ => unreachable!(),
  2407. }
  2408. let mut options_buffer =
  2409. vec![0u8; rpl_target_option.buffer_len() + transit_info_option.buffer_len()];
  2410. rpl_target_option.emit(&mut OptionPacket::new_unchecked(
  2411. &mut options_buffer[..rpl_target_option.buffer_len()],
  2412. ));
  2413. transit_info_option.emit(&mut OptionPacket::new_unchecked(
  2414. &mut options_buffer[rpl_target_option.buffer_len()..]
  2415. [..transit_info_option.buffer_len()],
  2416. ));
  2417. dao_repr.set_options(&options_buffer[..]);
  2418. let mut buffer = vec![0u8; dao_repr.buffer_len()];
  2419. dao_repr.emit(&mut Packet::new_unchecked(&mut buffer[..]));
  2420. assert_eq!(&data[..], &buffer[..]);
  2421. }
  2422. /// Parsing of DAO-ACK packets.
  2423. #[test]
  2424. fn dao_ack_packet() {
  2425. let data = [0x9b, 0x03, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x00];
  2426. let packet = Packet::new_checked(&data[..]).unwrap();
  2427. let dao_ack_repr = RplRepr::parse(&packet).unwrap();
  2428. match dao_ack_repr {
  2429. RplRepr::DestinationAdvertisementObjectAck {
  2430. rpl_instance_id,
  2431. sequence,
  2432. status,
  2433. dodag_id,
  2434. ..
  2435. } => {
  2436. assert_eq!(rpl_instance_id, InstanceId::from(0));
  2437. assert_eq!(sequence, 241);
  2438. assert_eq!(status, 0);
  2439. assert_eq!(dodag_id, None);
  2440. }
  2441. _ => unreachable!(),
  2442. }
  2443. let mut buffer = vec![0u8; dao_ack_repr.buffer_len()];
  2444. dao_ack_repr.emit(&mut Packet::new_unchecked(&mut buffer[..]));
  2445. assert_eq!(&data[..], &buffer[..]);
  2446. }
  2447. }