Parent Directory
|
Revision Log
|
Revision Graph
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 |