ISC DHCP 3.0b2pl23

This commit is contained in:
mellon 2001-04-02 21:56:50 +00:00
parent 2c7d48475b
commit 7ac99333ec
69 changed files with 10818 additions and 1176 deletions

View File

@ -1,20 +1,39 @@
.\" dhclient.conf.5
.\"
.\" Copyright (c) 1996-1999 Internet Software Consortium.
.\" Use is subject to license terms which appear in the file named
.\" ISC-LICENSE that should have accompanied this file when you
.\" received it. If a file named ISC-LICENSE did not accompany this
.\" file, or you are not sure the one you have is correct, you may
.\" obtain an applicable copy of the license at:
.\" Copyright (c) 1996-2001 Internet Software Consortium.
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\"
.\" http://www.isc.org/isc-license-1.0.html.
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. 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.
.\" 3. Neither the name of The Internet Software Consortium nor the names
.\" of its contributors may be used to endorse or promote products derived
.\" from this software without specific prior written permission.
.\"
.\" This file is part of the ISC DHCP distribution. The documentation
.\" associated with this file is listed in the file DOCUMENTATION,
.\" included in the top-level directory of this release.
.\" THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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.
.\"
.\" Support and other services are available for ISC products - see
.\" http://www.isc.org for more information.
.\" This software has been written for the Internet Software Consortium
.\" by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
.\" To learn more about the Internet Software Consortium, see
.\" ``http://www.isc.org/''. To learn more about Vixie Enterprises,
.\" see ``http://www.vix.com''. To learn more about Nominum, Inc., see
.\" ``http://www.nominum.com''.
.TH dhclient.conf 5
.SH NAME
dhclient.conf - DHCP client configuration file

View File

@ -50,8 +50,8 @@ if [ x$alias_subnet_mask != x ]; then
fi
if [ x$reason = xMEDIUM ]; then
ifconfig $interface $medium
ifconfig $interface inet -alias 0.0.0.0 $medium >/dev/null 2>&1
eval "ifconfig $interface $medium"
eval "ifconfig $interface inet -alias 0.0.0.0 $medium" >/dev/null 2>&1
sleep 1
exit_with_hooks 0
fi
@ -88,7 +88,7 @@ if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
fi
if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]
then
ifconfig $interface inet -alias $old_ip_address $medium
eval "ifconfig $interface inet -alias $old_ip_address $medium"
route delete $old_ip_address 127.1 >/dev/null 2>&1
for router in $old_routers; do
route delete default $router >/dev/null 2>&1
@ -104,8 +104,8 @@ if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
fi
if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \
[ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then
ifconfig $interface inet $new_ip_address $new_netmask_arg \
$new_broadcast_arg $medium
eval "ifconfig $interface inet $new_ip_address $new_netmask_arg \
$new_broadcast_arg $medium"
route add $new_ip_address 127.1 >/dev/null 2>&1
for router in $new_routers; do
route add default $router >/dev/null 2>&1
@ -133,7 +133,7 @@ if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ]; then
route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
fi
if [ x$old_ip_address != x ]; then
ifconfig $interface inet -alias $old_ip_address $medium
eval "ifconfig $interface inet -alias $old_ip_address $medium"
route delete $old_ip_address 127.1 >/dev/null 2>&1
for router in $old_routers; do
route delete default $router >/dev/null 2>&1
@ -160,8 +160,8 @@ if [ x$reason = xTIMEOUT ]; then
ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
fi
ifconfig $interface inet $new_ip_address $new_netmask_arg \
$new_broadcast_arg $medium
eval "ifconfig $interface inet $new_ip_address $new_netmask_arg \
$new_broadcast_arg $medium"
sleep 1
if [ "$new_routers" != "" ]; then
set $new_routers
@ -184,7 +184,7 @@ if [ x$reason = xTIMEOUT ]; then
exit_with_hooks 0
fi
fi
ifconfig $interface inet -alias $new_ip_address $medium
eval "ifconfig $interface inet -alias $new_ip_address $medium"
for router in $old_routers; do
route delete default $router >/dev/null 2>&1
done

View File

@ -52,7 +52,7 @@ relmajor=`echo $release |sed -e 's/^\([^\.]*\)\..*$/\1/'`
relminor=`echo $release |sed -e 's/^.*\.\([^\.]*\)$/\1/'`
if [ x$reason = xMEDIUM ]; then
$ifconfig $interface $medium
eval "$ifconfig $interface $medium"
$ifconfig $interface
sleep 1
exit_with_hooks 0
@ -104,8 +104,8 @@ if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
fi
if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \
[ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then
$ifconfig $interface inet $new_ip_address $new_netmask_arg \
$new_broadcast_arg $medium
eval "$ifconfig $interface inet $new_ip_address $new_netmask_arg \
$new_broadcast_arg $medium"
route add $new_ip_address 127.1 1 >/dev/null 2>&1
for router in $new_routers; do
route add default $router 1 >/dev/null 2>&1
@ -144,8 +144,8 @@ if [ x$reason = xTIMEOUT ]; then
$ifconfig ${interface}:1 0 down > /dev/null 2>&1
route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
fi
$ifconfig $interface inet $new_ip_address $new_netmask_arg \
$new_broadcast_arg $medium
eval "$ifconfig $interface inet $new_ip_address $new_netmask_arg \
$new_broadcast_arg $medium"
sleep 1
set $new_routers
if ping -s -n -I 1 $1 64 1; then

View File

@ -43,7 +43,7 @@
#ifndef lint
static char copyright[] =
"$Id: alloc.c,v 1.1.1.8 2000/09/04 23:10:04 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
"$Id: alloc.c,v 1.1.1.9 2001/04/02 21:56:51 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@ -57,6 +57,120 @@ OMAPI_OBJECT_ALLOC (shared_network, struct shared_network,
dhcp_type_shared_network)
OMAPI_OBJECT_ALLOC (group_object, struct group_object, dhcp_type_group)
int option_chain_head_allocate (ptr, file, line)
struct option_chain_head **ptr;
const char *file;
int line;
{
int size;
if (!ptr) {
log_error ("%s(%d): null pointer", file, line);
#if defined (POINTER_DEBUG)
abort ();
#else
return 0;
#endif
}
if (*ptr) {
log_error ("%s(%d): non-null pointer", file, line);
#if defined (POINTER_DEBUG)
abort ();
#else
*ptr = (struct option_chain_head *)0;
#endif
}
*ptr = dmalloc (sizeof **ptr, file, line);
if (*ptr) {
memset (*ptr, 0, sizeof **ptr);
(*ptr) -> refcnt = 1;
return 1;
}
return 0;
}
int option_chain_head_reference (ptr, bp, file, line)
struct option_chain_head **ptr;
struct option_chain_head *bp;
const char *file;
int line;
{
if (!ptr) {
log_error ("%s(%d): null pointer", file, line);
#if defined (POINTER_DEBUG)
abort ();
#else
return 0;
#endif
}
if (*ptr) {
log_error ("%s(%d): non-null pointer", file, line);
#if defined (POINTER_DEBUG)
abort ();
#else
*ptr = (struct option_chain_head *)0;
#endif
}
*ptr = bp;
bp -> refcnt++;
rc_register (file, line, ptr, bp, bp -> refcnt);
dmalloc_reuse (bp, file, line, 1);
return 1;
}
int option_chain_head_dereference (ptr, file, line)
struct option_chain_head **ptr;
const char *file;
int line;
{
int i;
struct option_chain_head *option_chain_head;
pair car, cdr;
if (!ptr || !*ptr) {
log_error ("%s(%d): null pointer", file, line);
#if defined (POINTER_DEBUG)
abort ();
#else
return 0;
#endif
}
option_chain_head = *ptr;
*ptr = (struct option_chain_head *)0;
--option_chain_head -> refcnt;
rc_register (file, line, ptr,
option_chain_head, option_chain_head -> refcnt);
if (option_chain_head -> refcnt > 0)
return 1;
if (option_chain_head -> refcnt < 0) {
log_error ("%s(%d): negative refcnt!", file, line);
#if defined (DEBUG_RC_HISTORY)
dump_rc_history ();
#endif
#if defined (POINTER_DEBUG)
abort ();
#else
return 0;
#endif
}
/* If there are any options on this head, free them. */
for (car = option_chain_head -> first; car; car = cdr) {
cdr = car -> cdr;
if (car -> car)
option_cache_dereference ((struct option_cache **)
(&car -> car), MDL);
dfree (car, MDL);
car = cdr;
}
dfree (option_chain_head, file, line);
return 1;
}
int group_allocate (ptr, file, line)
struct group **ptr;
const char *file;

View File

@ -3,7 +3,7 @@
Lexical scanner for dhcpd config file... */
/*
* Copyright (c) 1995-2000 Internet Software Consortium.
* Copyright (c) 1995-2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -43,7 +43,7 @@
#ifndef lint
static char copyright[] =
"$Id: conflex.c,v 1.1.1.11 2000/10/17 15:07:53 taca Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
"$Id: conflex.c,v 1.1.1.12 2001/04/02 21:56:52 mellon Exp $ Copyright (c) 1995-2001 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@ -208,12 +208,17 @@ static enum dhcp_token get_token (cfile)
cfile -> lexchar = p;
ttok = read_num_or_name (c, cfile);
break;
} else if (c == EOF) {
ttok = END_OF_FILE;
cfile -> tlen = 0;
break;
} else {
cfile -> lexline = l;
cfile -> lexchar = p;
tb [0] = c;
tb [1] = 0;
cfile -> tval = tb;
cfile -> tlen = 1;
ttok = c;
break;
}
@ -221,8 +226,9 @@ static enum dhcp_token get_token (cfile)
return ttok;
}
enum dhcp_token next_token (rval, cfile)
enum dhcp_token next_token (rval, rlen, cfile)
const char **rval;
unsigned *rlen;
struct parse *cfile;
{
int rv;
@ -240,14 +246,17 @@ enum dhcp_token next_token (rval, cfile)
}
if (rval)
*rval = cfile -> tval;
if (rlen)
*rlen = cfile -> tlen;
#ifdef DEBUG_TOKENS
fprintf (stderr, "%s:%d ", cfile -> tval, rv);
#endif
return rv;
}
enum dhcp_token peek_token (rval, cfile)
enum dhcp_token peek_token (rval, rlen, cfile)
const char **rval;
unsigned int *rlen;
struct parse *cfile;
{
int x;
@ -269,6 +278,8 @@ enum dhcp_token peek_token (rval, cfile)
}
if (rval)
*rval = cfile -> tval;
if (rlen)
*rlen = cfile -> tlen;
#ifdef DEBUG_TOKENS
fprintf (stderr, "(%s:%d) ", cfile -> tval, cfile -> token);
#endif
@ -397,6 +408,7 @@ static enum dhcp_token read_string (cfile)
--i;
}
cfile -> tokbuf [i] = 0;
cfile -> tlen = i;
cfile -> tval = cfile -> tokbuf;
return STRING;
}
@ -434,6 +446,7 @@ static enum dhcp_token read_number (c, cfile)
--i;
}
cfile -> tokbuf [i] = 0;
cfile -> tlen = i;
cfile -> tval = cfile -> tokbuf;
return token;
}
@ -462,6 +475,7 @@ static enum dhcp_token read_num_or_name (c, cfile)
--i;
}
cfile -> tokbuf [i] = 0;
cfile -> tlen = i;
cfile -> tval = cfile -> tokbuf;
return intern (cfile -> tval, rv);
}
@ -540,6 +554,8 @@ static enum dhcp_token intern (atom, dfv)
return BOOLEAN;
if (!strcasecmp (atom + 1, "alance"))
return BALANCE;
if (!strcasecmp (atom + 1, "ound"))
return BOUND;
break;
case 'c':
if (!strcasecmp (atom + 1, "ase"))
@ -554,6 +570,10 @@ static enum dhcp_token intern (atom, dfv)
return CHECK;
if (!strcasecmp (atom + 1, "lass"))
return CLASS;
if (!strcasecmp (atom + 1, "lose"))
return TOKEN_CLOSE;
if (!strcasecmp (atom + 1, "reate"))
return TOKEN_CREATE;
if (!strcasecmp (atom + 1, "iaddr"))
return CIADDR;
if (!strncasecmp (atom + 1, "lient", 5)) {
@ -561,6 +581,10 @@ static enum dhcp_token intern (atom, dfv)
return CLIENT_IDENTIFIER;
if (!strcasecmp (atom + 6, "-hostname"))
return CLIENT_HOSTNAME;
if (!strcasecmp (atom + 6, "-state"))
return CLIENT_STATE;
if (!strcasecmp (atom + 6, "-updates"))
return CLIENT_UPDATES;
if (!strcasecmp (atom + 6, "s"))
return CLIENTS;
}
@ -687,6 +711,8 @@ static enum dhcp_token intern (atom, dfv)
return HARDWARE;
if (!strcasecmp (atom + 1, "ostname"))
return HOSTNAME;
if (!strcasecmp (atom + 1, "elp"))
return TOKEN_HELP;
break;
case 'i':
if (!strcasecmp (atom + 1, "nclude"))
@ -803,6 +829,8 @@ static enum dhcp_token intern (atom, dfv)
return TOKEN_NULL;
if (!strcasecmp (atom + 1, "ext"))
return TOKEN_NEXT;
if (!strcasecmp (atom + 1, "ew"))
return TOKEN_NEW;
break;
case 'o':
if (!strcasecmp (atom + 1, "mapi"))
@ -811,6 +839,8 @@ static enum dhcp_token intern (atom, dfv)
return OR;
if (!strcasecmp (atom + 1, "n"))
return ON;
if (!strcasecmp (atom + 1, "pen"))
return TOKEN_OPEN;
if (!strcasecmp (atom + 1, "ption"))
return OPTION;
if (!strcasecmp (atom + 1, "ne-lease-per-client"))
@ -858,6 +888,8 @@ static enum dhcp_token intern (atom, dfv)
return RECOVER;
if (!strcasecmp (atom + 1, "ecover-done"))
return RECOVER_DONE;
if (!strcasecmp (atom + 1, "econtact-interval"))
return RECONTACT_INTERVAL;
if (!strcasecmp (atom + 1, "equest"))
return REQUEST;
if (!strcasecmp (atom + 1, "equire"))
@ -920,6 +952,8 @@ static enum dhcp_token intern (atom, dfv)
return SERVER_IDENTIFIER;
if (!strcasecmp (atom + 1, "elect-timeout"))
return SELECT_TIMEOUT;
if (!strcasecmp (atom + 1, "elect"))
return SELECT;
if (!strcasecmp (atom + 1, "end"))
return SEND;
if (!strcasecmp (atom + 1, "cript"))
@ -965,6 +999,8 @@ static enum dhcp_token intern (atom, dfv)
return TSTP;
if (!strcasecmp (atom + 1, "sfp"))
return TSFP;
if (!strcasecmp (atom + 1, "ransmission"))
return TRANSMISSION;
break;
case 'u':
if (!strcasecmp (atom + 1, "nset"))

View File

@ -0,0 +1,297 @@
/* trace.c
Subroutines that support dhcp tracing... */
/*
* Copyright (c) 2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of The Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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.
*
* This software has been written for the Internet Software Consortium
* by Ted Lemon, as part of a project for Nominum, Inc. To learn more
* about the Internet Software Consortium, see http://www.isc.org/. To
* learn more about Nominum, Inc., see ``http://www.nominum.com''.
*/
#include "dhcpd.h"
#if defined (TRACING)
void trace_interface_register (trace_type_t *ttype, struct interface_info *ip)
{
trace_interface_packet_t tipkt;
if (trace_record ()) {
memset (&tipkt, 0, sizeof tipkt);
memcpy (&tipkt.hw_address,
&ip -> hw_address, sizeof ip -> hw_address);
memcpy (&tipkt.primary_address,
&ip -> primary_address, sizeof ip -> primary_address);
memcpy (tipkt.name, ip -> name, sizeof ip -> name);
tipkt.index = htonl (ip -> index);
trace_write_packet (ttype, sizeof tipkt, (char *)&tipkt, MDL);
}
}
void trace_interface_input (trace_type_t *ttype, unsigned len, char *buf)
{
trace_interface_packet_t *tipkt;
struct interface_info *ip;
struct sockaddr_in *sin;
struct iaddr addr;
isc_result_t status;
if (len != sizeof *tipkt) {
log_error ("trace interface packet size mismatch: %ld != %d",
(long)(sizeof *tipkt), len);
return;
}
tipkt = (trace_interface_packet_t *)buf;
ip = (struct interface_info *)0;
status = interface_allocate (&ip, MDL);
if (status != ISC_R_SUCCESS) {
foo:
log_error ("trace_interface_input: %s.",
isc_result_totext (status));
return;
}
ip -> ifp = dmalloc (sizeof *(ip -> ifp), MDL);
if (!ip -> ifp) {
interface_dereference (&ip, MDL);
status = ISC_R_NOMEMORY;
goto foo;
}
memcpy (&ip -> hw_address, &tipkt -> hw_address,
sizeof ip -> hw_address);
memcpy (&ip -> primary_address, &tipkt -> primary_address,
sizeof ip -> primary_address);
memcpy (ip -> name, tipkt -> name, sizeof ip -> name);
ip -> index = ntohl (tipkt -> index);
interface_snorf (ip, 0);
if (dhcp_interface_discovery_hook)
(*dhcp_interface_discovery_hook) (ip);
/* Fake up an ifp. */
memcpy (ip -> ifp -> ifr_name, ip -> name, sizeof ip -> name);
#ifdef HAVE_SA_LEN
ip -> ifp -> ifr_addr.sa_len = sizeof (struct sockaddr_in);
#endif
sin = (struct sockaddr_in *)&ip -> ifp -> ifr_addr;
sin -> sin_addr = ip -> primary_address;
addr.len = 4;
memcpy (addr.iabuf, &sin -> sin_addr.s_addr, addr.len);
if (dhcp_interface_setup_hook)
(*dhcp_interface_setup_hook) (ip, &addr);
interface_stash (ip);
if (!quiet_interface_discovery) {
log_info ("Listening on Trace/%s/%s%s%s",
ip -> name,
print_hw_addr (ip -> hw_address.hbuf [0],
ip -> hw_address.hlen - 1,
&ip -> hw_address.hbuf [1]),
(ip -> shared_network ? "/" : ""),
(ip -> shared_network ?
ip -> shared_network -> name : ""));
if (strcmp (ip -> name, "fallback")) {
log_info ("Sending on Trace/%s/%s%s%s",
ip -> name,
print_hw_addr (ip -> hw_address.hbuf [0],
ip -> hw_address.hlen - 1,
&ip -> hw_address.hbuf [1]),
(ip -> shared_network ? "/" : ""),
(ip -> shared_network ?
ip -> shared_network -> name : ""));
}
}
interface_dereference (&ip, MDL);
}
void trace_interface_stop (trace_type_t *ttype) {
/* XXX */
}
void trace_inpacket_stash (struct interface_info *interface,
struct dhcp_packet *packet,
unsigned len,
unsigned int from_port,
struct iaddr from,
struct hardware *hfrom)
{
trace_inpacket_t tip;
trace_iov_t iov [2];
if (!trace_record ())
return;
tip.from_port = from_port;
tip.from = from;
if (hfrom) {
tip.hfrom = *hfrom;
tip.havehfrom = 1;
} else {
memset (&tip.hfrom, 0, sizeof tip.hfrom);
tip.havehfrom = 0;
}
tip.index = htonl (interface -> index);
iov [0].buf = (char *)&tip;
iov [0].len = sizeof tip;
iov [1].buf = (char *)packet;
iov [1].len = len;
trace_write_packet_iov (inpacket_trace, 2, iov, MDL);
}
void trace_inpacket_input (trace_type_t *ttype, unsigned len, char *buf)
{
trace_inpacket_t *tip;
int index;
if (len < sizeof *tip) {
log_error ("trace_input_packet: too short - %d", len);
return;
}
tip = (trace_inpacket_t *)buf;
index = ntohl (tip -> index);
if (index > interface_count ||
index < 0 ||
!interface_vector [index]) {
log_error ("trace_input_packet: unknown interface index %d",
index);
return;
}
if (!bootp_packet_handler) {
log_error ("trace_input_packet: no bootp packet handler.");
return;
}
(*bootp_packet_handler) (interface_vector [index],
(struct dhcp_packet *)(tip + 1),
len - sizeof *tip,
tip -> from_port,
tip -> from,
(tip -> havehfrom ?
&tip -> hfrom
: (struct hardware *)0));
}
void trace_inpacket_stop (trace_type_t *ttype) { }
ssize_t trace_packet_send (struct interface_info *interface,
struct packet *packet,
struct dhcp_packet *raw,
size_t len,
struct in_addr from,
struct sockaddr_in *to,
struct hardware *hto)
{
trace_outpacket_t tip;
trace_iov_t iov [2];
if (trace_record ()) {
if (hto) {
tip.hto = *hto;
tip.havehto = 1;
} else {
memset (&tip.hto, 0, sizeof tip.hto);
tip.havehto = 0;
}
tip.from.len = 4;
memcpy (tip.from.iabuf, &from, 4);
tip.to.len = 4;
memcpy (tip.to.iabuf, &to -> sin_addr, 4);
tip.to_port = to -> sin_port;
tip.index = htonl (interface -> index);
iov [0].buf = (char *)&tip;
iov [0].len = sizeof tip;
iov [1].buf = (char *)raw;
iov [1].len = len;
trace_write_packet_iov (outpacket_trace, 2, iov, MDL);
}
if (!trace_playback ()) {
return send_packet (interface, packet, raw, len,
from, to, hto);
}
return len;
}
void trace_outpacket_input (trace_type_t *ttype, unsigned len, char *buf)
{
trace_outpacket_t *tip;
int index;
if (len < sizeof *tip) {
log_error ("trace_input_packet: too short - %d", len);
return;
}
tip = (trace_outpacket_t *)buf;
index = ntohl (tip -> index);
if (index > interface_count ||
index < 0 ||
!interface_vector [index]) {
log_error ("trace_input_packet: unknown interface index %d",
index);
return;
}
/* XXX would be nice to somehow take notice of these. */
}
void trace_outpacket_stop (trace_type_t *ttype) { }
void trace_seed_stash (trace_type_t *ttype, unsigned seed)
{
u_int32_t outseed;
if (!trace_record ())
return;
outseed = htonl (seed);
trace_write_packet (ttype, sizeof outseed, (char *)&outseed, MDL);
return;
}
void trace_seed_input (trace_type_t *ttype, unsigned length, char *buf)
{
u_int32_t *seed;
if (length != sizeof seed) {
log_error ("trace_seed_input: wrong size (%d)", length);
}
seed = (u_int32_t *)buf;
srandom (ntohl (*seed));
}
void trace_seed_stop (trace_type_t *ttype) { }
#endif /* TRACING */

View File

@ -1,23 +1,42 @@
.\" dhcp-eval.5
.\"
.\" Copyright (c) 1996-1999 Internet Software Consortium.
.\" Use is subject to license terms which appear in the file named
.\" ISC-LICENSE that should have accompanied this file when you
.\" received it. If a file named ISC-LICENSE did not accompany this
.\" file, or you are not sure the one you have is correct, you may
.\" obtain an applicable copy of the license at:
.\" Copyright (c) 1996-2001 Internet Software Consortium.
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\"
.\" http://www.isc.org/isc-license-1.0.html.
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. 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.
.\" 3. Neither the name of The Internet Software Consortium nor the names
.\" of its contributors may be used to endorse or promote products derived
.\" from this software without specific prior written permission.
.\"
.\" This file is part of the ISC DHCP distribution. The documentation
.\" associated with this file is listed in the file DOCUMENTATION,
.\" included in the top-level directory of this release.
.\" THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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.
.\"
.\" Support and other services are available for ISC products - see
.\" http://www.isc.org for more information.
.TH dhcpd-eval 5
.\" This software has been written for the Internet Software Consortium
.\" by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
.\" To learn more about the Internet Software Consortium, see
.\" ``http://www.isc.org/''. To learn more about Vixie Enterprises,
.\" see ``http://www.vix.com''. To learn more about Nominum, Inc., see
.\" ``http://www.nominum.com''.
.TH dhcp-eval 5
.SH NAME
dhcp-conditionals - ISC DHCP conditional evaluation
dhcp-eval - ISC DHCP conditional evaluation
.SH DESCRIPTION
The Internet Software Consortium DHCP client and server both provide
the ability to perform conditional behavior depending on the contents
@ -226,7 +245,13 @@ contents packet as in the \fBsubstring\fR operator.
.PP
.RS 0.25i
A string, enclosed in quotes, may be specified as a data expression,
and returns the text between the quotes, encoded in ASCII.
and returns the text between the quotes, encoded in ASCII. The
backslash ('\\') character is treated specially, as in C programming:
'\\t' means TAB, '\\r' means carriage return, '\\n' means newline, and
'\\b' means bell. Any octal value can be specified with '\\nnn',
where nnn is any positive octal number less than 0400. Any
hexadecimal value can be specified with '\xnn', where nn is any
positive hexadecimal number less than 0xff.
.RE
.PP
.I colon-seperated hexadecimal list
@ -339,6 +364,51 @@ the current time and the time that the lease expires.
Any number between zero and the maximum representable size may be
specified as a numeric expression.
.RE
.PP
.B client-state
.PP
.RS 0.25i
The current state of the client instance being processed. This is
only useful in DHCP client configuration files. Possible values are:
.TP 2
.I \(bu
Booting - DHCP client is in the INIT state, and does not yet have an
IP address. The next message transmitted will be a DHCPDISCOVER,
which will be broadcast.
.TP
.I \(bu
Reboot - DHCP client is in the INIT-REBOOT state. It has an IP
address, but is not yet using it. The next message to be transmitted
will be a DHCPREQUEST, which will be broadcast. If no response is
heard, the client will bind to its address and move to the BOUND state.
.TP
.I \(bu
Select - DHCP client is in the SELECTING state - it has received at
least one DHCPOFFER message, but is waiting to see if it may receive
other DHCPOFFER messages from other servers. No messages are sent in
the SELECTING state.
.TP
.I \(bu
Request - DHCP client is in the REQUESTING state - it has received at
least one DHCPOFFER message, and has chosen which one it will
request. The next message to be sent will be a DHCPREQUEST message,
which will be broadcast.
.TP
.I \(bu
Bound - DHCP client is in the BOUND state - it has an IP address. No
messages are transmitted in this state.
.TP
.I \(bu
Renew - DHCP client is in the RENEWING state - it has an IP address,
and is trying to contact the server to renew it. The next message to
be sent will be a DHCPREQUEST message, which will be unicast directly
to the server.
.TP
.I \(bu
Rebind - DHCP client is in the REBINDING state - it has an IP address,
and is trying to contact any server to renew it. The next message to
be sent will be a DHCPREQUEST, which will be broadcast.
.RE
.SH
FUNCTIONS
Functions may be defined with the \fBdefine\fR statement. A function

View File

@ -84,7 +84,7 @@
#ifndef lint
static char copyright[] =
"$Id: dlpi.c,v 1.1.1.8 2000/09/04 23:10:10 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
"$Id: dlpi.c,v 1.1.1.9 2001/04/02 21:56:55 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@ -130,15 +130,7 @@ static int strioctl PROTO ((int fd, int cmd, int timeout, int len, char *dp));
#define DLPI_MAXDLBUF 8192 /* Buffer size */
#define DLPI_MAXDLADDR 1024 /* Max address size */
#define DLPI_DEVDIR "/dev/" /* Device directory */
#define DLPI_DEFAULTSAP 0x0800 /* IP protocol */
static void dlpi_makeaddr PROTO ((unsigned char *physaddr, int physaddrlen,
unsigned char *sap, int saplen,
unsigned char *buf));
static void dlpi_parseaddr PROTO ((unsigned char *buf,
unsigned char *physaddr,
int physaddrlen, unsigned char *sap,
int saplen));
static int dlpiopen PROTO ((char *ifname));
static int dlpiunit PROTO ((char *ifname));
static int dlpiinforeq PROTO ((int fd));
@ -211,13 +203,10 @@ int if_register_dlpi (info)
log_fatal ("Can't open DLPI device for %s: %m", info -> name);
}
/*
* Get information about the provider.
*/
/*
* Submit a DL_INFO_REQ request, to find
* the dl_mac_type and dl_provider_style
* Submit a DL_INFO_REQ request, to find the dl_mac_type and
* dl_provider_style
*/
if (dlpiinforeq(sock) < 0 || dlpiinfoack(sock, (char *)buf) < 0) {
log_fatal ("Can't get DLPI MAC type for %s: %m", info -> name);
@ -235,11 +224,21 @@ int if_register_dlpi (info)
info -> hw_address.hbuf [0] = HTYPE_FDDI;
break;
default:
log_fatal ("%s: unknown DLPI MAC type %ld",
info -> name,
dlp -> info_ack.dl_mac_type);
log_fatal ("%s: unsupported DLPI MAC type %ld",
info -> name, dlp -> info_ack.dl_mac_type);
break;
}
/*
* copy the sap length and broadcast address of this interface
* to interface_info. This fixes nothing but seemed nicer than to
* assume -2 and ffffff.
*/
info -> dlpi_sap_length = dlp -> info_ack.dl_sap_length;
info -> dlpi_broadcast_addr.hlen =
dlp -> info_ack.dl_brdcst_addr_length;
memcpy (info -> dlpi_broadcast_addr.hbuf,
(char *)dlp + dlp -> info_ack.dl_brdcst_addr_offset,
dlp -> info_ack.dl_brdcst_addr_length);
}
if (dlp -> info_ack.dl_provider_style == DL_STYLE2) {
@ -258,7 +257,7 @@ int if_register_dlpi (info)
/*
* Bind to the IP service access point (SAP), connectionless (CLDLS).
*/
if (dlpibindreq (sock, DLPI_DEFAULTSAP, 0, DL_CLDLS, 0, 0) < 0
if (dlpibindreq (sock, ETHERTYPE_IP, 0, DL_CLDLS, 0, 0) < 0
|| dlpibindack (sock, (char *)buf) < 0) {
log_fatal ("Can't bind DLPI device for %s: %m", info -> name);
}
@ -404,6 +403,8 @@ void if_register_receive (info)
{
#ifdef USE_DLPI_PFMOD
struct packetfilt pf;
struct ip iphdr;
u_int16_t offset;
#endif
/* Open a DLPI device and hang it on this interface... */
@ -417,19 +418,18 @@ void if_register_receive (info)
pf.Pf_Priority = 0;
pf.Pf_FilterLen = 0;
#ifdef USE_DLPI_RAW
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + 6;
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT + ENF_CAND;
pf.Pf_Filter [pf.Pf_FilterLen++] = htons (ETHERTYPE_IP);
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT;
pf.Pf_Filter [pf.Pf_FilterLen++] = htons (IPPROTO_UDP);
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + 11;
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSH00FF + ENF_AND;
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_CAND;
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + 18;
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT + ENF_CAND;
pf.Pf_Filter [pf.Pf_FilterLen++] = htons (local_port);
#else
#if defined (USE_DLPI_RAW)
# define ETHER_H_PREFIX (14) /* sizeof (ethernet_header) */
/*
* ethertype == ETHERTYPE_IP
*/
offset = 12;
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND;
pf.Pf_Filter [pf.Pf_FilterLen++] = htons (ETHERTYPE_IP);
# else
# define ETHER_H_PREFIX (0)
# endif /* USE_DLPI_RAW */
/*
* The packets that will be received on this file descriptor
* will be IP packets (due to the SAP that was specified in
@ -439,22 +439,32 @@ void if_register_receive (info)
* to the local port. All offsets are relative to the start
* of an IP packet.
*/
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT;
pf.Pf_Filter [pf.Pf_FilterLen++] = htons (IPPROTO_UDP);
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + 4;
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSH00FF + ENF_AND;
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_CAND;
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + 11;
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT + ENF_CAND;
pf.Pf_Filter [pf.Pf_FilterLen++] = htons (local_port);
#endif
/*
* BOOTPS destination port
*/
offset = ETHER_H_PREFIX + sizeof (iphdr) + sizeof (u_int16_t);
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND;
pf.Pf_Filter [pf.Pf_FilterLen++] = local_port;
/*
* protocol should be udp. this is a byte compare, test for
* endianess.
*/
offset = ETHER_H_PREFIX + ((u_int8_t *)&(iphdr.ip_p) - (u_int8_t *)&iphdr);
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_AND;
pf.Pf_Filter [pf.Pf_FilterLen++] = htons (0x00FF);
pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND;
pf.Pf_Filter [pf.Pf_FilterLen++] = htons (IPPROTO_UDP);
/* Install the filter... */
if (strioctl (info -> rfdesc, PFIOCSETF, INFTIM,
sizeof (pf), (char *)&pf) < 0) {
log_fatal ("Can't set PFMOD receive filter on %s: %m", info -> name);
}
#endif
#endif /* USE_DLPI_PFMOD */
if (!quiet_interface_discovery)
log_info ("Listening on DLPI/%s/%s%s%s",
@ -509,14 +519,12 @@ ssize_t send_packet (interface, packet, raw, len, from, to, hto)
struct hardware *hto;
{
unsigned hbufp = 0;
double hh [16];
double hh [32];
double ih [1536 / sizeof (double)];
unsigned char *dbuf = (unsigned char *)ih;
unsigned dbuflen;
unsigned char sap [2];
unsigned char dstaddr [DLPI_MAXDLADDR];
unsigned addrlen;
int saplen;
int result;
int fudge;
@ -529,8 +537,11 @@ ssize_t send_packet (interface, packet, raw, len, from, to, hto)
/* Assemble the headers... */
#ifdef USE_DLPI_RAW
assemble_hw_header (interface, (unsigned char *)hh, &dbuflen, hto);
if (dbuflen > sizeof hh)
log_fatal ("send_packet: hh buffer too small.\n");
fudge = dbuflen % 4; /* IP header must be word-aligned. */
memcpy (dbuf + fudge, (unsigned char *)hh, dbuflen);
dbuflen += fudge;
#else
fudge = 0;
#endif
@ -545,34 +556,52 @@ ssize_t send_packet (interface, packet, raw, len, from, to, hto)
#ifdef USE_DLPI_RAW
result = write (interface -> wfdesc, dbuf + fudge, dbuflen - fudge);
#else
/* XXX: Assumes ethernet, with two byte SAP */
sap [0] = 0x08; /* ETHERTYPE_IP, high byte */
sap [1] = 0x0; /* ETHERTYPE_IP, low byte */
saplen = -2; /* -2 indicates a two byte SAP at the end
of the address */
/* Setup the destination address */
if (hto && hto -> hlen == interface -> hw_address.hlen) {
dlpi_makeaddr (&hto -> hbuf [1],
hto -> hlen - 1, sap, saplen, dstaddr);
} else {
/* XXX: Assumes broadcast addr is all ones */
/* Really should get the broadcast address as part of the
* dlpiinforeq, and store it somewhere in the interface structure.
*/
unsigned char bcast_ether [DLPI_MAXDLADDR];
/*
* Setup the destination address (DLSAP) in dstaddr
*
* If sap_length < 0 we must deliver the DLSAP as phys+sap.
* If sap_length > 0 we must deliver the DLSAP as sap+phys.
*
* sap = Service Access Point == ETHERTYPE_IP
* sap + datalink address is called DLSAP in dlpi speak.
*/
{ /* ENCODE DLSAP */
unsigned char phys [DLPI_MAXDLADDR];
unsigned char sap [4];
int sap_len = interface -> dlpi_sap_length;
int phys_len = interface -> hw_address.hlen - 1;
memset ((char *)bcast_ether, 0xFF,
interface -> hw_address.hlen - 1);
dlpi_makeaddr (bcast_ether, interface -> hw_address.hlen - 1,
sap, saplen, dstaddr);
}
addrlen = interface -> hw_address.hlen - 1 + ABS (saplen);
/* sap = htons (ETHERTYPE_IP) kludge */
memset (sap, 0, sizeof (sap));
# if (BYTE_ORDER == LITTLE_ENDIAN)
sap [0] = 0x00;
sap [1] = 0x08;
# else
sap [0] = 0x08;
sap [1] = 0x00;
# endif
if (hto && hto -> hlen == interface -> hw_address.hlen)
memcpy ( phys, (char *) &hto -> hbuf [1], phys_len);
else
memcpy ( phys, interface -> dlpi_broadcast_addr.hbuf,
interface -> dlpi_broadcast_addr.hlen);
if (sap_len < 0) {
memcpy ( dstaddr, phys, phys_len);
memcpy ( (char *) &dstaddr [phys_len], sap, ABS (sap_len));
}
else {
memcpy ( dstaddr, (void *) sap, sap_len);
memcpy ( (char *) &dstaddr [sap_len], phys, phys_len);
}
addrlen = phys_len + ABS (sap_len);
} /* ENCODE DLSAP */
/* Send the packet down the wire... */
result = dlpiunitdatareq (interface -> wfdesc, dstaddr, addrlen,
0, 0, dbuf, dbuflen);
#endif
#endif /* USE_DLPI_RAW */
if (result < 0)
log_error ("send_packet: %m");
return result;
@ -588,10 +617,8 @@ ssize_t receive_packet (interface, buf, len, from, hfrom)
struct hardware *hfrom;
{
unsigned char dbuf [1536];
unsigned char sap [2];
unsigned char srcaddr [DLPI_MAXDLADDR];
unsigned long srcaddrlen;
int saplen;
int flags = 0;
int length = 0;
int offset = 0;
@ -610,20 +637,36 @@ ssize_t receive_packet (interface, buf, len, from, hfrom)
return length;
}
#ifndef USE_DLPI_RAW
/* Copy sender info */
/* XXX: Assumes ethernet, where SAP comes at end of haddr */
saplen = -2;
if (hfrom && (srcaddrlen ==
ABS (saplen) + interface -> hw_address.hlen - 1)) {
hfrom -> hbuf [0] = interface -> hw_address.hbuf [0];
hfrom -> hlen = interface -> hw_address.hlen;
dlpi_parseaddr (srcaddr, &hfrom -> hbuf [1],
interface -> hw_address.hlen - 1, sap, saplen);
} else if (hfrom) {
memset (hfrom, '\0', sizeof *hfrom);
}
#endif
# if !defined (USE_DLPI_RAW)
/*
* Copy the sender's hw address into hfrom
* If sap_len < 0 the DLSAP is as phys+sap.
* If sap_len > 0 the DLSAP is as sap+phys.
*
* sap is discarded here.
*/
{ /* DECODE DLSAP */
int sap_len = interface -> dlpi_sap_length;
int phys_len = interface -> hw_address.hlen - 1;
if (hfrom && (srcaddrlen == ABS (sap_len) + phys_len )) {
hfrom -> hbuf [0] = interface -> hw_address.hbuf [0];
hfrom -> hlen = interface -> hw_address.hlen;
if (sap_len < 0) {
memcpy ((char *) &hfrom -> hbuf [1], srcaddr, phys_len);
}
else {
memcpy ((char *) &hfrom -> hbuf [1], (char *) &srcaddr [phys_len],
phys_len);
}
}
else if (hfrom) {
memset (hfrom, '\0', sizeof *hfrom);
}
} /* DECODE_DLSAP */
# endif /* !defined (USE_DLPI_RAW) */
/* Decode the IP and UDP headers... */
bufix = 0;
@ -677,45 +720,6 @@ ssize_t receive_packet (interface, buf, len, from, hfrom)
#define DLPI_MAXWAIT 15 /* Max timeout */
static void dlpi_makeaddr (physaddr, physaddrlen, sap, saplen, buf)
unsigned char *physaddr;
int physaddrlen;
unsigned char *sap;
int saplen;
unsigned char *buf;
{
/*
* If the saplen is negative, the SAP goes at the end of the address,
* otherwise it goes at the beginning.
*/
if (saplen >= 0) {
memcpy ((char *)buf, (char *)sap, saplen);
memcpy ((char *)&buf [saplen], (char *)physaddr, physaddrlen);
} else {
memcpy ((char *)buf, (char *)physaddr, physaddrlen);
memcpy ((char *)&buf [physaddrlen], (char *)sap, 0 - saplen);
}
}
static void dlpi_parseaddr (buf, physaddr, physaddrlen, sap, saplen)
unsigned char *buf;
unsigned char *physaddr;
int physaddrlen;
unsigned char *sap;
int saplen;
{
/*
* If the saplen is negative, the SAP is at the end of the address,
* otherwise it is at the beginning.
*/
if (saplen >= 0) {
memcpy ((char *)sap, (char *)buf, saplen);
memcpy ((char *)physaddr, (char *)&buf [saplen], physaddrlen);
} else {
memcpy ((char *)physaddr, (char *)buf, physaddrlen);
memcpy ((char *)sap, (char *)&buf [physaddrlen], 0 - saplen);
}
}
/*
* Parse an interface name and extract the unit number

View File

@ -43,17 +43,18 @@
#ifndef lint
static char copyright[] =
"$Id: execute.c,v 1.1.1.6 2000/10/17 15:08:12 taca Exp $ Copyright (c) 1998-2000 The Internet Software Consortium. All rights reserved.\n";
"$Id: execute.c,v 1.1.1.7 2001/04/02 21:56:55 mellon Exp $ Copyright (c) 1998-2000 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
#include <omapip/omapip_p.h>
int execute_statements (result, packet, lease, in_options, out_options, scope,
statements)
int execute_statements (result, packet, lease, client_state,
in_options, out_options, scope, statements)
struct binding_value **result;
struct packet *packet;
struct lease *lease;
struct client_state *client_state;
struct option_state *in_options;
struct option_state *out_options;
struct binding_scope **scope;
@ -84,8 +85,8 @@ int execute_statements (result, packet, lease, in_options, out_options, scope,
log_debug ("exec: statements");
#endif
status = execute_statements (result, packet, lease,
in_options, out_options,
scope,
client_state, in_options,
out_options, scope,
r -> data.statements);
#if defined (DEBUG_EXPRESSIONS)
log_debug ("exec: statements returns %d", status);
@ -140,7 +141,7 @@ int execute_statements (result, packet, lease, in_options, out_options, scope,
log_debug ("exec: switch");
#endif
status = (find_matching_case
(&e, packet, lease,
(&e, packet, lease, client_state,
in_options, out_options, scope,
r -> data.s_switch.expr,
r -> data.s_switch.statements));
@ -149,7 +150,7 @@ int execute_statements (result, packet, lease, in_options, out_options, scope,
#endif
if (status) {
if (!(execute_statements
(result, packet, lease,
(result, packet, lease, client_state,
in_options, out_options, scope, e))) {
executable_statement_dereference
(&e, MDL);
@ -166,7 +167,8 @@ int execute_statements (result, packet, lease, in_options, out_options, scope,
case if_statement:
status = (evaluate_boolean_expression
(&rc, packet, lease, in_options,
(&rc, packet,
lease, client_state, in_options,
out_options, scope, r -> data.ie.expr));
#if defined (DEBUG_EXPRESSIONS)
@ -178,7 +180,7 @@ int execute_statements (result, packet, lease, in_options, out_options, scope,
if (!status)
rc = 0;
if (!execute_statements
(result, packet, lease,
(result, packet, lease, client_state,
in_options, out_options, scope,
rc ? r -> data.ie.true : r -> data.ie.false))
return 0;
@ -187,7 +189,7 @@ int execute_statements (result, packet, lease, in_options, out_options, scope,
case eval_statement:
status = evaluate_expression
((struct binding_value **)0,
packet, lease, in_options,
packet, lease, client_state, in_options,
out_options, scope, r -> data.eval);
#if defined (DEBUG_EXPRESSIONS)
log_debug ("exec: evaluate: %s",
@ -197,7 +199,8 @@ int execute_statements (result, packet, lease, in_options, out_options, scope,
case return_statement:
status = evaluate_expression
(result, packet, lease, in_options,
(result, packet,
lease, client_state, in_options,
out_options, scope, r -> data.retval);
#if defined (DEBUG_EXPRESSIONS)
log_debug ("exec: return: %s",
@ -221,8 +224,11 @@ int execute_statements (result, packet, lease, in_options, out_options, scope,
return 1;
case supersede_option_statement:
case send_option_statement:
#if defined (DEBUG_EXPRESSIONS)
log_debug ("exec: supersede option %s.%s",
log_debug ("exec: %s option %s.%s",
(r -> op == supersede_option_statement
? "supersede" : "send"),
r -> data.option -> option -> universe -> name,
r -> data.option -> option -> name);
goto option_statement;
@ -299,9 +305,9 @@ int execute_statements (result, packet, lease, in_options, out_options, scope,
if (r -> op == set_statement) {
status = (evaluate_expression
(&binding -> value, packet,
lease, in_options,
out_options, scope,
r -> data.set.expr));
lease, client_state,
in_options, out_options,
scope, r -> data.set.expr));
} else {
if (!(binding_value_allocate
(&binding -> value, MDL))) {
@ -330,9 +336,6 @@ int execute_statements (result, packet, lease, in_options, out_options, scope,
break;
}
binding = find_binding (*scope, r -> data.unset);
#if defined (DEBUG_EXPRESSIONS)
log_debug ("exec: unset %s", r -> data.unset);
#endif
if (binding) {
if (binding -> value)
binding_value_dereference
@ -379,6 +382,7 @@ int execute_statements (result, packet, lease, in_options, out_options, scope,
if (ns && binding) {
status = (evaluate_expression
(&binding -> value, packet, lease,
client_state,
in_options, out_options,
scope, e -> data.set.expr));
binding -> next = ns -> bindings;
@ -400,6 +404,7 @@ int execute_statements (result, packet, lease, in_options, out_options, scope,
*scope, MDL);
execute_statements
(result, packet, lease,
client_state,
in_options, out_options,
&ns, e -> data.let.statements);
}
@ -410,7 +415,8 @@ int execute_statements (result, packet, lease, in_options, out_options, scope,
case log_statement:
memset (&ds, 0, sizeof ds);
status = (evaluate_data_expression
(&ds, packet, lease, in_options,
(&ds, packet,
lease, client_state, in_options,
out_options, scope, r -> data.log.expr));
#if defined (DEBUG_EXPRESSIONS)
@ -442,7 +448,8 @@ int execute_statements (result, packet, lease, in_options, out_options, scope,
break;
default:
log_fatal ("bogus statement type %d", r -> op);
log_error ("bogus statement type %d", r -> op);
break;
}
executable_statement_dereference (&r, MDL);
if (next) {
@ -461,11 +468,13 @@ int execute_statements (result, packet, lease, in_options, out_options, scope,
specific scopes, so we recursively traverse the scope list, executing
the most outer scope first. */
void execute_statements_in_scope (result, packet, lease, in_options,
out_options, scope, group, limiting_group)
void execute_statements_in_scope (result, packet,
lease, client_state, in_options, out_options,
scope, group, limiting_group)
struct binding_value **result;
struct packet *packet;
struct lease *lease;
struct client_state *client_state;
struct option_state *in_options;
struct option_state *out_options;
struct binding_scope **scope;
@ -507,11 +516,12 @@ void execute_statements_in_scope (result, packet, lease, in_options,
}
if (group -> next)
execute_statements_in_scope (result, packet, lease,
execute_statements_in_scope (result, packet,
lease, client_state,
in_options, out_options, scope,
group -> next, limiting_group);
execute_statements (result, packet, lease, in_options, out_options,
scope, group -> statements);
execute_statements (result, packet, lease, client_state, in_options,
out_options, scope, group -> statements);
}
/* Dereference or free any subexpressions of a statement being freed. */
@ -620,6 +630,7 @@ int executable_statement_dereference (ptr, file, line)
break;
case supersede_option_statement:
case send_option_statement:
case default_option_statement:
case append_option_statement:
case prepend_option_statement:
@ -773,6 +784,7 @@ void write_statements (file, statements, indent)
break;
case supersede_option_statement:
case send_option_statement:
s = "supersede";
goto option_statement;
@ -841,6 +853,40 @@ void write_statements (file, statements, indent)
col = token_print_indent (file, col, indent + 6,
" ", "", ";");
break;
case log_statement:
indent_spaces (file, indent);
fprintf (file, "log ");
col = token_print_indent (file, col, indent + 4,
"", "", "(");
switch (r -> data.log.priority) {
case log_priority_fatal:
col = token_print_indent
(file, col, indent + 4, "",
" ", "fatal,");
break;
case log_priority_error:
col = token_print_indent
(file, col, indent + 4, "",
" ", "error,");
break;
case log_priority_debug:
col = token_print_indent
(file, col, indent + 4, "",
" ", "debug,");
break;
case log_priority_info:
col = token_print_indent
(file, col, indent + 4, "",
" ", "info,");
break;
}
col = write_expression (file, r -> data.log.expr,
indent + 4, indent + 4, 0);
col = token_print_indent (file, col, indent + 4,
"", "", ");");
break;
default:
log_fatal ("bogus statement type %d\n", r -> op);
@ -856,6 +902,7 @@ void write_statements (file, statements, indent)
int find_matching_case (struct executable_statement **ep,
struct packet *packet, struct lease *lease,
struct client_state *client_state,
struct option_state *in_options,
struct option_state *out_options,
struct binding_scope **scope,
@ -873,14 +920,15 @@ int find_matching_case (struct executable_statement **ep,
memset (&cd, 0, sizeof cd);
status = (evaluate_data_expression (&ds, packet, lease,
in_options, out_options,
scope, expr));
client_state, in_options,
out_options, scope, expr));
if (status) {
for (s = stmt; s; s = s -> next) {
if (s -> op == case_statement) {
sub = (evaluate_data_expression
(&cd, packet, lease, in_options,
out_options, scope, s -> data.c_case));
(&cd, packet, lease, client_state,
in_options, out_options,
scope, s -> data.c_case));
if (sub && cd.len == ds.len &&
!memcmp (cd.data, ds.data, cd.len))
{
@ -898,6 +946,7 @@ int find_matching_case (struct executable_statement **ep,
} else {
unsigned long n, c;
status = evaluate_numeric_expression (&n, packet, lease,
client_state,
in_options, out_options,
scope, expr);
@ -905,8 +954,9 @@ int find_matching_case (struct executable_statement **ep,
for (s = stmt; s; s = s -> next) {
if (s -> op == case_statement) {
sub = (evaluate_numeric_expression
(&c, packet, lease, in_options,
out_options, scope, s -> data.c_case));
(&c, packet, lease, client_state,
in_options, out_options,
scope, s -> data.c_case));
if (sub && n == c) {
executable_statement_reference
(ep, s -> next, MDL);

View File

@ -4,7 +4,7 @@
responses. */
/*
* Copyright (c) 1996-2000 Internet Software Consortium.
* Copyright (c) 1996-2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -44,7 +44,7 @@
#ifndef lint
static char copyright[] =
"$Id: icmp.c,v 1.1.1.10 2000/10/17 15:08:12 taca Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
"$Id: icmp.c,v 1.1.1.11 2001/04/02 21:56:55 mellon Exp $ Copyright (c) 1996-2001 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@ -60,6 +60,11 @@ struct icmp_state {
static struct icmp_state *icmp_state;
static omapi_object_type_t *dhcp_type_icmp;
#if defined (TRACING)
trace_type_t *trace_icmp_input;
trace_type_t *trace_icmp_output;
#endif
/* Initialize the ICMP protocol. */
void icmp_startup (routep, handler)
@ -95,33 +100,48 @@ void icmp_startup (routep, handler)
new -> type = dhcp_type_icmp;
new -> icmp_handler = handler;
/* Get the protocol number (should be 1). */
proto = getprotobyname ("icmp");
if (proto)
protocol = proto -> p_proto;
#if defined (TRACING)
trace_icmp_input = trace_type_register ("icmp-input", (void *)0,
trace_icmp_input_input,
trace_icmp_input_stop, MDL);
trace_icmp_output = trace_type_register ("icmp-output", (void *)0,
trace_icmp_output_input,
trace_icmp_output_stop, MDL);
/* Get a raw socket for the ICMP protocol. */
new -> socket = socket (AF_INET, SOCK_RAW, protocol);
if (new -> socket < 0)
log_fatal ("unable to create icmp socket: %m");
/* If we're playing back a trace file, don't create the socket
or set up the callback. */
if (!trace_playback ()) {
#endif
/* Get the protocol number (should be 1). */
proto = getprotobyname ("icmp");
if (proto)
protocol = proto -> p_proto;
/* Get a raw socket for the ICMP protocol. */
new -> socket = socket (AF_INET, SOCK_RAW, protocol);
if (new -> socket < 0)
log_fatal ("unable to create icmp socket: %m");
#if defined (HAVE_SETFD)
if (fcntl (new -> socket, F_SETFD, 1) < 0)
log_error ("Can't set close-on-exec on icmp socket: %m");
if (fcntl (new -> socket, F_SETFD, 1) < 0)
log_error ("Can't set close-on-exec on icmp: %m");
#endif
/* Make sure it does routing... */
state = 0;
if (setsockopt (new -> socket, SOL_SOCKET, SO_DONTROUTE,
(char *)&state, sizeof state) < 0)
log_fatal ("Can't disable SO_DONTROUTE on ICMP socket: %m");
/* Make sure it does routing... */
state = 0;
if (setsockopt (new -> socket, SOL_SOCKET, SO_DONTROUTE,
(char *)&state, sizeof state) < 0)
log_fatal ("Can't disable SO_DONTROUTE on ICMP: %m");
result = omapi_register_io_object ((omapi_object_t *)new,
icmp_readsocket, 0,
icmp_echoreply, 0, 0);
if (result != ISC_R_SUCCESS)
log_fatal ("Can't register icmp handle: %s",
isc_result_totext (result));
result = omapi_register_io_object ((omapi_object_t *)new,
icmp_readsocket, 0,
icmp_echoreply, 0, 0);
if (result != ISC_R_SUCCESS)
log_fatal ("Can't register icmp handle: %s",
isc_result_totext (result));
#if defined (TRACING)
}
#endif
icmp_state = new;
}
@ -140,6 +160,9 @@ int icmp_echorequest (addr)
struct sockaddr_in to;
struct icmp icmp;
int status;
#if defined (TRACING)
trace_iov_t iov [2];
#endif
if (!icmp_state)
log_fatal ("ICMP protocol used before initialization.");
@ -166,14 +189,41 @@ int icmp_echorequest (addr)
icmp.icmp_cksum = wrapsum (checksum ((unsigned char *)&icmp,
sizeof icmp, 0));
/* Send the ICMP packet... */
status = sendto (icmp_state -> socket, (char *)&icmp, sizeof icmp, 0,
(struct sockaddr *)&to, sizeof to);
if (status < 0)
log_error ("icmp_echorequest %s: %m", inet_ntoa(to.sin_addr));
#if defined (TRACING)
if (trace_playback ()) {
char *buf = (char *)0;
unsigned buflen = 0;
if (status != sizeof icmp)
return 0;
/* Consume the ICMP event. */
status = trace_get_packet (&trace_icmp_output, &buflen, &buf);
if (status != ISC_R_SUCCESS)
log_error ("icmp_echorequest: %s",
isc_result_totext (status));
if (buf)
dfree (buf, MDL);
} else {
if (trace_record ()) {
iov [0].buf = (char *)addr;
iov [0].len = sizeof *addr;
iov [1].buf = (char *)&icmp;
iov [1].len = sizeof icmp;
trace_write_packet_iov (trace_icmp_output,
2, iov, MDL);
}
#endif
/* Send the ICMP packet... */
status = sendto (icmp_state -> socket,
(char *)&icmp, sizeof icmp, 0,
(struct sockaddr *)&to, sizeof to);
if (status < 0)
log_error ("icmp_echorequest %s: %m",
inet_ntoa(to.sin_addr));
if (status != sizeof icmp)
return 0;
#if defined (TRACING)
}
#endif
return 1;
}
@ -183,12 +233,15 @@ isc_result_t icmp_echoreply (h)
struct icmp *icfrom;
struct ip *ip;
struct sockaddr_in from;
unsigned char icbuf [1500];
u_int8_t icbuf [1500];
int status;
SOCKLEN_T sl;
int hlen, len;
struct iaddr ia;
struct icmp_state *state;
#if defined (TRACING)
trace_iov_t iov [2];
#endif
state = (struct icmp_state *)h;
@ -222,7 +275,53 @@ isc_result_t icmp_echoreply (h)
memcpy (ia.iabuf, &from.sin_addr, sizeof from.sin_addr);
ia.len = sizeof from.sin_addr;
#if defined (TRACING)
if (trace_record ()) {
ia.len = htonl(ia.len);
iov [0].buf = (char *)&ia;
iov [0].len = sizeof ia;
iov [1].buf = (char *)icbuf;
iov [1].len = len;
trace_write_packet_iov (trace_icmp_input, 2, iov, MDL);
ia.len = ntohl(ia.len);
}
#endif
(*state -> icmp_handler) (ia, icbuf, len);
}
return ISC_R_SUCCESS;
}
#if defined (TRACING)
void trace_icmp_input_input (trace_type_t *ttype, unsigned length, char *buf)
{
struct iaddr *ia;
unsigned len;
u_int8_t *icbuf;
ia = (struct iaddr *)buf;
ia->len = ntohl(ia->len);
icbuf = (u_int8_t *)(ia + 1);
if (icmp_state -> icmp_handler)
(*icmp_state -> icmp_handler) (*ia, icbuf,
(int)(length - sizeof ia));
}
void trace_icmp_input_stop (trace_type_t *ttype) { }
void trace_icmp_output_input (trace_type_t *ttype, unsigned length, char *buf)
{
struct icmp *icmp;
struct iaddr *ia;
if (length != (sizeof (*icmp) + (sizeof *ia))) {
log_error ("trace_icmp_output_input: data size mismatch %d:%d",
length, (int)((sizeof (*icmp)) + (sizeof *ia)));
return;
}
ia = (struct iaddr *)buf;
icmp = (struct icmp *)(ia + 1);
log_error ("trace_icmp_output_input: unsent ping to %s", piaddr (*ia));
}
void trace_icmp_output_stop (trace_type_t *ttype) { }
#endif /* TRACING */

View File

@ -44,7 +44,7 @@
#ifndef lint
static char copyright[] =
"$Id: nit.c,v 1.1.1.10 2000/10/17 15:08:15 taca Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
"$Id: nit.c,v 1.1.1.11 2001/04/02 21:56:56 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@ -314,7 +314,8 @@ ssize_t send_packet (interface, packet, raw, len, from, to, hto)
/* Start with the sockaddr struct... */
junk = (struct sockaddr *)&hh [0];
hbufp = ((unsigned char *)&junk -> sa_data [0]) - &buf [0];
hbufp = (((unsigned char *)&junk -> sa_data [0]) -
(unsigned char *)&hh[0]);
ibufp = 0;
/* Assemble the headers... */

View File

@ -3,7 +3,7 @@
Parser for /etc/resolv.conf file. */
/*
* Copyright (c) 1996-2000 Internet Software Consortium.
* Copyright (c) 1996-2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -43,7 +43,7 @@
#ifndef lint
static char copyright[] =
"$Id: resolv.c,v 1.1.1.3 2000/04/22 07:11:37 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
"$Id: resolv.c,v 1.1.1.4 2001/04/02 21:56:59 mellon Exp $ Copyright (c) 1996-2001 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@ -74,8 +74,8 @@ void read_resolv_conf (parse_time)
cfile -> eol_token = 1;
do {
token = next_token (&val, cfile);
if (token == EOF)
token = next_token (&val, (unsigned *)0, cfile);
if (token == END_OF_FILE)
break;
else if (token == EOL)
continue;
@ -106,14 +106,15 @@ void read_resolv_conf (parse_time)
dn = (char *)0;
}
nd -> rcdate = parse_time;
token = peek_token (&val, cfile);
token = peek_token (&val,
(unsigned *)0, cfile);
} while (token != EOL);
if (token != EOL) {
parse_warn (cfile,
"junk after domain declaration");
skip_to_semi (cfile);
}
token = next_token (&val, cfile);
token = next_token (&val, (unsigned *)0, cfile);
} else if (token == NAMESERVER) {
struct name_server *ns, **sp;
struct iaddr iaddr;
@ -149,7 +150,7 @@ void read_resolv_conf (parse_time)
} else
skip_to_semi (cfile); /* Ignore what we don't grok. */
} while (1);
token = next_token (&val, cfile); /* Clear the peek buffer */
token = next_token (&val, (unsigned *)0, cfile);
/* Lose servers that are no longer in /etc/resolv.conf. */
sl = (struct name_server *)0;

File diff suppressed because it is too large Load Diff

View File

@ -24,19 +24,18 @@ OBJ = dhcpctl.o callback.o remote.o
MAN = dhcpctl.3
HDRS = dhcpctl.h
DEBUG = -g
INCLUDES = $(BINDINC) -I$(TOP)/includes
CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS)
DHCPCTLLIBS = libdhcpctl.a ../common/libdhcp.a $(BINDLIB) \
../omapip/libomapi.a ../dst/libdst.a
all: libdhcpctl.a svtest cltest $(CATMANPAGES)
all: libdhcpctl.a omshell cltest $(CATMANPAGES)
svtest: test.o libdhcpctl.a ../omapip/libomapi.a $(BINDLIB)
$(CC) $(DEBUG) $(LFLAGS) -o svtest test.o libdhcpctl.a \
../omapip/libomapi.a $(BINDLIB) $(LIBS)
omshell: omshell.o $(DHCPCTLLIBS)
$(CC) $(DEBUG) $(LFLAGS) -o omshell omshell.o $(DHCPCTLLIBS) $(LIBS)
cltest: cltest.o libdhcpctl.a ../omapip/libomapi.a $(BINDLIB)
$(CC) $(DEBUG) $(LFLAGS) -o cltest cltest.o libdhcpctl.a \
../omapip/libomapi.a $(BINDLIB) $(LIBS)
cltest: cltest.o $(DHCPCTLLIBS)
$(CC) $(DEBUG) $(LFLAGS) -o cltest cltest.o $(DHCPCTLLIBS) $(LIBS)
libdhcpctl.a: $(OBJ)
rm -f libdhcpctl.a
@ -78,7 +77,7 @@ distclean: realclean
-rm -f Makefile
links:
@for foo in $(SRC) $(MAN) test.c cltest.c $(HDRS); do \
@for foo in $(SRC) $(MAN) omshell.c cltest.c $(HDRS); do \
if [ ! -b $$foo ]; then \
rm -f $$foo; \
fi; \

View File

@ -0,0 +1,355 @@
/* omshell.c
Examine and modify omapi objects. */
/*
* Copyright (c) 2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of The Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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.
*
* This software has been written for the Internet Software Consortium
* by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
* To learn more about the Internet Software Consortium, see
* ``http://www.isc.org/''. To learn more about Vixie Enterprises,
* see ``http://www.vix.com''. To learn more about Nominum, Inc., see
* ``http://www.nominum.com''.
*/
#include <time.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <isc/result.h>
#include "dhcpctl.h"
#include "dhcpd.h"
/* Fixups */
isc_result_t find_class (struct class **c, const char *n, const char *f, int l)
{
return 0;
}
int parse_allow_deny (struct option_cache **oc, struct parse *cfile, int flag)
{
return 0;
}
void dhcp (struct packet *packet) { }
void bootp (struct packet *packet) { }
int check_collection (struct packet *p, struct lease *l, struct collection *c)
{
return 0;
}
void classify (struct packet *packet, struct class *class) { }
static void usage (char *s) {
fprintf (stderr,
"Usage: %s [-n <username>] [-p <password>] "
"[-a <algorithm>]\n", s);
exit (1);
}
static void check (isc_result_t status, const char *func) {
if (status != ISC_R_SUCCESS) {
fprintf (stderr, "%s: %s\n", func, isc_result_totext (status));
exit (1);
}
}
int main (int argc, char **argv, char **envp)
{
isc_result_t status, waitstatus;
dhcpctl_handle connection;
dhcpctl_handle authenticator;
dhcpctl_handle oh;
dhcpctl_data_string cid, ip_addr;
dhcpctl_data_string result, groupname, identifier;
const char *name = 0, *pass = 0, *algorithm = "hmac-md5";
int i, j;
int port = 7911;
const char *server = "127.0.0.1";
struct parse *cfile;
enum dhcp_token token;
const char *val;
char buf[1024];
char s1[1024];
for (i = 1; i < argc; i++) {
if (!strcmp (argv[i], "-n")) {
if (++i == argc)
usage(argv[0]);
name = argv[i];
} else if (!strcmp (argv[i], "-p")) {
if (++i == argc)
usage(argv[0]);
pass = argv[i];
} else if (!strcmp (argv[i], "-a")) {
if (++i == argc)
usage(argv[0]);
algorithm = argv[i];
} else if (!strcmp (argv[i], "-s")) {
if (++i == argc)
usage(argv[0]);
server = argv[i];
} else if (!strcmp (argv[i], "-P")) {
if (++i == argc)
usage(argv[0]);
port = atoi (argv[i]);
} else {
usage(argv[0]);
}
}
if ((name || pass) && !(name && pass))
usage(argv[0]);
status = dhcpctl_initialize ();
if (status != ISC_R_SUCCESS) {
fprintf (stderr, "dhcpctl_initialize: %s\n",
isc_result_totext (status));
exit (1);
}
authenticator = dhcpctl_null_handle;
if (name) {
status = dhcpctl_new_authenticator (&authenticator,
name, algorithm, pass,
strlen (pass) + 1);
if (status != ISC_R_SUCCESS) {
fprintf (stderr, "Cannot create authenticator: %s\n",
isc_result_totext (status));
exit (1);
}
}
memset (&connection, 0, sizeof connection);
status = dhcpctl_connect (&connection, server, port, authenticator);
if (status != ISC_R_SUCCESS) {
fprintf (stderr, "dhcpctl_connect: %s\n",
isc_result_totext (status));
exit (1);
}
memset (&oh, 0, sizeof oh);
do {
printf ("obj: ");
if (oh == NULL) {
printf ("<null>\n");
} else {
dhcpctl_remote_object_t *r =
(dhcpctl_remote_object_t *)oh;
omapi_generic_object_t *g =
(omapi_generic_object_t *)(r -> inner);
if (r -> rtype -> type != omapi_datatype_string) {
printf ("?\n");
} else {
printf ("%.*s\n",
(int)(r -> rtype -> u . buffer . len),
r -> rtype -> u . buffer . value);
}
for (i = 0; i < g -> nvalues; i++) {
omapi_value_t *v = g -> values [i];
printf ("%.*s = ", (int)v -> name -> len,
v -> name -> value);
switch (v -> value -> type) {
case omapi_datatype_int:
printf ("%d\n",
v -> value -> u . integer);
break;
case omapi_datatype_string:
printf ("\"%.*s\"\n",
(int)v -> value -> u.buffer.len,
v -> value -> u.buffer.value);
break;
case omapi_datatype_data:
printf ("%s\n",
print_hex_1
(v -> value -> u.buffer.len,
v -> value -> u.buffer.value,
60));
break;
case omapi_datatype_object:
printf ("<obj>\n");
break;
}
}
}
fputs ("> ", stdout);
fflush (stdout);
if (fgets (buf, sizeof(buf), stdin) == NULL)
break;
status = new_parse (&cfile, 0, buf, strlen(buf), "<STDIN>");
check(status, "new_parse()");
token = next_token (&val, (unsigned *)0, cfile);
switch (token) {
default:
parse_warn (cfile, "unknown token: %s", val);
break;
case END_OF_FILE:
break;
case TOKEN_HELP:
case '?':
printf ("Commands:\n");
printf (" new <object-type>\n");
printf (" set <name> = <value>\n");
printf (" create\n");
printf (" open\n");
break;
case TOKEN_NEW:
token = next_token (&val, (unsigned *)0, cfile);
if ((!is_identifier (token) && token != STRING) ||
next_token (NULL,
(unsigned *)0, cfile) != END_OF_FILE)
{
printf ("usage: new <object-type>\n");
break;
}
if (oh) {
printf ("an object is already open.\n");
break;
}
status = dhcpctl_new_object (&oh, connection, val);
if (status != ISC_R_SUCCESS) {
printf ("can't create object: %s\n",
isc_result_totext (status));
break;
}
break;
case TOKEN_CLOSE:
if (next_token (NULL,
(unsigned *)0, cfile) != END_OF_FILE) {
printf ("usage: close\n");
}
omapi_object_dereference (&oh, MDL);
break;
case TOKEN_SET:
token = next_token (&val, (unsigned *)0, cfile);
if ((!is_identifier (token) && token != STRING) ||
next_token (NULL, (unsigned *)0, cfile) != '=')
{
printf ("usage: set <name> = <value>\n");
break;
}
if (oh == NULL) {
printf ("no open object.\n");
break;
}
s1[0] = '\0';
strncat (s1, val, sizeof(s1)-1);
token = next_token (&val, (unsigned *)0, cfile);
switch (token) {
case STRING:
dhcpctl_set_string_value (oh, val, s1);
break;
case NUMBER:
dhcpctl_set_int_value (oh, atoi (val), s1);
break;
default:
printf ("invalid value.\n");
}
break;
case TOKEN_CREATE:
case TOKEN_OPEN:
if (next_token (NULL,
(unsigned *)0, cfile) != END_OF_FILE) {
printf ("usage: %s\n", val);
}
i = 0;
if (token == TOKEN_CREATE)
i = DHCPCTL_CREATE | DHCPCTL_EXCL;
status = dhcpctl_open_object (oh, connection, i);
if (status == ISC_R_SUCCESS)
status = dhcpctl_wait_for_completion
(oh, &waitstatus);
if (status == ISC_R_SUCCESS)
status = waitstatus;
if (status != ISC_R_SUCCESS) {
printf ("can't open object: %s\n",
isc_result_totext (status));
break;
}
break;
case UPDATE:
if (next_token (NULL, (unsigned *)0,
cfile) != END_OF_FILE) {
printf ("usage: %s\n", val);
}
status = dhcpctl_object_update(connection, oh);
if (status == ISC_R_SUCCESS)
status = dhcpctl_wait_for_completion
(oh, &waitstatus);
if (status == ISC_R_SUCCESS)
status = waitstatus;
if (status != ISC_R_SUCCESS) {
printf ("can't update object: %s\n",
isc_result_totext (status));
break;
}
break;
}
} while (1);
exit (0);
}

View File

@ -74,12 +74,26 @@ dhcpctl_status dhcpctl_new_authenticator (dhcpctl_handle *h,
}
strcpy (key -> name, name);
key -> algorithm = dmalloc (strlen (algorithm) + 1, MDL);
if (!key -> algorithm) {
omapi_auth_key_dereference (&key, MDL);
return ISC_R_NOMEMORY;
/* If the algorithm name isn't an FQDN, tack on the
.SIG-ALG.REG.NET. domain. */
if (strchr (algorithm, '.') == 0) {
static char add[] = ".SIG-ALG.REG.INT.";
key -> algorithm = dmalloc (strlen (algorithm) +
sizeof (add), MDL);
if (!key -> algorithm) {
omapi_auth_key_dereference (&key, MDL);
return ISC_R_NOMEMORY;
}
strcpy (key -> algorithm, algorithm);
strcat (key -> algorithm, add);
} else {
key -> algorithm = dmalloc (strlen (algorithm) + 1, MDL);
if (!key -> algorithm) {
omapi_auth_key_dereference (&key, MDL);
return ISC_R_NOMEMORY;
}
strcpy (key -> algorithm, algorithm);
}
strcpy (key -> algorithm, algorithm);
status = omapi_data_string_new (&key -> key, secret_len, MDL);
if (status != ISC_R_SUCCESS) {

View File

@ -0,0 +1,55 @@
# Makefile.dist
#
# Copyright (c) 1996-2000 Internet Software Consortium.
# Use is subject to license terms which appear in the file named
# ISC-LICENSE that should have accompanied this file when you
# received it. If a file named ISC-LICENSE did not accompany this
# file, or you are not sure the one you have is correct, you may
# obtain an applicable copy of the license at:
#
# http://www.isc.org/isc-license-1.0.html.
#
# This file is part of the ISC DHCP distribution. The documentation
# associated with this file is listed in the file DOCUMENTATION,
# included in the top-level directory of this release.
#
# Support and other services are available for ISC products - see
# http://www.isc.org for more information.
#
SRC = dst_support.c dst_api.c hmac_link.c md5_dgst.c base64.c prandom.c
OBJ = dst_support.o dst_api.o hmac_link.o md5_dgst.o base64.o prandom.o
HDRS = dst_internal.h md5.h md5_locl.h
INCLUDES = $(BINDINC) -I$(TOP)/includes
CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS) -DHMAC_MD5 -DMINIRES_LIB
all: libdst.a
install:
libdst.a: $(OBJ)
rm -f dst.a
ar cruv libdst.a $(OBJ)
$(RANLIB) libdst.a
depend:
$(MKDEP) $(INCLUDES) $(PREDEFINES) $(SRC)
clean:
-rm -f $(OBJ) libdst.a
realclean: clean
-rm -f *~ $(CATMANPAGES) $(SEDMANPAGES)
distclean: realclean
-rm -f Makefile
links:
@for foo in $(SRC) $(MAN) $(HDRS); do \
if [ ! -b $$foo ]; then \
rm -f $$foo; \
fi; \
ln -s $(TOP)/dst/$$foo $$foo; \
done
# Dependencies (semi-automatically-generated)

319
usr.sbin/dhcp/dst/base64.c Normal file
View File

@ -0,0 +1,319 @@
/*
* Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
/*
* Portions Copyright (c) 1995 by International Business Machines, Inc.
*
* International Business Machines, Inc. (hereinafter called IBM) grants
* permission under its copyrights to use, copy, modify, and distribute this
* Software with or without fee, provided that the above copyright notice and
* all paragraphs of this notice appear in all copies, and that the name of IBM
* not be used in connection with the marketing of any product incorporating
* the Software or modifications thereof, without specific, written prior
* permission.
*
* To the extent it has a right to do so, IBM grants an immunity from suit
* under its patents, if any, for the use, sale or manufacture of products to
* the extent that such products are used for performing Domain Name System
* dynamic updates in TCP/IP networks by means of the Software. No immunity is
* granted for any product per se or for any other function of any product.
*
* THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
* DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
* IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#if !defined(LINT) && !defined(CODECENTER)
static const char rcsid[] = "$Id: base64.c,v 1.1.1.1 2001/04/02 21:57:02 mellon Exp $";
#endif /* not lint */
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include "minires/minires.h"
#include "arpa/nameser.h"
#define Assert(Cond) if (!(Cond)) abort()
static const char Base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char Pad64 = '=';
/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
The following encoding technique is taken from RFC 1521 by Borenstein
and Freed. It is reproduced here in a slightly edited form for
convenience.
A 65-character subset of US-ASCII is used, enabling 6 bits to be
represented per printable character. (The extra 65th character, "=",
is used to signify a special processing function.)
The encoding process represents 24-bit groups of input bits as output
strings of 4 encoded characters. Proceeding from left to right, a
24-bit input group is formed by concatenating 3 8-bit input groups.
These 24 bits are then treated as 4 concatenated 6-bit groups, each
of which is translated into a single digit in the base64 alphabet.
Each 6-bit group is used as an index into an array of 64 printable
characters. The character referenced by the index is placed in the
output string.
Table 1: The Base64 Alphabet
Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y
Special processing is performed if fewer than 24 bits are available
at the end of the data being encoded. A full encoding quantum is
always completed at the end of a quantity. When fewer than 24 input
bits are available in an input group, zero bits are added (on the
right) to form an integral number of 6-bit groups. Padding at the
end of the data is performed using the '=' character.
Since all base64 input is an integral number of octets, only the
-------------------------------------------------
following cases can arise:
(1) the final quantum of encoding input is an integral
multiple of 24 bits; here, the final unit of encoded
output will be an integral multiple of 4 characters
with no "=" padding,
(2) the final quantum of encoding input is exactly 8 bits;
here, the final unit of encoded output will be two
characters followed by two "=" padding characters, or
(3) the final quantum of encoding input is exactly 16 bits;
here, the final unit of encoded output will be three
characters followed by one "=" padding character.
*/
int
b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) {
size_t datalength = 0;
u_char input[3];
u_char output[4];
size_t i;
while (2 < srclength) {
input[0] = *src++;
input[1] = *src++;
input[2] = *src++;
srclength -= 3;
output[0] = input[0] >> 2;
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
output[3] = input[2] & 0x3f;
Assert(output[0] < 64);
Assert(output[1] < 64);
Assert(output[2] < 64);
Assert(output[3] < 64);
if (datalength + 4 > targsize)
return (-1);
target[datalength++] = Base64[output[0]];
target[datalength++] = Base64[output[1]];
target[datalength++] = Base64[output[2]];
target[datalength++] = Base64[output[3]];
}
/* Now we worry about padding. */
if (0 != srclength) {
/* Get what's left. */
input[0] = input[1] = input[2] = '\0';
for (i = 0; i < srclength; i++)
input[i] = *src++;
output[0] = input[0] >> 2;
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
Assert(output[0] < 64);
Assert(output[1] < 64);
Assert(output[2] < 64);
if (datalength + 4 > targsize)
return (-1);
target[datalength++] = Base64[output[0]];
target[datalength++] = Base64[output[1]];
if (srclength == 1)
target[datalength++] = Pad64;
else
target[datalength++] = Base64[output[2]];
target[datalength++] = Pad64;
}
if (datalength >= targsize)
return (-1);
target[datalength] = '\0'; /* Returned value doesn't count \0. */
return (datalength);
}
/* skips all whitespace anywhere.
converts characters, four at a time, starting at (or after)
src from base - 64 numbers into three 8 bit bytes in the target area.
it returns the number of data bytes stored at the target, or -1 on error.
*/
int
b64_pton(src, target, targsize)
char const *src;
u_char *target;
size_t targsize;
{
int tarindex, state, ch;
char *pos;
state = 0;
tarindex = 0;
while ((ch = *src++) != '\0') {
if (isspace(ch)) /* Skip whitespace anywhere. */
continue;
if (ch == Pad64)
break;
pos = strchr(Base64, ch);
if (pos == 0) /* A non-base64 character. */
return (-1);
switch (state) {
case 0:
if (target) {
if ((size_t)tarindex >= targsize)
return (-1);
target[tarindex] = (pos - Base64) << 2;
}
state = 1;
break;
case 1:
if (target) {
if ((size_t)tarindex + 1 >= targsize)
return (-1);
target[tarindex] |= (pos - Base64) >> 4;
target[tarindex+1] = ((pos - Base64) & 0x0f)
<< 4 ;
}
tarindex++;
state = 2;
break;
case 2:
if (target) {
if ((size_t)tarindex + 1 >= targsize)
return (-1);
target[tarindex] |= (pos - Base64) >> 2;
target[tarindex+1] = ((pos - Base64) & 0x03)
<< 6;
}
tarindex++;
state = 3;
break;
case 3:
if (target) {
if ((size_t)tarindex >= targsize)
return (-1);
target[tarindex] |= (pos - Base64);
}
tarindex++;
state = 0;
break;
default:
abort();
}
}
/*
* We are done decoding Base-64 chars. Let's see if we ended
* on a byte boundary, and/or with erroneous trailing characters.
*/
if (ch == Pad64) { /* We got a pad char. */
ch = *src++; /* Skip it, get next. */
switch (state) {
case 0: /* Invalid = in first position */
case 1: /* Invalid = in second position */
return (-1);
case 2: /* Valid, means one byte of info */
/* Skip any number of spaces. */
for ((void)NULL; ch != '\0'; ch = *src++)
if (!isspace(ch))
break;
/* Make sure there is another trailing = sign. */
if (ch != Pad64)
return (-1);
ch = *src++; /* Skip the = */
/* Fall through to "single trailing =" case. */
/* FALLTHROUGH */
case 3: /* Valid, means two bytes of info */
/*
* We know this char is an =. Is there anything but
* whitespace after it?
*/
for ((void)NULL; ch != '\0'; ch = *src++)
if (!isspace(ch))
return (-1);
/*
* Now make sure for cases 2 and 3 that the "extra"
* bits that slopped past the last full byte were
* zeros. If we don't check them, they become a
* subliminal channel.
*/
if (target && target[tarindex] != 0)
return (-1);
}
} else {
/*
* We ended by seeing the end of the string. Make sure we
* have no partial bytes lying around.
*/
if (state != 0)
return (-1);
}
return (tarindex);
}

1081
usr.sbin/dhcp/dst/dst_api.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,160 @@
#ifndef DST_INTERNAL_H
#define DST_INTERNAL_H
/*
* Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
*
* Permission to use, copy modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
*/
#include <limits.h>
#include <sys/param.h>
#ifndef PATH_MAX
# ifdef POSIX_PATH_MAX
# define PATH_MAX POSIX_PATH_MAX
# else
# define PATH_MAX 255 /* this is the value of POSIX_PATH_MAX */
# endif
#endif
typedef struct dst_key {
char *dk_key_name; /* name of the key */
int dk_key_size; /* this is the size of the key in bits */
int dk_proto; /* what protocols this key can be used for */
int dk_alg; /* algorithm number from key record */
unsigned dk_flags; /* and the flags of the public key */
unsigned dk_id; /* identifier of the key */
void *dk_KEY_struct; /* pointer to key in crypto pkg fmt */
struct dst_func *dk_func; /* point to cryptto pgk specific function table */
} DST_KEY;
#define HAS_DST_KEY
#include <isc/dst.h>
/*
* define what crypto systems are supported for RSA,
* BSAFE is prefered over RSAREF; only one can be set at any time
*/
#if defined(BSAFE) && defined(RSAREF)
# error "Cannot have both BSAFE and RSAREF defined"
#endif
/* Declare dst_lib specific constants */
#define KEY_FILE_FORMAT "1.2"
/* suffixes for key file names */
#define PRIVATE_KEY "private"
#define PUBLIC_KEY "key"
/* error handling */
#ifdef REPORT_ERRORS
#define EREPORT(str) printf str
#else
#define EREPORT(str)
#endif
/* use our own special macro to FRRE memory */
#ifndef SAFE_FREE
#define SAFE_FREE(a) if(a != NULL){memset(a,0, sizeof(*a)); free(a); a=NULL;}
#define SAFE_FREE2(a,s) if (a != NULL && s > 0){memset(a,0, s);free(a); a=NULL;}
#endif
typedef struct dst_func {
int (*sign)(const int mode, DST_KEY *key, void **context,
const u_int8_t *data, const unsigned len,
u_int8_t *signature, const unsigned sig_len);
int (*verify)(const int mode, DST_KEY *key, void **context,
const u_int8_t *data, const unsigned len,
const u_int8_t *signature, const unsigned sig_len);
int (*compare)(const DST_KEY *key1, const DST_KEY *key2);
int (*generate)(DST_KEY *key, int parms);
void *(*destroy)(void *key);
/* conversion functions */
int (*to_dns_key)(const DST_KEY *key, u_int8_t *out,
const unsigned out_len);
int (*from_dns_key)(DST_KEY *key, const u_int8_t *str,
const unsigned str_len);
int (*to_file_fmt)(const DST_KEY *key, char *out,
const unsigned out_len);
int (*from_file_fmt)(DST_KEY *key, const char *out,
const unsigned out_len);
} dst_func;
extern dst_func *dst_t_func[DST_MAX_ALGS];
extern const char *key_file_fmt_str;
extern const char *dst_path;
#ifndef DST_HASH_SIZE
#define DST_HASH_SIZE 20 /* RIPEMD160 and SHA-1 are 20 bytes MD5 is 16 */
#endif
#if 0
int dst_bsafe_init(void);
int dst_rsaref_init(void);
#endif
int dst_hmac_md5_init(void);
#if 0
int dst_cylink_init(void);
int dst_eay_dss_init(void);
#endif
/* support functions */
/* base64 to bignum conversion routines */
int dst_s_conv_bignum_u8_to_b64( char *out_buf, const unsigned out_len,
const char *header,
const u_int8_t *bin_data,
const unsigned bin_len);
int dst_s_conv_bignum_b64_to_u8( const char **buf, u_int8_t *loc,
const unsigned loclen) ;
/* from higher level support routines */
int dst_s_calculate_bits( const u_int8_t *str, const int max_bits);
int dst_s_verify_str( const char **buf, const char *str);
/* conversion between dns names and key file names */
size_t dst_s_filename_length( const char *name, const char *suffix);
int dst_s_build_filename( char *filename, const char *name,
unsigned id, int alg, const char *suffix,
size_t filename_length);
FILE *dst_s_fopen (const char *filename, const char *mode, unsigned perm);
/* from file prandom.c */
int dst_s_random( u_int8_t *output, unsigned size);
int dst_s_semi_random( u_int8_t *output, unsigned size);
u_int32_t dst_s_quick_random( int inc);
void dst_s_quick_random_set( u_int32_t val, u_int32_t cnt);
/*
* read and write network byte order into u_int?_t
* all of these should be retired
*/
u_int16_t dst_s_get_int16( const u_int8_t *buf);
void dst_s_put_int16( u_int8_t *buf, const u_int16_t val);
u_int32_t dst_s_get_int32( const u_int8_t *buf);
void dst_s_put_int32( u_int8_t *buf, const u_int32_t val);
#ifdef DUMP
# undef DUMP
# define DUMP(a,b,c,d) dst_s_dump(a,b,c,d)
#else
# define DUMP(a,b,c,d)
#endif
#endif /* DST_INTERNAL_H */

View File

@ -0,0 +1,463 @@
static const char rcsid[] = "$Header: /cvsroot/src/usr.sbin/dhcp/dst/Attic/dst_support.c,v 1.1.1.1 2001/04/02 21:57:03 mellon Exp $";
/*
* Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
*
* Permission to use, copy modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
*/
#include <stdio.h>
#include <unistd.h>
#include <memory.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "minires/minires.h"
#include "arpa/nameser.h"
#include "dst_internal.h"
/*
* dst_s_conv_bignum_u8_to_b64
* This function converts binary data stored as a u_char[] to a
* base-64 string. Leading zeroes are discarded. If a header is
* supplied, it is prefixed to the input prior to encoding. The
* output is \n\0 terminated (the \0 is not included in output length).
* Parameters
* out_buf binary data to convert
* header character string to prefix to the output (label)
* bin_data binary data
* bin_len size of binary data
* Return
* -1 not enough space in output work area
* 0 no output
* >0 number of bytes written to output work area
*/
int
dst_s_conv_bignum_u8_to_b64(char *out_buf, const unsigned out_len,
const char *header, const u_char *bin_data,
const unsigned bin_len)
{
const u_char *bp = bin_data;
char *op = out_buf;
unsigned lenh = 0, len64 = 0;
unsigned local_in_len = bin_len;
unsigned local_out_len = out_len;
if (bin_data == NULL) /* no data no */
return (0);
if (out_buf == NULL || out_len <= 0) /* no output_work area */
return (-1);
/* suppress leading \0 */
for (; (*bp == 0x0) && (local_in_len > 0); local_in_len--)
bp++;
if (header) { /* add header to output string */
lenh = strlen(header);
if (lenh < out_len)
memcpy(op, header, lenh);
else
return (-1);
local_out_len -= lenh;
op += lenh;
}
len64 = b64_ntop(bp, local_in_len, op, local_out_len - 2);
if (len64 < 0)
return (-1);
op += len64++;
*(op++) = '\n'; /* put CR in the output */
*op = '\0'; /* make sure output is 0 terminated */
return (lenh + len64);
}
/*
* dst_s_verify_str()
* Validate that the input string(*str) is at the head of the input
* buffer(**buf). If so, move the buffer head pointer (*buf) to
* the first byte of data following the string(*str).
* Parameters
* buf Input buffer.
* str Input string.
* Return
* 0 *str is not the head of **buff
* 1 *str is the head of **buff, *buf is is advanced to
* the tail of **buf.
*/
int
dst_s_verify_str(const char **buf, const char *str)
{
unsigned b, s;
if (*buf == NULL) /* error checks */
return (0);
if (str == NULL || *str == '\0')
return (1);
b = strlen(*buf); /* get length of strings */
s = strlen(str);
if (s > b || strncmp(*buf, str, s)) /* check if same */
return (0); /* not a match */
(*buf) += s; /* advance pointer */
return (1);
}
/*
* dst_s_conv_bignum_b64_to_u8
* Read a line of base-64 encoded string from the input buffer,
* convert it to binary, and store it in an output area. The
* input buffer is read until reaching a newline marker or the
* end of the buffer. The binary data is stored in the last X
* number of bytes of the output area where X is the size of the
* binary output. If the operation is successful, the input buffer
* pointer is advanced. This procedure does not do network to host
* byte order conversion.
* Parameters
* buf Pointer to encoded input string. Pointer is updated if
* function is successfull.
* loc Output area.
* loclen Size in bytes of output area.
* Return
* >0 Return = number of bytes of binary data stored in loc.
* 0 Failure.
*/
int
dst_s_conv_bignum_b64_to_u8(const char **buf,
u_char *loc, const unsigned loclen)
{
unsigned blen;
char *bp;
u_char bstr[RAW_KEY_SIZE];
if (buf == NULL || *buf == NULL) { /* error checks */
EREPORT(("dst_s_conv_bignum_b64_to_u8: null input buffer.\n"));
return (0);
}
bp = strchr(*buf, '\n'); /* find length of input line */
if (bp != NULL)
*bp = (u_char) NULL;
blen = b64_pton(*buf, bstr, sizeof(bstr));
if (blen <= 0) {
EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is null.\n"));
return (0);
}
else if (loclen < blen) {
EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is longer than output buffer.\n"));
return (0);
}
if (bp)
*buf = bp; /* advancing buffer past \n */
memset(loc, 0, loclen - blen); /* clearing unused output area */
memcpy(loc + loclen - blen, bstr, blen); /* write last blen bytes */
return (blen);
}
/*
* dst_s_calculate_bits
* Given a binary number represented in a u_char[], determine
* the number of significant bits used.
* Parameters
* str An input character string containing a binary number.
* max_bits The maximum possible significant bits.
* Return
* N The number of significant bits in str.
*/
int
dst_s_calculate_bits(const u_char *str, const int max_bits)
{
const u_char *p = str;
u_char i, j = 0x80;
int bits;
for (bits = max_bits; *p == 0x00 && bits > 0; p++)
bits -= 8;
for (i = *p; (i & j) != j; j >>= 1)
bits--;
return (bits);
}
/*
* calculates a checksum used in kmt for a id.
* takes an array of bytes and a length.
* returns a 16 bit checksum.
*/
u_int16_t
dst_s_id_calc(const u_char *key, const unsigned keysize)
{
u_int32_t ac;
const u_char *kp = key;
unsigned size = keysize;
if (!key)
return 0;
for (ac = 0; size > 1; size -= 2, kp += 2)
ac += ((*kp) << 8) + *(kp + 1);
if (size > 0)
ac += ((*kp) << 8);
ac += (ac >> 16) & 0xffff;
return (ac & 0xffff);
}
/*
* dst_s_dns_key_id() Function to calculated DNSSEC footprint from KEY reocrd
* rdata (all of record)
* Input:
* dns_key_rdata: the raw data in wire format
* rdata_len: the size of the input data
* Output:
* the key footprint/id calcuated from the key data
*/
u_int16_t
dst_s_dns_key_id(const u_char *dns_key_rdata, const unsigned rdata_len)
{
unsigned key_data = 4;
if (!dns_key_rdata || (rdata_len < key_data))
return 0;
/* check the extended parameters bit in the DNS Key RR flags */
if (dst_s_get_int16(dns_key_rdata) & DST_EXTEND_FLAG)
key_data += 2;
/* compute id */
if (dns_key_rdata[3] == KEY_RSA) /* Algorithm RSA */
return dst_s_get_int16((const u_char *)
&dns_key_rdata[rdata_len - 3]);
else
/* compute a checksum on the key part of the key rr */
return dst_s_id_calc(&dns_key_rdata[key_data],
(rdata_len - key_data));
}
/*
* dst_s_get_int16
* This routine extracts a 16 bit integer from a two byte character
* string. The character string is assumed to be in network byte
* order and may be unaligned. The number returned is in host order.
* Parameter
* buf A two byte character string.
* Return
* The converted integer value.
*/
u_int16_t
dst_s_get_int16(const u_char *buf)
{
register u_int16_t a = 0;
a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1]));
return (a);
}
/*
* dst_s_get_int32
* This routine extracts a 32 bit integer from a four byte character
* string. The character string is assumed to be in network byte
* order and may be unaligned. The number returned is in host order.
* Parameter
* buf A four byte character string.
* Return
* The converted integer value.
*/
u_int32_t
dst_s_get_int32(const u_char *buf)
{
register u_int32_t a = 0;
a = ((u_int32_t)(buf[0] << 24)) | ((u_int32_t)(buf[1] << 16)) |
((u_int32_t)(buf[2] << 8)) | ((u_int32_t)(buf[3]));
return (a);
}
/*
* dst_s_put_int16
* Take a 16 bit integer and store the value in a two byte
* character string. The integer is assumed to be in network
* order and the string is returned in host order.
*
* Parameters
* buf Storage for a two byte character string.
* val 16 bit integer.
*/
void
dst_s_put_int16(u_int8_t *buf, const u_int16_t val)
{
buf[0] = (u_int8_t)(val >> 8);
buf[1] = (u_int8_t)(val);
}
/*
* dst_s_put_int32
* Take a 32 bit integer and store the value in a four byte
* character string. The integer is assumed to be in network
* order and the string is returned in host order.
*
* Parameters
* buf Storage for a four byte character string.
* val 32 bit integer.
*/
void
dst_s_put_int32(u_int8_t *buf, const u_int32_t val)
{
buf[0] = (u_int8_t)(val >> 24);
buf[1] = (u_int8_t)(val >> 16);
buf[2] = (u_int8_t)(val >> 8);
buf[3] = (u_int8_t)(val);
}
/*
* dst_s_filename_length
*
* This function returns the number of bytes needed to hold the
* filename for a key file. '/', '\' and ':' are not allowed.
* form: K<keyname>+<alg>+<id>.<suffix>
*
* Returns 0 if the filename would contain either '\', '/' or ':'
*/
size_t
dst_s_filename_length(const char *name, const char *suffix)
{
if (name == NULL)
return (0);
if (strrchr(name, '\\'))
return (0);
if (strrchr(name, '/'))
return (0);
if (strrchr(name, ':'))
return (0);
if (suffix == NULL)
return (0);
if (strrchr(suffix, '\\'))
return (0);
if (strrchr(suffix, '/'))
return (0);
if (strrchr(suffix, ':'))
return (0);
return (1 + strlen(name) + 6 + strlen(suffix));
}
/*
* dst_s_build_filename ()
* Builds a key filename from the key name, it's id, and a
* suffix. '\', '/' and ':' are not allowed. fA filename is of the
* form: K<keyname><id>.<suffix>
* form: K<keyname>+<alg>+<id>.<suffix>
*
* Returns -1 if the conversion fails:
* if the filename would be too long for space allotted
* if the filename would contain a '\', '/' or ':'
* Returns 0 on success
*/
int
dst_s_build_filename(char *filename, const char *name, unsigned id,
int alg, const char *suffix, size_t filename_length)
{
unsigned my_id;
if (filename == NULL)
return (-1);
memset(filename, 0, filename_length);
if (name == NULL)
return (-1);
if (suffix == NULL)
return (-1);
if (filename_length < 1 + strlen(name) + 4 + 6 + 1 + strlen(suffix))
return (-1);
my_id = id;
sprintf(filename, "K%s+%03d+%05d.%s", name, alg, my_id,
(const char *) suffix);
if (strrchr(filename, '/'))
return (-1);
if (strrchr(filename, '\\'))
return (-1);
if (strrchr(filename, ':'))
return (-1);
return (0);
}
/*
* dst_s_fopen ()
* Open a file in the dst_path directory. If perm is specified, the
* file is checked for existence first, and not opened if it exists.
* Parameters
* filename File to open
* mode Mode to open the file (passed directly to fopen)
* perm File permission, if creating a new file.
* Returns
* NULL Failure
* NON-NULL (FILE *) of opened file.
*/
FILE *
dst_s_fopen(const char *filename, const char *mode, unsigned perm)
{
FILE *fp;
char pathname[PATH_MAX];
unsigned plen = sizeof(pathname);
if (*dst_path != '\0') {
strcpy(pathname, dst_path);
plen -= strlen(pathname);
}
else
pathname[0] = '\0';
if (plen > strlen(filename))
strncpy(&pathname[PATH_MAX - plen], filename, plen-1);
else
return (NULL);
fp = fopen(pathname, mode);
if (perm)
chmod(pathname, perm);
return (fp);
}
#if 0
void
dst_s_dump(const int mode, const u_char *data, const int size,
const char *msg)
{
if (size > 0) {
#ifdef LONG_TEST
static u_char scratch[1000];
int n ;
n = b64_ntop(data, scratch, size, sizeof(scratch));
printf("%s: %x %d %s\n", msg, mode, n, scratch);
#else
printf("%s,%x %d\n", msg, mode, size);
#endif
}
}
#endif

View File

@ -0,0 +1,494 @@
#ifdef HMAC_MD5
#ifndef LINT
static const char rcsid[] = "$Header: /cvsroot/src/usr.sbin/dhcp/dst/Attic/hmac_link.c,v 1.1.1.1 2001/04/02 21:57:03 mellon Exp $";
#endif
/*
* Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
*
* Permission to use, copy modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
*/
/*
* This file contains an implementation of the HMAC-MD5 algorithm.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <sys/param.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "minires/minires.h"
#include "arpa/nameser.h"
#include "dst_internal.h"
#ifdef USE_MD5
# include "md5.h"
# ifndef _MD5_H_
# define _MD5_H_ 1 /* make sure we do not include rsaref md5.h file */
# endif
#endif
#define HMAC_LEN 64
#define HMAC_IPAD 0x36
#define HMAC_OPAD 0x5c
#define MD5_LEN 16
typedef struct hmackey {
u_char hk_ipad[64], hk_opad[64];
} HMAC_Key;
/**************************************************************************
* dst_hmac_md5_sign
* Call HMAC signing functions to sign a block of data.
* There are three steps to signing, INIT (initialize structures),
* UPDATE (hash (more) data), FINAL (generate a signature). This
* routine performs one or more of these steps.
* Parameters
* mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
* priv_key key to use for signing.
* context the context to be used in this digest
* data data to be signed.
* len length in bytes of data.
* signature location to store signature.
* sig_len size of the signature location
* returns
* N Success on SIG_MODE_FINAL = returns signature length in bytes
* 0 Success on SIG_MODE_INIT and UPDATE
* <0 Failure
*/
static int
dst_hmac_md5_sign(const int mode, DST_KEY *d_key, void **context,
const u_char *data, const unsigned len,
u_char *signature, const unsigned sig_len)
{
HMAC_Key *key;
int sign_len = 0;
MD5_CTX *ctx = NULL;
if (mode & SIG_MODE_INIT)
ctx = (MD5_CTX *) malloc(sizeof(*ctx));
else if (context)
ctx = (MD5_CTX *) *context;
if (ctx == NULL)
return (-1);
if (d_key == NULL || d_key->dk_KEY_struct == NULL)
return (-1);
key = (HMAC_Key *) d_key->dk_KEY_struct;
if (mode & SIG_MODE_INIT) {
MD5Init(ctx);
MD5Update(ctx, key->hk_ipad, HMAC_LEN);
}
if ((mode & SIG_MODE_UPDATE) && (data && len > 0))
MD5Update(ctx, (const unsigned char *)data, len);
if (mode & SIG_MODE_FINAL) {
if (signature == NULL || sig_len < MD5_LEN)
return (SIGN_FINAL_FAILURE);
MD5Final(signature, ctx);
/* perform outer MD5 */
MD5Init(ctx);
MD5Update(ctx, key->hk_opad, HMAC_LEN);
MD5Update(ctx, signature, MD5_LEN);
MD5Final(signature, ctx);
sign_len = MD5_LEN;
SAFE_FREE(ctx);
}
else {
if (context == NULL)
return (-1);
*context = (void *) ctx;
}
return (sign_len);
}
/**************************************************************************
* dst_hmac_md5_verify()
* Calls HMAC verification routines. There are three steps to
* verification, INIT (initialize structures), UPDATE (hash (more) data),
* FINAL (generate a signature). This routine performs one or more of
* these steps.
* Parameters
* mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
* dkey key to use for verify.
* data data signed.
* len length in bytes of data.
* signature signature.
* sig_len length in bytes of signature.
* returns
* 0 Success
* <0 Failure
*/
static int
dst_hmac_md5_verify(const int mode, DST_KEY *d_key, void **context,
const u_char *data, const unsigned len,
const u_char *signature, const unsigned sig_len)
{
HMAC_Key *key;
MD5_CTX *ctx = NULL;
if (mode & SIG_MODE_INIT)
ctx = (MD5_CTX *) malloc(sizeof(*ctx));
else if (context)
ctx = (MD5_CTX *) *context;
if (ctx == NULL)
return (-1);
if (d_key == NULL || d_key->dk_KEY_struct == NULL)
return (-1);
key = (HMAC_Key *) d_key->dk_KEY_struct;
if (mode & SIG_MODE_INIT) {
MD5Init(ctx);
MD5Update(ctx, key->hk_ipad, HMAC_LEN);
}
if ((mode & SIG_MODE_UPDATE) && (data && len > 0))
MD5Update(ctx, (const unsigned char *)data, len);
if (mode & SIG_MODE_FINAL) {
u_char digest[MD5_LEN];
if (signature == NULL || key == NULL || sig_len != MD5_LEN)
return (VERIFY_FINAL_FAILURE);
MD5Final(digest, ctx);
/* perform outer MD5 */
MD5Init(ctx);
MD5Update(ctx, key->hk_opad, HMAC_LEN);
MD5Update(ctx, digest, MD5_LEN);
MD5Final(digest, ctx);
SAFE_FREE(ctx);
if (memcmp(digest, signature, MD5_LEN) != 0)
return (VERIFY_FINAL_FAILURE);
}
else {
if (context == NULL)
return (-1);
*context = (void *) ctx;
}
return (0);
}
/**************************************************************************
* dst_buffer_to_hmac_md5
* Converts key from raw data to an HMAC Key
* This function gets in a pointer to the data
* Parameters
* hkey the HMAC key to be filled in
* key the key in raw format
* keylen the length of the key
* Return
* 0 Success
* <0 Failure
*/
static int
dst_buffer_to_hmac_md5(DST_KEY *dkey, const u_char *key, const unsigned keylen)
{
int i;
HMAC_Key *hkey = NULL;
MD5_CTX ctx;
unsigned local_keylen = keylen;
if (dkey == NULL || key == NULL || keylen < 0)
return (-1);
if ((hkey = (HMAC_Key *) malloc(sizeof(HMAC_Key))) == NULL)
return (-2);
memset(hkey->hk_ipad, 0, sizeof(hkey->hk_ipad));
memset(hkey->hk_opad, 0, sizeof(hkey->hk_opad));
/* if key is longer than HMAC_LEN bytes reset it to key=MD5(key) */
if (keylen > HMAC_LEN) {
u_char tk[MD5_LEN];
MD5Init(&ctx);
MD5Update(&ctx, (const unsigned char *)key, keylen);
MD5Final(tk, &ctx);
memset((void *) &ctx, 0, sizeof(ctx));
key = tk;
local_keylen = MD5_LEN;
}
/* start out by storing key in pads */
memcpy(hkey->hk_ipad, key, local_keylen);
memcpy(hkey->hk_opad, key, local_keylen);
/* XOR key with hk_ipad and opad values */
for (i = 0; i < HMAC_LEN; i++) {
hkey->hk_ipad[i] ^= HMAC_IPAD;
hkey->hk_opad[i] ^= HMAC_OPAD;
}
dkey->dk_key_size = local_keylen;
dkey->dk_KEY_struct = (void *) hkey;
return (1);
}
/**************************************************************************
* dst_hmac_md5_key_to_file_format
* Encodes an HMAC Key into the portable file format.
* Parameters
* hkey HMAC KEY structure
* buff output buffer
* buff_len size of output buffer
* Return
* 0 Failure - null input hkey
* -1 Failure - not enough space in output area
* N Success - Length of data returned in buff
*/
static int
dst_hmac_md5_key_to_file_format(const DST_KEY *dkey, char *buff,
const unsigned buff_len)
{
char *bp;
int i;
unsigned len, b_len, key_len;
u_char key[HMAC_LEN];
HMAC_Key *hkey;
if (dkey == NULL || dkey->dk_KEY_struct == NULL)
return (0);
if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str))
return (-1); /* no OR not enough space in output area */
hkey = (HMAC_Key *) dkey->dk_KEY_struct;
memset(buff, 0, buff_len); /* just in case */
/* write file header */
sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_HMAC_MD5, "HMAC");
bp = (char *) strchr(buff, '\0');
b_len = buff_len - (bp - buff);
memset(key, 0, HMAC_LEN);
for (i = 0; i < HMAC_LEN; i++)
key[i] = hkey->hk_ipad[i] ^ HMAC_IPAD;
for (i = HMAC_LEN - 1; i >= 0; i--)
if (key[i] != 0)
break;
key_len = i + 1;
strcat(bp, "Key: ");
bp += strlen("Key: ");
b_len = buff_len - (bp - buff);
len = b64_ntop(key, key_len, bp, b_len);
if (len < 0)
return (-1);
bp += len;
*(bp++) = '\n';
*bp = '\0';
b_len = buff_len - (bp - buff);
return (buff_len - b_len);
}
/**************************************************************************
* dst_hmac_md5_key_from_file_format
* Converts contents of a key file into an HMAC key.
* Parameters
* hkey structure to put key into
* buff buffer containing the encoded key
* buff_len the length of the buffer
* Return
* n >= 0 Foot print of the key converted
* n < 0 Error in conversion
*/
static int
dst_hmac_md5_key_from_file_format(DST_KEY *dkey, const char *buff,
const unsigned buff_len)
{
const char *p = buff, *eol;
u_char key[HMAC_LEN+1]; /* b64_pton needs more than 64 bytes do decode
* it should probably be fixed rather than doing
* this
*/
u_char *tmp;
unsigned key_len, len;
if (dkey == NULL)
return (-2);
if (buff == NULL)
return (-1);
memset(key, 0, sizeof(key));
if (!dst_s_verify_str(&p, "Key: "))
return (-3);
eol = strchr(p, '\n');
if (eol == NULL)
return (-4);
len = eol - p;
tmp = malloc(len + 2);
memcpy(tmp, p, len);
*(tmp + len) = 0x0;
key_len = b64_pton((char *)tmp, key, HMAC_LEN+1); /* see above */
SAFE_FREE2(tmp, len + 2);
if (dst_buffer_to_hmac_md5(dkey, key, key_len) < 0) {
return (-6);
}
return (0);
}
/*
* dst_hmac_md5_to_dns_key()
* function to extract hmac key from DST_KEY structure
* intput:
* in_key: HMAC-MD5 key
* output:
* out_str: buffer to write ot
* out_len: size of output buffer
* returns:
* number of bytes written to output buffer
*/
static int
dst_hmac_md5_to_dns_key(const DST_KEY *in_key, u_char *out_str,
const unsigned out_len)
{
HMAC_Key *hkey;
int i;
if (in_key == NULL || in_key->dk_KEY_struct == NULL ||
out_len <= in_key->dk_key_size || out_str == NULL)
return (-1);
hkey = (HMAC_Key *) in_key->dk_KEY_struct;
for (i = 0; i < in_key->dk_key_size; i++)
out_str[i] = hkey->hk_ipad[i] ^ HMAC_IPAD;
return (i);
}
/**************************************************************************
* dst_hmac_md5_compare_keys
* Compare two keys for equality.
* Return
* 0 The keys are equal
* NON-ZERO The keys are not equal
*/
static int
dst_hmac_md5_compare_keys(const DST_KEY *key1, const DST_KEY *key2)
{
HMAC_Key *hkey1 = (HMAC_Key *) key1->dk_KEY_struct;
HMAC_Key *hkey2 = (HMAC_Key *) key2->dk_KEY_struct;
return memcmp(hkey1->hk_ipad, hkey2->hk_ipad, HMAC_LEN);
}
/**************************************************************************
* dst_hmac_md5_free_key_structure
* Frees all (none) dynamically allocated structures in hkey
*/
static void *
dst_hmac_md5_free_key_structure(void *key)
{
HMAC_Key *hkey = key;
SAFE_FREE(hkey);
return (NULL);
}
/***************************************************************************
* dst_hmac_md5_generate_key
* Creates a HMAC key of size size with a maximum size of 63 bytes
* generating a HMAC key larger than 63 bytes makes no sense as that key
* is digested before use.
*/
static int
dst_hmac_md5_generate_key(DST_KEY *key, const int nothing)
{
u_char *buff;
int n;
unsigned size, len;
if (key == NULL || key->dk_alg != KEY_HMAC_MD5)
return (0);
size = (key->dk_key_size + 7) / 8; /* convert to bytes */
if (size <= 0)
return(0);
len = size > 64 ? 64 : size;
buff = malloc(len+8);
n = dst_random(DST_RAND_SEMI, len, buff);
n += dst_random(DST_RAND_KEY, len, buff);
if (n <= len) { /* failed getting anything */
SAFE_FREE2(buff, len);
return (-1);
}
n = dst_buffer_to_hmac_md5(key, buff, len);
SAFE_FREE2(buff, len);
if (n <= 0)
return (n);
return (1);
}
/*
* dst_hmac_md5_init() Function to answer set up function pointers for HMAC
* related functions
*/
int
dst_hmac_md5_init()
{
if (dst_t_func[KEY_HMAC_MD5] != NULL)
return (1);
dst_t_func[KEY_HMAC_MD5] = malloc(sizeof(struct dst_func));
if (dst_t_func[KEY_HMAC_MD5] == NULL)
return (0);
memset(dst_t_func[KEY_HMAC_MD5], 0, sizeof(struct dst_func));
dst_t_func[KEY_HMAC_MD5]->sign = dst_hmac_md5_sign;
dst_t_func[KEY_HMAC_MD5]->verify = dst_hmac_md5_verify;
dst_t_func[KEY_HMAC_MD5]->compare = dst_hmac_md5_compare_keys;
dst_t_func[KEY_HMAC_MD5]->generate = dst_hmac_md5_generate_key;
dst_t_func[KEY_HMAC_MD5]->destroy = dst_hmac_md5_free_key_structure;
dst_t_func[KEY_HMAC_MD5]->to_dns_key = dst_hmac_md5_to_dns_key;
dst_t_func[KEY_HMAC_MD5]->from_dns_key = dst_buffer_to_hmac_md5;
dst_t_func[KEY_HMAC_MD5]->to_file_fmt = dst_hmac_md5_key_to_file_format;
dst_t_func[KEY_HMAC_MD5]->from_file_fmt = dst_hmac_md5_key_from_file_format;
return (1);
}
#else
int
dst_hmac_md5_init(){
return (0);
}
#endif

101
usr.sbin/dhcp/dst/md5.h Normal file
View File

@ -0,0 +1,101 @@
/* crypto/md/md5.h */
/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#ifndef HEADER_MD5_H
#define HEADER_MD5_H
#ifdef __cplusplus
extern "C" {
#endif
#define MD5_CBLOCK 64
#define MD5_LBLOCK 16
#define MD5_BLOCK 16
#define MD5_LAST_BLOCK 56
#define MD5_LENGTH_BLOCK 8
#define MD5_DIGEST_LENGTH 16
typedef struct MD5state_st
{
unsigned long A,B,C,D;
unsigned long Nl,Nh;
unsigned long data[MD5_LBLOCK];
int num;
} MD5_CTX;
#ifndef NOPROTO
void MD5_Init(MD5_CTX *c);
void MD5_Update(MD5_CTX *c, const unsigned char *data, unsigned long len);
void MD5_Final(unsigned char *md, MD5_CTX *c);
unsigned char *MD5(unsigned char *d, unsigned long n, unsigned char *md);
#else
void MD5_Init();
void MD5_Update();
void MD5_Final();
unsigned char *MD5();
#endif
/* to provide backward compatabilty to RSAREF calls ogud@tis.com 1997/11/14 */
#define MD5Init(c) MD5_Init(c)
#define MD5Update(c,data, len) MD5_Update(c,data,len)
#define MD5Final(md, c) MD5_Final(md, c)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,373 @@
/* crypto/md/md5_dgst.c */
/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "md5_locl.h"
#include "minires/minires.h"
#ifdef USE_MD5 /* Added by ogud@tis.com 1998/1/26 */
const char *MD5_version="MD5 part of SSLeay 0.8.1 19-Jul-1997";
/* Implemented from RFC1321 The MD5 Message-Digest Algorithm
*/
#define INIT_DATA_A (unsigned long)0x67452301L
#define INIT_DATA_B (unsigned long)0xefcdab89L
#define INIT_DATA_C (unsigned long)0x98badcfeL
#define INIT_DATA_D (unsigned long)0x10325476L
#ifndef NOPROTO
static void md5_block(MD5_CTX *c, unsigned long *p);
#else
static void md5_block();
#endif
void MD5_Init(c)
MD5_CTX *c;
{
c->A=INIT_DATA_A;
c->B=INIT_DATA_B;
c->C=INIT_DATA_C;
c->D=INIT_DATA_D;
c->Nl=0;
c->Nh=0;
c->num=0;
}
void MD5_Update(c, data, len)
MD5_CTX *c;
const register unsigned char *data;
unsigned long len;
{
register ULONG *p;
int sw,sc;
ULONG l;
if (len == 0) return;
l=(c->Nl+(len<<3))&0xffffffffL;
/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
* Wei Dai <weidai@eskimo.com> for pointing it out. */
if (l < c->Nl) /* overflow */
c->Nh++;
c->Nh+=(len>>29);
c->Nl=l;
if (c->num != 0)
{
p=c->data;
sw=c->num>>2;
sc=c->num&0x03;
if ((c->num+len) >= MD5_CBLOCK)
{
l= p[sw];
p_c2l(data,l,sc);
p[sw++]=l;
for (; sw<MD5_LBLOCK; sw++)
{
c2l(data,l);
p[sw]=l;
}
len-=(MD5_CBLOCK-c->num);
md5_block(c,p);
c->num=0;
/* drop through and do the rest */
}
else
{
int ew,ec;
c->num+=(int)len;
if ((sc+len) < 4) /* ugly, add char's to a word */
{
l= p[sw];
p_c2l_p(data,l,sc,len);
p[sw]=l;
}
else
{
ew=(c->num>>2);
ec=(c->num&0x03);
l= p[sw];
p_c2l(data,l,sc);
p[sw++]=l;
for (; sw < ew; sw++)
{ c2l(data,l); p[sw]=l; }
if (ec)
{
c2l_p(data,l,ec);
p[sw]=l;
}
}
return;
}
}
/* we now can process the input data in blocks of MD5_CBLOCK
* chars and save the leftovers to c->data. */
p=c->data;
while (len >= MD5_CBLOCK)
{
#if defined(L_ENDIAN) || defined(B_ENDIAN)
memcpy(p,data,MD5_CBLOCK);
data+=MD5_CBLOCK;
#ifdef B_ENDIAN
for (sw=(MD5_LBLOCK/4); sw; sw--)
{
Endian_Reverse32(p[0]);
Endian_Reverse32(p[1]);
Endian_Reverse32(p[2]);
Endian_Reverse32(p[3]);
p+=4;
}
#endif
#else
for (sw=(MD5_LBLOCK/4); sw; sw--)
{
c2l(data,l); *(p++)=l;
c2l(data,l); *(p++)=l;
c2l(data,l); *(p++)=l;
c2l(data,l); *(p++)=l;
}
#endif
p=c->data;
md5_block(c,p);
len-=MD5_CBLOCK;
}
sc=(int)len;
c->num=sc;
if (sc)
{
sw=sc>>2; /* words to copy */
#ifdef L_ENDIAN
p[sw]=0;
memcpy(p,data,sc);
#else
sc&=0x03;
for ( ; sw; sw--)
{ c2l(data,l); *(p++)=l; }
c2l_p(data,l,sc);
*p=l;
#endif
}
}
static void md5_block(c, X)
MD5_CTX *c;
register ULONG *X;
{
register ULONG A,B,C,D;
A=c->A;
B=c->B;
C=c->C;
D=c->D;
/* Round 0 */
R0(A,B,C,D,X[ 0], 7,0xd76aa478L);
R0(D,A,B,C,X[ 1],12,0xe8c7b756L);
R0(C,D,A,B,X[ 2],17,0x242070dbL);
R0(B,C,D,A,X[ 3],22,0xc1bdceeeL);
R0(A,B,C,D,X[ 4], 7,0xf57c0fafL);
R0(D,A,B,C,X[ 5],12,0x4787c62aL);
R0(C,D,A,B,X[ 6],17,0xa8304613L);
R0(B,C,D,A,X[ 7],22,0xfd469501L);
R0(A,B,C,D,X[ 8], 7,0x698098d8L);
R0(D,A,B,C,X[ 9],12,0x8b44f7afL);
R0(C,D,A,B,X[10],17,0xffff5bb1L);
R0(B,C,D,A,X[11],22,0x895cd7beL);
R0(A,B,C,D,X[12], 7,0x6b901122L);
R0(D,A,B,C,X[13],12,0xfd987193L);
R0(C,D,A,B,X[14],17,0xa679438eL);
R0(B,C,D,A,X[15],22,0x49b40821L);
/* Round 1 */
R1(A,B,C,D,X[ 1], 5,0xf61e2562L);
R1(D,A,B,C,X[ 6], 9,0xc040b340L);
R1(C,D,A,B,X[11],14,0x265e5a51L);
R1(B,C,D,A,X[ 0],20,0xe9b6c7aaL);
R1(A,B,C,D,X[ 5], 5,0xd62f105dL);
R1(D,A,B,C,X[10], 9,0x02441453L);
R1(C,D,A,B,X[15],14,0xd8a1e681L);
R1(B,C,D,A,X[ 4],20,0xe7d3fbc8L);
R1(A,B,C,D,X[ 9], 5,0x21e1cde6L);
R1(D,A,B,C,X[14], 9,0xc33707d6L);
R1(C,D,A,B,X[ 3],14,0xf4d50d87L);
R1(B,C,D,A,X[ 8],20,0x455a14edL);
R1(A,B,C,D,X[13], 5,0xa9e3e905L);
R1(D,A,B,C,X[ 2], 9,0xfcefa3f8L);
R1(C,D,A,B,X[ 7],14,0x676f02d9L);
R1(B,C,D,A,X[12],20,0x8d2a4c8aL);
/* Round 2 */
R2(A,B,C,D,X[ 5], 4,0xfffa3942L);
R2(D,A,B,C,X[ 8],11,0x8771f681L);
R2(C,D,A,B,X[11],16,0x6d9d6122L);
R2(B,C,D,A,X[14],23,0xfde5380cL);
R2(A,B,C,D,X[ 1], 4,0xa4beea44L);
R2(D,A,B,C,X[ 4],11,0x4bdecfa9L);
R2(C,D,A,B,X[ 7],16,0xf6bb4b60L);
R2(B,C,D,A,X[10],23,0xbebfbc70L);
R2(A,B,C,D,X[13], 4,0x289b7ec6L);
R2(D,A,B,C,X[ 0],11,0xeaa127faL);
R2(C,D,A,B,X[ 3],16,0xd4ef3085L);
R2(B,C,D,A,X[ 6],23,0x04881d05L);
R2(A,B,C,D,X[ 9], 4,0xd9d4d039L);
R2(D,A,B,C,X[12],11,0xe6db99e5L);
R2(C,D,A,B,X[15],16,0x1fa27cf8L);
R2(B,C,D,A,X[ 2],23,0xc4ac5665L);
/* Round 3 */
R3(A,B,C,D,X[ 0], 6,0xf4292244L);
R3(D,A,B,C,X[ 7],10,0x432aff97L);
R3(C,D,A,B,X[14],15,0xab9423a7L);
R3(B,C,D,A,X[ 5],21,0xfc93a039L);
R3(A,B,C,D,X[12], 6,0x655b59c3L);
R3(D,A,B,C,X[ 3],10,0x8f0ccc92L);
R3(C,D,A,B,X[10],15,0xffeff47dL);
R3(B,C,D,A,X[ 1],21,0x85845dd1L);
R3(A,B,C,D,X[ 8], 6,0x6fa87e4fL);
R3(D,A,B,C,X[15],10,0xfe2ce6e0L);
R3(C,D,A,B,X[ 6],15,0xa3014314L);
R3(B,C,D,A,X[13],21,0x4e0811a1L);
R3(A,B,C,D,X[ 4], 6,0xf7537e82L);
R3(D,A,B,C,X[11],10,0xbd3af235L);
R3(C,D,A,B,X[ 2],15,0x2ad7d2bbL);
R3(B,C,D,A,X[ 9],21,0xeb86d391L);
c->A+=A&0xffffffffL;
c->B+=B&0xffffffffL;
c->C+=C&0xffffffffL;
c->D+=D&0xffffffffL;
}
void MD5_Final(md, c)
unsigned char *md;
MD5_CTX *c;
{
register int i,j;
register ULONG l;
register ULONG *p;
static unsigned char end[4]={0x80,0x00,0x00,0x00};
unsigned char *cp=end;
/* c->num should definitly have room for at least one more byte. */
p=c->data;
j=c->num;
i=j>>2;
/* purify often complains about the following line as an
* Uninitialized Memory Read. While this can be true, the
* following p_c2l macro will reset l when that case is true.
* This is because j&0x03 contains the number of 'valid' bytes
* already in p[i]. If and only if j&0x03 == 0, the UMR will
* occur but this is also the only time p_c2l will do
* l= *(cp++) instead of l|= *(cp++)
* Many thanks to Alex Tang <altitude@cic.net> for pickup this
* 'potential bug' */
#ifdef PURIFY
if ((j&0x03) == 0) p[i]=0;
#endif
l=p[i];
p_c2l(cp,l,j&0x03);
p[i]=l;
i++;
/* i is the next 'undefined word' */
if (c->num >= MD5_LAST_BLOCK)
{
for (; i<MD5_LBLOCK; i++)
p[i]=0;
md5_block(c,p);
i=0;
}
for (; i<(MD5_LBLOCK-2); i++)
p[i]=0;
p[MD5_LBLOCK-2]=c->Nl;
p[MD5_LBLOCK-1]=c->Nh;
md5_block(c,p);
cp=md;
l=c->A; l2c(l,cp);
l=c->B; l2c(l,cp);
l=c->C; l2c(l,cp);
l=c->D; l2c(l,cp);
/* clear stuff, md5_block may be leaving some stuff on the stack
* but I'm not worried :-) */
c->num=0;
/* memset((char *)&c,0,sizeof(c));*/
}
#ifdef undef
int printit(l)
unsigned long *l;
{
int i,ii;
for (i=0; i<2; i++)
{
for (ii=0; ii<8; ii++)
{
fprintf(stderr,"%08lx ",l[i*8+ii]);
}
fprintf(stderr,"\n");
}
}
#endif
#endif /* USE_MD5 */

View File

@ -0,0 +1,190 @@
/* crypto/md/md5_locl.h */
/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdlib.h>
#include <string.h>
#include "md5.h"
#define ULONG unsigned long
#define UCHAR unsigned char
#define UINT unsigned int
#if defined(NOCONST)
#define const
#endif
#undef c2l
#define c2l(c,l) (l = ((unsigned long)(*((c)++))) , \
l|=(((unsigned long)(*((c)++)))<< 8), \
l|=(((unsigned long)(*((c)++)))<<16), \
l|=(((unsigned long)(*((c)++)))<<24))
#undef p_c2l
#define p_c2l(c,l,n) { \
switch (n) { \
case 0: l =((unsigned long)(*((c)++))); \
case 1: l|=((unsigned long)(*((c)++)))<< 8; \
case 2: l|=((unsigned long)(*((c)++)))<<16; \
case 3: l|=((unsigned long)(*((c)++)))<<24; \
} \
}
/* NOTE the pointer is not incremented at the end of this */
#undef c2l_p
#define c2l_p(c,l,n) { \
l=0; \
(c)+=n; \
switch (n) { \
case 3: l =((unsigned long)(*(--(c))))<<16; \
case 2: l|=((unsigned long)(*(--(c))))<< 8; \
case 1: l|=((unsigned long)(*(--(c)))) ; \
} \
}
#undef p_c2l_p
#define p_c2l_p(c,l,sc,len) { \
switch (sc) \
{ \
case 0: l =((unsigned long)(*((c)++))); \
if (--len == 0) break; \
case 1: l|=((unsigned long)(*((c)++)))<< 8; \
if (--len == 0) break; \
case 2: l|=((unsigned long)(*((c)++)))<<16; \
} \
}
#undef l2c
#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
*((c)++)=(unsigned char)(((l)>>24)&0xff))
/* NOTE - c is not incremented as per l2c */
#undef l2cn
#define l2cn(l1,l2,c,n) { \
c+=n; \
switch (n) { \
case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \
case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \
case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \
case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \
case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \
case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \
case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \
case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \
} \
}
/* A nice byte order reversal from Wei Dai <weidai@eskimo.com> */
#if defined(WIN32)
/* 5 instructions with rotate instruction, else 9 */
#define Endian_Reverse32(a) \
{ \
unsigned long l=(a); \
(a)=((ROTATE(l,8)&0x00FF00FF)|(ROTATE(l,24)&0xFF00FF00)); \
}
#else
/* 6 instructions with rotate instruction, else 8 */
#define Endian_Reverse32(a) \
{ \
unsigned long l=(a); \
l=(((l&0xFF00FF00)>>8L)|((l&0x00FF00FF)<<8L)); \
(a)=ROTATE(l,16L); \
}
#endif
/*
#define F(x,y,z) (((x) & (y)) | ((~(x)) & (z)))
#define G(x,y,z) (((x) & (z)) | ((y) & (~(z))))
*/
/* As pointed out by Wei Dai <weidai@eskimo.com>, the above can be
* simplified to the code below. Wei attributes these optimisations
* to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
*/
#define F(x,y,z) ((((y) ^ (z)) & (x)) ^ (z))
#define G(x,y,z) ((((x) ^ (y)) & (z)) ^ (y))
#define H(x,y,z) ((x) ^ (y) ^ (z))
#define I(x,y,z) (((x) | (~(z))) ^ (y))
#undef ROTATE
#if defined(WIN32)
#define ROTATE(a,n) _lrotl(a,n)
#else
#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
#endif
#define R0(a,b,c,d,k,s,t) { \
a+=((k)+(t)+F((b),(c),(d))); \
a=ROTATE(a,s); \
a+=b; };\
#define R1(a,b,c,d,k,s,t) { \
a+=((k)+(t)+G((b),(c),(d))); \
a=ROTATE(a,s); \
a+=b; };
#define R2(a,b,c,d,k,s,t) { \
a+=((k)+(t)+H((b),(c),(d))); \
a=ROTATE(a,s); \
a+=b; };
#define R3(a,b,c,d,k,s,t) { \
a+=((k)+(t)+I((b),(c),(d))); \
a=ROTATE(a,s); \
a+=b; };

862
usr.sbin/dhcp/dst/prandom.c Normal file
View File

@ -0,0 +1,862 @@
#ifndef LINT
static const char rcsid[] = "$Header: /cvsroot/src/usr.sbin/dhcp/dst/Attic/prandom.c,v 1.1.1.1 2001/04/02 21:57:04 mellon Exp $";
#endif
/*
* Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
*
* Permission to use, copy modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
*/
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <dirent.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define NEED_PRAND_CONF
#include "minires/minires.h"
#include "dst_internal.h"
#include "arpa/nameser.h"
#ifndef DST_NUM_HASHES
#define DST_NUM_HASHES 4
#endif
#ifndef DST_NUMBER_OF_COUNTERS
#define DST_NUMBER_OF_COUNTERS 5 /* 32 * 5 == 160 == SHA(1) > MD5 */
#endif
/*
* the constant below is a prime number to make fixed data structues like
* stat and time wrap over blocks. This adds certain uncertanty to what is
* in each digested block.
* The prime number 2879 has the special property that when
* divided by 2,4 and 6 the result is also a prime numbers
*/
#ifndef DST_RANDOM_BLOCK_SIZE
#define DST_RANDOM_BLOCK_SIZE 2879
#endif
/*
* This constant dictatates how many bits we shift to the right before using a
*/
#ifndef DST_SHIFT
#define DST_SHIFT 9
#endif
/*
* An initalizer that is as bad as any other with half the bits set
*/
#ifndef DST_RANDOM_PATTERN
#define DST_RANDOM_PATTERN 0x8765CA93
#endif
/*
* things must have changed in the last 3600 seconds to be used
*/
#define MAX_OLD 3600
/*
* these two data structure are used to process input data into digests,
*
* The first structure is containts a pointer to a DST HMAC key
* the variables accompanying are used for
* step : select every step byte from input data for the hash
* block: number of data elements going into each hash
* digested: number of data elements digested so far
* curr: offset into the next input data for the first byte.
*/
typedef struct hash {
DST_KEY *key;
void *ctx;
int digested, block, step, curr;
} prand_hash;
/*
* This data structure controlls number of hashes and keeps track of
* overall progress in generating correct number of bytes of output.
* output : array to store the output data in
* needed : how many bytes of output are needed
* filled : number of bytes in output so far.
* bytes : total number of bytes processed by this structure
* file_digest : the HMAC key used to digest files.
*/
typedef struct work {
unsigned needed, filled, bytes;
u_char *output;
prand_hash *hash[DST_NUM_HASHES];
DST_KEY *file_digest;
} dst_work;
/*
* forward function declarations
*/
static int get_dev_random(u_char *output, unsigned size);
static int do_time(dst_work *work);
static int do_ls(dst_work *work);
static int unix_cmd(dst_work *work);
static int digest_file(dst_work *work);
static void force_hash(dst_work *work, prand_hash *hash);
static int do_hash(dst_work *work, prand_hash *hash, const u_char *input,
unsigned size);
static int my_digest(dst_work *tmp, const u_char *input, unsigned size);
static prand_hash *get_hmac_key(int step, int block);
static unsigned own_random(dst_work *work);
/*
* variables used in the quick random number generator
*/
static u_int32_t ran_val = DST_RANDOM_PATTERN;
static u_int32_t ran_cnt = (DST_RANDOM_PATTERN >> 10);
/*
* setting the quick_random generator to particular values or if both
* input parameters are 0 then set it to initial vlaues
*/
void
dst_s_quick_random_set(u_int32_t val, u_int32_t cnt)
{
ran_val = (val == 0) ? DST_RANDOM_PATTERN : val;
ran_cnt = (cnt == 0) ? (DST_RANDOM_PATTERN >> 10) : cnt;
}
/*
* this is a quick and random number generator that seems to generate quite
* good distribution of data
*/
u_int32_t
dst_s_quick_random(int inc)
{
ran_val = ((ran_val >> 13) ^ (ran_val << 19)) ^
((ran_val >> 7) ^ (ran_val << 25));
if (inc > 0) /* only increasing values accepted */
ran_cnt += inc;
ran_val += ran_cnt++;
return (ran_val);
}
/*
* get_dev_random: Function to read /dev/random reliably
* this function returns how many bytes where read from the device.
* port_after.h should set the control variable HAVE_DEV_RANDOM
*/
static int
get_dev_random(u_char *output, unsigned size)
{
#ifdef HAVE_DEV_RANDOM
struct stat st;
int n = 0, fd = -1, s;
s = stat("/dev/random", &st);
if (s == 0 && S_ISCHR(st.st_mode)) {
if ((fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) != -1) {
if ((n = read(fd, output, size)) < 0)
n = 0;
close(fd);
}
return (n);
}
#endif
return (0);
}
/*
* Portable way of getting the time values if gettimeofday is missing
* then compile with -DMISSING_GETTIMEOFDAY time() is POSIX compliant but
* gettimeofday() is not.
* Time of day is predictable, we are looking for the randomness that comes
* the last few bits in the microseconds in the timer are hard to predict when
* this is invoked at the end of other operations
*/
struct timeval *mtime;
static int
do_time(dst_work *work)
{
int cnt = 0;
static u_char tmp[sizeof(struct timeval) + sizeof(struct timezone)];
struct timezone *zone;
zone = (struct timezone *) tmp;
mtime = (struct timeval *)(tmp + sizeof(struct timezone));
gettimeofday(mtime, zone);
cnt = sizeof(tmp);
my_digest(work, tmp, sizeof(tmp));
return (cnt);
}
/*
* this function simulates the ls command, but it uses stat which gives more
* information and is harder to guess
* Each call to this function will visit the next directory on the list of
* directories, in a circular manner.
* return value is the number of bytes added to the temp buffer
*
* do_ls() does not visit subdirectories
* if attacker has access to machine it can guess most of the values seen
* thus it is important to only visit directories that are freqently updated
* Attacker that has access to the network can see network traffic
* when NFS mounted directories are accessed and know exactly the data used
* but may not know exactly in what order data is used.
* Returns the number of bytes that where returned in stat structures
*/
static int
do_ls(dst_work *work)
{
struct dir_info {
uid_t uid;
gid_t gid;
off_t size;
time_t atime, mtime, ctime;
};
static struct dir_info dir_info;
struct stat buf;
struct dirent *entry;
static int i = 0;
static unsigned long d_round = 0;
struct timeval tv;
int n = 0, tb_i = 0, out = 0;
unsigned dir_len;
char file_name[1024];
u_char tmp_buff[1024];
DIR *dir = NULL;
if (dirs[i] == NULL) /* if at the end of the list start over */
i = 0;
if (stat(dirs[i++], &buf)) /* directory does not exist */
return (0);
gettimeofday(&tv,NULL);
if (d_round == 0)
d_round = tv.tv_sec - MAX_OLD;
else if (i==1) /* if starting a new round cut what we accept */
d_round += (tv.tv_sec - d_round)/2;
if (buf.st_atime < d_round)
return (0);
EREPORT(("do_ls i %d filled %4d in_temp %4d\n",
i-1, work->filled, work->in_temp));
memcpy(tmp_buff, &buf, sizeof(buf));
tb_i += sizeof(buf);
if ((dir = opendir(dirs[i-1])) == NULL)/* open it for read */
return (0);
strcpy(file_name, dirs[i-1]);
dir_len = strlen(file_name);
file_name[dir_len++] = '/';
while ((entry = readdir(dir))) {
unsigned len = strlen(entry->d_name);
out += len;
if (my_digest(work, (u_char *)entry->d_name, len))
break;
memcpy(&file_name[dir_len], entry->d_name, len);
file_name[dir_len + len] = 0x0;
/* for all entries in dir get the stats */
if (stat(file_name, &buf) == 0) {
n++; /* count successfull stat calls */
/* copy non static fields */
dir_info.uid += buf.st_uid;
dir_info.gid += buf.st_gid;
dir_info.size += buf.st_size;
dir_info.atime += buf.st_atime;
dir_info.mtime += buf.st_mtime;
dir_info.ctime += buf.st_ctime;
out += sizeof(dir_info);
if(my_digest(work, (u_char *)&dir_info,
sizeof(dir_info)))
break;
}
}
closedir(dir); /* done */
out += do_time(work); /* add a time stamp */
return (out);
}
/*
* unix_cmd()
* this function executes the a command from the cmds[] list of unix commands
* configured in the prand_conf.h file
* return value is the number of bytes added to the randomness temp buffer
*
* it returns the number of bytes that where read in
* if more data is needed at the end time is added to the data.
* This function maintains a state to selects the next command to run
* returns the number of bytes read in from the command
*/
static int
unix_cmd(dst_work *work)
{
static int cmd_index = 0;
int cnt = 0, n;
FILE *pipe;
u_char buffer[4096];
if (cmds[cmd_index] == NULL)
cmd_index = 0;
EREPORT(("unix_cmd() i %d filled %4d in_temp %4d\n",
cmd_index, work->filled, work->in_temp));
pipe = popen(cmds[cmd_index++], "r"); /* execute the command */
while ((n = fread(buffer, sizeof(char), sizeof(buffer), pipe)) > 0) {
cnt += n; /* process the output */
if (my_digest(work, buffer, (unsigned)n))
break;
/* this adds some randomness to the output */
cnt += do_time(work);
}
while ((n = fread(buffer, sizeof(char), sizeof(buffer), pipe)) > 0)
NULL; /* drain the pipe */
pclose(pipe);
return (cnt); /* read how many bytes where read in */
}
/*
* digest_file() This function will read a file and run hash over it
* input is a file name
*/
static int
digest_file(dst_work *work)
{
static int f_cnt = 0;
static unsigned long f_round = 0;
FILE *fp;
void *ctx;
const char *name;
int no, i;
struct stat st;
struct timeval tv;
u_char buf[1024];
if (f_round == 0 || files[f_cnt] == NULL || work->file_digest == NULL)
if (gettimeofday(&tv, NULL)) /* only do this if needed */
return (0);
if (f_round == 0) /* first time called set to one hour ago */
f_round = (tv.tv_sec - MAX_OLD);
name = files[f_cnt++];
if (files[f_cnt] == NULL) { /* end of list of files */
if(f_cnt <= 1) /* list is too short */
return (0);
f_cnt = 0; /* start again on list */
f_round += (tv.tv_sec - f_round)/2; /* set new cutoff */
work->file_digest = dst_free_key(work->file_digest);
}
if (work->file_digest == NULL) {
work->file_digest = dst_buffer_to_key("", KEY_HMAC_MD5, 0, 0,
(u_char *)&tv, sizeof(tv));
if (work->file_digest == NULL)
return (0);
}
if (access(name, R_OK) || stat(name, &st))
return (0); /* no such file or not allowed to read it */
if (strncmp(name, "/proc/", 6) && st.st_mtime < f_round)
return(0); /* file has not changed recently enough */
if (dst_sign_data(SIG_MODE_INIT, work->file_digest, &ctx,
NULL, 0, NULL, 0)) {
work->file_digest = dst_free_key(work->file_digest);
return (0);
}
if ((fp = fopen(name, "r")) == NULL)
return (0);
for (no = 0; (i = fread(buf, sizeof(*buf), sizeof(buf), fp)) > 0;
no += i)
dst_sign_data(SIG_MODE_UPDATE, work->file_digest, &ctx,
buf, (unsigned)i, NULL, 0);
fclose(fp);
if (no >= 64) {
i = dst_sign_data(SIG_MODE_FINAL, work->file_digest, &ctx,
NULL, 0, &work->output[work->filled],
DST_HASH_SIZE);
if (i > 0)
work->filled += i;
}
else if (i > 0)
my_digest(work, buf, (unsigned)i);
my_digest(work, (const u_char *)name, strlen(name));
return (no + strlen(name));
}
/*
* function to perform the FINAL and INIT operation on a hash if allowed
*/
static void
force_hash(dst_work *work, prand_hash *hash)
{
int i = 0;
/*
* if more than half a block then add data to output
* otherwise adde the digest to the next hash
*/
if ((hash->digested * 2) > hash->block) {
i = dst_sign_data(SIG_MODE_FINAL, hash->key, &hash->ctx,
NULL, 0, &work->output[work->filled],
DST_HASH_SIZE);
hash->digested = 0;
dst_sign_data(SIG_MODE_INIT, hash->key, &hash->ctx,
NULL, 0, NULL, 0);
if (i > 0)
work->filled += i;
}
return;
}
/*
* This function takes the input data does the selection of data specified
* by the hash control block.
* The step varialbe in the work sturcture determines which 1/step bytes
* are used,
*
*/
static int
do_hash(dst_work *work, prand_hash *hash, const u_char *input, unsigned size)
{
const u_char *tmp = input;
u_char *tp, *abuf = (u_char *)0;
int i, n;
unsigned needed, avail, dig, cnt = size;
unsigned tmp_size = 0;
if (cnt <= 0 || input == NULL)
return (0);
if (hash->step > 1) { /* if using subset of input data */
tmp_size = size / hash->step + 2;
abuf = tp = malloc(tmp_size);
tmp = tp;
for (cnt = 0, i = hash->curr; i < size; i += hash->step, cnt++)
*(tp++) = input[i];
/* calcutate the starting point in the next input set */
hash->curr = (hash->step - (i - size)) % hash->step;
}
/* digest the data in block sizes */
for (n = 0; n < cnt; n += needed) {
avail = (cnt - n);
needed = hash->block - hash->digested;
dig = (avail < needed) ? avail : needed;
dst_sign_data(SIG_MODE_UPDATE, hash->key, &hash->ctx,
&tmp[n], dig, NULL, 0);
hash->digested += dig;
if (hash->digested >= hash->block)
force_hash(work, hash);
if (work->needed < work->filled) {
if (abuf)
SAFE_FREE2(abuf, tmp_size);
return (1);
}
}
if (tmp_size > 0)
SAFE_FREE2(abuf, tmp_size);
return (0);
}
/*
* Copy data from INPUT for length SIZE into the work-block TMP.
* If we fill the work-block, digest it; then,
* if work-block needs more data, keep filling with the rest of the input.
*/
static int
my_digest(dst_work *work, const u_char *input, unsigned size)
{
int i, full = 0;
static unsigned counter;
counter += size;
/* first do each one of the hashes */
for (i = 0; i < DST_NUM_HASHES && full == 0; i++)
full = do_hash(work, work->hash[i], input, size) +
do_hash(work, work->hash[i], (u_char *) &counter,
sizeof(counter));
/*
* if enough data has be generated do final operation on all hashes
* that have enough date for that
*/
for (i = 0; full && (i < DST_NUM_HASHES); i++)
force_hash(work, work->hash[i]);
return (full);
}
/*
* this function gets some semi random data and sets that as an HMAC key
* If we get a valid key this function returns that key initalized
* otherwise it returns NULL;
*/
static prand_hash *
get_hmac_key(int step, int block)
{
u_char *buff;
int temp = 0, n = 0;
unsigned size = 70;
DST_KEY *new_key = NULL;
prand_hash *new = NULL;
/* use key that is larger than digest algorithms (64) for key size */
buff = malloc(size);
if (buff == NULL)
return (NULL);
/* do not memset the allocated memory to get random bytes there */
/* time of day is somewhat random expecialy in the last bytes */
gettimeofday((struct timeval *) &buff[n], NULL);
n += sizeof(struct timeval);
/* get some semi random stuff in here stir it with micro seconds */
if (n < size) {
temp = dst_s_quick_random((int) buff[n - 1]);
memcpy(&buff[n], &temp, sizeof(temp));
n += sizeof(temp);
}
/* get the pid of this process and its parent */
if (n < size) {
temp = (int) getpid();
memcpy(&buff[n], &temp, sizeof(temp));
n += sizeof(temp);
}
if (n < size) {
temp = (int) getppid();
memcpy(&buff[n], &temp, sizeof(temp));
n += sizeof(temp);
}
/* get the user ID */
if (n < size) {
temp = (int) getuid();
memcpy(&buff[n], &temp, sizeof(temp));
n += sizeof(temp);
}
#ifndef GET_HOST_ID_MISSING
if (n < size) {
temp = (int) gethostid();
memcpy(&buff[n], &temp, sizeof(temp));
n += sizeof(temp);
}
#endif
/* get some more random data */
if (n < size) {
temp = dst_s_quick_random((int) buff[n - 1]);
memcpy(&buff[n], &temp, sizeof(temp));
n += sizeof(temp);
}
/* covert this into a HMAC key */
new_key = dst_buffer_to_key("", KEY_HMAC_MD5, 0, 0, buff, size);
SAFE_FREE(buff);
/* get the control structure */
if ((new = malloc(sizeof(prand_hash))) == NULL)
return (NULL);
new->digested = new->curr = 0;
new->step = step;
new->block = block;
new->key = new_key;
if (dst_sign_data(SIG_MODE_INIT, new_key, &new->ctx, NULL, 0, NULL, 0))
return (NULL);
return (new);
}
/*
* own_random()
* This function goes out and from various sources tries to generate enough
* semi random data that a hash function can generate a random data.
* This function will iterate between the two main random source sources,
* information from programs and directores in random order.
* This function return the number of bytes added to the random output buffer.
*/
static unsigned
own_random(dst_work *work)
{
int dir = 0, b;
int bytes, n, cmd = 0, dig = 0;
int start =0;
/*
* now get the initial seed to put into the quick random function from
* the address of the work structure
*/
bytes = (int) getpid();
/*
* proceed while needed
*/
while (work->filled < work->needed) {
EREPORT(("own_random r %08x b %6d t %6d f %6d\n",
ran_val, bytes, work->in_temp, work->filled));
/* pick a random number in the range of 0..7 based on that random number
* perform some operations that yield random data
*/
start = work->filled;
n = (dst_s_quick_random(bytes) >> DST_SHIFT) & 0x07;
switch (n) {
case 0:
case 3:
if (sizeof(cmds) > 2 *sizeof(*cmds)) {
b = unix_cmd(work);
cmd += b;
}
break;
case 1:
case 7:
if (sizeof(dirs) > 2 *sizeof(*dirs)) {
b = do_ls(work);
dir += b;
}
break;
case 4:
case 5:
/* retry getting data from /dev/random */
b = get_dev_random(&work->output[work->filled],
work->needed - work->filled);
if (b > 0)
work->filled += b;
break;
case 6:
if (sizeof(files) > 2 * sizeof(*files)) {
b = digest_file(work);
dig += b;
}
break;
case 2:
default: /* to make sure we make some progress */
work->output[work->filled++] = 0xff &
dst_s_quick_random(bytes);
b = 1;
break;
}
if (b > 0)
bytes += b;
}
return (work->filled);
}
/*
* dst_s_random() This function will return the requested number of bytes
* of randomness to the caller it will use the best available sources of
* randomness.
* The current order is to use /dev/random, precalculated randomness, and
* finaly use some system calls and programs to generate semi random data that
* is then digested to generate randomness.
* This function is thread safe as each thread uses its own context, but
* concurrent treads will affect each other as they update shared state
* information.
* It is strongly recommended that this function be called requesting a size
* that is not a multiple of the output of the hash function used.
*
* If /dev/random is not available this function is not suitable to generate
* large ammounts of data, rather it is suitable to seed a pseudo-random
* generator
* Returns the number of bytes put in the output buffer
*/
int
dst_s_random(u_char *output, unsigned size)
{
int n = 0, i;
unsigned s;
static u_char old_unused[DST_HASH_SIZE * DST_NUM_HASHES];
static unsigned unused = 0;
if (size <= 0 || output == NULL)
return (0);
if (size >= 2048)
return (-1);
/*
* Read from /dev/random
*/
n = get_dev_random(output, size);
/*
* If old data is available and needed use it
*/
if (n < size && unused > 0) {
unsigned need = size - n;
if (unused <= need) {
memcpy(output, old_unused, unused);
n += unused;
unused = 0;
} else {
memcpy(output, old_unused, need);
n += need;
unused -= need;
memcpy(old_unused, &old_unused[need], unused);
}
}
/*
* If we need more use the simulated randomness here.
*/
if (n < size) {
dst_work *my_work = (dst_work *) malloc(sizeof(dst_work));
if (my_work == NULL)
return (n);
my_work->needed = size - n;
my_work->filled = 0;
my_work->output = (u_char *) malloc(my_work->needed +
DST_HASH_SIZE *
DST_NUM_HASHES);
my_work->file_digest = NULL;
if (my_work->output == NULL)
return (n);
memset(my_work->output, 0x0, my_work->needed);
/* allocate upto 4 different HMAC hash functions out of order */
#if DST_NUM_HASHES >= 3
my_work->hash[2] = get_hmac_key(3, DST_RANDOM_BLOCK_SIZE / 2);
#endif
#if DST_NUM_HASHES >= 2
my_work->hash[1] = get_hmac_key(7, DST_RANDOM_BLOCK_SIZE / 6);
#endif
#if DST_NUM_HASHES >= 4
my_work->hash[3] = get_hmac_key(5, DST_RANDOM_BLOCK_SIZE / 4);
#endif
my_work->hash[0] = get_hmac_key(1, DST_RANDOM_BLOCK_SIZE);
if (my_work->hash[0] == NULL) /* if failure bail out */
return (n);
s = own_random(my_work);
/* if more generated than needed store it for future use */
if (s >= my_work->needed) {
EREPORT(("dst_s_random(): More than needed %d >= %d\n",
s, my_work->needed));
memcpy(&output[n], my_work->output, my_work->needed);
n += my_work->needed;
/* saving unused data for next time */
unused = s - my_work->needed;
memcpy(old_unused, &my_work->output[my_work->needed],
unused);
} else {
/* XXXX This should not happen */
EREPORT(("Not enough %d >= %d\n", s, my_work->needed));
memcpy(&output[n], my_work->output, s);
n += my_work->needed;
}
/* delete the allocated work area */
for (i = 0; i < DST_NUM_HASHES; i++) {
dst_free_key(my_work->hash[i]->key);
SAFE_FREE(my_work->hash[i]);
}
SAFE_FREE(my_work->output);
SAFE_FREE(my_work);
}
return (n);
}
/*
* A random number generator that is fast and strong
* this random number generator is based on HASHing data,
* the input to the digest function is a collection of <NUMBER_OF_COUNTERS>
* counters that is incremented between digest operations
* each increment operation amortizes to 2 bits changed in that value
* for 5 counters thus the input will amortize to have 10 bits changed
* The counters are initaly set using the strong random function above
* the HMAC key is selected by the same methold as the HMAC keys for the
* strong random function.
* Each set of counters is used for 2^25 operations
*
* returns the number of bytes written to the output buffer
* or negative number in case of error
*/
int
dst_s_semi_random(u_char *output, unsigned size)
{
static u_int32_t counter[DST_NUMBER_OF_COUNTERS];
static u_char semi_old[DST_HASH_SIZE];
static int semi_loc = 0, cnt = 0;
static unsigned hb_size = 0;
static DST_KEY *my_key = NULL;
prand_hash *hash;
unsigned out = 0;
unsigned i;
int n;
if (output == NULL || size <= 0)
return (-2);
/* check if we need a new key */
if (my_key == NULL || cnt > (1 << 25)) { /* get HMAC KEY */
if (my_key)
my_key->dk_func->destroy(my_key);
if ((hash = get_hmac_key(1, DST_RANDOM_BLOCK_SIZE)) == NULL)
return (0);
my_key = hash->key;
/* check if the key works stir the new key using some old random data */
hb_size = dst_sign_data(SIG_MODE_ALL, my_key, NULL,
(u_char *) counter, sizeof(counter),
semi_old, sizeof(semi_old));
if (hb_size <= 0) {
EREPORT(("dst_s_semi_random() Sign of alg %d failed %d\n",
my_key->dk_alg, hb_size));
return (-1);
}
/* new set the counters to random values */
dst_s_random((u_char *) counter, sizeof(counter));
cnt = 0;
}
/* if old data around use it first */
if (semi_loc < hb_size) {
if (size <= hb_size - semi_loc) { /* need less */
memcpy(output, &semi_old[semi_loc], size);
semi_loc += size;
return (size); /* DONE */
} else {
out = hb_size - semi_loc;
memcpy(output, &semi_old[semi_loc], out);
semi_loc += out;
}
}
/* generate more randome stuff */
while (out < size) {
/*
* modify at least one bit by incrementing at least one counter
* based on the last bit of the last counter updated update
* the next one.
* minimaly this operation will modify at least 1 bit,
* amortized 2 bits
*/
for (n = 0; n < DST_NUMBER_OF_COUNTERS; n++)
i = (int) counter[n]++;
i = dst_sign_data(SIG_MODE_ALL, my_key, NULL,
(u_char *) counter, hb_size,
semi_old, sizeof(semi_old));
if (i != hb_size)
EREPORT(("HMAC SIGNATURE FAILURE %d\n", i));
cnt++;
if (size - out < i) /* Not all data is needed */
semi_loc = i = size - out;
memcpy(&output[out], semi_old, i);
out += i;
}
return (out);
}

View File

@ -151,6 +151,7 @@ extern int h_errno;
#define ALIAS_NAMES_PERMUTED
#define SKIP_DUMMY_INTERFACES
#define SIOCGIFCONF_NULL_BUF_GIVES_CORRECT_LEN
#ifdef NEED_PRAND_CONF
#ifndef HAVE_DEV_RANDOM

View File

@ -59,6 +59,7 @@ extern int h_errno;
#include <net/if_dl.h>
#include <net/route.h>
#include <sys/sockio.h>
#import <net/if_arp.h>
#define ifr_netmask ifr_addr

View File

@ -0,0 +1,86 @@
/* trace.h
Definitions for dhcp tracing facility... */
/*
* Copyright (c) 2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of The Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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.
*
* This software has been written for the Internet Software Consortium
* by Ted Lemon, as part of a project for Nominum, Inc. To learn more
* about the Internet Software Consortium, see http://www.isc.org/. To
* learn more about Nominum, Inc., see ``http://www.nominum.com''.
*/
typedef struct {
struct in_addr primary_address;
u_int32_t index;
struct hardware hw_address;
char name [IFNAMSIZ];
} trace_interface_packet_t;
typedef struct {
u_int32_t index;
struct iaddr from;
u_int16_t from_port;
struct hardware hfrom;
u_int8_t havehfrom;
} trace_inpacket_t;
typedef struct {
u_int32_t index;
struct iaddr from;
struct iaddr to;
u_int16_t to_port;
struct hardware hto;
u_int8_t havehto;
} trace_outpacket_t;
void trace_interface_register (trace_type_t *, struct interface_info *);
void trace_interface_input (trace_type_t *, unsigned, char *);
void trace_interface_stop (trace_type_t *);
void trace_inpacket_stash (struct interface_info *,
struct dhcp_packet *, unsigned, unsigned int,
struct iaddr, struct hardware *);
void trace_inpacket_input (trace_type_t *, unsigned, char *);
void trace_inpacket_stop (trace_type_t *);
void trace_outpacket_input (trace_type_t *, unsigned, char *);
void trace_outpacket_stop (trace_type_t *);
ssize_t trace_packet_send (struct interface_info *,
struct packet *, struct dhcp_packet *, size_t,
struct in_addr,
struct sockaddr_in *, struct hardware *);
void trace_icmp_input_input (trace_type_t *, unsigned, char *);
void trace_icmp_input_stop (trace_type_t *);
void trace_icmp_output_input (trace_type_t *, unsigned, char *);
void trace_icmp_output_stop (trace_type_t *);
void trace_seed_stash (trace_type_t *, unsigned);
void trace_seed_input (trace_type_t *, unsigned, char *);
void trace_seed_stop (trace_type_t *);

View File

@ -293,7 +293,23 @@ enum dhcp_token {
SHUTDOWN = 589,
STARTUP = 590,
ENCAPSULATE = 591,
VENDOR = 592
VENDOR = 592,
CLIENT_STATE = 593,
INIT_REBOOT = 594,
TOKEN_INIT = 595,
SELECT = 596,
BOUND = 597,
RENEWING = 598,
REBINDING = 599,
RECONTACT_INTERVAL = 600,
CLIENT_UPDATES = 601,
TOKEN_NEW = 601,
TRANSMISSION = 602,
TOKEN_CLOSE = 603,
TOKEN_CREATE = 604,
TOKEN_OPEN = 605,
TOKEN_HELP = 606,
END_OF_FILE = 607
};
#define is_identifier(x) ((x) >= FIRST_TOKEN && \

View File

@ -25,58 +25,79 @@
ISC_LANG_BEGINDECLS
#define ISC_R_SUCCESS 0
#define ISC_R_NOMEMORY 1
#define ISC_R_TIMEDOUT 2
#define ISC_R_NOTHREADS 3
#define ISC_R_ADDRNOTAVAIL 4
#define ISC_R_ADDRINUSE 5
#define ISC_R_NOPERM 6
#define ISC_R_NOCONN 7
#define ISC_R_NETUNREACH 8
#define ISC_R_HOSTUNREACH 9
#define ISC_R_NETDOWN 10
#define ISC_R_HOSTDOWN 11
#define ISC_R_CONNREFUSED 12
#define ISC_R_NORESOURCES 13 /* not enough resources */
#define ISC_R_EOF 14 /* end of file */
#define ISC_R_BOUND 15 /* already bound */
#define ISC_R_TASKDONE 16 /* task is done */
#define ISC_R_LOCKBUSY 17
#define ISC_R_EXISTS 18
#define ISC_R_NOSPACE 19 /* ran out of space */
#define ISC_R_CANCELED 20
#define ISC_R_TASKNOSEND 21
#define ISC_R_SHUTTINGDOWN 22 /* shutting down */
#define ISC_R_NOTFOUND 23
#define ISC_R_UNEXPECTEDEND 24 /* unexpected end of input */
#define ISC_R_FAILURE 25 /* generic failure */
#define ISC_R_IOERROR 26
#define ISC_R_NOTIMPLEMENTED 27
#define ISC_R_UNBALANCED 28
#define ISC_R_NOMORE 29
#define ISC_R_INVALIDFILE 30
#define ISC_R_BADBASE64 31
#define ISC_R_UNEXPECTEDTOKEN 32
#define ISC_R_QUOTA 33
#define ISC_R_UNEXPECTED 34
#define ISC_R_ALREADYRUNNING 35
#define ISC_R_HOSTUNKNOWN 36
#define ISC_R_VERSIONMISMATCH 37
#define ISC_R_PROTOCOLERROR 38
#define ISC_R_INVALIDARG 39
#define ISC_R_NOTCONNECTED 40
#define ISC_R_NOTYET 41
#define ISC_R_UNCHANGED 42
#define ISC_R_MULTIPLE 43
#define ISC_R_KEYCONFLICT 44
#define ISC_R_BADPARSE 45
#define ISC_R_NOKEYS 46
#define ISC_R_KEY_UNKNOWN 47
#define ISC_R_INVALIDKEY 48
#define ISC_R_INCOMPLETE 49
typedef enum {
ISC_R_SUCCESS = 0,
ISC_R_NOMEMORY = 1,
ISC_R_TIMEDOUT = 2,
ISC_R_NOTHREADS = 3,
ISC_R_ADDRNOTAVAIL = 4,
ISC_R_ADDRINUSE = 5,
ISC_R_NOPERM = 6,
ISC_R_NOCONN = 7,
ISC_R_NETUNREACH = 8,
ISC_R_HOSTUNREACH = 9,
ISC_R_NETDOWN = 10,
ISC_R_HOSTDOWN = 11,
ISC_R_CONNREFUSED = 12,
ISC_R_NORESOURCES = 13,
ISC_R_EOF = 14,
ISC_R_BOUND = 15,
ISC_R_TASKDONE = 16,
ISC_R_LOCKBUSY = 17,
ISC_R_EXISTS = 18,
ISC_R_NOSPACE = 19,
ISC_R_CANCELED = 20,
ISC_R_TASKNOSEND = 21,
ISC_R_SHUTTINGDOWN = 22,
ISC_R_NOTFOUND = 23,
ISC_R_UNEXPECTEDEND = 24,
ISC_R_FAILURE = 25,
ISC_R_IOERROR = 26,
ISC_R_NOTIMPLEMENTED = 27,
ISC_R_UNBALANCED = 28,
ISC_R_NOMORE = 29,
ISC_R_INVALIDFILE = 30,
ISC_R_BADBASE64 = 31,
ISC_R_UNEXPECTEDTOKEN = 32,
ISC_R_QUOTA = 33,
ISC_R_UNEXPECTED = 34,
ISC_R_ALREADYRUNNING = 35,
ISC_R_HOSTUNKNOWN = 36,
ISC_R_VERSIONMISMATCH = 37,
ISC_R_PROTOCOLERROR = 38,
ISC_R_INVALIDARG = 39,
ISC_R_NOTCONNECTED = 40,
ISC_R_NOTYET = 41,
ISC_R_UNCHANGED = 42,
ISC_R_MULTIPLE = 43,
ISC_R_KEYCONFLICT = 44,
ISC_R_BADPARSE = 45,
ISC_R_NOKEYS = 46,
ISC_R_KEY_UNKNOWN = 47,
ISC_R_INVALIDKEY = 48,
ISC_R_INCOMPLETE = 49,
ISC_R_FORMERR = 50,
ISC_R_SERVFAIL = 51,
ISC_R_NXDOMAIN = 52,
ISC_R_NOTIMPL = 53,
ISC_R_REFUSED = 54,
ISC_R_YXDOMAIN = 55,
ISC_R_YXRRSET = 56,
ISC_R_NXRRSET = 57,
ISC_R_NOTAUTH = 58,
ISC_R_NOTZONE = 59,
ISC_R_BADSIG = 60,
ISC_R_BADKEY = 61,
ISC_R_BADTIME = 62,
ISC_R_NOROOTZONE = 63,
ISC_R_DESTADDRREQ = 64,
ISC_R_CROSSZONE = 65,
ISC_R_NO_TSIG = 66,
ISC_R_NOT_EQUAL = 67
} isc_result_t;
#define ISC_R_NRESULTS 50 /* Number of results */
#define ISC_R_NRESULTS 68 /* Number of results */
const char * isc_result_totext(isc_result_t);
isc_result_t isc_result_register(unsigned int base,

View File

@ -26,7 +26,6 @@
*** Core Types.
***/
typedef unsigned int isc_result_t;
typedef struct isc_mem isc_mem_t;
typedef struct isc_mempool isc_mempool_t;
typedef struct isc_msgcat isc_msgcat_t;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000 by Internet Software Consortium.
* Copyright (c) 2001 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -20,6 +20,7 @@
#include "minires/resolv.h"
#include "minires/res_update.h"
#include "isc/result.h"
/*
* Based on the Dynamic DNS reference implementation by Viraj Bais
@ -32,8 +33,9 @@ ns_updrec *minires_mkupdrec (int, const char *, unsigned int,
unsigned int, unsigned long);
void minires_freeupdrec (ns_updrec *);
int minires_nmkupdate (res_state, ns_updrec *, double *, unsigned *);
ns_rcode minires_nupdate (res_state, ns_updrec *);
isc_result_t minires_nupdate (res_state, ns_updrec *);
int minires_ninit (res_state);
ns_rcode isc_rcode_to_ns (isc_result_t);
#if defined (MINIRES_LIB)
#define res_update minires_update
@ -118,12 +120,12 @@ const char *res_servicename(u_int16_t, const char *);
u_int32_t ns_datetosecs (const char *cp, int *errp);
int b64_pton (char const *, unsigned char *, size_t);
unsigned int res_randomid (void);
ns_rcode res_findzonecut (res_state, const char *, ns_class, int, char *,
size_t, struct in_addr *, int, int *, void *);
int res_nsend (res_state,
double *, unsigned, double *, unsigned);
int res_nsendsigned (res_state, double *,
unsigned, ns_tsig_key *, double *, unsigned);
isc_result_t res_findzonecut (res_state, const char *, ns_class, int, char *,
size_t, struct in_addr *, int, int *, void *);
isc_result_t res_nsend (res_state,
double *, unsigned, double *, unsigned, unsigned *);
isc_result_t res_nsendsigned (res_state, double *, unsigned, ns_tsig_key *,
double *, unsigned, unsigned *);
int ns_samename (const char *, const char *);
int res_nameinquery (const char *, int, int,
const unsigned char *, const unsigned char *);
@ -135,27 +137,29 @@ unsigned int ns_get16 (const unsigned char *);
void res_close (void);
void res_nclose (res_state);
int res_ourserver_p (const res_state, const struct sockaddr_in *);
int ns_sign (unsigned char *, unsigned *,
unsigned, int, void *, const unsigned char *,
unsigned, unsigned char *, unsigned *, time_t);
isc_result_t ns_sign (unsigned char *, unsigned *,
unsigned, int, void *, const unsigned char *,
unsigned, unsigned char *, unsigned *, time_t);
const char *p_class (int);
const char *p_section (int section, int opcode);
int ns_makecanon (const char *, char *, size_t);
int ns_parserr (ns_msg *, ns_sect, int, ns_rr *);
isc_result_t ns_makecanon (const char *, char *, size_t);
isc_result_t ns_parserr (ns_msg *, ns_sect, int, ns_rr *);
int ns_samedomain (const char *, const char *);
int ns_name_uncompress (const u_char *, const u_char *,
const u_char *, char *, size_t);
int res_nmkquery (res_state, int,
const char *, ns_class, ns_type, const unsigned char *,
unsigned, const unsigned char *, double *, unsigned);
isc_result_t res_nmkquery (res_state, int, const char *, ns_class, ns_type,
const unsigned char *, unsigned,
const unsigned char *, double *,
unsigned, unsigned *);
int ns_initparse (const unsigned char *, unsigned, ns_msg *);
int res_nquery(res_state, const char *,
ns_class, ns_type, double *, unsigned anslen);
int res_nsearch(res_state, const char *,
ns_class, ns_type, double *, unsigned);
isc_result_t res_nquery(res_state, const char *,
ns_class, ns_type, double *, unsigned, unsigned *);
isc_result_t res_nsearch(res_state, const char *,
ns_class, ns_type, double *, unsigned, unsigned *);
const char *res_hostalias (const res_state, const char *, char *, size_t);
int res_nquerydomain(res_state, const char *, const char *,
ns_class class, ns_type type, double *, unsigned);
isc_result_t res_nquerydomain(res_state, const char *, const char *,
ns_class class, ns_type type,
double *, unsigned, unsigned *);
int ns_skiprr(const unsigned char *, const unsigned char *, ns_sect, int);
int dn_skipname (const unsigned char *, const unsigned char *);
@ -170,10 +174,10 @@ void putUShort (unsigned char *, u_int32_t);
void putShort (unsigned char *, int32_t);
void putUChar (unsigned char *, u_int32_t);
int ns_name_ntol (const unsigned char *, unsigned char *, size_t);
int ns_sign_tcp_init (void *,
const unsigned char *, unsigned, ns_tcp_tsig_state *);
int ns_sign_tcp (unsigned char *,
unsigned *, unsigned, int, ns_tcp_tsig_state *, int);
isc_result_t ns_sign_tcp_init (void *, const unsigned char *,
unsigned, ns_tcp_tsig_state *);
isc_result_t ns_sign_tcp (unsigned char *,
unsigned *, unsigned, int, ns_tcp_tsig_state *, int);
int ns_name_ntop (const unsigned char *, char *, size_t);
int ns_name_pton (const char *, unsigned char *, size_t);
int ns_name_unpack (const unsigned char *, const unsigned char *,
@ -185,11 +189,13 @@ int ns_name_compress (const char *, unsigned char *,
int ns_name_skip (const unsigned char **, const unsigned char *);
int ns_subdomain (const char *, const char *);
unsigned char *ns_find_tsig (unsigned char *, unsigned char *);
int ns_verify (unsigned char *, unsigned *, void *, const unsigned char *,
unsigned, unsigned char *, unsigned *, time_t *, int);
int ns_verify_tcp_init (void *,
const unsigned char *, unsigned, ns_tcp_tsig_state *);
int ns_verify_tcp (unsigned char *, unsigned *, ns_tcp_tsig_state *, int);
isc_result_t ns_verify (unsigned char *, unsigned *, void *,
const unsigned char *,
unsigned, unsigned char *, unsigned *, time_t *, int);
isc_result_t ns_verify_tcp_init (void *, const unsigned char *, unsigned,
ns_tcp_tsig_state *);
isc_result_t ns_verify_tcp (unsigned char *, unsigned *,
ns_tcp_tsig_state *, int);
int b64_ntop (unsigned char const *, size_t, char *, size_t);
ns_rcode find_cached_zone (const char *, ns_class, char *,
@ -198,6 +204,8 @@ int find_tsig_key (ns_tsig_key **, const char *, void *);
int forget_zone (void *);
int repudiate_zone (void *);
void cache_found_zone (ns_class, char *, struct in_addr *, int);
isc_result_t uerr2isc (int);
isc_result_t ns_rcode_to_isc (int);
#define DprintQ(a,b,c,d)
#define Dprint(a,b)
@ -207,3 +215,7 @@ void cache_found_zone (ns_class, char *, struct in_addr *, int);
#define USE_MD5
#endif
#if defined (TRACING)
void trace_mr_statp_setup (res_state);
#endif

View File

@ -16,7 +16,7 @@
*/
/*
* $Id: res_update.h,v 1.1.1.1 2000/04/22 07:11:51 mellon Exp $
* $Id: res_update.h,v 1.1.1.2 2001/04/02 21:57:07 mellon Exp $
*/
#ifndef __RES_UPDATE_H
@ -36,7 +36,8 @@ typedef struct ns_updrec {
ns_class r_class; /* class number */
ns_type r_type; /* type number */
u_int32_t r_ttl; /* time to live */
unsigned char* r_data; /* rdata fields as text string */
const unsigned char *r_data; /* rdata fields as text string */
unsigned char *r_data_ephem; /* pointer to freeable r_data */
unsigned int r_size; /* size of r_data field */
int r_opcode; /* type of operation */
/* following fields for private use by the resolver/server

View File

@ -85,7 +85,8 @@ struct rc_history_entry {
rc_history [rc_history_index].addr = (y); \
rc_history [rc_history_index].refcnt = (z); \
if (++rc_history_index == RC_HISTORY_MAX) \
rc_history_index = 0;\
rc_history_index = 0; \
++rc_history_count; \
} while (0)
#define rc_register_mdl(r, y, z) \
rc_register (__FILE__, __LINE__, r, y, z)
@ -105,4 +106,5 @@ extern unsigned long dmalloc_cutoff_generation;
#if defined (DEBUG_RC_HISTORY)
extern struct rc_history_entry rc_history [RC_HISTORY_MAX];
extern int rc_history_index;
extern int rc_history_count;
#endif

View File

@ -3,7 +3,7 @@
Definitions for the object management API and protocol... */
/*
* Copyright (c) 1996-1999 Internet Software Consortium.
* Copyright (c) 1996-2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -192,6 +192,75 @@ isc_result_t name##_reference (stype **pptr, stype *ptr, \
const char *file, int line); \
isc_result_t name##_dereference (stype **ptr, const char *file, int line);
typedef isc_result_t (*omapi_array_ref_t) (char **, char *, const char *, int);
typedef isc_result_t (*omapi_array_deref_t) (char **, const char *, int);
/* An extensible array type. */
typedef struct {
char **data;
omapi_array_ref_t ref;
omapi_array_deref_t deref;
int count;
int max;
} omapi_array_t;
#define OMAPI_ARRAY_TYPE(name, stype) \
isc_result_t name##_array_allocate (omapi_array_t **p, \
const char *file, int line) \
{ \
return (omapi_array_allocate \
(p, \
(omapi_array_ref_t)name##_reference, \
(omapi_array_deref_t)name##_dereference, \
file, line)); \
} \
\
isc_result_t name##_array_extend (omapi_array_t *pptr, stype *ptr, int *index,\
const char *file, int line) \
{ \
return omapi_array_extend (pptr, (char *)ptr, index, file, line); \
} \
\
isc_result_t name##_array_set (omapi_array_t *pptr, stype *ptr, int index, \
const char *file, int line) \
{ \
return omapi_array_set (pptr, (char *)ptr, index, file, line); \
} \
\
isc_result_t name##_array_lookup (stype **ptr, omapi_array_t *pptr, \
int index, const char *file, int line) \
{ \
return omapi_array_lookup ((char **)ptr, pptr, index, file, line); \
}
#define OMAPI_ARRAY_TYPE_DECL(name, stype) \
isc_result_t name##_array_allocate (omapi_array_t **, const char *, int); \
isc_result_t name##_array_extend (omapi_array_t *, stype *, int *, \
const char *, int); \
isc_result_t name##_array_set (omapi_array_t *, \
stype *, int, const char *, int); \
isc_result_t name##_array_lookup (stype **, \
omapi_array_t *, int, const char *, int)
#define omapi_array_foreach_begin(array, stype, var) \
{ \
int omapi_array_foreach_index; \
stype *var = (stype *)0; \
for (omapi_array_foreach_index = 0; \
omapi_array_foreach_index < (array) -> count; \
omapi_array_foreach_index++) { \
if ((array) -> data [omapi_array_foreach_index]) { \
((*(array) -> ref) \
((char **)&var, \
(array) -> data [omapi_array_foreach_index],\
MDL));
#define omapi_array_foreach_end(array, stype, var) \
(*(array) -> deref) ((char **)&var, MDL); \
} \
} \
}
isc_result_t omapi_protocol_connect (omapi_object_t *,
const char *, unsigned, omapi_object_t *);
isc_result_t omapi_connect_list (omapi_object_t *, omapi_addr_list_t *,
@ -520,4 +589,12 @@ isc_result_t omapi_addr_list_reference (omapi_addr_list_t **,
isc_result_t omapi_addr_list_dereference (omapi_addr_list_t **,
const char *, int);
isc_result_t omapi_array_allocate (omapi_array_t **, omapi_array_ref_t,
omapi_array_deref_t, const char *, int);
isc_result_t omapi_array_extend (omapi_array_t *, char *, int *,
const char *, int);
isc_result_t omapi_array_set (omapi_array_t *, void *, int, const char *, int);
isc_result_t omapi_array_lookup (char **,
omapi_array_t *, int, const char *, int);
OMAPI_ARRAY_TYPE_DECL(omapi_object, omapi_object_t);
#endif /* _OMAPIP_H_ */

View File

@ -3,7 +3,7 @@
Private master include file for the OMAPI library. */
/*
* Copyright (c) 1996-2000 Internet Software Consortium.
* Copyright (c) 1996-2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -75,6 +75,7 @@
#include <omapip/convert.h>
#include <omapip/hash.h>
#include <omapip/omapip.h>
#include <omapip/trace.h>
/* OMAPI protocol header, version 1.00 */
typedef struct {
@ -172,6 +173,7 @@ typedef struct {
typedef struct __omapi_listener_object {
OMAPI_OBJECT_PREAMBLE;
int socket; /* Connection socket. */
int index;
struct sockaddr_in address;
isc_result_t (*verify_addr) (omapi_object_t *, omapi_addr_t *);
} omapi_listener_object_t;
@ -179,6 +181,7 @@ typedef struct __omapi_listener_object {
typedef struct __omapi_connection_object {
OMAPI_OBJECT_PREAMBLE;
int socket; /* Connection socket. */
int32_t index;
omapi_connection_state_t state;
struct sockaddr_in remote_addr;
struct sockaddr_in local_addr;
@ -261,6 +264,19 @@ isc_result_t omapi_connection_sign_data (int mode,
const unsigned char *data,
const unsigned len,
omapi_typed_data_t **result);
isc_result_t omapi_listener_connect (omapi_connection_object_t **obj,
omapi_listener_object_t *listener,
int socket,
struct sockaddr_in *remote_addr);
void omapi_listener_trace_setup (void);
void omapi_connection_trace_setup (void);
void omapi_buffer_trace_setup (void);
void omapi_connection_register (omapi_connection_object_t *,
const char *, int);
void trace_mr_init (void);
OMAPI_ARRAY_TYPE_DECL(omapi_listener, omapi_listener_object_t);
OMAPI_ARRAY_TYPE_DECL(omapi_connection, omapi_connection_object_t);
extern int log_priority;
extern int log_perror;

View File

@ -0,0 +1,123 @@
/* trace.h
Definitions for omapi tracing facility... */
/*
* Copyright (c) 2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of The Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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.
*
* This software has been written for the Internet Software Consortium
* by Ted Lemon, as part of a project for Nominum, Inc. To learn more
* about the Internet Software Consortium, see http://www.isc.org/. To
* learn more about Nominum, Inc., see ``http://www.nominum.com''.
*/
#define TRACEFILE_MAGIC 0x64484370UL /* dHCp */
#define TRACEFILE_VERSION 1
/* The first thing in a trace file is the header, which basically just
defines the version of the file. */
typedef struct {
u_int32_t magic; /* Magic number for trace file. */
u_int32_t version; /* Version of file. */
int32_t hlen; /* Length of this header. */
int32_t phlen; /* Length of packet headers. */
} tracefile_header_t;
/* The trace file is composed of a bunch of trace packets. Each such packet
has a type, followed by a length, followed by a timestamp, followed by
the actual contents of the packet. The type indexes are not fixed -
they are allocated either on readback or when writing a trace file.
One index type is reserved - type zero means that this record is a type
name to index mapping. */
typedef struct {
u_int32_t type_index; /* Index to the type of handler that this
packet needs. */
u_int32_t length; /* Length of the packet. This includes
everything except the fixed header. */
u_int32_t when; /* When the packet was written. */
u_int32_t pad; /* Round this out to a quad boundary. */
} tracepacket_t;
#define TRACE_INDEX_MAPPING_SIZE 4 /* trace_index_mapping_t less name. */
typedef struct {
u_int32_t index;
char name [1];
} trace_index_mapping_t;
struct trace_type; /* forward */
typedef struct trace_type trace_type_t;
struct trace_type {
trace_type_t *next;
int index;
char *name;
void *baggage;
void (*have_packet) (trace_type_t *, unsigned, char *);
void (*stop_tracing) (trace_type_t *);
};
typedef struct trace_iov {
const char *buf;
unsigned len;
} trace_iov_t;
typedef struct {
u_int16_t addrtype;
u_int16_t addrlen;
u_int8_t address [16];
u_int16_t port;
} trace_addr_t;
int trace_playback (void);
int trace_record (void);
isc_result_t trace_init (void (*set_time) (u_int32_t), const char *, int);
isc_result_t trace_begin (const char *, const char *, int);
isc_result_t trace_write_packet (trace_type_t *, unsigned, const char *,
const char *, int);
isc_result_t trace_write_packet_iov (trace_type_t *, int, trace_iov_t *,
const char *, int);
void trace_type_stash (trace_type_t *);
trace_type_t *trace_type_register (const char *, void *,
void (*) (trace_type_t *,
unsigned, char *),
void (*) (trace_type_t *),
const char *, int);
void trace_stop (void);
void trace_index_map_input (trace_type_t *, unsigned, char *);
void trace_index_stop_tracing (trace_type_t *);
void trace_replay_init (void);
void trace_file_replay (const char *);
isc_result_t trace_get_next_packet (trace_type_t **, tracepacket_t *,
char **, unsigned *, unsigned *);
isc_result_t trace_get_file (trace_type_t *,
const char *, unsigned *, char **);
isc_result_t trace_get_packet (trace_type_t **, unsigned *, char **);
time_t trace_snoop_time (trace_type_t **);

View File

@ -45,6 +45,7 @@ struct executable_statement {
int refcnt;
struct executable_statement *next;
enum statement_op {
null_statement,
if_statement,
add_statement,
eval_statement,
@ -84,6 +85,7 @@ struct executable_statement {
# define ON_COMMIT 1
# define ON_EXPIRY 2
# define ON_RELEASE 4
# define ON_TRANSMISSION 8
struct executable_statement *statements;
} on;
struct {

View File

@ -3,7 +3,7 @@
Definitions for address trees... */
/*
* Copyright (c) 1996-1999 Internet Software Consortium.
* Copyright (c) 1996-2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -47,6 +47,22 @@ typedef struct _pair {
struct _pair *cdr;
} *pair;
struct option_chain_head {
int refcnt;
pair first;
};
struct enumeration_value {
const char *name;
u_int8_t value;
};
struct enumeration {
struct enumeration *next;
const char *name;
struct enumeration_value *values;
};
/* Tree node types... */
#define TREE_CONCAT 1
#define TREE_HOST_LOOKUP 2
@ -182,7 +198,8 @@ enum expr_op {
expr_remainder,
expr_binary_and,
expr_binary_or,
expr_binary_xor
expr_binary_xor,
expr_client_state
};
struct expression {
@ -281,6 +298,7 @@ struct packet; /* forward */
struct option_state; /* forward */
struct decoded_option_state; /* forward */
struct lease; /* forward */
struct client_state; /* forward */
struct universe {
const char *name;
@ -289,11 +307,13 @@ struct universe {
unsigned);
void (*save_func) (struct universe *, struct option_state *,
struct option_cache *);
void (*foreach) (struct packet *, struct lease *,
void (*foreach) (struct packet *,
struct lease *, struct client_state *,
struct option_state *, struct option_state *,
struct binding_scope **, struct universe *, void *,
void (*) (struct option_cache *, struct packet *,
struct lease *, struct option_state *,
struct lease *, struct client_state *,
struct option_state *,
struct option_state *,
struct binding_scope **,
struct universe *, void *));
@ -303,10 +323,10 @@ struct universe {
struct option_state *,
const char *, int);
int (*decode) (struct option_state *,
unsigned char *, unsigned, struct universe *);
const unsigned char *, unsigned, struct universe *);
int (*encapsulate) (struct data_string *, struct packet *,
struct lease *, struct option_state *,
struct option_state *,
struct lease *, struct client_state *,
struct option_state *, struct option_state *,
struct binding_scope **,
struct universe *);
void (*store_tag) PROTO ((unsigned char *, u_int32_t));

View File

@ -23,14 +23,12 @@ MAN = dhcpctl.3
SRC = res_mkupdate.c res_init.c res_update.c res_send.c res_comp.c \
res_sendsigned.c res_findzonecut.c res_query.c res_mkquery.c \
ns_date.c ns_parse.c ns_sign.c ns_name.c ns_samedomain.c ns_verify.c \
dst_api.c hmac_link.c md5_dgst.c prandom.c support.c base64.c
toisc.c
OBJ = res_mkupdate.o res_init.o res_update.o res_send.o res_comp.o \
res_sendsigned.o res_findzonecut.o res_query.o res_mkquery.o \
ns_date.o ns_parse.o ns_sign.o ns_name.o ns_samedomain.o ns_verify.o \
dst_api.o hmac_link.o md5_dgst.o prandom.o support.o base64.o
HDRS = dst_internal.h md5.h md5_locl.h
toisc.o
DEBUG = -g
INCLUDES = $(BINDINC) -I$(TOP)/includes
CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS) -DHMAC_MD5 -DMINIRES_LIB

View File

@ -16,7 +16,7 @@
*/
#ifndef lint
static const char rcsid[] = "$Id: ns_parse.c,v 1.1.1.1 2000/04/22 07:11:54 mellon Exp $";
static const char rcsid[] = "$Id: ns_parse.c,v 1.1.1.2 2001/04/02 21:57:08 mellon Exp $";
#endif
/* Import. */
@ -127,13 +127,13 @@ ns_initparse(const u_char *msg, unsigned msglen, ns_msg *handle) {
return (0);
}
int
isc_result_t
ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
int b;
/* Make section right. */
if (section < 0 || section >= ns_s_max)
RETERR(ENODEV);
return ISC_R_NOTIMPLEMENTED;
if (section != handle->_sect)
setsection(handle, section);
@ -161,7 +161,7 @@ ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
return (-1);
handle->_ptr += b;
if (handle->_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom)
RETERR(EMSGSIZE);
return ISC_R_NOSPACE;
rr->type = getUShort (handle->_ptr);
handle -> _ptr += 2;
rr->rr_class = getUShort (handle->_ptr);
@ -172,13 +172,13 @@ ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
rr->rdata = NULL;
} else {
if (handle->_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom)
RETERR(EMSGSIZE);
return ISC_R_NOSPACE;
rr->ttl = getULong (handle->_ptr);
handle -> _ptr += 4;
rr->rdlength = getUShort (handle->_ptr);
handle -> _ptr += 2;
if (handle->_ptr + rr->rdlength > handle->_eom)
RETERR(EMSGSIZE);
return ISC_R_NOSPACE;
rr->rdata = handle->_ptr;
handle->_ptr += rr->rdlength;
}
@ -186,7 +186,7 @@ ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
setsection(handle, (ns_sect)((int)section + 1));
/* All done. */
return (0);
return ISC_R_SUCCESS;
}
/* Private. */

View File

@ -16,7 +16,7 @@
*/
#ifndef lint
static const char rcsid[] = "$Id: ns_samedomain.c,v 1.1.1.1 2000/04/22 07:11:54 mellon Exp $";
static const char rcsid[] = "$Id: ns_samedomain.c,v 1.1.1.2 2001/04/02 21:57:08 mellon Exp $";
#endif
#include <sys/types.h>
@ -163,13 +163,12 @@ ns_subdomain(const char *a, const char *b) {
* foo\\. -> foo\\.
*/
int
isc_result_t
ns_makecanon(const char *src, char *dst, size_t dstsize) {
size_t n = strlen(src);
if (n + sizeof "." > dstsize) {
errno = EMSGSIZE;
return (-1);
ISC_R_NOSPACE;
}
strcpy(dst, src);
while (n > 0 && dst[n - 1] == '.') /* Ends in "." */
@ -180,7 +179,7 @@ ns_makecanon(const char *src, char *dst, size_t dstsize) {
dst[--n] = '\0';
dst[n++] = '.';
dst[n] = '\0';
return (0);
return ISC_R_SUCCESS;
}
/*
@ -196,9 +195,13 @@ ns_makecanon(const char *src, char *dst, size_t dstsize) {
int
ns_samename(const char *a, const char *b) {
char ta[NS_MAXDNAME], tb[NS_MAXDNAME];
isc_result_t status;
if (ns_makecanon(a, ta, sizeof ta) < 0 ||
ns_makecanon(b, tb, sizeof tb) < 0)
status = ns_makecanon(a, ta, sizeof ta);
if (status != ISC_R_SUCCESS)
return status;
status = ns_makecanon(b, tb, sizeof tb);
if (status != ISC_R_SUCCESS)
return (-1);
if (strcasecmp(ta, tb) == 0)
return (1);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999 by Internet Software Consortium, Inc.
* Copyright (c) 1999-2001 by Internet Software Consortium, Inc.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -16,7 +16,12 @@
*/
#ifndef lint
static const char rcsid[] = "$Id: ns_sign.c,v 1.1.1.1 2000/04/22 07:11:54 mellon Exp $";
static const char rcsid[] = "$Id: ns_sign.c,v 1.1.1.2 2001/04/02 21:57:09 mellon Exp $";
#endif
#if defined (TRACING)
#define time(x) trace_mr_time (x)
time_t trace_mr_time (time_t *);
#endif
/* Import. */
@ -44,8 +49,7 @@ static const char rcsid[] = "$Id: ns_sign.c,v 1.1.1.1 2000/04/22 07:11:54 mellon
#define BOUNDS_CHECK(ptr, count) \
do { \
if ((ptr) + (count) > eob) { \
errno = EMSGSIZE; \
return(NS_TSIG_ERROR_NO_SPACE); \
return ISC_R_NOSPACE; \
} \
} while (0)
@ -68,7 +72,7 @@ static const char rcsid[] = "$Id: ns_sign.c,v 1.1.1.1 2000/04/22 07:11:54 mellon
* - bad key / sign failed (-BADKEY)
* - not enough space (NS_TSIG_ERROR_NO_SPACE)
*/
int
isc_result_t
ns_sign(u_char *msg, unsigned *msglen, unsigned msgsize, int error, void *k,
const u_char *querysig, unsigned querysiglen, u_char *sig,
unsigned *siglen, time_t in_timesigned)
@ -83,7 +87,7 @@ ns_sign(u_char *msg, unsigned *msglen, unsigned msgsize, int error, void *k,
dst_init();
if (msg == NULL || msglen == NULL || sig == NULL || siglen == NULL)
return (-1);
ISC_R_INVALIDARG;
/* Name. */
if (key != NULL && error != ns_r_badsig && error != ns_r_badkey)
@ -92,7 +96,7 @@ ns_sign(u_char *msg, unsigned *msglen, unsigned msgsize, int error, void *k,
else
n = dn_comp("", cp, (unsigned)(eob - cp), NULL, NULL);
if (n < 0)
return (NS_TSIG_ERROR_NO_SPACE);
return ISC_R_NOSPACE;
name = cp;
cp += n;
@ -107,14 +111,14 @@ ns_sign(u_char *msg, unsigned *msglen, unsigned msgsize, int error, void *k,
/* Alg. */
if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) {
if (key->dk_alg != KEY_HMAC_MD5)
return (-ns_r_badkey);
return ISC_R_BADKEY;
n = dn_comp(NS_TSIG_ALG_HMAC_MD5,
cp, (unsigned)(eob - cp), NULL, NULL);
}
else
n = dn_comp("", cp, (unsigned)(eob - cp), NULL, NULL);
if (n < 0)
return (NS_TSIG_ERROR_NO_SPACE);
ISC_R_NOSPACE;
alg = cp;
cp += n;
@ -186,7 +190,7 @@ ns_sign(u_char *msg, unsigned *msglen, unsigned msgsize, int error, void *k,
n = dst_sign_data(SIG_MODE_FINAL, key, &ctx, NULL, 0,
sig, *siglen);
if (n < 0)
return (-ns_r_badkey);
ISC_R_BADKEY;
*siglen = n;
} else
*siglen = 0;
@ -218,28 +222,29 @@ ns_sign(u_char *msg, unsigned *msglen, unsigned msgsize, int error, void *k,
hp->arcount = htons(ntohs(hp->arcount) + 1);
*msglen = (cp - msg);
return (0);
return ISC_R_SUCCESS;
}
int
#if 0
isc_result_t
ns_sign_tcp_init(void *k, const u_char *querysig, unsigned querysiglen,
ns_tcp_tsig_state *state)
{
dst_init();
if (state == NULL || k == NULL || querysig == NULL || querysiglen < 0)
return (-1);
return ISC_R_INVALIDARG;
state->counter = -1;
state->key = k;
if (state->key->dk_alg != KEY_HMAC_MD5)
return (-ns_r_badkey);
return ISC_R_BADKEY;
if (querysiglen > sizeof(state->sig))
return (-1);
return ISC_R_NOSPACE;
memcpy(state->sig, querysig, querysiglen);
state->siglen = querysiglen;
return (0);
return ISC_R_SUCCESS;
}
int
isc_result_t
ns_sign_tcp(u_char *msg, unsigned *msglen, unsigned msgsize, int error,
ns_tcp_tsig_state *state, int done)
{
@ -250,13 +255,13 @@ ns_sign_tcp(u_char *msg, unsigned *msglen, unsigned msgsize, int error,
int n;
if (msg == NULL || msglen == NULL || state == NULL)
return (-1);
return ISC_R_INVALIDARG;
state->counter++;
if (state->counter == 0)
return (ns_sign(msg, msglen, msgsize, error, state->key,
state->sig, state->siglen,
state->sig, &state->siglen, 0));
return ns_sign(msg, msglen, msgsize, error, state->key,
state->sig, state->siglen,
state->sig, &state->siglen, 0);
if (state->siglen > 0) {
u_int16_t siglen_n = htons(state->siglen);
@ -273,7 +278,7 @@ ns_sign_tcp(u_char *msg, unsigned *msglen, unsigned msgsize, int error,
NULL, 0);
if (done == 0 && (state->counter % 100 != 0))
return (0);
return ISC_R_SUCCESS;
cp = msg + *msglen;
eob = msg + msgsize;
@ -282,7 +287,7 @@ ns_sign_tcp(u_char *msg, unsigned *msglen, unsigned msgsize, int error,
n = dn_comp(state->key->dk_key_name,
cp, (unsigned)(eob - cp), NULL, NULL);
if (n < 0)
return (NS_TSIG_ERROR_NO_SPACE);
return ISC_R_NOSPACE;
cp += n;
/* Type, class, ttl, length (not filled in yet). */
@ -297,7 +302,7 @@ ns_sign_tcp(u_char *msg, unsigned *msglen, unsigned msgsize, int error,
n = dn_comp(NS_TSIG_ALG_HMAC_MD5,
cp, (unsigned)(eob - cp), NULL, NULL);
if (n < 0)
return (NS_TSIG_ERROR_NO_SPACE);
return ISC_R_NOSPACE;
cp += n;
/* Time. */
@ -323,7 +328,7 @@ ns_sign_tcp(u_char *msg, unsigned *msglen, unsigned msgsize, int error,
n = dst_sign_data(SIG_MODE_FINAL, state->key, &state->ctx, NULL, 0,
state->sig, sizeof(state->sig));
if (n < 0)
return (-ns_r_badkey);
return ISC_R_BADKEY;
state->siglen = n;
/* Add the signature. */
@ -346,5 +351,6 @@ ns_sign_tcp(u_char *msg, unsigned *msglen, unsigned msgsize, int error,
hp->arcount = htons(ntohs(hp->arcount) + 1);
*msglen = (cp - msg);
return (0);
return ISC_R_SUCCESS;
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999 by Internet Software Consortium, Inc.
* Copyright (c) 1999-2001 by Internet Software Consortium, Inc.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -16,9 +16,11 @@
*/
#ifndef lint
static const char rcsid[] = "$Id: ns_verify.c,v 1.1.1.1 2000/04/22 07:11:54 mellon Exp $";
static const char rcsid[] = "$Id: ns_verify.c,v 1.1.1.2 2001/04/02 21:57:09 mellon Exp $";
#endif
#define time(x) trace_mr_time (x)
/* Import. */
#include <sys/types.h>
@ -40,6 +42,8 @@ static const char rcsid[] = "$Id: ns_verify.c,v 1.1.1.1 2000/04/22 07:11:54 mell
#include "arpa/nameser.h"
#include <isc/dst.h>
time_t trace_mr_time (time_t *);
/* Private. */
#define BOUNDS_CHECK(ptr, count) \
@ -126,7 +130,7 @@ ns_find_tsig(u_char *msg, u_char *eom) {
* - TSIG verification succeeds, error set to BADSIG (ns_r_badsig)
* - TSIG verification succeeds, error set to BADTIME (ns_r_badtime)
*/
int
isc_result_t
ns_verify(u_char *msg, unsigned *msglen, void *k,
const u_char *querysig, unsigned querysiglen,
u_char *sig, unsigned *siglen, time_t *timesigned, int nostrip)
@ -144,41 +148,41 @@ ns_verify(u_char *msg, unsigned *msglen, void *k,
dst_init();
if (msg == NULL || msglen == NULL || *msglen < 0)
return (-1);
return ISC_R_INVALIDARG;
eom = msg + *msglen;
recstart = ns_find_tsig(msg, eom);
if (recstart == NULL)
return (NS_TSIG_ERROR_NO_TSIG);
return ISC_R_NO_TSIG;
cp = recstart;
/* Read the key name. */
n = dn_expand(msg, eom, cp, name, MAXDNAME);
if (n < 0)
return (NS_TSIG_ERROR_FORMERR);
return ISC_R_FORMERR;
cp += n;
/* Read the type. */
BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ);
GETSHORT(type, cp);
if (type != ns_t_tsig)
return (NS_TSIG_ERROR_NO_TSIG);
return ISC_R_NO_TSIG;
/* Skip the class and TTL, save the length. */
cp += INT16SZ + INT32SZ;
GETSHORT(length, cp);
if (eom - cp != length)
return (NS_TSIG_ERROR_FORMERR);
return ISC_R_FORMERR;
/* Read the algorithm name. */
rdatastart = cp;
n = dn_expand(msg, eom, cp, alg, MAXDNAME);
if (n < 0)
return (NS_TSIG_ERROR_FORMERR);
return ISC_R_FORMERR;
if (ns_samename(alg, NS_TSIG_ALG_HMAC_MD5) != 1)
return (-ns_r_badkey);
return ISC_R_INVALIDKEY;
cp += n;
/* Read the time signed and fudge. */
@ -207,15 +211,15 @@ ns_verify(u_char *msg, unsigned *msglen, void *k,
cp += otherfieldlen;
if (cp != eom)
return (NS_TSIG_ERROR_FORMERR);
return ISC_R_FORMERR;
/* Verify that the key used is OK. */
if (key != NULL) {
if (key->dk_alg != KEY_HMAC_MD5)
return (-ns_r_badkey);
return ISC_R_INVALIDKEY;
if (error != ns_r_badsig && error != ns_r_badkey) {
if (ns_samename(key->dk_key_name, name) != 1)
return (-ns_r_badkey);
return ISC_R_INVALIDKEY;
}
}
@ -271,17 +275,17 @@ ns_verify(u_char *msg, unsigned *msglen, void *k,
sigstart, sigfieldlen);
if (n < 0)
return (-ns_r_badsig);
return ISC_R_BADSIG;
if (sig != NULL && siglen != NULL) {
if (*siglen < sigfieldlen)
return (NS_TSIG_ERROR_NO_SPACE);
return ISC_R_NOSPACE;
memcpy(sig, sigstart, sigfieldlen);
*siglen = sigfieldlen;
}
} else {
if (sigfieldlen > 0)
return (NS_TSIG_ERROR_FORMERR);
return ISC_R_FORMERR;
if (sig != NULL && siglen != NULL)
*siglen = 0;
}
@ -291,7 +295,7 @@ ns_verify(u_char *msg, unsigned *msglen, void *k,
/* Verify the time. */
if (abs((*timesigned) - time(NULL)) > fudge)
return (-ns_r_badtime);
return ISC_R_BADTIME;
if (nostrip == 0) {
*msglen = recstart - msg;
@ -299,30 +303,31 @@ ns_verify(u_char *msg, unsigned *msglen, void *k,
}
if (error != NOERROR)
return (error);
return ns_rcode_to_isc (error);
return (0);
return ISC_R_SUCCESS;
}
int
#if 0
isc_result_t
ns_verify_tcp_init(void *k, const u_char *querysig, unsigned querysiglen,
ns_tcp_tsig_state *state)
{
dst_init();
if (state == NULL || k == NULL || querysig == NULL || querysiglen < 0)
return (-1);
return ISC_R_INVALIDARG;
state->counter = -1;
state->key = k;
if (state->key->dk_alg != KEY_HMAC_MD5)
return (-ns_r_badkey);
return ISC_R_BADKEY;
if (querysiglen > sizeof(state->sig))
return (-1);
return ISC_R_NOSPACE;
memcpy(state->sig, querysig, querysiglen);
state->siglen = querysiglen;
return (0);
return ISC_R_SUCCESS;
}
int
isc_result_t
ns_verify_tcp(u_char *msg, unsigned *msglen, ns_tcp_tsig_state *state,
int required)
{
@ -336,7 +341,7 @@ ns_verify_tcp(u_char *msg, unsigned *msglen, ns_tcp_tsig_state *state,
time_t timesigned;
if (msg == NULL || msglen == NULL || state == NULL)
return (-1);
return ISC_R_INVALIDARG;
state->counter++;
if (state->counter == 0)
@ -360,10 +365,10 @@ ns_verify_tcp(u_char *msg, unsigned *msglen, ns_tcp_tsig_state *state,
if (recstart == NULL) {
if (required)
return (NS_TSIG_ERROR_NO_TSIG);
return ISC_R_NO_TSIG;
dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx,
msg, *msglen, NULL, 0);
return (0);
return ISC_R_SUCCESS;
}
hp->arcount = htons(ntohs(hp->arcount) - 1);
@ -373,34 +378,34 @@ ns_verify_tcp(u_char *msg, unsigned *msglen, ns_tcp_tsig_state *state,
/* Read the key name. */
n = dn_expand(msg, eom, cp, name, MAXDNAME);
if (n < 0)
return (NS_TSIG_ERROR_FORMERR);
return ISC_R_FORMERR;
cp += n;
/* Read the type. */
BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ);
GETSHORT(type, cp);
if (type != ns_t_tsig)
return (NS_TSIG_ERROR_NO_TSIG);
return ISC_R_NO_TSIG;
/* Skip the class and TTL, save the length. */
cp += INT16SZ + INT32SZ;
GETSHORT(length, cp);
if (eom - cp != length)
return (NS_TSIG_ERROR_FORMERR);
return ISC_R_FORMERR;
/* Read the algorithm name. */
rdatastart = cp;
n = dn_expand(msg, eom, cp, alg, MAXDNAME);
if (n < 0)
return (NS_TSIG_ERROR_FORMERR);
return ISC_R_FORMERR;
if (ns_samename(alg, NS_TSIG_ALG_HMAC_MD5) != 1)
return (-ns_r_badkey);
return ISC_R_BADKEY;
cp += n;
/* Verify that the key used is OK. */
if ((ns_samename(state->key->dk_key_name, name) != 1 ||
state->key->dk_alg != KEY_HMAC_MD5))
return (-ns_r_badkey);
return ISC_R_BADKEY;
/* Read the time signed and fudge. */
BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ);
@ -427,7 +432,7 @@ ns_verify_tcp(u_char *msg, unsigned *msglen, ns_tcp_tsig_state *state,
cp += otherfieldlen;
if (cp != eom)
return (NS_TSIG_ERROR_FORMERR);
return ISC_R_FORMERR;
/*
* Do the verification.
@ -445,25 +450,26 @@ ns_verify_tcp(u_char *msg, unsigned *msglen, ns_tcp_tsig_state *state,
n = dst_verify_data(SIG_MODE_FINAL, state->key, &state->ctx, NULL, 0,
sigstart, sigfieldlen);
if (n < 0)
return (-ns_r_badsig);
return ISC_R_BADSIG;
if (sigfieldlen > sizeof(state->sig))
return (ns_r_badsig);
return ISC_R_BADSIG;
if (sigfieldlen > sizeof(state->sig))
return (NS_TSIG_ERROR_NO_SPACE);
return ISC_R_NOSPACE;
memcpy(state->sig, sigstart, sigfieldlen);
state->siglen = sigfieldlen;
/* Verify the time. */
if (abs(timesigned - time(NULL)) > fudge)
return (-ns_r_badtime);
return ISC_R_BADTIME;
*msglen = recstart - msg;
if (error != NOERROR)
return (error);
return ns_rcode_to_isc (error);
return (0);
return ISC_R_SUCCESS;
}
#endif

View File

@ -1,5 +1,5 @@
#if !defined(lint) && !defined(SABER)
static const char rcsid[] = "$Id: res_findzonecut.c,v 1.1.1.5 2000/10/17 15:09:34 taca Exp $";
static const char rcsid[] = "$Id: res_findzonecut.c,v 1.1.1.6 2001/04/02 21:57:09 mellon Exp $";
#endif /* not lint */
/*
@ -64,17 +64,17 @@ static int add_addrs(res_state, rr_ns *, struct in_addr *, int);
static ns_rcode get_soa(res_state, const char *, ns_class,
char *, size_t, char *, size_t,
rrset_ns *);
static int get_ns(res_state, const char *, ns_class, rrset_ns *);
static ns_rcode get_glue(res_state, ns_class, rrset_ns *);
static int save_ns(res_state, ns_msg *, ns_sect,
const char *, ns_class, rrset_ns *);
static int save_a(res_state, ns_msg *, ns_sect,
const char *, ns_class, rrset_a *);
static isc_result_t get_ns(res_state, const char *, ns_class, rrset_ns *);
static isc_result_t get_glue(res_state, ns_class, rrset_ns *);
static isc_result_t save_ns(res_state, ns_msg *, ns_sect,
const char *, ns_class, rrset_ns *);
static isc_result_t save_a(res_state, ns_msg *, ns_sect,
const char *, ns_class, rrset_a *);
static void free_nsrrset(rrset_ns *);
static void free_nsrr(rrset_ns *, rr_ns *);
static rr_ns * find_ns(rrset_ns *, const char *);
static ns_rcode do_query(res_state, const char *, ns_class, ns_type,
double *, ns_msg *, int *);
static isc_result_t do_query(res_state, const char *, ns_class, ns_type,
double *, ns_msg *, int *);
/* Public. */
@ -133,7 +133,7 @@ static ns_rcode do_query(res_state, const char *, ns_class, ns_type,
* keep going. for the NS and A queries this means we just give up.
*/
ns_rcode
isc_result_t
res_findzonecut(res_state statp, const char *dname, ns_class class, int opts,
char *zname, size_t zsize, struct in_addr *addrs, int naddrs,
int *count, void *zcookie)
@ -142,7 +142,7 @@ res_findzonecut(res_state statp, const char *dname, ns_class class, int opts,
u_long save_pfcode;
rrset_ns nsrrs;
int n = 0;
ns_rcode rcode;
isc_result_t rcode;
DPRINTF(("START dname='%s' class=%s, zsize=%ld, naddrs=%d",
dname, p_class(class), (long)zsize, naddrs));
@ -153,9 +153,9 @@ res_findzonecut(res_state statp, const char *dname, ns_class class, int opts,
ISC_LIST_INIT(nsrrs);
DPRINTF (("look for a predefined zone statement"));
rcode = find_cached_zone (dname, class, zname, zsize, addrs, naddrs,
&n, zcookie);
if (rcode == ns_r_noerror)
rcode = find_cached_zone (dname, class, zname, zsize,
addrs, naddrs, &n, zcookie);
if (rcode == ISC_R_SUCCESS)
goto done;
DPRINTF(("get the soa, and see if it has enough glue"));
@ -245,15 +245,16 @@ get_soa(res_state statp, const char *dname, ns_class class,
ns_sect sect;
ns_msg msg;
u_int rcode;
ns_rcode status;
isc_result_t status;
/*
* Find closest enclosing SOA, even if it's for the root zone.
*/
/* First canonicalize dname (exactly one unescaped trailing "."). */
if (ns_makecanon(dname, tname, sizeof tname) < 0)
return ns_r_servfail;
status = ns_makecanon(dname, tname, sizeof tname);
if (status != ISC_R_SUCCESS)
return status;
dname = tname;
/* Now grovel the subdomains, hunting for an SOA answer or auth. */
@ -289,10 +290,11 @@ get_soa(res_state statp, const char *dname, ns_class class,
int rdlen;
ns_rr rr;
if (ns_parserr(&msg, sect, i, &rr) < 0) {
rcode = ns_parserr(&msg, sect, i, &rr) < 0;
if (rcode != ISC_R_SUCCESS) {
DPRINTF(("get_soa: ns_parserr(%s, %d) failed",
p_section(sect, ns_o_query), i));
return ns_r_servfail;
return rcode;
}
if (ns_rr_type(rr) == ns_t_cname ||
ns_rr_type(rr) == ns_t_dname)
@ -304,19 +306,18 @@ get_soa(res_state statp, const char *dname, ns_class class,
switch (sect) {
case ns_s_an:
if (ns_samedomain(dname, t) == 0) {
DPRINTF(("get_soa: ns_samedomain('%s', '%s') == 0",
dname, t));
errno = EPROTOTYPE;
return ns_r_notzone;
DPRINTF(("get_soa: %s'%s', '%s') == 0",
"ns_samedomain(", dname, t));
return ISC_R_NOTZONE;
}
break;
case ns_s_ns:
if (ns_samename(dname, t) == 1 ||
ns_samedomain(dname, t) == 0) {
DPRINTF(("get_soa: ns_samename() || !ns_samedomain('%s', '%s')",
DPRINTF(("get_soa: %smain('%s', '%s')",
"ns_samename() || !ns_samedo",
dname, t));
errno = EPROTOTYPE;
return ns_r_notzone;
return ISC_R_NOTZONE;
}
break;
default:
@ -325,8 +326,7 @@ get_soa(res_state statp, const char *dname, ns_class class,
if (strlen(t) + 1 > zsize) {
DPRINTF(("get_soa: zname(%d) too small (%d)",
zsize, strlen(t) + 1));
errno = EMSGSIZE;
return ns_r_servfail;
return ISC_R_NOSPACE;
}
strcpy(zname, t);
rdata = ns_rr_rdata(rr);
@ -334,15 +334,17 @@ get_soa(res_state statp, const char *dname, ns_class class,
if (ns_name_uncompress((u_char *)resp,
ns_msg_end(msg), rdata,
mname, msize) < 0) {
DPRINTF(("get_soa: ns_name_uncompress failed"));
return ns_r_servfail;
DPRINTF(("get_soa: %s failed",
"ns_name_uncompress"));
return ISC_R_NOMEMORY;
}
if (save_ns(statp, &msg, ns_s_ns,
zname, class, nsrrsp) < 0) {
rcode = save_ns(statp, &msg,
ns_s_ns, zname, class, nsrrsp);
if (rcode != ISC_R_SUCCESS) {
DPRINTF(("get_soa: save_ns failed"));
return ns_r_servfail;
return rcode;
}
return ns_r_noerror;
return ISC_R_SUCCESS;
}
/* If we're out of labels, then not even "." has an SOA! */
@ -353,43 +355,42 @@ get_soa(res_state statp, const char *dname, ns_class class,
while (*dname != '.') {
if (*dname == '\\')
if (*++dname == '\0') {
errno = EMSGSIZE;
return ns_r_servfail;
ISC_R_NOSPACE;
}
dname++;
}
}
DPRINTF(("get_soa: out of labels"));
errno = EDESTADDRREQ;
return ns_r_servfail;
return ISC_R_DESTADDRREQ;
}
static int
static isc_result_t
get_ns(res_state statp, const char *zname, ns_class class, rrset_ns *nsrrsp) {
double resp[NS_PACKETSZ / sizeof (double)];
ns_msg msg;
int n;
ns_rcode rcode;
isc_result_t rcode;
/* Go and get the NS RRs for this zone. */
rcode = do_query(statp, zname, class, ns_t_ns, resp, &msg, &n);
if (rcode != ns_r_noerror) {
if (rcode != ISC_R_SUCCESS) {
DPRINTF(("get_ns: do_query('zname', %s) failed (%d)",
zname, p_class(class), rcode));
return rcode;
}
/* Remember the NS RRs and associated A RRs that came back. */
if (save_ns(statp, &msg, ns_s_an, zname, class, nsrrsp) < 0) {
rcode = save_ns(statp, &msg, ns_s_an, zname, class, nsrrsp);
if (rcode != ISC_R_SUCCESS) {
DPRINTF(("get_ns save_ns('%s', %s) failed",
zname, p_class(class)));
return ns_r_servfail;
return rcode;
}
return ns_r_noerror;
return ISC_R_SUCCESS;
}
static ns_rcode
static isc_result_t
get_glue(res_state statp, ns_class class, rrset_ns *nsrrsp) {
rr_ns *nsrr, *nsrr_n;
@ -398,28 +399,29 @@ get_glue(res_state statp, ns_class class, rrset_ns *nsrrsp) {
double resp[NS_PACKETSZ / sizeof (double)];
ns_msg msg;
int n;
ns_rcode rcode;
isc_result_t rcode;
nsrr_n = ISC_LIST_NEXT(nsrr, link);
if (ISC_LIST_EMPTY(nsrr->addrs)) {
rcode = do_query(statp, nsrr->name, class, ns_t_a,
resp, &msg, &n);
if (rcode != ns_r_noerror) {
DPRINTF(("get_glue: do_query('%s', %s') failed",
nsrr->name, p_class(class)));
return rcode;
if (rcode != ISC_R_SUCCESS) {
DPRINTF(("get_glue: do_query('%s', %s') failed",
nsrr->name, p_class(class)));
return rcode;
}
if (n > 0) {
DPRINTF((
"get_glue: do_query('%s', %s') CNAME or DNAME found",
nsrr->name, p_class(class)));
}
if (save_a(statp, &msg, ns_s_an, nsrr->name, class,
&nsrr->addrs) < 0) {
rcode = save_a(statp, &msg, ns_s_an, nsrr->name, class,
&nsrr->addrs);
if (rcode != ISC_R_SUCCESS) {
DPRINTF(("get_glue: save_r('%s', %s) failed",
nsrr->name, p_class(class)));
return ns_r_servfail;
return rcode;
}
/* If it's still empty, it's just chaff. */
if (ISC_LIST_EMPTY(nsrr->addrs)) {
@ -429,15 +431,16 @@ get_glue(res_state statp, ns_class class, rrset_ns *nsrrsp) {
}
}
}
return ns_r_noerror;
return ISC_R_SUCCESS;
}
static int
static isc_result_t
save_ns(res_state statp, ns_msg *msg, ns_sect sect,
const char *owner, ns_class class,
rrset_ns *nsrrsp)
{
int i;
isc_result_t rcode;
for (i = 0; i < ns_msg_count(*msg, sect); i++) {
char tname[MAXDNAME];
@ -446,10 +449,11 @@ save_ns(res_state statp, ns_msg *msg, ns_sect sect,
ns_rr rr;
int rdlen;
if (ns_parserr(msg, sect, i, &rr) < 0) {
rcode = ns_parserr(msg, sect, i, &rr);
if (rcode != ISC_R_SUCCESS) {
DPRINTF(("save_ns: ns_parserr(%s, %d) failed",
p_section(sect, ns_o_query), i));
return (-1);
return rcode;
}
if (ns_rr_type(rr) != ns_t_ns ||
ns_rr_class(rr) != class ||
@ -460,7 +464,7 @@ save_ns(res_state statp, ns_msg *msg, ns_sect sect,
nsrr = malloc(sizeof *nsrr);
if (nsrr == NULL) {
DPRINTF(("save_ns: malloc failed"));
return (-1);
return ISC_R_NOMEMORY;
}
rdata = ns_rr_rdata(rr);
rdlen = ns_rr_rdlen(rr);
@ -469,42 +473,45 @@ save_ns(res_state statp, ns_msg *msg, ns_sect sect,
tname, sizeof tname) < 0) {
DPRINTF(("save_ns: ns_name_uncompress failed"));
free(nsrr);
return (-1);
return ISC_R_NOMEMORY;
}
nsrr->name = strdup(tname);
if (nsrr->name == NULL) {
DPRINTF(("save_ns: strdup failed"));
free(nsrr);
return (-1);
return ISC_R_NOMEMORY;
}
ISC_LIST_INIT(nsrr->addrs);
ISC_LIST_APPEND(*nsrrsp, nsrr, link);
}
if (save_a(statp, msg, ns_s_ar,
nsrr->name, class, &nsrr->addrs) < 0) {
rcode = save_a(statp, msg, ns_s_ar,
nsrr->name, class, &nsrr->addrs);
if (rcode != ISC_R_SUCCESS) {
DPRINTF(("save_ns: save_r('%s', %s) failed",
nsrr->name, p_class(class)));
return (-1);
return rcode;
}
}
return (0);
return ISC_R_SUCCESS;
}
static int
static isc_result_t
save_a(res_state statp, ns_msg *msg, ns_sect sect,
const char *owner, ns_class class,
rrset_a *arrsp)
{
int i;
isc_result_t rcode;
for (i = 0; i < ns_msg_count(*msg, sect); i++) {
ns_rr rr;
rr_a *arr;
if (ns_parserr(msg, sect, i, &rr) < 0) {
rcode = ns_parserr(msg, sect, i, &rr);
if (rcode != ISC_R_SUCCESS) {
DPRINTF(("save_a: ns_parserr(%s, %d) failed",
p_section(sect, ns_o_query), i));
return (-1);
return rcode;
}
if (ns_rr_type(rr) != ns_t_a ||
ns_rr_class(rr) != class ||
@ -514,12 +521,12 @@ save_a(res_state statp, ns_msg *msg, ns_sect sect,
arr = malloc(sizeof *arr);
if (arr == NULL) {
DPRINTF(("save_a: malloc failed"));
return (-1);
return ISC_R_NOMEMORY;
}
memcpy(&arr->addr, ns_rr_rdata(rr), NS_INADDRSZ);
ISC_LIST_APPEND(*arrsp, arr, link);
}
return (0);
return ISC_R_SUCCESS;
}
static void
@ -554,41 +561,42 @@ find_ns(rrset_ns *nsrrsp, const char *dname) {
return (NULL);
}
static ns_rcode
static isc_result_t
do_query(res_state statp, const char *dname, ns_class class, ns_type qtype,
double *resp, ns_msg *msg, int *alias_count)
{
double req[NS_PACKETSZ / sizeof (double)];
int i;
unsigned n;
isc_result_t status;
n = res_nmkquery(statp, ns_o_query, dname, class, qtype,
NULL, 0, NULL, req, NS_PACKETSZ);
if (n < 0) {
status = res_nmkquery(statp, ns_o_query, dname, class, qtype,
NULL, 0, NULL, req, NS_PACKETSZ, &n);
if (status != ISC_R_SUCCESS) {
DPRINTF(("do_query: res_nmkquery failed"));
return ns_r_servfail;
return status;
}
n = res_nsend(statp, req, n, resp, NS_PACKETSZ);
if (n < 0) {
status = res_nsend(statp, req, n, resp, NS_PACKETSZ, &n);
if (status != ISC_R_SUCCESS) {
DPRINTF(("do_query: res_nsend failed"));
return ns_r_servfail;
return status;
}
if (n == 0) {
DPRINTF(("do_query: res_nsend returned 0"));
errno = EMSGSIZE;
return ns_r_servfail;
return ISC_R_NOTFOUND;
}
if (ns_initparse((u_char *)resp, n, msg) < 0) {
DPRINTF(("do_query: ns_initparse failed"));
return ns_r_servfail;
return ISC_R_NOSPACE;
}
n = 0;
for (i = 0; i < ns_msg_count(*msg, ns_s_an); i++) {
ns_rr rr;
if (ns_parserr(msg, ns_s_an, i, &rr) < 0) {
status = ns_parserr(msg, ns_s_an, i, &rr);
if (status != ISC_R_SUCCESS) {
DPRINTF(("do_query: ns_parserr failed"));
return ns_r_servfail;
return status;
}
n += (ns_rr_class(rr) == class &&
(ns_rr_type(rr) == ns_t_cname ||
@ -596,5 +604,5 @@ do_query(res_state statp, const char *dname, ns_class class, ns_type qtype,
}
if (alias_count)
*alias_count = n;
return (ns_rcode)ns_msg_getflag (*msg, ns_f_rcode);
return ns_rcode_to_isc (ns_msg_getflag (*msg, ns_f_rcode));
}

View File

@ -70,7 +70,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
static const char rcsid[] = "$Id: res_init.c,v 1.1.1.1 2000/04/22 07:11:54 mellon Exp $";
static const char rcsid[] = "$Id: res_init.c,v 1.1.1.2 2001/04/02 21:57:09 mellon Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
@ -134,6 +134,10 @@ static u_int32_t net_mask (struct in_addr);
*/
extern int __res_vinit(res_state, int);
#if defined (TRACING)
u_int trace_mr_res_randomid(u_int);
#endif
int
res_ninit(res_state statp) {
@ -163,6 +167,9 @@ __res_vinit(res_state statp, int preinit) {
statp->retry = RES_DFLRETRY;
statp->options = RES_DEFAULT;
statp->id = res_randomid();
#if defined (TRACING)
statp->id = trace_mr_res_randomid (statp -> id);
#endif
}
#ifdef USELOOPBACK

View File

@ -70,7 +70,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
static const char rcsid[] = "$Id: res_mkquery.c,v 1.1.1.2 2000/07/20 05:50:19 mellon Exp $";
static const char rcsid[] = "$Id: res_mkquery.c,v 1.1.1.3 2001/04/02 21:57:09 mellon Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
@ -90,7 +90,7 @@ extern const char *_res_opcodes[];
* Form all types of queries.
* Returns the size of the result or -1.
*/
int
isc_result_t
res_nmkquery(res_state statp,
int op, /* opcode of query */
const char *dname, /* domain name */
@ -99,7 +99,8 @@ res_nmkquery(res_state statp,
unsigned datalen, /* length of data */
const u_char *newrr_in, /* new rr for modify or append */
double *buf, /* buffer to put query */
unsigned buflen) /* size of buffer */
unsigned buflen, /* size of buffer */
unsigned *rbuflen) /* returned size of buffer */
{
register HEADER *hp;
register u_char *cp;
@ -110,7 +111,7 @@ res_nmkquery(res_state statp,
* Initialize header fields.
*/
if ((buf == NULL) || (buflen < HFIXEDSZ))
return (-1);
return ISC_R_INVALIDARG;
memset(buf, 0, HFIXEDSZ);
hp = (HEADER *) buf;
hp->id = htons(++statp->id);
@ -130,9 +131,9 @@ res_nmkquery(res_state statp,
case QUERY: /*FALLTHROUGH*/
case NS_NOTIFY_OP:
if ((buflen -= QFIXEDSZ) < 0)
return (-1);
return ISC_R_NOSPACE;
if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
return (-1);
return ISC_R_NOSPACE;
cp += n;
buflen -= n;
putUShort(cp, type);
@ -148,7 +149,7 @@ res_nmkquery(res_state statp,
buflen -= RRFIXEDSZ;
n = dn_comp((const char *)data, cp, buflen, dnptrs, lastdnptr);
if (n < 0)
return (-1);
return ISC_R_NOSPACE;
cp += n;
buflen -= n;
putUShort(cp, T_NULL);
@ -167,7 +168,7 @@ res_nmkquery(res_state statp,
* Initialize answer section
*/
if (buflen < 1 + RRFIXEDSZ + datalen)
return (-1);
return ISC_R_NOSPACE;
*cp++ = '\0'; /* no domain name */
putUShort(cp, type);
cp += INT16SZ;
@ -185,7 +186,8 @@ res_nmkquery(res_state statp,
break;
default:
return (-1);
return ISC_R_NOTIMPLEMENTED;
}
return (cp - ((u_char *)buf));
*rbuflen = cp - ((u_char *)buf);
return ISC_R_SUCCESS;
}

View File

@ -21,7 +21,7 @@
*/
#if !defined(lint) && !defined(SABER)
static const char rcsid[] = "$Id: res_mkupdate.c,v 1.1.1.2 2000/07/20 05:50:20 mellon Exp $";
static const char rcsid[] = "$Id: res_mkupdate.c,v 1.1.1.3 2001/04/02 21:57:10 mellon Exp $";
#endif /* not lint */
#include <sys/types.h>
@ -47,10 +47,12 @@ static const char rcsid[] = "$Id: res_mkupdate.c,v 1.1.1.2 2000/07/20 05:50:20 m
#define DEBUG
#define MAXPORT 1024
static int getnum_str(u_char **, u_char *);
static int gethexnum_str(u_char **, u_char *);
static int getword_str(char *, int, u_char **, u_char *);
static int getstr_str(char *, int, u_char **, u_char *);
static int getnum_str(const u_char **, const u_char *);
static int gethexnum_str(const u_char **, const u_char *);
static int getword_str(char *, int,
const unsigned char **,
const unsigned char *);
static int getstr_str(char *, int, const u_char **, const u_char *);
struct valuelist {
struct valuelist * next;
@ -88,9 +90,9 @@ res_nmkupdate(res_state statp,
ns_updrec *rrecp_in, double *bp, unsigned *blp) {
ns_updrec *rrecp_start = rrecp_in;
HEADER *hp;
u_char *cp, *sp1, *sp2, *startp, *endp;
int i, soanum, multiline;
unsigned n;
u_char *cp, *sp1, *sp2;
const unsigned char *startp, *endp;
int n, i, soanum, multiline;
ns_updrec *rrecp;
struct in_addr ina;
char buf2[MAXDNAME];
@ -387,7 +389,7 @@ res_nmkupdate(res_state statp,
return (-1);
ShrinkBuffer(n+1);
*cp++ = n;
memcpy(cp, buf2, n);
memcpy(cp, buf2, (unsigned)n);
cp += n;
}
break;
@ -403,7 +405,7 @@ res_nmkupdate(res_state statp,
return (-1);
ShrinkBuffer(n+1);
*cp++ = n;
memcpy(cp, buf2, n);
memcpy(cp, buf2, (unsigned)n);
cp += n;
}
break;
@ -416,7 +418,7 @@ res_nmkupdate(res_state statp,
return (-1);
ShrinkBuffer(n+1);
*cp++ = n;
memcpy(cp, buf2, n);
memcpy(cp, buf2, (unsigned)n);
cp += n;
break;
case T_ISDN:
@ -428,7 +430,7 @@ res_nmkupdate(res_state statp,
return (-1);
ShrinkBuffer(n+1);
*cp++ = n;
memcpy(cp, buf2, n);
memcpy(cp, buf2, (unsigned)n);
cp += n;
if ((n = getstr_str(buf2, sizeof buf2, &startp,
endp)) < 0)
@ -437,7 +439,7 @@ res_nmkupdate(res_state statp,
return (-1);
ShrinkBuffer(n+1);
*cp++ = n;
memcpy(cp, buf2, n);
memcpy(cp, buf2, (unsigned)n);
cp += n;
break;
#if 0
@ -663,7 +665,7 @@ res_nmkupdate(res_state statp,
* word in the string.
*/
static int
getword_str(char *buf, int size, u_char **startpp, u_char *endp) {
getword_str(char *buf, int size, const u_char **startpp, const u_char *endp) {
char *cp;
int c;
@ -693,7 +695,7 @@ getword_str(char *buf, int size, u_char **startpp, u_char *endp) {
*/
static char digits[] = "0123456789";
static int
getstr_str(char *buf, int size, u_char **startpp, u_char *endp) {
getstr_str(char *buf, int size, const u_char **startpp, const u_char *endp) {
char *cp;
int c, c1 = 0;
int inquote = 0;
@ -770,12 +772,13 @@ getstr_str(char *buf, int size, u_char **startpp, u_char *endp) {
* update the start pointer to point after the number in the string.
*/
static int
gethexnum_str(u_char **startpp, u_char *endp) {
gethexnum_str(const u_char **startpp, const u_char *endp) {
int c, n;
int seendigit = 0;
int m = 0;
if (*startpp + 2 >= endp || strncasecmp((char *)*startpp, "0x", 2) != 0)
if (*startpp + 2 >= endp ||
strncasecmp((const char *)*startpp, "0x", 2) != 0)
return getnum_str(startpp, endp);
(*startpp)+=2;
for (n = 0; *startpp <= endp; ) {
@ -818,7 +821,7 @@ gethexnum_str(u_char **startpp, u_char *endp) {
* update the start pointer to point after the number in the string.
*/
static int
getnum_str(u_char **startpp, u_char *endp) {
getnum_str(const u_char **startpp, const u_char *endp) {
int c, n;
int seendigit = 0;
int m = 0;

View File

@ -70,7 +70,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
static const char rcsid[] = "$Id: res_query.c,v 1.1.1.2 2000/07/20 05:50:21 mellon Exp $";
static const char rcsid[] = "$Id: res_query.c,v 1.1.1.3 2001/04/02 21:57:10 mellon Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
@ -107,16 +107,18 @@ static const char rcsid[] = "$Id: res_query.c,v 1.1.1.2 2000/07/20 05:50:21 mell
*
* Caller must parse answer and determine whether it answers the question.
*/
int
isc_result_t
res_nquery(res_state statp,
const char *name, /* domain name */
ns_class class, ns_type type, /* class and type of query */
double *answer, /* buffer to put answer */
unsigned anslen) /* size of answer buffer */
unsigned anslen,
unsigned *ansret) /* size of answer buffer */
{
double buf[MAXPACKET / sizeof (double)];
HEADER *hp = (HEADER *) answer;
unsigned n;
isc_result_t rcode;
hp->rcode = NOERROR; /* default */
@ -125,24 +127,24 @@ res_nquery(res_state statp,
printf(";; res_query(%s, %d, %d)\n", name, class, type);
#endif
n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
buf, sizeof(buf));
if (n <= 0) {
rcode = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
buf, sizeof(buf), &n);
if (rcode != ISC_R_SUCCESS) {
#ifdef DEBUG
if (statp->options & RES_DEBUG)
printf(";; res_query: mkquery failed\n");
#endif
RES_SET_H_ERRNO(statp, NO_RECOVERY);
return (n);
return rcode;
}
n = res_nsend(statp, buf, n, answer, anslen);
if (n < 0) {
rcode = res_nsend(statp, buf, n, answer, anslen, &n);
if (rcode != ISC_R_SUCCESS) {
#ifdef DEBUG
if (statp->options & RES_DEBUG)
printf(";; res_query: send error\n");
#endif
RES_SET_H_ERRNO(statp, TRY_AGAIN);
return (n);
return rcode;
}
if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
@ -168,23 +170,26 @@ res_nquery(res_state statp,
RES_SET_H_ERRNO(statp, NO_RECOVERY);
break;
}
return (-1);
return ns_rcode_to_isc (hp -> rcode);
}
return (n);
*ansret = n;
return ISC_R_SUCCESS;
}
#if 0
/*
* Formulate a normal query, send, and retrieve answer in supplied buffer.
* Return the size of the response on success, -1 on error.
* If enabled, implement search rules until answer or unrecoverable failure
* is detected. Error code, if any, is left in H_ERRNO.
*/
int
isc_result_t
res_nsearch(res_state statp,
const char *name, /* domain name */
ns_class class, ns_type type, /* class and type of query */
double *answer, /* buffer to put answer */
unsigned anslen) /* size of answer */
unsigned anslen,
unsigned *ansret) /* size of answer */
{
const char *cp, * const *domain;
HEADER *hp = (HEADER *) answer;
@ -192,6 +197,7 @@ res_nsearch(res_state statp,
u_int dots;
int trailing_dot, ret;
int got_nodata = 0, got_servfail = 0, root_on_list = 0;
isc_result_t rcode;
errno = 0;
RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /* True if we never query. */
@ -205,15 +211,16 @@ res_nsearch(res_state statp,
/* If there aren't any dots, it could be a user-level alias. */
if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL)
return (res_nquery(statp, cp, class, type, answer, anslen));
return res_nquery(statp, cp, class, type,
answer, anslen, ansret);
/*
* If there are enough dots in the name, do no searching.
* (The threshold can be set with the "ndots" option.)
*/
if (dots >= statp->ndots || trailing_dot)
return (res_nquerydomain(statp, name, NULL, class, type,
answer, anslen));
return res_nquerydomain(statp, name, NULL, class, type,
answer, anslen, ansret);
/*
* We do at least one level of search if
@ -233,11 +240,13 @@ res_nsearch(res_state statp,
(domain[0][0] == '.' && domain[0][1] == '\0'))
root_on_list++;
ret = res_nquerydomain(statp, name, *domain,
class, type,
answer, anslen);
if (ret > 0)
return (ret);
rcode = res_nquerydomain(statp, name, *domain,
class, type,
answer, anslen, &ret);
if (rcode == ISC_R_SUCCESS && ret > 0) {
*ansret = ret;
return rcode;
}
/*
* If no server present, give up.
@ -254,7 +263,7 @@ res_nsearch(res_state statp,
*/
if (errno == ECONNREFUSED) {
RES_SET_H_ERRNO(statp, TRY_AGAIN);
return (-1);
return ISC_R_CONNREFUSED;
}
switch (statp->res_h_errno) {
@ -289,10 +298,12 @@ res_nsearch(res_state statp,
* list, then try an as-is query now.
*/
if (statp->ndots) {
ret = res_nquerydomain(statp, name, NULL, class, type,
answer, anslen);
if (ret > 0)
return (ret);
rcode = res_nquerydomain(statp, name, NULL, class, type,
answer, anslen, &ret);
if (rcode == ISC_R_SUCCESS && ret > 0) {
*ansret = ret;
return rcode;
}
}
/* if we got here, we didn't satisfy the search.
@ -302,24 +313,29 @@ res_nsearch(res_state statp,
* else send back meaningless H_ERRNO, that being the one from
* the last DNSRCH we did.
*/
if (got_nodata)
if (got_nodata) {
RES_SET_H_ERRNO(statp, NO_DATA);
else if (got_servfail)
return ISC_R_NOTFOUND;
} else if (got_servfail) {
RES_SET_H_ERRNO(statp, TRY_AGAIN);
return (-1);
return ISC_R_TIMEDOUT;
}
return ISC_R_UNEXPECTED;
}
#endif
/*
* Perform a call on res_query on the concatenation of name and domain,
* removing a trailing dot from name if domain is NULL.
*/
int
isc_result_t
res_nquerydomain(res_state statp,
const char *name,
const char *domain,
ns_class class, ns_type type,
double *answer,
unsigned anslen)
const char *name,
const char *domain,
ns_class class, ns_type type,
double *answer,
unsigned anslen,
unsigned *ansret)
{
char nbuf[MAXDNAME];
const char *longname = nbuf;
@ -338,7 +354,7 @@ res_nquerydomain(res_state statp,
n = strlen(name);
if (n >= MAXDNAME) {
RES_SET_H_ERRNO(statp, NO_RECOVERY);
return (-1);
return ISC_R_NOSPACE;
}
n--;
if (n >= 0 && name[n] == '.') {
@ -351,11 +367,12 @@ res_nquerydomain(res_state statp,
d = strlen(domain);
if (n + d + 1 >= MAXDNAME) {
RES_SET_H_ERRNO(statp, NO_RECOVERY);
return (-1);
return ISC_R_NOSPACE;
}
sprintf(nbuf, "%s.%s", name, domain);
}
return (res_nquery(statp, longname, class, type, answer, anslen));
return res_nquery(statp,
longname, class, type, answer, anslen, ansret);
}
const char *

View File

@ -52,7 +52,7 @@
*/
/*
* Portions Copyright (c) 1996-1999 by Internet Software Consortium.
* Portions Copyright (c) 1996-2001 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -70,9 +70,20 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
static const char rcsid[] = "$Id: res_send.c,v 1.1.1.2 2000/07/20 05:50:22 mellon Exp $";
static const char rcsid[] = "$Id: res_send.c,v 1.1.1.3 2001/04/02 21:57:10 mellon Exp $";
#endif /* LIBC_SCCS and not lint */
/* Rename the I/O functions in case we're tracing. */
#define send trace_mr_send
#define recvfrom trace_mr_recvfrom
#define read trace_mr_read
#define connect trace_mr_connect
#define socket trace_mr_socket
#define bind trace_mr_bind
#define close trace_mr_close
#define select trace_mr_select
#define time trace_mr_time
/*
* Send query to name server and wait for reply.
*/
@ -216,9 +227,10 @@ res_queriesmatch(const u_char *buf1, const u_char *eom1,
return (1);
}
int
isc_result_t
res_nsend(res_state statp,
double *buf, unsigned buflen, double *ans, unsigned anssiz)
double *buf, unsigned buflen,
double *ans, unsigned anssiz, unsigned *ansret)
{
HEADER *hp = (HEADER *) buf;
HEADER *anhp = (HEADER *) ans;
@ -227,8 +239,7 @@ res_nsend(res_state statp,
static int highestFD = FD_SETSIZE - 1;
if (anssiz < HFIXEDSZ) {
errno = EINVAL;
return (-1);
return ISC_R_INVALIDARG;
}
DprintQ((statp->options & RES_DEBUG) ||
(statp->pfcode & RES_PRF_QUERY),
@ -236,7 +247,7 @@ res_nsend(res_state statp,
v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
gotsomewhere = 0;
connreset = 0;
terrno = ETIMEDOUT;
terrno = ISC_R_TIMEDOUT;
badns = 0;
/*
@ -252,6 +263,10 @@ res_nsend(res_state statp,
statp->nsaddr_list[lastns] = ina;
}
#if defined (TRACING)
trace_mr_statp_setup (statp);
#endif
/*
* Send request, RETRY times, or until successful
*/
@ -289,7 +304,7 @@ res_nsend(res_state statp,
case res_error:
/*FALLTHROUGH*/
default:
return (-1);
return ISC_R_UNEXPECTED;
}
} while (!done);
}
@ -334,7 +349,7 @@ res_nsend(res_state statp,
SOCK_STREAM, 0);
if (statp->_sock < 0 ||
statp->_sock > highestFD) {
terrno = errno;
terrno = uerr2isc (errno);
Perror(statp, stderr,
"socket(vc)", errno);
return (-1);
@ -343,7 +358,7 @@ res_nsend(res_state statp,
if (connect(statp->_sock,
(struct sockaddr *)nsap,
sizeof *nsap) < 0) {
terrno = errno;
terrno = uerr2isc (errno);
Aerror(statp, stderr, "connect/vc",
errno, *nsap);
badns |= (1 << ns);
@ -362,7 +377,7 @@ res_nsend(res_state statp,
iov[1].iov_len = buflen;
if (writev(statp->_sock, iov, 2) !=
(INT16SZ + buflen)) {
terrno = errno;
terrno = uerr2isc (errno);
Perror(statp, stderr, "write failed", errno);
badns |= (1 << ns);
res_nclose(statp);
@ -381,7 +396,7 @@ res_nsend(res_state statp,
break;
}
if (n <= 0) {
terrno = errno;
terrno = uerr2isc (errno);
Perror(statp, stderr, "read failed", errno);
res_nclose(statp);
/*
@ -393,7 +408,8 @@ res_nsend(res_state statp,
* instead of failing. We only allow one reset
* per query to prevent looping.
*/
if (terrno == ECONNRESET && !connreset) {
if (terrno == ISC_R_CONNREFUSED &&
!connreset) {
connreset = 1;
res_nclose(statp);
goto same_ns;
@ -416,7 +432,7 @@ res_nsend(res_state statp,
*/
Dprint(statp->options & RES_DEBUG,
(stdout, ";; undersized: %d\n", len));
terrno = EMSGSIZE;
terrno = ISC_R_NOSPACE;
badns |= (1 << ns);
res_nclose(statp);
goto next_ns;
@ -430,7 +446,7 @@ res_nsend(res_state statp,
len -= n;
}
if (n <= 0) {
terrno = errno;
terrno = uerr2isc (errno);
Perror(statp, stderr, "read(vc)", errno);
res_nclose(statp);
goto next_ns;
@ -491,10 +507,10 @@ res_nsend(res_state statp,
#ifndef CAN_RECONNECT
bad_dg_sock:
#endif
terrno = errno;
terrno = uerr2isc (errno);
Perror(statp, stderr,
"socket(dg)", errno);
return (-1);
return terrno;
}
statp->_flags &= ~RES_F_CONN;
}
@ -667,7 +683,7 @@ res_nsend(res_state statp,
Dprint(statp->options & RES_DEBUG,
(stdout, ";; undersized: %d\n",
resplen));
terrno = EMSGSIZE;
terrno = ISC_R_NOSPACE;
badns |= (1 << ns);
res_nclose(statp);
goto next_ns;
@ -783,24 +799,24 @@ res_nsend(res_state statp,
case res_error:
/*FALLTHROUGH*/
default:
return (-1);
return ISC_R_UNEXPECTED;
}
} while (!done);
}
return (resplen);
*ansret = resplen;
return ISC_R_SUCCESS;
next_ns: ;
} /*foreach ns*/
} /*foreach retry*/
res_nclose(statp);
if (!v_circuit) {
if (!gotsomewhere)
errno = ECONNREFUSED; /* no nameservers found */
terrno = ISC_R_CONNREFUSED; /* no nameservers found */
else
errno = ETIMEDOUT; /* no answer obtained */
} else
errno = terrno;
return (-1);
errno = ISC_R_TIMEDOUT; /* no answer obtained */
}
return terrno;
}
/*

View File

@ -18,9 +18,10 @@
#include <isc/dst.h>
/* res_nsendsigned */
int
res_nsendsigned(res_state statp, double *msg, unsigned msglen,
ns_tsig_key *key, double *answer, unsigned anslen)
isc_result_t
res_nsendsigned(res_state statp,
double *msg, unsigned msglen, ns_tsig_key *key,
double *answer, unsigned anslen, unsigned *anssize)
{
res_state nstatp;
DST_KEY *dstkey;
@ -31,23 +32,20 @@ res_nsendsigned(res_state statp, double *msg, unsigned msglen,
u_char sig[64];
HEADER *hp;
time_t tsig_time;
int ret;
unsigned ret;
isc_result_t rcode;
dst_init();
nstatp = (res_state) malloc(sizeof(*statp));
if (nstatp == NULL) {
errno = ENOMEM;
return (-1);
}
if (nstatp == NULL)
return ISC_R_NOMEMORY;
memcpy(nstatp, statp, sizeof(*statp));
bufsize = msglen + 1024;
newmsg = (double *) malloc(bufsize);
if (newmsg == NULL) {
errno = ENOMEM;
return (-1);
}
if (newmsg == NULL)
return ISC_R_NOMEMORY;
memcpy(newmsg, msg, msglen);
newmsglen = msglen;
@ -59,25 +57,20 @@ res_nsendsigned(res_state statp, double *msg, unsigned msglen,
NS_KEY_PROT_ANY,
key->data, key->len);
if (dstkey == NULL) {
errno = EINVAL;
free(nstatp);
free(newmsg);
return (-1);
return ISC_R_INVALIDARG;
}
nstatp->nscount = 1;
siglen = sizeof(sig);
ret = ns_sign((u_char *)newmsg, &newmsglen, bufsize,
NOERROR, dstkey, NULL, 0,
sig, &siglen, 0);
if (ret < 0) {
rcode = ns_sign((u_char *)newmsg, &newmsglen, bufsize,
NOERROR, dstkey, NULL, 0,
sig, &siglen, 0);
if (rcode != ISC_R_SUCCESS) {
free (nstatp);
free (newmsg);
if (ret == NS_TSIG_ERROR_NO_SPACE)
errno = EMSGSIZE;
else if (ret == -1)
errno = EINVAL;
return (ret);
return rcode;
}
if (newmsglen > PACKETSZ || (nstatp->options & RES_IGNTC))
@ -89,27 +82,23 @@ res_nsendsigned(res_state statp, double *msg, unsigned msglen,
retry:
ret = res_nsend(nstatp, newmsg, newmsglen, answer, anslen);
if (ret < 0) {
rcode = res_nsend(nstatp, newmsg, newmsglen, answer, anslen, &ret);
if (rcode != ISC_R_SUCCESS) {
free (nstatp);
free (newmsg);
return (ret);
return rcode;
}
anslen = ret;
ret = ns_verify((u_char *)answer, &anslen, dstkey, sig, siglen,
NULL, NULL, &tsig_time,
(nstatp->options & RES_KEEPTSIG) ? 1 : 0);
if (ret != 0) {
rcode = ns_verify((u_char *)answer, &anslen, dstkey, sig, siglen,
NULL, NULL, &tsig_time,
(nstatp->options & RES_KEEPTSIG) ? 1 : 0);
if (rcode != ISC_R_SUCCESS) {
Dprint(nstatp->pfcode & RES_PRF_REPLY,
(stdout, ";; TSIG invalid (%s)\n", p_rcode(ret)));
free (nstatp);
free (newmsg);
if (ret == -1)
errno = EINVAL;
else
errno = ENOTTY;
return (-1);
return rcode;
}
Dprint(nstatp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG ok\n"));
@ -122,5 +111,6 @@ retry:
free (nstatp);
free (newmsg);
return (anslen);
*anssize = anslen;
return ISC_R_SUCCESS;
}

View File

@ -0,0 +1,322 @@
/* toisc.c
Convert non-ISC result codes to ISC result codes. */
/*
* Copyright (c) 2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of The Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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.
*
* This software has been written for the Internet Software Consortium
* by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
* To learn more about the Internet Software Consortium, see
* ``http://www.isc.org/''. To learn more about Vixie Enterprises,
* see ``http://www.vix.com''. To learn more about Nominum, Inc., see
* ``http://www.nominum.com''.
*/
#include <omapip/omapip_p.h>
#include "arpa/nameser.h"
#include "minires/minires.h"
isc_result_t ns_rcode_to_isc (int nsr)
{
switch (nsr) {
case ns_r_noerror:
return ISC_R_SUCCESS;
case ns_r_formerr:
return ISC_R_FORMERR;
case ns_r_servfail:
return ISC_R_SERVFAIL;
case ns_r_nxdomain:
return ISC_R_NXDOMAIN;
case ns_r_notimpl:
return ISC_R_NOTIMPL;
case ns_r_refused:
return ISC_R_REFUSED;
case ns_r_yxdomain:
return ISC_R_YXDOMAIN;
case ns_r_yxrrset:
return ISC_R_YXRRSET;
case ns_r_nxrrset:
return ISC_R_NXRRSET;
case ns_r_notauth:
return ISC_R_NOTAUTH;
case ns_r_notzone:
return ISC_R_NOTZONE;
case ns_r_badsig:
return ISC_R_BADSIG;
case ns_r_badkey:
return ISC_R_BADKEY;
case ns_r_badtime:
return ISC_R_BADTIME;
default:
;
}
return ISC_R_UNEXPECTED;
}
isc_result_t uerr2isc (int err)
{
switch (err) {
case EPERM:
return ISC_R_NOPERM;
case ENOENT:
return ISC_R_NOTFOUND;
case ESRCH:
return ISC_R_NOTFOUND;
case EIO:
return ISC_R_IOERROR;
case ENXIO:
return ISC_R_NOTFOUND;
case E2BIG:
return ISC_R_NOSPACE;
case ENOEXEC:
return ISC_R_FORMERR;
case ECHILD:
return ISC_R_NOTFOUND;
case ENOMEM:
return ISC_R_NOMEMORY;
case EACCES:
return ISC_R_NOPERM;
case EFAULT:
return ISC_R_INVALIDARG;
case EEXIST:
return ISC_R_EXISTS;
case EINVAL:
return ISC_R_INVALIDARG;
case ENOTTY:
return ISC_R_INVALIDARG;
case EFBIG:
return ISC_R_NOSPACE;
case ENOSPC:
return ISC_R_NOSPACE;
case EROFS:
return ISC_R_NOPERM;
case EMLINK:
return ISC_R_NOSPACE;
case EPIPE:
return ISC_R_NOTCONNECTED;
case EINPROGRESS:
return ISC_R_ALREADYRUNNING;
case EALREADY:
return ISC_R_ALREADYRUNNING;
case ENOTSOCK:
return ISC_R_INVALIDFILE;
case EDESTADDRREQ:
return ISC_R_DESTADDRREQ;
case EMSGSIZE:
return ISC_R_NOSPACE;
case EPROTOTYPE:
return ISC_R_INVALIDARG;
case ENOPROTOOPT:
return ISC_R_NOTIMPLEMENTED;
case EPROTONOSUPPORT:
return ISC_R_NOTIMPLEMENTED;
case ESOCKTNOSUPPORT:
return ISC_R_NOTIMPLEMENTED;
case EOPNOTSUPP:
return ISC_R_NOTIMPLEMENTED;
case EPFNOSUPPORT:
return ISC_R_NOTIMPLEMENTED;
case EAFNOSUPPORT:
return ISC_R_NOTIMPLEMENTED;
case EADDRINUSE:
return ISC_R_ADDRINUSE;
case EADDRNOTAVAIL:
return ISC_R_ADDRNOTAVAIL;
case ENETDOWN:
return ISC_R_NETDOWN;
case ENETUNREACH:
return ISC_R_NETUNREACH;
case ECONNABORTED:
return ISC_R_TIMEDOUT;
case ECONNRESET:
return ISC_R_CONNREFUSED;
case ENOBUFS:
return ISC_R_NOSPACE;
case EISCONN:
return ISC_R_ALREADYRUNNING;
case ENOTCONN:
return ISC_R_NOTCONNECTED;
case ESHUTDOWN:
return ISC_R_SHUTTINGDOWN;
case ETIMEDOUT:
return ISC_R_TIMEDOUT;
case ECONNREFUSED:
return ISC_R_CONNREFUSED;
case EHOSTDOWN:
return ISC_R_HOSTDOWN;
case EHOSTUNREACH:
return ISC_R_HOSTUNREACH;
case EDQUOT:
return ISC_R_QUOTA;
#ifdef EBADRPC
case EBADRPC:
return ISC_R_NOTIMPLEMENTED;
#endif
#ifdef ERPCMISMATCH
case ERPCMISMATCH:
return ISC_R_VERSIONMISMATCH;
#endif
#ifdef EPROGMISMATCH
case EPROGMISMATCH:
return ISC_R_VERSIONMISMATCH;
#endif
#ifdef EAUTH
case EAUTH:
return ISC_R_NOTAUTH;
#endif
#ifdef ENEEDAUTH
case ENEEDAUTH:
return ISC_R_NOTAUTH;
#endif
#ifdef EOVERFLOW
case EOVERFLOW:
return ISC_R_NOSPACE;
#endif
}
return ISC_R_UNEXPECTED;
}
ns_rcode isc_rcode_to_ns (isc_result_t isc)
{
switch (isc) {
case ISC_R_SUCCESS:
return ns_r_noerror;
case ISC_R_FORMERR:
return ns_r_formerr;
case ISC_R_SERVFAIL:
return ns_r_servfail;
case ISC_R_NXDOMAIN:
return ns_r_nxdomain;
case ISC_R_NOTIMPL:
return ns_r_notimpl;
case ISC_R_REFUSED:
return ns_r_refused;
case ISC_R_YXDOMAIN:
return ns_r_yxdomain;
case ISC_R_YXRRSET:
return ns_r_yxrrset;
case ISC_R_NXRRSET:
return ns_r_nxrrset;
case ISC_R_NOTAUTH:
return ns_r_notauth;
case ISC_R_NOTZONE:
return ns_r_notzone;
case ISC_R_BADSIG:
return ns_r_badsig;
case ISC_R_BADKEY:
return ns_r_badkey;
case ISC_R_BADTIME:
return ns_r_badtime;
default:
;
}
return ns_r_servfail;
}

View File

@ -55,6 +55,11 @@ unsigned long dmalloc_cutoff_generation;
#if defined (DEBUG_RC_HISTORY)
struct rc_history_entry rc_history [RC_HISTORY_MAX];
int rc_history_index;
int rc_history_count;
#endif
#if defined (DEBUG_RC_HISTORY)
static void print_rc_hist_entry (int);
#endif
VOIDPTR dmalloc (size, file, line)
@ -119,6 +124,7 @@ VOIDPTR dmalloc (size, file, line)
}
#endif
#endif
rc_register (file, line, 0, foo + DMDOFFSET, 1);
return bar;
}
@ -179,6 +185,7 @@ void dfree (ptr, file, line)
ptr = bar;
}
#endif
rc_register (file, line, 0, (unsigned char *)ptr + DMDOFFSET, 0);
free (ptr);
}
@ -280,9 +287,41 @@ void dmalloc_dump_outstanding ()
#if defined (DEBUG_MEMORY_LEAKAGE)
/* Don't count data that's actually on a free list
somewhere. */
if (dp -> file)
log_info (" %s(%d): %d",
dp -> file, dp -> line, dp -> size);
if (dp -> file) {
#if defined (DEBUG_RC_HISTORY)
/* If we have the info, see if this is actually
new garbage. */
if (rc_history_count < RC_HISTORY_MAX) {
int i, printit = 0, inhistory = 0, prefcnt = 0;
i = rc_history_index - rc_history_count;
if (i < 0)
i += RC_HISTORY_MAX;
do {
if (rc_history [i].addr == dp + 1) {
if (rc_history [i].refcnt == 1 &&
prefcnt == 0 && !printit) {
printit = 1;
inhistory = 1;
log_info (" %s(%d): %d",
dp -> file,
dp -> line,
dp -> size);
}
prefcnt = rc_history [i].refcnt;
if (printit)
print_rc_hist_entry (i);
}
if (++i == RC_HISTORY_MAX)
i = 0;
} while (i != rc_history_index);
if (!inhistory)
log_info (" %s(%d): %d", dp -> file,
dp -> line, dp -> size);
} else
#endif
log_info (" %s(%d): %d",
dp -> file, dp -> line, dp -> size);
}
#endif
}
if (dmalloc_list)
@ -291,21 +330,37 @@ void dmalloc_dump_outstanding ()
#endif /* DEBUG_MEMORY_LEAKAGE || DEBUG_MALLOC_POOL */
#if defined (DEBUG_RC_HISTORY)
static void print_rc_hist_entry (int i)
{
log_info (" referenced by %s(%d)[%lx]: addr = %lx refcnt = %x",
rc_history [i].file, rc_history [i].line,
(unsigned long)rc_history [i].reference,
(unsigned long)rc_history [i].addr,
rc_history [i].refcnt);
}
void dump_rc_history ()
{
int i;
i = rc_history_index;
do {
log_info (" referenced by %s(%d)[%lx]: addr = %lx refcnt = %x",
rc_history [i].file, rc_history [i].line,
(unsigned long)rc_history [i].reference,
(unsigned long)rc_history [i].addr,
rc_history [i].refcnt);
if (!rc_history [i].file)
i = 0;
else if (rc_history_count < RC_HISTORY_MAX) {
i -= rc_history_count;
if (i < 0)
i += RC_HISTORY_MAX;
}
rc_history_count = 0;
while (rc_history [i].file) {
print_rc_hist_entry (i);
++i;
if (i == RC_HISTORY_MAX)
i = 0;
} while (i != rc_history_index && rc_history [i].file);
if (i == rc_history_index)
break;
}
}
#endif
@ -481,6 +536,7 @@ isc_result_t omapi_object_dereference (omapi_object_t **h,
if (outer_reference)
omapi_object_dereference
(&(*h) -> outer, file, line);
(*h) -> refcnt--;
if (!(*h) -> type -> freer)
rc_register (file, line, h, *h, 0);
if ((*h) -> type -> destroy)

View File

@ -0,0 +1,153 @@
/* listener.c
Subroutines that support the omapi extensible array type. */
/*
* Copyright (c) 2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of The Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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.
*
* This software has been written for the Internet Software Consortium
* by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
* To learn more about the Internet Software Consortium, see
* ``http://www.isc.org/''. To learn more about Vixie Enterprises,
* see ``http://www.vix.com''. To learn more about Nominum, Inc., see
* ``http://www.nominum.com''.
*/
#include <omapip/omapip_p.h>
/* Allocate a new extensible array. */
isc_result_t omapi_array_allocate (omapi_array_t **array,
omapi_array_ref_t ref,
omapi_array_deref_t deref,
const char *file, int line)
{
isc_result_t status;
omapi_array_t *aptr;
if (!array || *array)
return ISC_R_INVALIDARG;
aptr = dmalloc (sizeof (omapi_array_t),file, line);
if (!aptr)
return ISC_R_NOMEMORY;
*array = aptr;
aptr -> ref = ref;
aptr -> deref = deref;
return ISC_R_SUCCESS;
}
/* Extend the size of the array by one entry (we may allocate more than that)
and store the specified value in the new array element. */
isc_result_t omapi_array_extend (omapi_array_t *array, char *ptr,
int *index, const char *file, int line)
{
isc_result_t status;
int new = array -> count;
status = omapi_array_set (array, ptr, new, file, line);
if (index && status == ISC_R_SUCCESS)
*index = new;
return status;
}
/* Set a value in the specified array, extending it if necessary. */
isc_result_t omapi_array_set (omapi_array_t *array, void *ptr, int index,
const char *file, int line)
{
char **newbuf;
int delta;
isc_result_t status;
if (!array)
return ISC_R_INVALIDARG;
if (!ptr)
return ISC_R_INVALIDARG;
if (index < 0)
return ISC_R_INVALIDARG;
/* If the proposed index is larger than the current available
space in the array, make more space in the array. */
if (array -> max <= index) {
delta = index - array -> max + 10;
newbuf = dmalloc ((array -> max + delta) * sizeof (char *),
file, line);
if (!newbuf)
return ISC_R_NOMEMORY;
/* Zero the new elements. */
memset (&newbuf [array -> max], 0, (sizeof (char *)) * delta);
array -> max += delta;
/* Copy the old array data into the new buffer. */
if (array -> data) {
memcpy (newbuf,
array -> data, array -> count * sizeof (char *));
dfree (array -> data, file, line);
}
array -> data = newbuf;
} else {
/* If there's already data there, and this is an array
of references, dereference what's there. */
if (array -> data [index]) {
status = ((*array -> deref) (&array -> data [index],
file, line));
if (status != ISC_R_SUCCESS)
return status;
}
}
/* Store the pointer using the referencer function. We have
either just memset this to zero or dereferenced what was
there previously, so there is no need to do anything if the
pointer we have been asked to store is null. */
if (ptr) {
status = (*array -> ref) (&array -> data [index], ptr,
file, line);
if (status != ISC_R_SUCCESS)
return status;
}
if (index >= array -> count)
array -> count = index + 1;
return ISC_R_SUCCESS;
}
isc_result_t omapi_array_lookup (char **ptr, omapi_array_t *array, int index,
const char *file, int line)
{
if (!array || !ptr || *ptr || index < 0 || index >= array -> count)
return ISC_R_INVALIDARG;
if (array -> data [index])
return (*array -> ref) (ptr,
array -> data [index], file, line);
return ISC_R_NOTFOUND;
}
OMAPI_ARRAY_TYPE_DECL(omapi_object, omapi_object_t);

View File

@ -3,7 +3,7 @@
Buffer access functions for the object management protocol... */
/*
* Copyright (c) 1999-2000 Internet Software Consortium.
* Copyright (c) 1999-2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -43,18 +43,118 @@
#include <omapip/omapip_p.h>
#if defined (TRACING)
static void trace_connection_input_input (trace_type_t *, unsigned, char *);
static void trace_connection_input_stop (trace_type_t *);
static void trace_connection_output_input (trace_type_t *, unsigned, char *);
static void trace_connection_output_stop (trace_type_t *);
static trace_type_t *trace_connection_input;
static trace_type_t *trace_connection_output;
static isc_result_t omapi_connection_reader_trace (omapi_object_t *,
unsigned, char *,
unsigned *);
extern omapi_array_t *omapi_connections;
void omapi_buffer_trace_setup ()
{
trace_connection_input =
trace_type_register ("connection-input",
(void *)0,
trace_connection_input_input,
trace_connection_input_stop, MDL);
trace_connection_output =
trace_type_register ("connection-output",
(void *)0,
trace_connection_output_input,
trace_connection_output_stop, MDL);
}
static void trace_connection_input_input (trace_type_t *ttype,
unsigned length, char *buf)
{
unsigned left, ol, cc = 0;
char *s;
int32_t connect_index;
isc_result_t status;
omapi_connection_object_t *c = (omapi_connection_object_t *)0;
memcpy (&connect_index, buf, sizeof connect_index);
connect_index = ntohl (connect_index);
omapi_array_foreach_begin (omapi_connections,
omapi_connection_object_t, lp) {
if (lp -> index == ntohl (connect_index)) {
omapi_connection_reference (&c, lp, MDL);
break;
}
} omapi_array_foreach_end (omapi_connections,
omapi_connection_object_t, lp);
if (!c) {
log_error ("trace connection input: no connection index %ld",
(long int)connect_index);
return;
}
s = buf + sizeof connect_index;
left = length - sizeof connect_index;;
while (left) {
ol = left;
status = omapi_connection_reader_trace ((omapi_object_t *)c,
left, s, &length);
if (status != ISC_R_SUCCESS) {
log_error ("trace connection input: %s",
isc_result_totext (status));
break;
}
if (ol == left) {
if (cc > 0) {
log_error ("trace connection_input: %s",
"input is not being consumed.");
break;
}
cc++;
} else
cc = 0;
}
}
static void trace_connection_input_stop (trace_type_t *ttype) { }
static void trace_connection_output_input (trace_type_t *ttype,
unsigned length, char *buf)
{
/* We *could* check to see if the output is correct, but for now
we aren't going to do that. */
}
static void trace_connection_output_stop (trace_type_t *ttype) { }
#endif
/* Make sure that at least len bytes are in the input buffer, and if not,
read enough bytes to make up the difference. */
isc_result_t omapi_connection_reader (omapi_object_t *h)
{
#if defined (TRACING)
return omapi_connection_reader_trace (h, 0, (char *)0, (unsigned *)0);
}
static isc_result_t omapi_connection_reader_trace (omapi_object_t *h,
unsigned stuff_len,
char *stuff_buf,
unsigned *stuff_taken)
{
#endif
omapi_buffer_t *buffer;
isc_result_t status;
unsigned read_len;
int read_status;
omapi_connection_object_t *c;
unsigned bytes_to_read;
if (!h || h -> type != omapi_type_connection)
return ISC_R_INVALIDARG;
c = (omapi_connection_object_t *)h;
@ -62,12 +162,13 @@ isc_result_t omapi_connection_reader (omapi_object_t *h)
/* Make sure c -> bytes_needed is valid. */
if (c -> bytes_needed < 0)
return ISC_R_INVALIDARG;
/* See if there are enough bytes. */
if (c -> in_bytes >= OMAPI_BUF_SIZE - 1 &&
c -> in_bytes > c -> bytes_needed)
return ISC_R_SUCCESS;
if (c -> inbufs) {
for (buffer = c -> inbufs; buffer -> next;
buffer = buffer -> next)
@ -93,8 +194,28 @@ isc_result_t omapi_connection_reader (omapi_object_t *h)
else
read_len = buffer -> head - buffer -> tail;
read_status = read (c -> socket,
&buffer -> buf [buffer -> tail], read_len);
#if defined (TRACING)
if (trace_playback()) {
if (stuff_len) {
if (read_len > stuff_len)
read_len = stuff_len;
if (stuff_taken)
*stuff_taken += read_len;
memcpy (&buffer -> buf [buffer -> tail],
stuff_buf, read_len);
stuff_len -= read_len;
stuff_buf += read_len;
read_status = read_len;
} else {
break;
}
} else
#endif
{
read_status = read (c -> socket,
&buffer -> buf [buffer -> tail],
read_len);
}
if (read_status < 0) {
if (errno == EWOULDBLOCK)
break;
@ -108,12 +229,34 @@ isc_result_t omapi_connection_reader (omapi_object_t *h)
} else
return ISC_R_UNEXPECTED;
}
/* If we got a zero-length read, as opposed to EWOULDBLOCK,
the remote end closed the connection. */
if (read_status == 0) {
omapi_disconnect (h, 0);
return ISC_R_SHUTTINGDOWN;
}
#if defined (TRACING)
if (trace_record ()) {
trace_iov_t iov [2];
int32_t connect_index;
connect_index = htonl (c -> index);
iov [0].buf = (char *)&connect_index;
iov [0].len = sizeof connect_index;
iov [1].buf = &buffer -> buf [buffer -> tail];
iov [1].len = read_status;
status = (trace_write_packet_iov
(trace_connection_input, 2, iov, MDL));
if (status != ISC_R_SUCCESS) {
trace_stop ();
log_error ("trace connection input: %s",
isc_result_totext (status));
}
}
#endif
buffer -> tail += read_status;
c -> in_bytes += read_status;
if (buffer -> tail == sizeof buffer -> buf)
@ -300,6 +443,7 @@ isc_result_t omapi_connection_writer (omapi_object_t *h)
omapi_buffer_t *buffer;
unsigned char *bufp;
omapi_connection_object_t *c;
isc_result_t status;
if (!h || h -> type != omapi_type_connection)
return ISC_R_INVALIDARG;
@ -355,6 +499,30 @@ isc_result_t omapi_connection_writer (omapi_object_t *h)
if (bytes_written == 0)
return ISC_R_SUCCESS;
#if defined (TRACING)
if (trace_record ()) {
trace_iov_t iov [2];
int32_t connect_index;
connect_index = htonl (c -> index);
iov [0].buf = (char *)&connect_index;
iov [0].len = sizeof connect_index;
iov [1].buf = &buffer -> buf [buffer -> tail];
iov [1].len = bytes_written;
status = (trace_write_packet_iov
(trace_connection_input, 2, iov,
MDL));
if (status != ISC_R_SUCCESS) {
trace_stop ();
log_error ("trace %s output: %s",
"connection",
isc_result_totext (status));
}
}
#endif
buffer -> head = first_byte + bytes_written - 1;
c -> out_bytes -= bytes_written;

View File

@ -3,7 +3,7 @@
Subroutines for dealing with connections. */
/*
* Copyright (c) 1999-2000 Internet Software Consortium.
* Copyright (c) 1999-2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -43,6 +43,18 @@
#include <omapip/omapip_p.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#if defined (TRACING)
static void trace_connect_input (trace_type_t *, unsigned, char *);
static void trace_connect_stop (trace_type_t *);
static void trace_disconnect_input (trace_type_t *, unsigned, char *);
static void trace_disconnect_stop (trace_type_t *);
trace_type_t *trace_connect;
trace_type_t *trace_disconnect;
extern omapi_array_t *trace_listeners;
#endif
OMAPI_OBJECT_ALLOC (omapi_connection,
omapi_connection_object_t, omapi_type_connection)
@ -107,6 +119,10 @@ isc_result_t omapi_connect_list (omapi_object_t *c,
omapi_connection_object_t *obj;
int flag;
struct sockaddr_in local_sin;
#if defined (TRACING)
trace_addr_t *addrs;
u_int16_t naddrs;
#endif
obj = (omapi_connection_object_t *)0;
status = omapi_connection_allocate (&obj, MDL);
@ -125,87 +141,294 @@ isc_result_t omapi_connect_list (omapi_object_t *c,
return status;
}
/* Create a socket on which to communicate. */
obj -> socket =
socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (obj -> socket < 0) {
omapi_connection_dereference (&obj, MDL);
if (errno == EMFILE || errno == ENFILE || errno == ENOBUFS)
return ISC_R_NORESOURCES;
return ISC_R_UNEXPECTED;
}
/* Set up the local address, if any. */
if (local_addr) {
/* Only do TCPv4 so far. */
if (local_addr -> addrtype != AF_INET) {
omapi_connection_dereference (&obj, MDL);
return ISC_R_INVALIDARG;
}
local_sin.sin_port = htons (local_addr -> port);
memcpy (&local_sin.sin_addr,
local_addr -> address,
local_addr -> addrlen);
#if defined (HAVE_SA_LEN)
local_sin.sin_len = sizeof local_addr;
#endif
local_sin.sin_family = AF_INET;
memset (&local_sin.sin_zero, 0, sizeof local_sin.sin_zero);
if (bind (obj -> socket, (struct sockaddr *)&local_sin,
sizeof local_sin) < 0) {
omapi_object_dereference ((omapi_object_t **)&obj,
MDL);
if (errno == EADDRINUSE)
return ISC_R_ADDRINUSE;
if (errno == EADDRNOTAVAIL)
return ISC_R_ADDRNOTAVAIL;
if (errno == EACCES)
return ISC_R_NOPERM;
return ISC_R_UNEXPECTED;
}
}
#if defined (HAVE_SETFD)
if (fcntl (obj -> socket, F_SETFD, 1) < 0) {
close (obj -> socket);
omapi_connection_dereference (&obj, MDL);
return ISC_R_UNEXPECTED;
}
#endif
/* Set the SO_REUSEADDR flag (this should not fail). */
flag = 1;
if (setsockopt (obj -> socket, SOL_SOCKET, SO_REUSEADDR,
(char *)&flag, sizeof flag) < 0) {
omapi_connection_dereference (&obj, MDL);
return ISC_R_UNEXPECTED;
}
/* Set the file to nonblocking mode. */
if (fcntl (obj -> socket, F_SETFL, O_NONBLOCK) < 0) {
omapi_connection_dereference (&obj, MDL);
return ISC_R_UNEXPECTED;
}
/* Store the address list on the object. */
omapi_addr_list_reference (&obj -> connect_list, remote_addrs, MDL);
obj -> cptr = 0;
status = (omapi_register_io_object
((omapi_object_t *)obj,
0, omapi_connection_writefd,
0, omapi_connection_connect,
omapi_connection_reaper));
if (status != ISC_R_SUCCESS)
goto out;
obj -> state = omapi_connection_unconnected;
status = omapi_connection_connect ((omapi_object_t *)obj);
#if defined (TRACING)
/* If we're playing back, don't actually try to connect - just leave
the object available for a subsequent connect or disconnect. */
if (!trace_playback ()) {
#endif
/* Create a socket on which to communicate. */
obj -> socket =
socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (obj -> socket < 0) {
omapi_connection_dereference (&obj, MDL);
if (errno == EMFILE || errno == ENFILE
|| errno == ENOBUFS)
return ISC_R_NORESOURCES;
return ISC_R_UNEXPECTED;
}
/* Set up the local address, if any. */
if (local_addr) {
/* Only do TCPv4 so far. */
if (local_addr -> addrtype != AF_INET) {
omapi_connection_dereference (&obj, MDL);
return ISC_R_INVALIDARG;
}
local_sin.sin_port = htons (local_addr -> port);
memcpy (&local_sin.sin_addr,
local_addr -> address,
local_addr -> addrlen);
#if defined (HAVE_SA_LEN)
local_sin.sin_len = sizeof local_addr;
#endif
local_sin.sin_family = AF_INET;
memset (&local_sin.sin_zero, 0,
sizeof local_sin.sin_zero);
if (bind (obj -> socket, (struct sockaddr *)&local_sin,
sizeof local_sin) < 0) {
omapi_object_dereference ((omapi_object_t **)
&obj, MDL);
if (errno == EADDRINUSE)
return ISC_R_ADDRINUSE;
if (errno == EADDRNOTAVAIL)
return ISC_R_ADDRNOTAVAIL;
if (errno == EACCES)
return ISC_R_NOPERM;
return ISC_R_UNEXPECTED;
}
}
#if defined (HAVE_SETFD)
if (fcntl (obj -> socket, F_SETFD, 1) < 0) {
close (obj -> socket);
omapi_connection_dereference (&obj, MDL);
return ISC_R_UNEXPECTED;
}
#endif
/* Set the SO_REUSEADDR flag (this should not fail). */
flag = 1;
if (setsockopt (obj -> socket, SOL_SOCKET, SO_REUSEADDR,
(char *)&flag, sizeof flag) < 0) {
omapi_connection_dereference (&obj, MDL);
return ISC_R_UNEXPECTED;
}
/* Set the file to nonblocking mode. */
if (fcntl (obj -> socket, F_SETFL, O_NONBLOCK) < 0) {
omapi_connection_dereference (&obj, MDL);
return ISC_R_UNEXPECTED;
}
status = (omapi_register_io_object
((omapi_object_t *)obj,
0, omapi_connection_writefd,
0, omapi_connection_connect,
omapi_connection_reaper));
if (status != ISC_R_SUCCESS)
goto out;
status = omapi_connection_connect ((omapi_object_t *)obj);
#if defined (TRACING)
}
omapi_connection_register (obj, MDL);
#endif
out:
omapi_connection_dereference (&obj, MDL);
return status;
}
#if defined (TRACING)
omapi_array_t *omapi_connections;
OMAPI_ARRAY_TYPE(omapi_connection, omapi_connection_object_t)
void omapi_connection_trace_setup (void) {
trace_connect = trace_type_register ("connect", (void *)0,
trace_connect_input,
trace_connect_stop, MDL);
trace_disconnect = trace_type_register ("disconnect", (void *)0,
trace_disconnect_input,
trace_disconnect_stop, MDL);
}
void omapi_connection_register (omapi_connection_object_t *obj,
const char *file, int line)
{
isc_result_t status;
trace_iov_t iov [6];
int iov_count = 0;
int32_t connect_index, listener_index;
static int32_t index;
if (!omapi_connections) {
status = omapi_connection_array_allocate (&omapi_connections,
file, line);
if (status != ISC_R_SUCCESS)
return;
}
status = omapi_connection_array_extend (omapi_connections, obj,
(int *)0, file, line);
if (status != ISC_R_SUCCESS) {
obj -> index = -1;
return;
}
if (trace_record ()) {
/* Connection registration packet:
int32_t index
int32_t listener_index [-1 means no listener]
u_int16_t remote_port
u_int16_t local_port
u_int32_t remote_addr
u_int32_t local_addr */
connect_index = htonl (index);
index++;
if (obj -> listener)
listener_index = htonl (obj -> listener -> index);
else
listener_index = htonl (-1);
iov [iov_count].buf = (char *)&connect_index;
iov [iov_count++].len = sizeof connect_index;
iov [iov_count].buf = (char *)&listener_index;
iov [iov_count++].len = sizeof listener_index;
iov [iov_count].buf = (char *)&obj -> remote_addr.sin_port;
iov [iov_count++].len = sizeof obj -> remote_addr.sin_port;
iov [iov_count].buf = (char *)&obj -> local_addr.sin_port;
iov [iov_count++].len = sizeof obj -> local_addr.sin_port;
iov [iov_count].buf = (char *)&obj -> remote_addr.sin_addr;
iov [iov_count++].len = sizeof obj -> remote_addr.sin_addr;
iov [iov_count].buf = (char *)&obj -> local_addr.sin_addr;
iov [iov_count++].len = sizeof obj -> local_addr.sin_addr;
status = trace_write_packet_iov (trace_connect,
iov_count, iov, file, line);
}
}
static void trace_connect_input (trace_type_t *ttype,
unsigned length, char *buf)
{
struct sockaddr_in remote, local;
int32_t connect_index, listener_index;
char *s = buf;
omapi_connection_object_t *obj;
isc_result_t status;
if (length != ((sizeof connect_index) +
(sizeof remote.sin_port) +
(sizeof remote.sin_addr)) * 2) {
log_error ("Trace connect: invalid length %d", length);
return;
}
memset (&remote, 0, sizeof remote);
memset (&local, 0, sizeof local);
memcpy (&connect_index, buf, sizeof connect_index);
s += sizeof connect_index;
memcpy (&listener_index, buf, sizeof listener_index);
s += sizeof listener_index;
memcpy (&remote.sin_port, s, sizeof remote.sin_port);
s += sizeof remote.sin_port;
memcpy (&local.sin_port, s, sizeof local.sin_port);
s += sizeof local.sin_port;
memcpy (&remote.sin_addr, s, sizeof remote.sin_addr);
s += sizeof remote.sin_addr;
memcpy (&local.sin_addr, s, sizeof local.sin_addr);
s += sizeof local.sin_addr;
connect_index = ntohl (connect_index);
listener_index = ntohl (listener_index);
/* If this was a connect to a listener, then we just slap together
a new connection. */
if (listener_index != -1) {
omapi_listener_object_t *listener;
listener = (omapi_listener_object_t *)0;
omapi_array_foreach_begin (trace_listeners,
omapi_listener_object_t, lp) {
if (lp -> address.sin_port == local.sin_port) {
omapi_listener_reference (&listener, lp, MDL);
omapi_listener_dereference (&lp, MDL);
break;
}
} omapi_array_foreach_end (trace_listeners,
omapi_listener_object_t, lp);
if (!listener) {
log_error ("%s%ld, addr %s, port %d",
"Spurious traced listener connect - index ",
(long int)listener_index,
inet_ntoa (local.sin_addr),
ntohs (local.sin_port));
return;
}
obj = (omapi_connection_object_t *)0;
status = omapi_listener_connect (&obj, listener, -1, &remote);
if (status != ISC_R_SUCCESS) {
log_error ("traced listener connect: %s",
isc_result_totext (status));
}
if (obj)
omapi_connection_dereference (&obj, MDL);
omapi_listener_dereference (&listener, MDL);
return;
}
/* Find the matching connect object, if there is one. */
omapi_array_foreach_begin (omapi_connections,
omapi_connection_object_t, lp) {
if (lp -> local_addr.sin_port == local.sin_port &&
(lp -> local_addr.sin_addr.s_addr == htonl (INADDR_ANY) ||
(lp -> local_addr.sin_addr.s_addr ==
local.sin_addr.s_addr))) {
lp -> state = omapi_connection_connected;
lp -> remote_addr = remote;
lp -> remote_addr.sin_family = AF_INET;
omapi_addr_list_dereference (&lp -> connect_list, MDL);
lp -> index = connect_index;
status = omapi_signal_in ((omapi_object_t *)lp,
"connect");
omapi_connection_dereference (&lp, MDL);
return;
}
} omapi_array_foreach_end (omapi_connections,
omapi_connection_object_t, lp);
log_error ("Spurious traced connect - index %ld, addr %s, port %d",
(long int)connect_index, inet_ntoa (remote.sin_addr),
ntohs (remote.sin_port));
return;
}
static void trace_connect_stop (trace_type_t *ttype) { }
static void trace_disconnect_input (trace_type_t *ttype,
unsigned length, char *buf)
{
int32_t *index;
if (length != sizeof *index) {
log_error ("trace disconnect: wrong length %d", length);
return;
}
index = (int32_t *)buf;
omapi_array_foreach_begin (omapi_connections,
omapi_connection_object_t, lp) {
if (lp -> index == ntohl (*index)) {
omapi_disconnect ((omapi_object_t *)lp, 1);
omapi_connection_dereference (&lp, MDL);
return;
}
} omapi_array_foreach_end (omapi_connections,
omapi_connection_object_t, lp);
log_error ("trace disconnect: no connection matching index %ld",
(long int)ntohl (*index));
}
static void trace_disconnect_stop (trace_type_t *ttype) { }
#endif
/* Disconnect a connection object from the remote end. If force is nonzero,
close the connection immediately. Otherwise, shut down the receiving end
but allow any unsent data to be sent before actually closing the socket. */
@ -214,6 +437,7 @@ isc_result_t omapi_disconnect (omapi_object_t *h,
int force)
{
omapi_connection_object_t *c;
isc_result_t status;
#ifdef DEBUG_PROTOCOL
log_debug ("omapi_disconnect(%s)", force ? "force" : "");
@ -223,24 +447,45 @@ isc_result_t omapi_disconnect (omapi_object_t *h,
if (c -> type != omapi_type_connection)
return ISC_R_INVALIDARG;
if (!force) {
/* If we're already disconnecting, we don't have to do
anything. */
if (c -> state == omapi_connection_disconnecting)
return ISC_R_SUCCESS;
#if defined (TRACING)
if (trace_record ()) {
int32_t index;
/* Try to shut down the socket - this sends a FIN to the
remote end, so that it won't send us any more data. If
the shutdown succeeds, and we still have bytes left to
write, defer closing the socket until that's done. */
if (!shutdown (c -> socket, SHUT_RD)) {
if (c -> out_bytes > 0) {
c -> state = omapi_connection_disconnecting;
return ISC_R_SUCCESS;
}
index = htonl (c -> index);
status = trace_write_packet (trace_disconnect,
sizeof index, (char *)&index,
MDL);
if (status != ISC_R_SUCCESS) {
trace_stop ();
log_error ("trace_write_packet: %s",
isc_result_totext (status));
}
}
close (c -> socket);
if (!trace_playback ()) {
#endif
if (!force) {
/* If we're already disconnecting, we don't have to do
anything. */
if (c -> state == omapi_connection_disconnecting)
return ISC_R_SUCCESS;
/* Try to shut down the socket - this sends a FIN to
the remote end, so that it won't send us any more
data. If the shutdown succeeds, and we still
have bytes left to write, defer closing the socket
until that's done. */
if (!shutdown (c -> socket, SHUT_RD)) {
if (c -> out_bytes > 0) {
c -> state =
omapi_connection_disconnecting;
return ISC_R_SUCCESS;
}
}
}
close (c -> socket);
#if defined (TRACING)
}
#endif
c -> state = omapi_connection_closed;
/* Disconnect from I/O object, if any. */
@ -456,7 +701,11 @@ static isc_result_t make_dst_key (DST_KEY **dst_key, omapi_object_t *a) {
(a, (omapi_object_t *)0, "key", &key);
if (status == ISC_R_SUCCESS) {
if (omapi_td_strcmp (algorithm -> value, "hmac-md5") == 0) {
if ((algorithm -> value -> type == omapi_datatype_data ||
algorithm -> value -> type == omapi_datatype_string) &&
strncasecmp ((char *)algorithm -> value -> u.buffer.value,
NS_TSIG_ALG_HMAC_MD5 ".",
algorithm -> value -> u.buffer.len) == 0) {
algorithm_id = KEY_HMAC_MD5;
} else {
status = ISC_R_INVALIDARG;

View File

@ -3,7 +3,7 @@
Subroutines that support the generic listener object. */
/*
* Copyright (c) 1999-2000 Internet Software Consortium.
* Copyright (c) 1999-2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -43,6 +43,15 @@
#include <omapip/omapip_p.h>
#if defined (TRACING)
omapi_array_t *trace_listeners;
static void trace_listener_accept_input (trace_type_t *, unsigned, char *);
static void trace_listener_remember (omapi_listener_object_t *,
const char *, int);
static void trace_listener_accept_stop (trace_type_t *);
trace_type_t *trace_listener_accept;
#endif
OMAPI_OBJECT_ALLOC (omapi_listener,
omapi_listener_object_t, omapi_type_listener)
@ -110,61 +119,72 @@ isc_result_t omapi_listen_addr (omapi_object_t *h,
memset (&(obj -> address.sin_zero), 0,
sizeof obj -> address.sin_zero);
/* Create a socket on which to listen. */
obj -> socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (!obj -> socket) {
omapi_listener_dereference (&obj, MDL);
if (errno == EMFILE || errno == ENFILE || errno == ENOBUFS)
return ISC_R_NORESOURCES;
return ISC_R_UNEXPECTED;
}
#if defined (TRACING)
/* If we're playing back a trace file, we remember the object
on the trace listener queue. */
if (trace_playback ()) {
trace_listener_remember (obj, MDL);
} else {
#endif
/* Create a socket on which to listen. */
obj -> socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (!obj -> socket) {
omapi_listener_dereference (&obj, MDL);
if (errno == EMFILE
|| errno == ENFILE || errno == ENOBUFS)
return ISC_R_NORESOURCES;
return ISC_R_UNEXPECTED;
}
#if defined (HAVE_SETFD)
if (fcntl (obj -> socket, F_SETFD, 1) < 0) {
close (obj -> socket);
omapi_listener_dereference (&obj, MDL);
return ISC_R_UNEXPECTED;
}
if (fcntl (obj -> socket, F_SETFD, 1) < 0) {
close (obj -> socket);
omapi_listener_dereference (&obj, MDL);
return ISC_R_UNEXPECTED;
}
#endif
/* Set the REUSEADDR option so that we don't fail to start if
we're being restarted. */
i = 1;
if (setsockopt (obj -> socket, SOL_SOCKET, SO_REUSEADDR,
(char *)&i, sizeof i) < 0) {
close (obj -> socket);
omapi_listener_dereference (&obj, MDL);
return ISC_R_UNEXPECTED;
}
/* Set the REUSEADDR option so that we don't fail to start if
we're being restarted. */
i = 1;
if (setsockopt (obj -> socket, SOL_SOCKET, SO_REUSEADDR,
(char *)&i, sizeof i) < 0) {
close (obj -> socket);
omapi_listener_dereference (&obj, MDL);
return ISC_R_UNEXPECTED;
}
/* Try to bind to the wildcard address using the port number
we were given. */
i = bind (obj -> socket,
(struct sockaddr *)&obj -> address,
sizeof obj -> address);
if (i < 0) {
omapi_listener_dereference (&obj, MDL);
if (errno == EADDRINUSE)
return ISC_R_ADDRNOTAVAIL;
if (errno == EPERM)
return ISC_R_NOPERM;
return ISC_R_UNEXPECTED;
}
/* Try to bind to the wildcard address using the port number
we were given. */
i = bind (obj -> socket,
(struct sockaddr *)&obj -> address, sizeof obj -> address);
if (i < 0) {
omapi_listener_dereference (&obj, MDL);
if (errno == EADDRINUSE)
return ISC_R_ADDRNOTAVAIL;
if (errno == EPERM)
return ISC_R_NOPERM;
return ISC_R_UNEXPECTED;
/* Now tell the kernel to listen for connections. */
if (listen (obj -> socket, max)) {
omapi_listener_dereference (&obj, MDL);
return ISC_R_UNEXPECTED;
}
if (fcntl (obj -> socket, F_SETFL, O_NONBLOCK) < 0) {
omapi_listener_dereference (&obj, MDL);
return ISC_R_UNEXPECTED;
}
status = omapi_register_io_object ((omapi_object_t *)obj,
omapi_listener_readfd, 0,
omapi_accept, 0, 0);
#if defined (TRACING)
}
/* Now tell the kernel to listen for connections. */
if (listen (obj -> socket, max)) {
omapi_listener_dereference (&obj, MDL);
return ISC_R_UNEXPECTED;
}
if (fcntl (obj -> socket, F_SETFL, O_NONBLOCK) < 0) {
omapi_listener_dereference (&obj, MDL);
return ISC_R_UNEXPECTED;
}
status = omapi_register_io_object ((omapi_object_t *)obj,
omapi_listener_readfd, 0,
omapi_accept, 0, 0);
#endif
omapi_listener_dereference (&obj, MDL);
return status;
}
@ -189,51 +209,46 @@ isc_result_t omapi_accept (omapi_object_t *h)
SOCKLEN_T len;
omapi_connection_object_t *obj;
omapi_listener_object_t *listener;
omapi_addr_t addr;
omapi_addr_t remote_addr;
int i;
struct sockaddr_in addr;
int socket;
if (h -> type != omapi_type_listener)
return ISC_R_INVALIDARG;
listener = (omapi_listener_object_t *)h;
#ifdef DEBUG_PROTOCOL
log_debug ("omapi_accept()");
#endif
/* Get the handle. */
obj = (omapi_connection_object_t *)0;
status = omapi_connection_allocate (&obj, MDL);
if (status != ISC_R_SUCCESS)
return status;
/* Accept the connection. */
len = sizeof obj -> remote_addr;
obj -> socket =
accept (listener -> socket,
((struct sockaddr *)
&(obj -> remote_addr)), &len);
if (obj -> socket < 0) {
omapi_connection_dereference (&obj, MDL);
len = sizeof addr;
socket = accept (listener -> socket,
((struct sockaddr *)&(addr)), &len);
if (socket < 0) {
if (errno == EMFILE || errno == ENFILE || errno == ENOBUFS)
return ISC_R_NORESOURCES;
return ISC_R_UNEXPECTED;
}
obj -> state = omapi_connection_connected;
#if defined (TRACING)
/* If we're recording a trace, remember the connection. */
if (trace_record ()) {
trace_iov_t iov [3];
u_int32_t lsock;
iov [0].buf = (char *)&addr.sin_port;
iov [0].len = sizeof addr.sin_port;
iov [1].buf = (char *)&addr.sin_addr;
iov [1].len = sizeof addr.sin_addr;
iov [2].buf = (char *)&listener -> address.sin_port;
iov [2].len = sizeof listener -> address.sin_port;
trace_write_packet_iov (trace_listener_accept,
3, iov, MDL);
}
#endif
/* Verify that this host is allowed to connect. */
if (listener -> verify_addr) {
addr.addrtype = AF_INET;
addr.addrlen = sizeof (obj -> remote_addr.sin_addr);
memcpy (addr.address, &obj -> remote_addr.sin_addr,
sizeof (obj -> remote_addr.sin_addr));
addr.port = ntohs(obj -> remote_addr.sin_port);
status = (listener -> verify_addr) (h, &addr);
if (status != ISC_R_SUCCESS) {
omapi_disconnect ((omapi_object_t *)obj, 1);
return status;
}
obj = (omapi_connection_object_t *)0;
status = omapi_listener_connect (&obj, listener, socket, &addr);
if (status != ISC_R_SUCCESS) {
close (socket);
return status;
}
status = omapi_register_io_object ((omapi_object_t *)obj,
@ -242,21 +257,130 @@ isc_result_t omapi_accept (omapi_object_t *h)
omapi_connection_reader,
omapi_connection_writer,
omapi_connection_reaper);
if (status != ISC_R_SUCCESS) {
omapi_connection_dereference (&obj, MDL);
return status;
}
omapi_listener_reference (&obj -> listener, listener, MDL);
status = omapi_signal (h, "connect", obj);
/* Lose our reference to the connection, so it'll be gc'd when it's
reaped. */
omapi_connection_dereference (&obj, MDL);
if (status != ISC_R_SUCCESS)
omapi_disconnect ((omapi_object_t *)(obj), 1);
return status;
}
isc_result_t omapi_listener_connect (omapi_connection_object_t **obj,
omapi_listener_object_t *listener,
int socket,
struct sockaddr_in *remote_addr)
{
isc_result_t status;
omapi_object_t *h = (omapi_object_t *)listener;
omapi_addr_t addr;
#ifdef DEBUG_PROTOCOL
log_debug ("omapi_accept()");
#endif
/* Get the handle. */
status = omapi_connection_allocate (obj, MDL);
if (status != ISC_R_SUCCESS)
return status;
(*obj) -> state = omapi_connection_connected;
(*obj) -> remote_addr = *remote_addr;
(*obj) -> socket = socket;
/* Verify that this host is allowed to connect. */
if (listener -> verify_addr) {
addr.addrtype = AF_INET;
addr.addrlen = sizeof (remote_addr -> sin_addr);
memcpy (addr.address, &remote_addr -> sin_addr,
sizeof (remote_addr -> sin_addr));
addr.port = ntohs(remote_addr -> sin_port);
status = (listener -> verify_addr) (h, &addr);
if (status != ISC_R_SUCCESS) {
omapi_disconnect ((omapi_object_t *)(*obj), 1);
omapi_connection_dereference (obj, MDL);
return status;
}
}
omapi_listener_reference (&(*obj) -> listener, listener, MDL);
#if defined (TRACING)
omapi_connection_register (*obj, MDL);
#endif
status = omapi_signal (h, "connect", (*obj));
return status;
}
#if defined (TRACING)
OMAPI_ARRAY_TYPE(omapi_listener, omapi_listener_object_t)
void omapi_listener_trace_setup (void) {
trace_listener_accept =
trace_type_register ("listener-accept", (void *)0,
trace_listener_accept_input,
trace_listener_accept_stop, MDL);
}
static void trace_listener_remember (omapi_listener_object_t *obj,
const char *file, int line)
{
isc_result_t status;
if (!trace_listeners) {
status = omapi_listener_array_allocate (&trace_listeners,
file, line);
if (status != ISC_R_SUCCESS) {
foo:
log_error ("trace_listener_remember: %s",
isc_result_totext (status));
return;
}
}
status = omapi_listener_array_extend (trace_listeners, obj,
&obj -> index, MDL);
if (status != ISC_R_SUCCESS)
goto foo;
}
static void trace_listener_accept_input (trace_type_t *ttype,
unsigned length, char *buf)
{
struct in_addr *addr;
u_int16_t *remote_port;
u_int16_t *local_port;
omapi_connection_object_t *obj;
isc_result_t status;
struct sockaddr_in remote_addr;
addr = (struct in_addr *)buf;
remote_port = (u_int16_t *)(addr + 1);
local_port = remote_port + 1;
memset (&remote_addr, 0, sizeof remote_addr);
remote_addr.sin_addr = *addr;
remote_addr.sin_port = *remote_port;
omapi_array_foreach_begin (trace_listeners,
omapi_listener_object_t, lp) {
if (lp -> address.sin_port == *local_port) {
obj = (omapi_connection_object_t *)0;
status = omapi_listener_connect (&obj,
lp, 0, &remote_addr);
omapi_listener_dereference (&lp, MDL);
return;
}
} omapi_array_foreach_end (trace_listeners,
omapi_listener_object_t, lp);
log_error ("trace_listener_accept: %s from %s/%d to port %d",
"unexpected connect",
inet_ntoa (*addr), *remote_port, *local_port);
}
static void trace_listener_accept_stop (trace_type_t *ttype) { }
#endif
isc_result_t omapi_listener_configure_security (omapi_object_t *h,
isc_result_t (*verify_addr)
(omapi_object_t *,

View File

@ -0,0 +1,488 @@
/* mrtrace.c
Subroutines that support minires tracing... */
/*
* Copyright (c) 2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of The Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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.
*
* This software has been written for the Internet Software Consortium
* by Ted Lemon, as part of a project for Nominum, Inc. To learn more
* about the Internet Software Consortium, see http://www.isc.org/. To
* learn more about Nominum, Inc., see ``http://www.nominum.com''.
*/
#include <omapip/omapip_p.h>
#include "minires/minires.h"
#include "arpa/nameser.h"
static void trace_mr_output_input (trace_type_t *, unsigned, char *);
static void trace_mr_output_stop (trace_type_t *);
static void trace_mr_input_input (trace_type_t *, unsigned, char *);
static void trace_mr_input_stop (trace_type_t *);
static void trace_mr_statp_input (trace_type_t *, unsigned, char *);
static void trace_mr_statp_stop (trace_type_t *);
static void trace_mr_randomid_input (trace_type_t *, unsigned, char *);
static void trace_mr_randomid_stop (trace_type_t *);
trace_type_t *trace_mr_output;
trace_type_t *trace_mr_input;
trace_type_t *trace_mr_statp;
trace_type_t *trace_mr_randomid;
ssize_t trace_mr_send (int, void *, size_t, int);
ssize_t trace_mr_read_playback (struct sockaddr_in *, void *, size_t);
void trace_mr_read_record (struct sockaddr_in *, void *, ssize_t);
ssize_t trace_mr_recvfrom (int s, void *, size_t, int,
struct sockaddr *, SOCKLEN_T *);
ssize_t trace_mr_read (int, void *, size_t);
int trace_mr_connect (int s, struct sockaddr *, SOCKLEN_T);
int trace_mr_socket (int, int, int);
int trace_mr_bind (int, const struct sockaddr *, SOCKLEN_T);
int trace_mr_close (int);
time_t trace_mr_time (time_t *);
int trace_mr_select (int, fd_set *, fd_set *, fd_set *, struct timeval *);
unsigned int trace_mr_res_randomid (unsigned int);
extern time_t cur_time;
#if defined (TRACING)
void trace_mr_init ()
{
trace_mr_output = trace_type_register ("mr-output", (void *)0,
trace_mr_output_input,
trace_mr_output_stop, MDL);
trace_mr_input = trace_type_register ("mr-input", (void *)0,
trace_mr_input_input,
trace_mr_input_stop, MDL);
trace_mr_statp = trace_type_register ("mr-statp", (void *)0,
trace_mr_statp_input,
trace_mr_statp_stop, MDL);
trace_mr_randomid = trace_type_register ("mr-randomid", (void *)0,
trace_mr_randomid_input,
trace_mr_randomid_stop, MDL);
}
void trace_mr_statp_setup (res_state statp)
{
unsigned buflen = 0;
char *buf = (char *)0;
isc_result_t status;
u_int32_t id;
int i;
if (trace_playback ()) {
int nscount;
status = trace_get_packet (&trace_mr_statp, &buflen, &buf);
if (status != ISC_R_SUCCESS) {
log_error ("trace_mr_statp: no statp packet found.");
return;
}
nscount = buflen / sizeof (struct in_addr);
if (nscount * (sizeof (struct in_addr)) != buflen ||
nscount < 1) {
log_error ("trace_mr_statp: bogus length: %d",
buflen);
return;
}
if (nscount > MAXNS)
nscount = MAXNS;
for (i = 0; i < nscount; i++) {
#if defined (HAVE_SA_LEN)
statp -> nsaddr_list [i].sin_len =
sizeof (struct sockaddr_in);
#endif
memset (&statp -> nsaddr_list [i].sin_zero, 0,
sizeof statp -> nsaddr_list [i].sin_zero);
statp -> nsaddr_list [i].sin_port = htons (53); /*XXX*/
statp -> nsaddr_list [i].sin_family = AF_INET;
memcpy (&statp -> nsaddr_list [i].sin_addr,
(buf + i * (sizeof (struct in_addr))),
sizeof (struct in_addr));
}
statp -> nscount = nscount;
dfree (buf, MDL);
buf = (char *)0;
}
if (trace_record ()) {
trace_iov_t *iov;
iov = dmalloc ((statp -> nscount *
sizeof (struct in_addr)), MDL);
if (!iov) {
trace_stop ();
log_error ("No memory for statp iov.");
return;
}
for (i = 0; i < statp -> nscount; i++) {
iov [i].buf =
(char *)&statp -> nsaddr_list [i].sin_addr;
iov [i].len = sizeof (struct in_addr);
}
trace_write_packet_iov (trace_mr_statp, i, iov, MDL);
dfree (iov, MDL);
}
}
#endif
ssize_t trace_mr_send (int fd, void *msg, size_t len, int flags)
{
ssize_t rv;
#if defined (TRACING)
isc_result_t status;
unsigned buflen = 0;
char *inbuf = (char *)0;
u_int32_t result;
u_int32_t sflags;
if (trace_playback()) {
status = trace_get_packet (&trace_mr_output, &buflen, &inbuf);
if (status != ISC_R_SUCCESS) {
log_error ("trace_mr_recvfrom: no input found.");
errno = ECONNREFUSED;
return -1;
}
if (buflen < sizeof result) {
log_error ("trace_mr_recvfrom: data too short.");
errno = ECONNREFUSED;
dfree (inbuf, MDL);
return -1;
}
memcpy (&result, inbuf, sizeof result);
rv = ntohl (result);
dfree (inbuf, MDL);
} else
#endif
rv = send (fd, msg, len, flags);
#if defined (TRACING)
if (trace_record ()) {
trace_iov_t iov [3];
result = htonl (rv);
sflags = htonl (flags);
iov [0].len = sizeof result;
iov [0].buf = (char *)&result;
iov [1].len = sizeof sflags;
iov [1].buf = (char *)&flags;
iov [2].len = len;
iov [2].buf = msg;
trace_write_packet_iov (trace_mr_output, 2, iov, MDL);
}
#endif
return rv;
}
#if defined (TRACING)
ssize_t trace_mr_read_playback (struct sockaddr_in *from,
void *buf, size_t nbytes)
{
isc_result_t status;
unsigned buflen = 0, left;
char *inbuf = (char *)0;
char *bufp;
u_int32_t result;
status = trace_get_packet (&trace_mr_input, &buflen, &inbuf);
if (status != ISC_R_SUCCESS) {
log_error ("trace_mr_recvfrom: no input found.");
errno = ECONNREFUSED;
return -1;
}
if (buflen < sizeof result) {
log_error ("trace_mr_recvfrom: data too short.");
errno = ECONNREFUSED;
dfree (inbuf, MDL);
return -1;
}
bufp = inbuf;
left = buflen;
memcpy (&result, bufp, sizeof result);
result = ntohl (result);
bufp += sizeof result;
left -= sizeof result;
if (result == 0) {
if (left < ((sizeof from -> sin_port) +
sizeof (from -> sin_addr))) {
log_error ("trace_mr_recvfrom: data too short.");
errno = ECONNREFUSED;
dfree (inbuf, MDL);
return -1;
}
if (from)
memcpy (&from -> sin_addr, bufp,
sizeof from -> sin_addr);
bufp += sizeof from -> sin_addr;
left -= sizeof from -> sin_addr;
if (from)
memcpy (&from -> sin_port, bufp,
sizeof from -> sin_port);
bufp += sizeof from -> sin_port;
left -= sizeof from -> sin_port;
if (from) {
from -> sin_family = AF_INET;
#if defined(HAVE_SA_LEN)
from -> sin_len = sizeof (struct sockaddr_in);
#endif
memset (from -> sin_zero, 0, sizeof from -> sin_zero);
}
if (left > nbytes) {
log_error ("trace_mr_recvfrom: too much%s",
" data.");
errno = ECONNREFUSED;
dfree (inbuf, MDL);
return -1;
}
memcpy (buf, bufp, left);
dfree (inbuf, MDL);
return left;
}
errno = ECONNREFUSED;
return -1;
}
void trace_mr_read_record (struct sockaddr_in *from, void *buf, ssize_t rv)
{
trace_iov_t iov [4];
u_int32_t result;
int iolen = 0;
static char zero [4] = { 0, 0, 0, 0 };
if (rv < 0)
result = htonl (errno); /* XXX */
else
result = 0;
iov [iolen].buf = (char *)&result;
iov [iolen++].len = sizeof result;
if (rv > 0) {
if (from) {
iov [iolen].buf = (char *)&from -> sin_addr;
iov [iolen++].len = sizeof from -> sin_addr;
iov [iolen].buf = (char *)&from -> sin_port;
iov [iolen++].len = sizeof from -> sin_port;
} else {
iov [iolen].buf = zero;
iov [iolen++].len = sizeof from -> sin_addr;
iov [iolen].buf = zero;
iov [iolen++].len = sizeof from -> sin_port;
}
iov [iolen].buf = buf;
iov [iolen++].len = rv;
}
trace_write_packet_iov (trace_mr_input, iolen, iov, MDL);
}
#endif
ssize_t trace_mr_recvfrom (int s, void *buf, size_t len, int flags,
struct sockaddr *from, SOCKLEN_T *fromlen)
{
ssize_t rv;
#if defined (TRACING)
if (trace_playback ())
rv = trace_mr_read_playback ((struct sockaddr_in *)from,
buf, len);
else
#endif
rv = recvfrom (s, buf, len, flags, from, fromlen);
#if defined (TRACING)
if (trace_record ()) {
trace_mr_read_record ((struct sockaddr_in *)from, buf, rv);
}
#endif
return rv;
}
ssize_t trace_mr_read (int d, void *buf, size_t nbytes)
{
ssize_t rv;
#if defined (TRACING)
if (trace_playback ())
rv = trace_mr_read_playback ((struct sockaddr_in *)0,
buf, nbytes);
else
#endif
rv = read (d, buf, nbytes);
#if defined (TRACING)
if (trace_record ()) {
trace_mr_read_record ((struct sockaddr_in *)0, buf, rv);
}
#endif
return rv;
}
int trace_mr_connect (int s, struct sockaddr *name, SOCKLEN_T namelen)
{
#if defined (TRACING)
if (!trace_playback ())
#endif
return connect (s, name, namelen);
#if defined (TRACING)
return 0;
#endif
}
int trace_mr_socket (int domain, int type, int protocol)
{
#if defined (TRACING)
if (!trace_playback ())
#endif
return socket (domain, type, protocol);
#if defined (TRACING)
return 100;
#endif
}
int trace_mr_bind (int s, const struct sockaddr *name, SOCKLEN_T namelen)
{
#if defined (TRACING)
if (!trace_playback ())
#endif
return bind (s, name, namelen);
#if defined (TRACING)
return 0;
#endif
}
int trace_mr_close (int s)
{
#if defined (TRACING)
if (!trace_playback ())
#endif
return close (s);
#if defined (TRACING)
return 0;
#endif
}
time_t trace_mr_time (time_t *tp)
{
#if defined (TRACING)
if (trace_playback ()) {
if (tp)
*tp = cur_time;
return cur_time;
}
#endif
return time (tp);
}
int trace_mr_select (int s, fd_set *r, fd_set *w, fd_set *x, struct timeval *t)
{
#if defined (TRACING)
trace_type_t *ttp = (trace_type_t *)0;
if (trace_playback ()) {
time_t nct = trace_snoop_time (&ttp);
time_t secr = t -> tv_sec;
t -> tv_sec = nct - cur_time;
if (t -> tv_sec > secr)
return 0;
if (ttp == trace_mr_input)
return 1;
return 0;
}
#endif
return select (s, r, w, x, t);
}
unsigned int trace_mr_res_randomid (unsigned int oldid)
{
u_int32_t id;
int rid = oldid;
#if defined (TRACING)
unsigned buflen = 0;
char *buf = (char *)0;
isc_result_t status;
if (trace_playback ()) {
int nscount;
status = trace_get_packet (&trace_mr_randomid, &buflen, &buf);
if (status != ISC_R_SUCCESS) {
log_error ("trace_mr_statp: no statp packet found.");
return oldid;
}
if (buflen != sizeof id) {
log_error ("trace_mr_randomid: bogus length: %d",
buflen);
return oldid;
}
memcpy (&id, buf, sizeof id);
dfree (buf, MDL);
buf = (char *)0;
rid = ntohl (id);
}
if (trace_record ()) {
id = htonl (rid);
trace_write_packet (trace_mr_randomid,
sizeof id, (char *)&id, MDL);
}
#endif
return rid;
}
#if defined (TRACING)
static void trace_mr_output_input (trace_type_t *ttype,
unsigned length, char *buf)
{
}
static void trace_mr_output_stop (trace_type_t *ttype)
{
}
static void trace_mr_input_input (trace_type_t *ttype,
unsigned length, char *buf)
{
log_error ("unaccounted-for minires input.");
}
static void trace_mr_input_stop (trace_type_t *ttype)
{
}
static void trace_mr_statp_input (trace_type_t *ttype,
unsigned length, char *buf)
{
log_error ("unaccounted-for minires statp input.");
}
static void trace_mr_statp_stop (trace_type_t *ttype)
{
}
static void trace_mr_randomid_input (trace_type_t *ttype,
unsigned length, char *buf)
{
log_error ("unaccounted-for minires randomid input.");
}
static void trace_mr_randomid_stop (trace_type_t *ttype)
{
}
#endif

View File

@ -4,7 +4,7 @@
until the actual libisc merge. */
/*
* Copyright (c) 1999-2000 Internet Software Consortium.
* Copyright (c) 1999-2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -95,6 +95,24 @@ static const char *text[ISC_R_NRESULTS] = {
"zone TSIG key not known", /* 47 */
"invalid TSIG key", /* 48 */
"operation in progress", /* 49 */
"DNS format error", /* 50 */
"DNS server failed", /* 51 */
"no such domain", /* 52 */
"not implemented", /* 53 */
"refused", /* 54 */
"domain already exists", /* 55 */
"RRset already exists", /* 56 */
"no such RRset", /* 57 */
"not authorized", /* 58 */
"not a zone", /* 59 */
"bad DNS signature", /* 60 */
"bad DNS key", /* 61 */
"clock skew too great", /* 62 */
"no root zone", /* 63 */
"destination address required", /* 64 */
"cross-zone update", /* 65 */
"no TSIG signature", /* 66 */
"not equal" /* 67 */
};
const char *isc_result_totext (isc_result_t result)

View File

@ -3,7 +3,7 @@
Subroutines providing general support for objects. */
/*
* Copyright (c) 1999-2000 Internet Software Consortium.
* Copyright (c) 1999-2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -180,6 +180,13 @@ isc_result_t omapi_init (void)
if (status != ISC_R_SUCCESS)
return status;
#if defined (TRACING)
omapi_listener_trace_setup ();
omapi_connection_trace_setup ();
omapi_buffer_trace_setup ();
trace_mr_init ();
#endif
/* This seems silly, but leave it. */
return ISC_R_SUCCESS;
}

View File

@ -0,0 +1,682 @@
/* trace.c
Subroutines that support tracing of OMAPI wire transactions and
provide a mechanism for programs using OMAPI to trace their own
transactions... */
/*
* Copyright (c) 2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of The Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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.
*
* This software has been written for the Internet Software Consortium
* by Ted Lemon, as part of a project for Nominum, Inc. To learn more
* about the Internet Software Consortium, see http://www.isc.org/. To
* learn more about Nominum, Inc., see ``http://www.nominum.com''.
*/
#include <omapip/omapip_p.h>
#if defined (TRACING)
void (*trace_set_time_hook) (u_int32_t);
static int tracing_stopped;
static int traceoutfile;
static int traceindex;
static trace_type_t **trace_types;
static int trace_type_count;
static int trace_type_max;
static trace_type_t *new_trace_types;
static FILE *traceinfile;
static tracefile_header_t tracefile_header;
static int trace_playback_flag;
trace_type_t trace_time_marker;
static isc_result_t trace_type_record (trace_type_t *,
unsigned, const char *, int);
int trace_playback ()
{
return trace_playback_flag;
}
int trace_record ()
{
if (traceoutfile)
return 1;
return 0;
}
isc_result_t trace_init (void (*set_time) (u_int32_t),
const char *file, int line)
{
trace_type_t *root_type;
static int root_setup = 0;
if (root_setup)
return ISC_R_SUCCESS;
trace_set_time_hook = set_time;
root_type = trace_type_register ("trace-index-mapping",
(void *)0, trace_index_map_input,
trace_index_stop_tracing, file, line);
if (!root_type)
return ISC_R_UNEXPECTED;
root_type -> index = 0;
trace_type_stash (root_type);
root_setup = 1;
return ISC_R_SUCCESS;
}
isc_result_t trace_begin (const char *filename,
const char *file, int line)
{
tracefile_header_t tfh;
int status;
trace_type_t *tptr, *next;
isc_result_t result;
if (traceoutfile) {
log_error ("%s(%d): trace_begin called twice",
file, line);
return ISC_R_INVALIDARG;
}
traceoutfile = open (filename, O_CREAT | O_WRONLY, 0644);
if (traceoutfile < 0) {
log_error ("%s(%d): trace_begin: %s: %m",
file, line, filename);
return ISC_R_UNEXPECTED;
}
#if defined (HAVE_SETFD)
if (fcntl (traceoutfile, F_SETFD, 1) < 0)
log_error ("Can't set close-on-exec on %s: %m", filename);
#endif
tfh.magic = htonl (TRACEFILE_MAGIC);
tfh.version = htonl (TRACEFILE_VERSION);
tfh.hlen = htonl (sizeof (tracefile_header_t));
tfh.phlen = htonl (sizeof (tracepacket_t));
status = write (traceoutfile, &tfh, sizeof tfh);
if (status < 0) {
log_error ("%s(%d): trace_begin write failed: %m", file, line);
return ISC_R_UNEXPECTED;
} else if (status != sizeof tfh) {
log_error ("%s(%d): trace_begin: short write (%d:%ld)",
file, line, status, (long)(sizeof tfh));
trace_stop ();
return ISC_R_UNEXPECTED;
}
/* Stash all the types that have already been set up. */
if (new_trace_types) {
next = new_trace_types;
new_trace_types = (trace_type_t *)0;
for (tptr = next; tptr; tptr = next) {
next = tptr -> next;
if (tptr -> index != 0) {
result = (trace_type_record
(tptr,
strlen (tptr -> name), file, line));
if (result != ISC_R_SUCCESS)
return status;
}
}
}
return ISC_R_SUCCESS;
}
isc_result_t trace_write_packet (trace_type_t *ttype, unsigned length,
const char *buf, const char *file, int line)
{
trace_iov_t iov;
iov.buf = buf;
iov.len = length;
return trace_write_packet_iov (ttype, 1, &iov, file, line);
}
isc_result_t trace_write_packet_iov (trace_type_t *ttype,
int count, trace_iov_t *iov,
const char *file, int line)
{
tracepacket_t tmp;
int status;
int i;
int length;
/* Really shouldn't get called here, but it may be hard to turn off
tracing midstream if the trace file write fails or something. */
if (tracing_stopped)
return 0;
if (!ttype) {
log_error ("%s(%d): trace_write_packet with null trace type",
file ? file : "<unknown file>", line);
return ISC_R_INVALIDARG;
}
if (!traceoutfile) {
log_error ("%s(%d): trace_write_packet with no tracefile.",
file ? file : "<unknown file>", line);
return ISC_R_INVALIDARG;
}
/* Compute the total length of the iov. */
length = 0;
for (i = 0; i < count; i++)
length += iov [i].len;
/* We have to swap out the data, because it may be read back on a
machine of different endianness. */
tmp.type_index = htonl (ttype -> index);
tmp.when = htonl (time ((time_t *)0)); /* XXX */
tmp.length = htonl (length);
status = write (traceoutfile, &tmp, sizeof tmp);
if (status < 0) {
log_error ("%s(%d): trace_write_packet write failed: %m",
file, line);
return ISC_R_UNEXPECTED;
} else if (status != sizeof tmp) {
log_error ("%s(%d): trace_write_packet: short write (%d:%ld)",
file, line, status, (long)(sizeof tmp));
trace_stop ();
}
for (i = 0; i < count; i++) {
status = write (traceoutfile, iov [i].buf, iov [i].len);
if (status < 0) {
log_error ("%s(%d): %s write failed: %m",
file, line, "trace_write_packet");
return ISC_R_UNEXPECTED;
} else if (status != iov [i].len) {
log_error ("%s(%d): %s: short write (%d:%d)",
file, line,
"trace_write_packet", status, length);
trace_stop ();
}
}
/* Write padding on the end of the packet to align the next
packet to an 8-byte boundary. This is in case we decide to
use mmap in some clever way later on. */
if (length % 8) {
static char zero [] = { 0, 0, 0, 0, 0, 0, 0 };
unsigned padl = 8 - (length % 8);
status = write (traceoutfile, zero, padl);
if (status < 0) {
log_error ("%s(%d): trace_write_packet write failed: %m",
file, line);
return ISC_R_UNEXPECTED;
} else if (status != padl) {
log_error ("%s(%d): trace_write_packet: short write (%d:%d)",
file, line, status, padl);
trace_stop ();
}
}
return ISC_R_SUCCESS;
}
void trace_type_stash (trace_type_t *tptr)
{
trace_type_t **vec;
int delta;
if (trace_type_max <= tptr -> index) {
delta = tptr -> index - trace_type_max + 10;
vec = dmalloc (((trace_type_max + delta) *
sizeof (trace_type_t *)), MDL);
if (!vec)
return;
memset (&vec [trace_type_max], 0,
(sizeof (trace_type_t *)) * delta);
trace_type_max += delta;
if (trace_types) {
memcpy (vec, trace_types,
trace_type_count * sizeof (trace_type_t *));
dfree (trace_types, MDL);
}
trace_types = vec;
}
trace_types [tptr -> index] = tptr;
if (tptr -> index >= trace_type_count)
trace_type_count = tptr -> index + 1;
}
trace_type_t *trace_type_register (const char *name,
void *baggage,
void (*have_packet) (trace_type_t *,
unsigned, char *),
void (*stop_tracing) (trace_type_t *),
const char *file, int line)
{
trace_type_t *ttmp, *tptr;
unsigned slen = strlen (name);
isc_result_t status;
ttmp = dmalloc (sizeof *ttmp, file, line);
if (!ttmp)
return ttmp;
ttmp -> index = -1;
ttmp -> name = dmalloc (slen + 1, file, line);
if (!ttmp -> name) {
dfree (ttmp, file, line);
return (trace_type_t *)0;
}
strcpy (ttmp -> name, name);
ttmp -> have_packet = have_packet;
ttmp -> stop_tracing = stop_tracing;
if (traceoutfile) {
status = trace_type_record (ttmp, slen, file, line);
if (status != ISC_R_SUCCESS) {
dfree (ttmp -> name, file, line);
dfree (ttmp, file, line);
return (trace_type_t *)0;
}
} else {
ttmp -> next = new_trace_types;
new_trace_types = ttmp;
}
return ttmp;
}
static isc_result_t trace_type_record (trace_type_t *ttmp, unsigned slen,
const char *file, int line)
{
trace_index_mapping_t *tim;
isc_result_t status;
tim = dmalloc (slen + TRACE_INDEX_MAPPING_SIZE, file, line);
if (!tim)
return ISC_R_NOMEMORY;
ttmp -> index = ++traceindex;
trace_type_stash (ttmp);
tim -> index = htonl (ttmp -> index);
memcpy (tim -> name, ttmp -> name, slen);
status = trace_write_packet (trace_types [0],
slen + TRACE_INDEX_MAPPING_SIZE,
(char *)tim, file, line);
dfree (tim, file, line);
return status;
}
/* Stop all registered trace types from trying to trace. */
void trace_stop (void)
{
int i;
for (i = 0; i < trace_type_count; i++)
if (trace_types [i] -> stop_tracing)
(*(trace_types [i] -> stop_tracing))
(trace_types [i]);
tracing_stopped = 1;
}
void trace_index_map_input (trace_type_t *ttype, unsigned length, char *buf)
{
trace_index_mapping_t *tmap;
unsigned len;
trace_type_t *tptr, **prev;
if (length < TRACE_INDEX_MAPPING_SIZE) {
log_error ("short trace index mapping");
return;
}
tmap = (trace_index_mapping_t *)buf;
prev = &new_trace_types;
for (tptr = new_trace_types; tptr; tptr = tptr -> next) {
len = strlen (tptr -> name);
if (len == length - TRACE_INDEX_MAPPING_SIZE &&
!memcmp (tptr -> name, tmap -> name, len)) {
tptr -> index = ntohl (tmap -> index);
trace_type_stash (tptr);
*prev = tptr -> next;
return;
}
prev = &tptr -> next;
}
log_error ("No registered trace type for type name %.*s",
(int)length - TRACE_INDEX_MAPPING_SIZE, tmap -> name);
return;
}
void trace_index_stop_tracing (trace_type_t *ttype) { }
void trace_replay_init (void)
{
trace_playback_flag = 1;
}
void trace_file_replay (const char *filename)
{
tracepacket_t *tpkt = (tracepacket_t *)0;
int status;
char *buf = (char *)0;
unsigned buflen;
unsigned bufmax = 0;
trace_type_t *ttype = (trace_type_t *)0;
isc_result_t result;
int len;
traceinfile = fopen (filename, "r");
if (!traceinfile) {
log_error ("Can't open tracefile %s: %m", filename);
return;
}
#if defined (HAVE_SETFD)
if (fcntl (fileno (traceinfile), F_SETFD, 1) < 0)
log_error ("Can't set close-on-exec on %s: %m", filename);
#endif
status = fread (&tracefile_header, 1,
sizeof tracefile_header, traceinfile);
if (status < sizeof tracefile_header) {
if (ferror (traceinfile))
log_error ("Error reading trace file header: %m");
else
log_error ("Short read on trace file header: %d %ld.",
status, (long)(sizeof tracefile_header));
goto out;
}
tracefile_header.magic = ntohl (tracefile_header.magic);
tracefile_header.version = ntohl (tracefile_header.version);
tracefile_header.hlen = ntohl (tracefile_header.hlen);
tracefile_header.phlen = ntohl (tracefile_header.phlen);
if (tracefile_header.magic != TRACEFILE_MAGIC) {
log_error ("%s: not a dhcp trace file.", filename);
goto out;
}
if (tracefile_header.version > TRACEFILE_VERSION) {
log_error ("tracefile version %ld > current %ld.",
(long int)tracefile_header.version,
(long int)TRACEFILE_VERSION);
goto out;
}
if (tracefile_header.phlen < sizeof *tpkt) {
log_error ("tracefile packet size too small - %ld < %ld",
(long int)tracefile_header.phlen,
(long int)sizeof *tpkt);
goto out;
}
len = (sizeof tracefile_header) - tracefile_header.hlen;
if (len < 0) {
log_error ("tracefile header size too small - %ld < %ld",
(long int)tracefile_header.hlen,
(long int)sizeof tracefile_header);
goto out;
}
if (len > 0) {
status = fseek (traceinfile, (long)len, SEEK_CUR);
if (status < 0) {
log_error ("can't seek past header: %m");
goto out;
}
}
tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
if (!tpkt) {
log_error ("can't allocate trace packet header.");
goto out;
}
while ((result = trace_get_next_packet (&ttype, tpkt, &buf, &buflen,
&bufmax)) == ISC_R_SUCCESS) {
(*ttype -> have_packet) (ttype, tpkt -> length, buf);
ttype = (trace_type_t *)0;
}
out:
fclose (traceinfile);
if (buf)
dfree (buf, MDL);
if (tpkt)
dfree (tpkt, MDL);
}
/* Get the next packet from the file. If ttp points to a nonzero pointer
to a trace type structure, check the next packet to see if it's of the
expected type, and back off if not. */
isc_result_t trace_get_next_packet (trace_type_t **ttp,
tracepacket_t *tpkt,
char **buf, unsigned *buflen,
unsigned *bufmax)
{
trace_type_t *ttype;
unsigned paylen;
int status;
int len;
fpos_t curpos;
status = fgetpos (traceinfile, &curpos);
if (status < 0)
log_error ("Can't save tracefile position: %m");
status = fread (tpkt, 1, (size_t)tracefile_header.phlen, traceinfile);
if (status < tracefile_header.phlen) {
if (ferror (traceinfile))
log_error ("Error reading trace packet header: %m");
else if (status == 0)
return ISC_R_EOF;
else
log_error ("Short read on trace packet header: "
"%ld %ld.",
(long int)status,
(long int)tracefile_header.phlen);
return ISC_R_PROTOCOLERROR;
}
/* Swap the packet. */
tpkt -> type_index = ntohl (tpkt -> type_index);
tpkt -> length = ntohl (tpkt -> length);
tpkt -> when = ntohl (tpkt -> when);
/* See if there's a handler for this packet type. */
if (tpkt -> type_index < trace_type_count &&
trace_types [tpkt -> type_index])
ttype = trace_types [tpkt -> type_index];
else {
log_error ("Trace packet with unknown index %ld",
(long int)tpkt -> type_index);
return ISC_R_PROTOCOLERROR;
}
/* If we were just hunting for the time marker, we've found it,
so back up to the beginning of the packet and return its
type. */
if (ttp && *ttp == &trace_time_marker) {
*ttp = ttype;
status = fsetpos (traceinfile, &curpos);
if (status < 0) {
log_error ("fsetpos in tracefile failed: %m");
return ISC_R_PROTOCOLERROR;
}
return ISC_R_EXISTS;
}
/* If we were supposed to get a particular kind of packet,
check to see that we got the right kind. */
if (ttp && *ttp && ttype != *ttp) {
log_error ("Read packet type %s when expecting %s",
ttype -> name, (*ttp) -> name);
status = fsetpos (traceinfile, &curpos);
if (status < 0) {
log_error ("fsetpos in tracefile failed: %m");
return ISC_R_PROTOCOLERROR;
}
return ISC_R_UNEXPECTEDTOKEN;
}
paylen = tpkt -> length;
if (paylen % 8)
paylen += 8 - (tpkt -> length % 8);
if (paylen > (*bufmax)) {
if ((*buf))
dfree ((*buf), MDL);
(*bufmax) = ((paylen + 1023) & ~1023U);
(*buf) = dmalloc ((*bufmax), MDL);
if (!(*buf)) {
log_error ("Can't allocate input buffer sized %d",
(*bufmax));
return ISC_R_NOMEMORY;
}
}
status = fread ((*buf), 1, paylen, traceinfile);
if (status < paylen) {
if (ferror (traceinfile))
log_error ("Error reading trace payload: %m");
else
log_error ("Short read on trace payload: %d %d.",
status, paylen);
return ISC_R_PROTOCOLERROR;
}
/* Store the actual length of the payload. */
*buflen = tpkt -> length;
if (trace_set_time_hook)
(*trace_set_time_hook) (tpkt -> when);
if (ttp)
*ttp = ttype;
return ISC_R_SUCCESS;
}
isc_result_t trace_get_packet (trace_type_t **ttp,
unsigned *buflen, char **buf)
{
tracepacket_t *tpkt;
unsigned bufmax = 0;
isc_result_t status;
if (!buf || *buf)
return ISC_R_INVALIDARG;
tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
if (!tpkt) {
log_error ("can't allocate trace packet header.");
return ISC_R_NOMEMORY;
}
status = trace_get_next_packet (ttp, tpkt, buf, buflen, &bufmax);
dfree (tpkt, MDL);
return status;
}
time_t trace_snoop_time (trace_type_t **ptp)
{
tracepacket_t *tpkt;
unsigned bufmax = 0;
unsigned buflen = 0;
char *buf = (char *)0;
isc_result_t status;
time_t result;
trace_type_t *ttp;
if (!ptp)
ptp = &ttp;
tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
if (!tpkt) {
log_error ("can't allocate trace packet header.");
return ISC_R_NOMEMORY;
}
*ptp = &trace_time_marker;
trace_get_next_packet (ptp, tpkt, &buf, &buflen, &bufmax);
result = tpkt -> when;
dfree (tpkt, MDL);
return result;
}
/* Get a packet from the trace input file that contains a file with the
specified name. We don't hunt for the packet - it should be the next
packet in the tracefile. If it's not, or something else bad happens,
return an error code. */
isc_result_t trace_get_file (trace_type_t *ttype,
const char *filename, unsigned *len, char **buf)
{
fpos_t curpos;
unsigned max = 0;
tracepacket_t *tpkt;
int status;
isc_result_t result;
/* Disallow some obvious bogosities. */
if (!buf || !len || *buf)
return ISC_R_INVALIDARG;
/* Save file position in case of filename mismatch. */
status = fgetpos (traceinfile, &curpos);
if (status < 0)
log_error ("Can't save tracefile position: %m");
tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
if (!tpkt) {
log_error ("can't allocate trace packet header.");
return ISC_R_NOMEMORY;
}
result = trace_get_next_packet (&ttype, tpkt, buf, len, &max);
if (result != ISC_R_SUCCESS) {
dfree (tpkt, MDL);
if (*buf)
dfree (*buf, MDL);
return result;
}
/* Make sure the filename is right. */
if (strcmp (filename, *buf)) {
log_error ("Read file %s when expecting %s", *buf, filename);
status = fsetpos (traceinfile, &curpos);
if (status < 0) {
log_error ("fsetpos in tracefile failed: %m");
dfree (tpkt, MDL);
dfree (*buf, MDL);
return ISC_R_PROTOCOLERROR;
}
return ISC_R_UNEXPECTEDTOKEN;
}
dfree (tpkt, MDL);
return ISC_R_SUCCESS;
}
#endif /* TRACING */

View File

@ -43,7 +43,7 @@
#ifndef lint
static char copyright[] =
"$Id: class.c,v 1.1.1.4 2000/10/17 15:10:03 taca Exp $ Copyright (c) 1998-2000 The Internet Software Consortium. All rights reserved.\n";
"$Id: class.c,v 1.1.1.5 2001/04/02 21:57:15 mellon Exp $ Copyright (c) 1998-2000 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
@ -84,10 +84,10 @@ void classification_setup ()
void classify_client (packet)
struct packet *packet;
{
execute_statements ((struct binding_value **)0,
packet, (struct lease *)0, packet -> options,
(struct option_state *)0, &global_scope,
default_classification_rules);
execute_statements ((struct binding_value **)0, packet,
(struct lease *)0, (struct client_state *)0,
packet -> options, (struct option_state *)0,
&global_scope, default_classification_rules);
}
int check_collection (packet, lease, collection)
@ -116,6 +116,7 @@ int check_collection (packet, lease, collection)
if (class -> expr) {
status = (evaluate_boolean_expression_result
(&ignorep, packet, lease,
(struct client_state *)0,
packet -> options, (struct option_state *)0,
lease ? &lease -> scope : &global_scope,
class -> expr));
@ -138,6 +139,7 @@ int check_collection (packet, lease, collection)
if (class -> submatch) {
status = (evaluate_data_expression
(&data, packet, lease,
(struct client_state *)0,
packet -> options, (struct option_state *)0,
lease ? &lease -> scope : &global_scope,
class -> submatch));

View File

@ -43,7 +43,7 @@
#ifndef lint
static char copyright[] =
"$Id: db.c,v 1.1.1.12 2000/09/04 23:10:38 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
"$Id: db.c,v 1.1.1.13 2001/04/02 21:57:16 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@ -65,6 +65,7 @@ int write_lease (lease)
int errors = 0;
int i;
struct binding *b;
char *s;
if (counting)
++count;
@ -176,25 +177,14 @@ int write_lease (lease)
}
if (lease -> uid_len) {
int i;
if (db_printable_len (lease -> uid,
lease -> uid_len)) {
fprintf (db_file, "\n uid \"%.*s\";",
(int)lease -> uid_len, lease -> uid);
} else {
errno = 0;
fprintf (db_file, "\n uid %2.2x", lease -> uid [0]);
if (errno) {
s = quotify_buf (lease -> uid, lease -> uid_len, MDL);
if (s) {
fprintf (db_file, "\n uid \"%s\";", s);
if (errno)
++errors;
}
for (i = 1; i < lease -> uid_len; i++) {
errno = 0;
fprintf (db_file, ":%2.2x", lease -> uid [i]);
if (errno) {
++errors;
}
}
putc (';', db_file);
}
dfree (s, MDL);
} else
++errors;
}
if (lease -> scope) {
for (b = lease -> scope -> bindings; b; b = b -> next) {
@ -202,52 +192,31 @@ int write_lease (lease)
continue;
if (b -> value -> type == binding_data) {
if (b -> value -> value.data.data) {
if (db_printable_len (b -> value -> value.data.data,
b -> value -> value.data.len)) {
s = quotify_buf (b -> value -> value.data.data,
b -> value -> value.data.len, MDL);
if (s) {
errno = 0;
fprintf (db_file, "\n set %s = \"%.*s\";",
b -> name,
(int)b -> value -> value.data.len,
b -> value -> value.data.data);
if (errno) {
++errors;
}
} else {
errno = 0;
fprintf (db_file, "\n set %s = ", b -> name);
if (errno) {
fprintf (db_file, "\n set %s = \"%s\";",
b -> name, s);
if (errno)
++errors;
}
for (i = 0; i < b -> value -> value.data.len; i++)
{
errno = 0;
fprintf (db_file, "%2.2x%s",
b -> value -> value.data.data [i],
i + 1 == b -> value -> value.data.len
? "" : ":");
if (errno) {
++errors;
}
}
errno = 0;
putc (';', db_file);
}
dfree (s, MDL);
} else
++errors;
}
} else if (b -> value -> type == binding_numeric) {
errno = 0;
fprintf (db_file, "\n set %s = %%%ld;",
b -> name, b -> value -> value.intval);
if (errno) {
if (errno)
++errors;
}
} else if (b -> value -> type == binding_boolean) {
errno = 0;
fprintf (db_file, "\n set %s = %s;",
b -> name,
b -> value -> value.intval ? "true" : "false");
if (errno) {
if (errno)
++errors;
}
} else if (b -> value -> type == binding_dns) {
log_error ("%s: persistent dns values not supported.",
b -> name);
@ -260,22 +229,40 @@ int write_lease (lease)
}
}
}
if (lease -> agent_options) {
struct option_cache *oc;
struct data_string ds;
pair p;
memset (&ds, 0, sizeof ds);
if (lease -> agent_options) {
for (p = lease -> agent_options -> first; p; p = p -> cdr) {
oc = (struct option_cache *)p -> car;
if (oc -> data.len) {
errno = 0;
fprintf (db_file, "\n option agent.%s %s;",
oc -> option -> name,
pretty_print_option (oc -> option,
oc -> data.data,
oc -> data.len,
1, 1));
if (errno)
++errors;
}
}
}
}
if (lease -> client_hostname &&
db_printable (lease -> client_hostname)) {
errno = 0;
fprintf (db_file, "\n client-hostname \"%s\";",
lease -> client_hostname);
if (errno) {
s = quotify_string (lease -> client_hostname, MDL);
if (s) {
errno = 0;
fprintf (db_file, "\n client-hostname \"%s\";", s);
if (errno)
++errors;
dfree (s, MDL);
} else
++errors;
}
}
if (lease -> hostname && db_printable (lease -> hostname)) {
errno = 0;
fprintf (db_file, "\n hostname \"%s\";",
lease -> hostname);
if (errno) {
++errors;
}
}
if (lease -> on_expiry) {
errno = 0;
@ -384,6 +371,7 @@ int write_host (host)
if (host -> fixed_addr &&
evaluate_option_cache (&ip_addrs, (struct packet *)0,
(struct lease *)0,
(struct client_state *)0,
(struct option_state *)0,
(struct option_state *)0,
&global_scope,
@ -668,10 +656,10 @@ int commit_leases ()
return 0;
}
/* If we've written more than a thousand leases or if
we haven't rewritten the lease database in over an
hour, rewrite it now. */
if (count > 1000 || (count && cur_time - write_time > 3600)) {
/* If we haven't rewritten the lease database in over an
hour, rewrite it now. (The length of time should probably
be configurable. */
if (count && cur_time - write_time > 3600) {
count = 0;
write_time = cur_time;
new_lease_file ();
@ -682,15 +670,38 @@ int commit_leases ()
void db_startup (testp)
int testp;
{
/* Read in the existing lease file... */
read_leases ();
isc_result_t status;
#if defined (TRACING)
if (!trace_playback ()) {
#endif
/* Read in the existing lease file... */
status = read_conf_file (path_dhcpd_db,
(struct group *)0, 0, 1);
/* XXX ignore status? */
#if defined (TRACING)
}
#endif
#if defined (TRACING)
/* If we're playing back, there is no lease file, so we can't
append it, so we create one immediately (maybe this isn't
the best solution... */
if (trace_playback ()) {
new_lease_file ();
}
#endif
if (!testp) {
db_file = fopen (path_dhcpd_db, "a");
if (!db_file)
log_fatal ("Can't open %s for append.", path_dhcpd_db);
expire_all_pools ();
GET_TIME (&write_time);
#if defined (TRACING)
if (trace_playback ())
write_time = cur_time;
else
#endif
GET_TIME (&write_time);
new_lease_file ();
}
}
@ -736,14 +747,20 @@ void new_lease_file ()
counting = 0;
write_leases ();
/* Get the old database out of the way... */
sprintf (backfname, "%s~", path_dhcpd_db);
if (unlink (backfname) < 0 && errno != ENOENT)
#if defined (TRACING)
if (!trace_playback ()) {
#endif
/* Get the old database out of the way... */
sprintf (backfname, "%s~", path_dhcpd_db);
if (unlink (backfname) < 0 && errno != ENOENT)
log_fatal ("Can't remove old lease database backup %s: %m",
backfname);
if (link (path_dhcpd_db, backfname) < 0)
backfname);
if (link (path_dhcpd_db, backfname) < 0)
log_fatal ("Can't backup lease database %s to %s: %m",
path_dhcpd_db, backfname);
path_dhcpd_db, backfname);
#if defined (TRACING)
}
#endif
/* Move in the new file... */
if (rename (newfname, path_dhcpd_db) < 0)

1070
usr.sbin/dhcp/server/ddns.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -4,36 +4,49 @@
#
# option definitions common to all supported networks...
option domain-name "fugue.com";
option domain-name-servers toccata.fugue.com;
option domain-name "example.org";
option domain-name-servers ns1.example.org, ns2.example.org;
option subnet-mask 255.255.255.224;
default-lease-time 600;
max-lease-time 7200;
subnet 204.152.187.0 netmask 255.255.255.0 {
# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.
#authoritative;
# Use this to send dhcp log messages to a different log file (you also
# have to hack syslog.conf to complete the redirection).
log-facility local7;
# No service will be given on this subnet, but declaring it helps the
# DHCP server to understand the network topology.
subnet 10.152.187.0 netmask 255.255.255.0 {
}
subnet 204.254.239.0 netmask 255.255.255.224 {
range 204.254.239.10 204.254.239.20;
option broadcast-address 204.254.239.31;
option routers prelude.fugue.com;
# This is a very basic subnet declaration.
subnet 10.254.239.0 netmask 255.255.255.224 {
range 10.254.239.10 10.254.239.20;
option routers rtr-239-0-1.example.org, rtr-239-0-2.example.org;
}
# The other subnet that shares this physical network
subnet 204.254.239.32 netmask 255.255.255.224 {
range dynamic-bootp 204.254.239.40 204.254.239.60;
option broadcast-address 204.254.239.31;
option routers snarg.fugue.com;
# This declaration allows BOOTP clients to get dynamic addresses,
# which we don't really recommend.
subnet 10.254.239.32 netmask 255.255.255.224 {
range dynamic-bootp 10.254.239.40 10.254.239.60;
option broadcast-address 10.254.239.31;
option routers rtr-239-32-1.example.org;
}
subnet 192.5.5.0 netmask 255.255.255.224 {
range 192.5.5.26 192.5.5.30;
option domain-name-servers bb.home.vix.com, gw.home.vix.com;
option domain-name "vix.com";
option routers 192.5.5.1;
option subnet-mask 255.255.255.224;
option broadcast-address 192.5.5.31;
# A slightly different configuration for an internal subnet.
subnet 10.5.5.0 netmask 255.255.255.224 {
range 10.5.5.26 10.5.5.30;
option domain-name-servers ns1.internal.example.org;
option domain-name "internal.example.org";
option routers 10.5.5.1;
option broadcast-address 10.5.5.31;
default-lease-time 600;
max-lease-time 7200;
}
@ -61,3 +74,28 @@ host fantasia {
fixed-address fantasia.fugue.com;
}
# You can declare a class of clients and then do address allocation
# based on that. The example below shows a case where all clients
# in a certain class get addresses on the 10.17.224/24 subnet, and all
# other clients get addresses on the 10.0.29/24 subnet.
class "foo" {
match if substring (option vendor-class-identifier, 0, 4) = "SUNW";
}
shared-network 224-29 {
subnet 10.17.224.0 netmask 255.255.255.0 {
option routers rtr-224.example.org;
}
subnet 10.0.29.0 netmask 255.255.255.0 {
option routers rtr-29.example.org;
}
pool {
allow members of "foo";
range 10.17.224.10 10.17.224.250;
}
pool {
deny members of "foo";
range 10.0.29.10 10.0.29.230;
}
}

View File

@ -3,7 +3,7 @@
Failover protocol support code... */
/*
* Copyright (c) 1999-2000 Internet Software Consortium.
* Copyright (c) 1999-2001 Internet Software Consortium.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -43,7 +43,7 @@
#ifndef lint
static char copyright[] =
"$Id: failover.c,v 1.1.1.6 2000/10/17 15:10:42 taca Exp $ Copyright (c) 1999-2000 The Internet Software Consortium. All rights reserved.\n";
"$Id: failover.c,v 1.1.1.7 2001/04/02 21:57:22 mellon Exp $ Copyright (c) 1999-2001 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@ -57,6 +57,12 @@ static isc_result_t do_a_failover_option (omapi_object_t *,
dhcp_failover_link_t *);
dhcp_failover_listener_t *failover_listeners;
static isc_result_t failover_message_reference (failover_message_t **,
failover_message_t *,
const char *file, int line);
static isc_result_t failover_message_dereference (failover_message_t **,
const char *file, int line);
void dhcp_failover_startup ()
{
dhcp_failover_state_t *state;
@ -190,6 +196,7 @@ isc_result_t dhcp_failover_link_initiate (omapi_object_t *h)
memset (&ds, 0, sizeof ds);
if (!evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0,
(struct client_state *)0,
(struct option_state *)0,
(struct option_state *)0,
&global_scope, obj -> peer_address, MDL)) {
@ -218,6 +225,7 @@ isc_result_t dhcp_failover_link_initiate (omapi_object_t *h)
if (!state -> me.address ||
!evaluate_option_cache (&ds, (struct packet *)0,
(struct lease *)0,
(struct client_state *)0,
(struct option_state *)0,
(struct option_state *)0,
&global_scope, state -> me.address,
@ -337,13 +345,15 @@ isc_result_t dhcp_failover_link_signal (omapi_object_t *h,
link -> state = dhcp_flink_message_wait;
link -> imsg = dmalloc (sizeof (failover_message_t), MDL);
if (!link -> imsg) {
status = ISC_R_NOMEMORY;
dhcp_flink_fail:
if (link -> imsg) {
dfree (link -> imsg, MDL);
link -> imsg = (failover_message_t *)0;
failover_message_dereference (&link->imsg,
MDL);
}
link -> state = dhcp_flink_disconnected;
log_info ("message length wait: no memory");
log_info ("message length wait: %s",
isc_result_totext (status));
omapi_disconnect (c, 1);
/* XXX just blow away the protocol state now?
XXX or will disconnect blow it away? */
@ -355,8 +365,10 @@ isc_result_t dhcp_failover_link_signal (omapi_object_t *h,
link -> imsg_count = 0; /* Bytes read. */
/* Maximum of 2048 bytes in any failover message. */
if (link -> imsg_len > DHCP_FAILOVER_MAX_MESSAGE_SIZE)
if (link -> imsg_len > DHCP_FAILOVER_MAX_MESSAGE_SIZE) {
status = ISC_R_UNEXPECTED;
goto dhcp_flink_fail;
}
if ((omapi_connection_require (c, link -> imsg_len - 2U)) !=
ISC_R_SUCCESS)
@ -407,7 +419,8 @@ isc_result_t dhcp_failover_link_signal (omapi_object_t *h,
/* Now start sucking options off the wire. */
while (link -> imsg_count < link -> imsg_len) {
if (do_a_failover_option (c, link) != ISC_R_SUCCESS)
status = do_a_failover_option (c, link);
if (status != ISC_R_SUCCESS)
goto dhcp_flink_fail;
}
@ -495,8 +508,7 @@ isc_result_t dhcp_failover_link_signal (omapi_object_t *h,
omapi_signal ((omapi_object_t *)link -> state_object,
"message", link);
link -> state = dhcp_flink_message_length_wait;
dfree (link -> imsg, MDL);
link -> imsg = (failover_message_t *)0;
failover_message_dereference (&link -> imsg, MDL);
/* XXX This is dangerous because we could get into a tight
XXX loop reading input without servicing any other stuff.
XXX There needs to be a way to relinquish control but
@ -785,8 +797,7 @@ isc_result_t dhcp_failover_link_destroy (omapi_object_t *h,
return ISC_R_INVALIDARG;
link = (dhcp_failover_link_t *)h;
if (link -> imsg) {
dfree (link -> imsg, file, line);
link -> imsg = (failover_message_t *)0;
failover_message_dereference (&link -> imsg, MDL);
}
if (link -> state_object)
dhcp_failover_state_dereference (&link -> state_object, MDL);
@ -918,9 +929,11 @@ isc_result_t dhcp_failover_listen (omapi_object_t *h)
}
/* Put this listener on the list. */
dhcp_failover_listener_reference (&obj -> next,
failover_listeners, MDL);
dhcp_failover_listener_dereference (&failover_listeners, MDL);
if (failover_listeners) {
dhcp_failover_listener_reference (&obj -> next,
failover_listeners, MDL);
dhcp_failover_listener_dereference (&failover_listeners, MDL);
}
dhcp_failover_listener_reference (&failover_listeners, obj, MDL);
return dhcp_failover_listener_dereference (&obj, MDL);
@ -1349,6 +1362,8 @@ isc_result_t dhcp_failover_state_transition (dhcp_failover_state_t *state,
XXX interrupted, because then when the connect
XXX occurred, we'd make a transition into
XXX normal, not recover. */
break; /* Kim says stay in recover. */
case normal:
return dhcp_failover_set_state
(state, communications_interrupted);
@ -1659,6 +1674,7 @@ isc_result_t dhcp_failover_peer_state_changed (dhcp_failover_state_t *state,
XXX the documentation for the shut_down state,
XXX not the normal state. */
dhcp_failover_set_state (state, partner_down);
break;
case paused:
dhcp_failover_set_state (state,
@ -1906,9 +1922,6 @@ int dhcp_failover_pool_rebalance (dhcp_failover_state_t *state)
for (p = s -> pools; p; p = p -> next) {
if (p -> failover_peer != state)
continue;
log_info ("pool %lx total %d free %d backup %d",
(unsigned long)p, p -> lease_count,
p -> free_leases, p -> backup_leases);
/* Right now we're giving the peer half of the free leases.
If we have more leases than the peer (i.e., more than
@ -1943,7 +1956,9 @@ int dhcp_failover_pool_rebalance (dhcp_failover_state_t *state)
lp -> next_binding_state = peer_lease_state;
lp -> tstp = cur_time;
lp -> starts = cur_time;
if (!supersede_lease (lp, (struct lease *)0, 1, 1, 0))
if (!supersede_lease (lp, (struct lease *)0, 0, 1, 0)
|| !write_lease (lp))
{
log_info ("can't commit lease %s on giveaway",
piaddr (lp -> ip_addr));
@ -1965,6 +1980,7 @@ int dhcp_failover_pool_rebalance (dhcp_failover_state_t *state)
}
}
}
commit_leases();
dhcp_failover_send_poolresp (state, leases_queued);
dhcp_failover_send_updates (state);
return leases_queued;
@ -2105,6 +2121,77 @@ int dhcp_failover_queue_update (struct lease *lease, int immediate)
return 1;
}
int dhcp_failover_send_acks (dhcp_failover_state_t *state)
{
failover_message_t *msg = (failover_message_t *)0;
/* Must commit all leases prior to acking them. */
if (!commit_leases ())
return 0;
while (state -> toack_queue_head) {
failover_message_reference
(&msg, state -> toack_queue_head, MDL);
failover_message_dereference
(&state -> toack_queue_head, MDL);
if (msg -> next) {
failover_message_reference
(&state -> toack_queue_head, msg -> next, MDL);
}
dhcp_failover_send_bind_ack (state, msg, 0, (const char *)0);
failover_message_dereference (&msg, MDL);
}
failover_message_dereference (&state -> toack_queue_tail, MDL);
state -> pending_acks = 0;
return 1;
}
void dhcp_failover_toack_queue_timeout (void *vs)
{
dhcp_failover_state_t *state = vs;
dhcp_failover_send_acks (state);
}
/* Queue an ack for a message. There is currently no way to queue a
negative ack -- these need to be sent directly. */
int dhcp_failover_queue_ack (dhcp_failover_state_t *state,
failover_message_t *msg)
{
if (state -> toack_queue_head) {
failover_message_reference
(&state -> toack_queue_tail -> next, msg, MDL);
failover_message_dereference (&state -> toack_queue_tail, MDL);
} else {
failover_message_reference (&state -> toack_queue_head,
msg, MDL);
}
failover_message_reference (&state -> toack_queue_tail, msg, MDL);
state -> pending_acks++;
/* Flush the toack queue whenever we exceed half the number of
allowed unacked updates. */
if (state -> pending_acks >= state -> partner.max_flying_updates / 2) {
dhcp_failover_send_acks (state);
}
/* Schedule a timeout to flush the ack queue. */
if (state -> pending_acks > 0) {
add_timeout (cur_time + 2,
dhcp_failover_toack_queue_timeout, state,
(tvref_t)dhcp_failover_state_reference,
(tvunref_t)dhcp_failover_state_dereference);
}
return 1;
}
void dhcp_failover_ack_queue_remove (dhcp_failover_state_t *state,
struct lease *lease)
{
@ -2122,14 +2209,15 @@ void dhcp_failover_ack_queue_remove (dhcp_failover_state_t *state,
} else {
lease_dereference (&state -> ack_queue_tail, MDL);
}
lease -> flags &= ~ON_ACK_QUEUE;
state -> cur_unacked_updates--;
return;
}
for (lp = state -> ack_queue_head;
lp && lp -> next_pending != lease; lp = lp -> next_pending)
;
if (lp) {
} else {
for (lp = state -> ack_queue_head;
lp && lp -> next_pending != lease;
lp = lp -> next_pending)
;
if (!lp)
return;
lease_dereference (&lp -> next_pending, MDL);
if (lease -> next_pending) {
lease_reference (&lp -> next_pending,
@ -2140,8 +2228,18 @@ void dhcp_failover_ack_queue_remove (dhcp_failover_state_t *state,
lease_reference (&state -> ack_queue_tail, lp, MDL);
}
}
lease -> flags &= ~ON_ACK_QUEUE;
state -> cur_unacked_updates--;
/*
* When updating leases as a result of an ack, we defer the commit
* for performance reasons. When there are no more acks pending,
* do a commit.
*/
if (state -> cur_unacked_updates == 0) {
commit_leases();
}
}
isc_result_t dhcp_failover_state_set_value (omapi_object_t *h,
@ -2149,9 +2247,61 @@ isc_result_t dhcp_failover_state_set_value (omapi_object_t *h,
omapi_data_string_t *name,
omapi_typed_data_t *value)
{
isc_result_t status;
if (h -> type != dhcp_type_failover_state)
return ISC_R_INVALIDARG;
/* This list of successful returns is completely wrong, but the
fastest way to make dhcpctl do something vaguely sane when
you try to change the local state. */
if (!omapi_ds_strcmp (name, "name")) {
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "peer_name")) {
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "partner-address")) {
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "local-address")) {
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "partner-port")) {
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "local-port")) {
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "max-outstanding-updates")) {
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "mclt")) {
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "load-balance-max-secs")) {
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "load-balance-hba")) {
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "partner-state")) {
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "local-state")) {
unsigned long l;
status = omapi_get_int_value (&l, value);
if (status != ISC_R_SUCCESS)
return status;
return dhcp_failover_set_state ((dhcp_failover_state_t *)h, l);
} else if (!omapi_ds_strcmp (name, "partner-stos")) {
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "local-stos")) {
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "hierarchy")) {
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "last-packet-sent")) {
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "last-timestamp-received")) {
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "skew")) {
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "max-response-delay")) {
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "cur-unacked-updates")) {
return ISC_R_SUCCESS;
}
if (h -> inner && h -> inner -> type -> set_value)
return (*(h -> inner -> type -> set_value))
(h -> inner, id, name, value);
@ -2245,6 +2395,7 @@ isc_result_t dhcp_failover_state_get_value (omapi_object_t *h,
memset (&ds, 0, sizeof ds);
if (!evaluate_option_cache (&ds, (struct packet *)0,
(struct lease *)0,
(struct client_state *)0,
(struct option_state *)0,
(struct option_state *)0,
&global_scope, oc, MDL)) {
@ -2642,6 +2793,7 @@ int dhcp_failover_state_match (dhcp_failover_state_t *state,
memset (&ds, 0, sizeof ds);
if (evaluate_option_cache (&ds, (struct packet *)0,
(struct lease *)0,
(struct client_state *)0,
(struct option_state *)0,
(struct option_state *)0,
&global_scope,
@ -2807,7 +2959,8 @@ const char *dhcp_failover_message_name (unsigned type)
}
}
const char *dhcp_failover_option_name (unsigned type) {
const char *dhcp_failover_option_name (unsigned type)
{
switch (type) {
case FTO_BINDING_STATUS:
return "binding-status";
@ -3597,7 +3750,6 @@ isc_result_t dhcp_failover_send_bind_update (dhcp_failover_state_t *state,
/* Send a Bind ACK message. */
isc_result_t dhcp_failover_send_bind_ack (dhcp_failover_state_t *state,
struct lease *lease,
failover_message_t *msg,
int reason, const char *message)
{
@ -3761,7 +3913,7 @@ isc_result_t dhcp_failover_send_update_request (dhcp_failover_state_t *state)
#if defined (DEBUG_FAILOVER_MESSAGES)
char obuf [64];
unsigned obufix = 0;
# define FMA obuf, &obufix, sizeof obuf
failover_print (FMA, "(updreq");
#else
@ -3866,6 +4018,12 @@ isc_result_t dhcp_failover_send_update_done (dhcp_failover_state_t *state)
log_debug ("%s", obuf);
}
#endif
/* There may be uncommitted leases at this point (since
dhcp_failover_process_bind_ack() doesn't commit leases);
commit the lease file. */
commit_leases();
return status;
}
@ -3946,22 +4104,37 @@ isc_result_t dhcp_failover_process_bind_update (dhcp_failover_state_t *state,
(lease, state,
msg -> binding_status));
if (new_binding_state != msg -> binding_status) {
char outbuf [100];
#if defined (HAVE_SNPRINTF)
snprintf (outbuf, sizeof outbuf,
"invalid state transition: %d to %d",
lease -> binding_state,
msg -> binding_status);
#else
sprintf (outbuf,
"invalid state transition: %d to %d",
lease -> binding_state,
msg -> binding_status);
#endif
dhcp_failover_send_bind_ack
(state, lease, msg, FTR_FATAL_CONFLICT,
"invalid binding state transition");
(state, msg, FTR_FATAL_CONFLICT,
outbuf);
goto out;
}
}
lt -> next_binding_state = new_binding_state;
}
/* Try to install the new information. */
if (!supersede_lease (lease, lt, 1, 0, 0)) {
if (!supersede_lease (lease, lt, 0, 0, 0) ||
!write_lease (lease)) {
message = "database update failed";
bad:
dhcp_failover_send_bind_ack (state, lease, msg,
reason, message);
dhcp_failover_send_bind_ack (state, msg, reason, message);
} else
dhcp_failover_send_bind_ack (state, lease, msg, 0, 0);
dhcp_failover_queue_ack (state, msg);
out:
if (lt)
lease_dereference (&lt, MDL);
if (lease)
@ -4013,7 +4186,8 @@ isc_result_t dhcp_failover_process_bind_ack (dhcp_failover_state_t *state,
}
/* Try to install the new information. */
supersede_lease (lease, lt, 1, 0, 0);
supersede_lease (lease, lt, 0, 0, 0);
write_lease (lease);
unqueue:
dhcp_failover_ack_queue_remove (state, lease);
@ -4290,6 +4464,7 @@ int load_balance_mine (struct packet *packet, dhcp_failover_state_t *state)
memset (&ds, 0, sizeof ds);
if (oc &&
evaluate_option_cache (&ds, packet, (struct lease *)0,
(struct client_state *)0,
packet -> options, (struct option_state *)0,
&global_scope, oc, MDL)) {
hbaix = loadb_p_hash (ds.data, ds.len);
@ -4523,7 +4698,30 @@ int lease_mine_to_reallocate (struct lease *lease)
}
return 0;
}
return 1;
if (lease)
return !(lease -> binding_state != FTS_FREE &&
lease -> binding_state != FTS_BACKUP);
else
return 0;
}
static isc_result_t failover_message_reference (failover_message_t **mp,
failover_message_t *m,
const char *file, int line)
{
*mp = m;
m -> refcnt++;
return ISC_R_SUCCESS;
}
static isc_result_t failover_message_dereference (failover_message_t **mp,
const char *file, int line)
{
(*mp) -> refcnt--;
if ((*mp) -> refcnt == 0) {
dfree (*mp, MDL);
}
return ISC_R_SUCCESS;
}
OMAPI_OBJECT_ALLOC (dhcp_failover_state, dhcp_failover_state_t,

View File

@ -43,7 +43,7 @@
#ifndef lint
static char copyright[] =
"$Id: mdb.c,v 1.1.1.6 2000/10/17 15:10:46 taca Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
"$Id: mdb.c,v 1.1.1.7 2001/04/02 21:57:23 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@ -154,7 +154,8 @@ isc_result_t enter_host (hd, dynamicp, commit)
DHO_DHCP_CLIENT_IDENTIFIER)) {
evaluate_option_cache
(&hd -> client_identifier, (struct packet *)0,
(struct lease *)0, (struct option_state *)0,
(struct lease *)0, (struct client_state *)0,
(struct option_state *)0,
(struct option_state *)0, &global_scope,
esp -> data.option, MDL);
break;
@ -377,6 +378,7 @@ int find_host_for_network (struct subnet **sp, struct host_decl **host,
continue;
if (!evaluate_option_cache (&fixed_addr, (struct packet *)0,
(struct lease *)0,
(struct client_state *)0,
(struct option_state *)0,
(struct option_state *)0,
&global_scope,
@ -773,6 +775,14 @@ int supersede_lease (comp, lease, commit, propogate, pimmediate)
struct lease *lp, **lq, *prev;
TIME lp_next_state;
#if defined (FAILOVER_PROTOCOL)
/* We must commit leases before sending updates regarding them
to failover peers. It is, therefore, an error to set pimmediate
and not commit. */
if (pimmediate && !commit)
return 0;
#endif
/* If there is no sample lease, just do the move. */
if (!lease)
goto just_move_it;
@ -849,19 +859,21 @@ int supersede_lease (comp, lease, commit, propogate, pimmediate)
lease -> uid, lease -> uid_len);
comp -> uid = &comp -> uid_buf [0];
comp -> uid_max = sizeof comp -> uid_buf;
comp -> uid_len = lease -> uid_len;
} else if (lease -> uid != &lease -> uid_buf [0]) {
comp -> uid = lease -> uid;
comp -> uid_max = lease -> uid_max;
lease -> uid = (unsigned char *)0;
lease -> uid_max = 0;
comp -> uid_len = lease -> uid_len;
lease -> uid_len = 0;
} else {
log_fatal ("corrupt lease uid."); /* XXX */
}
} else {
comp -> uid = (unsigned char *)0;
comp -> uid_max = 0;
comp -> uid_len = comp -> uid_max = 0;
}
comp -> uid_len = lease -> uid_len;
if (comp -> host)
host_dereference (&comp -> host, MDL);
host_reference (&comp -> host, lease -> host, MDL);
@ -875,11 +887,22 @@ int supersede_lease (comp, lease, commit, propogate, pimmediate)
binding_scope_dereference (&lease -> scope, MDL);
}
if (comp -> agent_options)
option_chain_head_dereference (&comp -> agent_options, MDL);
if (lease -> agent_options) {
/* Only retain the agent options if the lease is still
affirmatively associated with a client. */
if (lease -> next_binding_state == FTS_ACTIVE ||
lease -> next_binding_state == FTS_EXPIRED ||
lease -> next_binding_state == FTS_RESERVED ||
lease -> next_binding_state == FTS_BOOTP)
option_chain_head_reference (&comp -> agent_options,
lease -> agent_options,
MDL);
option_chain_head_dereference (&lease -> agent_options, MDL);
}
/* Record the hostname information in the lease. */
if (comp -> hostname)
dfree (comp -> hostname, MDL);
comp -> hostname = lease -> hostname;
lease -> hostname = (char *)0;
if (comp -> client_hostname)
dfree (comp -> client_hostname, MDL);
comp -> client_hostname = lease -> client_hostname;
@ -910,7 +933,7 @@ int supersede_lease (comp, lease, commit, propogate, pimmediate)
}
/* Record the lease in the uid hash if necessary. */
if (enter_uid && lease -> uid) {
if (enter_uid && comp -> uid) {
uid_hash_add (comp);
}
@ -928,6 +951,12 @@ int supersede_lease (comp, lease, commit, propogate, pimmediate)
comp -> next_binding_state = lease -> next_binding_state;
just_move_it:
if (!comp -> pool) {
log_error ("Supersede_lease: lease %s with no pool.",
piaddr (comp -> ip_addr));
return 0;
}
/* Figure out which queue it's on. */
switch (comp -> binding_state) {
case FTS_FREE:
@ -1026,28 +1055,54 @@ int supersede_lease (comp, lease, commit, propogate, pimmediate)
(tvunref_t)pool_dereference);
}
/* Return zero if we didn't commit the lease to permanent storage;
nonzero if we did. */
return commit && write_lease (comp) && commit_leases ()
if (commit) {
if (!write_lease (comp))
return 0;
if (!commit_leases ())
return 0;
}
#if defined (FAILOVER_PROTOCOL)
&& (!propogate ||
dhcp_failover_queue_update (comp, pimmediate))
if (propogate) {
if (!dhcp_failover_queue_update (comp, pimmediate))
return 0;
}
#endif
;
return 1;
}
void process_state_transition (struct lease *lease)
{
#if defined (FAILOVER_PROTOCOL)
dhcp_failover_state_t *peer;
if (lease && lease -> pool && lease -> pool -> failover_peer)
peer = lease -> pool -> failover_peer;
else
peer = (dhcp_failover_state_t *)0;
#endif
/* If the lease was active and is now no longer active, but isn't
released, then it just expired, so do the expiry event. */
if (lease -> next_binding_state != lease -> binding_state &&
(lease -> binding_state == FTS_ACTIVE ||
lease -> binding_state == FTS_BOOTP ||
lease -> binding_state == FTS_RESERVED) &&
lease -> next_binding_state != FTS_RELEASED) {
((
#if defined (FAILOVER_PROTOCOL)
peer &&
lease -> binding_state == FTS_EXPIRED &&
(lease -> next_binding_state == FTS_FREE ||
lease -> next_binding_state == FTS_BACKUP)) ||
(!peer &&
#endif
(lease -> binding_state == FTS_ACTIVE ||
lease -> binding_state == FTS_BOOTP ||
lease -> binding_state == FTS_RESERVED) &&
lease -> next_binding_state != FTS_RELEASED))) {
ddns_removals (lease);
if (lease -> on_expiry) {
execute_statements ((struct binding_value **)0,
(struct packet *)0, lease,
(struct client_state *)0,
(struct option_state *)0,
(struct option_state *)0, /* XXX */
&lease -> scope,
@ -1067,13 +1122,24 @@ void process_state_transition (struct lease *lease)
/* If the lease was active and is now released, do the release
event. */
if ((lease -> binding_state == FTS_ACTIVE ||
lease -> binding_state == FTS_BOOTP ||
lease -> binding_state == FTS_RESERVED) &&
lease -> next_binding_state == FTS_RELEASED) {
if (lease -> next_binding_state != lease -> binding_state &&
((
#if defined (FAILOVER_PROTOCOL)
peer &&
lease -> binding_state == FTS_RELEASED &&
(lease -> next_binding_state == FTS_FREE ||
lease -> next_binding_state == FTS_BACKUP)) ||
(!peer &&
#endif
(lease -> binding_state == FTS_ACTIVE ||
lease -> binding_state == FTS_BOOTP ||
lease -> binding_state == FTS_RESERVED) &&
lease -> next_binding_state == FTS_RELEASED))) {
ddns_removals (lease);
if (lease -> on_release) {
execute_statements ((struct binding_value **)0,
(struct packet *)0, lease,
(struct client_state *)0,
(struct option_state *)0,
(struct option_state *)0, /* XXX */
&lease -> scope,
@ -1133,14 +1199,6 @@ int lease_copy (struct lease **lp,
}
memcpy (lt -> uid, lease -> uid, lease -> uid_max);
}
if (lease -> hostname) {
lt -> hostname = dmalloc (strlen (lease -> hostname) + 1, MDL);
if (!lt -> hostname) {
lease_dereference (&lt, MDL);
return 0;
}
strcpy (lt -> hostname, lease -> hostname);
}
if (lease -> client_hostname) {
lt -> client_hostname =
dmalloc (strlen (lease -> client_hostname) + 1, MDL);
@ -1152,6 +1210,9 @@ int lease_copy (struct lease **lp,
}
if (lease -> scope)
binding_scope_reference (&lt -> scope, lease -> scope, MDL);
if (lease -> agent_options)
option_chain_head_reference (&lt -> agent_options,
lease -> agent_options, MDL);
host_reference (&lt -> host, lease -> host, file, line);
subnet_reference (&lt -> subnet, lease -> subnet, file, line);
pool_reference (&lt -> pool, lease -> pool, file, line);
@ -1188,9 +1249,11 @@ void release_lease (lease, packet)
{
/* If there are statements to execute when the lease is
released, execute them. */
ddns_removals (lease);
if (lease -> on_release) {
execute_statements ((struct binding_value **)0,
packet, lease, packet -> options,
packet, lease, (struct client_state *)0,
packet -> options,
(struct option_state *)0, /* XXX */
&lease -> scope, lease -> on_release);
if (lease -> on_release)
@ -1240,6 +1303,7 @@ void abandon_lease (lease, message)
if (!lease_copy (&lt, lease, MDL))
return;
#if 0
if (lt -> on_expiry)
executable_statement_dereference (&lease -> on_expiry, MDL);
if (lt -> on_release)
@ -1250,6 +1314,8 @@ void abandon_lease (lease, message)
/* Blow away any bindings. */
if (lt -> scope)
binding_scope_dereference (&lt -> scope, MDL);
#endif
lt -> ends = cur_time; /* XXX */
lt -> next_binding_state = FTS_ABANDONED;
@ -1278,6 +1344,7 @@ void dissociate_lease (lease)
if (!lease_copy (&lt, lease, MDL))
return;
#if 0
if (lt -> on_expiry)
executable_statement_dereference (&lease -> on_expiry, MDL);
if (lt -> on_release)
@ -1288,6 +1355,7 @@ void dissociate_lease (lease)
/* Blow away any bindings. */
if (lt -> scope)
binding_scope_dereference (&lt -> scope, MDL);
#endif
#if defined (FAILOVER_PROTOCOL)
if (lease -> pool && lease -> pool -> failover_peer) {
@ -1420,7 +1488,7 @@ void uid_hash_add (lease)
struct lease *lease;
{
struct lease *head = (struct lease *)0;
struct lease *scan;
struct lease *next = (struct lease *)0;
/* If it's not in the hash, just add it. */
@ -1429,9 +1497,13 @@ void uid_hash_add (lease)
lease -> uid_len, lease, MDL);
else {
/* Otherwise, attach it to the end of the list. */
for (scan = head; scan -> n_uid; scan = scan -> n_uid)
;
lease_reference (&scan -> n_uid, lease, MDL);
while (head -> n_uid) {
lease_reference (&next, head -> n_uid, MDL);
lease_dereference (&head, MDL);
lease_reference (&head, next, MDL);
lease_dereference (&next, MDL);
}
lease_reference (&head -> n_uid, lease, MDL);
lease_dereference (&head, MDL);
}
}
@ -1480,8 +1552,8 @@ void uid_hash_delete (lease)
break;
}
}
lease_dereference (&head, MDL);
}
lease_dereference (&head, MDL);
}
/* Add the specified lease to the hardware address hash. */
@ -1490,7 +1562,7 @@ void hw_hash_add (lease)
struct lease *lease;
{
struct lease *head = (struct lease *)0;
struct lease *scan;
struct lease *next = (struct lease *)0;
/* If it's not in the hash, just add it. */
if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
@ -1501,9 +1573,14 @@ void hw_hash_add (lease)
lease, MDL);
else {
/* Otherwise, attach it to the end of the list. */
for (scan = head; scan -> n_hw; scan = scan -> n_hw)
;
lease_reference (&scan -> n_hw, lease, MDL);
while (head -> n_hw) {
lease_reference (&next, head -> n_hw, MDL);
lease_dereference (&head, MDL);
lease_reference (&head, next, MDL);
lease_dereference (&next, MDL);
}
lease_reference (&head -> n_hw, lease, MDL);
lease_dereference (&head, MDL);
}
}
@ -1514,7 +1591,7 @@ void hw_hash_delete (lease)
struct lease *lease;
{
struct lease *head = (struct lease *)0;
struct lease *scan;
struct lease *next = (struct lease *)0;
/* If it's not in the hash, we have no work to do. */
if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
@ -1542,20 +1619,25 @@ void hw_hash_delete (lease)
/* Otherwise, look for the lease in the list of leases
attached to the hash table entry, and remove it if
we find it. */
for (scan = head; scan -> n_hw; scan = scan -> n_hw) {
if (scan -> n_hw == lease) {
lease_dereference (&scan -> n_hw, MDL);
while (head -> n_hw) {
if (head -> n_hw == lease) {
lease_dereference (&head -> n_hw, MDL);
if (lease -> n_hw) {
lease_reference (&scan -> n_hw,
lease_reference (&head -> n_hw,
lease -> n_hw, MDL);
lease_dereference (&lease -> n_hw,
MDL);
}
break;
}
lease_reference (&next, head -> n_hw, MDL);
lease_dereference (&head, MDL);
lease_reference (&head, next, MDL);
lease_dereference (&next, MDL);
}
}
lease_dereference (&head, MDL);
if (head)
lease_dereference (&head, MDL);
}
/* Write all interesting leases to permanent storage. */

View File

@ -43,7 +43,7 @@
#ifndef lint
static char copyright[] =
"$Id: stables.c,v 1.1.1.5 2000/10/17 15:10:52 taca Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
"$Id: stables.c,v 1.1.1.6 2001/04/02 21:57:24 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@ -482,14 +482,14 @@ struct option server_options [256] = {
{ "remote-port", "S", &server_universe, 34 },
{ "local-address", "I", &server_universe, 35 },
{ "omapi-key", "t", &server_universe, 36 },
{ "option-37", "X", &server_universe, 37 },
{ "option-38", "X", &server_universe, 38 },
{ "option-39", "X", &server_universe, 39 },
{ "option-40", "X", &server_universe, 40 },
{ "option-41", "X", &server_universe, 41 },
{ "option-42", "X", &server_universe, 42 },
{ "option-43", "X", &server_universe, 43 },
{ "option-44", "X", &server_universe, 44 },
{ "stash-agent-options", "f", &server_universe, 37 },
{ "ddns-ttl", "T", &server_universe, 38 },
{ "ddns-update-style", "Nddns-styles.", &server_universe, 39 },
{ "client-updates", "f", &server_universe, 40 },
{ "update-optimization", "f", &server_universe, 41 },
{ "ping-check", "f", &server_universe, 42 },
{ "update-static-leases", "f", &server_universe, 43 },
{ "log-facility", "Nsyslog-facilities.", &server_universe, 44 },
{ "option-45", "X", &server_universe, 45 },
{ "option-46", "X", &server_universe, 46 },
{ "option-47", "X", &server_universe, 47 },
@ -703,6 +703,89 @@ struct option server_options [256] = {
{ "option-end", "e", &server_universe, 255 },
};
struct enumeration_value ddns_styles_values [] = {
{ "none", 0 },
{ "ad-hoc", 1 },
{ "interim", 2 },
{ (char *)0, 0 }
};
struct enumeration ddns_styles = {
(struct enumeration *)0,
"ddns-styles",
ddns_styles_values
};
struct enumeration_value syslog_values [] = {
#if defined (LOG_KERN)
{ "kern", LOG_KERN },
#endif
#if defined (LOG_USER)
{ "user", LOG_USER },
#endif
#if defined (LOG_MAIL)
{ "mail", LOG_MAIL },
#endif
#if defined (LOG_DAEMON)
{ "daemon", LOG_DAEMON },
#endif
#if defined (LOG_AUTH)
{ "auth", LOG_AUTH },
#endif
#if defined (LOG_SYSLOG)
{ "syslog", LOG_SYSLOG },
#endif
#if defined (LOG_LPR)
{ "lpr", LOG_LPR },
#endif
#if defined (LOG_NEWS)
{ "news", LOG_NEWS },
#endif
#if defined (LOG_UUCP)
{ "uucp", LOG_UUCP },
#endif
#if defined (LOG_CRON)
{ "cron", LOG_CRON },
#endif
#if defined (LOG_AUTHPRIV)
{ "authpriv", LOG_AUTHPRIV },
#endif
#if defined (LOG_FTP)
{ "ftp", LOG_FTP },
#endif
#if defined (LOG_LOCAL0)
{ "local0", LOG_LOCAL0 },
#endif
#if defined (LOG_LOCAL1)
{ "local1", LOG_LOCAL1 },
#endif
#if defined (LOG_LOCAL2)
{ "local2", LOG_LOCAL2 },
#endif
#if defined (LOG_LOCAL3)
{ "local3", LOG_LOCAL3 },
#endif
#if defined (LOG_LOCAL4)
{ "local4", LOG_LOCAL4 },
#endif
#if defined (LOG_LOCAL5)
{ "local5", LOG_LOCAL5 },
#endif
#if defined (LOG_LOCAL6)
{ "local6", LOG_LOCAL6 },
#endif
#if defined (LOG_LOCAL7)
{ "local7", LOG_LOCAL7 },
#endif
{ (char *)0, 0 }
};
struct enumeration syslog_enum = {
(struct enumeration *)0,
"syslog-facilities",
syslog_values
};
void initialize_server_option_spaces()
{
int i;