]>
The Tcpdump Group git mirrors - libpcap/blob - pcap-can-linux.c
2 * Copyright (c) 2009 Felix Obenhuber
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote
15 * products derived from this software without specific prior written
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * SocketCan sniffing API implementation for Linux platform
31 * By Felix Obenhuber <felix@obenhuber.de>
40 #include "pcap-can-linux.h"
42 #ifdef NEED_STRERROR_H
51 #include <sys/ioctl.h>
52 #include <sys/socket.h>
54 #include <arpa/inet.h>
56 #include <linux/can.h>
57 #include <linux/can/raw.h>
59 /* not yet defined anywhere */
67 /* forward declaration */
68 static int can_activate(pcap_t
*);
69 static int can_read_linux(pcap_t
*, int , pcap_handler
, u_char
*);
70 static int can_inject_linux(pcap_t
*, const void *, size_t);
71 static int can_setfilter_linux(pcap_t
*, struct bpf_program
*);
72 static int can_setdirection_linux(pcap_t
*, pcap_direction_t
);
73 static int can_stats_linux(pcap_t
*, struct pcap_stat
*);
76 can_create(const char *device
, char *ebuf
)
80 p
= pcap_create_common(device
, ebuf
);
84 p
->activate_op
= can_activate
;
90 can_activate(pcap_t
* handle
)
92 struct sockaddr_can addr
;
95 /* Initialize some components of the pcap structure. */
98 handle
->linktype
= DLT_CAN_SOCKETCAN
;
99 handle
->read_op
= can_read_linux
;
100 handle
->inject_op
= can_inject_linux
;
101 handle
->setfilter_op
= can_setfilter_linux
;
102 handle
->setdirection_op
= can_setdirection_linux
;
103 handle
->set_datalink_op
= NULL
;
104 handle
->getnonblock_op
= pcap_getnonblock_fd
;
105 handle
->setnonblock_op
= pcap_setnonblock_fd
;
106 handle
->stats_op
= can_stats_linux
;
109 handle
->fd
= socket(PF_CAN
, SOCK_RAW
, CAN_RAW
);
112 snprintf(handle
->errbuf
, PCAP_ERRBUF_SIZE
, "Can't create raw socket %d:%s",
113 errno
, strerror(errno
));
117 /* get interface index */
118 memset(&ifr
, 0, sizeof(ifr
));
119 strncpy(ifr
.ifr_name
, handle
->opt
.source
, sizeof(ifr
.ifr_name
));
120 if (ioctl(handle
->fd
, SIOCGIFINDEX
, &ifr
) < 0)
122 snprintf(handle
->errbuf
, PCAP_ERRBUF_SIZE
,
123 "Unable to get interface index: %s",
124 pcap_strerror(errno
));
125 pcap_cleanup_live_common(handle
);
128 handle
->md
.ifindex
= ifr
.ifr_ifindex
;
130 /* allocate butter */
131 handle
->buffer
= malloc(handle
->bufsize
);
134 snprintf(handle
->errbuf
, PCAP_ERRBUF_SIZE
, "Can't allocate dump buffer: %s",
135 pcap_strerror(errno
));
136 pcap_cleanup_live_common(handle
);
140 /* Bind to the socket */
141 addr
.can_family
= AF_CAN
;
142 addr
.can_ifindex
= handle
->md
.ifindex
;
143 if( bind( handle
->fd
, (struct sockaddr
*)&addr
, sizeof(addr
) ) < 0 )
145 snprintf(handle
->errbuf
, PCAP_ERRBUF_SIZE
, "Can't attach to device %d %d:%s",
146 handle
->md
.ifindex
, errno
, strerror(errno
));
147 pcap_cleanup_live_common(handle
);
151 if (handle
->opt
.rfmon
)
153 /* Monitor mode doesn't apply to CAN devices. */
154 pcap_cleanup_live_common(handle
);
158 handle
->selectable_fd
= handle
->fd
;
165 can_read_linux(pcap_t
*handle
, int max_packets
, pcap_handler callback
, u_char
*user
)
168 struct pcap_pkthdr pkth
;
170 struct can_frame
* cf
;
172 iv
.iov_base
= &handle
->buffer
[handle
->offset
];
173 iv
.iov_len
= handle
->snapshot
;
175 memset(&msg
, 0, sizeof(msg
));
178 msg
.msg_control
= handle
->buffer
;
179 msg
.msg_controllen
= handle
->offset
;
183 pkth
.caplen
= recvmsg(handle
->fd
, &msg
, 0);
184 if (handle
->break_loop
)
186 handle
->break_loop
= 0;
189 } while ((pkth
.caplen
== -1) && (errno
== EINTR
));
193 snprintf(handle
->errbuf
, PCAP_ERRBUF_SIZE
, "Can't receive packet %d:%s",
194 errno
, strerror(errno
));
198 /* adjust capture len according to frame len */
199 cf
= (struct can_frame
*)&handle
->buffer
[8];
200 pkth
.caplen
-= 8 - cf
->can_dlc
;
201 pkth
.len
= pkth
.caplen
;
203 cf
->can_id
= htonl( cf
->can_id
);
205 if( -1 == gettimeofday(&pkth
.ts
, NULL
) )
207 snprintf(handle
->errbuf
, PCAP_ERRBUF_SIZE
, "Can't get time of day %d:%s",
208 errno
, strerror(errno
));
212 callback(user
, &pkth
, &handle
->buffer
[8]);
219 can_inject_linux(pcap_t
*handle
, const void *buf
, size_t size
)
221 /* not yet implemented */
222 snprintf(handle
->errbuf
, PCAP_ERRBUF_SIZE
, "inject not supported on "
229 can_stats_linux(pcap_t
*handle
, struct pcap_stat
*stats
)
231 /* not yet implemented */
232 stats
->ps_recv
= 0; /* number of packets received */
233 stats
->ps_drop
= 0; /* number of packets dropped */
234 stats
->ps_ifdrop
= 0; /* drops by interface -- only supported on some platforms */
240 can_setfilter_linux(pcap_t
*p
, struct bpf_program
*fp
)
242 /* not yet implemented */
248 can_setdirection_linux(pcap_t
*p
, pcap_direction_t d
)
250 /* no support for PCAP_D_OUT */
253 snprintf(p
->errbuf
, sizeof(p
->errbuf
),
254 "Setting direction to PCAP_D_OUT is not supported on can");