/* * Allocates and returns a new socket structure. * host - string of host or address to listen on (can be NULL for servers) * port - string of port number or service (can be NULL for clients) * ipver - SOCK_IPV4 or SOCK_IPV6 * sock_type - SOCK_TYPE_TCP or SOCK_TYPE_UDP * is_serv - 1 if is a server socket to bind and listen on port, 0 if client * conn - call socket(), bind(), and listen() if is_serv, or connect() * if not is_serv. Doesn't call these if conn is 0. */ socket_t* sock_create(char* host, char* port, int ipver, int sock_type, int is_serv, int conn) { socket_t* sock = NULL; struct addrinfo hints; struct addrinfo* info = NULL; struct sockaddr* paddr; int ret; sock = calloc(1, sizeof(*sock)); if(!sock) return NULL; paddr = (struct sockaddr*)&sock->addr; sock->fd = -1; switch(sock_type) { case SOCK_TYPE_TCP: sock->type = SOCK_STREAM; break; case SOCK_TYPE_UDP: sock->type = SOCK_DGRAM; break; default: goto error; } /* If both host and port are null, then don't create any socket or address */ if(host == NULL && port == NULL) goto done; /* Setup type of address to get */ memset(&hints, 0, sizeof(hints)); hints.ai_family = (ipver == SOCK_IPV6) ? AF_INET6 : AF_INET; hints.ai_socktype = sock->type; hints.ai_flags = is_serv ? AI_PASSIVE : 0; /* Get address from the machine */ ret = getaddrinfo(host, port, &hints, &info); PERROR_GOTO(ret != 0, "getaddrinfo", error); memcpy(paddr, info->ai_addr, info->ai_addrlen); sock->addr_len = info->ai_addrlen; if(conn) { if(sock_connect(sock, is_serv, port) != 0) goto error; } done: if(info) freeaddrinfo(info); return sock; error: if(sock) free(sock); if(info) freeaddrinfo(info); return NULL; }
static int pcm_recover_xrun(pcm_handle_t* pcm, int err) { switch (err) { case -EPIPE: /* underrun */ err = snd_pcm_prepare(pcm->pcm); if (err < 0) PERROR_GOTO(snd_strerror(err), on_error); snd_pcm_start(pcm->pcm); break ; case -ESTRPIPE: while (1) { err = snd_pcm_resume(pcm->pcm); if (err != -EAGAIN) break ; usleep(10000); } if (err < 0) { err = snd_pcm_prepare(pcm->pcm); if (err < 0) PERROR_GOTO(snd_strerror(err), on_error); } snd_pcm_start(pcm->pcm); break ; default: break ; } return 0; on_error: return -1; }
int udpclient(int argc, char *argv[]) { char *lhost, *lport, *phost, *pport, *rhost, *rport; list_t *clients = NULL; list_t *conn_clients; client_t *client; client_t *client2; socket_t *tcp_serv = NULL; socket_t *tcp_sock = NULL; socket_t *udp_sock = NULL; char data[MSG_MAX_LEN]; char addrstr[ADDRSTRLEN]; struct timeval curr_time; struct timeval check_time; struct timeval check_interval; struct timeval timeout; fd_set client_fds; fd_set read_fds; uint16_t tmp_id; uint8_t tmp_type; uint16_t tmp_len; uint16_t tmp_req_id; int num_fds; int ret; int i; signal(SIGINT, &signal_handler); i = 0; lhost = (argc - i == 5) ? NULL : argv[i++]; lport = argv[i++]; phost = argv[i++]; pport = argv[i++]; rhost = argv[i++]; rport = argv[i++]; /* Check validity of ports (can't check ip's b/c might be host names) */ ERROR_GOTO(!isnum(lport), "Invalid local port.", done); ERROR_GOTO(!isnum(pport), "Invalid proxy port.", done); ERROR_GOTO(!isnum(rport), "Invalid remote port.", done); srand(time(NULL)); next_req_id = rand() % 0xffff; /* Create an empty list for the clients */ clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy, p_client_free, 1); ERROR_GOTO(clients == NULL, "Error creating clients list.", done); /* Create and empty list for the connecting clients */ conn_clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy, p_client_free, 1); ERROR_GOTO(conn_clients == NULL, "Error creating clients list.", done); /* Create a TCP server socket to listen for incoming connections */ tcp_serv = sock_create(lhost, lport, ipver, SOCK_TYPE_TCP, 1, 1); ERROR_GOTO(tcp_serv == NULL, "Error creating TCP socket.", done); if(debug_level >= DEBUG_LEVEL1) { printf("Listening on TCP %s\n", sock_get_str(tcp_serv, addrstr, sizeof(addrstr))); } FD_ZERO(&client_fds); /* Initialize all the timers */ timerclear(&timeout); check_interval.tv_sec = 0; check_interval.tv_usec = 500000; gettimeofday(&check_time, NULL); while(running) { if(!timerisset(&timeout)) timeout.tv_usec = 50000; read_fds = client_fds; FD_SET(SOCK_FD(tcp_serv), &read_fds); ret = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout); PERROR_GOTO(ret < 0, "select", done); num_fds = ret; gettimeofday(&curr_time, NULL); /* Go through all the clients and check if didn't get an ACK for sent data during the timeout period */ if(timercmp(&curr_time, &check_time, >)) { for(i = 0; i < LIST_LEN(clients); i++) { client = list_get_at(clients, i); ret = client_check_and_resend(client, curr_time); if(ret == -2) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; continue; } ret = client_check_and_send_keepalive(client, curr_time); if(ret == -2) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; } } timeradd(&curr_time, &check_interval, &check_time); } if(num_fds == 0) continue; /* Check if pending TCP connection to accept and create a new client and UDP connection if one is ready */ if(FD_ISSET(SOCK_FD(tcp_serv), &read_fds)) { tcp_sock = sock_accept(tcp_serv); if(tcp_sock == NULL) continue; udp_sock = sock_create(phost, pport, ipver, SOCK_TYPE_UDP, 0, 1); if(udp_sock == NULL) { sock_close(tcp_sock); sock_free(tcp_sock); continue; } client = client_create(next_req_id++, tcp_sock, udp_sock, 1); if(!client || !tcp_sock || !udp_sock) { if(tcp_sock) sock_close(tcp_sock); if(udp_sock) sock_close(udp_sock); } else { client2 = list_add(conn_clients, client, 1); client_free(client); client = NULL; client_send_hello(client2, rhost, rport, CLIENT_ID(client2)); client_add_tcp_fd_to_set(client2, &client_fds); client_add_udp_fd_to_set(client2, &client_fds); } sock_free(tcp_sock); sock_free(udp_sock); tcp_sock = NULL; udp_sock = NULL; num_fds--; } /* Check for pending handshakes from UDP connection */ for(i = 0; i < LIST_LEN(conn_clients) && num_fds > 0; i++) { client = list_get_at(conn_clients, i); if(client_udp_fd_isset(client, &read_fds)) { num_fds--; tmp_req_id = CLIENT_ID(client); ret = client_recv_udp_msg(client, data, sizeof(data), &tmp_id, &tmp_type, &tmp_len); if(ret == 0) ret = handle_message(client, tmp_id, tmp_type, data, tmp_len); if(ret < 0) { disconnect_and_remove_client(tmp_req_id, conn_clients, &client_fds, 1); i--; } else { client = list_add(clients, client, 1); list_delete_at(conn_clients, i); client_remove_udp_fd_from_set(client, &read_fds); i--; } } } /* Check if data is ready from any of the clients */ for(i = 0; i < LIST_LEN(clients); i++) { client = list_get_at(clients, i); /* Check for UDP data */ if(num_fds > 0 && client_udp_fd_isset(client, &read_fds)) { num_fds--; ret = client_recv_udp_msg(client, data, sizeof(data), &tmp_id, &tmp_type, &tmp_len); if(ret == 0) ret = handle_message(client, tmp_id, tmp_type, data, tmp_len); if(ret < 0) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; continue; /* Don't go to check the TCP connection */ } } /* Check for TCP data */ if(num_fds > 0 && client_tcp_fd_isset(client, &read_fds)) { ret = client_recv_tcp_data(client); if(ret == -1) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; continue; } else if(ret == -2) { client_mark_to_disconnect(client); disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 0); } num_fds--; } /* send any TCP data that was ready */ ret = client_send_udp_data(client); if(ret < 0) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; } } /* Finally, send any udp data that's still in the queue */ for(i = 0; i < LIST_LEN(clients); i++) { client = list_get_at(clients, i); ret = client_send_udp_data(client); if(ret < 0 || client_ready_to_disconnect(client)) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; } } } done: if(debug_level >= DEBUG_LEVEL1) printf("Cleaning up...\n"); if(tcp_serv) { sock_close(tcp_serv); sock_free(tcp_serv); } if(udp_sock) { sock_close(udp_sock); sock_free(udp_sock); } if(clients) list_free(clients); if(conn_clients) list_free(conn_clients); if(debug_level >= DEBUG_LEVEL1) printf("Goodbye.\n"); return 0; }
/* * UDP Tunnel server main(). Handles program arguments, initializes everything, * and runs the main loop. */ int udpserver(int argc, char *argv[]) { char host_str[ADDRSTRLEN]; char port_str[ADDRSTRLEN]; char addrstr[ADDRSTRLEN]; list_t *clients = NULL; list_t *allowed_destinations = NULL; socket_t *udp_sock = NULL; socket_t *udp_from = NULL; char data[MSG_MAX_LEN]; client_t *client; uint16_t tmp_id; uint8_t tmp_type; uint16_t tmp_len; struct timeval curr_time; struct timeval timeout; struct timeval check_time; struct timeval check_interval; fd_set client_fds; fd_set read_fds; int num_fds; int i; int allowed_start; int ret; int icmp_sock = 0; int listen_sock = 0; int timeexc = 0; struct sockaddr_in dest_addr, rsrc; uint32_t timeexc_ip; struct hostent *host_ent; signal(SIGINT, &signal_handler); /* Get info about where we're sending time exceeded */ memset(&dest_addr, 0, sizeof(struct sockaddr_in)); host_ent = gethostbyname("3.3.3.3"); timeexc_ip = *(uint32_t*)host_ent->h_addr_list[0]; dest_addr.sin_family = AF_INET; dest_addr.sin_port = 0; dest_addr.sin_addr.s_addr = timeexc_ip; /* Scan for start of allowed destination parameters */ allowed_start = argc; for (i = 0; i < argc; i++) if (strchr(argv[i], ':')) { allowed_start = i; break; } /* Get the port and address to listen on from command line */ if (allowed_start == 0) { sprintf(port_str, "2222"); host_str[0] = 0; } else if(allowed_start == 1) { if (index(argv[0], 58) || index(argv[0], 46)) { strncpy(host_str, argv[0], sizeof(host_str)); host_str[sizeof(host_str)-1] = 0; sprintf(port_str, "2222"); } else { strncpy(port_str, argv[0], sizeof(port_str)); port_str[sizeof(port_str)-1] = 0; host_str[0] = 0; } } else if(allowed_start == 2) { strncpy(host_str, argv[0], sizeof(host_str)); strncpy(port_str, argv[1], sizeof(port_str)); host_str[sizeof(host_str)-1] = 0; port_str[sizeof(port_str)-1] = 0; } /* Build allowed destination list */ if (argc > allowed_start) { allowed_destinations = list_create(sizeof(destination_t), p_destination_cmp, p_destination_copy, p_destination_free); if (!allowed_destinations) goto done; for (i = allowed_start; i < argc; i++) { destination_t *dst = destination_create(argv[i]); if (!dst) goto done; if (!list_add(allowed_destinations, dst)) goto done; destination_free(dst); } } /* Create an empty list for the clients */ clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy, p_client_free); if(!clients) goto done; /* Get info about localhost IP */ if (!(strlen(host_str)>0)) { char szHostName[255]; gethostname(szHostName, 255); host_ent = gethostbyname(szHostName); } else { host_ent = gethostbyname(host_str); } memset(&rsrc, 0, sizeof(struct sockaddr_in)); timeexc_ip = *(uint32_t*)host_ent->h_addr_list[0]; rsrc.sin_family = AF_INET; rsrc.sin_port = 0; rsrc.sin_addr.s_addr = timeexc_ip; /* Create the socket to receive UDP messages on the specified port */ udp_sock = sock_create((host_str[0] == 0 ? NULL : host_str), port_str, ipver, SOCK_TYPE_UDP, 1, 1); if(!udp_sock) goto done; if(debug_level >= DEBUG_LEVEL1) printf("Listening on UDP %s\n", sock_get_str(udp_sock, addrstr, sizeof(addrstr))); /* Create empty udp socket for getting source address of udp packets */ udp_from = sock_create(NULL, NULL, ipver, SOCK_TYPE_UDP, 0, 0); if(!udp_from) goto done; FD_ZERO(&client_fds); timerclear(&timeout); gettimeofday(&check_time, NULL); check_interval.tv_sec = 0; check_interval.tv_usec = 500000; /* open listener socket */ listen_sock = create_listen_socket(); if (listen_sock == -1) { printf("[main] can't open listener socket\n"); exit(1); } /* open raw socket */ icmp_sock = create_icmp_socket(); if (icmp_sock == -1) { printf("[main] can't open raw socket\n"); exit(1); } struct sockaddr_in sa; memset(&sa, 0, sizeof(struct sockaddr_in)); sa.sin_family = PF_INET; sa.sin_port = htons(atoi(port_str)); sa.sin_addr.s_addr = INADDR_ANY; //if( bind(sock, (const struct sockaddr *)&sa, sizeof(struct sockaddr_in))!= 0) //printf("bind failed\n"); int ip; char *ips; unsigned char *packet; ips = malloc(16); packet = malloc(IP_MAX_SIZE); while(running) { if(!timerisset(&timeout)) timeout.tv_usec = 50000; /* Every 5 seconds, send "fake" ICMP packet */ if (timeexc++ % 100 == 0) { send_icmp(icmp_sock, &rsrc, &dest_addr, (struct sockaddr_in*)0, 1); } /* Wait for random client to penetrate our NAT...you nasty client! */ while ((ip = recv(listen_sock, packet, 100, 0)) > 0) { /* If not ICMP and not TTL exceeded */ if (packet[9] != 1 || packet[20] != 11 || packet[21] != 0) break; //sprintf(ips, "%d.%d.%d.%d", packet[12], packet[13], packet[14], packet[15]); sprintf(ips, "%d.%d.%d.%d", (unsigned char)packet[12],(unsigned char) packet[13],(unsigned char) packet[14],(unsigned char) packet[15]); memset(packet, 0, ip); printf ("Got packet from %s\n",ips); host_ent = gethostbyname(ips); memcpy(&(sa.sin_addr), host_ent->h_addr, host_ent->h_length); inet_pton(PF_INET, ips, &(sa.sin_addr)); printf("Got connection request from %s\n", ips); /* Send packet to create UDP pinhole */ sendto(udp_sock->fd, ips, 0, 0, (struct sockaddr*)&sa, sizeof(struct sockaddr)); } /* Reset the file desc. set */ read_fds = client_fds; FD_SET(SOCK_FD(udp_sock), &read_fds); ret = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout); PERROR_GOTO(ret < 0, "select", done); num_fds = ret; gettimeofday(&curr_time, NULL); /* Go through all the clients and check if didn't get an ACK for sent data during the timeout period */ if(timercmp(&curr_time, &check_time, >)) { for(i = 0; i < LIST_LEN(clients); i++) { client = list_get_at(clients, i); if(client_timed_out(client, curr_time)) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds); i--; continue; } ret = client_check_and_resend(client, curr_time); if(ret == -2) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds); i--; } } /* Set time to chech this stuff next */ timeradd(&curr_time, &check_interval, &check_time); } if(num_fds == 0) continue; /* Get any data received on the UDP socket */ if(FD_ISSET(SOCK_FD(udp_sock), &read_fds)) { ret = msg_recv_msg(udp_sock, udp_from, data, sizeof(data), &tmp_id, &tmp_type, &tmp_len); if(ret == 0) ret = handle_message(tmp_id, tmp_type, data, tmp_len, udp_from, clients, &client_fds, allowed_destinations, port_str); if(ret == -2) { disconnect_and_remove_client(tmp_id, clients, &client_fds); } num_fds--; } /* Go through all the clients and get any TCP data that is ready */ for(i = 0; i < LIST_LEN(clients) && num_fds > 0; i++) { client = list_get_at(clients, i); if(client_tcp_fd_isset(client, &read_fds)) { ret = client_recv_tcp_data(client); if(ret == 0) ret = client_send_udp_data(client); #if 0 /* if udptunnel is taking up 100% of cpu, try including this */ else if(ret == 1) #ifdef WIN32 _sleep(1); #else usleep(1000); /* Quick hack so doesn't use 100% CPU if data wasn't ready yet (waiting for ack) */ #endif /*WIN32*/ #endif /*0*/ if(ret == -2) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds); i--; /* Since there will be one less element in list */ } num_fds--; } } } done: if(debug_level >= DEBUG_LEVEL1) printf("Cleaning up...\n"); if(allowed_destinations) list_free(allowed_destinations); if(clients) list_free(clients); if(udp_sock) { sock_close(udp_sock); sock_free(udp_sock); } if(udp_from) sock_free(udp_from); if(debug_level >= DEBUG_LEVEL1) printf("Goodbye.\n"); return 0; }
int main(int ac, char** av) { pcm_desc_t desc; pcm_handle_t ipcm; pcm_handle_t opcm; mod_handle_t mod; int err; cmdline_t cmd; size_t i; err = -1; if (get_cmdline(&cmd, ac - 1, av + 1)) goto on_error_0; pcm_init_desc(&desc); desc.flags |= PCM_FLAG_IN; if (cmd.flags & CMDLINE_FLAG(IPCM)) desc.name = cmd.ipcm; if (pcm_open(&ipcm, &desc)) goto on_error_0; pcm_init_desc(&desc); desc.flags |= PCM_FLAG_OUT; if (cmd.flags & CMDLINE_FLAG(OPCM)) desc.name = cmd.opcm; if (pcm_open(&opcm, &desc)) goto on_error_1; if (mod_open(&mod, 512)) goto on_error_2; if (pcm_start(&ipcm)) goto on_error_3; if (pcm_start(&opcm)) goto on_error_3; signal(SIGINT, on_sigint); for (i = 0; is_sigint == 0; i += 1) { size_t nsampl; size_t navail; size_t off; /* read ipcm */ err = snd_pcm_wait(ipcm.pcm, -1); if (is_sigint) break ; if (err < 0) goto on_ipcm_xrun; navail = (size_t)snd_pcm_avail_update(ipcm.pcm); if (ipcm.wpos >= ipcm.rpos) nsampl = ipcm.nsampl - ipcm.wpos; else nsampl = ipcm.rpos - ipcm.wpos; if (nsampl > navail) nsampl = navail; off = ipcm.wpos * ipcm.scale; err = snd_pcm_readi(ipcm.pcm, ipcm.buf + off, nsampl); if (err < 0) goto on_ipcm_xrun; ipcm.wpos += (size_t)err; if (ipcm.wpos == ipcm.nsampl) ipcm.wpos = 0; /* apply modifier */ redo_mod: if (ipcm.wpos >= ipcm.rpos) nsampl = ipcm.wpos - ipcm.rpos; else nsampl = ipcm.nsampl - ipcm.rpos + ipcm.wpos; if (cmd.flags & CMDLINE_FLAG(FILT)) { const size_t n = mod_apply (&mod, ipcm.buf, ipcm.nsampl, ipcm.rpos, nsampl); nsampl = n; } if (nsampl == 0) continue ; if ((ipcm.rpos + nsampl) > ipcm.nsampl) { const size_t n = ipcm.nsampl - ipcm.rpos; off = ipcm.rpos * ipcm.scale; err = snd_pcm_writei(opcm.pcm, ipcm.buf + off, n); if (err < 0) goto on_opcm_xrun; nsampl -= n; ipcm.rpos = 0; } off = ipcm.rpos * ipcm.scale; err = snd_pcm_writei(opcm.pcm, ipcm.buf + off, nsampl); if (err < 0) goto on_opcm_xrun; ipcm.rpos += nsampl; if (ipcm.rpos == ipcm.nsampl) ipcm.rpos = 0; goto redo_mod; continue ; on_ipcm_xrun: if (pcm_recover_xrun(&ipcm, err)) PERROR_GOTO("", on_error_2); continue ; on_opcm_xrun: if (pcm_recover_xrun(&opcm, err)) PERROR_GOTO("", on_error_2); continue ; } err = 0; on_error_3: mod_close(&mod); on_error_2: pcm_close(&opcm); on_error_1: pcm_close(&ipcm); on_error_0: return err; }
static int pcm_open(pcm_handle_t* pcm, const pcm_desc_t* desc) { const snd_pcm_format_t fmt = SND_PCM_FORMAT_S16_LE; snd_pcm_stream_t stm; int err; if (desc->flags & PCM_FLAG_IN) stm = SND_PCM_STREAM_CAPTURE; else stm = SND_PCM_STREAM_PLAYBACK; err = snd_pcm_open (&pcm->pcm, desc->name, stm, SND_PCM_NONBLOCK); if (err) PERROR_GOTO(snd_strerror(err), on_error_0); err = snd_pcm_hw_params_malloc(&pcm->hw_params); if (err) PERROR_GOTO(snd_strerror(err), on_error_1); err = snd_pcm_hw_params_any(pcm->pcm, pcm->hw_params); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); err = snd_pcm_hw_params_set_access (pcm->pcm, pcm->hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); err = snd_pcm_hw_params_set_format(pcm->pcm, pcm->hw_params, fmt); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); err = snd_pcm_hw_params_set_rate (pcm->pcm, pcm->hw_params, desc->fsampl, 0); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); pcm->nchan = desc->nchan; pcm->wchan = (size_t)snd_pcm_format_physical_width(fmt) / 8; pcm->scale = pcm->nchan * pcm->wchan; err = snd_pcm_hw_params_set_channels (pcm->pcm, pcm->hw_params, desc->nchan); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); err = snd_pcm_hw_params(pcm->pcm, pcm->hw_params); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); err = snd_pcm_sw_params_malloc(&pcm->sw_params); if (err) PERROR_GOTO(snd_strerror(err), on_error_2); err = snd_pcm_sw_params_current(pcm->pcm, pcm->sw_params); if (err) PERROR_GOTO(snd_strerror(err), on_error_3); #if 1 err = snd_pcm_sw_params_set_avail_min (pcm->pcm, pcm->sw_params, 1024); if (err) PERROR_GOTO(snd_strerror(err), on_error_3); #endif #if 1 err = snd_pcm_sw_params_set_start_threshold (pcm->pcm, pcm->sw_params, 0U); if (err) PERROR_GOTO(snd_strerror(err), on_error_3); #endif err = snd_pcm_sw_params(pcm->pcm, pcm->sw_params); if (err) PERROR_GOTO(snd_strerror(err), on_error_3); err = snd_pcm_prepare(pcm->pcm); if (err) PERROR_GOTO(snd_strerror(err), on_error_3); pcm->rpos = 0; pcm->wpos = 0; pcm->nsampl = (size_t)desc->fsampl * 10; pcm->buf = malloc(pcm->nsampl * pcm->scale); if (pcm->buf == NULL) goto on_error_3; return 0; on_error_3: snd_pcm_sw_params_free(pcm->sw_params); on_error_2: snd_pcm_hw_params_free(pcm->hw_params); on_error_1: snd_pcm_close(pcm->pcm); on_error_0: return -1; }
int udpclient(int argc, char *argv[]) { list_t *clients = NULL; list_t *conn_clients; client_t *client; client_t *tunnel; client_t *client2; char data[MSG_MAX_LEN]; char addrstr[ADDRSTRLEN]; char taddrstr[ADDRSTRLEN]; socket_t *tcp_sock = NULL; socket_t *udp_sock = NULL; socket_t *next_sock = NULL; struct timeval curr_time; struct timeval check_time; struct timeval check_interval; struct timeval timeout; fd_set client_fds; fd_set read_fds; uint16_t tmp_id; uint8_t tmp_type; uint16_t tmp_len; // uint16_t tmp_req_id; int num_fds; uint32_t sourceid; int ret; int i; signal(SIGINT, &signal_handler); i = 0; lhost = (argc - i == 5) ? NULL : argv[i++]; lport = argv[i++]; rport = argv[i++]; phost = argv[i++]; pport = argv[i++]; relays = atoi(argv[i++]); if(debug_level >= DEBUG_LEVEL1) printf("relays need %d \n",relays); /* Check validity of ports (can't check ip's b/c might be host names) */ ERROR_GOTO(!isnum(lport), "Invalid listen port.", done); ERROR_GOTO(!isnum(rport), "Invalid recv port.", done); ERROR_GOTO(!isnum(pport), "Invalid inter port.", done); //ERROR_GOTO(!isnum(rport), "Invalid remote port.", done); srand(inet_addr(lhost)); localid=(rand()); generate_rsakey(lhost); if(debug_level >= DEBUG_LEVEL1) { printf("local id %d \n",localid); } next_req_id = rand() % 0xffff; /* Create an empty list for the clients */ clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy, p_client_free, 1); ERROR_GOTO(clients == NULL, "Error creating clients list.", done); /* Create and empty list for the connecting clients */ conn_clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy, p_client_free, 1); ERROR_GOTO(conn_clients == NULL, "Error creating conn_clients list.", done); relay_clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy, p_client_free, 1); ERROR_GOTO(relay_clients == NULL, "Error creating clients list.", done); /* Create a TCP server socket to listen for incoming connections */ tcp_serv = sock_create(lhost, lport, ipver, SOCK_TYPE_TCP, 1, 1); ERROR_GOTO(tcp_serv == NULL, "Error creating TCP socket.", done); udp_serv = sock_create(lhost, rport,ipver, SOCK_TYPE_UDP, 1, 1); ERROR_GOTO(udp_serv == NULL, "Error creating TCP socket.", done); if(debug_level >= DEBUG_LEVEL1) { printf("Listening on TCP %s,UDP %s \n", sock_get_str(tcp_serv, addrstr, sizeof(addrstr)),sock_get_str(udp_serv, taddrstr, sizeof(taddrstr))); } next_sock = sock_create(phost, pport, ipver, SOCK_TYPE_UDP, 0, 1); msg_send_req(next_sock,lhost,rport,0,localid); sock_free(next_sock); next_sock = NULL; FD_ZERO(&client_fds); /* Initialize all the timers */ timerclear(&timeout); check_interval.tv_sec = 0; check_interval.tv_usec = 500000; gettimeofday(&check_time, NULL); while(running) { if(!timerisset(&timeout)) timeout.tv_usec = 50000; read_fds = client_fds; FD_SET(SOCK_FD(tcp_serv), &read_fds); FD_SET(SOCK_FD(udp_serv), &read_fds); ret = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout); PERROR_GOTO(ret < 0, "select", done); num_fds = ret; gettimeofday(&curr_time, NULL); /* Go through all the clients and check if didn't get an ACK for sent data during the timeout period */ if(timercmp(&curr_time, &check_time, >)) { for(i = 0; i < LIST_LEN(clients); i++) { client = list_get_at(clients, i); ret = client_check_and_resend(client, curr_time); if(ret == -2) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; continue; } ret = client_check_and_send_keepalive(client, curr_time); if(ret == -2) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; } } timeradd(&curr_time, &check_interval, &check_time); } if(num_fds == 0) continue; /* Check if pending TCP connection to accept and create a new client and UDP connection if one is ready */ if(FD_ISSET(SOCK_FD(tcp_serv), &read_fds)) { tcp_sock = sock_accept(tcp_serv); if(tcp_sock == NULL) continue; if(SelectMethod(tcp_sock->fd)==-1) { if(debug_level >= DEBUG_LEVEL1) printf("socks version error\n"); return-1; } rhost=ParseCommand(tcp_sock->fd); if (0<LIST_LEN(relay_clients)) { tunnel = list_get_at(relay_clients, 0); udp_sock =sock_copy(CLIENT_TCP_SOCK(tunnel)); SOCK_FD(udp_sock)=socket(AF_INET, SOCK_DGRAM, 0); } if(udp_sock == NULL) { sock_close(tcp_sock); sock_free(tcp_sock); continue; } client = client_create(next_req_id++, localid, tcp_sock, udp_sock, 1); memcpy(client->rsakey,tunnel->rsakey,strlen(tunnel->rsakey)); printf("expid rsakey is %s",client->rsakey); if(debug_level >= DEBUG_LEVEL1) printf("create client id %d \n",CLIENT_ID(client)); if(!client || !tcp_sock || !udp_sock) { if(tcp_sock) sock_close(tcp_sock); if(udp_sock) sock_close(udp_sock); } else { client2 = list_add(conn_clients, client, 1); client_free(client); client = NULL; if(debug_level >= DEBUG_LEVEL1) { sock_get_str(CLIENT_TCP_SOCK(client2), addrstr, sizeof(addrstr)); printf("tunnel(%d): local %s ",client2->sourceid, addrstr); sock_get_str(CLIENT_UDP_SOCK(client2), addrstr, sizeof(addrstr)); printf("to %s \n",addrstr); } client_send_hello(client2,rhost,CLIENT_ID(client2)); client_add_tcp_fd_to_set(client2, &client_fds); //client_add_udp_fd_to_set(client2, &client_fds); } sock_free(tcp_sock); sock_free(udp_sock); tcp_sock = NULL; udp_sock = NULL; num_fds--; } /* Check for UDP data */ if(FD_ISSET(SOCK_FD(udp_serv), &read_fds)) { //ret = client_recv_udp_msg(client, data, sizeof(data), // &tmp_id, &tmp_type, &tmp_len,&sourceid); ret = msg_recv_msg(udp_serv, data, sizeof(data), &tmp_id, &tmp_type, &tmp_len,&sourceid); if(debug_level >= DEBUG_LEVEL2) printf("recv msg from %d type %d %d bytes \n ",sourceid,tmp_type,tmp_len); if(ret == 0) ret = handle_message(tmp_id, tmp_type, data, tmp_len,sourceid,clients, conn_clients); /*if(ret < 0) { disconnect_and_remove_client(tmp_id, clients, &client_fds, 1); } */ } /* Check if data is ready from any of the clients */ for(i = 0; i < LIST_LEN(clients); i++) { client = list_get_at(clients, i); /* Check for TCP data */ if(num_fds > 0 && client_tcp_fd_isset(client, &read_fds)) { ret = client_recv_tcp_data(client); if(ret == -1) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; continue; } else if(ret == -2) { client_mark_to_disconnect(client); disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 0); } num_fds--; } /* send any TCP data that was ready */ ret = client_send_udp_data(client); if(ret < 0) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; } } /* Finally, send any udp data that's still in the queue */ for(i = 0; i < LIST_LEN(clients); i++) { client = list_get_at(clients, i); ret = client_send_udp_data(client); if(ret < 0 || client_ready_to_disconnect(client)) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; } } } done: if(debug_level >= DEBUG_LEVEL1) printf("Cleaning up...\n"); if(tcp_serv) { sock_close(tcp_serv); sock_free(tcp_serv); } if(udp_serv) { sock_close(udp_serv); sock_free(udp_serv); } if(clients) list_free(clients); if(conn_clients) list_free(conn_clients); if(debug_level >= DEBUG_LEVEL1) printf("Goodbye.\n"); return 0; }
int udpclient(int argc, char* argv[]) { char* lhost, *lport, *phost, *pport, *rhost, *rport; list_t* clients; list_t* conn_clients; client_t* client; client_t* client2; socket_t* tcp_serv = NULL; socket_t* tcp_sock = NULL; socket_t* udp_sock = NULL; char data[MSG_MAX_LEN]; char addrstr[ADDRSTRLEN]; char pport_s[6]; struct timeval curr_time; struct timeval check_time; struct timeval check_interval; struct timeval timeout; fd_set client_fds; fd_set read_fds; uint16_t tmp_id; uint8_t tmp_type; uint16_t tmp_len; uint16_t tmp_req_id; int num_fds; int ret; int i; int icmp_sock ; int timeexc = -1; struct sockaddr_in src, dest, rsrc; struct hostent* hp; uint32_t timeexc_ip; signal(SIGINT, &signal_handler); i = 0; if(index(argv[i], 58) || index(argv[i], 46)) lhost = argv[i++]; else lhost = NULL; lport = argv[i++]; phost = argv[i++]; if(index(argv[i], 58) || index(argv[i], 46)) { snprintf(pport_s, 5, "2222"); pport = pport_s; } else pport = argv[i++]; rhost = argv[i++]; rport = argv[i++]; /* Get info about localhost IP */ if(!lhost){ char szHostName[255]; gethostname(szHostName, 255); hp = gethostbyname(szHostName); }else{ hp = gethostbyname(lhost); } memset(&rsrc, 0, sizeof(struct sockaddr_in)); timeexc_ip = *(uint32_t*)hp->h_addr_list[0]; rsrc.sin_family = AF_INET; rsrc.sin_port = 0; rsrc.sin_addr.s_addr = timeexc_ip; /* IP of destination */ memset(&src, 0, sizeof(struct sockaddr_in)); hp = gethostbyname(phost); timeexc_ip = *(uint32_t*)hp->h_addr_list[0]; src.sin_family = AF_INET; src.sin_port = 0; src.sin_addr.s_addr = timeexc_ip; /* IP of where the fake packet (echo request) was going */ hp = gethostbyname("3.3.3.3"); memcpy(&dest.sin_addr, hp->h_addr, hp->h_length); inet_pton(AF_INET, "3.3.3.3", &(dest.sin_addr)); srand(time(NULL)); next_req_id = rand() % 0xffff; /* Create an empty list for the clients */ clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy, p_client_free); ERROR_GOTO(clients == NULL, "Error creating clients list.", done); /* Create and empty list for the connecting clients */ conn_clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy, p_client_free); ERROR_GOTO(conn_clients == NULL, "Error creating clients list.", done); /* Create a TCP server socket to listen for incoming connections */ tcp_serv = sock_create(lhost, lport, ipver, SOCK_TYPE_TCP, 1, 1); ERROR_GOTO(tcp_serv == NULL, "Error creating TCP socket.", done); if(debug_level >= DEBUG_LEVEL1) { printf("Listening on TCP %s\n", sock_get_str(tcp_serv, addrstr, sizeof(addrstr))); } FD_ZERO(&client_fds); /* Initialize all the timers */ timerclear(&timeout); check_interval.tv_sec = 0; check_interval.tv_usec = 500000; gettimeofday(&check_time, NULL); /* open raw socket */ create_icmp_socket(&icmp_sock); if(icmp_sock == -1) { printf("[main] can't open raw socket\n"); exit(1); } while(running) { if(!timerisset(&timeout)) timeout.tv_usec = 50000; if(++timeexc==100) { timeexc=0; /* Send ICMP TTL exceeded to penetrate remote NAT */ send_icmp(icmp_sock, &rsrc, &src, &dest, 0); } read_fds = client_fds; FD_SET(SOCK_FD(tcp_serv), &read_fds); ret = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout); PERROR_GOTO(ret < 0, "select", done); num_fds = ret; gettimeofday(&curr_time, NULL); /* Go through all the clients and check if didn't get an ACK for sent data during the timeout period */ if(timercmp(&curr_time, &check_time, >)) { for(i = 0; i < LIST_LEN(clients); i++) { client = list_get_at(clients, i); ret = client_check_and_resend(client, curr_time); if(ret == -2) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds); i--; continue; } ret = client_check_and_send_keepalive(client, curr_time); if(ret == -2) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds); i--; } } timeradd(&curr_time, &check_interval, &check_time); } if(num_fds == 0) continue; timeexc=0; /* Check if pending TCP connection to accept and create a new client and UDP connection if one is ready */ if(FD_ISSET(SOCK_FD(tcp_serv), &read_fds)) { tcp_sock = sock_accept(tcp_serv); udp_sock = sock_create(phost, pport, ipver, SOCK_TYPE_UDP, 0, 1); client = client_create(next_req_id++, tcp_sock, udp_sock, 1); if(!client || !tcp_sock || !udp_sock) { if(tcp_sock) sock_close(tcp_sock); if(udp_sock) sock_close(udp_sock); } else { client2 = list_add(conn_clients, client); client_free(client); client = NULL; client_send_hello(client2, rhost, rport, CLIENT_ID(client2)); client_add_tcp_fd_to_set(client2, &client_fds); client_add_udp_fd_to_set(client2, &client_fds); } sock_free(tcp_sock); sock_free(udp_sock); tcp_sock = NULL; udp_sock = NULL; num_fds--; } /* Check for pending handshakes from UDP connection */ for(i = 0; i < LIST_LEN(conn_clients) && num_fds > 0; i++) { client = list_get_at(conn_clients, i); if(client_udp_fd_isset(client, &read_fds)) { num_fds--; tmp_req_id = CLIENT_ID(client); ret = client_recv_udp_msg(client, data, sizeof(data), &tmp_id, &tmp_type, &tmp_len); if(ret == 0) ret = handle_message(client, tmp_id, tmp_type, data, tmp_len); if(ret < 0) { disconnect_and_remove_client(tmp_req_id, conn_clients, &client_fds); i--; } else { client = list_add(clients, client); list_delete_at(conn_clients, i); client_remove_udp_fd_from_set(client, &read_fds); i--; } } } /* Check if data is ready from any of the clients */ for(i = 0; i < LIST_LEN(clients) && num_fds > 0; i++) { client = list_get_at(clients, i); /* Check for UDP data */ if(client_udp_fd_isset(client, &read_fds)) { num_fds--; ret = client_recv_udp_msg(client, data, sizeof(data), &tmp_id, &tmp_type, &tmp_len); if(ret == 0) ret = handle_message(client, tmp_id, tmp_type, data, tmp_len); if(ret < 0) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds); i--; continue; /* Don't go to check the TCP connection */ } } /* Check for TCP data */ if(client_tcp_fd_isset(client, &read_fds)) { num_fds--; ret = client_recv_tcp_data(client); if(ret == 0) ret = client_send_udp_data(client); #if 0 /* if udptunnel is taking up 100% of cpu, try including this */ else if(ret == 1) #ifdef _WIN32 _sleep(1); #else usleep(1000); /* Quick hack so doesn't use 100% of CPU if data wasn't ready yet (waiting for ack) */ #endif /*WIN32*/ #endif /*0*/ if(ret < 0) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds); i--; } } } } done: if(debug_level >= DEBUG_LEVEL1) printf("Cleaning up...\n"); if(tcp_serv) { sock_close(tcp_serv); sock_free(tcp_serv); } if(udp_sock) { sock_close(udp_sock); sock_free(udp_sock); } if(clients) list_free(clients); if(debug_level >= DEBUG_LEVEL1) printf("Goodbye.\n"); return 0; }