--- /dev/null
+#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));
+ }
+}