void netfpga_input_callback(unsigned char* arg, const struct pcap_pkthdr * pkt_hdr, unsigned char const* packet) {
	netfpga_input_arg* input_arg = (netfpga_input_arg*)arg;
	router_state* rs = input_arg->rs;
	struct sr_instance* sr = rs->sr;


	char* internal_names[4] = {"eth0", "eth1", "eth2", "eth3"};

	/* log packet */
	pthread_mutex_lock(rs->log_dumper_mutex);
	sr_log_packet(sr, (unsigned char*)packet, pkt_hdr->caplen);
	pthread_mutex_unlock(rs->log_dumper_mutex);

	/* send packet */
	sr_integ_input(sr, packet, pkt_hdr->caplen, internal_names[input_arg->interface_num]);
}
void netfpga_input(struct sr_instance* sr) {
	router_state* rs = get_router_state(sr);
	int i;
	char* internal_names[4] = {"eth0", "eth1", "eth2", "eth3"};

	/* setup select */
	fd_set read_set;
	FD_ZERO(&read_set);
	int READ_BUF_SIZE = 16384;
	unsigned char readBuf[READ_BUF_SIZE];

	while (1) {
		for (i = 0; i < 4; ++i) {
			FD_SET(rs->raw_sockets[i], &read_set);
		}

		struct timeval t;
		t.tv_usec = 500; // timeout every half a millisecond

		if (select(getMax(rs->raw_sockets, 4)+1, &read_set, NULL, NULL, NULL) < 0) {
			perror("select");
			exit(1);
		}

		for (i = 0; i < 4; ++i) {
			if (FD_ISSET(rs->raw_sockets[i], &read_set)) {
				// assume each read is a full packet
				int read_bytes = read(rs->raw_sockets[i], readBuf, READ_BUF_SIZE);

				/* log packet */
				pthread_mutex_lock(rs->log_dumper_mutex);
				sr_log_packet(sr, (unsigned char*)readBuf, read_bytes);
				pthread_mutex_unlock(rs->log_dumper_mutex);

				/* send packet */
				sr_integ_input(sr, readBuf, read_bytes, internal_names[i]);
			}
		}

	}

}
Beispiel #3
0
int sr_vns_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_vns_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_vns_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));

    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);
            sr_integ_close(sr);
            if(buf)
            { free(buf); }
            return 0;
            break;

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

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

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

    if(buf)
    { free(buf); }
    return 1;
}/* -- sr_vns_read_from_server -- */
int sr_cpu_input(struct sr_instance* sr)
{
	/* REQUIRES */
	assert(sr);
	
	fprintf(stderr, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
	fprintf(stderr, "!!!  sr_cpu_input(..) (sr_cpu_extension_nf2.c) called while running in cpu mode     !!!\n");
// 	fprintf(stderr, "!!!  you need to implement this function to read from the hardware                  !!!\n");
	fprintf(stderr, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
	
	//while (1);
		
	router_t* router = (router_t*) sr_get_subsystem(sr);
	int i;
	char* internal_names[NUM_INTERFACES] = {"eth0", "eth1", "eth2", "eth3"};
	
	/* setup select */
	fd_set read_set;
	FD_ZERO(&read_set);
	int READ_BUF_SIZE = 16384;
	unsigned char readBuf[READ_BUF_SIZE];
	
	while (1) {
		for (i = 0; i < NUM_INTERFACES; ++i) {
			FD_SET(router->sockfd[i], &read_set);
		}
		
// 		struct timeval t;
// 		t.tv_usec = 500; // timeout every half a millisecond
		
		int nfd = array_max(router->sockfd, NUM_INTERFACES) + 1;
		if (select(nfd, &read_set, NULL, NULL, NULL) < 0) {
			perror("select");
			exit(1);
		}
		
		for (i = 0; i < NUM_INTERFACES; ++i) {
			if (FD_ISSET(router->sockfd[i], &read_set)) {
				printf("\n\n Something on %s \n", internal_names[i]);
				// assume each read is a full packet
				int read_bytes = read(router->sockfd[i], readBuf, READ_BUF_SIZE);
				
				/* log packet */
//				pthread_mutex_lock(rs->log_dumper_mutex); //TODO: lock
				sr_log_packet(sr, (unsigned char*)readBuf, read_bytes);
//				pthread_mutex_unlock(rs->log_dumper_mutex);
				
				/* send packet */
				sr_integ_input(sr, readBuf, read_bytes, internal_names[i]);
			}
		}
	}
	
	//assert(0);
	
	/*
	 * TODO: Read packet from the hardware and pass to sr_integ_input(..)
	 *       e.g.
	 *
	 *  sr_integ_input(sr,
	 *          packet,   * lent *
	 *          len,
	 *          "eth2" ); * lent *
	 */
	
	/*
	 * Note: To log incoming packets, use sr_log_packet from sr_dumper.[c,h]
	 */
	
	/* RETURN 1 on success, 0 on failure.
	 * Note: With a 0 result, the router will shut-down
	 */
	return 1;
	
} /* -- sr_cpu_input -- */
Beispiel #5
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 -- */
int sr_cpu_input( struct sr_instance* sr ) {
    byte buf[ETH_MAX_LEN];
    ssize_t len;
    router_t* router;
    interface_t* intf;
    fd_set rdset, errset;
    int ret, max_fd;
    unsigned i;
    struct timeval timeout;

    /* loop until something interesting happens */
    do {
        /* clear the sets */
        FD_ZERO( &rdset );
        FD_ZERO( &errset );

        /* set the bits on interfaces' fd's that we care about */
        max_fd = -1;
        router = sr->interface_subsystem;
        for( i=0; i<router->num_interfaces; i++ ) {
            if( router->interface[i].enabled ) {
                FD_SET( router->interface[i].hw_fd, &rdset );
                FD_SET( router->interface[i].hw_fd, &errset );

                if( router->interface[i].hw_fd > max_fd )
                    max_fd = router->interface[i].hw_fd;

#ifdef _DEBUG_
                if( router->interface[i].hw_fd > FD_SETSIZE )
                    die( "Error: fd too big for select (%d > %d)",
                         router->interface[i].hw_fd, FD_SETSIZE );
#endif
            }
        }

        /* wait for something to happen */
        timeout.tv_sec  = 1;
        timeout.tv_usec = 0;
        ret = select( max_fd + 1, &rdset, NULL, &errset, &timeout );

        /* check each intf to see if something interesting happened on it */
        for( i=0; i<router->num_interfaces; i++ ) {
            intf = &router->interface[i];
            if( intf->enabled ) {
                /* check for available bytes in the input buffer */
                if( FD_ISSET( intf->hw_fd, &rdset ) ) {
                    len = real_read_once( intf->hw_fd, buf, ETH_MAX_LEN );
                    if( len == 0 )
                        debug_println( "Warning: HW socket closed to %s",
                                       intf->name );
                    else if( len < 0 )
                        debug_println( "Warning: error when reading on HW socket to %s",
                                       intf->name );
                    else {
#if 0
                        /* check packet for decap first */
                        if( len >= 34 ) {
                            if( buf[23] == 0x04 || buf[23] == 0xF4 ) {
                                debug_println( "*** DECAPSULATING PACKET ***" );

                                /* write a new Ethernet header */
                                byte* new_buf = buf + 20;
                                memset( new_buf, 0xFF, ETH_ADDR_LEN );
                                memcpy( new_buf+6, &router->interface[DECAP_NEXT_INTF].mac, ETH_ADDR_LEN );
                                *((uint16_t*)(new_buf+12)) = IPV4_ETHERTYPE;

                                /* send it back out nf2c{DECAP_NEXT_INTF} */
                                sr_cpu_output( new_buf, len-20, &router->interface[DECAP_NEXT_INTF] );
                                count+=len;
                                fprintf(stderr,"%llu\n",count-20);
                                continue;
                            }
                        }
#endif
                        /* send the packet to our processing pipeline */
                        sr_integ_input( sr, buf, len, intf );

                        /* log the received packet */
                        sr_log_packet( sr, buf, len );

                        return 1;
                    }
                }

                /* check for an error on the socket */
                if( FD_ISSET( intf->hw_fd, &errset ) ) {
                    debug_println( "Warning: error on HW socket to %s",
                                   intf->name );
                }
            }
        }
    }
    while( 1 );
}