static int output_sendto (int sock, const void *frame, int frame_size, struct sockaddr_in *addr) { struct frame_info { int8_t mask[2]; // 'FM' const int32_t len; // int8_t data[UDPDATA_MAX_SIZE]; }__attribute__((__packed__)); struct frame_info fm; fm.mask[0] = 'F'; fm.mask[1] = 'M'; fm.len = 0; unsigned char *p = NULL; p = (unsigned char *)frame; while(frame_size > 0) { static int cnt = 0; if(frame_size < UDPDATA_MAX_SIZE) fm.len = frame_size; else fm.len = UDPDATA_MAX_SIZE; memcpy(fm.data, p, fm.len); int i; for(i = 0; i < 5; i++){ sendto(sock, &fm, sizeof(fm), 0, (struct sockaddr*)addr, sizeof(struct sockaddr_in)); char answer[128]; int len; int ret; fd_set input; struct timeval timeout; FD_ZERO(&input); FD_SET(sock, &input); timeout.tv_sec = 0; timeout.tv_usec = 5000; ret = select(sock + 1, &input, NULL, NULL, &timeout); if (ret < 0) { perror("select"); break; } else if (ret == 0) { if(cnt == 0) printf("ERROR: no recv\n"); printf("%d\r", cnt++); fflush(stdout); } else { if (FD_ISSET(sock, &input)) { cnt = 0; len = recvfrom(sock, answer, sizeof(answer), 0, NULL, 0); if(len > 0) if(strncmp(answer, "OK", 2) == 0) break; } } } frame_size-=fm.len; p += fm.len; } p = NULL; return 0; }
int getReplyPackets(int method,int peer,int batchP, struct response_set *responses, unsigned char *transaction_id,int timeout) { /* set timeout alarm */ /* get packets until timeout, or until we get a packet from the specified peer if method==REQ_SERIAL. If REQ_SERIAL we also reject packets from other senders as they must be spoofs. */ struct timeval t; int timeout_secs; int timeout_usecs; int to=timeout; if (debug>1) printf("getReplyPackets(policy=%d)\n",method); /* Work out when the timeout will expire */ gettimeofday(&t,NULL); timeout_secs=t.tv_sec; timeout_usecs=t.tv_usec; if (to>1000) { timeout_secs+=(to/1000); to=to%1000; } timeout_usecs+=to*1000; if (timeout_usecs>1000000) { timeout_secs++; timeout_usecs-=1000000; } while(1) { unsigned char buffer[16384]; socklen_t recvaddrlen=sizeof(recvaddr); struct pollfd fds; client_port=((struct sockaddr_in*)&recvaddr)->sin_port; bzero((void *)&recvaddr,sizeof(recvaddr)); fds.fd=sock; fds.events=POLLIN; while (poll(&fds,1,10 /* wait for 10ms at a time */)<1) { gettimeofday(&t,NULL); if (t.tv_sec>timeout_secs) return 1; if (t.tv_sec==timeout_secs&&t.tv_usec>=timeout_usecs) return 1; } client_port=((struct sockaddr_in*)&recvaddr)->sin_port; int len=recvfrom(sock,buffer,sizeof(buffer),0,&recvaddr,&recvaddrlen); client_addr=((struct sockaddr_in*)&recvaddr)->sin_addr; if (debug) fprintf(stderr,"Received reply from %s (len=%d).\n",inet_ntoa(client_addr),len); if (debug>1) dump("recvaddr",(unsigned char *)&recvaddr,recvaddrlen); if (debug>2) dump("packet",(unsigned char *)buffer,len); if (dropPacketP(len)) { if (debug) fprintf(stderr,"Simulation mode: Dropped packet due to simulated link parameters.\n"); continue; } if (!packetOk(buffer,len,transaction_id)) { /* Packet passes tests - extract responses and append them to the end of the response list */ if (extractResponses(client_addr,buffer,len,responses)) return setReason("Problem extracting response fields from reply packets"); if (method==REQ_SERIAL||method==REQ_FIRSTREPLY) { if (!batchP) return 0; /* In batch mode we need ACTION_DONE to mark end of transmission. While it gets sent last, out-of-order delivery means we can't rely on such a nice arrangement. */ { /* XXX inefficient for long lists. XXX can be made better by working backwards from end using double-linked list and remembering the previous length of the list */ struct response *r=responses->responses; while(r) { if (r->code==ACTION_DONE) return 0; r=r->next; } } } else { if (debug>1) printf("Waiting for more packets, since called with policy %d\n",method); } } else { if (debug) setReason("Ignoring invalid packet"); } } }
static int rtp_read(URLContext *h, uint8_t *buf, int size) { RTPContext *s = h->priv_data; struct sockaddr_in from; socklen_t from_len; int len, fd_max, n; fd_set rfds; #if 0 for(;;) { from_len = sizeof(from); len = recvfrom (s->rtp_fd, buf, size, 0, (struct sockaddr *)&from, &from_len); if (len < 0) { if (ff_neterrno() == FF_NETERROR(EAGAIN) || ff_neterrno() == FF_NETERROR(EINTR)) continue; return AVERROR(EIO); } break; } #else for(;;) { /* build fdset to listen to RTP and RTCP packets */ FD_ZERO(&rfds); fd_max = s->rtp_fd; FD_SET(s->rtp_fd, &rfds); if (s->rtcp_fd > fd_max) fd_max = s->rtcp_fd; FD_SET(s->rtcp_fd, &rfds); n = select(fd_max + 1, &rfds, NULL, NULL, NULL); if (n > 0) { /* first try RTCP */ if (FD_ISSET(s->rtcp_fd, &rfds)) { from_len = sizeof(from); len = recvfrom (s->rtcp_fd, buf, size, 0, (struct sockaddr *)&from, &from_len); if (len < 0) { if (ff_neterrno() == FF_NETERROR(EAGAIN) || ff_neterrno() == FF_NETERROR(EINTR)) continue; return AVERROR(EIO); } break; } /* then RTP */ if (FD_ISSET(s->rtp_fd, &rfds)) { from_len = sizeof(from); len = recvfrom (s->rtp_fd, buf, size, 0, (struct sockaddr *)&from, &from_len); if (len < 0) { if (ff_neterrno() == FF_NETERROR(EAGAIN) || ff_neterrno() == FF_NETERROR(EINTR)) continue; return AVERROR(EIO); } break; } } } #endif return len; }
void dtls_server (int port) { int listen_sd; int sock, ret; struct sockaddr_in sa_serv; char buffer[MAX_MESSAGE_SIZE]; int mtu = 1400; unsigned char sequence[8]; gnutls_datum_t cookie_key; // Should this be regenerated for each incoming conn? // Certs char *cafile = "./certs/cert.pem"; char *crlfile = "./certs/crl.pem"; char *certfile = "./certs/cert.pem"; char *keyfile = "./certs/key.pem"; // Configure credentials and session gnutls_certificate_allocate_credentials (&x509_cred); gnutls_certificate_set_x509_trust_file (x509_cred, cafile, GNUTLS_X509_FMT_PEM); gnutls_certificate_set_x509_crl_file (x509_cred, crlfile, GNUTLS_X509_FMT_PEM); ret = gnutls_certificate_set_x509_key_file (x509_cred, certfile, keyfile, GNUTLS_X509_FMT_PEM); if (ret < 0) Die("No keys or certs were found"); // Set some crypto params and other stuff generate_dh_params (); // Diffie-Hellman gnutls_priority_init (&priority_cache, "PERFORMANCE:-VERS-TLS-ALL:+VERS-DTLS1.0:%SERVER_PRECEDENCE", NULL); gnutls_key_generate (&cookie_key, GNUTLS_COOKIE_KEY_SIZE); /* Socket operations */ listen_sd = socket (AF_INET, SOCK_DGRAM, 0); memset (&sa_serv, '\0', sizeof (sa_serv)); sa_serv.sin_family = AF_INET; sa_serv.sin_addr.s_addr = INADDR_ANY; sa_serv.sin_port = htons (port); /* DTLS requires the IP don't fragment (DF) bit to be set */ #if defined(IP_DONTFRAG) int optval = 1; setsockopt (listen_sd, IPPROTO_IP, IP_DONTFRAG, (const void *) &optval, sizeof (optval)); #elif defined(IP_MTU_DISCOVER) int optval = IP_PMTUDISC_DO; setsockopt(listen_sd, IPPROTO_IP, IP_MTU_DISCOVER, (const void*) &optval, sizeof (optval)); #endif bind (listen_sd, (struct sockaddr *) &sa_serv, sizeof (sa_serv)); printf ("UDP server ready. Listening to port '%d'.\n\n", port); for (;;) { printf ("Waiting for connection...\n"); sock = wait_for_connection (listen_sd); if (sock < 0) continue; // Someone is accepting a connection, get data structures ready priv_data_st priv; gnutls_dtls_prestate_st prestate; gnutls_session_t session; struct sockaddr_in cli_addr; socklen_t cli_addr_size; cli_addr_size = sizeof (cli_addr); ret = recvfrom (sock, buffer, sizeof (buffer), MSG_PEEK, (struct sockaddr *) &cli_addr, &cli_addr_size); if (ret > 0) { memset (&prestate, 0, sizeof (prestate)); ret = gnutls_dtls_cookie_verify (&cookie_key, &cli_addr, sizeof (cli_addr), buffer, ret, &prestate); if (ret < 0) /* cookie not valid */ { priv_data_st s; memset (&s, 0, sizeof (s)); s.fd = sock; s.cli_addr = (void *) &cli_addr; s.cli_addr_size = sizeof (cli_addr); printf ("Sending hello verify request to %s\n", human_addr ((struct sockaddr *) &cli_addr, sizeof (cli_addr), buffer, sizeof (buffer))); gnutls_dtls_cookie_send (&cookie_key, &cli_addr, sizeof (cli_addr), &prestate, (gnutls_transport_ptr_t) & s, push_func); /* discard peeked data */ recvfrom (sock, buffer, sizeof (buffer), 0, (struct sockaddr *) &cli_addr, &cli_addr_size); usleep (100); continue; } printf ("Accepted connection from %s\n", human_addr ((struct sockaddr *) &cli_addr, sizeof (cli_addr), buffer, sizeof (buffer))); } else continue; session = initialize_tls_session (); gnutls_dtls_prestate_set (session, &prestate); gnutls_dtls_set_mtu (session, mtu); priv.session = session; priv.fd = sock; priv.cli_addr = (struct sockaddr *) &cli_addr; priv.cli_addr_size = sizeof (cli_addr); gnutls_transport_set_ptr (session, &priv); gnutls_transport_set_push_function (session, push_func); gnutls_transport_set_pull_function (session, pull_func); gnutls_transport_set_pull_timeout_function (session, pull_timeout_func); do { ret = gnutls_handshake (session); } while (ret < 0 && gnutls_error_is_fatal (ret) == 0); if (ret < 0) { fprintf (stderr, "Error in handshake(): %s\n", gnutls_strerror (ret)); gnutls_deinit (session); continue; } printf ("- Handshake was completed\n"); for (;;) { do { ret = gnutls_record_recv_seq (session, buffer, MAX_MESSAGE_SIZE, sequence); } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); if (ret < 0) { fprintf (stderr, "Error in recv(): %s\n", gnutls_strerror (ret)); break; } if (ret == 0) { printf ("EOF\n\n"); break; } buffer[ret] = 0; printf ("received[%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x]: %s\n", sequence[0], sequence[1], sequence[2], sequence[3], sequence[4], sequence[5], sequence[6], sequence[7], buffer); /* reply back */ ret = gnutls_record_send (session, buffer, ret); if (ret < 0) { fprintf (stderr, "Error in send(): %s\n", gnutls_strerror (ret)); break; } } gnutls_bye (session, GNUTLS_SHUT_WR); gnutls_deinit (session); } close (listen_sd); gnutls_certificate_free_credentials (x509_cred); gnutls_priority_deinit (priority_cache); gnutls_global_deinit (); }
/** void HandleSecure() v0.3 * Handle the secure connections */ void HandleSecure() { int agentid; char buffer[OS_MAXSTR +1]; char cleartext_msg[OS_MAXSTR +1]; char srcip[IPSIZE +1]; char *tmp_msg; char srcmsg[OS_FLSIZE +1]; int recv_b; struct sockaddr_in peer_info; socklen_t peer_size; /* Send msg init */ send_msg_init(); /* Initializing key mutex. */ keyupdate_init(); /* Initializing manager */ manager_init(0); /* Creating Ar forwarder thread */ if(CreateThread(AR_Forward, (void *)NULL) != 0) { ErrorExit(THREAD_ERROR, ARGV0); } /* Creating wait_for_msgs thread */ if(CreateThread(wait_for_msgs, (void *)NULL) != 0) { ErrorExit(THREAD_ERROR, ARGV0); } /* Connecting to the message queue * Exit if it fails. */ if((logr.m_queue = StartMQ(DEFAULTQUEUE,WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQUEUE); } verbose(AG_AX_AGENTS, ARGV0, MAX_AGENTS); /* Reading authentication keys */ verbose(ENC_READ, ARGV0); OS_ReadKeys(&keys); debug1("%s: DEBUG: OS_StartCounter.", ARGV0); OS_StartCounter(&keys); debug1("%s: DEBUG: OS_StartCounter completed.", ARGV0); /* setting up peer size */ peer_size = sizeof(peer_info); logr.peer_size = sizeof(peer_info); /* Initializing some variables */ memset(buffer, '\0', OS_MAXSTR +1); memset(cleartext_msg, '\0', OS_MAXSTR +1); memset(srcmsg, '\0', OS_FLSIZE +1); tmp_msg = NULL; /* loop in here */ while(1) { /* Receiving message */ recv_b = recvfrom(logr.sock, buffer, OS_MAXSTR, 0, (struct sockaddr *)&peer_info, &peer_size); /* Nothing received */ if(recv_b <= 0) { continue; } /* Setting the source ip */ strncpy(srcip, inet_ntoa(peer_info.sin_addr), IPSIZE); srcip[IPSIZE] = '\0'; /* Getting a valid agentid */ if(buffer[0] == '!') { tmp_msg = buffer; tmp_msg++; /* We need to make sure that we have a valid id * and that we reduce the recv buffer size. */ while(isdigit((int)*tmp_msg)) { tmp_msg++; recv_b--; } if(*tmp_msg != '!') { merror(ENCFORMAT_ERROR, __local_name, srcip); continue; } *tmp_msg = '\0'; tmp_msg++; recv_b-=2; agentid = OS_IsAllowedDynamicID(&keys, buffer +1, srcip); if(agentid == -1) { if(check_keyupdate()) { agentid = OS_IsAllowedDynamicID(&keys, buffer +1, srcip); if(agentid == -1) { merror(ENC_IP_ERROR, ARGV0, srcip); continue; } } else { merror(ENC_IP_ERROR, ARGV0, srcip); continue; } } } else { agentid = OS_IsAllowedIP(&keys, srcip); if(agentid < 0) { if(check_keyupdate()) { agentid = OS_IsAllowedIP(&keys, srcip); if(agentid == -1) { merror(DENYIP_WARN,ARGV0,srcip); continue; } } else { merror(DENYIP_WARN,ARGV0,srcip); continue; } } tmp_msg = buffer; } /* Decrypting the message */ tmp_msg = ReadSecMSG(&keys, tmp_msg, cleartext_msg, agentid, recv_b -1); if(tmp_msg == NULL) { /* If duplicated, a warning was already generated */ continue; } /* Check if it is a control message */ if(IsValidHeader(tmp_msg)) { /* We need to save the peerinfo if it is a control msg */ memcpy(&keys.keyentries[agentid]->peer_info, &peer_info, peer_size); keys.keyentries[agentid]->rcvd = time(0); save_controlmsg(agentid, tmp_msg); continue; } /* Generating srcmsg */ snprintf(srcmsg, OS_FLSIZE,"(%s) %s",keys.keyentries[agentid]->name, keys.keyentries[agentid]->ip->ip); /* If we can't send the message, try to connect to the * socket again. If it not exit. */ if(SendMSG(logr.m_queue, tmp_msg, srcmsg, SECURE_MQ) < 0) { merror(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno)); if((logr.m_queue = StartMQ(DEFAULTQUEUE, WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQUEUE); } } } }
static int rtp_read(URLContext *h, uint8_t *buf, int size) { RTPContext *s = h->priv_data; struct sockaddr_storage from; socklen_t from_len; int len, n; struct pollfd p[2] = {{s->rtp_fd, POLLIN, 0}, {s->rtcp_fd, POLLIN, 0}}; #if 0 for(;;) { from_len = sizeof(from); len = recvfrom (s->rtp_fd, buf, size, 0, (struct sockaddr *)&from, &from_len); if (len < 0) { if (ff_neterrno() == AVERROR(EAGAIN) || ff_neterrno() == AVERROR(EINTR)) continue; return AVERROR(EIO); } break; } #else for(;;) { if (url_interrupt_cb()) return AVERROR_EXIT; /* build fdset to listen to RTP and RTCP packets */ n = poll(p, 2, 100); if (n > 0) { /* first try RTCP */ if (p[1].revents & POLLIN) { from_len = sizeof(from); len = recvfrom (s->rtcp_fd, buf, size, 0, (struct sockaddr *)&from, &from_len); if (len < 0) { if (ff_neterrno() == AVERROR(EAGAIN) || ff_neterrno() == AVERROR(EINTR)) continue; return AVERROR(EIO); } break; } /* then RTP */ if (p[0].revents & POLLIN) { from_len = sizeof(from); len = recvfrom (s->rtp_fd, buf, size, 0, (struct sockaddr *)&from, &from_len); if (len < 0) { if (ff_neterrno() == AVERROR(EAGAIN) || ff_neterrno() == AVERROR(EINTR)) continue; return AVERROR(EIO); } break; } } else if (n < 0) { if (ff_neterrno() == AVERROR(EINTR)) continue; return AVERROR(EIO); } } #endif return len; }
/* Callback function executed when something is received on fd */ int receive_callback(int file, void *arg) { char buf[sizeof(struct rudp_packet)]; struct sockaddr_in sender; size_t sender_length = sizeof(struct sockaddr_in); recvfrom(file, &buf, sizeof(struct rudp_packet), 0, (struct sockaddr *)&sender, &sender_length); struct rudp_packet *received_packet = malloc(sizeof(struct rudp_packet)); if(received_packet == NULL) { fprintf(stderr, "receive_callback: Error allocating packet\n"); return -1; } memcpy(received_packet, &buf, sizeof(struct rudp_packet)); struct rudp_hdr rudpheader = received_packet->header; char type[5]; short t = rudpheader.type; if(t == 1) strcpy(type, "DATA"); else if(t == 2) strcpy(type, "ACK"); else if(t == 4) strcpy(type, "SYN"); else if(t==5) strcpy(type, "FIN"); else strcpy(type, "BAD"); printf("Received %s packet from %s:%d seq number=%u on socket=%d\n",type, inet_ntoa(sender.sin_addr), ntohs(sender.sin_port),rudpheader.seqno,file); /* Locate the correct socket in the socket list */ if(socket_list_head == NULL) { fprintf(stderr, "Error: attempt to receive on invalid socket. No sockets in the list\n"); return -1; } else { /* We have sockets to check */ struct rudp_socket_list *curr_socket = socket_list_head; while(curr_socket != NULL) { if((int)curr_socket->rsock == file) { break; } curr_socket = curr_socket->next; } if((int)curr_socket->rsock == file) { /* We found the correct socket, now see if a session already exists for this peer */ if(curr_socket->sessions_list_head == NULL) { /* The list is empty, so we check if the sender has initiated the protocol properly (by sending a SYN) */ if(rudpheader.type == RUDP_SYN) { /* SYN Received. Create a new session at the head of the list */ u_int32_t seqno = rudpheader.seqno + 1; create_receiver_session(curr_socket, seqno, &sender); /* Respond with an ACK */ struct rudp_packet *p = create_rudp_packet(RUDP_ACK, seqno, 0, NULL); send_packet(true, (rudp_socket_t)file, p, &sender); free(p); } else { /* No sessions exist and we got a non-SYN, so ignore it */ } } else { /* Some sessions exist to be checked */ bool_t session_found = false; struct session *curr_session = curr_socket->sessions_list_head; struct session *last_session; while(curr_session != NULL) { if(curr_session->next == NULL) { last_session = curr_session; } if(compare_sockaddr(&curr_session->address, &sender) == 1) { /* Found an existing session */ session_found = true; break; } curr_session = curr_session->next; } if(session_found == false) { /* No session was found for this peer */ if(rudpheader.type == RUDP_SYN) { /* SYN Received. Send an ACK and create a new session */ u_int32_t seqno = rudpheader.seqno + 1; create_receiver_session(curr_socket, seqno, &sender); struct rudp_packet *p = create_rudp_packet(RUDP_ACK, seqno, 0, NULL); send_packet(true, (rudp_socket_t)file, p, &sender); free(p); } else { /* Session does not exist and non-SYN received - ignore it */ } } else { /* We found a matching session */ if(rudpheader.type == RUDP_SYN) { if(curr_session->receiver == NULL || curr_session->receiver->status == OPENING) { /* Create a new receiver session and ACK the SYN*/ struct receiver_session *new_receiver_session = malloc(sizeof(struct receiver_session)); if(new_receiver_session == NULL) { fprintf(stderr, "receive_callback: Error allocating receiver session\n"); return -1; } new_receiver_session->expected_seqno = rudpheader.seqno + 1; new_receiver_session->status = OPENING; new_receiver_session->session_finished = false; curr_session->receiver = new_receiver_session; u_int32_t seqno = curr_session->receiver->expected_seqno; struct rudp_packet *p = create_rudp_packet(RUDP_ACK, seqno, 0, NULL); send_packet(true, (rudp_socket_t)file, p, &sender); free(p); } else { /* Received a SYN when there is already an active receiver session, so we ignore it */ } } if(rudpheader.type == RUDP_ACK) { u_int32_t ack_sqn = received_packet->header.seqno; if(curr_session->sender->status == SYN_SENT) { /* This an ACK for a SYN */ u_int32_t syn_sqn = curr_session->sender->seqno; if( (ack_sqn - 1) == syn_sqn) { /* Delete the retransmission timeout */ event_timeout_delete(timeout_callback, curr_session->sender->syn_timeout_arg); struct timeoutargs *t = (struct timeoutargs *)curr_session->sender->syn_timeout_arg; free(t->packet); free(t->recipient); free(t); curr_session->sender->status = OPEN; while(curr_session->sender->data_queue != NULL) { /* Check if the window is already full */ if(curr_session->sender->sliding_window[RUDP_WINDOW-1] != NULL) { break; } else { int index; int i; /* Find the first unused window slot */ for(i = RUDP_WINDOW-1; i >= 0; i--) { if(curr_session->sender->sliding_window[i] == NULL) { index = i; } } /* Send packet, add to window and remove from queue */ u_int32_t seqno = ++syn_sqn; int len = curr_session->sender->data_queue->len; char *payload = curr_session->sender->data_queue->item; struct rudp_packet *datap = create_rudp_packet(RUDP_DATA, seqno, len, payload); curr_session->sender->seqno += 1; curr_session->sender->sliding_window[index] = datap; curr_session->sender->retransmission_attempts[index] = 0; struct data *temp = curr_session->sender->data_queue; curr_session->sender->data_queue = curr_session->sender->data_queue->next; free(temp->item); free(temp); send_packet(false, (rudp_socket_t)file, datap, &sender); } } } } else if(curr_session->sender->status == OPEN) { /* This is an ACK for DATA */ if(curr_session->sender->sliding_window[0] != NULL) { if(curr_session->sender->sliding_window[0]->header.seqno == (rudpheader.seqno-1)) { /* Correct ACK received. Remove the first window item and shift the rest left */ event_timeout_delete(timeout_callback, curr_session->sender->data_timeout_arg[0]); struct timeoutargs *args = (struct timeoutargs *)curr_session->sender->data_timeout_arg[0]; free(args->packet); free(args->recipient); free(args); free(curr_session->sender->sliding_window[0]); int i; if(RUDP_WINDOW == 1) { curr_session->sender->sliding_window[0] = NULL; curr_session->sender->retransmission_attempts[0] = 0; curr_session->sender->data_timeout_arg[0] = NULL; } else { for(i = 0; i < RUDP_WINDOW - 1; i++) { curr_session->sender->sliding_window[i] = curr_session->sender->sliding_window[i+1]; curr_session->sender->retransmission_attempts[i] = curr_session->sender->retransmission_attempts[i+1]; curr_session->sender->data_timeout_arg[i] = curr_session->sender->data_timeout_arg[i+1]; if(i == RUDP_WINDOW-2) { curr_session->sender->sliding_window[i+1] = NULL; curr_session->sender->retransmission_attempts[i+1] = 0; curr_session->sender->data_timeout_arg[i+1] = NULL; } } } while(curr_session->sender->data_queue != NULL) { if(curr_session->sender->sliding_window[RUDP_WINDOW-1] != NULL) { break; } else { int index; int i; /* Find the first unused window slot */ for(i = RUDP_WINDOW-1; i >= 0; i--) { if(curr_session->sender->sliding_window[i] == NULL) { index = i; } } /* Send packet, add to window and remove from queue */ curr_session->sender->seqno = curr_session->sender->seqno + 1; u_int32_t seqno = curr_session->sender->seqno; int len = curr_session->sender->data_queue->len; char *payload = curr_session->sender->data_queue->item; struct rudp_packet *datap = create_rudp_packet(RUDP_DATA, seqno, len, payload); curr_session->sender->sliding_window[index] = datap; curr_session->sender->retransmission_attempts[index] = 0; struct data *temp = curr_session->sender->data_queue; curr_session->sender->data_queue = curr_session->sender->data_queue->next; free(temp->item); free(temp); send_packet(false, (rudp_socket_t)file, datap, &sender); } } if(curr_socket->close_requested) { /* Can the socket be closed? */ struct session *head_sessions = curr_socket->sessions_list_head; while(head_sessions != NULL) { if(head_sessions->sender->session_finished == false) { if(head_sessions->sender->data_queue == NULL && head_sessions->sender->sliding_window[0] == NULL && head_sessions->sender->status == OPEN) { head_sessions->sender->seqno += 1; struct rudp_packet *p = create_rudp_packet(RUDP_FIN, head_sessions->sender->seqno, 0, NULL); send_packet(false, (rudp_socket_t)file, p, &head_sessions->address); free(p); head_sessions->sender->status = FIN_SENT; } } head_sessions = head_sessions->next; } } } } } else if(curr_session->sender->status == FIN_SENT) { /* Handle ACK for FIN */ if( (curr_session->sender->seqno + 1) == received_packet->header.seqno) { event_timeout_delete(timeout_callback, curr_session->sender->fin_timeout_arg); struct timeoutargs *t = curr_session->sender->fin_timeout_arg; free(t->packet); free(t->recipient); free(t); curr_session->sender->session_finished = true; if(curr_socket->close_requested) { /* See if we can close the socket */ struct session *head_sessions = curr_socket->sessions_list_head; bool_t all_done = true; while(head_sessions != NULL) { if(head_sessions->sender->session_finished == false) { all_done = false; } else if(head_sessions->receiver != NULL && head_sessions->receiver->session_finished == false) { all_done = false; } else { free(head_sessions->sender); if(head_sessions->receiver) { free(head_sessions->receiver); } } struct session *temp = head_sessions; head_sessions = head_sessions->next; free(temp); } if(all_done) { if(curr_socket->handler != NULL) { curr_socket->handler((rudp_socket_t)file, RUDP_EVENT_CLOSED, &sender); event_fd_delete(receive_callback, (rudp_socket_t)file); close(file); free(curr_socket); } } } } else { /* Received incorrect ACK for FIN - ignore it */ } } } else if(rudpheader.type == RUDP_DATA) { /* Handle DATA packet. If the receiver is OPENING, it can transition to OPEN */ if(curr_session->receiver->status == OPENING) { if(rudpheader.seqno == curr_session->receiver->expected_seqno) { curr_session->receiver->status = OPEN; } } if(rudpheader.seqno == curr_session->receiver->expected_seqno) { /* Sequence numbers match - ACK the data */ u_int32_t seqno = rudpheader.seqno + 1; curr_session->receiver->expected_seqno = seqno; struct rudp_packet *p = create_rudp_packet(RUDP_ACK, seqno, 0, NULL); send_packet(true, (rudp_socket_t)file, p, &sender); free(p); /* Pass the data up to the application */ if(curr_socket->recv_handler != NULL) curr_socket->recv_handler((rudp_socket_t)file, &sender, (void*)&received_packet->payload, received_packet->payload_length); } /* Handle the case where an ACK was lost */ else if(SEQ_GEQ(rudpheader.seqno, (curr_session->receiver->expected_seqno - RUDP_WINDOW)) && SEQ_LT(rudpheader.seqno, curr_session->receiver->expected_seqno)) { u_int32_t seqno = rudpheader.seqno + 1; struct rudp_packet *p = create_rudp_packet(RUDP_ACK, seqno, 0, NULL); send_packet(true, (rudp_socket_t)file, p, &sender); free(p); } } else if(rudpheader.type == RUDP_FIN) { if(curr_session->receiver->status == OPEN) { if(rudpheader.seqno == curr_session->receiver->expected_seqno) { /* If the FIN is correct, we can ACK it */ u_int32_t seqno = curr_session->receiver->expected_seqno + 1; struct rudp_packet *p = create_rudp_packet(RUDP_ACK, seqno, 0, NULL); send_packet(true, (rudp_socket_t)file, p, &sender); free(p); curr_session->receiver->session_finished = true; if(curr_socket->close_requested) { /* Can we close the socket now? */ struct session *head_sessions = curr_socket->sessions_list_head; int all_done = true; while(head_sessions != NULL) { if(head_sessions->sender->session_finished == false) { all_done = false; } else if(head_sessions->receiver != NULL && head_sessions->receiver->session_finished == false) { all_done = false; } else { free(head_sessions->sender); if(head_sessions->receiver) { free(head_sessions->receiver); } } struct session *temp = head_sessions; head_sessions = head_sessions->next; free(temp); } if(all_done) { if(curr_socket->handler != NULL) { curr_socket->handler((rudp_socket_t)file, RUDP_EVENT_CLOSED, &sender); event_fd_delete(receive_callback, (rudp_socket_t)file); close(file); free(curr_socket); } } } } else { /* FIN received with incorrect sequence number - ignore it */ } } } } } } } free(received_packet); return 0; }
/* The server waits for client to send its initial sequence number, send its own initial sequence number, and returns the client's initial sequence number. */ uint16_t handshake(int sockfd, struct sockaddr_in &clientaddr, socklen_t clientlen) { unsigned char handshake_buf[HEADERSIZE]; segment syn, ack; // receive syn long recv_len; if ((recv_len = recvfrom(sockfd, handshake_buf, HEADERSIZE, 0, (struct sockaddr *) &clientaddr, &clientlen)) < 8) { cerr << "syn error" << endl; return USHRT_MAX; } syn.decode(handshake_buf, HEADERSIZE); if (syn.getFlagsyn()) { server_seq = server_ack = seq_rand(MAX_SEQ_NUM); bool firstSyn = true; do {// send syn-ack segment synack; synack.setSeqnum(server_seq); setReplyAck(syn, synack, 1); client_ack = synack.getAcknum(); synack.setFlagsyn(); synack.setFlagack(); unsigned char *handshake_buf2 = synack.encode(NULL, 0); sendto(sockfd, handshake_buf2, HEADERSIZE, 0, (struct sockaddr *) &clientaddr, clientlen); if (firstSyn) { cout << "Sending packet " << server_seq << " " << cwnd << " " << ssthresh << " SYN" << endl; firstSyn = false; } else { cout << "Sending packet " << server_seq << " " << cwnd << " " << ssthresh << " Retransmission SYN" << endl; } clock_t clock_begin, clock_end; clock_begin = clock_end = clock(); double elapsed_secs = 0.0; // receive ack while ((recv_len = recvfrom(sockfd, handshake_buf, HEADERSIZE, MSG_DONTWAIT, (struct sockaddr *) &clientaddr, &clientlen)) == -1) { if (errno != EWOULDBLOCK && errno != EAGAIN) perror("recvfrom"); clock_end = clock(); elapsed_secs = double(clock_end - clock_begin) / CLOCKS_PER_SEC; if (elapsed_secs >= timeout) break; } if (elapsed_secs < timeout) { ack.decode(handshake_buf, HEADERSIZE); if (ack.getFlagsyn()) continue; else break; } } while (true); server_seq = (server_seq + 1) % MAX_SEQ_NUM; if (ack.getFlagack() && ack.getAcknum() == server_seq) { cout << "Receiving packet " << ack.getAcknum() << endl; server_ack = ack.getAcknum(); return client_ack; } else { cout << "ACK flag: " << ack.getFlagack() << endl; cout << "SYN flag: " << ack.getFlagsyn() << endl; cout << "ack num received: " << ack.getAcknum() << endl; cout << "global_seq: " << server_seq << endl; cerr << "ack flag error or acknum error" << endl; return USHRT_MAX; } } else { cerr << "syn flag error" << endl; return USHRT_MAX; } }
/* return -1 and set myip to empty string if failed to get it */ int get_myip(char *myip) { /* define local static variables */ static unsigned char tries = 0; //static unsigned char timeout = 1; static int myip_sockfd; static struct hostent *myip_server_ent; static struct sockaddr_in myip_servaddr; static char data[] = "\n"; static char tmpip[IPADDR_LEN]; static ssize_t n; /* TODO: may use a global var */ //static struct sigaction action; static struct timeval tv; /* TODO: may use a global var */ /* init vars */ tries = 0; tv.tv_sec = MYIP_TIMEOUT; tv.tv_usec = 0; bzero(tmpip, IPADDR_LEN); // bzero(myip, IPADDR_LEN); *myip = '\0'; bzero(&myip_servaddr, sizeof(myip_servaddr)); myip_servaddr.sin_family = AF_INET; myip_servaddr.sin_port = htons(myip_server_port); /* initialise signal handler bzero(&action, sizeof(action)); action.sa_handler = timed_out; action.sa_flags = 0; sigaction(SIGALRM, &action, 0); */ /* get IP of myip_server, and setup myip_servaddr */ myip_server_ent = gethostbyname(myip_server); if (myip_server_ent == NULL) { logwrite("get_myip: Error resolving myip_server!"); return(-1); } memcpy(&myip_servaddr.sin_addr.s_addr, myip_server_ent->h_addr_list[0], myip_server_ent->h_length); myip_sockfd = socket(AF_INET, SOCK_DGRAM, 0); setsockopt(myip_sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); /* try a few times to read myip */ while (tries < MAX_MYIP_TRIES) { sendto(myip_sockfd, data, 1, 0, (SA *)&myip_servaddr, sizeof(myip_servaddr)); //alarm(MYIP_TIMEOUT); if((n = recvfrom(myip_sockfd, tmpip, IPADDR_LEN, 0, NULL, NULL)) <= 0) { if (log_verbose) logwrite("get_myip: Timeout reading myip_server"); ++tries; } else { chomp(tmpip); if (log_verbose) { sprintf(msg, "get_myip: %s", tmpip); logwrite(msg); } break; /* got answer packet */ } } //alarm(0); close(myip_sockfd); /* make sure tmpip is in correct format */ if (sscanf(tmpip, "%u.%u.%u.%u", &int_tmp,&int_tmp,&int_tmp,&int_tmp) != 4) { return(-1); } else { strncpy(myip, tmpip, IPADDR_LEN); return(0); } }
int main(int argc,char** argv) { // vars // loops int paramloop; int loop; // some miscellaneous vars: int ret; // verboselevel int verboselevel; // active modules int modactive[3]; // vars for source and destination ipaddresses and ports char *s_ipaddress, *d_ipaddress; int s_port, d_port, d_portincr; struct in_addr myaddr_bin; char * myipaddress; // vars related to receiving data unsigned char receivebuffer[ETHERNETMTU]; int packetsize; int udp_packetsize; int dstar_data_len; // vars to process streams int packetsequence; int direction; int streamid; int streamid_instream; // vars related to sending data unsigned char sendbuffer[ETHERNETMTU]; struct sockaddr_in6 MulticastOutAddr; // vars to deal with DSTK frames dstkheader_str * dstkhead_in, *dstkhead_out; void * dstkdata; // dealing with IP, UDP and DSTAR headers struct iphdr * iphead; struct udphdr * udphead; struct dstar_rpc_header * dstar_rpc_head; unsigned char * dstardata; struct dstar_dv_rf_header * dv_rf_header; struct dstar_dv_header * dv_header; struct dstar_dv_data * dv_data; uint8_t this_sequence; char thismodule_c; int thismodule_i; int activestatus[3]; int activedirection[3]; u_short activestreamid[3]; // networking vars int sock_in, sock_out; // vars for timed interrupts struct sigaction sa; struct sigevent sev; timer_t timerid; struct itimerspec its; // ////// data definition done /// // main program starts here /// // part 1: initialise vars and check cli-arguments verboselevel=0; s_ipaddress=default_s_ipaddress; s_port=default_s_port; d_ipaddress=default_d_ipaddress; d_port=default_d_port; d_portincr=default_d_portincr; myipaddress=default_myipaddress; modactive[0]=0; modactive[1]=0; modactive[2]=0; activestatus[0]=0; activestatus[1]=0;activestatus[2]=0; global.inbound_timeout[0]=0; global.inbound_timeout[1]=0; global.inbound_timeout[2]=0; // CLI option decoding // format: rpc2amb [-v ] [-myip ipaddress] [-si ipaddress ] [-sp port] [-di ipaddress] [-dp port ] [-dpi portincease] module ... [module] for (paramloop=1;paramloop<argc;paramloop++) { char * thisarg=argv[paramloop]; if (strcmp(thisarg,"-V") == 0) { // -V = version fprintf(stderr,"%s version %s\n",argv[0],VERSION); exit(0); } else if (strcmp(thisarg,"-h") == 0) { // -h = help help(argv[0]); exit(0); } else if (strcmp(thisarg,"-v") == 0) { // -v = verbose verboselevel++; } else if (strcmp(thisarg,"-myip") == 0) { // -myip = my ipaddress on interface facing RPC if (paramloop+1 < argc) { paramloop++; myipaddress=argv[paramloop]; }; // end if } else if (strcmp(thisarg,"-si") == 0) { // -si = SOURCE ipaddress if (paramloop+1 < argc) { paramloop++; s_ipaddress=argv[paramloop]; }; // end if } else if (strcmp(thisarg,"-sp") == 0) { // -si = SOURCE port if (paramloop+1 < argc) { paramloop++; s_port=atoi(argv[paramloop]); }; // end if } else if (strcmp(thisarg,"-di") == 0) { // -di = DESTINATION ipaddress if (paramloop+1 < argc) { paramloop++; d_ipaddress=argv[paramloop]; }; // end if } else if (strcmp(thisarg,"-dp") == 0) { // -dp = DESTINATION port if (paramloop+1 < argc) { paramloop++; d_port=atoi(argv[paramloop]); }; // end if } else if (strcmp(thisarg,"-dpi") == 0) { // -dp = DESTINATION port increase if (paramloop+1 < argc) { paramloop++; d_portincr=atoi(argv[paramloop]); }; // end if } else { // modules: can be 'a' up to 'c' if ((thisarg[0] == 'a') || (thisarg[0] == 'A')) { modactive[0]=1; } else if ((thisarg[0] == 'b') || (thisarg[0] == 'B')) { modactive[1]=1; } else if ((thisarg[0] == 'c') || (thisarg[0] == 'C')) { modactive[2]=1; } else { fprintf(stderr,"Warning: unknown module %c\n",thisarg[0]); usage(argv[0]); }; // end elsif (...) - if }; // end elsif - elsif - elsif - if }; // end for // we should have at least one active module if (!(modactive[0] | modactive[1] | modactive[2])) { fprintf(stderr,"Error: At least one active module expected! \n"); usage(argv[0]); exit(-1); }; // end if // main program stats here: // start timed functions // establing handler for signal sa.sa_flags = 0; sa.sa_handler = funct_heartbeat; sigemptyset(&sa.sa_mask); ret=sigaction(SIGRTMIN, &sa, NULL); if (ret <0) { fprintf(stderr,"Error in sigaction!\n"); exit(-1); }; // end if /* Create the timer */ sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIGRTMIN; sev.sigev_value.sival_ptr = &timerid; ret=timer_create(CLOCKID, &sev, &timerid); if (ret < 0) { fprintf(stderr,"Error in timer_create!\n"); exit(-1); }; // end if // start timed function, every second its.it_value.tv_sec = 0; its.it_value.tv_nsec = 1; // immediatly its.it_interval.tv_sec = 1; // 1 second its.it_interval.tv_nsec = 0; ret=timer_settime(timerid, 0, &its, NULL); if (ret < 0) { fprintf(stderr,"Error in timer_settime!\n"); exit(-1); }; // end if // open inbound socket sock_in=open_and_join_mc(s_ipaddress,s_port,verboselevel); if (sock_in <= 0) { fprintf(stderr,"Error during open_and_join_mc!\n"); exit(-1); }; // end if sock_out=open_for_multicast_out(verboselevel); if (sock_out <= 0) { fprintf(stderr,"Error during open_for_multicast_out!\n"); exit(-1); }; // end if // convert my own ip-address into binary format ret=inet_pton(AF_INET,myipaddress,(void *)&myaddr_bin); // fill in fixed parts of outbound socket MulticastOutAddr.sin6_family=AF_INET6; MulticastOutAddr.sin6_scope_id=1; ret=inet_pton(AF_INET6,d_ipaddress,(void *)&MulticastOutAddr.sin6_addr); if (ret != 1) { fprintf(stderr,"Error: could not convert %s into valid address. Exiting\n",d_ipaddress); exit(1); }; // end if // init outbuffer // set pointer dstkheader to beginning of buffer dstkhead_out = (dstkheader_str *) sendbuffer; dstkdata = (void *) sendbuffer + sizeof(dstkheader_str); // fill in fixed parts dstkhead_out->version=1; // this version of this application only contains one single DSTK-subframe // inside one superframe. So, "last" is set to 1 dstkhead_out->flags = DSTK_FLG_LAST; streamid=0; packetsequence=0; while (forever) { // some local vars int foundit; int giveup; int dstkheaderoffset; int thisorigin; int otherfound; // Start receiving data from multicast stream // The payload of the ipv6 multicast-stream are the ipv4 // UDP packets exchanged by the gateway-server and the // repeater controller packetsize=recvfrom(sock_in,receivebuffer,ETHERNETMTU,0,NULL,0); if (packetsize == -1) { // no data received. Wait 2 ms and try again usleep(2000); continue; }; // end if // We should have received at least 20 octets (the size of the DSTK-header) if (packetsize < 20) { fprintf(stderr,"Packetsize to small! \n"); continue; }; // end if // check packet: We should find a DSTK frame: foundit=0; giveup=0; dstkheaderoffset=0; otherfound=0; while ((! foundit) && (! giveup)) { // check DSTK packet header dstkhead_in = (dstkheader_str *) (receivebuffer + dstkheaderoffset); if (dstkhead_in->version != 1) { fprintf(stderr,"DSTK header version 1 expected. Got %d\n",dstkhead_in->version); giveup=1; break; } else if ((ntohl(dstkhead_in->type) & TYPEMASK_FILT_NOFLAGS) == TYPE_RPC_IP) { // OK, found Ethernet frames of RPC-stream foundit=1; break; }; // OK, we found something, but it's not what we are looking for otherfound=1; // is there another subframe in the DSTK superframe? if ( (!(dstkhead_in->flags | DSTK_FLG_LAST)) && (dstkheaderoffset+ntohs(dstkhead_in->size)+sizeof(dstkheader_str) +sizeof(dstk_signature) <= packetsize )) { // not yet found, but there is a pointer to a structure further // on in the received packet // And it is still within the limits of the received packet // move up pointer dstkheaderoffset+=ntohs(dstkhead_in->size)+sizeof(dstkhead_in->size); // check for signature 'DSTK' if (memcmp(&receivebuffer[dstkheaderoffset],dstk_signature,sizeof(dstk_signature))) { // signature not found: give up giveup=1; } else { // signature found: move up pointer by 4 octets and repeat while-loop dstkheaderoffset += sizeof(dstk_signature); }; // end if } else { // give up giveup=1; }; // end else - elsif - elsif - if }; // end while if (giveup) { if (verboselevel >= 1) { if (otherfound) { fprintf(stderr,"Warning: received packet does not contain RPCIP sub-packet!\n"); } else { fprintf(stderr,"Warning: received packet is not a DSTK packet!\n"); }; // end else - if continue; }; // end if }; // end if // copy streamid streamid_instream=dstkhead_in->streamid1; // no need to convert // byte-order as we will just pass it on the outgoing stream // copy origin thisorigin=dstkhead_in->origin; // no need to convert as we just copy it to // from the incoming to the outgoing packets // sanity-check: check if the packet that has been received is large enough to // contain all data (error-check on overloading limits) // we are currently at the beginning of the DSTK header, the frame should be at least large // enough to hold the DATH header + the IP header + UDP header if (packetsize < dstkheaderoffset + sizeof(dstkheader_str) + sizeof(struct udphdr) + sizeof(struct iphdr) ) { if (verboselevel >= 1) { fprintf(stderr,"Warning: received frame is not large enough to contain DSTK_HEADER + IP header + UDP header\n"); }; // end if continue; }; // end if // we should have received an ipv4 IP-packet with UDP iphead = (struct iphdr *) (receivebuffer + dstkheaderoffset + sizeof(dstkheader_str)); // is it UDP? if (iphead->protocol != IPPROTO_UDP) { // not UDP if (verboselevel >= 1) { fprintf(stderr,"Warning: received packet is not a UDP packet!\n"); }; // end if continue; }; // end if // Determine direction // if it send by me? ret=bcmp(&iphead->saddr, &myaddr_bin, sizeof(struct in_addr)); if (ret == 0) { direction=1; // outbound #if DEBUG > 1 fprintf(stderr,"OUTBOUND! \n"); #endif } else { // was it addressed to me? ret=bcmp(&iphead->daddr, &myaddr_bin, sizeof(struct in_addr)); if (ret == 0) { #if DEBUG > 1 fprintf(stderr,"INBOUND! \n"); #endif direction=0; // inbound } else { // not send by me or addressed to me. Ignore it if (verboselevel >= 1) { fprintf(stderr,"Error: received packet is not send by or addressed to me!\n"); }; // end if continue; }; // end else - if }; // end else - if // go to UDP header, fetch length udphead = (struct udphdr *) (receivebuffer + dstkheaderoffset + sizeof(dstkheader_str) + sizeof(struct iphdr)); udp_packetsize=ntohs(udphead->len) - 8; // note: udp length includes 8 bytes of the UDP header // sanity-check: now we know the size of the UDP-packet, we can verify if the // packet that has been received is large enough to contain all data // (error-check on overloading limits) // we are currently at the beginning of the DSTK header, the frame should be at least large // enough to hold the DATH header + the IP header + UDP header + "udp_packet-size" of data if (packetsize < dstkheaderoffset + sizeof(dstkheader_str) + sizeof(struct udphdr) + sizeof(struct iphdr) + udp_packetsize ) { if (verboselevel >= 1) { fprintf(stderr,"Warning: received frame is not large enough to contain DSTK_HEADER + IP header + UDP header\n"); }; // end if continue; }; // end if // go to dstar header dstar_rpc_head = (struct dstar_rpc_header *) (receivebuffer + dstkheaderoffset + sizeof(dstkheader_str) + sizeof(struct iphdr) + sizeof(struct udphdr) ); // the first 4 octets of the header contain "DSTR" ret = strncmp("DSTR", (char *) dstar_rpc_head, 4); if (ret != 0) { // signature not found: not a star header if (verboselevel >= 1) { fprintf(stderr,"Error: received packet does not contain DSTAR signature\n"); }; // end if continue; }; // end if // dive further into package dstar_data_len = ntohs(dstar_rpc_head->dstar_data_len); #if DEBUG > 0 fprintf(stderr,"dstar_data_len = %d \n",dstar_data_len); #endif dstardata=(unsigned char *) (receivebuffer + dstkheaderoffset + sizeof(dstkheader_str) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dstar_rpc_header) ); // dstar_data_len can have the following values: // 48: first frame of DV stream // 19: normal frame of DV stream // 22: extended frame of DV stream (= normal frame + 3 octets at the end) // The data-transfer between the gateway-server and repeater-controller // happens in two phases: // the packet is send by one side. (rs-flag is set to 0x73) // after that, the reception of this packet is acknowleged by the remote // side (rs-flag is set to 0x72) // This program assumes that the exchange between the gateway-server and // works OK, so will just take a single-phase approach and ignore the // ACK messages if (dstar_rpc_head->dstar_rs_flag == 0x72) { if (verboselevel >= 3) { fprintf(stderr,"RStype ACK! \n"); }; // end if continue; }; // end if if (dstar_rpc_head->dstar_rs_flag != 0x73) { if (verboselevel >= 2) { fprintf(stderr,"NOT TYPE 0x73! \n"); }; // end if continue; }; // end if //fprintf(stderr,"dstar pkt type = %X \n",dstar_rpc_head->dstar_pkt_type); if (dstar_rpc_head->dstar_pkt_type != DSTAR_PKT_TYPE_DV) { // not a packet used for DV: ignore it if (verboselevel >= 2) { //fprintf(stderr,"Error: not a DV type packet: %X \n",dstar_rpc_head->dstar_pkt_type); fprintf(stderr,"NDV "); }; // end if continue; }; // end if // Check size if ((dstar_data_len != 19) && (dstar_data_len != 22) && (dstar_data_len != 48)) { if (verboselevel >= 1) { fprintf(stderr,"Error: Received DV packet has incorrect length: %d\n",dstar_data_len); }; // end if continue; }; // end if // set pointers to dv_header dv_header=(struct dstar_dv_header *) dstardata; // info: status: 0 = no DV stream active, 1 = stream active #if DEBUG > 1 fprintf(stderr,"dstar_data_len = %d \n",dstar_data_len); #endif // what kind of packet it is? // is it a start-of-stream packet if (dstar_data_len == 48) { // set pointer for rf_header dv_rf_header=(struct dstar_dv_rf_header *) (receivebuffer + dstkheaderoffset + sizeof(dstkheader_str) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dstar_rpc_header) + sizeof(struct dstar_dv_header) ); // determine module if (direction) { // outbound -> module is last character of rpt 2 thismodule_c=dv_rf_header->rpt2_callsign[7]; } else { // inbound -> compair with last character of rpt 1 thismodule_c=dv_rf_header->rpt1_callsign[7]; }; // end if if ((thismodule_c == 'A' || thismodule_c == 'a')) { thismodule_i=0; thismodule_c='A'; } else if ((thismodule_c == 'B' || thismodule_c == 'b')) { thismodule_i=1; thismodule_c='B'; } else if ((thismodule_c == 'C' || thismodule_c == 'c')) { thismodule_i=2; thismodule_c='C'; } else { fprintf(stderr,"Warning, received stream-start packet does not have valid module-name: %c\n",thismodule_c); continue; }; // end if // if is a module we are interested in? if (! (modactive[thismodule_i])) { if (verboselevel >= 2) { fprintf(stderr,"Message, received packet for module we are not interested in: %d\n",thismodule_i); }; // end if continue; }; // end if // accept it when // status is 0 (no DV-stream active) // or when timeout (additional check to deal with // stale sessions where we did not receive an "end-of-stream" packet // the "inbound timeout" value is "armed" with 50 in this function and decreased by // one in the "serialsend" function. As that function is started every 20 ms, the // session will timeout after 1 second. if ((activestatus[thismodule_i] == 0) || (global.inbound_timeout[thismodule_i] == 0)) { // copy streamid, set frame counter, set status and go to next packet if (verboselevel >= 1) { fprintf(stderr,"NS%X/%04X \n",direction,dv_header->dv_stream_id); }; // end if activestreamid[thismodule_i]=dv_header->dv_stream_id; activedirection[thismodule_i]=direction; activestatus[thismodule_i]=1; } else { if (verboselevel >= 2) { //fprintf(stderr,"Error: DV header received when DV voice-frame expected\n"); fprintf(stderr,"DVH "); }; // end if continue; }; // end else // frame is OK, fill in packet-type in header outgoing packet if (direction) { dstkhead_out->type=htonl(TYPE_AMB_CFG | TYPEMASK_FLG_DIR); } else { dstkhead_out->type=htonl(TYPE_AMB_CFG); }; // end else - if } else { // DV-data received // set pointer for rf_data dv_data=(struct dstar_dv_data *) (receivebuffer + dstkheaderoffset + sizeof(dstkheader_str) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dstar_rpc_header) + sizeof(struct dstar_dv_header) ); thismodule_i=-1; // determine module, based on streamid for (loop=0;((loop<=2) && (thismodule_i==-1));loop++) { if ((modactive[loop]) && (dv_header->dv_stream_id == activestreamid[loop])) { thismodule_i=loop; thismodule_c=(char) (0x41+loop); }; // end if }; // end for if (thismodule_i == -1) { if (verboselevel >= 2) { // fprintf(stderr,"Warning: received stream not linked to any active streams: %04X\n",dv_header->dv_stream_id); fprintf(stderr,"NAS%X/%04X ",direction,dv_header->dv_stream_id); }; // end if continue; }; // is it the correct direction? if (direction != activedirection[thismodule_i]) { if (verboselevel >= 1) { fprintf(stderr,"Warning: Receiving stream in opposite direction for stream %04X on module %d\n",dv_header->dv_stream_id,thismodule_i); }; // end if continue; }; // end if // check sequence number: should be between 0 and 20 this_sequence=(uint8_t) dv_data->dv_seqnr & 0x1f; // error check if (this_sequence > 20) { if (verboselevel >= 1) { fprintf(stderr,"Error: Invalid sequence number received: %d\n",this_sequence); }; // end if continue; }; // end if // last frame of stream? (6th bit set?) if ((uint8_t) dv_data->dv_seqnr & 0x40) { // set status to "off" activestatus[thismodule_i]=0; fprintf(stderr,"ES%04X \n",dv_header->dv_stream_id); }; // end if // frame is OK, fill in packet-type in header outgoing packet if (dstar_data_len == 19) { // standard digital voice frame if (direction) { dstkhead_out->type=htonl(TYPE_AMB_DV | TYPEMASK_FLG_DIR); } else { dstkhead_out->type=htonl(TYPE_AMB_DV); }; // end else - if } else { // extended digital voice frame (length 22) if (direction) { dstkhead_out->type=htonl(TYPE_AMB_DVE | TYPEMASK_FLG_DIR); } else { dstkhead_out->type=htonl(TYPE_AMB_DVE); }; // end else - if }; // end else - if }; // end else - if // OK, if the packet has not been rejected by all these checkes, re-broadcast it // fill in rest of header dstkhead_out->seq1=htons(packetsequence); dstkhead_out->seq2=0; packetsequence++; dstkhead_out->streamid1=htons((uint32_t)dv_header->dv_stream_id); // streamid2 is copy of streamid1 of incoming dstkhead_out->streamid2=streamid_instream; // origin dstkhead_out->origin=thisorigin; // copy data to dstkdata memcpy(dstkdata,dstardata,dstar_data_len); // set size dstkhead_out->size=htons(dstar_data_len); // set port MulticastOutAddr.sin6_port=htons((unsigned short int) d_port + thismodule_i * d_portincr); // copy data ret=sendto(sock_out,dstkhead_out,sizeof(dstkheader_str) + dstar_data_len,0,(struct sockaddr *) &MulticastOutAddr, sizeof(struct sockaddr_in6)); fprintf(stderr,"%c",thismodule_c); if (ret < 0) { fprintf(stderr,"Warning: sendto fails (error = %d(%s))\n",errno,strerror(errno)); }; // end if global.inbound_timeout[thismodule_i]=3; }; // end while (forever) // outside "forever" loop: we should never get here unless something went wrong return(0); };
int main(int argc, char **argv) { int sockfd; /* socket */ int portno; /* port to listen on */ struct sockaddr_in clientaddr; /* client addr */ socklen_t clientlen; /* byte size of client's address */ struct sockaddr_in serveraddr; /* server's addr */ int optval; /* flag value for setsockopt */ int fd; long file_size; long total_read = 0; unsigned char file_buf[MAX_SEQ_NUM_HALF]; unsigned long lastbyteSent, lastbyteAcked, maxbyte; unsigned char *lastbyteSentPtr, *lastbyteAckedPtr, *maxbytePtr; clock_t clock_start, clock_end; bool eof = false; int dupAck = 0; map<uint16_t, clock_t> time_map; /* check command line arguments */ if (argc != 3) error("Usage: ./server PORT-NUMBER FILE-NAME"); portno = atoi(argv[1]); /* socket: create the parent socket */ sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) error("ERROR opening socket"); optval = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval , sizeof(int)) == -1){ perror("setsockopt"); return 1; }; /* build the server's Internet address */ bzero((char *) &serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons((unsigned short)portno); /* bind: associate the parent socket with a port */ if (::bind(sockfd, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) == -1){ perror("bind"); return 2; } clientlen = sizeof(clientaddr); if (handshake(sockfd, clientaddr, clientlen) == USHRT_MAX) return 3; if ((fd = open(argv[2], O_RDONLY, 0644)) == -1){ perror("open"); return 4; } if ((file_size = lseek(fd, 0, SEEK_END)) == -1){ perror("lseek"); return 5; } if (lseek(fd, 0, SEEK_SET) == -1){ perror("lseek"); return 6; } maxbyte = lastbyteSent = lastbyteAcked = 0; maxbytePtr = lastbyteSentPtr = lastbyteAckedPtr = file_buf; clock_start = clock_end = clock(); bool firstRTT = true; while (!(eof && lastbyteAcked == maxbyte)) { for ( ; (lastbyteSent < maxbyte) && (unackedPackets < cwndPackets); (lastbyteSent += BUFSIZE) && (unackedPackets++)) { segment seg; seg.setSeqnum(server_seq); int send_size; if ((maxbyte-lastbyteSent)/BUFSIZE >= 1) send_size = BUFSIZE; else send_size = (int)(maxbyte - lastbyteSent); if (lastbyteSentPtr + send_size > file_buf + MAX_SEQ_NUM_HALF) { unsigned char temp[BUFSIZE]; long send_part2 = (lastbyteSentPtr + send_size) - (file_buf + MAX_SEQ_NUM_HALF); long send_part1 = send_size - send_part2; memcpy((char*)temp, (char*)lastbyteSentPtr, send_part1); memcpy((char*)(temp+send_part1), (char*)file_buf, send_part2); unsigned char *send_buf = seg.encode(temp, send_size); sendto(sockfd, send_buf, send_size+HEADERSIZE, 0, (struct sockaddr *)&clientaddr, clientlen); lastbyteSentPtr = lastbyteSentPtr + send_size - MAX_SEQ_NUM_HALF; } else { unsigned char *send_buf = seg.encode(lastbyteSentPtr, send_size); sendto(sockfd, send_buf, send_size+HEADERSIZE, 0, (struct sockaddr *)&clientaddr, clientlen); lastbyteSentPtr = lastbyteSentPtr + send_size; } clock_t now = clock(); time_map[server_seq] = now; cout << "Sending packet " << server_seq << " " << cwnd << " " << ssthresh << endl; server_seq = (server_seq + send_size) % MAX_SEQ_NUM; } while (true) { unsigned char recv_buf[HEADERSIZE]; long recv_len; if ((recv_len = recvfrom(sockfd, recv_buf, HEADERSIZE, MSG_DONTWAIT, (struct sockaddr *) &clientaddr, &clientlen)) == -1) { if (errno != EWOULDBLOCK && errno != EAGAIN) perror("recvfrom"); break; } segment ack; ack.decode(recv_buf, HEADERSIZE); if (ack.getFlagack()) { cout << "Receiving packet " << ack.getAcknum() << endl; if (ack.getAcknum() != server_ack) { map<uint16_t, clock_t>::iterator it = time_map.find(server_ack); if (it != time_map.end()) { clock_t now, then; now = clock(); then = it->second; time_map.erase(server_ack); double sampleRTT = double(now - then) / CLOCKS_PER_SEC; if (firstRTT) { estimatedRTT = sampleRTT; devRTT = sampleRTT / 2; adaptiveRTO = estimatedRTT + 4 * devRTT; timeout = adaptiveRTO; firstRTT = false; } else { double difference = sampleRTT - estimatedRTT >= 0 ? sampleRTT - estimatedRTT : estimatedRTT - sampleRTT; estimatedRTT = 0.875 * estimatedRTT + 0.125 * sampleRTT; devRTT = 0.75 * devRTT + 0.25 * difference; adaptiveRTO = estimatedRTT + 4 * devRTT; timeout = adaptiveRTO; } } uint16_t diff; if (ack.getAcknum() > server_ack) diff = ack.getAcknum() - server_ack; else diff = MAX_SEQ_NUM - server_ack + ack.getAcknum(); lastbyteAcked += diff; if (lastbyteAckedPtr + diff > file_buf + MAX_SEQ_NUM_HALF) lastbyteAckedPtr = lastbyteAckedPtr + diff - MAX_SEQ_NUM_HALF; else lastbyteAckedPtr = lastbyteAckedPtr + diff; server_ack = ack.getAcknum(); int num_acked = diff/BUFSIZE; unackedPackets -= num_acked; for (int i = 0; i < num_acked; i++) updateCwnd(); clock_start = clock_end = clock(); dupAck = 0; } else { if (state != FASTRECOVERY) { dupAck++; if (dupAck == 3) { state = FASTRECOVERY; dupAck = 0; ssthresh = cwnd/2 < BUFSIZE ? BUFSIZE : cwnd/2; ssthreshPackets = ssthresh / BUFSIZE; cwnd = ssthresh + BUFSIZE*3; cwndPackets = cwnd / BUFSIZE; segment seg; seg.setSeqnum(server_ack); int send_size; if ((maxbyte-lastbyteAcked)/BUFSIZE >= 1) send_size = BUFSIZE; else send_size = (int)(maxbyte - lastbyteAcked); if (lastbyteAckedPtr + send_size > file_buf + MAX_SEQ_NUM_HALF) { unsigned char temp[BUFSIZE]; long send_part2 = (lastbyteAckedPtr + send_size) - (file_buf + MAX_SEQ_NUM_HALF); long send_part1 = send_size - send_part2; memcpy((char*)temp, (char*)lastbyteAckedPtr, send_part1); memcpy((char*)(temp+send_part1), (char*)file_buf, send_part2); unsigned char *send_buf = seg.encode(temp, send_size); sendto(sockfd, send_buf, send_size+8, 0, (struct sockaddr *) &clientaddr, clientlen); } else { unsigned char *send_buf = seg.encode(lastbyteAckedPtr, send_size); sendto(sockfd, send_buf, send_size+8, 0, (struct sockaddr *) &clientaddr, clientlen); } cout << "Sending packet " << server_ack << " " << cwnd << " " << ssthresh << " Retransmission" << endl; clock_start = clock_end = clock(); time_map.erase(server_ack); } } else { cwnd += BUFSIZE; cwndPackets += 1; } } } } clock_end = clock(); double elapsed_secs = double(clock_end - clock_start) / CLOCKS_PER_SEC; if (elapsed_secs >= timeout) { state = SLOWSTART; dupAck = 0; ssthresh = cwnd/2 < BUFSIZE ? BUFSIZE : cwnd/2; ssthreshPackets = ssthresh / BUFSIZE; cwnd = BUFSIZE; cwndPackets = 1; segment seg; seg.setSeqnum(server_ack); int send_size; if ((maxbyte-lastbyteAcked)/BUFSIZE >= 1) send_size = BUFSIZE; else send_size = (int)(maxbyte - lastbyteAcked); if (lastbyteAckedPtr + send_size > file_buf + MAX_SEQ_NUM_HALF) { unsigned char temp[BUFSIZE]; long send_part2 = (lastbyteAckedPtr + send_size) - (file_buf + MAX_SEQ_NUM_HALF); long send_part1 = send_size - send_part2; memcpy((char*)temp, (char*)lastbyteAckedPtr, send_part1); memcpy((char*)(temp+send_part1), (char*)file_buf, send_part2); unsigned char *send_buf = seg.encode(temp, send_size); sendto(sockfd, send_buf, send_size+8, 0, (struct sockaddr *) &clientaddr, clientlen); } else { unsigned char *send_buf = seg.encode(lastbyteAckedPtr, send_size); sendto(sockfd, send_buf, send_size+8, 0, (struct sockaddr *) &clientaddr, clientlen); } cout << "Sending packet " << server_ack << " " << cwnd << " " << ssthresh << " Retransmission" << endl; clock_start = clock_end = clock(); timeout *= 2; time_map.erase(server_ack); } if (maxbyte - lastbyteAcked <= MAX_SEQ_NUM_HALF) { long bytes_left = MAX_SEQ_NUM_HALF - (maxbyte - lastbyteAcked); long bytes_read = 0; long read_len; if (MAX_SEQ_NUM_HALF-(maxbytePtr-file_buf) < (bytes_left)) { unsigned long part1 = MAX_SEQ_NUM_HALF - (maxbytePtr - file_buf); unsigned long part2 = bytes_left - part1; read_len = read(fd, maxbytePtr, part1); bytes_read += read_len; read_len = read(fd, file_buf, part2); bytes_read += read_len; } else { read_len = read(fd, maxbytePtr, bytes_left); bytes_read += read_len; } maxbyte += bytes_read; if (maxbytePtr + bytes_read > file_buf + MAX_SEQ_NUM_HALF) maxbytePtr = maxbytePtr + bytes_read - MAX_SEQ_NUM_HALF; else maxbytePtr = maxbytePtr + bytes_read; total_read += bytes_read; if (total_read == file_size) eof = true; } } teardown(sockfd, clientaddr, clientlen, 0, server_seq); }
slave_event_t slave_update(data_t *command, data_t *answer) { struct timeval timeout = { .tv_sec = 0, .tv_usec = 10000 }; struct sockaddr_in dev_addr = { .sin_family = AF_INET, .sin_port = htons(PORT_SLAVE), }; int8_t pkg[OPTIONS_NUM * sizeof(int32_t)] = {}; int len = sizeof(pkg), addr_len = sizeof(struct sockaddr_in); int sockfd; if (!serialize_cb || !deserialize_cb) return SLAVE_INIT_ERROR; if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("\n Error : Could not create socket \n"); return SLAVE_NETWORK_ERROR; } if (serialize_cb(command, pkg, &dev_addr) != SLAVE_DATA) return SLAVE_DATA_ERROR; #ifdef SLAVE_DEBUG_PRINT printf("Slave Interface Stub: Send command to slave\n"); #endif if ((len = sendto(sockfd, pkg, sizeof(pkg), 0, (struct sockaddr *)&dev_addr, addr_len)) < 0) { perror("send"); return SLAVE_NETWORK_ERROR; } if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) { perror("Error"); return SLAVE_NETWORK_ERROR; } if ((len = recvfrom(sockfd, pkg, sizeof(pkg), 0, (struct sockaddr *)&dev_addr, (socklen_t *)&addr_len)) <= 0) { perror("recv"); return SLAVE_TIMEOUT_ERROR; } #ifdef SLAVE_DEBUG_PRINT printf("Slave Interface Stub: Recv answer from slave\n"); #endif if (deserialize_cb(answer, pkg, &dev_addr) != SLAVE_DATA) return SLAVE_DATA_ERROR; return SLAVE_DATA; } int slave_init(slave_serialize_cb_t serialize_cb_, slave_deserialize_cb_t deserialize_cb_) { serialize_cb = serialize_cb_; deserialize_cb = deserialize_cb_; return 0; }
/* * Perform a DNS query by sending a packet */ void ngethostbyname(unsigned char *host , int query_type) { unsigned char buf[65536],*qname,*reader; int i , j , stop , s, random_server; srand ( time(NULL) ); // Initialize Random Seed random_server = rand() % dns_servercount; // Pick a random nameserver struct sockaddr_in a; struct RES_RECORD answers[20],auth[20],addit[20]; //The replies from the DNS server struct sockaddr_in dest; struct DNS_HEADER *dns = NULL; struct QUESTION *qinfo = NULL; s = socket(AF_INET , SOCK_DGRAM , IPPROTO_UDP); //UDP packet for DNS queries dest.sin_family = AF_INET; dest.sin_port = htons(53); dest.sin_addr.s_addr = inet_addr(dns_servers[random_server]); // Set the DNS structure to standard queries dns = (struct DNS_HEADER *)&buf; dns->id = (unsigned short) htons(getpid()); dns->qr = 0; dns->opcode = 0; dns->aa = 0; dns->tc = 0; dns->rd = 1; dns->ra = 0; dns->z = 0; dns->ad = 0; dns->cd = 0; dns->rcode = 0; dns->q_count = htons(1); dns->ans_count = 0; dns->auth_count = 0; dns->add_count = 0; // Query Portion qname =(unsigned char*)&buf[sizeof(struct DNS_HEADER)]; ChangetoDnsNameFormat(qname , host); qinfo =(struct QUESTION*)&buf[sizeof(struct DNS_HEADER) + (strlen((const char*)qname) + 1)]; qinfo->qtype = htons( query_type ); qinfo->qclass = htons(1); printf("\nSending Packet to %s (%s) ... " , dns_servernames[random_server], dns_servers[random_server]); if( sendto(s,(char*)buf,sizeof(struct DNS_HEADER) + (strlen((const char*)qname)+1) + sizeof(struct QUESTION),0,(struct sockaddr*)&dest,sizeof(dest)) < 0) { perror("sendto failed"); } printf("Done"); // Receive the response i = sizeof dest; printf("\nResponse Record Received ... "); if(recvfrom (s,(char*)buf , 65536 , 0 , (struct sockaddr*)&dest , (socklen_t*)&i ) < 0) { perror("recvfrom failed"); } printf("Done"); dns = (struct DNS_HEADER*) buf; //The Query field reader = &buf[sizeof(struct DNS_HEADER) + (strlen((const char*)qname)+1) + sizeof(struct QUESTION)]; printf("\nThe response contains : "); printf("\n\t %d Questions.",ntohs(dns->q_count)); printf("\n\t %d Answers.",ntohs(dns->ans_count)); printf("\n\t %d Authoritative Servers.",ntohs(dns->auth_count)); printf("\n\t %d Additional records.\n",ntohs(dns->add_count)); // Start Reading Answers stop=0; for(i=0;i<ntohs(dns->ans_count);i++) { answers[i].name=ReadName(reader,buf,&stop); reader = reader + stop; answers[i].resource = (struct R_DATA*)(reader); reader = reader + sizeof(struct R_DATA); if(ntohs(answers[i].resource->type) == 1) //If it's an ipv4 address { answers[i].rdata = (unsigned char*)malloc(ntohs(answers[i].resource->data_len)); for(j=0 ; j<ntohs(answers[i].resource->data_len) ; j++) { answers[i].rdata[j]=reader[j]; } answers[i].rdata[ntohs(answers[i].resource->data_len)] = '\0'; reader = reader + ntohs(answers[i].resource->data_len); } else { answers[i].rdata = ReadName(reader,buf,&stop); reader = reader + stop; } } // Read authorities for(i=0;i<ntohs(dns->auth_count);i++) { auth[i].name=ReadName(reader,buf,&stop); reader+=stop; auth[i].resource=(struct R_DATA*)(reader); reader+=sizeof(struct R_DATA); auth[i].rdata=ReadName(reader,buf,&stop); reader+=stop; } // Read additional for(i=0;i<ntohs(dns->add_count);i++) { addit[i].name=ReadName(reader,buf,&stop); reader+=stop; addit[i].resource=(struct R_DATA*)(reader); reader+=sizeof(struct R_DATA); if(ntohs(addit[i].resource->type)==1) { addit[i].rdata = (unsigned char*)malloc(ntohs(addit[i].resource->data_len)); for(j=0;j<ntohs(addit[i].resource->data_len);j++) addit[i].rdata[j]=reader[j]; addit[i].rdata[ntohs(addit[i].resource->data_len)]='\0'; reader+=ntohs(addit[i].resource->data_len); } else { addit[i].rdata=ReadName(reader,buf,&stop); reader+=stop; } } // Print Answers int answer_count = ntohs(dns->ans_count); printf("\nAnswer Records : %d \n" , answer_count ); for(i=0 ; i < answer_count ; i++) { printf("%s ",answers[i].name); printf("%d ",answers[i].resource->ttl); if( ntohs(answers[i].resource->type) == T_A) // IPv4 address { long *p; p=(long*)answers[i].rdata; a.sin_addr.s_addr=(*p); printf("IN NS %s",inet_ntoa(a.sin_addr)); } if(ntohs(answers[i].resource->type)==5) { //CNAME for an alias printf("IN CNAME %s",answers[i].rdata); } printf("\n"); } // Print Authorities printf("\nAuthoritive Records : %d \n" , ntohs(dns->auth_count) ); for( i=0 ; i < ntohs(dns->auth_count) ; i++) { printf("%s ",auth[i].name); printf("%d ",auth[i].resource->ttl); if(ntohs(auth[i].resource->type)==2) { printf("IN NS %s",auth[i].rdata); } printf("\n"); } // Print Additional Resource Records dns_servercount = ntohs(dns->add_count); printf("\nAdditional Records : %d \n" , dns_servercount ); for(i=0; i < dns_servercount ; i++) { printf("%s ",addit[i].name); if(ntohs(addit[i].resource->type)==1) { long *p; p=(long*)addit[i].rdata; a.sin_addr.s_addr=(*p); const char* temp_ip = inet_ntoa(a.sin_addr); const char* temp_name = addit[i].name; printf("IN A %s", temp_ip); strcpy(dns_servers[i] , temp_ip); strcpy(dns_servernames[i] , temp_name); } printf("\n"); } // Raise flag if answer records were received if( answer_count > 0 ) { done = 1; } else { //information for next iteration printf("\nNo answer record received - Picking a nameserver above at random ...\n"); } }
void handle_mcast( int rc, int sock_recv ) { char addrbuf[FULL_ADDSTRLEN+1]; char buf[512]; IP c_addr; socklen_t addrlen; int rc_recv; if( g_mcast_time <= time_now_sec() ) { if( kad_count_nodes( 0 ) == 0 ) { /* Join multicast group if possible */ if( g_mcast_registered == 0 && multicast_set_groups( sock_recv, &g_lpd_addr, gconf->dht_ifname, 1 ) == 0 ) { log_info( "LPD: No peers known. Joined multicast group." ); g_mcast_registered = 1; } if( g_mcast_registered == 1 ) { log_info( "LPD: Send multicast message to find nodes." ); /* Create message */ snprintf( buf, sizeof(buf), msg_fmt, str_addr( &g_lpd_addr, addrbuf ), atoi( gconf->dht_port ), g_infohash ); mcast_send_packets( buf, gconf->dht_ifname ); } } /* Cap number of received packets to 10 per minute */ g_packet_limit = 5 * PACKET_LIMIT_MAX; /* Try again in ~5 minutes */ g_mcast_time = time_add_min( 5 ); } if( rc <= 0 ) { return; } /* Reveice multicast ping */ addrlen = sizeof(IP); rc_recv = recvfrom( sock_recv, buf, sizeof(buf), 0, (struct sockaddr*) &c_addr, (socklen_t*) &addrlen ); if( rc_recv < 0 ) { log_warn( "LPD: Cannot receive multicast message: %s", strerror( errno ) ); return; } if( g_packet_limit < 0 ) { /* Too much traffic - leave multicast group for now */ if( g_mcast_registered == 1 && multicast_set_groups( sock_recv, &g_lpd_addr, gconf->dht_ifname, 0 ) == 0 ) { log_warn( "LPD: Too much traffic. Left multicast group." ); g_mcast_registered = 0; } return; } else { g_packet_limit--; } if( rc_recv >= sizeof(buf) ) { return; } else { buf[rc_recv] = '\0'; } int port = parse_packet( buf ); if( port > 0 ) { port_set( &c_addr, port ); log_debug( "LPD: Ping lonely peer at %s", str_addr( &c_addr, addrbuf ) ); kad_ping( &c_addr ); } else { log_debug( "LPD: Received invalid packet on multicast group." ); } }
/* This is sufficiently different from the TCP code (wrt SSL, etc) that it * resides in its own simpler function */ static int ncat_listen_dgram(int proto) { struct { int fd; union sockaddr_u addr; } sockfd[NUM_LISTEN_ADDRS]; int i, fdn = -1; int fdmax, nbytes, n, fds_ready; char buf[DEFAULT_UDP_BUF_LEN] = { 0 }; char *tempbuf = NULL; fd_set read_fds; union sockaddr_u remotess; socklen_t sslen = sizeof(remotess.storage); struct timeval tv; struct timeval *tvp = NULL; unsigned int num_sockets; for (i = 0; i < NUM_LISTEN_ADDRS; i++) { sockfd[i].fd = -1; sockfd[i].addr.storage.ss_family = AF_UNSPEC; } FD_ZERO(&read_fds); /* Initialize remotess struct so recvfrom() doesn't hit the fan.. */ zmem(&remotess.storage, sizeof(remotess.storage)); remotess.storage.ss_family = o.af; #ifdef WIN32 set_pseudo_sigchld_handler(decrease_conn_count); #else /* Reap on SIGCHLD */ Signal(SIGCHLD, sigchld_handler); /* Ignore the SIGPIPE that occurs when a client disconnects suddenly and we send data to it before noticing. */ Signal(SIGPIPE, SIG_IGN); #endif /* set for selecting udp listening sockets */ fd_set listen_fds; fd_list_t listen_fdlist; FD_ZERO(&listen_fds); init_fdlist(&listen_fdlist, num_listenaddrs); num_sockets = 0; for (i = 0; i < num_listenaddrs; i++) { /* create the UDP listen sockets */ sockfd[num_sockets].fd = do_listen(SOCK_DGRAM, proto, &listenaddrs[i]); if (sockfd[num_sockets].fd == -1) { if (o.debug > 0) logdebug("do_listen(\"%s\"): %s\n", inet_ntop_ez(&listenaddrs[i].storage, sizeof(listenaddrs[i].storage)), socket_strerror(socket_errno())); continue; } FD_SET(sockfd[num_sockets].fd, &listen_fds); add_fd(&listen_fdlist, sockfd[num_sockets].fd); sockfd[num_sockets].addr = listenaddrs[i]; num_sockets++; } if (num_sockets == 0) { if (num_listenaddrs == 1) bye("Unable to open listening socket on %s: %s", inet_ntop_ez(&listenaddrs[0].storage, sizeof(listenaddrs[0].storage)), socket_strerror(socket_errno())); else bye("Unable to open any listening sockets."); } if (o.idletimeout > 0) tvp = &tv; while (1) { int i, j, conn_count, socket_n; if (fdn != -1) { /*remove socket descriptor which is burnt */ FD_CLR(sockfd[fdn].fd, &listen_fds); rm_fd(&listen_fdlist, sockfd[fdn].fd); /* Rebuild the udp socket which got burnt */ sockfd[fdn].fd = do_listen(SOCK_DGRAM, proto, &sockfd[fdn].addr); if (sockfd[fdn].fd == -1) bye("do_listen: %s", socket_strerror(socket_errno())); FD_SET(sockfd[fdn].fd, &listen_fds); add_fd(&listen_fdlist, sockfd[fdn].fd); } fdn = -1; socket_n = -1; fd_set fds; FD_ZERO(&fds); while (1) { /* * We just select to get a list of sockets which we can talk to */ if (o.debug > 1) logdebug("selecting, fdmax %d\n", listen_fdlist.fdmax); fds = listen_fds; if (o.idletimeout > 0) ms_to_timeval(tvp, o.idletimeout); fds_ready = fselect(listen_fdlist.fdmax + 1, &fds, NULL, NULL, tvp); if (o.debug > 1) logdebug("select returned %d fds ready\n", fds_ready); if (fds_ready == 0) bye("Idle timeout expired (%d ms).", o.idletimeout); /* * Figure out which listening socket got a connection. This loop should * really call a function for each ready socket instead of breaking on * the first one. */ for (i = 0; i <= listen_fdlist.fdmax && fds_ready > 0; i++) { /* Loop through descriptors until there is something ready */ if (!FD_ISSET(i, &fds)) continue; /* Check each listening socket */ for (j = 0; j < num_sockets; j++) { if (i == sockfd[j].fd) { if (o.debug > 1) logdebug("Valid descriptor %d \n", i); fdn = j; socket_n = i; break; } } /* if we found a valid socket break */ if (fdn != -1) { fds_ready--; break; } } /* Make sure someone connected */ if (fdn == -1) continue; /* * We just peek so we can get the client connection details without * removing anything from the queue. Sigh. */ nbytes = recvfrom(socket_n, buf, sizeof(buf), MSG_PEEK, &remotess.sockaddr, &sslen); if (nbytes < 0) { loguser("%s.\n", socket_strerror(socket_errno())); close(socket_n); return 1; } /* Check conditions that might cause us to deny the connection. */ conn_count = get_conn_count(); if (conn_count >= o.conn_limit) { if (o.verbose) loguser("New connection denied: connection limit reached (%d)\n", conn_count); } else if (!allow_access(&remotess)) { if (o.verbose) loguser("New connection denied: not allowed\n"); } else { /* Good to go. */ break; } /* Dump the current datagram */ nbytes = recv(socket_n, buf, sizeof(buf), 0); if (nbytes < 0) { loguser("%s.\n", socket_strerror(socket_errno())); close(socket_n); return 1; } ncat_log_recv(buf, nbytes); } if (o.debug > 1) logdebug("Valid Connection from %d\n", socket_n); conn_inc++; /* * We're using connected udp. This has the down side of only * being able to handle one udp client at a time */ Connect(socket_n, &remotess.sockaddr, sslen); /* clean slate for buf */ zmem(buf, sizeof(buf)); /* are we executing a command? then do it */ if (o.cmdexec) { struct fdinfo info = { 0 }; info.fd = socket_n; if (o.keepopen) netrun(&info, o.cmdexec); else netexec(&info, o.cmdexec); continue; } FD_SET(socket_n, &read_fds); FD_SET(STDIN_FILENO, &read_fds); fdmax = socket_n; /* stdin -> socket and socket -> stdout */ while (1) { fd_set fds; fds = read_fds; if (o.debug > 1) logdebug("udp select'ing\n"); if (o.idletimeout > 0) ms_to_timeval(tvp, o.idletimeout); fds_ready = fselect(fdmax + 1, &fds, NULL, NULL, tvp); if (fds_ready == 0) bye("Idle timeout expired (%d ms).", o.idletimeout); if (FD_ISSET(STDIN_FILENO, &fds)) { nbytes = Read(STDIN_FILENO, buf, sizeof(buf)); if (nbytes < 0) { loguser("%s.\n", strerror(errno)); return 1; } else if (nbytes == 0) { return 0; } if (o.crlf) fix_line_endings((char *) buf, &nbytes, &tempbuf, &crlf_state); if (!o.recvonly) { if (tempbuf != NULL) n = send(socket_n, tempbuf, nbytes, 0); else n = send(socket_n, buf, nbytes, 0); if (n < nbytes) { loguser("%s.\n", socket_strerror(socket_errno())); close(socket_n); return 1; } ncat_log_send(buf, nbytes); } if (tempbuf != NULL) { free(tempbuf); tempbuf = NULL; } } if (FD_ISSET(socket_n, &fds)) { nbytes = recv(socket_n, buf, sizeof(buf), 0); if (nbytes < 0) { loguser("%s.\n", socket_strerror(socket_errno())); close(socket_n); return 1; } ncat_log_recv(buf, nbytes); if (!o.sendonly) Write(STDOUT_FILENO, buf, nbytes); } zmem(buf, sizeof(buf)); } } return 0; }
int main(int argc, char *argv[]) { struct tftphdr *tp; int n; int ch, on; struct sockaddr_storage me; int len; char *chroot_dir = NULL; struct passwd *nobody; const char *chuser = "******"; openlog("tftpd", LOG_PID | LOG_NDELAY, LOG_FTP); while ((ch = getopt(argc, argv, "cClns:u:")) != -1) { switch (ch) { case 'c': ipchroot = 1; break; case 'C': ipchroot = 2; break; case 'l': logging = 1; break; case 'n': suppress_naks = 1; break; case 's': chroot_dir = optarg; break; case 'u': chuser = optarg; break; default: syslog(LOG_WARNING, "ignoring unknown option -%c", ch); } } if (optind < argc) { struct dirlist *dirp; /* Get list of directory prefixes. Skip relative pathnames. */ for (dirp = dirs; optind < argc && dirp < &dirs[MAXDIRS]; optind++) { if (argv[optind][0] == '/') { dirp->name = argv[optind]; dirp->len = strlen(dirp->name); dirp++; } } } else if (chroot_dir) { dirs->name = "/"; dirs->len = 1; } if (ipchroot && chroot_dir == NULL) { syslog(LOG_ERR, "-c requires -s"); exit(1); } on = 1; if (ioctl(0, FIONBIO, &on) < 0) { syslog(LOG_ERR, "ioctl(FIONBIO): %m"); exit(1); } fromlen = sizeof (from); n = recvfrom(0, buf, sizeof (buf), 0, (struct sockaddr *)&from, &fromlen); if (n < 0) { syslog(LOG_ERR, "recvfrom: %m"); exit(1); } /* * Now that we have read the message out of the UDP * socket, we fork and exit. Thus, inetd will go back * to listening to the tftp port, and the next request * to come in will start up a new instance of tftpd. * * We do this so that inetd can run tftpd in "wait" mode. * The problem with tftpd running in "nowait" mode is that * inetd may get one or more successful "selects" on the * tftp port before we do our receive, so more than one * instance of tftpd may be started up. Worse, if tftpd * break before doing the above "recvfrom", inetd would * spawn endless instances, clogging the system. */ { int pid; int i, j; for (i = 1; i < 20; i++) { pid = fork(); if (pid < 0) { sleep(i); /* * flush out to most recently sent request. * * This may drop some request, but those * will be resent by the clients when * they timeout. The positive effect of * this flush is to (try to) prevent more * than one tftpd being started up to service * a single request from a single client. */ j = sizeof from; i = recvfrom(0, buf, sizeof (buf), 0, (struct sockaddr *)&from, &j); if (i > 0) { n = i; fromlen = j; } } else { break; } } if (pid < 0) { syslog(LOG_ERR, "fork: %m"); exit(1); } else if (pid != 0) { exit(0); } } /* * Since we exit here, we should do that only after the above * recvfrom to keep inetd from constantly forking should there * be a problem. See the above comment about system clogging. */ if (chroot_dir) { if (ipchroot) { char *tempchroot; struct stat sb; int statret; struct sockaddr_storage ss; char hbuf[NI_MAXHOST]; memcpy(&ss, &from, from.ss_len); unmappedaddr((struct sockaddr_in6 *)&ss); getnameinfo((struct sockaddr *)&ss, ss.ss_len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID); asprintf(&tempchroot, "%s/%s", chroot_dir, hbuf); statret = stat(tempchroot, &sb); if ((sb.st_mode & S_IFDIR) && (statret == 0 || (statret == -1 && ipchroot == 1))) chroot_dir = tempchroot; } /* Must get this before chroot because /etc might go away */ if ((nobody = getpwnam(chuser)) == NULL) { syslog(LOG_ERR, "%s: no such user", chuser); exit(1); } if (chroot(chroot_dir)) { syslog(LOG_ERR, "chroot: %s: %m", chroot_dir); exit(1); } chdir( "/" ); setuid(nobody->pw_uid); setgroups(1, &nobody->pw_gid); } len = sizeof(me); if (getsockname(0, (struct sockaddr *)&me, &len) == 0) { switch (me.ss_family) { case AF_INET: ((struct sockaddr_in *)&me)->sin_port = 0; break; case AF_INET6: ((struct sockaddr_in6 *)&me)->sin6_port = 0; break; default: /* unsupported */ break; } } else { memset(&me, 0, sizeof(me)); me.ss_family = from.ss_family; me.ss_len = from.ss_len; } alarm(0); close(0); close(1); peer = socket(from.ss_family, SOCK_DGRAM, 0); if (peer < 0) { syslog(LOG_ERR, "socket: %m"); exit(1); } if (bind(peer, (struct sockaddr *)&me, me.ss_len) < 0) { syslog(LOG_ERR, "bind: %m"); exit(1); } if (connect(peer, (struct sockaddr *)&from, from.ss_len) < 0) { syslog(LOG_ERR, "connect: %m"); exit(1); } tp = (struct tftphdr *)buf; tp->th_opcode = ntohs(tp->th_opcode); if (tp->th_opcode == RRQ || tp->th_opcode == WRQ) tftp(tp, n); exit(1); }
/* Main */ int main(int argc, char *argv[]) { int n, detach, sock; socklen_t size; struct sigaction sa; struct sockaddr_hci addr; struct ng_btsocket_hci_raw_filter filter; char buffer[HCSECD_BUFFER_SIZE]; ng_hci_event_pkt_t *event = NULL; detach = 1; while ((n = getopt(argc, argv, "df:h")) != -1) { switch (n) { case 'd': detach = 0; break; case 'f': config_file = optarg; break; case 'h': default: usage(); /* NOT REACHED */ } } if (config_file == NULL) usage(); /* NOT REACHED */ if (getuid() != 0) errx(1, "** ERROR: You should run %s as privileged user!", HCSECD_IDENT); /* Set signal handlers */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = sigint; sa.sa_flags = SA_NOCLDWAIT; if (sigaction(SIGINT, &sa, NULL) < 0) err(1, "Could not sigaction(SIGINT)"); if (sigaction(SIGTERM, &sa, NULL) < 0) err(1, "Could not sigaction(SIGINT)"); memset(&sa, 0, sizeof(sa)); sa.sa_handler = sighup; if (sigaction(SIGHUP, &sa, NULL) < 0) err(1, "Could not sigaction(SIGHUP)"); /* Open socket and set filter */ sock = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_HCI); if (sock < 0) err(1, "Could not create HCI socket"); memset(&filter, 0, sizeof(filter)); bit_set(filter.event_mask, NG_HCI_EVENT_PIN_CODE_REQ - 1); bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_REQ - 1); bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_NOTIFICATION - 1); if (setsockopt(sock, SOL_HCI_RAW, SO_HCI_RAW_FILTER, (void * const) &filter, sizeof(filter)) < 0) err(1, "Could not set HCI socket filter"); if (detach && daemon(0, 0) < 0) err(1, "Could not daemon()ize"); openlog(HCSECD_IDENT, LOG_NDELAY|LOG_PERROR|LOG_PID, LOG_DAEMON); read_config_file(); read_keys_file(); if (detach) { FILE *pid = NULL; if ((pid = fopen(HCSECD_PIDFILE, "w")) == NULL) { syslog(LOG_ERR, "Could not create PID file %s. %s (%d)", HCSECD_PIDFILE, strerror(errno), errno); exit(1); } fprintf(pid, "%d", getpid()); fclose(pid); } event = (ng_hci_event_pkt_t *) buffer; while (!done) { size = sizeof(addr); n = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr *) &addr, &size); if (n < 0) { if (errno == EINTR) continue; syslog(LOG_ERR, "Could not receive from HCI socket. " \ "%s (%d)", strerror(errno), errno); exit(1); } if (event->type != NG_HCI_EVENT_PKT) { syslog(LOG_ERR, "Received unexpected HCI packet, " \ "type=%#x", event->type); continue; } switch (event->event) { case NG_HCI_EVENT_PIN_CODE_REQ: process_pin_code_request_event(sock, &addr, (bdaddr_p)(event + 1)); break; case NG_HCI_EVENT_LINK_KEY_REQ: process_link_key_request_event(sock, &addr, (bdaddr_p)(event + 1)); break; case NG_HCI_EVENT_LINK_KEY_NOTIFICATION: process_link_key_notification_event(sock, &addr, (ng_hci_link_key_notification_ep *)(event + 1)); break; default: syslog(LOG_ERR, "Received unexpected HCI event, " \ "event=%#x", event->event); break; } } if (detach) if (remove(HCSECD_PIDFILE) < 0) syslog(LOG_ERR, "Could not remove PID file %s. %s (%d)", HCSECD_PIDFILE, strerror(errno), errno); dump_keys_file(); clean_config(); closelog(); close(sock); return (0); }
int UDPReceive::receive( char *buffer, int len, char *tag, double *ptime ) { struct sockaddr_in si_other; int slen=sizeof(si_other); //socklen_t slen=sizeof(si_other); RTHeader_t *pheader = (RTHeader_t*)recbuffer; bool goon=true; int bytes = 0; int packetnum=-1; int fragments=-1; int fragnum=-1; int nextfrag=1; while( goon ) { int ret=0; if( !leftover ) { ret = recvfrom(sock, recbuffer, 65000, 0,(sockaddr*) &si_other, &slen); } leftover=false; //printf("%s UDP Packet %ld Size %d Fragment %d of %d Nextfrag %d\n", tag, pheader->packetnum, ret, pheader->fragnum, pheader->fragments, nextfrag ); if( ret>sizeof( RTHeader_t ) ) { if( packetnum==-1 ) { //first fragment of the new packet packetnum = pheader->packetnum; } if( packetnum != pheader->packetnum ) { //last fragments lost printf("Last Frag %d lost", nextfrag ); leftover = true; return -1; } //printf("%s UDP Packet %ld Size %d Fragment %d of %d Nextfrag %d\n", tag, pheader->packetnum, ret, pheader->fragnum, pheader->fragments, nextfrag ); if( nextfrag!= pheader->fragnum ) { //a fragment is missing printf("Fragment %d lost\n", nextfrag ); return -1; } nextfrag++; memcpy( buffer+bytes, recbuffer + sizeof( RTHeader_t), ret - sizeof(RTHeader_t) ); bytes += ret - sizeof( RTHeader_t ); if(pheader->fragments == pheader->fragnum) goon=false; //last fragment packetnum = pheader->packetnum; fragments = pheader->fragments; fragnum = pheader->fragnum; *ptime = pheader->time; } else { printf("Fragment %d not larger than %d", pheader->fragnum, sizeof( RTHeader_t ) ); return -1; } } leftover = false; return bytes; }
static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* iface) { struct ETHInterface_pvt* ctx = Identity_containerOf(iface, struct ETHInterface_pvt, pub.generic.iface); struct Sockaddr* sa = (struct Sockaddr*) msg->bytes; Assert_true(msg->length >= Sockaddr_OVERHEAD); Assert_true(sa->addrLen <= ETHInterface_Sockaddr_SIZE); struct ETHInterface_Sockaddr sockaddr = { .generic = { .addrLen = 0 } }; Message_pop(msg, &sockaddr, sa->addrLen, NULL); struct sockaddr_ll addr; Bits_memcpyConst(&addr, &ctx->addrBase, sizeof(struct sockaddr_ll)); if (sockaddr.generic.flags & Sockaddr_flags_BCAST) { Bits_memset(addr.sll_addr, 0xff, 6); } else { Bits_memcpyConst(addr.sll_addr, sockaddr.mac, 6); } struct ETHInterface_Header hdr = { .version = ETHInterface_CURRENT_VERSION, .zero = 0, .length_be = Endian_hostToBigEndian16(msg->length + ETHInterface_Header_SIZE), .fc00_be = Endian_hostToBigEndian16(0xfc00) }; Message_push(msg, &hdr, ETHInterface_Header_SIZE, NULL); sendMessageInternal(msg, &addr, ctx); return NULL; } static void handleEvent2(struct ETHInterface_pvt* context, struct Allocator* messageAlloc) { struct Message* msg = Message_new(MAX_PACKET_SIZE, PADDING, messageAlloc); struct sockaddr_ll addr; uint32_t addrLen = sizeof(struct sockaddr_ll); // Knock it out of alignment by 2 bytes so that it will be // aligned when the idAndPadding is shifted off. Message_shift(msg, 2, NULL); int rc = recvfrom(context->socket, msg->bytes, msg->length, 0, (struct sockaddr*) &addr, &addrLen); if (rc < ETHInterface_Header_SIZE) { Log_debug(context->logger, "Failed to receive eth frame"); return; } Assert_true(msg->length >= rc); msg->length = rc; //Assert_true(addrLen == SOCKADDR_LL_LEN); struct ETHInterface_Header hdr; Message_pop(msg, &hdr, ETHInterface_Header_SIZE, NULL); // here we could put a switch statement to handle different versions differently. if (hdr.version != ETHInterface_CURRENT_VERSION) { Log_debug(context->logger, "DROP unknown version"); return; } uint16_t reportedLength = Endian_bigEndianToHost16(hdr.length_be); reportedLength -= ETHInterface_Header_SIZE; if (msg->length != reportedLength) { if (msg->length < reportedLength) { Log_debug(context->logger, "DROP size field is larger than frame"); return; } msg->length = reportedLength; } if (hdr.fc00_be != Endian_hostToBigEndian16(0xfc00)) { Log_debug(context->logger, "DROP bad magic"); return; } struct ETHInterface_Sockaddr sockaddr = { .zero = 0 }; Bits_memcpyConst(sockaddr.mac, addr.sll_addr, 6); sockaddr.generic.addrLen = ETHInterface_Sockaddr_SIZE; if (addr.sll_pkttype == PACKET_BROADCAST) { sockaddr.generic.flags |= Sockaddr_flags_BCAST; } Message_push(msg, &sockaddr, ETHInterface_Sockaddr_SIZE, NULL); Assert_true(!((uintptr_t)msg->bytes % 4) && "Alignment fault"); Iface_send(&context->pub.generic.iface, msg); } static void handleEvent(void* vcontext) { struct ETHInterface_pvt* context = Identity_check((struct ETHInterface_pvt*) vcontext); struct Allocator* messageAlloc = Allocator_child(context->pub.generic.alloc); handleEvent2(context, messageAlloc); Allocator_free(messageAlloc); } List* ETHInterface_listDevices(struct Allocator* alloc, struct Except* eh) { struct ifaddrs* ifaddr = NULL; if (getifaddrs(&ifaddr) || ifaddr == NULL) { Except_throw(eh, "getifaddrs() -> errno:%d [%s]", errno, strerror(errno)); } List* out = List_new(alloc); for (struct ifaddrs* ifa = ifaddr; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_PACKET) { List_addString(out, String_new(ifa->ifa_name, alloc), alloc); } } freeifaddrs(ifaddr); return out; } static int closeSocket(struct Allocator_OnFreeJob* j) { struct ETHInterface_pvt* ctx = Identity_check((struct ETHInterface_pvt*) j->userData); close(ctx->socket); return 0; } struct ETHInterface* ETHInterface_new(struct EventBase* eventBase, const char* bindDevice, struct Allocator* alloc, struct Except* exHandler, struct Log* logger) { struct ETHInterface_pvt* ctx = Allocator_calloc(alloc, sizeof(struct ETHInterface_pvt), 1); Identity_set(ctx); ctx->pub.generic.iface.send = sendMessage; ctx->pub.generic.alloc = alloc; ctx->logger = logger; struct ifreq ifr = { .ifr_ifindex = 0 }; ctx->socket = socket(AF_PACKET, SOCK_DGRAM, Ethernet_TYPE_CJDNS); if (ctx->socket == -1) { Except_throw(exHandler, "call to socket() failed. [%s]", strerror(errno)); } Allocator_onFree(alloc, closeSocket, ctx); CString_strncpy(ifr.ifr_name, bindDevice, IFNAMSIZ - 1); ctx->ifName = String_new(bindDevice, alloc); if (ioctl(ctx->socket, SIOCGIFINDEX, &ifr) == -1) { Except_throw(exHandler, "failed to find interface index [%s]", strerror(errno)); } ctx->ifindex = ifr.ifr_ifindex; if (ioctl(ctx->socket, SIOCGIFFLAGS, &ifr) < 0) { Except_throw(exHandler, "ioctl(SIOCGIFFLAGS) [%s]", strerror(errno)); } if (!((ifr.ifr_flags & IFF_UP) && (ifr.ifr_flags & IFF_RUNNING))) { Log_info(logger, "Bringing up interface [%s]", ifr.ifr_name); ifr.ifr_flags |= IFF_UP | IFF_RUNNING; if (ioctl(ctx->socket, SIOCSIFFLAGS, &ifr) < 0) { Except_throw(exHandler, "ioctl(SIOCSIFFLAGS) [%s]", strerror(errno)); } } ctx->addrBase = (struct sockaddr_ll) { .sll_family = AF_PACKET, .sll_protocol = Ethernet_TYPE_CJDNS, .sll_ifindex = ctx->ifindex, .sll_hatype = ARPHRD_ETHER, .sll_pkttype = PACKET_OTHERHOST, .sll_halen = ETH_ALEN }; if (bind(ctx->socket, (struct sockaddr*) &ctx->addrBase, sizeof(struct sockaddr_ll))) { Except_throw(exHandler, "call to bind() failed [%s]", strerror(errno)); } Socket_makeNonBlocking(ctx->socket); Event_socketRead(handleEvent, ctx, ctx->socket, eventBase, alloc, exHandler); return &ctx->pub; }
int main() { SOCKET wsocket; struct sockaddr_in server; struct sockaddr_in secondary_input; int slen; int recv_len; char _buffer[BUFLEN]; WSADATA wsa; slen = sizeof(secondary_input); // initialize socket printf("%s\n", "Initializing dear system sequence..."); if(WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { printf("%s%s\n", "ERR", "winsock failure initializing. Rejecting telemetry."); return WSAGetLastError(); } printf("%s", "Winsock initialized...\n"); // create socket if(wsocket = socket(AF_INET, SOCK_DGRAM, 0) == INVALID_SOCKET) { printf("%s%s\n", "ERR", "winsock failure spawning. Rejecting telemetry."); return WSAGetLastError(); } printf("%s", "Winsock spawned. Binding..."); // set struct properties server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(PORT); // bind socket if(bind(wsocket, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) { printf("%s%s\n", "ERR", "winsock failure binding. Rejecting telemetry."); return WSAGetLastError(); } printf("%s", "winsock ready. Listening for telemetry...\n"); while(1) { fflush(stdout); memset(_buffer, '\0', BUFLEN); // receive data if((recv_len = recvfrom(wsocket, _buffer, BUFLEN, 0, (struct sockaddr *)&secondary_input, &slen)) == SOCKET_ERROR) { printf("%s\n", "winsock failure receiving telemetry. Flushing..."); return WSAGetLastError(); } // print data printf("%s\n", _buffer); } closesocket(wsocket); WSACleanup(); return 0; }
int recv_data2(int fd,char * buffer,int buffer_len, struct sockaddr* from, socklen_t* fromlen) { return recvfrom(fd, buffer, buffer_len, 0, from, fromlen); }
void zmq::udp_engine_t::in_event() { struct sockaddr_in in_address; socklen_t in_addrlen = sizeof(sockaddr_in); #ifdef ZMQ_HAVE_WINDOWS int nbytes = recvfrom(fd, (char*) in_buffer, MAX_UDP_MSG, 0, (sockaddr*) &in_address, &in_addrlen); const int last_error = WSAGetLastError(); if (nbytes == SOCKET_ERROR) { wsa_assert( last_error == WSAENETDOWN || last_error == WSAENETRESET || last_error == WSAEWOULDBLOCK); return; } #else int nbytes = recvfrom(fd, in_buffer, MAX_UDP_MSG, 0, (sockaddr*) &in_address, &in_addrlen); if (nbytes == -1) { errno_assert(errno != EBADF && errno != EFAULT && errno != ENOMEM && errno != ENOTSOCK); return; } #endif int rc; int body_size; int body_offset; msg_t msg; if (options.raw_socket) { sockaddr_to_msg (&msg, &in_address); body_size = nbytes; body_offset = 0; } else { char* group_buffer = (char *)in_buffer + 1; int group_size = in_buffer[0]; rc = msg.init_size (group_size); errno_assert (rc == 0); msg.set_flags (msg_t::more); memcpy (msg.data (), group_buffer, group_size); // This doesn't fit, just ingore if (nbytes - 1 < group_size) return; body_size = nbytes - 1 - group_size; body_offset = 1 + group_size; } rc = session->push_msg (&msg); errno_assert (rc == 0 || (rc == -1 && errno == EAGAIN)); // Pipe is full if (rc != 0) { rc = msg.close (); errno_assert (rc == 0); reset_pollin (handle); return; } rc = msg.close (); errno_assert (rc == 0); rc = msg.init_size (body_size); errno_assert (rc == 0); memcpy (msg.data (), in_buffer + body_offset, body_size); rc = session->push_msg (&msg); errno_assert (rc == 0); rc = msg.close (); errno_assert (rc == 0); session->flush (); }
int main(int argc, char **argv) { struct sockaddr_in myaddr; /* our address */ struct sockaddr_in remaddr; /* remote address */ socklen_t addrlen = sizeof(remaddr); /* length of addresses */ int recvlen; /* # bytes received */ int fd; /* our socket */ int msgcnt = 0; /* count # of messages we received */ unsigned char buf[BUFSIZE]; /* receive buffer */ /* create a UDP socket */ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("cannot create socket\n"); return 0; } /* bind the socket to any valid IP address and a specific port */ memset((char *)&myaddr, 0, sizeof(myaddr)); myaddr.sin_family = AF_INET; myaddr.sin_addr.s_addr = htonl(INADDR_ANY); myaddr.sin_port = htons(SERVICE_PORT); if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) { perror("bind failed"); return 0; } /* now loop, receiving data and printing what we received */ int count = 0; int flag = 1; int i; struct timeval start, end; printf("waiting on port %d\n", SERVICE_PORT); for (i = 0; i < 50000; i++) { //printf("waiting on port %d\n", SERVICE_PORT); recvlen = recvfrom(fd, buf, BUFSIZE, 0, (struct sockaddr *)&remaddr, &addrlen); if (recvlen > 0) { if (flag){ flag = 0; gettimeofday(&start, NULL); } buf[recvlen] = 0; count+=recvlen; //printf("received message: \"%s\" (%d bytes) from %s\n", buf, recvlen, inet_ntoa(remaddr.sin_addr)); } else printf("uh oh - something went wrong!\n"); /*sprintf(buf, "ack %d", msgcnt++); printf("sending response \"%s\"\n", buf); if (sendto(fd, buf, strlen(buf), 0, (struct sockaddr *)&remaddr, addrlen) < 0) perror("sendto");*/ } gettimeofday(&end, NULL); double startm = (start.tv_sec) * 1000 + (start.tv_usec) / 1000 ; double endm = (end.tv_sec) * 1000 + (end.tv_usec) / 1000 ; double diff = endm - startm; printf("size: %d\ntime: %lf\nspeed: %lf KBps\n", count, diff, (count/1024)/(diff/1000)); printf("speed: %lf Mbps\n", ((count*8)/(1024*1024))/(diff/1000)); /* never exits */ }
/** * Makes a remote procedure call on the specific server. */ return_type make_remote_call(const char *servernameorip, const int serverportnumber, const char *procedure_name, const int nparams, ...) { return_type rt; rt.return_val = NULL; rt.return_size = 0; // Create server address struct sockaddr_in server_socket_address; memset((char *)&server_socket_address, 0, sizeof(server_socket_address)); server_socket_address.sin_port = htons(serverportnumber); server_socket_address.sin_family = AF_INET; // Lookup the server's IP using the hostname provided struct hostent *server_ip_address; server_ip_address = gethostbyname(servernameorip); memcpy((void *)&server_socket_address.sin_addr, server_ip_address->h_addr_list[0], server_ip_address->h_length); // Create client socket and bind address to it int client_socket = socket(AF_INET, SOCK_DGRAM, 0); struct sockaddr_in client_socket_address; memset((char *)&client_socket_address, 0, sizeof(client_socket_address)); client_socket_address.sin_addr.s_addr = htonl(INADDR_ANY); client_socket_address.sin_family = AF_INET; client_socket_address.sin_port = htons(client_port); bind(client_socket, (struct sockaddr *)&client_socket_address, sizeof(client_socket_address)); /** * Pack data into buffer * * Buffer serialization format: * [functionSize | functionName] * [argumentSize | argument] * [argumentSize | argument] */ unsigned char buffer[buffer_size]; memset(buffer, 0, sizeof(buffer)); // Pack function name and size in buffer int function_name_size = strlen(procedure_name) + 1; unsigned char *serial_result = int_serialize(buffer, function_name_size); unsigned char *function_name = (unsigned char*)procedure_name; int i = 0; while (i < function_name_size) { serial_result[i] = function_name[i]; i++; } serial_result = serial_result + function_name_size; serial_result = int_serialize(serial_result, nparams); // Pack argument size and argument in buffer va_list var_args; va_start(var_args, nparams); i = 0; while (i < nparams) { // Put argument size in buffer int arg_size = va_arg(var_args, int); serial_result = int_serialize(serial_result, arg_size); // Put argument in buffer void *arg = va_arg(var_args, void *); unsigned char *char_arg = (unsigned char*)arg; int j = 0; while (j < arg_size) { serial_result[j] = char_arg[j]; j++; } serial_result = serial_result + arg_size; i++; } va_end(var_args); /** * Make remote procedure call */ sendto(client_socket, buffer, buffer_size, 0, (struct sockaddr *)&server_socket_address, sizeof(server_socket_address)); /** * Listen for the result of remote procedure call */ struct sockaddr_in remote_address; socklen_t addrlen = sizeof(remote_address); unsigned char receive_buffer[buffer_size]; while (1) { int receive_length = recvfrom(client_socket, (void *)receive_buffer, buffer_size, 0, (struct sockaddr *)&remote_address, &addrlen); if (receive_length > 0) { // Got a good message! Woot! unsigned char *return_value_buffer = receive_buffer + 4; int return_size = *(int*)receive_buffer; unsigned char return_value[return_size]; int k = 0; while (k < return_size) { return_value[k] = return_value_buffer[k]; k++; } memset((unsigned char *)&rt, 0, sizeof(rt)); rt.return_val = return_value; rt.return_size = return_size; return rt; } } }
void* Working(void* arg) { int r,i,chk,sock_id; char buf[BUFSIZE]; // InitWorkServer(); #ifdef TCP int id; id=*((int*)arg); #endif #ifdef UDP sock_id=socket(AF_INET,SOCK_DGRAM,0); struct sockaddr_in my_addr,cl_addr; int y=1; my_addr.sin_addr=((struct sockaddr_in*)arg)->sin_addr; my_addr.sin_family=((struct sockaddr_in*)arg)->sin_family; my_addr.sin_port=((struct sockaddr_in*)arg)->sin_port; setsockopt(sock_id, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(int)); chk=bind(sock_id,(struct sockaddr*)&my_addr,sizeof(struct sockaddr_in)); if(chk<0) perror("bind srv\n"); socklen_t len; len=sizeof(struct sockaddr_in); printf("my port is %d\n",ntohs(my_addr.sin_port)); #endif while(1) { #ifdef TCP chk=recv(id,buf,BUFSIZE*sizeof(char),0); #endif #ifdef UDP chk=recvfrom(sock_id,buf,BUFSIZE*sizeof(char),0,(struct sockaddr*)&cl_addr,&len); #endif if(chk==-1) { perror("receive\n"); continue; } else { r=rand()%2; if(r) { for(i=0;i<BUFSIZE;i++) { if(buf[i]>='a'&&buf[i]<='z') buf[i]-=32; } } else { for(i=0;i<BUFSIZE;i++) { if(buf[i]>='A'&&buf[i]<='Z') buf[i]+=32; } } #ifdef TCP chk=send(id,buf,BUFSIZE*sizeof(char),0); if(chk==-1) { perror("send\n"); continue; } #endif #ifdef UDP chk=sendto(sock_id,buf,BUFSIZE*sizeof(char),0,(struct sockaddr*)&cl_addr,len); if(chk==-1) { perror("send\n"); continue; } #endif printf("send %s\n",buf); } } }
int escuchaCliente(int socket, struct sockaddr_in addr) { char buffer[BUFFERSIZE]; char aux[BUFFERSIZE]; int bytecount; int fin=0; int code=0; /* Código de salida por defecto */ time_t t; struct tm *tmp; socklen_t slen=sizeof(addr); while (!fin) { memset(buffer, 0, BUFFERSIZE); if((bytecount=recvfrom(socket,buffer,BUFFERSIZE,0,(struct sockaddr*)&addr,&slen))==-1) { error(5, "No puedo recibir información"); } printf("%s\n",buffer); /* Evaluamos los comandos */ /* El sistema de gestión de comandos es muy rudimentario, pero nos vale */ /* Comando TIME - Da la hora */ if (strncmp(buffer, "TIME", 4)==0) { memset(buffer, 0, BUFFERSIZE); t = time(NULL); tmp = localtime(&t); strftime(buffer, BUFFERSIZE, "%Y-%m-%d %H:%M:%S", tmp); } /* Comando EXIT - Cierra la conexión actual */ else if (strncmp(buffer, "EXIT", 4)==0) { memset(buffer, 0, BUFFERSIZE); sprintf(buffer, "Hasta luego. Vuelve pronto %s\n", inet_ntoa(addr.sin_addr)); fin=1; } /* Comando CERRAR - Cierra el servidor */ else if (strncmp(buffer, "CERRAR", 6)==0) { memset(buffer, 0, BUFFERSIZE); sprintf(buffer, "Adiós. Cierro el servidor\n"); fin=1; code=99; /* Salir del programa */ } else { sprintf(aux, "ECHO: %s\n", buffer); strcpy(buffer, aux); } if(bytecount = sendto(socket,buffer,strlen(buffer),0, (struct sockaddr*)&addr, sizeof(addr))==-1){ error(6, "No puedo enviar información"); } } close(socket); return code; }
/* ask a helper process to do some filtering */ u_char /* 1=got an answer */ ask_helper(DCC_CLNT_CTXT *ctxt, void *logp, time_t avail_us, /* spend at most this much time */ HELPER_REQ_HDR *req, /* request sent to helper */ int req_len, HELPER_RESP_HDR *resp, /* put answer here */ int resp_len) { DCC_EMSG emsg; DCC_SOCKU send_su; socklen_t su_len; DCC_SOCKU recv_su; char sustr[DCC_SU2STR_SIZE]; char sustr2[DCC_SU2STR_SIZE]; u_char counted; u_int gen; struct timeval now; time_t us; DCC_POLLFD pollfd; int i; emsg[0] = '\0'; /* We will use the client context socket to talk to the helper, * so ensure that it is open */ if (!helper_soc_open(emsg, ctxt)) { thr_trace_msg(logp, "DNSBL reopen %s", emsg); return 0; } /* keep the lock until we have sent our request and wake-up call * to ensure that some other thread does not shut down all of * the helpers. */ helper_lock(); gettimeofday(&now, 0); /* If it has been a long time since we used a helper, then the last * of them might be about to die of boredom. Fix that race by * restarting all of them. * Most dying helpers should be reaped by the totals timer thread. */ if (helper.idle_helpers > 0 && DCC_IS_TIME(now.tv_sec, helper.idle_restart, HELPER_IDLE_RESTART)) { reap_helpers(1); if (helper.idle_helpers > 0) terminate_helpers(); gettimeofday(&now, 0); } /* Restart all helpers if the current helper socket is the wrong * family. This should happen only when the DCC client library * has chosen a new server */ if (helper.soc != INVALID_SOCKET && ctxt->soc[0].loc.sa.sa_family != AF_UNSPEC && helper.su.sa.sa_family != ctxt->soc[0].loc.sa.sa_family) { terminate_helpers(); gettimeofday(&now, 0); } helper.idle_restart = now.tv_sec + HELPER_IDLE_RESTART; if (helper.idle_helpers - helper.slow_helpers > 0) { /* avoid taking the last idle helper because there are * usually fewer truly idle helpers than we think because * we don't always wait for them to finish */ if (helper.idle_helpers > 2 || helper.total_helpers >= helper.max_helpers || !new_helper(ctxt, logp, req->id)) --helper.idle_helpers; counted = 1; } else if (helper.total_helpers >= helper.max_helpers) { if (helper.debug > 0) thr_trace_msg(logp, "%s DNSBL %d idle, %d slow, and" " %d total DNSBL helpers", req->id, helper.idle_helpers, helper.slow_helpers, helper.total_helpers); counted = 0; } else { if (!new_helper(ctxt, logp, req->id)) { helper_unlock(); return 0; } counted = 1; } /* The resolution of the BIND timeout limits is seconds, so even on * systems where the timeout limits work, the helper might delay * a second or two. To keep the count of idle helpers as accurate * as possible, always wait at least 1 second for an answer * and 2 seconds for an answer to reach the parent. */ req->avail_us = avail_us; avail_us += DCC_US; req->start = now; req->magic = HELPER_MAGIC_REQ; req->version = HELPER_VERSION; req->sn = ++helper.sn; gen = helper.gen; /* snapshot the address in case another thread restarts the helpers */ send_su = helper.su; /* If the client context socket is connected but not to the helper * socket, * then either disconnect it or connect to the helper's socket */ if (ctxt->soc[0].rem.sa.sa_family != AF_UNSPEC && !DCC_SU_EQ(&ctxt->soc[0].rem, &send_su) && !helper_soc_connect(emsg, ctxt, &send_su)) { thr_trace_msg(logp, "DNSBL soc_connect(): %s", emsg); help_finish(gen, 0, counted, 1); helper_unlock(); return 0; } if (ctxt->soc[0].rem.sa.sa_family == AF_UNSPEC) { i = sendto(ctxt->soc[0].s, req, req_len, 0, &send_su.sa, DCC_SU_LEN(&send_su)); } else { i = send(ctxt->soc[0].s, req, req_len, 0); } if (i != req_len) { if (i < 0) thr_trace_msg(logp, "%s DNSBL sendto(%s): %s", req->id, dcc_su2str(sustr, sizeof(sustr), &send_su), ERROR_STR()); else thr_trace_msg(logp, "%s DNSBL sendto(%s)=%d", req->id, dcc_su2str(sustr, sizeof(sustr), &send_su), i); help_finish(gen, 0, counted, 1); helper_unlock(); return 0; } /* awaken a helper */ i = write(helper.pipe_write, "x", 1); if (i != 1) { if (i < 0) thr_trace_msg(logp, "%s DNSBL write(pipe_write=%d): %s", req->id, helper.pipe_write, ERROR_STR()); else thr_trace_msg(logp, "%s DNSBL write(pipe_write)=%d", req->id, i); help_finish(gen, 0, counted, 1); helper_unlock(); return 0; } helper_unlock(); for (;;) { us = avail_us - tv_diff2us(&now, &req->start); if (us < 0) us = 0; pollfd.fd = ctxt->soc[0].s; i = select_poll(emsg, &pollfd, 1, 1, us); if (i < 0) { thr_error_msg(logp, "%s DNSBL %s", req->id, emsg); help_finish(gen, 0, counted, 0); return 0; } gettimeofday(&now, 0); if (i == 0) { if (helper.debug) thr_trace_msg(logp, "%s DNSBL no helper answer after" " %1.f sec", req->id, tv_diff2us(&now, &req->start) / (DCC_US*1.0)); helper_lock(); if (helper.slow_helpers<=helper.total_helpers/MAX_SLOW) ++helper.slow_helpers; help_finish(gen, 0, counted, 1); helper_unlock(); return 0; } su_len = sizeof(recv_su); i = recvfrom(ctxt->soc[0].s, resp, resp_len, 0, &recv_su.sa, &su_len); /* because we are using UDP, we might get stray packets */ if (i != resp_len) { if (i < 0) { thr_trace_msg(logp, "%s DNSBL recvfrom(): %s", req->id, ERROR_STR()); if (DCC_BLOCK_ERROR()) continue; help_finish(gen, 0, counted, 0); return 0; } if (helper.debug > 1) thr_trace_msg(logp, "%s DNSBL recvfrom(%s)=%d", req->id, dcc_su2str(sustr, sizeof(sustr), &recv_su), i); continue; } if (!DCC_SUnP_EQ(&send_su, &recv_su)) { if (helper.debug != 0) thr_trace_msg(logp, "%s DNSBL recvfrom(%s)" " instead of %s", req->id, dcc_su2str(sustr, sizeof(sustr), &recv_su), dcc_su2str(sustr2, sizeof(sustr2), &send_su)); continue; } if (resp->magic != HELPER_MAGIC_RESP || resp->version != HELPER_VERSION || resp->sn != req->sn) { if (helper.debug >1 ) thr_trace_msg(logp, "%s DNSBL recvfrom(%s)" " magic=%#08x sn=%d", req->id, dcc_su2str(sustr, sizeof(sustr), &recv_su), resp->magic, resp->sn); continue; } if (helper.debug > 4) thr_trace_msg(logp,"%s DNSBL answer from %s", req->id, dcc_su2str(sustr, sizeof(sustr), &recv_su)); help_finish(gen, 1, counted, 0); return 1; } }
PingStatus Pinger::PingUDP(uint32 lAddr, uint32 ttl, bool doLog) { // UDPing reworked ping sequence --> int nTTL = ttl; int nRet; sockaddr_in sa; int nAddrLen = sizeof(struct sockaddr_in); char bufICMP[1500]; // allow full MTU // clear ICMP socket before sending UDP - not best solution, but may be needed to exclude late responses etc u_long bytes2read = 0; do { nRet = ioctlsocket(is, FIONREAD, &bytes2read); if (bytes2read > 0) { // ignore errors here sa.sin_family = AF_INET; sa.sin_addr.s_addr = INADDR_ANY; sa.sin_port = 0; nRet = recvfrom (is, /* socket */ (LPSTR)bufICMP, /* buffer */ 1500, /* length */ 0, /* flags */ (sockaddr*)&sa, /* source */ &nAddrLen); /* addrlen*/ //if (lastTimeOut) lastTimeOut--; //if (!lastTimeOut && toNowTimeOut) { // toNowTimeOut--; // if (toNowTimeOut) lastTimeOut = 3; //} } } while (bytes2read > 0); // set TTL value for UDP packet - should success with winsock 2 // NB! take care about IP_TTL value - it's redefined in Ws2tcpip.h! // TODO: solve next problem correctly: // eMule is linking sockets functions using wsock32.lib (IP_TTL=7) // to use IP_TTL define, we must enforce linker to bind this function // to ws2_32.lib (IP_TTL=4) (linker options: ignore wsock32.lib) nRet = setsockopt(us, IPPROTO_IP, IP_TTL, (char*)&nTTL, sizeof(int)); if (nRet==SOCKET_ERROR) { DWORD lastError = WSAGetLastError(); PingStatus returnValue; returnValue.success = false; returnValue.delay = TIMEOUT; returnValue.error = lastError; //if (toNowTimeOut < 3) toNowTimeOut++; // lastTimeOut = 3; return returnValue; } sa.sin_family = AF_INET; sa.sin_addr.s_addr = lAddr; sa.sin_port = htons(UDP_PORT); // send lonely UDP packet with almost minimal content (0 bytes is allowed too, but no data will be sent then) nRet = sendto(us, (LPSTR)&nTTL, 4, 0, (sockaddr*)&sa, sizeof(sa)); // send four bytes - TTL :) CTimeTick m_time; m_time.Tick(); if (nRet==SOCKET_ERROR) { DWORD lastError = WSAGetLastError(); PingStatus returnValue; returnValue.success = false; returnValue.error = lastError; //if (toNowTimeOut < 3) toNowTimeOut++; // lastTimeOut = 3; return returnValue; } IPHeader* reply = (IPHeader*)bufICMP; bytes2read = 0; int timeoutOpt = TIMEOUT; bool noRcvTimeOut = false; nRet = setsockopt(is, SOL_SOCKET, SO_RCVTIMEO, (const char*) &timeoutOpt, sizeof(timeoutOpt)); if (nRet==SOCKET_ERROR) noRcvTimeOut = true; float usResTime = 0.0f; while((usResTime += m_time.Tick()) < TIMEOUT){ if (noRcvTimeOut){ nRet = ioctlsocket(is, FIONREAD, &bytes2read); if (nRet != 0) { DWORD lastError = WSAGetLastError(); PingStatus returnValue; returnValue.success = false; returnValue.delay = TIMEOUT; returnValue.error = lastError; //if (toNowTimeOut < 3) toNowTimeOut++; // lastTimeOut = 3; return returnValue; } if (bytes2read > 0) { // read and filter incoming ICMP } else { Sleep(1); // share time with other threads continue; } } sa.sin_family = AF_INET; sa.sin_addr.s_addr = INADDR_ANY; sa.sin_port = 0; nRet = recvfrom (is, /* socket */ (LPSTR)bufICMP, /* buffer */ 1500, /* length */ 0, /* flags */ (sockaddr*)&sa, /* source */ &nAddrLen); /* addrlen*/ usResTime += m_time.Tick(); if (nRet==SOCKET_ERROR) { DWORD lastError = WSAGetLastError(); PingStatus returnValue; returnValue.success = false; returnValue.delay = TIMEOUT; returnValue.error = lastError; //if (toNowTimeOut < 3) toNowTimeOut++; // lastTimeOut = 3; return returnValue; } unsigned short header_len = reply->h_len * 4; ICMPHeader* icmphdr = (ICMPHeader*)(bufICMP + header_len); IN_ADDR stDestAddr; stDestAddr.s_addr = reply->source_ip; if (((icmphdr->type == ICMP_TTL_EXPIRE) || (icmphdr->type == ICMP_DEST_UNREACH)) && (icmphdr->UDP.dest_port == htons(UDP_PORT)) && (icmphdr->hdrsent.dest_ip == lAddr)) { PingStatus returnValue; if(icmphdr->type == ICMP_TTL_EXPIRE) { returnValue.success = true; returnValue.status = IP_TTL_EXPIRED_TRANSIT; returnValue.delay = usResTime; returnValue.destinationAddress = stDestAddr.s_addr; returnValue.ttl = ttl; } else { returnValue.success = true; returnValue.status = IP_DEST_HOST_UNREACHABLE; returnValue.delay = usResTime; returnValue.destinationAddress = stDestAddr.s_addr; returnValue.ttl = 64 - (reply->ttl & 63); } if(doLog) { theApp.QueueDebugLogLine(false,_T("Reply (UDP-pinger) from %s: bytes=%d time=%3.2fms TTL=%i"), ipstr(stDestAddr), nRet, usResTime, returnValue.ttl); } return returnValue; } else { // verbose log filtered packets info (not seen yet...) //if (lastTimeOut) lastTimeOut--; //if (!lastTimeOut && toNowTimeOut) { // toNowTimeOut--; // if (toNowTimeOut) lastTimeOut = 3; //} if(doLog) { theApp.QueueDebugLogLine(false,_T("Filtered reply (UDP-pinger) from %s: bytes=%d time=%3.2fms TTL=%i type=%i"), ipstr(stDestAddr), nRet, usResTime, 64 - (reply->ttl & 63), icmphdr->type); } } } //if (usResTime >= TIMEOUT) { // if (toNowTimeOut < 3) toNowTimeOut++; // lastTimeOut = 3; //} // UDPing reworked ping sequence end <-- PingStatus returnValue; returnValue.success = false; returnValue.delay = TIMEOUT; returnValue.error = IP_REQ_TIMED_OUT; return returnValue; }
/* helper processes start here via fork()/exec() in the parent */ void DCC_NORET helper_child(DCC_SOCKET s, int fd, int total_helpers) { sigset_t sigs; socklen_t soc_len; DNSBL_REQ req; int req_len; DNSBL_RESP resp; DCC_SOCKU req_su; socklen_t su_len; struct timeval now; u_char wake_buf; int secs, i; /* this process inherits via exec() by dccm or dccifd odd signal * blocking from some pthreads implementations including FreeBSD 5.* */ signal(SIGHUP, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGTERM, SIG_IGN); sigemptyset(&sigs); sigaddset(&sigs, SIGALRM); sigprocmask(SIG_UNBLOCK, &sigs, 0); helper_init(0); if (have_helpers) dcc_logbad(EX_SOFTWARE, "no threads for DNSBL helpers"); helper.total_helpers = total_helpers; helper.pipe_read = fd; helper.soc = s; soc_len = sizeof(helper.su); if (0 > getsockname(helper.soc, &helper.su.sa, &soc_len)) dcc_logbad(EX_IOERR, "DNSBL helper getsockname(%d): %s", helper.soc, ERROR_STR()); if (helper.debug > 1) dcc_trace_msg("DNSBL helper process starting on %s", dcc_su2str_err(&helper.su)); for (;;) { /* Use read() and SIGALRM to watch for a wake-up byte * from the parent, the parent ending and closing the pipe, * or enough idle time to require our retirement. This * tactic awakens a single child for each wake-up call * from the parent. Using select() or poll() on the main * socket awakens a thundering herd of children */ secs = HELPER_IDLE_STOP_SECS+1; if (helper.total_helpers > 0) secs /= helper.total_helpers+1; if (secs < 5) secs = 5; signal(SIGALRM, helper_alarm); #ifdef HAVE_SIGINTERRUPT siginterrupt(SIGALRM, 1); #endif helper_alarm_hit = 0; alarm(secs); for (;;) { su_len = sizeof(req_su); req_len = recvfrom(helper.soc, &req, ISZ(req), 0, &req_su.sa, &su_len); /* sleep until awakened if no work is ready */ if (req_len <= 0) { if (req_len == 0) dcc_logbad(EX_IOERR, "DNSBL helper recvfrom()=0"); if (!DCC_BLOCK_ERROR()) dcc_logbad(EX_IOERR, "DNSBL helper recvfrom():" " %s", ERROR_STR()); if (helper_alarm_hit) helper_exit("idle helper exit"); i = read(helper.pipe_read, &wake_buf, 1); /* The other end of the pipe can be marked * non-blocking by some pthreads * implementations. That makes read() on this * end fail with EAGAIN. When that happens, * fall back on select() or poll(). * Even on such pthread implementations, * it rarely happens. */ if (i < 0 && DCC_BLOCK_ERROR()) { DCC_POLLFD pollfd; DCC_EMSG emsg; pollfd.fd = helper.pipe_read; i = select_poll(emsg, &pollfd, 1, 0, -1); if (i < 0) dcc_logbad(EX_IOERR, "dnsbl HELPER %s", emsg); } /* loof for work after a wake-up call */ if (i > 0) continue; if (helper_alarm_hit) continue; if (i == 0) helper_exit("shutdown"); if (i < 0) { dcc_logbad(EX_OSERR, "DNSBL read(terminate): %s", ERROR_STR()); } } if (req_len != helper.req_len) { if (helper.debug) dcc_trace_msg("DNSBL helper" " recvfrom(parent %s)=%d" " instead of %d", dcc_su2str_err(&req_su), req_len, helper.req_len); continue; } /* we might get stray packets because we cannot * connect to a single port */ if (!DCC_SUnP_EQ(&helper.su, &req_su)) { if (helper.debug) dcc_trace_msg("DNSBL helper" " request from" " %s instead of %s", dcc_su2str_err(&req_su), dcc_su2str_err(&helper.su)); continue; } if (req.hdr.magic != HELPER_MAGIC_REQ || req.hdr.version != HELPER_VERSION) { if (helper.debug) dcc_trace_msg("DNSBL helper" " recvfrom(parent %s)" " magic=%#08x", dcc_su2str_err(&req_su), req.hdr.magic); continue; } break; } gettimeofday(&now, 0); alarm(0); /* do not bother working if it is already too late to answer, * perhaps because a previous helper died */ i = tv_diff2us(&now, &req.hdr.start); if (i >= req.hdr.avail_us) { if (helper.debug > 1) dcc_trace_msg("%s DNSBL helper" " already too late to start;" " used %.1f of %.1f seconds", req.hdr.id, i / (DCC_US*1.0), req.hdr.avail_us / (DCC_US*1.0)); continue; } memset(&resp, 0, sizeof(resp)); resp.hdr.magic = HELPER_MAGIC_RESP; resp.hdr.version = HELPER_VERSION; resp.hdr.sn = req.hdr.sn; /* do the work and send an answer if we have one */ if (!dnsbl_work(&req, &resp)) continue; /* do not answer if it is too late */ gettimeofday(&now, 0); i = tv_diff2us(&now, &req.hdr.start); if (i > (req.hdr.avail_us + DCC_US/2)) { if (helper.debug > 1) dcc_trace_msg("%s DNSBL helper" " too late to answer;" " used %.1f of %.1f seconds", req.hdr.id, i / (DCC_US*1.0), req.hdr.avail_us / (DCC_US*1.0)); continue; } i = sendto(helper.soc, &resp, sizeof(resp), 0, &req_su.sa, DCC_SU_LEN(&req_su)); if (i != sizeof(resp)) { if (i < 0) dcc_error_msg("%s helper sendto(%s): %s", req.hdr.id, dcc_su2str_err(&req_su), ERROR_STR()); else dcc_error_msg("%s helper sendto(%s)=%d", req.hdr.id, dcc_su2str_err(&req_su), i); } } }
/** * The main program * * Parameters: * - int argc => The number of arguments passed * - char** args => The arguments list * * Return: * - int => The result of the execution */ int main(int argc, char** args) { /* ##### Process parameters and get filter ##### */ int filter = process_params(argc, args); /* ##### Network structures ##### */ // Initialize the client socket struct sockaddr_in destination; int client_socket = init_socket(args[1], &destination); // Parameters for the packet transmission struct packet to_server; struct packet from_server; socklen_t destination_length = (socklen_t)sizeof(struct sockaddr); /* ##### Audio reader parameters ##### */ // Some more variables that we'll need for reading audio files int sample_rate, sample_size, channels; int write_init_audio = 0; /* ##### Timeout parameters ##### */ int nb; fd_set watch_over; struct timeval timeout; /* ##### Filter parameters ##### */ // For volume filter int volume_value; // For echo filter int nb_buffers_per_echo = 0, nb_samples_per_buffer, current_buffer_position, to_read_position; char* echo_buffer; char volume_buffer[BUFFER_SIZE]; /* ################################################## Sending the filename ################################################## */ // The first packet to send is the filename create_packet(&to_server, P_FILENAME, args[2]); // Send the packet containing the filename if (sendto(client_socket, &to_server, sizeof(struct packet), 0, (struct sockaddr*)&destination, destination_length) == -1) { perror("Error during the sending of the filename packet"); return 1; } /* ################################################## Talk with the server ################################################## */ do { // Clear and reinitialize the fd set FD_ZERO(&watch_over); FD_SET(client_socket, &watch_over); timeout.tv_sec = 0; timeout.tv_usec = TIMEOUT_CLIENT; // 200ms nb = select(client_socket+1, &watch_over, NULL, NULL, &timeout); // Clear packets clear_packet(&to_server); clear_packet(&from_server); // If error during the select if (nb < 0) { perror("Can't attach the select to the file descriptor"); return 1; } // Just request the same packet if timeout reached if (nb == 0) { to_server.type = P_REQ_SAME_PACKET; if (sendto(client_socket, &to_server, sizeof(struct packet), 0, (struct sockaddr*)&destination, destination_length) == -1) { perror("Can't request same packet"); return 1; } } // If open, just act normally if (FD_ISSET(client_socket, &watch_over)) { // Wait a packet if (recvfrom(client_socket, &from_server, sizeof(struct packet), 0, (struct sockaddr*)&destination, &destination_length) != -1) { // In function of the type of the packet received switch (from_server.type) { // --------------- An server error happened on the server --------------- case P_ERR_TRANSMISSION: case P_SERVER_ERROR: // Display the error printf("%s\n", from_server.message); // Close connection close_connection(client_socket, "Closing due to server error", 0); break; // --------------- The first response from the server is received --------------- case P_FILE_HEADER: // Get the informations about the audio file sample_rate = *((int*)(from_server.message)); sample_size = *((int*)(from_server.message + BUFFER_SPACE)); channels = *((int*)(from_server.message + 2*BUFFER_SPACE)); // ----- Filters initialisation ----- switch (filter) { // If none do nothing case F_NONE: break; // If mono, just force the channel to one case F_MONO: channels = 1; break; // If volume, get the value of the filter parameter case F_VOLUME: volume_value = atoi(args[4]); nb_samples_per_buffer = BUFFER_SIZE/(sample_size/8); break; // If echo, allocate the echo buffer case F_ECHO: // Calculate the number of bytes needed for one second nb_buffers_per_echo = (ECHO_IN_SCDS * sample_rate * (sample_size/8)) / BUFFER_SIZE; // Allocate the table of buffers echo_buffer = malloc(nb_buffers_per_echo * BUFFER_SIZE); // The buffer position and the buffer to read put to 0 current_buffer_position = 0; to_read_position = 0; break; // If speed case F_SPEED: // Multiply the framerate sample_rate = sample_rate * atoi(args[4]); break; // If unknown default: close_connection(client_socket, "Unknown filter", write_init_audio); break; } // Initialize the write end write_init_audio = aud_writeinit(sample_rate, sample_size, channels); // If an error happened if (write_init_audio < 1) { // If echo filter, free the buffer if (filter == F_ECHO) free(echo_buffer); // Close the connection close_connection(client_socket, "Error at getting the audio output device", 0); } // If everything's ok, request the first block clear_packet(&to_server); to_server.type = P_REQ_NEXT_BLOCK; // Send the request if (sendto(client_socket, &to_server, sizeof(struct packet), 0, (struct sockaddr*)&destination, destination_length) == -1) { // If echo filter, free the buffer if (filter == F_ECHO) free(echo_buffer); // Close the connection close_connection(client_socket, "Error at requesting the first block", write_init_audio); } break; // --------------- A block is received, read it --------------- case P_BLOCK: // Read the music on the audio output (in function of the filter passed) switch (filter) { // If none, mono or speed case F_NONE: case F_MONO: case F_SPEED: if (write(write_init_audio, from_server.message, BUFFER_SIZE) == -1) close_connection(client_socket, "Error at writing a block on audio output", write_init_audio); break; // If echo case F_ECHO: // Read the content of the buffer received if (write(write_init_audio, from_server.message, BUFFER_SIZE) == -1) { // Echo filter so free the buffer free(echo_buffer); // Close connection close_connection(client_socket, "Error at writing a block on audio output", write_init_audio); } // Then put this buffer into the echo buffer if the buffer isn't full if (current_buffer_position < nb_buffers_per_echo) { memcpy((echo_buffer + current_buffer_position*BUFFER_SIZE), from_server.message, BUFFER_SIZE); ++current_buffer_position; } // If the echo buffer is full else { // Read the current buffer position if (write(write_init_audio, (echo_buffer + to_read_position*BUFFER_SIZE), BUFFER_SIZE) == -1) { // Echo filter so free the buffer free(echo_buffer); // Close connection close_connection(client_socket, "Error at writing an echo block on audio output", write_init_audio); } // And replace it with the new one memcpy((echo_buffer + to_read_position*BUFFER_SIZE), from_server.message, BUFFER_SIZE); // Increment the flag to_read_position = (to_read_position+1)%nb_buffers_per_echo; } break; // If upper or lower volume case F_VOLUME: // Clear the temporary buffer memset(volume_buffer, 0, BUFFER_SIZE); // Variables used in the loop int i; // The increment var and a temporary value int tmp; // Temporary var // Get each sample and multiply its value for (i = 0; i < nb_samples_per_buffer; ++i) { // Multiply the value of the sample, get a double value tmp = *((int*)(from_server.message + i*sizeof(int))) * volume_value; // Then store it in the temporary buffer *((int*)(volume_buffer + i*sizeof(int))) = tmp; } // And in the end, read the whole buffer if (write(write_init_audio, volume_buffer, BUFFER_SIZE) == -1) close_connection(client_socket, "Error at writing a volume changed block on audio output", write_init_audio); break; // If an unknown filter, error! default: close_connection(client_socket, "Filter passed unknown", write_init_audio); break; } // End of filter's switch // If everything's ok, request the next block clear_packet(&to_server); to_server.type = P_REQ_NEXT_BLOCK; // Send the request if (sendto(client_socket, &to_server, sizeof(struct packet), 0, (struct sockaddr*)&destination, destination_length) == -1) { // If echo filter, free the buffer if (filter == F_ECHO) free(echo_buffer); // Close connection close_connection(client_socket, "Error at requesting a block", write_init_audio); } break; // --------------- The last block is received, read it --------------- case P_EOF: // Read the music on the audio output (in function of the filter passed) switch (filter) { // If none, mono or speed case F_NONE: case F_MONO: case F_SPEED: if (write(write_init_audio, from_server.message, BUFFER_SIZE) == -1) close_connection(client_socket, "Error at writing a block on audio output", write_init_audio); break; // If echo case F_ECHO: // Read the content of the buffer received if (write(write_init_audio, from_server.message, BUFFER_SIZE) == -1) { // Echo filter so free the buffer free(echo_buffer); // Close connection close_connection(client_socket, "Error at writing a block on audio output", write_init_audio); } // And in the end, just read the whole echo buffer left if (write(write_init_audio, (echo_buffer + to_read_position*BUFFER_SIZE), ((current_buffer_position - to_read_position)*BUFFER_SIZE)) == -1) { // Echo filter so free the buffer free(echo_buffer); // Close connection close_connection(client_socket, "Error at writing the last echo block on audio output", write_init_audio); } // Free the echo_buffer in the end free(echo_buffer); break; // If upper or lower volume case F_VOLUME: // Clear the temporary buffer memset(volume_buffer, 0, BUFFER_SIZE); // Variables used in the loop int i; // The increment var and a temporary value int tmp; // Temporary var // Get each sample and multiply its value for (i = 0; i < nb_samples_per_buffer; ++i) { // Multiply the value of the sample, get a double value tmp = *((int*)(from_server.message + i*sizeof(int))) * volume_value; // Then store it in the temporary buffer *((int*)(volume_buffer + i*sizeof(int))) = tmp; } // And in the end, read the whole buffer if (write(write_init_audio, volume_buffer, BUFFER_SIZE) == -1) close_connection(client_socket, "Error at writing a volume changed block on audio output", write_init_audio); break; // If an unknown filter, error! default: close_connection(client_socket, "Filter passed unknown", write_init_audio); break; } // If everything's ok, send the last packet clear_packet(&to_server); // Close the connection close_connection(client_socket, "The file was correctly read, close the connection, bye", write_init_audio); break; // --------------- Unknown type --------------- default: close_connection(client_socket, "Packet type unknown", write_init_audio); break; } } } // If an error during the receiving of a packet else { // If echo filter, free the buffer (only if it has been initialized) if ((filter == F_ECHO) && (nb_buffers_per_echo > 0)) free(echo_buffer); // Close connection perror("Error during the receiving of a packet, the server may be busy"); return 0; } } while (from_server.type != P_CLOSE_TRANSMISSION); // Close the connection close_connection(client_socket, "The reading is done, close connection now", write_init_audio); // If everything's was ok (but the server is normally just waiting for clients) return 0; }