X-Git-Url: http://rtime.felk.cvut.cz/gitweb/socketcan-devel.git/blobdiff_plain/054c7a7dcc540654f0e0a5716893957becefce7c..932abb70dd7df77d197bab86d2db49f1a2c56f60:/kernel/2.6/net/can/gw.c diff --git a/kernel/2.6/net/can/gw.c b/kernel/2.6/net/can/gw.c index e512427..d7257cc 100644 --- a/kernel/2.6/net/can/gw.c +++ b/kernel/2.6/net/can/gw.c @@ -1,7 +1,7 @@ /* * gw.c - CAN frame Gateway/Router/Bridge with netlink interface * - * Copyright (c) 2002-2010 Volkswagen Group Electronic Research + * Copyright (c) 2011 Volkswagen Group Electronic Research * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,11 +58,12 @@ #include #include #include +#include #include /* for RCSID. Removed by mkpatch script */ RCSID("$Id$"); -#define CAN_GW_VERSION "20101205" +#define CAN_GW_VERSION "20101209" static __initdata const char banner[] = KERN_INFO "can: netlink gateway (rev " CAN_GW_VERSION ")\n"; @@ -76,8 +77,6 @@ static struct notifier_block notifier; static struct kmem_cache *cgw_cache __read_mostly; -#define CGW_SK_MAGIC ((void *)(¬ifier)) - /* structure that contains the (on-the-fly) CAN frame modifications */ struct cf_mod { struct { @@ -144,8 +143,8 @@ struct cgw_job { /* modification functions that are invoked in the hot path in can_can_gw_rcv */ -#define MODFUNC(func, op) static void func (struct can_frame *cf, \ - struct cf_mod *mod) { op ; } +#define MODFUNC(func, op) static void func(struct can_frame *cf, \ + struct cf_mod *mod) { op ; } MODFUNC(mod_and_id, cf->can_id &= mod->modframe.and.can_id) MODFUNC(mod_and_dlc, cf->can_dlc &= mod->modframe.and.can_dlc) @@ -175,10 +174,10 @@ static inline void canframecpy(struct can_frame *dst, struct can_frame *src) static int cgw_chk_csum_parms(s8 fr, s8 to, s8 re) { - /* + /* * absolute dlc values 0 .. 7 => 0 .. 7, e.g. data [0] * relative to received dlc -1 .. -8 : - * e.g. for received dlc = 8 + * e.g. for received dlc = 8 * -1 => index = 7 (data[7]) * -3 => index = 5 (data[5]) * -8 => index = 0 (data[0]) @@ -190,7 +189,7 @@ static int cgw_chk_csum_parms(s8 fr, s8 to, s8 re) return 0; else return -EINVAL; -} +} static inline int calc_idx(int idx, int rx_dlc) { @@ -213,10 +212,10 @@ static void cgw_csum_xor_rel(struct can_frame *cf, struct cgw_csum_xor *xor) if (from <= to) { for (i = from; i <= to; i++) - val ^= cf->data[i]; + val ^= cf->data[i]; } else { for (i = from; i >= to; i--) - val ^= cf->data[i]; + val ^= cf->data[i]; } cf->data[res] = val; @@ -345,8 +344,8 @@ 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 */ - if (skb->sk == CGW_SK_MAGIC) + /* do not handle already routed frames - see comment below */ + if (skb_mac_header_was_set(skb)) return; if (!(gwj->dst.dev->flags & IFF_UP)) { @@ -370,8 +369,15 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data) return; } - /* mark routed frames with a 'special' sk value */ - nskb->sk = CGW_SK_MAGIC; + /* + * 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); nskb->dev = gwj->dst.dev; /* pointer to modifiable CAN frame */ @@ -438,7 +444,7 @@ static int cgw_notifier(struct notifier_block *nb, hlist_for_each_entry_safe(gwj, n, nx, &cgw_list, list) { - if (gwj->src.dev == dev || gwj->dst.dev == dev) { + if (gwj->src.dev == dev || gwj->dst.dev == dev) { hlist_del(&gwj->list); cgw_unregister_filter(gwj); kfree(gwj); @@ -589,7 +595,7 @@ cont: } /* check for common and gwtype specific attributes */ -static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, +static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, u8 gwtype, void *gwtypeattr) { struct nlattr *tb[CGW_MAX+1]; @@ -598,7 +604,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, int err = 0; /* initialize modification & checksum data space */ - memset(mod, 0, sizeof(*mod)); + memset(mod, 0, sizeof(*mod)); err = nlmsg_parse(nlh, sizeof(struct rtcanmsg), tb, CGW_MAX, NULL); if (err < 0) @@ -737,7 +743,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, /* check CGW_TYPE_CAN_CAN specific attributes */ struct can_can_gw *ccgw = (struct can_can_gw *)gwtypeattr; - memset(ccgw, 0, sizeof(*ccgw)); + memset(ccgw, 0, sizeof(*ccgw)); /* check for can_filter in attributes */ if (tb[CGW_FILTER] && @@ -815,7 +821,8 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh, if (!gwj->src.dev) goto out; - if (gwj->src.dev->type != ARPHRD_CAN) + /* check for CAN netdev not using header_ops - see gw_rcv() */ + if (gwj->src.dev->type != ARPHRD_CAN || gwj->src.dev->header_ops) goto put_src_out; gwj->dst.dev = dev_get_by_index(&init_net, gwj->ccgw.dst_idx); @@ -823,9 +830,10 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh, if (!gwj->dst.dev) goto put_src_out; - if (gwj->dst.dev->type != ARPHRD_CAN) + /* check for CAN netdev not using header_ops - see gw_rcv() */ + if (gwj->dst.dev->type != ARPHRD_CAN || gwj->dst.dev->header_ops) goto put_src_dst_out; - + ASSERT_RTNL(); err = cgw_register_filter(gwj);