int sr_read_from_server(struct sr_instance* sr /* borrowed */) { int command, len; unsigned char *buf = 0; c_packet_ethernet_header* sr_pkt = 0; int ret = 0, bytes_read = 0; /* REQUIRES */ assert(sr); /*--------------------------------------------------------------------------- Read a command from the server -------------------------------------------------------------------------*/ bytes_read = 0; /* attempt to read the size of the incoming packet */ while( bytes_read < 4) { do { /* -- just in case SIGALRM breaks recv -- */ errno = 0; /* -- hacky glibc workaround -- */ if((ret = recv(sr->sockfd,((uint8_t*)&len) + bytes_read, 4 - bytes_read, 0)) == -1) { if ( errno == EINTR ) { continue; } perror("recv(..):sr_client.c::sr_read_from_server"); return -1; } bytes_read += ret; } while ( errno == EINTR); /* be mindful of signals */ } len = ntohl(len); if ( len > 10000 || len < 0 ) { fprintf(stderr,"Error: command length to large %d\n",len); close(sr->sockfd); return -1; } if((buf = malloc(len)) == 0) { fprintf(stderr,"Error: out of memory (sr_read_from_server)\n"); return -1; } /* set first field of command since we've already read it */ *((int *)buf) = htonl(len); bytes_read = 0; /* read the rest of the command */ while ( bytes_read < len - 4) { do {/* -- just in case SIGALRM breaks recv -- */ errno = 0; /* -- hacky glibc workaround -- */ if ((ret = read(sr->sockfd, buf+4+bytes_read, len - 4 - bytes_read)) == -1) { if ( errno == EINTR ) { continue; } fprintf(stderr,"Error: failed reading command body %d\n",ret); close(sr->sockfd); return -1; } bytes_read += ret; } while (errno == EINTR); /* be mindful of signals */ } command = *(((int *)buf)+1) = ntohl(*(((int *)buf)+1)); switch (command) { /* ------------- VNSPACKET -------------------- */ case VNSPACKET: sr_pkt = (c_packet_ethernet_header *)buf; /* -- check if it is an ARP to another router if so drop -- */ if ( sr_arp_req_not_for_us(sr, (buf+sizeof(c_packet_header)), len - sizeof(c_packet_ethernet_header) + sizeof(struct sr_ethernet_hdr), (char*)(buf + sizeof(c_base))) ) { break; } /* -- log packet -- */ sr_log_packet(sr, buf + sizeof(c_packet_header), ntohl(sr_pkt->mLen) - sizeof(c_packet_header)); /* -- pass to router, student's code should take over here -- */ sr_handlepacket(sr, (buf+sizeof(c_packet_header)), len - sizeof(c_packet_ethernet_header) + sizeof(struct sr_ethernet_hdr), (char*)(buf + sizeof(c_base))); break; /* ------------- VNSCLOSE -------------------- */ case VNSCLOSE: fprintf(stderr,"VNS server closed session.\n"); fprintf(stderr,"Reason: %s\n",((c_close*)buf)->mErrorMessage); sr_session_closed_help(); if(buf) { free(buf); } return 0; break; /* ------------- VNSHWINFO -------------------- */ case VNSHWINFO: sr_handle_hwinfo(sr,(c_hwinfo*)buf); if(sr_verify_routing_table(sr) != 0) { fprintf(stderr,"Routing table not consistent with hardware\n"); return -1; } printf(" <-- Ready to process packets --> \n"); break; default: Debug("unknown command: %d\n", command); break; }/* -- switch -- */ if(buf) { free(buf); } return 1; }/* -- sr_read_from_server -- */
void arp_handlepacket(struct sr_instance *sr, uint8_t *packet, unsigned int len, char *interface) { printf("** Recieved ARP packet\n"); /* Initalize ARP header from the Packet */ struct sr_arp_hdr *arp_hdr = arp_header(packet); /* Interface the packet arrived in */ struct sr_if *r_iface = sr_get_interface(sr,interface); /* Check if interface->ip = arp header->ip */ if (r_iface->ip != arp_hdr->ar_tip){ return; } /* validate ARP packet */ if (!arp_validpacket(packet, len)) return; if (ntohs(arp_hdr->ar_op) == arp_op_request){ if(sr_arp_req_not_for_us(sr, packet, len, interface)) return; printf("** ARP packet request to me \n"); /* Build and send ARP packet */ build_arp_reply(sr, arp_hdr, r_iface); } else if (ntohs(arp_hdr->ar_op) == arp_op_reply) { printf("** ARP packet reply to me\n"); struct sr_arpentry *arp_entry; struct sr_arpreq *arp_req; struct sr_if *s_interface; struct sr_packet *pkt_wait; struct sr_packet *temp; uint8_t *send_packet; unsigned int eth_pkt_len; /* Check ARP cache */ arp_entry = sr_arpcache_lookup(&sr->cache, arp_hdr->ar_sip); if (arp_entry != 0){ free(arp_entry); } else { arp_req = sr_arpcache_insert(&sr->cache, arp_hdr->ar_sha, arp_hdr->ar_sip); printf("** ARP entry created\n"); /* Check ARP request queue, if not empty send out packets on it*/ if (arp_req != 0) { pkt_wait = arp_req->packets; while (pkt_wait != 0) { printf("** ARP resolved, sending queued packets\n"); /* Send the packets out */ s_interface = sr_get_interface(sr, pkt_wait->iface); struct sr_ethernet_hdr sr_ether_hdr; /* Construct the ethernet packet */ sr_ether_hdr.ether_type = htons(ethertype_ip); memcpy(sr_ether_hdr.ether_shost, s_interface->addr, ETHER_ADDR_LEN); memcpy(sr_ether_hdr.ether_dhost, arp_hdr->ar_sha, ETHER_ADDR_LEN); /* Copy the packet into the sender buf */ eth_pkt_len = pkt_wait->len + sizeof(struct sr_ethernet_hdr); send_packet = malloc(eth_pkt_len); memcpy(send_packet, &sr_ether_hdr, sizeof(struct sr_ethernet_hdr)); memcpy(send_packet + sizeof(struct sr_ethernet_hdr), pkt_wait->buf, pkt_wait->len); sr_send_packet(sr, send_packet, eth_pkt_len, s_interface->name); temp = pkt_wait; pkt_wait = pkt_wait->next; free(temp); } printf("** All queued packets sent\n"); } } } }