# Copyright 2018 syzkaller project authors. All rights reserved.
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

# AF_CAN support.

include <linux/net.h>
include <linux/socket.h>
include <uapi/linux/if.h>
include <uapi/linux/can.h>
include <uapi/linux/can/raw.h>
include <uapi/linux/can/bcm.h>

resource sock_can[sock]
resource sock_can_raw[sock_can]
resource sock_can_bcm[sock_can]
resource ifindex_vcan[ifindex]

socket$can_raw(domain const[AF_CAN], type const[SOCK_RAW], proto const[CAN_RAW]) sock_can_raw
bind$can_raw(fd sock_can_raw, addr ptr[in, sockaddr_can], len bytesize[addr])
sendmsg$can_raw(fd sock_can_raw, msg ptr[in, msghdr_can[can_raw_msg]], f flags[send_flags])

socket$can_bcm(domain const[AF_CAN], type const[SOCK_DGRAM], proto const[CAN_BCM]) sock_can_bcm
connect$can_bcm(fd sock_can_bcm, addr ptr[in, sockaddr_can], len bytesize[addr])
sendmsg$can_bcm(fd sock_can_bcm, msg ptr[in, msghdr_can[can_bcm_msg]], f flags[send_flags])

# TODO: do setsockopt/getsockopt/ioctl.

ioctl$ifreq_SIOCGIFINDEX_vcan(fd sock_can, cmd const[SIOCGIFINDEX], arg ptr[inout, ifreq_dev_t["vcan0", ifindex_vcan]])

sockaddr_can {
	can_family	const[AF_CAN, int16]
	can_ifindex	ifindex_vcan[opt]
	rx_id		const[0, int32]
	tx_id		const[0, int32]
}

type msghdr_can[MSG] {
	addr	ptr[in, sockaddr_can]
	addrlen	len[addr, int32]
	vec	ptr[in, iovec[in, MSG]]
	vlen	const[1, intptr]
	ctrl	const[0, intptr]
	ctrllen	const[0, intptr]
	f	flags[send_flags, int32]
}

can_raw_msg [
	can	can_frame
	canfd	canfd_frame
] [varlen]

can_bcm_msg {
	opcode	flags[can_bcm_opcodes, int32]
	flags	flags[can_bcm_flags, int32]
	count	int32
	ival1	timeval
	ival2	timeval
	can_id	canid_t
	nframes	const[1, int32]
	frames	can_raw_msg
}

type can_frame_t[DATA_SIZE] {
	can_id	canid_t
	len	int8[0:DATA_SIZE]
	flags	flags[can_frame_flags, int8]
	__res0	const[0, int8]
	__res1	const[0, int8]
	data	array[int8, DATA_SIZE]
}

type can_frame can_frame_t[CAN_MAX_DLEN]
type canfd_frame can_frame_t[CANFD_MAX_DLEN]

canid_t {
	id	int32:29[0:4]
	err	int32:1
	rtr	int32:1
	eff	int32:1
}

can_bcm_opcodes = TX_SETUP, TX_DELETE, TX_READ, TX_SEND, RX_SETUP, RX_DELETE, RX_READ
can_bcm_flags = SETTIMER, STARTTIMER, TX_COUNTEVT, TX_ANNOUNCE, TX_CP_CAN_ID, RX_FILTER_ID, RX_CHECK_DLC, RX_NO_AUTOTIMER, RX_ANNOUNCE_RESUME, TX_RESET_MULTI_IDX, RX_RTR_FRAME, CAN_FD_FRAME
can_frame_flags = CANFD_BRS, CANFD_ESI