#include <net/pkt_cls.h>
#include <linux/can.h>
-#define EM_CAN_RULES_MAX 500
+#define EM_CAN_RULES_MAX 500
struct canid_match {
/* For each SFF CAN ID (11 bit) there is one record in this bitfield */
{
struct canid_match *cm = em_canid_priv(m);
canid_t can_id;
- unsigned int match = false;
+ int match = false;
int i;
+ const struct can_filter *lp;
can_id = em_canid_get_id(skb);
if (can_id & CAN_EFF_FLAG) {
- can_id &= CAN_EFF_MASK;
-
- for (i = 0; i < cm->eff_rules_count; i++) {
- if (!(((cm->rules_raw[i].can_id ^ can_id) &
- cm->rules_raw[i].can_mask) & CAN_EFF_MASK)) {
+ for (i = 0, lp = cm->rules_raw;
+ i < cm->eff_rules_count; i++, lp++) {
+ if (!(((lp->can_id ^ can_id) & lp->can_mask))) {
match = true;
break;
}
*/
struct canid_match *cm;
struct canid_match *cm_old = (struct canid_match *) m->data;
- int err;
int i;
int rulescnt;
- if (len < sizeof(struct can_filter))
+ if (len % sizeof(struct can_filter))
+ return -EINVAL;
+
+ if (len > sizeof(struct can_filter) * EM_CAN_RULES_MAX)
return -EINVAL;
rulescnt = len / sizeof(struct can_filter);
- err = -ENOBUFS;
cm = kzalloc(sizeof(struct canid_match) + sizeof(struct can_filter) *
rulescnt, GFP_KERNEL);
- if (cm == NULL)
- goto errout;
+ if (!cm)
+ return -ENOMEM;
cm->sff_rules_count = 0;
cm->eff_rules_count = 0;
cm->rules_count = rulescnt;
- err = -EINVAL;
-
- /* Be sure to fit into the array */
- if (cm->rules_count > EM_CAN_RULES_MAX)
- goto errout_free;
/*
* We need two for() loops for copying rules into
/* Process EFF frame rules*/
for (i = 0; i < cm->rules_count; i++) {
- if ((conf[i].can_id & CAN_EFF_FLAG) &&
- (conf[i].can_mask & CAN_EFF_FLAG)) {
+ if (((conf[i].can_id & CAN_EFF_FLAG) &&
+ (conf[i].can_mask & CAN_EFF_FLAG)) ||
+ !(conf[i].can_mask & CAN_EFF_FLAG)) {
memcpy(cm->rules_raw + cm->eff_rules_count,
&conf[i],
sizeof(struct can_filter));
m->data = (unsigned long) cm;
if (cm_old != NULL) {
- printk("canid: Configuring an existing ematch!\n");
+ printk(KERN_ERR"canid: Configuring an existing ematch!\n");
kfree(cm_old);
}
return 0;
-
-errout_free:
- kfree(cm);
-errout:
- return err;
}
static void em_canid_destroy(struct tcf_proto *tp, struct tcf_ematch *m)
* When configuring this ematch 'rules_count' is set not to exceed
* 'rules_raw' array size
*/
- if (nla_put_nohdr(skb, sizeof(cm->rules_raw[0]) * cm->rules_count,
+ if (nla_put_nohdr(skb, sizeof(struct can_filter) * cm->rules_count,
&cm->rules_raw) < 0)
- goto nla_put_failure;
+ return -EMSGSIZE;
return 0;
-
-nla_put_failure:
- return -1;
}
static struct tcf_ematch_ops em_canid_ops = {