#include <socketcan/can/version.h> /* for RCSID. Removed by mkpatch script */
RCSID("$Id$");
+/*
+ * To send multiple CAN frame content within TX_SETUP or to filter
+ * CAN messages with multiplex index within RX_SETUP, the number of
+ * different filters is limited to 256 due to the one byte index value.
+ */
+#define MAX_NFRAMES 256
+
/* use of last_frames[index].can_dlc */
#define RX_RECV 0x40 /* received data for this element */
#define RX_THR 0x80 /* element not been sent due to throttle feature */
struct list_head list;
int ifindex;
canid_t can_id;
- int flags;
+ u32 flags;
unsigned long frames_abs, frames_filtered;
struct timeval ival1, ival2;
struct hrtimer timer, thrtimer;
struct tasklet_struct tsklet, thrtsklet;
ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;
int rx_ifindex;
- int count;
- int nframes;
- int currframe;
+ u32 count;
+ u32 nframes;
+ u32 currframe;
struct can_frame *frames;
struct can_frame *last_frames;
struct can_frame sframe;
/*
* procfs functions
*/
-static char *bcm_proc_getifname(int ifindex)
+static char *bcm_proc_getifname(char *result, int ifindex)
{
struct net_device *dev;
if (!ifindex)
return "any";
- /* no usage counting */
+ read_lock(&dev_base_lock);
dev = __dev_get_by_index(&init_net, ifindex);
if (dev)
- return dev->name;
+ strcpy(result, dev->name);
+ else
+ strcpy(result, "???");
+ read_unlock(&dev_base_lock);
- return "???";
+ return result;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
static int bcm_proc_show(struct seq_file *m, void *v)
{
+ char ifname[IFNAMSIZ];
struct sock *sk = (struct sock *)m->private;
struct bcm_sock *bo = bcm_sk(sk);
struct bcm_op *op;
seq_printf(m, " / sk %p", sk);
seq_printf(m, " / bo %p", bo);
seq_printf(m, " / dropped %lu", bo->dropped_usr_msgs);
- seq_printf(m, " / bound %s", bcm_proc_getifname(bo->ifindex));
+ seq_printf(m, " / bound %s", bcm_proc_getifname(ifname, bo->ifindex));
seq_printf(m, " <<<\n");
list_for_each_entry(op, &bo->rx_ops, list) {
continue;
seq_printf(m, "rx_op: %03X %-5s ",
- op->can_id, bcm_proc_getifname(op->ifindex));
- seq_printf(m, "[%d]%c ", op->nframes,
+ op->can_id, bcm_proc_getifname(ifname, op->ifindex));
+ seq_printf(m, "[%u]%c ", op->nframes,
(op->flags & RX_CHECK_DLC)?'d':' ');
if (op->kt_ival1.tv64)
seq_printf(m, "timeo=%lld ",
list_for_each_entry(op, &bo->tx_ops, list) {
- seq_printf(m, "tx_op: %03X %s [%d] ",
- op->can_id, bcm_proc_getifname(op->ifindex),
+ seq_printf(m, "tx_op: %03X %s [%u] ",
+ op->can_id,
+ bcm_proc_getifname(ifname, op->ifindex),
op->nframes);
if (op->kt_ival1.tv64)
static int bcm_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
+ char ifname[IFNAMSIZ];
int len = 0;
struct sock *sk = (struct sock *)data;
struct bcm_sock *bo = bcm_sk(sk);
len += snprintf(page + len, PAGE_SIZE - len, " / dropped %lu",
bo->dropped_usr_msgs);
len += snprintf(page + len, PAGE_SIZE - len, " / bound %s",
- bcm_proc_getifname(bo->ifindex));
+ bcm_proc_getifname(ifname, bo->ifindex));
len += snprintf(page + len, PAGE_SIZE - len, " <<<\n");
list_for_each_entry(op, &bo->rx_ops, list) {
len += snprintf(page + len, PAGE_SIZE - len,
"rx_op: %03X %-5s ",
- op->can_id, bcm_proc_getifname(op->ifindex));
+ op->can_id, bcm_proc_getifname(ifname, op->ifindex));
len += snprintf(page + len, PAGE_SIZE - len, "[%d]%c ",
op->nframes,
(op->flags & RX_CHECK_DLC)?'d':' ');
len += snprintf(page + len, PAGE_SIZE - len,
"tx_op: %03X %s [%d] ",
- op->can_id, bcm_proc_getifname(op->ifindex),
+ op->can_id,
+ bcm_proc_getifname(ifname, op->ifindex),
op->nframes);
if (op->kt_ival1.tv64)
struct can_frame *firstframe;
struct sockaddr_can *addr;
struct sock *sk = op->sk;
- int datalen = head->nframes * CFSIZ;
+ unsigned int datalen = head->nframes * CFSIZ;
int err;
skb = alloc_skb(sizeof(*head) + datalen, gfp_any());
* bcm_rx_cmp_to_index - (bit)compares the currently received data to formerly
* received data stored in op->last_frames[]
*/
-static void bcm_rx_cmp_to_index(struct bcm_op *op, int index,
+static void bcm_rx_cmp_to_index(struct bcm_op *op, unsigned int index,
const struct can_frame *rxdata)
{
/*
/*
* bcm_rx_do_flush - helper for bcm_rx_thr_flush
*/
-static inline int bcm_rx_do_flush(struct bcm_op *op, int update, int index)
+static inline int bcm_rx_do_flush(struct bcm_op *op, int update,
+ unsigned int index)
{
if ((op->last_frames) && (op->last_frames[index].can_dlc & RX_THR)) {
if (update)
int updated = 0;
if (op->nframes > 1) {
- int i;
+ unsigned int i;
/* for MUX filter we start at index 1 */
for (i = 1; i < op->nframes; i++)
{
struct bcm_op *op = (struct bcm_op *)data;
const struct can_frame *rxframe = (struct can_frame *)skb->data;
- int i;
+ unsigned int i;
/* disable timeout */
hrtimer_cancel(&op->timer);
{
struct bcm_sock *bo = bcm_sk(sk);
struct bcm_op *op;
- int i, err;
+ unsigned int i;
+ int err;
/* we need a real device to send frames */
if (!ifindex)
return -ENODEV;
- /* we need at least one can_frame */
- if (msg_head->nframes < 1)
+ /* check nframes boundaries - we need at least one can_frame */
+ if (msg_head->nframes < 1 || msg_head->nframes > MAX_NFRAMES)
return -EINVAL;
/* check the given can_id */
msg_head->nframes = 0;
}
+ /* the first element contains the mux-mask => MAX_NFRAMES + 1 */
+ if (msg_head->nframes > MAX_NFRAMES + 1)
+ return -EINVAL;
+
if ((msg_head->flags & RX_RTR_FRAME) &&
((msg_head->nframes != 1) ||
(!(msg_head->can_id & CAN_RTR_FLAG))))