Esempio n. 1
0
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 -- */
Esempio n. 2
0
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");

            } 
          }   
      }
}