[cvs] / netsukuku / src / andna_cache.c Repository:
ViewVC logotype

View of /netsukuku/src/andna_cache.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.62 - (download) (as text) (annotate)
Sun Aug 27 07:06:28 2006 UTC (4 years ago) by alpt
Branch: MAIN
CVS Tags: HEAD
Changes since 1.61: +8 -9 lines
module.c completed: the NTK API for modules is ready, now it's time to
modularize the rest of the code.
    1 /* This file is part of Netsukuku
    2  * (c) Copyright 2005 Andrea Lo Pumo aka AlpT <alpt@freaknet.org>
    3  *
    4  * This source code is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public License as published
    6  * by the Free Software Foundation; either version 2 of the License,
    7  * or (at your option) any later version.
    8  *
    9  * This source code is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   12  * Please refer to the GNU Public License for more details.
   13  *
   14  * You should have received a copy of the GNU Public License along with
   15  * this source code; if not, write to:
   16  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   17  *
   18  * --
   19  * andna_cache.c:
   20  * Functions to manipulate all the andna's caches.
   21  */
   22 
   23 #include "includes.h"
   24 #include <string.h>
   25 
   26 #include "crypto.h"
   27 #include "andna_cache.h"
   28 #include "snsd_cache.h"
   29 #include "common.h"
   30 #include "hash.h"
   31 
   32 
   33 int net_family;
   34 
   35 void andna_caches_init(int family)
   36 {
   37   net_family = family;
   38 
   39   setzero(&lcl_keyring, sizeof(lcl_keyring));
   40 
   41   andna_lcl=(lcl_cache *)clist_init(&lcl_counter);
   42   andna_c=(andna_cache *)clist_init(&andna_c_counter);
   43   andna_counter_c=(counter_c *)clist_init(&cc_counter);
   44   andna_rhc=(rh_cache *)clist_init(&rhc_counter);
   45 }
   46 
   47 /*
   48  * andna_32bit_hash
   49  *
   50  * It returns the 32bit hash of the md5 hash of the `hname' string.
   51  */
   52 u_int andna_32bit_hash(char *hname)
   53 {
   54   u_char hashm5[ANDNA_HASH_SZ];
   55 
   56   hash_md5((u_char*)hname, strlen(hname), hashm5);
   57   return fnv_32_buf(hashm5, ANDNA_HASH_SZ, FNV1_32_INIT);
   58 }
   59 
   60 /*
   61  *
   62  *  *  *  *  Local Cache functions  *  *  *
   63  *
   64  */
   65 
   66 /*
   67  * lcl_new_keyring
   68  *
   69  * It generates a new keyring.
   70  */
   71 void lcl_new_keyring(lcl_cache_keyring *keyring)
   72 {
   73   setzero(keyring, sizeof(lcl_cache_keyring));
   74   loginfo("Generating a new ANDNA keyring");
   75 
   76   /* Generate the new key pair for the first time */
   77   keyring->priv_rsa = genrsa(ANDNA_PRIVKEY_BITS, &keyring->pubkey,
   78       &keyring->pkey_len, &keyring->privkey, &keyring->skey_len);
   79 }
   80 
   81 /*
   82  * lcl_destroy_keyring
   83  *
   84  * destroys accurately the keyring ^_^
   85  */
   86 void lcl_destroy_keyring(lcl_cache_keyring *keyring)
   87 {
   88   if(keyring->priv_rsa)
   89     RSA_free(keyring->priv_rsa);
   90   if(keyring->pubkey)
   91     xfree(keyring->pubkey);
   92   if(keyring->privkey)
   93     xfree(keyring->privkey);
   94 
   95   setzero(keyring, sizeof(lcl_cache_keyring));
   96 }
   97 
   98 /*
   99  * lcl_cache_new: builds a new lcl_cache generating a new rsa key pair and
  100  * setting the hostname in the struct
  101  */
  102 lcl_cache *lcl_cache_new(char *hname)
  103 {
  104   lcl_cache *alcl;
  105 
  106   alcl=(lcl_cache *)xzalloc(sizeof(lcl_cache));
  107 
  108   alcl->hostname = xstrdup(hname);
  109   alcl->hash = andna_32bit_hash(hname);
  110 
  111   return alcl;
  112 }
  113 
  114 void lcl_cache_free(lcl_cache *alcl)
  115 {
  116   if(alcl->hostname)
  117     xfree(alcl->hostname);
  118   alcl->snsd_counter=0;
  119   if(alcl->service)
  120     snsd_service_llist_del(&alcl->service);
  121 }
  122 
  123 void lcl_cache_destroy(lcl_cache *head, int *counter)
  124 {
  125   lcl_cache *alcl=head, *next;
  126 
  127   if(!alcl || !lcl_counter)
  128     return;
  129 
  130   list_safe_for(alcl, next) {
  131     lcl_cache_free(alcl);
  132     xfree(alcl);
  133   }
  134   *counter=0;
  135 }
  136 
  137 lcl_cache *lcl_cache_find_hname(lcl_cache *alcl, char *hname)
  138 {
  139   u_int hash;
  140 
  141   if(!alcl || !lcl_counter)
  142     return 0;
  143 
  144   hash = andna_32bit_hash(hname);
  145   list_for(alcl)
  146     if(alcl->hash == hash && alcl->hostname &&
  147       !strncmp(alcl->hostname, hname, ANDNA_MAX_HNAME_LEN))
  148       return alcl;
  149   return 0;
  150 }
  151 
  152 lcl_cache *lcl_cache_find_hash(lcl_cache *alcl, u_int hash)
  153 {
  154   if(!alcl || !lcl_counter)
  155     return 0;
  156 
  157   list_for(alcl)
  158     if(alcl->hash == hash && alcl->hostname)
  159       return alcl;
  160   return 0;
  161 }
  162 
  163 int is_lcl_hname_registered(lcl_cache *alcl)
  164 {
  165   return alcl->timestamp;
  166 }
  167 
  168 /*
  169  * lcl_get_registered_hnames
  170  *
  171  * It returns a duplicated lcl_cache of `alcl', which contains only
  172  * hostnames already registered.
  173  * Note that the structs present in the returned cache are in a different
  174  * mallocated space, so you should free them.
  175  */
  176 lcl_cache *lcl_get_registered_hnames(lcl_cache *alcl)
  177 {
  178   lcl_cache *lcl;
  179 
  180   lcl=list_copy_some(alcl, is_lcl_hname_registered);
  181   list_for(lcl) {
  182     lcl->hostname=xstrdup(lcl->hostname);
  183     lcl->service=snsd_service_llist_copy(lcl->service,
  184                  SNSD_ALL_SERVICE, 0);
  185   }
  186 
  187   return lcl;
  188 }
  189 
  190 /*
  191  *
  192  *  *  *  *  Andna Cache functions  *  *  *
  193  *
  194  */
  195 
  196 andna_cache_queue *ac_queue_findpubk(andna_cache *ac, char *pubk)
  197 {
  198   andna_cache_queue *acq=ac->acq;
  199 
  200   if(!acq)
  201     return 0;
  202   list_for(acq)
  203     if(!memcmp(acq->pubkey, pubk, ANDNA_PKEY_LEN))
  204         return acq;
  205   return 0;
  206 }
  207 
  208 /*
  209  * ac_queue_add
  210  *
  211  * adds a new entry in the andna cache queue, which is `ac'->acq.
  212  * The elements in the new `ac'->acq are updated.
  213  * If an `ac'->acq struct with an `ac'->acq->pubkey equal to `pubkey' already
  214  * exists, then only the timestamp and the IP will be updated.
  215  *
  216  * It returns the pointer to the acq struct. If it isn't possible to add a new
  217  * entry in the queue, 0 will be returned.
  218  *
  219  * Remember to update the acq->timestamp value after this call.
  220  */
  221 andna_cache_queue *ac_queue_add(andna_cache *ac, char *pubkey)
  222 {
  223   andna_cache_queue *acq;
  224 
  225   /*
  226    * This call is not necessary because it's already done by
  227    * andna_cache_del_expired().
  228    * * ac_queue_del_expired(ac); * *
  229    */
  230 
  231   if(!(acq=ac_queue_findpubk(ac, pubkey))) {
  232     if(ac->queue_counter >= ANDNA_MAX_QUEUE || ac->flags & ANDNA_FULL)
  233       return 0;
  234 
  235     acq=xzalloc(sizeof(andna_cache_queue));
  236     memcpy(acq->pubkey, pubkey, ANDNA_PKEY_LEN);
  237     clist_append(&ac->acq, 0, &ac->queue_counter, acq);
  238   }
  239 
  240 
  241   if(ac->queue_counter >= ANDNA_MAX_QUEUE)
  242     ac->flags|=ANDNA_FULL;
  243 
  244   return acq;
  245 }
  246 
  247 void ac_queue_del(andna_cache *ac, andna_cache_queue *acq)
  248 {
  249 
  250   acq->snsd_counter=0;
  251   if(acq->service)
  252     snsd_service_llist_del(&acq->service);
  253   clist_del(&ac->acq, &ac->queue_counter, acq);
  254   ac->flags&=~ANDNA_FULL;
  255 }
  256 
  257 /*
  258  * ac_queue_del_expired: removes the expired entries from the
  259  * andna_cache_queue `ac'->acq.
  260  */
  261 void ac_queue_del_expired(andna_cache *ac)
  262 {
  263   andna_cache_queue *acq, *next;
  264   time_t cur_t;
  265 
  266   if(!ac || !ac->acq)
  267     return;
  268 
  269   cur_t=time(0);
  270   acq=ac->acq;
  271   list_safe_for(acq, next)
  272     if(cur_t - acq->timestamp > ANDNA_EXPIRATION_TIME)
  273       ac_queue_del(ac, acq);
  274 }
  275 
  276 /*
  277  * ac_queue_destroy: destroys an andna_cache_queue
  278  */
  279 void ac_queue_destroy(andna_cache *ac)
  280 {
  281   andna_cache_queue *acq, *next;
  282 
  283   if(!ac || !ac->acq)
  284     return;
  285 
  286   acq=ac->acq;
  287   list_safe_for(acq, next)
  288     ac_queue_del(ac, acq);
  289 }
  290 
  291 andna_cache *andna_cache_findhash(int hash[MAX_IP_INT])
  292 {
  293   andna_cache *ac=andna_c;
  294 
  295   if(!andna_c_counter)
  296     return 0;
  297 
  298   list_for(ac)
  299     if(!memcmp(ac->hash, hash, ANDNA_HASH_SZ))
  300       return ac;
  301   return 0;
  302 }
  303 
  304 /*
  305  * andna_cache_gethash
  306  *
  307  * It searches an andna_cache entry which has the same hash of `hash'.
  308  * If it found but this entry is expired, it is deleted from the cache and 0 is
  309  * returned.
  310  * If it isn't found 0 is returned, otherwise a pointer to the entry is
  311  * returned.
  312  */
  313 andna_cache *andna_cache_gethash(int hash[MAX_IP_INT])
  314 {
  315   andna_cache *ac;
  316 
  317   ac=andna_cache_findhash(hash);
  318   if(ac && andna_cache_del_ifexpired(ac))
  319     return 0;
  320 
  321   return ac;
  322 }
  323 
  324 andna_cache *andna_cache_addhash(int hash[MAX_IP_INT])
  325 {
  326   andna_cache *ac;
  327 
  328   andna_cache_del_expired();
  329 
  330   if(!(ac=andna_cache_findhash(hash))) {
  331     ac=xzalloc(sizeof(andna_cache));
  332     memcpy(ac->hash, hash, ANDNA_HASH_SZ);
  333 
  334     clist_add(&andna_c, &andna_c_counter, ac);
  335   }
  336 
  337   return ac;
  338 }
  339 
  340 /*
  341  * andna_cache_del_ifexpired
  342  *
  343  * If `ac' is expired, it deletes it and returns 1; otherwise 0 is returned.
  344  */
  345 int andna_cache_del_ifexpired(andna_cache *ac)
  346 {
  347   ac_queue_del_expired(ac);
  348 
  349   if(!ac->queue_counter) {
  350     clist_del(&andna_c, &andna_c_counter, ac);
  351     return 1;
  352   }
  353 
  354   return 0;
  355 }
  356 
  357 void andna_cache_del_expired(void)
  358 {
  359         andna_cache *ac=andna_c, *next;
  360 
  361         if(!andna_c_counter)
  362                 return;
  363 
  364   list_safe_for(ac, next)
  365     andna_cache_del_ifexpired(ac);
  366 }
  367 
  368 /*
  369  * andna_cache_destroy
  370  *
  371  * destroys the andna_c llist
  372  */
  373 void andna_cache_destroy(void)
  374 {
  375   andna_cache *ac=andna_c, *next;
  376 
  377         if(!andna_c_counter)
  378                 return;
  379 
  380   list_safe_for(ac, next) {
  381     ac_queue_destroy(ac);
  382     clist_del(&andna_c, &andna_c_counter, ac);
  383   }
  384 }
  385 
  386 
  387 /*
  388  *
  389  *  *  *  *  Counter Cache functions  *  *  *
  390  *
  391  */
  392 
  393 /*
  394  * Remeber to update the cch->timestamp value after this call.
  395  */
  396 counter_c_hashes *cc_hashes_add(counter_c *cc, int hash[MAX_IP_INT])
  397 {
  398   counter_c_hashes *cch;
  399 
  400   /* The purge is already done in counter_c_del_expired(), so it is not
  401    * necessary to call it here.
  402    * * cc_hashes_del_expired(cc); * *
  403    */
  404 
  405   if(!(cch=cc_findhash(cc, hash))) {
  406     if(cc->hashes >= ANDNA_MAX_HOSTNAMES || cc->flags & ANDNA_FULL)
  407       return 0;
  408 
  409     cch=xzalloc(sizeof(counter_c_hashes));
  410     memcpy(cch->hash, hash, ANDNA_HASH_SZ);
  411 
  412     clist_add(&cc->cch, &cc->hashes, cch);
  413   }
  414 
  415   if(cc->hashes >= ANDNA_MAX_HOSTNAMES)
  416     cc->flags|=ANDNA_FULL;
  417 
  418   return cch;
  419 }
  420 
  421 void cc_hashes_del(counter_c *cc, counter_c_hashes *cch)
  422 {
  423   clist_del(&cc->cch, &cc->hashes, cch);
  424   cc->flags&=~ANDNA_FULL;
  425 }
  426 
  427 void cc_hashes_del_expired(counter_c *cc)
  428 {
  429   counter_c_hashes *cch, *next;
  430   time_t cur_t;
  431 
  432   if(!cc || !cc->cch || !cc->hashes)
  433     return;
  434 
  435   cur_t=time(0);
  436   cch=cc->cch;
  437 
  438   list_safe_for(cch, next)
  439     if(cur_t - cch->timestamp > ANDNA_EXPIRATION_TIME)
  440       cc_hashes_del(cc, cch);
  441 }
  442 
  443 void cc_hashes_destroy(counter_c *cc)
  444 {
  445   counter_c_hashes *cch, *next;
  446 
  447   if(!cc || !cc->cch || !cc->hashes)
  448     return;
  449 
  450   cch=cc->cch;
  451   list_safe_for(cch, next)
  452     cc_hashes_del(cc, cch);
  453 }
  454 
  455 counter_c_hashes *cc_findhash(counter_c *cc, int hash[MAX_IP_INT])
  456 {
  457   counter_c_hashes *cch=cc->cch;
  458 
  459   if(!cc->hashes || !cch)
  460     return 0;
  461 
  462   list_for(cch)
  463     if(!memcmp(cch->hash, hash, ANDNA_HASH_SZ))
  464       return cch;
  465   return 0;
  466 }
  467 
  468 counter_c *counter_c_findpubk(char *pubk)
  469 {
  470   counter_c *cc=andna_counter_c;
  471 
  472   if(!cc_counter || !cc)
  473     return 0;
  474 
  475   list_for(cc)
  476     if(!memcmp(&cc->pubkey, pubk, ANDNA_PKEY_LEN))
  477       return cc;
  478   return 0;
  479 }
  480 
  481 counter_c *counter_c_add(inet_prefix *rip, char *pubkey)
  482 {
  483   counter_c *cc;
  484 
  485   counter_c_del_expired();
  486 
  487   if(!(cc=counter_c_findpubk(pubkey))) {
  488     cc=xzalloc(sizeof(counter_c));
  489 
  490     memcpy(cc->pubkey, pubkey, ANDNA_PKEY_LEN);
  491     clist_add(&andna_counter_c, &cc_counter, cc);
  492   }
  493 
  494   return cc;
  495 }
  496 
  497 void counter_c_del_expired(void)
  498 {
  499   counter_c *cc=andna_counter_c, *next;
  500 
  501   if(!cc)
  502     return;
  503 
  504   list_safe_for(cc, next) {
  505     cc_hashes_del_expired(cc);
  506     if(!cc->hashes)
  507       clist_del(&andna_counter_c, &cc_counter, cc);
  508   }
  509 }
  510 
  511 /*
  512  * counter_c_destroy
  513  *
  514  * destroy the andna_counter_c llist
  515  */
  516 void counter_c_destroy(void)
  517 {
  518   counter_c *cc=andna_counter_c, *next;
  519 
  520   if(!cc)
  521     return;
  522 
  523   list_safe_for(cc, next) {
  524     cc_hashes_destroy(cc);
  525     clist_del(&andna_counter_c, &cc_counter, cc);
  526   }
  527 }
  528 
  529 /*
  530  *
  531  *  *  *  *  Resolved hostnames cache functions  *  *  *
  532  *
  533  */
  534 
  535 rh_cache *rh_cache_new_hash(u_int hash, time_t timestamp)
  536 {
  537   rh_cache *rhc;
  538 
  539   rhc=xzalloc(sizeof(rh_cache));
  540   rhc->hash=hash;
  541   rhc->timestamp=timestamp;
  542 
  543   return rhc;
  544 }
  545 
  546 rh_cache *rh_cache_new(char *hname, time_t timestamp)
  547 {
  548   return rh_cache_new_hash(andna_32bit_hash(hname), timestamp);
  549 }
  550 
  551 /*
  552  * rh_cache_add_hash
  553  *
  554  * It searches a struct in the rh_cache which has the hash value equal to
  555  * `hash'.
  556  * If it isn't found a new one is added. In both cases the pointer to the
  557  * struct will be returned.
  558  *
  559  * On error 0 is returned.
  560  */
  561 rh_cache *rh_cache_add_hash(u_int hash, time_t timestamp)
  562 {
  563   rh_cache *rhc;
  564 
  565   if(!(rhc=rh_cache_find_hash(hash))) {
  566     if(rhc_counter >= ANDNA_MAX_HOSTNAMES) {
  567       /* Delete the expired hnames and see if there's empty
  568        * space */
  569       rh_cache_del_expired();
  570 
  571       if(rhc_counter >= ANDNA_MAX_HOSTNAMES) {
  572         /* Delete the oldest struct in cache */
  573         rhc=list_last(andna_rhc);
  574         clist_del(&andna_rhc, &rhc_counter, rhc);
  575       }
  576     }
  577 
  578     rhc=rh_cache_new_hash(hash, timestamp);
  579     clist_add(&andna_rhc, &rhc_counter, rhc);
  580   }
  581 
  582   rhc->timestamp=timestamp;
  583 
  584   return rhc;
  585 }
  586 
  587 /*
  588  * rh_cache_add
  589  *
  590  * It searches a struct in the rh_cache which is associated to `hname'.
  591  * If it isn't found a new one is added. In both cases the pointer to the
  592  * struct will be returned.
  593  *
  594  * On error 0 is returned.
  595  */
  596 rh_cache *rh_cache_add(char *hname, time_t timestamp)
  597 {
  598   return rh_cache_add_hash(andna_32bit_hash(hname), timestamp);
  599 }
  600 
  601 rh_cache *rh_cache_find_hash(u_int hash)
  602 {
  603   rh_cache *rhc=andna_rhc, *next;
  604   time_t cur_t;
  605 
  606   if(!rhc || !rhc_counter)
  607     return 0;
  608 
  609   cur_t=time(0);
  610 
  611   list_safe_for(rhc, next)
  612     if(rhc->hash == hash) {
  613       if(cur_t - rhc->timestamp > ANDNA_EXPIRATION_TIME) {
  614         /* This hostname expired, delete it from the
  615          * cache */
  616         rh_cache_del(rhc);
  617         continue;
  618       } else
  619         /* Each time we find a hname in the rh_cache,
  620          * we move it on top of the llist. */
  621         andna_rhc=list_moveontop(andna_rhc, rhc);
  622       return rhc;
  623     }
  624   return 0;
  625 }
  626 
  627 rh_cache *rh_cache_find_hname(char *hname)
  628 {
  629   u_int hash;
  630 
  631   hash=andna_32bit_hash(hname);
  632   return rh_cache_find_hash(hash);
  633 }
  634 
  635 void rh_cache_del(rh_cache *rhc)
  636 {
  637   rhc->snsd_counter=0;
  638   if(rhc->service)
  639     snsd_service_llist_del(&rhc->service);
  640 
  641   clist_del(&andna_rhc, &rhc_counter, rhc);
  642 }
  643 
  644 void rh_cache_del_expired(void)
  645 {
  646   rh_cache *rhc=andna_rhc, *next;
  647   time_t cur_t;
  648 
  649   if(!rhc || !rhc_counter)
  650     return;
  651 
  652   cur_t=time(0);
  653 
  654   list_safe_for(rhc, next)
  655     if(cur_t - rhc->timestamp > ANDNA_EXPIRATION_TIME)
  656       rh_cache_del(rhc);
  657 }
  658 
  659 void rh_cache_flush(void)
  660 {
  661   rh_cache *rhc=andna_rhc, *next;
  662 
  663   list_safe_for(rhc, next)
  664     rh_cache_del(rhc);
  665 }
  666 
  667 /*
  668  *
  669  *  *  *  *  Pack/Unpack functions  *  *  *
  670  *
  671  */
  672 
  673 char *pack_lcl_keyring(lcl_cache_keyring *keyring, size_t *pack_sz)
  674 {
  675   struct lcl_keyring_pkt_hdr key_hdr;
  676   size_t sz;
  677   char *pack, *buf;
  678 
  679   key_hdr.skey_len=keyring->skey_len;
  680   key_hdr.pkey_len=keyring->pkey_len;
  681   sz=LCL_KEYRING_HDR_PACK_SZ(&key_hdr);
  682 
  683   pack=buf=xmalloc(sz);
  684   bufput(&key_hdr, sizeof(struct lcl_keyring_pkt_hdr));
  685   ints_host_to_network(pack, lcl_keyring_pkt_hdr_iinfo);
  686 
  687   bufput(keyring->privkey, keyring->skey_len);
  688   bufput(keyring->pubkey, keyring->pkey_len);
  689 
  690   *pack_sz=sz;
  691   return pack;
  692 }
  693 
  694 /*
  695  * unpack_lcl_keyring: unpacks a lcl keyring. On error it returns -1.
  696  * In `keyring' it restores the packed keys.
  697  */
  698 int unpack_lcl_keyring(lcl_cache_keyring *keyring, char *pack, size_t pack_sz)
  699 {
  700   struct lcl_keyring_pkt_hdr *hdr;
  701   char *buf;
  702   u_char *pk;
  703 
  704 
  705   hdr=(struct lcl_keyring_pkt_hdr *)pack;
  706   ints_network_to_host(hdr, lcl_keyring_pkt_hdr_iinfo);
  707 
  708   /*
  709    * Restore the keyring
  710    */
  711   keyring->skey_len=hdr->skey_len;
  712   keyring->pkey_len=hdr->pkey_len;
  713   if(keyring->skey_len > ANDNA_SKEY_MAX_LEN) {
  714     error(ERROR_MSG "Invalid keyring header", ERROR_FUNC);
  715     return -1;
  716   }
  717 
  718   keyring->privkey=xmalloc(hdr->skey_len);
  719   keyring->pubkey=xmalloc(hdr->pkey_len);
  720 
  721   /* extract the private key */
  722   buf=pack+sizeof(struct lcl_keyring_pkt_hdr);
  723   bufget(keyring->privkey, hdr->skey_len);
  724 
  725   /* public key */
  726   bufget(keyring->pubkey, hdr->pkey_len);
  727 
  728   pk=keyring->privkey;
  729   if(!(keyring->priv_rsa=get_rsa_priv((const u_char **)&pk,
  730           keyring->skey_len))) {
  731     error(ERROR_MSG "Cannot unpack the priv key from the"
  732         " lcl_pack: %s", ERROR_POS, ssl_strerr());
  733     return -1;
  734   }
  735 
  736   return 0;
  737 }
  738 
  739 /*
  740  * pack_lcl_cache
  741  *
  742  * packs the entire local cache linked list that starts with the head
  743  * `local_cache'. The size of the pack is stored in `pack_sz'.
  744  * The pointer to the newly allocated pack is returned.
  745  * Note that the pack is in network byte order.
  746  */
  747 char *pack_lcl_cache(lcl_cache *local_cache, size_t *pack_sz)
  748 {
  749   struct lcl_cache_pkt_hdr lcl_hdr;
  750   lcl_cache *alcl=local_cache;
  751   size_t sz=0, slen;
  752   char *pack, *buf, *body;
  753 
  754   lcl_hdr.tot_caches=0;
  755   sz=LCL_CACHE_HDR_PACK_SZ;
  756 
  757   /* Calculate the final pack size */
  758   list_for(alcl) {
  759     sz+=LCL_CACHE_BODY_PACK_SZ(strlen(alcl->hostname)+1);
  760     lcl_hdr.tot_caches++;
  761   }
  762 
  763   pack=buf=xmalloc(sz);
  764   bufput(&lcl_hdr, sizeof(struct lcl_cache_pkt_hdr));
  765   ints_host_to_network(pack, lcl_cache_pkt_hdr_iinfo);
  766 
  767   *pack_sz=0;
  768   if(lcl_hdr.tot_caches) {
  769     alcl=local_cache;
  770 
  771     list_for(alcl) {
  772       body=buf;
  773 
  774       bufput(&alcl->hname_updates, sizeof(u_short));
  775       bufput(&alcl->timestamp, sizeof(time_t));
  776 
  777       slen=strlen(alcl->hostname)+1;
  778       bufput(alcl->hostname, slen);
  779 
  780       ints_host_to_network(body, lcl_cache_pkt_body_iinfo);
  781     }
  782   }
  783 
  784   *pack_sz=sz;
  785   return pack;
  786 }
  787 
  788 /*
  789  * unpack_lcl_cache
  790  *
  791  * Unpacks a packed local cache linked list and returns its head.
  792  * `counter' is set to the number of struct in the llist.
  793  *
  794  * On error 0 is returned and `*counter' is set to -1.
  795  *
  796  * Note: `pack' is modified during the unpacking.
  797  */
  798 lcl_cache *unpack_lcl_cache(char *pack, size_t pack_sz, int *counter)
  799 {
  800   struct lcl_cache_pkt_hdr *hdr;
  801   lcl_cache *alcl, *alcl_head=0;
  802   char *buf;
  803   size_t slen, unpacked_sz;
  804   int i=0;
  805 
  806   hdr=(struct lcl_cache_pkt_hdr *)pack;
  807   buf=pack+sizeof(struct lcl_cache_pkt_hdr);
  808   unpacked_sz=sizeof(struct lcl_cache_pkt_hdr);
  809   ints_network_to_host(hdr, lcl_cache_pkt_hdr_iinfo);
  810   *counter=0;
  811 
  812   if(hdr->tot_caches > ANDNA_MAX_HOSTNAMES)
  813     ERROR_FINISH(*counter, -1, finish);
  814 
  815   *counter=0;
  816   if(hdr->tot_caches) {
  817     for(i=0; i<hdr->tot_caches; i++) {
  818       unpacked_sz+=LCL_CACHE_BODY_PACK_SZ(0);
  819       if(unpacked_sz > pack_sz)
  820         ERROR_FINISH(*counter, -1, finish);
  821 
  822       slen=strlen(buf+sizeof(u_short)+sizeof(time_t))+1;
  823       if(slen > ANDNA_MAX_HNAME_LEN ||
  824           (unpacked_sz+=slen) > pack_sz)
  825         ERROR_FINISH(*counter, -1, finish);
  826 
  827       ints_network_to_host(buf, lcl_cache_pkt_body_iinfo);
  828 
  829       alcl=xzalloc(sizeof(lcl_cache));
  830 
  831       bufget(&alcl->hname_updates,  sizeof(u_short));
  832       bufget(&alcl->timestamp, sizeof(time_t));
  833 
  834       alcl->hostname=xstrdup(buf);
  835       alcl->hash=andna_32bit_hash(alcl->hostname);
  836       buf+=slen;
  837 
  838       clist_add(&alcl_head, counter, alcl);
  839     }
  840   }
  841 
  842 finish:
  843   return alcl_head;
  844 }
  845 
  846 /*
  847  * pack_andna_cache_queue
  848  *
  849  * It packs an andna_cache_queue struct. The package is stored in `pack' which
  850  * has `tot_pack_sz' allocated bytes.
  851  * `acq' is the struct which will be packed.
  852  * `pack_type' is equal to ACACHE_PACK_FILE or ACACHE_PACK_PKT, it specify if
  853  * the package will be stored in a file or will be sent over a network.
  854  *
  855  * The number of bytes written in `pack' is returned.
  856  */
  857 int pack_andna_cache_queue(char *pack, size_t tot_pack_sz,
  858          andna_cache_queue *acq, int pack_type)
  859 {
  860   char *buf=pack;
  861   u_int t;
  862   int pack_sz=0;
  863 
  864   if(pack_type == ACACHE_PACK_PKT)
  865     t = time(0) - acq->timestamp;
  866   else
  867     t = acq->timestamp;
  868 
  869   bufput(&t, sizeof(uint32_t));
  870   bufput(&acq->hname_updates, sizeof(u_short));
  871   bufput(&acq->pubkey, ANDNA_PKEY_LEN);
  872   bufput(&acq->snsd_counter, sizeof(u_short));
  873 
  874   pack_sz+=ACQ_BODY_PACK_SZ;
  875   ints_host_to_network(pack, acq_body_iinfo);
  876 
  877   pack_sz+=snsd_pack_all_services(buf, tot_pack_sz, acq->service);
  878 
  879   return pack_sz;
  880 }
  881 
  882 /*
  883  * pack_single_andna_cache
  884  *
  885  * It packs an andna_cache struct. The package is stored in `pack' which
  886  * has `tot_pack_sz' allocated bytes.
  887  * `ac' is the struct which will be packed.
  888  * `pack_type' is equal to ACACHE_PACK_FILE or ACACHE_PACK_PKT, it specify if
  889  * the package will be stored in a file or will be sent over a network.
  890  *
  891  * The number of bytes written in `pack' is returned.
  892  */
  893 int pack_single_andna_cache(char *pack, size_t tot_pack_sz,
  894           andna_cache *ac, int pack_type)
  895 {
  896   andna_cache_queue *acq;
  897   char *buf=pack;
  898   int pack_sz=0;
  899   size_t psz;
  900 
  901   bufput(ac->hash, ANDNA_HASH_SZ);
  902   bufput(&ac->flags, sizeof(char));
  903   bufput(&ac->queue_counter, sizeof(u_short));
  904 
  905   pack_sz+=ACACHE_BODY_PACK_SZ;
  906   ints_host_to_network(pack, andna_cache_body_iinfo);
  907 
  908   acq=ac->acq;
  909   list_for(acq) {
  910     psz=pack_andna_cache_queue(buf, tot_pack_sz, acq, pack_type);
  911     buf+=psz;
  912     pack_sz+=psz;
  913     tot_pack_sz-=psz;
  914   }
  915 
  916   return pack_sz;
  917 }
  918 
  919 /*
  920  * pack_andna_cache
  921  *
  922  * It packs the entire andna cache linked list that starts with
  923  * the head `acache'.
  924  * The size of the pack is stored in `pack_sz'.
  925  * `pack_type' specifies if the package will be saved in a file or sent over
  926  * the net, it is equal to ACACHE_PACK_FILE or to ACACHE_PACK_PKT.
  927  *
  928  * The pointer to the newly allocated pack is returned.
  929  * The pack is written in network order.
  930  */
  931 char *pack_andna_cache(andna_cache *acache, size_t *pack_sz, int pack_type)
  932 {
  933   struct andna_cache_pkt_hdr hdr;
  934   andna_cache *ac=acache;
  935   andna_cache_queue *acq;
  936   char *pack, *buf;
  937   size_t sz, free_sz, acq_sz, service_sz, psz;
  938 
  939   /* Calculate the pack size */
  940   ac=acache;
  941   hdr.tot_caches=0;
  942   sz=sizeof(struct andna_cache_pkt_hdr);
  943   list_for(ac) {
  944     acq=ac->acq;
  945     acq_sz=0;
  946     list_for(acq) {
  947       service_sz = SNSD_SERVICE_LLIST_PACK_SZ(acq->service);
  948       acq_sz     = ACQ_PACK_SZ(service_sz);
  949     }
  950     sz+=ACACHE_PACK_SZ(acq_sz);
  951     hdr.tot_caches++;
  952   }
  953 
  954 
  955   free_sz=sz;
  956   buf=pack=xmalloc(sz);
  957 
  958   /* Write the header of the package */
  959   bufput(&hdr, sizeof(struct andna_cache_pkt_hdr));
  960   free_sz-=sizeof(struct andna_cache_pkt_hdr);
  961 
  962   ints_host_to_network(pack, andna_cache_pkt_hdr_iinfo);
  963 
  964   if(!hdr.tot_caches)
  965     goto finish;
  966 
  967   /* Pack the rest of the andna_cache */
  968   ac=acache;
  969   list_for(ac) {
  970     psz=pack_single_andna_cache(buf, free_sz, ac, pack_type);
  971     buf+=psz;
  972     free_sz-=psz;
  973   }
  974 
  975 finish:
  976   *pack_sz=sz;
  977   return pack;
  978 }
  979 
  980 /*
  981  * unpack_acq_llist
  982  *
  983  * ac->queue_counter must contain the number of acq structs contained in the
  984  * package.
  985  *
  986  * `*unpacked_sz' is incremented by the number of unpacked bytes.
  987  *
  988  * `pack_type' specifies if the package will be saved in a file or sent over
  989  * the net, it is equal to ACACHE_PACK_FILE or to ACACHE_PACK_PKT.
  990  */
  991 andna_cache_queue *
  992 unpack_acq_llist(char *pack, size_t pack_sz, size_t *unpacked_sz,
  993       andna_cache *ac, int pack_type)
  994 {
  995   andna_cache_queue *acq=0;
  996   int e, tmp_counter=0;
  997   u_short snsd_counter;
  998   time_t cur_t;
  999   char *buf;
 1000 
 1001   cur_t=time(0);
 1002   buf=pack;
 1003   for(e=0; e < ac->queue_counter; e++) {
 1004     acq=xzalloc(sizeof(andna_cache_queue));
 1005 
 1006     ints_network_to_host(buf, acq_body_iinfo);
 1007 
 1008     bufget(&acq->timestamp, sizeof(uint32_t));
 1009     if(pack_type == ACACHE_PACK_PKT)
 1010       acq->timestamp = cur_t - acq->timestamp;
 1011 
 1012     bufget(&acq->hname_updates, sizeof(u_short));
 1013     bufget(&acq->pubkey, ANDNA_PKEY_LEN);
 1014     bufget(&acq->snsd_counter, sizeof(u_short));
 1015 
 1016     pack_sz-=ACACHE_BODY_PACK_SZ;
 1017     (*unpacked_sz)+=ACACHE_BODY_PACK_SZ;
 1018     acq->service=snsd_unpack_all_service(buf, pack_sz, unpacked_sz,
 1019               &snsd_counter);
 1020     if(acq->snsd_counter != snsd_counter) {
 1021       debug(DBG_SOFT, ERROR_MSG "unpack_acq:"
 1022           "snsd_counter (%d) != snsd_counter (%d)",
 1023           ERROR_POS, acq->snsd_counter,
 1024           snsd_counter);
 1025       xfree(acq);
 1026       list_destroy(ac->acq);
 1027       return 0;
 1028     }
 1029 
 1030     clist_add(&ac->acq, &tmp_counter, acq);
 1031   }
 1032 
 1033   return ac->acq;
 1034 }
 1035 
 1036 /*
 1037  * unpack_andna_cache
 1038  *
 1039  * Unpacks a packed andna cache linked list and returns the
 1040  * its head.
 1041  * `counter' is set to the number of struct in the llist.
 1042  * `pack_type' specifies if the package will be saved in a file or sent over
 1043  * the net, it is equal to ACACHE_PACK_FILE or to ACACHE_PACK_PKT.
 1044  *
 1045  * On error 0 is returned and `*counter' is set to -1.
 1046  * Warning: `pack' will be modified during the unpacking.
 1047  */
 1048 andna_cache *unpack_andna_cache(char *pack, size_t pack_sz, int *counter,
 1049     int pack_type)
 1050 {
 1051   struct andna_cache_pkt_hdr *hdr;
 1052   andna_cache *ac, *ac_head=0;
 1053   char *buf;
 1054   size_t sz=0;
 1055   int i, err=0;
 1056   size_t unpacked_sz=0;
 1057 
 1058   hdr=(struct andna_cache_pkt_hdr *)pack;
 1059   ints_network_to_host(hdr, andna_cache_pkt_hdr_iinfo);
 1060   *counter=0;
 1061 
 1062   if(!hdr->tot_caches)
 1063     ERROR_FINISH(err, 1, finish);
 1064 
 1065   buf=pack + sizeof(struct andna_cache_pkt_hdr);
 1066   sz=sizeof(struct andna_cache_pkt_hdr);
 1067 
 1068   for(i=0; i<hdr->tot_caches; i++) {
 1069     sz+=ACACHE_BODY_PACK_SZ;
 1070     if(sz > pack_sz)
 1071       ERROR_FINISH(err, 1, finish); /* overflow */
 1072 
 1073     ac=xzalloc(sizeof(andna_cache));
 1074 
 1075     ints_network_to_host(buf, andna_cache_body_iinfo);
 1076 
 1077     bufget(ac->hash, ANDNA_HASH_SZ);
 1078     bufget(&ac->flags, sizeof(char));
 1079     bufget(&ac->queue_counter, sizeof(u_short));
 1080 
 1081     sz+=ACQ_PACK_SZ(0)*ac->queue_counter;
 1082     if(sz > pack_sz)
 1083       ERROR_FINISH(err, 1, finish); /* overflow */
 1084 
 1085     unpacked_sz+=ACACHE_BODY_PACK_SZ;
 1086 
 1087     ac->acq=unpack_acq_llist(buf, pack_sz-unpacked_sz, &unpacked_sz,
 1088         ac, pack_type);
 1089     clist_add(&ac_head, counter, ac);
 1090   }
 1091 
 1092 finish:
 1093   if(err)
 1094     *counter=-1;
 1095   return ac_head;
 1096 }
 1097 
 1098 /*
 1099  * pack_counter_cache: packs the entire counter cache linked list that starts
 1100  * with the head `counter'. The size of the pack is stored in `pack_sz'.
 1101  * The pointer to the newly allocated pack is returned.
 1102  * The pack will be in network order.
 1103  */
 1104 char *pack_counter_cache(counter_c *countercache, size_t *pack_sz)
 1105 {
 1106   struct counter_c_pkt_hdr hdr;
 1107   counter_c *cc=countercache;
 1108   counter_c_hashes *cch;
 1109   char *pack, *buf, *p;
 1110   size_t sz;
 1111   time_t cur_t;
 1112   uint32_t t;
 1113 
 1114   /* Calculate the pack size */
 1115   hdr.tot_caches=0;
 1116   sz=sizeof(struct counter_c_pkt_hdr);
 1117   list_for(cc) {
 1118     sz+=COUNTER_CACHE_PACK_SZ(cc->hashes);
 1119     hdr.tot_caches++;
 1120   }
 1121 
 1122   pack=xmalloc(sz);
 1123   memcpy(pack, &hdr, sizeof(struct counter_c_pkt_hdr));
 1124   ints_host_to_network(pack, counter_c_pkt_hdr_iinfo);
 1125 
 1126   if(hdr.tot_caches) {
 1127     cur_t=time(0);
 1128 
 1129     buf=pack + sizeof(struct counter_c_pkt_hdr);
 1130     cc=countercache;
 1131     list_for(cc) {
 1132       p=buf;
 1133 
 1134       bufput(cc->pubkey, ANDNA_PKEY_LEN);
 1135       bufput(&cc->flags, sizeof(char));
 1136       bufput(&cc->hashes, sizeof(u_short));
 1137 
 1138       ints_host_to_network(p, counter_c_body_iinfo);
 1139 
 1140       cch=cc->cch;
 1141       list_for(cch) {
 1142         p=buf;
 1143 
 1144         t = cur_t - cch->timestamp;
 1145         bufput(&t, sizeof(uint32_t));
 1146 
 1147         bufput(&cch->hname_updates, sizeof(u_short));
 1148         bufput(cch->hash, ANDNA_HASH_SZ);
 1149 
 1150         ints_host_to_network(p, counter_c_hashes_body_iinfo);
 1151       }
 1152     }
 1153   }
 1154 
 1155   *pack_sz=sz;
 1156   return pack;
 1157 }
 1158 
 1159 
 1160 /*
 1161  * unpack_counter_cache
 1162  *
 1163  * Unpacks a packed counter cache linked list and returns the its head.
 1164  * `counter' is set to the number of struct in the llist.
 1165  *
 1166  * On error 0 is returned and `*counter' is set to -1.
 1167  *
 1168  * Note: `pack' will be modified during the unpacking.
 1169  */
 1170 counter_c *unpack_counter_cache(char *pack, size_t pack_sz, int *counter)
 1171 {
 1172   struct counter_c_pkt_hdr *hdr;
 1173   counter_c *cc, *cc_head=0;
 1174   counter_c_hashes *cch;
 1175   char *buf;
 1176   size_t sz;
 1177   int i, e, fake_int=0;
 1178   time_t cur_t;
 1179 
 1180   hdr=(struct counter_c_pkt_hdr *)pack;
 1181   ints_network_to_host(hdr, counter_c_pkt_hdr_iinfo);
 1182   *counter=0;
 1183 
 1184   if(hdr->tot_caches) {
 1185     cur_t = time(0);
 1186 
 1187     buf=pack + sizeof(struct counter_c_pkt_hdr);
 1188     sz=sizeof(struct counter_c_pkt_hdr);
 1189 
 1190     for(i=0; i<hdr->tot_caches; i++) {
 1191       sz+=COUNTER_CACHE_BODY_PACK_SZ;
 1192       if(sz > pack_sz)
 1193         /* We don't want to overflow */
 1194         ERROR_FINISH(*counter, -1, finish);
 1195 
 1196       cc=xzalloc(sizeof(counter_c));
 1197 
 1198       ints_network_to_host(buf, counter_c_body_iinfo);
 1199 
 1200       bufget(cc->pubkey, ANDNA_PKEY_LEN);
 1201       bufget(&cc->flags, sizeof(char));
 1202       bufget(&cc->hashes, sizeof(u_short));
 1203 
 1204 
 1205       sz+=COUNTER_CACHE_HASHES_PACK_SZ * cc->hashes;
 1206       if(sz > pack_sz)
 1207         /* bleah */
 1208         ERROR_FINISH(*counter, -1, finish);
 1209 
 1210       for(e=0; e < cc->hashes; e++) {
 1211         cch=xzalloc(sizeof(counter_c_hashes));
 1212 
 1213         ints_network_to_host(buf, counter_c_hashes_body_iinfo);
 1214 
 1215         cch->timestamp=0;
 1216         bufget(&cch->timestamp, sizeof(uint32_t));
 1217         cch->timestamp = cur_t - cch->timestamp;
 1218 
 1219         bufget(&cch->hname_updates, sizeof(u_short));
 1220         bufget(cch->hash, ANDNA_HASH_SZ);
 1221 
 1222         clist_add(&cc->cch, &fake_int, cch);
 1223       }
 1224 
 1225       clist_add(&cc_head, counter, cc);
 1226     }
 1227   }
 1228 finish:
 1229   return cc_head;
 1230 }
 1231 
 1232 
 1233 /*
 1234  * pack_rh_cache
 1235  *
 1236  * It packs the entire resolved hnames cache linked list that starts
 1237  * with the head `rhcache'. The size of the pack is stored in `pack_sz'.
 1238  * The pointer to the newly allocated pack is returned.
 1239  * The pack will be in network order.
 1240  */
 1241 char *pack_rh_cache(rh_cache *rhcache, size_t *pack_sz)
 1242 {
 1243   struct rh_cache_pkt_hdr rh_hdr;
 1244   rh_cache *rhc=rhcache;
 1245   size_t tot_pack_sz=0, service_sz;
 1246   char *pack, *buf, *body;
 1247 
 1248   rh_hdr.tot_caches=0;
 1249   tot_pack_sz=sizeof(struct rh_cache_pkt_hdr);
 1250 
 1251   /* Calculate the final pack size */
 1252   list_for(rhc) {
 1253     service_sz=SNSD_SERVICE_LLIST_PACK_SZ(rhc->service);
 1254     tot_pack_sz+=RH_CACHE_BODY_PACK_SZ(service_sz);
 1255     rh_hdr.tot_caches++;
 1256   }
 1257   *pack_sz=tot_pack_sz;
 1258 
 1259   buf=pack=xmalloc(tot_pack_sz);
 1260   bufput(&rh_hdr, sizeof(struct rh_cache_pkt_hdr));
 1261   tot_pack_sz-=sizeof(struct rh_cache_pkt_hdr);
 1262 
 1263   ints_host_to_network(pack, rh_cache_pkt_hdr_iinfo);
 1264 
 1265   if(rh_hdr.tot_caches) {
 1266     rhc=rhcache;
 1267 
 1268     list_for(rhc) {
 1269       body=buf;
 1270 
 1271       bufput(&rhc->hash, sizeof(u_int));
 1272       bufput(&rhc->flags, sizeof(char));
 1273       bufput(&rhc->timestamp, sizeof(time_t));
 1274 
 1275       tot_pack_sz-=RH_CACHE_BODY_PACK_SZ(0);
 1276 
 1277       tot_pack_sz-=snsd_pack_all_services(buf, tot_pack_sz,
 1278                  rhc->service);
 1279 
 1280       /* host -> network order */
 1281       ints_host_to_network(buf, rh_cache_pkt_body_iinfo);
 1282     }
 1283   }
 1284 
 1285   return pack;
 1286 }
 1287 
 1288 /*
 1289  * unpack_rh_cache
 1290  *
 1291  * Unpacks a packed resolved hnames cache linked list and returns its head.
 1292  * `counter' is set to the number of struct in the llist.
 1293  *
 1294  * On error 0 is returned and `*counter' is set to -1.
 1295  *
 1296  * Note: `pack' will be modified during the unpacking.
 1297  */
 1298 rh_cache *unpack_rh_cache(char *pack, size_t pack_sz, int *counter)
 1299 {
 1300   struct rh_cache_pkt_hdr *hdr;
 1301   rh_cache *rhc=0, *rhc_head=0;
 1302   char *buf;
 1303   size_t unpacked_sz=0;
 1304   int i=0;
 1305 
 1306   hdr=(struct rh_cache_pkt_hdr *)pack;
 1307   ints_network_to_host(hdr, rh_cache_pkt_hdr_iinfo);
 1308   *counter=0;
 1309 
 1310   if(hdr->tot_caches > ANDNA_MAX_RHC_HNAMES)
 1311     ERROR_FINISH(*counter, -1, finish);
 1312 
 1313   *counter=0;
 1314   if(hdr->tot_caches) {
 1315     buf=pack + sizeof(struct rh_cache_pkt_hdr);
 1316     unpacked_sz=sizeof(struct rh_cache_pkt_hdr);
 1317 
 1318     for(i=0; i<hdr->tot_caches; i++) {
 1319       unpacked_sz+=RH_CACHE_BODY_PACK_SZ(0);
 1320       if(unpacked_sz > pack_sz)
 1321         ERROR_FINISH(*counter, -1, finish);
 1322 
 1323       ints_network_to_host(buf, rh_cache_pkt_body_iinfo);
 1324 
 1325       rhc=xzalloc(sizeof(rh_cache));
 1326 
 1327       bufget(&rhc->hash, sizeof(u_int));
 1328       bufget(&rhc->flags, sizeof(char));
 1329       bufget(&rhc->timestamp, sizeof(time_t));
 1330 
 1331       rhc->service=snsd_unpack_all_service(buf, pack_sz,
 1332           &unpacked_sz, 0);
 1333 
 1334       clist_add(&rhc_head, counter, rhc);
 1335     }
 1336   }
 1337 
 1338 finish:
 1339   return rhc_head;
 1340 }
 1341 
 1342 
 1343 /*
 1344  *
 1345  *  *  *  *  Save/Load functions  *  *  *
 1346  *
 1347  */
 1348 
 1349 /*
 1350  * save_lcl_keyring: saves a local cache keyring in the specified `file'.
 1351  */
 1352 int save_lcl_keyring(lcl_cache_keyring *keyring, char *file)
 1353 {
 1354   FILE *fd;
 1355   size_t pack_sz;
 1356   char *pack;
 1357 
 1358   /*Pack!*/
 1359   pack=pack_lcl_keyring(keyring, &pack_sz);
 1360   if(!pack_sz || !pack)
 1361     return 0;
 1362 
 1363   if((fd=fopen(file, "w"))==NULL) {
 1364     error("Cannot save the lcl_keyring in %s: %s", file,
 1365         strerror(errno));
 1366     return -1;
 1367   }
 1368 
 1369   /*Write!*/
 1370   fwrite(pack, pack_sz, 1, fd);
 1371 
 1372   xfree(pack);
 1373   fclose(fd);
 1374   return 0;
 1375 }
 1376 
 1377 /*
 1378  * load_lcl_keyring
 1379  *
 1380  * loads from `file' a local cache keyring and restores in it the RSA keys.
 1381  *
 1382  * On error -1 is returned.
 1383  */
 1384 int load_lcl_keyring(lcl_cache_keyring *keyring, char *file)
 1385 {
 1386   FILE *fd;
 1387   char *pack=0;
 1388   size_t pack_sz;
 1389   int ret=0;
 1390 
 1391   if(!(fd=fopen(file, "r"))) {
 1392     error("Cannot load the lcl_keyring from %s: %s", file,
 1393         strerror(errno));
 1394     return -1;
 1395   }
 1396 
 1397   fseek(fd, 0, SEEK_END);
 1398   pack_sz=ftell(fd);
 1399   rewind(fd);
 1400 
 1401   pack=xmalloc(pack_sz);
 1402   if(!fread(pack, pack_sz, 1, fd))
 1403     ERROR_FINISH(ret, -1, finish);
 1404 
 1405   ret=unpack_lcl_keyring(keyring, pack, pack_sz);
 1406 
 1407 finish:
 1408   if(pack)
 1409     xfree(pack);
 1410   fclose(fd);
 1411 
 1412   if(ret < 0)
 1413     debug(DBG_NORMAL, "Malformed or empty lcl_keyring file. "
 1414         "Aborting load_lcl_keyring().");
 1415   return ret;
 1416 }
 1417 
 1418 
 1419 /*
 1420  * save_lcl_cache: saves a local cache linked list in the specified `file'.
 1421  */
 1422 int save_lcl_cache(lcl_cache *lcl, char *file)
 1423 {
 1424   FILE *fd;
 1425   size_t pack_sz;
 1426   char *pack;
 1427 
 1428   /*Pack!*/
 1429   pack=pack_lcl_cache(lcl, &pack_sz);
 1430   if(!pack_sz || !pack)
 1431     return 0;
 1432 
 1433   if((fd=fopen(file, "w"))==NULL) {
 1434     error("Cannot save the lcl_cache in %s: %s", file, strerror(errno));
 1435     return -1;
 1436   }
 1437 
 1438   /*Write!*/
 1439   fwrite(pack, pack_sz, 1, fd);
 1440 
 1441   xfree(pack);
 1442   fclose(fd);
 1443   return 0;
 1444 }
 1445 
 1446 /*
 1447  * load_lcl_cache: loads from `file' a local cache list and returns the head
 1448  * of the newly allocated llist. In `counter' it is stored the number of
 1449  * structs of the llist.
 1450  * On error 0 is returned.
 1451  */
 1452 lcl_cache *load_lcl_cache(char *file, int *counter)
 1453 {
 1454   lcl_cache *lcl=0;
 1455   FILE *fd;
 1456   char *pack=0;
 1457   size_t pack_sz;
 1458 
 1459   if(!(fd=fopen(file, "r"))) {
 1460     error("Cannot load the lcl_cache from %s: %s", file, strerror(errno));
 1461     return 0;
 1462   }
 1463 
 1464   fseek(fd, 0, SEEK_END);
 1465   pack_sz=ftell(fd);
 1466   rewind(fd);
 1467 
 1468   pack=xmalloc(pack_sz);
 1469   if(!fread(pack, pack_sz, 1, fd))
 1470     goto finish;
 1471 
 1472   lcl=unpack_lcl_cache(pack, pack_sz, counter);
 1473 
 1474 finish:
 1475   if(pack)
 1476     xfree(pack);
 1477   fclose(fd);
 1478   if(!lcl && counter < 0)
 1479     error("Malformed lcl_cache file (%s)"
 1480         "Aborting load_lcl_cache().", file);
 1481   return lcl;
 1482 }
 1483 
 1484 
 1485 /*
 1486  * save_andna_cache: saves an andna cache linked list in the `file' specified
 1487  */
 1488 int save_andna_cache(andna_cache *acache, char *file)
 1489 {
 1490   FILE *fd;
 1491   size_t pack_sz;
 1492   char *pack;
 1493 
 1494   /*Pack!*/
 1495   pack=pack_andna_cache(acache, &pack_sz, ACACHE_PACK_FILE);
 1496   if(!pack_sz || !pack)
 1497     return 0;
 1498 
 1499   if((fd=fopen(file, "w"))==NULL) {
 1500     error("Cannot save the andna_cache in %s: %s", file, strerror(errno));
 1501     return -1;
 1502   }
 1503 
 1504   /*Write!*/
 1505   fwrite(pack, pack_sz, 1, fd);
 1506 
 1507   xfree(pack);
 1508   fclose(fd);
 1509   return 0;
 1510 }
 1511 
 1512 /*
 1513  * load_andna_cache: loads from `file' an andna cache list and returns the head
 1514  * of the newly allocated llist. In `counter' it is stored the number of
 1515  * list's structs.
 1516  * On error 0 is returned.
 1517  */
 1518 andna_cache *load_andna_cache(char *file, int *counter)
 1519 {
 1520   andna_cache *acache=0;
 1521   FILE *fd;
 1522   char *pack=0;
 1523   size_t pack_sz;
 1524 
 1525   if((fd=fopen(file, "r"))==NULL) {
 1526     error("Cannot load the andna_cache from %s: %s", file, strerror(errno));
 1527     return 0;
 1528   }
 1529 
 1530   fseek(fd, 0, SEEK_END);
 1531   pack_sz=ftell(fd);
 1532   rewind(fd);
 1533 
 1534   pack=xmalloc(pack_sz);
 1535   if(!fread(pack, pack_sz, 1, fd))
 1536     goto finish;
 1537 
 1538   acache=unpack_andna_cache(pack, pack_sz, counter, ACACHE_PACK_FILE);
 1539 
 1540 finish:
 1541   if(pack)
 1542     xfree(pack);
 1543   fclose(fd);
 1544   if(!acache && counter < 0)
 1545     error("Malformed andna_cache file."
 1546         " Aborting load_andna_cache().");
 1547   else if(!acache)
 1548     debug(DBG_NORMAL, "Empty andna_cache file.");
 1549 
 1550   return acache;
 1551 }
 1552 
 1553 
 1554 /*
 1555  * save_counter_c: saves a counter cache linked list in the `file' specified
 1556  */
 1557 int save_counter_c(counter_c *countercache, char *file)
 1558 {
 1559   FILE *fd;
 1560   size_t pack_sz;
 1561   char *pack;
 1562 
 1563   /*Pack!*/
 1564   pack=pack_counter_cache(countercache, &pack_sz);
 1565   if(!pack_sz || !pack)
 1566     return 0;
 1567 
 1568   if((fd=fopen(file, "w"))==NULL) {
 1569     error("Cannot save the counter_c in %s: %s", file, strerror(errno));
 1570     return -1;
 1571   }
 1572 
 1573   /*Write!*/
 1574   fwrite(pack, pack_sz, 1, fd);
 1575 
 1576   xfree(pack);
 1577   fclose(fd);
 1578   return 0;
 1579 }
 1580 
 1581 /*
 1582  * load_counter_c: loads from `file' a counter cache list and returns the head
 1583  * of the newly allocated llist. In `counter' it is stored the number of
 1584  * list's structs.
 1585  * On error 0 is returned.
 1586  */
 1587 counter_c *load_counter_c(char *file, int *counter)
 1588 {
 1589   counter_c *countercache=0;
 1590   FILE *fd;
 1591   char *pack=0;
 1592   size_t pack_sz;
 1593 
 1594   if((fd=fopen(file, "r"))==NULL) {
 1595     error("Cannot load the counter_c from %s: %s", file, strerror(errno));
 1596     return 0;
 1597   }
 1598 
 1599   fseek(fd, 0, SEEK_END);
 1600   pack_sz=ftell(fd);
 1601   rewind(fd);
 1602 
 1603   pack=xmalloc(pack_sz);
 1604   if(!fread(pack, pack_sz, 1, fd))
 1605     goto finish;
 1606 
 1607   countercache=unpack_counter_cache(pack, pack_sz, counter);
 1608 
 1609 finish:
 1610   if(pack)
 1611     xfree(pack);
 1612   fclose(fd);
 1613   if(!countercache && counter < 0)
 1614     debug(DBG_NORMAL, "Malformed counter_c file (%s). "
 1615         "Aborting load_counter_c().", file);
 1616   return countercache;
 1617 }
 1618 
 1619 
 1620 /*
 1621  * save_rh_cache: saves the resolved hnames cache linked list `rh' in the
 1622  * `file' specified.
 1623  */
 1624 int save_rh_cache(rh_cache *rh, char *file)
 1625 {
 1626   FILE *fd=0;
 1627   size_t pack_sz;
 1628   char *pack;
 1629 
 1630   /*Pack!*/
 1631   pack=pack_rh_cache(rh, &pack_sz);
 1632   if(!pack_sz || !pack)
 1633     return 0;
 1634 
 1635   if(!(fd=fopen(file, "w"))) {
 1636     error("Cannot save the rh_cache in %s: %s",
 1637         file, strerror(errno));
 1638     return -1;
 1639   }
 1640 
 1641   /*Write!*/
 1642   fwrite(pack, pack_sz, 1, fd);
 1643 
 1644   xfree(pack);
 1645   fclose(fd);
 1646   return 0;
 1647 }
 1648 
 1649 /*
 1650  * load_rh_cache: loads from `file' a resolved hnames cache list and returns
 1651  * the head of the newly allocated llist. In `counter' it is stored the number
 1652  * of structs of the llist.
 1653  * On error 0 is returned.
 1654  */
 1655 rh_cache *load_rh_cache(char *file, int *counter)
 1656 {
 1657   rh_cache *rh=0;
 1658   FILE *fd;
 1659   char *pack=0;
 1660   size_t pack_sz;
 1661 
 1662   if((fd=fopen(file, "r"))==NULL) {
 1663     error("Cannot load the rh_cache from %s: %s", file, strerror(errno));
 1664     return 0;
 1665   }
 1666 
 1667   fseek(fd, 0, SEEK_END);
 1668   pack_sz=ftell(fd);
 1669   rewind(fd);
 1670 
 1671   pack=xmalloc(pack_sz);
 1672   if(!fread(pack, pack_sz, 1, fd))
 1673     goto finish;
 1674 
 1675   rh=unpack_rh_cache(pack, pack_sz, counter);
 1676 
 1677 finish:
 1678   if(pack)
 1679     xfree(pack);
 1680   fclose(fd);
 1681   if(!rh && counter < 0)
 1682     error("Malformed rh_cache file (%s). "
 1683         "Aborting load_rh_cache().", file);
 1684   return rh;
 1685 }
 1686 
 1687 
 1688 /*
 1689  * load_hostnames
 1690  *
 1691  * It reads the `file' specified and reads each line in it.
 1692  * The strings read are the hostnames that will be registered in andna.
 1693  * Only ANDNA_MAX_HOSTNAMES lines are read. Each line can be maximum of
 1694  * ANDNA_MAX_HNAME_LEN character long.
 1695  *
 1696  * This function updates automagically the old local cache that is pointed by
 1697  * `*old_alcl_head'. The hostnames that are no more present in the loaded
 1698  * `file' are discarded from the local cache.
 1699  * Since a new local cache is allocated and the old is destroyed, the new
 1700  * pointer to it is written in `*old_alcl_head'.
 1701  *
 1702  * The `old_alcl_counter' is updated too.
 1703  *
 1704  * This function shall be used each time the `file' changes.
 1705  *
 1706  * On error -1 is returned, otherwise 0 shall be the sacred value.
 1707  */
 1708 int load_hostnames(char *file, lcl_cache **old_alcl_head, int *old_alcl_counter)
 1709 {
 1710   FILE *fd;
 1711   char buf[ANDNA_MAX_HNAME_LEN+1];
 1712   size_t slen;
 1713   time_t cur_t, diff;
 1714   int i=0;
 1715 
 1716   lcl_cache *alcl, *old_alcl, *new_alcl_head=0;
 1717   int new_alcl_counter=0;
 1718 
 1719   if((fd=fopen(file, "r"))==NULL) {
 1720     error("Cannot load any hostnames from %s: %s", file, strerror(errno));
 1721     return -1;
 1722   }
 1723 
 1724   cur_t=time(0);
 1725   while(!feof(fd) && i < ANDNA_MAX_HOSTNAMES) {
 1726     setzero(buf, ANDNA_MAX_HNAME_LEN+1);
 1727     fgets(buf, ANDNA_MAX_HNAME_LEN, fd);
 1728     if(feof(fd))
 1729       break;
 1730 
 1731     if((*buf)=='#' || (*buf)=='\n' || !(*buf)) {
 1732       /* Strip off the comment lines */
 1733       continue;
 1734     } else {
 1735       slen=strlen(buf);
 1736       if(buf[slen-1] == '\n') {
 1737         /* Don't include the newline in the string */
 1738         buf[slen-1]='\0';
 1739         slen=strlen(buf);
 1740       }
 1741 
 1742       /* Add the hname in the new local cache */
 1743       alcl = lcl_cache_new(buf);
 1744       clist_add(&new_alcl_head, &new_alcl_counter, alcl);
 1745 
 1746       /*
 1747        * If there is an equal entry in the old lcl_cache and
 1748        * it isn't expired, copy the old data in the new
 1749        * struct.
 1750        */
 1751       old_alcl = lcl_cache_find_hname(*old_alcl_head,
 1752           alcl->hostname);
 1753       if(old_alcl) {
 1754         diff=cur_t - old_alcl->timestamp;
 1755         if(diff < ANDNA_EXPIRATION_TIME) {
 1756           alcl->timestamp=old_alcl->timestamp;
 1757           alcl->hname_updates=old_alcl->hname_updates;
 1758         }
 1759       }
 1760       i++;
 1761     }
 1762   }
 1763 
 1764   /* Remove completely the old lcl_cache */
 1765   lcl_cache_destroy(*old_alcl_head, old_alcl_counter);
 1766 
 1767   /* Update the pointers */
 1768   *old_alcl_head=new_alcl_head;
 1769   *old_alcl_counter=new_alcl_counter;
 1770 
 1771   fclose(fd);
 1772   return 0;
 1773 }
 1774 
 1775 /*
 1776  * load_snsd
 1777  *
 1778  * It loads the SNSD records to be registered from the given `file'.
 1779  * In the file there shall be one record per line, up to SNSD_MAX_RECORDS-1#
 1780  * records.
 1781  *
 1782  * Each line has to be written in the following format:
 1783  *  hostname:snsd_hostname:service:priority:weight[:pub_key_file]
 1784  * or
 1785  *  hostname:snsd_ip:service:priority:weight[:pub_key_file]
 1786  *
 1787  * The old records present in `alcl_head' will be deleted and substituted by
 1788  * the loaded ones.
 1789  *
 1790  * On error -1 is returned.
 1791  * If a syntax error is encountered in the file -2 is returned.
 1792  */
 1793 int load_snsd(char *file, lcl_cache *alcl_head)
 1794 {
 1795 #define MAX_SNSD_LINE_SZ    (ANDNA_MAX_HNAME_LEN*4)
 1796 
 1797   FILE *fd;
 1798   size_t slen;
 1799   int line=0, fields, e, service, nodes, ret=0, err;
 1800   char buf[MAX_SNSD_LINE_SZ+1], **records;
 1801   u_char proto, abort=0;
 1802 
 1803   lcl_cache *alcl;
 1804   snsd_service *sns;
 1805   snsd_prio *snp;
 1806   snsd_node *snd, snsd_node;
 1807   inet_prefix ip;
 1808 
 1809   /* Delete all the old snsd records */
 1810   alcl=alcl_head;
 1811   list_for(alcl)
 1812     if(alcl->service)
 1813       snsd_service_llist_del(&alcl->service);
 1814 
 1815   if((fd=fopen(file, "r"))==NULL) {
 1816     error("Cannot open the snsd_nodes file from %s: %s",
 1817         file, strerror(errno));
 1818     return -1;
 1819   }
 1820 
 1821   line=1;
 1822   while(!feof(fd) && line <= SNSD_MAX_RECORDS-1) {
 1823     setzero(buf, MAX_SNSD_LINE_SZ+1);
 1824     fgets(buf, MAX_SNSD_LINE_SZ, fd);
 1825     if(feof(fd))
 1826       break;
 1827 
 1828     if((*buf)=='#' || (*buf)=='\n' || !(*buf)) {
 1829       /* Strip off the comment lines */
 1830       line++;
 1831       continue;
 1832     } else {
 1833       slen=strlen(buf);
 1834       if(buf[slen-1] == '\n') {
 1835         /* Don't include the newline in the string */
 1836         buf[slen-1]='\0';
 1837         slen=strlen(buf);
 1838       }
 1839 
 1840       records=split_string(buf, ":", &fields, MAX_SNSD_FIELDS,
 1841           ANDNA_MAX_HNAME_LEN*2);
 1842       if(fields < MIN_SNSD_FIELDS) {
 1843         error("%s: Syntax error in line %d.\n"
 1844           "  The correct syntax is:\n"
 1845           "  \thostname:snsd_hostname:service:"
 1846                "priority:weight[:pub_key_file]\n"
 1847           "  or\n"
 1848           "  \thostname:snsd_ip:service:"
 1849                "priority:weight[:pub_key_file]",
 1850           file, line);
 1851         ERROR_FINISH(abort, 1, skip_line);
 1852       }
 1853 
 1854       /*
 1855        * hostname
 1856        */
 1857       alcl=lcl_cache_find_hname(alcl_head, records[0]);
 1858       if(!alcl) {
 1859         error("%s: line %d: The hostname \"%s\" doesn't"
 1860           " exist in your local cache.\n"
 1861           "  Register it in the `andna_hostnames' file",
 1862           file, line, records[0]);
 1863         ERROR_FINISH(abort, 1, skip_line);
 1864       }
 1865 
 1866       /*
 1867        * snsd record
 1868        */
 1869       if(str_to_inet(records[1], &ip) >= 0) {
 1870         inet_copy_ipdata_raw(snsd_node.record, &ip);
 1871         snsd_node.flags=SNSD_NODE_IP;
 1872       } else {
 1873         hash_md5((u_char*)records[1], strlen(records[1]),
 1874             (u_char *)snsd_node.record);
 1875         snsd_node.flags=SNSD_NODE_HNAME;
 1876       }
 1877 
 1878       if(!strncmp(records[0], records[1],
 1879           ANDNA_MAX_HNAME_LEN) &&
 1880             !strcmp(records[2], "0"))
 1881         snsd_node.flags=SNSD_NODE_MAIN_IP | SNSD_NODE_IP;
 1882 
 1883       /***
 1884        * Parse service and protocol
 1885        */
 1886       err=str_to_snsd_service(records[2], &service, &proto);
 1887       if(err == -1)
 1888         error("%s: error in line %d: \"%s\""
 1889             " isn't a valid protocol\n",
 1890             file, line, records[2]);
 1891       else if(err == -2)
 1892         error("%s: error in line %d: \"%s\""
 1893             " isn't a valid service\n",
 1894             file, line, records[2]);
 1895       if(err < 0)
 1896         ERROR_FINISH(abort, 1, skip_line);
 1897       /**/
 1898 
 1899       /* Store service and protocol */
 1900       sns=snsd_add_service(&alcl->service, service, proto);
 1901 
 1902       /* priority */
 1903       snp=snsd_add_prio(&sns->prio, atoi(records[3]));
 1904       nodes=snsd_count_prio_nodes(sns->prio);
 1905       if(nodes >= SNSD_MAX_REC_SERV-1) {
 1906         error("%s: The maximum number of records for"
 1907               " the service \"%d\" has been reached.\n"
 1908               "  The maximum is %d records per service",
 1909               file, service, SNSD_MAX_REC_SERV);
 1910         ERROR_FINISH(abort, 1, skip_line);
 1911       }
 1912 
 1913       /* node and weight */
 1914       snd=snsd_add_node(&snp->node, &alcl->snsd_counter,
 1915           SNSD_MAX_RECORDS-1, snsd_node.record);
 1916       snd->weight=SNSD_WEIGHT(atoi(records[4]));
 1917       snd->flags|=snsd_node.flags;
 1918 
 1919       /* pub_key_file
 1920        * TODO:
 1921        * if(fields >= 6)
 1922        *   snd->pubkey=load_pubkey(records[5])
 1923        */
 1924 
 1925 
 1926 skip_line:
 1927       for(e=0; e<fields; e++)
 1928         xfree(records[e]);
 1929       if(abort)
 1930         ERROR_FINISH(ret, -2, finish);
 1931     }
 1932     line++;
 1933   }
 1934 
 1935 finish:
 1936   fclose(fd);
 1937   return ret;
 1938 }
 1939 
 1940 
 1941 /*
 1942  *
 1943  *  *  *  *  Modify /etc/resolv.conf  *  *  *
 1944  *
 1945  */
 1946 
 1947 
 1948 /*
 1949  * add_resolv_conf: It opens `file' and write in the first line `hname' moving
 1950  * down the previous lines. The old `file' is backupped in `file'.bak.
 1951  * Example: add_resolv_conf("nameserver 127.0.0.1", "/etc/resolv.conf").
 1952  * Use del_resolv_conf to restore `file' with its backup.
 1953  * On error -1 is returned.
 1954  */
 1955 int add_resolv_conf(char *hname, char *file)
 1956 {
 1957   FILE *fin=0,    /* `file' */
 1958        *fin_bak=0,  /* `file'.bak */
 1959        *fout=0,   /* The replaced `file' */
 1960        *fout_back=0;  /* The backup of `file' */
 1961 
 1962   char *buf=0, *p, *file_bk=0;
 1963   size_t buf_sz;
 1964   int ret=0;
 1965 
 1966   /*
 1967    *  Open and read `file'
 1968    */
 1969 
 1970   if(!(fin=fopen(file, "r"))) {
 1971     error("add_resolv_conf: cannot load %s: %s", file, strerror(errno));
 1972     ERROR_FINISH(ret, -1, finish);
 1973   }
 1974 
 1975   /* Prepare the name of the backup file */
 1976   file_bk=xmalloc(strlen(file) + strlen(".bak") + 1);
 1977   *file_bk=0;
 1978   strcpy(stpcpy(file_bk, file), ".bak");
 1979 
 1980 reread_fin:
 1981   fseek(fin, 0, SEEK_END);
 1982   buf_sz=ftell(fin);
 1983   rewind(fin);
 1984 
 1985   buf=xmalloc(buf_sz);
 1986   if(!fread(buf, buf_sz, 1, fin)) {
 1987     error("add_resolv_conf: it wasn't possible to read the %s file",
 1988         file);
 1989     ERROR_FINISH(ret, -1, finish);
 1990   }
 1991 
 1992   /*
 1993    * If there is already the `hname' string in the first line, try to
 1994    * read `file'.bak, if it doesn't exist do nothing.
 1995    */
 1996   if(buf_sz-1 >= strlen(hname) && !strncmp(buf, hname, strlen(hname))) {
 1997     if(fin == fin_bak) {
 1998       /*
 1999        * We've already read `fin_bak', and it has
 2000        * the `hname' string in its first line too. Stop it.
 2001        */
 2002       goto finish;
 2003     }
 2004 
 2005     debug(DBG_NORMAL, "add_resolv_conf: Reading %s instead",
 2006         file_bk);
 2007     if(!(fin_bak=fopen(file_bk, "r")))
 2008       goto finish;
 2009 
 2010     fclose(fin);
 2011     fin=fin_bak;
 2012 
 2013     goto reread_fin;
 2014   }
 2015 
 2016   /*
 2017    * Backup `file' in `file'.bak
 2018    */
 2019   if(!(fout_back=fopen(file_bk, "w"))) {
 2020     error("add_resolv_conf: cannot create a backup copy of %s in %s: %s", file,
 2021       file_bk, strerror(errno));
 2022     ERROR_FINISH(ret, -1, finish);
 2023   }
 2024   fwrite(buf, buf_sz, 1, fout_back);
 2025 
 2026   /*
 2027    * Delete `file'
 2028    */
 2029   fclose(fin);
 2030   fin=0;
 2031   unlink(file);
 2032 
 2033   /*
 2034    * Add as a first line `hname' in `file'
 2035    */
 2036   if(!(fout=fopen(file, "w"))) {
 2037     error("add_resolv_conf: cannot reopen %s to overwrite it: %s", file,
 2038         strerror(errno));
 2039     ERROR_FINISH(ret, -1, finish);
 2040   }
 2041   fprintf(fout, "%s\n", hname);
 2042   p=buf;
 2043   while(*p) {
 2044     if(*p != '#')
 2045       fprintf(fout, "#");
 2046     while(*p) {
 2047       fprintf(fout, "%c", *p);
 2048       if(*p == '\n')
 2049         break;
 2050       p++;
 2051     }
 2052     if(!*p)
 2053       break;
 2054     p++;
 2055   }
 2056   /*fwrite(buf, buf_sz, 1, fout);*/
 2057 
 2058 finish:
 2059   if(buf)
 2060     xfree(buf);
 2061   if(file_bk)
 2062     xfree(file_bk);
 2063   if(fin)
 2064     fclose(fin);
 2065   if(fout)
 2066     fclose(fout);
 2067   if(fout_back)
 2068     fclose(fout_back);
 2069 
 2070   return ret;
 2071 }
 2072 
 2073 /*
 2074  * del_resolv_conf
 2075  *
 2076  * restores the old `file' modified by add_resolv_conf() by
 2077  * copying `file'.bak over `file'. If the `hname' string is present in
 2078  * `file'.bak it won't be written in `file'.
 2079  * On error it returns -1.
 2080  */
 2081 int del_resolv_conf(char *hname, char *file)
 2082 {
 2083   FILE *fin=0, *fout=0;
 2084 
 2085   char *buf=0, *p, *file_bk=0, tmp_buf[128+1];
 2086   size_t buf_sz;
 2087   int ret=0;
 2088 
 2089   /*
 2090    *  Open and read `file'.bak
 2091    */
 2092   file_bk=xmalloc(strlen(file) + strlen(".bak") + 1);
 2093   *file_bk=0;
 2094   strcpy(stpcpy(file_bk, file), ".bak");
 2095   if(!(fin=fopen(file_bk, "r"))) {
 2096     /*error("del_resolv_conf: cannot load %s: %s", file_bk, strerror(errno));*/
 2097     ERROR_FINISH(ret, -1, finish);
 2098   }
 2099 
 2100   fseek(fin, 0, SEEK_END);
 2101   buf_sz=ftell(fin);
 2102   rewind(fin);
 2103 
 2104   if(!buf_sz) {
 2105     /* `file_bk' is empty, delete it */
 2106     unlink(file_bk);
 2107     ERROR_FINISH(ret, -1, finish);
 2108   }
 2109 
 2110   buf=p=xzalloc(buf_sz);
 2111   while(fgets(tmp_buf, 128, fin)) {
 2112     /* Skip the line which is equal to `hname' */
 2113     if(!strncmp(tmp_buf, hname, strlen(hname)))
 2114       continue;
 2115     memput(p, tmp_buf, strlen(tmp_buf));
 2116   }
 2117 
 2118   /*
 2119    * Delete `file'
 2120    */
 2121   unlink(file);
 2122 
 2123   /*
 2124    * Copy `file'.bak in `file'
 2125    */
 2126 
 2127   if(!(fout=fopen(file, "w"))) {
 2128     error("del_resolv_conf: cannot copy %s in %s: %s", file_bk,
 2129       file, strerror(errno));
 2130     ERROR_FINISH(ret, -1, finish);
 2131   }
 2132   fprintf(fout, "%s", buf);
 2133 
 2134   /*
 2135    * delete `file'.bak
 2136    */
 2137 
 2138   fclose(fin);
 2139   fin=0;
 2140   unlink(file_bk);
 2141 
 2142 finish:
 2143   if(buf)
 2144     xfree(buf);
 2145   if(file_bk)
 2146     xfree(file_bk);
 2147   if(fin)
 2148     fclose(fin);
 2149   if(fout)
 2150     fclose(fout);
 2151 
 2152   return ret;
 2153 }

alpt (at) freaknet (dot) org
ViewVC Help
Powered by ViewVC 1.1-dev