Blame view

net/can/af_can.c 21.7 KB
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  /*
   * af_can.c - Protocol family CAN core module
   *            (used by different CAN protocol modules)
   *
   * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in the
   *    documentation and/or other materials provided with the distribution.
   * 3. Neither the name of Volkswagen nor the names of its contributors
   *    may be used to endorse or promote products derived from this software
   *    without specific prior written permission.
   *
   * Alternatively, provided that this notice is retained in full, this
   * software may be distributed under the terms of the GNU General
   * Public License ("GPL") version 2, in which case the provisions of the
   * GPL apply INSTEAD OF those given above.
   *
   * The provided data structures and external interfaces from this code
   * are not restricted to be used by modules with a GPL compatible license.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
   * DAMAGE.
   *
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
   */
  
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/kmod.h>
  #include <linux/slab.h>
  #include <linux/list.h>
  #include <linux/spinlock.h>
  #include <linux/rcupdate.h>
  #include <linux/uaccess.h>
  #include <linux/net.h>
  #include <linux/netdevice.h>
  #include <linux/socket.h>
  #include <linux/if_ether.h>
  #include <linux/if_arp.h>
  #include <linux/skbuff.h>
  #include <linux/can.h>
  #include <linux/can/core.h>
d751e6239   Manuel Zerpies   net/can: use prin...
59
  #include <linux/ratelimit.h>
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  #include <net/net_namespace.h>
  #include <net/sock.h>
  
  #include "af_can.h"
  
  static __initdata const char banner[] = KERN_INFO
  	"can: controller area network core (" CAN_VERSION_STRING ")
  ";
  
  MODULE_DESCRIPTION("Controller Area Network PF_CAN core");
  MODULE_LICENSE("Dual BSD/GPL");
  MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>, "
  	      "Oliver Hartkopp <oliver.hartkopp@volkswagen.de>");
  
  MODULE_ALIAS_NETPROTO(PF_CAN);
  
  static int stats_timer __read_mostly = 1;
  module_param(stats_timer, int, S_IRUGO);
  MODULE_PARM_DESC(stats_timer, "enable timer for statistics (default:on)");
20dd3850b   Oliver Hartkopp   can: Speed up CAN...
79
80
  /* receive filters subscribed for 'all' CAN devices */
  struct dev_rcv_lists can_rx_alldev_list;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
81
82
83
84
85
  static DEFINE_SPINLOCK(can_rcvlists_lock);
  
  static struct kmem_cache *rcv_cache __read_mostly;
  
  /* table of registered CAN protocols */
1650629d1   Kurt Van Dijck   can: make struct ...
86
  static const struct can_proto *proto_tab[CAN_NPROTO] __read_mostly;
1ca050d90   Oliver Hartkopp   can: convert prot...
87
  static DEFINE_MUTEX(proto_tab_lock);
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
88
89
90
91
92
93
94
95
  
  struct timer_list can_stattimer;   /* timer for statistics update */
  struct s_stats    can_stats;       /* packet statistics */
  struct s_pstats   can_pstats;      /* receive list statistics */
  
  /*
   * af_can socket functions
   */
53914b679   Oliver Hartkopp   can: make struct ...
96
  int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
97
98
99
100
101
102
103
104
105
106
107
108
  {
  	struct sock *sk = sock->sk;
  
  	switch (cmd) {
  
  	case SIOCGSTAMP:
  		return sock_get_timestamp(sk, (struct timeval __user *)arg);
  
  	default:
  		return -ENOIOCTLCMD;
  	}
  }
53914b679   Oliver Hartkopp   can: make struct ...
109
  EXPORT_SYMBOL(can_ioctl);
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
110
111
112
113
114
  
  static void can_sock_destruct(struct sock *sk)
  {
  	skb_queue_purge(&sk->sk_receive_queue);
  }
c8d55a9d9   Kurt Van Dijck   can: rename can_t...
115
  static const struct can_proto *can_get_proto(int protocol)
1ca050d90   Oliver Hartkopp   can: convert prot...
116
  {
1650629d1   Kurt Van Dijck   can: make struct ...
117
  	const struct can_proto *cp;
1ca050d90   Oliver Hartkopp   can: convert prot...
118
119
120
121
122
123
124
125
126
  
  	rcu_read_lock();
  	cp = rcu_dereference(proto_tab[protocol]);
  	if (cp && !try_module_get(cp->prot->owner))
  		cp = NULL;
  	rcu_read_unlock();
  
  	return cp;
  }
c8d55a9d9   Kurt Van Dijck   can: rename can_t...
127
128
129
130
  static inline void can_put_proto(const struct can_proto *cp)
  {
  	module_put(cp->prot->owner);
  }
3f378b684   Eric Paris   net: pass kern to...
131
132
  static int can_create(struct net *net, struct socket *sock, int protocol,
  		      int kern)
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
133
134
  {
  	struct sock *sk;
1650629d1   Kurt Van Dijck   can: make struct ...
135
  	const struct can_proto *cp;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
136
137
138
139
140
141
  	int err = 0;
  
  	sock->state = SS_UNCONNECTED;
  
  	if (protocol < 0 || protocol >= CAN_NPROTO)
  		return -EINVAL;
09ad9bc75   Octavian Purdila   net: use net_eq t...
142
  	if (!net_eq(net, &init_net))
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
143
  		return -EAFNOSUPPORT;
c8d55a9d9   Kurt Van Dijck   can: rename can_t...
144
  	cp = can_get_proto(protocol);
1ca050d90   Oliver Hartkopp   can: convert prot...
145

95a5afca4   Johannes Berg   net: Remove CONFI...
146
  #ifdef CONFIG_MODULES
1ca050d90   Oliver Hartkopp   can: convert prot...
147
148
  	if (!cp) {
  		/* try to load protocol module if kernel is modular */
5423dd67b   Urs Thuermann   [CAN]: Clean up m...
149
  		err = request_module("can-proto-%d", protocol);
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
150
151
152
153
154
155
  
  		/*
  		 * In case of error we only print a message but don't
  		 * return the error code immediately.  Below we will
  		 * return -EPROTONOSUPPORT
  		 */
d751e6239   Manuel Zerpies   net/can: use prin...
156
157
  		if (err)
  			printk_ratelimited(KERN_ERR "can: request_module "
5423dd67b   Urs Thuermann   [CAN]: Clean up m...
158
159
  			       "(can-proto-%d) failed.
  ", protocol);
1ca050d90   Oliver Hartkopp   can: convert prot...
160

c8d55a9d9   Kurt Van Dijck   can: rename can_t...
161
  		cp = can_get_proto(protocol);
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
162
  	}
5423dd67b   Urs Thuermann   [CAN]: Clean up m...
163
  #endif
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
164

0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
165
166
167
168
169
170
  	/* check for available protocol and correct usage */
  
  	if (!cp)
  		return -EPROTONOSUPPORT;
  
  	if (cp->type != sock->type) {
1ca050d90   Oliver Hartkopp   can: convert prot...
171
  		err = -EPROTOTYPE;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
172
173
  		goto errout;
  	}
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
  	sock->ops = cp->ops;
  
  	sk = sk_alloc(net, PF_CAN, GFP_KERNEL, cp->prot);
  	if (!sk) {
  		err = -ENOMEM;
  		goto errout;
  	}
  
  	sock_init_data(sock, sk);
  	sk->sk_destruct = can_sock_destruct;
  
  	if (sk->sk_prot->init)
  		err = sk->sk_prot->init(sk);
  
  	if (err) {
  		/* release sk on errors */
  		sock_orphan(sk);
  		sock_put(sk);
  	}
  
   errout:
c8d55a9d9   Kurt Van Dijck   can: rename can_t...
195
  	can_put_proto(cp);
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
196
197
198
199
200
201
202
203
204
205
206
207
  	return err;
  }
  
  /*
   * af_can tx path
   */
  
  /**
   * can_send - transmit a CAN frame (optional with local loopback)
   * @skb: pointer to socket buffer with CAN frame in data section
   * @loop: loopback for listeners on local CAN sockets (recommended default!)
   *
481a81991   Oliver Hartkopp   can: fix NOHZ loc...
208
209
   * Due to the loopback this routine must not be called from hardirq context.
   *
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
210
211
212
213
214
215
   * Return:
   *  0 on success
   *  -ENETDOWN when the selected interface is down
   *  -ENOBUFS on full driver queue (see net_xmit_errno())
   *  -ENOMEM when local loopback failed at calling skb_clone()
   *  -EPERM when trying to send on a non-CAN interface
7f2d38eb7   Oliver Hartkopp   can: add sanity c...
216
   *  -EINVAL when the skb->data does not contain a valid CAN frame
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
217
218
219
   */
  int can_send(struct sk_buff *skb, int loop)
  {
c2ab7ac22   Oliver Hartkopp   can: Fix can_send...
220
  	struct sk_buff *newskb = NULL;
7f2d38eb7   Oliver Hartkopp   can: add sanity c...
221
  	struct can_frame *cf = (struct can_frame *)skb->data;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
222
  	int err;
7f2d38eb7   Oliver Hartkopp   can: add sanity c...
223
224
225
226
  	if (skb->len != sizeof(struct can_frame) || cf->can_dlc > 8) {
  		kfree_skb(skb);
  		return -EINVAL;
  	}
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
  	if (skb->dev->type != ARPHRD_CAN) {
  		kfree_skb(skb);
  		return -EPERM;
  	}
  
  	if (!(skb->dev->flags & IFF_UP)) {
  		kfree_skb(skb);
  		return -ENETDOWN;
  	}
  
  	skb->protocol = htons(ETH_P_CAN);
  	skb_reset_network_header(skb);
  	skb_reset_transport_header(skb);
  
  	if (loop) {
  		/* local loopback of sent CAN frames */
  
  		/* indication for the CAN driver: do loopback */
  		skb->pkt_type = PACKET_LOOPBACK;
  
  		/*
  		 * The reference to the originating sock may be required
  		 * by the receiving socket to check whether the frame is
  		 * its own. Example: can_raw sockopt CAN_RAW_RECV_OWN_MSGS
  		 * Therefore we have to ensure that skb->sk remains the
  		 * reference to the originating sock by restoring skb->sk
  		 * after each skb_clone() or skb_orphan() usage.
  		 */
  
  		if (!(skb->dev->flags & IFF_ECHO)) {
  			/*
  			 * If the interface is not capable to do loopback
  			 * itself, we do it here.
  			 */
c2ab7ac22   Oliver Hartkopp   can: Fix can_send...
261
  			newskb = skb_clone(skb, GFP_ATOMIC);
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
262
263
264
265
266
267
268
269
  			if (!newskb) {
  				kfree_skb(skb);
  				return -ENOMEM;
  			}
  
  			newskb->sk = skb->sk;
  			newskb->ip_summed = CHECKSUM_UNNECESSARY;
  			newskb->pkt_type = PACKET_BROADCAST;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
270
271
272
273
274
275
276
277
278
279
  		}
  	} else {
  		/* indication for the CAN driver: no loopback required */
  		skb->pkt_type = PACKET_HOST;
  	}
  
  	/* send to netdevice */
  	err = dev_queue_xmit(skb);
  	if (err > 0)
  		err = net_xmit_errno(err);
c2ab7ac22   Oliver Hartkopp   can: Fix can_send...
280
  	if (err) {
ce030edfb   Wei Yongjun   can: remove some ...
281
  		kfree_skb(newskb);
c2ab7ac22   Oliver Hartkopp   can: Fix can_send...
282
283
284
285
  		return err;
  	}
  
  	if (newskb)
481a81991   Oliver Hartkopp   can: fix NOHZ loc...
286
  		netif_rx_ni(newskb);
c2ab7ac22   Oliver Hartkopp   can: Fix can_send...
287

0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
288
289
290
  	/* update statistics */
  	can_stats.tx_frames++;
  	can_stats.tx_frames_delta++;
c2ab7ac22   Oliver Hartkopp   can: Fix can_send...
291
  	return 0;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
292
293
294
295
296
297
298
299
300
  }
  EXPORT_SYMBOL(can_send);
  
  /*
   * af_can rx path
   */
  
  static struct dev_rcv_lists *find_dev_rcv_lists(struct net_device *dev)
  {
20dd3850b   Oliver Hartkopp   can: Speed up CAN...
301
302
303
304
  	if (!dev)
  		return &can_rx_alldev_list;
  	else
  		return (struct dev_rcv_lists *)dev->ml_priv;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
305
  }
d253eee20   Oliver Hartkopp   can: Fix CAN_(EFF...
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
  /**
   * find_rcv_list - determine optimal filterlist inside device filter struct
   * @can_id: pointer to CAN identifier of a given can_filter
   * @mask: pointer to CAN mask of a given can_filter
   * @d: pointer to the device filter struct
   *
   * Description:
   *  Returns the optimal filterlist to reduce the filter handling in the
   *  receive path. This function is called by service functions that need
   *  to register or unregister a can_filter in the filter lists.
   *
   *  A filter matches in general, when
   *
   *          <received_can_id> & mask == can_id & mask
   *
   *  so every bit set in the mask (even CAN_EFF_FLAG, CAN_RTR_FLAG) describe
   *  relevant bits for the filter.
   *
   *  The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
   *  filter for error frames (CAN_ERR_FLAG bit set in mask). For error frames
   *  there is a special filterlist and a special rx path filter handling.
   *
   * Return:
   *  Pointer to optimal filterlist for the given can_id/mask pair.
   *  Constistency checked mask.
   *  Reduced can_id to have a preprocessed filter compare value.
   */
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
333
334
335
336
  static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask,
  					struct dev_rcv_lists *d)
  {
  	canid_t inv = *can_id & CAN_INV_FILTER; /* save flag before masking */
d253eee20   Oliver Hartkopp   can: Fix CAN_(EFF...
337
  	/* filter for error frames in extra filterlist */
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
338
  	if (*mask & CAN_ERR_FLAG) {
d253eee20   Oliver Hartkopp   can: Fix CAN_(EFF...
339
  		/* clear CAN_ERR_FLAG in filter entry */
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
340
341
342
  		*mask &= CAN_ERR_MASK;
  		return &d->rx[RX_ERR];
  	}
d253eee20   Oliver Hartkopp   can: Fix CAN_(EFF...
343
344
345
346
347
348
349
  	/* with cleared CAN_ERR_FLAG we have a simple mask/value filterpair */
  
  #define CAN_EFF_RTR_FLAGS (CAN_EFF_FLAG | CAN_RTR_FLAG)
  
  	/* ensure valid values in can_mask for 'SFF only' frame filtering */
  	if ((*mask & CAN_EFF_FLAG) && !(*can_id & CAN_EFF_FLAG))
  		*mask &= (CAN_SFF_MASK | CAN_EFF_RTR_FLAGS);
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
350
351
352
353
354
355
356
357
358
359
360
  
  	/* reduce condition testing at receive time */
  	*can_id &= *mask;
  
  	/* inverse can_id/can_mask filter */
  	if (inv)
  		return &d->rx[RX_INV];
  
  	/* mask == 0 => no condition testing at receive time */
  	if (!(*mask))
  		return &d->rx[RX_ALL];
d253eee20   Oliver Hartkopp   can: Fix CAN_(EFF...
361
  	/* extra filterlists for the subscription of a single non-RTR can_id */
f64f9e719   Joe Perches   net: Move && and ...
362
363
  	if (((*mask & CAN_EFF_RTR_FLAGS) == CAN_EFF_RTR_FLAGS) &&
  	    !(*can_id & CAN_RTR_FLAG)) {
d253eee20   Oliver Hartkopp   can: Fix CAN_(EFF...
364
365
366
367
368
369
370
371
372
  
  		if (*can_id & CAN_EFF_FLAG) {
  			if (*mask == (CAN_EFF_MASK | CAN_EFF_RTR_FLAGS)) {
  				/* RFC: a future use-case for hash-tables? */
  				return &d->rx[RX_EFF];
  			}
  		} else {
  			if (*mask == (CAN_SFF_MASK | CAN_EFF_RTR_FLAGS))
  				return &d->rx_sff[*can_id];
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
373
  		}
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
  	}
  
  	/* default: filter via can_id/can_mask */
  	return &d->rx[RX_FIL];
  }
  
  /**
   * can_rx_register - subscribe CAN frames from a specific interface
   * @dev: pointer to netdevice (NULL => subcribe from 'all' CAN devices list)
   * @can_id: CAN identifier (see description)
   * @mask: CAN mask (see description)
   * @func: callback function on filter match
   * @data: returned parameter for callback function
   * @ident: string for calling module indentification
   *
   * Description:
   *  Invokes the callback function with the received sk_buff and the given
   *  parameter 'data' on a matching receive filter. A filter matches, when
   *
   *          <received_can_id> & mask == can_id & mask
   *
   *  The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
   *  filter for error frames (CAN_ERR_FLAG bit set in mask).
   *
1fa17d4ba   Oliver Hartkopp   can: omit unneede...
398
399
400
401
402
403
   *  The provided pointer to the sk_buff is guaranteed to be valid as long as
   *  the callback function is running. The callback function must *not* free
   *  the given sk_buff while processing it's task. When the given sk_buff is
   *  needed after the end of the callback function it must be cloned inside
   *  the callback function with skb_clone().
   *
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
   * Return:
   *  0 on success
   *  -ENOMEM on missing cache mem to create subscription entry
   *  -ENODEV unknown device
   */
  int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
  		    void (*func)(struct sk_buff *, void *), void *data,
  		    char *ident)
  {
  	struct receiver *r;
  	struct hlist_head *rl;
  	struct dev_rcv_lists *d;
  	int err = 0;
  
  	/* insert new receiver  (dev,canid,mask) -> (func,data) */
8b64056da   Oliver Hartkopp   can: deny filterl...
419
420
  	if (dev && dev->type != ARPHRD_CAN)
  		return -ENODEV;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
  	r = kmem_cache_alloc(rcv_cache, GFP_KERNEL);
  	if (!r)
  		return -ENOMEM;
  
  	spin_lock(&can_rcvlists_lock);
  
  	d = find_dev_rcv_lists(dev);
  	if (d) {
  		rl = find_rcv_list(&can_id, &mask, d);
  
  		r->can_id  = can_id;
  		r->mask    = mask;
  		r->matches = 0;
  		r->func    = func;
  		r->data    = data;
  		r->ident   = ident;
  
  		hlist_add_head_rcu(&r->list, rl);
  		d->entries++;
  
  		can_pstats.rcv_entries++;
  		if (can_pstats.rcv_entries_max < can_pstats.rcv_entries)
  			can_pstats.rcv_entries_max = can_pstats.rcv_entries;
  	} else {
  		kmem_cache_free(rcv_cache, r);
  		err = -ENODEV;
  	}
  
  	spin_unlock(&can_rcvlists_lock);
  
  	return err;
  }
  EXPORT_SYMBOL(can_rx_register);
  
  /*
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
   * can_rx_delete_receiver - rcu callback for single receiver entry removal
   */
  static void can_rx_delete_receiver(struct rcu_head *rp)
  {
  	struct receiver *r = container_of(rp, struct receiver, rcu);
  
  	kmem_cache_free(rcv_cache, r);
  }
  
  /**
   * can_rx_unregister - unsubscribe CAN frames from a specific interface
   * @dev: pointer to netdevice (NULL => unsubcribe from 'all' CAN devices list)
   * @can_id: CAN identifier
   * @mask: CAN mask
   * @func: callback function on filter match
   * @data: returned parameter for callback function
   *
   * Description:
   *  Removes subscription entry depending on given (subscription) values.
   */
  void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask,
  		       void (*func)(struct sk_buff *, void *), void *data)
  {
  	struct receiver *r = NULL;
  	struct hlist_head *rl;
  	struct hlist_node *next;
  	struct dev_rcv_lists *d;
8b64056da   Oliver Hartkopp   can: deny filterl...
483
484
  	if (dev && dev->type != ARPHRD_CAN)
  		return;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
  	spin_lock(&can_rcvlists_lock);
  
  	d = find_dev_rcv_lists(dev);
  	if (!d) {
  		printk(KERN_ERR "BUG: receive list not found for "
  		       "dev %s, id %03X, mask %03X
  ",
  		       DNAME(dev), can_id, mask);
  		goto out;
  	}
  
  	rl = find_rcv_list(&can_id, &mask, d);
  
  	/*
  	 * Search the receiver list for the item to delete.  This should
  	 * exist, since no receiver may be unregistered that hasn't
  	 * been registered before.
  	 */
  
  	hlist_for_each_entry_rcu(r, next, rl, list) {
f64f9e719   Joe Perches   net: Move && and ...
505
506
  		if (r->can_id == can_id && r->mask == mask &&
  		    r->func == func && r->data == data)
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
  			break;
  	}
  
  	/*
  	 * Check for bugs in CAN protocol implementations:
  	 * If no matching list item was found, the list cursor variable next
  	 * will be NULL, while r will point to the last item of the list.
  	 */
  
  	if (!next) {
  		printk(KERN_ERR "BUG: receive list entry not found for "
  		       "dev %s, id %03X, mask %03X
  ",
  		       DNAME(dev), can_id, mask);
  		r = NULL;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
522
523
524
525
526
527
528
529
530
531
  		goto out;
  	}
  
  	hlist_del_rcu(&r->list);
  	d->entries--;
  
  	if (can_pstats.rcv_entries > 0)
  		can_pstats.rcv_entries--;
  
  	/* remove device structure requested by NETDEV_UNREGISTER */
20dd3850b   Oliver Hartkopp   can: Speed up CAN...
532
533
534
535
  	if (d->remove_on_zero_entries && !d->entries) {
  		kfree(d);
  		dev->ml_priv = NULL;
  	}
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
536
537
538
539
540
541
542
  
   out:
  	spin_unlock(&can_rcvlists_lock);
  
  	/* schedule the receiver item for deletion */
  	if (r)
  		call_rcu(&r->rcu, can_rx_delete_receiver);
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
543
544
545
546
547
  }
  EXPORT_SYMBOL(can_rx_unregister);
  
  static inline void deliver(struct sk_buff *skb, struct receiver *r)
  {
1fa17d4ba   Oliver Hartkopp   can: omit unneede...
548
549
  	r->func(skb, r->data);
  	r->matches++;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
  }
  
  static int can_rcv_filter(struct dev_rcv_lists *d, struct sk_buff *skb)
  {
  	struct receiver *r;
  	struct hlist_node *n;
  	int matches = 0;
  	struct can_frame *cf = (struct can_frame *)skb->data;
  	canid_t can_id = cf->can_id;
  
  	if (d->entries == 0)
  		return 0;
  
  	if (can_id & CAN_ERR_FLAG) {
  		/* check for error frame entries only */
  		hlist_for_each_entry_rcu(r, n, &d->rx[RX_ERR], list) {
  			if (can_id & r->mask) {
  				deliver(skb, r);
  				matches++;
  			}
  		}
  		return matches;
  	}
  
  	/* check for unfiltered entries */
  	hlist_for_each_entry_rcu(r, n, &d->rx[RX_ALL], list) {
  		deliver(skb, r);
  		matches++;
  	}
  
  	/* check for can_id/mask entries */
  	hlist_for_each_entry_rcu(r, n, &d->rx[RX_FIL], list) {
  		if ((can_id & r->mask) == r->can_id) {
  			deliver(skb, r);
  			matches++;
  		}
  	}
  
  	/* check for inverted can_id/mask entries */
  	hlist_for_each_entry_rcu(r, n, &d->rx[RX_INV], list) {
  		if ((can_id & r->mask) != r->can_id) {
  			deliver(skb, r);
  			matches++;
  		}
  	}
f706644d5   Oliver Hartkopp   can: omit receive...
595
596
597
  	/* check filterlists for single non-RTR can_ids */
  	if (can_id & CAN_RTR_FLAG)
  		return matches;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
  	if (can_id & CAN_EFF_FLAG) {
  		hlist_for_each_entry_rcu(r, n, &d->rx[RX_EFF], list) {
  			if (r->can_id == can_id) {
  				deliver(skb, r);
  				matches++;
  			}
  		}
  	} else {
  		can_id &= CAN_SFF_MASK;
  		hlist_for_each_entry_rcu(r, n, &d->rx_sff[can_id], list) {
  			deliver(skb, r);
  			matches++;
  		}
  	}
  
  	return matches;
  }
  
  static int can_rcv(struct sk_buff *skb, struct net_device *dev,
  		   struct packet_type *pt, struct net_device *orig_dev)
  {
  	struct dev_rcv_lists *d;
7f2d38eb7   Oliver Hartkopp   can: add sanity c...
620
  	struct can_frame *cf = (struct can_frame *)skb->data;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
621
  	int matches;
1758c0947   Oliver Hartkopp   can: Use WARN_ONC...
622
623
  	if (!net_eq(dev_net(dev), &init_net))
  		goto drop;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
624

1758c0947   Oliver Hartkopp   can: Use WARN_ONC...
625
626
627
628
629
630
631
632
  	if (WARN_ONCE(dev->type != ARPHRD_CAN ||
  		      skb->len != sizeof(struct can_frame) ||
  		      cf->can_dlc > 8,
  		      "PF_CAN: dropped non conform skbuf: "
  		      "dev type %d, len %d, can_dlc %d
  ",
  		      dev->type, skb->len, cf->can_dlc))
  		goto drop;
7f2d38eb7   Oliver Hartkopp   can: add sanity c...
633

0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
  	/* update statistics */
  	can_stats.rx_frames++;
  	can_stats.rx_frames_delta++;
  
  	rcu_read_lock();
  
  	/* deliver the packet to sockets listening on all devices */
  	matches = can_rcv_filter(&can_rx_alldev_list, skb);
  
  	/* find receive list for this device */
  	d = find_dev_rcv_lists(dev);
  	if (d)
  		matches += can_rcv_filter(d, skb);
  
  	rcu_read_unlock();
62bcaa130   Oliver Hartkopp   can: Network Drop...
649
650
  	/* consume the skbuff allocated by the netdevice driver */
  	consume_skb(skb);
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
651
652
653
654
655
  
  	if (matches > 0) {
  		can_stats.matches++;
  		can_stats.matches_delta++;
  	}
6ca8b990e   Oliver Hartkopp   can: use correct ...
656
  	return NET_RX_SUCCESS;
1758c0947   Oliver Hartkopp   can: Use WARN_ONC...
657
658
659
  
  drop:
  	kfree_skb(skb);
6ca8b990e   Oliver Hartkopp   can: use correct ...
660
  	return NET_RX_DROP;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
  }
  
  /*
   * af_can protocol functions
   */
  
  /**
   * can_proto_register - register CAN transport protocol
   * @cp: pointer to CAN protocol structure
   *
   * Return:
   *  0 on success
   *  -EINVAL invalid (out of range) protocol number
   *  -EBUSY  protocol already in use
   *  -ENOBUF if proto_register() fails
   */
1650629d1   Kurt Van Dijck   can: make struct ...
677
  int can_proto_register(const struct can_proto *cp)
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
678
679
680
681
682
683
684
685
686
687
  {
  	int proto = cp->protocol;
  	int err = 0;
  
  	if (proto < 0 || proto >= CAN_NPROTO) {
  		printk(KERN_ERR "can: protocol number %d out of range
  ",
  		       proto);
  		return -EINVAL;
  	}
a2fea5f19   Urs Thuermann   [CAN]: Move proto...
688
689
690
  	err = proto_register(cp->prot, 0);
  	if (err < 0)
  		return err;
1ca050d90   Oliver Hartkopp   can: convert prot...
691
  	mutex_lock(&proto_tab_lock);
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
692
693
694
695
696
  	if (proto_tab[proto]) {
  		printk(KERN_ERR "can: protocol %d already registered
  ",
  		       proto);
  		err = -EBUSY;
53914b679   Oliver Hartkopp   can: make struct ...
697
  	} else
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
698
  		RCU_INIT_POINTER(proto_tab[proto], cp);
a2fea5f19   Urs Thuermann   [CAN]: Move proto...
699

1ca050d90   Oliver Hartkopp   can: convert prot...
700
  	mutex_unlock(&proto_tab_lock);
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
701

0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
702
  	if (err < 0)
a2fea5f19   Urs Thuermann   [CAN]: Move proto...
703
  		proto_unregister(cp->prot);
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
704
705
706
707
708
709
710
711
712
  
  	return err;
  }
  EXPORT_SYMBOL(can_proto_register);
  
  /**
   * can_proto_unregister - unregister CAN transport protocol
   * @cp: pointer to CAN protocol structure
   */
1650629d1   Kurt Van Dijck   can: make struct ...
713
  void can_proto_unregister(const struct can_proto *cp)
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
714
715
  {
  	int proto = cp->protocol;
1ca050d90   Oliver Hartkopp   can: convert prot...
716
717
  	mutex_lock(&proto_tab_lock);
  	BUG_ON(proto_tab[proto] != cp);
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
718
  	RCU_INIT_POINTER(proto_tab[proto], NULL);
1ca050d90   Oliver Hartkopp   can: convert prot...
719
720
721
  	mutex_unlock(&proto_tab_lock);
  
  	synchronize_rcu();
a2fea5f19   Urs Thuermann   [CAN]: Move proto...
722
723
  
  	proto_unregister(cp->prot);
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
724
725
726
727
728
729
730
731
732
733
734
  }
  EXPORT_SYMBOL(can_proto_unregister);
  
  /*
   * af_can notifier to create/remove CAN netdevice specific structs
   */
  static int can_notifier(struct notifier_block *nb, unsigned long msg,
  			void *data)
  {
  	struct net_device *dev = (struct net_device *)data;
  	struct dev_rcv_lists *d;
721499e89   YOSHIFUJI Hideaki   netns: Use net_eq...
735
  	if (!net_eq(dev_net(dev), &init_net))
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
736
737
738
739
740
741
742
743
  		return NOTIFY_DONE;
  
  	if (dev->type != ARPHRD_CAN)
  		return NOTIFY_DONE;
  
  	switch (msg) {
  
  	case NETDEV_REGISTER:
20dd3850b   Oliver Hartkopp   can: Speed up CAN...
744
  		/* create new dev_rcv_lists for this device */
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
745
746
747
748
749
750
751
  		d = kzalloc(sizeof(*d), GFP_KERNEL);
  		if (!d) {
  			printk(KERN_ERR
  			       "can: allocation of receive list failed
  ");
  			return NOTIFY_DONE;
  		}
20dd3850b   Oliver Hartkopp   can: Speed up CAN...
752
753
  		BUG_ON(dev->ml_priv);
  		dev->ml_priv = d;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
754
755
756
757
758
  
  		break;
  
  	case NETDEV_UNREGISTER:
  		spin_lock(&can_rcvlists_lock);
20dd3850b   Oliver Hartkopp   can: Speed up CAN...
759
  		d = dev->ml_priv;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
760
  		if (d) {
20dd3850b   Oliver Hartkopp   can: Speed up CAN...
761
  			if (d->entries)
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
762
  				d->remove_on_zero_entries = 1;
20dd3850b   Oliver Hartkopp   can: Speed up CAN...
763
764
765
766
  			else {
  				kfree(d);
  				dev->ml_priv = NULL;
  			}
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
767
768
769
770
771
772
  		} else
  			printk(KERN_ERR "can: notifier: receive list not "
  			       "found for dev %s
  ", dev->name);
  
  		spin_unlock(&can_rcvlists_lock);
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
773
774
775
776
777
778
779
780
781
782
783
  		break;
  	}
  
  	return NOTIFY_DONE;
  }
  
  /*
   * af_can module init/exit functions
   */
  
  static struct packet_type can_packet __read_mostly = {
09640e636   Harvey Harrison   net: replace uses...
784
  	.type = cpu_to_be16(ETH_P_CAN),
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
785
786
787
  	.dev  = NULL,
  	.func = can_rcv,
  };
ec1b4cf74   Stephen Hemminger   net: mark net_pro...
788
  static const struct net_proto_family can_family_ops = {
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
789
790
791
792
793
794
795
796
797
798
799
800
801
  	.family = PF_CAN,
  	.create = can_create,
  	.owner  = THIS_MODULE,
  };
  
  /* notifier block for netdevice event */
  static struct notifier_block can_netdev_notifier __read_mostly = {
  	.notifier_call = can_notifier,
  };
  
  static __init int can_init(void)
  {
  	printk(banner);
20dd3850b   Oliver Hartkopp   can: Speed up CAN...
802
  	memset(&can_rx_alldev_list, 0, sizeof(can_rx_alldev_list));
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
803
804
805
806
  	rcv_cache = kmem_cache_create("can_receiver", sizeof(struct receiver),
  				      0, 0, NULL);
  	if (!rcv_cache)
  		return -ENOMEM;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
  	if (stats_timer) {
  		/* the statistics are updated every second (timer triggered) */
  		setup_timer(&can_stattimer, can_stat_update, 0);
  		mod_timer(&can_stattimer, round_jiffies(jiffies + HZ));
  	} else
  		can_stattimer.function = NULL;
  
  	can_init_proc();
  
  	/* protocol register */
  	sock_register(&can_family_ops);
  	register_netdevice_notifier(&can_netdev_notifier);
  	dev_add_pack(&can_packet);
  
  	return 0;
  }
  
  static __exit void can_exit(void)
  {
20dd3850b   Oliver Hartkopp   can: Speed up CAN...
826
  	struct net_device *dev;
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
827
828
  
  	if (stats_timer)
d9e64f83e   rajan.aggarwal85@gmail.com   net/can/af_can.c:...
829
  		del_timer_sync(&can_stattimer);
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
830
831
832
833
834
835
836
  
  	can_remove_proc();
  
  	/* protocol unregister */
  	dev_remove_pack(&can_packet);
  	unregister_netdevice_notifier(&can_netdev_notifier);
  	sock_unregister(PF_CAN);
20dd3850b   Oliver Hartkopp   can: Speed up CAN...
837
838
839
840
841
842
843
844
845
846
847
  	/* remove created dev_rcv_lists from still registered CAN devices */
  	rcu_read_lock();
  	for_each_netdev_rcu(&init_net, dev) {
  		if (dev->type == ARPHRD_CAN && dev->ml_priv){
  
  			struct dev_rcv_lists *d = dev->ml_priv;
  
  			BUG_ON(d->entries);
  			kfree(d);
  			dev->ml_priv = NULL;
  		}
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
848
  	}
20dd3850b   Oliver Hartkopp   can: Speed up CAN...
849
  	rcu_read_unlock();
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
850

382bfeec4   Jesper Dangaard Brouer   can: af_can.c use...
851
  	rcu_barrier(); /* Wait for completion of call_rcu()'s */
0d66548a1   Oliver Hartkopp   [CAN]: Add PF_CAN...
852
853
854
855
856
  	kmem_cache_destroy(rcv_cache);
  }
  
  module_init(can_init);
  module_exit(can_exit);