diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 7c2d9b2..6e188d2 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -73,8 +73,22 @@ jobs: - name: Check a package with specific feature combination. run: cargo test --locked ${{ matrix.command }} + clippy: + runs-on: ubuntu-latest + name: clippy + strategy: + matrix: + crate: + - ipmi-rs-core + - ipmi-rs-log + - ipmi-rs + steps: + - uses: actions/checkout@v5 + - name: Run cargo clippy + run: cargo clippy --locked --all-features -p ${{ matrix.crate }} -- -Dwarnings + ci-success: runs-on: ubuntu-latest - needs: [check-format, check, test] + needs: [check-format, check, test, clippy] steps: - - run: true \ No newline at end of file + - run: true diff --git a/ipmi-rs-core/src/connection/request.rs b/ipmi-rs-core/src/connection/request.rs index 87788c8..f19c3dc 100644 --- a/ipmi-rs-core/src/connection/request.rs +++ b/ipmi-rs-core/src/connection/request.rs @@ -36,7 +36,6 @@ impl Request { } /// Get a shared reference to the data of the request (does not include netfn or command). - pub fn data(&self) -> &[u8] { self.message.data() } diff --git a/ipmi-rs-core/src/storage/sdr/event_offset.rs b/ipmi-rs-core/src/storage/sdr/event_offset.rs index 9408dd1..708cc10 100644 --- a/ipmi-rs-core/src/storage/sdr/event_offset.rs +++ b/ipmi-rs-core/src/storage/sdr/event_offset.rs @@ -537,7 +537,7 @@ pub fn decode_event( if event_type_code == 0x6F { // Sensor-specific event decode_sensor_event_offset(f, sensor_type, offset) - } else if event_type_code >= 0x01 && event_type_code <= 0x0C { + } else if (0x01..=0x0C).contains(&event_type_code) { // Generic event decode_generic_event_offset(f, event_type_code, offset) } else { diff --git a/ipmi-rs/src/file.rs b/ipmi-rs/src/file.rs index acdb428..5733c47 100644 --- a/ipmi-rs/src/file.rs +++ b/ipmi-rs/src/file.rs @@ -52,7 +52,7 @@ pub struct IpmiRequest { impl IpmiRequest { pub fn log(&self, level: log::Level) { log::log!(level, " Message ID = 0x{:02X}", self.msg_id); - self.message.log(level) + self.message.log(level); } } @@ -70,7 +70,7 @@ impl IpmiRecv { fn log(&self, level: log::Level) { log::log!(level, " Type = 0x{:02X}", self.recv_type); log::log!(level, " Message ID = 0x{:02X}", self.msg_id); - self.message.log(level) + self.message.log(level); } } @@ -105,7 +105,7 @@ mod ioctl { use nix::{ioctl_read, ioctl_readwrite}; - use super::*; + use super::{IpmiRecv, IpmiRequest}; ioctl_readwrite!(ipmi_recv_msg_trunc, IPMI_IOC_MAGIC, 11, IpmiRecv); ioctl_read!(ipmi_send_request, IPMI_IOC_MAGIC, 13, IpmiRequest); @@ -243,10 +243,9 @@ impl File { if let Ok(addr) = u8::try_from(my_addr) { Ok(Address(addr)) } else { - Err(io::Error::new( - io::ErrorKind::Other, - format!("ipmi_get_my_address returned non-u8 address: {}", my_addr), - )) + Err(io::Error::other(format!( + "ipmi_get_my_address returned non-u8 address: {my_addr}" + ))) } } } @@ -379,20 +378,16 @@ impl IpmiConnection for File { if response.seq() == self.seq { Ok(response) } else { - Err(io::Error::new( - io::ErrorKind::Other, - format!( - "Invalid sequence number on response. Expected {}, got {}", - self.seq, - response.seq() - ), - )) + Err(io::Error::other(format!( + "Invalid sequence number on response. Expected {}, got {}", + self.seq, + response.seq() + ))) } } - Err(e) => Err(io::Error::new( - io::ErrorKind::Other, - format!("Error while creating response. {:?}", e), - )), + Err(e) => Err(io::Error::other(format!( + "Error while creating response. {e:?}" + ))), } } diff --git a/ipmi-rs/src/rmcp/asf.rs b/ipmi-rs/src/rmcp/asf.rs index bcf1595..b987386 100644 --- a/ipmi-rs/src/rmcp/asf.rs +++ b/ipmi-rs/src/rmcp/asf.rs @@ -12,7 +12,7 @@ impl TryFrom for SupportedInteractions { let dmtf_dash = (value & 0x10) == 0x10; // All of these bits must be 0 - if (value & 0b01011111) != 0 { + if (value & 0b0101_1111) != 0 { return Err(()); } @@ -122,7 +122,7 @@ impl ASFMessageType { u8::from(*supported_entities), u8::from(*supported_interactions), ]); - buffer.extend(std::iter::repeat(0).take(6)); + buffer.extend(std::iter::repeat_n(0, 6)); } } } diff --git a/ipmi-rs/src/rmcp/v1_5/auth.rs b/ipmi-rs/src/rmcp/v1_5/auth.rs index 929eff5..cf11460 100644 --- a/ipmi-rs/src/rmcp/v1_5/auth.rs +++ b/ipmi-rs/src/rmcp/v1_5/auth.rs @@ -26,10 +26,10 @@ pub fn calculate( (AuthType::MD2, Some(password)) => { Ok(Some(calculate_md2(password, session_id, session_seq, data))) } - (AuthType::MD5, Some(_password)) => { + (AuthType::MD5, Some(password)) => { #[cfg(feature = "md5")] return Ok(Some(super::md5::calculate_md5( - _password, + password, session_id, session_seq, data, diff --git a/ipmi-rs/src/rmcp/v1_5/md2.rs b/ipmi-rs/src/rmcp/v1_5/md2.rs index 42cb8f0..dd501a4 100644 --- a/ipmi-rs/src/rmcp/v1_5/md2.rs +++ b/ipmi-rs/src/rmcp/v1_5/md2.rs @@ -66,7 +66,9 @@ where } } - if !self.finished { + if self.finished { + None + } else { self.finished = true; let i = 16 - chunk_len; @@ -74,8 +76,6 @@ where chunk[idx] = i as u8; } Some(chunk) - } else { - None } } } diff --git a/ipmi-rs/src/rmcp/v1_5/message.rs b/ipmi-rs/src/rmcp/v1_5/message.rs index 4d7532c..62d68dd 100644 --- a/ipmi-rs/src/rmcp/v1_5/message.rs +++ b/ipmi-rs/src/rmcp/v1_5/message.rs @@ -54,37 +54,36 @@ impl Message { let session_sequence = u32::from_le_bytes(data[1..5].try_into().unwrap()); let session_id = u32::from_le_bytes(data[5..9].try_into().unwrap()); - let (auth_type, data) = match data[0] { - 0x00 => (AuthType::None, &data[9..]), - _ => { - if data.len() < 26 { - return Err(ReadError::NotEnoughData); - } - - let auth_code: [u8; 16] = data[9..25].try_into().unwrap(); - - let auth_type = match data[0] { - 0x01 => AuthType::MD2, - 0x02 => AuthType::MD5, - 0x04 => AuthType::Key, - v => return Err(ReadError::UnsupportedAuthType(v)), - }; - - let data = &data[25..]; - - if !auth::verify( - &auth_type, - auth_code, - password, - session_id, - session_sequence, - data, - ) { - return Err(ReadError::AuthcodeError); - } - - (auth_type, data) + let (auth_type, data) = if data[0] == 0x00 { + (AuthType::None, &data[9..]) + } else { + if data.len() < 26 { + return Err(ReadError::NotEnoughData); + } + + let auth_code: [u8; 16] = data[9..25].try_into().unwrap(); + + let auth_type = match data[0] { + 0x01 => AuthType::MD2, + 0x02 => AuthType::MD5, + 0x04 => AuthType::Key, + v => return Err(ReadError::UnsupportedAuthType(v)), + }; + + let data = &data[25..]; + + if !auth::verify( + &auth_type, + auth_code, + password, + session_id, + session_sequence, + data, + ) { + return Err(ReadError::AuthcodeError); } + + (auth_type, data) }; let data_len = data[0]; diff --git a/ipmi-rs/src/rmcp/v1_5/mod.rs b/ipmi-rs/src/rmcp/v1_5/mod.rs index 0f40d21..45ae1ec 100644 --- a/ipmi-rs/src/rmcp/v1_5/mod.rs +++ b/ipmi-rs/src/rmcp/v1_5/mod.rs @@ -85,7 +85,7 @@ impl State { pub fn new(socket: UdpSocket) -> Self { Self { socket: RmcpIpmiSocket::new(socket), - ipmb_state: Default::default(), + ipmb_state: IpmbState::default(), auth_type: AuthType::None, password: None, session_id: None, @@ -107,11 +107,10 @@ impl State { let password = if let Some(password) = password { if password.len() > 16 { return Err(ActivationError::PasswordTooLong); - } else { - let mut padded = [0u8; 16]; - padded[..password.len()].copy_from_slice(password); - Some(padded) } + let mut padded = [0u8; 16]; + padded[..password.len()].copy_from_slice(password); + Some(padded) } else { None }; @@ -189,7 +188,7 @@ impl IpmiConnection for State { let message = Message { auth_type: self.auth_type, session_sequence_number: self.session_sequence, - session_id: self.session_id.map(|v| v.get()).unwrap_or(0), + session_id: self.session_id.map_or(0, std::num::NonZero::get), payload: final_data, }; @@ -209,7 +208,7 @@ impl IpmiConnection for State { .write_data(self.password.as_ref(), buffer) .map_err(Send::Ipmi) }) { - Ok(_) => Ok(()), + Ok(()) => Ok(()), Err(Send::Ipmi(ipmi)) => Err(RmcpIpmiSendError::V1_5(ipmi)), Err(Send::Io(io)) => Err(RmcpIpmiSendError::V1_5(WriteError::Io(io))), } diff --git a/ipmi-rs/src/rmcp/v2_0/crypto/state.rs b/ipmi-rs/src/rmcp/v2_0/crypto/state.rs index 3ef9fcd..a7fd829 100644 --- a/ipmi-rs/src/rmcp/v2_0/crypto/state.rs +++ b/ipmi-rs/src/rmcp/v2_0/crypto/state.rs @@ -35,10 +35,7 @@ impl Default for CryptoState { impl CryptoState { fn kg(&self) -> &[u8] { - self.kg - .as_ref() - .map(|v| &v[..]) - .unwrap_or(self.password.as_ref()) + self.kg.as_ref().map_or(self.password.as_ref(), |v| &v[..]) } } diff --git a/ipmi-rs/src/rmcp/v2_0/crypto/sub_state.rs b/ipmi-rs/src/rmcp/v2_0/crypto/sub_state.rs index 322f9b8..1fe12e7 100644 --- a/ipmi-rs/src/rmcp/v2_0/crypto/sub_state.rs +++ b/ipmi-rs/src/rmcp/v2_0/crypto/sub_state.rs @@ -52,7 +52,7 @@ impl SubState { // Integrity PAD let pad_length = (4 - auth_code_data_len % 4) % 4; - buffer.extend(std::iter::repeat(0xFF).take(pad_length)); + buffer.extend(std::iter::repeat_n(0xFF, pad_length)); // Pad length buffer.push(pad_length as u8); @@ -74,7 +74,7 @@ impl SubState { IntegrityAlgorithm::HmacMd5_128 => todo!(), IntegrityAlgorithm::Md5_128 => todo!(), IntegrityAlgorithm::HmacSha256_128 => todo!(), - }; + } } Ok(()) @@ -138,14 +138,14 @@ impl SubState { buffer.extend_from_slice(&(data_len as u16).to_le_bytes()); // Data - buffer.extend(data) + buffer.extend(data); } ConfidentialityAlgorithm::AesCbc128 => { let mut iv = [0u8; 16]; - if !cfg!(test) { - getrandom::fill(&mut iv).unwrap(); - } else { + if cfg!(test) { iv = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + } else { + getrandom::fill(&mut iv).unwrap(); } // Length diff --git a/ipmi-rs/src/rmcp/v2_0/messages/open_session.rs b/ipmi-rs/src/rmcp/v2_0/messages/open_session.rs index f252b88..f41d7d2 100644 --- a/ipmi-rs/src/rmcp/v2_0/messages/open_session.rs +++ b/ipmi-rs/src/rmcp/v2_0/messages/open_session.rs @@ -44,7 +44,7 @@ impl AlgorithmPayload { // Payload len OR null byte if null_byte { - buffer.push(0x00) + buffer.push(0x00); } else { buffer.push(0x08); } @@ -57,7 +57,10 @@ impl AlgorithmPayload { } pub fn from_data(data: &[u8]) -> Result { - use AlgorithmPayloadError::*; + use AlgorithmPayloadError::{ + IncorrectDataLen, IncorrectPayloadLenValue, UnknownAuthAlgorithm, + UnknownConfidentialityAlgorithm, UnknownIntegrityAlgorithm, UnknownPayloadType, + }; if data.len() != 8 { return Err(IncorrectDataLen); @@ -109,7 +112,7 @@ pub struct OpenSessionRequest { impl OpenSessionRequest { pub fn write_data(&self, buffer: &mut Vec) { buffer.push(self.message_tag); - buffer.push(self.requested_max_privilege.map(Into::into).unwrap_or(0)); + buffer.push(self.requested_max_privilege.map_or(0, Into::into)); // Two reserved bytes buffer.push(0); @@ -150,7 +153,12 @@ pub struct OpenSessionResponse { impl OpenSessionResponse { pub fn from_data(data: &[u8]) -> Result { - use ParseSessionResponseError::*; + use ParseSessionResponseError::{ + AlgorithmPayloadError, AuthPayloadWasNonAuthAlgorithm, + ConfidentialityPayloadWasNonConfidentialityAlgorithm, HaveErrorCode, + IntegrityPayloadWasNonIntegrityAlgorithm, InvalidPrivilegeLevel, NotEnoughData, + ZeroManagedSystemSessionId, ZeroRemoteConsoleSessionId, + }; if data.len() < 2 { return Err(NotEnoughData);