mirror of
https://github.com/rwinkhart/sys.git
synced 2026-09-01 22:57:29 -04:00
unix: add J1939 protocol support on socketcan interface
Fixes golang/go#42797 Change-Id: Ia7be73e53438dec80903c95de0e6829005741a0f GitHub-Last-Rev: bc3583533928d549ea6bedd4dae13e0643da2a44 GitHub-Pull-Request: golang/sys#91 Reviewed-on: https://go-review.googlesource.com/c/sys/+/272767 Run-TryBot: Matt Layher <mdlayher@gmail.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com> Reviewed-by: Matt Layher <mdlayher@gmail.com> Trust: Tobias Klauser <tobias.klauser@gmail.com>
This commit is contained in:
@@ -169,7 +169,7 @@ func Test_anyToSockaddr(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "AF_CAN",
|
name: "AF_CAN CAN_RAW",
|
||||||
rsa: sockaddrCANToAny(RawSockaddrCAN{
|
rsa: sockaddrCANToAny(RawSockaddrCAN{
|
||||||
Family: AF_CAN,
|
Family: AF_CAN,
|
||||||
Ifindex: 12345678,
|
Ifindex: 12345678,
|
||||||
@@ -185,6 +185,27 @@ func Test_anyToSockaddr(t *testing.T) {
|
|||||||
RxID: 0xAAAAAAAA,
|
RxID: 0xAAAAAAAA,
|
||||||
TxID: 0xBBBBBBBB,
|
TxID: 0xBBBBBBBB,
|
||||||
},
|
},
|
||||||
|
skt: SocketSpec{domain: AF_CAN, typ: SOCK_RAW, protocol: CAN_RAW},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "AF_CAN CAN_J1939",
|
||||||
|
rsa: sockaddrCANToAny(RawSockaddrCAN{
|
||||||
|
Family: AF_CAN,
|
||||||
|
Ifindex: 12345678,
|
||||||
|
Addr: [16]byte{
|
||||||
|
0xAA, 0xAA, 0xAA, 0xAA,
|
||||||
|
0xAA, 0xAA, 0xAA, 0xAA,
|
||||||
|
0xBB, 0xBB, 0xBB, 0xBB,
|
||||||
|
0xCC, 0x00, 0x00, 0x00,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
sa: &SockaddrCANJ1939{
|
||||||
|
Ifindex: 12345678,
|
||||||
|
Name: 0xAAAAAAAAAAAAAAAA,
|
||||||
|
PGN: 0xBBBBBBBB,
|
||||||
|
Addr: 0xCC,
|
||||||
|
},
|
||||||
|
skt: SocketSpec{domain: AF_CAN, typ: SOCK_DGRAM, protocol: CAN_J1939},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "AF_MAX EAFNOSUPPORT",
|
name: "AF_MAX EAFNOSUPPORT",
|
||||||
@@ -205,10 +226,16 @@ func Test_anyToSockaddr(t *testing.T) {
|
|||||||
if tt.skt.domain != 0 {
|
if tt.skt.domain != 0 {
|
||||||
fd, err = Socket(tt.skt.domain, tt.skt.typ, tt.skt.protocol)
|
fd, err = Socket(tt.skt.domain, tt.skt.typ, tt.skt.protocol)
|
||||||
// Some sockaddr types need specific kernel modules running: if these
|
// Some sockaddr types need specific kernel modules running: if these
|
||||||
// are not present we'll get EPROTONOSUPPORT back when trying to create
|
// are not present we'll get EPROTONOSUPPORT/EAFNOSUPPORT back when
|
||||||
// the socket. Skip the test in this situation.
|
// trying to create the socket. Skip the test in this situation.
|
||||||
if err == EPROTONOSUPPORT {
|
if err == EPROTONOSUPPORT {
|
||||||
t.Skip("socket family/protocol not supported by kernel")
|
t.Skip("socket family/protocol not supported by kernel")
|
||||||
|
} else if err == EAFNOSUPPORT {
|
||||||
|
t.Skip("socket address family not supported by kernel")
|
||||||
|
} else if err == EACCES {
|
||||||
|
// Some platforms might require elevated privileges to perform
|
||||||
|
// actions on sockets. Skip the test in this situation.
|
||||||
|
t.Skip("socket operation not permitted")
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
t.Fatalf("socket(%v): %v", tt.skt, err)
|
t.Fatalf("socket(%v): %v", tt.skt, err)
|
||||||
}
|
}
|
||||||
|
|||||||
+65
-12
@@ -641,6 +641,36 @@ func (sa *SockaddrCAN) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
|||||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrCAN, nil
|
return unsafe.Pointer(&sa.raw), SizeofSockaddrCAN, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SockaddrCANJ1939 implements the Sockaddr interface for AF_CAN using J1939
|
||||||
|
// protocol (https://en.wikipedia.org/wiki/SAE_J1939). For more information
|
||||||
|
// on the purposes of the fields, check the official linux kernel documentation
|
||||||
|
// available here: https://www.kernel.org/doc/Documentation/networking/j1939.rst
|
||||||
|
type SockaddrCANJ1939 struct {
|
||||||
|
Ifindex int
|
||||||
|
Name uint64
|
||||||
|
PGN uint32
|
||||||
|
Addr uint8
|
||||||
|
raw RawSockaddrCAN
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sa *SockaddrCANJ1939) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||||
|
if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff {
|
||||||
|
return nil, 0, EINVAL
|
||||||
|
}
|
||||||
|
sa.raw.Family = AF_CAN
|
||||||
|
sa.raw.Ifindex = int32(sa.Ifindex)
|
||||||
|
n := (*[8]byte)(unsafe.Pointer(&sa.Name))
|
||||||
|
for i := 0; i < 8; i++ {
|
||||||
|
sa.raw.Addr[i] = n[i]
|
||||||
|
}
|
||||||
|
p := (*[4]byte)(unsafe.Pointer(&sa.PGN))
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
sa.raw.Addr[i+8] = p[i]
|
||||||
|
}
|
||||||
|
sa.raw.Addr[12] = sa.Addr
|
||||||
|
return unsafe.Pointer(&sa.raw), SizeofSockaddrCAN, nil
|
||||||
|
}
|
||||||
|
|
||||||
// SockaddrALG implements the Sockaddr interface for AF_ALG type sockets.
|
// SockaddrALG implements the Sockaddr interface for AF_ALG type sockets.
|
||||||
// SockaddrALG enables userspace access to the Linux kernel's cryptography
|
// SockaddrALG enables userspace access to the Linux kernel's cryptography
|
||||||
// subsystem. The Type and Name fields specify which type of hash or cipher
|
// subsystem. The Type and Name fields specify which type of hash or cipher
|
||||||
@@ -1150,20 +1180,43 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
|||||||
return sa, nil
|
return sa, nil
|
||||||
|
|
||||||
case AF_CAN:
|
case AF_CAN:
|
||||||
pp := (*RawSockaddrCAN)(unsafe.Pointer(rsa))
|
proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL)
|
||||||
sa := &SockaddrCAN{
|
if err != nil {
|
||||||
Ifindex: int(pp.Ifindex),
|
return nil, err
|
||||||
}
|
}
|
||||||
rx := (*[4]byte)(unsafe.Pointer(&sa.RxID))
|
|
||||||
for i := 0; i < 4; i++ {
|
|
||||||
rx[i] = pp.Addr[i]
|
|
||||||
}
|
|
||||||
tx := (*[4]byte)(unsafe.Pointer(&sa.TxID))
|
|
||||||
for i := 0; i < 4; i++ {
|
|
||||||
tx[i] = pp.Addr[i+4]
|
|
||||||
}
|
|
||||||
return sa, nil
|
|
||||||
|
|
||||||
|
pp := (*RawSockaddrCAN)(unsafe.Pointer(rsa))
|
||||||
|
|
||||||
|
switch proto {
|
||||||
|
case CAN_J1939:
|
||||||
|
sa := &SockaddrCANJ1939{
|
||||||
|
Ifindex: int(pp.Ifindex),
|
||||||
|
}
|
||||||
|
name := (*[8]byte)(unsafe.Pointer(&sa.Name))
|
||||||
|
for i := 0; i < 8; i++ {
|
||||||
|
name[i] = pp.Addr[i]
|
||||||
|
}
|
||||||
|
pgn := (*[4]byte)(unsafe.Pointer(&sa.PGN))
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
pgn[i] = pp.Addr[i+8]
|
||||||
|
}
|
||||||
|
addr := (*[1]byte)(unsafe.Pointer(&sa.Addr))
|
||||||
|
addr[0] = pp.Addr[12]
|
||||||
|
return sa, nil
|
||||||
|
default:
|
||||||
|
sa := &SockaddrCAN{
|
||||||
|
Ifindex: int(pp.Ifindex),
|
||||||
|
}
|
||||||
|
rx := (*[4]byte)(unsafe.Pointer(&sa.RxID))
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
rx[i] = pp.Addr[i]
|
||||||
|
}
|
||||||
|
tx := (*[4]byte)(unsafe.Pointer(&sa.TxID))
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
tx[i] = pp.Addr[i+4]
|
||||||
|
}
|
||||||
|
return sa, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil, EAFNOSUPPORT
|
return nil, EAFNOSUPPORT
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user