3 /* XXX Hack not to include the Mach BPF interface */
17 #include <device/device.h>
18 #include <device/device_types.h>
19 #include <device/net_status.h>
20 #include <net/if_ether.h>
25 struct pcap_stat stat
;
28 int filtering_in_kernel
;
31 /* Accept all packets. */
32 static struct bpf_insn filter
[] = {
33 { NETF_IN
| NETF_OUT
| NETF_BPF
, 0, 0, 0 },
34 { BPF_RET
| BPF_K
, 0, 0, MAXIMUM_SNAPLEN
},
37 /* device_set_filter calls net_set_filter which uses CSPF_BYTES which counts in
38 * shorts, not elements, so using extra parenthesis to silence compilers which
39 * believe we are computing wrong here. */
40 #define FILTER_COUNT (sizeof(filter) / (sizeof(short)))
43 PCAP_WARN_UNUSED_RESULT
44 pcap_device_set_filter(pcap_t
*p
, filter_array_t filter_array
,
45 const mach_msg_type_number_t filter_count
)
48 struct pcap_hurd
*ph
= p
->priv
;
49 kr
= device_set_filter(ph
->mach_dev
, ph
->rcv_port
,
50 MACH_MSG_TYPE_MAKE_SEND
, 0,
51 filter_array
, filter_count
);
54 pcapint_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
, errno
,
60 pcap_setfilter_hurd(pcap_t
*p
, struct bpf_program
*program
)
62 if (! program
|| pcapint_install_bpf_program(p
, program
) < 0) {
63 pcapint_strlcpy(p
->errbuf
, "setfilter: invalid program",
69 * The bytecode is valid and the copy in p->fcode can be used for
70 * userland filtering if kernel filtering does not work out.
72 * The kernel BPF implementation supports neither BPF_MOD nor BPF_XOR,
73 * it also fails to reject unsupported bytecode properly, so the check
76 struct pcap_hurd
*ph
= p
->priv
;
77 for (u_int i
= 0; i
< program
->bf_len
; i
++) {
78 u_short c
= program
->bf_insns
[i
].code
;
79 if (BPF_CLASS(c
) == BPF_ALU
&&
80 (BPF_OP(c
) == BPF_MOD
|| BPF_OP(c
) == BPF_XOR
))
85 * The kernel takes an array of 16-bit Hurd network filter commands, no
86 * more than NET_MAX_FILTER elements. The first four commands form a
87 * header that says "BPF bytecode follows", the rest is a binary copy
88 * of 64-bit instructions of the required BPF bytecode.
90 mach_msg_type_number_t cmdcount
= 4 + 4 * program
->bf_len
;
91 if (cmdcount
> NET_MAX_FILTER
)
94 filter_t cmdbuffer
[NET_MAX_FILTER
];
95 memcpy(cmdbuffer
, filter
, sizeof(struct bpf_insn
));
96 memcpy(cmdbuffer
+ 4, program
->bf_insns
,
97 program
->bf_len
* sizeof(struct bpf_insn
));
98 if (pcap_device_set_filter(p
, cmdbuffer
, cmdcount
))
100 ph
->filtering_in_kernel
= 1;
105 * Could not install a new kernel filter for a reason, so replace any
106 * previous kernel filter with one that accepts all packets and lets
107 * userland filtering do the job. If that fails too, something is
108 * badly broken and even userland filtering would not work correctly,
109 * so expose the failure.
111 ph
->filtering_in_kernel
= 0;
112 return pcap_device_set_filter(p
, (filter_array_t
)filter
, FILTER_COUNT
);
116 pcap_read_hurd(pcap_t
*p
, int cnt _U_
, pcap_handler callback
, u_char
*user
)
118 struct net_rcv_msg
*msg
;
119 struct pcap_hurd
*ph
;
120 struct pcap_pkthdr h
;
127 msg
= (struct net_rcv_msg
*)p
->buffer
;
132 return PCAP_ERROR_BREAK
;
135 kr
= mach_msg(&msg
->msg_hdr
, MACH_RCV_MSG
| MACH_RCV_INTERRUPT
, 0,
136 p
->bufsize
, ph
->rcv_port
, MACH_MSG_TIMEOUT_NONE
,
138 clock_gettime(CLOCK_REALTIME
, &ts
);
141 if (kr
== MACH_RCV_INTERRUPTED
)
144 pcapint_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
, kr
,
151 /* XXX Ethernet support only */
153 * wirelen calculation assumes the following:
154 * msg->packet_type.msgt_name == MACH_MSG_TYPE_BYTE
155 * msg->packet_type.msgt_size == 8
156 * msg->packet_type.msgt_number is a size in bytes
158 wirelen
= ETH_HLEN
+ msg
->net_rcv_msg_packet_count
159 - sizeof(struct packet_header
);
160 pkt
= p
->buffer
+ offsetof(struct net_rcv_msg
, packet
)
161 + sizeof(struct packet_header
) - ETH_HLEN
;
162 memmove(pkt
, p
->buffer
+ offsetof(struct net_rcv_msg
, header
),
166 * It seems, kernel device filters treat the K in BPF_MOD as a Boolean:
167 * so long as it is positive, the Mach message will contain the entire
168 * packet and wirelen will be set accordingly. Thus the caplen value
169 * for the callback needs to be calculated for every packet no matter
170 * which type of filtering is in effect.
172 * For the userland filtering this calculated value is not an input:
173 * buflen always equals wirelen and a userland program can examine the
174 * entire packet, same way as a kernel program. It is not an output
175 * either: pcapint_filter() returns either zero or MAXIMUM_SNAPLEN.
176 * The same principle applies to kernel filtering.
178 caplen
= (wirelen
> p
->snapshot
) ? p
->snapshot
: wirelen
;
180 if (! ph
->filtering_in_kernel
&&
181 ! pcapint_filter(p
->fcode
.bf_insns
, pkt
, wirelen
, wirelen
)) {
186 h
.ts
.tv_sec
= ts
.tv_sec
;
187 h
.ts
.tv_usec
= ts
.tv_nsec
/ 1000;
190 callback(user
, &h
, pkt
);
195 pcap_inject_hurd(pcap_t
*p
, const void *buf
, int size
)
197 struct pcap_hurd
*ph
;
202 kr
= device_write(ph
->mach_dev
, D_NOWAIT
, 0,
203 (io_buf_ptr_t
)buf
, size
, &count
);
206 pcapint_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
, kr
,
215 pcap_stats_hurd(pcap_t
*p
, struct pcap_stat
*ps
)
217 struct pcap_hurd
*ph
;
225 pcap_cleanup_hurd(pcap_t
*p
)
227 struct pcap_hurd
*ph
;
231 if (ph
->rcv_port
!= MACH_PORT_NULL
) {
232 mach_port_deallocate(mach_task_self(), ph
->rcv_port
);
233 ph
->rcv_port
= MACH_PORT_NULL
;
236 if (ph
->mach_dev
!= MACH_PORT_NULL
) {
237 device_close(ph
->mach_dev
);
238 ph
->mach_dev
= MACH_PORT_NULL
;
241 pcapint_cleanup_live_common(p
);
245 pcap_activate_hurd(pcap_t
*p
)
247 struct pcap_hurd
*ph
;
250 int ret
= PCAP_ERROR
;
254 if (p
->snapshot
<= 0 || p
->snapshot
> MAXIMUM_SNAPLEN
)
255 p
->snapshot
= MAXIMUM_SNAPLEN
;
257 /* Try devnode first */
258 master
= file_name_lookup(p
->opt
.device
, O_READ
| O_WRITE
, 0);
260 if (master
!= MACH_PORT_NULL
)
261 kr
= device_open(master
, D_WRITE
| D_READ
, "eth", &ph
->mach_dev
);
263 /* If unsuccessful, try Mach device */
264 kr
= get_privileged_ports(NULL
, &master
);
267 pcapint_fmt_errmsg_for_errno(p
->errbuf
,
268 PCAP_ERRBUF_SIZE
, kr
, "get_privileged_ports");
270 ret
= PCAP_ERROR_PERM_DENIED
;
274 kr
= device_open(master
, D_READ
| D_WRITE
, p
->opt
.device
,
278 mach_port_deallocate(mach_task_self(), master
);
281 pcapint_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
, kr
,
283 if (kr
== ED_NO_SUCH_DEVICE
) /* not ENODEV */
284 ret
= PCAP_ERROR_NO_SUCH_DEVICE
;
288 kr
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
,
292 pcapint_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
, kr
,
293 "mach_port_allocate");
297 p
->bufsize
= sizeof(struct net_rcv_msg
);
298 p
->buffer
= malloc(p
->bufsize
);
300 if (p
->buffer
== NULL
) {
301 pcapint_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
307 * XXX Ethernet only currently
309 * XXX - does "Ethernet only currently" mean "the only devices
310 * on which the Hurd supports packet capture are Ethernet
311 * devices", or "it supports other devices but makes them
312 * all provide Ethernet headers"?
314 * If the latter, is there a way to determine whether the
315 * device is a real Ethernet, so that we could offer DLT_DOCSIS,
316 * in case you're capturing DOCSIS traffic that a Cisco Cable
317 * Modem Termination System is putting out onto an Ethernet
318 * (it doesn't put an Ethernet header onto the wire, it puts
319 * raw DOCSIS frames out on the wire inside the low-level
322 p
->linktype
= DLT_EN10MB
;
324 p
->read_op
= pcap_read_hurd
;
325 p
->inject_op
= pcap_inject_hurd
;
326 p
->setfilter_op
= pcap_setfilter_hurd
;
327 p
->stats_op
= pcap_stats_hurd
;
332 pcap_cleanup_hurd(p
);
337 pcapint_create_interface(const char *device _U_
, char *ebuf
)
339 struct pcap_hurd
*ph
;
342 p
= PCAP_CREATE_COMMON(ebuf
, struct pcap_hurd
);
347 ph
->mach_dev
= MACH_PORT_NULL
;
348 ph
->rcv_port
= MACH_PORT_NULL
;
349 p
->activate_op
= pcap_activate_hurd
;
354 can_be_bound(const char *name
)
357 * On Hurd lo appears in the list of interfaces, but the call to
358 * device_open() fails with: "(os/device) no such device".
360 if (! strcmp(name
, "lo"))
366 get_if_flags(const char *name _U_
, bpf_u_int32
*flags
, char *errbuf _U_
)
369 * This would apply to the loopback interface if it worked. Ethernet
370 * interfaces appear up and running regardless of the link status.
372 *flags
|= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE
;
377 pcapint_platform_finddevs(pcap_if_list_t
*devlistp
, char *errbuf
)
379 return pcapint_findalldevs_interfaces(devlistp
, errbuf
, can_be_bound
,
384 * Libpcap version string.
387 pcap_lib_version(void)
389 return PCAP_VERSION_STRING
;