#include #include #include #include #include #include #include "headers.h" #include "errno.h" #include #include #include const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); void printDetails(unsigned char* p); typedef void (*callback)(void); unsigned int THIS_IP; unsigned short THIS_PORT = htons(80); int nResourcesGET; int* hashesGET; double** valuesGET; int nResourcesPOST; int* hashesPOST; callback* valuesPOST; int socket_receive; int socket_send; unsigned char responseSegmentBytes[] = { //IP 0x45, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40, 0x00, 0x40, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //TCP 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x10, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, //Data 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d, 0x0a, 0x41}; // Calculo do checksum TCP para os campos nao variaveis unsigned int calculoPrevioParaChecksumTcpResponseSegment = 0x29090;//0x15501;//0xD07D; unsigned char synAckSegmentBytes[] = { //IP 0x45, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40, 0x00, 0x40, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //TCP 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x12, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00}; // Calculo do checksum TCP para os campos nao variaveis unsigned int calculoPrevioParaChecksumTcpSynAckSegment = 0xD07B; // Calculo do checksum IP para os campos nao variaveis unsigned int calculoPrevioParaChecksumIpSegment = 0xC52E; int makeHash(unsigned char* string) { int hash=7; for (int i = 0; string[i]; i++) { hash = hash * 31 + string[i]; } return hash; } void registerGET(unsigned char** resourceNames, double** values, int n) { hashesGET = (int*) malloc(sizeof(int*) * n); for (int i = 0; i < n; i++) { hashesGET[i] = makeHash(resourceNames[i]); } valuesGET = values; nResourcesGET = n; } void registerPOST(unsigned char** resourceNames, callback* funcs, int n) { hashesPOST = (int*) malloc(sizeof(int*) * n); for (int i = 0; i < n; i++) { hashesPOST[i] = makeHash(resourceNames[i]); } valuesPOST = funcs; nResourcesPOST = n; } unsigned char buffer[128]; Segment* receiveNextDatagram(){ if (recvfrom(socket_receive, &buffer, sizeof(buffer), 0, NULL, NULL) < 0) { perror("PROBLEMAS NO RECEBIMENTO DE PACOTE"); } return (Segment*) buffer; } void prepararSocket(){ if ((socket_receive = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) { perror("ERRO: Socket nao pode ser criado..."); exit(EXIT_FAILURE); } if ((socket_send = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { perror("ERRO: Socket nao pode ser criado..."); exit(EXIT_FAILURE); } } // Passo 2 do 3-Way Handshake do TCP void sendSynAck(int destination, short destPort, int sequenceNumber){ Segment* s = (Segment*)synAckSegmentBytes; //IP s->destIp = destination; //TCP s->destPort = destPort; s->ackNumber = sequenceNumber + 0x01000000; //Calculo do Checksum TCP unsigned int somaParaCheckSum = calculoPrevioParaChecksumTcpSynAckSegment; somaParaCheckSum += htons(s->ackNumber>>16); somaParaCheckSum += htons(s->ackNumber & 0xFFFF); somaParaCheckSum += htons(destPort); somaParaCheckSum += htons(destination>>16); somaParaCheckSum += htons(destination & 0xFFFF); s->checksumTcp = ntohs(~((somaParaCheckSum & 0xFFFF) + (somaParaCheckSum>>16))); //Calculo do Checksum IP somaParaCheckSum = calculoPrevioParaChecksumIpSegment; somaParaCheckSum += htons(destination>>16); somaParaCheckSum += htons(destination & 0xFFFF); s->checksumIp = ntohs(~((somaParaCheckSum & 0xFFFF) + (somaParaCheckSum>>16))); struct sockaddr_in dst_addr; memset(&dst_addr, 0, sizeof(dst_addr)); dst_addr.sin_family = AF_INET; dst_addr.sin_port = htons(destPort); struct in_addr endIp; endIp.s_addr = destination; dst_addr.sin_addr = endIp; int tmp = sendto(socket_send, s, sizeof(*s), 0, (struct sockaddr *)&dst_addr, sizeof(dst_addr)); std::cout << "Quantidade de bytes enviados: " << tmp << std::endl; } void sendResponse(unsigned int destination, unsigned short destPort, unsigned int ackNumber, unsigned int sequenceNumber, int dataLen){ Segment* s = (Segment*)responseSegmentBytes; //IP s->destIp = destination; //TCP s->destPort = destPort; //Deal with ack and sequence numbers // std::cout << ackNumber << std::endl; s->ackNumber = ackNumber; s->seqNumber = sequenceNumber; //Calculo do Checksum TCP unsigned int somaParaCheckSum = calculoPrevioParaChecksumTcpResponseSegment; somaParaCheckSum += htons(ackNumber>>16); somaParaCheckSum += htons(ackNumber & 0xFFFF); somaParaCheckSum += htons(sequenceNumber>>16); somaParaCheckSum += htons(sequenceNumber & 0xFFFF); somaParaCheckSum += htons(destPort); somaParaCheckSum += htons(destination>>16); somaParaCheckSum += htons(destination & 0xFFFF); s->checksumTcp = ntohs(~((somaParaCheckSum & 0xFFFF) + (somaParaCheckSum>>16))); //Calculo do Checksum IP somaParaCheckSum = calculoPrevioParaChecksumIpSegment; somaParaCheckSum += htons(destination>>16); somaParaCheckSum += htons(destination & 0xFFFF); s->checksumIp = ntohs(~((somaParaCheckSum & 0xFFFF) + (somaParaCheckSum>>16))); struct sockaddr_in dst_addr; memset(&dst_addr, 0, sizeof(dst_addr)); dst_addr.sin_family = AF_INET; dst_addr.sin_port = htons(destPort); struct in_addr endIp; endIp.s_addr = destination; dst_addr.sin_addr = endIp; int tmp = sendto(socket_send, s, sizeof(*s) + dataLen, 0, (struct sockaddr *)&dst_addr, sizeof(dst_addr)); std::cout << "Quantidade de bytes enviados: " << tmp << std::endl; } void printDetails(Segment* s) { if (s->protocol != 6) { std::cout << "Received non-tcp packet." << std::endl; return; } struct in_addr sourceStruct; sourceStruct.s_addr = s->srcIp; char sourceString[15]; inet_ntop(AF_INET, &sourceStruct, sourceString, 15); struct in_addr destinationStruct; destinationStruct.s_addr = s->destIp; char destinationString[15]; inet_ntop(AF_INET, &destinationStruct, destinationString, 15); std::cout << sourceString << ":" << ntohs(s->srcPort) << " -> " << destinationString << ":" << ntohs(s->destPort) << " ("; if (s->headerLength != 5) std::cout << " !IP options (" << s->headerLength << ")! "; if (s->syn) std::cout << " SYN "; if (s->ack) std::cout << " ACK "; if (s->rst) std::cout << " RST "; std::cout << ")" << std::endl; } void setMyIpAddress() { //TODO: Pegar o IP na inicialização THIS_IP = 16777343; ((Segment*)synAckSegmentBytes)->srcIp = THIS_IP; ((Segment*)responseSegmentBytes)->srcIp = THIS_IP; calculoPrevioParaChecksumTcpSynAckSegment += htons(THIS_IP>>16); calculoPrevioParaChecksumTcpSynAckSegment += htons(THIS_IP & 0xFFFF); calculoPrevioParaChecksumTcpResponseSegment += htons(THIS_IP>>16); calculoPrevioParaChecksumTcpResponseSegment += htons(THIS_IP & 0xFFFF); calculoPrevioParaChecksumIpSegment += htons(THIS_IP>>16); calculoPrevioParaChecksumIpSegment += htons(THIS_IP & 0xFFFF); } void listen() { //printDetails(synAckSegment); prepararSocket(); setMyIpAddress(); while (1) { Segment* s = receiveNextDatagram(); //printDetails(s); if ((s->destIp == THIS_IP) && (s->destPort == THIS_PORT)) { printDetails(s); if (s->syn == 1) { // Segmento TCP requisitando conexão sendSynAck(s->srcIp, s->srcPort, s->seqNumber); } else { unsigned char* data = ((unsigned char *) s) + 40; unsigned char i = 0; unsigned char resourceName[32]; if (data[0] == 'G') { // GET std::cout << "TAMANHO: " << ntohs(s->size) << std::endl; sendResponse(s->srcIp, s->srcPort, htonl(ntohl(s->seqNumber) + ntohs(s->size) - 40), s->ackNumber, 18); while ((resourceName[i] = data[4 + i++]) != ' '); resourceName[i - 1] = '\0'; int hash = makeHash(resourceName); for (i = 0; i < nResourcesGET; i++) { if (hashesGET[i] == hash) { //TODO enviar o valor //send(responseSegment, s->srcIp, s->srcPort, s->id, s->seqNumber + 1, s->ackNumber/*, *(valuesGET[i])*/); break; } } } else if (data[2] == 'S') { // POST while ((resourceName[i] = data[5 + i++]) != ' '); resourceName[i - 1] = '\0'; int hash = makeHash(resourceName); for (i = 0; i < nResourcesPOST; i++) { if (hashesPOST[i] == hash) { valuesPOST[i](); break; } } } } } } } int main(){ listen(); return 1; }