/** Initialize the firewall rules
 */
int
fw_init(void)
{
    int result = 0;
    int new_fw_state;
    t_client *client = NULL;

    if (!init_icmp_socket()) {
        return 0;
    }

    debug(LOG_INFO, "Initializing Firewall");
    result = iptables_fw_init();

    if (restart_orig_pid) {
        debug(LOG_INFO, "Restoring firewall rules for clients inherited from parent");
        LOCK_CLIENT_LIST();
        client = client_get_first_client();
        while (client) {
            new_fw_state = client->fw_connection_state;
            client->fw_connection_state = FW_MARK_NONE;
            fw_allow(client, new_fw_state);
            client = client->next;
        }
        UNLOCK_CLIENT_LIST();
    }

    return result;
}
int
main(int argc, char **argv) {
    int opt, sockfd;
    int background_flag = 1;
    int if_index = 0;
    fd_set rfds;
    struct timeval timeout;

    while ((opt = getopt(argc, argv, "fi:")) != -1) {
        switch (opt) {
            case 'f': /* foreground */
                background_flag = 0;
                break;
            case 'i':
                if_index = if_nametoindex(optarg);
                break;
            default: 
                usage();
                exit(EXIT_FAILURE);
        }
    }

    openlog("routeradv_listend", LOG_CONS|LOG_PERROR, LOG_DAEMON);

    sockfd = init_icmp_socket(if_index);
    if (sockfd < 0)
        return 1;
    
    if (background_flag)
        daemonize(sockfd);

    init_routers();

    for (;;) {
        FD_ZERO(&rfds);
        FD_SET(sockfd, &rfds);

        memset(&timeout, 0, sizeof(timeout));
        timeout.tv_sec = next_timeout();

        if (select(sockfd + 1, &rfds, NULL, NULL, &timeout) < 0) {
            /* select() might have failed because we received a signal, so we need to check */
            if (errno != EINTR) {
                syslog(LOG_CRIT, "select: %s", strerror(errno));
                return 1;
            }
            /* handle signals */
            continue; /* our file descriptor sets are undefined, so select again */
        }

        if (FD_ISSET (sockfd, &rfds))
            recv_icmp_msg(sockfd);

        handle_routers();
    }

    return 0;
}
Example #3
0
int binary_search(SOCKADDR_IN *dst, int timeout, RouteInfo *rinfo)
{
	
	int ttl=0, high=32, low=1, iterations=MAX_ITERATIONS, retries = 0;
	ULONG start_test_timestamp = GetTickCount();
	SOCKET sr;
	
	sr = init_icmp_socket();

	rinfo->cnt_packet_waste=0;
	strcpy(rinfo->path, UNDEFINED_PATH);
	rinfo->resp_ttl=UNDEFINED_TTL;
	rinfo->hopdist = UNDEFINED_TTL;

	// counting iterations is just to make sure 
	// no one is fooling us into an infinite loop
	while (iterations--) 
	{
		if (!ttl) ttl = STARTING_TTL;	// this is the first time ttl is set.
										// since most sites are closer than 32, we start with it.
		else ttl = (high+low)/2;

		switch (udping(sr, dst, 0, timeout, &rinfo->rtt,
						&rinfo->cnt_packet_waste, (unsigned short)ttl))
		{
		case -1: // too short
			low = ttl+1;
			break;
		case 1: // exact or too long
			if (high == ttl || (ttl+low)/2 == ttl) // exact!
			{
				rinfo->time_waste_on_test = GetTickCount()-start_test_timestamp;
				rinfo->hopdist = ttl;
				closesocket(sr);
				return 1;
			}
			high = ttl; // too long...
			break;
		case 0: // timeout
			if (ttl < high && retries != NUMBER_OF_RETRIES) // if possible, let's give it another chance.
			{
				high--;
				retries++;
				break;
			}
			rinfo->time_waste_on_test = GetTickCount()-start_test_timestamp;
			closesocket(sr);
			return 0;
		}
	}
	rinfo->time_waste_on_test = GetTickCount()-start_test_timestamp;
	closesocket(sr);
	return 0;
}
Example #4
0
int copied_ttl(SOCKADDR_IN *dst, unsigned int timeout, RouteInfo *rinfo)
{
	SOCKET sr;
	SOCKADDR_IN from;
	int icmp_type, delta, is_packet_recieved, copiedttl;
	unsigned short seq_sent, seq_resp;
	ULONG start_test_timestamp = GetTickCount();

	sr = init_icmp_socket();
	
	strcpy(rinfo->path, UNDEFINED_PATH);
	rinfo->resp_ttl = UNDEFINED_TTL;
	rinfo->cnt_packet_waste = 0;
	seq_sent = INITIAL_SEQ;

	while(GetTickCount()-start_test_timestamp < timeout*1000)
	{
		ULONG start_packet_timestamp = GetTickCount();
		
		send_udp_packet(dst, MAX_TTL, seq_sent);
		
		rinfo->cnt_packet_waste++;

		is_packet_recieved = wait_for_icmp(sr, &seq_resp, &icmp_type, &from, &copiedttl, timeout);
		delta = GetTickCount()-start_packet_timestamp;
		if (!is_packet_recieved)		//we got no reply
		{					
		//	fprintf(stderr, "%3d  Request timed out\t", MAX_TTL);
			break;
		}		
		if(seq_sent == seq_resp)		//check if this is our ICMP packet
		{
			if (icmp_type == ICMP_DEST_UNREACH)
			{
				rinfo->time_waste_on_test = GetTickCount() - start_test_timestamp;
				rinfo->rtt = delta;
				rinfo->hopdist = MAX_TTL+1-copiedttl;
				closesocket(sr);
				return 1;
			}
		}
		//it was not a response to our packet. send it again		
	}

	closesocket(sr);
	return 0;
}
Example #5
0
unsigned int __stdcall ping_thread_entry(void *data)
#endif
{
    PingThreadData *pdata = (PingThreadData *)data;
    
    int maxfd, ret;
    fd_set all_rset, rset;
    struct timeval to;

    I3ServerList *list = pdata->list;
    char *url = pdata->url;
    uint64_t *ping_start_time = pdata->ping_start_time;
       
    int num_pings;
    I3ServerListNode *next_to_ping;
    uint64_t last_ping_time, curr_time;
    uint64_t last_add_new_i3servers, last_update_serverlist;
 
    FD_ZERO(&all_rset);
    FD_ZERO(&rset);

    /* socket init */
#ifdef ICMP_PING
    if (init_icmp_socket(&ping_sock) == -1)
	abort();
#else
    if (init_udp_socket(&ping_sock) == -1)
	abort();
#endif
    FD_SET(ping_sock, &all_rset);
    maxfd = ping_sock + 1;
    
    /* initial populate the list of i3 servers */
    update_i3_server_list(url, list, &next_to_ping);

    /* determine coordinates */
    init_coordinates(list);

    /* add some close-by servers from the list based on coordinates */
    change_ping_list(list, &next_to_ping, 1);
       
    /* eternal loop */
    last_ping_time = last_add_new_i3servers = last_update_serverlist = wall_time();
    set_status(ping_start_time, last_ping_time);
    for (;;) {
		rset = all_rset;
        to.tv_sec = 0; to.tv_usec = 10000;
        if ((ret = select(maxfd, &rset, NULL, NULL, &to)) < 0) {
            if (errno == EINTR)
                continue;
            else {
                perror("select");
                abort();
            }
        }

		/* message received on icmp socket */
		if (FD_ISSET(ping_sock, &rset)) {
			uint32_t addr; uint16_t port, seq; uint64_t rtt;
#ifdef ICMP_PING
			if (recv_echo_reply(ping_sock, &addr, &seq, &rtt)) {
#else
			if (recv_i3_echo_reply(ping_sock, &addr, &port, &seq, &rtt)) {
#endif
				update_ping_information(list, addr, seq, rtt);
			}
		}

		/* need to ping */
		curr_time = wall_time();
		if (list->num_ping_list > 0) {
			char status = get_status(ping_start_time, curr_time);
			num_pings = (curr_time - last_ping_time)/
				(period_ping[status]/list->num_ping_list);
			if (num_pings > 0) {
				if (NULL == next_to_ping) {
					I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, 
							"No servers to ping. Aborting\n");
				}
				send_npings(ping_sock, list, &next_to_ping, num_pings);
				last_ping_time = curr_time;
			}
		}
	
		/* change the list of i3 servers */
		if (curr_time - last_add_new_i3servers >
					period_pick_new_server[get_status(ping_start_time, curr_time)]) {
			/* testing just the best server */
			uint32_t best_addr; uint16_t best_port; uint64_t best_rtt;
			struct in_addr ia;
			int required_k = 1;
			int ret = get_top_k(list, required_k, &best_addr, &best_port, &best_rtt);
			
			if (ret != required_k) {
				// We couldn't find the request k top nodes.

				I3_PRINT_INFO0 (
						I3_INFO_LEVEL_WARNING,
						"I3 Ping Thread: Unable to obtain top k nodes.\n"
						);
				// Dilip: Feb 20, 2006.  I don't think the following works.
				// TODO: Start
				// We set the last_add_new_servers to fool the thread
				// to wait for some time before trying again to get
				// the top k nodes.
				//last_add_new_i3servers = curr_time;
				// TODO: End

				// Sleep for some time before trying again.
#				if defined (_WIN32)
					Sleep ( 25 ); // 25 milliseconds
#				else
					usleep(25 * 1000); // 25 milliseconds
#				endif				
				continue;
			}

			ia.s_addr = htonl(best_addr);
			I3_PRINT_DEBUG3(I3_INFO_LEVEL_MINIMAL,
					"Best node: %s:%d with RTT %Ld\n", 
					inet_ntoa(ia), best_port, best_rtt
					);
	    
			I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_VERBOSE, "Adding new servers to list\n");
			change_ping_list(list, &next_to_ping, 0);
			last_add_new_i3servers = curr_time;
		}
	
		/* update (wget) i3 server list */
		if (curr_time - last_update_serverlist > PERIOD_SERVERLIST_WGET) {
			I3_PRINT_DEBUG0(	I3_DEBUG_LEVEL_VERBOSE, 
								"Updating server list from server\n");
			update_i3_server_list(url, list, &next_to_ping);
			last_update_serverlist = curr_time;
		}
    }

#ifndef _WIN32
    pthread_exit(0);
#endif
    return 0;
}
Example #6
0
/* To determine the coordinates of the local node initially
 * Ping a subset of nodes and determine coordinates */
void init_coordinates(I3ServerList *list)
{
    int n = MIN(NUM_LANDMARKS_COORDINATE, list->num_newservers + list->num_ping_list);
    I3ServerListNode *node = list->list, *temp_node;
    uint64_t start_time = wall_time();
    Coordinates_RTT coord_rtt[NUM_LANDMARKS_COORDINATE];
    int num_landmarks = 0; int started_full_list = 0;
    struct in_addr ia;
    nw_skt_t tmp_ping_sock;

#ifdef ICMP_PING
    if (init_icmp_socket(&tmp_ping_sock) == -1)
	abort();
#else
    if (init_udp_socket(&tmp_ping_sock) == -1)
	abort();
#endif

    // wait for responses and accumulate
    // cut and pasted from below
    while ((wall_time() - start_time < COORD_INIT_PING_WAIT_TIME) && 
	    (num_landmarks < n)) {
	fd_set rset;
	struct timeval to;
	int ret;

	FD_ZERO(&rset);

	if (!node && !started_full_list) {
	    node = list-> full_list;
	    started_full_list = 1;
	}
	
	if (node) {
	    ia.s_addr = htonl(node->addr);
	    I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE,
		    "Sending ICMP echo request to %s\n", inet_ntoa(ia));
#ifdef ICMP_PING
	    send_echo_request(tmp_ping_sock, node->addr, 0);
#else
	    i3_echo_request(tmp_ping_sock, node->addr, node->port, 0);
#endif
	    node = node->next_list;
	}

	FD_SET(tmp_ping_sock, &rset);
        to.tv_sec = 0; to.tv_usec = 200000ULL;
        if ((ret = select(tmp_ping_sock+1, &rset, NULL, NULL, &to)) < 0) {
	    int err = nw_error();
            if (err == EINTR)
                continue;
            else {
                perror("select");
                abort();
            }
        }

	// message received on icmp socket
	if (FD_ISSET(tmp_ping_sock, &rset)) {
	    uint32_t addr; uint16_t port, seq; uint64_t rtt;
#ifdef ICMP_PING
	    if (recv_echo_reply(tmp_ping_sock, &addr, &seq, &rtt)) {
#else
	    if (recv_i3_echo_reply(tmp_ping_sock, &addr, &port, &seq, &rtt)) {
#endif
		temp_node = lookup_i3server(list, addr);
		assert(NULL != temp_node);

		coord_rtt[num_landmarks].coord = temp_node->coord;
		coord_rtt[num_landmarks].rtt = rtt;
		num_landmarks++;

		ia.s_addr = htonl(addr);
		I3_PRINT_DEBUG4(I3_DEBUG_LEVEL_VERBOSE,
			"Node: %s Coordinate: %.1f:%.1f RTT: %Ld\n",
			inet_ntoa(ia), temp_node->coord.latitude,
			temp_node->coord.longitude, rtt);
	    }
	}
    }
    nw_close(tmp_ping_sock);

    // compute own coordinate
    compute_coordinates(num_landmarks, coord_rtt);
}

/* Update the coordinates of a node using ping information */
void update_coordinate(I3ServerList *list, I3ServerListNode *next_to_ping)
{
    Coordinates_RTT coord_rtt[NUM_LANDMARKS_COORDINATE];
    int count, num_landmarks = 0;
    I3ServerListNode *node;

    // n1 and n2: number of landmarks from ping_list and rest in
    // proportion to the number of nodes in those lists
    int i, n = MIN(NUM_LANDMARKS_COORDINATE, 
	    list->num_newservers + list->num_ping_list);
    int n1 = ((float)list->num_ping_list/
	    (list->num_newservers + list->num_ping_list)) * n;
    int n2 = n-n1;

    // add from ping list
    count = 0;
    for (i = 0, node = list->list; 
	    i < list->num_ping_list, count < n1;
	    node = node->next_list, ++i) {
	if (node->n > 0) {
	    coord_rtt[count].rtt = get_rtt_node(node);
	    coord_rtt[count].coord = node->coord;
	    count++;
	}
    }
    num_landmarks = count;

    // add from rest
    count = 0;
    for (i = 0, node = list->full_list; 
	    i < list->num_newservers, count < n2; 
	    node = node->next_list, ++i) {
	if (node->n > 0) {
	    coord_rtt[num_landmarks + count].rtt = get_rtt_node(node);
	    coord_rtt[num_landmarks + count].coord = node->coord;
	    count++;
	}
    }
    num_landmarks += count;

    // recompute coordinates
    compute_coordinates(num_landmarks, coord_rtt);

    // repopulate ping list afresh
    change_ping_list(list, &next_to_ping, 1);
}