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
int sr_read_from_server_expect(struct sr_instance* sr /* borrowed */, int expected_cmd)
{
    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 = (unsigned char*)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 */
    }

    /* My entry for most unreadable line of code - guido */
    /* ... you win - mc                                  */
    command = *(((int *)buf)+1) = ntohl(*(((int *)buf)+1));

    /* make sure the command is what we expected if we were expecting something */
    if(expected_cmd && command!=expected_cmd) {
        if(command != VNSCLOSE) { /* VNSCLOSE is always ok */
            fprintf(stderr, "Error: expected command %d but got %d\n", expected_cmd, command);
            return -1;
        }
    }

    ret = 1;
    switch (command)
    {
        /* -------------        VNSPACKET     -------------------- */

        case VNSPACKET:
            sr_pkt = (c_packet_ethernet_header *)buf;

            /* -- 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_integ_input(sr,
                    (buf+sizeof(c_packet_header)), /* lent */
                    len - sizeof(c_packet_header),
                    (const char*)buf + sizeof(c_base)); /* lent */

            break;

            /* -------------        VNSCLOSE      -------------------- */

        case VNSCLOSE:
            fprintf(stderr,"VNS server closed session.\n");
            fprintf(stderr,"Reason: %s\n",((c_close*)buf)->mErrorMessage);
            sr_close_instance(sr); /* closes the VNS socket and logfile */

            if(buf)
            { free(buf); }
            return 0;
            break;

            /* -------------        VNSBANNER      -------------------- */

        case VNSBANNER:
            fprintf(stderr,"%s",((c_banner*)buf)->mBannerMessage);
            break;

            /* -------------     VNSHWINFO     -------------------- */

        case VNSHWINFO:
            sr_handle_hwinfo(sr,(c_hwinfo*)buf);
            break;

            /* ---------------- VNS_RTABLE ---------------- */
        case VNS_RTABLE:
            fprintf(stderr, "not yet setup to handle VNS_RTABLE message\n");
            sr_close_instance(sr);
            if(buf) { free(buf); }
            return 0;
            break;

            /* ------------- VNS_AUTH_REQUEST ------------- */
        case VNS_AUTH_REQUEST:
            if(!sr_handle_auth_request(sr, (c_auth_request*)buf))
                ret = -1;
            break;

            /* ------------- VNS_AUTH_STATUS -------------- */
        case VNS_AUTH_STATUS:
            if(!sr_handle_auth_status(sr, (c_auth_status*)buf))
                ret = -1;
            break;

        default:
            printf("unknown command: %d\n", command);
            break;

    }/* -- switch -- */

    if(buf)
    { free(buf); }
    return ret;
}/* -- sr_read_from_server -- */