/* ************************************************** */ int set_header(call_t *c, packet_t *packet, destination_t *dst) { struct nodedata *nodedata = get_node_private_data(c); struct neighbor *n_hop = get_nexthop(c, dst->id); destination_t destination; struct routing_header *header = (struct routing_header *) (packet->data + nodedata->overhead); call_t c0 = {get_entity_bindings_down(c)->elts[0], c->node, c->entity}; /* No route available */ if (dst->id != BROADCAST_ADDR && n_hop == NULL) { return -1; } /* Set routing header */ header->dst = dst->id; header->src = c->node; header->hop = nodedata->hop; /* Set MAC header */ if (dst->id == BROADCAST_ADDR) { destination.id = BROADCAST_ADDR; } else { destination.id = n_hop->id; } destination.position.x = -1; destination.position.y = -1; destination.position.z = -1; return SET_HEADER(&c0, packet, &destination); }
/* ************************************************** */ int set_header(call_t *c, packet_t *packet, destination_t *dst) { struct nodedata *nodedata = get_node_private_data(c); struct neighbor *n_hop = get_nexthop(c, &(dst->position)); destination_t destination; struct routing_header *header = (struct routing_header *) (packet->data + nodedata->overhead); call_t c0 = {get_entity_bindings_down(c)->elts[0], c->node, c->entity}; /* if no route, return -1 */ if (dst->id != BROADCAST_ADDR && n_hop == NULL) { nodedata->data_noroute++; return -1; } else if (dst->id == BROADCAST_ADDR) { n_hop->id = BROADCAST_ADDR; } /* set routing header */ header->dst = dst->id; header->dst_pos.x = dst->position.x; header->dst_pos.y = dst->position.y; header->dst_pos.z = dst->position.z; header->src = c->node; header->src_pos.x = get_node_position(c->node)->x; header->src_pos.y = get_node_position(c->node)->y; header->src_pos.z = get_node_position(c->node)->z; header->type = DATA_PACKET; header->hop = nodedata->hop; /* Set mac header */ destination.id = n_hop->id; destination.position.x = -1; destination.position.y = -1; destination.position.z = -1; return SET_HEADER(&c0, packet, &destination); }
/* ************************************************** */ void forward(call_t *c, packet_t *packet) { struct nodedata *nodedata = get_node_private_data(c); call_t c0 = {get_entity_bindings_down(c)->elts[0], c->node, c->entity}; struct routing_header *header = (struct routing_header *) (packet->data + nodedata->overhead); struct neighbor *n_hop = get_nexthop(c, &(header->dst_pos)); destination_t destination; /* delivers packet to application layer */ if (n_hop == NULL) { array_t *up = get_entity_bindings_up(c); int i = up->size; while (i--) { call_t c_up = {up->elts[i], c->node, c->entity}; packet_t *packet_up; if (i > 0) { packet_up = packet_clone(packet); } else { packet_up = packet; } RX(&c_up, packet_up); } return; } /* update hop count */ header->hop--; if (header->hop == 0) { nodedata->data_hop++; packet_dealloc(packet); return; } /* set mac header */ destination.id = n_hop->id; destination.position.x = -1; destination.position.y = -1; destination.position.z = -1; if (SET_HEADER(&c0, packet, &destination) == -1) { packet_dealloc(packet); return; } /* forwarding packet */ nodedata->data_tx++; TX(&c0, packet); }
/* ************************************************** */ void forward(call_t *c, packet_t *packet) { struct nodedata *nodedata = get_node_private_data(c); call_t c0 = {get_entity_bindings_down(c)->elts[0], c->node, c->entity}; struct routing_header *header = (struct routing_header *) (packet->data + nodedata->overhead); struct neighbor *n_hop = get_nexthop(c, header->dst); destination_t destination; /* No route available */ if (n_hop == NULL) { packet_dealloc(packet); return; } /* Update hop count */ header->hop--; /* Hop count reached */ if (header->hop == 0) { packet_dealloc(packet); return; } /* Set MAC header */ destination.id = n_hop->id; destination.position.x = -1; destination.position.y = -1; destination.position.z = -1; if (SET_HEADER(&c0, packet, &destination) == -1) { packet_dealloc(packet); return; } /* Forwarding packet */ PRINT_ROUTING("forward: Node %d forwards a packet " "(from %d to %d, hop limit %d)\n", c->node, header->src, header->dst, header->hop); TX(&c0, packet); }
int v_connect(int socket, struct in_addr *addr, uint16_t port){ #ifdef DEBUG printf(" v_connect() Trying to connect\n"); #endif //bind the socket to a random port int ret; struct in_addr any_addr; any_addr.s_addr = 0; ret = v_bind(socket, &any_addr, rand()%MAXPORT); //something went wrong at v_bind (no socket, not valid pnum) if(ret < 0) { #ifdef DEBUG printf(" v_connect() error : v_bind() failed\n"); #endif return -1; } #ifdef DEBUG printf(" v_connect() : v_bind() success\n"); #endif socket_t *so = fd_lookup(socket); if (so == NULL) { #ifdef DEBUG printf(" v_connect() error : fd_lookup() failed\n"); #endif set_socketstate(so, CLOSE); return -1; } #ifdef DEBUG printf(" v_connect() : fd_lookup() success\n"); #endif //store it in the lookup table (urport, myport, uraddr) + init windows init_windows(so); //populate socket with info so->urport = port; so->uraddr = addr->s_addr; //my addr is the interface IP address we will be sending request out to interface_t *i = get_nexthop(so->uraddr); if (i == NULL) { set_socketstate(so, CLOSE); return -EHOSTUNREACH; } so->myaddr = i->sourcevip; so->myseq = rand() % MAXSEQ; #ifdef SIMPLESEQ so->myseq = 0; #endif #ifdef DEBUG printf(" v_connect() : so->* success\n"); #endif #ifdef DEBUG printf(" v_connect: Added socket %d to socket_table"_NORMAL_"\n", so->id); #endif HASH_ADD(hh2, socket_table, urport, keylen, so); set_socketstate(so, SYN_SENT); #ifdef DEBUG printf(" v_connect() : socket %d moved into state SYN_SENT\n", so->id); #endif tcp_send_handshake(1, so); #ifdef DEBUG printf(_RED_" v_connect: send syn"_NORMAL_"\n"); printf(_BLUE_" v_connect: timed out"_NORMAL_"\n"); #endif time_t now = time(NULL); time_t next = now; time_t diff = 0; int count = 0; //send a connection request (first grip) while ((count < MAX_SYN_REQ)) { if (so->state == ESTABLISHED) { break; } next = time(NULL); diff = next-now; if (diff == 1) { tcp_send_handshake(1, so); count++; #ifdef DEBUG printf(_RED_" v_connect: send syn"_NORMAL_"\n"); printf(_BLUE_" v_connect: timed out"_NORMAL_"\n"); #endif now = next; } } // Could not connect if (so->state == SYN_SENT || so->state == CLOSE) { set_socketstate(so, CLOSED); return -ENOTCONN; } //commence buffer management int s = (int)socket; pthread_attr_t thr_attr; pthread_attr_init(&thr_attr); pthread_attr_setdetachstate(&thr_attr, PTHREAD_CREATE_DETACHED); pthread_create(&so->th, &thr_attr, buf_mgmt, (void *) s); return 0; }
/** * TODO : take the pseudo header function out. NOTE : make sure it is generic * enough to be called by handshake funcs AND send data funcs. * TODO : 3rd shake might have data * TODO : RST */ void tcp_send_handshake(int gripnum, socket_t *socket){ tcphdr *header = NULL; switch(gripnum) { case 0: printf("\t TODO : RST NOT IMPLEMENTED YET\n"); case SYN_SENT://1'st shake header = tcp_mastercrafter(socket->myport, socket->urport, socket->myseq, 0,0,1,0,0,0, WINSIZE); //half the max sequence number break; case SYN_RCVD://2'nd shake header = tcp_mastercrafter(socket->myport, socket->urport, (socket->myseq)++, socket->ackseq, 0,1,0,0,1, WINSIZE); break; case ESTABLISHED://3'rd shake header = tcp_mastercrafter(socket->myport, socket->urport, ++(socket->myseq), socket->ackseq, 0,0,0,0,1, WINSIZE); break; case FIN_WAIT_1:// from ESTABLISHED --> FIN_WAIT_1 state (FIN SEGMENT) header = tcp_mastercrafter(socket->myport, socket->urport, socket->myseq, socket->ackseq, 1,0,0,0,1,MAXSEQ); break; case CLOSE_WAIT: //regular ACK header = tcp_mastercrafter(socket->myport, socket->urport, socket->myseq, socket->ackseq, 0,0,0,0,1,MAXSEQ); break; case LAST_ACK: // moving from CLOSE_WAIT --> LAST_ACK (FIN SEGMENT) header = tcp_mastercrafter(socket->myport, socket->urport, socket->myseq, socket->ackseq, 1,0,0,0,1,MAXSEQ); break; case CLOSING: // moving from FIN_WAIT_1 --> CLOSING header = tcp_mastercrafter(socket->myport, socket->urport, socket->myseq, socket->ackseq, 1,0,0,0,1,MAXSEQ); break; case ACKNOWLEDGE: printf("RST, ACK\n"); header = tcp_mastercrafter(socket->myport, socket->urport, socket->myseq, socket->ackseq, 0,0,0,0,1,MAXSEQ); case RST: // RST packet header = tcp_mastercrafter(socket->myport, socket->urport, socket->myseq, socket->ackseq, 1,0,0,0,1,MAXSEQ); break; default: printf("\t WARNING : Unknown shake!\n"); return; } //0. make sure TCP header is not NULL if (header == NULL) { printf("\tWARNING : Could not make TCP header\n"); return; } struct pseudo_tcpp *tcp_packet = (uint16_t *)malloc(sizeof(struct pseudo_tcpp)); memset(tcp_packet, 0x0, sizeof(struct pseudo_tcpp)); //1. fill the pseudiheader part ((uint32_t *)tcp_packet)[0] = socket->myaddr; ((uint32_t *)tcp_packet)[1] = socket->uraddr; ((uint8_t *)tcp_packet)[9] = (uint8_t)TCP; ((uint16_t *)tcp_packet)[5] = ntohs((uint16_t)TCPHDRSIZE); //2. fill the header tcp_hton(header); memcpy(&tcp_packet->tcp, header, TCPHDRSIZE); //3. data (NONE) //TODO : 3rd handshake could have data. memset(tcp_packet->payload, 0, 1024); //4. checksum uint16_t checksum = tcp_checksum(tcp_packet, TCPHDRSIZE+12); //5. set the checksum in the TCP header header->check = checksum; if (header->check == 0) { printf("\t ERROR : something went wrong with checksum\n"); header->check = 0xffffff; } //6. TODO : error checking interface_t *nexthop = get_nexthop(socket->uraddr); //TODO : packet top pass to ip char *packet = (char *)malloc(TCPHDRSIZE+IPHDRSIZE); if (packet == NULL) { printf("\t ERROR : Malloc failed\n"); return; } //7. copy the TCP header to ip packet memset(packet, 0, TCPHDRSIZE+IPHDRSIZE); memcpy(packet, header, TCPHDRSIZE); //8. NO data, so you are done : pass to ip encapsulate_inip(socket->myaddr,socket->uraddr,(uint8_t)TCP,header, TCPHDRSIZE, &packet); //9. TCP/IP packet all set, sending time int ret = send_ip(nexthop, packet, TCPHDRSIZE+IPHDRSIZE); free(tcp_packet); free(packet); free(header); return; }