Skip to content

Commit

Permalink
Added check to verify that CAN_EFF_FLAG is set when CAN ID exceeds 11…
Browse files Browse the repository at this point in the history
… bit - Closes #31
  • Loading branch information
derek-will committed May 15, 2022
1 parent 6ea4412 commit 587fbd2
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 6 deletions.
19 changes: 17 additions & 2 deletions src/SocketCANSharp/CanFdFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,27 @@ namespace SocketCANSharp
[StructLayout(LayoutKind.Sequential)]
public struct CanFdFrame
{
private uint _canId;

/// <summary>
/// Controller Area Network Identifier structure:
/// bit 0-28: CAN identifier (11 or 29 bit)
/// bit 29: Error frame flag (0 = Data frame, 1 = Error frame)
/// bit 30: Remote frame flag (1 = Remote Transmission Request (RTR) bit is set)
/// bit 31: Frame format flag (0 = standard 11 bit, 1 = extended 29 bit)
/// </summary>
public uint CanId { get; set; }
public uint CanId
{
get
{
return _canId;
}
set
{
SocketCanUtils.ThrowIfCanIdStructureInvalid(value);
_canId = value;
}
}
/// <summary>
/// Frame length in bytes.
/// </summary>
Expand Down Expand Up @@ -87,7 +100,9 @@ public CanFdFrame(uint canId, byte[] data, CanFdFlags flags)
if (data.Length > SocketCanConstants.CANFD_MAX_DLEN)
throw new ArgumentOutOfRangeException(nameof(data), $"Data must be {SocketCanConstants.CANFD_MAX_DLEN} bytes or less");

CanId = canId;
SocketCanUtils.ThrowIfCanIdStructureInvalid(canId);

_canId = canId;
Length = (byte) data?.Length;
Flags = flags;
Res0 = 0x00;
Expand Down
19 changes: 17 additions & 2 deletions src/SocketCANSharp/CanFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,27 @@ namespace SocketCANSharp
[StructLayout(LayoutKind.Sequential)]
public struct CanFrame
{
private uint _canId;

/// <summary>
/// Controller Area Network Identifier structure:
/// bit 0-28: CAN identifier (11 or 29 bit)
/// bit 29: Error frame flag (0 = Data frame, 1 = Error frame)
/// bit 30: Remote frame flag (1 = Remote Transmission Request (RTR) bit is set)
/// bit 31: Frame format flag (0 = standard 11 bit, 1 = extended 29 bit)
/// </summary>
public uint CanId { get; set; }
public uint CanId
{
get
{
return _canId;
}
set
{
SocketCanUtils.ThrowIfCanIdStructureInvalid(value);
_canId = value;
}
}
/// <summary>
/// Frame length in bytes.
/// </summary>
Expand Down Expand Up @@ -86,7 +99,9 @@ public CanFrame(uint canId, byte[] data)
if (data.Length > SocketCanConstants.CAN_MAX_DLEN)
throw new ArgumentOutOfRangeException(nameof(data), $"Data must be {SocketCanConstants.CAN_MAX_DLEN} bytes or less");

CanId = canId;
SocketCanUtils.ThrowIfCanIdStructureInvalid(canId);

_canId = canId;
Length = (byte) data?.Length;
Pad = 0x00;
Res0 = 0x00;
Expand Down
30 changes: 28 additions & 2 deletions src/SocketCANSharp/SockAddrCanIsoTp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,40 @@ namespace SocketCANSharp
[StructLayout(LayoutKind.Sequential)]
public class SockAddrCanIsoTp : SockAddrCan
{
private uint _rxId;
private uint _txId;

/// <summary>
/// CAN ID to receive on. Typically, CAN frames coming from the ECU will use this CAN ID (ex. 0x7e8).
/// </summary>
public uint RxId { get; set; }
public uint RxId
{
get
{
return _rxId;
}
set
{
SocketCanUtils.ThrowIfCanIdStructureInvalid(value);
_rxId = value;
}
}

/// <summary>
/// CAN ID to transmit with. Typically, CAN frames being sent from the Tester will use this CAN ID (ex. 0x7e0).
/// </summary>
public uint TxId { get; set; }
public uint TxId
{
get
{
return _txId;
}
set
{
SocketCanUtils.ThrowIfCanIdStructureInvalid(value);
_txId = value;
}
}

/// <summary>
/// Initializes a SocketCAN ISO-TP address structure with default values of zeroes.
Expand Down
58 changes: 58 additions & 0 deletions src/SocketCANSharp/SocketCanUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#region License
/*
BSD 3-Clause License
Copyright (c) 2021, Derek Will
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#endregion

using System;

namespace SocketCANSharp
{
/// <summary>
/// Set of SocketCAN utility functions.
/// </summary>
public static class SocketCanUtils
{
/// <summary>
/// Validates the SocketCAN CAN Identifier structure.
/// </summary>
/// <param name="canId">CAN Identifier structure</param>
/// <exception cref="ArgumentException">CAN_EFF_FLAG not set on a CAN ID that exceeds 11 bits.</exception>
public static void ThrowIfCanIdStructureInvalid(uint canId)
{
uint rawId = canId & SocketCanConstants.CAN_EFF_MASK; // remove ERR, RTR, and EFF flags
if (rawId > 0x7ff && (canId & (uint)CanIdFlags.CAN_EFF_FLAG) == 0)
{
throw new ArgumentException("CAN_EFF_FLAG must be set when CAN ID exceeds 11 bits.", nameof(canId));
}
}
}
}
33 changes: 33 additions & 0 deletions test/SocketCANSharpTest/CanFdFrameWriteTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
*/
#endregion

using System;
using NUnit.Framework;
using SocketCANSharp;
using System.Net.Sockets;
Expand Down Expand Up @@ -175,5 +176,37 @@ public void CanFdFrameWrite_29BitAddressing_Success_Test()
int nBytes = LibcNativeMethods.Write(socketHandle, ref canFdFrame, Marshal.SizeOf(typeof(CanFdFrame)));
Assert.AreEqual(72, nBytes);
}

[Test]
public void CanFdFrameWrite_InvalidAddress_Ctor_Failure_Test()
{
var ifr = new Ifreq("vcan0");
int ioctlResult = LibcNativeMethods.Ioctl(socketHandle, SocketCanConstants.SIOCGIFINDEX, ifr);
Assert.AreNotEqual(-1, ioctlResult);

var addr = new SockAddrCan(ifr.IfIndex);

int bindResult = LibcNativeMethods.Bind(socketHandle, addr, Marshal.SizeOf(typeof(SockAddrCan)));
Assert.AreNotEqual(-1, bindResult);

Assert.Throws<ArgumentException>(() => new CanFdFrame(0x18db33f1, new byte[] { 0x11, 0x22 }, CanFdFlags.None));
}

[Test]
public void CanFdFrameWrite_InvalidAddress_Property_Failure_Test()
{
var ifr = new Ifreq("vcan0");
int ioctlResult = LibcNativeMethods.Ioctl(socketHandle, SocketCanConstants.SIOCGIFINDEX, ifr);
Assert.AreNotEqual(-1, ioctlResult);

var addr = new SockAddrCan(ifr.IfIndex);

int bindResult = LibcNativeMethods.Bind(socketHandle, addr, Marshal.SizeOf(typeof(SockAddrCan)));
Assert.AreNotEqual(-1, bindResult);

var canFdFrame = new CanFdFrame(0x123, new byte[] { 0x11, 0x22 }, CanFdFlags.None);

Assert.Throws<ArgumentException>(() => canFdFrame.CanId = 0x18db33f1);
}
}
}
31 changes: 31 additions & 0 deletions test/SocketCANSharpTest/CanFrameWriteTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
*/
#endregion

using System;
using NUnit.Framework;
using SocketCANSharp;
using System.Net.Sockets;
Expand Down Expand Up @@ -152,5 +153,35 @@ public void CanFrameWrite_ErrorFrame_Success_Test()
int nBytes = LibcNativeMethods.Write(socketHandle, ref canFrame, Marshal.SizeOf(typeof(CanFrame)));
Assert.AreEqual(16, nBytes);
}

[Test]
public void CanFrameWrite_InvalidAddress_Ctor_Failure_Test()
{
var ifr = new Ifreq("vcan0");
int ioctlResult = LibcNativeMethods.Ioctl(socketHandle, SocketCanConstants.SIOCGIFINDEX, ifr);
Assert.AreNotEqual(-1, ioctlResult);

var addr = new SockAddrCan(ifr.IfIndex);
int bindResult = LibcNativeMethods.Bind(socketHandle, addr, Marshal.SizeOf(typeof(SockAddrCan)));
Assert.AreNotEqual(-1, bindResult);

Assert.Throws<ArgumentException>(() => new CanFrame(0x18db33f1, new byte[] { 0x11, 0x22 }));
}

[Test]
public void CanFrameWrite_InvalidAddress_Property_Failure_Test()
{
var ifr = new Ifreq("vcan0");
int ioctlResult = LibcNativeMethods.Ioctl(socketHandle, SocketCanConstants.SIOCGIFINDEX, ifr);
Assert.AreNotEqual(-1, ioctlResult);

var addr = new SockAddrCan(ifr.IfIndex);
int bindResult = LibcNativeMethods.Bind(socketHandle, addr, Marshal.SizeOf(typeof(SockAddrCan)));
Assert.AreNotEqual(-1, bindResult);

var canFrame = new CanFrame(0x123, new byte[] { 0x11, 0x22 });

Assert.Throws<ArgumentException>(() => canFrame.CanId = 0x18db33f1);
}
}
}
29 changes: 29 additions & 0 deletions test/SocketCANSharpTest/CanIsoTpTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
*/
#endregion

using System;
using NUnit.Framework;
using SocketCANSharp;
using System.Net.Sockets;
Expand Down Expand Up @@ -407,5 +408,33 @@ public void CAN_ISOTP_1_to_N_ClassicCAN_Success_Test()
nBytes = LibcNativeMethods.Read(obdTester2SocketHandle, receiveResponseMessage, receiveResponseMessage.Length);
Assert.AreEqual(6, nBytes);
}

[Test]
public void CAN_ISOTP_SockAddr_InvalidAddress_TxId_Failure_Test()
{
var ifr = new Ifreq("vcan0");
int ioctlResult = LibcNativeMethods.Ioctl(testerSocketHandle, SocketCanConstants.SIOCGIFINDEX, ifr);
Assert.AreNotEqual(-1, ioctlResult);

Assert.Throws<ArgumentException>(() => new SockAddrCanIsoTp(ifr.IfIndex)
{
TxId = 0x1500,
RxId = 0x600,
});
}

[Test]
public void CAN_ISOTP_SockAddr_InvalidAddress_RxId_Failure_Test()
{
var ifr = new Ifreq("vcan0");
int ioctlResult = LibcNativeMethods.Ioctl(testerSocketHandle, SocketCanConstants.SIOCGIFINDEX, ifr);
Assert.AreNotEqual(-1, ioctlResult);

Assert.Throws<ArgumentException>(() => new SockAddrCanIsoTp(ifr.IfIndex)
{
TxId = 0x500,
RxId = 0x1600,
});
}
}
}

0 comments on commit 587fbd2

Please sign in to comment.