static int icmp_recv(struct netbuf *pkt) { struct icmp_header *icmphdr; icmphdr = (struct icmp_header *)pkt->top; /* 正式にはコンソールドライバタスクに依頼する必要があるが,とりあえず */ puts("ICMP received: "); putxval(pkt->option.common.ipaddr.addr, 8); puts(" "); putxval(icmphdr->type, 2); puts(" "); putxval(icmphdr->code, 2); puts(" "); putxval(ntoh2(icmphdr->checksum), 4); puts("\n"); switch (icmphdr->type) { case ICMP_TYPE_REPLY: break; case ICMP_TYPE_REQUEST: icmp_sendpkt(pkt->option.common.ipaddr.addr, ICMP_TYPE_REPLY, icmphdr->code, ntoh2(icmphdr->param.id), ntoh2(icmphdr->param.sequence_number), pkt->size - sizeof(struct icmp_header), (char *)icmphdr + sizeof(*icmphdr)); break; } return 0; }
static int arp_recv(struct netbuf *pkt) { struct addrset *addr; struct arp_header *arphdr; uint32 ipaddr; uint32 ipaddr_n; arphdr = (struct arp_header *)pkt->top; if (ntoh2(arphdr->hardware) != ARP_HARDWARE_ETHER) return 0; if (ntoh2(arphdr->protocol) != ETHERNET_TYPE_IP) return 0; switch (ntoh2(arphdr->operation)) { case ARP_OPERATION_REPLY: case ARP_OPERATION_REQUEST: memcpy(&ipaddr_n, arphdr->sender_ipaddr, IPADDR_SIZE); ipaddr = ntoh4(ipaddr_n); addr = arp_setaddr(ipaddr, arphdr->sender_macaddr); arp_flush(-1); if (ntoh2(arphdr->operation) == ARP_OPERATION_REPLY) break; ipaddr_n = hton4(my_ipaddr); if (memcmp(arphdr->target_ipaddr, &ipaddr_n, IPADDR_SIZE)) break; /* ARP reply を返送 */ arp_sendpkt(ARP_OPERATION_REPLY, addr->macaddr, addr->ipaddr); break; default: break; } return 0; }
static MyEventType NetGenFunc(EventGenRec *gen, MyEvent *event) { int result; short type, size; netint2 data[2]; result = MyRead(sock, netBuf + netBufSize, netBufGoal - netBufSize); if (result < 0) { lostConn = 1; return E_lostConn; } netBufSize += result; if (netBufSize < netBufGoal) return E_none; memcpy(data, netBuf, sizeof(data)); type = ntoh2(data[0]); size = ntoh2(data[1]); if (size >= sizeof(netBuf)) fatal("Received an invalid packet (too large), possibly an attempt\n" " to exploit a vulnerability in versions before 0.52 !"); netBufGoal = size; if (netBufSize < netBufGoal) return E_none; netBufSize = 0; netBufGoal = HEADER_SIZE; event->u.net.type = type; event->u.net.size = size - HEADER_SIZE; event->u.net.data = netBuf + HEADER_SIZE; if (type == NP_endConn) { gotEndConn = 1; return E_lostConn; } else if (type == NP_byeBye) { lostConn = 1; return E_lostConn; } return E_net; }