aboutsummaryrefslogtreecommitdiffstats
path: root/net/can/gw.c
diff options
context:
space:
mode:
authorOliver Hartkopp <socketcan@hartkopp.net>2013-01-17 12:43:44 -0500
committerMarc Kleine-Budde <mkl@pengutronix.de>2013-01-26 10:59:01 -0500
commitbe286bafe1f4069094865264f29805854c5788bf (patch)
tree1db2a2fa446d714e6b64630f6b6d91525d9f4984 /net/can/gw.c
parentd904d3edcbb26efc86ea3575bb4265559801a94b (diff)
can: gw: add a variable limit for CAN frame routings
To prevent a possible misconfiguration (e.g. circular CAN frame routings) limit the number of routings of a single CAN frame to a small variable value. The limit can be specified by the module parameter 'max_hops' (1..6). The default value is 1 (one hop), according to the original can-gw behaviour. Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'net/can/gw.c')
-rw-r--r--net/can/gw.c56
1 files changed, 40 insertions, 16 deletions
diff --git a/net/can/gw.c b/net/can/gw.c
index 37a3efb7cc9d..4216a80618cb 100644
--- a/net/can/gw.c
+++ b/net/can/gw.c
@@ -42,6 +42,7 @@
42#include <linux/module.h> 42#include <linux/module.h>
43#include <linux/init.h> 43#include <linux/init.h>
44#include <linux/types.h> 44#include <linux/types.h>
45#include <linux/kernel.h>
45#include <linux/list.h> 46#include <linux/list.h>
46#include <linux/spinlock.h> 47#include <linux/spinlock.h>
47#include <linux/rcupdate.h> 48#include <linux/rcupdate.h>
@@ -58,14 +59,25 @@
58#include <net/net_namespace.h> 59#include <net/net_namespace.h>
59#include <net/sock.h> 60#include <net/sock.h>
60 61
61#define CAN_GW_VERSION "20101209" 62#define CAN_GW_VERSION "20130117"
62static __initconst const char banner[] = 63#define CAN_GW_NAME "can-gw"
63 KERN_INFO "can: netlink gateway (rev " CAN_GW_VERSION ")\n";
64 64
65MODULE_DESCRIPTION("PF_CAN netlink gateway"); 65MODULE_DESCRIPTION("PF_CAN netlink gateway");
66MODULE_LICENSE("Dual BSD/GPL"); 66MODULE_LICENSE("Dual BSD/GPL");
67MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>"); 67MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>");
68MODULE_ALIAS("can-gw"); 68MODULE_ALIAS(CAN_GW_NAME);
69
70#define CGW_MIN_HOPS 1
71#define CGW_MAX_HOPS 6
72#define CGW_DEFAULT_HOPS 1
73
74static unsigned int max_hops __read_mostly = CGW_DEFAULT_HOPS;
75module_param(max_hops, uint, S_IRUGO);
76MODULE_PARM_DESC(max_hops,
77 "maximum " CAN_GW_NAME " routing hops for CAN frames "
78 "(valid values: " __stringify(CGW_MIN_HOPS) "-"
79 __stringify(CGW_MAX_HOPS) " hops, "
80 "default: " __stringify(CGW_DEFAULT_HOPS) ")");
69 81
70static HLIST_HEAD(cgw_list); 82static HLIST_HEAD(cgw_list);
71static struct notifier_block notifier; 83static struct notifier_block notifier;
@@ -339,8 +351,23 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
339 struct sk_buff *nskb; 351 struct sk_buff *nskb;
340 int modidx = 0; 352 int modidx = 0;
341 353
342 /* do not handle already routed frames - see comment below */ 354 /*
343 if (skb_mac_header_was_set(skb)) 355 * Do not handle CAN frames routed more than 'max_hops' times.
356 * In general we should never catch this delimiter which is intended
357 * to cover a misconfiguration protection (e.g. circular CAN routes).
358 *
359 * The Controller Area Network controllers only accept CAN frames with
360 * correct CRCs - which are not visible in the controller registers.
361 * According to skbuff.h documentation the csum_start element for IP
362 * checksums is undefined/unsued when ip_summed == CHECKSUM_UNNECESSARY.
363 * Only CAN skbs can be processed here which already have this property.
364 */
365
366#define cgw_hops(skb) ((skb)->csum_start)
367
368 BUG_ON(skb->ip_summed != CHECKSUM_UNNECESSARY);
369
370 if (cgw_hops(skb) >= max_hops)
344 return; 371 return;
345 372
346 if (!(gwj->dst.dev->flags & IFF_UP)) { 373 if (!(gwj->dst.dev->flags & IFF_UP)) {
@@ -371,15 +398,8 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
371 return; 398 return;
372 } 399 }
373 400
374 /* 401 /* put the incremented hop counter in the cloned skb */
375 * Mark routed frames by setting some mac header length which is 402 cgw_hops(nskb) = cgw_hops(skb) + 1;
376 * not relevant for the CAN frames located in the skb->data section.
377 *
378 * As dev->header_ops is not set in CAN netdevices no one is ever
379 * accessing the various header offsets in the CAN skbuffs anyway.
380 * E.g. using the packet socket to read CAN frames is still working.
381 */
382 skb_set_mac_header(nskb, 8);
383 nskb->dev = gwj->dst.dev; 403 nskb->dev = gwj->dst.dev;
384 404
385 /* pointer to modifiable CAN frame */ 405 /* pointer to modifiable CAN frame */
@@ -903,7 +923,11 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
903 923
904static __init int cgw_module_init(void) 924static __init int cgw_module_init(void)
905{ 925{
906 printk(banner); 926 /* sanitize given module parameter */
927 max_hops = clamp_t(unsigned int, max_hops, CGW_MIN_HOPS, CGW_MAX_HOPS);
928
929 pr_info("can: netlink gateway (rev " CAN_GW_VERSION ") max_hops=%d\n",
930 max_hops);
907 931
908 cgw_cache = kmem_cache_create("can_gw", sizeof(struct cgw_job), 932 cgw_cache = kmem_cache_create("can_gw", sizeof(struct cgw_job),
909 0, 0, NULL); 933 0, 0, NULL);