1*d56f51eaSDavid van Moolenbroek /* $NetBSD: pcap-can-linux.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */
2*d56f51eaSDavid van Moolenbroek
3*d56f51eaSDavid van Moolenbroek /*
4*d56f51eaSDavid van Moolenbroek * Copyright (c) 2009 Felix Obenhuber
5*d56f51eaSDavid van Moolenbroek * All rights reserved.
6*d56f51eaSDavid van Moolenbroek *
7*d56f51eaSDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
8*d56f51eaSDavid van Moolenbroek * modification, are permitted provided that the following conditions
9*d56f51eaSDavid van Moolenbroek * are met:
10*d56f51eaSDavid van Moolenbroek *
11*d56f51eaSDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
12*d56f51eaSDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
13*d56f51eaSDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright
14*d56f51eaSDavid van Moolenbroek * notice, this list of conditions and the following disclaimer in the
15*d56f51eaSDavid van Moolenbroek * documentation and/or other materials provided with the distribution.
16*d56f51eaSDavid van Moolenbroek * 3. The name of the author may not be used to endorse or promote
17*d56f51eaSDavid van Moolenbroek * products derived from this software without specific prior written
18*d56f51eaSDavid van Moolenbroek * permission.
19*d56f51eaSDavid van Moolenbroek *
20*d56f51eaSDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21*d56f51eaSDavid van Moolenbroek * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*d56f51eaSDavid van Moolenbroek * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23*d56f51eaSDavid van Moolenbroek * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24*d56f51eaSDavid van Moolenbroek * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25*d56f51eaSDavid van Moolenbroek * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26*d56f51eaSDavid van Moolenbroek * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27*d56f51eaSDavid van Moolenbroek * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28*d56f51eaSDavid van Moolenbroek * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29*d56f51eaSDavid van Moolenbroek * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30*d56f51eaSDavid van Moolenbroek * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*d56f51eaSDavid van Moolenbroek *
32*d56f51eaSDavid van Moolenbroek * SocketCan sniffing API implementation for Linux platform
33*d56f51eaSDavid van Moolenbroek * By Felix Obenhuber <felix@obenhuber.de>
34*d56f51eaSDavid van Moolenbroek *
35*d56f51eaSDavid van Moolenbroek */
36*d56f51eaSDavid van Moolenbroek
37*d56f51eaSDavid van Moolenbroek #include <sys/cdefs.h>
38*d56f51eaSDavid van Moolenbroek __RCSID("$NetBSD: pcap-can-linux.c,v 1.3 2015/03/31 21:39:42 christos Exp $");
39*d56f51eaSDavid van Moolenbroek
40*d56f51eaSDavid van Moolenbroek #ifdef HAVE_CONFIG_H
41*d56f51eaSDavid van Moolenbroek #include "config.h"
42*d56f51eaSDavid van Moolenbroek #endif
43*d56f51eaSDavid van Moolenbroek
44*d56f51eaSDavid van Moolenbroek #include "pcap-int.h"
45*d56f51eaSDavid van Moolenbroek #include "pcap-can-linux.h"
46*d56f51eaSDavid van Moolenbroek
47*d56f51eaSDavid van Moolenbroek #ifdef NEED_STRERROR_H
48*d56f51eaSDavid van Moolenbroek #include "strerror.h"
49*d56f51eaSDavid van Moolenbroek #endif
50*d56f51eaSDavid van Moolenbroek
51*d56f51eaSDavid van Moolenbroek #include <errno.h>
52*d56f51eaSDavid van Moolenbroek #include <stdlib.h>
53*d56f51eaSDavid van Moolenbroek #include <unistd.h>
54*d56f51eaSDavid van Moolenbroek #include <fcntl.h>
55*d56f51eaSDavid van Moolenbroek #include <string.h>
56*d56f51eaSDavid van Moolenbroek #include <sys/ioctl.h>
57*d56f51eaSDavid van Moolenbroek #include <sys/socket.h>
58*d56f51eaSDavid van Moolenbroek #include <net/if.h>
59*d56f51eaSDavid van Moolenbroek #include <arpa/inet.h>
60*d56f51eaSDavid van Moolenbroek
61*d56f51eaSDavid van Moolenbroek #include <linux/can.h>
62*d56f51eaSDavid van Moolenbroek #include <linux/can/raw.h>
63*d56f51eaSDavid van Moolenbroek
64*d56f51eaSDavid van Moolenbroek /* not yet defined anywhere */
65*d56f51eaSDavid van Moolenbroek #ifndef PF_CAN
66*d56f51eaSDavid van Moolenbroek #define PF_CAN 29
67*d56f51eaSDavid van Moolenbroek #endif
68*d56f51eaSDavid van Moolenbroek #ifndef AF_CAN
69*d56f51eaSDavid van Moolenbroek #define AF_CAN PF_CAN
70*d56f51eaSDavid van Moolenbroek #endif
71*d56f51eaSDavid van Moolenbroek
72*d56f51eaSDavid van Moolenbroek /* forward declaration */
73*d56f51eaSDavid van Moolenbroek static int can_activate(pcap_t *);
74*d56f51eaSDavid van Moolenbroek static int can_read_linux(pcap_t *, int , pcap_handler , u_char *);
75*d56f51eaSDavid van Moolenbroek static int can_inject_linux(pcap_t *, const void *, size_t);
76*d56f51eaSDavid van Moolenbroek static int can_setfilter_linux(pcap_t *, struct bpf_program *);
77*d56f51eaSDavid van Moolenbroek static int can_setdirection_linux(pcap_t *, pcap_direction_t);
78*d56f51eaSDavid van Moolenbroek static int can_stats_linux(pcap_t *, struct pcap_stat *);
79*d56f51eaSDavid van Moolenbroek
80*d56f51eaSDavid van Moolenbroek /*
81*d56f51eaSDavid van Moolenbroek * Private data for capturing on Linux CANbus devices.
82*d56f51eaSDavid van Moolenbroek */
83*d56f51eaSDavid van Moolenbroek struct pcap_can {
84*d56f51eaSDavid van Moolenbroek int ifindex; /* interface index of device we're bound to */
85*d56f51eaSDavid van Moolenbroek };
86*d56f51eaSDavid van Moolenbroek
87*d56f51eaSDavid van Moolenbroek int
can_findalldevs(pcap_if_t ** devlistp,char * errbuf)88*d56f51eaSDavid van Moolenbroek can_findalldevs(pcap_if_t **devlistp, char *errbuf)
89*d56f51eaSDavid van Moolenbroek {
90*d56f51eaSDavid van Moolenbroek /*
91*d56f51eaSDavid van Moolenbroek * There are no platform-specific devices since each device
92*d56f51eaSDavid van Moolenbroek * exists as a regular network interface.
93*d56f51eaSDavid van Moolenbroek *
94*d56f51eaSDavid van Moolenbroek * XXX - true?
95*d56f51eaSDavid van Moolenbroek */
96*d56f51eaSDavid van Moolenbroek return 0;
97*d56f51eaSDavid van Moolenbroek }
98*d56f51eaSDavid van Moolenbroek
99*d56f51eaSDavid van Moolenbroek pcap_t *
can_create(const char * device,char * ebuf,int * is_ours)100*d56f51eaSDavid van Moolenbroek can_create(const char *device, char *ebuf, int *is_ours)
101*d56f51eaSDavid van Moolenbroek {
102*d56f51eaSDavid van Moolenbroek const char *cp;
103*d56f51eaSDavid van Moolenbroek char *cpend;
104*d56f51eaSDavid van Moolenbroek long devnum;
105*d56f51eaSDavid van Moolenbroek pcap_t* p;
106*d56f51eaSDavid van Moolenbroek
107*d56f51eaSDavid van Moolenbroek /* Does this look like a CANbus device? */
108*d56f51eaSDavid van Moolenbroek cp = strrchr(device, '/');
109*d56f51eaSDavid van Moolenbroek if (cp == NULL)
110*d56f51eaSDavid van Moolenbroek cp = device;
111*d56f51eaSDavid van Moolenbroek /* Does it begin with "can" or "vcan"? */
112*d56f51eaSDavid van Moolenbroek if (strncmp(cp, "can", 3) == 0) {
113*d56f51eaSDavid van Moolenbroek /* Begins with "can" */
114*d56f51eaSDavid van Moolenbroek cp += 3; /* skip past "can" */
115*d56f51eaSDavid van Moolenbroek } else if (strncmp(cp, "vcan", 4) == 0) {
116*d56f51eaSDavid van Moolenbroek /* Begins with "vcan" */
117*d56f51eaSDavid van Moolenbroek cp += 4;
118*d56f51eaSDavid van Moolenbroek } else {
119*d56f51eaSDavid van Moolenbroek /* Nope, doesn't begin with "can" or "vcan" */
120*d56f51eaSDavid van Moolenbroek *is_ours = 0;
121*d56f51eaSDavid van Moolenbroek return NULL;
122*d56f51eaSDavid van Moolenbroek }
123*d56f51eaSDavid van Moolenbroek /* Yes - is "can" or "vcan" followed by a number from 0? */
124*d56f51eaSDavid van Moolenbroek devnum = strtol(cp, &cpend, 10);
125*d56f51eaSDavid van Moolenbroek if (cpend == cp || *cpend != '\0') {
126*d56f51eaSDavid van Moolenbroek /* Not followed by a number. */
127*d56f51eaSDavid van Moolenbroek *is_ours = 0;
128*d56f51eaSDavid van Moolenbroek return NULL;
129*d56f51eaSDavid van Moolenbroek }
130*d56f51eaSDavid van Moolenbroek if (devnum < 0) {
131*d56f51eaSDavid van Moolenbroek /* Followed by a non-valid number. */
132*d56f51eaSDavid van Moolenbroek *is_ours = 0;
133*d56f51eaSDavid van Moolenbroek return NULL;
134*d56f51eaSDavid van Moolenbroek }
135*d56f51eaSDavid van Moolenbroek
136*d56f51eaSDavid van Moolenbroek /* OK, it's probably ours. */
137*d56f51eaSDavid van Moolenbroek *is_ours = 1;
138*d56f51eaSDavid van Moolenbroek
139*d56f51eaSDavid van Moolenbroek p = pcap_create_common(device, ebuf, sizeof (struct pcap_can));
140*d56f51eaSDavid van Moolenbroek if (p == NULL)
141*d56f51eaSDavid van Moolenbroek return (NULL);
142*d56f51eaSDavid van Moolenbroek
143*d56f51eaSDavid van Moolenbroek p->activate_op = can_activate;
144*d56f51eaSDavid van Moolenbroek return (p);
145*d56f51eaSDavid van Moolenbroek }
146*d56f51eaSDavid van Moolenbroek
147*d56f51eaSDavid van Moolenbroek
148*d56f51eaSDavid van Moolenbroek static int
can_activate(pcap_t * handle)149*d56f51eaSDavid van Moolenbroek can_activate(pcap_t* handle)
150*d56f51eaSDavid van Moolenbroek {
151*d56f51eaSDavid van Moolenbroek struct pcap_can *handlep = handle->priv;
152*d56f51eaSDavid van Moolenbroek struct sockaddr_can addr;
153*d56f51eaSDavid van Moolenbroek struct ifreq ifr;
154*d56f51eaSDavid van Moolenbroek
155*d56f51eaSDavid van Moolenbroek /* Initialize some components of the pcap structure. */
156*d56f51eaSDavid van Moolenbroek handle->bufsize = 24;
157*d56f51eaSDavid van Moolenbroek handle->offset = 8;
158*d56f51eaSDavid van Moolenbroek handle->linktype = DLT_CAN_SOCKETCAN;
159*d56f51eaSDavid van Moolenbroek handle->read_op = can_read_linux;
160*d56f51eaSDavid van Moolenbroek handle->inject_op = can_inject_linux;
161*d56f51eaSDavid van Moolenbroek handle->setfilter_op = can_setfilter_linux;
162*d56f51eaSDavid van Moolenbroek handle->setdirection_op = can_setdirection_linux;
163*d56f51eaSDavid van Moolenbroek handle->set_datalink_op = NULL;
164*d56f51eaSDavid van Moolenbroek handle->getnonblock_op = pcap_getnonblock_fd;
165*d56f51eaSDavid van Moolenbroek handle->setnonblock_op = pcap_setnonblock_fd;
166*d56f51eaSDavid van Moolenbroek handle->stats_op = can_stats_linux;
167*d56f51eaSDavid van Moolenbroek
168*d56f51eaSDavid van Moolenbroek /* Create socket */
169*d56f51eaSDavid van Moolenbroek handle->fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
170*d56f51eaSDavid van Moolenbroek if (handle->fd < 0)
171*d56f51eaSDavid van Moolenbroek {
172*d56f51eaSDavid van Moolenbroek snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't create raw socket %d:%s",
173*d56f51eaSDavid van Moolenbroek errno, strerror(errno));
174*d56f51eaSDavid van Moolenbroek return PCAP_ERROR;
175*d56f51eaSDavid van Moolenbroek }
176*d56f51eaSDavid van Moolenbroek
177*d56f51eaSDavid van Moolenbroek /* get interface index */
178*d56f51eaSDavid van Moolenbroek memset(&ifr, 0, sizeof(ifr));
179*d56f51eaSDavid van Moolenbroek strlcpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name));
180*d56f51eaSDavid van Moolenbroek if (ioctl(handle->fd, SIOCGIFINDEX, &ifr) < 0)
181*d56f51eaSDavid van Moolenbroek {
182*d56f51eaSDavid van Moolenbroek snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
183*d56f51eaSDavid van Moolenbroek "Unable to get interface index: %s",
184*d56f51eaSDavid van Moolenbroek pcap_strerror(errno));
185*d56f51eaSDavid van Moolenbroek pcap_cleanup_live_common(handle);
186*d56f51eaSDavid van Moolenbroek return PCAP_ERROR;
187*d56f51eaSDavid van Moolenbroek }
188*d56f51eaSDavid van Moolenbroek handlep->ifindex = ifr.ifr_ifindex;
189*d56f51eaSDavid van Moolenbroek
190*d56f51eaSDavid van Moolenbroek /* allocate butter */
191*d56f51eaSDavid van Moolenbroek handle->buffer = malloc(handle->bufsize);
192*d56f51eaSDavid van Moolenbroek if (!handle->buffer)
193*d56f51eaSDavid van Moolenbroek {
194*d56f51eaSDavid van Moolenbroek snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s",
195*d56f51eaSDavid van Moolenbroek pcap_strerror(errno));
196*d56f51eaSDavid van Moolenbroek pcap_cleanup_live_common(handle);
197*d56f51eaSDavid van Moolenbroek return PCAP_ERROR;
198*d56f51eaSDavid van Moolenbroek }
199*d56f51eaSDavid van Moolenbroek
200*d56f51eaSDavid van Moolenbroek /* Bind to the socket */
201*d56f51eaSDavid van Moolenbroek addr.can_family = AF_CAN;
202*d56f51eaSDavid van Moolenbroek addr.can_ifindex = handlep->ifindex;
203*d56f51eaSDavid van Moolenbroek if( bind( handle->fd, (struct sockaddr*)&addr, sizeof(addr) ) < 0 )
204*d56f51eaSDavid van Moolenbroek {
205*d56f51eaSDavid van Moolenbroek snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't attach to device %d %d:%s",
206*d56f51eaSDavid van Moolenbroek handlep->ifindex, errno, strerror(errno));
207*d56f51eaSDavid van Moolenbroek pcap_cleanup_live_common(handle);
208*d56f51eaSDavid van Moolenbroek return PCAP_ERROR;
209*d56f51eaSDavid van Moolenbroek }
210*d56f51eaSDavid van Moolenbroek
211*d56f51eaSDavid van Moolenbroek if (handle->opt.rfmon)
212*d56f51eaSDavid van Moolenbroek {
213*d56f51eaSDavid van Moolenbroek /* Monitor mode doesn't apply to CAN devices. */
214*d56f51eaSDavid van Moolenbroek pcap_cleanup_live_common(handle);
215*d56f51eaSDavid van Moolenbroek return PCAP_ERROR_RFMON_NOTSUP;
216*d56f51eaSDavid van Moolenbroek }
217*d56f51eaSDavid van Moolenbroek
218*d56f51eaSDavid van Moolenbroek handle->selectable_fd = handle->fd;
219*d56f51eaSDavid van Moolenbroek return 0;
220*d56f51eaSDavid van Moolenbroek
221*d56f51eaSDavid van Moolenbroek }
222*d56f51eaSDavid van Moolenbroek
223*d56f51eaSDavid van Moolenbroek
224*d56f51eaSDavid van Moolenbroek static int
can_read_linux(pcap_t * handle,int max_packets,pcap_handler callback,u_char * user)225*d56f51eaSDavid van Moolenbroek can_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
226*d56f51eaSDavid van Moolenbroek {
227*d56f51eaSDavid van Moolenbroek struct msghdr msg;
228*d56f51eaSDavid van Moolenbroek struct pcap_pkthdr pkth;
229*d56f51eaSDavid van Moolenbroek struct iovec iv;
230*d56f51eaSDavid van Moolenbroek struct can_frame* cf;
231*d56f51eaSDavid van Moolenbroek
232*d56f51eaSDavid van Moolenbroek iv.iov_base = &handle->buffer[handle->offset];
233*d56f51eaSDavid van Moolenbroek iv.iov_len = handle->snapshot;
234*d56f51eaSDavid van Moolenbroek
235*d56f51eaSDavid van Moolenbroek memset(&msg, 0, sizeof(msg));
236*d56f51eaSDavid van Moolenbroek msg.msg_iov = &iv;
237*d56f51eaSDavid van Moolenbroek msg.msg_iovlen = 1;
238*d56f51eaSDavid van Moolenbroek msg.msg_control = handle->buffer;
239*d56f51eaSDavid van Moolenbroek msg.msg_controllen = handle->offset;
240*d56f51eaSDavid van Moolenbroek
241*d56f51eaSDavid van Moolenbroek do
242*d56f51eaSDavid van Moolenbroek {
243*d56f51eaSDavid van Moolenbroek pkth.caplen = recvmsg(handle->fd, &msg, 0);
244*d56f51eaSDavid van Moolenbroek if (handle->break_loop)
245*d56f51eaSDavid van Moolenbroek {
246*d56f51eaSDavid van Moolenbroek handle->break_loop = 0;
247*d56f51eaSDavid van Moolenbroek return -2;
248*d56f51eaSDavid van Moolenbroek }
249*d56f51eaSDavid van Moolenbroek } while ((pkth.caplen == -1) && (errno == EINTR));
250*d56f51eaSDavid van Moolenbroek
251*d56f51eaSDavid van Moolenbroek if (pkth.caplen == -1)
252*d56f51eaSDavid van Moolenbroek {
253*d56f51eaSDavid van Moolenbroek snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't receive packet %d:%s",
254*d56f51eaSDavid van Moolenbroek errno, strerror(errno));
255*d56f51eaSDavid van Moolenbroek return -1;
256*d56f51eaSDavid van Moolenbroek }
257*d56f51eaSDavid van Moolenbroek
258*d56f51eaSDavid van Moolenbroek /* adjust capture len according to frame len */
259*d56f51eaSDavid van Moolenbroek cf = (struct can_frame*)&handle->buffer[8];
260*d56f51eaSDavid van Moolenbroek pkth.caplen -= 8 - cf->can_dlc;
261*d56f51eaSDavid van Moolenbroek pkth.len = pkth.caplen;
262*d56f51eaSDavid van Moolenbroek
263*d56f51eaSDavid van Moolenbroek cf->can_id = htonl( cf->can_id );
264*d56f51eaSDavid van Moolenbroek
265*d56f51eaSDavid van Moolenbroek if( -1 == gettimeofday(&pkth.ts, NULL) )
266*d56f51eaSDavid van Moolenbroek {
267*d56f51eaSDavid van Moolenbroek snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get time of day %d:%s",
268*d56f51eaSDavid van Moolenbroek errno, strerror(errno));
269*d56f51eaSDavid van Moolenbroek return -1;
270*d56f51eaSDavid van Moolenbroek }
271*d56f51eaSDavid van Moolenbroek
272*d56f51eaSDavid van Moolenbroek callback(user, &pkth, &handle->buffer[8]);
273*d56f51eaSDavid van Moolenbroek
274*d56f51eaSDavid van Moolenbroek return 1;
275*d56f51eaSDavid van Moolenbroek }
276*d56f51eaSDavid van Moolenbroek
277*d56f51eaSDavid van Moolenbroek
278*d56f51eaSDavid van Moolenbroek static int
can_inject_linux(pcap_t * handle,const void * buf,size_t size)279*d56f51eaSDavid van Moolenbroek can_inject_linux(pcap_t *handle, const void *buf, size_t size)
280*d56f51eaSDavid van Moolenbroek {
281*d56f51eaSDavid van Moolenbroek /* not yet implemented */
282*d56f51eaSDavid van Moolenbroek snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
283*d56f51eaSDavid van Moolenbroek "can devices");
284*d56f51eaSDavid van Moolenbroek return (-1);
285*d56f51eaSDavid van Moolenbroek }
286*d56f51eaSDavid van Moolenbroek
287*d56f51eaSDavid van Moolenbroek
288*d56f51eaSDavid van Moolenbroek static int
can_stats_linux(pcap_t * handle,struct pcap_stat * stats)289*d56f51eaSDavid van Moolenbroek can_stats_linux(pcap_t *handle, struct pcap_stat *stats)
290*d56f51eaSDavid van Moolenbroek {
291*d56f51eaSDavid van Moolenbroek /* not yet implemented */
292*d56f51eaSDavid van Moolenbroek stats->ps_recv = 0; /* number of packets received */
293*d56f51eaSDavid van Moolenbroek stats->ps_drop = 0; /* number of packets dropped */
294*d56f51eaSDavid van Moolenbroek stats->ps_ifdrop = 0; /* drops by interface -- only supported on some platforms */
295*d56f51eaSDavid van Moolenbroek return 0;
296*d56f51eaSDavid van Moolenbroek }
297*d56f51eaSDavid van Moolenbroek
298*d56f51eaSDavid van Moolenbroek
299*d56f51eaSDavid van Moolenbroek static int
can_setfilter_linux(pcap_t * p,struct bpf_program * fp)300*d56f51eaSDavid van Moolenbroek can_setfilter_linux(pcap_t *p, struct bpf_program *fp)
301*d56f51eaSDavid van Moolenbroek {
302*d56f51eaSDavid van Moolenbroek /* not yet implemented */
303*d56f51eaSDavid van Moolenbroek return 0;
304*d56f51eaSDavid van Moolenbroek }
305*d56f51eaSDavid van Moolenbroek
306*d56f51eaSDavid van Moolenbroek
307*d56f51eaSDavid van Moolenbroek static int
can_setdirection_linux(pcap_t * p,pcap_direction_t d)308*d56f51eaSDavid van Moolenbroek can_setdirection_linux(pcap_t *p, pcap_direction_t d)
309*d56f51eaSDavid van Moolenbroek {
310*d56f51eaSDavid van Moolenbroek /* no support for PCAP_D_OUT */
311*d56f51eaSDavid van Moolenbroek if (d == PCAP_D_OUT)
312*d56f51eaSDavid van Moolenbroek {
313*d56f51eaSDavid van Moolenbroek snprintf(p->errbuf, sizeof(p->errbuf),
314*d56f51eaSDavid van Moolenbroek "Setting direction to PCAP_D_OUT is not supported on can");
315*d56f51eaSDavid van Moolenbroek return -1;
316*d56f51eaSDavid van Moolenbroek }
317*d56f51eaSDavid van Moolenbroek
318*d56f51eaSDavid van Moolenbroek p->direction = d;
319*d56f51eaSDavid van Moolenbroek
320*d56f51eaSDavid van Moolenbroek return 0;
321*d56f51eaSDavid van Moolenbroek }
322*d56f51eaSDavid van Moolenbroek
323*d56f51eaSDavid van Moolenbroek
324*d56f51eaSDavid van Moolenbroek /* eof */
325