static void apply_hosts_file(jdns_dnsparams_t *a, const char *path) { int n; jdns_dnshostlist_t *list; list = read_hosts_file(path); for(n = 0; n < list->count; ++n) jdns_dnshostlist_append(a->hosts, list->item[n]); jdns_dnshostlist_delete(list); }
/* * Function: main * Purpose: * Comments: */ int main(int argc, char *argv[]) { int i; struct sigaction si_sa; int euid, ruid; struct host_entry *cursor; /* * first things first * if anything goes wrong anywhere, we want to be super careful to release * any file descriptor we have on /dev/lkm, and it probably makes sense to * shutdown the raw socket we have too. */ atexit(cleanup); /* * get the effective and the real user id's so we know if we are running * with elevated permissions or not */ euid = geteuid(); ruid = getuid(); /* check for the command line arguments */ if(check_options(argc,argv) == 0) { return -1; } /* * open the raw socket now. i used to have this further down closer to * where it was needed, but because you can't change the euid/uid to and * from root (unless you're the superuser) i can only do this once */ if(options & OPT_IPV4) { if(open_ipmp_sockets4() == 0) return -1; } else if(options & OPT_IPV6) { if(open_ipmp_sockets6() == 0) return -1; } else { if(open_ipmp_sockets4() == 0) return -1; if(open_ipmp_sockets6() == 0) return -1; } /* * revoke the permissions we requested as we only need them to open a raw * socket. this is to reduce the impact of any buffer overflow exploits * that may be present */ if(ruid != euid) { setreuid(ruid, ruid); } /* * we get the pid so we can identify incoming ipmp packets destined for * this instance of ipmp_ping */ pid = getpid(); /* * need to know about the addresses this host has */ learn_localaddresses(); /* * in FreeBSD, the actual ping is done by a kernel module that has a syscall * in it. the kernel module allows the protocol to get a timestamp as close * to when the mbuf is actually sent to ip_output as possible */ #if defined(__FreeBSD__) if((options & OPT_RAW) == 0) { i = get_syscall("ipmp_ping", &syscall_num); if(i != 0) { printerror(i, strerror, "could not get the syscall for ipmp_ping"); return -1; } } #endif /* * the -n option means that the user has supplied a list of hosts to * ping, so we read those entries and put them in an list of hosts with * details regarding each host. the task of putting hosts into the list * is handled by read_hosts_file * * if the -n option isnt specified, we create a list containing just the * one host to ping. this way, all the program logic can be used in a * multitude of situations. */ if(options & OPT_NLANR) { /* * if something went wrong parsing the file, we quit. */ if(read_hosts_file() == 0) { return -1; } } else { /* * if the user didnt specify a host to ping, we bail, telling them * why first... */ if(argc - optind != 1) { usage(0); return -1; } /* * if we can't add a host entry for the host supplied on the command line * tell the user that it couldnt be parse and cleanup */ if(add_host_entry(argv[optind], NULL) == 0) { return -1; } } /* * we now put some handlers into action so if the user ctrl-c's us we have * the opportunity to tell them what we found out first * also, if the user specified a timeout, put an alarm in for that so we * can bail when they tell us to... */ sigemptyset(&si_sa.sa_mask); si_sa.sa_flags = 0; si_sa.sa_handler = alarm_bells; if(sigaction(SIGINT, &si_sa, 0) == -1) { printerror(errno, strerror, "could not set sigaction for SIGINT"); return -1; } if(options & OPT_TIMEOUT) { if(sigaction(SIGALRM, &si_sa, 0) == -1) { printerror(errno, strerror, "could not set sigaction for SIGALRM"); return -1; } } /* * we loop for as long as we have not been told to finish up. * the finish_up loop will exit when * - there has been an alarm set that goes off * - a SIGINT is received (from e.g. Ctrl-C) * - we have got_all_response()'s * * this is not an expensive loop in terms of cpu cycles, as the * recv_echo_response will sleep if there is nothing to recv until we have * told it to stop blocking - typically one second or whatever the between * timeout is. * * the loop does two things: * - sends echo requests * - receives echo responses * * the loop sends packets, pausing for however long the timeout is set for * between packets. this pause is implemented in the recv_echo_response * function in a call to select(2). if we cannot send a request to one of * them, we bail, as this probably means the syscall could not be called. * * the loop recv's the response and associates the packet with a host_entry * we then parse that response for the host entry, and then check if we have * now got all the responses we are looking for. if we have, we exit the * loop by setting the finish_up flag */ sent_all_requests = 0; i = 0; cursor = head; while(finish_up == 0) { while(sent_all_requests == 0) { if(send_echo_request(cursor) != 0) { return -1; } cursor->tx++; if(cursor->tx == count) { cursor = cursor->next; if(cursor == NULL) { sent_all_requests = 1; alarm(timeout); break; } } if(wait_between > 0) { gettimeofday(&wait_between_tv, &tz); timeval_add(&wait_between_tv, wait_between); break; } } while(time_to_send_request() == 0 && finish_up == 0) { if(recv_echo_responses() > 0) { if(got_all_responses() == 1) { finish_up = 1; } } } } /* * if we have been given a list of hosts to ping, we have to print out which * hosts did not give us a reply */ if(options & OPT_NLANR) { show_loss(); } return 0; }