1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723 |
- /* This file is part of Netsukuku
- * (c) Copyright 2005 Andrea Lo Pumo aka AlpT <alpt@freaknet.org>
- *
- * This source code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This source code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * Please refer to the GNU Public License for more details.
- *
- * You should have received a copy of the GNU Public License along with
- * this source code; if not, write to:
- * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * --
- *
- * radar.c
- *
- * The radar sends in broadcast a bouquet of MAX_RADAR_SCANS# packets and waits
- * for the ECHO_REPLY of the nodes which are alive. It then recollects the
- * replies and builds a small statistic, updates, if necessary, the internal
- * maps, the bnode maps and the qspn buffer.
- * A radar is fired periodically by the radar_daemon(), which is started as a
- * thread.
- */
-
- #include "includes.h"
-
- #include "llist.c"
- #include "endianness.h"
- #include "if.h"
- #include "bmap.h"
- #include "route.h"
- #include "request.h"
- #include "pkts.h"
- #include "qspn.h"
- #include "radar.h"
- #include "netsukuku.h"
- #include "common.h"
-
- pthread_attr_t radar_qspn_send_t_attr;
-
- void
- first_init_radar(void)
- {
- max_radar_wait = MAX_RADAR_WAIT;
-
- pthread_attr_init(&radar_qspn_send_t_attr);
- pthread_attr_setdetachstate(&radar_qspn_send_t_attr,
- PTHREAD_CREATE_DETACHED);
-
- /* register the radar's ops in the pkt_op_table */
- add_pkt_op(ECHO_ME, SKT_BCAST, ntk_udp_radar_port, radard);
- add_pkt_op(ECHO_REPLY, SKT_UDP, ntk_udp_radar_port, radar_recv_reply);
-
- rlist = (struct rnode_list *) clist_init(&rlist_counter);
- alwd_rnodes =
- (struct allowed_rnode *) clist_init(&alwd_rnodes_counter);
-
- radar_daemon_ctl = 0;
- init_radar();
- }
-
- void
- last_close_radar(void)
- {
- close_radar();
- rnl_reset(&rlist, &rlist_counter);
- }
-
- void
- init_radar(void)
- {
- hook_retry = 0;
- my_echo_id = 0;
- total_radar_scans = 0;
- setzero(radar_scans, sizeof(radar_scans));
- radar_scan_mutex = 0;
-
- radar_q = (struct radar_queue *) clist_init(&radar_q_counter);
-
- setzero(send_qspn_now, sizeof(u_char) * MAX_LEVELS);
- }
-
-
- void
- close_radar(void)
- {
- if (radar_q_counter)
- clist_destroy(&radar_q, &radar_q_counter);
- }
-
- void
- reset_radar(void)
- {
- if (me.cur_node->flags & MAP_HNODE) {
- free_new_node();
- rnl_reset(&rlist, &rlist_counter);
- }
-
- close_radar();
- init_radar();
- }
-
- /*
- * free_new_node
- *
- * frees all the temporary alloced rq->node structs used at the
- * hook time.
- */
- void
- free_new_node(void)
- {
- struct radar_queue *rq;
-
- rq = radar_q;
- list_for(rq)
- if (rq->node && ((int) rq->node != RADQ_EXT_RNODE)) {
- xfree(rq->node);
- rq->node = 0;
- }
- }
-
- /*
- * find_node_radar_q
- *
- * returns the first radar_queue struct which has the
- * rq->node pointer equal to `node'.
- */
- struct radar_queue *
- find_node_radar_q(map_node * node)
- {
- struct radar_queue *rq;
-
- rq = radar_q;
- list_for(rq)
- if (rq->node == node)
- return rq;
- return 0;
- }
-
- /*
- * find_ip_radar_q
- *
- * returns the first radar_queue struct which has the rq->ip
- * member equal to the given `ip'.
- */
- struct radar_queue *
- find_ip_radar_q(inet_prefix * ip)
- {
- struct radar_queue *rq;
-
- rq = radar_q;
- list_for(rq)
- if (!memcmp(rq->ip.data, ip->data, MAX_IP_SZ))
- return rq;
-
- return 0;
- }
-
- /*
- * rnl_add
- *
- * adds a new rnode_list struct in the `*rnlist' list. The new
- * allocated struct will be filled respectively with `rnode' and `dev'.
- * It returns the added `rnode_list' struct.
- */
- struct rnode_list *
- rnl_add(struct rnode_list **rnlist, int *rnlist_counter,
- map_node * rnode, interface * dev)
- {
- struct rnode_list *rnl;
-
- rnl = xzalloc(sizeof(struct rnode_list));
- rnl->node = (map_node *) rnode;
- rnl->dev[0] = dev;
- rnl->dev_n++;
-
- clist_add(rnlist, rnlist_counter, rnl);
-
- return rnl;
- }
-
- /*
- * rnl_del
- *
- * deletes the `rnl' struct from the `rnlist' rnode_list.
- * If `close_socket' is not zero, `rnl'->tcp_sk will be closed.
- */
- void
- rnl_del(struct rnode_list **rnlist, int *rnlist_counter,
- struct rnode_list *rnl, int close_socket)
- {
- if (rnl) {
- if (close_socket && rnl->tcp_sk)
- inet_close(&rnl->tcp_sk);
- clist_del(rnlist, rnlist_counter, rnl);
- }
- if (!(*rnlist_counter))
- *rnlist = 0;
- }
-
- /*
- * rnl_reset
- *
- * reset the whole rnode_list
- */
- void
- rnl_reset(struct rnode_list **rnlist, int *rnlist_counter)
- {
- struct rnode_list *rnl = *rnlist, *next;
-
- list_safe_for(rnl, next)
- rnl_del(rnlist, rnlist_counter, rnl, 1);
- *rnlist = (struct rnode_list *) clist_init(rnlist_counter);
- }
-
-
- /*
- * rnl_del_dead_rnode
- *
- * it removes all the rnode_list structs which are related
- * to a rnode which doesn't exist anymore in `root_node'
- * It returns the number of delete rnodes_list structs.
- */
- int
- rnl_del_dead_rnode(struct rnode_list **rnlist, int *rnlist_counter,
- map_node * root_node)
- {
- struct rnode_list *rnl = *rnlist, *next;
- int i = 0;
-
- list_safe_for(rnl, next)
- if (rnode_find(root_node, rnl->node) < 0) {
- rnl_del(rnlist, rnlist_counter, rnl, 1);
- i++;
- }
-
- return i;
- }
-
- /*
- * rnl_find_rpos
- *
- * returns the first rnode_list struct, contained in
- * `rnlist', which has rnl->node equal to `node'.
- */
- struct rnode_list *
- rnl_find_node(struct rnode_list *rnlist, map_node * node)
- {
- struct rnode_list *rnl = rnlist;
-
- list_for(rnl)
- if (rnl->node == node)
- return rnl;
-
- return 0;
- }
-
- /*
- * rnl_add_dev
- *
- * If `rnl' is 0 a new struct is added in `*rnlist' using `node'.
- * In both cases the `new_dev' is added in the rnl->dev[] array of
- * pointers (if it isn't already present there) and rnl->dev_n is
- * incremented.
- * On error -1 is returned.
- */
- int
- rnl_add_dev(struct rnode_list **rnlist, int *rnlist_counter,
- struct rnode_list *rnl, map_node * node, interface * new_dev)
- {
- int i;
-
- if (!rnl) {
- rnl = rnl_add(rnlist, rnlist_counter, node, new_dev);
- return 0;
- }
-
- if (rnl->dev_n >= MAX_INTERFACES)
- return -1;
-
- for (i = 0; i < rnl->dev_n; i++)
- if (rnl->dev[i] == new_dev)
- return 0;
-
- rnl->dev[rnl->dev_n++] = new_dev;
-
- return 0;
- }
-
- /*
- * rnl_del_dev
- *
- * It searches a pointer in the rnl->dev[] array equal to
- * `del_dev'. If it is found, it is set to 0 and rnl->dev_n is decremented,
- * otherwise 0 is returned.
- * If rnlist->dev_n is 0, the found rnlist struct is deleted from the llist.
- * On error -1 is returned.
- */
- int
- rnl_del_dev(struct rnode_list **rnlist, int *rnlist_counter,
- struct rnode_list *rnl, interface * del_dev)
- {
- int i;
-
- if (!rnl)
- return 0;
-
- if (rnl->dev_n <= 0)
- return -1;
-
- for (i = 0; i < rnl->dev_n; i++) {
- if (rnl->dev[i] == del_dev) {
- if (i == rnl->dev_n - 1)
- rnl->dev[i] = 0;
- else {
- rnl->dev[i] = rnl->dev[rnl->dev_n - 1];
- rnl->dev[rnl->dev_n - 1] = 0;
- }
- rnl->dev_n--;
- break;
- }
- }
-
- if (!rnl->dev_n)
- rnl_del(rnlist, rnlist_counter, rnl, 1);
-
- return 0;
- }
-
- /*
- * rnl_update_devs
- *
- * it updates the device array present in the rnode_list struct of `node'.
- * It searches in rnlist a struct which have rnlist->node == `node',
- * then it substitutes rnlist->dev with `devs' and rnlist->dev_n with `dev_n'.
- * If there is a difference between the new `devs' array and the old one, 1 is
- * returned.
- */
- int
- rnl_update_devs(struct rnode_list **rnlist, int *rnlist_counter,
- map_node * node, interface ** devs, int dev_n)
- {
- struct rnode_list *old_rnl, *new_rnl;
- int i, dev_pos, update = 0;
-
- old_rnl = rnl_find_node(*rnlist, node);
-
- if (!dev_n) {
- /*
- * The new `devs' array is empty, therefore delete old_rnl
- */
- rnl_del(rnlist, rnlist_counter, old_rnl, 1);
- return 0;
- }
-
- if (old_rnl)
- /*
- * Diff old_rnl->dev and `devs'
- */
- for (i = 0; i < dev_n; i++) {
- dev_pos = FIND_PTR(devs[i], old_rnl->dev, old_rnl->dev_n);
- if (dev_pos < 0) {
- update = 1;
- break;
- }
- } else if (!old_rnl)
- update = 1;
-
- if (update) {
- new_rnl = rnl_add(rnlist, rnlist_counter, node, devs[0]);
- for (i = 1; i < dev_n; i++)
- rnl_add_dev(rnlist, rnlist_counter, new_rnl, node, devs[i]);
-
- new_rnl->tcp_sk = (old_rnl) ? old_rnl->tcp_sk : 0;
- rnl_del(rnlist, rnlist_counter, old_rnl, 0);
- }
-
- return update;
- }
-
- interface **
- rnl_get_dev(struct rnode_list * rnlist, map_node * node)
- {
- struct rnode_list *rnl;
-
- rnl = rnl_find_node(rnlist, node);
- return !rnl ? 0 : rnl->dev;
- }
-
- interface *
- rnl_get_rand_dev(struct rnode_list * rnlist, map_node * node)
- {
- struct rnode_list *rnl;
-
- return !(rnl = rnl_find_node(rnlist, node)) ?
- 0 : rnl->dev[rand_range(0, rnl->dev_n - 1)];
- }
-
- /*
- * rnl_get_sk
- *
- * It returns the tcp socket associated to rnode `node'.
- * If the socket is set to zero, it tries to create a tcp connection to
- * `node' to the `ntk_tcp_port' port.
- *
- * On error -1 is returned.
- */
- int
- rnl_get_sk(struct rnode_list *rnlist, map_node * node)
- {
- struct rnode_list *rnl;
-
- if (!(rnl = rnl_find_node(rnlist, node)))
- return -1;
-
- if (!rnl->tcp_sk) {
- inet_prefix to;
- int i;
-
- if (me.cur_node->flags & MAP_HNODE) {
- struct radar_queue *rq;
-
- /* If we are hooking, get the IP from the radar
- * queue */
- if (!(rq = find_node_radar_q(rnl->node)))
- return -1;
- inet_copy(&to, &rq->ip);
-
- } else {
- rnodetoip((u_int) me.int_map, (u_int) node,
- me.cur_quadg.ipstart[1], &to);
- }
-
- /* Try to connect using the `i'th device. If it fails, try
- * another device */
- for (i = 0; i < rnl->dev_n && rnl->tcp_sk <= 0; i++)
- rnl->tcp_sk = pkt_tcp_connect(&to, ntk_tcp_port, rnl->dev[i]);
-
- /* If the socket is connected, set it to keepalive */
- if ((rnl->tcp_sk = (rnl->tcp_sk <= 0) ? 0 : rnl->tcp_sk))
- set_keepalive_sk(rnl->tcp_sk);
-
- }
-
- return rnl->tcp_sk > 0 ? rnl->tcp_sk : -1;
- }
-
- /*
- * rnl_set_sk
- *
- * It sets the socket associated to rnode `node' to `sk'
- */
- void
- rnl_set_sk(struct rnode_list *rnlist, map_node * node, int sk)
- {
- struct rnode_list *rnl;
-
- if (!(rnl = rnl_find_node(rnlist, node)))
- return;
-
- rnl->tcp_sk = sk;
- }
-
- /*
- * rnl_close_all_sk
- *
- * It closes all the opened tcp_sk of the `rnlist' llist
- */
- void
- rnl_close_all_sk(struct rnode_list *rnlist)
- {
- struct rnode_list *rnl = rnlist;
-
- list_for(rnl)
- if (rnl->tcp_sk)
- inet_close(&rnl->tcp_sk);
- }
-
- /*
- * rnl_fill_rq
- *
- * It sets the `pkt'->sk and `pkt'->to variables.
- * The `pkt'->sk is retrieved using rnl_get_sk()
- *
- * On error -1 is returned.
- */
- int
- rnl_fill_rq(map_node * rnode, PACKET * pkt)
- {
- int tries = 0;
-
- retry:
- if (!pkt->sk && (pkt->sk = rnl_get_sk(rlist, rnode)) <= 0) {
- error(ERROR_MSG "Couldn't get the socket associated "
- "to dst_rnode", ERROR_FUNC);
- return -1;
- }
-
- if (inet_getpeername(pkt->sk, &pkt->to, 0) < 0) {
- tries++;
- if (tries < 2)
- goto retry;
- return -1;
- }
-
- return 0;
- }
-
- /*
- * rnl_send_rq
- *
- * It is a wrapper to send_rq. It is used to send or receive a packet to/from
- * the specified `rnode'.
- *
- * On error -1 is returned.
- *
- * Note: the pkt->sk must not be closed.
- */
- int
- rnl_send_rq(map_node * rnode,
- PACKET * pkt, int pkt_flags, u_char rq, int rq_id, u_char re,
- int check_ack, PACKET * rpkt)
- {
- int ret, tries = 0;
-
- retry:
- if (!pkt->sk && rnl_fill_rq(rnode, pkt) < 0)
- return -1;
-
- ret = send_rq(pkt, pkt_flags, rq, rq_id, re, check_ack, rpkt);
- if ((ret == SEND_RQ_ERR_CONNECT || ret == SEND_RQ_ERR_SEND ||
- ret == SEND_RQ_ERR_RECV)) {
-
- /* The socket has been corrupted, set it to 0 and try again */
- inet_close(&pkt->sk);
- rnl_set_sk(rlist, rnode, 0);
-
- tries++;
- if (tries < 2)
- goto retry;
- }
-
- return ret;
- }
-
- /*
- * is_rnode_allowed
- *
- * it verifies if the rnode described by the `rip' IP is
- * present in the `alr' llist. If it is 1 is returned, otherwise 0.
- */
- int
- is_rnode_allowed(inet_prefix rip, struct allowed_rnode *alr)
- {
- int i, e, gid[MAX_LEVELS];
-
- iptogids(&rip, gid, FAMILY_LVLS);
-
- list_for(alr) {
- for (e = 0, i = alr->min_level; i < alr->tot_level; i++)
- if (gid[i] != alr->gid[i]) {
- e = 1;
- break;
- }
- if (!e)
- return 1;
- }
-
- return 0;
- }
-
- /*
- * new_rnode_allowed
- *
- * add a new allowed rnode in the `alr' llist which has
- * already `*alr_counter' members. `gid', `min_lvl', and `tot_lvl' are the
- * respective field of the new allowed_rnode struct.
- */
- void
- new_rnode_allowed(struct allowed_rnode **alr, int *alr_counter,
- int *gid, int min_lvl, int tot_lvl)
- {
- struct allowed_rnode *new_alr;
-
- new_alr = xmalloc(sizeof(struct allowed_rnode));
-
- new_alr->min_level = min_lvl;
- new_alr->tot_level = tot_lvl;
-
- setzero(new_alr->gid, sizeof(int) * MAX_LEVELS);
- memcpy(&new_alr->gid[min_lvl], &gid[min_lvl],
- sizeof(int) * (tot_lvl - min_lvl));
-
- debug(DBG_SOFT,
- "new_rnode_allowed: %d, %d, %d, %d. min_lvl: %d, tot_lvl: %d",
- gid[0], gid[1], gid[2], gid[3], min_lvl, tot_lvl);
-
- clist_add(alr, alr_counter, new_alr);
- }
-
- void
- reset_rnode_allowed(struct allowed_rnode **alr, int *alr_counter)
- {
- if (*alr)
- list_destroy((*alr));
- *alr = (struct allowed_rnode *) clist_init(alr_counter);
- }
-
- /*
- * count_hooking_nodes
- *
- * returns the number of hooking nodes, which are stored
- * in the radar_queue.
- */
- int
- count_hooking_nodes(void)
- {
- struct radar_queue *rq;
- int total_hooking_nodes = 0;
-
- rq = radar_q;
- list_for(rq) {
- if (!rq->node)
- continue;
-
- if (rq->node->flags & MAP_HNODE)
- total_hooking_nodes++;
- }
-
- return total_hooking_nodes;
- }
-
-
- /*
- * final_radar_queue
- *
- * analyses the received ECHO_REPLY pkt and write the
- * average rtt of each found node in the radar_queue.
- */
- void
- final_radar_queue(void)
- {
- struct radar_queue *rq;
- int e;
- struct timeval sum;
- u_int f_rtt;
-
- setzero(&sum, sizeof(struct timeval));
-
- rq = radar_q;
- list_for(rq) {
- if (!rq->node)
- continue;
-
- /* Sum the rtt of all the received pongs */
- for (e = 0; e < rq->pongs; e++)
- timeradd(&rq->rtt[e], &sum, &sum);
-
- /* Add penality rtt for each pong lost */
- for (; e < MAX_RADAR_SCANS; e++)
- timeradd(&rq->rtt[e - rq->pongs], &sum, &sum);
-
- f_rtt = MILLISEC(sum) / MAX_RADAR_SCANS;
- MILLISEC_TO_TV(f_rtt, rq->final_rtt);
- }
-
- my_echo_id = 0;
- }
-
- /*
- * radar_remove_old_rnodes
- *
- * It removes all the old rnodes ^_- It store in rnode_delete[level] the number
- * of deleted rnodes. This function is used by radar_update_map
- */
- int
- radar_remove_old_rnodes(char *rnode_deleted)
- {
- map_node *node, *root_node, *broot_node;
- map_gnode *gnode;
- map_bnode *bnode;
- ext_rnode *e_rnode = 0;
- ext_rnode_cache *erc;
- struct qspn_buffer *qb;
- struct rnode_list *rnl;
- int i, e, node_pos, bm, rnode_pos, bnode_rnode_pos, root_node_pos;
- int broot_node_pos;
- int level, blevel, external_node, total_levels, first_level;
- void *void_map, *void_gnode;
-
- if (!me.cur_node->links)
- return 0;
-
- for (i = 0; i < me.cur_node->links; i++) {
- node = (map_node *) me.cur_node->r_node[i].r_node;
-
- if (!(node->flags & MAP_VOID))
- /* The rnode is not really dead! */
- continue;
-
- if (node->flags & MAP_ERNODE) {
- e_rnode = (ext_rnode *) node;
- external_node = 1;
- total_levels = e_rnode->quadg.levels;
- first_level = 1;
- quadg_setflags(&e_rnode->quadg, MAP_VOID);
- } else {
- external_node = 0;
- total_levels = 1;
- first_level = 0;
- }
-
- for (level = first_level; level < total_levels; level++) {
- qspn_set_map_vars(level, 0, &root_node, &root_node_pos, 0);
- blevel = level - 1;
-
- /* delete the rnode from the rnode_list */
- rnl = rnl_find_node(rlist, node);
- rnl_del(&rlist, &rlist_counter, rnl, 1);
-
- /*
- * Just delete it from all the maps.
- */
-
- if (!level && !external_node) {
- void_map = me.int_map;
- node_pos = pos_from_node(node, me.int_map);
- rnode_pos = i;
-
- debug(DBG_NORMAL, "radar: The node %d is dead", node_pos);
-
- /* delete it from the int_map and update the gcount */
- map_node_del(node);
- qspn_dec_gcount((int *) qspn_gnode_count, level + 1, 1);
-
- /* delete the route */
- rt_update_node(0, node, 0, 0, 0, level);
-
- send_qspn_now[level] = 1;
- } else {
- void_map = me.ext_map;
- gnode = e_rnode->quadg.gnode[_EL(level)];
-
- /** delete the direct route to the ext_node */
- if (level == 1)
- rt_update_node(&e_rnode->quadg.ipstart[0],
- e_rnode, 0, 0, 0, /*level=0 */ 0);
- /**/ void_gnode = (void *) gnode;
- if (!void_gnode)
- continue;
-
- node_pos = pos_from_gnode(gnode, me.ext_map[_EL(level)]);
- rnode_pos = g_rnode_find((map_gnode *) root_node, gnode);
-
- debug(DBG_NORMAL, "The ext_node (gid %d, lvl %d) is"
- " dead", e_rnode->quadg.gid[level], level);
-
- /* bnode_map update */
- for (e = 0; blevel >= 0; blevel--) {
- qspn_set_map_vars(blevel, 0, &broot_node,
- &broot_node_pos, 0);
- bm = map_find_bnode(me.bnode_map[blevel],
- me.bmap_nodes[blevel],
- broot_node_pos);
- if (bm == -1)
- continue;
-
- bnode = &me.bnode_map[blevel][bm];
- bnode_rnode_pos = rnode_find(bnode,
- (map_node *) e_rnode->
- quadg.gnode[_EL(level)]);
- if (bnode_rnode_pos != -1)
- rnode_del(bnode, bnode_rnode_pos);
-
- if (!bnode->links) {
- me.bnode_map[blevel] =
- map_bnode_del(me.bnode_map[blevel],
- &me.bmap_nodes[blevel], bnode);
- broot_node->flags &= ~MAP_BNODE;
- } else
- e = 1;
- }
- if (!e) /* We are no more a bnode */
- me.cur_node->flags &= ~MAP_BNODE;
-
- /* If we were the only bnode which bordered on
- * `gnode', delete it from the map */
- if (map_find_bnode_rnode
- (me.bnode_map[level - 1], me.bmap_nodes[level - 1],
- gnode) == -1) {
- qspn_dec_gcount((int *) qspn_gnode_count, level + 1,
- gnode->gcount);
- gmap_node_del(gnode);
- gnode_dec_seeds(&me.cur_quadg, level); /* update the seeds */
- }
-
- /* Delete the entries from the routing table */
- rt_update_node(0, 0, &e_rnode->quadg, 0, 0, level);
-
- send_qspn_now[level] = 1;
- }
-
- if (rnode_pos >= 0 && root_node->links > 0)
- rnode_del(root_node, rnode_pos);
-
- if (!root_node->links) {
- /* We are alone in the dark. Sigh. */
- qspn_time_reset(level, level, FAMILY_LVLS);
- } else if (!external_node)
- erc_update_rnodepos(me.cur_erc, root_node, rnode_pos);
-
- /* Now we delete it from the qspn_buffer */
- if (qspn_b[level]) {
- qb = qspn_b[level];
- qb = qspn_b_find_rnode(qb, node);
- if (qb)
- qspn_b[level] = list_del(qspn_b[level], qb);
- }
-
- SET_BIT(rnode_deleted, level);
- }
-
- /*
- * Kick out the external_node from the root_node and destroy it
- * from the ext_rnode_cache
- */
- if (external_node) {
- /* external rnode cache update */
- erc = erc_find(me.cur_erc, e_rnode);
- if (erc)
- e_rnode_del(&me.cur_erc, &me.cur_erc_counter, erc);
- rnode_del(me.cur_node, i);
- }
-
- /* If the rnode we deleted from the root_node was swapped with
- * the last rnodes, we have to inspect again the same
- * root_node->r_node[ `i' ] rnode, because now it is another
- * rnode */
- if (i != (me.cur_node->links + 1) - 1)
- i--;
- }
-
- if (!me.cur_node->links) {
- /* - Diary -
- * Tue Mar 14 07:29:58 CET 2006
- * Damn! All my rnodes died, I am the last survivor in this
- * great lone land... I have to reset my memory... farewell!
- */
- qspn_reset_counters(FAMILY_LVLS);
- }
-
- return 0;
- }
-
- /*
- * radar_update_bmap
- *
- * updates the bnode map of the given `level' the root_node bnode in the bmap
- * will also point to the gnode of level `gnode_level'+1 that is
- * `rq'->quadg.gnode[_EL(gnode_level+1)].
- */
- void
- radar_update_bmap(struct radar_queue *rq, int level, int gnode_level)
- {
- map_gnode *gnode;
- map_node *root_node;
- map_rnode *rnode, rn;
- int bm, rnode_pos, root_node_pos;
- void *void_map;
-
- if (level == me.cur_quadg.levels - 1)
- return;
-
- qspn_set_map_vars(level, 0, &root_node, &root_node_pos, 0);
- void_map = me.ext_map;
- gnode = rq->quadg.gnode[_EL(gnode_level + 1)];
-
- bm = map_find_bnode(me.bnode_map[level], me.bmap_nodes[level],
- root_node_pos);
- if (bm == -1) {
- bm = map_add_bnode(&me.bnode_map[level], &me.bmap_nodes[level],
- root_node_pos, 0);
- rnode_pos = -1;
- } else
- rnode_pos = rnode_find(&me.bnode_map[level][bm], &gnode->g);
-
- if (rnode_pos == -1) {
- setzero(&rn, sizeof(map_rnode));
- rn.r_node = (int *) &gnode->g;
- rnode_add(&me.bnode_map[level][bm], &rn);
- rnode_pos = 0;
- }
-
- rnode = &me.bnode_map[level][bm].r_node[rnode_pos];
- rnode->trtt = MILLISEC(rq->final_rtt);
- }
-
- /*
- * 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);
- }
-
- /*
- * add_radar_q
- *
- * It returns the radar_q struct which handles the pkt.from node.
- * If the node is not present in the radar_q, it is added, and the
- * relative struct will be returned.
- */
- struct
- radar_queue *
- add_radar_q(PACKET pkt)
- {
- map_node *rnode;
- quadro_group quadg;
- struct radar_queue *rq;
- u_int ret = 0;
- int dev_pos;
-
- if (me.cur_node->flags & MAP_HNODE) {
- /*
- * We are hooking, we haven't yet an int_map, an ext_map,
- * a stable ip, so we create fake nodes that will be delete after
- * the hook.
- */
- if (!(rq = find_ip_radar_q(&pkt.from))) {
- map_rnode rnn;
-
- rnode = xmalloc(sizeof(map_node));
- setzero(rnode, sizeof(map_node));
- setzero(&rnn, sizeof(map_rnode));
-
- rnn.r_node = (int *) me.cur_node;
- rnode_add(rnode, &rnn);
- } else
- rnode = rq->node;
- }
-
- iptoquadg(pkt.from, me.ext_map, &quadg,
- QUADG_GID | QUADG_GNODE | QUADG_IPSTART);
-
- if (!(me.cur_node->flags & MAP_HNODE)) {
- iptomap((u_int) me.int_map, pkt.from, me.cur_quadg.ipstart[1],
- &rnode);
- ret = quadg_gids_cmp(me.cur_quadg, quadg, 1);
- }
-
- if (!ret)
- rq = find_node_radar_q(rnode);
- else
- rq = find_ip_radar_q(&pkt.from);
-
- if (!rq) {
- /*
- * If pkt.from isn't already in the queue, add it.
- */
-
- rq = xzalloc(sizeof(struct radar_queue));
-
- if (ret)
- rq->node = (map_node *) RADQ_EXT_RNODE;
- else {
- rq->node = rnode;
- /* This pkt has been sent from another hooking
- * node, let's remember this. */
- if (pkt.hdr.flags & HOOK_PKT)
- rq->node->flags |= MAP_HNODE;
- }
-
- if (pkt.hdr.flags & HOOK_PKT)
- rq->flags |= MAP_HNODE;
-
- inet_copy(&rq->ip, &pkt.from);
- memcpy(&rq->quadg, &quadg, sizeof(quadro_group));
- rq->dev[0] = pkt.dev;
- rq->dev_n++;
-
- clist_add(&radar_q, &radar_q_counter, rq);
- } else {
- /*
- * Check if the input device is in the rq->dev array,
- * if not add it.
- */
- if (rq->dev_n < MAX_INTERFACES) {
- dev_pos = FIND_PTR(pkt.dev, rq->dev, rq->dev_n);
- if (dev_pos < 0)
- rq->dev[rq->dev_n++] = pkt.dev;
- }
- }
-
- return rq;
- }
-
- /*
- * radar_exec_reply
- *
- * It reads the received ECHO_REPLY pkt and updates the radar
- * queue, storing the calculated rtt and the other infos relative to the sender
- * node.
- */
- int
- radar_exec_reply(PACKET pkt)
- {
- struct timeval t;
- struct radar_queue *rq;
- u_int rtt_ms = 0;
- int dev_pos;
-
- gettimeofday(&t, 0);
-
- /*
- * Get the radar_queue struct relative to pkt.from
- */
- rq = add_radar_q(pkt);
-
- dev_pos = ifs_get_pos(me.cur_ifs, me.cur_ifs_n, pkt.dev);
- if (dev_pos < 0)
- debug(DBG_NORMAL, "The 0x%x ECHO_REPLY pkt was received by a non "
- "existent interface", pkt.hdr.id);
-
- if (me.cur_node->flags & MAP_HNODE) {
- if (pkt.hdr.flags & HOOK_PKT) {
- u_char scanning;
- memcpy(&scanning, pkt.msg, sizeof(u_char));
-
- /*
- * If the pkt.from node has finished his scan, and we
- * never received one of its ECHO_ME pkts, and we are
- * still scanning, set the hook_retry.
- */
- if (!scanning && !rq->pings &&
- (radar_scan_mutex ||
- radar_scans[dev_pos] <= MAX_RADAR_SCANS)) {
- hook_retry = 1;
- }
- }
- }
-
- if (rq->pongs < radar_scans[dev_pos]) {
- timersub(&t, &scan_start, &rq->rtt[(int) rq->pongs]);
- /*
- * Now we divide the rtt, because (t - scan_start) is the time
- * the pkt used to reach B from A and to return to A from B
- */
- rtt_ms = MILLISEC(rq->rtt[(int) rq->pongs]) / 2;
- MILLISEC_TO_TV(rtt_ms, rq->rtt[(int) rq->pongs]);
-
- rq->pongs++;
- }
-
- return 0;
- }
-
-
- /*
- * radar_recv_reply
- *
- * It handles the ECHO_REPLY pkts
- */
- int
- radar_recv_reply(PACKET pkt)
- {
- if (!my_echo_id || !radar_scan_mutex || !total_radar_scans)
- return -1;
-
- if (pkt.hdr.id != my_echo_id) {
- debug(DBG_NORMAL, "I received an ECHO_REPLY with id: 0x%x, but "
- "my current ECHO_ME is 0x%x", pkt.hdr.id, my_echo_id);
- return -1;
- }
-
- /*
- * If the `alwd_rnodes_counter' counter isn't zero, verify that
- * `pkt.from' is an allowed rnode, otherwise drop this pkt
- */
- if (alwd_rnodes_counter && !is_rnode_allowed(pkt.from, alwd_rnodes)) {
- debug(DBG_INSANE, "Filtering 0x%x ECHO_REPLY", pkt.hdr.id);
- return -1;
- }
-
- /*
- * If the rnode is in restricted mode and we are not, drop the pkt.
- * If we are in restricted mode and the rnode isn't, drop the pkt
- */
- if ((pkt.hdr.flags & RESTRICTED_PKT && !restricted_mode) ||
- (!(pkt.hdr.flags & RESTRICTED_PKT) && restricted_mode))
- return -1;
-
- return radar_exec_reply(pkt);
- }
-
- /*
- * radar_qspn_send_t
- *
- * This function is used only by radar_scan().
- * It just call the qspn_send() function. We use a thread
- * because the qspn_send() may sleep, and we don't want to halt the
- * radar_scan().
- */
- void *
- radar_qspn_send_t(void *level)
- {
- int *p;
- u_char i;
-
- p = (int *) level;
- i = (u_char) * p;
-
- xfree(p);
- qspn_send(i);
-
- return NULL;
- }
-
- /*
- * radar_scan
- *
- * It starts the scan of the local area.
- *
- * It sends MAX_RADAR_SCANS packets in broadcast then it waits MAX_RADAR_WAIT
- * and in the while the echo replies are gathered. After MAX_RADAR_WAIT it
- * stops to receive echo replies and it does a statistical analysis of the
- * gathered echo replies, it updates the r_nodes in the map and sends a qspn
- * round if something is changed in the map and if the `activate_qspn' argument
- * is non zero.
- *
- * It returns 1 if another radar_scan is in progress, -1 if something went
- * wrong, 0 on success.
- */
- int
- radar_scan(int activate_qspn)
- {
- pthread_t thread;
- PACKET pkt;
- int i, d, *p;
- ssize_t err;
- u_char echo_scan;
-
- /* We are already doing a radar scan, that's not good */
- if (radar_scan_mutex)
- return 1;
- radar_scan_mutex = 1;
-
- /*
- * We create the PACKET
- */
- setzero(&pkt, sizeof(PACKET));
- inet_setip_bcast(&pkt.to, my_family);
- my_echo_id = rand();
-
- gettimeofday(&scan_start, 0);
-
- /*
- * Send a bouquet of ECHO_ME pkts
- */
-
- if (me.cur_node->flags & MAP_HNODE) {
- pkt.hdr.sz = sizeof(u_char);
- pkt.hdr.flags |= HOOK_PKT | BCAST_PKT;
- pkt.msg = xmalloc(pkt.hdr.sz);
- debug(DBG_INSANE, "Radar scan 0x%x activated", my_echo_id);
- } else
- total_radars++;
-
- if (restricted_mode)
- pkt.hdr.flags |= RESTRICTED_PKT;
-
- /* Loop through the me.cur_ifs array, sending the bouquet using all the
- * interfaces we have */
- for (d = 0; d < me.cur_ifs_n; d++) {
-
- pkt_add_dev(&pkt, &me.cur_ifs[d], 1);
- pkt.sk = 0; /* Create a new socket */
-
- /* Send MAX_RADAR_SCANS# packets using me.cur_ifs[d] as
- * outgoing interface */
- for (i = 0, echo_scan = 0; i < MAX_RADAR_SCANS; i++, echo_scan++) {
- if (me.cur_node->flags & MAP_HNODE)
- memcpy(pkt.msg, &echo_scan, sizeof(u_char));
-
- err = send_rq(&pkt, 0, ECHO_ME, my_echo_id, 0, 0, 0);
- if (err < 0) {
- if (errno == ENODEV) {
- /*
- * The me.cur_ifs[d] device doesn't
- * exist anymore. Delete it.
- */
- fatal("The device \"%s\" has been removed",
- me.cur_ifs[d].dev_name);
- ifs_del(me.cur_ifs, &me.cur_ifs_n, d);
- d--;
- } else
- error(ERROR_MSG "Error while sending the"
- " scan 0x%x... skipping",
- ERROR_FUNC, my_echo_id);
- break;
- }
- radar_scans[d]++;
- total_radar_scans++;
- }
-
- if (!radar_scans[d])
- error("radar_scan(): The scan 0x%x on the %s interface failed."
- " Not a single scan was sent", my_echo_id,
- pkt.dev->dev_name);
-
- if (pkt.sk > 0)
- inet_close(&pkt.sk);
- }
-
- pkt_free(&pkt, 1);
-
- if (!total_radar_scans) {
- error("radar_scan(): The scan 0x%x failed. It wasn't possible "
- "to send a single scan", my_echo_id);
- return -1;
- }
-
- xtimer(max_radar_wait, max_radar_wait << 1, &radar_wait_counter);
-
- final_radar_queue();
- radar_update_map();
-
- if (activate_qspn)
- for (i = 0; i < me.cur_quadg.levels; i++)
- if (send_qspn_now[i]) {
- p = xmalloc(sizeof(int));
- *p = i;
- /* We start a new qspn_round in the `i'-th level */
- pthread_create(&thread, &radar_qspn_send_t_attr,
- radar_qspn_send_t, (void *) p);
- }
-
- if (!(me.cur_node->flags & MAP_HNODE))
- reset_radar();
-
- radar_scan_mutex = 0;
- return 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;
- }
-
- /*
- * refresh_hook_root_node
- *
- * At hooking the radar_scan doesn't have an int_map, so
- * all the nodes it found are stored in fake nodes. When we finish the hook,
- * instead, we have an int_map, so we convert all this fake nodes into real
- * nodes. To do this we modify each rq->node of the radar_queue and recall the
- * radar_update_map() func.
- * rnode_list and qspn_b are also updated.
- * Note: the me.cur_node must be deleted prior the call of this function.
- */
- int
- refresh_hook_root_node(void)
- {
- struct radar_queue *rq;
- map_node *rnode;
- int ret;
-
- rq = radar_q;
- list_for(rq) {
- ret = iptomap((u_int) me.int_map, rq->ip, me.cur_quadg.ipstart[1],
- &rnode);
- if (ret)
- rq->node = (map_node *) RADQ_EXT_RNODE;
- else
- rq->node = rnode;
- }
-
- radar_update_map();
-
- /*
- * Remove all the rnode_list structs which refers to the fake
- * rnodes.
- */
- rnl_del_dead_rnode(&rlist, &rlist_counter, me.cur_node);
-
- /* Do the same for the qspn_b buffer */
- qspn_b_del_all_dead_rnodes();
-
- return 0;
- }
-
- /*
- * radar_daemon
- *
- * keeps the radar up until the end of the universe.
- */
- void *
- radar_daemon(void *null)
- {
- /* If `radar_daemon_ctl' is set to 0 the radar_daemon will stop.
- * It will restart when it becomes again 1 */
- radar_daemon_ctl = 1;
-
- debug(DBG_NORMAL, "Radar daemon up & running");
- for (;;) {
- while (!radar_daemon_ctl)
- sleep(1);
-
- radar_scan(1);
- }
- }
-
- /*
- * radar_wait_new_scan
- *
- * It sleeps until a new radar scan is sent
- */
- void
- radar_wait_new_scan(void)
- {
- int old_echo_id, old_radar_wait_counter;
-
- old_echo_id = my_echo_id;
- old_radar_wait_counter = radar_wait_counter;
-
- for (; old_echo_id == my_echo_id;) {
- usleep(505050);
-
- /* If the radar_wait_counter doesn't change, that means that
- * the radar isn't active */
- if (radar_wait_counter == old_radar_wait_counter)
- break;
- }
- }
-
- /*EoW*/
|