void disconnect(char *src_ip, char *dst_ip, char *path, int recv_port){ // build fin packet char buf[10000]; char ack_buf[10000]; size_t len, sent, recv_size; struct iphdr *iph; struct tcphdr *tcph; if (passive_fin == 0){ len = build_fin_packet(buf, 2000, src_ip, dst_ip, recv_port, seq_num, expected_seq); sent = sendto(sock_send, buf, len, 0, (struct sockaddr *)&sin_send, sizeof(sin_send)); printf("FIN packet sent, size: %u\n", sent); } // receive ack while (connected == 1){ recv_size = recv(sock_recv, buf, sizeof(buf), 0); if (recv_size < IP_HDR_SIZE + TCP_HDR_SIZE) { continue; } iph = (struct iphdr *)buf; tcph = (struct tcphdr *)(buf + IP_HDR_SIZE); if (iph->saddr != inet_addr(dst_ip) && tcph->source != htons(HTTP_PORT) && ntohl(tcph->dest) != recv_port){ continue; } if (tcph->fin == 1 && tcph->ack == 1){ seq_num += 1; len = build_ack(ack_buf, buf, recv_port, src_ip, dst_ip, seq_num); sendto(sock_send, ack_buf, len, 0, (struct sockaddr *)&sin_send, sizeof(sin_send)); return; } } }
void handle_incoming_msgs(Receiver * receiver, LLnode ** outgoing_frames_head_ptr) { //TODO: Suggested steps for handling incoming frames // 1) Dequeue the Frame from the sender->input_framelist_head // 2) Convert the char * buffer to a Frame data type // 3) Check whether the frame is corrupted // 4) Check whether the frame is for this receiver // 5) Do sliding window protocol for sender/receiver pair int incoming_msgs_length = ll_get_length(receiver->input_framelist_head); while (incoming_msgs_length > 0) { //Pop a node off the front of the link list and update the count LLnode * ll_inmsg_node = ll_pop_node(&receiver->input_framelist_head); incoming_msgs_length = ll_get_length(receiver->input_framelist_head); //DUMMY CODE: Print the raw_char_buf //NOTE: You should not blindly print messages! // Ask yourself: Is this message really for me? // Is this message corrupted? // Is this an old, retransmitted message? char * raw_char_buf = (char *) ll_inmsg_node->value; if (chksum_all(raw_char_buf)) { fprintf(stderr, "chksum error\n"); free(raw_char_buf); free(ll_inmsg_node); continue; } Frame * inframe = convert_char_to_frame(raw_char_buf); if (inframe->src == receiver->send_id) { if (inframe->dst == receiver->recv_id) { Frame * outframe; char* buf; outframe = build_ack(receiver, inframe); buf = add_chksum(outframe); print_receiver(receiver); ll_append_node(outgoing_frames_head_ptr, buf); free(outframe); } } //free(inframe); free(raw_char_buf); free(ll_inmsg_node); } }
void receive_data(char *src_ip, char *dst_ip, char *path, int recv_port){ // build syn packet char buf[10000]; char ack_buf[10000]; size_t len, recv_size, data_size; struct iphdr *iph; struct tcphdr *tcph; int first = 1; while (all_get == 0){ memset(buf, 0, sizeof(buf)); recv_size = recv(sock_recv, buf, sizeof(buf), 0); if (recv_size < IP_HDR_SIZE + TCP_HDR_SIZE) { continue; } iph = (struct iphdr *)buf; tcph = (struct tcphdr *)(buf + IP_HDR_SIZE); if (iph->saddr != inet_addr(dst_ip) && tcph->source != htons(HTTP_PORT) && ntohl(tcph->dest) != recv_port){ continue; } data_size = (recv_size - IP_HDR_SIZE - TCP_HDR_SIZE); if (tcph->ack == 1 && tcph->syn == 0 && tcph->fin == 0 && tcph->rst == 0) { if (ntohl(tcph->seq) > expected_seq){ continue; } if (ntohl(tcph->seq) == expected_seq){ if (first == 1){ int doc_size = proc_http(buf+IP_HDR_SIZE+TCP_HDR_SIZE, data_size); last_seq = ntohl(tcph->seq) + doc_size; printf("doc size: %d\n", doc_size); first = 0; } expected_seq += data_size; write(fd, buf+IP_HDR_SIZE+TCP_HDR_SIZE, data_size); } len = build_ack(ack_buf, buf, recv_port, src_ip, dst_ip, seq_num); sendto(sock_send, ack_buf, len, 0, (struct sockaddr *)&sin_send, sizeof(sin_send)); } if(ntohl(tcph->seq) + data_size == last_seq){ printf("All data received\n"); return; } if (tcph->fin == 1) { passive_fin = 1; } } }
void conn_server(char *src_ip, char *dst_ip, char *path, int recv_port){ // build syn packet char buf[10000]; char ack_buf[10000]; size_t len, sent, recv_size, http_req_size; struct iphdr *iph; struct tcphdr *tcph; len = build_syn_packet(buf, 2000, src_ip, dst_ip, recv_port, start_seq_num); sent = sendto(sock_send, buf, len, 0, (struct sockaddr *)&sin_send, sizeof(sin_send)); printf("SYN packet sent, size: %u\n", sent); // receive ack while (connected != 1){ recv_size = recv(sock_recv, buf, sizeof(buf), 0); if (recv_size < IP_HDR_SIZE + TCP_HDR_SIZE) { continue; } iph = (struct iphdr *)buf; tcph = (struct tcphdr *)(buf + IP_HDR_SIZE); if (iph->saddr != inet_addr(dst_ip) && tcph->source != htons(HTTP_PORT) && ntohl(tcph->dest) != recv_port){ continue; } printf("Received: %u\n", recv_size); if (tcph->syn == 1 && tcph->ack == 1){ seq_num = start_seq_num + 1; len = build_ack(ack_buf, buf, recv_port, src_ip, dst_ip, seq_num); sendto(sock_send, ack_buf, len, 0, (struct sockaddr *)&sin_send, sizeof(sin_send)); printf("Ack replied for connection\n"); len = build_http_req(ack_buf, buf, 10000, src_ip, dst_ip, recv_port, path, seq_num); http_req_size = len - IP_HDR_SIZE - TCP_HDR_SIZE; sendto(sock_send, ack_buf, len, 0, (struct sockaddr *)&sin_send, sizeof(sin_send)); continue; } if (tcph->ack == 1) { if (ntohl(tcph->ack_seq) == seq_num + http_req_size){ seq_num += http_req_size; expected_seq = ntohl(tcph->seq); connected = 1; } } } }
/* this is the main function with the loops and modes */ void shoot(char *buf, int buff_size) { struct timespec sleep_ms_s, sleep_rem; int ret, cseqtmp, rand_tmp; char buf2[BUFSIZE], buf3[BUFSIZE], lport_str[LPORT_STR_LEN]; /* delays.retryAfter = DEFAULT_TIMEOUT; */ if (transport == SIP_UDP_TRANSPORT) { delays.retryAfter = timer_t1; } else { delays.retryAfter = timer_final; } inv_trans = 0; cseq_counter = 1; usrlocstep = REG_REP; /* initalize local vars */ cdata.dontsend=cdata.dontrecv=counters.retrans_r_c=counters.retrans_s_c= 0; delays.big_delay=counters.send_counter=counters.run= 0; timers.delaytime.tv_sec = 0; timers.delaytime.tv_usec = 0; usern = NULL; /* initialize local arrays */ memset(buf2, 0, BUFSIZE); memset(buf3, 0, BUFSIZE); memset(lport_str, 0, LPORT_STR_LEN); cdata.csock = cdata.usock = -1; cdata.connected = 0; cdata.buf_tmp = NULL; cdata.buf_tmp_size = 0; memset(&(timers.sendtime), 0, sizeof(timers.sendtime)); memset(&(timers.recvtime), 0, sizeof(timers.recvtime)); memset(&(timers.firstsendt), 0, sizeof(timers.firstsendt)); memset(&(timers.starttime), 0, sizeof(timers.starttime)); memset(&(timers.delaytime), 0, sizeof(timers.delaytime)); req = buf; rep = buf2; rec = buf3; create_sockets(&cdata); if (sleep_ms != 0) { if (sleep_ms == -2) { rand_tmp = rand(); sleep_ms_s.tv_sec = rand_tmp / 1000; sleep_ms_s.tv_nsec = (rand_tmp % 1000) * 1000000; } else { sleep_ms_s.tv_sec = sleep_ms / 1000; sleep_ms_s.tv_nsec = (sleep_ms % 1000) * 1000000; } } if (replace_b == 1){ replace_string(req, "$dsthost$", domainname); replace_string(req, "$srchost$", fqdn); sprintf(lport_str, "%i", lport); replace_string(req, "$port$", lport_str); if (username) replace_string(req, "$user$", username); } if (replace_str) replace_strings(req, replace_str); /* set all regular expression to simplfy the result code indetification */ regcomp(&(regexps.replyexp), "^SIP/[0-9]\\.[0-9] [1-6][0-9][0-9]", REG_EXTENDED|REG_NOSUB|REG_ICASE); regcomp(&(regexps.proexp), "^SIP/[0-9]\\.[0-9] 1[0-9][0-9] ", REG_EXTENDED|REG_NOSUB|REG_ICASE); regcomp(&(regexps.okexp), "^SIP/[0-9]\\.[0-9] 2[0-9][0-9] ", REG_EXTENDED|REG_NOSUB|REG_ICASE); regcomp(&(regexps.redexp), "^SIP/[0-9]\\.[0-9] 3[0-9][0-9] ", REG_EXTENDED|REG_NOSUB|REG_ICASE); regcomp(&(regexps.authexp), "^SIP/[0-9]\\.[0-9] 40[17] ", REG_EXTENDED|REG_NOSUB|REG_ICASE); regcomp(&(regexps.errexp), "^SIP/[0-9]\\.[0-9] 4[0-9][0-9] ", REG_EXTENDED|REG_NOSUB|REG_ICASE); regcomp(&(regexps.tmhexp), "^SIP/[0-9]\\.[0-9] 483 ", REG_EXTENDED|REG_NOSUB|REG_ICASE); if (username) { if (nameend > 0) { usern = str_alloc(strlen(username) + 12); create_usern(usern, username, namebeg); } else { if (*(username + strlen(username) - 1) != '@') { usern = str_alloc(strlen(username) + 2); create_usern(usern, username, -1); } else { usern = username; } } } if (usrloc == 1||invite == 1||message == 1){ /* calculate the number of required steps and create initial mes */ if (usrloc == 1) { create_msg(REQ_REG, req, NULL, usern, cseq_counter); usrlocstep=REG_REP; } else if (invite == 1) { create_msg(REQ_INV, req, rep, usern, cseq_counter); inv_trans = 1; usrlocstep=INV_RECV; } else { create_msg(REQ_MES, req, rep, usern, cseq_counter); if (mes_body) usrlocstep=MES_OK_RECV; else usrlocstep=MES_RECV; } } else if (trace == 1){ /* for trace we need some spezial initis */ namebeg=0; create_msg(REQ_OPT, req, NULL, usern, cseq_counter); set_maxforw(req, namebeg); } else if (flood == 1){ if (nameend<=0) nameend=INT_MAX; namebeg=1; create_msg(REQ_FLOOD, req, NULL, usern, cseq_counter); } else if (randtrash == 1){ counters.randretrys=0; namebeg=1; create_msg(REQ_RAND, req, NULL, usern, cseq_counter); nameend=(int)strlen(req); if (trashchar == 1){ if (trashchar < nameend) nameend=trashchar; else fprintf(stderr, "warning: number of trashed chars to big. setting to " "request length\n"); } trash_random(req); } else { /* for none of the modes we also need some inits */ if (file_b == 0) { namebeg=1; create_msg(REQ_OPT, req, NULL, usern, cseq_counter); } else { if (STRNCASECMP(req, INV_STR, INV_STR_LEN) == 0) { inv_trans = 1; } if(via_ins == 1) add_via(req); } /* delays.retryAfter = delays.retryAfter / 10; */ if(maxforw!=-1) set_maxforw(req, maxforw); } cdata.connected = set_target(&(cdata.adr), address, rport, cdata.csock, cdata.connected); /* here we go until someone decides to exit */ while(1) { before_sending(); if (sleep_ms == -2) { rand_tmp = rand(); sleep_ms_s.tv_sec = rand_tmp / 1000; sleep_ms_s.tv_nsec = (rand_tmp % 1000) * 1000; } if (sleep_ms != 0) { dbg("sleeping for %li s + %li ns\n", sleep_ms_s.tv_sec, sleep_ms_s.tv_nsec); nanosleep(&sleep_ms_s, &sleep_rem); } send_message(req, &cdata, &counters, &timers); /* in flood we are only interested in sending so skip the rest */ if (flood == 0) { ret = recv_message(rec, BUFSIZE, inv_trans, &delays, &timers, &counters, &cdata, ®exps); if(ret > 0) { if (usrlocstep == INV_OK_RECV) { swap_ptr(&rep, &req); } /* send ACK for non-provisional reply on INVITE */ if ((STRNCASECMP(req, "INVITE", 6)==0) && (regexec(&(regexps.replyexp), rec, 0, 0, 0) == REG_NOERROR) && (regexec(&(regexps.proexp), rec, 0, 0, 0) == REG_NOMATCH)) { build_ack(req, rec, rep, ®exps); cdata.dontsend = 0; inv_trans = 0; /* lets fire the ACK to the server */ send_message(rep, &cdata, &counters, &timers); inv_trans = 1; } /* check for old CSeq => ignore retransmission */ cseqtmp = cseq(rec); if ((0 < cseqtmp) && (cseqtmp < cseq_counter)) { if (verbose>0) { printf("ignoring retransmission\n"); } counters.retrans_r_c++; cdata.dontsend = 1; continue; } else if (regexec(&(regexps.authexp), rec, 0, 0, 0) == REG_NOERROR) { if (!username && !auth_username) { if (timing > 0) { timing--; if (timing == 0) { if (counters.run == 0) { counters.run++; } printf("%.3f/%.3f/%.3f ms\n", delays.small_delay, delays.all_delay / counters.run, delays.big_delay); exit_code(0, __PRETTY_FUNCTION__, NULL); } counters.run++; new_transaction(req, rep); delays.retryAfter = timer_t1; continue; } fprintf(stderr, "%s\nerror: received 40[17] but cannot " "authentication without a username or auth username\n", rec); log_message(req); exit_code(2, __PRETTY_FUNCTION__, "missing username for authentication"); } /* prevents a strange error */ regcomp(&(regexps.authexp), "^SIP/[0-9]\\.[0-9] 40[17] ", REG_EXTENDED|REG_NOSUB|REG_ICASE); insert_auth(req, rec); if (verbose > 2) printf("\nreceived:\n%s\n", rec); new_transaction(req, rep); continue; } /* if auth...*/ /* lets see if received a redirect */ if (redirects == 1 && regexec(&(regexps.redexp), rec, 0, 0, 0) == REG_NOERROR) { handle_3xx(&(cdata.adr)); } /* if redircts... */ else if (trace == 1) { trace_reply(); } /* if trace ... */ else if (usrloc == 1||invite == 1||message == 1) { handle_usrloc(); } else if (randtrash == 1) { handle_randtrash(); } else { handle_default(); } /* redirect, auth, and modes */ } /* ret > 0 */ else if (ret == -1) { // we did not got anything back, send again /* no re-transmission on reliable transports */ if (transport != SIP_UDP_TRANSPORT) { cdata.dontsend = 1; } continue; } else if (ret == -2) { // we received non-matching ICMP cdata.dontsend = 1; continue; } else { if (usrloc == 1) { printf("failed\n"); } perror("socket error"); exit_code(3, __PRETTY_FUNCTION__, "internal socket error"); } } /* !flood */ else { if (counters.send_counter == 1) { memcpy(&(timers.firstsendt), &(timers.sendtime), sizeof(struct timeval)); } if (namebeg==nameend) { printf("flood end reached\n"); printf("it took %.3f ms seconds to send %i request.\n", deltaT(&(timers.firstsendt), &(timers.sendtime)), namebeg); printf("we sent %f requests per second.\n", (namebeg/(deltaT(&(timers.firstsendt), &(timers.sendtime)))*1000)); exit_code(0, __PRETTY_FUNCTION__, NULL); } namebeg++; cseq_counter++; create_msg(REQ_FLOOD, req, NULL, usern, cseq_counter); } } /* while 1 */ /* this should never happen any more... */ if (randtrash == 1) { exit_code(0, __PRETTY_FUNCTION__, NULL); } printf("** give up retransmissioning....\n"); if (counters.retrans_r_c>0 && (verbose > 1)) { printf("%i retransmissions received during test\n", counters.retrans_r_c); } if (counters.retrans_s_c>0 && (verbose > 1)) { printf("sent %i retransmissions during test\n", counters.retrans_s_c); } exit_code(3, __PRETTY_FUNCTION__, "got outside of endless messaging loop"); }