int oflops_get_channel_raw_fd(struct oflops_context * ctx, oflops_channel_name ch) { struct ifreq ifr; struct sockaddr_ll saddrll; struct channel_info * ch_info; if(ch >= ctx->n_channels) return -1; // no such channel ch_info = &ctx->channels[ch]; if(ch_info->raw_sock != -1) // already allocated? return ch_info->raw_sock; // else, setup raw socket ch_info->raw_sock = socket(AF_PACKET,SOCK_RAW, htons(ETH_P_ALL)); if( ch_info->raw_sock == -1) perror_and_exit("raw socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL))",1); // bind to a specific port strncpy(ifr.ifr_name,ch_info->dev,IFNAMSIZ); if( ioctl( ch_info->raw_sock, SIOCGIFINDEX, &ifr) == -1 ) perror_and_exit("ioctl()",1); memset(&saddrll, 0, sizeof(saddrll)); saddrll.sll_family = AF_PACKET; saddrll.sll_protocol = ETH_P_ALL; saddrll.sll_ifindex = ifr.ifr_ifindex; if ( bind(ch_info->raw_sock, (struct sockaddr *) &saddrll, sizeof(struct sockaddr_ll)) == -1 ) perror_and_exit("bind()",1); return ch_info->raw_sock; }
int make_sockaddr(unsigned char addr_type, address_union *address, unsigned int port, struct sockaddr **addr_p, socklen_t *addr_len_p) { switch (addr_type) { case ATYP_IPV4: { struct sockaddr_in *connect_sin = malloc(sizeof(struct sockaddr_in)); if (connect_sin == NULL) perror_and_exit("malloc"); memset(connect_sin, 0, sizeof(struct sockaddr_in)); connect_sin->sin_family = AF_INET; connect_sin->sin_port = htons(port); memcpy(&(connect_sin->sin_addr.s_addr), address->ipv4, 4); *addr_p = (struct sockaddr *)connect_sin; *addr_len_p = sizeof(struct sockaddr_in); break; } case ATYP_IPV6: { struct sockaddr_in6 *connect_sin6 = malloc(sizeof(struct sockaddr_in6)); if (connect_sin6 == NULL) perror_and_exit("malloc"); memset(connect_sin6, 0, sizeof(struct sockaddr_in6)); connect_sin6->sin6_family = AF_INET6; connect_sin6->sin6_port = htons(port); memcpy(&(connect_sin6->sin6_addr.s6_addr), address->ipv6, 16); *addr_p = (struct sockaddr *)connect_sin6; *addr_len_p = sizeof(struct sockaddr_in6); break; } case ATYP_DOMAIN: { char port_str[6]; // max len = 5 (for 65535) +1 for ending '\0' int printed = snprintf(port_str, sizeof(port_str), "%u", port); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsign-compare" assert(printed > 0 && printed < sizeof(port_str)); #pragma GCC diagnostic pop (void)printed; struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; struct addrinfo *res; int ret = getaddrinfo(address->domain_name, port_str, &hints, &res); if (ret == EAI_NONAME || ret == EAI_NODATA ) return REP_HOST_UNREACHABLE; else if (ret != 0) printf_and_exit("getaddrinfo: %s", gai_strerror(ret)); unsigned int addr_len = res->ai_addrlen; struct sockaddr *addr = malloc(addr_len); if (addr == NULL) perror_and_exit("malloc"); memcpy(addr, res->ai_addr, addr_len); freeaddrinfo(res); *addr_p = addr; *addr_len_p = addr_len; break; } } return 0; }
void Request::connect_server(bool is_nonblocking){ /* connect server */ server_fd = socket(AF_INET, SOCK_STREAM, 0); if( server_fd < 0 ) perror_and_exit("create socket error"); if( socket_connect(server_fd, addr) < 0 ) perror_and_exit(("connect to " + addr.ipv4_addr_str + ":" + std::to_string(addr.port_hbytes) + " error").c_str()); is_server_connect = true; if( is_nonblocking ){ int flags = fcntl(server_fd, F_GETFL, 0); fcntl(server_fd, F_SETFL, flags | O_NONBLOCK); } }
void setup_server_socket(global_config_struct *global_config, global_resources_struct *global_resources) { server_bind_addr_struct *server_bind_addr = &global_config->server_bind_addr; struct sockaddr_storage *addr = &server_bind_addr->addr; socklen_t addr_len = server_bind_addr->addr_len; int server_sockfd = socket(addr->ss_family, SOCK_STREAM, 0); if (server_sockfd < 0) perror_and_exit("socket"); int yes = 1; if (setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes))) perror_and_exit("setsockopt"); if (bind(server_sockfd, (struct sockaddr *)addr, addr_len)) perror_and_exit("bind"); global_resources->server_sockfd = server_sockfd; }
/* * Initializes the logging system of oflops. * @param filename The file where the logging messages are stored. */ void oflops_log_init(const char *filename) { logger = fopen(filename, "w"); if(logger == NULL) { perror_and_exit("failed to open log file", 1); } }
socketfd_t bind_and_listen_tcp_socket(SocketAddr& listen_addr){ /* bind and listen tcp socket with listen_addr */ socketfd_t listen_socket; listen_socket = socket(AF_INET, SOCK_STREAM, 0); if( listen_socket < 0 ) perror_and_exit("create socket error"); // int on = 1; // setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on)); if( socket_bind(listen_socket, listen_addr) < 0 ) perror_and_exit("bind error"); if( listen(listen_socket, 1) < 0) perror_and_exit("listen error"); return listen_socket; }
void Request::open_batch_file(){ /* open batch_file */ batch_file_stream.open(batch_file, std::fstream::in); if( !batch_file_stream ){ perror_and_exit(("open batch_file " + batch_file + " error").c_str()); } is_batch_file_open = true; }
/********************************************************************** * hook for the test module to get access to a udp file descriptor bound * to the data channel's device **/ int oflops_get_channel_fd(struct oflops_context * ctx, oflops_channel_name ch) { struct ifreq ifr; struct channel_info * ch_info; if(ch >= ctx->n_channels) return -1; // no such channel ch_info = &ctx->channels[ch]; if(ch_info->sock != -1) // already allocated? return ch_info->sock; // else, setup raw socket ch_info->sock = socket(AF_INET,SOCK_DGRAM,0); // UDP socket if( ch_info->sock == -1) perror_and_exit("udp socket(AF_INET,SOCK_DGRAM,0)",1); // bind to a specific port strncpy(ifr.ifr_name,ch_info->dev,IFNAMSIZ); if( ioctl( ch_info->sock, SIOCGIFINDEX, &ifr) == -1 ) perror_and_exit("ioctl() bind to dev",1); return ch_info->sock; }
ssize_t write_wrapper(int fd, const void *buf, size_t count) { ssize_t write_bytes = write(fd, buf, count); if (write_bytes < 0) { if (errno == ECONNRESET) return -1; else perror_and_exit("write"); } if (write_bytes == 0) return -1; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsign-compare" assert(write_bytes <= count); #pragma GCC diagnostic pop return write_bytes; }
ssize_t read_wrapper(int fd, void *buf, size_t count) { ssize_t read_bytes = read(fd, buf, count); if (read_bytes < 0) { if (errno == ECONNRESET) return -1; else perror_and_exit("read"); } if (read_bytes == 0) return -1; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsign-compare" assert(read_bytes <= count); #pragma GCC diagnostic pop return read_bytes; }
bool Request::send_batch_file_data_to_server_once(){ if( !is_batch_file_open ) return false; if( !is_server_connect ) return false; std::string command; if( std::getline(batch_file_stream, command) ){ command += "\n"; int w_size = write_all(server_fd, command.c_str(), command.length()); if( w_size < 0 ){ perror_and_exit("write error"); } nl2br(command); print_html_content(id, "<b>" + command + "</b>"); return true; } batch_file_stream.close(); is_batch_file_open = false; return false; }
void everror_and_exit(const char *s) { perror_and_exit(s); }
void process_args(int argc, char* argv[], global_config_struct *global_config) { cmdline_args_struct args_; cmdline_args_struct *args = &args_; parse_args(argc, argv, args); in_port_t port; { if (args->bind_port != NULL) { int p = atoi(args->bind_port); if (p <= 0 || p >= LARGE_PORT_NUMBER) printf_and_exit("invalid port"); else port = (in_port_t)p; } else { port = default_bind_port; } } { server_bind_addr_struct *server_bind_addr = &global_config->server_bind_addr; assert(args->bind_ipv4 == NULL || args->bind_ipv6 == NULL); if (args->bind_ipv6 != NULL) { assert(sizeof(server_bind_addr->addr) >= sizeof(struct sockaddr_in6)); struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&server_bind_addr->addr; memset(sin6, 0, sizeof(struct sockaddr_in6)); sin6->sin6_family = AF_INET6; sin6->sin6_port = htons(port); int ret = inet_pton(AF_INET6, args->bind_ipv6, &sin6->sin6_addr); if (ret < 0) perror_and_exit("inet_pton"); else if (ret != 1) printf_and_exit("invalid ipv6 address"); server_bind_addr->addr_len = sizeof(struct sockaddr_in6); } else { assert(sizeof(server_bind_addr->addr) >= sizeof(struct sockaddr_in)); struct sockaddr_in *sin = (struct sockaddr_in *)&server_bind_addr->addr; sin->sin_family = AF_INET; sin->sin_port = htons(port); if (args->bind_ipv4 == NULL) { sin->sin_addr.s_addr = htonl(default_bind_addr); } else { if (!inet_aton(args->bind_ipv4, &sin->sin_addr)) printf_and_exit("invalid ip address"); } server_bind_addr->addr_len = sizeof(struct sockaddr_in); } } size_t transfer_buffer_size; { if (args->transfer_buffer_size != NULL) { long long int size = atoll(args->transfer_buffer_size); if (size <= 0) printf_and_exit("invalid transfer buffer size"); else if (size == LONG_MAX || size > SSIZE_MAX) printf_and_exit("too large transfer buffer size"); else transfer_buffer_size = (size_t)size; } else { transfer_buffer_size = default_transfer_buffer_size; } } global_config->transfer_buffer_size = transfer_buffer_size; }
void listen_server_socket(global_resources_struct *global_resources) { if (listen(global_resources->server_sockfd, MAXPENDING)) perror_and_exit("listen"); }
int main(int argc, char *argv[]){ /* * 1. parse env QUERY_STRING * 2. check connection_server * 3. connect to server, and print response * 3.1. connect to server (non-blocking) * 3.2. read data from batch file, and send data as input to server * 3.3. get response from server, and print as html_version to stdout */ std::map<std::string, std::string> query_parameters; query_parameters = cgi::http_get_parameters(); std::vector<Request> all_requests; for( int i = 1; i <= 5; i++ ){ std::string host_name = "h" + std::to_string(i); std::string port_name = "p" + std::to_string(i); std::string batch_file_name = "f" + std::to_string(i); if( query_parameters.count(host_name) > 0 ){ std::string host = query_parameters[host_name]; int port = std::stoi(query_parameters[port_name]); std::string batch_file = query_parameters[batch_file_name]; all_requests.emplace_back(host, port, batch_file, all_requests.size()); } } std::fstream err_log; err_log.open("cgi_error.log", std::fstream::out); for( const auto& req: all_requests ){ err_log << req.addr.ipv4_addr_str << std::endl; err_log << req.addr.port_hbytes << std::endl; err_log << req.batch_file << std::endl; } /* part3 */ /* initialization of every Request * 1. make an connection * 2. open batch_file */ #if 0 // single connection Request req = all_requests[0]; req.connect_server(false); req.open_batch_file(); req.send_batch_file_data_to_server(); print_html_before_content(all_requests); while( 1 ){ // req.send_batch_file_data_to_server_once(); std::string msg; msg = req.read_server_response(1024, false); if( msg.empty() ){ close(req.server_fd); break; } nl2br(msg); print_html_content(req.id, msg); } print_html_after_content(); #endif int request_num = all_requests.size(); for( auto& req: all_requests ){ req.open_batch_file(); req.connect_server(true); } // std::cerr << "send out\n"; /* recieve msg from server and print out */ fd_set read_fds, write_fds; int max_fd = -1; FD_ZERO(&read_fds); for( const auto& req: all_requests ){ if( req.is_server_connect ){ FD_SET(req.server_fd, &read_fds); if( max_fd < req.server_fd ){ max_fd = req.server_fd; } } } max_fd += 1; err_log << "request_num start:" << request_num << std::endl; print_http_header(); print_html_before_content(all_requests); while( request_num > 0 ){ fd_set select_read_fds = read_fds; int s_ret = 0; s_ret = select(max_fd, &select_read_fds, NULL, NULL, NULL); err_log << "\nSELECT return: " << s_ret << std::endl; err_log << "request_num:" << request_num << std::endl; if( s_ret < 0 ) perror_and_exit("select error"); for( auto& req: all_requests ){ if( FD_ISSET(req.server_fd, &select_read_fds) ){ err_log << "fd " << req.server_fd << " can be read\n"; std::string msg; msg = req.read_server_response(1024, true); err_log << "msg: " << msg << "\n"; if( msg.empty() ){ /* this server has no response */ err_log << "FD_CLR: " << req.addr.ipv4_addr_str << std::endl; FD_CLR(req.server_fd, &read_fds); err_log << "FD_CLR finish: " << req.addr.port_hbytes << std::endl; close(req.server_fd); req.is_server_connect = false; request_num--; err_log << "request_num after clear:" << request_num << std::endl; continue; } nl2br(msg); print_html_content(req.id, msg); // write to socket. req.send_batch_file_data_to_server_once(); } } } err_log << "end of requests\n"; print_html_after_content(); err_log << "print_html_after_content() finish\n"; err_log.close(); return 0; }
int destroy(struct oflops_context *ctx) { char msg[1024]; struct timeval now; FILE *out = fopen(logfile, "w"); struct entry *np; long long t[3], t_sq[3], mean, std; int count[3], min_id[3], max_id[3]; int ch; float loss; int xid; gettimeofday(&now, NULL); printf("destroying code\n"); snprintf(msg, 1024, "OFPT_ERROR_DELAY:%lld", delay_false_modificaton); oflops_log(now, GENERIC_MSG, msg); snprintf(msg, 1024, "OFPT_INSERT_DELAY:%lld", delay_modificaton); oflops_log(now, GENERIC_MSG, msg); for(ch = 0; ch < ctx->n_channels-1; ch++) { count[ch] = 0; min_id[ch] = INT_MAX; max_id[ch] = INT_MIN; t[ch] = 0; t_sq[ch] = 0; } for (np = head.tqh_first; np != NULL; np = np->entries.tqe_next) { if(fprintf(out, "%lu;%lu.%06lu;%lu.%06lu;%d\n", (long unsigned int)np->id, (long unsigned int)np->snd.tv_sec, (long unsigned int)np->snd.tv_usec, (long unsigned int)np->rcv.tv_sec, (long unsigned int)np->rcv.tv_usec, np->ch) < 0) perror_and_exit("fprintf fail", 1); ch = np->ch - 1; count[ch]++; min_id[ch] = (np->id < min_id[ch])?np->id:min_id[ch]; max_id[ch] = (np->id > max_id[ch])?np->id:max_id[ch]; t[ch] += time_diff(&np->snd, &np->rcv); t_sq[ch] += time_diff(&np->snd, &np->rcv)*time_diff(&np->snd, &np->rcv); free(np); } for(ch = 0; ch < ctx->n_channels-1; ch++) { if(count[ch] == 0) continue; mean = t[ch]/count[ch]; std = (t_sq[ch]/count[ch]) - mean*mean; if(std >= 0) std = sqrt(std); else std = LONG_MAX; loss = (float)count[ch]/(float)(max_id[ch] - min_id[ch]); snprintf(msg, 1024, "statistics:port:%d:%lld:%lld:%.4f:%d", ctx->channels[ch + 1].of_port, mean, std, loss, count[ch]); oflops_log(now, GENERIC_MSG, msg); } t[0] = 0; t_sq[0] = 0; for (xid = 1 ; xid < trans_id; xid++) { t[0] +=delay[xid]; t_sq[0] += delay[xid]*delay[xid]; } std = (t_sq[0]/trans_id) - mean*mean; std = (std >= 0)?sqrt(std):LONG_MAX; snprintf(msg, 1024, "ofp_echo_statistics:%lld:%lld", t[0]/trans_id, std); oflops_log(now, GENERIC_MSG, msg); return 0; }
int socks5_connect(int client_sockfd, int *connect_sockfd_p) { uint8_t buffer[4]; if (read_all(client_sockfd, buffer, 4)) return -2; unsigned char ver = buffer[0]; unsigned char cmd = buffer[1]; unsigned char reserved = buffer[2]; unsigned char addr_type = buffer[3]; if (ver != SOCKS_VER) return -1; if (reserved != 0) return -1; if (!(addr_type == ATYP_IPV4 || addr_type == ATYP_DOMAIN || addr_type == ATYP_IPV6)) return -1; static address_union address; // thread unsafe switch (addr_type) { case ATYP_IPV4: { if (read_all(client_sockfd, address.ipv4, 4)) return -2; break; } case ATYP_IPV6: { if (read_all(client_sockfd, address.ipv6, 16)) return -2; break; } case ATYP_DOMAIN: { if (read_all(client_sockfd, buffer, 1)) return -2; unsigned char domain_name_len = buffer[0]; if (domain_name_len == 0) return -1; assert(sizeof(char) == 1); if (read_all(client_sockfd, address.domain_name, domain_name_len)) return -2; address.domain_name[domain_name_len] = 0; break; } } if (read_all(client_sockfd, buffer, 2)) return -2; unsigned int port = ntohs(*(uint16_t *)buffer); uint8_t resp_buf[10] = { SOCKS_VER, 0/*rep*/, 0/*rsv*/, ATYP_IPV4, 0, 0, 0, 0/*bind.ipv4*/, 0, 0/*bind.port*/ }; unsigned char rep; if (cmd == CMD_CONNECT) { rep = REP_SUCCEEDED; struct sockaddr *connect_addr; socklen_t connect_addr_len; int ret = make_sockaddr(addr_type, &address, port, &connect_addr, &connect_addr_len); assert(ret >= 0); if (ret > 0) { rep = ret; } else { int connect_sockfd = socket(connect_addr->sa_family, SOCK_STREAM, 0); if (connect_sockfd < 0) perror_and_exit("socket"); if (connect(connect_sockfd, connect_addr, connect_addr_len)) { if (errno == ECONNREFUSED || errno == ENETUNREACH || errno == ETIMEDOUT) { switch (errno) { case ECONNREFUSED: rep = REP_CONNECTION_REFUSED; break; case ETIMEDOUT: rep = REP_HOST_UNREACHABLE; break; case ENETUNREACH: rep = REP_NETWORK_UNREACHABLE; break; } if (close(connect_sockfd)) perror_and_exit("close"); } else perror_and_exit("connect"); } else { *connect_sockfd_p = connect_sockfd; } free(connect_addr); } } else { rep = REP_COMMAND_NOT_SUPPORTED; } resp_buf[1] = rep; if (write_all(client_sockfd, resp_buf, sizeof(resp_buf))) { if (rep == REP_SUCCEEDED) { if (close(*connect_sockfd_p)) perror_and_exit("close"); } return -2; } return (rep == REP_SUCCEEDED ? 0 : 1); }
/** * Initialization code with parameters * @param ctx */ int init(struct oflops_context *ctx, char * config_str) { char *pos = NULL; char *param = config_str; int len = strlen(config_str); char *value = NULL; char *action; struct ofp_action_output *act_out; //init counters finished = 0; struct timeval now; gettimeofday(&now, NULL); cli_param = strdup(config_str); while(*config_str == ' ') { config_str++; } param = config_str; while(1) { pos = index(param, ' '); if((pos == NULL)) { if (*param != '\0') { pos = param + strlen(param) + 1; } else break; } *pos='\0'; pos++; value = index(param,'='); *value = '\0'; value++; //fprintf(stderr, "param = %s, value = %s\n", param, value); if(value != NULL) { if(strcmp(param, "pkt_size") == 0) { //parse int to get pkt size pkt_size = strtol(value, NULL, 0); if((pkt_size < MIN_PKT_SIZE) && (pkt_size > MAX_PKT_SIZE)) perror_and_exit("Invalid packet size value", 1); } else if(strcmp(param, "data_rate") == 0) { //parse int to get rate of background data datarate = strtol(value, NULL, 0); if((datarate < 0) || (datarate > 1010)) perror_and_exit("Invalid data rate param(Values between 1 and 1010)", 1); } else if(strcmp(param, "probe_rate") == 0) { //parse int to get measurement probe rate proberate = strtol(value, NULL, 0); if((proberate <= 0) || (proberate >= 1010)) perror_and_exit("Invalid probe rate param(Value between 1 and 1010)", 1); } else if(strcmp(param, "action") == 0) { char *p = value; while((*p != ' ') && (*p != '\0') && (config_str + len > p)) { action = p; //find where value ends and set it to null to extract the string. p = index(p, ','); if(p == NULL) { p = config_str + len + 1; *p='\0'; } else { *p = '\0'; p++; } //set null char to split action param and action value param = index(action, '/'); if(param != NULL) { *param = '\0'; param++; } //check if action value is correct and append it at the end of the action list if(*action >= '0' && *action <= '9') { append_action((*action) - '0', param); } else if (*action == 'a') { append_action(10, param); } else { printf("invalid action: %1s", action); continue; } } } else if(strcmp(param, "table") == 0) { //parse int to get pkt size table = strtol(value, NULL, 0); if((table < 0) && (table > 2)) perror_and_exit("Invalid table number", 1); } else if(strcmp(param, "flows") == 0) { //parse int to get pkt size flows = strtol(value, NULL, 0); if(flows <= 0) perror_and_exit("Invalid flow number", 1); } else fprintf(stderr, "Invalid parameter:%s\n", param); param = pos; } } //calculate sendind interval if(datarate > 0) { data_snd_interval = (pkt_size * byte_to_bits * sec_to_usec) / (datarate * mbits_to_bits); fprintf(stderr, "Sending data interval : %u usec (pkt_size: %u bytes, rate: %u Mbits/sec )\n", (uint32_t)data_snd_interval, (uint32_t)pkt_size, (uint32_t)datarate); } else { fprintf(stderr, "background data probe is disabled\n"); data_snd_interval = 0; } probe_snd_interval = (pkt_size * byte_to_bits * sec_to_usec) / (proberate * mbits_to_bits); fprintf(stderr, "Sending probe interval : %u usec (pkt_size: %u bytes, rate: %u Mbits/sec )\n", (uint32_t)probe_snd_interval, (uint32_t)pkt_size, (uint32_t)proberate); //by default the new rule should be redirected to port 2 to make the measurement easier /* fprintf(stderr, "by default output packet to port 1\n"); */ /* command_len += sizeof(struct ofp_action_output); */ /* command = realloc(command, command_len); */ /* act_out = (struct ofp_action_output *) */ /* (command + (command_len - sizeof(struct ofp_action_output))); */ /* act_out->type = htons(0); */ /* act_out->len = htons(8); */ /* act_out->max_len = htons(0); */ /* act_out->port = htons(ctx->channels[OFLOPS_DATA3].of_port); */ return 0; }