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