/******************************************************************* * Every time handle_packet() is called, update_buffer() is called. The function walks through * the packet buffer and checks if the necessary mac address is now in the arp cache. If it is, * then the MAC address is added to the ethernet header and the packet is send and removed * from the buffer. If the address is not in the cache and less than 5 arp requests have already * been sent, then another arp request is sent. Otherwise the packet is deleted from the buffer * and an ICMP port unreachable is sent. *******************************************************************/ void update_buffer(struct packet_state* ps,struct packet_buffer* queue) { struct packet_buffer* buf_walker=0; buf_walker=queue; while(buf_walker) { uint32_t search_ip=buf_walker->gw_IP; struct arp_cache_entry* ent=search_cache(ps, search_ip); if(ent!=NULL) /*MAC Address is in ARP Cache. Send packet. */ { struct sr_ethernet_hdr *eth = (struct sr_ethernet_hdr *)(buf_walker->packet); memmove(eth->ether_dhost, ent->mac, ETHER_ADDR_LEN); struct sr_if *iface=sr_get_interface(ps->sr, buf_walker->interface); memmove(eth->ether_shost, iface->addr, ETHER_ADDR_LEN); eth->ether_type = htons(ETHERTYPE_IP); sr_send_packet(ps->sr, buf_walker->packet, buf_walker->pack_len, buf_walker->interface); buf_walker=delete_from_buffer(ps,buf_walker); } else if(buf_walker->num_arp_reqs < 5) /*Send another arp request. */ { buf_walker->num_arp_reqs++; sr_send_packet(ps->sr, buf_walker->arp_req, buf_walker->arp_len, buf_walker->interface); buf_walker=buf_walker->next; } else /* 5 ARP Request already sent, send ICMP Port Unreachable and Delete from Buffer.*/ { int off = sizeof(struct sr_ethernet_hdr) + sizeof(struct ip); ps->res_len=off; ps->response += sizeof(struct sr_ethernet_hdr); struct ip *res_ip = (struct ip*) ps->response; /*IP Header for ICMP Port Unreachable*/ ps->response += sizeof(struct ip); ps->packet = buf_walker->packet; ps->packet += sizeof(struct sr_ethernet_hdr); struct ip *ip_hdr = (struct ip*) (ps->packet); /*IP Header from original packet. */ ps->packet += sizeof(struct ip); icmp_response(ps, ip_hdr, ICMPT_DESTUN, ICMPC_HOSTUN); /*Construct ICMP */ memmove(res_ip, ip_hdr, sizeof(struct ip)); res_ip->ip_len = htons(ps->res_len - sizeof(struct sr_ethernet_hdr)); res_ip->ip_ttl = INIT_TTL; res_ip->ip_tos = ip_hdr->ip_tos; res_ip->ip_p = IPPROTO_ICMP; /* Finding interface to send ICMP out of*/ struct sr_rt* iface_rt_entry=get_routing_if(ps, ip_hdr->ip_src); struct sr_if* iface=sr_get_interface(ps->sr, iface_rt_entry->interface); res_ip->ip_src.s_addr = iface->ip; res_ip->ip_dst = ip_hdr->ip_src; res_ip->ip_sum = 0; res_ip->ip_sum = cksum((uint8_t *)res_ip, sizeof(struct ip)); res_ip->ip_sum = htons(res_ip->ip_sum); ps->response = (uint8_t *) res_ip - sizeof(struct sr_ethernet_hdr); struct sr_ethernet_hdr* eth_resp=(struct sr_ethernet_hdr*)ps->response; memmove(eth_resp->ether_dhost,buf_walker->old_eth->ether_shost,ETHER_ADDR_LEN); memmove(eth_resp->ether_shost,iface->addr, ETHER_ADDR_LEN); eth_resp->ether_type=htons(ETHERTYPE_IP); sr_send_packet(ps->sr, ps->response, ps->res_len, iface_rt_entry->interface); buf_walker=delete_from_buffer(ps,buf_walker); } } }
int run_shell() { Value tmp_value; int ascii_code = -1; int cmd_code = -1; wprintf(L""); for (;;) { tmp_value = get_char(); ascii_code = tmp_value.integer; // EXPECTATIONS cmd_code = analyse_expectations(ascii_code); //wprintf(L"%d %d %lc\n",ascii_code, cmd_code, tmp_value.character); switch(cmd_code) { case EOT_CMD: quit_shell(); break; case DEL_L: delete_from_buffer(false); break; case DEL_R: delete_from_buffer(true); break; case UP_A_K: wprintf(L"UP"); break; case DOWN_A_K: wprintf(L"DOWN"); break; case RIGHT_A_K: move_cusor(CURSOR_DIR_RIGHT); break; case LEFT_A_K: move_cusor(CURSOR_DIR_LEFT); break; case BEGIN: move_cusor(CURSOR_DIR_BEGIN); break; case END: move_cusor(CURSOR_DIR_END); break; case ENTER_CMD: if(handle_cmd() == RET_ERROR) { print_error("Error while executing command!"); } break; case NO_CMD: push_elem(buffer, tmp_value); print_buffer(true); break; default: //printf("%d => %c\n", ascii_code, tmp_value.character); break; } } return RET_OK; }