089ea0ab81f4cfb0aa27f499d97d4b909cac1121
2 * Copyright (c) 1996, 1997
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 static const char rcsid
[] =
23 "@(#) $Header: /usr/local/cvs/linux/tools/build/e100boot/libpcap-0.4/pcap-linux.c,v 1.1 1999/08/26 10:05:24 johana Exp $ (LBL)";
26 #include <sys/param.h>
27 #include <sys/ioctl.h>
28 #include <sys/socket.h>
32 #ifdef HAVE_NET_IF_ARP_H
33 #include <net/if_arp.h>
35 #include <linux/if_arp.h>
37 #include <linux/if_ether.h>
39 #include <netinet/in.h>
48 static struct ifreq saved_ifr
;
49 static int read_timout_ms
= 0;
54 #ifdef HAVE_OS_PROTO_H
58 void linux_restore_ifr(void);
61 pcap_stats(pcap_t
*p
, struct pcap_stat
*ps
)
69 pcap_read(pcap_t
*p
, int cnt
, pcap_handler callback
, u_char
*user
)
81 if (read_timout_ms
== 0) {
86 tv
.tv_sec
= read_timout_ms
/1000;
87 tv
.tv_usec
= read_timout_ms
%1000;
92 bp
= p
->buffer
+ p
->offset
;
95 memset(bp
, 0, p
->md
.pad
);
102 fromlen
= sizeof(from
);
103 select(FD_SETSIZE
, &mask
, NULL
, NULL
, &tv
);
104 if (FD_ISSET(p
->fd
, &mask
) == 0) {
108 cc
= recvfrom(p
->fd
, bp
, bufsize
, 0, &from
, &fromlen
);
110 /* Don't choke when we get ptraced */
117 return (0); /* XXX */
119 sprintf(p
->errbuf
, "read: %s", pcap_strerror(errno
));
122 } while (strcmp(p
->md
.device
, from
.sa_data
));
124 /* If we need have leading zero bytes, adjust count */
126 bp
= p
->buffer
+ p
->offset
;
128 /* If we need to step over leading junk, adjust count and pointer */
132 /* Captured length can't exceed our read buffer size */
134 if (caplen
> bufsize
)
137 /* Captured length can't exceed the snapshot length */
138 if (caplen
> p
->snapshot
)
139 caplen
= p
->snapshot
;
141 if (p
->fcode
.bf_insns
== NULL
||
142 bpf_filter(p
->fcode
.bf_insns
, bp
, cc
, caplen
)) {
143 struct pcap_pkthdr h
;
145 ++p
->md
.stat
.ps_recv
;
147 if (ioctl(p
->fd
, SIOCGSTAMP
, &h
.ts
) < 0) {
148 sprintf(p
->errbuf
, "SIOCGSTAMP: %s",
149 pcap_strerror(errno
));
154 (*callback
)(user
, &h
, bp
);
161 pcap_open_live(char *device
, int snaplen
, int promisc
, int to_ms
, char *ebuf
)
163 register int fd
, broadcast
;
168 read_timout_ms
= to_ms
;
169 p
= (pcap_t
*)malloc(sizeof(*p
));
171 sprintf(ebuf
, "malloc: %s", pcap_strerror(errno
));
174 memset(p
, 0, sizeof(*p
));
177 fd
= socket(PF_INET
, SOCK_PACKET
, htons(ETH_P_ALL
));
179 sprintf(ebuf
, "socket: %s", pcap_strerror(errno
));
184 /* Bind to the interface name */
185 memset(&sa
, 0, sizeof(sa
));
186 sa
.sa_family
= AF_INET
;
187 (void)strncpy(sa
.sa_data
, device
, sizeof(sa
.sa_data
));
188 if (bind(p
->fd
, &sa
, sizeof(sa
))) {
189 sprintf(ebuf
, "bind: %s: %s", device
, pcap_strerror(errno
));
193 memset(&ifr
, 0, sizeof(ifr
));
194 strncpy(ifr
.ifr_name
, device
, sizeof(ifr
.ifr_name
));
195 if (ioctl(p
->fd
, SIOCGIFHWADDR
, &ifr
) < 0 ) {
196 sprintf(ebuf
, "SIOCGIFHWADDR: %s", pcap_strerror(errno
));
200 switch (ifr
.ifr_hwaddr
.sa_family
) {
203 case ARPHRD_METRICOM
:
204 p
->linktype
= DLT_EN10MB
;
210 p
->linktype
= DLT_EN3MB
;
215 p
->linktype
= DLT_AX25
;
220 p
->linktype
= DLT_PRONET
;
224 p
->linktype
= DLT_CHAOS
;
228 p
->linktype
= DLT_IEEE802
;
233 p
->linktype
= DLT_ARCNET
;
242 p
->linktype
= DLT_RAW
;
245 case ARPHRD_LOOPBACK
:
246 p
->linktype
= DLT_NULL
;
252 /* Not all versions of the kernel has this define */
254 p
->linktype
= DLT_FDDI
;
260 case ARPHRD_LOCALTLK
:
262 case ARPHRD_APPLETLK
:
270 /* XXX currently do not know what to do with these... */
275 sprintf(ebuf
, "unknown physical layer type 0x%x",
276 ifr
.ifr_hwaddr
.sa_family
);
280 /* Base the buffer size on the interface MTU */
281 memset(&ifr
, 0, sizeof(ifr
));
282 strncpy(ifr
.ifr_name
, device
, sizeof(ifr
.ifr_name
));
283 if (ioctl(p
->fd
, SIOCGIFMTU
, &ifr
) < 0 ) {
284 sprintf(ebuf
, "SIOCGIFMTU: %s", pcap_strerror(errno
));
288 /* Leave room for link header (which is never large under linux...) */
289 p
->bufsize
= ifr
.ifr_mtu
+ 64;
291 p
->buffer
= (u_char
*)malloc(p
->bufsize
+ p
->offset
);
292 if (p
->buffer
== NULL
) {
293 sprintf(ebuf
, "malloc: %s", pcap_strerror(errno
));
298 if (promisc
&& broadcast
) {
299 memset(&ifr
, 0, sizeof(ifr
));
300 strcpy(ifr
.ifr_name
, device
);
301 if (ioctl(p
->fd
, SIOCGIFFLAGS
, &ifr
) < 0 ) {
302 sprintf(ebuf
, "SIOCGIFFLAGS: %s", pcap_strerror(errno
));
306 ifr
.ifr_flags
|= IFF_PROMISC
;
307 if (ioctl(p
->fd
, SIOCSIFFLAGS
, &ifr
) < 0 ) {
308 sprintf(ebuf
, "SIOCSIFFLAGS: %s", pcap_strerror(errno
));
311 ifr
.ifr_flags
&= ~IFF_PROMISC
;
312 atexit(linux_restore_ifr
);
315 p
->md
.device
= strdup(device
);
316 if (p
->md
.device
== NULL
) {
317 sprintf(ebuf
, "malloc: %s", pcap_strerror(errno
));
320 p
->snapshot
= snaplen
;
326 if (p
->buffer
!= NULL
)
328 if (p
->md
.device
!= NULL
)
335 pcap_setfilter(pcap_t
*p
, struct bpf_program
*fp
)
343 linux_restore_ifr(void)
347 fd
= socket(PF_INET
, SOCK_PACKET
, htons(0x0003));
349 fprintf(stderr
, "linux socket: %s", pcap_strerror(errno
));
350 else if (ioctl(fd
, SIOCSIFFLAGS
, &saved_ifr
) < 0)
351 fprintf(stderr
, "linux SIOCSIFFLAGS: %s", pcap_strerror(errno
));
This page took 0.065504 seconds and 3 git commands to generate.