9 #include "vtl_harness.h"
15 /* Connection List Handling */
16 struct VTL_CON g_vtl_cons[MAX_VTL_CONS];
21 int add_vtl_con(RawEthernetPacket * pkt);
22 int find_vtl_con(RawEthernetPacket * pkt);
25 int handle_local_tcp_pkt(RawEthernetPacket * pkt, iface_t * dev);
26 int handle_remote_tcp_pkt(RawEthernetPacket * pkt);
28 /* Packet functions */
29 int make_ack_pkt(RawEthernetPacket * pkt, int vcon_i);
30 int init_ack_template(RawEthernetPacket * pkt);
33 unsigned short ip_id_ctr = 1;
35 int main(int argc, char ** argv) {
36 RawEthernetPacket pkt;
37 RawEthernetPacket ack_pkt;
40 unsigned long src_addr;
42 debug_init("./vtl.log");
44 JRLDBG("Starting VTP Daemon\n");
46 for (i = 0; i < MAX_VTL_CONS; i++) {
47 g_vtl_cons[i].con_model.type = TCP_MODEL;
48 g_vtl_cons[i].in_use = false;
49 g_vtl_cons[i].next = -1;
50 g_vtl_cons[i].prev = -1;
58 src_addr = ToIPAddress(argv[2]);
59 dev = if_connect(argv[1]);
61 while (if_read_pkt(dev, &pkt) != -1) {
65 if (is_tcp_pkt(&pkt)) {
66 if (GET_IP_SRC(pkt.data) == src_addr) {
67 handle_local_tcp_pkt(&pkt, dev);
68 } else if (GET_IP_DST(pkt.data) == src_addr) {
69 if (GET_IP_ID(pkt.data) == ip_id_ctr -1) {
72 handle_remote_tcp_pkt(&pkt);
73 printf("Remote tcp packet\n");
86 int handle_local_tcp_pkt(RawEthernetPacket * pkt, iface_t * dev) {
87 printf("local tcp pkt\n");
88 RawEthernetPacket ack_pkt;
90 int index = find_vtl_con(pkt);
93 // packet in the system
94 sync_model(&(g_vtl_cons[index].con_model), pkt);
97 // dbg_dump_model(&(g_vtl_cons[index].con_model));
98 if (GET_TCP_DATA_LEN(pkt->data) > 0) {
99 create_empty_pkt(&(g_vtl_cons[index].con_model), &ack_pkt, INBOUND_PKT);
100 dbg_print_pkt_info(&ack_pkt);
101 if_write_pkt(dev, &ack_pkt);
105 if (is_syn_pkt(pkt)) {
108 index = add_vtl_con(pkt);
109 printf("Connection added at %d\n", index);
119 int handle_remote_tcp_pkt(RawEthernetPacket * pkt) {
122 index = find_vtl_con(pkt);
125 sync_model(&(g_vtl_cons[index].con_model), pkt);
126 g_vtl_cons[index].con_model.model.ip_model.dst.ip_id = ip_id_ctr++;
134 int find_vtl_con(RawEthernetPacket * pkt) {
139 FOREACH_VTL_CON(i,g_vtl_cons) {
140 if (is_model_pkt(&(g_vtl_cons[i].con_model), pkt)) {
150 int add_vtl_con(RawEthernetPacket * pkt) {
153 for (i = 0; i < MAX_VTL_CONS; i++) {
154 if (!(g_vtl_cons[i].in_use)) {
155 JRLDBG("Adding connection in slot %d\n", i);
157 initialize_model(&(g_vtl_cons[i].con_model), pkt);
158 g_vtl_cons[i].in_use = true;
160 dbg_dump_model(&(g_vtl_cons[i].con_model));
162 if (g_first_vtl == -1)
165 g_vtl_cons[i].prev = g_last_vtl;
166 g_vtl_cons[i].next = -1;
168 if (g_last_vtl != -1) {
169 g_vtl_cons[g_last_vtl].next = i;
186 int handle_tcp_pkt(RawEthernetPacket *pkt) {
189 unsigned short ip_pkt_len = 0;
190 // unsigned char ip_hdr_len = (*(pkt->data + ETH_HDR_LEN) & 0x0f) << 2;
191 unsigned char ip_hdr_len = IP_HDR_LEN(pkt->data);
192 unsigned short * ip_pkt_len_ptr = (unsigned short *)(pkt->data + ETH_HDR_LEN + 2);
193 ip_pkt_len = ntohs(*ip_pkt_len_ptr);
195 JRLDBG("IP Header Length = %d(%x)\n", ip_hdr_len, *(pkt->data + ETH_HDR_LEN));
196 JRLDBG("IP Packet Length = %hu\n", ip_pkt_len);
198 if (is_syn_pkt(pkt) == 0) {
199 // we don't mess with connection establishment
201 unsigned long payload_len = 0;
202 unsigned short tcp_hdr_len = 0;
206 tcp_hdr_len = (*(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) & 0xf0) >> 2;
207 payload_len = ip_pkt_len - (ip_hdr_len + tcp_hdr_len);
209 if ((payload_len == 0) && (is_ack_pkt(pkt) == 1)) {
210 // we just kill empty acks.
214 vcon_i = find_remote_vtp_con(pkt);
216 // Create ACK and send it.
217 make_ack_pkt(pkt, vcon_i);
219 g_vtl_cons[vcon_i].ack_template.VtpSerialize(vtp_in_fd, &tmp);
222 if(is_ack_pkt(pkt) == 1) {
223 int vcon_i = find_remote_vtp_con(pkt);
225 make_ack_pkt(pkt, vcon_i);
227 g_vtl_cons[vcon_i].ack_template.VtpSerialize(vtp_in_fd, &tmp);
230 unsigned long * seq_num_ptr ;
231 unsigned long seq_num = 0;
232 unsigned long payload_len = 0;
233 unsigned short tcp_hdr_len = 0;
234 unsigned long ack = 0;
236 JRLDBG("Packet is a Syn Packet\n");
238 seq_num_ptr = (unsigned long *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 4);
239 seq_num = ntohl(*seq_num_ptr);
240 JRLDBG("Sequence Number = %lu\n", seq_num);
242 tcp_hdr_len = (*(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) & 0xf0) >> 2;
243 payload_len = ip_pkt_len - (ip_hdr_len + tcp_hdr_len);
245 JRLDBG("TCP Header Length = %hu\n", tcp_hdr_len);
246 JRLDBG("Payload Length = %lu\n", payload_len);
250 ack = (payload_len > 0) ? (seq_num + payload_len) : (seq_num + 1);
251 JRLDBG("Ack Num = %lu\n", ack);
258 int handle_rem_tcp_pkt(RawEthernetPacket * pkt) {
259 unsigned long * seq_num_ptr;
260 unsigned long seq_num;
261 unsigned char ip_hdr_len = IP_HDR_LEN(pkt->data);
263 seq_num_ptr = (unsigned long *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 4);
264 seq_num = ntohl(*seq_num_ptr);
265 JRLDBG("Received Packet, SeqNum = %lu\n", seq_num);
267 if (is_syn_pkt(pkt) == 1) {
270 add_vtp_con(pkt, seq_num);
271 JRLDBG("Received Syn Packet, SeqNum = %lu\n", seq_num);
273 unsigned short ip_pkt_len = 0;
274 unsigned short * ip_pkt_len_ptr = (unsigned short *)(pkt->data + ETH_HDR_LEN + 2);
275 unsigned long payload_len = 0;
276 unsigned short tcp_hdr_len = 0;
277 int i_vcon = find_vtp_con(pkt);
279 ip_pkt_len = ntohs(*ip_pkt_len_ptr);
281 tcp_hdr_len = (*(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) & 0xf0) >> 2;
283 if (tcp_hdr_len > 20) {
284 unsigned long ts = get_tcp_timestamp(pkt->data + ETH_HDR_LEN + ip_hdr_len + 20, tcp_hdr_len - 20);
285 JRLDBG("TCP Timestamp = %lu(%lu)\n", ts, (unsigned long)ntohl(ts));
286 g_vtl_cons[i_vcon].tcp_timestamp = ts;
289 payload_len = ip_pkt_len - (ip_hdr_len + tcp_hdr_len);
290 seq_num += payload_len;
291 JRLDBG("Received Data Packet, SeqNum = %lu\n", seq_num);
292 g_vtl_cons[i_vcon].rem_seq_num = seq_num;
293 JRLDBG("Remote Sequence Number (con: %d) = %lu\n", i_vcon, seq_num);
298 unsigned short tcp_cksum = 0;
300 *(unsigned long *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 8) = 0;
303 offset = ETH_HDR_LEN + ip_hdr_len + 13;
304 *(pkt->data + offset) &= 0xef;
307 *(unsigned short *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 16) = 0;
310 tcp_cksum = get_tcp_checksum(pkt, ip_pkt_len - ip_hdr_len);
313 *(unsigned short *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 16) = tcp_cksum;
324 int make_ack_pkt(RawEthernetPacket * pkt, int vcon_i) {
325 unsigned long * seq_num_ptr ;
326 unsigned long seq_num = 0;
327 unsigned long rem_seq_num = 0;
328 unsigned long payload_len = 0;
329 unsigned short tcp_hdr_len = 0;
330 unsigned long ack = 0;
331 unsigned long local_ts = 0;
332 unsigned short tcp_cksum = 0;
333 unsigned char ip_hdr_len = IP_HDR_LEN(pkt->data);
334 unsigned short ip_pkt_len = *(unsigned short *)(pkt->data + ETH_HDR_LEN + 2);
335 RawEthernetPacket * ack_pkt = &(g_vtl_cons[vcon_i].ack_template);
336 unsigned short ack_ip_pkt_len = *(unsigned short *)(ack_pkt->data + ETH_HDR_LEN + 2);
337 unsigned char ack_ip_hdr_len = IP_HDR_LEN(ack_pkt->data);
339 ip_pkt_len = ntohs(ip_pkt_len);
340 ack_ip_pkt_len = ntohs(ack_ip_pkt_len);
342 seq_num_ptr = (unsigned long *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 4);
343 seq_num = ntohl(*seq_num_ptr);
344 JRLDBG("Sequence Number = %lu\n", seq_num);
346 tcp_hdr_len = (*(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) & 0xf0) >> 2;
348 if (is_syn_pkt(pkt) == 1) {
351 payload_len = ip_pkt_len - (ip_hdr_len + tcp_hdr_len);
353 JRLDBG("TCP Header Length = %hu\n", tcp_hdr_len);
354 JRLDBG("Payload Length = %lu\n", payload_len);
356 ack = seq_num + payload_len;
357 JRLDBG("Ack Num = %lu\n", ack);
361 g_vtl_cons[vcon_i].ip_id--;
362 *(unsigned short *)(ack_pkt->data + ETH_HDR_LEN + 4) = htons(g_vtl_cons[vcon_i].ip_id);
364 // Recompute IP checksum
365 *(unsigned short *)(ack_pkt->data + ETH_HDR_LEN + 10) = 0;
366 *(unsigned short *)(ack_pkt->data + ETH_HDR_LEN + 10) = get_ip_checksum(ack_pkt);
369 // Set Sequence Number
370 rem_seq_num = htonl(g_vtl_cons[vcon_i].rem_seq_num);
371 *(unsigned long *)(ack_pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 4) = rem_seq_num;
375 *(unsigned long *)(ack_pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 8) = ack;
377 // Set TCP Timestamp option
378 local_ts = get_tcp_timestamp(pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 20, tcp_hdr_len - 20);
380 // We use this for debugging:
381 // If the TCPDump trace shows timestamps with the value of '5' then they are our packets
384 *(unsigned long *)(ack_pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 24) = g_vtl_cons[vcon_i].tcp_timestamp;
385 // *(unsigned long *)(ack_pkt->data + ETH_HDR_LEN + ip_hdr_len + 24) = htonl(5);
388 *(unsigned long *)(ack_pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 28) = local_ts;
391 *(unsigned short *)(ack_pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 16) = 0;
394 tcp_cksum = get_tcp_checksum(ack_pkt, ack_ip_pkt_len - ack_ip_hdr_len);
397 *(unsigned short *)(ack_pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 16) = tcp_cksum;
406 // Connection List Handling //
410 int init_ack_template(RawEthernetPacket * pkt) {
411 // We assume here that the ethernet and ip headers are ok, except for ip pkt length
412 // TCP is mostly right because its pulled off of a syn packet
413 // we need to zero the data, and reset the syn flag.
415 unsigned short IP_PACKET_LEN = 52;
416 unsigned short TCP_HEADER_LEN = 32;
417 unsigned char ip_hdr_len = IP_HDR_LEN(pkt->data);
418 unsigned short ip_pkt_len = 0;
419 unsigned short tcp_hdr_len = 0;
420 unsigned short payload_len = 0;
421 unsigned short * ip_pkt_len_ptr = (unsigned short *)(pkt->data + ETH_HDR_LEN + 2);
422 unsigned int offset = 0;
423 unsigned short ip_chksum = 0;
425 JRLDBG("--> Initializing ACK Template <--\n");
427 ip_pkt_len = ntohs(*ip_pkt_len_ptr);
428 JRLDBG("ip_pkt_len = %hu\n", ip_pkt_len);
430 tcp_hdr_len = (*(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) & 0xf0) >> 2;
431 payload_len = ip_pkt_len - (ip_hdr_len + tcp_hdr_len);
432 JRLDBG("tcp_hdr_len = %hu\n", tcp_hdr_len);
433 JRLDBG("payload_len = %hu\n", payload_len);
435 // set only the ack flags
436 offset = ETH_HDR_LEN + ip_hdr_len + 13;
437 *(pkt->data + offset) |= 0x10;
438 *(pkt->data + offset) &= 0xd0;
440 // set up tcp options
441 offset = ETH_HDR_LEN + ip_hdr_len + 20;
442 *(pkt->data + offset) = 0x01;
444 *(pkt->data + offset) = 0x01;
446 *(pkt->data + offset) = 0x08;
448 *(pkt->data + offset) = 0x0a;
450 // Set Header Lengths
451 // IP HEADER = 20 (same)
452 // IP PACKET LEN = 52
453 // TCP Header len = 32
455 ip_pkt_len = htons(IP_PACKET_LEN);
456 memcpy(pkt->data + ETH_HDR_LEN + 2, &ip_pkt_len, 2);
457 tcp_hdr_len = (TCP_HEADER_LEN << 2);
458 *(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) &= 0x0f;
459 *(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) |= tcp_hdr_len;
461 JRLDBG("Setting TEMPLATE TCPLEN = %2x\n", *(pkt->data + ETH_HDR_LEN +ip_hdr_len + 12));
463 // Set IP Header chksum
464 *(unsigned short *)(pkt->data + ETH_HDR_LEN + 10) = 0;
465 ip_chksum = get_ip_checksum(pkt);
466 *(unsigned short *)(pkt->data + ETH_HDR_LEN + 10) = ip_chksum;
469 // Set RawEthernetPacket size
470 pkt->set_size(IP_PACKET_LEN + ETH_HDR_LEN);
473 JRLDBG("--> ACK Template Initialized <--\n");