bool icmp_base::send_icmp(const interface *intf, const in6_addr &dst, int rta, icmp6_hdr *hdr, uint16_t len) const { if (IN6_IS_ADDR_LINKLOCAL(&dst) || IN6_IS_ADDR_MC_LINKLOCAL(&dst)) return send_icmp(intf, *intf->linklocal(), dst, rta, hdr, len); else { if (intf->globals().empty()) { if (g_mrd->should_log(DEBUG)) { g_mrd->log().xprintf( "[ICMPv6] Failed to send message to " "%{addr}, no global address.\n", dst); } return false; } return send_icmp(intf, *intf->globals().begin(), dst, rta, hdr, len); } }
bool icmp_base::send_icmp(const in6_addr &dst, icmp6_hdr *hdr, uint16_t len) const { interface *intf = g_mrd->rib().path_towards(dst); if (!intf) return false; return send_icmp(intf, dst, hdr, len); }
int main(int argc, char *argv[]) { int c; u_long src_ip, dst_ip; char errbuf[256]; char *device = NULL; struct libnet_link_int *l; printf("link layer ICMP packet building/writing test\n"); src_ip = 0; dst_ip = 0; while ((c = getopt(argc, argv, "i:d:s:")) != EOF) { switch (c) { case 'd': if (!(dst_ip = libnet_name_resolve(optarg, 1))) { fprintf(stderr, "Bad destination IP address: %s\n", optarg); exit(1); } break; case 'i': device = optarg; break; case 's': if (!(src_ip = libnet_name_resolve(optarg, 1))) { fprintf(stderr, "Bad source IP address: %s\n", optarg); exit(1); } break; default: exit(EXIT_FAILURE); } } if (!src_ip || !dst_ip || !device) { usage(argv[0]); exit(EXIT_FAILURE); } if ((l = libnet_open_link_interface(device, errbuf)) == NULL) { fprintf(stderr, "libnet_open_link_interface: %s\n", errbuf); exit(EXIT_FAILURE); } c = send_icmp(l, device, src_ip, dst_ip); return (c == -1 ? EXIT_FAILURE : EXIT_SUCCESS); }
int main(int argc, char *argv[]) { char *device, *proto; int opt=0; while ((opt = getopt(argc, argv, "hp:i:")) != -1) { switch (opt) { case 'p': proto = optarg; break; case 'h': usage(argv[0]); exit(EXIT_SUCCESS); case 'i': device = optarg; break; default: usage(argv[0]); exit(EXIT_FAILURE); } } printf("argc=%d | optind=%d\n", argc, optind); if (optind != 5) { usage(argv[0]); exit(EXIT_FAILURE); } /* decide which protocol to use */ if (strcmp(proto, "arp") == 0) { printf("Packet shaping using libnet 1.1: ARP [LINK IPv4]\n"); send_arp(device); /* Use ARP protocol */ } else if (strcmp(proto, "icmp") == 0) { printf("Packet shaping using libnet 1.1: ICMPv4 [LINK IPv4]\n"); send_icmp(device); /* Use ICMPv4 protocol */ } else { printf("Unknown protocol, please specify either arp, icmp.\n\n"); exit(EXIT_FAILURE); } return (EXIT_SUCCESS); }
void handle_arpreq(struct sr_instance* sr, struct sr_arpreq *cache_req_ptr) { char *iface_name = cache_req_ptr->packets->iface; struct sr_if *interface = sr_get_interface(sr, iface_name); /*Only broadcast if this hasn't been sent out before: *Otherwise, our packet has been added to the end of the * request's linkedlist in the cache: do nothing*/ if (difftime(time(0), cache_req_ptr->sent) > 1.0) { if (cache_req_ptr->times_sent >= 5) { struct sr_packet *req_pkt_ptr = cache_req_ptr->packets; for (; req_pkt_ptr; req_pkt_ptr = req_pkt_ptr->next) { send_icmp(sr, req_pkt_ptr->buf, req_pkt_ptr->len, interface, dest_host_unreach_type, dest_host_unreach_code); } sr_arpreq_destroy(&(sr->cache), cache_req_ptr); } else { /*Create space for the request*/ uint8_t* eth_pkt_buf = (uint8_t *) malloc(sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t)); uint8_t* arp_pkt_buf; /*Pointers to where different header structs start in the packet*/ sr_ethernet_hdr_t* req_eth_header = (sr_ethernet_hdr_t*) eth_pkt_buf; /* Allocate mem for reply packet buffer */ /* Copy addresses and type into the ethernet header */ uint8_t broadcast_addr[ETHER_ADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; memcpy(req_eth_header->ether_dhost, broadcast_addr, ETHER_ADDR_LEN); memcpy(req_eth_header->ether_shost, interface->addr, ETHER_ADDR_LEN); req_eth_header->ether_type = ethertype_arp; /* Convert to network byte ordering */ hton_eth_hdr(&req_eth_header); /* Get the Arp Buffer and Build the Arp packet*/ arp_pkt_buf = eth_pkt_buf + sizeof(sr_ethernet_hdr_t); sr_create_arp_req_packet(arp_pkt_buf, cache_req_ptr, interface); /* Send the ARP request packet */ sr_send_packet(sr, eth_pkt_buf, sizeof(sr_ethernet_hdr_t) + sizeof(sr_arp_hdr_t), interface->name); cache_req_ptr->sent = time(0); cache_req_ptr->times_sent++; free(eth_pkt_buf); } } }
int command_main(int argc, char *argv[]) { char *p; int size; long prev_time; send_use(SERIAL_DEFAULT_DEVICE); while (1) { send_write("command> "); /* プロンプト表示 */ /* コンソールからの受信文字列を受け取る */ kz_recv(MSGBOX_ID_CONSINPUT, &size, &p); if (p == NULL) { send_write("expired.\n"); continue; } p[size] = '\0'; if (!strncmp(p, "echo", 4)) { /* echoコマンド */ send_write(p + 4); /* echoに続く文字列を出力する */ send_write("\n"); } else if (!strncmp(p, "timer", 5)) { /* timerコマンド */ send_write("timer start.\n"); send_start(1000); } else if (!strncmp(p, "ping", 4)) { /* pingコマンド */ send_write("ping start.\n"); send_icmp(); } else if (!strncmp(p, "tftp", 4)) { /* tftpコマンド */ send_write("tftp start.\n"); send_tftp(); } else if (!strncmp(p, "debug", 5)) { /* デバッガ起動 */ set_debug_traps(); force_break(); } else if (!strncmp(p, "call", 4)) { /* ダミー関数の呼び出し */ send_write(func(p + 4)); } else if (!strncmp(p, "get", 3)) { /* get */ prev_time = get_time(); putxval(prev_time, 8); puts("\n"); } else { send_write("unknown.\n"); } kz_kmfree(p); } 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; }
/*Returns 0 on success and error code on fail*/ int sr_handleip(struct sr_instance* sr, uint8_t* packet, unsigned int len, struct sr_if* in_f, uint8_t** ethernet_data_addr){ sr_ip_hdr_t* ip_header_buffer = (sr_ip_hdr_t*) *ethernet_data_addr; /* Get headers from packet */ /*sr_ethernet_hdr_t* eth_hdr = (sr_ethernet_hdr_t*) packet; uint8_t * ip_pkt_buf = packet + sizeof(sr_ethernet_hdr_t); sr_ip_hdr_t* ip_hdr = (sr_ip_hdr_t*) (packet + sizeof(sr_ethernet_hdr_t)); */ uint8_t * icmp_pkt_buf = packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t); sr_icmp_hdr_t* icmp_hdr = (sr_icmp_hdr_t*) icmp_pkt_buf; struct sr_if* ret_if; /* return interface */ if (check_ip_sum(ip_header_buffer) == 0) { /*Pass Checksum*/ printf("Checksum Pass\n"); } else { /*Fail Checksum*/ printf("Checksum Fail\n"); return -1; } /*If the TTL went to 0*/ if (decrement_ttl(ip_header_buffer) == -1) { /*Send ICMP with the proper TTL decrease type and icmp code*/ printf("TTL reached 0\n"); send_icmp(sr, packet, len, in_f, time_exceed_type, time_exceed_code); return -1; } /*Check if the IP packet is for us and not a echo request*/ ret_if = sr_get_interface_from_ip(sr, ip_header_buffer->ip_dst); if(ret_if && !(ip_header_buffer->ip_p == ip_protocol_icmp && icmp_hdr->icmp_type == echo_req_type && icmp_hdr->icmp_code == echo_req_code)) { /* The IP packet is FOR US */ printf("FOR US, NOT ECHO REQ"); /* Check if it is an echo request */ if (ip_header_buffer->ip_p == ip_protocol_tcp || ip_header_buffer->ip_p == ip_protocol_udp) { /* It is TCP/UDP send ICMP port unreachable SEND: an ICMP port unreachable to sending host*/ send_icmp(sr, packet, len, in_f, port_unreach_type, port_unreach_code); } else { ; /* According to the Assignment: IGNORE THE PACKET*/ } } else { /*If it's not in the routing table, send ICMP net unreachable*/ struct sr_rt * routing_node; uint32_t ip_dest; /*If it's for us, we want to send back to the source, so check for the source in the routing table*/ if (ret_if) { /* The IP packet is FOR US */ printf("FOR US\n"); ip_dest = ip_header_buffer->ip_src; } /*If not for us, we want to keep forwarding to the destination so check for that in the routing table*/ else { /* The IP packet is NOT FOR US */ printf("NOT FOR US\n"); ip_dest = ip_header_buffer->ip_dst; } if ((routing_node = check_routing_table(sr, ip_dest)) == NULL) { printf("NOT in routing table\n"); send_icmp(sr, packet, len, in_f, dest_net_unreach_type, dest_net_unreach_code); } else { printf("In routing table\n"); /*Got the routing table node in routing_node */ /*Next hop IP address is in gateway *Look it up in arpcache_lookup to see if we know the MAC address */ uint32_t nexthopIP = routing_node->gw.s_addr; struct sr_arpentry *arp_dest = sr_arpcache_lookup(&(sr->cache), nexthopIP); struct sr_if* nexthopInterface = sr_get_interface(sr, routing_node->interface); /*Create an ethernet header in front of the packet to forward regardless of whether or not we've found the next hop IP: need it in both cases*/ /*Allocate space for ethernet header and packet, copy in contents of packet*/ uint8_t* eth_header_packet = malloc(len); uint8_t* ip_header = eth_header_packet + sizeof(sr_ethernet_hdr_t); uint8_t* only_packet = eth_header_packet + sizeof(sr_ethernet_hdr_t) + sizeof(sr_ip_hdr_t); memcpy(ip_header, ip_header_buffer, sizeof(sr_ip_hdr_t)); memcpy(only_packet, (packet+sizeof(sr_ethernet_hdr_t)+sizeof(sr_ip_hdr_t)), len-sizeof(sr_ethernet_hdr_t)-sizeof(sr_ip_hdr_t)); /*Save it in struct form*/ sr_ethernet_hdr_t* packet_to_forward = (sr_ethernet_hdr_t*)eth_header_packet; /*Now set the actual ethernet header for the packet*/ packet_to_forward->ether_type = htons(ethertype_ip); memcpy(packet_to_forward->ether_shost, nexthopInterface->addr, ETHER_ADDR_LEN); /*If NULL, send out the arp request*/ if(arp_dest == NULL){ printf("Not in arp cache: need to send an ARP request!\n"); broadcast_arp_req(sr, nexthopIP, packet_to_forward, len, routing_node, nexthopInterface); } /*Otherwise just forward the packet to arp_dest's MAC address*/ else { /*It's for us, it must be an echo request*/ if (ret_if) { /*Doesn't have a code so just passing 0 as code*/ struct sr_if *interface = sr_get_interface(sr, routing_node->interface); send_icmp_echo_reply(sr, packet, len, interface, arp_dest->mac, echo_reply_type, 0); } else { printf("In arp cache: just forwarding the packet\n"); memcpy(packet_to_forward->ether_dhost, arp_dest->mac, ETHER_ADDR_LEN); sr_send_packet(sr, (uint8_t*)packet_to_forward, len, routing_node->interface); /*Free the arp_dest that sr_arpcache_lookup created*/ free(arp_dest); } } } } return 0; }
bool icmp_base::send_icmp(const interface *intf, const in6_addr &src, const in6_addr &to, icmp6_hdr *hdr, uint16_t len) const { return send_icmp(intf, src, to, -1, hdr, len); }
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; }