int sr_cpu_output(struct sr_instance* sr /* borrowed */, uint8_t* buf /* borrowed */ , unsigned int len, const char* iface /* borrowed */) { /* REQUIRES */ assert(sr); assert(buf); assert(iface); fprintf(stderr, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); fprintf(stderr, "!!! sr_cpu_output(..) (sr_cpu_extension_nf2.c) called while running in cpu mode !!!\n"); fprintf(stderr, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); router_t* router = sr_get_subsystem(sr); int written_length = 0; int i = 0; /* log the packet */ // pthread_mutex_lock(rs->log_dumper_mutex);//TODO: lock sr_log_packet(sr, buf, len); // pthread_mutex_unlock(rs->log_dumper_mutex); char* internal_names[4] = {"eth0", "eth1", "eth2", "eth3"}; for (i = 0; i < 4; ++i) { if (strcmp(iface, internal_names[i]) == 0) { break; } } /* setup select */ fd_set write_set; FD_ZERO(&write_set); while (written_length < len) { FD_SET(router->sockfd[i], &write_set); // struct timeval t; // t.tv_sec = 0; // t.tv_usec = 500; // timeout every half a millisecond if (select(router->sockfd[i]+1, NULL, &write_set, NULL, NULL) < 0) { perror("select"); exit(1); } if (FD_ISSET(router->sockfd[i], &write_set)) { int w = 0; if ((w = write(router->sockfd[i], &buf[written_length], len - written_length)) == -1) { perror("write"); exit(1); } written_length += w; } } /* Return the length of the packet on success, -1 on failure */ return len; } /* -- sr_cpu_output -- */
int netfpga_output(struct sr_instance* sr, uint8_t* packet, unsigned int len, const char* iface) { router_state* rs = get_router_state(sr); int written_length = 0; int i = 0; /* log the packet */ pthread_mutex_lock(rs->log_dumper_mutex); sr_log_packet(sr, packet, len); pthread_mutex_unlock(rs->log_dumper_mutex); char* internal_names[4] = {"eth0", "eth1", "eth2", "eth3"}; for (i = 0; i < 4; ++i) { if (strcmp(iface, internal_names[i]) == 0) { break; } } /* setup select */ fd_set write_set; FD_ZERO(&write_set); while (written_length < len) { FD_SET(rs->raw_sockets[i], &write_set); struct timeval t; t.tv_sec = 0; t.tv_usec = 500; // timeout every half a millisecond if (select(rs->raw_sockets[i]+1, NULL, &write_set, NULL, NULL) < 0) { perror("select"); exit(1); } if (FD_ISSET(rs->raw_sockets[i], &write_set)) { int w = 0; if ((w = write(rs->raw_sockets[i], packet+written_length, len-written_length)) == -1) { perror("write"); exit(1); } written_length += w; } } /* if ((written_length = libnet_adv_write_link((libnet_t*)rs->libnet_context[i], packet, len)) != len) { printf("Error writing packet using libnet, expected length: %i returned length: %i\n", len, written_length); } */ return 0; }
int sr_send_packet(struct sr_instance* sr /* borrowed */, uint8_t* buf /* borrowed */ , unsigned int len, const char* iface /* borrowed */) { c_packet_header *sr_pkt; unsigned int total_len = len + (sizeof(c_packet_header)); /* REQUIRES */ assert(sr); assert(buf); assert(iface); /* don't waste my time ... */ if ( len < sizeof(struct sr_ethernet_hdr) ) { fprintf(stderr , "** Error: packet is wayy to short \n"); return -1; } /* Create packet */ sr_pkt = (c_packet_header *)malloc(len + sizeof(c_packet_header)); assert(sr_pkt); sr_pkt->mLen = htonl(total_len); sr_pkt->mType = htonl(VNSPACKET); strncpy(sr_pkt->mInterfaceName,iface,16); memcpy(((uint8_t*)sr_pkt) + sizeof(c_packet_header), buf,len); /* -- log packet -- */ sr_log_packet(sr,buf,len); printf("\n<<<< Sending packet of length %d \n",len); dump_raw(buf,len); if ( ! sr_ether_addrs_match_interface( sr, buf, iface) ) { fprintf( stderr, "*** Error: problem with ethernet header, check log\n"); free ( sr_pkt ); return -1; } if( write(sr->sockfd, sr_pkt, total_len) < total_len ) { fprintf(stderr, "Error writing packet\n"); free(sr_pkt); return -1; } free(sr_pkt); return 0; } /* -- sr_send_packet -- */
int sr_vns_send_packet(struct sr_instance* sr /* borrowed */, uint8_t* buf /* borrowed */ , unsigned int len, const char* iface /* borrowed */) { c_packet_header *sr_pkt; unsigned int total_len = len + (sizeof(c_packet_header)); /* REQUIRES */ assert(sr); assert(buf); assert(iface); /* don't waste my time ... */ if ( len < 14 /* sizeof ethernet header */ ) { fprintf(stderr , "** Error: packet is wayy to short \n"); return -1; } /* Create packet */ sr_pkt = (c_packet_header *)malloc(total_len); assert(sr_pkt); sr_pkt->mLen = htonl(total_len); sr_pkt->mType = htonl(VNSPACKET); strncpy(sr_pkt->mInterfaceName,iface,16); memcpy(((uint8_t*)sr_pkt) + sizeof(c_packet_header), buf,len); /* -- log packet -- */ sr_log_packet(sr,buf,len); if ( pthread_mutex_lock(&(sr->send_lock)) ) { assert (0); } if( write(sr->sockfd, sr_pkt, total_len) < (signed int)total_len ) { fprintf(stderr, "Error writing packet\n"); free(sr_pkt); if ( pthread_mutex_unlock(&(sr->send_lock)) ) { assert (0); } return -1; } if ( pthread_mutex_unlock(&(sr->send_lock)) ) { assert (0); } free(sr_pkt); return 0; } /* -- sr_send_packet -- */
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]); } } } }
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 -- */
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 -- */
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 ); }