예제 #1
0
/*
 *  udp_exec_pkt: passes the received udp packet to pkt_exec().
 * `passed_argv' is a pointer to a udp_exec_pkt_argv struct 
 */
void *
udp_exec_pkt(void *passed_argv)
{
	struct udp_exec_pkt_argv argv;

	PACKET rpkt;
	const char *ntop;

	memcpy(&argv, passed_argv, sizeof(struct udp_exec_pkt_argv));
	memcpy(&rpkt, argv.recv_pkt, sizeof(PACKET));

	if (argv.flags & UDP_THREAD_FOR_EACH_PKT)
		pthread_mutex_unlock(&udp_exec_lock);

	/* Drop any packet we sent in broadcast */
	if (!memcmp(rpkt.from.data, me.cur_ip.data, MAX_IP_SZ)) {
		pkt_free(&rpkt, 0);
		return 0;
	}

	if (add_accept(rpkt.from, 1)) {
		ntop = inet_to_str(rpkt.from);
		debug(DBG_NORMAL, "ACPT: dropped UDP pkt from %s: "
			  "Accept table full.", ntop);
		return 0;
	}

	pkt_exec(rpkt, argv.acpt_idx);
	pkt_free(&rpkt, 0);

	return 0;
}
예제 #2
0
파일: inet_addr.c 프로젝트: Julia117/embox
const char * inet_ntop(int af, const void *addr, char *buff,
		socklen_t buff_sz) {
	int ret;

	switch (af) {
	default:
		ret = -EAFNOSUPPORT;
		break;
	case AF_INET:
		ret = inet_to_str((const struct in_addr *)addr, buff,
				buff_sz);
		break;
	case AF_INET6:
		ret = inet6_to_str((const struct in6_addr *)addr, buff,
				buff_sz);
		break;
	}

	if (ret != 0) {
		SET_ERRNO(-ret);
		return NULL;
	}

	return buff;
}
예제 #3
0
파일: gmap.c 프로젝트: Netsukuku/netsukuku
const char *
rnode_to_ipstr(u_int mapstart, u_int maprnode, inet_prefix ipstart)
{
	inet_prefix ip;

	rnodetoip(mapstart, maprnode, ipstart, &ip);

	return inet_to_str(ip);
}
예제 #4
0
파일: igs.c 프로젝트: Netsukuku/netsukuku
/*
 * internet_hosts_to_ip: replace the hostnames present in
 * `server_opt.inet_hosts' with IP strings. The IPs are obtained
 * with a normal DNS resolution. The hosts which cannot be resolved are
 * deleted from the `inet_hosts' array.
 */
void
internet_hosts_to_ip(void)
{
	int i;

	for (i = 0; i < server_opt.inet_hosts_counter; i++) {
		inet_prefix ip;

		if (andns_gethostbyname(server_opt.inet_hosts[i], &ip)) {
			error("Cannot resolve \"%s\". Check your netsukuku.conf",
				  server_opt.inet_hosts[i]);

			/* remove the hname from `inet_hosts' */
			xfree(server_opt.inet_hosts[i]);
			server_opt.inet_hosts[i] =
				server_opt.inet_hosts[server_opt.inet_hosts_counter - 1];
			server_opt.inet_hosts_counter--;
		} else {
			xfree(server_opt.inet_hosts[i]);
			server_opt.inet_hosts[i] = xstrdup(inet_to_str(ip));
		}
	}
}
예제 #5
0
void *
tcp_daemon(void *door)
{
	pthread_t thread;
	pthread_attr_t t_attr;

	PACKET rpkt;
	struct sockaddr_storage addr;
	socklen_t addrlen = sizeof addr;
	inet_prefix ip;

	fd_set fdset;
	int fd, ret, err, i;

	interface *ifs;
	int max_sk_idx, dev_sk[me.cur_ifs_n];

	u_short tcp_port = *(u_short *) door;
	const char *ntop;

	pthread_attr_init(&t_attr);
	pthread_attr_setdetachstate(&t_attr, PTHREAD_CREATE_DETACHED);

	debug(DBG_SOFT, "Preparing the tcp listening socket on port %d",
		  tcp_port);

	err = sockets_all_ifs(my_family, SOCK_STREAM, tcp_port, me.cur_ifs,
						  me.cur_ifs_n, dev_sk, &max_sk_idx);
	if (!err)
		return NULL;
	else if (err < 0)
		fatal("Creation of the %s daemon aborted. "
			  "Is there another ntkd running?", "tcp");

	pthread_mutex_init(&tcp_exec_lock, 0);

	for (i = 0; i < me.cur_ifs_n; i++) {
		if (!dev_sk[i])
			continue;
		/* 
		 * While we are accepting the connections we keep the socket non
		 * blocking.
		 */
		if (set_nonblock_sk(dev_sk[i])) {
			pthread_mutex_unlock(&tcp_daemon_lock);
			return NULL;
		}

		/* Shhh, it's listening... */
		if (listen(dev_sk[i], 5) == -1) {
			inet_close(&dev_sk[i]);
			pthread_mutex_unlock(&tcp_daemon_lock);
			return NULL;
		}
	}

	debug(DBG_NORMAL, "Tcp daemon on port %d up & running", tcp_port);
	pthread_mutex_unlock(&tcp_daemon_lock);
	for (;;) {
		FD_ZERO(&fdset);

		if (!me.cur_ifs_n) {
			/* All the devices have been removed while ntkd was
			 * running, sleep well */
			sleep(1);
			continue;
		}

		for (i = 0; i < me.cur_ifs_n; i++)
			if (dev_sk[i])
				FD_SET(dev_sk[i], &fdset);

		ret = select(dev_sk[max_sk_idx] + 1, &fdset, NULL, NULL, NULL);
		if (sigterm_timestamp)
			/* NetsukukuD has been closed */
			break;
		if (ret < 0 && errno != EINTR)
			error("daemon_tcp: select error: %s", strerror(errno));
		if (ret < 0)
			continue;

		for (i = 0; i < me.cur_ifs_n; i++) {
			ifs = &me.cur_ifs[i];
			if (!dev_sk[i])
				continue;

			if (!FD_ISSET(dev_sk[i], &fdset))
				continue;

			fd = accept(dev_sk[i], (struct sockaddr *) &addr, &addrlen);
			if (fd == -1) {
				if (errno != EINTR && errno != EWOULDBLOCK)
					error("daemon_tcp: accept(): %s", strerror(errno));
				continue;
			}

			setzero(&rpkt, sizeof(PACKET));
			pkt_addsk(&rpkt, my_family, fd, SKT_TCP);
			pkt_add_dev(&rpkt, ifs, 0);
			rpkt.flags = MSG_WAITALL;
			pkt_addport(&rpkt, tcp_port);

			ntop = 0;
			sockaddr_to_inet((struct sockaddr *) &addr, &ip, 0);
			pkt_addfrom(&rpkt, &ip);
			if (server_opt.dbg_lvl)
				ntop = inet_to_str(ip);

			if ((ret = add_accept(ip, 0))) {
				debug(DBG_NORMAL, "ACPT: drop connection with %s: "
					  "Accept table full.", ntop);

				/* Omg, we cannot take it anymore, go away: ACK_NEGATIVE */
				pkt_err(rpkt, ret, 1);
				inet_close(&fd);
				continue;
			} else {
				/* 
				 * Ok, the connection is good, send back the
				 * ACK_AFFERMATIVE.
				 */
				pkt_addto(&rpkt, &rpkt.from);
				send_rq(&rpkt, 0, ACK_AFFERMATIVE, 0, 0, 0, 0);
			}

			if (unset_nonblock_sk(fd))
				continue;

			pthread_mutex_lock(&tcp_exec_lock);
			err =
				pthread_create(&thread, &t_attr, tcp_recv_loop,
							   (void *) &rpkt);
			pthread_detach(thread);
			pthread_mutex_lock(&tcp_exec_lock);
			pthread_mutex_unlock(&tcp_exec_lock);
		}
	}
	return NULL;
}
예제 #6
0
파일: igs.c 프로젝트: Netsukuku/netsukuku
/*
 * init_internet_gateway_search:
 * Initialization of the igs.c code.
 */
void
init_internet_gateway_search(void)
{
	inet_prefix new_gw;
	char new_gw_dev[IFNAMSIZ];

	pthread_t ping_thread;
	pthread_attr_t t_attr;
	int i, ret, res, e;

	active_gws = 0;
	igw_multi_gw_disabled = 0;
	setzero(multigw_nh, sizeof(igw_nexthop) * MAX_MULTIPATH_ROUTES);

	/*
	 * Just return if we aren't in restricted mode or if the user doesn't
	 * want to use shared internet connections
	 */
	if (!restricted_mode || (!server_opt.use_shared_inet &&
							 !server_opt.share_internet))
		return;

	loginfo("Activating the Internet Gateway Search engine");

	init_igws(&me.igws, &me.igws_counter, GET_LEVELS(my_family));
	init_tunnels_ifs();

	/* delete all the old tunnels */
	del_all_tunnel_ifs(0, 0, 0, NTK_TUNL_PREFIX);

	/*
	 * Bring tunl0 up (just to test if the ipip module is loaded)
	 */
	loginfo("Checking if \"" DEFAULT_TUNL_IF "\" exists");
	if (tunnel_change(0, 0, 0, DEFAULT_TUNL_PREFIX, DEFAULT_TUNL_NUMBER) <
		0) {
		printf("Cannot read \"" DEFAULT_TUNL_IF "\". "
			   "Is the \"ipip\" kernel module loaded?\n"
			   "  If you don't care about using the shared internet "
			   "connections of the ntk nodes\n"
			   "  around you, disable the \"use_shared_inet\" option "
			   "in netsukuku.conf");
		del_resolv_conf("nameserver 127.0.0.1", "/etc/resolv.conf");
		exit(1);
	}
	ifs_del_all_name(me.cur_ifs, &me.cur_ifs_n, NTK_TUNL_PREFIX);
	ifs_del_all_name(me.cur_ifs, &me.cur_ifs_n, DEFAULT_TUNL_PREFIX);

	/*
	 * Delete old routing rules
	 */
	reset_igw_rules();

	/*
	 * Init netfilter
	 */
	res = mark_init(server_opt.share_internet);
	if (res) {
		error(err_str);
		error("Cannot set the netfilter rules needed for the multi-igw. "
			  "This feature will be disabled");
		igw_multi_gw_disabled = 1;
	}

	/*
	 * Check anomalies: from this point we initialize stuff only if we
	 * have an Inet connection
	 */
	if (!server_opt.inet_connection)
		return;
	if (!server_opt.inet_hosts)
		fatal("You didn't specified any Internet hosts in the "
			  "configuration file. What hosts should I ping?");

	/*
	 * If we are sharing our internet connection, activate the
	 * masquerading.
	 */
	if (server_opt.share_internet) {
		igw_exec_masquerade_sh(server_opt.ip_masq_script, 0);
		if (!server_opt.ip_masq_script)
			fatal("No masquerading script was configured!");
	};

	/*
	 * Get the default gateway route currently set in the kernel routing
	 * table
	 */
	setzero(&new_gw, sizeof(inet_prefix));
	ret = rt_get_default_gw(&new_gw, new_gw_dev);

	/*
	 * If there is no IP set in the route, fetch it at least from the
	 * device included in it.
	 */
	if (!new_gw.family && *new_gw_dev) {
		if (get_dev_ip(&new_gw, my_family, new_gw_dev) < 0)
			(*new_gw_dev) = 0;
	}

	if (ret < 0 || (!*new_gw_dev && !new_gw.family)) {
		/* Nothing useful has been found  */

		loginfo("The retrieval of the default gw from the kernel failed.");

		if (!server_opt.inet_gw.data[0])
			fatal("The default gw isn't set in the kernel and you "
				  "didn't specified it in netsukuku.conf. "
				  "Cannot continue!");
	} else if (!server_opt.inet_gw_dev ||
			   strncmp(new_gw_dev, server_opt.inet_gw_dev, IFNAMSIZ) ||
			   memcmp(new_gw.data, server_opt.inet_gw.data, MAX_IP_SZ)) {

		if (server_opt.inet_gw.data[0])
			loginfo("Your specified Internet gateway doesn't match with "
					"the one currently stored in the kernel routing table."
					"I'm going to use the kernel gateway: %s dev %s",
					inet_to_str(new_gw), new_gw_dev);

		if (!server_opt.inet_gw_dev)
			server_opt.inet_gw_dev = xstrdup(new_gw_dev);
		else
			strncpy(server_opt.inet_gw_dev, new_gw_dev, IFNAMSIZ);
		memcpy(&server_opt.inet_gw, &new_gw, sizeof(inet_prefix));

		/* Delete the default gw, we are replacing it */
		rt_delete_def_gw(0);
	}

	loginfo("Using \"%s dev %s\" as your first Internet gateway.",
			inet_to_str(server_opt.inet_gw), server_opt.inet_gw_dev);
	if (rt_replace_def_gw(server_opt.inet_gw_dev, server_opt.inet_gw, 0))
		fatal("Cannot set the default gw to %s %s",
			  inet_to_str(server_opt.inet_gw), server_opt.inet_gw_dev);
	active_gws++;

	/*
	 * Activate the anti-loop multi-igw shield
	 */
	if (server_opt.share_internet) {
		rule_add(0, 0, 0, 0, FWMARK_ALISHIELD, RTTABLE_ALISHIELD);
		if (rt_replace_def_gw(server_opt.inet_gw_dev, server_opt.inet_gw,
							  RTTABLE_ALISHIELD)) {
			error("Cannot set the default route in the ALISHIELD table. "
				  "Disabling the multi-inet_gw feature");
			igw_multi_gw_disabled = 1;
		}
	}


	/*
	 * Activate the traffic shaping for the `server_opt.inet_gw_dev'
	 * device
	 */
	if (server_opt.shape_internet)
		igw_exec_tcshaper_sh(server_opt.tc_shaper_script, 0,
							 server_opt.inet_gw_dev,
							 server_opt.my_upload_bw,
							 server_opt.my_dnload_bw);

	for (i = 0; i < me.cur_ifs_n; i++)
		if (!strcmp(me.cur_ifs[i].dev_name, server_opt.inet_gw_dev)) {
			for (e = 0; e < server_opt.ifs_n; e++)
				if (!strcmp(server_opt.ifs[i], server_opt.inet_gw_dev))
					fatal("You specified the \"%s\" interface"
						  " in the options, but this device is also"
						  " part of the primary Internet gw route."
						  " Don't include \"%s\" in the list of "
						  "interfaces utilised by the daemon",
						  server_opt.inet_gw_dev, server_opt.inet_gw_dev);

			loginfo("Deleting the \"%s\" interface from the device "
					"list since it is part of the primary Internet"
					" gw route.", me.cur_ifs[i].dev_name);

			ifs_del(me.cur_ifs, &me.cur_ifs_n, i);
			if (me.cur_ifs_n <= 0)
				fatal
					("The deleted interface cannot be used by NetsukukuD because it is part\n"
					 "  of your primary Internet gw route. You have to specify another\n"
					 "  interface with the -i option or you won't be able share your"
					 "  Internet connection");
		}

	loginfo("Launching the first ping to the Internet hosts");
	if (!server_opt.disable_andna)
		internet_hosts_to_ip();
	me.inet_connected = igw_check_inet_conn();
	if (me.inet_connected)
		loginfo("The Internet connection is up & running");
	else
		loginfo("The Internet connection appears to be down");
	if (!me.inet_connected && server_opt.share_internet)
		fatal("We are not connected to the Internet, but you want to "
			  "share your connection. Please check your options");

	debug(DBG_SOFT, "Evoking the Internet ping daemon.");
	pthread_attr_init(&t_attr);
	pthread_attr_setdetachstate(&t_attr, PTHREAD_CREATE_DETACHED);
	pthread_create(&ping_thread, &t_attr, igw_check_inet_conn_t, 0);
}
예제 #7
0
/*
 * radar_update_map
 *
 * it updates the int_map and the ext_map if any bnodes are found.
 * Note that the rnodes in the map are held in a different way. First of all the qspn
 * is not applied to them (we already know how to reach them ;) and they have only
 * one rnode... ME. So me.cur_node->r_node[x].r_node->r_node[0] == me.cur_node.
 * Gotcha?
 */
void
radar_update_map(void)
{
    struct qspn_buffer *qb;
    struct radar_queue *rq;
    ext_rnode_cache *erc;
    map_gnode *gnode = 0;
    map_node *node, *root_node;
    map_rnode rnn, *new_root_rnode;
    ext_rnode *e_rnode;

    int i, diff, rnode_pos;
    u_char rnode_added[MAX_LEVELS / 8], rnode_deleted[MAX_LEVELS / 8];
    int level, external_node, total_levels, root_node_pos, node_update;
    void *void_map;
    const char *ntop;
    char updated_rnodes, routes_update, devs_update;

    updated_rnodes = routes_update = devs_update = 0;
    setzero(rnode_added, sizeof(rnode_added));
    setzero(rnode_deleted, sizeof(rnode_deleted));

    /**
     * Let's consider all our rnodes void, in this way we'll know what
     * rnodes will remain void after the update.
     */
    for (i = 0; i < me.cur_node->links; i++) {
        node = (map_node *) me.cur_node->r_node[i].r_node;
        node->flags |= MAP_VOID | MAP_UPDATE;
    }
    /**/ rq = radar_q;
    list_for(rq) {
        if (!rq->node)
            continue;
        if (!(me.cur_node->flags & MAP_HNODE) && (rq->flags & MAP_HNODE))
            continue;

        /*
         * We need to know if it is a node which is not in the gnode
         * where we are (external_rnode).
         */
        if ((int) rq->node == RADQ_EXT_RNODE) {
            external_node = 1;
            total_levels = rq->quadg.levels;
        } else {
            external_node = 0;
            total_levels = 1;
        }

        for (level = total_levels - 1; level >= 0; level--) {
            qspn_set_map_vars(level, 0, &root_node, &root_node_pos, 0);
            node_update = devs_update = 0;

            if (!level) {
                void_map = me.int_map;
                node = rq->node;
            } else {
                /* Skip the levels where the ext_rnode belongs
                 * to our same gids */
                if (!quadg_gids_cmp(rq->quadg, me.cur_quadg, level))
                    continue;

                /* Update only the gnodes which belongs to
                 * our same gid of the upper level, because
                 * we don't keep the internal info of the
                 * extern gnodes. */
                if ((level < rq->quadg.levels - 1) &&
                        quadg_gids_cmp(rq->quadg, me.cur_quadg, level + 1)) {
                    rq->quadg.gnode[_EL(level)] = 0;
                    continue;
                }

                /* Ehi, we are a bnode */
                root_node->flags |= MAP_BNODE;
                me.cur_node->flags |= MAP_BNODE;

                void_map = me.ext_map;
                gnode = rq->quadg.gnode[_EL(level)];
                node = &gnode->g;
            }

            if (external_node && !level && me.cur_erc_counter) {
                erc = e_rnode_find(me.cur_erc, &rq->quadg, 0);
                if (!erc)
                    rnode_pos = -1;
                else {
                    rnode_pos = erc->rnode_pos;
                    node = (map_node *) erc->e;
                }
            } else
                rnode_pos = rnode_find(root_node, node);

            if (rnode_pos == -1) {	/* W00t, we've found a new rnode! */
                node_update = 1;
                rnode_pos = root_node->links;

                ntop = inet_to_str(rq->quadg.ipstart[level]);
                if (server_opt.dbg_lvl || !level)
                    loginfo
                    ("Radar: New node found: %s, ext: %d, level: %d",
                     ntop, external_node, level);

                if (external_node && !level) {
                    /*
                     * If this node we are processing is external, at level 0,
                     * in the root_node's rnodes we add a rnode which point
                     * to a ext_rnode struct.
                     */

                    setzero(&rnn, sizeof(map_rnode));
                    e_rnode = xzalloc(sizeof(ext_rnode));

                    memcpy(&e_rnode->quadg, &rq->quadg,
                           sizeof(quadro_group));
                    e_rnode->node.flags =
                        MAP_BNODE | MAP_GNODE | MAP_RNODE | MAP_ERNODE;
                    rnn.r_node = (int *) e_rnode;
                    node = rq->node = &e_rnode->node;
                    new_root_rnode = &rnn;

                    /* Update the external_rnode_cache list */
                    e_rnode_add(&me.cur_erc, e_rnode, rnode_pos,
                                &me.cur_erc_counter);
                } else {
                    /*We purge all the node's rnodes. */
                    rnode_destroy(node);

                    /*
                     * This node has only one rnode,
                     * and that is the root_node.
                     */
                    setzero(&rnn, sizeof(map_rnode));
                    rnn.r_node = (int *) root_node;
                    rnode_add(node, &rnn);

                    /* It is a border node */
                    if (level)
                        node->flags |= MAP_BNODE | MAP_GNODE;
                    node->flags |= MAP_RNODE;

                    /*
                     * Fill the rnode to be added in the
                     * root_node.
                     */
                    setzero(&rnn, sizeof(map_rnode));
                    rnn.r_node = (int *) node;
                    new_root_rnode = &rnn;
                }

                /*
                 * The new node is added in the root_node's
                 * rnodes.
                 */
                rnode_add(root_node, new_root_rnode);


                /* Update the qspn_buffer */
                if (!external_node || level) {
                    qb = xzalloc(sizeof(struct qspn_buffer));
                    qb->rnode = node;
                    qspn_b[level] = list_add(qspn_b[level], qb);

                    send_qspn_now[level] = 1;
                }

                /* If the new rnode wasn't present in the map,
                 * then it is also a new node in the map, so
                 * update the seeds counter too */
                if (!level && !external_node && (node->flags & MAP_VOID)) {
                    gnode_inc_seeds(&me.cur_quadg, level);
                    qspn_inc_gcount(qspn_gnode_count, level + 1, 1);
                }

                SET_BIT(rnode_added, level);
            } else {
                /*
                 * Nah, We have the node in the map. Let's see if
                 * its rtt is changed
                 */

                if (!send_qspn_now[level] && node->links) {
                    diff = abs(root_node->r_node[rnode_pos].trtt -
                               MILLISEC(rq->final_rtt));
                    if (diff >= RTT_DELTA) {
                        node_update = 1;
                        send_qspn_now[level] = 1;
                        debug(DBG_NOISE, "node %s rtt changed, diff: %d",
                              inet_to_str(rq->ip), diff);
                    }
                }
            }

            /* Restore the flags */
            if (level)
                gnode->flags &= ~GMAP_VOID;
            node->flags &= ~MAP_VOID & ~MAP_UPDATE & ~QSPN_OLD;


            /*
             * Update the devices list of the rnode
             */
            if (!level) {
                devs_update = rnl_update_devs(&rlist, &rlist_counter,
                                              node, rq->dev, rq->dev_n);
                if (devs_update)
                    routes_update++;
            }


            /* Nothing is really changed */
            if (!node_update)
                continue;

            /* Update the rtt */
            root_node->r_node[rnode_pos].trtt = MILLISEC(rq->final_rtt);

            /* Bnode map stuff */
            if (external_node && level) {
                /*
                 * All the root_node bnodes which are in the
                 * bmaps of level smaller than `level' points to
                 * the same gnode which is rq->quadg.gnode[_EL(level-1+1)].
                 * This is because the inferior levels cannot
                 * have knowledge about the bordering gnode
                 * which is in an upper level, but it's necessary that
                 * they know which who the root_node borders on,
                 * so the get_route algorithm can descend to
                 * the inferior levels and it will still know
                 * what is the border node which is linked
                 * to the target gnode.
                 */
                for (i = 0; i < level; i++)
                    radar_update_bmap(rq, i, level - 1);
                send_qspn_now[level - 1] = 1;
            }

            if (node_update || devs_update)
                node->flags |= MAP_UPDATE;

        }						/*for(level=0, ...) */

        updated_rnodes++;
    }							/*list_for(rq) */

    /* Burn the deads */
    if (updated_rnodes < me.cur_node->links)
        radar_remove_old_rnodes((char *) rnode_deleted);

    /* <<keep your room tidy... order, ORDER>> */
    if (!is_bufzero(rnode_added, sizeof(rnode_added)) ||
            !is_bufzero(rnode_deleted, sizeof(rnode_deleted))) {

        /***
         * qsort the rnodes of me.cur_node and me.cur_quadg comparing
         * their trtt */
        rnode_trtt_order(me.cur_node);

        for (i = 1; i < me.cur_quadg.levels; i++)
            if (TEST_BIT(rnode_added, i) || TEST_BIT(rnode_deleted, i))
                rnode_trtt_order(&me.cur_quadg.gnode[_EL(i)]->g);
        /**/
        /* adjust the rnode_pos variables in the ext_rnode_cache list */
        erc_reorder_rnodepos(&me.cur_erc, &me.cur_erc_counter,
                             me.cur_node);
    }

    /* Give a refresh to the kernel */
    if ((!is_bufzero(rnode_added, sizeof(rnode_added)) ||
            routes_update) && !(me.cur_node->flags & MAP_HNODE))
        rt_rnodes_update(1);
}
예제 #8
0
/*
 * radard
 *
 * It sends back to rpkt.from the ECHO_REPLY pkt in reply to the ECHO_ME
 * pkt received.
 */
int
radard(PACKET rpkt)
{
    PACKET pkt;
    struct radar_queue *rq;
    ssize_t err;
    const char *ntop = 0;
    int dev_pos;
    u_char echo_scans_count;

    if (alwd_rnodes_counter && !is_rnode_allowed(rpkt.from, alwd_rnodes)) {
        debug(DBG_INSANE, "Filtering 0x%x ECHO_ME", rpkt.hdr.id);
        return -1;
    }

    if ((rpkt.hdr.flags & RESTRICTED_PKT && !restricted_mode) ||
            (!(rpkt.hdr.flags & RESTRICTED_PKT) && restricted_mode))
        return -1;

    dev_pos = ifs_get_pos(me.cur_ifs, me.cur_ifs_n, rpkt.dev);
    if (dev_pos < 0)
        debug(DBG_NORMAL, "The 0x%x ECHO_ME pkt was received by a non "
              "existent interface", rpkt.hdr.id);

    /* If we are hooking we reply only to others hooking nodes */
    if (me.cur_node->flags & MAP_HNODE) {
        if (rpkt.hdr.flags & HOOK_PKT) {
            memcpy(&echo_scans_count, rpkt.msg, sizeof(u_char));

            /*
             * So, we are hooking, but we haven't yet started the
             * first scan or we have done less scans than rpkt.from,
             * this means that this node, who is hooking
             * too and sent us this rpkt, has started the hook
             * before us. If we are in a black zone, this flag
             * will be used to decide which of the hooking nodes
             * have to create the new gnode: if it is set we'll wait,
             * the other hooking node will create the gnode, then we
             * restart the hook. Clear?
             */
            if (!radar_scan_mutex
                    || echo_scans_count >= radar_scans[dev_pos])
                hook_retry = 1;
        } else {
            /*debug(DBG_NOISE, "ECHO_ME pkt dropped: We are hooking"); */
            return 0;
        }
    }

    /* We create the ECHO_REPLY pkt */
    setzero(&pkt, sizeof(PACKET));
    pkt_addto(&pkt, &rpkt.from);
    pkt_addsk(&pkt, rpkt.from.family, rpkt.sk, SKT_UDP);

    if (me.cur_node->flags & MAP_HNODE) {
        /*
         * We attach in the ECHO_REPLY a flag that indicates if we have
         * finished our radar_scan or not. This is usefull if we already
         * sent all the ECHO_ME pkts of our radar scan and while we are
         * waiting the MAX_RADAR_WAIT another node start the hooking:
         * with this flag it can know if we came before him.
         */
        u_char scanning = 1;

        pkt.hdr.sz = sizeof(u_char);
        pkt.hdr.flags |= HOOK_PKT;
        pkt.msg = xmalloc(pkt.hdr.sz);
        if (radar_scans[dev_pos] == MAX_RADAR_SCANS)
            scanning = 0;
        memcpy(pkt.msg, &scanning, sizeof(u_char));

        /*
         * W Poetry Palazzolo, the enlightening holy garden.
         * Sat Mar 12 20:41:36 CET 2005
         */
    }

    if (restricted_mode)
        pkt.hdr.flags |= RESTRICTED_PKT;

    /* We send it */
    err = send_rq(&pkt, 0, ECHO_REPLY, rpkt.hdr.id, 0, 0, 0);
    pkt_free(&pkt, 0);
    if (err < 0) {
        error("radard(): Cannot send back the ECHO_REPLY to %s.", ntop);
        return -1;
    }

    /*
     * Ok, we have sent the reply, now we can update the radar_queue with
     * calm.
     */
    if (radar_q) {
        rq = add_radar_q(rpkt);
        rq->pings++;

#ifdef DEBUG
        if (server_opt.dbg_lvl && rq->pings == 1 &&
                me.cur_node->flags & MAP_HNODE) {
            ntop = inet_to_str(pkt.to);
            debug(DBG_INSANE, "%s(0x%x) to %s", rq_to_str(ECHO_REPLY),
                  rpkt.hdr.id, ntop);
        }
#endif
    }
    return 0;
}
예제 #9
0
파일: inet_addr.c 프로젝트: Julia117/embox
char * inet_ntoa(struct in_addr in) {
	static char buff[INET_ADDRSTRLEN];
	return 0 == inet_to_str(&in, &buff[0], ARRAY_SIZE(buff))
			? &buff[0] : NULL;
}