123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589 |
- /* 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.
- *
- * --
- * andna.c:
- * Here there are all the functions that send, receive and exec ANDNA packets.
- * All the threads of the ANDNA daemon and the main andna functions are here
- * too.
- */
-
- #include "includes.h"
-
- #include "inet.h"
- #include "endianness.h"
- #include "map.h"
- #include "gmap.h"
- #include "bmap.h"
- #include "route.h"
- #include "request.h"
- #include "tracer.h"
- #include "qspn.h"
- #include "radar.h"
- #include "netsukuku.h"
- #include "daemon.h"
- #include "crypto.h"
- #include "snsd_cache.h"
- #include "andna_cache.h"
- #include "andna.h"
- #include "andns.h"
- #include "dns_wrapper.h"
- #include "hash.h"
- #include "common.h"
-
-
- /*
- *
- * * * * (de)-Initialization functions * * *
- *
- */
-
- /*
- * andna_load_caches
- *
- * loads all the ANDNA caches
- */
- int
- andna_load_caches(void)
- {
- int ret = 0;
-
- if (file_exist(server_opt.lclkey_file) &&
- (!load_lcl_keyring(&lcl_keyring, server_opt.lclkey_file)))
- debug(DBG_NORMAL, "Andna LCL Keyring loaded");
-
- if (file_exist(server_opt.lcl_file) &&
- (andna_lcl = load_lcl_cache(server_opt.lcl_file, &lcl_counter)))
- debug(DBG_NORMAL, "Andna Local Cache loaded");
-
- if (file_exist(server_opt.andna_cache_file) &&
- (andna_c = load_andna_cache(server_opt.andna_cache_file,
- &andna_c_counter)))
- debug(DBG_NORMAL, "Andna cache loaded");
-
- if (file_exist(server_opt.counter_c_file) &&
- (andna_counter_c = load_counter_c(server_opt.counter_c_file,
- &cc_counter)))
- debug(DBG_NORMAL, "Counter cache loaded");
-
- if (file_exist(server_opt.rhc_file) &&
- (andna_rhc = load_rh_cache(server_opt.rhc_file, &rhc_counter)))
- debug(DBG_NORMAL, "Resolved hostnames cache loaded");
-
- if (file_exist(server_opt.andna_hnames_file) &&
- !(load_hostnames(server_opt.andna_hnames_file,
- &andna_lcl, &lcl_counter)))
- debug(DBG_NORMAL, "Hostnames file loaded");
-
- if (file_exist(server_opt.snsd_nodes_file) &&
- !(ret = load_snsd(server_opt.snsd_nodes_file, andna_lcl)))
- debug(DBG_NORMAL, "SNSD nodes loaded");
- else if (ret == -2)
- fatal("Malformed %s file", server_opt.snsd_nodes_file);
-
- return 0;
- }
-
- int
- andna_save_caches(void)
- {
- debug(DBG_NORMAL, "Saving the andna local cache");
- save_lcl_cache(andna_lcl, server_opt.lcl_file);
-
- debug(DBG_NORMAL, "Saving the andna cache");
- save_andna_cache(andna_c, server_opt.andna_cache_file);
-
- debug(DBG_NORMAL, "Saving the andna counter cache");
- save_counter_c(andna_counter_c, server_opt.counter_c_file);
-
- debug(DBG_NORMAL, "Saving the resolved hnames cache");
- save_rh_cache(andna_rhc, server_opt.rhc_file);
-
- return 0;
- }
-
- /*
- * andna_resolvconf_modify: modifies /etc/resolv.conf. See add_resolv_conf().
- */
- void
- andna_resolvconf_modify(void)
- {
- int ret;
- char *my_nameserv;
-
- if (!server_opt.disable_resolvconf) {
- loginfo("Modifying /etc/resolv.conf");
-
- my_nameserv =
- my_family == AF_INET ? MY_NAMESERV : MY_NAMESERV_IPV6;
- ret = add_resolv_conf(my_nameserv, ETC_RESOLV_CONF);
- if (ret < 0)
- error("It wasn't possible to modify %s, you have to add "
- "\"%s\" by yourself", ETC_RESOLV_CONF, my_nameserv);
- } else
- loginfo
- ("Modification of /etc/resolv.conf is disabled: do it by yourself.");
- }
-
- void
- andna_resolvconf_restore(void)
- {
- char *my_nameserv;
-
- /*
- * If there are valid nameserver in /etc/resolv.conf (excluding
- * "127.0.0.1", do not restore the backup. Probably /etc/resolv.conf
- * has been edited manually. Damn you, user! Why can't we code you ;)
- */
- reset_andns_ns();
- if (collect_resolv_conf(ETC_RESOLV_CONF) != -1)
- return;
- reset_andns_ns();
-
- my_nameserv = my_family == AF_INET ? MY_NAMESERV : MY_NAMESERV_IPV6;
- del_resolv_conf(my_nameserv, ETC_RESOLV_CONF);
- }
-
- void
- andna_init(void)
- {
- /* register the andna's ops in the pkt_op_table */
- add_pkt_op(ANDNA_REGISTER_HNAME, SKT_TCP, andna_tcp_port,
- andna_recv_reg_rq);
- add_pkt_op(ANDNA_CHECK_COUNTER, SKT_TCP, andna_tcp_port,
- andna_recv_check_counter);
- add_pkt_op(ANDNA_RESOLVE_HNAME, SKT_UDP, andna_udp_port,
- andna_recv_resolve_rq);
- add_pkt_op(ANDNA_RESOLVE_REPLY, SKT_UDP, andna_udp_port, 0);
- add_pkt_op(ANDNA_RESOLVE_IP, SKT_TCP, andna_tcp_port,
- andna_recv_rev_resolve_rq);
- add_pkt_op(ANDNA_REV_RESOLVE_REPLY, SKT_TCP, andna_tcp_port, 0);
- add_pkt_op(ANDNA_GET_ANDNA_CACHE, SKT_TCP, andna_tcp_port,
- put_andna_cache);
- add_pkt_op(ANDNA_PUT_ANDNA_CACHE, SKT_TCP, andna_tcp_port, 0);
- add_pkt_op(ANDNA_GET_COUNT_CACHE, SKT_TCP, andna_tcp_port,
- put_counter_cache);
- add_pkt_op(ANDNA_PUT_COUNT_CACHE, SKT_TCP, andna_tcp_port, 0);
- add_pkt_op(ANDNA_GET_SINGLE_ACACHE, SKT_UDP, andna_udp_port,
- put_single_acache);
- add_pkt_op(ANDNA_SPREAD_SACACHE, SKT_UDP, andna_udp_port,
- recv_spread_single_acache);
-
-
- if (!server_opt.disable_resolvconf)
- /* Restore resolv.conf if our backup is still there */
- andna_resolvconf_restore();
-
- pkt_queue_init();
-
- andna_caches_init(my_family);
- snsd_cache_init(my_family);
-
- /* Load the good old caches */
- andna_load_caches();
-
- if (!lcl_keyring.priv_rsa) {
- /*
- * No keyring was loaded, generate a new one save it
- */
- lcl_new_keyring(&lcl_keyring);
-
- debug(DBG_NORMAL, "Saving the new andna local keyring");
- save_lcl_keyring(&lcl_keyring, server_opt.lclkey_file);
- /**/}
-
- /* Init ANDNS */
- if (andns_init(restricted_mode, ETC_RESOLV_CONF, my_family) < 0)
- if (andns_init(restricted_mode, ETC_RESOLV_CONF_BAK, my_family) <
- 0) {
- error("In %s there isn't a single Internet nameserver.",
- ETC_RESOLV_CONF);
- loginfo("Internet hostname resolution is disabled");
- }
-
- setzero(last_reg_pkt_id, sizeof(int) * ANDNA_MAX_FLOODS);
- setzero(last_counter_pkt_id, sizeof(int) * ANDNA_MAX_FLOODS);
- setzero(last_spread_acache_pkt_id, sizeof(int) * ANDNA_MAX_FLOODS);
-
- /* Modify /etc/resolv.conf if requested */
- andna_resolvconf_modify();
- }
-
- void
- andna_close(void)
- {
- andna_save_caches();
- if (!server_opt.disable_resolvconf)
- andna_resolvconf_restore();
- andns_close();
- lcl_destroy_keyring(&lcl_keyring);
- lcl_cache_destroy(andna_lcl, &lcl_counter);
- andna_cache_destroy();
- counter_c_destroy();
- rh_cache_flush();
- pkt_queue_close();
- }
-
-
- /*
- *
- * * * * Hash_node search functions * * *
- *
- */
-
- /*
- * andna_hash_by_family
- *
- * If `family' is equal to AF_INET, in `hash' it stores the
- * 32bit hash of the `msg', otherwise it just copies `msg' to `hash_ip'.
- * Note that this function is used to hash other hashes, so it operates on the
- * ANDNA_HASH_SZ fixed length.
- */
- void
- andna_hash_by_family(int family, void *msg, u_int hash[MAX_IP_INT])
- {
- setzero(hash, ANDNA_HASH_SZ);
-
- if (family == AF_INET)
- hash[0] = fnv_32_buf((u_char *) msg, ANDNA_HASH_SZ, FNV1_32_INIT);
- else
- memcpy(hash, msg, ANDNA_HASH_SZ);
- }
-
- /*
- * andna_hash
- *
- * This function makes a digest of `msg' which is `len' bytes big and
- * stores it in `hash'.
- * If `family'is equal to AF_INET, in `ip_hash' it stores the 32bit hash
- * of the `hash', otherwise it just copies `hash' to `ip_hash'.
- *
- * Note: `hash' is a single string of `MAX_IP_INT'*4 bytes, it is the MD5 hash
- * of `msg', therefore do not attempt to convert it to network order.
- */
- void
- andna_hash(int family, void *msg, int len, u_int hash[MAX_IP_INT],
- u_int ip_hash[MAX_IP_INT])
- {
- hash_md5(msg, len, (u_char *) hash);
- andna_hash_by_family(family, (u_char *) hash, ip_hash);
- }
-
- /*
- * is_hgnode_excluded: it converts the `qg'->gid to an ip, then it searches a
- * member of `excluded_hgnode', which has all its gids, from the level `lvl` to
- * FAMILY_LVLS, equal to the ip. If it is found 1 is returned, otherwise 0
- * will be the return value.
- * This function is utilised by find_hash_gnode() to exclude from the search
- * the hash_gnodes not wanted.
- * All the `excluded_hgnode[x]' which are a null pointer are skipped.
- */
- int
- is_hgnode_excluded(quadro_group * qg, u_int ** excluded_hgnode,
- int tot_excluded_hgnodes, int lvl)
- {
- int i, e, x, total_levels = FAMILY_LVLS;
- inet_prefix ip;
-
- for (e = 0; e < tot_excluded_hgnodes; e++) {
- x = 0;
- if (!excluded_hgnode[e])
- continue;
-
- inet_setip_raw(&ip, excluded_hgnode[e], my_family);
- for (i = lvl; i < total_levels; i++) {
- #ifdef DEBUG
- debug(DBG_INSANE,
- "is_hgnode_excluded: l %d, qg->gid %d, ipgid %d", i,
- qg->gid[i], iptogid(&ip, i));
- #endif
- if (qg->gid[i] != iptogid(&ip, i)) {
- x = 1;
- break;
- }
- }
- if (!x)
- return 1;
- }
- return 0;
- }
-
- /*
- * is_hgnodeip_excluded: is a wrapper of is_hgnode_excluded() which takes as
- * first argv an inet_prefix instead of a quadro_group
- */
- int
- is_hgnodeip_excluded(inet_prefix * hgnodeip, u_int ** excluded_hgnode,
- int tot_excluded_hgnodes)
- {
- quadro_group qg;
-
- iptoquadg(*hgnodeip, 0, &qg, QUADG_GID);
- return is_hgnode_excluded(&qg, excluded_hgnode, tot_excluded_hgnodes,
- 0);
- }
-
- /*
- * random_gid_level_0: chooses a random gid of level 0, which is up, and
- * stores it in `qg'->gid[0], then convert it to an ip and stores it in `to'.
- * If `exclude_me' isn't zero, it won't choose ourself as the gid of level 0.
- * If the gid is found 0 is returned otherwise -1 is the return value.
- * If the gid found is also a MAP_ME node, 2 is returned.
- */
- int
- random_gid_level_0(quadro_group * qg, inet_prefix * to, int exclude_me)
- {
- int x, e, i;
-
- /*
- * Set `e' and `i' to a rand value from 0 to MAXGROUPNODE-1.
- * In the first for go from `e' to MAXGROUPNODE-1, if nothing is found
- * continue in the second for and go from `i' to 0. If nothing is
- * found return -1.
- */
-
- for (x = 0, e = i = rand_range(0, MAXGROUPNODE - 1); e < MAXGROUPNODE;
- e++) {
- if (!(me.int_map[e].flags & MAP_VOID)) {
- if (exclude_me && (me.int_map[e].flags & MAP_ME))
- continue;
- qg->gid[0] = e;
- x = 1;
- break;
- }
- }
- if (!x)
- for (x = 0; i >= 0; i--) {
- if (!(me.int_map[i].flags & MAP_VOID)) {
- if (exclude_me && (me.int_map[i].flags & MAP_ME))
- continue;
- qg->gid[0] = i;
- x = 1;
- break;
- }
- }
- if (x) {
- gidtoipstart(qg->gid, me.cur_quadg.levels, me.cur_quadg.levels,
- my_family, to);
- debug(DBG_NOISE, "find_hashgnode: Internal found: gid0 %d, to "
- "%s!", qg->gid[0], inet_to_str(*to));
- return me.int_map[qg->gid[0]].flags & MAP_ME ? 2 : 0;
- }
-
- return -1;
- }
-
- /*
- * find_hash_gnode_recurse: it recurse itself to create multiple sub tree. The
- * tree is started by find_hash_gnode()
- */
- int
- find_hash_gnode_recurse(quadro_group qg, int level, inet_prefix * to,
- u_int ** excluded_hgnode, int tot_excluded_hgnodes,
- int exclude_me)
- {
- int gid, i, e, steps, err, ret;
- map_gnode *gnode;
-
- if (!level)
- return random_gid_level_0(&qg, to, exclude_me);
-
- /*
- * This is how the ip nearer to `hash' is found:
- * - find_hash_gnode() calls, for the first time,
- * find_hash_gnode_recurse(). The hash's ip is converted as a
- * quadro_group and stored in the argv `qg' and the parameter `level'
- * is set to the number of total levels available minus one.
- * - if `level' is equal to 0 choose a random gid of level 0 an
- * convert `qg' in the inet_prefix format, store it in `to' and
- * return.
- * loop1:
- * - If the gnode `gq'.gid[level] is down increment or decrement
- * (alternatively) `gq'.gid[level] and continue the loop1.
- * If (it is up) {
- * if (`gq'.gid[level] is a gnode where we belong) {
- * call recursively find_hash_gnode_recurse,
- * giving the new modified `qg' and `level'-1 as
- * new parametres.
- * If (the return value is not an error) {
- * return now with that value because in
- * a sub tree, the hash_gnode was already
- * found.
- * }
- * } otherwise {
- * return and stor into `to' the ip of the
- * border_node that will be used to forward the
- * pkt to the hash_gnode.
- * }
- * }
- * - return -1
- */
-
- #if 0 /* TOO NOISY */
- debug(DBG_INSANE, "find_hashgnode: lvl %d, start gid %d", level,
- qg.gid[level]);
- #endif
-
- /* the maximum steps required to complete the for. */
- steps =
- qg.gid[level] >=
- MAXGROUPNODE / 2 ? qg.gid[level] : MAXGROUPNODE - qg.gid[level];
-
- for (i = 0, e = 1, gid = qg.gid[level]; i < steps;
- e & 1 ? i++ : i, e = (~(e & 1)) & 1) {
- /* `i' is incremented only when `e' is odd, while `e'
- * is always alternated between 0 and 1. */
-
- if (!(e & 1) && (qg.gid[level] + i < MAXGROUPNODE))
- gid = qg.gid[level] + i;
- else if (qg.gid[level] - i >= 0)
- gid = qg.gid[level] - i;
- else
- continue;
-
- gnode = gnode_from_pos(gid, me.ext_map[_EL(level)]);
- if (!(gnode->g.flags & MAP_VOID) && !(gnode->flags & GMAP_VOID)) {
- qg.gid[level] = gid;
-
- #if 0 /* TOO NOISY */
- debug(DBG_NOISE, "find_hashgnode: lvl %d gid %d", level,
- qg.gid[level]);
- #endif
-
- if (!quadg_gids_cmp(qg, me.cur_quadg, level)) {
- /* Is this hash_gnode not wanted ? */
- if (excluded_hgnode && level == 1 &&
- is_hgnode_excluded(&qg, excluded_hgnode,
- tot_excluded_hgnodes, 1))
- continue; /* yea, exclude it */
-
- ret =
- find_hash_gnode_recurse(qg, level - 1, to,
- excluded_hgnode,
- tot_excluded_hgnodes,
- exclude_me);
- if (ret != -1)
- /* We have found it in some sub trees. */
- return ret;
- } else {
- /* Check if it is excluded */
- if (excluded_hgnode &&
- is_hgnode_excluded(&qg, excluded_hgnode,
- tot_excluded_hgnodes, level))
- continue; /* Yes, it is */
-
- err = get_gw_ips(me.int_map, me.ext_map, me.bnode_map,
- me.bmap_nodes, &me.cur_quadg,
- gnode, level, 0, to, 0, 1);
- debug(DBG_NOISE,
- "find_hashgnode: ext_found, err %d, to %s!", err,
- inet_to_str(*to));
-
- if (err >= 0)
- /*
- * Forward the pkt to the found
- * border_node, which will forward it
- * to the hash_gnode
- */
- return 1;
- }
- }
-
- } /* for(...) */
-
-
- #if 0 /* TOO NOISY */
- debug(DBG_INSANE, "find_hashgnode: Exausted: lvl %d gid %d", level,
- qg.gid[level]);
- #endif
- /* We didn't find anything in the this level, so
- * returns from this tree */
- return -1;
- }
-
- /*
- * find_hash_gnode: It stores in `to' the ip of the node nearer to the
- * `hash'_gnode and returns 0. If we aren't part of the hash_gnode, it sets in
- * `to' the ip of the bnode_gnode that will route the pkt and returns 1.
- * If the found hash_gnode is the MAP_ME node itself then 2 is returned.
- * If either a hash_gnode and a bnode_gnode aren't found, -1 is returned.
- * All the hash_gnodes included in `excluded_hgnode' will be excluded by the
- * algorithm.
- * If `exclude_me' is set to 1, it will not return ourself as the hash_gnode.
- */
- int
- find_hash_gnode(u_int hash[MAX_IP_INT], inet_prefix * to,
- u_int ** excluded_hgnode, int tot_excluded_hgnodes,
- int exclude_me)
- {
- int total_levels;
- quadro_group qg;
-
- total_levels = FAMILY_LVLS;
-
- /* Hash to ip and quadro_group conversion */
- inet_setip(to, hash, my_family);
- inet_htonl(to->data, to->family);
- iptoquadg(*to, me.ext_map, &qg, QUADG_GID | QUADG_GNODE);
-
-
- return find_hash_gnode_recurse(qg, total_levels - 1, to,
- excluded_hgnode, tot_excluded_hgnodes,
- exclude_me);
- }
-
-
- /*
- *
- * * * * Packets * * *
- *
- */
-
- /*
- * andna_flood_pkt: Sends the `rpkt' pkt to all the rnodes of our same gnode
- * and exclude the the rpkt->from node if `exclude_rfrom' is non zero.
- * The return value of flood_pkt_send() is returned.
- */
- int
- andna_flood_pkt(PACKET * rpkt, int exclude_rfrom)
- {
- PACKET flood_pkt;
- int real_from_rpos = -1, ret;
- int (*exclude_function) (TRACER_PKT_EXCLUDE_VARS);
-
- pkt_copy(&flood_pkt, rpkt);
- flood_pkt.sk = 0;
- /* be sure that the other nodes don't reply to rfrom again */
- flood_pkt.hdr.flags &= ~ASYNC_REPLY;
- flood_pkt.hdr.flags |= BCAST_PKT;
-
- /* If the pkt was sent from an our rnode, ignore it while flooding */
- if (exclude_rfrom)
- real_from_rpos = ip_to_rfrom(flood_pkt.from, 0, 0, 0);
- if (real_from_rpos < 0 || !exclude_rfrom) {
- exclude_function = exclude_glevel;
- real_from_rpos = -1;
- } else
- exclude_function = exclude_from_and_glevel;
- ret =
- flood_pkt_send(exclude_function, 1, -1, real_from_rpos, flood_pkt);
-
- return ret;
- }
-
- /*
- * andna_find_flood_pkt_id: Search in the `ids_array' a member which is equal
- * to `pkt_id', if it is found its array position is returned otherwise -1
- * will be the return value
- */
- int
- andna_find_flood_pkt_id(int *ids_array, int pkt_id)
- {
- int i;
-
- for (i = 0; i < ANDNA_MAX_FLOODS; i++)
- if (ids_array[i] == pkt_id)
- return i;
- return -1;
- }
-
- /*
- * andna_add_flood_pkt_id: If the `pkt_id' is already present in the
- * `ids_array', 1 is returned, otherwise `pkt_id' is added at the 0 position
- * of the array. All the array elements, except the last one, will be
- * preserved and shifted of one position like a FIFO.
- */
- int
- andna_add_flood_pkt_id(int *ids_array, int pkt_id)
- {
- int i;
-
- if ((i = andna_find_flood_pkt_id(ids_array, pkt_id)) < 0) {
- int tmp_array[ANDNA_MAX_FLOODS - 1];
-
- /* Shift the array of one position to free the position 0
- * where the new id will be added */
- memcpy(tmp_array, ids_array, sizeof(int) * (ANDNA_MAX_FLOODS - 1));
- memcpy(&ids_array[1], tmp_array,
- sizeof(int) * (ANDNA_MAX_FLOODS - 1));
- ids_array[0] = pkt_id;
-
- return 0;
- }
-
- return 1;
- }
-
-
- /*
- *
- * * * * Hostname registration * * *
- *
- */
-
- /*
- * andna_register_hname
- *
- * Registers or updates the `alcl->hostname' hostname. It also registers the
- * snsd records present in `alcl->service'.
- *
- * If `snsd_delete' is not null, the registration request becomes a deletion
- * request: it will ask to andna to delete all the snsd records equal to
- * `snsd_delete'.
- */
- int
- andna_register_hname(lcl_cache * alcl, snsd_service * snsd_delete)
- {
- PACKET pkt, rpkt;
- struct andna_reg_pkt req;
- u_int hash_gnode[MAX_IP_INT];
- inet_prefix to;
-
- snsd_service *snsd;
- char *sign = 0, *buf;
- const char *ntop;
- int ret = 0;
- ssize_t err, pkt_sz = 0;
- time_t cur_t;
-
- setzero(&req, sizeof(req));
- setzero(&pkt, sizeof(pkt));
- setzero(&rpkt, sizeof(rpkt));
- cur_t = time(0);
-
- if (alcl->flags & ANDNA_UPDATING)
- /* we are already updating this node! */
- return 0;
-
- alcl->flags |= ANDNA_UPDATING;
-
- if (alcl->timestamp) {
- if (cur_t > alcl->timestamp &&
- (cur_t - alcl->timestamp) < ANDNA_MIN_UPDATE_TIME)
- /* We have too wait a little more before sending an
- * update */
- return -1;
-
- req.flags |= ANDNA_PKT_UPDATE;
- req.hname_updates = ++alcl->hname_updates;
- }
-
- /* Don't register the hname while we are (re)-hooking,
- * our IP might change */
- while (me.cur_node->flags & MAP_HNODE)
- sleep(1);
-
- /*
- * Filling the request structure
- */
-
- inet_copy_ipdata(req.rip, &me.cur_ip);
- andna_hash(my_family, alcl->hostname, strlen(alcl->hostname),
- req.hash, hash_gnode);
- memcpy(req.pubkey, lcl_keyring.pubkey, ANDNA_PKEY_LEN);
-
- /* Convert the pkt from host to network order */
- ints_host_to_network((void *) &req, andna_reg_pkt_iinfo);
-
- /* Sign the packet */
- sign = (char *) rsa_sign((u_char *) & req, ANDNA_REG_SIGNED_BLOCK_SZ,
- lcl_keyring.priv_rsa, 0);
- memcpy(req.sign, sign, ANDNA_SIGNATURE_LEN);
-
- /* Find the hash_gnode that corresponds to the hash `hash_gnode' */
- if ((err = find_hash_gnode(hash_gnode, &to, 0, 0, 1)) < 0) {
- debug(DBG_SOFT, "andna_register_hname: hash_gnode not found ;(");
- ERROR_FINISH(ret, -1, finish);
- } else if (err == 1)
- req.flags |= ANDNA_PKT_FORWARD;
-
- if (snsd_delete) {
- snsd = snsd_delete;
- req.flags |= ANDNA_PKT_SNSD_DEL;
- } else
- snsd = alcl->service;
-
- ntop = inet_to_str(to);
- debug(DBG_INSANE, "Quest %s to %s", rq_to_str(ANDNA_REGISTER_HNAME),
- ntop);
-
- /* Fill the packet and send the request */
- pkt_sz = ANDNA_REG_PKT_SZ + SNSD_SERVICE_LLIST_PACK_SZ(alcl->service);
- pkt_addto(&pkt, &to);
- pkt_addcompress(&pkt);
- pkt_fill_hdr(&pkt.hdr, ASYNC_REPLY, 0, ANDNA_REGISTER_HNAME, pkt_sz);
-
- pkt.msg = buf = xmalloc(pkt_sz);
-
- memcpy(pkt.msg, &req, ANDNA_REG_PKT_SZ);
- buf += ANDNA_REG_PKT_SZ;
-
- if (snsd_pack_all_services(buf, pkt_sz - ANDNA_REG_PKT_SZ, snsd) < 0) {
- debug(DBG_SOFT, "andna_register_hname: couldn't pack "
- "alcl->service");
- ERROR_FINISH(ret, -1, finish);
- }
-
- err =
- send_rq(&pkt, 0, ANDNA_REGISTER_HNAME, 0, ACK_AFFERMATIVE, 1,
- &rpkt);
- if (err < 0) {
- error("andna_register_hname(): Registration of \"%s\" to %s "
- "failed.", alcl->hostname, ntop);
- ERROR_FINISH(ret, -1, finish);
- }
-
- /* Ehi, we've registered it! Update the hname timestamp */
- alcl->timestamp = cur_t;
-
- finish:
- alcl->flags &= ~ANDNA_UPDATING;
- if (sign)
- xfree(sign);
- pkt_free(&pkt, 1);
- pkt_free(&rpkt, 0);
- return ret;
- }
-
- /*
- * andna_recv_reg_rq
- *
- * It takes care of a registration request. If we aren't
- * the rightful hash_gnode, we forward the request (again), otherwise the
- * request is examined. If it is valid the hostname is registered or updated
- * in the andna_cache.
- */
- int
- andna_recv_reg_rq(PACKET rpkt)
- {
- PACKET pkt, rpkt_local_copy;
- struct andna_reg_pkt *req;
- u_int hash_gnode[MAX_IP_INT], *excluded_hgnode[1];
- inet_prefix rfrom, to;
-
- RSA *pubkey = 0;
- andna_cache_queue *acq = 0;
- andna_cache *ac = 0;
- snsd_service *snsd_unpacked = 0;
- snsd_node *snd = 0;
-
- time_t cur_t;
- u_short snsd_counter;
- int ret = 0, err;
- size_t unpacked_sz, packed_sz;
- char *ntop = 0, *rfrom_ntop = 0, *snsd_pack;
- u_char forwarded_pkt = 0;
- const u_char *pk;
-
- pkt_copy(&rpkt_local_copy, &rpkt);
-
- req = (struct andna_reg_pkt *) rpkt_local_copy.msg;
- if (rpkt.hdr.sz < ANDNA_REG_PKT_SZ ||
- rpkt.hdr.sz > SNSD_SERVICE_MAX_LLIST_PACK_SZ)
- ERROR_FINISH(ret, -1, finish);
-
- packed_sz = rpkt.hdr.sz - ANDNA_REG_PKT_SZ;
- snsd_pack = rpkt_local_copy.msg + ANDNA_REG_PKT_SZ;
-
- if (rpkt.hdr.flags & BCAST_PKT)
- /* The pkt we received has been only forwarded to us */
- forwarded_pkt = 1;
-
- /* Check if we already received this pkt during the flood */
- if (forwarded_pkt &&
- andna_add_flood_pkt_id(last_reg_pkt_id, rpkt.hdr.id)) {
- debug(DBG_INSANE, "Dropped 0x%0x andna pkt, we already "
- "received it", rpkt.hdr.id);
- ERROR_FINISH(ret, 0, finish);
- }
-
- /* Save the real sender of the request */
- inet_setip(&rfrom, req->rip, my_family);
-
- ntop = xstrdup(inet_to_str(rpkt.from));
- rfrom_ntop = xstrdup(inet_to_str(rfrom));
- debug(DBG_SOFT, "Received %s%sfrom %s, rfrom %s",
- rq_to_str(rpkt.hdr.op), forwarded_pkt ? " (forwarded) " : " ",
- ntop, rfrom_ntop);
-
- memcpy(&pkt, &rpkt, sizeof(PACKET));
- inet_copy(&pkt.from, &rfrom);
-
- /* Send the replies in UDP, they are so tiny */
- pkt_addsk(&pkt, my_family, 0, SKT_UDP);
-
- /* Verify the signature */
- pk = (const u_char *) req->pubkey;
- pubkey = get_rsa_pub(&pk, ANDNA_PKEY_LEN);
- if (!pubkey || !verify_sign((u_char *) req, ANDNA_REG_SIGNED_BLOCK_SZ,
- (u_char *) req->sign, ANDNA_SIGNATURE_LEN,
- pubkey)) {
- /* Bad, bad signature */
- debug(DBG_SOFT, "Invalid signature of the 0x%x reg request",
- rpkt.hdr.id);
- if (!forwarded_pkt)
- pkt_err(pkt, E_INVALID_SIGNATURE, 0);
- ERROR_FINISH(ret, -1, finish);
- }
-
- /* Revert the packet from network to host order */
- ints_network_to_host((void *) req, andna_reg_pkt_iinfo);
-
- /* If we don't belong to the gnode of `rfrom', then we have to exclude
- * it from the find_hash_gnode search, since we have received the
- * pkt from that gnode and it is likely that `rfrom' is the only node
- * of that gnode.
- */
- excluded_hgnode[0] = ip_gids_cmp(rfrom, me.cur_ip, 1) ? rfrom.data : 0;
-
- /*
- * Are we the hash_gnode for req->hash? Check also if we have to
- * continue to forward the pkt to make it reach the real hash_gnode
- */
-
- andna_hash_by_family(my_family, (u_char *) req->hash, hash_gnode);
- if ((err =
- find_hash_gnode(hash_gnode, &to, excluded_hgnode, 1, 0)) < 0) {
- debug(DBG_SOFT,
- "We are not the right (rounded)hash_gnode. "
- "Rejecting the 0x%x reg request", rpkt.hdr.id);
- if (!forwarded_pkt)
- pkt_err(pkt, E_ANDNA_WRONG_HASH_GNODE, 0);
- ERROR_FINISH(ret, -1, finish);
- } else if (err == 1) {
- if (!(req->flags & ANDNA_PKT_FORWARD)) {
- if (!forwarded_pkt)
- pkt_err(pkt, E_ANDNA_WRONG_HASH_GNODE, 0);
- ERROR_FINISH(ret, -1, finish);
- }
-
- /* Continue to forward the received pkt */
- debug(DBG_SOFT, "The reg request pkt will be forwarded to: %s",
- inet_to_str(to));
- ret = forward_pkt(rpkt, to);
- goto finish;
- }
-
- /* Are we a new hash_gnode ? */
- if (time(0) - me.uptime < (ANDNA_EXPIRATION_TIME / 3) &&
- !(ac = andna_cache_findhash((int *) req->hash))) {
- /*
- * We are a new hash_gnode and we haven't this hostname in our
- * andna_cache, so we have to check if there is an
- * old hash_gnode which has already registered this hostname.
- */
- if ((ac = get_single_andna_c(req->hash, hash_gnode))) {
- /*
- * The hostname was already registered, so we save it
- * in our andna_cache.
- */
- clist_add(&andna_c, &andna_c_counter, ac);
-
- /* Spread it in our gnode */
- spread_single_acache(req->hash);
- }
- }
-
- /* Ask the counter_node if it is ok to register/update the hname */
- if (!(req->flags & ANDNA_PKT_SNSD_DEL)) {
- if (andna_check_counter(rpkt) == -1) {
- debug(DBG_SOFT, "Registration rq 0x%x rejected: %s",
- rpkt.hdr.id, rq_strerror(E_ANDNA_CHECK_COUNTER));
- if (!forwarded_pkt)
- pkt_err(pkt, E_ANDNA_CHECK_COUNTER, 0);
- ERROR_FINISH(ret, -1, finish);
- }
- }
-
- /***
- * Finally, let's register/update the hname
- */
- cur_t = time(0);
- ac = andna_cache_addhash((int *) req->hash);
- acq = ac_queue_add(ac, req->pubkey);
- if (!acq) {
- debug(DBG_SOFT, "Registration rq 0x%x rejected: %s",
- rpkt.hdr.id, rq_strerror(E_ANDNA_QUEUE_FULL));
- if (!forwarded_pkt)
- pkt_err(pkt, E_ANDNA_QUEUE_FULL, 0);
- ERROR_FINISH(ret, -1, finish);
- }
- /***/
-
- /**
- * Check if the counter of number of updates matches with the pkt */
- if (acq->hname_updates > req->hname_updates) {
- debug(DBG_SOFT, "Registration rq 0x%x rejected: hname_updates"
- " mismatch %d > %d", rpkt.hdr.id,
- acq->hname_updates, req->hname_updates);
- if (!forwarded_pkt)
- pkt_err(pkt, E_ANDNA_HUPDATE_MISMATCH, 0);
- ERROR_FINISH(ret, -1, finish);
- }
- /**/
- /**
- * Has the registration request been sent too early ? */
- if (cur_t > acq->timestamp &&
- (cur_t - acq->timestamp) < ANDNA_MIN_UPDATE_TIME) {
- debug(DBG_SOFT, "Registration rq 0x%x rejected: %s",
- rpkt.hdr.id, rq_strerror(E_ANDNA_UPDATE_TOO_EARLY));
- if (!forwarded_pkt)
- pkt_err(pkt, E_ANDNA_UPDATE_TOO_EARLY, 0);
- ERROR_FINISH(ret, -1, finish);
- }
- /**/
- /*
- * SNSD services registration
- */
- if (acq != ac->acq) {
- /*
- * This request has been queued in the acq. We store the main
- * ip and discard the rest of the snsd records
- */
- snsd_add_mainip(&snsd_unpacked, &snsd_counter,
- SNSD_MAX_QUEUE_RECORDS,
- (uintptr_t*)rfrom.data);
- } else {
- /*
- * Register the snsd records
- */
-
- /* unpack the snsd services */
- snsd_unpacked = snsd_unpack_all_service(snsd_pack, packed_sz,
- &unpacked_sz,
- &snsd_counter);
-
- if ((!snsd_unpacked && req->flags & ANDNA_PKT_SNSD_DEL) ||
- (snsd_counter > SNSD_MAX_RECORDS - 1)) {
-
- debug(DBG_SOFT,
- "Registration rq 0x%x rejected: couldn't unpack"
- " the snsd llist", rpkt.hdr.id);
- if (!forwarded_pkt)
- pkt_err(pkt, E_INVALID_REQUEST, 0);
- ERROR_FINISH(ret, -1, finish);
- }
-
- if (req->flags & ANDNA_PKT_SNSD_DEL) {
- /*
- * Delete, from the andna_cache, all the snsd records
- * which are equal to those included in the
- * registration pkt.
- */
- snsd_record_del_selected(&acq->service, &acq->snsd_counter,
- snsd_unpacked);
- } else {
- /*
- * Register the snsd services in our andna_cache
- */
-
- /* Add the mainip and update its IP */
- snd = snsd_add_mainip(&snsd_unpacked, &snsd_counter,
- SNSD_MAX_RECORDS,
- (uintptr_t*)rfrom.data);
- inet_copy_ipdata_raw((u_int*)snd->record, &rfrom);
-
- /**
- * Set the mainip flag only to the real mainip record,
- * in this way we're sure that there is only one. */
- snsd_unset_all_flags(snsd_unpacked, SNSD_NODE_MAIN_IP);
- snd->flags |= SNSD_NODE_MAIN_IP;
- /**/}
- }
-
- /*
- * substitute the old snsd records with the new ones
- */
- snsd_service_llist_del(&acq->service);
- acq->service = snsd_unpacked;
- acq->snsd_counter = snsd_counter;
-
- /*
- * Final registration step: touch the hname timestamp
- */
- acq->hname_updates = req->hname_updates + 1;
- acq->timestamp = cur_t;
-
- /* Reply to the requester: <<Yes, don't worry, it worked.>> */
- if (!forwarded_pkt) {
- debug(DBG_SOFT, "Registration rq 0x%x accepted.", rpkt.hdr.id);
- pkt.msg = 0;
- pkt_fill_hdr(&pkt.hdr, ASYNC_REPLIED, rpkt.hdr.id, ACK_AFFERMATIVE,
- 0);
- ret = forward_pkt(pkt, rfrom);
- }
-
- /**
- * Broadcast the request to the entire gnode of level 1 to let the
- * other nodes register the hname.
- */
- if (!forwarded_pkt)
- andna_add_flood_pkt_id(last_reg_pkt_id, rpkt.hdr.id);
- andna_flood_pkt(&rpkt, 1);
- /**/ finish:
- if (ntop)
- xfree(ntop);
- if (rfrom_ntop)
- xfree(rfrom_ntop);
- if (pubkey)
- RSA_free(pubkey);
- pkt_free(&rpkt_local_copy, 0);
-
- return ret;
- }
-
- /*
- * andna_check_counter
- *
- * asks the counter_node if it is ok to accept the registration request in
- * `pkt' and register the requested hname.
- *
- * If -1 is returned the answer is no.
- */
- int
- andna_check_counter(PACKET pkt)
- {
- PACKET rpkt;
- int ret = 0, err;
- u_int rip_hash[MAX_IP_INT], hash_gnode[MAX_IP_INT];
- struct andna_reg_pkt *req;
- const char *ntop;
- u_char forwarded_pkt = 0;
-
- setzero(&rpkt, sizeof(PACKET));
- req = (struct andna_reg_pkt *) pkt.msg;
- pkt.msg = 0;
-
- if (pkt.hdr.flags & BCAST_PKT)
- forwarded_pkt = 1;
-
- /* Calculate the hash of the IP of the sender node. This hash will
- * be used to reach its counter node. */
- andna_hash(my_family, req->rip, MAX_IP_SZ, rip_hash, hash_gnode);
-
- /* Find a hash_gnode for the rip_hash */
- req->flags &= ~ANDNA_PKT_FORWARD;
-
- if ((err = find_hash_gnode(hash_gnode, &pkt.to, 0, 0, 1)) < 0) {
- debug(DBG_INSANE, "andna_check_counter: Couldn't find a decent"
- " counter_gnode");
- ERROR_FINISH(ret, -1, finish);
- } else if (err == 1)
- req->flags |= ANDNA_PKT_FORWARD;
-
- ntop = inet_to_str(pkt.to);
- debug(DBG_INSANE, "Quest %s to %s", rq_to_str(ANDNA_CHECK_COUNTER),
- ntop);
-
- pkt.hdr.flags |= ASYNC_REPLY;
-
- /* Append our ip in the pkt */
- pkt.hdr.sz = ANDNA_REG_PKT_SZ + MAX_IP_SZ;
- pkt.msg = xmalloc(pkt.hdr.sz);
- memcpy(pkt.msg, req, ANDNA_REG_PKT_SZ);
- inet_copy_ipdata((u_int *) (pkt.msg + ANDNA_REG_PKT_SZ), &me.cur_ip);
-
- /* If we are checking a registration pkt which has been only
- * forwarded to us (and already registered), we tell the counter_node
- * to just check the request. We don't want it to update its
- * hname_updates counter */
- if (forwarded_pkt) {
- req = (struct andna_reg_pkt *) pkt.msg;
- req->flags |= ANDNA_PKT_JUST_CHECK;
-
- /* Adjust the flags */
- pkt.hdr.flags &= ~BCAST_PKT;
- }
-
- /* Throw it */
- pkt.sk = 0; /* Create a new connection */
- ret =
- send_rq(&pkt, 0, ANDNA_CHECK_COUNTER, 0, ACK_AFFERMATIVE, 1,
- &rpkt);
- ret = (ret < 0) ? -1 : ret;
-
- finish:
- pkt_free(&pkt, 1);
- pkt_free(&rpkt, 0);
- return ret;
- }
-
- int
- andna_recv_check_counter(PACKET rpkt)
- {
- PACKET pkt, rpkt_local_copy;
- struct andna_reg_pkt *req;
- inet_prefix rfrom, to;
- RSA *pubkey = 0;
- counter_c *cc;
- counter_c_hashes *cch;
- u_int rip_hash[MAX_IP_INT], hash_gnode[MAX_IP_INT],
- *excluded_hgnode[1];
- int ret = 0, err, old_updates;
-
- char *ntop = 0, *rfrom_ntop = 0, *buf;
- u_char forwarded_pkt = 0, just_check = 0;
- const u_char *pk;
-
- pkt_copy(&rpkt_local_copy, &rpkt);
- ntop = xstrdup(inet_to_str(rpkt.from));
-
- req = (struct andna_reg_pkt *) rpkt_local_copy.msg;
- if (rpkt.hdr.sz != ANDNA_REG_PKT_SZ + MAX_IP_SZ) {
- debug(DBG_SOFT,
- ERROR_MSG "Malformed check_counter pkt from %s: %d != %d",
- ERROR_FUNC, ntop, rpkt.hdr.sz, ANDNA_REG_PKT_SZ + MAX_IP_SZ);
- ERROR_FINISH(ret, -1, finish);
- }
-
- if (rpkt.hdr.flags & BCAST_PKT)
- /* The pkt we received has been only forwarded to us */
- forwarded_pkt = 1;
-
- if (req->flags & ANDNA_PKT_JUST_CHECK)
- just_check = 1;
-
- /* Check if we already received this pkt during the flood */
- if (forwarded_pkt &&
- andna_add_flood_pkt_id(last_counter_pkt_id, rpkt.hdr.id)) {
- debug(DBG_INSANE, "Dropped 0x%0x andna pkt, we already "
- "received it", rpkt.hdr.id);
- ERROR_FINISH(ret, 0, finish);
- }
-
- /* Save the real sender of the request */
- buf = rpkt.msg + ANDNA_REG_PKT_SZ;
- inet_setip(&rfrom, (u_int *) buf, my_family);
-
- rfrom_ntop = xstrdup(inet_to_str(rfrom));
- debug(DBG_SOFT, "Received %s%sfrom %s, rfrom %s",
- rq_to_str(rpkt.hdr.op), forwarded_pkt ? " (forwarded) " : " ",
- ntop, rfrom_ntop);
-
- memcpy(&pkt, &rpkt, sizeof(PACKET));
- inet_copy(&pkt.from, &rfrom);
-
- /* Reply to rfrom using a UDP sk, since the replies are very small */
- pkt_addsk(&pkt, my_family, 0, SKT_UDP);
-
- /* Verify the signature */
- pk = (const u_char *) req->pubkey;
- pubkey = get_rsa_pub(&pk, ANDNA_PKEY_LEN);
- if (!pubkey || !verify_sign((u_char *) req, ANDNA_REG_SIGNED_BLOCK_SZ,
- (u_char *) req->sign, ANDNA_SIGNATURE_LEN,
- pubkey)) {
- /* Bad signature */
- debug(DBG_SOFT, "Invalid signature of the 0x%x check "
- "counter request", rpkt.hdr.id);
- if (!forwarded_pkt)
- pkt_err(pkt, E_INVALID_SIGNATURE, 0);
- ERROR_FINISH(ret, -1, finish);
- }
-
- /* Revert the packet from network to host order */
- ints_network_to_host((void *) req, andna_reg_pkt_iinfo);
-
- /* If don't belong to the gnode of `rfrom', then we have to exclude
- * it from the find_hash_gnode search, since we have received the
- * pkt from that gnode and it is likely that `rfrom' is the only node
- * of that gnode.
- */
- excluded_hgnode[0] = ip_gids_cmp(rfrom, me.cur_ip, 1) ? rfrom.data : 0;
- debug(DBG_INSANE, "excluded_hgnode: %x ", excluded_hgnode[0]);
-
- /*
- * Check if we are the real counter node or if we have to continue to
- * forward the pkt
- */
-
- andna_hash(my_family, req->rip, MAX_IP_SZ, rip_hash, hash_gnode);
- if ((err =
- find_hash_gnode(hash_gnode, &to, excluded_hgnode, 1, 0)) < 0) {
- debug(DBG_SOFT,
- "We are not the real (rounded)hash_gnode. "
- "Rejecting the 0x%x check_counter request", rpkt.hdr.id);
- if (!forwarded_pkt)
- pkt_err(pkt, E_ANDNA_WRONG_HASH_GNODE, 0);
- ERROR_FINISH(ret, -1, finish);
- } else if (err == 1) {
- if (!(req->flags & ANDNA_PKT_FORWARD)) {
- if (!forwarded_pkt)
- pkt_err(pkt, E_ANDNA_WRONG_HASH_GNODE, 0);
- ERROR_FINISH(ret, -1, finish);
- }
-
- /* Continue to forward the received pkt */
- debug(DBG_SOFT, "The check_counter rq pkt will be forwarded "
- "to: %s", inet_to_str(to));
- ret = forward_pkt(rpkt, to);
- goto finish;
- }
-
- /* Finally, let's register/update the hname */
- cc = counter_c_add(&rfrom, req->pubkey);
- if (!just_check)
- cch = cc_hashes_add(cc, (int *) req->hash);
- else
- cch = cc_findhash(cc, (int *) req->hash);
- if (!cch) {
- debug(DBG_SOFT, "Request %s (0x%x) rejected: %s",
- rq_to_str(rpkt.hdr.op), rpkt.hdr.id,
- rq_strerror(E_ANDNA_TOO_MANY_HNAME));
- if (!forwarded_pkt)
- pkt_err(pkt, E_ANDNA_TOO_MANY_HNAME, 0);
- ERROR_FINISH(ret, -1, finish);
- }
-
- old_updates = cch->hname_updates;
- old_updates -= ! !just_check;
- if (old_updates > req->hname_updates) {
- debug(DBG_SOFT, "Request %s (0x%x) rejected: hname_updates"
- " mismatch %d > %d", rq_to_str(rpkt.hdr.op), rpkt.hdr.id,
- old_updates, req->hname_updates);
- if (!forwarded_pkt)
- pkt_err(pkt, E_ANDNA_HUPDATE_MISMATCH, 0);
- ERROR_FINISH(ret, -1, finish);
- } else if (!just_check) {
- /* Touch the hname */
- cch->hname_updates = req->hname_updates + 1;
- cch->timestamp = time(0);
- }
-
- /* Report the successful result to rfrom */
- if (!forwarded_pkt || just_check) {
- debug(DBG_SOFT, "Check_counter rq 0x%x accepted.", rpkt.hdr.id);
- pkt_fill_hdr(&pkt.hdr, ASYNC_REPLIED, rpkt.hdr.id,
- ACK_AFFERMATIVE, 0);
- pkt.msg = 0;
- ret = forward_pkt(pkt, rfrom);
- }
-
- /*
- * Broadcast the request to the entire gnode of level 1 to let the
- * other counter_nodes register the hname.
- */
- if (!just_check) {
- if (!forwarded_pkt)
- andna_add_flood_pkt_id(last_counter_pkt_id, rpkt.hdr.id);
- andna_flood_pkt(&rpkt, forwarded_pkt);
- }
-
- finish:
- if (ntop)
- xfree(ntop);
- if (rfrom_ntop)
- xfree(rfrom_ntop);
- if (pubkey)
- RSA_free(pubkey);
- pkt_free(&rpkt_local_copy, 0);
-
- return ret;
- }
-
-
- /*
- *
- * * * * Hostname/IP resolution * * *
- *
- */
-
- /*
- * andna_resolve_hash_locally
- *
- * It tries to resolve the given md5 hname-hash by searching in the
- * local andna caches.
- * It uses the same arguments of `andna_resolve_hash' see below).
- */
- snsd_service *
- andna_resolve_hash_locally(u_int hname_hash[MAX_IP_INT], int service,
- u_char proto, int *records)
- {
- struct andna_resolve_rq_pkt req;
- lcl_cache *lcl;
- rh_cache *rhc;
- andna_cache *ac;
- snsd_service *ret;
- u_int hash;
-
- setzero(&req, sizeof(req));
-
- hash = fnv_32_buf(hname_hash, ANDNA_HASH_SZ, FNV1_32_INIT);
-
- #ifndef ANDNA_DEBUG
-
- /*
- * Search the hostname in the local cache first. Maybe we are so
- * dumb that we are trying to resolve the same ip we registered.
- */
- if ((lcl = lcl_cache_find_hash(andna_lcl, hash))) {
- u_short fake_counter = 0;
-
- *records = lcl->snsd_counter;
- ret = snsd_service_llist_copy(lcl->service, service, proto);
-
- /* Add our current main ip */
- if (service == SNSD_ALL_SERVICE ||
- service == SNSD_DEFAULT_SERVICE || !ret)
- snsd_add_mainip(&ret, &fake_counter,
- SNSD_MAX_RECORDS,
- (uintptr_t*)me.cur_ip.data);
- return ret;
- }
-
- /*
- * Last try before asking to ANDNA: let's see if we have it in
- * the resolved_hnames cache
- */
- if ((rhc = rh_cache_find_hash(hash))) {
- *records = rhc->snsd_counter;
- ret = snsd_service_llist_copy(rhc->service, service, proto);
-
- if (!ret && (service != SNSD_ALL_SERVICE) &&
- (service != SNSD_DEFAULT_SERVICE))
- /* The specific service hasn't been found, fallback to
- * SNSD_DEFAULT_SERVICE */
- ret = snsd_service_llist_copy(rhc->service,
- SNSD_DEFAULT_SERVICE, 0);
- if (ret)
- return ret;
- }
- #endif
-
- /*
- * If we manage an andna_cache, it's better to peek at it.
- */
- if ((ac = andna_cache_gethash((int *) hname_hash))) {
- *records = ac->acq->snsd_counter;
-
- ret = snsd_service_llist_copy(ac->acq->service, service, proto);
-
- if (!ret && (service != SNSD_ALL_SERVICE) &&
- (service != SNSD_DEFAULT_SERVICE))
- /* The specific service hasn't been found, fallback to
- * SNSD_DEFAULT_SERVICE */
- ret = snsd_service_llist_copy(ac->acq->service,
- SNSD_DEFAULT_SERVICE, 0);
- if (ret)
- return ret;
- }
-
- return 0;
- }
-
- /*
- * andna_resolve_hash
- *
- * It returns a snsd_service llist (see snsd.h) which contains the snsd
- * records of the resolved hostname. Among them there's at least the mainip
- * record which can be found using snsd_find_mainip().
- *
- * `hname_hash' is the full MD5 hash of the hostname we want to resolve.
- *
- * `service' specifies the service number of the resolution. If it is equal to
- * -1 the resolution will return all the registered snds records.
- *
- * `proto' is the protocol of the `service', it must be specified in the
- * proto_to_8bit() format.
- *
- * In `*records' the number of records stored in the returned snsd_service
- * llist is written.
- *
- * It returns 0 on error
- */
- snsd_service *
- andna_resolve_hash(u_int hname_hash[MAX_IP_INT], int service,
- u_char proto, int *records)
- {
- PACKET pkt, rpkt;
- struct andna_resolve_rq_pkt req;
- struct andna_resolve_reply_pkt *reply;
- rh_cache *rhc;
- snsd_service *sns_dup;
- u_int hash_gnode[MAX_IP_INT], hash32;
- inet_prefix to;
-
- snsd_service *sns, *snsd_unpacked, *ret = 0;
-
- const char *ntop;
- char *snsd_packed;
- u_short snsd_counter = 0;
- size_t packed_sz, unpacked_sz;
- ssize_t err;
-
- *records = 0;
- setzero(&req, sizeof(req));
- setzero(&pkt, sizeof(pkt));
- setzero(&rpkt, sizeof(pkt));
-
- hash32 =
- fnv_32_buf((u_char *) hname_hash, ANDNA_HASH_SZ, FNV1_32_INIT);
-
- /* Try to resolve the hostname locally */
- sns = andna_resolve_hash_locally(hname_hash, service, proto, records);
- if (sns)
- return sns;
-
- /*
- * Fill the request structure.
- */
- req.service = service;
- req.proto = proto;
- inet_copy_ipdata(req.rip, &me.cur_ip);
- memcpy(req.hash, hname_hash, ANDNA_HASH_SZ);
- andna_hash_by_family(my_family, hname_hash, hash_gnode);
-
- /*
- * Ok, we have to ask to someone for the resolution.
- * Let's see to whom we have to send the pkt
- */
- if ((err = find_hash_gnode(hash_gnode, &to, 0, 0, 1)) < 0)
- ERROR_FINISH(ret, 0, finish);
- else if (err == 1)
- req.flags |= ANDNA_PKT_FORWARD;
-
- ntop = inet_to_str(to);
- debug(DBG_INSANE, "Quest %s to %s", rq_to_str(ANDNA_RESOLVE_HNAME),
- ntop);
-
-
- /*
- * Fill the packet and send the request
- */
-
- /* host -> network order */
- ints_host_to_network(&req, andna_resolve_rq_pkt_iinfo);
-
- pkt_addto(&pkt, &to);
- pkt.pkt_flags |= PKT_SET_LOWDELAY;
- pkt.hdr.flags |= ASYNC_REPLY;
- pkt.hdr.sz = ANDNA_RESOLVE_RQ_PKT_SZ;
- pkt.msg = xmalloc(pkt.hdr.sz);
- memcpy(pkt.msg, &req, pkt.hdr.sz);
-
- setzero(&rpkt, sizeof(PACKET));
- err =
- send_rq(&pkt, 0, ANDNA_RESOLVE_HNAME, 0, ANDNA_RESOLVE_REPLY, 1,
- &rpkt);
- if (err < 0) {
- debug(DBG_NORMAL, ERROR_MSG "Resolution of 0x%x failed.",
- ERROR_FUNC, pkt.hdr.id);
- ERROR_FINISH(ret, 0, finish);
- }
-
- if (rpkt.hdr.sz <= ANDNA_RESOLVE_REPLY_PKT_SZ ||
- rpkt.hdr.sz > (SNSD_SERVICE_MAX_PACK_SZ +
- ANDNA_RESOLVE_REPLY_PKT_SZ))
- ERROR_FINISH(ret, 0, finish);
-
- /*
- * Take the ip we need from the replied pkt
- */
- reply = (struct andna_resolve_reply_pkt *) rpkt.msg;
-
- /* network -> host order */
- ints_network_to_host(reply, andna_resolve_reply_pkt_iinfo);
-
- /* Unpack the received snsd records */
- snsd_packed = rpkt.msg + sizeof(struct andna_resolve_reply_pkt);
- packed_sz = rpkt.hdr.sz - sizeof(struct andna_resolve_reply_pkt);
- if (service == -1)
- snsd_unpacked = snsd_unpack_all_service(snsd_packed, packed_sz,
- &unpacked_sz,
- &snsd_counter);
- else
- snsd_unpacked = snsd_unpack_service(snsd_packed, packed_sz,
- &unpacked_sz, &snsd_counter);
-
- if (!snsd_unpacked ||
- ((service == SNSD_ALL_SERVICE ||
- service == SNSD_DEFAULT_SERVICE) &&
- !snsd_find_mainip(snsd_unpacked))) {
- debug(DBG_SOFT, ERROR_MSG "Malformed resolution reply (0x%x)",
- ERROR_FUNC, rpkt.hdr.id);
- ERROR_FINISH(ret, 0, finish);
- }
- *records = snsd_counter;
- ret = snsd_unpacked;
-
- /*
- * Add the hostname in the resolved_hnames cache since it was
- * successful resolved ;)
- */
- reply->timestamp = time(0) - reply->timestamp;
- rhc = rh_cache_add_hash(hash32, reply->timestamp);
- sns_dup = snsd_service_llist_copy(snsd_unpacked, SNSD_ALL_SERVICE, 0);
- snsd_service_llist_merge(&rhc->service, &rhc->snsd_counter, sns_dup);
-
- finish:
- pkt_free(&pkt, 1);
- pkt_free(&rpkt, 0);
- return ret;
- }
-
- /*
- * andna_resolve_hname
- *
- * It is a wrapper to andna_resolve_hash() (see above): it hashes the given
- * `hname' string and calls andna_resolve_hash.
- *
- * It returns 0 on error
- */
- snsd_service *
- andna_resolve_hname(char *hname, int service, u_char proto, int *records)
- {
- u_int hname_hash[MAX_IP_INT];
-
- hash_md5((u_char *) hname, strlen(hname), (u_char *) hname_hash);
-
- return andna_resolve_hash(hname_hash, service, proto, records);
- }
-
- /*
- * andna_recv_resolve_rq
- *
- * replies to a hostname resolve request by giving the snsd records associated
- * to the hostname.
- */
- int
- andna_recv_resolve_rq(PACKET rpkt)
- {
- PACKET pkt, rpkt_local_copy;
- struct andna_resolve_rq_pkt *req;
- struct andna_resolve_reply_pkt reply;
-
- andna_cache *ac;
- snsd_service *sns;
-
- u_int hash_gnode[MAX_IP_INT];
- inet_prefix rfrom, to;
- u_short service;
- size_t pack_sz;
- int ret = 0, err;
- char *ntop = 0, *rfrom_ntop = 0, *buf;
- u_char spread_the_acache = 0;
-
-
- if (rpkt.hdr.sz != ANDNA_RESOLVE_RQ_PKT_SZ)
- ERROR_FINISH(ret, -1, finish);
-
- pkt_copy(&rpkt_local_copy, &rpkt);
- req = (struct andna_resolve_rq_pkt *) rpkt_local_copy.msg;
-
- /* Save the real sender of the request */
- inet_setip(&rfrom, req->rip, my_family);
-
- ntop = xstrdup(inet_to_str(rpkt.from));
- rfrom_ntop = xstrdup(inet_to_str(rfrom));
- debug(DBG_NOISE, "Andna Resolve request 0x%x from: %s, real from: %s",
- rpkt.hdr.id, ntop, rfrom_ntop);
-
- memcpy(&pkt, &rpkt, sizeof(PACKET));
- inet_copy(&pkt.from, &rfrom);
- pkt_addsk(&pkt, my_family, 0, SKT_UDP);
- pkt_addcompress(&pkt);
- pkt_addlowdelay(&pkt);
- pkt_addlowdelay(&rpkt);
-
- /* network -> host order conversion of the rpkt_local_copy.smg */
- ints_network_to_host((void *) req, andna_resolve_rq_pkt_iinfo);
-
- /*
- * Are we the right hash_gnode or have we to still forward the pkt ?
- */
- andna_hash_by_family(my_family, (u_char *) req->hash, hash_gnode);
- if ((err = find_hash_gnode(hash_gnode, &to, 0, 0, 0)) < 0) {
- debug(DBG_SOFT, "We are not the real (rounded)hash_gnode. "
- "Rejecting the 0x%x resolve_hname request", rpkt.hdr.id);
- pkt_err(pkt, E_ANDNA_WRONG_HASH_GNODE, 0);
- ERROR_FINISH(ret, -1, finish);
- } else if (err == 1) {
- if (!(req->flags & ANDNA_PKT_FORWARD)) {
- pkt_err(pkt, E_ANDNA_WRONG_HASH_GNODE, 0);
- ERROR_FINISH(ret, -1, finish);
- }
-
- /* Continue to forward the received pkt */
- debug(DBG_SOFT, "The resolve_hame rq pkt will be forwarded "
- "to: %s", inet_to_str(to));
- ret = forward_pkt(rpkt, to);
- goto finish;
- }
-
- /*
- * Search the hostname to resolve in the andna_cache
- */
- if (!(ac = andna_cache_gethash((int *) req->hash))) {
-
- /* We don't have that hname in our andna_cache */
-
- if (time(0) - me.uptime < (ANDNA_EXPIRATION_TIME / 2)) {
- /*
- * We are a new hash_gnode, let's see if there is
- * an old hash_gnode which has this hostname.
- */
- if ((ac = get_single_andna_c(req->hash, hash_gnode))) {
- /*
- * We got the andna_cache from the old
- * hash_gnode. Save it in our andna_cache, then
- * reply to `rfrom' and diffuse it in our gnode
- */
- clist_add(&andna_c, &andna_c_counter, ac);
-
- spread_the_acache = 1;
- goto reply_resolve_rq;
- }
- }
-
-
- /* Nothing to do, there isn't it, bye. */
- debug(DBG_SOFT, "Request %s (0x%x) rejected: %s",
- rq_to_str(rpkt.hdr.op), rpkt.hdr.id,
- rq_strerror(E_ANDNA_NO_HNAME));
- pkt_err(pkt, E_ANDNA_NO_HNAME, 0);
- ERROR_FINISH(ret, -1, finish);
- }
-
- reply_resolve_rq:
- /*
- * Send back the ip associated to the hname
- */
- debug(DBG_SOFT, "Resolve request 0x%x accepted", rpkt.hdr.id);
-
- /* Write the reply */
- setzero(&reply, sizeof(reply));
- reply.timestamp = time(0) - ac->acq->timestamp;
-
- /* host -> network order */
- ints_host_to_network((void *) &reply, andna_resolve_reply_pkt_iinfo);
-
- pack_sz = sizeof(reply);
- pack_sz += req->service == SNSD_ALL_SERVICE ?
- SNSD_SERVICE_LLIST_PACK_SZ(ac->acq->service) :
- SNSD_SERVICE_SINGLE_PACK_SZ(ac->acq->service);
- pkt_fill_hdr(&pkt.hdr, ASYNC_REPLIED, rpkt.hdr.id, ANDNA_RESOLVE_REPLY,
- pack_sz);
-
- pkt.msg = buf = xmalloc(pkt.hdr.sz);
- memcpy(pkt.msg, &reply, sizeof(reply));
- buf += sizeof(reply);
- pack_sz -= sizeof(reply);
-
- if (req->service == SNSD_ALL_SERVICE)
- /* Pack all the registered snsd records */
- ret = snsd_pack_all_services(buf, pack_sz, ac->acq->service);
- else {
- /* Pack the snsd records of the specified service number */
- service = (u_short) req->service;
- sns = snsd_find_service(ac->acq->service, service, req->proto);
-
- if (!sns && service != SNSD_DEFAULT_SERVICE) {
- /*
- * The specified service and proto record hasn't been
- * found, fallback to SNSD_DEFAULT_SERVICE
- */
- sns = snsd_find_service(ac->acq->service,
- SNSD_DEFAULT_SERVICE, 0);
- }
-
- /* pack what we found */
- ret = snsd_pack_service(buf, pack_sz, sns);
- }
- if (ret < 0) {
- debug(DBG_NORMAL, "Cannot pack the services for the 0x%x "
- "resolve request", rpkt.hdr.id);
- goto finish;
- }
-
- /* Forward it */
- ret = forward_pkt(pkt, rfrom);
- pkt_free(&pkt, 0);
-
- if (spread_the_acache) {
- /* Spread the received andna_cache in our gnode */
- spread_single_acache(req->hash);
- }
-
- finish:
- if (ntop)
- xfree(ntop);
- if (rfrom_ntop)
- xfree(rfrom_ntop);
- pkt_free(&rpkt_local_copy, 0);
-
- return ret;
- }
-
- /*
- * andna_reverse_resolve
- *
- * It returns the copy of the local cache of a remote node.
- * The ip of the node is specified in `ip'.
- *
- * On error 0 is returned.
- */
- lcl_cache *
- andna_reverse_resolve(inet_prefix ip)
- {
- PACKET pkt, rpkt;
- lcl_cache *unpacked_lcl = 0, *ret = 0;
- inet_prefix to;
-
- const char *ntop;
- int tmp_counter;
- ssize_t err;
-
- setzero(&pkt, sizeof(PACKET));
- setzero(&rpkt, sizeof(PACKET));
- inet_copy(&to, &ip);
-
- ntop = inet_to_str(to);
- debug(DBG_INSANE, "Quest %s to %s", rq_to_str(ANDNA_RESOLVE_IP), ntop);
-
- /* We have been asked to reverse resolve our same IP */
- if (!memcmp(to.data, me.cur_ip.data, MAX_IP_SZ) ||
- LOOPBACK(htonl(to.data[0])))
- return lcl_get_registered_hnames(andna_lcl);
-
- /*
- * Fill the packet and send the request
- */
- pkt_addto(&pkt, &to);
- pkt_addfrom(&rpkt, &to);
- pkt_addtimeout(&pkt, ANDNA_REV_RESOLVE_RQ_TIMEOUT, 1, 1);
-
- err =
- send_rq(&pkt, 0, ANDNA_RESOLVE_IP, 0, ANDNA_REV_RESOLVE_REPLY, 1,
- &rpkt);
- if (err < 0) {
- error(ERROR_MSG "Reverse resolution of the %s "
- "ip failed.", ERROR_FUNC, inet_to_str(to));
- ERROR_FINISH(ret, 0, finish);
- }
-
- unpacked_lcl = unpack_lcl_cache(rpkt.msg, rpkt.hdr.sz, &tmp_counter);
- if (tmp_counter > ANDNA_MAX_HOSTNAMES || tmp_counter < 0)
- ERROR_FINISH(ret, 0, finish);
- ret = unpacked_lcl;
-
- finish:
- pkt_free(&pkt, 1);
- pkt_free(&rpkt, 1);
- return ret;
- }
-
- /*
- * andna_recv_rev_resolve_rq
- *
- * It replies to a reverse hostname resolve request which asks all the
- * hostnames associated with a given ip.
- */
- int
- andna_recv_rev_resolve_rq(PACKET rpkt)
- {
- PACKET pkt;
-
- const char *ntop;
- int ret = 0, err;
-
- lcl_cache *alcl = andna_lcl;
-
- setzero(&pkt, sizeof(PACKET));
-
- ntop = inet_to_str(rpkt.from);
- debug(DBG_INSANE,
- "Andna reverse resolve request received 0x%x from %s",
- rpkt.hdr.id, ntop);
-
- /*
- * Build the reply pkt
- */
-
- pkt_fill_hdr(&pkt.hdr, 0, rpkt.hdr.id, ANDNA_REV_RESOLVE_REPLY, 0);
-
- /* Build the list of registered hnames */
- if (!(pkt.msg = pack_lcl_cache(alcl, &pkt.hdr.sz))) {
- pkt_err(rpkt, E_ANDNA_NO_HNAME, 0);
- ERROR_FINISH(ret, -1, finish);
- }
-
- debug(DBG_INSANE, "Reverse resolve request 0x%x accepted",
- rpkt.hdr.id);
-
- /*
- * Send it.
- */
-
- pkt_addto(&pkt, &rpkt.from);
- pkt_addsk(&pkt, my_family, rpkt.sk, rpkt.sk_type);
- pkt_addcompress(&pkt);
- err = send_rq(&pkt, 0, ANDNA_REV_RESOLVE_REPLY, rpkt.hdr.id, 0, 0, 0);
- if (err < 0)
- ERROR_FINISH(ret, -1, finish);
- finish:
- pkt_free(&pkt, 0);
- return ret;
- }
-
-
- /*
- *
- * * * * Andna caches transfer * * *
- *
- */
-
- /*
- * get_single_andna_c
- *
- * It sends the ANDNA_GET_SINGLE_ACACHE request to the old `hash_gnode' of `hash'
- * to retrieve the andna_cache that contains the information about `hash'.
- */
- andna_cache *
- get_single_andna_c(u_int hash[MAX_IP_INT], u_int hash_gnode[MAX_IP_INT])
- {
- PACKET pkt, rpkt;
- struct single_acache_hdr req_hdr;
- andna_cache *ret = 0;
- u_int *new_hgnodes[1];
- size_t pack_sz;
- int err, counter;
- const char *ntop;
- char *pack;
-
- setzero(&pkt, sizeof(PACKET));
- setzero(&rpkt, sizeof(PACKET));
- setzero(&req_hdr, sizeof(struct single_acache_hdr));
-
- /*
- * Find the old hash_gnode that corresponds to the hash `hash_gnode',
- * but exclude from the search ourself 'cause we are a new hash_gnode
- * and we are trying to reach the new one.
- */
- new_hgnodes[0] = me.cur_ip.data;
- if ((err =
- find_hash_gnode(hash_gnode, &pkt.to, new_hgnodes, 1, 1)) < 0) {
- debug(DBG_SOFT, "get_single_andna_c: old hash_gnode not found");
- ERROR_FINISH(ret, 0, finish);
- } else if (err == 1)
- req_hdr.flags |= ANDNA_PKT_FORWARD;
-
- req_hdr.hgnodes = 1;
- inet_copy_ipdata(req_hdr.rip, &me.cur_ip);
- memcpy(req_hdr.hash, hash, MAX_IP_SZ);
-
- /* host -> network order */
- ints_host_to_network((void *) &req_hdr, single_acache_hdr_iinfo);
-
- /* Pack the request */
- pkt.hdr.flags |= ASYNC_REPLY;
- pkt.hdr.sz = SINGLE_ACACHE_PKT_SZ(1);
- pkt.msg = xmalloc(pkt.hdr.sz);
- memcpy(pkt.msg, &req_hdr, pkt.hdr.sz);
-
- /* Append our ip at the end of the pkt */
- inet_copy_ipdata((u_int *) (pkt.msg +
- sizeof(struct single_acache_hdr)),
- &me.cur_ip);
-
- ntop = inet_to_str(pkt.to);
- debug(DBG_INSANE, "Quest %s to %s", rq_to_str(ANDNA_GET_SINGLE_ACACHE),
- ntop);
- err =
- send_rq(&pkt, 0, ANDNA_GET_SINGLE_ACACHE, 0, ACK_AFFERMATIVE, 1,
- &rpkt);
- if (err < 0)
- ERROR_FINISH(ret, 0, finish);
-
- /* Unpack the waited reply */
- pack_sz = rpkt.hdr.sz;
- pack = rpkt.msg;
- ret = unpack_andna_cache(pack, pack_sz, &counter, ACACHE_PACK_PKT);
- if (!ret && counter < 0) {
- error("get_single_acache(): Malformed andna_cache.");
- ERROR_FINISH(ret, 0, finish);
- }
-
- finish:
- pkt_free(&pkt, 1);
- pkt_free(&rpkt, 0);
- return ret;
- }
-
- /*
- * put_single_acache
- *
- * It replies to a get_single_acache request as described
- * in andna.h (near the single_acache_hdr struct).
- */
- int
- put_single_acache(PACKET rpkt)
- {
- PACKET pkt, rpkt_local_copy;
- struct single_acache_hdr *req_hdr;
- u_int hash_gnode[MAX_IP_INT], **new_hgnodes = 0;
- inet_prefix rfrom, to;
- andna_cache *ac, *ac_tmp = 0;
- char *buf;
- char *ntop = 0, *rfrom_ntop = 0;
- int ret = 0, i;
- ssize_t err = 0;
- size_t pkt_sz = 0;
-
-
- pkt_copy(&rpkt_local_copy, &rpkt);
- req_hdr = (struct single_acache_hdr *) rpkt_local_copy.msg;
-
- /* Save the real sender of the request */
- inet_setip(&rfrom, req_hdr->rip, my_family);
-
- ntop = xstrdup(inet_to_str(rpkt.from));
- rfrom_ntop = xstrdup(inet_to_str(rfrom));
- debug(DBG_NOISE, "Andna get single cache request 0x%x from: %s, real "
- "from: %s", rpkt.hdr.id, ntop, rfrom_ntop);
-
- memcpy(&pkt, &rpkt, sizeof(PACKET));
- inet_copy(&pkt.from, &rfrom);
- pkt_addsk(&pkt, my_family, 0, SKT_UDP);
- pkt_addcompress(&pkt);
-
- /* network -> host order */
- ints_network_to_host(req_hdr, single_acache_hdr_iinfo);
-
- /* Verify the validity of the header */
- if (rpkt.hdr.sz != SINGLE_ACACHE_PKT_SZ(req_hdr->hgnodes) ||
- req_hdr->hgnodes > ANDNA_MAX_NEW_GNODES) {
- debug(DBG_NOISE, "Malformed GET_SINGLE_ACACHE pkt: %d, %d, %d",
- rpkt.hdr.sz, SINGLE_ACACHE_PKT_SZ(req_hdr->hgnodes),
- req_hdr->hgnodes);
- pkt_err(pkt, E_INVALID_REQUEST, 0);
- ERROR_FINISH(ret, -1, finish);
- }
-
- /* Unpack the hash_gnodes to exclude */
- new_hgnodes = xmalloc(sizeof(u_int *) * (req_hdr->hgnodes + 1));
- buf = rpkt.msg + sizeof(struct single_acache_hdr);
- for (i = 0; i < req_hdr->hgnodes; i++) {
- new_hgnodes[i] = (u_int *) buf;
- inet_ntohl(new_hgnodes[i], me.cur_ip.family);
- buf += MAX_IP_SZ;
- }
-
- /*
- * Check if we are the destined old hash_gnode or if we have to still
- * forward the pkt
- */
-
- andna_hash_by_family(my_family, (u_char *) req_hdr->hash, hash_gnode);
- if ((err = find_hash_gnode(hash_gnode, &to, new_hgnodes,
- req_hdr->hgnodes, 0)) < 0) {
- debug(DBG_SOFT, "We are not the real (rounded)hash_gnode. "
- "Rejecting the 0x%x get_single_acache request", rpkt.hdr.id);
- pkt_err(pkt, E_ANDNA_WRONG_HASH_GNODE, 0);
- ERROR_FINISH(ret, -1, finish);
- } else if (err == 1) {
- /* Continue to forward the received pkt */
- debug(DBG_SOFT, "The 0x%x rq pkt will be forwarded "
- "to: %s", rpkt.hdr.id, inet_to_str(to));
- ret = forward_pkt(rpkt, to);
- goto finish;
- }
-
-
- /*
- * Search in our andna_cache if we have what `rfrom' wants.
- */
- if (!(ac = andna_cache_gethash((int *) req_hdr->hash))) {
-
- /*
- * Nothing found! Maybe it's because we have an uptime less than
- * (ANDNA_EXPIRATION_TIME/2) and so we are a new hash_gnode,
- * therefore we have to forward the pkt to an older hash_gnode.
- */
- if (time(0) - me.uptime < (ANDNA_EXPIRATION_TIME / 2)) {
- new_hgnodes[req_hdr->hgnodes] = me.cur_ip.data;
- if ((err = find_hash_gnode(hash_gnode, &to, new_hgnodes,
- req_hdr->hgnodes + 1, 1)) < 0) {
- /* An older hash_gnode doesn't exist */
- debug(DBG_SOFT,
- "put_single_andna_c: old hash_gnode not found");
- ERROR_FINISH(ret, -1, finish);
- }
-
- /*
- * Append our ip at the end of the pkt and forward it
- * to the older hash_gnode.
- */
- memcpy(&pkt, &rpkt, sizeof(PACKET));
- pkt.sk = 0;
- pkt.hdr.sz = rpkt.hdr.sz + MAX_IP_SZ;
- pkt.msg = xmalloc(pkt.hdr.sz);
- memcpy(pkt.msg, rpkt.msg, rpkt.hdr.sz);
- inet_copy_ipdata((u_int *) (pkt.msg + rpkt.hdr.sz),
- &me.cur_ip);
-
- debug(DBG_SOFT, "The 0x%x rq pkt will be forwarded "
- "to an older hgnode: %s", rpkt.hdr.id, inet_to_str(to));
- ret = forward_pkt(pkt, to);
- pkt_free(&pkt, 1);
- goto finish;
- }
-
-
- /*
- * We are neither a new hash_gnode so the
- * get_andna_single_cache propagation ends here and we reply to
- * `rfrom': <<That andna_cache doesn't exist, bye bye!>>
- */
- debug(DBG_SOFT, "Request %s (0x%x) rejected: %s",
- rq_to_str(rpkt.hdr.op), rpkt.hdr.id,
- rq_strerror(E_ANDNA_NO_HNAME));
- pkt_err(pkt, E_ANDNA_NO_HNAME, 0);
- ERROR_FINISH(ret, -1, finish);
- }
-
- /*
- * We found the andna_cache! Let's reply.
- * Pack the `ac' andna_cache and send it to `rfrom'
- */
-
- setzero(&pkt, sizeof(PACKET));
- pkt_fill_hdr(&pkt.hdr, ASYNC_REPLIED, rpkt.hdr.id, ACK_AFFERMATIVE, 0);
- pkt_addto(&pkt, &rfrom);
- pkt_addsk(&pkt, my_family, 0, SKT_TCP);
- pkt_addport(&pkt, rpkt.port);
- pkt_addcompress(&pkt);
-
- /* Exctract the `ac' cache from the llist, so we can pack it alone */
- ac_tmp = list_dup(ac);
- pkt.msg = pack_andna_cache(ac_tmp, &pkt_sz, ACACHE_PACK_PKT);
- pkt.hdr.sz = pkt_sz;
-
- debug(DBG_INSANE, "Reply put_single_acache to %s", ntop);
- err = send_rq(&pkt, 0, ACK_AFFERMATIVE, rpkt.hdr.id, 0, 0, 0);
- pkt_free(&pkt, 0);
- if (err < 0) {
- error("put_andna_cache(): Cannot send the put_single_acache "
- "reply to %s.", ntop);
- ERROR_FINISH(ret, -1, finish);
- }
- finish:
- if (ac_tmp)
- xfree(ac_tmp);
- if (new_hgnodes)
- xfree(new_hgnodes);
- if (ntop)
- xfree(ntop);
- if (rfrom_ntop)
- xfree(rfrom_ntop);
- pkt_free(&rpkt_local_copy, 0);
-
- return ret;
- }
-
- /*
- * spread_single_acache
- *
- * It tells to all the rnodes to get the single andna_cache of `hash'
- * using get_single_andna_c()
- */
- int
- spread_single_acache(u_int hash[MAX_IP_INT])
- {
- PACKET pkt;
- struct spread_acache_pkt req;
-
- setzero(&pkt, sizeof(PACKET));
- memcpy(req.hash, hash, MAX_IP_SZ);
-
- ints_host_to_network(&req, spread_acache_pkt_info);
-
- pkt_fill_hdr(&pkt.hdr, 0, 0, ANDNA_SPREAD_SACACHE,
- SPREAD_ACACHE_PKT_SZ);
- pkt.msg = xmalloc(pkt.hdr.sz);
- memcpy(pkt.msg, &req, pkt.hdr.sz);
-
- debug(DBG_NOISE, "Spreading the single andna_cache 0x%x", pkt.hdr.id);
- andna_add_flood_pkt_id(last_spread_acache_pkt_id, pkt.hdr.id);
- return andna_flood_pkt(&pkt, 0);
- }
-
- /*
- * recv_spread_single_acache
- *
- * It receives and execute the ANDNA_SPREAD_SACACHE request.
- */
- int
- recv_spread_single_acache(PACKET rpkt)
- {
- PACKET rpkt_local_copy;
- struct spread_acache_pkt *req;
- andna_cache *ac;
- u_int hash_gnode[MAX_IP_INT];
- int ret = 0;
-
- pkt_copy(&rpkt_local_copy, &rpkt);
- req = (struct spread_acache_pkt *) rpkt_local_copy.msg;
-
- if (rpkt.hdr.sz != SPREAD_ACACHE_PKT_SZ)
- ERROR_FINISH(ret, -1, finish);
-
- /* network -> host order */
- ints_network_to_host(req, spread_acache_pkt_info);
-
- /* Check if we already received this pkt during the flood */
- if (andna_add_flood_pkt_id(last_spread_acache_pkt_id, rpkt.hdr.id)) {
- debug(DBG_INSANE, "Dropped 0x%0x andna pkt, we already "
- "received it", rpkt.hdr.id);
- ERROR_FINISH(ret, 0, finish);
- }
-
- if (time(0) - me.uptime > (ANDNA_EXPIRATION_TIME / 2) ||
- (ac = andna_cache_findhash((int *) req->hash))) {
- /* We don't need to get the andna_cache from an old
- * hash_gnode, since we currently are one of them! */
- debug(DBG_NOISE, "recv_spread_single_acache: We are an old "
- "hash_gnode, dropping 0x%x", rpkt.hdr.id);
- ERROR_FINISH(ret, -1, finish);
- }
-
- debug(DBG_NOISE, "Received the spreaded andna_cache 0x%x",
- rpkt.hdr.id);
-
- /*
- * Do as the rpkt tells us to do: retrieve the andna_hash for
- * req->hash from the old hash_gnode and store it.
- */
- andna_hash_by_family(my_family, (u_char *) req->hash, hash_gnode);
- if ((ac = get_single_andna_c(req->hash, hash_gnode))) {
- /* Save it in our andna_cache. */
- clist_add(&andna_c, &andna_c_counter, ac);
- } else {
- debug(DBG_NOISE, "recv_spread_single_acache: (0x%x) "
- "get_single_andna_c request failed", rpkt.hdr.id);
- ERROR_FINISH(ret, -1, finish);
- }
-
- /* Continue to forward the pkt in the gnode */
- andna_flood_pkt(&rpkt, 1);
-
- finish:
- pkt_free(&rpkt_local_copy, 0);
- return ret;
- }
-
- /*
- * get_andna_cache
- *
- * sends the ANDNA_GET_ANDNA_CACHE request to rnode `dst_rnode' to retrieve its
- * andna_cache.
- */
- andna_cache *
- get_andna_cache(map_node * dst_rnode, int *counter)
- {
- PACKET pkt, rpkt;
- andna_cache *ret = 0;
- size_t pack_sz;
- int err;
- char *pack;
-
- setzero(&pkt, sizeof(PACKET));
- setzero(&rpkt, sizeof(PACKET));
-
- if (rnl_fill_rq(dst_rnode, &pkt) < 0)
- ERROR_FINISH(ret, 0, finish);
- if (server_opt.dbg_lvl) {
- const char *ntop;
- ntop = inet_to_str(pkt.to);
- debug(DBG_INSANE, "Quest %s to %s",
- rq_to_str(ANDNA_GET_ANDNA_CACHE), ntop);
- }
- pkt_addtimeout(&pkt, ANDNA_HOOK_TIMEOUT, 1, 1);
-
- err = send_rq(&pkt, 0, ANDNA_GET_ANDNA_CACHE, 0,
- ANDNA_PUT_ANDNA_CACHE, 1, &rpkt);
- if (err < 0) {
- ret = 0;
- goto finish;
- }
-
- pack_sz = rpkt.hdr.sz;
- pack = rpkt.msg;
- ret = unpack_andna_cache(pack, pack_sz, counter, ACACHE_PACK_PKT);
- if (!ret && counter < 0)
- error("get_andna_cache(): Malformed or empty andna_cache. "
- "Cannot load it");
-
- finish:
- pkt_free(&pkt, 0);
- pkt_free(&rpkt, 0);
- return ret;
- }
-
- /*
- * put_andna_cache
- *
- * replies to a ANDNA_GET_ANDNA_CACHE request, sending back the complete
- * andna cache
- */
- int
- put_andna_cache(PACKET rq_pkt)
- {
- PACKET pkt;
- const char *ntop;
- int ret = 0;
- ssize_t err = 0;
- size_t pkt_sz = 0;
-
- ntop = inet_to_str(rq_pkt.from);
-
- setzero(&pkt, sizeof(PACKET));
- pkt_addto(&pkt, &rq_pkt.from);
- pkt_addsk(&pkt, my_family, rq_pkt.sk, rq_pkt.sk_type);
- pkt_addcompress(&pkt);
-
- pkt.msg = pack_andna_cache(andna_c, &pkt_sz, ACACHE_PACK_PKT);
- pkt.hdr.sz = pkt_sz;
- debug(DBG_INSANE, "Reply %s to %s", re_to_str(ANDNA_PUT_ANDNA_CACHE),
- ntop);
- err = send_rq(&pkt, 0, ANDNA_PUT_ANDNA_CACHE, rq_pkt.hdr.id, 0, 0, 0);
- if (err < 0) {
- error
- ("put_andna_cache(): Cannot send the ANDNA_PUT_ANDNA_CACHE reply to %s.",
- ntop);
- ERROR_FINISH(ret, -1, finish);
- }
- finish:
- pkt_free(&pkt, 0);
- return ret;
- }
-
-
- /*
- * get_counter_cache
- *
- * sends the ANDNA_GET_COUNT_CACHE request to rnode `dst_rnode' to retrieve its
- * counter_cache.
- */
- counter_c *
- get_counter_cache(map_node * dst_rnode, int *counter)
- {
- PACKET pkt, rpkt;
- counter_c *ccache, *ret = 0;
- size_t pack_sz;
- int err;
- char *pack;
-
- setzero(&pkt, sizeof(PACKET));
- setzero(&rpkt, sizeof(PACKET));
-
- if (rnl_fill_rq(dst_rnode, &pkt) < 0)
- ERROR_FINISH(ret, 0, finish);
- if (server_opt.dbg_lvl) {
- const char *ntop;
- ntop = inet_to_str(pkt.to);
- debug(DBG_INSANE, "Quest %s to %s",
- rq_to_str(ANDNA_GET_COUNT_CACHE), ntop);
- }
- pkt_addtimeout(&pkt, ANDNA_HOOK_TIMEOUT, 1, 1);
-
- err = send_rq(&pkt, 0, ANDNA_GET_COUNT_CACHE, 0,
- ANDNA_PUT_COUNT_CACHE, 1, &rpkt);
- if (err < 0) {
- ret = 0;
- goto finish;
- }
-
- pack_sz = rpkt.hdr.sz;
- pack = rpkt.msg;
- ret = ccache = unpack_counter_cache(pack, pack_sz, counter);
- if (!ccache && counter < 0)
- error(ERROR_MSG "Malformed counter_cache. Cannot load it",
- ERROR_FUNC);
-
- finish:
- pkt_free(&pkt, 0);
- pkt_free(&rpkt, 0);
- return ret;
- }
-
- /*
- * put_counter_cache
- *
- * replies to a ANDNA_GET_COUNT_CACHE request, sending back the
- * complete andna cache.
- */
- int
- put_counter_cache(PACKET rq_pkt)
- {
- PACKET pkt;
- const char *ntop;
- int ret = 0;
- ssize_t err = 0;
- size_t pkt_sz = 0;
-
- ntop = inet_to_str(rq_pkt.from);
-
- setzero(&pkt, sizeof(PACKET));
- pkt_addto(&pkt, &rq_pkt.from);
- pkt_addsk(&pkt, my_family, rq_pkt.sk, rq_pkt.sk_type);
- pkt_addcompress(&pkt);
-
- pkt.msg = pack_counter_cache(andna_counter_c, &pkt_sz);
- pkt.hdr.sz = pkt_sz;
- debug(DBG_INSANE, "Reply %s to %s", re_to_str(ANDNA_PUT_COUNT_CACHE),
- ntop);
- err = send_rq(&pkt, 0, ANDNA_PUT_COUNT_CACHE, rq_pkt.hdr.id, 0, 0, 0);
- if (err < 0) {
- error
- ("put_counter_cache(): Cannot send the ANDNA_PUT_COUNT_CACHE reply to %s.",
- ntop);
- ERROR_FINISH(ret, -1, finish);
- }
- finish:
- pkt_free(&pkt, 0);
- return ret;
- }
-
-
- /*
- *
- * * * * ANDNA threads * * *
- *
- */
-
- /*
- * andna_hook
- *
- * The andna_hook gets the andna_cache and the counter_node cache from
- * the nearest rnodes.
- */
- void *
- andna_hook(void *null)
- {
- inet_prefix to;
- map_node *node;
- int e = 0, i;
-
- setzero(&to, sizeof(inet_prefix));
-
- /* Block these requests */
- op_filter_set(ANDNA_SPREAD_SACACHE);
-
- loginfo("Starting the ANDNA hook.");
-
- if (!me.cur_node->links) {
- /* nothing to do */
- debug(DBG_NORMAL, "There are no nodes, skipping the ANDNA hook.");
- goto finish;
- }
-
- /*
- * Send the GET_ANDNA_CACHE request to the nearest rnode we have, if it
- * fails send it to the second rnode and so on...
- */
- for (i = 0, e = 0; i < me.cur_node->links; i++) {
- node = (map_node *) me.cur_node->r_node[i].r_node;
- if (!node || node->flags & MAP_ERNODE)
- continue;
-
- andna_c = get_andna_cache(node, &andna_c_counter);
- if (andna_c) {
- e = 1;
- break;
- }
- }
- if (!e)
- loginfo
- ("None of the rnodes in this area gave me the andna_cache.");
-
- /*
- * Send the GET_COUNT_CACHE request to the nearest rnode we have, if it
- * fails send it to the second rnode and so on...
- */
- for (i = 0, e = 0; i < me.cur_node->links; i++) {
- node = (map_node *) me.cur_node->r_node[i].r_node;
- if (!node || node->flags & MAP_ERNODE)
- continue;
-
- andna_counter_c = get_counter_cache(node, &cc_counter);
- if (andna_counter_c) {
- e = 1;
- break;
- }
- }
- if (!e)
- loginfo
- ("None of the rnodes in this area gave me the counter_cache.");
-
- finish:
- /* Un-block these requests */
- op_filter_clr(ANDNA_SPREAD_SACACHE);
-
- loginfo("ANDNA hook completed");
-
- return 0;
- }
-
- /*
- * andna_min_update_retry
- *
- * waits ANDNA_MIN_UPDATE_TIME seconds and then updates `void_alcl'.
- */
- void *
- andna_min_update_retry(void *void_alcl)
- {
- lcl_cache *alcl = (lcl_cache *) void_alcl;
- int ret;
-
- sleep(ANDNA_MIN_UPDATE_TIME);
-
- ret = andna_register_hname(alcl, 0);
- if (!ret)
- loginfo("Hostname \"%s\" registered/updated "
- "successfully", alcl->hostname);
-
- return 0;
- }
-
- /*
- * andna_update_hnames
- *
- * updates/registers all the hostnames present in the local cache.
- * If `only_new_hname' is not zero, it registers only the new hostnames
- * added in the local cache.
- */
- void
- andna_update_hnames(int only_new_hname)
- {
- pthread_t thread;
- lcl_cache *alcl = andna_lcl;
- int ret, updates = 0;
-
- list_for(alcl) {
- if (only_new_hname && alcl->timestamp)
- /* don't register old hnames */
- continue;
-
- ret = andna_register_hname(alcl, 0);
- if (!ret) {
- loginfo("Hostname \"%s\" registered/updated "
- "successfully", alcl->hostname);
- updates++;
- } else {
- /* Wait ANDNA_MIN_UPDATE_TIME seconds then retry to
- * update it */
- pthread_create(&thread, 0, andna_min_update_retry,
- (void *) alcl);
- pthread_detach(thread);
- }
- }
- if (updates)
- save_lcl_cache(andna_lcl, server_opt.lcl_file);
- }
-
- /*
- * andna_maintain_hnames_active
- *
- * periodically registers and keep up to date the hostnames of the local cache.
- */
- void *
- andna_maintain_hnames_active(void *null)
- {
- lcl_cache *alcl;
- int ret, updates;
-
- /* Wait a bit before trying to register the hname. The first QSPN must
- * be already sent */
- while (time(0) - me.uptime < QSPN_WAIT_ROUND / 2)
- sleep(1);
-
- for (;;) {
- updates = 0;
- alcl = andna_lcl;
-
- /** If we don't have rnodes, it's useless to try
- * anything */
- while (!me.cur_node->links)
- sleep(2);
- /**/ list_for(alcl) {
- ret = andna_register_hname(alcl, 0);
- if (!ret) {
- loginfo("Hostname \"%s\" registered/updated "
- "successfully", alcl->hostname);
- updates++;
- }
- }
-
- if (updates)
- save_lcl_cache(andna_lcl, server_opt.lcl_file);
-
- sleep((ANDNA_EXPIRATION_TIME / 2) + rand_range(1, 10));
- }
-
- return 0;
- }
-
- void *
- andna_main(void *null)
- {
- struct udp_daemon_argv ud_argv;
- u_short *port;
- pthread_t thread;
- pthread_attr_t t_attr;
-
- pthread_attr_init(&t_attr);
- pthread_attr_setdetachstate(&t_attr, PTHREAD_CREATE_DETACHED);
-
- setzero(&ud_argv, sizeof(struct udp_daemon_argv));
- port = xmalloc(sizeof(u_short));
-
- pthread_mutex_init(&udp_daemon_lock, 0);
- pthread_mutex_init(&tcp_daemon_lock, 0);
-
- debug(DBG_SOFT, "Evoking the andna udp daemon.");
- ud_argv.port = andna_udp_port;
- ud_argv.flags |= UDP_THREAD_FOR_EACH_PKT;
- pthread_mutex_lock(&udp_daemon_lock);
- pthread_create(&thread, &t_attr, udp_daemon, (void *) &ud_argv);
- pthread_mutex_lock(&udp_daemon_lock);
- pthread_mutex_unlock(&udp_daemon_lock);
-
- debug(DBG_SOFT, "Evoking the andna tcp daemon.");
- *port = andna_tcp_port;
- pthread_mutex_lock(&tcp_daemon_lock);
- pthread_create(&thread, &t_attr, tcp_daemon, (void *) port);
- pthread_mutex_lock(&tcp_daemon_lock);
- pthread_mutex_unlock(&tcp_daemon_lock);
-
- /*
- * Start the ANDNA hook
- */
- pthread_create(&thread, &t_attr, andna_hook, 0);
-
- /*
- * DNS wrapper
- */
- debug(DBG_SOFT, "Evoking the DNS wrapper daemon.");
- pthread_create(&thread, &t_attr, dns_wrapper_thread, 0);
-
- /*
- * Start the hostnames updater and register
- */
- andna_maintain_hnames_active(0);
-
- xfree(port);
- return 0;
- }
|