9 #include "vtl_harness.h"
17 unsigned short g_fflags;
20 int g_do_local_ack = 0;
21 /* IP Address utility functions */
25 /* Global Pipe Descriptors */
26 int vtp_in_fd, vtp_out_fd;
29 /* Connection List Handling */
30 struct VTP_CON g_vtp_cons[MAX_VTP_CONS];
35 int add_vtp_con(RawEthernetPacket * pkt, unsigned long seq_num);
36 int find_vtp_con(RawEthernetPacket * pkt);
37 int find_remote_vtp_con(RawEthernetPacket * pkt);
40 int handle_fifo_pkt(RawEthernetPacket * pkt, struct in_addr server_addr);
41 int handle_tcp_pkt(RawEthernetPacket * pkt, struct in_addr server_addr);
42 int handle_rem_tcp_pkt(RawEthernetPacket * pkt);
43 int handle_control_pkt(RawEthernetPacket * pkt, struct in_addr server_addr);
44 int handle_config_pkt(RawEthernetPacket * pkt);
46 /* Packet functions */
47 int make_ack_pkt(RawEthernetPacket * pkt, int vcon_i);
48 int init_ack_template(RawEthernetPacket * pkt);
51 int main(int argc, char ** argv) {
58 RawEthernetPacket pkt;
59 RawEthernetPacket * recv_pkts;
63 debug_init("/tmp/vtp.1");
65 JRLDBG("Starting VTP Daemon\n");
67 for (i = 0; i < MAX_VTP_CONS; i++) {
68 g_vtp_cons[i].rem_seq_num = 0;
69 g_vtp_cons[i].dest_ip = 0;
70 g_vtp_cons[i].src_ip = 0;
71 g_vtp_cons[i].src_port = 0;
72 g_vtp_cons[i].dest_port = 0;
73 g_vtp_cons[i].tcp_timestamp = 0;
74 g_vtp_cons[i].in_use = false;
75 g_vtp_cons[i].next = -1;
76 g_vtp_cons[i].prev = -1;
84 vtp_in_fd = open(VTP_FIFO_RECVFILE, O_WRONLY);
85 JRLDBG("Opened RECVFILE pipe\n");
87 vtp_out_fd = open(VTP_FIFO_SENDFILE, O_RDONLY);
88 JRLDBG("Opened SENDFILE pipe\n");
91 if ((vtp_socket = vtp_init()) < 0) {
92 JRLDBG("VTP Transport Layer failed to initialize\n");
97 FD_SET(vtp_out_fd, &all_set);
100 FD_SET(vtp_socket, &all_set);
102 maxfd = (vtp_out_fd > vtp_socket) ? vtp_out_fd : vtp_socket ;
104 // block indefinately, because we have all the socks in the FDSET
115 int n_pkts_recvd = 0;
118 conns = select(maxfd + 1, &rset, NULL, NULL, tm_ptr);
119 if ((conns > 0) && (FD_ISSET(vtp_out_fd, &rset))) {
120 struct in_addr server_addr;
121 JRLDBG("Reception on vtp_out_fd\n");
122 // we got a packet on the FIFO
123 if (pkt.VtpUnserialize(vtp_out_fd, &server_addr) <= 0) {
124 JRLDBG("VNET Connection has closed. We are exiting\n");
127 handle_fifo_pkt(&pkt, server_addr);
130 //JRLDBG("Calling VTP Receive routine\n");
131 if ((vtp_socket == 0) || ((conns > 0) && (vtp_socket > 0) && FD_ISSET(vtp_socket, &rset))) {
132 if ((n_pkts_recvd = vtp_recv(&recv_pkts)) > 0) {
135 JRLDBG("Receive returned %d packets\n", n_pkts_recvd);
137 for (i = 0; i < n_pkts_recvd; i++) {
139 if (is_tcp_pkt(&(recv_pkts[i])) == 1) {
140 JRLDBG("Received a TCP packet\n");
141 if (g_do_local_ack == 1) {
142 handle_rem_tcp_pkt(&(recv_pkts[i]));
146 JRLDBG("Serializing packet %d to VNET\n", i);
147 recv_pkts[i].VtpSerialize(vtp_in_fd, &tmp);
163 int handle_fifo_pkt(RawEthernetPacket * pkt, struct in_addr server_addr) {
164 JRLDBG("Received a packet\n");
165 // if (strncmp(pkt->type,"et",2) == 0) {
166 if ((pkt->type[0] == 'e') && (pkt->type[1] == 't')) {
167 JRLDBG("Packet is Ethernet\n");
168 if (is_tcp_pkt(pkt) == 0) {
169 JRLDBG("Packet is a non-TCP Packet\n");
170 vtp_send(pkt, server_addr);
172 JRLDBG("Packet is a TCP Packet\n");
173 handle_tcp_pkt(pkt, server_addr);
176 } else if (strncmp(pkt->type,"lc",2) == 0) {
177 JRLDBG("Packet is a Link Control Packet\n");
178 handle_control_pkt(pkt, server_addr);
179 } else if (strncmp(pkt->type, "cf", 2) == 0) {
180 JRLDBG("Packet is a Configuration packet\n");
181 handle_config_pkt(pkt);
187 int handle_config_pkt(RawEthernetPacket * pkt) {
193 int handle_control_pkt(RawEthernetPacket* pkt, struct in_addr server_addr) {
194 if (strncmp(pkt->data,"con",3) == 0) {
195 struct in_addr con_addr;
196 unsigned short con_port = 0;
197 unsigned int offset = 3;
200 do_binary_to_string((unsigned char*)(&server_addr),ip);
201 JRLDBG("Control Message: Connect to %s\n", ip);
203 memcpy(&con_addr, pkt->data + offset,sizeof(struct in_addr));
204 offset += sizeof(struct in_addr);
205 con_port = *((unsigned short *)(pkt->data + offset));
207 vtp_connect(con_addr, con_port);
208 } else if (strncmp(pkt->data, "gwc", 3) == 0) {
209 struct in_addr con_addr;
210 unsigned short con_port;
211 unsigned int offset = 3;
213 memcpy(&con_addr, pkt->data + offset, sizeof(struct in_addr));
214 offset += sizeof(struct in_addr);
215 con_port = *((unsigned short *)(pkt->data + offset));
217 vtp_connect(con_addr, con_port);
219 } else if (strncmp(pkt->data, "stop", 4) == 0) {
227 int handle_tcp_pkt(RawEthernetPacket *pkt, struct in_addr server_addr) {
229 if (g_do_local_ack == 1) {
230 unsigned short ip_pkt_len = 0;
231 // unsigned char ip_hdr_len = (*(pkt->data + ETH_HDR_LEN) & 0x0f) << 2;
232 unsigned char ip_hdr_len = IP_HDR_LEN(pkt->data);
233 unsigned short * ip_pkt_len_ptr = (unsigned short *)(pkt->data + ETH_HDR_LEN + 2);
234 ip_pkt_len = ntohs(*ip_pkt_len_ptr);
236 JRLDBG("IP Header Length = %d(%x)\n", ip_hdr_len, *(pkt->data + ETH_HDR_LEN));
237 JRLDBG("IP Packet Length = %hu\n", ip_pkt_len);
239 if (is_syn_pkt(pkt) == 0) {
240 // we don't mess with connection establishment
242 unsigned long payload_len = 0;
243 unsigned short tcp_hdr_len = 0;
247 tcp_hdr_len = (*(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) & 0xf0) >> 2;
248 payload_len = ip_pkt_len - (ip_hdr_len + tcp_hdr_len);
250 if ((payload_len == 0) && (is_ack_pkt(pkt) == 1)) {
251 // we just kill empty acks.
255 vcon_i = find_remote_vtp_con(pkt);
257 // Create ACK and send it.
258 make_ack_pkt(pkt, vcon_i);
260 g_vtp_cons[vcon_i].ack_template.VtpSerialize(vtp_in_fd, &tmp);
263 if(is_ack_pkt(pkt) == 1) {
264 int vcon_i = find_remote_vtp_con(pkt);
266 make_ack_pkt(pkt, vcon_i);
268 g_vtp_cons[vcon_i].ack_template.VtpSerialize(vtp_in_fd, &tmp);
271 unsigned long * seq_num_ptr ;
272 unsigned long seq_num = 0;
273 unsigned long payload_len = 0;
274 unsigned short tcp_hdr_len = 0;
275 unsigned long ack = 0;
277 JRLDBG("Packet is a Syn Packet\n");
279 seq_num_ptr = (unsigned long *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 4);
280 seq_num = ntohl(*seq_num_ptr);
281 JRLDBG("Sequence Number = %lu\n", seq_num);
283 tcp_hdr_len = (*(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) & 0xf0) >> 2;
284 payload_len = ip_pkt_len - (ip_hdr_len + tcp_hdr_len);
286 JRLDBG("TCP Header Length = %hu\n", tcp_hdr_len);
287 JRLDBG("Payload Length = %lu\n", payload_len);
291 ack = (payload_len > 0) ? (seq_num + payload_len) : (seq_num + 1);
292 JRLDBG("Ack Num = %lu\n", ack);
298 vtp_send(pkt, server_addr);
303 int handle_rem_tcp_pkt(RawEthernetPacket * pkt) {
304 unsigned long * seq_num_ptr;
305 unsigned long seq_num;
306 unsigned char ip_hdr_len = IP_HDR_LEN(pkt->data);
308 seq_num_ptr = (unsigned long *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 4);
309 seq_num = ntohl(*seq_num_ptr);
310 JRLDBG("Received Packet, SeqNum = %lu\n", seq_num);
312 if (is_syn_pkt(pkt) == 1) {
315 add_vtp_con(pkt, seq_num);
316 JRLDBG("Received Syn Packet, SeqNum = %lu\n", seq_num);
318 unsigned short ip_pkt_len = 0;
319 unsigned short * ip_pkt_len_ptr = (unsigned short *)(pkt->data + ETH_HDR_LEN + 2);
320 unsigned long payload_len = 0;
321 unsigned short tcp_hdr_len = 0;
322 int i_vcon = find_vtp_con(pkt);
324 ip_pkt_len = ntohs(*ip_pkt_len_ptr);
326 tcp_hdr_len = (*(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) & 0xf0) >> 2;
328 if (tcp_hdr_len > 20) {
329 unsigned long ts = get_tcp_timestamp(pkt->data + ETH_HDR_LEN + ip_hdr_len + 20, tcp_hdr_len - 20);
330 JRLDBG("TCP Timestamp = %lu(%lu)\n", ts, (unsigned long)ntohl(ts));
331 g_vtp_cons[i_vcon].tcp_timestamp = ts;
334 payload_len = ip_pkt_len - (ip_hdr_len + tcp_hdr_len);
335 seq_num += payload_len;
336 JRLDBG("Received Data Packet, SeqNum = %lu\n", seq_num);
337 g_vtp_cons[i_vcon].rem_seq_num = seq_num;
338 JRLDBG("Remote Sequence Number (con: %d) = %lu\n", i_vcon, seq_num);
343 unsigned short tcp_cksum = 0;
345 *(unsigned long *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 8) = 0;
348 offset = ETH_HDR_LEN + ip_hdr_len + 13;
349 *(pkt->data + offset) &= 0xef;
352 *(unsigned short *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 16) = 0;
355 tcp_cksum = get_tcp_checksum(pkt, ip_pkt_len - ip_hdr_len);
358 *(unsigned short *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 16) = tcp_cksum;
369 int make_ack_pkt(RawEthernetPacket * pkt, int vcon_i) {
370 unsigned long * seq_num_ptr ;
371 unsigned long seq_num = 0;
372 unsigned long rem_seq_num = 0;
373 unsigned long payload_len = 0;
374 unsigned short tcp_hdr_len = 0;
375 unsigned long ack = 0;
376 unsigned long local_ts = 0;
377 unsigned short tcp_cksum = 0;
378 unsigned char ip_hdr_len = IP_HDR_LEN(pkt->data);
379 unsigned short ip_pkt_len = *(unsigned short *)(pkt->data + ETH_HDR_LEN + 2);
380 RawEthernetPacket * ack_pkt = &(g_vtp_cons[vcon_i].ack_template);
381 unsigned short ack_ip_pkt_len = *(unsigned short *)(ack_pkt->data + ETH_HDR_LEN + 2);
382 unsigned char ack_ip_hdr_len = IP_HDR_LEN(ack_pkt->data);
384 ip_pkt_len = ntohs(ip_pkt_len);
385 ack_ip_pkt_len = ntohs(ack_ip_pkt_len);
387 seq_num_ptr = (unsigned long *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 4);
388 seq_num = ntohl(*seq_num_ptr);
389 JRLDBG("Sequence Number = %lu\n", seq_num);
391 tcp_hdr_len = (*(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) & 0xf0) >> 2;
393 if (is_syn_pkt(pkt) == 1) {
396 payload_len = ip_pkt_len - (ip_hdr_len + tcp_hdr_len);
398 JRLDBG("TCP Header Length = %hu\n", tcp_hdr_len);
399 JRLDBG("Payload Length = %lu\n", payload_len);
401 ack = seq_num + payload_len;
402 JRLDBG("Ack Num = %lu\n", ack);
406 g_vtp_cons[vcon_i].ip_id--;
407 *(unsigned short *)(ack_pkt->data + ETH_HDR_LEN + 4) = htons(g_vtp_cons[vcon_i].ip_id);
409 // Recompute IP checksum
410 *(unsigned short *)(ack_pkt->data + ETH_HDR_LEN + 10) = 0;
411 *(unsigned short *)(ack_pkt->data + ETH_HDR_LEN + 10) = get_ip_checksum(ack_pkt);
414 // Set Sequence Number
415 rem_seq_num = htonl(g_vtp_cons[vcon_i].rem_seq_num);
416 *(unsigned long *)(ack_pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 4) = rem_seq_num;
420 *(unsigned long *)(ack_pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 8) = ack;
422 // Set TCP Timestamp option
423 local_ts = get_tcp_timestamp(pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 20, tcp_hdr_len - 20);
425 /* We use this for debugging:
426 * If the TCPDump trace shows timestamps with the value of '5' then they are our packets
429 *(unsigned long *)(ack_pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 24) = g_vtp_cons[vcon_i].tcp_timestamp;
430 //*(unsigned long *)(ack_pkt->data + ETH_HDR_LEN + ip_hdr_len + 24) = htonl(5);
433 *(unsigned long *)(ack_pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 28) = local_ts;
436 *(unsigned short *)(ack_pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 16) = 0;
439 tcp_cksum = get_tcp_checksum(ack_pkt, ack_ip_pkt_len - ack_ip_hdr_len);
442 *(unsigned short *)(ack_pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 16) = tcp_cksum;
451 /* Connection List Handling */
453 int find_vtp_con(RawEthernetPacket * pkt) {
456 unsigned long * src_addr;
457 unsigned long * dest_addr;
458 unsigned short * src_port;
459 unsigned short * dest_port;
460 unsigned char ip_hdr_len = IP_HDR_LEN(pkt->data);
462 src_addr = (unsigned long *)(pkt->data + ETH_HDR_LEN + 12);
463 dest_addr = (unsigned long *)(pkt->data + ETH_HDR_LEN + 16);
464 src_port = (unsigned short *)(pkt->data + ETH_HDR_LEN + ip_hdr_len);
465 dest_port = (unsigned short *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 2);
467 // for (i = 0; i < MAX_CONS; i++) {
468 FOREACH_VTP_CON(i,g_vtp_cons) {
469 if ((g_vtp_cons[i].dest_ip == *dest_addr) && (g_vtp_cons[i].src_ip == *src_addr) &&
470 (g_vtp_cons[i].dest_port = *dest_port) && (g_vtp_cons[i].src_port == *src_port)) {
479 /* An received packet has the header fields reversed wrt src/dest
480 * So we have to be able to index remote packets as well
482 int find_remote_vtp_con(RawEthernetPacket * pkt) {
485 unsigned long * src_addr;
486 unsigned long * dest_addr;
487 unsigned short * src_port;
488 unsigned short * dest_port;
489 unsigned char ip_hdr_len = IP_HDR_LEN(pkt->data);
491 src_addr = (unsigned long *)(pkt->data + ETH_HDR_LEN + 12);
492 dest_addr = (unsigned long *)(pkt->data + ETH_HDR_LEN + 16);
493 src_port = (unsigned short *)(pkt->data + ETH_HDR_LEN + ip_hdr_len);
494 dest_port = (unsigned short *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 2);
496 // for (i = 0; i < MAX_CONS; i++) {
497 FOREACH_VTP_CON(i,g_vtp_cons) {
498 if ((g_vtp_cons[i].src_ip == *dest_addr) && (g_vtp_cons[i].dest_ip == *src_addr) &&
499 (g_vtp_cons[i].src_port = *dest_port) && (g_vtp_cons[i].dest_port == *src_port)) {
508 int add_vtp_con(RawEthernetPacket * pkt, unsigned long seq_num) {
510 unsigned long * src_addr;
511 unsigned long * dest_addr;
512 unsigned short * src_port;
513 unsigned short * dest_port;
514 unsigned char ip_hdr_len = IP_HDR_LEN(pkt->data);
515 unsigned short tcp_hdr_len = (*(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) & 0xf0) >> 2;
517 src_addr = (unsigned long *)(pkt->data + ETH_HDR_LEN + 12);
518 dest_addr = (unsigned long *)(pkt->data + ETH_HDR_LEN + 16);
519 src_port = (unsigned short *)(pkt->data + ETH_HDR_LEN + ip_hdr_len);
520 dest_port = (unsigned short *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 2);
522 for (i = 0; i < MAX_VTP_CONS; i++) {
523 if (!(g_vtp_cons[i].in_use)) {
524 JRLDBG("Adding connection in slot %d\n", i);
525 g_vtp_cons[i].rem_seq_num = seq_num;
527 // ADD PACKET CONNECTION INFO
528 g_vtp_cons[i].dest_ip = *dest_addr;
529 g_vtp_cons[i].src_ip = *src_addr;
530 g_vtp_cons[i].src_port = *src_port;
531 g_vtp_cons[i].dest_port = *dest_port;
532 g_vtp_cons[i].ack_template = *pkt;
533 g_vtp_cons[i].ip_id = ntohs(*(unsigned short *)(pkt->data + ETH_HDR_LEN + 4));
535 init_ack_template(&(g_vtp_cons[i].ack_template));
537 if (tcp_hdr_len > 20) {
538 unsigned long ts = get_tcp_timestamp(pkt->data + ETH_HDR_LEN + ip_hdr_len + 20, tcp_hdr_len - 20);
539 JRLDBG("TCP Timestamp = %lu(%lu)\n", ts, (unsigned long)ntohl(ts));
540 g_vtp_cons[i].tcp_timestamp = ts;
543 g_vtp_cons[i].in_use = true;
545 if (g_first_vtp == -1)
548 g_vtp_cons[i].prev = g_last_vtp;
549 g_vtp_cons[i].next = -1;
551 if (g_last_vtp != -1) {
552 g_vtp_cons[g_last_vtp].next = i;
565 int init_ack_template(RawEthernetPacket * pkt) {
566 // We assume here that the ethernet and ip headers are ok, except for ip pkt length
567 // TCP is mostly right because its pulled off of a syn packet
568 // we need to zero the data, and reset the syn flag.
570 unsigned short IP_PACKET_LEN = 52;
571 unsigned short TCP_HEADER_LEN = 32;
572 unsigned char ip_hdr_len = IP_HDR_LEN(pkt->data);
573 unsigned short ip_pkt_len = 0;
574 unsigned short tcp_hdr_len = 0;
575 unsigned short payload_len = 0;
576 unsigned short * ip_pkt_len_ptr = (unsigned short *)(pkt->data + ETH_HDR_LEN + 2);
577 unsigned int offset = 0;
578 unsigned short ip_chksum = 0;
580 JRLDBG("--> Initializing ACK Template <--\n");
582 ip_pkt_len = ntohs(*ip_pkt_len_ptr);
583 JRLDBG("ip_pkt_len = %hu\n", ip_pkt_len);
585 tcp_hdr_len = (*(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) & 0xf0) >> 2;
586 payload_len = ip_pkt_len - (ip_hdr_len + tcp_hdr_len);
587 JRLDBG("tcp_hdr_len = %hu\n", tcp_hdr_len);
588 JRLDBG("payload_len = %hu\n", payload_len);
590 // set only the ack flags
591 offset = ETH_HDR_LEN + ip_hdr_len + 13;
592 *(pkt->data + offset) |= 0x10;
593 *(pkt->data + offset) &= 0xd0;
595 // set up tcp options
596 offset = ETH_HDR_LEN + ip_hdr_len + 20;
597 *(pkt->data + offset) = 0x01;
599 *(pkt->data + offset) = 0x01;
601 *(pkt->data + offset) = 0x08;
603 *(pkt->data + offset) = 0x0a;
605 // Set Header Lengths
606 // IP HEADER = 20 (same)
607 // IP PACKET LEN = 52
608 // TCP Header len = 32
610 ip_pkt_len = htons(IP_PACKET_LEN);
611 memcpy(pkt->data + ETH_HDR_LEN + 2, &ip_pkt_len, 2);
612 tcp_hdr_len = (TCP_HEADER_LEN << 2);
613 *(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) &= 0x0f;
614 *(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) |= tcp_hdr_len;
616 JRLDBG("Setting TEMPLATE TCPLEN = %2x\n", *(pkt->data + ETH_HDR_LEN +ip_hdr_len + 12));
618 // Set IP Header chksum
619 *(unsigned short *)(pkt->data + ETH_HDR_LEN + 10) = 0;
620 ip_chksum = get_ip_checksum(pkt);
621 *(unsigned short *)(pkt->data + ETH_HDR_LEN + 10) = ip_chksum;
624 // Set RawEthernetPacket size
625 pkt->set_size(IP_PACKET_LEN + ETH_HDR_LEN);
628 JRLDBG("--> ACK Template Initialized <--\n");