#include <net/pkt_cls.h>
#include <linux/can.h>
-#define EM_CAN_RULES_SIZE 32
+#define EM_CAN_RULES_MAX 500
struct canid_match {
- /*
- * Raw rules copied from netlink message; Used for sending
- * information to userspace (when 'tc filter show' is invoked)
- * AND when matching EFF frames
- */
- struct can_filter rules_raw[EM_CAN_RULES_SIZE];
-
/* For each SFF CAN ID (11 bit) there is one record in this bitfield */
DECLARE_BITMAP(match_sff, (1 << CAN_SFF_ID_BITS));
int rules_count;
- int eff_rules_count;
int sff_rules_count;
+ int eff_rules_count;
+
+ /*
+ * Raw rules copied from netlink message; Used for sending
+ * information to userspace (when 'tc filter show' is invoked)
+ * AND when matching EFF frames
+ */
+ struct can_filter rules_raw[];
};
/**
static inline struct canid_match *em_canid_priv(struct tcf_ematch *m)
{
- return (struct canid_match *) (m)->data;
+ return (struct canid_match *) m->data;
}
static int em_canid_match(struct sk_buff *skb, struct tcf_ematch *m,
* fixed size EM_CAN_RULES_SIZE
*/
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))
return -EINVAL;
+ rulescnt = len / sizeof(struct can_filter);
+
err = -ENOBUFS;
- cm = kzalloc(sizeof(*cm), GFP_KERNEL);
+ cm = kzalloc(sizeof(struct canid_match) + sizeof(struct can_filter) *
+ rulescnt, GFP_KERNEL);
if (cm == NULL)
goto errout;
cm->sff_rules_count = 0;
cm->eff_rules_count = 0;
- cm->rules_count = len/sizeof(struct can_filter);
+ cm->rules_count = rulescnt;
err = -EINVAL;
/* Be sure to fit into the array */
- if (cm->rules_count > EM_CAN_RULES_SIZE)
+ if (cm->rules_count > EM_CAN_RULES_MAX)
goto errout_free;
/*
m->datalen = sizeof(*cm);
m->data = (unsigned long) cm;
+ if (cm_old != NULL) {
+ printk("canid: Configuring an existing ematch!\n");
+ kfree(cm_old);
+ }
+
return 0;
errout_free: