Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


added network server files
[palacios.git] / misc / network_servers / vtl / vtl_model.cc
diff --git a/misc/network_servers/vtl/vtl_model.cc b/misc/network_servers/vtl/vtl_model.cc
new file mode 100644 (file)
index 0000000..2b95abd
--- /dev/null
@@ -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));
+  }  
+}