forked from woai3c/MIT6.828
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtestinput.c
115 lines (96 loc) · 2.76 KB
/
testinput.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "ns.h"
#include <netif/etharp.h>
static envid_t output_envid;
static envid_t input_envid;
static struct jif_pkt *pkt = (struct jif_pkt*)REQVA;
static void
announce(void)
{
// We need to pre-announce our IP so we don't have to deal
// with ARP requests. Ideally, we would use gratuitous ARP
// for this, but QEMU's ARP implementation is dumb and only
// listens for very specific ARP requests, such as requests
// for the gateway IP.
uint8_t mac[6] = {0x52, 0x54, 0x00, 0x12, 0x34, 0x56};
uint32_t myip = inet_addr(IP);
uint32_t gwip = inet_addr(DEFAULT);
int r;
if ((r = sys_page_alloc(0, pkt, PTE_P|PTE_U|PTE_W)) < 0)
panic("sys_page_map: %e", r);
struct etharp_hdr *arp = (struct etharp_hdr*)pkt->jp_data;
pkt->jp_len = sizeof(*arp);
memset(arp->ethhdr.dest.addr, 0xff, ETHARP_HWADDR_LEN);
memcpy(arp->ethhdr.src.addr, mac, ETHARP_HWADDR_LEN);
arp->ethhdr.type = htons(ETHTYPE_ARP);
arp->hwtype = htons(1); // Ethernet
arp->proto = htons(ETHTYPE_IP);
arp->_hwlen_protolen = htons((ETHARP_HWADDR_LEN << 8) | 4);
arp->opcode = htons(ARP_REQUEST);
memcpy(arp->shwaddr.addr, mac, ETHARP_HWADDR_LEN);
memcpy(arp->sipaddr.addrw, &myip, 4);
memset(arp->dhwaddr.addr, 0x00, ETHARP_HWADDR_LEN);
memcpy(arp->dipaddr.addrw, &gwip, 4);
ipc_send(output_envid, NSREQ_OUTPUT, pkt, PTE_P|PTE_W|PTE_U);
sys_page_unmap(0, pkt);
}
static void
hexdump(const char *prefix, const void *data, int len)
{
int i;
char buf[80];
char *end = buf + sizeof(buf);
char *out = NULL;
for (i = 0; i < len; i++) {
if (i % 16 == 0)
out = buf + snprintf(buf, end - buf,
"%s%04x ", prefix, i);
out += snprintf(out, end - out, "%02x", ((uint8_t*)data)[i]);
if (i % 16 == 15 || i == len - 1)
cprintf("%.*s\n", out - buf, buf);
if (i % 2 == 1)
*(out++) = ' ';
if (i % 16 == 7)
*(out++) = ' ';
}
}
void
umain(int argc, char **argv)
{
envid_t ns_envid = sys_getenvid();
int i, r, first = 1;
binaryname = "testinput";
output_envid = fork();
if (output_envid < 0)
panic("error forking");
else if (output_envid == 0) {
output(ns_envid);
return;
}
input_envid = fork();
if (input_envid < 0)
panic("error forking");
else if (input_envid == 0) {
input(ns_envid);
return;
}
cprintf("Sending ARP announcement...\n");
announce();
while (1) {
envid_t whom;
int perm;
int32_t req = ipc_recv((int32_t *)&whom, pkt, &perm);
if (req < 0)
panic("ipc_recv: %e", req);
if (whom != input_envid)
panic("IPC from unexpected environment %08x", whom);
if (req != NSREQ_INPUT)
panic("Unexpected IPC %d", req);
hexdump("input: ", pkt->jp_data, pkt->jp_len);
cprintf("\n");
// Only indicate that we're waiting for packets once
// we've received the ARP reply
if (first)
cprintf("Waiting for packets...\n");
first = 0;
}
}