X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=misc%2Fnetwork_servers%2Fvtl%2Fvtl_model.cc;fp=misc%2Fnetwork_servers%2Fvtl%2Fvtl_model.cc;h=2b95abd5a00b420dbf1114fef995b4a818c0eccf;hp=0000000000000000000000000000000000000000;hb=ac93f0773f4c6cef2f2f542240695a8706037d41;hpb=c016bb46bd68474161e275a5ace086c3fb810d9f diff --git a/misc/network_servers/vtl/vtl_model.cc b/misc/network_servers/vtl/vtl_model.cc new file mode 100644 index 0000000..2b95abd --- /dev/null +++ b/misc/network_servers/vtl/vtl_model.cc @@ -0,0 +1,562 @@ +#include "vtl_model.h" + + + +/* VTL Models */ + + + + + +vtl_model_t * new_vtl_model(model_type_t type) { + vtl_model_t * model = (vtl_model_t *)malloc(sizeof(vtl_model_t)); + + model->type = type; + + return model; +} + + +int initialize_ethernet_model(ethernet_model_t * model, RawEthernetPacket * pkt, int dir = OUTBOUND_PKT) { + ASSERT((model != NULL) && (pkt != NULL)); + + printf("initializing ethernet model\n"); + if (dir == OUTBOUND_PKT) { + GET_ETH_DST(pkt->data, model->dst.addr); + GET_ETH_SRC(pkt->data, model->src.addr); + } else if (dir == INBOUND_PKT) { + GET_ETH_DST(pkt->data, model->src.addr); + GET_ETH_SRC(pkt->data, model->dst.addr); + } else { + return -1; + } + + model->type = GET_ETH_TYPE(pkt->data); + + return 0; +} + +int initialize_ip_model(ip_model_t * model, RawEthernetPacket * pkt, int dir) { + ASSERT((model != NULL) && (pkt != NULL)); + + if (!is_ip_pkt(pkt)) { + return -1; + } + + if (dir == OUTBOUND_PKT) { + model->src.addr = GET_IP_SRC(pkt->data); + model->dst.addr = GET_IP_DST(pkt->data); + model->dst.ip_id = 1; + model->src.ip_id = GET_IP_ID(pkt->data); + model->src.ttl = GET_IP_TTL(pkt->data); + model->dst.ttl = 1; + } else if (dir == INBOUND_PKT) { + model->src.addr = GET_IP_DST(pkt->data); + model->dst.addr = GET_IP_SRC(pkt->data); + model->src.ip_id = 1; + model->dst.ip_id = GET_IP_ID(pkt->data); + model->src.ttl = 1; + model->dst.ttl = GET_IP_TTL(pkt->data); + } else { + return -1; + } + + model->version = GET_IP_VERSION(pkt->data); + model->proto = GET_IP_PROTO(pkt->data); + + if (initialize_ethernet_model(&(model->ethernet), pkt, dir) == -1) { + return -1; + } + + return 0; +} + +int initialize_tcp_model(tcp_model_t * model, RawEthernetPacket * pkt, int dir) { + ASSERT((model != NULL) && (pkt != NULL)); + + tcp_opts_t options; + + if (!is_tcp_pkt(pkt)) { + return -1; + } + + parse_tcp_options(&options, pkt); + + if (dir == OUTBOUND_PKT) { + model->src.port = GET_TCP_SRC_PORT(pkt->data); + model->dst.port = GET_TCP_DST_PORT(pkt->data); + model->src.seq_num = compute_next_tcp_seq_num(pkt); + model->src.last_ack = GET_TCP_ACK_NUM(pkt->data); + model->src.win = GET_TCP_WIN(pkt->data); + model->src.mss = options.mss; + model->src.ts = options.local_ts; + model->dst.mss = 0; + model->dst.ts = 0; + } else if (dir == INBOUND_PKT) { + model->src.port = GET_TCP_DST_PORT(pkt->data); + model->dst.port = GET_TCP_SRC_PORT(pkt->data); + model->dst.last_ack = GET_TCP_ACK_NUM(pkt->data); + model->src.seq_num = 1; + model->dst.seq_num = compute_next_tcp_seq_num(pkt); + model->dst.win = GET_TCP_WIN(pkt->data); + model->dst.mss = options.mss; + model->dst.ts = options.local_ts; + model->src.mss = 0; + model->src.ts = 0; + } else { + return -1; + } + + if (initialize_ip_model(&(model->ip), pkt, dir) == -1) { + return -1; + } + + return 0; +} + +int initialize_udp_model(udp_model_t * model, RawEthernetPacket * pkt, int dir) { + ASSERT((model != NULL) && (pkt != NULL)); + + if (!is_udp_pkt(pkt)) { + return -1; + } + + if (dir == OUTBOUND_PKT) { + model->src.port = GET_UDP_SRC_PORT(pkt->data); + model->dst.port = GET_UDP_DST_PORT(pkt->data); + } else if (dir == INBOUND_PKT) { + model->src.port = GET_UDP_DST_PORT(pkt->data); + model->dst.port = GET_UDP_SRC_PORT(pkt->data); + } else { + return -1; + } + + if (initialize_ip_model(&(model->ip), pkt, dir) == -1) { + return -1; + } + + return 0; +} + + + +int initialize_model(vtl_model_t * model, RawEthernetPacket * pkt, int dir) { + ASSERT((model != NULL) && (pkt != NULL)); + + if (model->type == TCP_MODEL) { + return initialize_tcp_model(&(model->model.tcp_model), pkt, dir); + } else if (model->type == UDP_MODEL) { + return initialize_udp_model(&(model->model.udp_model), pkt, dir); + } else if (model->type == IP_MODEL) { + } else if (model->type == ETHERNET_MODEL) { + } + + return -1; +} + + + +int is_ethernet_model_pkt(ethernet_model_t * model, RawEthernetPacket * pkt) { + ASSERT((model != NULL) && (pkt != NULL)); + + if ((memcmp(model->src.addr, ETH_SRC(pkt->data), 6) == 0) && + (memcmp(model->dst.addr, ETH_DST(pkt->data), 6) == 0)) { + return OUTBOUND_PKT; + } else if ((memcmp(model->src.addr, ETH_DST(pkt->data), 6) == 0) && + (memcmp(model->dst.addr, ETH_SRC(pkt->data), 6) == 0)) { + return INBOUND_PKT; + } + + return INVALID_PKT; +} + +int is_ip_model_pkt(ip_model_t * model, RawEthernetPacket * pkt) { + ASSERT((model != NULL) && (pkt != NULL)); + + if (!is_ip_pkt(pkt)) { + return INVALID_PKT; + } + + if ((model->src.addr == GET_IP_SRC(pkt->data)) && + (model->dst.addr == GET_IP_DST(pkt->data))) { + return OUTBOUND_PKT; + } else if ((model->src.addr == GET_IP_DST(pkt->data)) && + (model->dst.addr == GET_IP_SRC(pkt->data))) { + return INBOUND_PKT; + } + + return INVALID_PKT; +} + + +int is_tcp_model_pkt(tcp_model_t * model, RawEthernetPacket * pkt) { + ASSERT((model != NULL) && (pkt != NULL)); + int ip_ret; + + if (!is_tcp_pkt(pkt)) { + return INVALID_PKT; + } + + if ((ip_ret = is_ip_model_pkt(&(model->ip), pkt)) == INVALID_PKT) { + return INVALID_PKT; + } + + + if (ip_ret == OUTBOUND_PKT) { + if ((model->src.port == GET_TCP_SRC_PORT(pkt->data)) && + (model->dst.port == GET_TCP_DST_PORT(pkt->data))) { + return OUTBOUND_PKT; + } + } else if (ip_ret == INBOUND_PKT) { + if ((model->src.port == GET_TCP_DST_PORT(pkt->data)) && + (model->dst.port == GET_TCP_SRC_PORT(pkt->data))) { + return INBOUND_PKT; + } + } + return INVALID_PKT; +} + +int is_udp_model_pkt(udp_model_t * model, RawEthernetPacket * pkt) { + ASSERT((model != NULL) && (pkt != NULL)); + int ip_ret; + + if (!is_udp_pkt(pkt)) { + return INVALID_PKT; + } + + if ((ip_ret = is_ip_model_pkt(&(model->ip), pkt)) == INVALID_PKT) { + return INVALID_PKT; + } + + if (ip_ret == OUTBOUND_PKT) { + if ((model->src.port == GET_UDP_SRC_PORT(pkt->data)) && + (model->dst.port == GET_UDP_DST_PORT(pkt->data))) { + return OUTBOUND_PKT; + } + } else if (ip_ret == INBOUND_PKT) { + if ((model->src.port == GET_UDP_DST_PORT(pkt->data)) && + (model->dst.port == GET_UDP_SRC_PORT(pkt->data))) { + return INBOUND_PKT; + } + } + + return INBOUND_PKT; +} + +int is_model_pkt(vtl_model_t * model, RawEthernetPacket * pkt) { + ASSERT((model != NULL) && (pkt != NULL)); + + if (model->type == TCP_MODEL) { + return is_tcp_model_pkt(&(model->model.tcp_model), pkt); + } + + return INVALID_PKT; +} + + +int sync_ip_model(ip_model_t * model, RawEthernetPacket * pkt) { + ASSERT((model != NULL) && (pkt != NULL)); + + int ip_ret; + + ip_ret = is_ip_model_pkt(model, pkt); + + if (ip_ret == OUTBOUND_PKT) { + model->src.ip_id = GET_IP_ID(pkt->data); + model->src.ttl = GET_IP_TTL(pkt->data); + } else if (ip_ret == INBOUND_PKT) { + model->dst.ip_id = GET_IP_ID(pkt->data); + model->dst.ttl = GET_IP_TTL(pkt->data); + } else { + return -1; + } + + return 0; +} + + +int sync_tcp_model(tcp_model_t * model, RawEthernetPacket * pkt) { + ASSERT((model != NULL) && (pkt != NULL)); + int tcp_ret; + tcp_opts_t options; + int has_opts = 0; + + tcp_ret = is_tcp_model_pkt(model, pkt); + + has_opts = parse_tcp_options(&options, pkt); + + if (tcp_ret == OUTBOUND_PKT) { + model->src.seq_num = compute_next_tcp_seq_num(pkt); + model->src.last_ack = GET_TCP_ACK_NUM(pkt->data); + model->src.win = GET_TCP_WIN(pkt->data); + if (has_opts == 0) { + model->src.mss = options.mss; + model->src.ts = options.local_ts; + } + } else if (tcp_ret == INBOUND_PKT) { + model->dst.last_ack = GET_TCP_ACK_NUM(pkt->data); + model->dst.seq_num = compute_next_tcp_seq_num(pkt); + model->dst.win = GET_TCP_WIN(pkt->data); + if (has_opts == 0) { + model->dst.mss = options.mss; + model->dst.ts = options.local_ts; + } + } else { + return -1; + } + + if (sync_ip_model(&(model->ip), pkt) == -1) { + return -1; + } + + return 0; +} + + +int sync_udp_model(udp_model_t * model, RawEthernetPacket * pkt) { + ASSERT((model != NULL) && (pkt != NULL)); + int udp_ret; + + udp_ret = is_udp_model_pkt(model, pkt); + + if (udp_ret == INVALID_PKT) { + return -1; + } + + if (sync_ip_model(&(model->ip), pkt) == -1) { + return -1; + } + + return 0; +} + +int sync_model(vtl_model_t * model, RawEthernetPacket * pkt) { + + if (model->type == TCP_MODEL) { + return sync_tcp_model(&(model->model.tcp_model), pkt); + } else if (model->type == IP_MODEL) { + return sync_ip_model(&(model->model.ip_model), pkt); + } + return -1; +} + +int create_empty_ethernet_pkt(ethernet_model_t * model, RawEthernetPacket * pkt, int dir) { + if (dir == OUTBOUND_PKT) { + SET_ETH_SRC(pkt->data, model->src.addr); + SET_ETH_DST(pkt->data, model->dst.addr); + } else if (dir == INBOUND_PKT) { + SET_ETH_SRC(pkt->data, model->dst.addr); + SET_ETH_DST(pkt->data, model->src.addr); + } + SET_ETH_TYPE(pkt->data, model->type); + pkt->set_size(ETH_HDR_LEN); + + return 0; +} + + +int create_empty_ip_pkt(ip_model_t * model, RawEthernetPacket * pkt, int dir) { + create_empty_ethernet_pkt(&(model->ethernet), pkt, dir); + + SET_IP_VERSION(pkt->data, model->version); + SET_IP_HDR_LEN(pkt->data, 20); + SET_IP_SVC_TYPE(pkt->data, 0); + SET_IP_TOTAL_LEN(pkt->data, 20); // WE ARE JUST AN EMPTY PACKET HERE + SET_IP_FLAGS(pkt->data, 0); + SET_IP_FRAG(pkt->data, 0); + SET_IP_PROTO(pkt->data, model->proto); + + + if (dir == OUTBOUND_PKT) { + SET_IP_ID(pkt->data, model->src.ip_id + 1); + SET_IP_TTL(pkt->data, model->src.ttl); + SET_IP_SRC(pkt->data, model->src.addr); + SET_IP_DST(pkt->data, model->dst.addr); + } else if (dir == INBOUND_PKT) { + SET_IP_ID(pkt->data, model->dst.ip_id + 1); + SET_IP_TTL(pkt->data, model->dst.ttl); + // SET_IP_TTL(pkt->data, 5); + SET_IP_SRC(pkt->data, model->dst.addr); + SET_IP_DST(pkt->data, model->src.addr); + } + + compute_ip_checksum(pkt); + pkt->set_size(compute_pkt_size(pkt)); + + return 0; +} + +int create_empty_tcp_pkt(tcp_model_t * model, RawEthernetPacket * pkt, int dir) { + create_empty_ip_pkt(&(model->ip), pkt, dir); + + SET_TCP_HDR_LEN(pkt->data, 20); + SET_TCP_RSVD(pkt->data, 0); + SET_TCP_FLAGS(pkt->data, 0); + SET_TCP_URG_PTR(pkt->data, 0); + + if (dir == OUTBOUND_PKT) { + SET_TCP_SRC_PORT(pkt->data, model->src.port); + SET_TCP_DST_PORT(pkt->data, model->dst.port); + SET_TCP_SEQ_NUM(pkt->data, model->src.seq_num); + + // This is kind of weird + // We set the ack number to last ack that was sent on the actual channel + // We want to insert packets into the connection without messing things up + // So we don't want to ack data that hasn't necessarily been received + // Since we're blowing away the seq_num sequence anyway, this might not matter + // SET_TCP_ACK_NUM(pkt->data, model->src.last_ack); + SET_TCP_ACK_NUM(pkt->data, model->dst.seq_num); + SET_TCP_ACK_FLAG(pkt->data); + + SET_TCP_WIN(pkt->data, model->src.win); + + } else if (dir == INBOUND_PKT) { + SET_TCP_SRC_PORT(pkt->data, model->dst.port); + SET_TCP_DST_PORT(pkt->data, model->src.port); + + SET_TCP_SEQ_NUM(pkt->data, model->dst.seq_num); + + // This is kind of weird + // We set the ack number to last ack that was sent on the actual channel + // We want to insert packets into the connection without messing things up + // So we don't want to ack data that hasn't necessarily been received + // Since we're blowing away the seq_num sequence anyway, this might not matter + //SET_TCP_ACK_NUM(pkt->data, model->dst.last_ack); + SET_TCP_ACK_NUM(pkt->data, model->src.seq_num); + + SET_TCP_ACK_FLAG(pkt->data); + + SET_TCP_WIN(pkt->data, model->dst.win); + } + + + SET_IP_TOTAL_LEN(pkt->data, GET_IP_HDR_LEN(pkt->data) + GET_TCP_HDR_LEN(pkt->data)); + pkt->set_size(compute_pkt_size(pkt)); + + compute_ip_checksum(pkt); + + compute_tcp_checksum(pkt); + + JRLDBG("tcp_len = %d\n", GET_TCP_HDR_LEN(pkt->data)); + + + // Set the ip hdr len + + return 0; +} + + +int create_empty_udp_pkt(udp_model_t * model, RawEthernetPacket * pkt, int dir) { + create_empty_ip_pkt(&(model->ip), pkt, dir); + + if (dir == OUTBOUND_PKT) { + SET_UDP_SRC_PORT(pkt->data, model->src.port); + SET_UDP_DST_PORT(pkt->data, model->dst.port); + } else if (dir == INBOUND_PKT) { + SET_UDP_SRC_PORT(pkt->data, model->dst.port); + SET_UDP_DST_PORT(pkt->data, model->src.port); + } + SET_UDP_LEN(pkt->data, 8); + SET_IP_TOTAL_LEN(pkt->data, GET_IP_HDR_LEN(pkt->data) + GET_UDP_LEN(pkt->data)); + + compute_ip_checksum(pkt); + compute_udp_checksum(pkt); + + return 0; +} + +int create_empty_pkt(vtl_model_t * model, RawEthernetPacket * pkt, int dir) { + if (model->type == TCP_MODEL) { + return create_empty_tcp_pkt(&(model->model.tcp_model), pkt, dir); + } else if (model->type == UDP_MODEL) { + return create_empty_udp_pkt(&(model->model.udp_model), pkt, dir); + } else if (model->type == IP_MODEL) { + return create_empty_ip_pkt(&(model->model.ip_model), pkt, dir); + } + return -1; +} + + + + +void dbg_dump_eth_model(ethernet_model_t * model) { + char src_mac[6]; + char dst_mac[6]; + + printf("ETHERNET MODEL {\n"); + + printf("\tType: %s\n", get_eth_protocol(model->type)); + + mac_to_string(model->src.addr, src_mac); + printf("\tSrc Host {\n"); + printf("\t\taddr: %s\n", src_mac); + printf("\t}\n"); + + mac_to_string(model->dst.addr, dst_mac); + printf("\tDST Host {\n"); + printf("\t\taddr: %s\n", dst_mac); + printf("\t}\n"); + printf("}\n"); +} + + + +void dbg_dump_ip_model(ip_model_t * model) { + dbg_dump_eth_model(&(model->ethernet)); + + printf("IP MODEL {\n"); + printf("\tVersion: %d\n", model->version); + printf("\tProtocol: %s\n", get_ip_protocol(model->proto)); + + printf("\tSrc Host {\n"); + printf("\t\taddr: %s\n", ip_to_string(model->src.addr)); + printf("\t\tIP ID: %lu\n", model->src.ip_id); + printf("\t\tttl: %d\n", model->src.ttl); + printf("\t}\n"); + + printf("\tDst Host {\n"); + printf("\t\taddr: %s\n", ip_to_string(model->dst.addr)); + printf("\t\tIP ID: %lu\n", model->dst.ip_id); + printf("\t\tttl: %d\n", model->dst.ttl); + printf("\t}\n"); + + printf("}\n"); +} + +void dbg_dump_tcp_model(tcp_model_t * model) { + dbg_dump_ip_model(&(model->ip)); + + printf("TCP MODEL {\n"); + printf("\tSrc Host {\n"); + printf("\t\tport: %hu\n", model->src.port); + printf("\t\tseq: %lu\n", (unsigned long)(model->src.seq_num)); + printf("\t\tlast ack: %lu\n", (unsigned long)(model->src.last_ack)); + printf("\t\tWin Size: %hu\n", model->src.win); + printf("\t\tTimestamp: %lu\n", (unsigned long)(model->src.ts)); + printf("\t\tMSS: %hu\n", model->src.mss); + + printf("\t}\n"); + + printf("\tDst Host {\n"); + printf("\t\tport: %hu\n", model->dst.port); + printf("\t\tseq: %lu\n", (unsigned long)(model->dst.seq_num)); + printf("\t\tlast ack: %lu\n", (unsigned long)(model->dst.last_ack)); + printf("\t\tWin Size: %hu\n", model->dst.win); + printf("\t\tTimestamp: %lu\n", (unsigned long)(model->dst.ts)); + printf("\t\tMSS: %hu\n", model->dst.mss); + printf("\t}\n"); + + + printf("}\n"); + +} + + + +void dbg_dump_model(vtl_model_t * model) { + if (model->type == TCP_MODEL) { + dbg_dump_tcp_model(&(model->model.tcp_model)); + } else if (model->type == IP_MODEL) { + dbg_dump_ip_model(&(model->model.ip_model)); + } +}