rpl.rs 98 KB

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