Added patches/openhip-bind directory with patch to bind production

release 9.7.2-P3 to allow the HIP extension to DNS as specified by RFC 5205.

Added contribution from Alexander Kiening to process the HIP extension
to the DNS response and to evaluate the RVS address in the DNS response
and continue with the connection establishment process by sending I1
packets to the RVS.  It will also support a list of RVSes
rather than a single RVS.


git-svn-id: svn://svn.code.sf.net/p/openhip/code/hip/trunk@63 4c5cb64f-9889-4596-9799-84b02dc3effa
This commit is contained in:
Orlie Brewer 2011-03-02 23:56:45 +00:00
parent df9d288048
commit b459136e9a
15 changed files with 1886 additions and 20 deletions

View File

@ -0,0 +1,21 @@
HIP RR for BIND 9.x
Supports RFC 5205
Files:
hip_55.h
hip_55.c
This patch has been tested with the bind production release 9.7.2-P3.
To enable BIND 9.x to process the HIP RR, follow these steps.
1. Download and unpack the BIND 9.x server
tar xzf bind-9.7.2-P3.tar.gz
2. Copy the HIP RR files to the proper directory:
cp hip_55.c bind-9.7.2-P3/lib/dns/rdata/generic/
cp hip_55.h bind-9.7.2-P3/lib/dns/rdata/generic/
3. Compile BIND in the usual fashion (run make clean if recompiling)
./configure
make
make install
4. Use the included hi2dns utility to add HIP RRs to your zone files.

View File

@ -0,0 +1,49 @@
# Copyright (c) 2006-2011, The Boeing Company.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of The Boeing Company nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
CC = gcc
XMLL = $(shell xml2-config --libs)
XMLI = $(shell xml2-config --cflags)
CFLAGS = -g -Wall -O2 ${XMLI}
# -g for debug
OBJS = hi2dns.o
all: hi2dns
hi2dns: ${OBJS}
${CC} ${OBJS} -o hi2dns -lcrypto ${XMLL} ${CFLAGS}
hi2dns.o: hi2dns.h
clean:
@echo Cleaning...
rm -f hi2dns ${OBJS}

View File

@ -0,0 +1,23 @@
This patch implements the HIP extension to DNS as specified by RFC 5205.
It allows DNS servers to store and return HIP resource records (RRs) with
a Host Identity (HI, the public component of the public-private key pair),
Host Identity Tag (HIT, a truncated hash of the public key), and an optional
number of Domain Names of rendezvous servers (RVSs).
The general steps are:
Apply the patch hip_55 to bind and build.
Compile hi2dns and generate HIP RRs using hi2dns.
Edit named.conf and the zone file adding the HIP RRs.
Start the named.
Use dig to check your RRs.
See INSTALL.BIND for building and installing bind. See README.simple.example
for details of the other steps. For more information, see the wiki page:
http://www.openhip.org/wiki/index.php?title=Usage#HIP_DNS_records

View File

@ -0,0 +1,117 @@
This file gives the steps and configuration files for a simple example case.
In the simple example, we have a HIP-enable host alice, trying to contact
another HIP-enable host bob. The host alice does not have any of bob's data
in her known_hosts_identities.xml file. The host bob will register with a RVS
and will have his HIP RR stored with a HIP-enable DNS server. Our domain
name for the example is domain.com. The IP address of our HIP-enable DNS
server is 192.168.0.159 and the IP address of our RVS is 192.168.0.166.
Generate bob's HIP RR.
Compile the program hi2dns by typing make hit2dns.
Before running this program on bob, make sure that the name in the
my_host_identities.xml file is the same name that will be used in DNS.
# /usr/local/sbin/hi2dns /usr/local/etc/hip/my_host_identities.xml
Loading Host Identities from XML file '/usr/local/etc/hip/my_host_identities.xml'...
Loading Host Identity...(DSA 1024-bit) bob.domain.com
done.
HIP RRs:
bob.domain.com. IN HIP ( 1 200100126706037C58F879BC9411E48B
CMdzIYxzfsjumTtPLe0w9I7azpFf11cmLEWExEwhHxi9luXwYcTwpCP3/mtrhbNM73LOFKDTpSIv4Izs5lvmwmWFSIncHtvRPsiydNqfdbomzLmHcjYCeH6SK6hEIfIsPInLmwb9YP4BlB3dd/5rEok9p27rwdEo2X8GeNdyK1NByFBvNYIUsWovrEs2iVA4eBHH2jOCJpAJ4U7EdLryky5p07HxhRetlZQYTM386uluxNXvkxM+hLRwk8UrIM010CSSs5WexkmWJbxPpQguIsWzdOFt0AEyznGwICFwkaxxe2EjkcdsH7LogxfBvYFx1B7Lg+IQwDzJsy6BBWHCFiHHPW2qwCj0sVhdp/QlGXGMybCe74dqUHHUurpDAXW4kra0ljUG2IahK8S4c3hi+5FZ8zmgjAW6h1BHl3DIFTFt+Eimp6rR83cnvjaykpxRZ/uhK5qsglDbPDlGjBVMwua3dl/Npoe2jZdEY3z8/1cZW5ug0ZqYHbKI9BJApUhl2RBjEQc69JKMgPxkYn/wazFYJxtY
)
Create named.conf and zone file on the HIP-enabled DNS server.
Simple example of named.conf for the domain "domain.com":
options {
directory "/usr/local/var/named";
};
zone "domain.com" IN {
type master;
file "db.domain.com";
};
Thus, the zone file will be /usr/local/var/named/db.domain.com.
Create the zone file for "domain.com" and copy the previously generated HIP RR
into it. Note that in the example below, we have added the RVS FQDN to the
HIP RR and added the A record for the RVS. The A record for the RVS can be
in the HIP-enabled DNS server or a normal DNS server. The IP address of the
HIP-enabled DNS is specified by the dns_server parameter in the hip.conf
file on alice. The IP address of the DNS server having the A record of
the RVS should be listed in the /etc/resolv.conf file on alice. In our case
they are the same.
Simple example of zone file "db.domain.com":
$TTL 86400
@ IN SOA @ root (
42 ; serial
3H ; refresh
15M ; retry
1W ; expiry
1D ) ; minimum
IN NS @
IN A 192.168.0.159
bob.domain.com. IN HIP ( 1 200100126706037C58F879BC9411E48B
CMdzIYxzfsjumTtPLe0w9I7azpFf11cmLEWExEwhHxi9luXwYcTwpCP3/mtrhbNM73LOFKDTpSIv4Izs5lvmwmWFSIncHtvRPsiydNqfdbomzLmHcjYCeH6SK6hEIfIsPInLmwb9YP4BlB3dd/5rEok9p27rwdEo2X8GeNdyK1NByFBvNYIUsWovrEs2iVA4eBHH2jOCJpAJ4U7EdLryky5p07HxhRetlZQYTM386uluxNXvkxM+hLRwk8UrIM010CSSs5WexkmWJbxPpQguIsWzdOFt0AEyznGwICFwkaxxe2EjkcdsH7LogxfBvYFx1B7Lg+IQwDzJsy6BBWHCFiHHPW2qwCj0sVhdp/QlGXGMybCe74dqUHHUurpDAXW4kra0ljUG2IahK8S4c3hi+5FZ8zmgjAW6h1BHl3DIFTFt+Eimp6rR83cnvjaykpxRZ/uhK5qsglDbPDlGjBVMwua3dl/Npoe2jZdEY3z8/1cZW5ug0ZqYHbKI9BJApUhl2RBjEQc69JKMgPxkYn/wazFYJxtY
rvs.domain.com.
)
rvs.domain.com. A 192.168.0.166
Start the patched named daemon on your HIP-enable DNS server:
# /usr/local/sbin/named -c /usr/local/etc/named/named.conf -g
You can can test your DNS configuration using the dig command from the patched
bind software:
# /usr/local/bin/dig hip bob.domain.com
and
# /usr/local/bin/dig a rvs.domain.com
Start the HIP daemon on rvs.domain.com with
# /usr/local/sbin/hip -v -a -rvs
Start the HIP daemon on bob (note the known_hosts_identities.xml on bob
should have the HI and IP address for rvs.domain.com)
# /usr/local/sbin/hip -v -a
Have bob register with rvs, for example just ping <LSI of rvs.domain.com>
On alice, ensure that there is no information on bob in the
known_hosts_identities.xml file and that the following is in the hip.conf file:
<disable_dns_lookups>no</disable_dns_lookups>
<disable_notify>yes</disable_notify>
<disable_dns_thread>no</disable_dns_thread>
<dns_server>192.168.0.159</dns_server>
<enable_broadcast>no</enable_broadcast>
<disable_udp>yes</disable_udp>
<preferred_interface>eth1</preferred_interface>
<save_known_identities>no</save_known_identities>
where the dns_server is the IP address of the HIP-enabled DNS server and
the preferred_interface is set to the appropriate interface. Also, make
sure that the IP address of the DNS server holding the A record of the RVS
is in /etc/resolv.conf. This can be the same as the HIP-enabled DNS server
as in our example.
Start the hip daemon on alice
# /usr/local/sbin/hip -v
and then
# ping -n bob.domain.com.hip

View File

@ -0,0 +1,576 @@
/*
Copyright (c) 2006-2011, The Boeing Company.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of The Boeing Company nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <openssl/dsa.h>
#include <openssl/dsa.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <fcntl.h>
#include <libxml2/libxml/tree.h> /* all XML stuff */
#include "hi2dns.h"
/* Globals */
hi_node *my_hi_head;
/* Function declarations - most taken from hip_util.c */
void parse_xml_attributes(xmlAttrPtr attr, hi_node *hi);
void parse_xml_hostid(xmlNodePtr node, hi_node *hi);
int read_identities_file(char *filename, int mine);
hi_node *create_new_hi_node();
void append_hi_node(hi_node **head, hi_node *append);
int hex_to_bin(char *src, char *dst, int dst_len);
int hi_to_base64(hi_node *hi, __u8 *p);
int bn2bin_safe(const BIGNUM *a, unsigned char *to, int len);
void print_hex(void* data, int len);
int main(int argc, char **argv)
{
hi_node *hi;
__u8 base64[2048];
char fname[255];
int tabs;
char *dash;
/* command-line parameters */
sprintf(fname, "%s", HIP_MYID_FILENAME);
if (argc > 1) {
if ((argc > 2) || (strcmp(argv[1], "-h") == 0) ||
(strcmp(argv[1], "--help") == 0)) {
fprintf(stderr, "usage: %s [file.xml]\n\n", argv[0]);
fprintf(stderr, "Will read Host Identities from the ");
fprintf(stderr, "specified file if provided, or from ");
fprintf(stderr, "the\ndefault file %s.\n\n", fname);
return(0);
} else {
strncpy(fname, argv[1], sizeof(fname));
}
}
/* read HIs from XML */
my_hi_head = NULL;
printf("Loading Host Identities from XML file '%s'...\n", fname);
if (read_identities_file(fname, TRUE) < 0) {
fprintf(stderr, "error loading Host Identities.\n");
return(-1);
}
printf("done.\n\n");
/* output HIs in DNS RR format */
printf("HIP RRs:\n");
for (hi = my_hi_head; hi; hi=hi->next) {
memset(base64, 0, sizeof(base64));
dash = strrchr(hi->name, '-'); /* remove dash */
if (dash)
*dash = '\0';
if ((40 - strlen(hi->name)) > 0) /* indent by 40 chars */
tabs = (40 - strlen(hi->name))/8;
else
tabs = 0;
printf("%s", hi->name);
if (strrchr(hi->name, '.')) /* trailing dot if no domain */
printf(".");
for ( ; tabs > 0; tabs--)
printf("\t");
/* class, type, and record */
printf("IN HIP ( %u ", (hi->algorithm_id == HI_ALG_DSA) ? 1 :
(hi->algorithm_id == HI_ALG_RSA) ? 2 : 0); /* pk_alg */
print_hex(hi->hit, HIT_SIZE); /* HIT */
printf("\n");
if (hi_to_base64(hi, base64) < 0)
printf("\t\t*** error converting Host Identity ***\n");
else
printf("\t\t\t\t\t%s\n", base64); /* pk */
printf(" )\n");
} /* end for */
printf("\n");
return 0;
}
/*
* Traverse the linked-list of XML attributes stored in attr, and
* store the value of each attribute into the hi_node structure.
*/
void parse_xml_attributes(xmlAttrPtr attr, hi_node *hi)
{
char *value;
int tmp;
/* first set some defaults if certain attributes are absent */
if (hi == NULL)
return;
hi->r1_gen_count = 0;
hi->anonymous = 0;
hi->allow_incoming = 1;
hi->skip_addrcheck = 0;
while (attr) {
if ((attr->type==XML_ATTRIBUTE_NODE) &&
(attr->children) &&
(attr->children->type==XML_TEXT_NODE))
value = (char *)attr->children->content;
else /* no attribute value */
continue;
/* save recognized attributes */
if (strcmp((char *)attr->name, "alg")==0) {
//memcpy(alg, value, strlen(value));
} else if (strcmp((char *)attr->name, "alg_id")==0) {
sscanf(value, "%d", &tmp);
hi->algorithm_id = (char)tmp;
} else if (strcmp((char *)attr->name, "length")==0) {
sscanf(value, "%d", &hi->size);
} else if (strcmp((char *)attr->name, "anon")==0) {
if (*value == 'y')
hi->anonymous = 1;
else
hi->anonymous = 0;
} else if (strcmp((char *)attr->name, "incoming")==0) {
if (*value == 'y')
hi->allow_incoming = 1;
else
hi->allow_incoming = 0;
} else if (strcmp((char *)attr->name, "r1count")==0) {
sscanf(value, "%llu", &hi->r1_gen_count);
} else if (strcmp((char *)attr->name, "addrcheck")==0) {
if (strcmp(value, "no")==0)
hi->skip_addrcheck = TRUE;
}
attr = attr->next;
}
}
/*
* Traverse the linked-list of child nodes stored in node, and
* store the content of each element into the DSA structure or
* into the HIT.
*/
void parse_xml_hostid(xmlNodePtr node, hi_node *hi)
{
char *data;
struct sockaddr_storage ss_addr;
struct sockaddr *addr;
sockaddr_list *list;
addr = (struct sockaddr*) &ss_addr;
memset(hi->hit, 0, HIT_SIZE);
memset(&hi->lsi, 0, sizeof(struct sockaddr_storage));
for (; node; node = node->next) {
/* skip entity refs */
if (strcmp((char *)node->name, "text")==0)
continue;
data = (char *)xmlNodeGetContent(node);
/* populate the DSA structure */
switch (hi->algorithm_id) {
case HI_ALG_DSA:
if (strcmp((char *)node->name, "P")==0) {
BN_hex2bn(&hi->dsa->p, data);
} else if (strcmp((char *)node->name, "Q")==0) {
BN_hex2bn(&hi->dsa->q, data);
} else if (strcmp((char *)node->name, "G")==0) {
BN_hex2bn(&hi->dsa->g, data);
} else if (strcmp((char *)node->name, "PUB")==0) {
BN_hex2bn(&hi->dsa->pub_key, data);
} else if (strcmp((char *)node->name, "PRIV")==0) {
BN_hex2bn(&hi->dsa->priv_key, data);
}
break;
case HI_ALG_RSA:
if (strcmp((char *)node->name, "N")==0) {
BN_hex2bn(&hi->rsa->n, data);
} else if (strcmp((char *)node->name, "E")==0) {
BN_hex2bn(&hi->rsa->e, data);
} else if (strcmp((char *)node->name, "D")==0) {
BN_hex2bn(&hi->rsa->d, data);
} else if (strcmp((char *)node->name, "P")==0) {
BN_hex2bn(&hi->rsa->p, data);
} else if (strcmp((char *)node->name, "Q")==0) {
BN_hex2bn(&hi->rsa->q, data);
} else if (strcmp((char *)node->name, "dmp1")==0) {
BN_hex2bn(&hi->rsa->dmp1, data);
} else if (strcmp((char *)node->name, "dmq1")==0) {
BN_hex2bn(&hi->rsa->dmq1, data);
} else if (strcmp((char *)node->name, "iqmp")==0) {
BN_hex2bn(&hi->rsa->iqmp, data);
}
break;
default:
break;
}
/* get HI values that are not algorithm-specific */
if (strcmp((char *)node->name, "HIT")==0) {
/* HIT that looks like IPv6 address */
if (index(data, ':')) {
memset(addr, 0, sizeof(addr));
addr->sa_family = AF_INET6;
if (inet_pton(addr->sa_family,
data, SA2IP(addr)) <= 0) {
printf("%s '%s' for %s invalid.\n",
node->name, data, hi->name);
xmlFree(data);
continue;
}
memcpy(hi->hit, SA2IP(addr), HIT_SIZE);
} else { /* HIT that is plain hex */
hex_to_bin(data, (char *)hi->hit, HIT_SIZE);
}
} else if (strcmp((char *)node->name, "name")==0) {
memset(hi->name, 0, sizeof(hi->name));
strncpy(hi->name, data, sizeof(hi->name));
hi->name_len = strlen(hi->name);
} else if ((strcmp((char *)node->name, "LSI")==0) ||
(strcmp((char *)node->name, "addr")==0)) {
memset(addr, 0, sizeof(struct sockaddr_storage));
/* Determine address family - IPv6 must have a ':' */
addr->sa_family = ((index(data, ':')==NULL) ? AF_INET : AF_INET6);
if (inet_pton(addr->sa_family, data, SA2IP(addr)) > 0) {
list = &hi->addrs;
/* first entry in address list */
if ((strcmp((char *)node->name, "addr")==0) &&
(VALID_FAM(&list->addr))) {
// add_address_to_list(&list, addr, 0);
/* LSI */
} else if (strcmp((char *)node->name,"LSI")==0){
memcpy(&hi->lsi, addr, SALEN(addr));
/* additional address entry */
} else {
memcpy(&list->addr, addr, SALEN(addr));
}
} else {
printf("%s '%s' for %s not valid.\n",
node->name, data, hi->name);
}
}
xmlFree(data);
}
}
/*
* function read_identities_file()
*
* filename name of the XML file to open
* mine is this my list of Host Identities?
* if TRUE, store HIs/HITs into my_hi_list, otherwise
* store into peer_hi_list.
*
*/
int read_identities_file(char *filename, int mine)
{
xmlDocPtr doc = NULL;
xmlNodePtr node = NULL;
hi_node *hi;
char name[255];
doc = xmlParseFile(filename);
if (doc == NULL) {
fprintf(stderr, "Error parsing xml file (%s)\n", filename);
return(-1);
}
node = xmlDocGetRootElement(doc);
for (node = node->children; node; node = node->next)
{
if (strcmp((char *)node->name, "host_identity")==0) {
printf("Loading Host Identity...");
hi = create_new_hi_node();
parse_xml_attributes(node->properties, hi);
printf( "(%s %d-bit) ",
HI_TYPESTR(hi->algorithm_id), hi->size*8);
switch (hi->algorithm_id) {
case HI_ALG_DSA:
hi->dsa = DSA_new();
break;
case HI_ALG_RSA:
hi->rsa = RSA_new();
break;
default:
if (mine) {
printf( "Unknown algorithm found ");
printf( "in XML file: %u\n",
hi->algorithm_id);
if (hi->dsa) DSA_free(hi->dsa);
if (hi->rsa) RSA_free(hi->rsa);
free(hi);
continue;
}
}
/* fill in the DSA/RSA structure, HIT, LSI, name */
parse_xml_hostid(node->children, hi);
/* if LSI is not configured, it is 24-bits of HIT */
if (!VALID_FAM(&hi->lsi)) {
__u32 lsi = ntohl(HIT2LSI(hi->hit));
hi->lsi.ss_family = AF_INET;
memcpy(SA2IP(&hi->lsi), &lsi, sizeof(__u32));
}
if (mine) {
/* addresses for HIs in my_host_identities will
* be added later per association */
memset(&hi->addrs.addr, 0,
sizeof(struct sockaddr_storage));
printf( "%s\n", hi->name);
} else {
/* get HI name */
strcpy(name, hi->name);
if (rindex(name, '-'))
name[strlen(name)-strlen(rindex(name,'-'))] = 0;
}
/* link this HI into a global list */
append_hi_node(mine ? &my_hi_head : NULL, hi);
}
/*
* add other XML tags here
*/
}
xmlFreeDoc(doc);
xmlCleanupParser();
return(0);
}
/*
* Create an hi_node
*/
hi_node *create_new_hi_node()
{
hi_node *ret;
ret = (hi_node *) malloc(sizeof(hi_node));
if (ret == NULL) {
printf("Malloc error: creating new hi_node\n");
return NULL;
}
memset(ret, 0, sizeof(hi_node));
return(ret);
}
/*
* Append an hi_node to a list
*/
void append_hi_node(hi_node **head, hi_node *append)
{
hi_node *hi_p;
if (*head == NULL) {
*head = append;
return;
}
for (hi_p = *head; hi_p->next; hi_p = hi_p->next);
hi_p->next = append;
}
/*
*
* function hex_to_bin()
*
* in: src = input hex data
* dst = output binary data
* dst_len = requested number of binary bytes
*
* out: returns bytes converted if successful,
* -1 if error
*
*/
int hex_to_bin(char *src, char *dst, int dst_len)
{
char hex[] = "0123456789abcdef";
char hexcap[] = "0123456789ABCDEF";
char *p, c;
int src_len, total, i, val;
unsigned char o;
if ((!src) || (!dst))
return(-1);
src_len = strlen(src);
if (dst_len > src_len)
return(-1);
/* chop any '0x' prefix */
if ((src[0]=='0') && (src[1]=='x')) {
src += 2;
src_len -= 2;
}
/* convert requested number of bytes from hex to binary */
total = 0;
for (i=0; (i < src_len) && (total < dst_len) ; i+=2) {
/* most significant nibble */
c = src[i];
/*
* Normally would use tolower(), but have found problems
* with dynamic linking and different glibc versions
*/
if ((p = strchr(hex, c)) == NULL) {
if ((p = strchr(hexcap, c)) == NULL) {
continue;
}
val = p - hexcap;
} else {
val = p - hex;
}
if (val < 0 || val > 15) {
return(-1);
}
o = val << 4;
/* least significant nibble */
c = src[i+1];
if ((p = strchr(hex, c)) == NULL) {
if ((p = strchr(hexcap, c)) == NULL) {
continue;
}
val = p - hexcap;
} else {
val = p - hex;
}
if (val < 0 || val > 15) {
return(-1);
}
o += val;
dst[total] = o;
total++;
if (total >= src_len)
total = dst_len;
}
return total;
}
/*
* function hi_to_base64()
*
* in: hi = the Host Identity from which HIT is computed
* p = ptr to destination bytes
*
* out: Returns 0 if successful, -1 on error.
*
* Converts the Host Identity to a Type 1 SHA-1 HIT.
*
*/
int hi_to_base64(hi_node *hi, __u8 *p)
{
int len, location;
__u8 *data=NULL;
__u16 e_len;
if (!hi)
return(-1);
switch (hi->algorithm_id) {
case HI_ALG_DSA: /* RFC 2536 */
if ((!hi->dsa) || (!hi->dsa->q) || (!hi->dsa->p) ||
(!hi->dsa->g) || (!hi->dsa->pub_key))
return(-1);
len = 1 + DSA_PRIV + (3*hi->size);
data = malloc(len);
if (!data)
return(-1);
/* Encode T, Q, P, G, Y */
data[0] = (hi->size - 64)/8;
bn2bin_safe(hi->dsa->q, &data[1], DSA_PRIV);
bn2bin_safe(hi->dsa->p, &data[1+DSA_PRIV], hi->size);
bn2bin_safe(hi->dsa->g, &data[1+DSA_PRIV+hi->size], hi->size);
bn2bin_safe(hi->dsa->pub_key, &data[1+DSA_PRIV+(2*hi->size)],
hi->size);
location = len;
break;
case HI_ALG_RSA: /* RFC 3110 */
if ((!hi->rsa) || (!hi->rsa->e) || (!hi->rsa->n))
return(-1);
e_len = BN_num_bytes(hi->rsa->e);
if (e_len > 255)
len = 3 + e_len + RSA_size(hi->rsa);
else
len = 1 + e_len + RSA_size(hi->rsa);
data = malloc(len);
if (!data)
return(-1);
/* Encode e_len, exponent(e), modulus(n) */
if (e_len > 255) {
__u16 *p = (__u16*) &data[1];
data[0] = 0x0;
*p = htons(e_len);
location = 3;
} else {
data[0] = (__u8) e_len;
location = 1;
}
location += bn2bin_safe(hi->rsa->e, &data[location], e_len);
location += bn2bin_safe(hi->rsa->n, &data[location],
RSA_size(hi->rsa));
break;
default:
return(-1);
}
/* this base64 encodes the HI */
len = EVP_EncodeBlock(p, data, location);
/*printf("\n len = %d location = %d \n", len, location);*/
/*print_hex(data, location);*/
free(data);
return(len);
}
/*
* function bn2bin_safe(BIGNUM *dest)
*
* BN_bin2bn() chops off the leading zero(es) of the BIGNUM,
* so numbers end up being left shifted.
* This fixes that by enforcing an expected destination length.
*/
int bn2bin_safe(const BIGNUM *a, unsigned char *to, int len)
{
int padlen = len - BN_num_bytes(a);
/* add leading zeroes when needed */
if (padlen > 0)
memset(to, 0, padlen);
BN_bn2bin(a, &to[padlen]);
/* return value from BN_bn2bin() may differ from length */
return(len);
}
/*
* function print_hex()
*
* Generic binary to hex printer.
*/
void print_hex(void* data, int len)
{
int i;
unsigned char *p = (unsigned char*) data;
for (i=0; i < len; i++)
printf("%.2X", p[i]);
}

View File

@ -0,0 +1,234 @@
/*
Copyright (c) 2006-2011, The Boeing Company.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of The Boeing Company nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _NET_HIP_H_
#define _NET_HIP_H_
#include <asm/types.h>
#include <sys/socket.h> /* sockaddr */
#include <netinet/in.h>
#include <openssl/bn.h>
#include <openssl/hmac.h>
#include <openssl/rsa.h>
#include <time.h>
/*
* Implementation configuration options
*/
#ifndef __UMH__
#define HIP_CONF_FILENAME "/etc/hip/hip.conf"
#define HIP_MYID_FILENAME "/etc/hip/my_host_identities.xml"
#define HIP_KNOWNID_FILENAME "/etc/hip/known_host_identities.xml"
#define HIP_LOCK_FILENAME "/var/run/hip.pid"
#define HIP_LOG_FILENAME "/var/log/hipd.log"
#else
#define HIP_CONF_FILENAME "hip.conf"
#define HIP_MYID_FILENAME "my_host_identities.xml"
#define HIP_KNOWNID_FILENAME "known_host_identities.xml"
#define HIP_LOCK_FILENAME "hip.pid"
#define HIP_LOG_FILENAME "hipd.log"
#endif
/*
* Implementation limits
*/
#define MAX_HI_NAMESIZE 255 /* number of bytes for HI Domain Identifier */
#define MAX_HI_BITS 2048 /* number of bits of largest HI accepted - this
* may limit the time spent w/ DSA verification */
/*
* IPsec-related constants
*/
#define DSA_PRIV 20 /* Size in bytes of DSA private key and Q value */
/*
* Miscellaneous constants and enums
*/
#define TRUE 1
#define FALSE 0
/*
* Macros
*/
#define DBG(x) x /* Debugging */
#define TDIFF(a, b) ((a).tv_sec - (b).tv_sec) /* Time diff in seconds */
/* get pointer to IP from a sockaddr
* useful for inet_ntop calls */
#define SA2IP(x) (((struct sockaddr*)x)->sa_family==AF_INET) ? \
(void*)&((struct sockaddr_in*)x)->sin_addr : \
(void*)&((struct sockaddr_in6*)x)->sin6_addr
/* get socket address length in bytes */
#define SALEN(x) (((struct sockaddr*)x)->sa_family==AF_INET) ? \
sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)
/* get IP address length in bytes */
#define SAIPLEN(x) (((struct sockaddr*)x)->sa_family==AF_INET) ? 4 : 16
/* cast to sockaddr */
#define SA(x) ((struct sockaddr*)x)
/* boolean to text yes/no */
#define yesno(x) x ? "yes" : "no"
/* convert lower 24-bits of HIT to LSI */
#define HIT_SIZE 16
#define HIT_PREFIX_TYPE1_SHA1 0x40
#define HIT2LSI(a) ( 0x01000000L | \
((a[HIT_SIZE-3]<<16)+(a[HIT_SIZE-2]<<8)+(a[HIT_SIZE-1])))
#define IS_LSI32(a) ((a & 0xFF) == 0x01)
#define IS_LSI(a) ( ( ((struct sockaddr_in*)a)->sin_family == AF_INET) && \
(IS_LSI32(((struct sockaddr_in*)a)->sin_addr.s_addr)))
#define VALID_FAM(a) ( (((struct sockaddr*)a)->sa_family == AF_INET) || \
(((struct sockaddr*)a)->sa_family == AF_INET6) )
/*
* typedefs
*/
typedef __u8 hip_hit [HIT_SIZE]; /* 16-byte (128 bit) Host Identity Tag */
/*
* list of struct sockaddrs
*/
typedef struct _sockaddr_list
{
struct _sockaddr_list *next;
struct sockaddr_storage addr; /* 128 bytes, enough to store any size */
int if_index; /* link index */
int lifetime; /* address lifetime in seconds*/
int status; /* status from enum ADDRESS_STATES */
int preferred; /* set to TRUE if it's a new pending preferred addr */
__u32 nonce; /* random value for address verification */
struct timeval creation_time;
} sockaddr_list;
/* For reference: struct DSA definition from openssl/dsa.h */
/*
* struct dsa_st {
*
* * This first variable is used to pick up errors where
* * a DSA is passed instead of of a EVP_PKEY *
int pad;
int version;
int write_params;
BIGNUM *p;
BIGNUM *q; * == 20 *
BIGNUM *g;
BIGNUM *pub_key; * y public key *
BIGNUM *priv_key; * x private key *
... (plus some other fields not used in HIP)
*/
typedef struct _hi_node {
struct _hi_node *next;
hip_hit hit;
struct sockaddr_storage lsi;
/*
* IP address is needed to select a HIT corresponding to
* an IP address. This value needs update upon readdress.
* Only the first entry of addrs is used for hip_assoc,
* while the list addrs->next is populated when building the
* HI tables.
*/
pthread_mutex_t addrs_mutex; /* provide DHT thread synchronization */
struct _sockaddr_list addrs;
/* Key data */
int size; /* Size in bytes of the Host Identity */
DSA *dsa; /* HI in DSA format */
RSA *rsa; /* HI in RSA format */
__u64 r1_gen_count; /* R1 generation counter */
__u32 update_id; /* this host's Update ID */
/* Options */
char algorithm_id;
char anonymous;
char allow_incoming;
char skip_addrcheck;
char name[MAX_HI_NAMESIZE];
int name_len; /* use this instead of strlen() */
} hi_node;
typedef struct _pseudo_header6
{
unsigned char src_addr[16];
unsigned char dst_addr[16];
__u32 packet_length;
char zero[3];
__u8 next_hdr;
} pseudo_header6;
typedef struct _pseudo_header
{
unsigned char src_addr[4];
unsigned char dst_addr[4];
__u8 zero;
__u8 protocol;
__u16 packet_length;
} pseudo_header;
/* HI (signature) algorithms */
enum {
HI_ALG_RESERVED,
HI_ALG_DSA = 3,
HI_ALG_RSA = 5,
} HI_ALGORITHMS;
#define HIP_RSA_DFT_EXP RSA_F4 /* 0x10001L = 65537; 3 and 17 are also common */
#define HI_TYPESTR(a) ((a==HI_ALG_DSA) ? "DSA" : \
(a==HI_ALG_RSA) ? "RSA" : "UNKNOWN")
/* HI Domain Identifier types */
enum {
DIT_NONE, /* none included */
DIT_FQDN, /* Fully Qualified Domain Name, in binary format */
DIT_NAI, /* Network Access Identifier, binary, login@FQDN */
} HI_DIT;
typedef enum {
D_DEFAULT,
D_VERBOSE,
D_QUIET,
} DEBUG_MODES;
typedef enum {
NORM,
NORMT,
WARN,
ERR,
#ifndef OUT /* Windows */
OUT,
#endif
} LOG_LEVELS;
#endif /* _NET_HIP_H_ */

View File

@ -0,0 +1,541 @@
/*
Copyright (c) 2006-2011, The Boeing Company.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of The Boeing Company nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Files to support draft-ietf-hip-dns */
#ifndef RDATA_GENERIC_HIP_55_C
#define RDATA_GENERIC_HIP_55_C
#include <math.h>
#include <dst/dst.h>
#define RRTYPE_HIP_ATTRIBUTES (0)
#define TOBEDEFINED_HIP_RR 55
/* #define HIP_55_DEBUG */
static inline isc_result_t
fromtext_hip(ARGS_FROMTEXT) {
isc_token_t token;
dns_secalg_t pk_alg;
int pk_length, hit_length;
isc_buffer_t buffer;
dns_name_t name;
isc_uint8_t *p;
REQUIRE(type == TOBEDEFINED_HIP_RR);
UNUSED(type);
UNUSED(rdclass);
UNUSED(origin);
UNUSED(options);
UNUSED(callbacks);
#ifdef HIP_55_DEBUG
fprintf(stderr, "HIPRR: fromtext_hip\n");
#endif
/* PK algorithm */
RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
ISC_FALSE));
pk_alg = (isc_uint8_t)token.value.as_ulong;
/* save ptr to start of buffer, pk_length not yet known */
p = isc_buffer_used(target);
RETERR(uint8_tobuffer(0, target)); /* HIT length */
RETERR(uint8_tobuffer(pk_alg, target));
RETERR(uint16_tobuffer(0, target)); /* PK length */
/* could also use isc_tokentype_string and
dns_secalg_fromtext(&pk_alg, &token.value.as_textregion) function */
/*
* HIT
*/
hit_length = 16;
RETERR(isc_hex_tobuffer(lexer, target, hit_length));
p[0] = (isc_uint8_t)hit_length;
/*
* Public Key
*/
/* There is no white space in the public key as per RFC 5205,
* so find out how many characters there are and put it back.
* Base64 encodes three bytes into four characters as per RFC 4648.
* The third parameter to isc_base64_tobuffer is the number of bytes
* to decode. -1 cannot be used as the third parameter to
* isc_base64_tobuffer because that reads until end of record.
*/
RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
ISC_FALSE));
if (token.type != isc_tokentype_string)
return (ISC_R_UNEXPECTEDTOKEN);
pk_length = ceil(3*token.value.as_textregion.length/4.0);
isc_lex_ungettoken(lexer, &token);
if (pk_length > HIP_55_MAX_PK_LENGTH)
RETERR(ISC_R_RANGE);
RETERR(isc_base64_tobuffer(lexer, target, pk_length));
p[2] = (isc_uint8_t) ((pk_length & 0xff00U) >> 8);
p[3] = (isc_uint8_t) (pk_length & 0x00ffU);
/* Rendezvous Servers */
while (isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
ISC_FALSE) == ISC_R_SUCCESS) {
dns_name_init(&name, NULL);
buffer_fromregion(&buffer, &token.value.as_region);
origin = (origin != NULL) ? origin : dns_rootname;
RETTOK(dns_name_fromtext(&name, &buffer, origin,
options, target));
}
return (ISC_R_SUCCESS);
}
static inline isc_result_t
totext_hip(ARGS_TOTEXT) {
isc_region_t sr, dr;
char buf[sizeof("256")];
dns_secalg_t pk_alg;
isc_uint8_t hit_length;
isc_uint16_t pk_length;
dns_name_t prefix, name;
isc_boolean_t sub;
#ifdef HIP_55_DEBUG
fprintf(stderr, "HIPRR: totext_hip\n");
#endif
REQUIRE(rdata->type == TOBEDEFINED_HIP_RR);
REQUIRE(rdata->length != 0);
dns_rdata_toregion(rdata, &sr);
/*
* hit length 1
* pk algorithm 1
* pk length 1
*/
hit_length = sr.base[0];
pk_alg = sr.base[1];
isc_region_consume(&sr, 2);
pk_length = uint16_fromregion(&sr);
isc_region_consume(&sr, 2);
if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
RETERR(str_totext(" (", target));
sprintf(buf, "%u", pk_alg);
RETERR(str_totext(buf, target));
RETERR(str_totext(tctx->linebreak, target));
RETERR(str_totext(" ", target));
/*
* HIT
*/
REQUIRE(hit_length <= sr.length);
dr = sr;
dr.length = hit_length;
RETERR(isc_hex_totext(&dr, tctx->width - 2,
tctx->linebreak, target));
if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0)
RETERR(str_totext(tctx->linebreak, target));
else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
RETERR(str_totext(" ", target));
isc_region_consume(&sr, hit_length);
/*
* Public Key
*/
REQUIRE(pk_length <= sr.length);
dr = sr;
dr.length = pk_length;
RETERR(str_totext(tctx->linebreak, target));
RETERR(isc_base64_totext(&dr, tctx->width - 2,
tctx->linebreak, target));
RETERR(str_totext(tctx->linebreak, target));
isc_region_consume(&sr, pk_length);
/*
* RVS (optional)
*/
while (sr.length > 0) {
dns_name_init(&name, NULL);
dns_name_init(&prefix, NULL);
dns_name_fromregion(&name, &sr);
isc_region_consume(&sr, name_length(&name));
sub = name_prefix(&name, tctx->origin, &prefix);
RETERR(str_totext(tctx->linebreak, target));
RETERR(dns_name_totext(&prefix, sub, target));
}
if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
RETERR(str_totext(" )", target));
return (ISC_R_SUCCESS);
}
static inline isc_result_t
fromwire_hip(ARGS_FROMWIRE) {
isc_region_t sr;
dns_name_t name;
isc_uint8_t hit_length;
isc_uint16_t pk_length;
#ifdef HIP_55_DEBUG
fprintf(stderr, "HIPRR: fromwire_hip\n");
#endif
REQUIRE(type == TOBEDEFINED_HIP_RR);
UNUSED(type);
UNUSED(rdclass);
UNUSED(dctx);
UNUSED(options);
dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
isc_buffer_activeregion(source, &sr);
if (sr.length < 4)
return (ISC_R_UNEXPECTEDEND);
RETERR(mem_tobuffer(target, sr.base, 2));
hit_length = sr.base[0];
isc_buffer_forward(source, 2);
isc_buffer_activeregion(source, &sr);
pk_length = uint16_fromregion(&sr);
isc_buffer_forward(source, 2);
RETERR(mem_tobuffer(target, sr.base, 2));
isc_buffer_activeregion(source, &sr);
if (sr.length < (hit_length + pk_length))
return (ISC_R_UNEXPECTEDEND);
isc_buffer_forward(source, hit_length + pk_length);
RETERR(mem_tobuffer(target, sr.base, hit_length + pk_length));
isc_buffer_activeregion(source, &sr);
while (sr.length > 0) {
dns_name_init(&name, NULL);
RETERR(dns_name_fromwire(&name, source, dctx, options, target));
isc_buffer_activeregion(source, &sr); /* update sr.length */
}
return(ISC_R_SUCCESS);
}
static inline isc_result_t
towire_hip(ARGS_TOWIRE) {
isc_region_t sr;
dns_offsets_t offsets;
dns_name_t name;
isc_uint8_t hit_length;
isc_uint16_t pk_length;
#ifdef HIP_55_DEBUG
fprintf(stderr, "HIPRR: towire_hip\n");
#endif
REQUIRE(rdata->type == TOBEDEFINED_HIP_RR);
REQUIRE(rdata->length != 0);
UNUSED(cctx);
dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
dns_rdata_toregion(rdata, &sr);
/*
* HIT length: 1
* PK algorithm: 1
* PK length: 2
*/
RETERR(mem_tobuffer(target, sr.base, 4));
hit_length = sr.base[0];
isc_region_consume(&sr, 2);
pk_length = uint16_fromregion(&sr);
isc_region_consume(&sr, 2);
/*
* HIT: variable
* PK: variable
*/
REQUIRE(hit_length <= sr.length);
RETERR(mem_tobuffer(target, sr.base, hit_length));
isc_region_consume(&sr, hit_length);
REQUIRE(pk_length <= sr.length);
RETERR(mem_tobuffer(target, sr.base, pk_length));
isc_region_consume(&sr, pk_length);
/*
* RVS (optional)
*/
while (sr.length > 0) {
dns_name_init(&name, offsets);
dns_name_fromregion(&name, &sr);
isc_region_consume(&sr, name_length(&name));
RETERR( dns_name_towire(&name, cctx, target) );
}
return(ISC_R_SUCCESS);
}
static inline int
compare_hip(ARGS_COMPARE) {
isc_region_t r1;
isc_region_t r2;
REQUIRE(rdata1->type == rdata2->type);
REQUIRE(rdata1->rdclass == rdata2->rdclass);
REQUIRE(rdata1->type == TOBEDEFINED_HIP_RR);
REQUIRE(rdata1->length != 0);
REQUIRE(rdata2->length != 0);
dns_rdata_toregion(rdata1, &r1);
dns_rdata_toregion(rdata2, &r2);
/* XXX could more carefully do dns_name_rdatacompare() for RVS */
return (isc_region_compare(&r1, &r2));
}
static inline isc_result_t
fromstruct_hip(ARGS_FROMSTRUCT) {
dns_rdata_hip_t *hiprr = (dns_rdata_hip_t *) source;
int i;
#ifdef HIP_55_DEBUG
fprintf(stderr, "HIPRR: fromstruct_hip\n");
#endif
REQUIRE(type == TOBEDEFINED_HIP_RR);
REQUIRE(source != NULL);
REQUIRE(hiprr->common.rdtype == type);
REQUIRE(hiprr->common.rdclass == rdclass);
UNUSED(type);
UNUSED(rdclass);
RETERR(uint8_tobuffer(hiprr->hit_length, target));
RETERR(uint8_tobuffer(hiprr->pk_algorithm, target));
RETERR(uint16_tobuffer(hiprr->pk_length, target));
RETERR(mem_tobuffer(target, hiprr->hit, hiprr->hit_length));
RETERR(mem_tobuffer(target, hiprr->pk, hiprr->pk_length));
for (i = 0; i < MAX_NUM_RVS; i++) {
if (hiprr->rvs_name[i].length > 0)
RETERR(name_tobuffer(&hiprr->rvs_name[i], target));
else
break;
}
return (ISC_R_SUCCESS);
}
static inline isc_result_t
tostruct_hip(ARGS_TOSTRUCT) {
dns_rdata_hip_t *hiprr = (dns_rdata_hip_t *) target;
isc_region_t sr;
dns_name_t name;
int i;
#ifdef HIP_55_DEBUG
fprintf(stderr, "HIPRR: tostruct_hip\n");
#endif
REQUIRE(rdata->type == TOBEDEFINED_HIP_RR);
REQUIRE(target != NULL);
REQUIRE(rdata->length != 0);
hiprr->common.rdclass = rdata->rdclass;
hiprr->common.rdtype = rdata->type;
ISC_LINK_INIT(&hiprr->common, link);
dns_rdata_toregion(rdata, &sr);
/* HIT length */
if (sr.length < 1)
return (ISC_R_UNEXPECTEDEND);
hiprr->hit_length = uint8_fromregion(&sr);
isc_region_consume(&sr, 1);
check_hip_length(hiprr->hit_length, HIP_55_MAX_HIT_LENGTH);
/* Public Key algorithm */
if (sr.length < 1)
return (ISC_R_UNEXPECTEDEND);
hiprr->pk_algorithm = uint8_fromregion(&sr);
isc_region_consume(&sr, 1);
/* Public Key length */
if (sr.length < 2)
return (ISC_R_UNEXPECTEDEND);
hiprr->pk_length = uint16_fromregion(&sr);
isc_region_consume(&sr, 2);
/* HIT */
if (sr.length < hiprr->hit_length)
return (ISC_R_UNEXPECTEDEND);
hiprr->hit = mem_maybedup(mctx, sr.base, hiprr->hit_length);
if (hiprr->hit == NULL)
goto cleanup;
isc_region_consume(&sr, hiprr->hit_length);
/* Public Key */
if (sr.length < hiprr->pk_length)
return (ISC_R_UNEXPECTEDEND);
hiprr->pk = mem_maybedup(mctx, sr.base, hiprr->pk_length);
if (hiprr->pk == NULL)
goto cleanup;
isc_region_consume(&sr, hiprr->pk_length);
/* optional RVS(s) */
dns_name_init(&hiprr->rvs_name[0], NULL);
for (i = 0; sr.length > 0 && i < MAX_NUM_RVS; i++) {
dns_name_init(&hiprr->rvs_name[i], NULL);
dns_name_init(&name, NULL);
dns_name_fromregion(&name, &sr);
RETERR(name_duporclone(&name, mctx, &hiprr->rvs_name[i]));
isc_region_consume(&sr, name_length(&hiprr->rvs_name[i]));
}
hiprr->mctx = mctx;
return (ISC_R_SUCCESS);
cleanup:
if (hiprr->hit != NULL)
isc_mem_free(mctx, hiprr->hit);
if (hiprr->pk != NULL)
isc_mem_free(mctx, hiprr->pk);
/* if (mctx != NULL)
dns_name_free( &hiprr->rvs_name[0], mctx); */
return (ISC_R_NOMEMORY);
}
static inline void
freestruct_hip(ARGS_FREESTRUCT) {
dns_rdata_hip_t *hiprr = (dns_rdata_hip_t *) source;
int i;
#ifdef HIP_55_DEBUG
fprintf(stderr, "HIPRR: freestruct_hip\n");
#endif
REQUIRE(source != NULL);
REQUIRE(hiprr->common.rdtype == TOBEDEFINED_HIP_RR);
if (hiprr->mctx == NULL)
return;
if (hiprr->hit != NULL)
isc_mem_free(hiprr->mctx, hiprr->hit);
if (hiprr->pk != NULL)
isc_mem_free(hiprr->mctx, hiprr->pk);
for (i = 0; i < MAX_NUM_RVS; i++) {
if (hiprr->rvs_name[i].length > 0)
dns_name_free(&hiprr->rvs_name[i], hiprr->mctx);
else
break;
}
hiprr->mctx = NULL;
}
static inline isc_result_t
additionaldata_hip(ARGS_ADDLDATA) {
REQUIRE(rdata->type == TOBEDEFINED_HIP_RR);
UNUSED(rdata);
UNUSED(add);
UNUSED(arg);
return (ISC_R_SUCCESS);
}
static inline isc_result_t
digest_hip(ARGS_DIGEST) {
isc_region_t r;
#ifdef HIP_55_DEBUG
fprintf(stderr, "HIPRR: digest_hip\n");
#endif
REQUIRE(rdata->type == TOBEDEFINED_HIP_RR);
dns_rdata_toregion(rdata, &r);
return((digest)(arg, &r));
}
static inline isc_boolean_t
checkowner_hip(ARGS_CHECKOWNER) {
REQUIRE(type == TOBEDEFINED_HIP_RR);
UNUSED(name);
UNUSED(type);
UNUSED(rdclass);
UNUSED(wildcard);
return (ISC_TRUE);
}
static inline isc_boolean_t
checknames_hip(ARGS_CHECKNAMES) {
isc_region_t region;
dns_name_t name;
isc_uint8_t hit_length;
isc_uint16_t pk_length;
int len;
#ifdef HIP_55_DEBUG
fprintf(stderr, "HIPRR: checknames_hip\n");
#endif
REQUIRE(rdata->type == TOBEDEFINED_HIP_RR);
UNUSED(owner);
dns_rdata_toregion(rdata, &region);
hit_length = region.base[0];
isc_region_consume(&region, 2);
pk_length = uint16_fromregion(&region);
isc_region_consume(&region, 2);
len = hit_length + pk_length;
isc_region_consume(&region, len); /* eat all data before rvs */
while (region.length > 0) {
dns_name_init(&name, NULL);
dns_name_fromregion(&name, &region);
if (!dns_name_ishostname(&name, ISC_FALSE)) {
if (bad != NULL)
dns_name_clone(&name, bad);
return (ISC_FALSE);
}
if (name_length(&name) == 0)
break;
isc_region_consume(&region, name_length(&name));
}
return (ISC_TRUE);
}
static inline int
casecompare_hip(ARGS_COMPARE) {
return (compare_hip(rdata1, rdata2));
}
#endif /* RDATA_GENERIC_HIP_55_C */

View File

@ -0,0 +1,57 @@
/*
Copyright (c) 2006-2011, The Boeing Company.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of The Boeing Company nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GENERIC_HIP_55_H
#define GENERIC_HIP_55_H 1
/* The following size limits may be changed. */
#define HIP_55_MAX_HIT_LENGTH 16 /* 128 bit HIT size limit */
#define HIP_55_MAX_PK_LENGTH 512 /* 4096 bit RSA key size limit */
#define MAX_NUM_RVS 8
#define check_hip_length(length, max) \
if (length > max) return (ISC_R_FAILURE);
typedef struct dns_rdata_hip {
dns_rdatacommon_t common;
isc_mem_t *mctx;
isc_uint8_t hit_length;
isc_uint8_t pk_algorithm;
isc_uint16_t pk_length;
unsigned char * hit;
unsigned char * pk;
/* RVS is optional */
dns_name_t rvs_name[MAX_NUM_RVS];
} dns_rdata_hip_t;
#endif /* GENERIC_HIP_55_H */

View File

@ -397,7 +397,32 @@ typedef struct _hi_node {
struct _hi_node *next;
hip_hit hit;
struct sockaddr_storage lsi;
struct sockaddr_storage rvs;
hip_mutex_t *rvs_mutex; /* Sync for DNS rvs resolving threads */
/*
* Do not try to contact the node until the
* RVS servers are resolved.
*/
pthread_cond_t *rvs_cond;
int *rvs_count; /* Number of RVS DNS petitions still to resolve */
int *copies; /* Number of copies of the mutex structures */
/*
* List of hostnames of all RVS servers as received from the
* DNS server.
* (Double zero ended list)
*/
char **rvs_hostnames;
/*
* List of IP addresses corresponding to the RVS hostnames.
* Each hostname can be resolved to multiple addresses or
* to none, so there cannot be direct 1-1 reationship between
* RVS hostnames and addresses.
*/
struct _sockaddr_list **rvs_addrs;
/*
* IP address is needed to select a HIT corresponding to
* an IP address. This value needs update upon readdress.

View File

@ -327,9 +327,7 @@ void init_hip(int ac, char **av)
printf("Error creating ESP input thread.\n");
exit(1);
}
#ifdef SMA_CRAWLER
hip_sleep(1); /* Wait a sec for config */
#endif /* SMA_CRAWLER */
if (!is_dns_thread_disabled()) {
/* XXX hip.conf may not be loaded yet */
if (pthread_create(&dns_thrd, NULL, hip_dns, NULL)) {

View File

@ -1664,8 +1664,9 @@ int hip_convert_lsi_to_peer(struct sockaddr *lsi, hip_hit *hitp,
* could do BEX for IPv6 and update to v4 addr?
*/
}
} else if (VALID_FAM(&peer_hi->rvs)) {
memcpy(SA(dst), SA(&peer_hi->rvs), SALEN(&peer_hi->rvs));
} else if (VALID_FAM(&(*(peer_hi->rvs_addrs))->addr)) {
memcpy(SA(dst), SA(&(*(peer_hi->rvs_addrs))->addr),
SALEN(&(*(peer_hi->rvs_addrs))->addr));
}
/* my preferred address becomes src (instead of LSI) */

View File

@ -1054,6 +1054,7 @@ hip_retransmit_waiting_packets(struct timeval* time1)
hiphdr *hiph;
char typestr[12];
int offset;
struct _sockaddr_list *item;
for (i=0; i < max_hip_assoc; i++) {
hip_a = &hip_assoc_table[i];
@ -1103,16 +1104,64 @@ hip_retransmit_waiting_packets(struct timeval* time1)
gettimeofday(&hip_a->rexmt_cache.xmit_time, NULL);
hip_a->rexmt_cache.retransmits++;
} else {
/* move to state E_FAILED for I1_SENT/I2_SENT */
switch (hip_a->state) {
case I1_SENT:
/* try next RVS address if there is one */
if(*(hip_a->peer_hi->rvs_addrs)){
for(item = *(hip_a->peer_hi->rvs_addrs); item; item = item->next) {
if(item->status != DEPRECATED){
struct sockaddr *cur_rvs;
cur_rvs = SA(&item->addr);
log_(NORMT, "RVS server %s not reachable, changing status to DEPRECATED.\n", logaddr(cur_rvs));
item->status = DEPRECATED; /* set currently used RVS address to DEPRECATED */
break;
}
}
if(item->next){
/* Send the I1 to next RVS server */
src = SA(&hip_a->hi->addrs.addr);
dst = SA(&item->next->addr);
offset = 0;
if (hip_a->udp)
offset += sizeof(udphdr) + sizeof(__u32);
hiph = (hiphdr*) &hip_a->rexmt_cache.packet[offset];
hip_packet_type(hiph->packet_type, typestr);
if (!hip_a->udp){
/* recalcualte HIP checksum because of changed destination IP/HIT*/
hiph->checksum = 0;
hiph->checksum = checksum_packet( hip_a->rexmt_cache.packet, src, dst);
}
memcpy(&hip_a->rexmt_cache.dst, &item->next->addr, sizeof(struct sockaddr_storage));
log_(NORMT, "Retransmitting %s packet from %s to ",
typestr, logaddr(src));
log_(NORM, "next RVS server in list: %s\n", logaddr(dst));
hip_retransmit(hip_a, hip_a->rexmt_cache.packet,
hip_a->rexmt_cache.len, src, dst);
gettimeofday(&hip_a->rexmt_cache.xmit_time, NULL);
hip_a->rexmt_cache.retransmits = 0; /* reset retransmit counter */
} else {
/* reset the status of all RVS servers */
for(item = *(hip_a->peer_hi->rvs_addrs); item; item = item->next) {
item->status = UNVERIFIED;
}
set_state(hip_a, E_FAILED);
clear_retransmissions(hip_a);
}
} else {
set_state(hip_a, E_FAILED);
clear_retransmissions(hip_a);
}
break;
/* move to state E_FAILED for I2_SENT */
case I2_SENT:
set_state(hip_a, E_FAILED);
clear_retransmissions(hip_a);
break;
default:
clear_retransmissions(hip_a);
break;
}
clear_retransmissions(hip_a);
}
}
}

View File

@ -160,8 +160,16 @@ int hip_send_I1(hip_hit *hit, hip_assoc *hip_a)
log_(NORMT, "Relaying HIP_I1 packet (%d bytes)...\n", location);
do_retrans = FALSE;
} else { /* normal I1, not relayed by RVS */
if (VALID_FAM(&hip_a->peer_hi->rvs)){/* use RVS instead of DST*/
dst = SA(&hip_a->peer_hi->rvs);
pthread_mutex_lock(hip_a->peer_hi->rvs_mutex);
/* Block in case of RVS DNS resolution is NOT ready */
if(*(hip_a->peer_hi->rvs_count) > 0) {
log_(NORMT, "Waiting for RVS DNS resolution\n");
pthread_cond_wait(hip_a->peer_hi->rvs_cond, hip_a->peer_hi->rvs_mutex);
log_(NORMT, "Waiting done, sending I1 now.\n");
}
pthread_mutex_unlock(hip_a->peer_hi->rvs_mutex);
if (*(hip_a->peer_hi->rvs_addrs) != NULL){/* use RVS instead of DST*/
dst = SA(&(*(hip_a->peer_hi->rvs_addrs))->addr);
if (hip_a->udp && dst->sa_family == AF_INET) {
((struct sockaddr_in *)dst)->sin_port =
((struct sockaddr_in *)
@ -2094,7 +2102,6 @@ int build_tlv_hmac(hip_assoc *hip_a, __u8 *data, int location, int type)
memcpy( hmac->hmac,
&hmac_md[hmac_md_len-sizeof(hmac->hmac)],
sizeof(hmac->hmac));
return(eight_byte_align(sizeof(tlv_hmac)));
}

View File

@ -79,6 +79,7 @@
#include <libxml/tree.h>
#ifndef HITGEN
/*
* function add_addresses_from_dns()
*
@ -333,6 +334,15 @@ hi_node *create_new_hi_node()
}
memset(ret, 0, sizeof(hi_node));
pthread_mutex_init(&ret->addrs_mutex, NULL);
ret->rvs_addrs = malloc(sizeof(struct _sockaddr_list *));
*(ret->rvs_addrs) = NULL;
ret->rvs_count = malloc(sizeof(int));
*(ret->rvs_count) = 0;
ret->rvs_mutex = malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(ret->rvs_mutex, NULL);
ret->rvs_cond = malloc(sizeof(pthread_cond_t));
pthread_cond_init (ret->rvs_cond, NULL);
return(ret);
}
@ -470,12 +480,11 @@ int key_data_to_hi(const __u8 *data, __u8 alg, int hi_length, __u8 di_type,
/* prepare *hi_p */
if (*hi_p == NULL) {
*hi_p = (hi_node *) malloc(sizeof(hi_node));
*hi_p = create_new_hi_node();
if (*hi_p == NULL) {
log_(WARN, "Malloc error for storing HI\n");
return(-1);
}
memset(*hi_p, 0, sizeof(hi_node));
}
hi = *hi_p;
if (alg==HI_ALG_DSA && hi->dsa) {
@ -544,6 +553,9 @@ int key_data_to_hi(const __u8 *data, __u8 alg, int hi_length, __u8 di_type,
log_(WARN, "Unknown DI type (%d) in HI", di_type);
return(-1);
}
hi->rvs_hostnames = malloc(sizeof(char *));
hi->rvs_hostnames[0] = NULL;
return(offset);
}
@ -780,8 +792,18 @@ hip_assoc *init_hip_assoc(hi_node *my_host_id, const hip_hit *peer_hit)
stored_hi->skip_addrcheck;
memcpy(&hip_a->peer_hi->lsi, &stored_hi->lsi,
SALEN(&stored_hi->lsi));
memcpy(&hip_a->peer_hi->rvs, &stored_hi->rvs,
SALEN(&stored_hi->rvs));
memcpy(&hip_a->peer_hi->name, &stored_hi->name,
stored_hi->name_len);
hip_a->peer_hi->rvs_mutex = stored_hi->rvs_mutex;
hip_a->peer_hi->rvs_cond = stored_hi->rvs_cond;
hip_a->peer_hi->rvs_count = stored_hi->rvs_count;
hip_a->peer_hi->rvs_addrs = stored_hi->rvs_addrs;
if(stored_hi->copies == NULL) {
stored_hi->copies = malloc(sizeof(int));
*(stored_hi->copies) = 1;
}
(*(stored_hi->copies))++;
hip_a->peer_hi->copies = stored_hi->copies;
}
}
memset(&hip_a->peer_hi->addrs, 0, sizeof(sockaddr_list));
@ -894,6 +916,25 @@ void free_hi_node(hi_node *hi)
if (hi->rsa)
hip_rsa_free(hi->rsa);
pthread_mutex_destroy(&hi->addrs_mutex);
if(hi->copies != NULL) {
(*(hi->copies))--;
if(*(hi->copies) == 0) { /* Last instance of this node */
free(hi->rvs_count);
free(hi->copies);
free(hi->rvs_addrs);
pthread_cond_destroy(hi->rvs_cond);
pthread_mutex_destroy(hi->rvs_mutex);
free(hi->rvs_cond);
free(hi->rvs_mutex);
}
} else { /* Only instance of this node */
free(hi->rvs_count);
free(hi->rvs_addrs);
pthread_cond_destroy(hi->rvs_cond);
pthread_mutex_destroy(hi->rvs_mutex);
free(hi->rvs_cond);
free(hi->rvs_mutex);
}
free(hi);
}
@ -1138,6 +1179,91 @@ int is_dns_thread_disabled()
return(HCNF.disable_dns_thread);
}
int add_rvs_hostname_to_node(hi_node *hi, char *dnsName) {
int i = 0, len;
/* Calculate current size of list */
while(hi->rvs_hostnames[i] != NULL) {
/*printf(" Pos %d: %s\n", i, hi->rvs_hostnames[i]);*/
i++;
}
/* Alloc memory for current i + 1 new name + NULL */
hi->rvs_hostnames = realloc(hi->rvs_hostnames, (i+2) * sizeof(char *));
hi->rvs_hostnames[i+1] = NULL;
if (hi->rvs_hostnames == NULL) return -1;
len = strnlen(dnsName, 255) + 1;
/* printf(" Adding %s (%d)\n", dnsName, len); */
hi->rvs_hostnames[i] = malloc(len);
memcpy(hi->rvs_hostnames[i], dnsName, len);
return 0;
}
struct rvs_dns_request {
char *name;
hi_node *node;
};
void print_rvs_addr_list(sockaddr_list *list)
{
sockaddr_list *l;
log_(NORM, "Address list: [");
for (l = list; l; l=l->next) {
log_(NORM, "(%d)%s, ", l->if_index,
logaddr((struct sockaddr*)&l->addr));
}
log_(NORM, "]\n");
}
#ifndef HITGEN
void *background_resolve(void *arg) {
hi_node *hi;
char *name;
int addr, err;
struct addrinfo hints, *aux, *res = NULL;
struct sockaddr_in *a;
struct rvs_dns_request *req;
req = (struct rvs_dns_request *) arg;
name = req->name;
hi = req->node;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_RAW;
log_(NORM, "*** Trying resolve %s ***\n", name);
err = getaddrinfo(name, NULL, &hints, &res);
log_(NORM, "*** RESOLVE %s FINISHED!! ***\n", name);
/* Start critical section */
pthread_mutex_lock(hi->rvs_mutex);
for(aux = res; aux !=NULL; aux = aux->ai_next) {
a = (struct sockaddr_in *)aux->ai_addr;
/* addr = ntohl(a->sin_addr.s_addr); */
addr = a->sin_addr.s_addr;
add_address_to_list(hi->rvs_addrs, aux->ai_addr, 0);
print_rvs_addr_list(*(hi->rvs_addrs));
}
(*(hi->rvs_count))--;
if(*(hi->rvs_count) == 0) {
log_(NORM, "*** RESOLVE OF ALL RVS FINISHED!! ***\n");
pthread_cond_broadcast(hi->rvs_cond);
} else {
log_(NORM, "*** Still %d to go... ***\n", *(hi->rvs_count));
}
pthread_mutex_unlock(hi->rvs_mutex);
/* End critical section */
freeaddrinfo(res);
free(arg);
pthread_exit(NULL);
}
#endif /* HITGEN */
/*
* receive_hip_dns_response()
*
@ -1236,10 +1362,51 @@ __u32 receive_hip_dns_response(unsigned char *buff, int len)
} else {
/* printf("%s: HIT validated OK.\n", fn); */
}
/* TODO: read in RVS names here and
* store them somewhere
int pos = p - ((unsigned char*)&dnsans->ans_len + sizeof(dnsans->ans_len));
int remainingBytes = ntohs(dnsans->ans_len) - pos;
int rvsCount = 0;
while (remainingBytes > 0) {
char dnsName[255];
int dnsLen = strnlen((char*) p, remainingBytes) + 1;
memcpy(dnsName, p+1, dnsLen - 1); /* First char is metadata */
int i = 0;
for (;i < dnsLen - 2; i++) {
if (dnsName[i] < 22) {
dnsName[i] = '.';
}
}
fprintf(stderr, "RVS: %s\n", dnsName);
add_rvs_hostname_to_node(hi, dnsName); /* Add hostanmes to hi_node struct */
rvsCount++;
p += dnsLen;
remainingBytes -= dnsLen;
}
/* TODO: handle pthread_t values correctly (IF NEEDED)
* Dynamic thread ID creation would need a non-blocking pthread_join
* to liberate the memory reserved for the IDs...
* Note: pthread_create does not accept NULL as a first argument,
* unlike other implementations found online (QNX)
*/
/* printf("Found HI, %d bytes remain\n", p - buff); */
#ifndef HITGEN
int j;
pthread_t pt;
struct rvs_dns_request *argument;
if(rvsCount > 0) {
*(hi->rvs_count) += rvsCount;
for(j = 0; hi->rvs_hostnames[j] != NULL; j++) {
printf(" %d: %s\n", j, hi->rvs_hostnames[j]);
argument = malloc(sizeof(struct rvs_dns_request));
argument->name = hi->rvs_hostnames[j];
argument->node = hi;
/* Created thread will free allocated memory */
pthread_create(&pt, NULL, background_resolve, (void *)argument);
} /* for */
} /* if */
#endif
append_hi_node(&peer_hi_head, hi);
lsi = ntohl(HIT2LSI(hi->hit));
return(lsi);

View File

@ -264,7 +264,7 @@ void parse_xml_hostid(xmlNodePtr node, hi_node *hi)
memcpy(&hi->lsi, addr, SALEN(addr));
/* rendevous server (RVS) */
} else if (strcmp((char *)node->name,"RVS")==0){
memcpy(&hi->rvs, addr, SALEN(addr));
add_address_to_list(hi->rvs_addrs, addr, 0);
/* first (preferred) entry in address list */
} else {
memcpy(&list->addr, addr, SALEN(addr));
@ -650,8 +650,9 @@ int hi_to_xml(xmlNodePtr root_node, hi_node *h, int mine)
addr_to_str(SA(&h->lsi), (__u8*)addr, INET6_ADDRSTRLEN);
xmlNewChild(hi, NULL, BAD_CAST "LSI", BAD_CAST addr);
}
if (VALID_FAM(&h->rvs)) {
addr_to_str(SA(&h->rvs), (__u8*)addr, INET6_ADDRSTRLEN);
sockaddr_list *l;
for(l = *(h->rvs_addrs); l != NULL; l = l->next) {
addr_to_str(SA(&l->addr), (__u8*)addr, INET6_ADDRSTRLEN);
xmlNewChild(hi, NULL, BAD_CAST "RVS", BAD_CAST addr);
}