diff options
author | Oliver Hartkopp <oliver.hartkopp@volkswagen.de> | 2007-11-16 18:53:09 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:54:10 -0500 |
commit | c18ce101f2e47d97ace125033e2896895a6db3dd (patch) | |
tree | 9e85bb469d1a756f7f270bde67a681972fdf8097 /net/can | |
parent | 0d66548a10cbbe0ef256852d63d30603f0f73f9b (diff) |
[CAN]: Add raw protocol
This patch adds the CAN raw protocol.
Signed-off-by: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
Signed-off-by: Urs Thuermann <urs.thuermann@volkswagen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/can')
-rw-r--r-- | net/can/Kconfig | 11 | ||||
-rw-r--r-- | net/can/Makefile | 3 | ||||
-rw-r--r-- | net/can/raw.c | 763 |
3 files changed, 777 insertions, 0 deletions
diff --git a/net/can/Kconfig b/net/can/Kconfig index 8b92790747e5..4718d1f50ab3 100644 --- a/net/can/Kconfig +++ b/net/can/Kconfig | |||
@@ -15,3 +15,14 @@ menuconfig CAN | |||
15 | 15 | ||
16 | If you want CAN support you should say Y here and also to the | 16 | If you want CAN support you should say Y here and also to the |
17 | specific driver for your controller(s) below. | 17 | specific driver for your controller(s) below. |
18 | |||
19 | config CAN_RAW | ||
20 | tristate "Raw CAN Protocol (raw access with CAN-ID filtering)" | ||
21 | depends on CAN | ||
22 | default N | ||
23 | ---help--- | ||
24 | The raw CAN protocol option offers access to the CAN bus via | ||
25 | the BSD socket API. You probably want to use the raw socket in | ||
26 | most cases where no higher level protocol is being used. The raw | ||
27 | socket has several filter options e.g. ID masking / error frames. | ||
28 | To receive/send raw CAN messages, use AF_CAN with protocol CAN_RAW. | ||
diff --git a/net/can/Makefile b/net/can/Makefile index 4c7563c2ccb2..86f1cf21fce4 100644 --- a/net/can/Makefile +++ b/net/can/Makefile | |||
@@ -4,3 +4,6 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_CAN) += can.o | 5 | obj-$(CONFIG_CAN) += can.o |
6 | can-objs := af_can.o proc.o | 6 | can-objs := af_can.o proc.o |
7 | |||
8 | obj-$(CONFIG_CAN_RAW) += can-raw.o | ||
9 | can-raw-objs := raw.o | ||
diff --git a/net/can/raw.c b/net/can/raw.c new file mode 100644 index 000000000000..aeefd1419d00 --- /dev/null +++ b/net/can/raw.c | |||
@@ -0,0 +1,763 @@ | |||
1 | /* | ||
2 | * raw.c - Raw sockets for protocol family CAN | ||
3 | * | ||
4 | * Copyright (c) 2002-2007 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 | * Send feedback to <socketcan-users@lists.berlios.de> | ||
41 | * | ||
42 | */ | ||
43 | |||
44 | #include <linux/module.h> | ||
45 | #include <linux/init.h> | ||
46 | #include <linux/uio.h> | ||
47 | #include <linux/net.h> | ||
48 | #include <linux/netdevice.h> | ||
49 | #include <linux/socket.h> | ||
50 | #include <linux/if_arp.h> | ||
51 | #include <linux/skbuff.h> | ||
52 | #include <linux/can.h> | ||
53 | #include <linux/can/core.h> | ||
54 | #include <linux/can/raw.h> | ||
55 | #include <net/sock.h> | ||
56 | #include <net/net_namespace.h> | ||
57 | |||
58 | #define CAN_RAW_VERSION CAN_VERSION | ||
59 | static __initdata const char banner[] = | ||
60 | KERN_INFO "can: raw protocol (rev " CAN_RAW_VERSION ")\n"; | ||
61 | |||
62 | MODULE_DESCRIPTION("PF_CAN raw protocol"); | ||
63 | MODULE_LICENSE("Dual BSD/GPL"); | ||
64 | MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>"); | ||
65 | |||
66 | #define MASK_ALL 0 | ||
67 | |||
68 | /* | ||
69 | * A raw socket has a list of can_filters attached to it, each receiving | ||
70 | * the CAN frames matching that filter. If the filter list is empty, | ||
71 | * no CAN frames will be received by the socket. The default after | ||
72 | * opening the socket, is to have one filter which receives all frames. | ||
73 | * The filter list is allocated dynamically with the exception of the | ||
74 | * list containing only one item. This common case is optimized by | ||
75 | * storing the single filter in dfilter, to avoid using dynamic memory. | ||
76 | */ | ||
77 | |||
78 | struct raw_sock { | ||
79 | struct sock sk; | ||
80 | int bound; | ||
81 | int ifindex; | ||
82 | struct notifier_block notifier; | ||
83 | int loopback; | ||
84 | int recv_own_msgs; | ||
85 | int count; /* number of active filters */ | ||
86 | struct can_filter dfilter; /* default/single filter */ | ||
87 | struct can_filter *filter; /* pointer to filter(s) */ | ||
88 | can_err_mask_t err_mask; | ||
89 | }; | ||
90 | |||
91 | static inline struct raw_sock *raw_sk(const struct sock *sk) | ||
92 | { | ||
93 | return (struct raw_sock *)sk; | ||
94 | } | ||
95 | |||
96 | static void raw_rcv(struct sk_buff *skb, void *data) | ||
97 | { | ||
98 | struct sock *sk = (struct sock *)data; | ||
99 | struct raw_sock *ro = raw_sk(sk); | ||
100 | struct sockaddr_can *addr; | ||
101 | int error; | ||
102 | |||
103 | if (!ro->recv_own_msgs) { | ||
104 | /* check the received tx sock reference */ | ||
105 | if (skb->sk == sk) { | ||
106 | kfree_skb(skb); | ||
107 | return; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | /* | ||
112 | * Put the datagram to the queue so that raw_recvmsg() can | ||
113 | * get it from there. We need to pass the interface index to | ||
114 | * raw_recvmsg(). We pass a whole struct sockaddr_can in skb->cb | ||
115 | * containing the interface index. | ||
116 | */ | ||
117 | |||
118 | BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct sockaddr_can)); | ||
119 | addr = (struct sockaddr_can *)skb->cb; | ||
120 | memset(addr, 0, sizeof(*addr)); | ||
121 | addr->can_family = AF_CAN; | ||
122 | addr->can_ifindex = skb->dev->ifindex; | ||
123 | |||
124 | error = sock_queue_rcv_skb(sk, skb); | ||
125 | if (error < 0) | ||
126 | kfree_skb(skb); | ||
127 | } | ||
128 | |||
129 | static int raw_enable_filters(struct net_device *dev, struct sock *sk, | ||
130 | struct can_filter *filter, | ||
131 | int count) | ||
132 | { | ||
133 | int err = 0; | ||
134 | int i; | ||
135 | |||
136 | for (i = 0; i < count; i++) { | ||
137 | err = can_rx_register(dev, filter[i].can_id, | ||
138 | filter[i].can_mask, | ||
139 | raw_rcv, sk, "raw"); | ||
140 | if (err) { | ||
141 | /* clean up successfully registered filters */ | ||
142 | while (--i >= 0) | ||
143 | can_rx_unregister(dev, filter[i].can_id, | ||
144 | filter[i].can_mask, | ||
145 | raw_rcv, sk); | ||
146 | break; | ||
147 | } | ||
148 | } | ||
149 | |||
150 | return err; | ||
151 | } | ||
152 | |||
153 | static int raw_enable_errfilter(struct net_device *dev, struct sock *sk, | ||
154 | can_err_mask_t err_mask) | ||
155 | { | ||
156 | int err = 0; | ||
157 | |||
158 | if (err_mask) | ||
159 | err = can_rx_register(dev, 0, err_mask | CAN_ERR_FLAG, | ||
160 | raw_rcv, sk, "raw"); | ||
161 | |||
162 | return err; | ||
163 | } | ||
164 | |||
165 | static void raw_disable_filters(struct net_device *dev, struct sock *sk, | ||
166 | struct can_filter *filter, | ||
167 | int count) | ||
168 | { | ||
169 | int i; | ||
170 | |||
171 | for (i = 0; i < count; i++) | ||
172 | can_rx_unregister(dev, filter[i].can_id, filter[i].can_mask, | ||
173 | raw_rcv, sk); | ||
174 | } | ||
175 | |||
176 | static inline void raw_disable_errfilter(struct net_device *dev, | ||
177 | struct sock *sk, | ||
178 | can_err_mask_t err_mask) | ||
179 | |||
180 | { | ||
181 | if (err_mask) | ||
182 | can_rx_unregister(dev, 0, err_mask | CAN_ERR_FLAG, | ||
183 | raw_rcv, sk); | ||
184 | } | ||
185 | |||
186 | static inline void raw_disable_allfilters(struct net_device *dev, | ||
187 | struct sock *sk) | ||
188 | { | ||
189 | struct raw_sock *ro = raw_sk(sk); | ||
190 | |||
191 | raw_disable_filters(dev, sk, ro->filter, ro->count); | ||
192 | raw_disable_errfilter(dev, sk, ro->err_mask); | ||
193 | } | ||
194 | |||
195 | static int raw_enable_allfilters(struct net_device *dev, struct sock *sk) | ||
196 | { | ||
197 | struct raw_sock *ro = raw_sk(sk); | ||
198 | int err; | ||
199 | |||
200 | err = raw_enable_filters(dev, sk, ro->filter, ro->count); | ||
201 | if (!err) { | ||
202 | err = raw_enable_errfilter(dev, sk, ro->err_mask); | ||
203 | if (err) | ||
204 | raw_disable_filters(dev, sk, ro->filter, ro->count); | ||
205 | } | ||
206 | |||
207 | return err; | ||
208 | } | ||
209 | |||
210 | static int raw_notifier(struct notifier_block *nb, | ||
211 | unsigned long msg, void *data) | ||
212 | { | ||
213 | struct net_device *dev = (struct net_device *)data; | ||
214 | struct raw_sock *ro = container_of(nb, struct raw_sock, notifier); | ||
215 | struct sock *sk = &ro->sk; | ||
216 | |||
217 | if (dev->nd_net != &init_net) | ||
218 | return NOTIFY_DONE; | ||
219 | |||
220 | if (dev->type != ARPHRD_CAN) | ||
221 | return NOTIFY_DONE; | ||
222 | |||
223 | if (ro->ifindex != dev->ifindex) | ||
224 | return NOTIFY_DONE; | ||
225 | |||
226 | switch (msg) { | ||
227 | |||
228 | case NETDEV_UNREGISTER: | ||
229 | lock_sock(sk); | ||
230 | /* remove current filters & unregister */ | ||
231 | if (ro->bound) | ||
232 | raw_disable_allfilters(dev, sk); | ||
233 | |||
234 | if (ro->count > 1) | ||
235 | kfree(ro->filter); | ||
236 | |||
237 | ro->ifindex = 0; | ||
238 | ro->bound = 0; | ||
239 | ro->count = 0; | ||
240 | release_sock(sk); | ||
241 | |||
242 | sk->sk_err = ENODEV; | ||
243 | if (!sock_flag(sk, SOCK_DEAD)) | ||
244 | sk->sk_error_report(sk); | ||
245 | break; | ||
246 | |||
247 | case NETDEV_DOWN: | ||
248 | sk->sk_err = ENETDOWN; | ||
249 | if (!sock_flag(sk, SOCK_DEAD)) | ||
250 | sk->sk_error_report(sk); | ||
251 | break; | ||
252 | } | ||
253 | |||
254 | return NOTIFY_DONE; | ||
255 | } | ||
256 | |||
257 | static int raw_init(struct sock *sk) | ||
258 | { | ||
259 | struct raw_sock *ro = raw_sk(sk); | ||
260 | |||
261 | ro->bound = 0; | ||
262 | ro->ifindex = 0; | ||
263 | |||
264 | /* set default filter to single entry dfilter */ | ||
265 | ro->dfilter.can_id = 0; | ||
266 | ro->dfilter.can_mask = MASK_ALL; | ||
267 | ro->filter = &ro->dfilter; | ||
268 | ro->count = 1; | ||
269 | |||
270 | /* set default loopback behaviour */ | ||
271 | ro->loopback = 1; | ||
272 | ro->recv_own_msgs = 0; | ||
273 | |||
274 | /* set notifier */ | ||
275 | ro->notifier.notifier_call = raw_notifier; | ||
276 | |||
277 | register_netdevice_notifier(&ro->notifier); | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | static int raw_release(struct socket *sock) | ||
283 | { | ||
284 | struct sock *sk = sock->sk; | ||
285 | struct raw_sock *ro = raw_sk(sk); | ||
286 | |||
287 | unregister_netdevice_notifier(&ro->notifier); | ||
288 | |||
289 | lock_sock(sk); | ||
290 | |||
291 | /* remove current filters & unregister */ | ||
292 | if (ro->bound) { | ||
293 | if (ro->ifindex) { | ||
294 | struct net_device *dev; | ||
295 | |||
296 | dev = dev_get_by_index(&init_net, ro->ifindex); | ||
297 | if (dev) { | ||
298 | raw_disable_allfilters(dev, sk); | ||
299 | dev_put(dev); | ||
300 | } | ||
301 | } else | ||
302 | raw_disable_allfilters(NULL, sk); | ||
303 | } | ||
304 | |||
305 | if (ro->count > 1) | ||
306 | kfree(ro->filter); | ||
307 | |||
308 | ro->ifindex = 0; | ||
309 | ro->bound = 0; | ||
310 | ro->count = 0; | ||
311 | |||
312 | release_sock(sk); | ||
313 | sock_put(sk); | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static int raw_bind(struct socket *sock, struct sockaddr *uaddr, int len) | ||
319 | { | ||
320 | struct sockaddr_can *addr = (struct sockaddr_can *)uaddr; | ||
321 | struct sock *sk = sock->sk; | ||
322 | struct raw_sock *ro = raw_sk(sk); | ||
323 | int ifindex; | ||
324 | int err = 0; | ||
325 | int notify_enetdown = 0; | ||
326 | |||
327 | if (len < sizeof(*addr)) | ||
328 | return -EINVAL; | ||
329 | |||
330 | lock_sock(sk); | ||
331 | |||
332 | if (ro->bound && addr->can_ifindex == ro->ifindex) | ||
333 | goto out; | ||
334 | |||
335 | if (addr->can_ifindex) { | ||
336 | struct net_device *dev; | ||
337 | |||
338 | dev = dev_get_by_index(&init_net, addr->can_ifindex); | ||
339 | if (!dev) { | ||
340 | err = -ENODEV; | ||
341 | goto out; | ||
342 | } | ||
343 | if (dev->type != ARPHRD_CAN) { | ||
344 | dev_put(dev); | ||
345 | err = -ENODEV; | ||
346 | goto out; | ||
347 | } | ||
348 | if (!(dev->flags & IFF_UP)) | ||
349 | notify_enetdown = 1; | ||
350 | |||
351 | ifindex = dev->ifindex; | ||
352 | |||
353 | /* filters set by default/setsockopt */ | ||
354 | err = raw_enable_allfilters(dev, sk); | ||
355 | dev_put(dev); | ||
356 | |||
357 | } else { | ||
358 | ifindex = 0; | ||
359 | |||
360 | /* filters set by default/setsockopt */ | ||
361 | err = raw_enable_allfilters(NULL, sk); | ||
362 | } | ||
363 | |||
364 | if (!err) { | ||
365 | if (ro->bound) { | ||
366 | /* unregister old filters */ | ||
367 | if (ro->ifindex) { | ||
368 | struct net_device *dev; | ||
369 | |||
370 | dev = dev_get_by_index(&init_net, ro->ifindex); | ||
371 | if (dev) { | ||
372 | raw_disable_allfilters(dev, sk); | ||
373 | dev_put(dev); | ||
374 | } | ||
375 | } else | ||
376 | raw_disable_allfilters(NULL, sk); | ||
377 | } | ||
378 | ro->ifindex = ifindex; | ||
379 | ro->bound = 1; | ||
380 | } | ||
381 | |||
382 | out: | ||
383 | release_sock(sk); | ||
384 | |||
385 | if (notify_enetdown) { | ||
386 | sk->sk_err = ENETDOWN; | ||
387 | if (!sock_flag(sk, SOCK_DEAD)) | ||
388 | sk->sk_error_report(sk); | ||
389 | } | ||
390 | |||
391 | return err; | ||
392 | } | ||
393 | |||
394 | static int raw_getname(struct socket *sock, struct sockaddr *uaddr, | ||
395 | int *len, int peer) | ||
396 | { | ||
397 | struct sockaddr_can *addr = (struct sockaddr_can *)uaddr; | ||
398 | struct sock *sk = sock->sk; | ||
399 | struct raw_sock *ro = raw_sk(sk); | ||
400 | |||
401 | if (peer) | ||
402 | return -EOPNOTSUPP; | ||
403 | |||
404 | addr->can_family = AF_CAN; | ||
405 | addr->can_ifindex = ro->ifindex; | ||
406 | |||
407 | *len = sizeof(*addr); | ||
408 | |||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | static int raw_setsockopt(struct socket *sock, int level, int optname, | ||
413 | char __user *optval, int optlen) | ||
414 | { | ||
415 | struct sock *sk = sock->sk; | ||
416 | struct raw_sock *ro = raw_sk(sk); | ||
417 | struct can_filter *filter = NULL; /* dyn. alloc'ed filters */ | ||
418 | struct can_filter sfilter; /* single filter */ | ||
419 | struct net_device *dev = NULL; | ||
420 | can_err_mask_t err_mask = 0; | ||
421 | int count = 0; | ||
422 | int err = 0; | ||
423 | |||
424 | if (level != SOL_CAN_RAW) | ||
425 | return -EINVAL; | ||
426 | if (optlen < 0) | ||
427 | return -EINVAL; | ||
428 | |||
429 | switch (optname) { | ||
430 | |||
431 | case CAN_RAW_FILTER: | ||
432 | if (optlen % sizeof(struct can_filter) != 0) | ||
433 | return -EINVAL; | ||
434 | |||
435 | count = optlen / sizeof(struct can_filter); | ||
436 | |||
437 | if (count > 1) { | ||
438 | /* filter does not fit into dfilter => alloc space */ | ||
439 | filter = kmalloc(optlen, GFP_KERNEL); | ||
440 | if (!filter) | ||
441 | return -ENOMEM; | ||
442 | |||
443 | err = copy_from_user(filter, optval, optlen); | ||
444 | if (err) { | ||
445 | kfree(filter); | ||
446 | return err; | ||
447 | } | ||
448 | } else if (count == 1) { | ||
449 | err = copy_from_user(&sfilter, optval, optlen); | ||
450 | if (err) | ||
451 | return err; | ||
452 | } | ||
453 | |||
454 | lock_sock(sk); | ||
455 | |||
456 | if (ro->bound && ro->ifindex) | ||
457 | dev = dev_get_by_index(&init_net, ro->ifindex); | ||
458 | |||
459 | if (ro->bound) { | ||
460 | /* (try to) register the new filters */ | ||
461 | if (count == 1) | ||
462 | err = raw_enable_filters(dev, sk, &sfilter, 1); | ||
463 | else | ||
464 | err = raw_enable_filters(dev, sk, filter, | ||
465 | count); | ||
466 | if (err) { | ||
467 | if (count > 1) | ||
468 | kfree(filter); | ||
469 | |||
470 | goto out_fil; | ||
471 | } | ||
472 | |||
473 | /* remove old filter registrations */ | ||
474 | raw_disable_filters(dev, sk, ro->filter, ro->count); | ||
475 | } | ||
476 | |||
477 | /* remove old filter space */ | ||
478 | if (ro->count > 1) | ||
479 | kfree(ro->filter); | ||
480 | |||
481 | /* link new filters to the socket */ | ||
482 | if (count == 1) { | ||
483 | /* copy filter data for single filter */ | ||
484 | ro->dfilter = sfilter; | ||
485 | filter = &ro->dfilter; | ||
486 | } | ||
487 | ro->filter = filter; | ||
488 | ro->count = count; | ||
489 | |||
490 | out_fil: | ||
491 | if (dev) | ||
492 | dev_put(dev); | ||
493 | |||
494 | release_sock(sk); | ||
495 | |||
496 | break; | ||
497 | |||
498 | case CAN_RAW_ERR_FILTER: | ||
499 | if (optlen != sizeof(err_mask)) | ||
500 | return -EINVAL; | ||
501 | |||
502 | err = copy_from_user(&err_mask, optval, optlen); | ||
503 | if (err) | ||
504 | return err; | ||
505 | |||
506 | err_mask &= CAN_ERR_MASK; | ||
507 | |||
508 | lock_sock(sk); | ||
509 | |||
510 | if (ro->bound && ro->ifindex) | ||
511 | dev = dev_get_by_index(&init_net, ro->ifindex); | ||
512 | |||
513 | /* remove current error mask */ | ||
514 | if (ro->bound) { | ||
515 | /* (try to) register the new err_mask */ | ||
516 | err = raw_enable_errfilter(dev, sk, err_mask); | ||
517 | |||
518 | if (err) | ||
519 | goto out_err; | ||
520 | |||
521 | /* remove old err_mask registration */ | ||
522 | raw_disable_errfilter(dev, sk, ro->err_mask); | ||
523 | } | ||
524 | |||
525 | /* link new err_mask to the socket */ | ||
526 | ro->err_mask = err_mask; | ||
527 | |||
528 | out_err: | ||
529 | if (dev) | ||
530 | dev_put(dev); | ||
531 | |||
532 | release_sock(sk); | ||
533 | |||
534 | break; | ||
535 | |||
536 | case CAN_RAW_LOOPBACK: | ||
537 | if (optlen != sizeof(ro->loopback)) | ||
538 | return -EINVAL; | ||
539 | |||
540 | err = copy_from_user(&ro->loopback, optval, optlen); | ||
541 | |||
542 | break; | ||
543 | |||
544 | case CAN_RAW_RECV_OWN_MSGS: | ||
545 | if (optlen != sizeof(ro->recv_own_msgs)) | ||
546 | return -EINVAL; | ||
547 | |||
548 | err = copy_from_user(&ro->recv_own_msgs, optval, optlen); | ||
549 | |||
550 | break; | ||
551 | |||
552 | default: | ||
553 | return -ENOPROTOOPT; | ||
554 | } | ||
555 | return err; | ||
556 | } | ||
557 | |||
558 | static int raw_getsockopt(struct socket *sock, int level, int optname, | ||
559 | char __user *optval, int __user *optlen) | ||
560 | { | ||
561 | struct sock *sk = sock->sk; | ||
562 | struct raw_sock *ro = raw_sk(sk); | ||
563 | int len; | ||
564 | void *val; | ||
565 | int err = 0; | ||
566 | |||
567 | if (level != SOL_CAN_RAW) | ||
568 | return -EINVAL; | ||
569 | if (get_user(len, optlen)) | ||
570 | return -EFAULT; | ||
571 | if (len < 0) | ||
572 | return -EINVAL; | ||
573 | |||
574 | switch (optname) { | ||
575 | |||
576 | case CAN_RAW_FILTER: | ||
577 | lock_sock(sk); | ||
578 | if (ro->count > 0) { | ||
579 | int fsize = ro->count * sizeof(struct can_filter); | ||
580 | if (len > fsize) | ||
581 | len = fsize; | ||
582 | err = copy_to_user(optval, ro->filter, len); | ||
583 | } else | ||
584 | len = 0; | ||
585 | release_sock(sk); | ||
586 | |||
587 | if (!err) | ||
588 | err = put_user(len, optlen); | ||
589 | return err; | ||
590 | |||
591 | case CAN_RAW_ERR_FILTER: | ||
592 | if (len > sizeof(can_err_mask_t)) | ||
593 | len = sizeof(can_err_mask_t); | ||
594 | val = &ro->err_mask; | ||
595 | break; | ||
596 | |||
597 | case CAN_RAW_LOOPBACK: | ||
598 | if (len > sizeof(int)) | ||
599 | len = sizeof(int); | ||
600 | val = &ro->loopback; | ||
601 | break; | ||
602 | |||
603 | case CAN_RAW_RECV_OWN_MSGS: | ||
604 | if (len > sizeof(int)) | ||
605 | len = sizeof(int); | ||
606 | val = &ro->recv_own_msgs; | ||
607 | break; | ||
608 | |||
609 | default: | ||
610 | return -ENOPROTOOPT; | ||
611 | } | ||
612 | |||
613 | if (put_user(len, optlen)) | ||
614 | return -EFAULT; | ||
615 | if (copy_to_user(optval, val, len)) | ||
616 | return -EFAULT; | ||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | static int raw_sendmsg(struct kiocb *iocb, struct socket *sock, | ||
621 | struct msghdr *msg, size_t size) | ||
622 | { | ||
623 | struct sock *sk = sock->sk; | ||
624 | struct raw_sock *ro = raw_sk(sk); | ||
625 | struct sk_buff *skb; | ||
626 | struct net_device *dev; | ||
627 | int ifindex; | ||
628 | int err; | ||
629 | |||
630 | if (msg->msg_name) { | ||
631 | struct sockaddr_can *addr = | ||
632 | (struct sockaddr_can *)msg->msg_name; | ||
633 | |||
634 | if (addr->can_family != AF_CAN) | ||
635 | return -EINVAL; | ||
636 | |||
637 | ifindex = addr->can_ifindex; | ||
638 | } else | ||
639 | ifindex = ro->ifindex; | ||
640 | |||
641 | dev = dev_get_by_index(&init_net, ifindex); | ||
642 | if (!dev) | ||
643 | return -ENXIO; | ||
644 | |||
645 | skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT, | ||
646 | &err); | ||
647 | if (!skb) { | ||
648 | dev_put(dev); | ||
649 | return err; | ||
650 | } | ||
651 | |||
652 | err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); | ||
653 | if (err < 0) { | ||
654 | kfree_skb(skb); | ||
655 | dev_put(dev); | ||
656 | return err; | ||
657 | } | ||
658 | skb->dev = dev; | ||
659 | skb->sk = sk; | ||
660 | |||
661 | err = can_send(skb, ro->loopback); | ||
662 | |||
663 | dev_put(dev); | ||
664 | |||
665 | if (err) | ||
666 | return err; | ||
667 | |||
668 | return size; | ||
669 | } | ||
670 | |||
671 | static int raw_recvmsg(struct kiocb *iocb, struct socket *sock, | ||
672 | struct msghdr *msg, size_t size, int flags) | ||
673 | { | ||
674 | struct sock *sk = sock->sk; | ||
675 | struct sk_buff *skb; | ||
676 | int error = 0; | ||
677 | int noblock; | ||
678 | |||
679 | noblock = flags & MSG_DONTWAIT; | ||
680 | flags &= ~MSG_DONTWAIT; | ||
681 | |||
682 | skb = skb_recv_datagram(sk, flags, noblock, &error); | ||
683 | if (!skb) | ||
684 | return error; | ||
685 | |||
686 | if (size < skb->len) | ||
687 | msg->msg_flags |= MSG_TRUNC; | ||
688 | else | ||
689 | size = skb->len; | ||
690 | |||
691 | error = memcpy_toiovec(msg->msg_iov, skb->data, size); | ||
692 | if (error < 0) { | ||
693 | skb_free_datagram(sk, skb); | ||
694 | return error; | ||
695 | } | ||
696 | |||
697 | sock_recv_timestamp(msg, sk, skb); | ||
698 | |||
699 | if (msg->msg_name) { | ||
700 | msg->msg_namelen = sizeof(struct sockaddr_can); | ||
701 | memcpy(msg->msg_name, skb->cb, msg->msg_namelen); | ||
702 | } | ||
703 | |||
704 | skb_free_datagram(sk, skb); | ||
705 | |||
706 | return size; | ||
707 | } | ||
708 | |||
709 | static struct proto_ops raw_ops __read_mostly = { | ||
710 | .family = PF_CAN, | ||
711 | .release = raw_release, | ||
712 | .bind = raw_bind, | ||
713 | .connect = sock_no_connect, | ||
714 | .socketpair = sock_no_socketpair, | ||
715 | .accept = sock_no_accept, | ||
716 | .getname = raw_getname, | ||
717 | .poll = datagram_poll, | ||
718 | .ioctl = NULL, /* use can_ioctl() from af_can.c */ | ||
719 | .listen = sock_no_listen, | ||
720 | .shutdown = sock_no_shutdown, | ||
721 | .setsockopt = raw_setsockopt, | ||
722 | .getsockopt = raw_getsockopt, | ||
723 | .sendmsg = raw_sendmsg, | ||
724 | .recvmsg = raw_recvmsg, | ||
725 | .mmap = sock_no_mmap, | ||
726 | .sendpage = sock_no_sendpage, | ||
727 | }; | ||
728 | |||
729 | static struct proto raw_proto __read_mostly = { | ||
730 | .name = "CAN_RAW", | ||
731 | .owner = THIS_MODULE, | ||
732 | .obj_size = sizeof(struct raw_sock), | ||
733 | .init = raw_init, | ||
734 | }; | ||
735 | |||
736 | static struct can_proto raw_can_proto __read_mostly = { | ||
737 | .type = SOCK_RAW, | ||
738 | .protocol = CAN_RAW, | ||
739 | .capability = -1, | ||
740 | .ops = &raw_ops, | ||
741 | .prot = &raw_proto, | ||
742 | }; | ||
743 | |||
744 | static __init int raw_module_init(void) | ||
745 | { | ||
746 | int err; | ||
747 | |||
748 | printk(banner); | ||
749 | |||
750 | err = can_proto_register(&raw_can_proto); | ||
751 | if (err < 0) | ||
752 | printk(KERN_ERR "can: registration of raw protocol failed\n"); | ||
753 | |||
754 | return err; | ||
755 | } | ||
756 | |||
757 | static __exit void raw_module_exit(void) | ||
758 | { | ||
759 | can_proto_unregister(&raw_can_proto); | ||
760 | } | ||
761 | |||
762 | module_init(raw_module_init); | ||
763 | module_exit(raw_module_exit); | ||