mirror of
https://github.com/ChronosX88/netsukuku.git
synced 2024-11-22 18:22:18 +00:00
307 lines
9.4 KiB
C
307 lines
9.4 KiB
C
/* This file is part of Netsukuku
|
|
* (c) Copyright 2006 Andrea Lo Pumo aka AlpT <alpt@freaknet.org>
|
|
*
|
|
* This source code is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as published
|
|
* by the Free Software Foundation; either version 2 of the License,
|
|
* or (at your option) any later version.
|
|
*
|
|
* This source code is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* Please refer to the GNU Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Public License along with
|
|
* this source code; if not, write to:
|
|
* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#ifndef SNSD_H
|
|
#define SNSD_H
|
|
|
|
#include "inet.h"
|
|
#include "crypto.h"
|
|
#include "endianness.h"
|
|
#include "llist.c"
|
|
|
|
/*
|
|
* SNSD definitions
|
|
*/
|
|
|
|
#define SNSD_MAX_RECORDS 256 /* Number of maximum SNSD records
|
|
which can be stored in an
|
|
andna_cache */
|
|
#define SNSD_MAX_QUEUE_RECORDS 1 /* There can be only one snsd
|
|
record for the queued hnames */
|
|
#define SNSD_MAX_REC_SERV 16 /* Maximum records per service */
|
|
|
|
#define SNSD_ALL_SERVICE (-1) /* A service number equal to -1
|
|
refers to all the available
|
|
services */
|
|
#define SNSD_DEFAULT_SERVICE 0
|
|
#define SNSD_DEFAULT_PROTO 1 /* tcp */
|
|
#define SNSD_DEFAULT_PRIO 16
|
|
#define SNSD_DEFAULT_WEIGHT 1
|
|
|
|
#define SNSD_WEIGHT(x) ((x) & 0x7f) /* The snsd weight has to
|
|
be <= 127 */
|
|
|
|
/* Fields used in the syntax for the `snsd_nodes' file:
|
|
* hostname:snsd_hostname:service:priority:weight[:pub_key_file]
|
|
*/
|
|
#define MAX_SNSD_LINE_SZ (ANDNA_MAX_HNAME_LEN*4)
|
|
#define MAX_SNSD_FIELDS 6
|
|
#define MIN_SNSD_FIELDS 5
|
|
|
|
/* * snsd_node flags * */
|
|
#define SNSD_NODE_HNAME 1 /* A hname is associated in the
|
|
snsd record */
|
|
#define SNSD_NODE_IP (1<<1) /* An IP is associated in the
|
|
snsd record */
|
|
#define SNSD_NODE_MAIN_IP (1<<2) /* This is the first IP registered
|
|
to the hname, it can't be
|
|
deleted */
|
|
|
|
|
|
/*
|
|
* snsd_node, snsd_service, snsd_prio
|
|
*
|
|
* They are three linked list. They are all orthogonal to each other.
|
|
* The snsd_node llist is inside each snsd_prio struct which is inside each
|
|
* snsd_service struct:
|
|
* || service X <-> service Y <-> service Z <-> ... ||
|
|
* | | |
|
|
* V V V
|
|
* snsd_prio_1-->node snsd_prio_1-->node ...-->...
|
|
* | |
|
|
* V V
|
|
* snsd_prio_2-->node ...-->node
|
|
* |
|
|
* V
|
|
* ...-->node
|
|
*
|
|
* Using this schema, we don't have to sort them, ever. The nodes are already
|
|
* grouped by service and in each service by priority.
|
|
*
|
|
* These llist are directly embedded in the andna_cache, lcl_cache and
|
|
* rh_cache.
|
|
*
|
|
* The andna_cache keeps all the SNSD nodes associated to the registered
|
|
* hostname. The andna_cache doesn't need `snsd_node->pubkey'.
|
|
*
|
|
* The rh_cache stores only records which are of the SNSD_NODE_IP type.
|
|
*
|
|
* When the lcl_cache is saved, its snsd llist is discarded because it is
|
|
* loaded each time from the /etc/netsukuku/snsd_nodes file.
|
|
*/
|
|
struct snsd_node
|
|
{
|
|
LLIST_HDR (struct snsd_node);
|
|
|
|
u_int record[MAX_IP_INT]; /* It can be the IP or the md5
|
|
hash of the hname of the
|
|
SNSD node */
|
|
RSA *pubkey; /* pubkey of the snsd_node */
|
|
char flags; /* This will tell us what
|
|
`record' is */
|
|
|
|
u_char weight;
|
|
};
|
|
typedef struct snsd_node snsd_node;
|
|
/* In the pack of a snsd_node we don't save the `pubkey' */
|
|
#define SNSD_NODE_PACK_SZ (MAX_IP_SZ+sizeof(char)*2)
|
|
|
|
struct snsd_prio
|
|
{
|
|
LLIST_HDR (struct snsd_prio);
|
|
|
|
u_char prio; /* Priority of the SNSD node */
|
|
|
|
snsd_node *node;
|
|
};
|
|
typedef struct snsd_prio snsd_prio;
|
|
#define SNSD_PRIO_PACK_SZ (sizeof(char))
|
|
|
|
struct snsd_service
|
|
{
|
|
LLIST_HDR (struct snsd_service);
|
|
|
|
u_short service; /* Service number */
|
|
u_char proto; /* TCP/UDP, see the `proto_str'
|
|
static array below */
|
|
|
|
snsd_prio *prio;
|
|
};
|
|
typedef struct snsd_service snsd_service;
|
|
#define SNSD_SERVICE_PACK_SZ (sizeof(u_short)+sizeof(u_char))
|
|
|
|
|
|
/*
|
|
*
|
|
* * * * snsd structs package * * *
|
|
*
|
|
*/
|
|
|
|
struct snsd_node_llist_hdr
|
|
{
|
|
u_short count; /* # of snsd_node structs packed
|
|
in the body */
|
|
}_PACKED_;
|
|
INT_INFO snsd_node_llist_hdr_iinfo = { 1, { INT_TYPE_16BIT }, { 0 }, { 1 } };
|
|
/*
|
|
* the body of the pkt is:
|
|
*
|
|
* struct snsd_node_pack {
|
|
* u_int record[MAX_IP_INT];
|
|
* char flags;
|
|
* u_char weight;
|
|
* } pack[hdr.nodes];
|
|
*/
|
|
#define SNSD_NODE_LLIST_PACK_SZ(head) (list_count((head))*SNSD_NODE_PACK_SZ \
|
|
+ sizeof(struct snsd_node_llist_hdr))
|
|
|
|
struct snsd_prio_llist_hdr
|
|
{
|
|
u_short count; /* number of structs packed in
|
|
the body */
|
|
}_PACKED_;
|
|
INT_INFO snsd_prio_llist_hdr_iinfo = { 1, { INT_TYPE_16BIT }, { 0 }, { 1 } };
|
|
/*
|
|
* the body is:
|
|
*
|
|
* snsd_prio_pack {
|
|
* u_char prio;
|
|
* char snsd_node_llist_pack[SNSD_NODE_LLIST_PACK_SZ];
|
|
* } pack[hdr.count];
|
|
*/
|
|
#define SNSD_PRIO_LLIST_PACK_SZ(head) \
|
|
({ \
|
|
snsd_prio *_p=(head); \
|
|
int _priosz=0; \
|
|
\
|
|
list_for(_p) { \
|
|
_priosz+=SNSD_NODE_LLIST_PACK_SZ(_p->node); \
|
|
_priosz+=SNSD_PRIO_PACK_SZ; \
|
|
} \
|
|
_priosz+=sizeof(struct snsd_prio_llist_hdr); \
|
|
_priosz; \
|
|
})
|
|
|
|
|
|
struct snsd_service_llist_hdr
|
|
{
|
|
u_short count;
|
|
}_PACKED_;
|
|
INT_INFO snsd_service_llist_hdr_iinfo = { 1, { INT_TYPE_16BIT }, { 0 }, { 1 } };
|
|
/*
|
|
* the body is:
|
|
* u_short service;
|
|
* u_char proto;
|
|
* char snsd_prio_llist_pack[SNSD_PRIO_LLIST_PACK_SZ];
|
|
*/
|
|
#define SNSD_SERVICE_LLIST_PACK_SZ(head) \
|
|
({ \
|
|
snsd_service *_s=(head); \
|
|
int _srvsz=0; \
|
|
if(_s) { \
|
|
list_for(_s) { \
|
|
_srvsz+=SNSD_PRIO_LLIST_PACK_SZ(_s->prio); \
|
|
_srvsz+=SNSD_SERVICE_PACK_SZ; \
|
|
} \
|
|
_srvsz+=sizeof(struct snsd_service_llist_hdr); \
|
|
} \
|
|
_srvsz; \
|
|
})
|
|
|
|
#define SNSD_SERVICE_SINGLE_PACK_SZ(head) \
|
|
({ SNSD_SERVICE_PACK_SZ + \
|
|
SNSD_PRIO_LLIST_PACK_SZ((head)->prio); \
|
|
})
|
|
|
|
#define SNSD_SERVICE_MAX_PACK_SZ \
|
|
( ( (SNSD_NODE_PACK_SZ + SNSD_PRIO_PACK_SZ) * \
|
|
(SNSD_MAX_REC_SERV) ) + \
|
|
SNSD_SERVICE_PACK_SZ + \
|
|
sizeof(struct snsd_prio_llist_hdr) + \
|
|
sizeof(struct snsd_service_llist_hdr) \
|
|
)
|
|
|
|
#define SNSD_SERVICE_MAX_LLIST_PACK_SZ \
|
|
(( SNSD_NODE_PACK_SZ + SNSD_PRIO_PACK_SZ + SNSD_SERVICE_PACK_SZ + \
|
|
sizeof(struct snsd_prio_llist_hdr))*SNSD_MAX_RECORDS + \
|
|
sizeof(struct snsd_service_llist_hdr) \
|
|
)
|
|
|
|
|
|
/*
|
|
* This array is used to associate a 8bit number to a protocol name.
|
|
* The number is the position of the protocol name in this array.
|
|
* For example: "tcp" is in the first position so its associated number is 1,
|
|
* while the number for "udp" is 2.
|
|
*
|
|
* Since we limit the proto number to an 8bit number, there can be only 255
|
|
* protocols in this array.
|
|
*/
|
|
const static char proto_str[][5] =
|
|
{
|
|
{ "tcp" },
|
|
{ "udp" },
|
|
{ 0 },
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
*
|
|
* * * Functions' declaration * * *
|
|
*
|
|
*/
|
|
|
|
void snsd_cache_init(int family);
|
|
u_char str_to_snsd_proto(char *proto_name);
|
|
const char *snsd_proto_to_str(u_char proto);
|
|
int str_to_snsd_service(char *str, int *service, u_char *proto);
|
|
struct servent *snsd_service_to_str(int service, u_char proto,
|
|
char **service_str, char **proto_str);
|
|
|
|
snsd_service *snsd_find_service(snsd_service *sns, u_short service, u_char proto);
|
|
snsd_service *snsd_add_service(snsd_service **head, u_short service, u_char proto);
|
|
snsd_prio *snsd_find_prio(snsd_prio *snp, u_char prio);
|
|
snsd_prio *snsd_add_prio(snsd_prio **head, u_char prio);
|
|
snsd_node *snsd_find_node_by_record(snsd_node *snd, u_int record[MAX_IP_INT]);
|
|
snsd_node *snsd_add_node(snsd_node **head, u_short *counter,
|
|
u_short max_records, u_int record[MAX_IP_INT]);
|
|
snsd_node *snsd_add_mainip(snsd_service **head, u_short *counter,
|
|
u_short max_records, u_int record[MAX_IP_INT]);
|
|
void snsd_service_llist_del(snsd_service **head);
|
|
void snsd_record_del_selected(snsd_service **head, u_short *snd_counter,
|
|
snsd_service *selected);
|
|
|
|
int snsd_pack_service(char *pack, size_t free_sz, snsd_service *service);
|
|
snsd_service *snsd_unpack_service(char *pack, size_t pack_sz,
|
|
size_t *unpacked_sz, u_short *nodes_counter);
|
|
int snsd_pack_all_services(char *pack, size_t pack_sz, snsd_service *head);
|
|
snsd_service *snsd_unpack_all_service(char *pack, size_t pack_sz,
|
|
size_t *unpacked_sz, u_short *nodes_counter);
|
|
|
|
snsd_node *snsd_choose_wrand(snsd_node *head);
|
|
snsd_prio *snsd_highest_prio(snsd_prio *head);
|
|
snsd_node *snsd_find_mainip(snsd_service *sns);
|
|
void snsd_unset_all_flags(snsd_service *sns, u_char flag);
|
|
snsd_service *snsd_service_llist_copy(snsd_service *sns, int service,
|
|
u_char proto);
|
|
|
|
void snsd_merge_node(snsd_node **head, u_short *snsd_counter, snsd_node *new);
|
|
void snsd_node_llist_merge(snsd_node **dst, u_short *snsd_counter, snsd_node *src);
|
|
void snsd_merge_prio(snsd_prio **head, u_short *snsd_counter, snsd_prio *new);
|
|
void snsd_prio_llist_merge(snsd_prio **dst, u_short *snsd_counter, snsd_prio *src);
|
|
void snsd_merge_service(snsd_service **head, u_short *snsd_counter,
|
|
snsd_service *new);
|
|
void snsd_service_llist_merge(snsd_service **dst, u_short *snsd_counter,
|
|
snsd_service *src);
|
|
|
|
int snsd_count_nodes(snsd_node *head);
|
|
int snsd_count_prio_nodes(snsd_prio *head);
|
|
int snsd_count_service_nodes(snsd_service *head);
|
|
#endif /*SNSD_H*/
|