Ejemplo n.º 1
0
/*
 * Decompress the TCP data of an SKB.
 */
int tcp_decompress(__u8 *ippacket, __u8 *lzbuffer,
		qlz_state_decompress *state_decompress) {
	struct iphdr *iph = NULL;
	struct tcphdr *tcph = NULL;
	__u16 oldsize = 0, newsize = 0; /* Store old, and new size of the TCP data. */
	__u8 *tcpdata = NULL; /* Starting location for the TCP data. */
	char message[LOGSZ];

	if (DEBUG_COMPRESSION == true) {
		sprintf(message, "[OpenNOP]: Entering into TCP DECOMPRESS \n");
		logger(LOG_INFO, message);
	}

	if ((ippacket != NULL) && (NULL != state_decompress)) { // If the skb or state_decompress is NULL abort compression.
		iph = (struct iphdr *) ippacket; // Access ip header.
		memset(state_decompress, 0, sizeof(qlz_state_decompress));

		if ((iph->protocol == IPPROTO_TCP)) { // If this is not a TCP segment abort compression.
			tcph = (struct tcphdr *) (((u_int32_t *) ippacket) + iph->ihl); // Access tcp header.
			oldsize = (__u16)(ntohs(iph->tot_len) - iph->ihl * 4) - tcph->doff
					* 4;

			tcpdata = (__u8 *) tcph + tcph->doff * 4; // Find starting location of the TCP data.

			if ((oldsize > 0) && (lzbuffer != NULL)) {

				newsize = qlz_decompress((char *) tcpdata, (char *) lzbuffer,
						state_decompress);
				memmove(tcpdata, lzbuffer, newsize); // Move decompressed data to packet.
				iph->tot_len = htons(ntohs(iph->tot_len) + (newsize - oldsize));// Fix packet length.
				__set_tcp_option((__u8 *) iph, 33, 3, 0); // Set compression flag to 0.
/*
				tcph->seq = htonl(ntohl(tcph->seq) - 8000); // Decrease SEQ number.
*/

				if (DEBUG_COMPRESSION == true) {
					sprintf(
							message,
							"[OpenNOP] Decompressing [%d] size of data to [%d] \n",
							oldsize, newsize);
					logger(LOG_INFO, message);
				}
				// return 1;
				// fruiz return amount of data expansion
				return newsize-oldsize;
			}
		}
	}
	return -1;
}
Ejemplo n.º 2
0
/*
 * This sends a keep alive message to the specified IP.
 * It does not tag the packet with the Accelerator ID this
 * prevents the keepalive messages from recreating dead sessions
 * in remote Accelerators.
 */
void sendkeepalive
(__u32 saddr, __u16 source, __u32 seq,
__u32 daddr, __u16 dest, __u32 ack_seq){
	char packet[BUFSIZE];
	struct iphdr *iph = NULL;
	struct tcphdr *tcph = NULL;
	struct sockaddr_in sin, din;
	__u16 tcplen;

	memset(packet, 0, BUFSIZE);

	sin.sin_family = AF_INET;
	din.sin_family = AF_INET;
	
	sin.sin_port = source;
	din.sin_port = dest;
	
	sin.sin_addr.s_addr = saddr;
	din.sin_addr.s_addr = daddr;

	iph = (struct iphdr *)packet;
	iph->ihl = 5; // IP header length.
	iph->version = 4; // IP version 4.
	iph->tos = 0; // No TOS.
	iph->tot_len=htons(sizeof(struct iphdr) + sizeof(struct tcphdr)); // L3 + L4 header length.
	iph->id = 0; // What?
	iph->frag_off = 0; // No fragmenting.
	iph->ttl = 64; // Set a TTL.
	iph->protocol = IPPROTO_TCP; // TCP protocol.
	iph->check = 0; // No IP checksum yet.
	iph->saddr = saddr; // Source IP.
	iph->daddr = daddr; // Dest IP.
	
	tcph = (struct tcphdr *) (((u_int32_t *)iph) + iph->ihl);
	tcph->check = 0; // No TCP checksum yet.
	tcph->source = source; // Source TCP Port.
	tcph->dest = dest; // Destination TCP Port.
	tcph->seq = htonl(seq - 1); // Current SEQ minus one is used for TCP keepalives.
	tcph->ack_seq = htonl( ack_seq - 1); // Ummm not sure yet.
	tcph->res1 = 0; // Not sure.
	tcph->doff = 5; // TCP Offset.  At least 5 if there are no TCP options.
	tcph->fin = 0; // FIN flag.
	tcph->syn = 0; // SYN flag.
	tcph->rst = 0; // RST flag.
	tcph->psh = 0; // PSH flag.
	tcph->ack = 1; // ACK flag.
	tcph->urg = 0; // URG flag.
	
	__set_tcp_option((__u8 *)iph,32,6,localID); // Add the Accelerator ID to this packet.
	
	tcplen = ntohs(iph->tot_len) - iph->ihl*4;
	tcph->check = 0;
	tcph->check = tcp_sum_calc(tcplen,
		(unsigned short *)&iph->saddr,
		(unsigned short *)&iph->daddr,
		(unsigned short *)tcph);
 	iph->check = 0;
 	iph->check = ip_sum_calc(iph->ihl*4,
		(unsigned short *)iph);
	
	
	if(sendto(rawsock, packet, ntohs(iph->tot_len), 0, (struct sockaddr *)&din, sizeof(din)) < 0){
		printf("sendto() error\n");
	}
	
	return;
}
Ejemplo n.º 3
0
/*
 * Deoptimize the TCP data of an SKB.
 */
int tcp_deoptimize(pDeduplicator pd, __u8 *ippacket, __u8 *regenerated_packet) {

	struct iphdr *iph = NULL;
	struct tcphdr *tcph = NULL;
	__u16 oldsize = 0, newsize = 0; /* Store old, and new size of the TCP data. */
	__u8 *tcpdata = NULL; /* Starting location for the TCP data. */
	char message[LOGSZ];
	UncompReturnStatus status;
	

	if (DEBUG_DEDUPLICATION1 == true) {
		sprintf(message, "[SDEDUP]: Entering into TCP DEOPTIMIZATION \n");
		logger(LOG_INFO, message);
	}

	if ((ippacket != NULL)) { // If the skb or state_decompress is NULL abort compression.
		iph = (struct iphdr *) ippacket; // Access ip header.

		if ((iph->protocol == IPPROTO_TCP)) { // If this is not a TCP segment abort compression.

			if (DEBUG_DEDUPLICATION == true) {
				sprintf(message, "[SDEDUP]: IP Packet ID %u\n", ntohs(iph->id));
				logger(LOG_INFO, message);
			}

			tcph = (struct tcphdr *) (((u_int32_t *) ippacket) + iph->ihl); // Access tcp header.
			oldsize = (__u16)(ntohs(iph->tot_len) - iph->ihl * 4) - tcph->doff* 4;
			tcpdata = (__u8 *) tcph + tcph->doff * 4; // Find starting location of the TCP data.

			if ((oldsize > 0) && (regenerated_packet != NULL)) {

#ifdef BASIC
				if(deoptimize(tcpdata, oldsize, regenerated_packet, &newsize) == 2)
					return HASH_NOT_FOUND;
#endif

#ifdef ROLLING
				uncomp(pd,regenerated_packet, &newsize, tcpdata, oldsize, &status);
				if(status.code == UNCOMP_FP_NOT_FOUND)
					return HASH_NOT_FOUND;
#endif

				memmove(tcpdata, regenerated_packet, newsize); // Move decompressed data to packet.
				iph->tot_len = htons(ntohs(iph->tot_len) + (newsize - oldsize));// Fix packet length.
				__set_tcp_option((__u8 *) iph, 31, 3, 0); // Set compression flag to 0.
                    /* Bellido: change from decreasing seq number to changing most significant bit
				tcph->seq = htonl(ntohl(tcph->seq) - 8000); // Decrease SEQ number.
                */
                tcph->seq = htonl(ntohl(tcph->seq) ^ 1 << 31 ); // Change most significant bit

				if (DEBUG_DEDUPLICATION == true) {
					sprintf( message,
							"[SDEDUP]: Decompressing [%d] size of data to [%d] \n",
							oldsize, newsize);
					logger(LOG_INFO, message);
				}
				// return OK;
				// fruiz return amount of expanded data
				if (newsize >= oldsize) return newsize-oldsize; else return ERROR;
			}
		}
	}

	if (DEBUG_DEDUPLICATION == true) {
		sprintf( message, "[SDEDUP]: Packet NULL\n");
		logger(LOG_INFO, message);
	}
	return ERROR;
}
Ejemplo n.º 4
0
/*
 * Optimize the TCP data of an SKB.
 */
unsigned int tcp_optimize(pDeduplicator pd, __u8 *ippacket, __u8 *buffered_packet) {

	struct iphdr *iph = NULL;
	struct tcphdr *tcph = NULL;
	__u16 oldsize = 0, newsize = 0; /* Store old, and new size of the TCP data. */
	__u8 *tcpdata = NULL; /* Starting location for the TCP data. */
	char message[LOGSZ];
	int compressed;

	if (DEBUG_DEDUPLICATION == true) {
		sprintf(message, "[DEDUP]: Entering into TCP OPTIMIZATION \n");
		logger(LOG_INFO, message);
	}

	// If the skb or state_compress is NULL abort compression.
	if ((ippacket != NULL) && (deduplication == true)) {
		iph = (struct iphdr *) ippacket; // Access ip header.

		if ((iph->protocol == IPPROTO_TCP)) { // If this is not a TCP segment abort deduplication.
			tcph = (struct tcphdr *) (((u_int32_t *) ippacket) + iph->ihl);
			oldsize = (__u16)(ntohs(iph->tot_len) - iph->ihl * 4) - tcph->doff * 4;
			tcpdata = (__u8 *) tcph + tcph->doff * 4; // Find starting location of the TCP data.

			if (oldsize > 0) { // Only compress if there is any data.

				if (DEBUG_DEDUPLICATION == true) {
					sprintf(message,
							"[DEDUP]: IP packet ID: %u\n", ntohs(iph->id));
					logger(LOG_INFO, message);
				}

				newsize = (oldsize * 2);

				if (DEBUG_DEDUPLICATION1  == true) {
					sprintf(message, "[DEDUP]: Begin deduplication.\n");
					logger(LOG_INFO, message);
				}

#ifdef BASIC
				optimize(tcpdata, oldsize, buffered_packet, &newsize);
#endif

#ifdef ROLLING
				dedup(pd, tcpdata, oldsize, buffered_packet, &newsize);
#endif
				compressed = newsize < oldsize;

				if (DEBUG_DEDUPLICATION == true) {
					sprintf(message,
							"[DEDUP]: OLD SIZE: %u \t NEW SIZE: %u\n", oldsize, newsize);
					logger(LOG_INFO, message);
				}

				if(compressed){

					if (DEBUG_DEDUPLICATION == true) {
						sprintf(message,
								"[DEDUP]: IP packet %u COMPRESSED\n", ntohs(iph->id));
						logger(LOG_INFO, message);
					}

					memmove(tcpdata, buffered_packet, newsize);// Move compressed data to packet.
					// Set the ip packet and the TCP options
					iph->tot_len = htons(ntohs(iph->tot_len) - (oldsize - newsize));// Fix packet length.
					__set_tcp_option((__u8 *) iph, 31, 3, 1); // Set compression flag.
                    /* Bellido: change from increasing seq number to changing most significant bit
					tcph->seq = htonl(ntohl(tcph->seq) + 8000); // Increase SEQ number.
                    */
					tcph->seq = htonl(ntohl(tcph->seq) ^ 1 << 31 ); // Change most significant bit
				}

				if (DEBUG_DEDUPLICATION == true) {
					sprintf(message, "[DEDUP]: Leaving TCP OPTIMIZATION \n");
					logger(LOG_INFO, message);
				}
			}
		}
	}
	// fruiz return amount of redundancy elimination
	if (compressed) return oldsize-newsize; else return 0;
}
Ejemplo n.º 5
0
int fetcher_callback(struct nfq_q_handle *hq, struct nfgenmsg *nfmsg,
		struct nfq_data *nfa, void *data) {
	u_int32_t id = 0;
	struct iphdr *iph = NULL;
	struct tcphdr *tcph = NULL;
	struct session *thissession = NULL;
	struct packet *thispacket = NULL;
	struct nfqnl_msg_packet_hdr *ph;
	struct timeval tv;
	__u32 largerIP, smallerIP, remoteID;
	__u16 largerIPPort, smallerIPPort, mms;
	int ret;
	int incomingQueueNum;
	unsigned char *originalpacket = NULL;
	char strIP[20];

    // for debugging purposes
    char saddr[INET_ADDRSTRLEN];
    char daddr[INET_ADDRSTRLEN];

	ph = nfq_get_msg_packet_hdr(nfa);

	if (ph) {
		id = ntohl(ph->packet_id);
	}

	ret = nfq_get_payload(nfa, &originalpacket);

	if (servicestate >= RUNNING) {

		iph = (struct iphdr *) originalpacket;

		thefetcher.metrics.bytesin += ntohs(iph->tot_len);

		/* We need to double check that only TCP packets get accelerated. */
		/* This is because we are working from the Netfilter QUEUE. */
		/* User could QUEUE UDP traffic, and we cannot accelerate UDP. */
		if ((iph->protocol == IPPROTO_TCP) && (id != 0)) {

			tcph = (struct tcphdr *) (((u_int32_t *) originalpacket) + iph->ihl);

            // for debugging purpose
			inet_ntop(AF_INET, &iph->saddr, saddr, INET_ADDRSTRLEN);
			inet_ntop(AF_INET, &iph->daddr, daddr, INET_ADDRSTRLEN);

			/* Check what IP address is larger. */
			sort_sockets(&largerIP, &largerIPPort, &smallerIP, &smallerIPPort,
					iph->saddr, tcph->source, iph->daddr, tcph->dest);

			// remoteID = (__u32) __get_tcp_option((__u8 *)originalpacket,32);
			if (__get_tcp_option((__u8 *)originalpacket,32) ) {
				unsigned char *tcpdata =  (unsigned char *) tcph + tcph->doff * 4; // Find starting location of the TCP data.
				unsigned int incLen   = (__u16)(ntohs(iph->tot_len) - iph->ihl * 4) - tcph->doff * 4;
				if (incLen < sizeof(OpennopHeader)) {
					LOGERROR(lc_fetcher, "detected opennop option but incoming TCP data length less than opennop header length!!!!");
					return nfq_set_verdict(hq, id, NF_DROP,0,NULL);
				}

				pOpennopHeader oh = (pOpennopHeader) tcpdata;
				remoteID = oh->opennopID;
				incomingQueueNum = oh->queuenum;
				if (oh->pattern != OPENNOP_PATTERN) {
					LOGERROR(lc_fetcher, "option 32 found but bad pattern!!!");
					return nfq_set_verdict(hq, id, NF_DROP,0,NULL);
				}
			} else remoteID = 0;

			inet_ntop(AF_INET, &remoteID, strIP, INET_ADDRSTRLEN);
			//LOGDEBUG(lc_fetcher, "The accellerator ID is:%s", strIP);

			if (remoteID == 0) { 
			    LOGTRACE(lc_fetcher, "Packet from CLIENT: SYN=%d/FIN=%d/ACK=%d/RST=%d, %s:%d->%s:%d, IP_Id=%d, NFQ_Id=%d, TCP_seq=%u, ACK_seq=%u, Total_len=%d, TCP_hlen=%d, IP_hlen=%d, Data_len=%d", 
                  tcph->syn, tcph->fin, tcph->ack, tcph->rst, saddr, ntohs(tcph->source), daddr, ntohs(tcph->dest), ntohs(iph->id), id, ntohl(tcph->seq), ntohl(tcph->ack_seq),
                  ntohs(iph->tot_len), tcph->doff * 4, iph->ihl * 4, ntohs(iph->tot_len) - tcph->doff * 4 - iph->ihl * 4);
            } else {
			    LOGTRACE(lc_fetcher, "Packet from %s: SYN=%d/FIN=%d/ACK=%d/RST=%d, %s:%d->%s:%d, IP_Id=%d, NFQ_Id=%d, TCP_seq=%u, ACK_seq=%u, Total_len=%d, TCP_hlen=%d, IP_hlen=%d, Data_len=%d", 
                  strIP, tcph->syn, tcph->fin, tcph->ack, tcph->rst, saddr, ntohs(tcph->source), daddr, ntohs(tcph->dest), ntohs(iph->id), id, ntohl(tcph->seq), ntohl(tcph->ack_seq),
                  ntohs(iph->tot_len), tcph->doff * 4, iph->ihl * 4, ntohs(iph->tot_len) - tcph->doff * 4 - iph->ihl * 4);
            }    

			thissession = getsession(largerIP, largerIPPort, smallerIP, smallerIPPort); // Check for an outstanding syn.

				// if (thissession != NULL) {
                //     LOGDEBUG(lc_sesman_check, "****** [SESSION MANAGER] LargerIPseq: %u SmallerIPseq %u, TCP_seq=%u", thissession->largerIPseq, thissession->smallerIPseq, ntohl(tcph->seq));
                // }

			/* Check if this a SYN packet to identify a new session. */
			/* This packet will not be placed in a work queue, but  */
			/* will be accepted here because it does not have any data. */
			//if ((tcph->syn == 1) && (tcph->ack == 0)) {
            
			if (tcph->syn == 1) {
                
                //
                // SYN segment
                //
                if (tcph->ack == 0) {
					if (remoteID == 0) { LOGDEBUG(lc_fetcher, "SYN from CLIENT: %s:%d->%s:%d", saddr, ntohs(tcph->source), daddr, ntohs(tcph->dest) ); }
        	        else               { LOGDEBUG(lc_fetcher, "SYN from %s: %s:%d->%s:%d", strIP, saddr, ntohs(tcph->source), daddr, ntohs(tcph->dest) ); }
				} else {
					if (remoteID == 0) { LOGDEBUG(lc_fetcher, "SYN+ACK from CLIENT: %s:%d->%s:%d", saddr, ntohs(tcph->source), daddr, ntohs(tcph->dest) ); } 
					else               { LOGDEBUG(lc_fetcher, "SYN+ACK from %s: %s:%d->%s:%d", strIP, saddr, ntohs(tcph->source), daddr, ntohs(tcph->dest) ); }
				}

				if (thissession == NULL) {
					if (remoteID != 0) thissession = insertsession(largerIP, largerIPPort, smallerIP, smallerIPPort, incomingQueueNum); // Insert into sessions list.
					else thissession = insertsession(largerIP, largerIPPort, smallerIP, smallerIPPort, -1); // Insert into sessions list.
					if (remoteID == 0) { LOGDEBUG(lc_fetcher, "New session from CLIENT created: %s:%d->%s:%d", saddr, ntohs(tcph->source), daddr, ntohs(tcph->dest) ) }
                    else               { LOGDEBUG(lc_fetcher, "New session from %s created: %s:%d->%s:%d", strIP, saddr, ntohs(tcph->source), daddr, ntohs(tcph->dest) ) };
				}

				/* We need to check for NULL to make sure */
				/* that a record for the session was created */
				if (thissession != NULL) {

					gettimeofday(&tv,NULL); // Get the time from hardware.
					thissession->lastactive = tv.tv_sec; // Update the session timestamp.

					sourceisclient(largerIP, iph, thissession, tcph->ack == 0);
					updateseq(largerIP, iph, tcph, thissession);
					updateseqnumber(largerIP, iph, tcph, thissession);

					if (remoteID == 0) { // Accelerator ID was not found.

						mms = __get_tcp_option((__u8 *)originalpacket,2);

						if (mms > 68) {

							if (__set_tcp_option((__u8 *)originalpacket,2,4,mms - 68) == -1) {// Reduce the MSS.
								LOGERROR(lc_fetcher, "Cannot reduce MSS in 68, fetcher.c, packet is a SYN, IP datagram ID %x, current value of TCP doff %d",ntohs(iph->id), tcph->doff);
							} 
							if (__set_tcp_option((__u8 *)originalpacket,32,3,1) == -1) { // Add the Accelerator ID to this packet.
								LOGERROR(lc_fetcher, "Cannot set opennop option to 1, fetcher.c, packet is a SYN, IP datagram ID %x, current value of TCP doff %d",ntohs(iph->id), tcph->doff);
							} else {
								unsigned char *tcpdata =  (unsigned char *) tcph + tcph->doff * 4; // Find starting location of the TCP data.
								pOpennopHeader oh = (pOpennopHeader) tcpdata;
								oh->opennopID = localID;
								oh->seqNo = 0;
								oh->compression = 0;
								oh->deduplication = 0;
								oh->reasonForNoOptimization = NOT_RELEVANT;
								oh->pattern = OPENNOP_PATTERN;
								oh->queuenum = thissession->queue;
								iph->tot_len = htons(ntohs(iph->tot_len)+sizeof(OpennopHeader));
								LOGTRACE(lc_fetcher, "Adding opennop header to SYN packet: IP total length=%d",ntohs(iph->tot_len));
							}

							saveacceleratorid(largerIP, localID, iph, thissession);

							/*
							 * Changing anything requires the IP and TCP
							 * checksum to need recalculated.
							 */
							checksum(originalpacket);
						}
					} else { // Accelerator ID was found.

					    //LOGDEBUG(lc_fetcher, "New session from %s created: %s:%d->%s:%d", strIP, saddr, ntohs(tcph->source), daddr, ntohs(tcph->dest) );

						if (__set_tcp_option((__u8 *)originalpacket,32,3,0) == -1) { 
							LOGERROR(lc_fetcher, "Cannot set opennop option to 0, fetcher.c, packet is a SYN, IP datagram ID %x, current value of TCP doff %d",ntohs(iph->id), tcph->doff);
						} else iph->tot_len = htons(ntohs(iph->tot_len)-sizeof(OpennopHeader));
						checksum(originalpacket);
						saveacceleratorid(largerIP, remoteID, iph, thissession);

					}

                    if (tcph->ack == 0) {
					    thissession->state = TCP_SYN_SENT;
                        LOGDEBUG(lc_fetcher, "Session state set to TCP_SYN_SENT");
                    } else {
						thissession->state = TCP_ESTABLISHED;
                        LOGDEBUG(lc_fetcher, "Session state set to TCP_ESTABLISHED");
                    }
				}

				/* Before we return let increment the packets counter. */
				thefetcher.metrics.packets++;

				/* This is the last step for a SYN packet. */
				/* accept all SYN packets. */
				return nfq_set_verdict(hq, id, NF_ACCEPT, ntohs(iph->tot_len), (unsigned char *)originalpacket);

			// } else if (tcph->rst == 1) { 
                
                //
                // RESET segment
                //
                // LOGDEBUG(lc_fetcher, "Session RESET %s:%d->%s:%d", saddr, ntohs(tcph->source), daddr, ntohs(tcph->dest));
                // clearsession(thissession);
		// fruiz // 
		// thissession = NULL;

                /* Before we return let increment the packets counter. */
				// thefetcher.metrics.packets++;
			    // return nfq_set_verdict(hq, id, NF_ACCEPT, 0, NULL);


//			} else if (tcph->fin == 1) {  
//                
//                //
//                // FIN segment
//                //
//                LOGDEBUG(lc_fetcher, "FIN packet: %s:%d->%s:%d", saddr, ntohs(tcph->source), daddr, ntohs(tcph->dest));
//				if (thissession != NULL) {
//                    switch (thissession->state) {
//                        case TCP_ESTABLISHED:
//                                thissession->state = TCP_CLOSING;
//                                LOGDEBUG(lc_fetcher, "Session half closed: %s:%d->%s:%d", saddr, ntohs(tcph->source), daddr, ntohs(tcph->dest));
//                                break;
//                        case TCP_CLOSING:
//                                clearsession(thissession);
//                                LOGDEBUG(lc_fetcher, "Session full closed: %s:%d->%s:%d", saddr, ntohs(tcph->source), daddr, ntohs(tcph->dest));
//                                break;
//                    }
//                }
//
//                /* Before we return let increment the packets counter. */
//				thefetcher.metrics.packets++;
//	LOGDEBUG(lc_fetcher, "hq=%d, id=%d", hq, id);
//                int res = nfq_set_verdict(hq, id, NF_ACCEPT, ntohs(iph->tot_len), (unsigned char *)originalpacket);
//                LOGDEBUG(lc_fetcher, "Returning FIN packet %d", res);
//			    //return nfq_set_verdict(hq, id, NF_ACCEPT, 0, NULL);
//				//return nfq_set_verdict(hq, id, NF_ACCEPT, ntohs(iph->tot_len), (unsigned char *)originalpacket);
//				return res;


			} else { 

                //
                // DATA or FIN segment
                //
				if (thissession != NULL) { // DATA segment in an active session

                    //LOGDEBUG(lc_sesman_check, "[SESSION MANAGER] LargerIPseq: %u SmallerIPseq %u", thissession->largerIPseq, thissession->smallerIPseq);

					gettimeofday(&tv,NULL); // Get the time from hardware.
					thissession->lastactive = tv.tv_sec; // Update the active timer.
					thissession->deadcounter = 0; // Reset the dead counter.

					if (__get_tcp_option((__u8 *)originalpacket,32) == 2) { // Keepalive, can drop
						LOGDEBUG(lc_fetcher, "Received keepalive: %s:%d->%s:%d", saddr, ntohs(tcph->source), daddr, ntohs(tcph->dest) );
						return nfq_set_verdict(hq, id, NF_DROP,0,NULL);
					}

					thispacket = get_freepacket_buffer();

					if (thispacket != NULL){
						save_packet(thispacket,hq, id, ret, (__u8 *)originalpacket, thissession);

						if (remoteID == 0){
						    LOGTRACE(lc_fetcher, "Packet sent to optimize");
							optimize_packet(thissession->queue, thispacket);
						} else {
						    LOGTRACE(lc_fetcher, "Packet sent to deoptimize");
							deoptimize_packet(thissession->queue, thispacket);
						}

					} else {
						LOGERROR(lc_fetcher, "Failed getting packet buffer for processing");
					}
					/* Before we return let increment the packets counter. */
					thefetcher.metrics.packets++;
					return 0;

				} else { // DATA segment and no active session exists


                    int data_len = ntohs(iph->tot_len) - tcph->doff * 4 - iph->ihl * 4;
                    if (data_len > 0) {
                        LOGDEBUG(lc_fetcher, "No session found for: SYN=%d/FIN=%d/ACK=%d/RST=%d, %s:%d->%s:%d, Opt_ID=%s, IP_Id=%d, NFQ_Id=%d, Total_len=%d, TCP_hlen=%d, IP_hlen=%d, Data_len=%d", 
                                tcph->syn, tcph->fin, tcph->ack, tcph->rst, saddr, ntohs(tcph->source), daddr, ntohs(tcph->dest), strIP, ntohs(iph->id), id, 
                                ntohs(iph->tot_len), tcph->doff * 4, iph->ihl * 4, ntohs(iph->tot_len) - tcph->doff * 4 - iph->ihl * 4);
                    }

    				/* We only want to create new sessions for active sessions. */
    				/* This means we exclude anything accept ACK packets. */

    				if (tcph->ack == 1) {

    					if (remoteID != 0) { // Detected remote Accelerator so it is safe to add this session.
    						thissession = insertsession(largerIP, largerIPPort, smallerIP, smallerIPPort, incomingQueueNum); // Insert into sessions list.

   							if (thissession != NULL) { // Test to make sure the session was added.
					            
                                LOGDEBUG(lc_fetcher, "Created NEW session for: %s:%d->%s:%d", saddr, ntohs(tcph->source), daddr, ntohs(tcph->dest) );

							    thissession->state = TCP_ESTABLISHED;

							    saveacceleratorid(largerIP, remoteID, iph, thissession);

							    thispacket = get_freepacket_buffer();

							    if (thispacket != NULL){
								    save_packet(thispacket,hq, id, ret, (__u8 *)originalpacket, thissession);
								    updateseqnumber(largerIP, iph, tcph, thissession); //Update the stored TCP sequence number
								    deoptimize_packet(thissession->queue, thispacket);
							    } else {
								    LOGERROR(lc_fetcher, "Failed getting packet buffer for deoptimization.");
							    }
							    /* Before we return let increment the packets counter. */
							    thefetcher.metrics.packets++;
							    return 0;
                            } else {
                                LOGERROR(lc_fetcher, "Failed to create session for: %s:%d->%s:%d", saddr, ntohs(tcph->source), daddr, ntohs(tcph->dest) );
                            }
                        }
				    }
					/* Before we return let increment the packets counter. */
					thefetcher.metrics.packets++;
                    //LOGERROR(lc_fetcher, "Unknown packet: %s:%d->%s:%d", saddr, ntohs(tcph->source), daddr, ntohs(tcph->dest) );
					return nfq_set_verdict(hq, id, NF_ACCEPT, ntohs(iph->tot_len), (unsigned char *)originalpacket);
			    }
			}
		} else { /* Packet was not a TCP Packet or ID was 0. */
Ejemplo n.º 6
0
/*
 * Compresses the TCP data of an SKB.
 */
unsigned int tcp_compress(__u8 *ippacket, __u8 *lzbuffer,
		qlz_state_compress *state_compress) {
	struct iphdr *iph = NULL;
	struct tcphdr *tcph = NULL;
	__u16 oldsize = 0, newsize = 0; /* Store old, and new size of the TCP data. */
	__u8 *tcpdata = NULL; /* Starting location for the TCP data. */
	char message[LOGSZ];

	if (DEBUG_COMPRESSION == true) {
		sprintf(message, "[OpenNOP]: Entering into TCP COMPRESS \n");
		logger(LOG_INFO, message);
	}

	// If the skb or state_compress is NULL abort compression.
	if ((ippacket != NULL) && (NULL != state_compress) && (compression == true)) {
		iph = (struct iphdr *) ippacket; // Access ip header.
		memset(state_compress, 0, sizeof(qlz_state_compress));

		if ((iph->protocol == IPPROTO_TCP)) { // If this is not a TCP segment abort compression.
			tcph = (struct tcphdr *) (((u_int32_t *) ippacket) + iph->ihl);
			oldsize = (__u16)(ntohs(iph->tot_len) - iph->ihl * 4) - tcph->doff * 4;
			tcpdata = (__u8 *) tcph + tcph->doff * 4; // Find starting location of the TCP data.

			if (DEBUG_COMPRESSION == true) {
				sprintf(message,
						"Compression: Original TCP data length is: %u\n",
						oldsize);
				logger(LOG_INFO, message);
			}

			if (oldsize > 0) { // Only compress if there is any data.
				newsize = (oldsize * 2);

				if (lzbuffer != NULL) {

					if (DEBUG_COMPRESSION == true) {
						sprintf(message, "Compression: Begin compression.\n");
						logger(LOG_INFO, message);
					}

					newsize = qlz_compress((char *) tcpdata, (char *) lzbuffer,
							oldsize, state_compress);
				} else {

					if (DEBUG_COMPRESSION == true) {
						sprintf(message, "Compression: lzbuffer was NULL!\n");
						logger(LOG_INFO, message);
					}
				}

				if (DEBUG_COMPRESSION == true) {
					sprintf(message,
							"Compression: New TCP data length is: %u\n",
							newsize);
					logger(LOG_INFO, message);
				}

				if (newsize < oldsize) {
					memmove(tcpdata, lzbuffer, newsize); // Move compressed data to packet.
					//pskb_trim(skb,skb->len - (oldsize - newsize)); // Remove extra space from skb.
					iph->tot_len = htons(ntohs(iph->tot_len) - (oldsize - newsize));// Fix packet length.
					__set_tcp_option((__u8 *) iph, 31, 3, 1); // Set compression flag.
					tcph->seq = htonl(ntohl(tcph->seq) + 8000); // Increase SEQ number.

					if (DEBUG_COMPRESSION == true) {
						sprintf(message,
								"Compressing [%d] size of data to [%d] \n",
								oldsize, newsize);
						logger(LOG_INFO, message);
					}
				}

				if (DEBUG_COMPRESSION == true) {
					sprintf(message, "[OpenNOP]: Leaving TCP COMPRESS \n");
					logger(LOG_INFO, message);
				}
			}
		}
	}
	return 1;
}
Ejemplo n.º 7
0
/*
 * This sends a keep alive message to the specified IP.
 * It does not tag the packet with the Accelerator ID this
 * prevents the keepalive messages from recreating dead sessions
 * in remote Accelerators.
 */
void sendkeepalive
(__u32 saddr, __u16 source, __u32 seq,
__u32 daddr, __u16 dest, __u32 ack_seq){
	char packet[BUFSIZE];
	struct iphdr *iph = NULL;
	struct tcphdr *tcph = NULL;
	//struct sockaddr_in sin;
	struct sockaddr_in din;
	__u16 tcplen;

	memset(packet, 0, BUFSIZE);

	//sin.sin_family = AF_INET;
	din.sin_family = AF_INET;
	
	//sin.sin_port = source;
	din.sin_port = dest;
	
	//sin.sin_addr.s_addr = saddr;
	din.sin_addr.s_addr = daddr;

	iph = (struct iphdr *)packet;
	iph->ihl = 5; // IP header length.
	iph->version = 4; // IP version 4.
	iph->tos = 0; // No TOS.
	iph->tot_len=htons(sizeof(struct iphdr) + sizeof(struct tcphdr)); // L3 + L4 header length.
	iph->id = 0; // What?
	iph->frag_off = 0; // No fragmenting.
	iph->ttl = 64; // Set a TTL.
	iph->protocol = IPPROTO_TCP; // TCP protocol.
	iph->check = 0; // No IP checksum yet.
	iph->saddr = saddr; // Source IP.
	iph->daddr = daddr; // Dest IP.
	
	tcph = (struct tcphdr *) (((u_int32_t *)iph) + iph->ihl);
	tcph->check = 0; // No TCP checksum yet.
	tcph->source = source; // Source TCP Port.
	tcph->dest = dest; // Destination TCP Port.
	tcph->seq = htonl(seq - 1); // Current SEQ minus one is used for TCP keepalives.
	tcph->ack_seq = htonl( ack_seq - 1); // Ummm not sure yet.
	tcph->res1 = 0; // Not sure.
	tcph->doff = 5; // TCP Offset.  At least 5 if there are no TCP options.
	tcph->fin = 0; // FIN flag.
	tcph->syn = 0; // SYN flag.
	tcph->rst = 0; // RST flag.
	tcph->psh = 0; // PSH flag.
	tcph->ack = 1; // ACK flag.
	tcph->urg = 0; // URG flag.
	
	if (__set_tcp_option((__u8 *)iph,32,3,2) == -1) { // Add the Accelerator ID to this packet.
		LOGDEBUG(lc_sesman, "Sessioncleanup: Cannot add accelerator ID, sessioncleanup.c, IP datagram ID %x, current value of TCP doff %d",ntohs(iph->id), tcph->doff);
	} else {
    		unsigned char *tcpdata =  (unsigned char *) tcph + tcph->doff * 4; // Find starting location of the TCP data.
                pOpennopHeader oh = (pOpennopHeader) tcpdata;
                oh->opennopID = localID;
                oh->seqNo = 0;
                oh->compression = 0;
                oh->deduplication = 0;
                oh->reasonForNoOptimization = NOT_RELEVANT;
                oh->queuenum = 0;
                oh->pattern = OPENNOP_PATTERN;
                iph->tot_len = htons(ntohs(iph->tot_len)+sizeof(OpennopHeader));
	}
	
	tcplen = ntohs(iph->tot_len) - iph->ihl*4;
	tcph->check = 0;
	tcph->check = tcp_sum_calc(tcplen,
		(unsigned short *)&iph->saddr,
		(unsigned short *)&iph->daddr,
		(unsigned short *)tcph);
 	iph->check = 0;
 	iph->check = ip_sum_calc(iph->ihl*4,
		(unsigned short *)iph);
	
	
	if(sendto(rawsock, packet, ntohs(iph->tot_len), 0, (struct sockaddr *)&din, sizeof(din)) < 0){
		printf("sendto() error\n");
	}
	
	return;
}