Skip to content

Commit 04b51af

Browse files
richardbrauninfrastation
authored andcommitted
Add GNU/Hurd support (with NETDDE) support, from Debian
1 parent 011d002 commit 04b51af

File tree

2 files changed

+274
-0
lines changed

2 files changed

+274
-0
lines changed

configure.ac

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,7 @@ else
674674
AC_CHECK_HEADERS(net/nit.h sys/net/nit.h)
675675
AC_CHECK_HEADERS(linux/socket.h net/raw.h sys/dlpi.h)
676676
AC_CHECK_HEADERS(config/HaikuConfig.h)
677+
AC_CHECK_HEADERS(hurd.h)
677678

678679
if test "$ac_cv_lbl_bpf_h_defines_biocsetif" = yes; then
679680
#
@@ -735,6 +736,11 @@ else
735736
# Haiku.
736737
#
737738
V_PCAP=haiku
739+
elif test "$ac_cv_header_hurd_h" = yes; then
740+
#
741+
# Hurd.
742+
#
743+
V_PCAP=hurd
738744
else
739745
#
740746
# Nothing we support.
@@ -1057,6 +1063,11 @@ snoop)
10571063
PLATFORM_C_SRC="pcap-snoop.c"
10581064
;;
10591065

1066+
hurd)
1067+
PLATFORM_C_SRC="pcap-hurd.c"
1068+
LIBS="$LIBS -lrt"
1069+
;;
1070+
10601071
dag)
10611072
#
10621073
# --with-pcap=dag is the only way to get here, and it means

pcap-hurd.c

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
#define _GNU_SOURCE
2+
3+
/* XXX Hack not to include the Mach BPF interface */
4+
#define _DEVICE_BPF_H_
5+
6+
#ifdef HAVE_CONFIG_H
7+
#include "config.h"
8+
#endif
9+
10+
#include <fcntl.h>
11+
#include <hurd.h>
12+
#include <mach.h>
13+
#include <time.h>
14+
#include <errno.h>
15+
#include <stdio.h>
16+
#include <stddef.h>
17+
#include <stdlib.h>
18+
#include <string.h>
19+
#include <device/device.h>
20+
#include <device/device_types.h>
21+
#include <device/net_status.h>
22+
#include <net/if_ether.h>
23+
24+
#include "pcap-int.h"
25+
26+
struct pcap_hurd {
27+
struct pcap_stat stat;
28+
device_t mach_dev;
29+
mach_port_t rcv_port;
30+
};
31+
32+
static struct bpf_insn filter[] = {
33+
{ NETF_IN | NETF_OUT | NETF_BPF, 0, 0, 0 },
34+
{ BPF_RET | BPF_K, 0, 0, 1500 },
35+
};
36+
37+
#define FILTER_COUNT (sizeof(filter) / sizeof(short))
38+
39+
static int
40+
pcap_read_hurd(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
41+
{
42+
struct net_rcv_msg *msg;
43+
struct pcap_hurd *ph;
44+
struct pcap_pkthdr h;
45+
struct timespec ts;
46+
int ret, wirelen, caplen;
47+
u_char *pkt;
48+
kern_return_t kr;
49+
50+
ph = p->priv;
51+
msg = (struct net_rcv_msg *)p->buffer;
52+
53+
retry:
54+
if (p->break_loop) {
55+
p->break_loop = 0;
56+
return PCAP_ERROR_BREAK;
57+
}
58+
59+
kr = mach_msg(&msg->msg_hdr, MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0,
60+
p->bufsize, ph->rcv_port, MACH_MSG_TIMEOUT_NONE,
61+
MACH_PORT_NULL);
62+
63+
if (kr) {
64+
if (kr == MACH_RCV_INTERRUPTED)
65+
goto retry;
66+
67+
snprintf(p->errbuf, sizeof(p->errbuf), "mach_msg: %s",
68+
pcap_strerror(kr));
69+
return PCAP_ERROR;
70+
}
71+
72+
ph->stat.ps_recv++;
73+
74+
/* XXX Ethernet support only */
75+
wirelen = ETH_HLEN + msg->net_rcv_msg_packet_count
76+
- sizeof(struct packet_header);
77+
pkt = p->buffer + offsetof(struct net_rcv_msg, packet)
78+
+ sizeof(struct packet_header) - ETH_HLEN;
79+
memmove(pkt, p->buffer + offsetof(struct net_rcv_msg, header),
80+
ETH_HLEN);
81+
82+
caplen = (wirelen > p->snapshot) ? p->snapshot : wirelen;
83+
ret = bpf_filter(p->fcode.bf_insns, pkt, wirelen, caplen);
84+
85+
if (!ret)
86+
goto out;
87+
88+
clock_gettime(CLOCK_REALTIME, &ts);
89+
h.ts.tv_sec = ts.tv_sec;
90+
h.ts.tv_usec = ts.tv_nsec / 1000;
91+
h.len = wirelen;
92+
h.caplen = caplen;
93+
callback(user, &h, pkt);
94+
95+
out:
96+
return 1;
97+
}
98+
99+
static int
100+
pcap_inject_hurd(pcap_t *p, const void *buf, int size)
101+
{
102+
struct pcap_hurd *ph;
103+
kern_return_t kr;
104+
int count;
105+
106+
ph = p->priv;
107+
kr = device_write(ph->mach_dev, D_NOWAIT, 0,
108+
(io_buf_ptr_t)buf, size, &count);
109+
110+
if (kr) {
111+
snprintf(p->errbuf, sizeof(p->errbuf), "device_write: %s",
112+
pcap_strerror(kr));
113+
return -1;
114+
}
115+
116+
return count;
117+
}
118+
119+
static int
120+
pcap_stats_hurd(pcap_t *p, struct pcap_stat *ps)
121+
{
122+
struct pcap_hurd *ph;
123+
124+
ph = p->priv;
125+
*ps = ph->stat;
126+
return 0;
127+
}
128+
129+
static void
130+
pcap_cleanup_hurd(pcap_t *p)
131+
{
132+
struct pcap_hurd *ph;
133+
134+
ph = p->priv;
135+
136+
if (ph->rcv_port != MACH_PORT_NULL) {
137+
mach_port_deallocate(mach_task_self(), ph->rcv_port);
138+
ph->rcv_port = MACH_PORT_NULL;
139+
}
140+
141+
if (ph->mach_dev != MACH_PORT_NULL) {
142+
device_close(ph->mach_dev);
143+
ph->mach_dev = MACH_PORT_NULL;
144+
}
145+
146+
pcap_cleanup_live_common(p);
147+
}
148+
149+
static int
150+
pcap_activate_hurd(pcap_t *p)
151+
{
152+
struct pcap_hurd *ph;
153+
mach_port_t master;
154+
kern_return_t kr;
155+
156+
ph = p->priv;
157+
158+
/* Try devnode first */
159+
master = file_name_lookup(p->opt.device, O_READ | O_WRITE, 0);
160+
161+
if (master != MACH_PORT_NULL)
162+
kr = device_open(master, D_WRITE | D_READ, "eth", &ph->mach_dev);
163+
else {
164+
/* If unsuccessful, try Mach device */
165+
kr = get_privileged_ports(NULL, &master);
166+
167+
if (kr) {
168+
snprintf(p->errbuf, sizeof(p->errbuf),
169+
"get_privileged_ports: %s", pcap_strerror(kr));
170+
goto error;
171+
}
172+
173+
kr = device_open(master, D_READ | D_WRITE, p->opt.device,
174+
&ph->mach_dev);
175+
}
176+
177+
mach_port_deallocate(mach_task_self(), master);
178+
179+
if (kr) {
180+
snprintf(p->errbuf, sizeof(p->errbuf), "device_open: %s",
181+
pcap_strerror(kr));
182+
goto error;
183+
}
184+
185+
kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE,
186+
&ph->rcv_port);
187+
188+
if (kr) {
189+
snprintf(p->errbuf, sizeof(p->errbuf), "mach_port_allocate: %s",
190+
pcap_strerror(kr));
191+
goto error;
192+
}
193+
194+
kr = device_set_filter(ph->mach_dev, ph->rcv_port,
195+
MACH_MSG_TYPE_MAKE_SEND, 0,
196+
(filter_array_t)filter, FILTER_COUNT);
197+
198+
if (kr) {
199+
snprintf(p->errbuf, sizeof(p->errbuf), "device_set_filter: %s",
200+
pcap_strerror(kr));
201+
goto error;
202+
}
203+
204+
/* XXX Ethernet only currently */
205+
p->linktype = DLT_EN10MB;
206+
207+
p->bufsize = sizeof(struct net_rcv_msg);
208+
p->buffer = malloc(p->bufsize);
209+
210+
if (p->buffer == NULL) {
211+
snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s",
212+
pcap_strerror(errno));
213+
goto error;
214+
}
215+
216+
p->dlt_list = malloc(sizeof(*p->dlt_list));
217+
218+
if (p->dlt_list != NULL)
219+
*p->dlt_list = DLT_EN10MB;
220+
221+
p->read_op = pcap_read_hurd;
222+
p->inject_op = pcap_inject_hurd;
223+
p->setfilter_op = install_bpf_program;
224+
p->stats_op = pcap_stats_hurd;
225+
226+
return 0;
227+
228+
error:
229+
pcap_cleanup_hurd(p);
230+
return PCAP_ERROR;
231+
}
232+
233+
pcap_t *
234+
pcap_create_interface(const char *device _U_, char *ebuf)
235+
{
236+
struct pcap_hurd *ph;
237+
pcap_t *p;
238+
239+
p = PCAP_CREATE_COMMON(ebuf, struct pcap_hurd);
240+
if (p == NULL)
241+
return NULL;
242+
243+
ph = p->priv;
244+
ph->mach_dev = MACH_PORT_NULL;
245+
ph->rcv_port = MACH_PORT_NULL;
246+
p->activate_op = pcap_activate_hurd;
247+
return p;
248+
}
249+
250+
int
251+
pcap_platform_finddevs(pcap_if_list_t *alldevsp, char *errbuf)
252+
{
253+
return 0;
254+
}
255+
256+
/*
257+
* Libpcap version string.
258+
*/
259+
const char *
260+
pcap_lib_version(void)
261+
{
262+
return PCAP_VERSION_STRING;
263+
}

0 commit comments

Comments
 (0)