|
@@ -42,6 +42,7 @@
|
|
|
#include <linux/module.h>
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/types.h>
|
|
|
+#include <linux/kernel.h>
|
|
|
#include <linux/list.h>
|
|
|
#include <linux/spinlock.h>
|
|
|
#include <linux/rcupdate.h>
|
|
@@ -58,14 +59,25 @@
|
|
|
#include <net/net_namespace.h>
|
|
|
#include <net/sock.h>
|
|
|
|
|
|
-#define CAN_GW_VERSION "20101209"
|
|
|
-static __initconst const char banner[] =
|
|
|
- KERN_INFO "can: netlink gateway (rev " CAN_GW_VERSION ")\n";
|
|
|
+#define CAN_GW_VERSION "20130117"
|
|
|
+#define CAN_GW_NAME "can-gw"
|
|
|
|
|
|
MODULE_DESCRIPTION("PF_CAN netlink gateway");
|
|
|
MODULE_LICENSE("Dual BSD/GPL");
|
|
|
MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>");
|
|
|
-MODULE_ALIAS("can-gw");
|
|
|
+MODULE_ALIAS(CAN_GW_NAME);
|
|
|
+
|
|
|
+#define CGW_MIN_HOPS 1
|
|
|
+#define CGW_MAX_HOPS 6
|
|
|
+#define CGW_DEFAULT_HOPS 1
|
|
|
+
|
|
|
+static unsigned int max_hops __read_mostly = CGW_DEFAULT_HOPS;
|
|
|
+module_param(max_hops, uint, S_IRUGO);
|
|
|
+MODULE_PARM_DESC(max_hops,
|
|
|
+ "maximum " CAN_GW_NAME " routing hops for CAN frames "
|
|
|
+ "(valid values: " __stringify(CGW_MIN_HOPS) "-"
|
|
|
+ __stringify(CGW_MAX_HOPS) " hops, "
|
|
|
+ "default: " __stringify(CGW_DEFAULT_HOPS) ")");
|
|
|
|
|
|
static HLIST_HEAD(cgw_list);
|
|
|
static struct notifier_block notifier;
|
|
@@ -339,8 +351,23 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
|
|
|
struct sk_buff *nskb;
|
|
|
int modidx = 0;
|
|
|
|
|
|
- /* do not handle already routed frames - see comment below */
|
|
|
- if (skb_mac_header_was_set(skb))
|
|
|
+ /*
|
|
|
+ * Do not handle CAN frames routed more than 'max_hops' times.
|
|
|
+ * In general we should never catch this delimiter which is intended
|
|
|
+ * to cover a misconfiguration protection (e.g. circular CAN routes).
|
|
|
+ *
|
|
|
+ * The Controller Area Network controllers only accept CAN frames with
|
|
|
+ * correct CRCs - which are not visible in the controller registers.
|
|
|
+ * According to skbuff.h documentation the csum_start element for IP
|
|
|
+ * checksums is undefined/unsued when ip_summed == CHECKSUM_UNNECESSARY.
|
|
|
+ * Only CAN skbs can be processed here which already have this property.
|
|
|
+ */
|
|
|
+
|
|
|
+#define cgw_hops(skb) ((skb)->csum_start)
|
|
|
+
|
|
|
+ BUG_ON(skb->ip_summed != CHECKSUM_UNNECESSARY);
|
|
|
+
|
|
|
+ if (cgw_hops(skb) >= max_hops)
|
|
|
return;
|
|
|
|
|
|
if (!(gwj->dst.dev->flags & IFF_UP)) {
|
|
@@ -371,15 +398,8 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * Mark routed frames by setting some mac header length which is
|
|
|
- * not relevant for the CAN frames located in the skb->data section.
|
|
|
- *
|
|
|
- * As dev->header_ops is not set in CAN netdevices no one is ever
|
|
|
- * accessing the various header offsets in the CAN skbuffs anyway.
|
|
|
- * E.g. using the packet socket to read CAN frames is still working.
|
|
|
- */
|
|
|
- skb_set_mac_header(nskb, 8);
|
|
|
+ /* put the incremented hop counter in the cloned skb */
|
|
|
+ cgw_hops(nskb) = cgw_hops(skb) + 1;
|
|
|
nskb->dev = gwj->dst.dev;
|
|
|
|
|
|
/* pointer to modifiable CAN frame */
|
|
@@ -903,7 +923,11 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
|
|
|
|
|
|
static __init int cgw_module_init(void)
|
|
|
{
|
|
|
- printk(banner);
|
|
|
+ /* sanitize given module parameter */
|
|
|
+ max_hops = clamp_t(unsigned int, max_hops, CGW_MIN_HOPS, CGW_MAX_HOPS);
|
|
|
+
|
|
|
+ pr_info("can: netlink gateway (rev " CAN_GW_VERSION ") max_hops=%d\n",
|
|
|
+ max_hops);
|
|
|
|
|
|
cgw_cache = kmem_cache_create("can_gw", sizeof(struct cgw_job),
|
|
|
0, 0, NULL);
|