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 * strerror() on GNU/Hurd maps Mach error messages to strings,
44 * so we can use pcapint_fmt_errmsg_for_errno() to format
47 #define pcapint_fmt_errmsg_for_kern_return_t pcapint_fmt_errmsg_for_errno
50 PCAP_WARN_UNUSED_RESULT
51 pcap_device_set_filter(pcap_t
*p
, filter_array_t filter_array
,
52 const mach_msg_type_number_t filter_count
)
55 struct pcap_hurd
*ph
= p
->priv
;
56 kr
= device_set_filter(ph
->mach_dev
, ph
->rcv_port
,
57 MACH_MSG_TYPE_MAKE_SEND
, 0,
58 filter_array
, filter_count
);
61 pcapint_fmt_errmsg_for_kern_return_t(p
->errbuf
, PCAP_ERRBUF_SIZE
, kr
,
67 pcap_setfilter_hurd(pcap_t
*p
, struct bpf_program
*program
)
69 if (! program
|| pcapint_install_bpf_program(p
, program
) < 0) {
70 pcapint_strlcpy(p
->errbuf
, "setfilter: invalid program",
76 * The bytecode is valid and the copy in p->fcode can be used for
77 * userland filtering if kernel filtering does not work out.
79 * The kernel BPF implementation supports neither BPF_MOD nor BPF_XOR,
80 * it also fails to reject unsupported bytecode properly, so the check
83 struct pcap_hurd
*ph
= p
->priv
;
84 for (u_int i
= 0; i
< program
->bf_len
; i
++) {
85 u_short c
= program
->bf_insns
[i
].code
;
86 if (BPF_CLASS(c
) == BPF_ALU
&&
87 (BPF_OP(c
) == BPF_MOD
|| BPF_OP(c
) == BPF_XOR
))
92 * The kernel takes an array of 16-bit Hurd network filter commands, no
93 * more than NET_MAX_FILTER elements. The first four commands form a
94 * header that says "BPF bytecode follows", the rest is a binary copy
95 * of 64-bit instructions of the required BPF bytecode.
97 mach_msg_type_number_t cmdcount
= 4 + 4 * program
->bf_len
;
98 if (cmdcount
> NET_MAX_FILTER
)
101 filter_t cmdbuffer
[NET_MAX_FILTER
];
102 memcpy(cmdbuffer
, filter
, sizeof(struct bpf_insn
));
103 memcpy(cmdbuffer
+ 4, program
->bf_insns
,
104 program
->bf_len
* sizeof(struct bpf_insn
));
105 if (pcap_device_set_filter(p
, cmdbuffer
, cmdcount
))
107 ph
->filtering_in_kernel
= 1;
112 * Could not install a new kernel filter for a reason, so replace any
113 * previous kernel filter with one that accepts all packets and lets
114 * userland filtering do the job. If that fails too, something is
115 * badly broken and even userland filtering would not work correctly,
116 * so expose the failure.
118 ph
->filtering_in_kernel
= 0;
119 return pcap_device_set_filter(p
, (filter_array_t
)filter
, FILTER_COUNT
);
123 pcap_read_hurd(pcap_t
*p
, int cnt _U_
, pcap_handler callback
, u_char
*user
)
125 struct net_rcv_msg
*msg
;
126 struct pcap_hurd
*ph
;
127 struct pcap_pkthdr h
;
134 msg
= (struct net_rcv_msg
*)p
->buffer
;
139 return PCAP_ERROR_BREAK
;
142 kr
= mach_msg(&msg
->msg_hdr
, MACH_RCV_MSG
| MACH_RCV_INTERRUPT
, 0,
143 p
->bufsize
, ph
->rcv_port
, MACH_MSG_TIMEOUT_NONE
,
145 clock_gettime(CLOCK_REALTIME
, &ts
);
148 if (kr
== MACH_RCV_INTERRUPTED
)
151 pcapint_fmt_errmsg_for_kern_return_t(p
->errbuf
, PCAP_ERRBUF_SIZE
, kr
,
158 /* XXX Ethernet support only */
160 * wirelen calculation assumes the following:
161 * msg->packet_type.msgt_name == MACH_MSG_TYPE_BYTE
162 * msg->packet_type.msgt_size == 8
163 * msg->packet_type.msgt_number is a size in bytes
165 wirelen
= ETH_HLEN
+ msg
->net_rcv_msg_packet_count
166 - sizeof(struct packet_header
);
167 pkt
= p
->buffer
+ offsetof(struct net_rcv_msg
, packet
)
168 + sizeof(struct packet_header
) - ETH_HLEN
;
169 memmove(pkt
, p
->buffer
+ offsetof(struct net_rcv_msg
, header
),
173 * It seems, kernel device filters treat the K in BPF_RET as a Boolean:
174 * so long as it is positive, the Mach message will contain the entire
175 * packet and wirelen will be set accordingly. Thus the caplen value
176 * for the callback needs to be calculated for every packet no matter
177 * which type of filtering is in effect.
179 * For the userland filtering this calculated value is not an input:
180 * buflen always equals wirelen and a userland program can examine the
181 * entire packet, same way as a kernel program. It is not an output
182 * either: pcapint_filter() returns either zero or MAXIMUM_SNAPLEN.
183 * The same principle applies to kernel filtering.
185 caplen
= (wirelen
> p
->snapshot
) ? p
->snapshot
: wirelen
;
187 if (! ph
->filtering_in_kernel
&&
188 ! pcapint_filter(p
->fcode
.bf_insns
, pkt
, wirelen
, wirelen
)) {
193 h
.ts
.tv_sec
= ts
.tv_sec
;
194 h
.ts
.tv_usec
= ts
.tv_nsec
/ 1000;
197 callback(user
, &h
, pkt
);
202 pcap_inject_hurd(pcap_t
*p
, const void *buf
, int size
)
204 struct pcap_hurd
*ph
;
209 kr
= device_write(ph
->mach_dev
, D_NOWAIT
, 0,
210 (io_buf_ptr_t
)buf
, size
, &count
);
213 pcapint_fmt_errmsg_for_kern_return_t(p
->errbuf
, PCAP_ERRBUF_SIZE
, kr
,
222 pcap_stats_hurd(pcap_t
*p
, struct pcap_stat
*ps
)
224 struct pcap_hurd
*ph
;
232 pcap_cleanup_hurd(pcap_t
*p
)
234 struct pcap_hurd
*ph
;
238 if (ph
->rcv_port
!= MACH_PORT_NULL
) {
239 mach_port_deallocate(mach_task_self(), ph
->rcv_port
);
240 ph
->rcv_port
= MACH_PORT_NULL
;
243 if (ph
->mach_dev
!= MACH_PORT_NULL
) {
244 device_close(ph
->mach_dev
);
245 ph
->mach_dev
= MACH_PORT_NULL
;
248 pcapint_cleanup_live_common(p
);
252 pcap_activate_hurd(pcap_t
*p
)
254 struct pcap_hurd
*ph
;
257 int ret
= PCAP_ERROR
;
261 if (p
->snapshot
<= 0 || p
->snapshot
> MAXIMUM_SNAPLEN
)
262 p
->snapshot
= MAXIMUM_SNAPLEN
;
264 /* Try devnode first */
265 master
= file_name_lookup(p
->opt
.device
, O_READ
| O_WRITE
, 0);
267 if (master
!= MACH_PORT_NULL
)
268 kr
= device_open(master
, D_WRITE
| D_READ
, "eth", &ph
->mach_dev
);
270 /* If unsuccessful, try Mach device */
271 kr
= get_privileged_ports(NULL
, &master
);
274 pcapint_fmt_errmsg_for_kern_return_t(p
->errbuf
,
275 PCAP_ERRBUF_SIZE
, kr
, "get_privileged_ports");
277 ret
= PCAP_ERROR_PERM_DENIED
;
281 kr
= device_open(master
, D_READ
| D_WRITE
, p
->opt
.device
,
285 mach_port_deallocate(mach_task_self(), master
);
288 pcapint_fmt_errmsg_for_kern_return_t(p
->errbuf
, PCAP_ERRBUF_SIZE
, kr
,
290 if (kr
== ED_NO_SUCH_DEVICE
) /* not ENODEV */
291 ret
= PCAP_ERROR_NO_SUCH_DEVICE
;
295 kr
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
,
299 pcapint_fmt_errmsg_for_kern_return_t(p
->errbuf
, PCAP_ERRBUF_SIZE
, kr
,
300 "mach_port_allocate");
304 p
->bufsize
= sizeof(struct net_rcv_msg
);
305 p
->buffer
= malloc(p
->bufsize
);
307 if (p
->buffer
== NULL
) {
308 pcapint_fmt_errmsg_for_errno(p
->errbuf
, PCAP_ERRBUF_SIZE
,
314 * XXX Ethernet only currently
316 * XXX - does "Ethernet only currently" mean "the only devices
317 * on which the Hurd supports packet capture are Ethernet
318 * devices", or "it supports other devices but makes them
319 * all provide Ethernet headers"?
321 * If the latter, is there a way to determine whether the
322 * device is a real Ethernet, so that we could offer DLT_DOCSIS,
323 * in case you're capturing DOCSIS traffic that a Cisco Cable
324 * Modem Termination System is putting out onto an Ethernet
325 * (it doesn't put an Ethernet header onto the wire, it puts
326 * raw DOCSIS frames out on the wire inside the low-level
329 p
->linktype
= DLT_EN10MB
;
331 p
->read_op
= pcap_read_hurd
;
332 p
->inject_op
= pcap_inject_hurd
;
333 p
->setfilter_op
= pcap_setfilter_hurd
;
334 p
->stats_op
= pcap_stats_hurd
;
339 pcap_cleanup_hurd(p
);
344 pcapint_create_interface(const char *device _U_
, char *ebuf
)
346 struct pcap_hurd
*ph
;
349 p
= PCAP_CREATE_COMMON(ebuf
, struct pcap_hurd
);
354 ph
->mach_dev
= MACH_PORT_NULL
;
355 ph
->rcv_port
= MACH_PORT_NULL
;
356 p
->activate_op
= pcap_activate_hurd
;
361 can_be_bound(const char *name
)
364 * On Hurd lo appears in the list of interfaces, but the call to
365 * device_open() fails with: "(os/device) no such device".
367 if (! strcmp(name
, "lo"))
373 get_if_flags(const char *name _U_
, bpf_u_int32
*flags
, char *errbuf _U_
)
376 * This would apply to the loopback interface if it worked. Ethernet
377 * interfaces appear up and running regardless of the link status.
379 *flags
|= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE
;
384 pcapint_platform_finddevs(pcap_if_list_t
*devlistp
, char *errbuf
)
386 return pcapint_findalldevs_interfaces(devlistp
, errbuf
, can_be_bound
,
391 * Libpcap version string.
394 pcap_lib_version(void)
396 return PCAP_VERSION_STRING
;