ISC DHCP 3.0b2pl23
This commit is contained in:
parent
2c7d48475b
commit
7ac99333ec
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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"))
|
||||
|
297
usr.sbin/dhcp/common/ctrace.c
Normal file
297
usr.sbin/dhcp/common/ctrace.c
Normal 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 */
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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... */
|
||||
|
@ -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
@ -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; \
|
||||
|
355
usr.sbin/dhcp/dhcpctl/omshell.c
Normal file
355
usr.sbin/dhcp/dhcpctl/omshell.c
Normal 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);
|
||||
}
|
@ -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) {
|
||||
|
55
usr.sbin/dhcp/dst/Makefile.dist
Normal file
55
usr.sbin/dhcp/dst/Makefile.dist
Normal 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
319
usr.sbin/dhcp/dst/base64.c
Normal 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
1081
usr.sbin/dhcp/dst/dst_api.c
Normal file
File diff suppressed because it is too large
Load Diff
160
usr.sbin/dhcp/dst/dst_internal.h
Normal file
160
usr.sbin/dhcp/dst/dst_internal.h
Normal 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 */
|
463
usr.sbin/dhcp/dst/dst_support.c
Normal file
463
usr.sbin/dhcp/dst/dst_support.c
Normal 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
|
494
usr.sbin/dhcp/dst/hmac_link.c
Normal file
494
usr.sbin/dhcp/dst/hmac_link.c
Normal 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
101
usr.sbin/dhcp/dst/md5.h
Normal 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
|
373
usr.sbin/dhcp/dst/md5_dgst.c
Normal file
373
usr.sbin/dhcp/dst/md5_dgst.c
Normal 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 */
|
190
usr.sbin/dhcp/dst/md5_locl.h
Normal file
190
usr.sbin/dhcp/dst/md5_locl.h
Normal 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
862
usr.sbin/dhcp/dst/prandom.c
Normal 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);
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
86
usr.sbin/dhcp/includes/ctrace.h
Normal file
86
usr.sbin/dhcp/includes/ctrace.h
Normal 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 *);
|
@ -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 && \
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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_ */
|
||||
|
@ -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;
|
||||
|
123
usr.sbin/dhcp/includes/omapip/trace.h
Normal file
123
usr.sbin/dhcp/includes/omapip/trace.h
Normal 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 **);
|
@ -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 {
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 *
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
}
|
||||
|
322
usr.sbin/dhcp/minires/toisc.c
Normal file
322
usr.sbin/dhcp/minires/toisc.c
Normal 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;
|
||||
}
|
@ -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)
|
||||
|
153
usr.sbin/dhcp/omapip/array.c
Normal file
153
usr.sbin/dhcp/omapip/array.c
Normal 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);
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 *,
|
||||
|
488
usr.sbin/dhcp/omapip/mrtrace.c
Normal file
488
usr.sbin/dhcp/omapip/mrtrace.c
Normal 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
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
682
usr.sbin/dhcp/omapip/trace.c
Normal file
682
usr.sbin/dhcp/omapip/trace.c
Normal 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 */
|
@ -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));
|
||||
|
@ -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
1070
usr.sbin/dhcp/server/ddns.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 (<, 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,
|
||||
|
@ -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 (<, 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 (< -> scope, lease -> scope, MDL);
|
||||
if (lease -> agent_options)
|
||||
option_chain_head_reference (< -> agent_options,
|
||||
lease -> agent_options, MDL);
|
||||
host_reference (< -> host, lease -> host, file, line);
|
||||
subnet_reference (< -> subnet, lease -> subnet, file, line);
|
||||
pool_reference (< -> 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 (<, 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 (< -> 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 (<, 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 (< -> 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. */
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user