can-gw: add a variable limit for CAN frame routings
Subsystems (4)
Oliver Hartkopp
maintainerRFC PATCH 1/1 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.
---
Having the possibility of only a single CAN frame routing (one hop) hinders use-cases for some complex application setups. To enable more than one CAN frame routing process with a single CAN frame (skb) a counter needed to be implemented to prevent an endless frame processing (e.g. due to some kind of misconfiguration).
As the skb control buffer (cb) potentially gets modified by net/sched in the tx path the csum element for IP checksums is re-used for the counter, as CAN frame skbs (ARPHRD_CAN) never contain any kind of checksums (see src comment).
@Marc: I wanted to sent this patch on netdev ML to see if there are any objections of using skb->csum in the way i proposed here. When the patch is fine please take it via can-next for this net-next cycle then. Tnx.
include/uapi/linux/can/gw.h +1 -0
@@ -44,6 +44,7 @@ enum {CGW_SRC_IF ,/* ifindex of source network interface */ CGW_DST_IF ,/* ifindex of destination network interface */ CGW_FILTER ,/* specify struct can_filter on source CAN device */ +CGW_DELETED ,/* number of deleted CAN frames (see max_hops param) */ __CGW_MAX };
net/can/gw.c +47 -14
111 lines not on this page · raw message
Marc Kleine-Budde
maintainerQuoted 16 lines · Oliver Hartkopp
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 <[email protected]>---
Having the possibility of only a single CAN frame routing (one hop) hinders use-cases for some complex application setups. To enable more than one CAN frame routing process with a single CAN frame (skb) a counter needed to be implemented to prevent an endless frame processing (e.g. due to some kind of misconfiguration).
Quoted 7 lines
As the skb control buffer (cb) potentially gets modified by net/sched in the tx path the csum element for IP checksums is re-used for the counter, as CAN frame skbs (
ARPHRD_CAN) never contain any kind of checksums (see src comment).@Marc: I wanted to sent this patch on netdev ML to see if there are any objections of using
skb->csumin the way i proposed here. When the patch is fine please take it via can-next for this net-next cycle then. Tnx.
Fine with me. I'll take the patch as usual, once it's ready. See a nitpick inline.
Quoted 119 lines
include/uapi/linux/can/gw.h +1
-0@@ -44,6 +44,7 @@ enum {CGW_SRC_IF ,/* ifindex of source network interface */ CGW_DST_IF ,/* ifindex of destination network interface */ CGW_FILTER ,/* specify struct can_filter on source CAN device */ +CGW_DELETED ,/* number of deleted CAN frames (see max_hops param) */ __CGW_MAX };net/can/gw.c +39
-13@@ -57,15 +57,23 @@#include <net/net_namespace.h> #include <net/sock.h> -#define CAN_GW_VERSION "20101209" +#define CAN_GW_VERSION "20130107"static __initconst const char banner[] = -KERN_INFO "can: netlink gateway (rev " CAN_GW_VERSION ")\n" ; +KERN_INFO "can: netlink gateway (rev " CAN_GW_VERSION ")" ;MODULE_DESCRIPTION ("PF_CAN netlink gateway" );MODULE_LICENSE ("Dual BSD/GPL" );MODULE_AUTHOR ("Oliver Hartkopp <[email protected]>" );MODULE_ALIAS ("can-gw" ); +#define CAN_GW_MAX_HOPS 6 + +static unsigned int max_hops__read_mostly =1 ; +module_param (max_hops, uint,S_IRUGO ); +MODULE_PARM_DESC (max_hops, +"maximum can-gw routing hops for CAN frames " +"(valid values: 1-6 hops, default: 1)" ); +static HLIST_HEAD (cgw_list);static struct notifier_block notifier;@@ -118,6 +126,7 @@ struct cgw_job {struct rcu_head rcu;u32 handled_frames;u32 dropped_frames; +u32 deleted_frames;struct cf_mod mod;union {/* CAN frame data source */ @@ -338,9 +347,27 @@ 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 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) + +BUG_ON (skb->ip_summed !=CHECKSUM_UNNECESSARY ); + +if (cgw_hops (skb) >= max_hops) { +/* indicate deleted frames due to misconfiguration */ + gwj->deleted_frames++;return ; + }if (!(gwj->dst.dev->flags &IFF_UP )) { gwj->dropped_frames++;@@ -363,15 +390,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 */ @@ -472,6 +492,11 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type, goto cancel; } +if (gwj->deleted_frames) { +if (nla_put_u32 (skb,CGW_DELETED , gwj->deleted_frames) <0 ) + goto cancel; + } +/* check non default settings of attributes */ if (gwj->mod.modtype.and) {@@ -771,6 +796,7 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh, gwj->handled_frames =0 ; gwj->dropped_frames =0 ; + gwj->deleted_frames =0 ; gwj->flags = r->flags; gwj->gwtype = r->gwtype;
net/can/gw.c static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) · line 929
Quoted 10 lines
net/can/gw.c +6
-1@@ -895,7 +921,14 @@ 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 */ +if (max_hops <1 ) + max_hops =1 ; + +if (max_hops >CAN_GW_MAX_HOPS ) + max_hops =CAN_GW_MAX_HOPS ;
You can make use of clamp(val, min, max) here.
net/can/gw.c static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) · line 934
Quoted 5 lines
net/can/gw.c +2
-0+ +printk ("%s max_hops=%d\n" , banner, max_hops); cgw_cache =kmem_cache_create ("can_gw" ,sizeof (struct cgw_job ),0 ,0 ,NULL );
Marc
Signature · 4 lines
Pengutronix e.K. | Marc Kleine-Budde | Industrial Linux Solutions | Phone: +49-231-2826-924 | Vertretung West/Dortmund | Fax: +49-5121-206917-5555 | Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
Am 08.01.2013 09:40, schrieb Marc Kleine-Budde:
Quoted 16 lines · Oliver Hartkopp
net/can/gw.c static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) · line 929
Quoted 12 lines
static __init int cgw_module_init(void) {net/can/gw.c +6
-1-printk (banner); +/* sanitize given module parameter */ +if (max_hops <1 ) + max_hops =1 ; + +if (max_hops >CAN_GW_MAX_HOPS ) + max_hops =CAN_GW_MAX_HOPS ;You can make use of
clamp(val, min, max)here.
ok.
I added
#include <linux/kernel.h>
where clamp is defined and reduced the code above to
clamp_t(unsigned int, max_hops, CAN_GW_MIN_HOPS, CAN_GW_MAX_HOPS);
Unfortunately clamp(max_hops, CAN_GW_MIN_HOPS, CAN_GW_MAX_HOPS) did not work.
=> (warning: comparison of distinct pointer types lacks a cast)
Will send the v2 when there're no other remarks tommorrow.
Tnx,
Oliver
Marc Kleine-Budde
maintainerQuoted 24 lines · Oliver Hartkopp
Am 08.01.2013 09:40, schrieb Marc Kleine-Budde:
Quoted 14 lines · Oliver Hartkopp
net/can/gw.c static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) · line 929
Quoted 12 lines
static __init int cgw_module_init(void) {net/can/gw.c +6
-1-printk (banner); +/* sanitize given module parameter */ +if (max_hops <1 ) + max_hops =1 ; + +if (max_hops >CAN_GW_MAX_HOPS ) + max_hops =CAN_GW_MAX_HOPS ;Quoted 2 lines
You can make use of
clamp(val, min, max)here.ok.
I added
#include <linux/kernel.h>
Quoted 8 lines
where clamp is defined and reduced the code above to
clamp_t(unsigned int, max_hops, CAN_GW_MIN_HOPS, CAN_GW_MAX_HOPS);Unfortunately
clamp(max_hops, CAN_GW_MIN_HOPS, CAN_GW_MAX_HOPS)did not work.=> (warning: comparison of distinct pointer types lacks a cast)
Defines are probably unsinged longs, by default.
Quoted 1 line
Will send the v2 when there're no other remarks tommorrow.
Marc
Signature · 4 lines
Pengutronix e.K. | Marc Kleine-Budde | Industrial Linux Solutions | Phone: +49-231-2826-924 | Vertretung West/Dortmund | Fax: +49-5121-206917-5555 | Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |