/* This file is part of Netsukuku * (c) Copyright 2005 Andrea Lo Pumo aka AlpT * * This source code is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * This source code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * Please refer to the GNU Public License for more details. * * You should have received a copy of the GNU Public License along with * this source code; if not, write to: * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef ANDNA_CACHE_H #define ANDNA_CACHE_H #include "inet.h" #include "crypto.h" #include "endianness.h" #include "llist.c" #include "snsd_cache.h" /* * ANDNA definitions */ #define ANDNA_MAX_BACKUP_GNODES 2 #define ANDNA_MAX_QUEUE 5 #define ANDNA_MAX_HNAME_LEN 512 /* (null terminator included) */ #define ANDNA_MAX_HOSTNAMES 256 /* Max number of hnames per node */ #define ANDNA_MAX_RHC_HNAMES 512 /* Max number of hnames kept in the resolved_hnames cache* */ #define ANDNA_EXPIRATION_TIME 259200 /* 3 days (in seconds) */ #define ANDNA_MIN_UPDATE_TIME 3600 /* The minum amount of time to be waited before sending an update of the hname. */ #define ANDNA_PRIVKEY_BITS 1024 #define ANDNA_SKEY_MAX_LEN 900 #define ANDNA_PKEY_LEN 140 #define ANDNA_HASH_SZ (MAX_IP_SZ) #define ANDNA_SIGNATURE_LEN 128 /* Returns the number of nodes to be used in a backup_gnode */ #define ANDNA_BACKUP_NODES(seeds) ({(seeds) > 8 ? \ ((seeds)*32)/MAXGROUPNODE : (seeds);}) #ifdef DEBUG #undef ANDNA_EXPIRATION_TIME #define ANDNA_EXPIRATION_TIME 100 #undef ANDNA_MIN_UPDATE_TIME #define ANDNA_MIN_UPDATE_TIME 2 #endif /* * * * Cache stuff * * * */ /* * andna_cache flags * */ #define ANDNA_BACKUP 1 /* We are a backup_node */ #define ANDNA_COUNTER (1<<1) /* We are a counter_node */ #define ANDNA_ROUNDED (1<<2) /* We are a rounded_hash_node */ #define ANDNA_FULL (1<<3) /* Queue full */ #define ANDNA_UPDATING (1<<4) /* The hname is being updated right now */ /* * andna_cache_queue * * The queue of the andna_cache. (see below). */ struct andna_cache_queue { LLIST_HDR(struct andna_cache_queue); time_t timestamp; u_short hname_updates; /* numbers of hname's updates */ char pubkey[ANDNA_PKEY_LEN]; u_short snsd_counter; /* # of `snsd' nodes */ snsd_service *service; }; typedef struct andna_cache_queue andna_cache_queue; /* * andna_cache * * It keeps the entries of the hostnames registered by other nodes. */ struct andna_cache { LLIST_HDR(struct andna_cache); u_int hash[MAX_IP_INT]; /* hostname's hash */ char flags; u_short queue_counter; andna_cache_queue *acq; /* The queue of the registration. The first is the active one */ }; typedef struct andna_cache andna_cache; /* part of the counter cache, see below */ struct counter_c_hashes { LLIST_HDR(struct counter_c_hashes); time_t timestamp; u_short hname_updates; int hash[MAX_IP_INT]; }; typedef struct counter_c_hashes counter_c_hashes; INT_INFO counter_c_hashes_body_iinfo = { 2, {INT_TYPE_32BIT, INT_TYPE_16BIT}, {0, sizeof(time_t)} , {1, 1} }; /* * counter_c * Counter node's cache. * * All the infos regarding a particular register_node are stored here. For * example, we need to know how many hostnames he already registered. */ struct counter_c { LLIST_HDR(struct counter_c); char pubkey[ANDNA_PKEY_LEN]; char flags; u_short hashes; /* The number of hashes in cch */ counter_c_hashes *cch; /* The hashes of the hnames */ }; typedef struct counter_c counter_c; INT_INFO counter_c_body_iinfo = { 1, {INT_TYPE_16BIT}, {ANDNA_PKEY_LEN + sizeof(char)}, {1} }; /* * lcl_cache_keyring * * The lcl keyring is used to store the RSA keys used to complete some of the * ANDNA requests, (f.e. registering or updating a hname). */ typedef struct { u_int skey_len; u_int pkey_len; u_char *privkey; /* secret key packed */ u_char *pubkey; /* pubkey packed */ RSA *priv_rsa; /* key pair unpacked */ } lcl_cache_keyring; /* * lcl_cache * * The Local Andna Cache keeps all the hostnames which have been register by * localhost (ourself). */ struct lcl_cache { LLIST_HDR(struct lcl_cache); char *hostname; /* The registered hostname */ u_int hash; /* 32bit hash of the md5 hash of the hname */ u_short hname_updates; /* How many updates we've done for this hostname */ time_t timestamp; /* the last time when the hname was updated. If it is 0, the hname has still to be registered */ u_short snsd_counter; /* # of `snsds' */ snsd_service *service; char flags; }; typedef struct lcl_cache lcl_cache; /* * resolved_hnames_cache * * This cache keeps info on the already resolved hostnames, so we won't have * to resolve them soon again. * In order to optimize the search we order the linked list by the time * of hname resolution. The last hname which has been searched/resolved is * always moved at the head of the llist, in this way, at the end of the llist * there is the hname which has been searched for the first time but has been * ignored until now. * When the cache is full, the hname which is at the end of the llist is * removed to empty new space. * The hname which have the `timestamp' expired are removed too. */ struct resolved_hnames_cache { LLIST_HDR(struct resolved_hnames_cache); u_int hash; /* 32bit hash of the md5 hash of the hname */ char flags; time_t timestamp; /* the last time when the hname was updated. With this we know that at timestamp+ANDNA_EXPIRATION_TIME this cache will expire. */ u_short snsd_counter; snsd_service *service; }; typedef struct resolved_hnames_cache rh_cache; /* * * * * Global vars * * * */ andna_cache *andna_c; int andna_c_counter; counter_c *andna_counter_c; int cc_counter; lcl_cache_keyring lcl_keyring; lcl_cache *andna_lcl; int lcl_counter; rh_cache *andna_rhc; int rhc_counter; /* * * * * * Package stuff * * * * */ /* * * * * lcl cache package * * * */ struct lcl_keyring_pkt_hdr { u_int skey_len; u_int pkey_len; } _PACKED_; /* * the rest of the pkt is: * * char privkey[hdr.skey_len]; * char pubkey[hdr.pkey_len]; */ INT_INFO lcl_keyring_pkt_hdr_iinfo = { 2, {INT_TYPE_32BIT, INT_TYPE_32BIT}, {0, sizeof(u_int)} , {1, 1} }; #define LCL_KEYRING_HDR_PACK_SZ(khdr) (sizeof(struct lcl_keyring_pkt_hdr) + \ (khdr)->skey_len + (khdr)->pkey_len) /* * The local cache pkt is used to pack the entire local cache to save it in a * file or to send it to a node. */ struct lcl_cache_pkt_hdr { u_short tot_caches; /* How many lcl structs there are in the pkt's body */ } _PACKED_; INT_INFO lcl_cache_pkt_hdr_iinfo = { 1, {INT_TYPE_16BIT}, {0}, {1} }; #define LCL_CACHE_HDR_PACK_SZ (sizeof(struct lcl_cache_pkt_hdr)) /* * The body is: * * struct lcl_cache_pkt_body { * u_short hname_updates; * time_t timestamp; * char hostname[strlen(hostname)+1]; * null terminated * * } body[ hdr.tot_caches ]; * */ #define LCL_CACHE_BODY_PACK_SZ(hname_len) ((hname_len) + sizeof(u_short) \ + sizeof(time_t)) INT_INFO lcl_cache_pkt_body_iinfo = { 2, {INT_TYPE_16BIT, INT_TYPE_32BIT}, {0, sizeof(u_short)} , {1, 1} }; /* * * * * andna cache package * * * */ /* * the body of the acq_pkt is: * struct acq_pkt_body { * time_t timestamp; * u_short hname_updates; * char pubkey[ANDNA_PKEY_LEN]; * * u_short snsd_counter; * char snsd_service_pack[SNSD_SERVICE_PACK_SZ]; * }; */ INT_INFO acq_body_iinfo = { 3, {INT_TYPE_32BIT, INT_TYPE_16BIT, INT_TYPE_16BIT} , {0, sizeof(time_t), sizeof(time_t) + sizeof(u_short) + ANDNA_PKEY_LEN} , {1, 1, 1} }; #define ACQ_BODY_PACK_SZ (sizeof(time_t) + sizeof(u_short)*2 + \ ANDNA_PKEY_LEN) #define ACQ_PACK_SZ(snsd_pack_sz) (ACQ_BODY_PACK_SZ + (snsd_pack_sz)) struct andna_cache_pkt_hdr { u_short tot_caches; } _PACKED_; INT_INFO andna_cache_pkt_hdr_iinfo = { 1, {INT_TYPE_16BIT}, {0}, {1} }; /* * The body is: * struct andna_cache_pack { * u_int hash[MAX_IP_INT]; * char flags; * u_short queue_counter; * char acq_pack[ACQ_PACK_SZ*queue_counter]; * } acache_pack[hdr.tot_caches]; */ INT_INFO andna_cache_body_iinfo = { 1, {INT_TYPE_16BIT}, {MAX_IP_SZ + sizeof(char)}, {1} }; #define ACACHE_BODY_PACK_SZ (ANDNA_HASH_SZ + sizeof(char) + \ sizeof(u_short)) #define ACACHE_PACK_SZ(acq_pack_sz) ((acq_pack_sz) + ACACHE_BODY_PACK_SZ) /* * If the acache pack will be sent on a network packet, the `acq->timestamp' * will be the difference of the current time with the same `acq->timestamp', * in this way the node which receives the packet will add its current time to * `acq->timestamp'. This is necessary because the sending and receiving node * don't have the clock synced. Note that the rtt isn't considered because it * is generally very small and the ANDNA times don't need an accurate * precision, f.e. the expiration time is three days long. * If the pack is saved on a file, then `acq->timestamp' remains the same. * Problem: if the clock is changed, acq->timestamp will refer to the old * clock. */ #define ACACHE_PACK_FILE 1 #define ACACHE_PACK_PKT 2 /* * The counter cache pkt is similar to the andna_cache_pkt, it is completely * arranged in the same way. */ struct counter_c_pkt_hdr { u_short tot_caches; } _PACKED_; INT_INFO counter_c_pkt_hdr_iinfo = { 1, {INT_TYPE_16BIT}, {0}, {1} }; #define COUNTER_CACHE_HASHES_PACK_SZ (sizeof(time_t) + sizeof(u_short) + \ ANDNA_HASH_SZ) #define COUNTER_CACHE_BODY_PACK_SZ (ANDNA_PKEY_LEN + sizeof(char) + \ sizeof(u_short)) #define COUNTER_CACHE_PACK_SZ(hashes) ((COUNTER_CACHE_HASHES_PACK_SZ*(hashes))\ + COUNTER_CACHE_BODY_PACK_SZ) /* * * * * Resolved hostnames cache pkt. * * * */ struct rh_cache_pkt_hdr { u_short tot_caches; /* How many lcl structs there are in the pkt's hdr */ } _PACKED_; INT_INFO rh_cache_pkt_hdr_iinfo = { 1, {INT_TYPE_16BIT}, {0}, {1} }; /* * The body is: * struct rh_cache_pkt_body { * u_int hash; * char flags; * time_t timestamp; * * u_short snsd_counter; * char snsd_service_pack[SNSD_SERVICE_PACK_SZ]; * } body[ hdr.tot_caches ]; */ #define RH_CACHE_BODY_PACK_SZ(snsd_pack_sz) (sizeof(u_int)+sizeof(char)+ \ sizeof(time_t)+sizeof(u_short)+\ (snsd_pack_sz)) INT_INFO rh_cache_pkt_body_iinfo = { 3, {INT_TYPE_32BIT, INT_TYPE_32BIT, INT_TYPE_16BIT}, {0, sizeof(u_int) + sizeof(char), sizeof(u_int) + sizeof(char) + sizeof(time_t)} , {1, 1, 1} }; /* * * * Functions' declaration * * * */ void andna_caches_init(int family); void lcl_new_keyring(lcl_cache_keyring * keyring); void lcl_destroy_keyring(lcl_cache_keyring * keyring); lcl_cache *lcl_cache_new(char *hname); void lcl_cache_free(lcl_cache * alcl); void lcl_cache_destroy(lcl_cache * head, int *counter); lcl_cache *lcl_cache_find_hname(lcl_cache * head, char *hname); lcl_cache *lcl_cache_find_hash(lcl_cache * alcl, u_int hash); lcl_cache *lcl_get_registered_hnames(lcl_cache * alcl); andna_cache_queue *ac_queue_findpubk(andna_cache * ac, char *pubk); andna_cache_queue *ac_queue_add(andna_cache * ac, char *pubkey); void ac_queue_del(andna_cache * ac, andna_cache_queue * acq); void ac_queue_del_expired(andna_cache * ac); void ac_queue_destroy(andna_cache * ac); andna_cache *andna_cache_findhash(int hash[MAX_IP_INT]); andna_cache *andna_cache_gethash(int hash[MAX_IP_INT]); andna_cache *andna_cache_addhash(int hash[MAX_IP_INT]); int andna_cache_del_ifexpired(andna_cache * ac); void andna_cache_del_expired(void); void andna_cache_destroy(void); counter_c_hashes *cc_hashes_add(counter_c * cc, int hash[MAX_IP_INT]); void cc_hashes_del(counter_c * cc, counter_c_hashes * cch); int counter_c_del_ifexpired(counter_c * cc); void cc_hashes_del_expired(counter_c * cc); void cc_hashes_destroy(counter_c * cc); counter_c_hashes *cc_findhash(counter_c * cc, int hash[MAX_IP_INT]); counter_c *counter_c_findpubk(char *pubk); counter_c *counter_c_add(inet_prefix * rip, char *pubkey); void counter_c_del_expired(void); void counter_c_destroy(void); rh_cache *rh_cache_new(char *hname, time_t timestamp); rh_cache *rh_cache_add_hash(u_int hash, time_t timestamp); rh_cache *rh_cache_add(char *hname, time_t timestamp); rh_cache *rh_cache_find_hash(u_int hash); rh_cache *rh_cache_find_hname(char *hname); void rh_cache_del(rh_cache * rhc); void rh_cache_del_expired(void); void rh_cache_flush(void); char *pack_lcl_keyring(lcl_cache_keyring * keyring, size_t * pack_sz); int unpack_lcl_keyring(lcl_cache_keyring * keyring, char *pack, size_t pack_sz); char *pack_lcl_cache(lcl_cache * local_cache, size_t * pack_sz); lcl_cache *unpack_lcl_cache(char *pack, size_t pack_sz, int *counter); char *pack_andna_cache(andna_cache * acache, size_t * pack_sz, int pack_type); andna_cache *unpack_andna_cache(char *pack, size_t pack_sz, int *counter, int pack_type); char *pack_counter_cache(counter_c * countercache, size_t * pack_sz); counter_c *unpack_counter_cache(char *pack, size_t pack_sz, int *counter); char *pack_rh_cache(rh_cache * rhcache, size_t * pack_sz); rh_cache *unpack_rh_cache(char *pack, size_t pack_sz, int *counter); int save_lcl_keyring(lcl_cache_keyring * keyring, char *file); int load_lcl_keyring(lcl_cache_keyring * keyring, char *file); int save_lcl_cache(lcl_cache * lcl, char *file); lcl_cache *load_lcl_cache(char *file, int *counter); int save_andna_cache(andna_cache * acache, char *file); andna_cache *load_andna_cache(char *file, int *counter); int save_counter_c(counter_c * countercache, char *file); counter_c *load_counter_c(char *file, int *counter); int save_rh_cache(rh_cache * rh, char *file); rh_cache *load_rh_cache(char *file, int *counter); int load_hostnames(char *file, lcl_cache ** old_alcl_head, int *old_alcl_counter); int load_snsd(char *file, lcl_cache * alcl_head); int add_resolv_conf(char *hname, char *file); int del_resolv_conf(char *hname, char *file); #endif /*ANDNA_CACHE_H */