aboutsummaryrefslogtreecommitdiffstats
path: root/net/can
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /net/can
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'net/can')
-rw-r--r--net/can/Kconfig11
-rw-r--r--net/can/Makefile3
-rw-r--r--net/can/af_can.c134
-rw-r--r--net/can/af_can.h5
-rw-r--r--net/can/bcm.c7
-rw-r--r--net/can/gw.c939
-rw-r--r--net/can/proc.c7
-rw-r--r--net/can/raw.c57
8 files changed, 58 insertions, 1105 deletions
diff --git a/net/can/Kconfig b/net/can/Kconfig
index 03200699d27..89395b2c8bc 100644
--- a/net/can/Kconfig
+++ b/net/can/Kconfig
@@ -40,16 +40,5 @@ config CAN_BCM
40 CAN messages are used on the bus (e.g. in automotive environments). 40 CAN messages are used on the bus (e.g. in automotive environments).
41 To use the Broadcast Manager, use AF_CAN with protocol CAN_BCM. 41 To use the Broadcast Manager, use AF_CAN with protocol CAN_BCM.
42 42
43config CAN_GW
44 tristate "CAN Gateway/Router (with netlink configuration)"
45 depends on CAN
46 default N
47 ---help---
48 The CAN Gateway/Router is used to route (and modify) CAN frames.
49 It is based on the PF_CAN core infrastructure for msg filtering and
50 msg sending and can optionally modify routed CAN frames on the fly.
51 CAN frames can be routed between CAN network interfaces (one hop).
52 They can be modified with AND/OR/XOR/SET operations as configured
53 by the netlink configuration interface known e.g. from iptables.
54 43
55source "drivers/net/can/Kconfig" 44source "drivers/net/can/Kconfig"
diff --git a/net/can/Makefile b/net/can/Makefile
index cef49eb1f5c..2d3894b3274 100644
--- a/net/can/Makefile
+++ b/net/can/Makefile
@@ -10,6 +10,3 @@ can-raw-y := raw.o
10 10
11obj-$(CONFIG_CAN_BCM) += can-bcm.o 11obj-$(CONFIG_CAN_BCM) += can-bcm.o
12can-bcm-y := bcm.o 12can-bcm-y := bcm.o
13
14obj-$(CONFIG_CAN_GW) += can-gw.o
15can-gw-y := gw.o
diff --git a/net/can/af_can.c b/net/can/af_can.c
index ddac1ee2ed2..9b0c32a2690 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -38,10 +38,11 @@
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
39 * DAMAGE. 39 * DAMAGE.
40 * 40 *
41 * Send feedback to <socketcan-users@lists.berlios.de>
42 *
41 */ 43 */
42 44
43#include <linux/module.h> 45#include <linux/module.h>
44#include <linux/stddef.h>
45#include <linux/init.h> 46#include <linux/init.h>
46#include <linux/kmod.h> 47#include <linux/kmod.h>
47#include <linux/slab.h> 48#include <linux/slab.h>
@@ -63,7 +64,7 @@
63 64
64#include "af_can.h" 65#include "af_can.h"
65 66
66static __initconst const char banner[] = KERN_INFO 67static __initdata const char banner[] = KERN_INFO
67 "can: controller area network core (" CAN_VERSION_STRING ")\n"; 68 "can: controller area network core (" CAN_VERSION_STRING ")\n";
68 69
69MODULE_DESCRIPTION("Controller Area Network PF_CAN core"); 70MODULE_DESCRIPTION("Controller Area Network PF_CAN core");
@@ -221,46 +222,30 @@ static int can_create(struct net *net, struct socket *sock, int protocol,
221 * -ENOBUFS on full driver queue (see net_xmit_errno()) 222 * -ENOBUFS on full driver queue (see net_xmit_errno())
222 * -ENOMEM when local loopback failed at calling skb_clone() 223 * -ENOMEM when local loopback failed at calling skb_clone()
223 * -EPERM when trying to send on a non-CAN interface 224 * -EPERM when trying to send on a non-CAN interface
224 * -EMSGSIZE CAN frame size is bigger than CAN interface MTU
225 * -EINVAL when the skb->data does not contain a valid CAN frame 225 * -EINVAL when the skb->data does not contain a valid CAN frame
226 */ 226 */
227int can_send(struct sk_buff *skb, int loop) 227int can_send(struct sk_buff *skb, int loop)
228{ 228{
229 struct sk_buff *newskb = NULL; 229 struct sk_buff *newskb = NULL;
230 struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 230 struct can_frame *cf = (struct can_frame *)skb->data;
231 int err = -EINVAL; 231 int err;
232
233 if (skb->len == CAN_MTU) {
234 skb->protocol = htons(ETH_P_CAN);
235 if (unlikely(cfd->len > CAN_MAX_DLEN))
236 goto inval_skb;
237 } else if (skb->len == CANFD_MTU) {
238 skb->protocol = htons(ETH_P_CANFD);
239 if (unlikely(cfd->len > CANFD_MAX_DLEN))
240 goto inval_skb;
241 } else
242 goto inval_skb;
243 232
244 /* 233 if (skb->len != sizeof(struct can_frame) || cf->can_dlc > 8) {
245 * Make sure the CAN frame can pass the selected CAN netdevice. 234 kfree_skb(skb);
246 * As structs can_frame and canfd_frame are similar, we can provide 235 return -EINVAL;
247 * CAN FD frames to legacy CAN drivers as long as the length is <= 8
248 */
249 if (unlikely(skb->len > skb->dev->mtu && cfd->len > CAN_MAX_DLEN)) {
250 err = -EMSGSIZE;
251 goto inval_skb;
252 } 236 }
253 237
254 if (unlikely(skb->dev->type != ARPHRD_CAN)) { 238 if (skb->dev->type != ARPHRD_CAN) {
255 err = -EPERM; 239 kfree_skb(skb);
256 goto inval_skb; 240 return -EPERM;
257 } 241 }
258 242
259 if (unlikely(!(skb->dev->flags & IFF_UP))) { 243 if (!(skb->dev->flags & IFF_UP)) {
260 err = -ENETDOWN; 244 kfree_skb(skb);
261 goto inval_skb; 245 return -ENETDOWN;
262 } 246 }
263 247
248 skb->protocol = htons(ETH_P_CAN);
264 skb_reset_network_header(skb); 249 skb_reset_network_header(skb);
265 skb_reset_transport_header(skb); 250 skb_reset_transport_header(skb);
266 251
@@ -317,10 +302,6 @@ int can_send(struct sk_buff *skb, int loop)
317 can_stats.tx_frames_delta++; 302 can_stats.tx_frames_delta++;
318 303
319 return 0; 304 return 0;
320
321inval_skb:
322 kfree_skb(skb);
323 return err;
324} 305}
325EXPORT_SYMBOL(can_send); 306EXPORT_SYMBOL(can_send);
326 307
@@ -355,8 +336,8 @@ static struct dev_rcv_lists *find_dev_rcv_lists(struct net_device *dev)
355 * relevant bits for the filter. 336 * relevant bits for the filter.
356 * 337 *
357 * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can 338 * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
358 * filter for error messages (CAN_ERR_FLAG bit set in mask). For error msg 339 * filter for error frames (CAN_ERR_FLAG bit set in mask). For error frames
359 * frames there is a special filterlist and a special rx path filter handling. 340 * there is a special filterlist and a special rx path filter handling.
360 * 341 *
361 * Return: 342 * Return:
362 * Pointer to optimal filterlist for the given can_id/mask pair. 343 * Pointer to optimal filterlist for the given can_id/mask pair.
@@ -368,7 +349,7 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask,
368{ 349{
369 canid_t inv = *can_id & CAN_INV_FILTER; /* save flag before masking */ 350 canid_t inv = *can_id & CAN_INV_FILTER; /* save flag before masking */
370 351
371 /* filter for error message frames in extra filterlist */ 352 /* filter for error frames in extra filterlist */
372 if (*mask & CAN_ERR_FLAG) { 353 if (*mask & CAN_ERR_FLAG) {
373 /* clear CAN_ERR_FLAG in filter entry */ 354 /* clear CAN_ERR_FLAG in filter entry */
374 *mask &= CAN_ERR_MASK; 355 *mask &= CAN_ERR_MASK;
@@ -429,7 +410,7 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask,
429 * <received_can_id> & mask == can_id & mask 410 * <received_can_id> & mask == can_id & mask
430 * 411 *
431 * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can 412 * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
432 * filter for error message frames (CAN_ERR_FLAG bit set in mask). 413 * filter for error frames (CAN_ERR_FLAG bit set in mask).
433 * 414 *
434 * The provided pointer to the sk_buff is guaranteed to be valid as long as 415 * The provided pointer to the sk_buff is guaranteed to be valid as long as
435 * the callback function is running. The callback function must *not* free 416 * the callback function is running. The callback function must *not* free
@@ -599,7 +580,7 @@ static int can_rcv_filter(struct dev_rcv_lists *d, struct sk_buff *skb)
599 return 0; 580 return 0;
600 581
601 if (can_id & CAN_ERR_FLAG) { 582 if (can_id & CAN_ERR_FLAG) {
602 /* check for error message frame entries only */ 583 /* check for error frame entries only */
603 hlist_for_each_entry_rcu(r, n, &d->rx[RX_ERR], list) { 584 hlist_for_each_entry_rcu(r, n, &d->rx[RX_ERR], list) {
604 if (can_id & r->mask) { 585 if (can_id & r->mask) {
605 deliver(skb, r); 586 deliver(skb, r);
@@ -653,11 +634,24 @@ static int can_rcv_filter(struct dev_rcv_lists *d, struct sk_buff *skb)
653 return matches; 634 return matches;
654} 635}
655 636
656static void can_receive(struct sk_buff *skb, struct net_device *dev) 637static int can_rcv(struct sk_buff *skb, struct net_device *dev,
638 struct packet_type *pt, struct net_device *orig_dev)
657{ 639{
658 struct dev_rcv_lists *d; 640 struct dev_rcv_lists *d;
641 struct can_frame *cf = (struct can_frame *)skb->data;
659 int matches; 642 int matches;
660 643
644 if (!net_eq(dev_net(dev), &init_net))
645 goto drop;
646
647 if (WARN_ONCE(dev->type != ARPHRD_CAN ||
648 skb->len != sizeof(struct can_frame) ||
649 cf->can_dlc > 8,
650 "PF_CAN: dropped non conform skbuf: "
651 "dev type %d, len %d, can_dlc %d\n",
652 dev->type, skb->len, cf->can_dlc))
653 goto drop;
654
661 /* update statistics */ 655 /* update statistics */
662 can_stats.rx_frames++; 656 can_stats.rx_frames++;
663 can_stats.rx_frames_delta++; 657 can_stats.rx_frames_delta++;
@@ -681,49 +675,7 @@ static void can_receive(struct sk_buff *skb, struct net_device *dev)
681 can_stats.matches++; 675 can_stats.matches++;
682 can_stats.matches_delta++; 676 can_stats.matches_delta++;
683 } 677 }
684}
685
686static int can_rcv(struct sk_buff *skb, struct net_device *dev,
687 struct packet_type *pt, struct net_device *orig_dev)
688{
689 struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
690 678
691 if (unlikely(!net_eq(dev_net(dev), &init_net)))
692 goto drop;
693
694 if (WARN_ONCE(dev->type != ARPHRD_CAN ||
695 skb->len != CAN_MTU ||
696 cfd->len > CAN_MAX_DLEN,
697 "PF_CAN: dropped non conform CAN skbuf: "
698 "dev type %d, len %d, datalen %d\n",
699 dev->type, skb->len, cfd->len))
700 goto drop;
701
702 can_receive(skb, dev);
703 return NET_RX_SUCCESS;
704
705drop:
706 kfree_skb(skb);
707 return NET_RX_DROP;
708}
709
710static int canfd_rcv(struct sk_buff *skb, struct net_device *dev,
711 struct packet_type *pt, struct net_device *orig_dev)
712{
713 struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
714
715 if (unlikely(!net_eq(dev_net(dev), &init_net)))
716 goto drop;
717
718 if (WARN_ONCE(dev->type != ARPHRD_CAN ||
719 skb->len != CANFD_MTU ||
720 cfd->len > CANFD_MAX_DLEN,
721 "PF_CAN: dropped non conform CAN FD skbuf: "
722 "dev type %d, len %d, datalen %d\n",
723 dev->type, skb->len, cfd->len))
724 goto drop;
725
726 can_receive(skb, dev);
727 return NET_RX_SUCCESS; 679 return NET_RX_SUCCESS;
728 680
729drop: 681drop:
@@ -767,7 +719,7 @@ int can_proto_register(const struct can_proto *cp)
767 proto); 719 proto);
768 err = -EBUSY; 720 err = -EBUSY;
769 } else 721 } else
770 RCU_INIT_POINTER(proto_tab[proto], cp); 722 rcu_assign_pointer(proto_tab[proto], cp);
771 723
772 mutex_unlock(&proto_tab_lock); 724 mutex_unlock(&proto_tab_lock);
773 725
@@ -788,7 +740,7 @@ void can_proto_unregister(const struct can_proto *cp)
788 740
789 mutex_lock(&proto_tab_lock); 741 mutex_lock(&proto_tab_lock);
790 BUG_ON(proto_tab[proto] != cp); 742 BUG_ON(proto_tab[proto] != cp);
791 RCU_INIT_POINTER(proto_tab[proto], NULL); 743 rcu_assign_pointer(proto_tab[proto], NULL);
792 mutex_unlock(&proto_tab_lock); 744 mutex_unlock(&proto_tab_lock);
793 745
794 synchronize_rcu(); 746 synchronize_rcu();
@@ -857,14 +809,10 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg,
857 809
858static struct packet_type can_packet __read_mostly = { 810static struct packet_type can_packet __read_mostly = {
859 .type = cpu_to_be16(ETH_P_CAN), 811 .type = cpu_to_be16(ETH_P_CAN),
812 .dev = NULL,
860 .func = can_rcv, 813 .func = can_rcv,
861}; 814};
862 815
863static struct packet_type canfd_packet __read_mostly = {
864 .type = cpu_to_be16(ETH_P_CANFD),
865 .func = canfd_rcv,
866};
867
868static const struct net_proto_family can_family_ops = { 816static const struct net_proto_family can_family_ops = {
869 .family = PF_CAN, 817 .family = PF_CAN,
870 .create = can_create, 818 .create = can_create,
@@ -878,12 +826,6 @@ static struct notifier_block can_netdev_notifier __read_mostly = {
878 826
879static __init int can_init(void) 827static __init int can_init(void)
880{ 828{
881 /* check for correct padding to be able to use the structs similarly */
882 BUILD_BUG_ON(offsetof(struct can_frame, can_dlc) !=
883 offsetof(struct canfd_frame, len) ||
884 offsetof(struct can_frame, data) !=
885 offsetof(struct canfd_frame, data));
886
887 printk(banner); 829 printk(banner);
888 830
889 memset(&can_rx_alldev_list, 0, sizeof(can_rx_alldev_list)); 831 memset(&can_rx_alldev_list, 0, sizeof(can_rx_alldev_list));
@@ -906,7 +848,6 @@ static __init int can_init(void)
906 sock_register(&can_family_ops); 848 sock_register(&can_family_ops);
907 register_netdevice_notifier(&can_netdev_notifier); 849 register_netdevice_notifier(&can_netdev_notifier);
908 dev_add_pack(&can_packet); 850 dev_add_pack(&can_packet);
909 dev_add_pack(&canfd_packet);
910 851
911 return 0; 852 return 0;
912} 853}
@@ -921,7 +862,6 @@ static __exit void can_exit(void)
921 can_remove_proc(); 862 can_remove_proc();
922 863
923 /* protocol unregister */ 864 /* protocol unregister */
924 dev_remove_pack(&canfd_packet);
925 dev_remove_pack(&can_packet); 865 dev_remove_pack(&can_packet);
926 unregister_netdevice_notifier(&can_netdev_notifier); 866 unregister_netdevice_notifier(&can_netdev_notifier);
927 sock_unregister(PF_CAN); 867 sock_unregister(PF_CAN);
diff --git a/net/can/af_can.h b/net/can/af_can.h
index 1dccb4c3389..34253b84e30 100644
--- a/net/can/af_can.h
+++ b/net/can/af_can.h
@@ -35,6 +35,8 @@
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
36 * DAMAGE. 36 * DAMAGE.
37 * 37 *
38 * Send feedback to <socketcan-users@lists.berlios.de>
39 *
38 */ 40 */
39 41
40#ifndef AF_CAN_H 42#ifndef AF_CAN_H
@@ -104,9 +106,6 @@ struct s_pstats {
104 unsigned long rcv_entries_max; 106 unsigned long rcv_entries_max;
105}; 107};
106 108
107/* receive filters subscribed for 'all' CAN devices */
108extern struct dev_rcv_lists can_rx_alldev_list;
109
110/* function prototypes for the CAN networklayer procfs (proc.c) */ 109/* function prototypes for the CAN networklayer procfs (proc.c) */
111extern void can_init_proc(void); 110extern void can_init_proc(void);
112extern void can_remove_proc(void); 111extern void can_remove_proc(void);
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 969b7cdff59..c84963d2dee 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -37,6 +37,8 @@
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38 * DAMAGE. 38 * DAMAGE.
39 * 39 *
40 * Send feedback to <socketcan-users@lists.berlios.de>
41 *
40 */ 42 */
41 43
42#include <linux/module.h> 44#include <linux/module.h>
@@ -77,7 +79,7 @@
77 (CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG)) 79 (CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG))
78 80
79#define CAN_BCM_VERSION CAN_VERSION 81#define CAN_BCM_VERSION CAN_VERSION
80static __initconst const char banner[] = KERN_INFO 82static __initdata const char banner[] = KERN_INFO
81 "can: broadcast manager protocol (rev " CAN_BCM_VERSION " t)\n"; 83 "can: broadcast manager protocol (rev " CAN_BCM_VERSION " t)\n";
82 84
83MODULE_DESCRIPTION("PF_CAN broadcast manager protocol"); 85MODULE_DESCRIPTION("PF_CAN broadcast manager protocol");
@@ -1084,9 +1086,6 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
1084 op->sk = sk; 1086 op->sk = sk;
1085 op->ifindex = ifindex; 1087 op->ifindex = ifindex;
1086 1088
1087 /* ifindex for timeout events w/o previous frame reception */
1088 op->rx_ifindex = ifindex;
1089
1090 /* initialize uninitialized (kzalloc) structure */ 1089 /* initialize uninitialized (kzalloc) structure */
1091 hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 1090 hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
1092 op->timer.function = bcm_rx_timeout_handler; 1091 op->timer.function = bcm_rx_timeout_handler;
diff --git a/net/can/gw.c b/net/can/gw.c
deleted file mode 100644
index 574dda78eb0..00000000000
--- a/net/can/gw.c
+++ /dev/null
@@ -1,939 +0,0 @@
1/*
2 * gw.c - CAN frame Gateway/Router/Bridge with netlink interface
3 *
4 * Copyright (c) 2011 Volkswagen Group Electronic Research
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Volkswagen nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * Alternatively, provided that this notice is retained in full, this
20 * software may be distributed under the terms of the GNU General
21 * Public License ("GPL") version 2, in which case the provisions of the
22 * GPL apply INSTEAD OF those given above.
23 *
24 * The provided data structures and external interfaces from this code
25 * are not restricted to be used by modules with a GPL compatible license.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38 * DAMAGE.
39 *
40 */
41
42#include <linux/module.h>
43#include <linux/init.h>
44#include <linux/types.h>
45#include <linux/list.h>
46#include <linux/spinlock.h>
47#include <linux/rcupdate.h>
48#include <linux/rculist.h>
49#include <linux/net.h>
50#include <linux/netdevice.h>
51#include <linux/if_arp.h>
52#include <linux/skbuff.h>
53#include <linux/can.h>
54#include <linux/can/core.h>
55#include <linux/can/gw.h>
56#include <net/rtnetlink.h>
57#include <net/net_namespace.h>
58#include <net/sock.h>
59
60#define CAN_GW_VERSION "20101209"
61static __initconst const char banner[] =
62 KERN_INFO "can: netlink gateway (rev " CAN_GW_VERSION ")\n";
63
64MODULE_DESCRIPTION("PF_CAN netlink gateway");
65MODULE_LICENSE("Dual BSD/GPL");
66MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>");
67MODULE_ALIAS("can-gw");
68
69static HLIST_HEAD(cgw_list);
70static struct notifier_block notifier;
71
72static struct kmem_cache *cgw_cache __read_mostly;
73
74/* structure that contains the (on-the-fly) CAN frame modifications */
75struct cf_mod {
76 struct {
77 struct can_frame and;
78 struct can_frame or;
79 struct can_frame xor;
80 struct can_frame set;
81 } modframe;
82 struct {
83 u8 and;
84 u8 or;
85 u8 xor;
86 u8 set;
87 } modtype;
88 void (*modfunc[MAX_MODFUNCTIONS])(struct can_frame *cf,
89 struct cf_mod *mod);
90
91 /* CAN frame checksum calculation after CAN frame modifications */
92 struct {
93 struct cgw_csum_xor xor;
94 struct cgw_csum_crc8 crc8;
95 } csum;
96 struct {
97 void (*xor)(struct can_frame *cf, struct cgw_csum_xor *xor);
98 void (*crc8)(struct can_frame *cf, struct cgw_csum_crc8 *crc8);
99 } csumfunc;
100};
101
102
103/*
104 * So far we just support CAN -> CAN routing and frame modifications.
105 *
106 * The internal can_can_gw structure contains data and attributes for
107 * a CAN -> CAN gateway job.
108 */
109struct can_can_gw {
110 struct can_filter filter;
111 int src_idx;
112 int dst_idx;
113};
114
115/* list entry for CAN gateways jobs */
116struct cgw_job {
117 struct hlist_node list;
118 struct rcu_head rcu;
119 u32 handled_frames;
120 u32 dropped_frames;
121 struct cf_mod mod;
122 union {
123 /* CAN frame data source */
124 struct net_device *dev;
125 } src;
126 union {
127 /* CAN frame data destination */
128 struct net_device *dev;
129 } dst;
130 union {
131 struct can_can_gw ccgw;
132 /* tbc */
133 };
134 u8 gwtype;
135 u16 flags;
136};
137
138/* modification functions that are invoked in the hot path in can_can_gw_rcv */
139
140#define MODFUNC(func, op) static void func(struct can_frame *cf, \
141 struct cf_mod *mod) { op ; }
142
143MODFUNC(mod_and_id, cf->can_id &= mod->modframe.and.can_id)
144MODFUNC(mod_and_dlc, cf->can_dlc &= mod->modframe.and.can_dlc)
145MODFUNC(mod_and_data, *(u64 *)cf->data &= *(u64 *)mod->modframe.and.data)
146MODFUNC(mod_or_id, cf->can_id |= mod->modframe.or.can_id)
147MODFUNC(mod_or_dlc, cf->can_dlc |= mod->modframe.or.can_dlc)
148MODFUNC(mod_or_data, *(u64 *)cf->data |= *(u64 *)mod->modframe.or.data)
149MODFUNC(mod_xor_id, cf->can_id ^= mod->modframe.xor.can_id)
150MODFUNC(mod_xor_dlc, cf->can_dlc ^= mod->modframe.xor.can_dlc)
151MODFUNC(mod_xor_data, *(u64 *)cf->data ^= *(u64 *)mod->modframe.xor.data)
152MODFUNC(mod_set_id, cf->can_id = mod->modframe.set.can_id)
153MODFUNC(mod_set_dlc, cf->can_dlc = mod->modframe.set.can_dlc)
154MODFUNC(mod_set_data, *(u64 *)cf->data = *(u64 *)mod->modframe.set.data)
155
156static inline void canframecpy(struct can_frame *dst, struct can_frame *src)
157{
158 /*
159 * Copy the struct members separately to ensure that no uninitialized
160 * data are copied in the 3 bytes hole of the struct. This is needed
161 * to make easy compares of the data in the struct cf_mod.
162 */
163
164 dst->can_id = src->can_id;
165 dst->can_dlc = src->can_dlc;
166 *(u64 *)dst->data = *(u64 *)src->data;
167}
168
169static int cgw_chk_csum_parms(s8 fr, s8 to, s8 re)
170{
171 /*
172 * absolute dlc values 0 .. 7 => 0 .. 7, e.g. data [0]
173 * relative to received dlc -1 .. -8 :
174 * e.g. for received dlc = 8
175 * -1 => index = 7 (data[7])
176 * -3 => index = 5 (data[5])
177 * -8 => index = 0 (data[0])
178 */
179
180 if (fr > -9 && fr < 8 &&
181 to > -9 && to < 8 &&
182 re > -9 && re < 8)
183 return 0;
184 else
185 return -EINVAL;
186}
187
188static inline int calc_idx(int idx, int rx_dlc)
189{
190 if (idx < 0)
191 return rx_dlc + idx;
192 else
193 return idx;
194}
195
196static void cgw_csum_xor_rel(struct can_frame *cf, struct cgw_csum_xor *xor)
197{
198 int from = calc_idx(xor->from_idx, cf->can_dlc);
199 int to = calc_idx(xor->to_idx, cf->can_dlc);
200 int res = calc_idx(xor->result_idx, cf->can_dlc);
201 u8 val = xor->init_xor_val;
202 int i;
203
204 if (from < 0 || to < 0 || res < 0)
205 return;
206
207 if (from <= to) {
208 for (i = from; i <= to; i++)
209 val ^= cf->data[i];
210 } else {
211 for (i = from; i >= to; i--)
212 val ^= cf->data[i];
213 }
214
215 cf->data[res] = val;
216}
217
218static void cgw_csum_xor_pos(struct can_frame *cf, struct cgw_csum_xor *xor)
219{
220 u8 val = xor->init_xor_val;
221 int i;
222
223 for (i = xor->from_idx; i <= xor->to_idx; i++)
224 val ^= cf->data[i];
225
226 cf->data[xor->result_idx] = val;
227}
228
229static void cgw_csum_xor_neg(struct can_frame *cf, struct cgw_csum_xor *xor)
230{
231 u8 val = xor->init_xor_val;
232 int i;
233
234 for (i = xor->from_idx; i >= xor->to_idx; i--)
235 val ^= cf->data[i];
236
237 cf->data[xor->result_idx] = val;
238}
239
240static void cgw_csum_crc8_rel(struct can_frame *cf, struct cgw_csum_crc8 *crc8)
241{
242 int from = calc_idx(crc8->from_idx, cf->can_dlc);
243 int to = calc_idx(crc8->to_idx, cf->can_dlc);
244 int res = calc_idx(crc8->result_idx, cf->can_dlc);
245 u8 crc = crc8->init_crc_val;
246 int i;
247
248 if (from < 0 || to < 0 || res < 0)
249 return;
250
251 if (from <= to) {
252 for (i = crc8->from_idx; i <= crc8->to_idx; i++)
253 crc = crc8->crctab[crc^cf->data[i]];
254 } else {
255 for (i = crc8->from_idx; i >= crc8->to_idx; i--)
256 crc = crc8->crctab[crc^cf->data[i]];
257 }
258
259 switch (crc8->profile) {
260
261 case CGW_CRC8PRF_1U8:
262 crc = crc8->crctab[crc^crc8->profile_data[0]];
263 break;
264
265 case CGW_CRC8PRF_16U8:
266 crc = crc8->crctab[crc^crc8->profile_data[cf->data[1] & 0xF]];
267 break;
268
269 case CGW_CRC8PRF_SFFID_XOR:
270 crc = crc8->crctab[crc^(cf->can_id & 0xFF)^
271 (cf->can_id >> 8 & 0xFF)];
272 break;
273
274 }
275
276 cf->data[crc8->result_idx] = crc^crc8->final_xor_val;
277}
278
279static void cgw_csum_crc8_pos(struct can_frame *cf, struct cgw_csum_crc8 *crc8)
280{
281 u8 crc = crc8->init_crc_val;
282 int i;
283
284 for (i = crc8->from_idx; i <= crc8->to_idx; i++)
285 crc = crc8->crctab[crc^cf->data[i]];
286
287 switch (crc8->profile) {
288
289 case CGW_CRC8PRF_1U8:
290 crc = crc8->crctab[crc^crc8->profile_data[0]];
291 break;
292
293 case CGW_CRC8PRF_16U8:
294 crc = crc8->crctab[crc^crc8->profile_data[cf->data[1] & 0xF]];
295 break;
296
297 case CGW_CRC8PRF_SFFID_XOR:
298 crc = crc8->crctab[crc^(cf->can_id & 0xFF)^
299 (cf->can_id >> 8 & 0xFF)];
300 break;
301 }
302
303 cf->data[crc8->result_idx] = crc^crc8->final_xor_val;
304}
305
306static void cgw_csum_crc8_neg(struct can_frame *cf, struct cgw_csum_crc8 *crc8)
307{
308 u8 crc = crc8->init_crc_val;
309 int i;
310
311 for (i = crc8->from_idx; i >= crc8->to_idx; i--)
312 crc = crc8->crctab[crc^cf->data[i]];
313
314 switch (crc8->profile) {
315
316 case CGW_CRC8PRF_1U8:
317 crc = crc8->crctab[crc^crc8->profile_data[0]];
318 break;
319
320 case CGW_CRC8PRF_16U8:
321 crc = crc8->crctab[crc^crc8->profile_data[cf->data[1] & 0xF]];
322 break;
323
324 case CGW_CRC8PRF_SFFID_XOR:
325 crc = crc8->crctab[crc^(cf->can_id & 0xFF)^
326 (cf->can_id >> 8 & 0xFF)];
327 break;
328 }
329
330 cf->data[crc8->result_idx] = crc^crc8->final_xor_val;
331}
332
333/* the receive & process & send function */
334static void can_can_gw_rcv(struct sk_buff *skb, void *data)
335{
336 struct cgw_job *gwj = (struct cgw_job *)data;
337 struct can_frame *cf;
338 struct sk_buff *nskb;
339 int modidx = 0;
340
341 /* do not handle already routed frames - see comment below */
342 if (skb_mac_header_was_set(skb))
343 return;
344
345 if (!(gwj->dst.dev->flags & IFF_UP)) {
346 gwj->dropped_frames++;
347 return;
348 }
349
350 /*
351 * clone the given skb, which has not been done in can_rcv()
352 *
353 * When there is at least one modification function activated,
354 * we need to copy the skb as we want to modify skb->data.
355 */
356 if (gwj->mod.modfunc[0])
357 nskb = skb_copy(skb, GFP_ATOMIC);
358 else
359 nskb = skb_clone(skb, GFP_ATOMIC);
360
361 if (!nskb) {
362 gwj->dropped_frames++;
363 return;
364 }
365
366 /*
367 * Mark routed frames by setting some mac header length which is
368 * not relevant for the CAN frames located in the skb->data section.
369 *
370 * As dev->header_ops is not set in CAN netdevices no one is ever
371 * accessing the various header offsets in the CAN skbuffs anyway.
372 * E.g. using the packet socket to read CAN frames is still working.
373 */
374 skb_set_mac_header(nskb, 8);
375 nskb->dev = gwj->dst.dev;
376
377 /* pointer to modifiable CAN frame */
378 cf = (struct can_frame *)nskb->data;
379
380 /* perform preprocessed modification functions if there are any */
381 while (modidx < MAX_MODFUNCTIONS && gwj->mod.modfunc[modidx])
382 (*gwj->mod.modfunc[modidx++])(cf, &gwj->mod);
383
384 /* check for checksum updates when the CAN frame has been modified */
385 if (modidx) {
386 if (gwj->mod.csumfunc.crc8)
387 (*gwj->mod.csumfunc.crc8)(cf, &gwj->mod.csum.crc8);
388
389 if (gwj->mod.csumfunc.xor)
390 (*gwj->mod.csumfunc.xor)(cf, &gwj->mod.csum.xor);
391 }
392
393 /* clear the skb timestamp if not configured the other way */
394 if (!(gwj->flags & CGW_FLAGS_CAN_SRC_TSTAMP))
395 nskb->tstamp.tv64 = 0;
396
397 /* send to netdevice */
398 if (can_send(nskb, gwj->flags & CGW_FLAGS_CAN_ECHO))
399 gwj->dropped_frames++;
400 else
401 gwj->handled_frames++;
402}
403
404static inline int cgw_register_filter(struct cgw_job *gwj)
405{
406 return can_rx_register(gwj->src.dev, gwj->ccgw.filter.can_id,
407 gwj->ccgw.filter.can_mask, can_can_gw_rcv,
408 gwj, "gw");
409}
410
411static inline void cgw_unregister_filter(struct cgw_job *gwj)
412{
413 can_rx_unregister(gwj->src.dev, gwj->ccgw.filter.can_id,
414 gwj->ccgw.filter.can_mask, can_can_gw_rcv, gwj);
415}
416
417static int cgw_notifier(struct notifier_block *nb,
418 unsigned long msg, void *data)
419{
420 struct net_device *dev = (struct net_device *)data;
421
422 if (!net_eq(dev_net(dev), &init_net))
423 return NOTIFY_DONE;
424 if (dev->type != ARPHRD_CAN)
425 return NOTIFY_DONE;
426
427 if (msg == NETDEV_UNREGISTER) {
428
429 struct cgw_job *gwj = NULL;
430 struct hlist_node *n, *nx;
431
432 ASSERT_RTNL();
433
434 hlist_for_each_entry_safe(gwj, n, nx, &cgw_list, list) {
435
436 if (gwj->src.dev == dev || gwj->dst.dev == dev) {
437 hlist_del(&gwj->list);
438 cgw_unregister_filter(gwj);
439 kfree(gwj);
440 }
441 }
442 }
443
444 return NOTIFY_DONE;
445}
446
447static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type,
448 u32 pid, u32 seq, int flags)
449{
450 struct cgw_frame_mod mb;
451 struct rtcanmsg *rtcan;
452 struct nlmsghdr *nlh;
453
454 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtcan), flags);
455 if (!nlh)
456 return -EMSGSIZE;
457
458 rtcan = nlmsg_data(nlh);
459 rtcan->can_family = AF_CAN;
460 rtcan->gwtype = gwj->gwtype;
461 rtcan->flags = gwj->flags;
462
463 /* add statistics if available */
464
465 if (gwj->handled_frames) {
466 if (nla_put_u32(skb, CGW_HANDLED, gwj->handled_frames) < 0)
467 goto cancel;
468 }
469
470 if (gwj->dropped_frames) {
471 if (nla_put_u32(skb, CGW_DROPPED, gwj->dropped_frames) < 0)
472 goto cancel;
473 }
474
475 /* check non default settings of attributes */
476
477 if (gwj->mod.modtype.and) {
478 memcpy(&mb.cf, &gwj->mod.modframe.and, sizeof(mb.cf));
479 mb.modtype = gwj->mod.modtype.and;
480 if (nla_put(skb, CGW_MOD_AND, sizeof(mb), &mb) < 0)
481 goto cancel;
482 }
483
484 if (gwj->mod.modtype.or) {
485 memcpy(&mb.cf, &gwj->mod.modframe.or, sizeof(mb.cf));
486 mb.modtype = gwj->mod.modtype.or;
487 if (nla_put(skb, CGW_MOD_OR, sizeof(mb), &mb) < 0)
488 goto cancel;
489 }
490
491 if (gwj->mod.modtype.xor) {
492 memcpy(&mb.cf, &gwj->mod.modframe.xor, sizeof(mb.cf));
493 mb.modtype = gwj->mod.modtype.xor;
494 if (nla_put(skb, CGW_MOD_XOR, sizeof(mb), &mb) < 0)
495 goto cancel;
496 }
497
498 if (gwj->mod.modtype.set) {
499 memcpy(&mb.cf, &gwj->mod.modframe.set, sizeof(mb.cf));
500 mb.modtype = gwj->mod.modtype.set;
501 if (nla_put(skb, CGW_MOD_SET, sizeof(mb), &mb) < 0)
502 goto cancel;
503 }
504
505 if (gwj->mod.csumfunc.crc8) {
506 if (nla_put(skb, CGW_CS_CRC8, CGW_CS_CRC8_LEN,
507 &gwj->mod.csum.crc8) < 0)
508 goto cancel;
509 }
510
511 if (gwj->mod.csumfunc.xor) {
512 if (nla_put(skb, CGW_CS_XOR, CGW_CS_XOR_LEN,
513 &gwj->mod.csum.xor) < 0)
514 goto cancel;
515 }
516
517 if (gwj->gwtype == CGW_TYPE_CAN_CAN) {
518
519 if (gwj->ccgw.filter.can_id || gwj->ccgw.filter.can_mask) {
520 if (nla_put(skb, CGW_FILTER, sizeof(struct can_filter),
521 &gwj->ccgw.filter) < 0)
522 goto cancel;
523 }
524
525 if (nla_put_u32(skb, CGW_SRC_IF, gwj->ccgw.src_idx) < 0)
526 goto cancel;
527
528 if (nla_put_u32(skb, CGW_DST_IF, gwj->ccgw.dst_idx) < 0)
529 goto cancel;
530 }
531
532 return nlmsg_end(skb, nlh);
533
534cancel:
535 nlmsg_cancel(skb, nlh);
536 return -EMSGSIZE;
537}
538
539/* Dump information about all CAN gateway jobs, in response to RTM_GETROUTE */
540static int cgw_dump_jobs(struct sk_buff *skb, struct netlink_callback *cb)
541{
542 struct cgw_job *gwj = NULL;
543 struct hlist_node *n;
544 int idx = 0;
545 int s_idx = cb->args[0];
546
547 rcu_read_lock();
548 hlist_for_each_entry_rcu(gwj, n, &cgw_list, list) {
549 if (idx < s_idx)
550 goto cont;
551
552 if (cgw_put_job(skb, gwj, RTM_NEWROUTE, NETLINK_CB(cb->skb).portid,
553 cb->nlh->nlmsg_seq, NLM_F_MULTI) < 0)
554 break;
555cont:
556 idx++;
557 }
558 rcu_read_unlock();
559
560 cb->args[0] = idx;
561
562 return skb->len;
563}
564
565static const struct nla_policy cgw_policy[CGW_MAX+1] = {
566 [CGW_MOD_AND] = { .len = sizeof(struct cgw_frame_mod) },
567 [CGW_MOD_OR] = { .len = sizeof(struct cgw_frame_mod) },
568 [CGW_MOD_XOR] = { .len = sizeof(struct cgw_frame_mod) },
569 [CGW_MOD_SET] = { .len = sizeof(struct cgw_frame_mod) },
570 [CGW_CS_XOR] = { .len = sizeof(struct cgw_csum_xor) },
571 [CGW_CS_CRC8] = { .len = sizeof(struct cgw_csum_crc8) },
572 [CGW_SRC_IF] = { .type = NLA_U32 },
573 [CGW_DST_IF] = { .type = NLA_U32 },
574 [CGW_FILTER] = { .len = sizeof(struct can_filter) },
575};
576
577/* check for common and gwtype specific attributes */
578static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod,
579 u8 gwtype, void *gwtypeattr)
580{
581 struct nlattr *tb[CGW_MAX+1];
582 struct cgw_frame_mod mb;
583 int modidx = 0;
584 int err = 0;
585
586 /* initialize modification & checksum data space */
587 memset(mod, 0, sizeof(*mod));
588
589 err = nlmsg_parse(nlh, sizeof(struct rtcanmsg), tb, CGW_MAX,
590 cgw_policy);
591 if (err < 0)
592 return err;
593
594 /* check for AND/OR/XOR/SET modifications */
595
596 if (tb[CGW_MOD_AND]) {
597 nla_memcpy(&mb, tb[CGW_MOD_AND], CGW_MODATTR_LEN);
598
599 canframecpy(&mod->modframe.and, &mb.cf);
600 mod->modtype.and = mb.modtype;
601
602 if (mb.modtype & CGW_MOD_ID)
603 mod->modfunc[modidx++] = mod_and_id;
604
605 if (mb.modtype & CGW_MOD_DLC)
606 mod->modfunc[modidx++] = mod_and_dlc;
607
608 if (mb.modtype & CGW_MOD_DATA)
609 mod->modfunc[modidx++] = mod_and_data;
610 }
611
612 if (tb[CGW_MOD_OR]) {
613 nla_memcpy(&mb, tb[CGW_MOD_OR], CGW_MODATTR_LEN);
614
615 canframecpy(&mod->modframe.or, &mb.cf);
616 mod->modtype.or = mb.modtype;
617
618 if (mb.modtype & CGW_MOD_ID)
619 mod->modfunc[modidx++] = mod_or_id;
620
621 if (mb.modtype & CGW_MOD_DLC)
622 mod->modfunc[modidx++] = mod_or_dlc;
623
624 if (mb.modtype & CGW_MOD_DATA)
625 mod->modfunc[modidx++] = mod_or_data;
626 }
627
628 if (tb[CGW_MOD_XOR]) {
629 nla_memcpy(&mb, tb[CGW_MOD_XOR], CGW_MODATTR_LEN);
630
631 canframecpy(&mod->modframe.xor, &mb.cf);
632 mod->modtype.xor = mb.modtype;
633
634 if (mb.modtype & CGW_MOD_ID)
635 mod->modfunc[modidx++] = mod_xor_id;
636
637 if (mb.modtype & CGW_MOD_DLC)
638 mod->modfunc[modidx++] = mod_xor_dlc;
639
640 if (mb.modtype & CGW_MOD_DATA)
641 mod->modfunc[modidx++] = mod_xor_data;
642 }
643
644 if (tb[CGW_MOD_SET]) {
645 nla_memcpy(&mb, tb[CGW_MOD_SET], CGW_MODATTR_LEN);
646
647 canframecpy(&mod->modframe.set, &mb.cf);
648 mod->modtype.set = mb.modtype;
649
650 if (mb.modtype & CGW_MOD_ID)
651 mod->modfunc[modidx++] = mod_set_id;
652
653 if (mb.modtype & CGW_MOD_DLC)
654 mod->modfunc[modidx++] = mod_set_dlc;
655
656 if (mb.modtype & CGW_MOD_DATA)
657 mod->modfunc[modidx++] = mod_set_data;
658 }
659
660 /* check for checksum operations after CAN frame modifications */
661 if (modidx) {
662
663 if (tb[CGW_CS_CRC8]) {
664 struct cgw_csum_crc8 *c = nla_data(tb[CGW_CS_CRC8]);
665
666 err = cgw_chk_csum_parms(c->from_idx, c->to_idx,
667 c->result_idx);
668 if (err)
669 return err;
670
671 nla_memcpy(&mod->csum.crc8, tb[CGW_CS_CRC8],
672 CGW_CS_CRC8_LEN);
673
674 /*
675 * select dedicated processing function to reduce
676 * runtime operations in receive hot path.
677 */
678 if (c->from_idx < 0 || c->to_idx < 0 ||
679 c->result_idx < 0)
680 mod->csumfunc.crc8 = cgw_csum_crc8_rel;
681 else if (c->from_idx <= c->to_idx)
682 mod->csumfunc.crc8 = cgw_csum_crc8_pos;
683 else
684 mod->csumfunc.crc8 = cgw_csum_crc8_neg;
685 }
686
687 if (tb[CGW_CS_XOR]) {
688 struct cgw_csum_xor *c = nla_data(tb[CGW_CS_XOR]);
689
690 err = cgw_chk_csum_parms(c->from_idx, c->to_idx,
691 c->result_idx);
692 if (err)
693 return err;
694
695 nla_memcpy(&mod->csum.xor, tb[CGW_CS_XOR],
696 CGW_CS_XOR_LEN);
697
698 /*
699 * select dedicated processing function to reduce
700 * runtime operations in receive hot path.
701 */
702 if (c->from_idx < 0 || c->to_idx < 0 ||
703 c->result_idx < 0)
704 mod->csumfunc.xor = cgw_csum_xor_rel;
705 else if (c->from_idx <= c->to_idx)
706 mod->csumfunc.xor = cgw_csum_xor_pos;
707 else
708 mod->csumfunc.xor = cgw_csum_xor_neg;
709 }
710 }
711
712 if (gwtype == CGW_TYPE_CAN_CAN) {
713
714 /* check CGW_TYPE_CAN_CAN specific attributes */
715
716 struct can_can_gw *ccgw = (struct can_can_gw *)gwtypeattr;
717 memset(ccgw, 0, sizeof(*ccgw));
718
719 /* check for can_filter in attributes */
720 if (tb[CGW_FILTER])
721 nla_memcpy(&ccgw->filter, tb[CGW_FILTER],
722 sizeof(struct can_filter));
723
724 err = -ENODEV;
725
726 /* specifying two interfaces is mandatory */
727 if (!tb[CGW_SRC_IF] || !tb[CGW_DST_IF])
728 return err;
729
730 ccgw->src_idx = nla_get_u32(tb[CGW_SRC_IF]);
731 ccgw->dst_idx = nla_get_u32(tb[CGW_DST_IF]);
732
733 /* both indices set to 0 for flushing all routing entries */
734 if (!ccgw->src_idx && !ccgw->dst_idx)
735 return 0;
736
737 /* only one index set to 0 is an error */
738 if (!ccgw->src_idx || !ccgw->dst_idx)
739 return err;
740 }
741
742 /* add the checks for other gwtypes here */
743
744 return 0;
745}
746
747static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh,
748 void *arg)
749{
750 struct rtcanmsg *r;
751 struct cgw_job *gwj;
752 int err = 0;
753
754 if (!capable(CAP_NET_ADMIN))
755 return -EPERM;
756
757 if (nlmsg_len(nlh) < sizeof(*r))
758 return -EINVAL;
759
760 r = nlmsg_data(nlh);
761 if (r->can_family != AF_CAN)
762 return -EPFNOSUPPORT;
763
764 /* so far we only support CAN -> CAN routings */
765 if (r->gwtype != CGW_TYPE_CAN_CAN)
766 return -EINVAL;
767
768 gwj = kmem_cache_alloc(cgw_cache, GFP_KERNEL);
769 if (!gwj)
770 return -ENOMEM;
771
772 gwj->handled_frames = 0;
773 gwj->dropped_frames = 0;
774 gwj->flags = r->flags;
775 gwj->gwtype = r->gwtype;
776
777 err = cgw_parse_attr(nlh, &gwj->mod, CGW_TYPE_CAN_CAN, &gwj->ccgw);
778 if (err < 0)
779 goto out;
780
781 err = -ENODEV;
782
783 /* ifindex == 0 is not allowed for job creation */
784 if (!gwj->ccgw.src_idx || !gwj->ccgw.dst_idx)
785 goto out;
786
787 gwj->src.dev = dev_get_by_index(&init_net, gwj->ccgw.src_idx);
788
789 if (!gwj->src.dev)
790 goto out;
791
792 /* check for CAN netdev not using header_ops - see gw_rcv() */
793 if (gwj->src.dev->type != ARPHRD_CAN || gwj->src.dev->header_ops)
794 goto put_src_out;
795
796 gwj->dst.dev = dev_get_by_index(&init_net, gwj->ccgw.dst_idx);
797
798 if (!gwj->dst.dev)
799 goto put_src_out;
800
801 /* check for CAN netdev not using header_ops - see gw_rcv() */
802 if (gwj->dst.dev->type != ARPHRD_CAN || gwj->dst.dev->header_ops)
803 goto put_src_dst_out;
804
805 ASSERT_RTNL();
806
807 err = cgw_register_filter(gwj);
808 if (!err)
809 hlist_add_head_rcu(&gwj->list, &cgw_list);
810
811put_src_dst_out:
812 dev_put(gwj->dst.dev);
813put_src_out:
814 dev_put(gwj->src.dev);
815out:
816 if (err)
817 kmem_cache_free(cgw_cache, gwj);
818
819 return err;
820}
821
822static void cgw_remove_all_jobs(void)
823{
824 struct cgw_job *gwj = NULL;
825 struct hlist_node *n, *nx;
826
827 ASSERT_RTNL();
828
829 hlist_for_each_entry_safe(gwj, n, nx, &cgw_list, list) {
830 hlist_del(&gwj->list);
831 cgw_unregister_filter(gwj);
832 kfree(gwj);
833 }
834}
835
836static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
837{
838 struct cgw_job *gwj = NULL;
839 struct hlist_node *n, *nx;
840 struct rtcanmsg *r;
841 struct cf_mod mod;
842 struct can_can_gw ccgw;
843 int err = 0;
844
845 if (!capable(CAP_NET_ADMIN))
846 return -EPERM;
847
848 if (nlmsg_len(nlh) < sizeof(*r))
849 return -EINVAL;
850
851 r = nlmsg_data(nlh);
852 if (r->can_family != AF_CAN)
853 return -EPFNOSUPPORT;
854
855 /* so far we only support CAN -> CAN routings */
856 if (r->gwtype != CGW_TYPE_CAN_CAN)
857 return -EINVAL;
858
859 err = cgw_parse_attr(nlh, &mod, CGW_TYPE_CAN_CAN, &ccgw);
860 if (err < 0)
861 return err;
862
863 /* two interface indices both set to 0 => remove all entries */
864 if (!ccgw.src_idx && !ccgw.dst_idx) {
865 cgw_remove_all_jobs();
866 return 0;
867 }
868
869 err = -EINVAL;
870
871 ASSERT_RTNL();
872
873 /* remove only the first matching entry */
874 hlist_for_each_entry_safe(gwj, n, nx, &cgw_list, list) {
875
876 if (gwj->flags != r->flags)
877 continue;
878
879 if (memcmp(&gwj->mod, &mod, sizeof(mod)))
880 continue;
881
882 /* if (r->gwtype == CGW_TYPE_CAN_CAN) - is made sure here */
883 if (memcmp(&gwj->ccgw, &ccgw, sizeof(ccgw)))
884 continue;
885
886 hlist_del(&gwj->list);
887 cgw_unregister_filter(gwj);
888 kfree(gwj);
889 err = 0;
890 break;
891 }
892
893 return err;
894}
895
896static __init int cgw_module_init(void)
897{
898 printk(banner);
899
900 cgw_cache = kmem_cache_create("can_gw", sizeof(struct cgw_job),
901 0, 0, NULL);
902
903 if (!cgw_cache)
904 return -ENOMEM;
905
906 /* set notifier */
907 notifier.notifier_call = cgw_notifier;
908 register_netdevice_notifier(&notifier);
909
910 if (__rtnl_register(PF_CAN, RTM_GETROUTE, NULL, cgw_dump_jobs, NULL)) {
911 unregister_netdevice_notifier(&notifier);
912 kmem_cache_destroy(cgw_cache);
913 return -ENOBUFS;
914 }
915
916 /* Only the first call to __rtnl_register can fail */
917 __rtnl_register(PF_CAN, RTM_NEWROUTE, cgw_create_job, NULL, NULL);
918 __rtnl_register(PF_CAN, RTM_DELROUTE, cgw_remove_job, NULL, NULL);
919
920 return 0;
921}
922
923static __exit void cgw_module_exit(void)
924{
925 rtnl_unregister_all(PF_CAN);
926
927 unregister_netdevice_notifier(&notifier);
928
929 rtnl_lock();
930 cgw_remove_all_jobs();
931 rtnl_unlock();
932
933 rcu_barrier(); /* Wait for completion of call_rcu()'s */
934
935 kmem_cache_destroy(cgw_cache);
936}
937
938module_init(cgw_module_init);
939module_exit(cgw_module_exit);
diff --git a/net/can/proc.c b/net/can/proc.c
index ae566902d2b..0016f733969 100644
--- a/net/can/proc.c
+++ b/net/can/proc.c
@@ -37,6 +37,8 @@
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38 * DAMAGE. 38 * DAMAGE.
39 * 39 *
40 * Send feedback to <socketcan-users@lists.berlios.de>
41 *
40 */ 42 */
41 43
42#include <linux/module.h> 44#include <linux/module.h>
@@ -83,6 +85,9 @@ static const char rx_list_name[][8] = {
83 [RX_EFF] = "rx_eff", 85 [RX_EFF] = "rx_eff",
84}; 86};
85 87
88/* receive filters subscribed for 'all' CAN devices */
89extern struct dev_rcv_lists can_rx_alldev_list;
90
86/* 91/*
87 * af_can statistics stuff 92 * af_can statistics stuff
88 */ 93 */
@@ -397,7 +402,7 @@ static inline void can_rcvlist_sff_proc_show_one(struct seq_file *m,
397 int i; 402 int i;
398 int all_empty = 1; 403 int all_empty = 1;
399 404
400 /* check whether at least one list is non-empty */ 405 /* check wether at least one list is non-empty */
401 for (i = 0; i < 0x800; i++) 406 for (i = 0; i < 0x800; i++)
402 if (!hlist_empty(&d->rx_sff[i])) { 407 if (!hlist_empty(&d->rx_sff[i])) {
403 all_empty = 0; 408 all_empty = 0;
diff --git a/net/can/raw.c b/net/can/raw.c
index 5b0e3e330d9..dea99a6e596 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -37,6 +37,8 @@
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38 * DAMAGE. 38 * DAMAGE.
39 * 39 *
40 * Send feedback to <socketcan-users@lists.berlios.de>
41 *
40 */ 42 */
41 43
42#include <linux/module.h> 44#include <linux/module.h>
@@ -55,7 +57,7 @@
55#include <net/net_namespace.h> 57#include <net/net_namespace.h>
56 58
57#define CAN_RAW_VERSION CAN_VERSION 59#define CAN_RAW_VERSION CAN_VERSION
58static __initconst const char banner[] = 60static __initdata const char banner[] =
59 KERN_INFO "can: raw protocol (rev " CAN_RAW_VERSION ")\n"; 61 KERN_INFO "can: raw protocol (rev " CAN_RAW_VERSION ")\n";
60 62
61MODULE_DESCRIPTION("PF_CAN raw protocol"); 63MODULE_DESCRIPTION("PF_CAN raw protocol");
@@ -82,7 +84,6 @@ struct raw_sock {
82 struct notifier_block notifier; 84 struct notifier_block notifier;
83 int loopback; 85 int loopback;
84 int recv_own_msgs; 86 int recv_own_msgs;
85 int fd_frames;
86 int count; /* number of active filters */ 87 int count; /* number of active filters */
87 struct can_filter dfilter; /* default/single filter */ 88 struct can_filter dfilter; /* default/single filter */
88 struct can_filter *filter; /* pointer to filter(s) */ 89 struct can_filter *filter; /* pointer to filter(s) */
@@ -120,14 +121,6 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
120 if (!ro->recv_own_msgs && oskb->sk == sk) 121 if (!ro->recv_own_msgs && oskb->sk == sk)
121 return; 122 return;
122 123
123 /* do not pass frames with DLC > 8 to a legacy socket */
124 if (!ro->fd_frames) {
125 struct canfd_frame *cfd = (struct canfd_frame *)oskb->data;
126
127 if (unlikely(cfd->len > CAN_MAX_DLEN))
128 return;
129 }
130
131 /* clone the given skb to be able to enqueue it into the rcv queue */ 124 /* clone the given skb to be able to enqueue it into the rcv queue */
132 skb = skb_clone(oskb, GFP_ATOMIC); 125 skb = skb_clone(oskb, GFP_ATOMIC);
133 if (!skb) 126 if (!skb)
@@ -300,7 +293,6 @@ static int raw_init(struct sock *sk)
300 /* set default loopback behaviour */ 293 /* set default loopback behaviour */
301 ro->loopback = 1; 294 ro->loopback = 1;
302 ro->recv_own_msgs = 0; 295 ro->recv_own_msgs = 0;
303 ro->fd_frames = 0;
304 296
305 /* set notifier */ 297 /* set notifier */
306 ro->notifier.notifier_call = raw_notifier; 298 ro->notifier.notifier_call = raw_notifier;
@@ -579,15 +571,6 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
579 571
580 break; 572 break;
581 573
582 case CAN_RAW_FD_FRAMES:
583 if (optlen != sizeof(ro->fd_frames))
584 return -EINVAL;
585
586 if (copy_from_user(&ro->fd_frames, optval, optlen))
587 return -EFAULT;
588
589 break;
590
591 default: 574 default:
592 return -ENOPROTOOPT; 575 return -ENOPROTOOPT;
593 } 576 }
@@ -646,12 +629,6 @@ static int raw_getsockopt(struct socket *sock, int level, int optname,
646 val = &ro->recv_own_msgs; 629 val = &ro->recv_own_msgs;
647 break; 630 break;
648 631
649 case CAN_RAW_FD_FRAMES:
650 if (len > sizeof(int))
651 len = sizeof(int);
652 val = &ro->fd_frames;
653 break;
654
655 default: 632 default:
656 return -ENOPROTOOPT; 633 return -ENOPROTOOPT;
657 } 634 }
@@ -687,13 +664,8 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
687 } else 664 } else
688 ifindex = ro->ifindex; 665 ifindex = ro->ifindex;
689 666
690 if (ro->fd_frames) { 667 if (size != sizeof(struct can_frame))
691 if (unlikely(size != CANFD_MTU && size != CAN_MTU)) 668 return -EINVAL;
692 return -EINVAL;
693 } else {
694 if (unlikely(size != CAN_MTU))
695 return -EINVAL;
696 }
697 669
698 dev = dev_get_by_index(&init_net, ifindex); 670 dev = dev_get_by_index(&init_net, ifindex);
699 if (!dev) 671 if (!dev)
@@ -711,6 +683,9 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
711 if (err < 0) 683 if (err < 0)
712 goto free_skb; 684 goto free_skb;
713 685
686 /* to be able to check the received tx sock reference in raw_rcv() */
687 skb_shinfo(skb)->tx_flags |= SKBTX_DRV_NEEDS_SK_REF;
688
714 skb->dev = dev; 689 skb->dev = dev;
715 skb->sk = sk; 690 skb->sk = sk;
716 691
@@ -735,9 +710,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock,
735 struct msghdr *msg, size_t size, int flags) 710 struct msghdr *msg, size_t size, int flags)
736{ 711{
737 struct sock *sk = sock->sk; 712 struct sock *sk = sock->sk;
738 struct raw_sock *ro = raw_sk(sk);
739 struct sk_buff *skb; 713 struct sk_buff *skb;
740 int rxmtu;
741 int err = 0; 714 int err = 0;
742 int noblock; 715 int noblock;
743 716
@@ -748,20 +721,10 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock,
748 if (!skb) 721 if (!skb)
749 return err; 722 return err;
750 723
751 /* 724 if (size < skb->len)
752 * when serving a legacy socket the DLC <= 8 is already checked inside
753 * raw_rcv(). Now check if we need to pass a canfd_frame to a legacy
754 * socket and cut the possible CANFD_MTU/CAN_MTU length to CAN_MTU
755 */
756 if (!ro->fd_frames)
757 rxmtu = CAN_MTU;
758 else
759 rxmtu = skb->len;
760
761 if (size < rxmtu)
762 msg->msg_flags |= MSG_TRUNC; 725 msg->msg_flags |= MSG_TRUNC;
763 else 726 else
764 size = rxmtu; 727 size = skb->len;
765 728
766 err = memcpy_toiovec(msg->msg_iov, skb->data, size); 729 err = memcpy_toiovec(msg->msg_iov, skb->data, size);
767 if (err < 0) { 730 if (err < 0) {