Blame view

net/can/raw.c 20.2 KB
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
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
  /*
   * raw.c - Raw sockets for protocol family CAN
   *
   * 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.
   *
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
40
41
42
43
44
45
   */
  
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/uio.h>
  #include <linux/net.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
46
  #include <linux/slab.h>
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
47
48
49
50
51
52
  #include <linux/netdevice.h>
  #include <linux/socket.h>
  #include <linux/if_arp.h>
  #include <linux/skbuff.h>
  #include <linux/can.h>
  #include <linux/can/core.h>
156c2bb9f   Oliver Hartkopp   can: add private ...
53
  #include <linux/can/skb.h>
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
54
55
56
57
58
  #include <linux/can/raw.h>
  #include <net/sock.h>
  #include <net/net_namespace.h>
  
  #define CAN_RAW_VERSION CAN_VERSION
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
59
60
61
62
  
  MODULE_DESCRIPTION("PF_CAN raw protocol");
  MODULE_LICENSE("Dual BSD/GPL");
  MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>");
b13bb2e99   Lothar Waßmann   net/can: add modu...
63
  MODULE_ALIAS("can-proto-1");
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
64
65
66
67
68
69
70
71
72
73
74
75
  
  #define MASK_ALL 0
  
  /*
   * A raw socket has a list of can_filters attached to it, each receiving
   * the CAN frames matching that filter.  If the filter list is empty,
   * no CAN frames will be received by the socket.  The default after
   * opening the socket, is to have one filter which receives all frames.
   * The filter list is allocated dynamically with the exception of the
   * list containing only one item.  This common case is optimized by
   * storing the single filter in dfilter, to avoid using dynamic memory.
   */
514ac99c6   Oliver Hartkopp   can: fix multiple...
76
  struct uniqframe {
d3b58c47d   Oliver Hartkopp   can: replace time...
77
  	int skbcnt;
514ac99c6   Oliver Hartkopp   can: fix multiple...
78
  	const struct sk_buff *skb;
a5581ef4c   Oliver Hartkopp   can: introduce ne...
79
  	unsigned int join_rx_count;
514ac99c6   Oliver Hartkopp   can: fix multiple...
80
  };
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
81
82
83
84
85
86
87
  struct raw_sock {
  	struct sock sk;
  	int bound;
  	int ifindex;
  	struct notifier_block notifier;
  	int loopback;
  	int recv_own_msgs;
e2d265d3b   Oliver Hartkopp   canfd: add suppor...
88
  	int fd_frames;
a5581ef4c   Oliver Hartkopp   can: introduce ne...
89
  	int join_filters;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
90
91
92
93
  	int count;                 /* number of active filters */
  	struct can_filter dfilter; /* default/single filter */
  	struct can_filter *filter; /* pointer to filter(s) */
  	can_err_mask_t err_mask;
514ac99c6   Oliver Hartkopp   can: fix multiple...
94
  	struct uniqframe __percpu *uniq;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
95
  };
1e55659ce   Oliver Hartkopp   can-raw: add msg_...
96
97
98
99
100
101
102
  /*
   * Return pointer to store the extra msg flags for raw_recvmsg().
   * We use the space of one unsigned int beyond the 'struct sockaddr_can'
   * in skb->cb.
   */
  static inline unsigned int *raw_flags(struct sk_buff *skb)
  {
b4772ef87   Eyal Birger   net: use common m...
103
104
  	sock_skb_cb_check_size(sizeof(struct sockaddr_can) +
  			       sizeof(unsigned int));
1e55659ce   Oliver Hartkopp   can-raw: add msg_...
105
106
107
108
  
  	/* return pointer after struct sockaddr_can */
  	return (unsigned int *)(&((struct sockaddr_can *)skb->cb)[1]);
  }
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
109
110
111
112
  static inline struct raw_sock *raw_sk(const struct sock *sk)
  {
  	return (struct raw_sock *)sk;
  }
1e55659ce   Oliver Hartkopp   can-raw: add msg_...
113
  static void raw_rcv(struct sk_buff *oskb, void *data)
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
114
115
116
117
  {
  	struct sock *sk = (struct sock *)data;
  	struct raw_sock *ro = raw_sk(sk);
  	struct sockaddr_can *addr;
1e55659ce   Oliver Hartkopp   can-raw: add msg_...
118
119
  	struct sk_buff *skb;
  	unsigned int *pflags;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
120

1fa17d4ba   Oliver Hartkopp   can: omit unneede...
121
  	/* check the received tx sock reference */
1e55659ce   Oliver Hartkopp   can-raw: add msg_...
122
  	if (!ro->recv_own_msgs && oskb->sk == sk)
1fa17d4ba   Oliver Hartkopp   can: omit unneede...
123
  		return;
821047c40   Oliver Hartkopp   can: remove CAN F...
124
125
126
  	/* do not pass non-CAN2.0 frames to a legacy socket */
  	if (!ro->fd_frames && oskb->len != CAN_MTU)
  		return;
e2d265d3b   Oliver Hartkopp   canfd: add suppor...
127

514ac99c6   Oliver Hartkopp   can: fix multiple...
128
129
  	/* eliminate multiple filter matches for the same skb */
  	if (this_cpu_ptr(ro->uniq)->skb == oskb &&
d3b58c47d   Oliver Hartkopp   can: replace time...
130
  	    this_cpu_ptr(ro->uniq)->skbcnt == can_skb_prv(oskb)->skbcnt) {
a5581ef4c   Oliver Hartkopp   can: introduce ne...
131
132
133
134
135
136
137
138
  		if (ro->join_filters) {
  			this_cpu_inc(ro->uniq->join_rx_count);
  			/* drop frame until all enabled filters matched */
  			if (this_cpu_ptr(ro->uniq)->join_rx_count < ro->count)
  				return;
  		} else {
  			return;
  		}
514ac99c6   Oliver Hartkopp   can: fix multiple...
139
140
  	} else {
  		this_cpu_ptr(ro->uniq)->skb = oskb;
d3b58c47d   Oliver Hartkopp   can: replace time...
141
  		this_cpu_ptr(ro->uniq)->skbcnt = can_skb_prv(oskb)->skbcnt;
a5581ef4c   Oliver Hartkopp   can: introduce ne...
142
143
144
145
  		this_cpu_ptr(ro->uniq)->join_rx_count = 1;
  		/* drop first frame to check all enabled filters? */
  		if (ro->join_filters && ro->count > 1)
  			return;
514ac99c6   Oliver Hartkopp   can: fix multiple...
146
  	}
1fa17d4ba   Oliver Hartkopp   can: omit unneede...
147
  	/* clone the given skb to be able to enqueue it into the rcv queue */
1e55659ce   Oliver Hartkopp   can-raw: add msg_...
148
  	skb = skb_clone(oskb, GFP_ATOMIC);
1fa17d4ba   Oliver Hartkopp   can: omit unneede...
149
150
  	if (!skb)
  		return;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
151
152
153
154
155
156
157
  
  	/*
  	 *  Put the datagram to the queue so that raw_recvmsg() can
  	 *  get it from there.  We need to pass the interface index to
  	 *  raw_recvmsg().  We pass a whole struct sockaddr_can in skb->cb
  	 *  containing the interface index.
  	 */
b4772ef87   Eyal Birger   net: use common m...
158
  	sock_skb_cb_check_size(sizeof(struct sockaddr_can));
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
159
160
161
162
  	addr = (struct sockaddr_can *)skb->cb;
  	memset(addr, 0, sizeof(*addr));
  	addr->can_family  = AF_CAN;
  	addr->can_ifindex = skb->dev->ifindex;
1e55659ce   Oliver Hartkopp   can-raw: add msg_...
163
164
165
166
167
168
169
  	/* add CAN specific message flags for raw_recvmsg() */
  	pflags = raw_flags(skb);
  	*pflags = 0;
  	if (oskb->sk)
  		*pflags |= MSG_DONTROUTE;
  	if (oskb->sk == sk)
  		*pflags |= MSG_CONFIRM;
a219994bf   Urs Thuermann   [CAN]: Minor clea...
170
  	if (sock_queue_rcv_skb(sk, skb) < 0)
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
171
172
  		kfree_skb(skb);
  }
8e8cda6d7   Mario Kicherer   can: initial supp...
173
174
175
  static int raw_enable_filters(struct net *net, struct net_device *dev,
  			      struct sock *sk, struct can_filter *filter,
  			      int count)
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
176
177
178
179
180
  {
  	int err = 0;
  	int i;
  
  	for (i = 0; i < count; i++) {
8e8cda6d7   Mario Kicherer   can: initial supp...
181
  		err = can_rx_register(net, dev, filter[i].can_id,
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
182
  				      filter[i].can_mask,
f1712c737   Eric Dumazet   can: Fix kernel p...
183
  				      raw_rcv, sk, "raw", sk);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
184
185
186
  		if (err) {
  			/* clean up successfully registered filters */
  			while (--i >= 0)
8e8cda6d7   Mario Kicherer   can: initial supp...
187
  				can_rx_unregister(net, dev, filter[i].can_id,
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
188
189
190
191
192
193
194
195
  						  filter[i].can_mask,
  						  raw_rcv, sk);
  			break;
  		}
  	}
  
  	return err;
  }
8e8cda6d7   Mario Kicherer   can: initial supp...
196
197
  static int raw_enable_errfilter(struct net *net, struct net_device *dev,
  				struct sock *sk, can_err_mask_t err_mask)
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
198
199
200
201
  {
  	int err = 0;
  
  	if (err_mask)
8e8cda6d7   Mario Kicherer   can: initial supp...
202
  		err = can_rx_register(net, dev, 0, err_mask | CAN_ERR_FLAG,
f1712c737   Eric Dumazet   can: Fix kernel p...
203
  				      raw_rcv, sk, "raw", sk);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
204
205
206
  
  	return err;
  }
8e8cda6d7   Mario Kicherer   can: initial supp...
207
208
209
  static void raw_disable_filters(struct net *net, struct net_device *dev,
  				struct sock *sk, struct can_filter *filter,
  				int count)
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
210
211
212
213
  {
  	int i;
  
  	for (i = 0; i < count; i++)
8e8cda6d7   Mario Kicherer   can: initial supp...
214
215
  		can_rx_unregister(net, dev, filter[i].can_id,
  				  filter[i].can_mask, raw_rcv, sk);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
216
  }
8e8cda6d7   Mario Kicherer   can: initial supp...
217
218
  static inline void raw_disable_errfilter(struct net *net,
  					 struct net_device *dev,
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
219
220
221
222
223
  					 struct sock *sk,
  					 can_err_mask_t err_mask)
  
  {
  	if (err_mask)
8e8cda6d7   Mario Kicherer   can: initial supp...
224
  		can_rx_unregister(net, dev, 0, err_mask | CAN_ERR_FLAG,
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
225
226
  				  raw_rcv, sk);
  }
8e8cda6d7   Mario Kicherer   can: initial supp...
227
228
  static inline void raw_disable_allfilters(struct net *net,
  					  struct net_device *dev,
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
229
230
231
  					  struct sock *sk)
  {
  	struct raw_sock *ro = raw_sk(sk);
8e8cda6d7   Mario Kicherer   can: initial supp...
232
233
  	raw_disable_filters(net, dev, sk, ro->filter, ro->count);
  	raw_disable_errfilter(net, dev, sk, ro->err_mask);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
234
  }
8e8cda6d7   Mario Kicherer   can: initial supp...
235
236
  static int raw_enable_allfilters(struct net *net, struct net_device *dev,
  				 struct sock *sk)
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
237
238
239
  {
  	struct raw_sock *ro = raw_sk(sk);
  	int err;
8e8cda6d7   Mario Kicherer   can: initial supp...
240
  	err = raw_enable_filters(net, dev, sk, ro->filter, ro->count);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
241
  	if (!err) {
8e8cda6d7   Mario Kicherer   can: initial supp...
242
  		err = raw_enable_errfilter(net, dev, sk, ro->err_mask);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
243
  		if (err)
8e8cda6d7   Mario Kicherer   can: initial supp...
244
245
  			raw_disable_filters(net, dev, sk, ro->filter,
  					    ro->count);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
246
247
248
249
250
251
  	}
  
  	return err;
  }
  
  static int raw_notifier(struct notifier_block *nb,
351638e7d   Jiri Pirko   net: pass info st...
252
  			unsigned long msg, void *ptr)
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
253
  {
351638e7d   Jiri Pirko   net: pass info st...
254
  	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
255
256
  	struct raw_sock *ro = container_of(nb, struct raw_sock, notifier);
  	struct sock *sk = &ro->sk;
8e8cda6d7   Mario Kicherer   can: initial supp...
257
  	if (!net_eq(dev_net(dev), sock_net(sk)))
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
258
259
260
261
262
263
264
265
266
267
268
269
270
271
  		return NOTIFY_DONE;
  
  	if (dev->type != ARPHRD_CAN)
  		return NOTIFY_DONE;
  
  	if (ro->ifindex != dev->ifindex)
  		return NOTIFY_DONE;
  
  	switch (msg) {
  
  	case NETDEV_UNREGISTER:
  		lock_sock(sk);
  		/* remove current filters & unregister */
  		if (ro->bound)
8e8cda6d7   Mario Kicherer   can: initial supp...
272
  			raw_disable_allfilters(dev_net(dev), dev, sk);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
  
  		if (ro->count > 1)
  			kfree(ro->filter);
  
  		ro->ifindex = 0;
  		ro->bound   = 0;
  		ro->count   = 0;
  		release_sock(sk);
  
  		sk->sk_err = ENODEV;
  		if (!sock_flag(sk, SOCK_DEAD))
  			sk->sk_error_report(sk);
  		break;
  
  	case NETDEV_DOWN:
  		sk->sk_err = ENETDOWN;
  		if (!sock_flag(sk, SOCK_DEAD))
  			sk->sk_error_report(sk);
  		break;
  	}
  
  	return NOTIFY_DONE;
  }
  
  static int raw_init(struct sock *sk)
  {
  	struct raw_sock *ro = raw_sk(sk);
  
  	ro->bound            = 0;
  	ro->ifindex          = 0;
  
  	/* set default filter to single entry dfilter */
  	ro->dfilter.can_id   = 0;
  	ro->dfilter.can_mask = MASK_ALL;
  	ro->filter           = &ro->dfilter;
  	ro->count            = 1;
  
  	/* set default loopback behaviour */
  	ro->loopback         = 1;
  	ro->recv_own_msgs    = 0;
e2d265d3b   Oliver Hartkopp   canfd: add suppor...
313
  	ro->fd_frames        = 0;
a5581ef4c   Oliver Hartkopp   can: introduce ne...
314
  	ro->join_filters     = 0;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
315

514ac99c6   Oliver Hartkopp   can: fix multiple...
316
317
318
319
  	/* alloc_percpu provides zero'ed memory */
  	ro->uniq = alloc_percpu(struct uniqframe);
  	if (unlikely(!ro->uniq))
  		return -ENOMEM;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
320
321
322
323
324
325
326
327
328
329
330
  	/* set notifier */
  	ro->notifier.notifier_call = raw_notifier;
  
  	register_netdevice_notifier(&ro->notifier);
  
  	return 0;
  }
  
  static int raw_release(struct socket *sock)
  {
  	struct sock *sk = sock->sk;
10022a6c6   Oliver Hartkopp   can: add missing ...
331
332
333
334
335
336
  	struct raw_sock *ro;
  
  	if (!sk)
  		return 0;
  
  	ro = raw_sk(sk);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
337
338
339
340
341
342
343
344
345
  
  	unregister_netdevice_notifier(&ro->notifier);
  
  	lock_sock(sk);
  
  	/* remove current filters & unregister */
  	if (ro->bound) {
  		if (ro->ifindex) {
  			struct net_device *dev;
8e8cda6d7   Mario Kicherer   can: initial supp...
346
  			dev = dev_get_by_index(sock_net(sk), ro->ifindex);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
347
  			if (dev) {
8e8cda6d7   Mario Kicherer   can: initial supp...
348
  				raw_disable_allfilters(dev_net(dev), dev, sk);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
349
350
351
  				dev_put(dev);
  			}
  		} else
8e8cda6d7   Mario Kicherer   can: initial supp...
352
  			raw_disable_allfilters(sock_net(sk), NULL, sk);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
353
354
355
356
357
358
359
360
  	}
  
  	if (ro->count > 1)
  		kfree(ro->filter);
  
  	ro->ifindex = 0;
  	ro->bound   = 0;
  	ro->count   = 0;
514ac99c6   Oliver Hartkopp   can: fix multiple...
361
  	free_percpu(ro->uniq);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
362

f7e5cc0c4   Lothar Waßmann   net/can bugfix: u...
363
364
  	sock_orphan(sk);
  	sock->sk = NULL;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
  	release_sock(sk);
  	sock_put(sk);
  
  	return 0;
  }
  
  static int raw_bind(struct socket *sock, struct sockaddr *uaddr, int len)
  {
  	struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
  	struct sock *sk = sock->sk;
  	struct raw_sock *ro = raw_sk(sk);
  	int ifindex;
  	int err = 0;
  	int notify_enetdown = 0;
  
  	if (len < sizeof(*addr))
  		return -EINVAL;
adb552c31   Marc Kleine-Budde   can: raw: raw_bin...
382
383
  	if (addr->can_family != AF_CAN)
  		return -EINVAL;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
384
385
386
387
388
389
390
391
  
  	lock_sock(sk);
  
  	if (ro->bound && addr->can_ifindex == ro->ifindex)
  		goto out;
  
  	if (addr->can_ifindex) {
  		struct net_device *dev;
8e8cda6d7   Mario Kicherer   can: initial supp...
392
  		dev = dev_get_by_index(sock_net(sk), addr->can_ifindex);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
  		if (!dev) {
  			err = -ENODEV;
  			goto out;
  		}
  		if (dev->type != ARPHRD_CAN) {
  			dev_put(dev);
  			err = -ENODEV;
  			goto out;
  		}
  		if (!(dev->flags & IFF_UP))
  			notify_enetdown = 1;
  
  		ifindex = dev->ifindex;
  
  		/* filters set by default/setsockopt */
8e8cda6d7   Mario Kicherer   can: initial supp...
408
  		err = raw_enable_allfilters(sock_net(sk), dev, sk);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
409
  		dev_put(dev);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
410
411
412
413
  	} else {
  		ifindex = 0;
  
  		/* filters set by default/setsockopt */
8e8cda6d7   Mario Kicherer   can: initial supp...
414
  		err = raw_enable_allfilters(sock_net(sk), NULL, sk);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
415
416
417
418
419
420
421
  	}
  
  	if (!err) {
  		if (ro->bound) {
  			/* unregister old filters */
  			if (ro->ifindex) {
  				struct net_device *dev;
8e8cda6d7   Mario Kicherer   can: initial supp...
422
423
  				dev = dev_get_by_index(sock_net(sk),
  						       ro->ifindex);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
424
  				if (dev) {
8e8cda6d7   Mario Kicherer   can: initial supp...
425
426
  					raw_disable_allfilters(dev_net(dev),
  							       dev, sk);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
427
428
429
  					dev_put(dev);
  				}
  			} else
8e8cda6d7   Mario Kicherer   can: initial supp...
430
  				raw_disable_allfilters(sock_net(sk), NULL, sk);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
  		}
  		ro->ifindex = ifindex;
  		ro->bound = 1;
  	}
  
   out:
  	release_sock(sk);
  
  	if (notify_enetdown) {
  		sk->sk_err = ENETDOWN;
  		if (!sock_flag(sk, SOCK_DEAD))
  			sk->sk_error_report(sk);
  	}
  
  	return err;
  }
  
  static int raw_getname(struct socket *sock, struct sockaddr *uaddr,
9b2c45d47   Denys Vlasenko   net: make getname...
449
  		       int peer)
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
450
451
452
453
454
455
456
  {
  	struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
  	struct sock *sk = sock->sk;
  	struct raw_sock *ro = raw_sk(sk);
  
  	if (peer)
  		return -EOPNOTSUPP;
e84b90ae5   Eric Dumazet   can: Fix raw_getn...
457
  	memset(addr, 0, sizeof(*addr));
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
458
459
  	addr->can_family  = AF_CAN;
  	addr->can_ifindex = ro->ifindex;
9b2c45d47   Denys Vlasenko   net: make getname...
460
  	return sizeof(*addr);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
461
462
463
  }
  
  static int raw_setsockopt(struct socket *sock, int level, int optname,
b7058842c   David S. Miller   net: Make setsock...
464
  			  char __user *optval, unsigned int optlen)
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
465
466
467
468
469
470
471
472
473
474
475
476
  {
  	struct sock *sk = sock->sk;
  	struct raw_sock *ro = raw_sk(sk);
  	struct can_filter *filter = NULL;  /* dyn. alloc'ed filters */
  	struct can_filter sfilter;         /* single filter */
  	struct net_device *dev = NULL;
  	can_err_mask_t err_mask = 0;
  	int count = 0;
  	int err = 0;
  
  	if (level != SOL_CAN_RAW)
  		return -EINVAL;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
477
478
479
480
481
482
  
  	switch (optname) {
  
  	case CAN_RAW_FILTER:
  		if (optlen % sizeof(struct can_filter) != 0)
  			return -EINVAL;
332b05ca7   Marc Kleine-Budde   can: raw: raw_set...
483
484
  		if (optlen > CAN_RAW_FILTER_MAX * sizeof(struct can_filter))
  			return -EINVAL;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
485
486
487
488
  		count = optlen / sizeof(struct can_filter);
  
  		if (count > 1) {
  			/* filter does not fit into dfilter => alloc space */
16dff9180   Julia Lawall   net/can: Use memd...
489
490
491
  			filter = memdup_user(optval, optlen);
  			if (IS_ERR(filter))
  				return PTR_ERR(filter);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
492
  		} else if (count == 1) {
4ffa87012   Eric Dumazet   can: avoids a fal...
493
  			if (copy_from_user(&sfilter, optval, sizeof(sfilter)))
3f91bd420   Sam Ravnborg   can: Fix copy_fro...
494
  				return -EFAULT;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
495
496
497
498
499
  		}
  
  		lock_sock(sk);
  
  		if (ro->bound && ro->ifindex)
8e8cda6d7   Mario Kicherer   can: initial supp...
500
  			dev = dev_get_by_index(sock_net(sk), ro->ifindex);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
501
502
503
504
  
  		if (ro->bound) {
  			/* (try to) register the new filters */
  			if (count == 1)
8e8cda6d7   Mario Kicherer   can: initial supp...
505
506
  				err = raw_enable_filters(sock_net(sk), dev, sk,
  							 &sfilter, 1);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
507
  			else
8e8cda6d7   Mario Kicherer   can: initial supp...
508
509
  				err = raw_enable_filters(sock_net(sk), dev, sk,
  							 filter, count);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
510
511
512
  			if (err) {
  				if (count > 1)
  					kfree(filter);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
513
514
515
516
  				goto out_fil;
  			}
  
  			/* remove old filter registrations */
8e8cda6d7   Mario Kicherer   can: initial supp...
517
518
  			raw_disable_filters(sock_net(sk), dev, sk, ro->filter,
  					    ro->count);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
  		}
  
  		/* remove old filter space */
  		if (ro->count > 1)
  			kfree(ro->filter);
  
  		/* link new filters to the socket */
  		if (count == 1) {
  			/* copy filter data for single filter */
  			ro->dfilter = sfilter;
  			filter = &ro->dfilter;
  		}
  		ro->filter = filter;
  		ro->count  = count;
  
   out_fil:
  		if (dev)
  			dev_put(dev);
  
  		release_sock(sk);
  
  		break;
  
  	case CAN_RAW_ERR_FILTER:
  		if (optlen != sizeof(err_mask))
  			return -EINVAL;
3f91bd420   Sam Ravnborg   can: Fix copy_fro...
545
546
  		if (copy_from_user(&err_mask, optval, optlen))
  			return -EFAULT;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
547
548
549
550
551
552
  
  		err_mask &= CAN_ERR_MASK;
  
  		lock_sock(sk);
  
  		if (ro->bound && ro->ifindex)
8e8cda6d7   Mario Kicherer   can: initial supp...
553
  			dev = dev_get_by_index(sock_net(sk), ro->ifindex);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
554
555
556
557
  
  		/* remove current error mask */
  		if (ro->bound) {
  			/* (try to) register the new err_mask */
8e8cda6d7   Mario Kicherer   can: initial supp...
558
559
  			err = raw_enable_errfilter(sock_net(sk), dev, sk,
  						   err_mask);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
560
561
562
563
564
  
  			if (err)
  				goto out_err;
  
  			/* remove old err_mask registration */
8e8cda6d7   Mario Kicherer   can: initial supp...
565
566
  			raw_disable_errfilter(sock_net(sk), dev, sk,
  					      ro->err_mask);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
  		}
  
  		/* link new err_mask to the socket */
  		ro->err_mask = err_mask;
  
   out_err:
  		if (dev)
  			dev_put(dev);
  
  		release_sock(sk);
  
  		break;
  
  	case CAN_RAW_LOOPBACK:
  		if (optlen != sizeof(ro->loopback))
  			return -EINVAL;
3f91bd420   Sam Ravnborg   can: Fix copy_fro...
583
584
  		if (copy_from_user(&ro->loopback, optval, optlen))
  			return -EFAULT;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
585
586
587
588
589
590
  
  		break;
  
  	case CAN_RAW_RECV_OWN_MSGS:
  		if (optlen != sizeof(ro->recv_own_msgs))
  			return -EINVAL;
3f91bd420   Sam Ravnborg   can: Fix copy_fro...
591
592
  		if (copy_from_user(&ro->recv_own_msgs, optval, optlen))
  			return -EFAULT;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
593
594
  
  		break;
e2d265d3b   Oliver Hartkopp   canfd: add suppor...
595
596
597
598
599
600
601
602
  	case CAN_RAW_FD_FRAMES:
  		if (optlen != sizeof(ro->fd_frames))
  			return -EINVAL;
  
  		if (copy_from_user(&ro->fd_frames, optval, optlen))
  			return -EFAULT;
  
  		break;
a5581ef4c   Oliver Hartkopp   can: introduce ne...
603
604
605
606
607
608
609
610
  	case CAN_RAW_JOIN_FILTERS:
  		if (optlen != sizeof(ro->join_filters))
  			return -EINVAL;
  
  		if (copy_from_user(&ro->join_filters, optval, optlen))
  			return -EFAULT;
  
  		break;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
  	default:
  		return -ENOPROTOOPT;
  	}
  	return err;
  }
  
  static int raw_getsockopt(struct socket *sock, int level, int optname,
  			  char __user *optval, int __user *optlen)
  {
  	struct sock *sk = sock->sk;
  	struct raw_sock *ro = raw_sk(sk);
  	int len;
  	void *val;
  	int err = 0;
  
  	if (level != SOL_CAN_RAW)
  		return -EINVAL;
  	if (get_user(len, optlen))
  		return -EFAULT;
  	if (len < 0)
  		return -EINVAL;
  
  	switch (optname) {
  
  	case CAN_RAW_FILTER:
  		lock_sock(sk);
  		if (ro->count > 0) {
  			int fsize = ro->count * sizeof(struct can_filter);
  			if (len > fsize)
  				len = fsize;
653252c23   Pavel Emelyanov   net: Fix wrong in...
641
642
  			if (copy_to_user(optval, ro->filter, len))
  				err = -EFAULT;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
  		} else
  			len = 0;
  		release_sock(sk);
  
  		if (!err)
  			err = put_user(len, optlen);
  		return err;
  
  	case CAN_RAW_ERR_FILTER:
  		if (len > sizeof(can_err_mask_t))
  			len = sizeof(can_err_mask_t);
  		val = &ro->err_mask;
  		break;
  
  	case CAN_RAW_LOOPBACK:
  		if (len > sizeof(int))
  			len = sizeof(int);
  		val = &ro->loopback;
  		break;
  
  	case CAN_RAW_RECV_OWN_MSGS:
  		if (len > sizeof(int))
  			len = sizeof(int);
  		val = &ro->recv_own_msgs;
  		break;
e2d265d3b   Oliver Hartkopp   canfd: add suppor...
668
669
670
671
672
  	case CAN_RAW_FD_FRAMES:
  		if (len > sizeof(int))
  			len = sizeof(int);
  		val = &ro->fd_frames;
  		break;
a5581ef4c   Oliver Hartkopp   can: introduce ne...
673
674
675
676
677
  	case CAN_RAW_JOIN_FILTERS:
  		if (len > sizeof(int))
  			len = sizeof(int);
  		val = &ro->join_filters;
  		break;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
678
679
680
681
682
683
684
685
686
687
  	default:
  		return -ENOPROTOOPT;
  	}
  
  	if (put_user(len, optlen))
  		return -EFAULT;
  	if (copy_to_user(optval, val, len))
  		return -EFAULT;
  	return 0;
  }
1b7841404   Ying Xue   net: Remove iocb ...
688
  static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
689
690
691
692
693
694
695
696
697
  {
  	struct sock *sk = sock->sk;
  	struct raw_sock *ro = raw_sk(sk);
  	struct sk_buff *skb;
  	struct net_device *dev;
  	int ifindex;
  	int err;
  
  	if (msg->msg_name) {
342dfc306   Steffen Hurrle   net: add build-ti...
698
  		DECLARE_SOCKADDR(struct sockaddr_can *, addr, msg->msg_name);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
699

5e5073280   Kurt Van Dijck   can: test size of...
700
701
  		if (msg->msg_namelen < sizeof(*addr))
  			return -EINVAL;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
702
703
704
705
706
707
  		if (addr->can_family != AF_CAN)
  			return -EINVAL;
  
  		ifindex = addr->can_ifindex;
  	} else
  		ifindex = ro->ifindex;
a43608fa7   Oliver Hartkopp   can: raw: check f...
708
709
710
711
712
713
  	dev = dev_get_by_index(sock_net(sk), ifindex);
  	if (!dev)
  		return -ENXIO;
  
  	err = -EINVAL;
  	if (ro->fd_frames && dev->mtu == CANFD_MTU) {
e2d265d3b   Oliver Hartkopp   canfd: add suppor...
714
  		if (unlikely(size != CANFD_MTU && size != CAN_MTU))
a43608fa7   Oliver Hartkopp   can: raw: check f...
715
  			goto put_dev;
e2d265d3b   Oliver Hartkopp   canfd: add suppor...
716
717
  	} else {
  		if (unlikely(size != CAN_MTU))
a43608fa7   Oliver Hartkopp   can: raw: check f...
718
  			goto put_dev;
e2d265d3b   Oliver Hartkopp   canfd: add suppor...
719
  	}
7f2d38eb7   Oliver Hartkopp   can: add sanity c...
720

156c2bb9f   Oliver Hartkopp   can: add private ...
721
722
  	skb = sock_alloc_send_skb(sk, size + sizeof(struct can_skb_priv),
  				  msg->msg_flags & MSG_DONTWAIT, &err);
ebad5c098   Ilpo Järvinen   can: merge error ...
723
724
  	if (!skb)
  		goto put_dev;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
725

2bf3440d7   Oliver Hartkopp   can: rework skb r...
726
727
  	can_skb_reserve(skb);
  	can_skb_prv(skb)->ifindex = dev->ifindex;
d3b58c47d   Oliver Hartkopp   can: replace time...
728
  	can_skb_prv(skb)->skbcnt = 0;
156c2bb9f   Oliver Hartkopp   can: add private ...
729

6ce8e9ce5   Al Viro   new helper: memcp...
730
  	err = memcpy_from_msg(skb_put(skb, size), msg, size);
ebad5c098   Ilpo Järvinen   can: merge error ...
731
732
  	if (err < 0)
  		goto free_skb;
bf84a0106   Daniel Borkmann   net: sock: make s...
733

8f932f762   Willem de Bruijn   net: add missing ...
734
  	skb_setup_tx_timestamp(skb, sk->sk_tsflags);
cff0d6e6e   Oliver Hartkopp   can-raw: Fix skb_...
735

c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
736
737
  	skb->dev = dev;
  	skb->sk  = sk;
bb5ecb0c6   Rostislav Lisovy   can: Propagate SO...
738
  	skb->priority = sk->sk_priority;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
739
740
741
742
743
744
  
  	err = can_send(skb, ro->loopback);
  
  	dev_put(dev);
  
  	if (err)
ebad5c098   Ilpo Järvinen   can: merge error ...
745
  		goto send_failed;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
746
747
  
  	return size;
ebad5c098   Ilpo Järvinen   can: merge error ...
748
749
750
751
752
753
754
  
  free_skb:
  	kfree_skb(skb);
  put_dev:
  	dev_put(dev);
  send_failed:
  	return err;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
755
  }
1b7841404   Ying Xue   net: Remove iocb ...
756
757
  static int raw_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
  		       int flags)
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
758
759
760
  {
  	struct sock *sk = sock->sk;
  	struct sk_buff *skb;
a219994bf   Urs Thuermann   [CAN]: Minor clea...
761
  	int err = 0;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
762
763
764
765
  	int noblock;
  
  	noblock =  flags & MSG_DONTWAIT;
  	flags   &= ~MSG_DONTWAIT;
a219994bf   Urs Thuermann   [CAN]: Minor clea...
766
  	skb = skb_recv_datagram(sk, flags, noblock, &err);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
767
  	if (!skb)
a219994bf   Urs Thuermann   [CAN]: Minor clea...
768
  		return err;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
769

821047c40   Oliver Hartkopp   can: remove CAN F...
770
  	if (size < skb->len)
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
771
772
  		msg->msg_flags |= MSG_TRUNC;
  	else
821047c40   Oliver Hartkopp   can: remove CAN F...
773
  		size = skb->len;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
774

7eab8d9e8   Al Viro   new helper: memcp...
775
  	err = memcpy_to_msg(msg, skb->data, size);
a219994bf   Urs Thuermann   [CAN]: Minor clea...
776
  	if (err < 0) {
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
777
  		skb_free_datagram(sk, skb);
a219994bf   Urs Thuermann   [CAN]: Minor clea...
778
  		return err;
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
779
  	}
3b885787e   Neil Horman   net: Generalize s...
780
  	sock_recv_ts_and_drops(msg, sk, skb);
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
781
782
  
  	if (msg->msg_name) {
342dfc306   Steffen Hurrle   net: add build-ti...
783
  		__sockaddr_check_size(sizeof(struct sockaddr_can));
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
784
785
786
  		msg->msg_namelen = sizeof(struct sockaddr_can);
  		memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
  	}
1e55659ce   Oliver Hartkopp   can-raw: add msg_...
787
788
  	/* assign the flags that have been recorded in raw_rcv() */
  	msg->msg_flags |= *(raw_flags(skb));
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
789
790
791
792
  	skb_free_datagram(sk, skb);
  
  	return size;
  }
53914b679   Oliver Hartkopp   can: make struct ...
793
  static const struct proto_ops raw_ops = {
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
794
795
796
797
798
799
800
  	.family        = PF_CAN,
  	.release       = raw_release,
  	.bind          = raw_bind,
  	.connect       = sock_no_connect,
  	.socketpair    = sock_no_socketpair,
  	.accept        = sock_no_accept,
  	.getname       = raw_getname,
a11e1d432   Linus Torvalds   Revert changes to...
801
  	.poll          = datagram_poll,
53914b679   Oliver Hartkopp   can: make struct ...
802
  	.ioctl         = can_ioctl,	/* use can_ioctl() from af_can.c */
c7cbdbf29   Arnd Bergmann   net: rework SIOCG...
803
  	.gettstamp     = sock_gettstamp,
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
  	.listen        = sock_no_listen,
  	.shutdown      = sock_no_shutdown,
  	.setsockopt    = raw_setsockopt,
  	.getsockopt    = raw_getsockopt,
  	.sendmsg       = raw_sendmsg,
  	.recvmsg       = raw_recvmsg,
  	.mmap          = sock_no_mmap,
  	.sendpage      = sock_no_sendpage,
  };
  
  static struct proto raw_proto __read_mostly = {
  	.name       = "CAN_RAW",
  	.owner      = THIS_MODULE,
  	.obj_size   = sizeof(struct raw_sock),
  	.init       = raw_init,
  };
1650629d1   Kurt Van Dijck   can: make struct ...
820
  static const struct can_proto raw_can_proto = {
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
821
822
  	.type       = SOCK_RAW,
  	.protocol   = CAN_RAW,
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
823
824
825
826
827
828
829
  	.ops        = &raw_ops,
  	.prot       = &raw_proto,
  };
  
  static __init int raw_module_init(void)
  {
  	int err;
b111b78c6   Jeremiah Mahler   can: eliminate ba...
830
831
  	pr_info("can: raw protocol (rev " CAN_RAW_VERSION ")
  ");
c18ce101f   Oliver Hartkopp   [CAN]: Add raw pr...
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
  
  	err = can_proto_register(&raw_can_proto);
  	if (err < 0)
  		printk(KERN_ERR "can: registration of raw protocol failed
  ");
  
  	return err;
  }
  
  static __exit void raw_module_exit(void)
  {
  	can_proto_unregister(&raw_can_proto);
  }
  
  module_init(raw_module_init);
  module_exit(raw_module_exit);